[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.3

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