]> andersk Git - openssh.git/blob - auth-passwd.c
- More reformatting merged from OpenBSD CVS
[openssh.git] / auth-passwd.c
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  * Created: Sat Mar 18 05:11:38 1995 ylo
6  * Password authentication.  This file contains the functions to check whether
7  * the password is valid for the user.
8  */
9
10 #include "includes.h"
11
12 #ifndef HAVE_PAM
13
14 RCSID("$Id$");
15
16 #include "packet.h"
17 #include "ssh.h"
18 #include "servconf.h"
19 #include "xmalloc.h"
20
21 #ifdef HAVE_SHADOW_H
22 #include <shadow.h>
23 #endif
24
25 #ifdef HAVE_MD5_PASSWORDS
26 #include "md5crypt.h"
27 #endif
28
29 /*
30  * Tries to authenticate the user using password.  Returns true if
31  * authentication succeeds.
32  */
33 int 
34 auth_password(struct passwd * pw, const char *password)
35 {
36         extern ServerOptions options;
37         char *encrypted_password;
38 #ifdef HAVE_SHADOW_H
39         struct spwd *spw;
40 #endif
41
42         if (pw->pw_uid == 0 && options.permit_root_login == 2)
43                 return 0;
44         if (*password == '\0' && options.permit_empty_passwd == 0)
45                 return 0;
46         /* deny if no user. */
47         if (pw == NULL)
48                 return 0;
49
50 #ifdef SKEY
51         if (options.skey_authentication == 1) {
52                 if (strncasecmp(password, "s/key", 5) == 0) {
53                         char *skeyinfo = skey_keyinfo(pw->pw_name);
54                         if (skeyinfo == NULL) {
55                                 debug("generating fake skeyinfo for %.100s.",
56                                     pw->pw_name);
57                                 skeyinfo = skey_fake_keyinfo(pw->pw_name);
58                         }
59                         if (skeyinfo != NULL)
60                                 packet_send_debug(skeyinfo);
61                         /* Try again. */
62                         return 0;
63                 } else if (skey_haskey(pw->pw_name) == 0 &&
64                            skey_passcheck(pw->pw_name, (char *) password) != -1) {
65                         /* Authentication succeeded. */
66                         return 1;
67                 }
68                 /* Fall back to ordinary passwd authentication. */
69         }
70 #endif
71
72 #if defined(KRB4)
73         /*
74          * Support for Kerberos v4 authentication
75          * - Dug Song <dugsong@UMICH.EDU>
76          */
77         if (options.kerberos_authentication) {
78                 AUTH_DAT adata;
79                 KTEXT_ST tkt;
80                 struct hostent *hp;
81                 unsigned long faddr;
82                 char localhost[MAXHOSTNAMELEN];
83                 char phost[INST_SZ];
84                 char realm[REALM_SZ];
85                 int r;
86
87                 /*
88                  * Try Kerberos password authentication only for non-root
89                  * users and only if Kerberos is installed.
90                  */
91                 if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) {
92
93                         /* Set up our ticket file. */
94                         if (!krb4_init(pw->pw_uid)) {
95                                 log("Couldn't initialize Kerberos ticket file for %s!",
96                                     pw->pw_name);
97                                 goto kerberos_auth_failure;
98                         }
99                         /* Try to get TGT using our password. */
100                         r = krb_get_pw_in_tkt((char *) pw->pw_name, "",
101                             realm, "krbtgt", realm,
102                             DEFAULT_TKT_LIFE, (char *) password);
103                         if (r != INTK_OK) {
104                                 packet_send_debug("Kerberos V4 password "
105                                     "authentication for %s failed: %s",
106                                     pw->pw_name, krb_err_txt[r]);
107                                 goto kerberos_auth_failure;
108                         }
109                         /* Successful authentication. */
110                         chown(tkt_string(), pw->pw_uid, pw->pw_gid);
111
112                         /*
113                          * Now that we have a TGT, try to get a local
114                          * "rcmd" ticket to ensure that we are not talking
115                          * to a bogus Kerberos server.
116                          */
117                         (void) gethostname(localhost, sizeof(localhost));
118                         (void) strlcpy(phost, (char *) krb_get_phost(localhost),
119                             INST_SZ);
120                         r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33);
121
122                         if (r == KSUCCESS) {
123                                 if (!(hp = gethostbyname(localhost))) {
124                                         log("Couldn't get local host address!");
125                                         goto kerberos_auth_failure;
126                                 }
127                                 memmove((void *) &faddr, (void *) hp->h_addr,
128                                     sizeof(faddr));
129
130                                 /* Verify our "rcmd" ticket. */
131                                 r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost,
132                                     faddr, &adata, "");
133                                 if (r == RD_AP_UNDEC) {
134                                         /*
135                                          * Probably didn't have a srvtab on
136                                          * localhost. Allow login.
137                                          */
138                                         log("Kerberos V4 TGT for %s unverifiable, "
139                                             "no srvtab installed? krb_rd_req: %s",
140                                             pw->pw_name, krb_err_txt[r]);
141                                 } else if (r != KSUCCESS) {
142                                         log("Kerberos V4 %s ticket unverifiable: %s",
143                                             KRB4_SERVICE_NAME, krb_err_txt[r]);
144                                         goto kerberos_auth_failure;
145                                 }
146                         } else if (r == KDC_PR_UNKNOWN) {
147                                 /*
148                                  * Allow login if no rcmd service exists, but
149                                  * log the error.
150                                  */
151                                 log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
152                                     "not registered, or srvtab is wrong?", pw->pw_name,
153                                 krb_err_txt[r], KRB4_SERVICE_NAME, phost);
154                         } else {
155                                 /*
156                                  * TGT is bad, forget it. Possibly spoofed!
157                                  */
158                                 packet_send_debug("WARNING: Kerberos V4 TGT "
159                                     "possibly spoofed for %s: %s",
160                                     pw->pw_name, krb_err_txt[r]);
161                                 goto kerberos_auth_failure;
162                         }
163
164                         /* Authentication succeeded. */
165                         return 1;
166
167         kerberos_auth_failure:
168                         krb4_cleanup_proc(NULL);
169
170                         if (!options.kerberos_or_local_passwd)
171                                 return 0;
172                 } else {
173                         /* Logging in as root or no local Kerberos realm. */
174                         packet_send_debug("Unable to authenticate to Kerberos.");
175                 }
176                 /* Fall back to ordinary passwd authentication. */
177         }
178 #endif                          /* KRB4 */
179
180         /* Check for users with no password. */
181         if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0)
182                 return 1;
183
184 #ifdef HAVE_SHADOW_H
185         spw = getspnam(pw->pw_name);
186         if (spw == NULL)
187                 return(0);
188
189         if ((spw->sp_namp == NULL) || (strcmp(pw->pw_name, spw->sp_namp) != 0))
190                 fatal("Shadow lookup returned garbage.");
191
192         if (strlen(spw->sp_pwdp) < 3)
193                 return(0);
194
195         /* Encrypt the candidate password using the proper salt. */
196 #ifdef HAVE_MD5_PASSWORDS
197         if (is_md5_salt(spw->sp_pwdp))
198                 encrypted_password = md5_crypt(password, spw->sp_pwdp);
199         else
200                 encrypted_password = crypt(password, spw->sp_pwdp);
201 #else /* HAVE_MD5_PASSWORDS */    
202         encrypted_password = crypt(password, spw->sp_pwdp);
203 #endif /* HAVE_MD5_PASSWORDS */    
204         /* Authentication is accepted if the encrypted passwords are identical. */
205         return (strcmp(encrypted_password, spw->sp_pwdp) == 0);
206 #else /* !HAVE_SHADOW_H */
207         encrypted_password = crypt(password,
208             (pw->pw_passwd[0] && pw->pw_passwd[1]) ? pw->pw_passwd : "xx");
209
210         /* Authentication is accepted if the encrypted passwords are identical. */
211         return (strcmp(encrypted_password, pw->pw_passwd) == 0);
212 #endif /* !HAVE_SHADOW_H */
213 }
214 #endif /* !HAVE_PAM */
This page took 0.295633 seconds and 5 git commands to generate.