diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-09-26 20:53:39 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-09-26 20:53:39 +0000 |
commit | 8c922cd518cd36a281ce7cb57136ab3daff4af36 (patch) | |
tree | 3e941e108cbcb7ced11e67bd3d01c5e04dfa6283 /usr.bin/ssh/auth-passwd.c | |
parent | 51e6206503f4e208e20bee340a0992c2dbccf1fa (diff) |
i bet a lot of people didn't know what ssh 1.2.16 had a nice license.
well, except for the patent issues. someone in sweden (forget their
name at the moment) cleaned out most of the patented code, and now
this code removes rsa code. when this is done, it will link against
libssl, but the work isn't completely done yet. then we need to bring
this up to modern days, featurewise.
Diffstat (limited to 'usr.bin/ssh/auth-passwd.c')
-rw-r--r-- | usr.bin/ssh/auth-passwd.c | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/usr.bin/ssh/auth-passwd.c b/usr.bin/ssh/auth-passwd.c new file mode 100644 index 00000000000..10d21ca0bf9 --- /dev/null +++ b/usr.bin/ssh/auth-passwd.c @@ -0,0 +1,343 @@ +/* + +auth-passwd.c + +Author: Tatu Ylonen <ylo@cs.hut.fi> + +Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland + All rights reserved + +Created: Sat Mar 18 05:11:38 1995 ylo + +Password authentication. This file contains the functions to check whether +the password is valid for the user. + +*/ + +#include "includes.h" +RCSID("$Id: auth-passwd.c,v 1.1 1999/09/26 20:53:33 deraadt Exp $"); + +#ifdef HAVE_SCO_ETC_SHADOW +# include <sys/security.h> +# include <sys/audit.h> +# include <prot.h> +#else /* HAVE_SCO_ETC_SHADOW */ +#ifdef HAVE_ETC_SHADOW +#include <shadow.h> +#endif /* HAVE_ETC_SHADOW */ +#endif /* HAVE_SCO_ETC_SHADOW */ +#ifdef HAVE_ETC_SECURITY_PASSWD_ADJUNCT +#include <sys/label.h> +#include <sys/audit.h> +#include <pwdadj.h> +#endif /* HAVE_ETC_SECURITY_PASSWD_ADJUNCT */ +#include "packet.h" +#include "ssh.h" +#include "servconf.h" +#include "xmalloc.h" + +#ifdef HAVE_SECURID +/* Support for Security Dynamics SecurID card. + Contributed by Donald McKillican <dmckilli@qc.bell.ca>. */ +#define SECURID_USERS "/etc/securid.users" +#include "sdi_athd.h" +#include "sdi_size.h" +#include "sdi_type.h" +#include "sdacmvls.h" +#include "sdconf.h" +union config_record configure; +static int securid_initialized = 0; +#endif /* HAVE_SECURID */ + +#ifdef KRB4 +#include <sys/param.h> +#include <krb.h> +extern char *ticket; +#endif /* KRB4 */ + +/* Tries to authenticate the user using password. Returns true if + authentication succeeds. */ + +int auth_password(const char *server_user, const char *password) +{ + extern ServerOptions options; + extern char *crypt(const char *key, const char *salt); + struct passwd *pw; + char *encrypted_password; + char correct_passwd[200]; + + if (*password == '\0' && options.permit_empty_passwd == 0) + { + packet_send_debug("Server does not permit empty password login."); + return 0; + } + + /* Get the encrypted password for the user. */ + pw = getpwnam(server_user); + if (!pw) + return 0; + +#ifdef HAVE_SECURID + /* Support for Security Dynamics SecurId card. + Contributed by Donald McKillican <dmckilli@qc.bell.ca>. */ +#if defined(KRB4) + if (options.kerberos_or_local_passwd) +#endif /* KRB4 */ + { + /* + * the way we decide if this user is a securid user or not is + * to check to see if they are included in /etc/securid.users + */ + int found = 0; + FILE *securid_users = fopen(SECURID_USERS, "r"); + char *c; + char su_user[257]; + + if (securid_users) + { + while (fgets(su_user, sizeof(su_user), securid_users)) + { + if (c = strchr(su_user, '\n')) + *c = '\0'; + if (strcmp(su_user, server_user) == 0) + { + found = 1; + break; + } + } + } + fclose(securid_users); + + if (found) + { + /* The user has a SecurID card. */ + struct SD_CLIENT sd_dat, *sd; + log("SecurID authentication for %.100s required.", server_user); + + /* + * if no pass code has been supplied, fail immediately: passing + * a null pass code to sd_check causes a core dump + */ + if (*password == '\0') + { + log("No pass code given, authentication rejected."); + return 0; + } + + sd = &sd_dat; + if (!securid_initialized) + { + memset(&sd_dat, 0, sizeof(sd_dat)); /* clear struct */ + creadcfg(); /* accesses sdconf.rec */ + if (sd_init(sd)) + packet_disconnect("Cannot contact securid server."); + securid_initialized = 1; + } + return sd_check(password, server_user, sd) == ACM_OK; + } + } + /* If the user has no SecurID card specified, we fall to normal + password code. */ +#endif /* HAVE_SECURID */ + + /* Save the encrypted password. */ + strncpy(correct_passwd, pw->pw_passwd, sizeof(correct_passwd)); + +#ifdef HAVE_OSF1_C2_SECURITY + osf1c2_getprpwent(correct_passwd, pw->pw_name, sizeof(correct_passwd)); +#else /* HAVE_OSF1_C2_SECURITY */ + /* If we have shadow passwords, lookup the real encrypted password from + the shadow file, and replace the saved encrypted password with the + real encrypted password. */ +#ifdef HAVE_SCO_ETC_SHADOW + { + struct pr_passwd *pr = getprpwnam(pw->pw_name); + pr = getprpwnam(pw->pw_name); + if (pr) + strncpy(correct_passwd, pr->ufld.fd_encrypt, sizeof(correct_passwd)); + endprpwent(); + } +#else /* HAVE_SCO_ETC_SHADOW */ +#ifdef HAVE_ETC_SHADOW + { + struct spwd *sp = getspnam(pw->pw_name); + if (sp) + strncpy(correct_passwd, sp->sp_pwdp, sizeof(correct_passwd)); + endspent(); + } +#else /* HAVE_ETC_SHADOW */ +#ifdef HAVE_ETC_SECURITY_PASSWD_ADJUNCT + { + struct passwd_adjunct *sp = getpwanam(pw->pw_name); + if (sp) + strncpy(correct_passwd, sp->pwa_passwd, sizeof(correct_passwd)); + endpwaent(); + } +#else /* HAVE_ETC_SECURITY_PASSWD_ADJUNCT */ +#ifdef HAVE_ETC_SECURITY_PASSWD + { + FILE *f; + char line[1024], looking_for_user[200], *cp; + int found_user = 0; + f = fopen("/etc/security/passwd", "r"); + if (f) + { + sprintf(looking_for_user, "%.190s:", server_user); + while (fgets(line, sizeof(line), f)) + { + if (strchr(line, '\n')) + *strchr(line, '\n') = 0; + if (strcmp(line, looking_for_user) == 0) + found_user = 1; + else + if (line[0] != '\t' && line[0] != ' ') + found_user = 0; + else + if (found_user) + { + for (cp = line; *cp == ' ' || *cp == '\t'; cp++) + ; + if (strncmp(cp, "password = ", strlen("password = ")) == 0) + { + strncpy(correct_passwd, cp + strlen("password = "), + sizeof(correct_passwd)); + correct_passwd[sizeof(correct_passwd) - 1] = 0; + break; + } + } + } + fclose(f); + } + } +#endif /* HAVE_ETC_SECURITY_PASSWD */ +#endif /* HAVE_ETC_SECURITY_PASSWD_ADJUNCT */ +#endif /* HAVE_ETC_SHADOW */ +#endif /* HAVE_SCO_ETC_SHADOW */ +#endif /* HAVE_OSF1_C2_SECURITY */ + + /* Check for users with no password. */ +#if defined(KRB4) + if (options.kerberos_or_local_passwd) +#endif /* KRB4 */ + if (strcmp(password, "") == 0 && strcmp(correct_passwd, "") == 0) + { + packet_send_debug("Login permitted without a password because the account has no password."); + return 1; /* The user has no password and an empty password was tried. */ + } + + /* Encrypt the candidate password using the proper salt. */ +#ifdef HAVE_OSF1_C2_SECURITY + encrypted_password = (char *)osf1c2crypt(password, + (correct_passwd[0] && correct_passwd[1]) ? + correct_passwd : "xx"); +#else /* HAVE_OSF1_C2_SECURITY */ +#ifdef HAVE_SCO_ETC_SHADOW + encrypted_password = bigcrypt(password, + (correct_passwd[0] && correct_passwd[1]) ? + correct_passwd : "xx"); +#else /* HAVE_SCO_ETC_SHADOW */ + encrypted_password = crypt(password, + (correct_passwd[0] && correct_passwd[1]) ? + correct_passwd : "xx"); +#endif /* HAVE_SCO_ETC_SHADOW */ +#endif /* HAVE_OSF1_C2_SECURITY */ + + /* Authentication is accepted if the encrypted passwords are identical. */ +#if defined(KRB4) + if (options.kerberos_or_local_passwd) +#endif /* KRB4 */ + if (strcmp(encrypted_password, correct_passwd) == 0) + return 1; /* Success */ + +#if defined(KRB4) + if (options.kerberos_authentication) + { + AUTH_DAT adata; + KTEXT_ST tkt; + struct hostent *hp; + unsigned long faddr; + char localhost[MAXHOSTNAMELEN]; /* local host name */ + char phost[INST_SZ]; /* host instance */ + char realm[REALM_SZ]; /* local Kerberos realm */ + int r; + + /* Try Kerberos password authentication only for non-root + users and only if Kerberos is installed. */ + if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) { + + /* Set up our ticket file. */ + if (!ssh_tf_init(pw->pw_uid)) { + log("Couldn't initialize Kerberos ticket file for %.100s!", + server_user); + goto kerberos_auth_failure; + } + /* Try to get TGT using our password. */ + r = krb_get_pw_in_tkt(server_user, "", realm, "krbtgt", realm, + DEFAULT_TKT_LIFE, password); + if (r != INTK_OK) { + packet_send_debug("Kerberos V4 password authentication for %.100s " + "failed: %.100s", server_user, krb_err_txt[r]); + goto kerberos_auth_failure; + } + /* Successful authentication. */ + chown(ticket, pw->pw_uid, pw->pw_gid); + + (void) gethostname(localhost, sizeof(localhost)); + (void) strncpy(phost, (char *)krb_get_phost(localhost), INST_SZ); + phost[INST_SZ-1] = 0; + + /* Now that we have a TGT, try to get a local "rcmd" ticket to + ensure that we are not talking to a bogus Kerberos server. */ + r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33); + + if (r == KSUCCESS) { + if (!(hp = gethostbyname(localhost))) { + log("Couldn't get local host address!"); + goto kerberos_auth_failure; + } + memmove((void *)&faddr, (void *)hp->h_addr, sizeof(faddr)); + + /* Verify our "rcmd" ticket. */ + r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost, faddr, &adata, ""); + if (r == RD_AP_UNDEC) { + /* Probably didn't have a srvtab on localhost. Allow login. */ + log("Kerberos V4 TGT for %.100s unverifiable, no srvtab? " + "krb_rd_req: %.100s", server_user, krb_err_txt[r]); + } + else if (r != KSUCCESS) { + log("Kerberos V4 %.100s ticket unverifiable: %.100s", + KRB4_SERVICE_NAME, krb_err_txt[r]); + goto kerberos_auth_failure; + } + } + else if (r == KDC_PR_UNKNOWN) { + /* Allow login if no rcmd service exists, but log the error. */ + log("Kerberos V4 TGT for %.100s unverifiable: %.100s; %.100s.%.100s " + "not registered, or srvtab is wrong?", server_user, + krb_err_txt[r], KRB4_SERVICE_NAME, phost); + } + else { + /* TGT is bad, forget it. Possibly spoofed. */ + packet_send_debug("WARNING: Kerberos V4 TGT possibly spoofed for" + "%.100s: %.100s", server_user, krb_err_txt[r]); + goto kerberos_auth_failure; + } + + /* Authentication succeeded. */ + return 1; + + kerberos_auth_failure: + (void) dest_tkt(); + xfree(ticket); + ticket = NULL; + if (!options.kerberos_or_local_passwd ) return 0; + } + else /* Logging in as root or no local Kerberos realm. */ + packet_send_debug("Unable to authenticate to Kerberos."); + + /* Fall back to ordinary passwd authentication. */ + } +#endif /* KRB4 */ + + return 0; /* Fail */ +} |