Annotation of src/usr.bin/ssh/auth1.c, Revision 1.1
1.1 ! markus 1: /*
! 2: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
! 3: * All rights reserved
! 4: */
! 5:
! 6: #include "includes.h"
! 7: RCSID("$OpenBSD: auth1.c,v 1.1 2000/04/18 15:01:30 markus Exp $");
! 8:
! 9: #include "xmalloc.h"
! 10: #include "rsa.h"
! 11: #include "ssh.h"
! 12: #include "packet.h"
! 13: #include "buffer.h"
! 14: #include "cipher.h"
! 15: #include "mpaux.h"
! 16: #include "servconf.h"
! 17: #include "compat.h"
! 18: #include "auth.h"
! 19: #include "session.h"
! 20:
! 21: /* import */
! 22: extern ServerOptions options;
! 23: extern char *forced_command;
! 24:
! 25: /*
! 26: * convert ssh auth msg type into description
! 27: */
! 28: char *
! 29: get_authname(int type)
! 30: {
! 31: static char buf[1024];
! 32: switch (type) {
! 33: case SSH_CMSG_AUTH_PASSWORD:
! 34: return "password";
! 35: case SSH_CMSG_AUTH_RSA:
! 36: return "rsa";
! 37: case SSH_CMSG_AUTH_RHOSTS_RSA:
! 38: return "rhosts-rsa";
! 39: case SSH_CMSG_AUTH_RHOSTS:
! 40: return "rhosts";
! 41: #ifdef KRB4
! 42: case SSH_CMSG_AUTH_KERBEROS:
! 43: return "kerberos";
! 44: #endif
! 45: #ifdef SKEY
! 46: case SSH_CMSG_AUTH_TIS_RESPONSE:
! 47: return "s/key";
! 48: #endif
! 49: }
! 50: snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
! 51: return buf;
! 52: }
! 53:
! 54: /*
! 55: * The user does not exist or access is denied,
! 56: * but fake indication that authentication is needed.
! 57: */
! 58: void
! 59: do_fake_authloop1(char *user)
! 60: {
! 61: int attempt = 0;
! 62:
! 63: log("Faking authloop for illegal user %.200s from %.200s port %d",
! 64: user,
! 65: get_remote_ipaddr(),
! 66: get_remote_port());
! 67:
! 68: /* Indicate that authentication is needed. */
! 69: packet_start(SSH_SMSG_FAILURE);
! 70: packet_send();
! 71: packet_write_wait();
! 72:
! 73: /*
! 74: * Keep reading packets, and always respond with a failure. This is
! 75: * to avoid disclosing whether such a user really exists.
! 76: */
! 77: for (attempt = 1;; attempt++) {
! 78: /* Read a packet. This will not return if the client disconnects. */
! 79: int plen;
! 80: int type = packet_read(&plen);
! 81: #ifdef SKEY
! 82: unsigned int dlen;
! 83: char *password, *skeyinfo;
! 84: password = NULL;
! 85: /* Try to send a fake s/key challenge. */
! 86: if (options.skey_authentication == 1 &&
! 87: (skeyinfo = skey_fake_keyinfo(user)) != NULL) {
! 88: if (type == SSH_CMSG_AUTH_TIS) {
! 89: packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
! 90: packet_put_string(skeyinfo, strlen(skeyinfo));
! 91: packet_send();
! 92: packet_write_wait();
! 93: continue;
! 94: } else if (type == SSH_CMSG_AUTH_PASSWORD &&
! 95: options.password_authentication &&
! 96: (password = packet_get_string(&dlen)) != NULL &&
! 97: dlen == 5 &&
! 98: strncasecmp(password, "s/key", 5) == 0 ) {
! 99: packet_send_debug(skeyinfo);
! 100: }
! 101: }
! 102: if (password != NULL)
! 103: xfree(password);
! 104: #endif
! 105: if (attempt > AUTH_FAIL_MAX)
! 106: packet_disconnect(AUTH_FAIL_MSG, user);
! 107:
! 108: /*
! 109: * Send failure. This should be indistinguishable from a
! 110: * failed authentication.
! 111: */
! 112: packet_start(SSH_SMSG_FAILURE);
! 113: packet_send();
! 114: packet_write_wait();
! 115: }
! 116: /* NOTREACHED */
! 117: abort();
! 118: }
! 119:
! 120: /*
! 121: * read packets and try to authenticate local user *pw.
! 122: * return if authentication is successfull
! 123: */
! 124: void
! 125: do_authloop(struct passwd * pw)
! 126: {
! 127: int attempt = 0;
! 128: unsigned int bits;
! 129: RSA *client_host_key;
! 130: BIGNUM *n;
! 131: char *client_user, *password;
! 132: char user[1024];
! 133: unsigned int dlen;
! 134: int plen, nlen, elen;
! 135: unsigned int ulen;
! 136: int type = 0;
! 137: void (*authlog) (const char *fmt,...) = verbose;
! 138:
! 139: /* Indicate that authentication is needed. */
! 140: packet_start(SSH_SMSG_FAILURE);
! 141: packet_send();
! 142: packet_write_wait();
! 143:
! 144: for (attempt = 1;; attempt++) {
! 145: int authenticated = 0;
! 146: strlcpy(user, "", sizeof user);
! 147:
! 148: /* Get a packet from the client. */
! 149: type = packet_read(&plen);
! 150:
! 151: /* Process the packet. */
! 152: switch (type) {
! 153: #ifdef AFS
! 154: case SSH_CMSG_HAVE_KERBEROS_TGT:
! 155: if (!options.kerberos_tgt_passing) {
! 156: /* packet_get_all(); */
! 157: verbose("Kerberos tgt passing disabled.");
! 158: break;
! 159: } else {
! 160: /* Accept Kerberos tgt. */
! 161: char *tgt = packet_get_string(&dlen);
! 162: packet_integrity_check(plen, 4 + dlen, type);
! 163: if (!auth_kerberos_tgt(pw, tgt))
! 164: verbose("Kerberos tgt REFUSED for %s", pw->pw_name);
! 165: xfree(tgt);
! 166: }
! 167: continue;
! 168:
! 169: case SSH_CMSG_HAVE_AFS_TOKEN:
! 170: if (!options.afs_token_passing || !k_hasafs()) {
! 171: /* packet_get_all(); */
! 172: verbose("AFS token passing disabled.");
! 173: break;
! 174: } else {
! 175: /* Accept AFS token. */
! 176: char *token_string = packet_get_string(&dlen);
! 177: packet_integrity_check(plen, 4 + dlen, type);
! 178: if (!auth_afs_token(pw, token_string))
! 179: verbose("AFS token REFUSED for %s", pw->pw_name);
! 180: xfree(token_string);
! 181: }
! 182: continue;
! 183: #endif /* AFS */
! 184: #ifdef KRB4
! 185: case SSH_CMSG_AUTH_KERBEROS:
! 186: if (!options.kerberos_authentication) {
! 187: /* packet_get_all(); */
! 188: verbose("Kerberos authentication disabled.");
! 189: break;
! 190: } else {
! 191: /* Try Kerberos v4 authentication. */
! 192: KTEXT_ST auth;
! 193: char *tkt_user = NULL;
! 194: char *kdata = packet_get_string((unsigned int *) &auth.length);
! 195: packet_integrity_check(plen, 4 + auth.length, type);
! 196:
! 197: if (auth.length < MAX_KTXT_LEN)
! 198: memcpy(auth.dat, kdata, auth.length);
! 199: xfree(kdata);
! 200:
! 201: authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
! 202:
! 203: if (authenticated) {
! 204: snprintf(user, sizeof user, " tktuser %s", tkt_user);
! 205: xfree(tkt_user);
! 206: }
! 207: }
! 208: break;
! 209: #endif /* KRB4 */
! 210:
! 211: case SSH_CMSG_AUTH_RHOSTS:
! 212: if (!options.rhosts_authentication) {
! 213: verbose("Rhosts authentication disabled.");
! 214: break;
! 215: }
! 216: /*
! 217: * Get client user name. Note that we just have to
! 218: * trust the client; this is one reason why rhosts
! 219: * authentication is insecure. (Another is
! 220: * IP-spoofing on a local network.)
! 221: */
! 222: client_user = packet_get_string(&ulen);
! 223: packet_integrity_check(plen, 4 + ulen, type);
! 224:
! 225: /* Try to authenticate using /etc/hosts.equiv and
! 226: .rhosts. */
! 227: authenticated = auth_rhosts(pw, client_user);
! 228:
! 229: snprintf(user, sizeof user, " ruser %s", client_user);
! 230: xfree(client_user);
! 231: break;
! 232:
! 233: case SSH_CMSG_AUTH_RHOSTS_RSA:
! 234: if (!options.rhosts_rsa_authentication) {
! 235: verbose("Rhosts with RSA authentication disabled.");
! 236: break;
! 237: }
! 238: /*
! 239: * Get client user name. Note that we just have to
! 240: * trust the client; root on the client machine can
! 241: * claim to be any user.
! 242: */
! 243: client_user = packet_get_string(&ulen);
! 244:
! 245: /* Get the client host key. */
! 246: client_host_key = RSA_new();
! 247: if (client_host_key == NULL)
! 248: fatal("RSA_new failed");
! 249: client_host_key->e = BN_new();
! 250: client_host_key->n = BN_new();
! 251: if (client_host_key->e == NULL || client_host_key->n == NULL)
! 252: fatal("BN_new failed");
! 253: bits = packet_get_int();
! 254: packet_get_bignum(client_host_key->e, &elen);
! 255: packet_get_bignum(client_host_key->n, &nlen);
! 256:
! 257: if (bits != BN_num_bits(client_host_key->n))
! 258: error("Warning: keysize mismatch for client_host_key: "
! 259: "actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
! 260: packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
! 261:
! 262: authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
! 263: RSA_free(client_host_key);
! 264:
! 265: snprintf(user, sizeof user, " ruser %s", client_user);
! 266: xfree(client_user);
! 267: break;
! 268:
! 269: case SSH_CMSG_AUTH_RSA:
! 270: if (!options.rsa_authentication) {
! 271: verbose("RSA authentication disabled.");
! 272: break;
! 273: }
! 274: /* RSA authentication requested. */
! 275: n = BN_new();
! 276: packet_get_bignum(n, &nlen);
! 277: packet_integrity_check(plen, nlen, type);
! 278: authenticated = auth_rsa(pw, n);
! 279: BN_clear_free(n);
! 280: break;
! 281:
! 282: case SSH_CMSG_AUTH_PASSWORD:
! 283: if (!options.password_authentication) {
! 284: verbose("Password authentication disabled.");
! 285: break;
! 286: }
! 287: /*
! 288: * Read user password. It is in plain text, but was
! 289: * transmitted over the encrypted channel so it is
! 290: * not visible to an outside observer.
! 291: */
! 292: password = packet_get_string(&dlen);
! 293: packet_integrity_check(plen, 4 + dlen, type);
! 294:
! 295: /* Try authentication with the password. */
! 296: authenticated = auth_password(pw, password);
! 297:
! 298: memset(password, 0, strlen(password));
! 299: xfree(password);
! 300: break;
! 301:
! 302: #ifdef SKEY
! 303: case SSH_CMSG_AUTH_TIS:
! 304: debug("rcvd SSH_CMSG_AUTH_TIS");
! 305: if (options.skey_authentication == 1) {
! 306: char *skeyinfo = skey_keyinfo(pw->pw_name);
! 307: if (skeyinfo == NULL) {
! 308: debug("generating fake skeyinfo for %.100s.", pw->pw_name);
! 309: skeyinfo = skey_fake_keyinfo(pw->pw_name);
! 310: }
! 311: if (skeyinfo != NULL) {
! 312: /* we send our s/key- in tis-challenge messages */
! 313: debug("sending challenge '%s'", skeyinfo);
! 314: packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
! 315: packet_put_string(skeyinfo, strlen(skeyinfo));
! 316: packet_send();
! 317: packet_write_wait();
! 318: continue;
! 319: }
! 320: }
! 321: break;
! 322: case SSH_CMSG_AUTH_TIS_RESPONSE:
! 323: debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
! 324: if (options.skey_authentication == 1) {
! 325: char *response = packet_get_string(&dlen);
! 326: debug("skey response == '%s'", response);
! 327: packet_integrity_check(plen, 4 + dlen, type);
! 328: authenticated = (skey_haskey(pw->pw_name) == 0 &&
! 329: skey_passcheck(pw->pw_name, response) != -1);
! 330: xfree(response);
! 331: }
! 332: break;
! 333: #else
! 334: case SSH_CMSG_AUTH_TIS:
! 335: /* TIS Authentication is unsupported */
! 336: log("TIS authentication unsupported.");
! 337: break;
! 338: #endif
! 339:
! 340: default:
! 341: /*
! 342: * Any unknown messages will be ignored (and failure
! 343: * returned) during authentication.
! 344: */
! 345: log("Unknown message during authentication: type %d", type);
! 346: break;
! 347: }
! 348:
! 349: /*
! 350: * Check if the user is logging in as root and root logins
! 351: * are disallowed.
! 352: * Note that root login is allowed for forced commands.
! 353: */
! 354: if (authenticated && pw->pw_uid == 0 && !options.permit_root_login) {
! 355: if (forced_command) {
! 356: log("Root login accepted for forced command.");
! 357: } else {
! 358: authenticated = 0;
! 359: log("ROOT LOGIN REFUSED FROM %.200s",
! 360: get_canonical_hostname());
! 361: }
! 362: }
! 363:
! 364: /* Raise logging level */
! 365: if (authenticated ||
! 366: attempt == AUTH_FAIL_LOG ||
! 367: type == SSH_CMSG_AUTH_PASSWORD)
! 368: authlog = log;
! 369:
! 370: authlog("%s %s for %.200s from %.200s port %d%s",
! 371: authenticated ? "Accepted" : "Failed",
! 372: get_authname(type),
! 373: pw->pw_uid == 0 ? "ROOT" : pw->pw_name,
! 374: get_remote_ipaddr(),
! 375: get_remote_port(),
! 376: user);
! 377:
! 378: if (authenticated)
! 379: return;
! 380:
! 381: if (attempt > AUTH_FAIL_MAX)
! 382: packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
! 383:
! 384: /* Send a message indicating that the authentication attempt failed. */
! 385: packet_start(SSH_SMSG_FAILURE);
! 386: packet_send();
! 387: packet_write_wait();
! 388: }
! 389: }
! 390:
! 391: /*
! 392: * Performs authentication of an incoming connection. Session key has already
! 393: * been exchanged and encryption is enabled.
! 394: */
! 395: void
! 396: do_authentication()
! 397: {
! 398: struct passwd *pw, pwcopy;
! 399: int plen;
! 400: unsigned int ulen;
! 401: char *user;
! 402:
! 403: /* Get the name of the user that we wish to log in as. */
! 404: packet_read_expect(&plen, SSH_CMSG_USER);
! 405:
! 406: /* Get the user name. */
! 407: user = packet_get_string(&ulen);
! 408: packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
! 409:
! 410: setproctitle("%s", user);
! 411:
! 412: #ifdef AFS
! 413: /* If machine has AFS, set process authentication group. */
! 414: if (k_hasafs()) {
! 415: k_setpag();
! 416: k_unlog();
! 417: }
! 418: #endif /* AFS */
! 419:
! 420: /* Verify that the user is a valid user. */
! 421: pw = getpwnam(user);
! 422: if (!pw || !allowed_user(pw))
! 423: do_fake_authloop1(user);
! 424: xfree(user);
! 425:
! 426: /* Take a copy of the returned structure. */
! 427: memset(&pwcopy, 0, sizeof(pwcopy));
! 428: pwcopy.pw_name = xstrdup(pw->pw_name);
! 429: pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
! 430: pwcopy.pw_uid = pw->pw_uid;
! 431: pwcopy.pw_gid = pw->pw_gid;
! 432: pwcopy.pw_dir = xstrdup(pw->pw_dir);
! 433: pwcopy.pw_shell = xstrdup(pw->pw_shell);
! 434: pw = &pwcopy;
! 435:
! 436: /*
! 437: * If we are not running as root, the user must have the same uid as
! 438: * the server.
! 439: */
! 440: if (getuid() != 0 && pw->pw_uid != getuid())
! 441: packet_disconnect("Cannot change user when server not running as root.");
! 442:
! 443: debug("Attempting authentication for %.100s.", pw->pw_name);
! 444:
! 445: /* If the user has no password, accept authentication immediately. */
! 446: if (options.password_authentication &&
! 447: #ifdef KRB4
! 448: (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
! 449: #endif /* KRB4 */
! 450: auth_password(pw, "")) {
! 451: /* Authentication with empty password succeeded. */
! 452: log("Login for user %s from %.100s, accepted without authentication.",
! 453: pw->pw_name, get_remote_ipaddr());
! 454: } else {
! 455: /* Loop until the user has been authenticated or the
! 456: connection is closed, do_authloop() returns only if
! 457: authentication is successfull */
! 458: do_authloop(pw);
! 459: }
! 460:
! 461: /* The user has been authenticated and accepted. */
! 462: packet_start(SSH_SMSG_SUCCESS);
! 463: packet_send();
! 464: packet_write_wait();
! 465:
! 466: /* Perform session preparation. */
! 467: do_authenticated(pw);
! 468: }