$NetBSD: patch-at,v 1.2 2000/04/23 19:17:30 thorpej Exp $ --- auth-passwd.c.orig Wed May 12 04:19:23 1999 +++ auth-passwd.c Tue Apr 18 11:48:03 2000 @@ -301,29 +301,25 @@ static int securid_initialized = 0; #endif /* HAVE_SECURID */ -#ifdef KERBEROS -#if defined(KRB5) +#ifdef KRB5 #include extern krb5_context ssh_context; extern krb5_auth_context auth_context; -#else -#include #endif /* KRB5 */ -#endif /* KERBEROS */ -#ifdef AFS -#include -#include -#endif /* AFS */ +#ifdef KRB4 +#include +#include +#endif /* KRB4 */ -#if defined(KERBEROS) || defined(AFS_KERBEROS) +#if defined(KRB4) || defined(KRB5) extern char *ticket; -#endif /* KERBEROS || AFS_KERBEROS */ +#endif /* KRB4 || KRB5 */ /* Tries to authenticate the user using password. Returns true if authentication succeeds. */ -#if defined(KERBEROS) && defined(KRB5) +#ifdef KRB5 /* * This routine with some modification is from the MIT V5B6 appl/bsd/login.c * @@ -479,16 +475,16 @@ 0 }; #endif krb5_preauthtype * preauth = preauth_list; -#endif /* KERBEROS */ +#endif /* KRB5 */ /* Tries to authenticate the user using password. Returns true if authentication succeeds. */ -#ifdef KERBEROS +#ifdef KRB5 int auth_password(const char *server_user, const char *password, krb5_principal client) -#else /* KERBEROS */ +#else /* KRB5 */ int auth_password(const char *server_user, const char *password) -#endif /* KERBEROS */ +#endif /* KRB5 */ { #if defined(_AIX) && defined(HAVE_AUTHENTICATE) char *message; @@ -505,7 +501,7 @@ } #else /* _AIX41 && HAVE_AUTHENTICATE */ -#ifdef KERBEROS +#ifdef KRB5 krb5_error_code problem; int krb5_options = KDC_OPT_RENEWABLE | KDC_OPT_FORWARDABLE; krb5_deltat rlife = 0; @@ -515,7 +511,7 @@ krb5_ccache ccache; char ccname[80]; int results; -#endif /* KERBEROS */ +#endif /* KRB5 */ extern ServerOptions options; extern char *crypt(const char *key, const char *salt); struct passwd *pw; @@ -537,10 +533,9 @@ saved_pw_name = xstrdup(pw->pw_name); saved_pw_passwd = xstrdup(pw->pw_passwd); -#if defined(KERBEROS) - if (options.kerberos_authentication) - { #if defined(KRB5) + if (options.kerberos_authentication && client != NULL) + { snprintf(ccname, sizeof(ccname), "FILE:/tmp/krb5cc_l%d", getpid()); if (problem = krb5_cc_resolve(ssh_context, ccname, &ccache)) @@ -658,9 +653,96 @@ return 0; } } + } #endif /* KRB5 */ +#ifdef 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, 0) == KSUCCESS) { + + /* Set up our ticket file. */ + if (!ssh_tf_init(pw->pw_uid)) { + log_msg("Couldn't initialize Kerberos ticket file for %s!", + server_user); + goto kerberos_auth_failure; + } + /* Try to get TGT using our password. */ + if ((r = krb_get_pw_in_tkt((char *)server_user, "", realm, "krbtgt", + realm, DEFAULT_TKT_LIFE, (char *)password)) != INTK_OK) { + packet_send_debug("Kerberos V4 password authentication for %s " + "failed: %s", 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_msg("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_msg("Kerberos V4 TGT for %s unverifiable, no srvtab? " + "krb_rd_req: %s", server_user, krb_err_txt[r]); + } + else if (r != KSUCCESS) { + log_msg("Kerberos V4 %s ticket unverifiable: %s", + 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_msg("Kerberos V4 TGT for %s unverifiable: %s; %s.%s " + "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" + "%s: %s", 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 /* KERBEROS */ +#endif /* KRB4 */ #ifdef HAVE_SECURID /* Support for Security Dynamics SecurId card.