[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.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: }