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