1043840dfSDag-Erling Smørgrav /* $OpenBSD: auth2-gss.c,v 1.10 2005/07/17 07:17:54 djm Exp $ */ 2d95e11bfSDag-Erling Smørgrav 3d95e11bfSDag-Erling Smørgrav /* 4d95e11bfSDag-Erling Smørgrav * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. 5d95e11bfSDag-Erling Smørgrav * 6d95e11bfSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 7d95e11bfSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 8d95e11bfSDag-Erling Smørgrav * are met: 9d95e11bfSDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 10d95e11bfSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 11d95e11bfSDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 12d95e11bfSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 13d95e11bfSDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 14d95e11bfSDag-Erling Smørgrav * 15d95e11bfSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR 16d95e11bfSDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17d95e11bfSDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18d95e11bfSDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19d95e11bfSDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20d95e11bfSDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21d95e11bfSDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22d95e11bfSDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23d95e11bfSDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24d95e11bfSDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25d95e11bfSDag-Erling Smørgrav */ 26d95e11bfSDag-Erling Smørgrav 27d95e11bfSDag-Erling Smørgrav #include "includes.h" 28d95e11bfSDag-Erling Smørgrav 29d95e11bfSDag-Erling Smørgrav #ifdef GSSAPI 30d95e11bfSDag-Erling Smørgrav 31d95e11bfSDag-Erling Smørgrav #include "auth.h" 32d95e11bfSDag-Erling Smørgrav #include "ssh2.h" 33d95e11bfSDag-Erling Smørgrav #include "xmalloc.h" 34d95e11bfSDag-Erling Smørgrav #include "log.h" 35d95e11bfSDag-Erling Smørgrav #include "dispatch.h" 36d95e11bfSDag-Erling Smørgrav #include "servconf.h" 37d95e11bfSDag-Erling Smørgrav #include "compat.h" 38d95e11bfSDag-Erling Smørgrav #include "packet.h" 39d95e11bfSDag-Erling Smørgrav #include "monitor_wrap.h" 40d95e11bfSDag-Erling Smørgrav 41d95e11bfSDag-Erling Smørgrav #include "ssh-gss.h" 42d95e11bfSDag-Erling Smørgrav 43d95e11bfSDag-Erling Smørgrav extern ServerOptions options; 44d95e11bfSDag-Erling Smørgrav 45d95e11bfSDag-Erling Smørgrav static void input_gssapi_token(int type, u_int32_t plen, void *ctxt); 46efcad6b7SDag-Erling Smørgrav static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); 47d95e11bfSDag-Erling Smørgrav static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); 48d95e11bfSDag-Erling Smørgrav static void input_gssapi_errtok(int, u_int32_t, void *); 49d95e11bfSDag-Erling Smørgrav 50d95e11bfSDag-Erling Smørgrav /* 51d95e11bfSDag-Erling Smørgrav * We only support those mechanisms that we know about (ie ones that we know 52d95e11bfSDag-Erling Smørgrav * how to check local user kuserok and the like 53d95e11bfSDag-Erling Smørgrav */ 54d95e11bfSDag-Erling Smørgrav static int 55d95e11bfSDag-Erling Smørgrav userauth_gssapi(Authctxt *authctxt) 56d95e11bfSDag-Erling Smørgrav { 57d74d50a8SDag-Erling Smørgrav gss_OID_desc goid = {0, NULL}; 58d95e11bfSDag-Erling Smørgrav Gssctxt *ctxt = NULL; 59d95e11bfSDag-Erling Smørgrav int mechs; 60d95e11bfSDag-Erling Smørgrav gss_OID_set supported; 61d95e11bfSDag-Erling Smørgrav int present; 62d95e11bfSDag-Erling Smørgrav OM_uint32 ms; 63d95e11bfSDag-Erling Smørgrav u_int len; 64043840dfSDag-Erling Smørgrav u_char *doid = NULL; 65d95e11bfSDag-Erling Smørgrav 66d95e11bfSDag-Erling Smørgrav if (!authctxt->valid || authctxt->user == NULL) 67d95e11bfSDag-Erling Smørgrav return (0); 68d95e11bfSDag-Erling Smørgrav 69d95e11bfSDag-Erling Smørgrav mechs = packet_get_int(); 70d95e11bfSDag-Erling Smørgrav if (mechs == 0) { 71d95e11bfSDag-Erling Smørgrav debug("Mechanism negotiation is not supported"); 72d95e11bfSDag-Erling Smørgrav return (0); 73d95e11bfSDag-Erling Smørgrav } 74d95e11bfSDag-Erling Smørgrav 75d95e11bfSDag-Erling Smørgrav ssh_gssapi_supported_oids(&supported); 76d95e11bfSDag-Erling Smørgrav do { 77d95e11bfSDag-Erling Smørgrav mechs--; 78d95e11bfSDag-Erling Smørgrav 79d95e11bfSDag-Erling Smørgrav if (doid) 80d95e11bfSDag-Erling Smørgrav xfree(doid); 81d95e11bfSDag-Erling Smørgrav 82efcad6b7SDag-Erling Smørgrav present = 0; 83d95e11bfSDag-Erling Smørgrav doid = packet_get_string(&len); 84d95e11bfSDag-Erling Smørgrav 85043840dfSDag-Erling Smørgrav if (len > 2 && doid[0] == SSH_GSS_OIDTYPE && 86efcad6b7SDag-Erling Smørgrav doid[1] == len - 2) { 87d74d50a8SDag-Erling Smørgrav goid.elements = doid + 2; 88d74d50a8SDag-Erling Smørgrav goid.length = len - 2; 89d74d50a8SDag-Erling Smørgrav gss_test_oid_set_member(&ms, &goid, supported, 90efcad6b7SDag-Erling Smørgrav &present); 91efcad6b7SDag-Erling Smørgrav } else { 92efcad6b7SDag-Erling Smørgrav logit("Badly formed OID received"); 93d95e11bfSDag-Erling Smørgrav } 94d95e11bfSDag-Erling Smørgrav } while (mechs > 0 && !present); 95d95e11bfSDag-Erling Smørgrav 96d95e11bfSDag-Erling Smørgrav gss_release_oid_set(&ms, &supported); 97d95e11bfSDag-Erling Smørgrav 98d95e11bfSDag-Erling Smørgrav if (!present) { 99d95e11bfSDag-Erling Smørgrav xfree(doid); 100d95e11bfSDag-Erling Smørgrav return (0); 101d95e11bfSDag-Erling Smørgrav } 102d95e11bfSDag-Erling Smørgrav 103d74d50a8SDag-Erling Smørgrav if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) { 104d95e11bfSDag-Erling Smørgrav xfree(doid); 105d95e11bfSDag-Erling Smørgrav return (0); 106d95e11bfSDag-Erling Smørgrav } 107d95e11bfSDag-Erling Smørgrav 108d95e11bfSDag-Erling Smørgrav authctxt->methoddata=(void *)ctxt; 109d95e11bfSDag-Erling Smørgrav 110d95e11bfSDag-Erling Smørgrav packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE); 111d95e11bfSDag-Erling Smørgrav 112efcad6b7SDag-Erling Smørgrav /* Return the OID that we received */ 113d95e11bfSDag-Erling Smørgrav packet_put_string(doid, len); 114d95e11bfSDag-Erling Smørgrav 115d95e11bfSDag-Erling Smørgrav packet_send(); 116d95e11bfSDag-Erling Smørgrav xfree(doid); 117d95e11bfSDag-Erling Smørgrav 118d95e11bfSDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); 119d95e11bfSDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); 120d95e11bfSDag-Erling Smørgrav authctxt->postponed = 1; 121d95e11bfSDag-Erling Smørgrav 122d95e11bfSDag-Erling Smørgrav return (0); 123d95e11bfSDag-Erling Smørgrav } 124d95e11bfSDag-Erling Smørgrav 125d95e11bfSDag-Erling Smørgrav static void 126d95e11bfSDag-Erling Smørgrav input_gssapi_token(int type, u_int32_t plen, void *ctxt) 127d95e11bfSDag-Erling Smørgrav { 128d95e11bfSDag-Erling Smørgrav Authctxt *authctxt = ctxt; 129d95e11bfSDag-Erling Smørgrav Gssctxt *gssctxt; 130d95e11bfSDag-Erling Smørgrav gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; 131d95e11bfSDag-Erling Smørgrav gss_buffer_desc recv_tok; 132efcad6b7SDag-Erling Smørgrav OM_uint32 maj_status, min_status, flags; 133d95e11bfSDag-Erling Smørgrav u_int len; 134d95e11bfSDag-Erling Smørgrav 135d95e11bfSDag-Erling Smørgrav if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) 136d95e11bfSDag-Erling Smørgrav fatal("No authentication or GSSAPI context"); 137d95e11bfSDag-Erling Smørgrav 138d95e11bfSDag-Erling Smørgrav gssctxt = authctxt->methoddata; 139d95e11bfSDag-Erling Smørgrav recv_tok.value = packet_get_string(&len); 140d95e11bfSDag-Erling Smørgrav recv_tok.length = len; /* u_int vs. size_t */ 141d95e11bfSDag-Erling Smørgrav 142d95e11bfSDag-Erling Smørgrav packet_check_eom(); 143d95e11bfSDag-Erling Smørgrav 144d95e11bfSDag-Erling Smørgrav maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok, 145efcad6b7SDag-Erling Smørgrav &send_tok, &flags)); 146d95e11bfSDag-Erling Smørgrav 147d95e11bfSDag-Erling Smørgrav xfree(recv_tok.value); 148d95e11bfSDag-Erling Smørgrav 149d95e11bfSDag-Erling Smørgrav if (GSS_ERROR(maj_status)) { 150d95e11bfSDag-Erling Smørgrav if (send_tok.length != 0) { 151d95e11bfSDag-Erling Smørgrav packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK); 152d95e11bfSDag-Erling Smørgrav packet_put_string(send_tok.value, send_tok.length); 153d95e11bfSDag-Erling Smørgrav packet_send(); 154d95e11bfSDag-Erling Smørgrav } 155d95e11bfSDag-Erling Smørgrav authctxt->postponed = 0; 156d95e11bfSDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 157efcad6b7SDag-Erling Smørgrav userauth_finish(authctxt, 0, "gssapi-with-mic"); 158d95e11bfSDag-Erling Smørgrav } else { 159d95e11bfSDag-Erling Smørgrav if (send_tok.length != 0) { 160d95e11bfSDag-Erling Smørgrav packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); 161d95e11bfSDag-Erling Smørgrav packet_put_string(send_tok.value, send_tok.length); 162d95e11bfSDag-Erling Smørgrav packet_send(); 163d95e11bfSDag-Erling Smørgrav } 164d95e11bfSDag-Erling Smørgrav if (maj_status == GSS_S_COMPLETE) { 165d95e11bfSDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 166efcad6b7SDag-Erling Smørgrav if (flags & GSS_C_INTEG_FLAG) 167efcad6b7SDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, 168efcad6b7SDag-Erling Smørgrav &input_gssapi_mic); 169efcad6b7SDag-Erling Smørgrav else 170efcad6b7SDag-Erling Smørgrav dispatch_set( 171efcad6b7SDag-Erling Smørgrav SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, 172d95e11bfSDag-Erling Smørgrav &input_gssapi_exchange_complete); 173d95e11bfSDag-Erling Smørgrav } 174d95e11bfSDag-Erling Smørgrav } 175d95e11bfSDag-Erling Smørgrav 176d95e11bfSDag-Erling Smørgrav gss_release_buffer(&min_status, &send_tok); 177d95e11bfSDag-Erling Smørgrav } 178d95e11bfSDag-Erling Smørgrav 179d95e11bfSDag-Erling Smørgrav static void 180d95e11bfSDag-Erling Smørgrav input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) 181d95e11bfSDag-Erling Smørgrav { 182d95e11bfSDag-Erling Smørgrav Authctxt *authctxt = ctxt; 183d95e11bfSDag-Erling Smørgrav Gssctxt *gssctxt; 184d95e11bfSDag-Erling Smørgrav gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; 185d95e11bfSDag-Erling Smørgrav gss_buffer_desc recv_tok; 186d95e11bfSDag-Erling Smørgrav OM_uint32 maj_status; 187d95e11bfSDag-Erling Smørgrav u_int len; 188d95e11bfSDag-Erling Smørgrav 189d95e11bfSDag-Erling Smørgrav if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) 190d95e11bfSDag-Erling Smørgrav fatal("No authentication or GSSAPI context"); 191d95e11bfSDag-Erling Smørgrav 192d95e11bfSDag-Erling Smørgrav gssctxt = authctxt->methoddata; 193d95e11bfSDag-Erling Smørgrav recv_tok.value = packet_get_string(&len); 194d95e11bfSDag-Erling Smørgrav recv_tok.length = len; 195d95e11bfSDag-Erling Smørgrav 196d95e11bfSDag-Erling Smørgrav packet_check_eom(); 197d95e11bfSDag-Erling Smørgrav 198d95e11bfSDag-Erling Smørgrav /* Push the error token into GSSAPI to see what it says */ 199d95e11bfSDag-Erling Smørgrav maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok, 200d95e11bfSDag-Erling Smørgrav &send_tok, NULL)); 201d95e11bfSDag-Erling Smørgrav 202d95e11bfSDag-Erling Smørgrav xfree(recv_tok.value); 203d95e11bfSDag-Erling Smørgrav 204d95e11bfSDag-Erling Smørgrav /* We can't return anything to the client, even if we wanted to */ 205d95e11bfSDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 206d95e11bfSDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); 207d95e11bfSDag-Erling Smørgrav 208d95e11bfSDag-Erling Smørgrav /* The client will have already moved on to the next auth */ 209d95e11bfSDag-Erling Smørgrav 210d95e11bfSDag-Erling Smørgrav gss_release_buffer(&maj_status, &send_tok); 211d95e11bfSDag-Erling Smørgrav } 212d95e11bfSDag-Erling Smørgrav 213d95e11bfSDag-Erling Smørgrav /* 214d95e11bfSDag-Erling Smørgrav * This is called when the client thinks we've completed authentication. 215d95e11bfSDag-Erling Smørgrav * It should only be enabled in the dispatch handler by the function above, 216d95e11bfSDag-Erling Smørgrav * which only enables it once the GSSAPI exchange is complete. 217d95e11bfSDag-Erling Smørgrav */ 218d95e11bfSDag-Erling Smørgrav 219d95e11bfSDag-Erling Smørgrav static void 220d95e11bfSDag-Erling Smørgrav input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) 221d95e11bfSDag-Erling Smørgrav { 222d95e11bfSDag-Erling Smørgrav Authctxt *authctxt = ctxt; 223d95e11bfSDag-Erling Smørgrav Gssctxt *gssctxt; 224d95e11bfSDag-Erling Smørgrav int authenticated; 225d95e11bfSDag-Erling Smørgrav 226d95e11bfSDag-Erling Smørgrav if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) 227d95e11bfSDag-Erling Smørgrav fatal("No authentication or GSSAPI context"); 228d95e11bfSDag-Erling Smørgrav 229d95e11bfSDag-Erling Smørgrav gssctxt = authctxt->methoddata; 230d95e11bfSDag-Erling Smørgrav 231d95e11bfSDag-Erling Smørgrav /* 232efcad6b7SDag-Erling Smørgrav * We don't need to check the status, because we're only enabled in 233efcad6b7SDag-Erling Smørgrav * the dispatcher once the exchange is complete 234d95e11bfSDag-Erling Smørgrav */ 235d95e11bfSDag-Erling Smørgrav 236d95e11bfSDag-Erling Smørgrav packet_check_eom(); 237d95e11bfSDag-Erling Smørgrav 238d95e11bfSDag-Erling Smørgrav authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); 239d95e11bfSDag-Erling Smørgrav 240d95e11bfSDag-Erling Smørgrav authctxt->postponed = 0; 241d95e11bfSDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 242d95e11bfSDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); 243efcad6b7SDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); 244d95e11bfSDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); 245efcad6b7SDag-Erling Smørgrav userauth_finish(authctxt, authenticated, "gssapi-with-mic"); 246efcad6b7SDag-Erling Smørgrav } 247efcad6b7SDag-Erling Smørgrav 248efcad6b7SDag-Erling Smørgrav static void 249efcad6b7SDag-Erling Smørgrav input_gssapi_mic(int type, u_int32_t plen, void *ctxt) 250efcad6b7SDag-Erling Smørgrav { 251efcad6b7SDag-Erling Smørgrav Authctxt *authctxt = ctxt; 252efcad6b7SDag-Erling Smørgrav Gssctxt *gssctxt; 253efcad6b7SDag-Erling Smørgrav int authenticated = 0; 254efcad6b7SDag-Erling Smørgrav Buffer b; 255efcad6b7SDag-Erling Smørgrav gss_buffer_desc mic, gssbuf; 256efcad6b7SDag-Erling Smørgrav u_int len; 257efcad6b7SDag-Erling Smørgrav 258efcad6b7SDag-Erling Smørgrav if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) 259efcad6b7SDag-Erling Smørgrav fatal("No authentication or GSSAPI context"); 260efcad6b7SDag-Erling Smørgrav 261efcad6b7SDag-Erling Smørgrav gssctxt = authctxt->methoddata; 262efcad6b7SDag-Erling Smørgrav 263efcad6b7SDag-Erling Smørgrav mic.value = packet_get_string(&len); 264efcad6b7SDag-Erling Smørgrav mic.length = len; 265efcad6b7SDag-Erling Smørgrav 266efcad6b7SDag-Erling Smørgrav ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, 267efcad6b7SDag-Erling Smørgrav "gssapi-with-mic"); 268efcad6b7SDag-Erling Smørgrav 269efcad6b7SDag-Erling Smørgrav gssbuf.value = buffer_ptr(&b); 270efcad6b7SDag-Erling Smørgrav gssbuf.length = buffer_len(&b); 271efcad6b7SDag-Erling Smørgrav 272efcad6b7SDag-Erling Smørgrav if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) 273efcad6b7SDag-Erling Smørgrav authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); 274efcad6b7SDag-Erling Smørgrav else 275efcad6b7SDag-Erling Smørgrav logit("GSSAPI MIC check failed"); 276efcad6b7SDag-Erling Smørgrav 277efcad6b7SDag-Erling Smørgrav buffer_free(&b); 278efcad6b7SDag-Erling Smørgrav xfree(mic.value); 279efcad6b7SDag-Erling Smørgrav 280efcad6b7SDag-Erling Smørgrav authctxt->postponed = 0; 281efcad6b7SDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 282efcad6b7SDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); 283efcad6b7SDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); 284efcad6b7SDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); 285efcad6b7SDag-Erling Smørgrav userauth_finish(authctxt, authenticated, "gssapi-with-mic"); 286d95e11bfSDag-Erling Smørgrav } 287d95e11bfSDag-Erling Smørgrav 288d95e11bfSDag-Erling Smørgrav Authmethod method_gssapi = { 289efcad6b7SDag-Erling Smørgrav "gssapi-with-mic", 290d95e11bfSDag-Erling Smørgrav userauth_gssapi, 291d95e11bfSDag-Erling Smørgrav &options.gss_authentication 292d95e11bfSDag-Erling Smørgrav }; 293d95e11bfSDag-Erling Smørgrav 294d95e11bfSDag-Erling Smørgrav #endif /* GSSAPI */ 295