1a04a10f8SKris Kennaway /* 2a04a10f8SKris Kennaway * Copyright (c) 2000 Markus Friedl. All rights reserved. 3a04a10f8SKris Kennaway * 4a04a10f8SKris Kennaway * Redistribution and use in source and binary forms, with or without 5a04a10f8SKris Kennaway * modification, are permitted provided that the following conditions 6a04a10f8SKris Kennaway * are met: 7a04a10f8SKris Kennaway * 1. Redistributions of source code must retain the above copyright 8a04a10f8SKris Kennaway * notice, this list of conditions and the following disclaimer. 9a04a10f8SKris Kennaway * 2. Redistributions in binary form must reproduce the above copyright 10a04a10f8SKris Kennaway * notice, this list of conditions and the following disclaimer in the 11a04a10f8SKris Kennaway * documentation and/or other materials provided with the distribution. 12a04a10f8SKris Kennaway * 13a04a10f8SKris Kennaway * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14a04a10f8SKris Kennaway * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15a04a10f8SKris Kennaway * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16a04a10f8SKris Kennaway * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17a04a10f8SKris Kennaway * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18a04a10f8SKris Kennaway * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19a04a10f8SKris Kennaway * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20a04a10f8SKris Kennaway * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21a04a10f8SKris Kennaway * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22a04a10f8SKris Kennaway * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23a04a10f8SKris Kennaway */ 24c2d3a559SKris Kennaway 25a04a10f8SKris Kennaway #include "includes.h" 2680628bacSDag-Erling Smørgrav RCSID("$OpenBSD: auth2.c,v 1.93 2002/05/31 11:35:15 markus Exp $"); 27a04a10f8SKris Kennaway 28ca3176e7SBrian Feldman #include "ssh2.h" 29a04a10f8SKris Kennaway #include "xmalloc.h" 30a04a10f8SKris Kennaway #include "packet.h" 31ca3176e7SBrian Feldman #include "log.h" 32a04a10f8SKris Kennaway #include "servconf.h" 33a04a10f8SKris Kennaway #include "compat.h" 34a04a10f8SKris Kennaway #include "auth.h" 35a04a10f8SKris Kennaway #include "dispatch.h" 36ca3176e7SBrian Feldman #include "pathnames.h" 3780628bacSDag-Erling Smørgrav #include "monitor_wrap.h" 38a04a10f8SKris Kennaway 39a04a10f8SKris Kennaway /* import */ 40a04a10f8SKris Kennaway extern ServerOptions options; 41ca3176e7SBrian Feldman extern u_char *session_id2; 42a04a10f8SKris Kennaway extern int session_id2_len; 43a04a10f8SKris Kennaway 4480628bacSDag-Erling Smørgrav Authctxt *x_authctxt = NULL; 4509958426SBrian Feldman 4680628bacSDag-Erling Smørgrav /* methods */ 4780628bacSDag-Erling Smørgrav 4880628bacSDag-Erling Smørgrav extern Authmethod method_none; 4980628bacSDag-Erling Smørgrav extern Authmethod method_pubkey; 5080628bacSDag-Erling Smørgrav extern Authmethod method_passwd; 5180628bacSDag-Erling Smørgrav extern Authmethod method_kbdint; 5280628bacSDag-Erling Smørgrav extern Authmethod method_hostbased; 5380628bacSDag-Erling Smørgrav 5480628bacSDag-Erling Smørgrav Authmethod *authmethods[] = { 5580628bacSDag-Erling Smørgrav &method_none, 5680628bacSDag-Erling Smørgrav &method_pubkey, 5780628bacSDag-Erling Smørgrav &method_passwd, 5880628bacSDag-Erling Smørgrav &method_kbdint, 5980628bacSDag-Erling Smørgrav &method_hostbased, 6080628bacSDag-Erling Smørgrav NULL 6109958426SBrian Feldman }; 6209958426SBrian Feldman 63a04a10f8SKris Kennaway /* protocol */ 64a04a10f8SKris Kennaway 65af12a3e7SDag-Erling Smørgrav static void input_service_request(int, u_int32_t, void *); 66af12a3e7SDag-Erling Smørgrav static void input_userauth_request(int, u_int32_t, void *); 67a04a10f8SKris Kennaway 68a04a10f8SKris Kennaway /* helper */ 69af12a3e7SDag-Erling Smørgrav static Authmethod *authmethod_lookup(const char *); 70af12a3e7SDag-Erling Smørgrav static char *authmethods_get(void); 7180628bacSDag-Erling Smørgrav int user_key_allowed(struct passwd *, Key *); 7280628bacSDag-Erling Smørgrav int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); 73a04a10f8SKris Kennaway 74a04a10f8SKris Kennaway /* 7509958426SBrian Feldman * loop until authctxt->success == TRUE 76a04a10f8SKris Kennaway */ 77a04a10f8SKris Kennaway 7880628bacSDag-Erling Smørgrav Authctxt * 79af12a3e7SDag-Erling Smørgrav do_authentication2(void) 80a04a10f8SKris Kennaway { 81ca3176e7SBrian Feldman Authctxt *authctxt = authctxt_new(); 82ca3176e7SBrian Feldman 8309958426SBrian Feldman x_authctxt = authctxt; /*XXX*/ 8409958426SBrian Feldman 85af12a3e7SDag-Erling Smørgrav /* challenge-response is implemented via keyboard interactive */ 86af12a3e7SDag-Erling Smørgrav if (options.challenge_response_authentication) 87ca3176e7SBrian Feldman options.kbd_interactive_authentication = 1; 88989dd127SDag-Erling Smørgrav if (options.pam_authentication_via_kbd_int) 89989dd127SDag-Erling Smørgrav options.kbd_interactive_authentication = 1; 90989dd127SDag-Erling Smørgrav if (use_privsep) 91989dd127SDag-Erling Smørgrav options.pam_authentication_via_kbd_int = 0; 92ca3176e7SBrian Feldman 93af12a3e7SDag-Erling Smørgrav dispatch_init(&dispatch_protocol_error); 94a04a10f8SKris Kennaway dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); 9509958426SBrian Feldman dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); 9680628bacSDag-Erling Smørgrav 9780628bacSDag-Erling Smørgrav return (authctxt); 98a04a10f8SKris Kennaway } 99a04a10f8SKris Kennaway 100af12a3e7SDag-Erling Smørgrav static void 101af12a3e7SDag-Erling Smørgrav input_service_request(int type, u_int32_t seq, void *ctxt) 102a04a10f8SKris Kennaway { 10309958426SBrian Feldman Authctxt *authctxt = ctxt; 104ca3176e7SBrian Feldman u_int len; 105a04a10f8SKris Kennaway int accept = 0; 106a04a10f8SKris Kennaway char *service = packet_get_string(&len); 107af12a3e7SDag-Erling Smørgrav packet_check_eom(); 108a04a10f8SKris Kennaway 10909958426SBrian Feldman if (authctxt == NULL) 11009958426SBrian Feldman fatal("input_service_request: no authctxt"); 11109958426SBrian Feldman 112a04a10f8SKris Kennaway if (strcmp(service, "ssh-userauth") == 0) { 11309958426SBrian Feldman if (!authctxt->success) { 114a04a10f8SKris Kennaway accept = 1; 115a04a10f8SKris Kennaway /* now we can handle user-auth requests */ 116a04a10f8SKris Kennaway dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); 117a04a10f8SKris Kennaway } 118a04a10f8SKris Kennaway } 119a04a10f8SKris Kennaway /* XXX all other service requests are denied */ 120a04a10f8SKris Kennaway 121a04a10f8SKris Kennaway if (accept) { 122a04a10f8SKris Kennaway packet_start(SSH2_MSG_SERVICE_ACCEPT); 123a04a10f8SKris Kennaway packet_put_cstring(service); 124a04a10f8SKris Kennaway packet_send(); 125a04a10f8SKris Kennaway packet_write_wait(); 126a04a10f8SKris Kennaway } else { 127a04a10f8SKris Kennaway debug("bad service request %s", service); 128a04a10f8SKris Kennaway packet_disconnect("bad service request %s", service); 129a04a10f8SKris Kennaway } 130a04a10f8SKris Kennaway xfree(service); 131a04a10f8SKris Kennaway } 132a04a10f8SKris Kennaway 133af12a3e7SDag-Erling Smørgrav static void 134af12a3e7SDag-Erling Smørgrav input_userauth_request(int type, u_int32_t seq, void *ctxt) 135a04a10f8SKris Kennaway { 13609958426SBrian Feldman Authctxt *authctxt = ctxt; 13709958426SBrian Feldman Authmethod *m = NULL; 138ca3176e7SBrian Feldman char *user, *service, *method, *style = NULL; 139a04a10f8SKris Kennaway int authenticated = 0; 140a04a10f8SKris Kennaway 14109958426SBrian Feldman if (authctxt == NULL) 14209958426SBrian Feldman fatal("input_userauth_request: no authctxt"); 143a04a10f8SKris Kennaway 14409958426SBrian Feldman user = packet_get_string(NULL); 14509958426SBrian Feldman service = packet_get_string(NULL); 14609958426SBrian Feldman method = packet_get_string(NULL); 147a04a10f8SKris Kennaway debug("userauth-request for user %s service %s method %s", user, service, method); 148ca3176e7SBrian Feldman debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); 149a04a10f8SKris Kennaway 150ca3176e7SBrian Feldman if ((style = strchr(user, ':')) != NULL) 151ca3176e7SBrian Feldman *style++ = 0; 152ca3176e7SBrian Feldman 153ca3176e7SBrian Feldman if (authctxt->attempt++ == 0) { 15409958426SBrian Feldman /* setup auth context */ 15580628bacSDag-Erling Smørgrav authctxt->pw = PRIVSEP(getpwnamallow(user)); 15680628bacSDag-Erling Smørgrav if (authctxt->pw && strcmp(service, "ssh-connection")==0) { 15709958426SBrian Feldman authctxt->valid = 1; 15809958426SBrian Feldman debug2("input_userauth_request: setting up authctxt for %s", user); 15909958426SBrian Feldman #ifdef USE_PAM 160989dd127SDag-Erling Smørgrav PRIVSEP(start_pam(authctxt->pw->pw_name)); 16109958426SBrian Feldman #endif 16209958426SBrian Feldman } else { 16309958426SBrian Feldman log("input_userauth_request: illegal user %s", user); 164989dd127SDag-Erling Smørgrav #ifdef USE_PAM 165989dd127SDag-Erling Smørgrav PRIVSEP(start_pam("NOUSER")); 166989dd127SDag-Erling Smørgrav #endif 167a04a10f8SKris Kennaway } 16880628bacSDag-Erling Smørgrav setproctitle("%s%s", authctxt->pw ? user : "unknown", 16980628bacSDag-Erling Smørgrav use_privsep ? " [net]" : ""); 17009958426SBrian Feldman authctxt->user = xstrdup(user); 17109958426SBrian Feldman authctxt->service = xstrdup(service); 172af12a3e7SDag-Erling Smørgrav authctxt->style = style ? xstrdup(style) : NULL; 17380628bacSDag-Erling Smørgrav if (use_privsep) 17480628bacSDag-Erling Smørgrav mm_inform_authserv(service, style); 175af12a3e7SDag-Erling Smørgrav } else if (strcmp(user, authctxt->user) != 0 || 17609958426SBrian Feldman strcmp(service, authctxt->service) != 0) { 177af12a3e7SDag-Erling Smørgrav packet_disconnect("Change of username or service not allowed: " 178af12a3e7SDag-Erling Smørgrav "(%s,%s) -> (%s,%s)", 179af12a3e7SDag-Erling Smørgrav authctxt->user, authctxt->service, user, service); 180a04a10f8SKris Kennaway } 181ca3176e7SBrian Feldman /* reset state */ 182af12a3e7SDag-Erling Smørgrav auth2_challenge_stop(authctxt); 183ca3176e7SBrian Feldman authctxt->postponed = 0; 18403e72be8SBrian Feldman 185ca3176e7SBrian Feldman /* try to authenticate user */ 18609958426SBrian Feldman m = authmethod_lookup(method); 18709958426SBrian Feldman if (m != NULL) { 18809958426SBrian Feldman debug2("input_userauth_request: try method %s", method); 18909958426SBrian Feldman authenticated = m->userauth(authctxt); 19009958426SBrian Feldman } 191ca3176e7SBrian Feldman userauth_finish(authctxt, authenticated, method); 19209958426SBrian Feldman 19309958426SBrian Feldman xfree(service); 19409958426SBrian Feldman xfree(user); 19509958426SBrian Feldman xfree(method); 19609958426SBrian Feldman } 19709958426SBrian Feldman 198ca3176e7SBrian Feldman void 199ca3176e7SBrian Feldman userauth_finish(Authctxt *authctxt, int authenticated, char *method) 200ca3176e7SBrian Feldman { 201af12a3e7SDag-Erling Smørgrav char *methods; 202af12a3e7SDag-Erling Smørgrav 203ca3176e7SBrian Feldman if (!authctxt->valid && authenticated) 204ca3176e7SBrian Feldman fatal("INTERNAL ERROR: authenticated invalid user %s", 205ca3176e7SBrian Feldman authctxt->user); 206ca3176e7SBrian Feldman 207ca3176e7SBrian Feldman /* Special handling for root */ 208ca3176e7SBrian Feldman if (authenticated && authctxt->pw->pw_uid == 0 && 209ca3176e7SBrian Feldman !auth_root_allowed(method)) 210ca3176e7SBrian Feldman authenticated = 0; 211ca3176e7SBrian Feldman 212989dd127SDag-Erling Smørgrav #ifdef USE_PAM 213989dd127SDag-Erling Smørgrav if (!use_privsep && authenticated && authctxt->user && 214989dd127SDag-Erling Smørgrav !do_pam_account(authctxt->user, NULL)) 215989dd127SDag-Erling Smørgrav authenticated = 0; 216989dd127SDag-Erling Smørgrav #endif /* USE_PAM */ 217989dd127SDag-Erling Smørgrav 218ca3176e7SBrian Feldman /* Log before sending the reply */ 219ca3176e7SBrian Feldman auth_log(authctxt, authenticated, method, " ssh2"); 220ca3176e7SBrian Feldman 221af12a3e7SDag-Erling Smørgrav if (authctxt->postponed) 222af12a3e7SDag-Erling Smørgrav return; 223af12a3e7SDag-Erling Smørgrav 224af12a3e7SDag-Erling Smørgrav /* XXX todo: check if multiple auth methods are needed */ 225af12a3e7SDag-Erling Smørgrav if (authenticated == 1) { 226af12a3e7SDag-Erling Smørgrav /* turn off userauth */ 227af12a3e7SDag-Erling Smørgrav dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); 228af12a3e7SDag-Erling Smørgrav packet_start(SSH2_MSG_USERAUTH_SUCCESS); 229af12a3e7SDag-Erling Smørgrav packet_send(); 230af12a3e7SDag-Erling Smørgrav packet_write_wait(); 231af12a3e7SDag-Erling Smørgrav /* now we can break out */ 232af12a3e7SDag-Erling Smørgrav authctxt->success = 1; 233af12a3e7SDag-Erling Smørgrav } else { 234989dd127SDag-Erling Smørgrav if (authctxt->failures++ > AUTH_FAIL_MAX) { 235989dd127SDag-Erling Smørgrav #ifdef WITH_AIXAUTHENTICATE 236989dd127SDag-Erling Smørgrav /* XXX: privsep */ 237989dd127SDag-Erling Smørgrav loginfailed(authctxt->user, 238989dd127SDag-Erling Smørgrav get_canonical_hostname(options.verify_reverse_mapping), 239989dd127SDag-Erling Smørgrav "ssh"); 240989dd127SDag-Erling Smørgrav #endif /* WITH_AIXAUTHENTICATE */ 241af12a3e7SDag-Erling Smørgrav packet_disconnect(AUTH_FAIL_MSG, authctxt->user); 242989dd127SDag-Erling Smørgrav } 243af12a3e7SDag-Erling Smørgrav methods = authmethods_get(); 244af12a3e7SDag-Erling Smørgrav packet_start(SSH2_MSG_USERAUTH_FAILURE); 245af12a3e7SDag-Erling Smørgrav packet_put_cstring(methods); 246af12a3e7SDag-Erling Smørgrav packet_put_char(0); /* XXX partial success, unused */ 247af12a3e7SDag-Erling Smørgrav packet_send(); 248af12a3e7SDag-Erling Smørgrav packet_write_wait(); 249af12a3e7SDag-Erling Smørgrav xfree(methods); 250af12a3e7SDag-Erling Smørgrav } 251ca3176e7SBrian Feldman } 25209958426SBrian Feldman 25309958426SBrian Feldman /* get current user */ 254a04a10f8SKris Kennaway 255a04a10f8SKris Kennaway struct passwd* 256a04a10f8SKris Kennaway auth_get_user(void) 257a04a10f8SKris Kennaway { 25809958426SBrian Feldman return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL; 259a04a10f8SKris Kennaway } 260a04a10f8SKris Kennaway 26109958426SBrian Feldman #define DELIM "," 26209958426SBrian Feldman 263af12a3e7SDag-Erling Smørgrav static char * 26409958426SBrian Feldman authmethods_get(void) 265a04a10f8SKris Kennaway { 266af12a3e7SDag-Erling Smørgrav Buffer b; 26709958426SBrian Feldman char *list; 26880628bacSDag-Erling Smørgrav int i; 269a04a10f8SKris Kennaway 270af12a3e7SDag-Erling Smørgrav buffer_init(&b); 27180628bacSDag-Erling Smørgrav for (i = 0; authmethods[i] != NULL; i++) { 27280628bacSDag-Erling Smørgrav if (strcmp(authmethods[i]->name, "none") == 0) 27309958426SBrian Feldman continue; 27480628bacSDag-Erling Smørgrav if (authmethods[i]->enabled != NULL && 27580628bacSDag-Erling Smørgrav *(authmethods[i]->enabled) != 0) { 276af12a3e7SDag-Erling Smørgrav if (buffer_len(&b) > 0) 277af12a3e7SDag-Erling Smørgrav buffer_append(&b, ",", 1); 27880628bacSDag-Erling Smørgrav buffer_append(&b, authmethods[i]->name, 27980628bacSDag-Erling Smørgrav strlen(authmethods[i]->name)); 28009958426SBrian Feldman } 28109958426SBrian Feldman } 282af12a3e7SDag-Erling Smørgrav buffer_append(&b, "\0", 1); 283af12a3e7SDag-Erling Smørgrav list = xstrdup(buffer_ptr(&b)); 284af12a3e7SDag-Erling Smørgrav buffer_free(&b); 28509958426SBrian Feldman return list; 28609958426SBrian Feldman } 28709958426SBrian Feldman 288af12a3e7SDag-Erling Smørgrav static Authmethod * 28909958426SBrian Feldman authmethod_lookup(const char *name) 29009958426SBrian Feldman { 29180628bacSDag-Erling Smørgrav int i; 29280628bacSDag-Erling Smørgrav 29309958426SBrian Feldman if (name != NULL) 29480628bacSDag-Erling Smørgrav for (i = 0; authmethods[i] != NULL; i++) 29580628bacSDag-Erling Smørgrav if (authmethods[i]->enabled != NULL && 29680628bacSDag-Erling Smørgrav *(authmethods[i]->enabled) != 0 && 29780628bacSDag-Erling Smørgrav strcmp(name, authmethods[i]->name) == 0) 29880628bacSDag-Erling Smørgrav return authmethods[i]; 29980628bacSDag-Erling Smørgrav debug2("Unrecognized authentication method name: %s", 30080628bacSDag-Erling Smørgrav name ? name : "NULL"); 301a04a10f8SKris Kennaway return NULL; 302a04a10f8SKris Kennaway } 303