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