auth2-gss.c revision 126274
1141104Sharti/* $OpenBSD: auth2-gss.c,v 1.7 2003/11/21 11:57:03 djm Exp $ */ 21590Srgrimes 31590Srgrimes/* 41590Srgrimes * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. 51590Srgrimes * 61590Srgrimes * Redistribution and use in source and binary forms, with or without 71590Srgrimes * modification, are permitted provided that the following conditions 81590Srgrimes * are met: 91590Srgrimes * 1. Redistributions of source code must retain the above copyright 101590Srgrimes * notice, this list of conditions and the following disclaimer. 111590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer in the 131590Srgrimes * documentation and/or other materials provided with the distribution. 141590Srgrimes * 151590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR 161590Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 171590Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 181590Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 191590Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 201590Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 211590Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 221590Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 231590Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 241590Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 251590Srgrimes */ 261590Srgrimes 271590Srgrimes#include "includes.h" 281590Srgrimes 291590Srgrimes#ifdef GSSAPI 301590Srgrimes 311590Srgrimes#include "auth.h" 321590Srgrimes#include "ssh2.h" 331590Srgrimes#include "xmalloc.h" 341590Srgrimes#include "log.h" 351590Srgrimes#include "dispatch.h" 361590Srgrimes#include "servconf.h" 3762833Swsanchez#include "compat.h" 3862833Swsanchez#include "packet.h" 391590Srgrimes#include "monitor_wrap.h" 401590Srgrimes 4162833Swsanchez#include "ssh-gss.h" 4294587Sobrien 431590Srgrimesextern ServerOptions options; 441590Srgrimes 451590Srgrimesstatic void input_gssapi_token(int type, u_int32_t plen, void *ctxt); 461590Srgrimesstatic void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); 471590Srgrimesstatic void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); 481590Srgrimesstatic void input_gssapi_errtok(int, u_int32_t, void *); 491590Srgrimes 501590Srgrimes/* 511590Srgrimes * We only support those mechanisms that we know about (ie ones that we know 521590Srgrimes * how to check local user kuserok and the like 531590Srgrimes */ 541590Srgrimesstatic int 55141270Shartiuserauth_gssapi(Authctxt *authctxt) 56141270Sharti{ 57146338Sharti gss_OID_desc oid = {0, NULL}; 58141270Sharti Gssctxt *ctxt = NULL; 591590Srgrimes int mechs; 60141270Sharti gss_OID_set supported; 61141270Sharti int present; 62141270Sharti OM_uint32 ms; 631590Srgrimes u_int len; 64141270Sharti char *doid = NULL; 65141270Sharti 66141270Sharti if (!authctxt->valid || authctxt->user == NULL) 67141270Sharti return (0); 681590Srgrimes 69141270Sharti mechs = packet_get_int(); 70141270Sharti if (mechs == 0) { 71141270Sharti debug("Mechanism negotiation is not supported"); 72141270Sharti return (0); 731590Srgrimes } 74141270Sharti 75141270Sharti ssh_gssapi_supported_oids(&supported); 76141270Sharti do { 77141270Sharti mechs--; 78141270Sharti 791590Srgrimes if (doid) 80141270Sharti xfree(doid); 81141270Sharti 82141270Sharti present = 0; 831590Srgrimes doid = packet_get_string(&len); 84141270Sharti 85141270Sharti if (len > 2 && 861590Srgrimes doid[0] == SSH_GSS_OIDTYPE && 87141270Sharti doid[1] == len - 2) { 881590Srgrimes oid.elements = doid + 2; 891590Srgrimes oid.length = len - 2; 90141104Sharti gss_test_oid_set_member(&ms, &oid, supported, 91144387Sharti &present); 92141104Sharti } else { 93141104Sharti logit("Badly formed OID received"); 94141104Sharti } 95144387Sharti } while (mechs > 0 && !present); 96144387Sharti 97176799Simp gss_release_oid_set(&ms, &supported); 98141104Sharti 99141104Sharti if (!present) { 100141104Sharti xfree(doid); 101141104Sharti return (0); 102141104Sharti } 1031590Srgrimes 104141104Sharti if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &oid)))) { 105142457Sharti xfree(doid); 106200630Sstas return (0); 107141104Sharti } 108141104Sharti 109141104Sharti authctxt->methoddata=(void *)ctxt; 110141104Sharti 111141104Sharti packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE); 112146066Sharti 113141104Sharti /* Return the OID that we received */ 114141104Sharti packet_put_string(doid, len); 115141104Sharti 116141104Sharti packet_send(); 1171590Srgrimes xfree(doid); 118142173Sharti 119142173Sharti dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); 120142173Sharti dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); 121142173Sharti authctxt->postponed = 1; 122142173Sharti 123142173Sharti return (0); 124142173Sharti} 125143657Sharti 126144387Shartistatic void 1271590Srgrimesinput_gssapi_token(int type, u_int32_t plen, void *ctxt) 1281590Srgrimes{ 129144387Sharti Authctxt *authctxt = ctxt; 130144387Sharti Gssctxt *gssctxt; 1311590Srgrimes gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; 132144387Sharti gss_buffer_desc recv_tok; 133144387Sharti OM_uint32 maj_status, min_status, flags; 134144387Sharti u_int len; 135144387Sharti 136144387Sharti if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) 137144387Sharti fatal("No authentication or GSSAPI context"); 138144387Sharti 139144387Sharti gssctxt = authctxt->methoddata; 140144387Sharti recv_tok.value = packet_get_string(&len); 141144387Sharti recv_tok.length = len; /* u_int vs. size_t */ 142144387Sharti 143144387Sharti packet_check_eom(); 144144387Sharti 145144387Sharti maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok, 146144387Sharti &send_tok, &flags)); 147144387Sharti 148144387Sharti xfree(recv_tok.value); 149144387Sharti 150144387Sharti if (GSS_ERROR(maj_status)) { 151144387Sharti if (send_tok.length != 0) { 152144387Sharti packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK); 153144387Sharti packet_put_string(send_tok.value, send_tok.length); 154144387Sharti packet_send(); 155144387Sharti } 156144387Sharti authctxt->postponed = 0; 157144387Sharti dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 158144387Sharti userauth_finish(authctxt, 0, "gssapi-with-mic"); 159144387Sharti } else { 160144387Sharti if (send_tok.length != 0) { 161144387Sharti packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); 162144387Sharti packet_put_string(send_tok.value, send_tok.length); 163144387Sharti packet_send(); 164144387Sharti } 165144387Sharti if (maj_status == GSS_S_COMPLETE) { 166144387Sharti dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 167144387Sharti if (flags & GSS_C_INTEG_FLAG) 168144387Sharti dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, 169144387Sharti &input_gssapi_mic); 170144387Sharti else 171144387Sharti dispatch_set( 172144387Sharti SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, 173144387Sharti &input_gssapi_exchange_complete); 174144387Sharti } 175144387Sharti } 176144387Sharti 177144387Sharti gss_release_buffer(&min_status, &send_tok); 178144387Sharti} 179144387Sharti 180144387Shartistatic void 181144387Shartiinput_gssapi_errtok(int type, u_int32_t plen, void *ctxt) 182144387Sharti{ 183144387Sharti Authctxt *authctxt = ctxt; 184144387Sharti Gssctxt *gssctxt; 185144387Sharti gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; 186144387Sharti gss_buffer_desc recv_tok; 187144387Sharti OM_uint32 maj_status; 188144387Sharti u_int len; 189144387Sharti 190144387Sharti if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) 191144387Sharti fatal("No authentication or GSSAPI context"); 192144387Sharti 193144387Sharti gssctxt = authctxt->methoddata; 1941590Srgrimes recv_tok.value = packet_get_string(&len); 1951590Srgrimes recv_tok.length = len; 1961590Srgrimes 1971590Srgrimes packet_check_eom(); 1981590Srgrimes 199104696Sjmallett /* Push the error token into GSSAPI to see what it says */ 200104696Sjmallett maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok, 201104696Sjmallett &send_tok, NULL)); 2021590Srgrimes 2031590Srgrimes xfree(recv_tok.value); 204146338Sharti 2051590Srgrimes /* We can't return anything to the client, even if we wanted to */ 2061590Srgrimes dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 2071590Srgrimes dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); 2081590Srgrimes 2091590Srgrimes /* The client will have already moved on to the next auth */ 2101590Srgrimes 2111590Srgrimes gss_release_buffer(&maj_status, &send_tok); 2121590Srgrimes} 213146338Sharti 214138512Sharti/* 2151590Srgrimes * This is called when the client thinks we've completed authentication. 216142173Sharti * It should only be enabled in the dispatch handler by the function above, 217142173Sharti * which only enables it once the GSSAPI exchange is complete. 218142173Sharti */ 219142173Sharti 220142173Shartistatic void 221142173Shartiinput_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) 222142173Sharti{ 223141270Sharti Authctxt *authctxt = ctxt; 2241590Srgrimes Gssctxt *gssctxt; 225142173Sharti int authenticated; 2268874Srgrimes 227142173Sharti if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) 2281590Srgrimes fatal("No authentication or GSSAPI context"); 229142173Sharti 230142173Sharti gssctxt = authctxt->methoddata; 231142173Sharti 232142173Sharti /* 233142173Sharti * We don't need to check the status, because we're only enabled in 234142173Sharti * the dispatcher once the exchange is complete 235142937Sharti */ 236142173Sharti 237142173Sharti packet_check_eom(); 2388874Srgrimes 239142173Sharti authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); 240142173Sharti 241146338Sharti authctxt->postponed = 0; 242142173Sharti dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 243142173Sharti dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); 2448874Srgrimes dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); 245142173Sharti dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); 246142173Sharti userauth_finish(authctxt, authenticated, "gssapi-with-mic"); 247142173Sharti} 248142173Sharti 249142173Shartistatic void 2501590Srgrimesinput_gssapi_mic(int type, u_int32_t plen, void *ctxt) 2511590Srgrimes{ 252142173Sharti Authctxt *authctxt = ctxt; 253142173Sharti Gssctxt *gssctxt; 254146027Sharti int authenticated = 0; 255142173Sharti Buffer b; 2561590Srgrimes gss_buffer_desc mic, gssbuf; 257142173Sharti u_int len; 258142173Sharti 259142173Sharti if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) 260142173Sharti fatal("No authentication or GSSAPI context"); 261142173Sharti 262142173Sharti gssctxt = authctxt->methoddata; 2631590Srgrimes 2641590Srgrimes mic.value = packet_get_string(&len); 265142173Sharti mic.length = len; 2661590Srgrimes 267142173Sharti ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, 2681590Srgrimes "gssapi-with-mic"); 269142173Sharti 270142173Sharti gssbuf.value = buffer_ptr(&b); 271143105Sharti gssbuf.length = buffer_len(&b); 2721590Srgrimes 2731590Srgrimes if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) 274142173Sharti authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); 275142173Sharti else 276142173Sharti logit("GSSAPI MIC check failed"); 277142173Sharti 278142173Sharti buffer_free(&b); 279142173Sharti xfree(mic.value); 280142173Sharti 281142173Sharti authctxt->postponed = 0; 282142173Sharti dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 283142937Sharti dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); 284142173Sharti dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); 285142173Sharti dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); 286142173Sharti userauth_finish(authctxt, authenticated, "gssapi-with-mic"); 287142173Sharti} 288142173Sharti 289142173ShartiAuthmethod method_gssapi = { 290146338Sharti "gssapi-with-mic", 291142173Sharti userauth_gssapi, 292142173Sharti &options.gss_authentication 293142173Sharti}; 294142173Sharti 295142173Sharti#endif /* GSSAPI */ 296142173Sharti