[BACK]Return to auth-passwd.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/auth-passwd.c, Revision 1.4

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