Annotation of src/usr.bin/ssh/auth-passwd.c, Revision 1.1
1.1 ! deraadt 1: /*
! 2:
! 3: auth-passwd.c
! 4:
! 5: Author: Tatu Ylonen <ylo@cs.hut.fi>
! 6:
! 7: Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
! 8: All rights reserved
! 9:
! 10: Created: Sat Mar 18 05:11:38 1995 ylo
! 11:
! 12: Password authentication. This file contains the functions to check whether
! 13: the password is valid for the user.
! 14:
! 15: */
! 16:
! 17: #include "includes.h"
! 18: RCSID("$Id: auth-passwd.c,v 1.10 1999/05/04 17:57:18 bg Exp $");
! 19:
! 20: #ifdef HAVE_SCO_ETC_SHADOW
! 21: # include <sys/security.h>
! 22: # include <sys/audit.h>
! 23: # include <prot.h>
! 24: #else /* HAVE_SCO_ETC_SHADOW */
! 25: #ifdef HAVE_ETC_SHADOW
! 26: #include <shadow.h>
! 27: #endif /* HAVE_ETC_SHADOW */
! 28: #endif /* HAVE_SCO_ETC_SHADOW */
! 29: #ifdef HAVE_ETC_SECURITY_PASSWD_ADJUNCT
! 30: #include <sys/label.h>
! 31: #include <sys/audit.h>
! 32: #include <pwdadj.h>
! 33: #endif /* HAVE_ETC_SECURITY_PASSWD_ADJUNCT */
! 34: #include "packet.h"
! 35: #include "ssh.h"
! 36: #include "servconf.h"
! 37: #include "xmalloc.h"
! 38:
! 39: #ifdef HAVE_SECURID
! 40: /* Support for Security Dynamics SecurID card.
! 41: Contributed by Donald McKillican <dmckilli@qc.bell.ca>. */
! 42: #define SECURID_USERS "/etc/securid.users"
! 43: #include "sdi_athd.h"
! 44: #include "sdi_size.h"
! 45: #include "sdi_type.h"
! 46: #include "sdacmvls.h"
! 47: #include "sdconf.h"
! 48: union config_record configure;
! 49: static int securid_initialized = 0;
! 50: #endif /* HAVE_SECURID */
! 51:
! 52: #ifdef KRB4
! 53: #include <sys/param.h>
! 54: #include <krb.h>
! 55: extern char *ticket;
! 56: #endif /* KRB4 */
! 57:
! 58: /* Tries to authenticate the user using password. Returns true if
! 59: authentication succeeds. */
! 60:
! 61: int auth_password(const char *server_user, const char *password)
! 62: {
! 63: extern ServerOptions options;
! 64: extern char *crypt(const char *key, const char *salt);
! 65: struct passwd *pw;
! 66: char *encrypted_password;
! 67: char correct_passwd[200];
! 68:
! 69: if (*password == '\0' && options.permit_empty_passwd == 0)
! 70: {
! 71: packet_send_debug("Server does not permit empty password login.");
! 72: return 0;
! 73: }
! 74:
! 75: /* Get the encrypted password for the user. */
! 76: pw = getpwnam(server_user);
! 77: if (!pw)
! 78: return 0;
! 79:
! 80: #ifdef HAVE_SECURID
! 81: /* Support for Security Dynamics SecurId card.
! 82: Contributed by Donald McKillican <dmckilli@qc.bell.ca>. */
! 83: #if defined(KRB4)
! 84: if (options.kerberos_or_local_passwd)
! 85: #endif /* KRB4 */
! 86: {
! 87: /*
! 88: * the way we decide if this user is a securid user or not is
! 89: * to check to see if they are included in /etc/securid.users
! 90: */
! 91: int found = 0;
! 92: FILE *securid_users = fopen(SECURID_USERS, "r");
! 93: char *c;
! 94: char su_user[257];
! 95:
! 96: if (securid_users)
! 97: {
! 98: while (fgets(su_user, sizeof(su_user), securid_users))
! 99: {
! 100: if (c = strchr(su_user, '\n'))
! 101: *c = '\0';
! 102: if (strcmp(su_user, server_user) == 0)
! 103: {
! 104: found = 1;
! 105: break;
! 106: }
! 107: }
! 108: }
! 109: fclose(securid_users);
! 110:
! 111: if (found)
! 112: {
! 113: /* The user has a SecurID card. */
! 114: struct SD_CLIENT sd_dat, *sd;
! 115: log("SecurID authentication for %.100s required.", server_user);
! 116:
! 117: /*
! 118: * if no pass code has been supplied, fail immediately: passing
! 119: * a null pass code to sd_check causes a core dump
! 120: */
! 121: if (*password == '\0')
! 122: {
! 123: log("No pass code given, authentication rejected.");
! 124: return 0;
! 125: }
! 126:
! 127: sd = &sd_dat;
! 128: if (!securid_initialized)
! 129: {
! 130: memset(&sd_dat, 0, sizeof(sd_dat)); /* clear struct */
! 131: creadcfg(); /* accesses sdconf.rec */
! 132: if (sd_init(sd))
! 133: packet_disconnect("Cannot contact securid server.");
! 134: securid_initialized = 1;
! 135: }
! 136: return sd_check(password, server_user, sd) == ACM_OK;
! 137: }
! 138: }
! 139: /* If the user has no SecurID card specified, we fall to normal
! 140: password code. */
! 141: #endif /* HAVE_SECURID */
! 142:
! 143: /* Save the encrypted password. */
! 144: strncpy(correct_passwd, pw->pw_passwd, sizeof(correct_passwd));
! 145:
! 146: #ifdef HAVE_OSF1_C2_SECURITY
! 147: osf1c2_getprpwent(correct_passwd, pw->pw_name, sizeof(correct_passwd));
! 148: #else /* HAVE_OSF1_C2_SECURITY */
! 149: /* If we have shadow passwords, lookup the real encrypted password from
! 150: the shadow file, and replace the saved encrypted password with the
! 151: real encrypted password. */
! 152: #ifdef HAVE_SCO_ETC_SHADOW
! 153: {
! 154: struct pr_passwd *pr = getprpwnam(pw->pw_name);
! 155: pr = getprpwnam(pw->pw_name);
! 156: if (pr)
! 157: strncpy(correct_passwd, pr->ufld.fd_encrypt, sizeof(correct_passwd));
! 158: endprpwent();
! 159: }
! 160: #else /* HAVE_SCO_ETC_SHADOW */
! 161: #ifdef HAVE_ETC_SHADOW
! 162: {
! 163: struct spwd *sp = getspnam(pw->pw_name);
! 164: if (sp)
! 165: strncpy(correct_passwd, sp->sp_pwdp, sizeof(correct_passwd));
! 166: endspent();
! 167: }
! 168: #else /* HAVE_ETC_SHADOW */
! 169: #ifdef HAVE_ETC_SECURITY_PASSWD_ADJUNCT
! 170: {
! 171: struct passwd_adjunct *sp = getpwanam(pw->pw_name);
! 172: if (sp)
! 173: strncpy(correct_passwd, sp->pwa_passwd, sizeof(correct_passwd));
! 174: endpwaent();
! 175: }
! 176: #else /* HAVE_ETC_SECURITY_PASSWD_ADJUNCT */
! 177: #ifdef HAVE_ETC_SECURITY_PASSWD
! 178: {
! 179: FILE *f;
! 180: char line[1024], looking_for_user[200], *cp;
! 181: int found_user = 0;
! 182: f = fopen("/etc/security/passwd", "r");
! 183: if (f)
! 184: {
! 185: sprintf(looking_for_user, "%.190s:", server_user);
! 186: while (fgets(line, sizeof(line), f))
! 187: {
! 188: if (strchr(line, '\n'))
! 189: *strchr(line, '\n') = 0;
! 190: if (strcmp(line, looking_for_user) == 0)
! 191: found_user = 1;
! 192: else
! 193: if (line[0] != '\t' && line[0] != ' ')
! 194: found_user = 0;
! 195: else
! 196: if (found_user)
! 197: {
! 198: for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
! 199: ;
! 200: if (strncmp(cp, "password = ", strlen("password = ")) == 0)
! 201: {
! 202: strncpy(correct_passwd, cp + strlen("password = "),
! 203: sizeof(correct_passwd));
! 204: correct_passwd[sizeof(correct_passwd) - 1] = 0;
! 205: break;
! 206: }
! 207: }
! 208: }
! 209: fclose(f);
! 210: }
! 211: }
! 212: #endif /* HAVE_ETC_SECURITY_PASSWD */
! 213: #endif /* HAVE_ETC_SECURITY_PASSWD_ADJUNCT */
! 214: #endif /* HAVE_ETC_SHADOW */
! 215: #endif /* HAVE_SCO_ETC_SHADOW */
! 216: #endif /* HAVE_OSF1_C2_SECURITY */
! 217:
! 218: /* Check for users with no password. */
! 219: #if defined(KRB4)
! 220: if (options.kerberos_or_local_passwd)
! 221: #endif /* KRB4 */
! 222: if (strcmp(password, "") == 0 && strcmp(correct_passwd, "") == 0)
! 223: {
! 224: packet_send_debug("Login permitted without a password because the account has no password.");
! 225: return 1; /* The user has no password and an empty password was tried. */
! 226: }
! 227:
! 228: /* Encrypt the candidate password using the proper salt. */
! 229: #ifdef HAVE_OSF1_C2_SECURITY
! 230: encrypted_password = (char *)osf1c2crypt(password,
! 231: (correct_passwd[0] && correct_passwd[1]) ?
! 232: correct_passwd : "xx");
! 233: #else /* HAVE_OSF1_C2_SECURITY */
! 234: #ifdef HAVE_SCO_ETC_SHADOW
! 235: encrypted_password = bigcrypt(password,
! 236: (correct_passwd[0] && correct_passwd[1]) ?
! 237: correct_passwd : "xx");
! 238: #else /* HAVE_SCO_ETC_SHADOW */
! 239: encrypted_password = crypt(password,
! 240: (correct_passwd[0] && correct_passwd[1]) ?
! 241: correct_passwd : "xx");
! 242: #endif /* HAVE_SCO_ETC_SHADOW */
! 243: #endif /* HAVE_OSF1_C2_SECURITY */
! 244:
! 245: /* Authentication is accepted if the encrypted passwords are identical. */
! 246: #if defined(KRB4)
! 247: if (options.kerberos_or_local_passwd)
! 248: #endif /* KRB4 */
! 249: if (strcmp(encrypted_password, correct_passwd) == 0)
! 250: return 1; /* Success */
! 251:
! 252: #if defined(KRB4)
! 253: if (options.kerberos_authentication)
! 254: {
! 255: AUTH_DAT adata;
! 256: KTEXT_ST tkt;
! 257: struct hostent *hp;
! 258: unsigned long faddr;
! 259: char localhost[MAXHOSTNAMELEN]; /* local host name */
! 260: char phost[INST_SZ]; /* host instance */
! 261: char realm[REALM_SZ]; /* local Kerberos realm */
! 262: int r;
! 263:
! 264: /* Try Kerberos password authentication only for non-root
! 265: users and only if Kerberos is installed. */
! 266: if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) {
! 267:
! 268: /* Set up our ticket file. */
! 269: if (!ssh_tf_init(pw->pw_uid)) {
! 270: log("Couldn't initialize Kerberos ticket file for %.100s!",
! 271: server_user);
! 272: goto kerberos_auth_failure;
! 273: }
! 274: /* Try to get TGT using our password. */
! 275: r = krb_get_pw_in_tkt(server_user, "", realm, "krbtgt", realm,
! 276: DEFAULT_TKT_LIFE, password);
! 277: if (r != INTK_OK) {
! 278: packet_send_debug("Kerberos V4 password authentication for %.100s "
! 279: "failed: %.100s", server_user, krb_err_txt[r]);
! 280: goto kerberos_auth_failure;
! 281: }
! 282: /* Successful authentication. */
! 283: chown(ticket, pw->pw_uid, pw->pw_gid);
! 284:
! 285: (void) gethostname(localhost, sizeof(localhost));
! 286: (void) strncpy(phost, (char *)krb_get_phost(localhost), INST_SZ);
! 287: phost[INST_SZ-1] = 0;
! 288:
! 289: /* Now that we have a TGT, try to get a local "rcmd" ticket to
! 290: ensure that we are not talking to a bogus Kerberos server. */
! 291: r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33);
! 292:
! 293: if (r == KSUCCESS) {
! 294: if (!(hp = gethostbyname(localhost))) {
! 295: log("Couldn't get local host address!");
! 296: goto kerberos_auth_failure;
! 297: }
! 298: memmove((void *)&faddr, (void *)hp->h_addr, sizeof(faddr));
! 299:
! 300: /* Verify our "rcmd" ticket. */
! 301: r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost, faddr, &adata, "");
! 302: if (r == RD_AP_UNDEC) {
! 303: /* Probably didn't have a srvtab on localhost. Allow login. */
! 304: log("Kerberos V4 TGT for %.100s unverifiable, no srvtab? "
! 305: "krb_rd_req: %.100s", server_user, krb_err_txt[r]);
! 306: }
! 307: else if (r != KSUCCESS) {
! 308: log("Kerberos V4 %.100s ticket unverifiable: %.100s",
! 309: KRB4_SERVICE_NAME, krb_err_txt[r]);
! 310: goto kerberos_auth_failure;
! 311: }
! 312: }
! 313: else if (r == KDC_PR_UNKNOWN) {
! 314: /* Allow login if no rcmd service exists, but log the error. */
! 315: log("Kerberos V4 TGT for %.100s unverifiable: %.100s; %.100s.%.100s "
! 316: "not registered, or srvtab is wrong?", server_user,
! 317: krb_err_txt[r], KRB4_SERVICE_NAME, phost);
! 318: }
! 319: else {
! 320: /* TGT is bad, forget it. Possibly spoofed. */
! 321: packet_send_debug("WARNING: Kerberos V4 TGT possibly spoofed for"
! 322: "%.100s: %.100s", server_user, krb_err_txt[r]);
! 323: goto kerberos_auth_failure;
! 324: }
! 325:
! 326: /* Authentication succeeded. */
! 327: return 1;
! 328:
! 329: kerberos_auth_failure:
! 330: (void) dest_tkt();
! 331: xfree(ticket);
! 332: ticket = NULL;
! 333: if (!options.kerberos_or_local_passwd ) return 0;
! 334: }
! 335: else /* Logging in as root or no local Kerberos realm. */
! 336: packet_send_debug("Unable to authenticate to Kerberos.");
! 337:
! 338: /* Fall back to ordinary passwd authentication. */
! 339: }
! 340: #endif /* KRB4 */
! 341:
! 342: return 0; /* Fail */
! 343: }