diff options
Diffstat (limited to 'auth1.c')
-rw-r--r-- | auth1.c | 147 |
1 files changed, 121 insertions, 26 deletions
@@ -10,7 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include "includes.h" | 12 | #include "includes.h" |
13 | RCSID("$OpenBSD: auth1.c,v 1.52 2003/08/28 12:54:34 markus Exp $"); | 13 | RCSID("$OpenBSD: auth1.c,v 1.47 2003/02/06 21:22:42 markus Exp $"); |
14 | 14 | ||
15 | #include "xmalloc.h" | 15 | #include "xmalloc.h" |
16 | #include "rsa.h" | 16 | #include "rsa.h" |
@@ -49,6 +49,10 @@ get_authname(int type) | |||
49 | case SSH_CMSG_AUTH_TIS: | 49 | case SSH_CMSG_AUTH_TIS: |
50 | case SSH_CMSG_AUTH_TIS_RESPONSE: | 50 | case SSH_CMSG_AUTH_TIS_RESPONSE: |
51 | return "challenge-response"; | 51 | return "challenge-response"; |
52 | #if defined(KRB4) || defined(KRB5) | ||
53 | case SSH_CMSG_AUTH_KERBEROS: | ||
54 | return "kerberos"; | ||
55 | #endif | ||
52 | } | 56 | } |
53 | snprintf(buf, sizeof buf, "bad-auth-msg-%d", type); | 57 | snprintf(buf, sizeof buf, "bad-auth-msg-%d", type); |
54 | return buf; | 58 | return buf; |
@@ -69,15 +73,15 @@ do_authloop(Authctxt *authctxt) | |||
69 | char info[1024]; | 73 | char info[1024]; |
70 | u_int dlen; | 74 | u_int dlen; |
71 | u_int ulen; | 75 | u_int ulen; |
72 | int prev, type = 0; | 76 | int type = 0; |
73 | struct passwd *pw = authctxt->pw; | 77 | struct passwd *pw = authctxt->pw; |
74 | 78 | ||
75 | debug("Attempting authentication for %s%.100s.", | 79 | debug("Attempting authentication for %s%.100s.", |
76 | authctxt->valid ? "" : "illegal user ", authctxt->user); | 80 | authctxt->valid ? "" : "illegal user ", authctxt->user); |
77 | 81 | ||
78 | /* If the user has no password, accept authentication immediately. */ | 82 | /* If the user has no password, accept authentication immediately. */ |
79 | if (options.password_authentication && | 83 | if (options.password_authentication && options.permit_empty_passwd && |
80 | #ifdef KRB5 | 84 | #if defined(KRB4) || defined(KRB5) |
81 | (!options.kerberos_authentication || options.kerberos_or_local_passwd) && | 85 | (!options.kerberos_authentication || options.kerberos_or_local_passwd) && |
82 | #endif | 86 | #endif |
83 | PRIVSEP(auth_password(authctxt, ""))) { | 87 | PRIVSEP(auth_password(authctxt, ""))) { |
@@ -99,22 +103,104 @@ do_authloop(Authctxt *authctxt) | |||
99 | info[0] = '\0'; | 103 | info[0] = '\0'; |
100 | 104 | ||
101 | /* Get a packet from the client. */ | 105 | /* Get a packet from the client. */ |
102 | prev = type; | ||
103 | type = packet_read(); | 106 | type = packet_read(); |
104 | 107 | ||
105 | /* | ||
106 | * If we started challenge-response authentication but the | ||
107 | * next packet is not a response to our challenge, release | ||
108 | * the resources allocated by get_challenge() (which would | ||
109 | * normally have been released by verify_response() had we | ||
110 | * received such a response) | ||
111 | */ | ||
112 | if (prev == SSH_CMSG_AUTH_TIS && | ||
113 | type != SSH_CMSG_AUTH_TIS_RESPONSE) | ||
114 | abandon_challenge_response(authctxt); | ||
115 | |||
116 | /* Process the packet. */ | 108 | /* Process the packet. */ |
117 | switch (type) { | 109 | switch (type) { |
110 | |||
111 | #if defined(KRB4) || defined(KRB5) | ||
112 | case SSH_CMSG_AUTH_KERBEROS: | ||
113 | if (!options.kerberos_authentication) { | ||
114 | verbose("Kerberos authentication disabled."); | ||
115 | } else { | ||
116 | char *kdata = packet_get_string(&dlen); | ||
117 | packet_check_eom(); | ||
118 | |||
119 | if (kdata[0] == 4) { /* KRB_PROT_VERSION */ | ||
120 | #ifdef KRB4 | ||
121 | KTEXT_ST tkt, reply; | ||
122 | tkt.length = dlen; | ||
123 | if (tkt.length < MAX_KTXT_LEN) | ||
124 | memcpy(tkt.dat, kdata, tkt.length); | ||
125 | |||
126 | if (PRIVSEP(auth_krb4(authctxt, &tkt, | ||
127 | &client_user, &reply))) { | ||
128 | authenticated = 1; | ||
129 | snprintf(info, sizeof(info), | ||
130 | " tktuser %.100s", | ||
131 | client_user); | ||
132 | |||
133 | packet_start( | ||
134 | SSH_SMSG_AUTH_KERBEROS_RESPONSE); | ||
135 | packet_put_string((char *) | ||
136 | reply.dat, reply.length); | ||
137 | packet_send(); | ||
138 | packet_write_wait(); | ||
139 | } | ||
140 | #endif /* KRB4 */ | ||
141 | } else { | ||
142 | #ifdef KRB5 | ||
143 | krb5_data tkt, reply; | ||
144 | tkt.length = dlen; | ||
145 | tkt.data = kdata; | ||
146 | |||
147 | if (PRIVSEP(auth_krb5(authctxt, &tkt, | ||
148 | &client_user, &reply))) { | ||
149 | authenticated = 1; | ||
150 | snprintf(info, sizeof(info), | ||
151 | " tktuser %.100s", | ||
152 | client_user); | ||
153 | |||
154 | /* Send response to client */ | ||
155 | packet_start( | ||
156 | SSH_SMSG_AUTH_KERBEROS_RESPONSE); | ||
157 | packet_put_string((char *) | ||
158 | reply.data, reply.length); | ||
159 | packet_send(); | ||
160 | packet_write_wait(); | ||
161 | |||
162 | if (reply.length) | ||
163 | xfree(reply.data); | ||
164 | } | ||
165 | #endif /* KRB5 */ | ||
166 | } | ||
167 | xfree(kdata); | ||
168 | } | ||
169 | break; | ||
170 | #endif /* KRB4 || KRB5 */ | ||
171 | |||
172 | #if defined(AFS) || defined(KRB5) | ||
173 | /* XXX - punt on backward compatibility here. */ | ||
174 | case SSH_CMSG_HAVE_KERBEROS_TGT: | ||
175 | packet_send_debug("Kerberos TGT passing disabled before authentication."); | ||
176 | break; | ||
177 | #ifdef AFS | ||
178 | case SSH_CMSG_HAVE_AFS_TOKEN: | ||
179 | packet_send_debug("AFS token passing disabled before authentication."); | ||
180 | break; | ||
181 | #endif /* AFS */ | ||
182 | #endif /* AFS || KRB5 */ | ||
183 | |||
184 | case SSH_CMSG_AUTH_RHOSTS: | ||
185 | if (!options.rhosts_authentication) { | ||
186 | verbose("Rhosts authentication disabled."); | ||
187 | break; | ||
188 | } | ||
189 | /* | ||
190 | * Get client user name. Note that we just have to | ||
191 | * trust the client; this is one reason why rhosts | ||
192 | * authentication is insecure. (Another is | ||
193 | * IP-spoofing on a local network.) | ||
194 | */ | ||
195 | client_user = packet_get_string(&ulen); | ||
196 | packet_check_eom(); | ||
197 | |||
198 | /* Try to authenticate using /etc/hosts.equiv and .rhosts. */ | ||
199 | authenticated = auth_rhosts(pw, client_user); | ||
200 | |||
201 | snprintf(info, sizeof info, " ruser %.100s", client_user); | ||
202 | break; | ||
203 | |||
118 | case SSH_CMSG_AUTH_RHOSTS_RSA: | 204 | case SSH_CMSG_AUTH_RHOSTS_RSA: |
119 | if (!options.rhosts_rsa_authentication) { | 205 | if (!options.rhosts_rsa_authentication) { |
120 | verbose("Rhosts with RSA authentication disabled."); | 206 | verbose("Rhosts with RSA authentication disabled."); |
@@ -211,7 +297,7 @@ do_authloop(Authctxt *authctxt) | |||
211 | * Any unknown messages will be ignored (and failure | 297 | * Any unknown messages will be ignored (and failure |
212 | * returned) during authentication. | 298 | * returned) during authentication. |
213 | */ | 299 | */ |
214 | logit("Unknown message during authentication: type %d", type); | 300 | log("Unknown message during authentication: type %d", type); |
215 | break; | 301 | break; |
216 | } | 302 | } |
217 | #ifdef BSD_AUTH | 303 | #ifdef BSD_AUTH |
@@ -225,6 +311,8 @@ do_authloop(Authctxt *authctxt) | |||
225 | authctxt->user); | 311 | authctxt->user); |
226 | 312 | ||
227 | #ifdef _UNICOS | 313 | #ifdef _UNICOS |
314 | if (type == SSH_CMSG_AUTH_PASSWORD && !authenticated) | ||
315 | cray_login_failure(authctxt->user, IA_UDBERR); | ||
228 | if (authenticated && cray_access_denied(authctxt->user)) { | 316 | if (authenticated && cray_access_denied(authctxt->user)) { |
229 | authenticated = 0; | 317 | authenticated = 0; |
230 | fatal("Access denied for user %s.",authctxt->user); | 318 | fatal("Access denied for user %s.",authctxt->user); |
@@ -244,10 +332,9 @@ do_authloop(Authctxt *authctxt) | |||
244 | !auth_root_allowed(get_authname(type))) | 332 | !auth_root_allowed(get_authname(type))) |
245 | authenticated = 0; | 333 | authenticated = 0; |
246 | #endif | 334 | #endif |
247 | |||
248 | #ifdef USE_PAM | 335 | #ifdef USE_PAM |
249 | if (options.use_pam && authenticated && | 336 | if (!use_privsep && authenticated && |
250 | !PRIVSEP(do_pam_account())) | 337 | !do_pam_account(pw->pw_name, client_user)) |
251 | authenticated = 0; | 338 | authenticated = 0; |
252 | #endif | 339 | #endif |
253 | 340 | ||
@@ -262,8 +349,9 @@ do_authloop(Authctxt *authctxt) | |||
262 | if (authenticated) | 349 | if (authenticated) |
263 | return; | 350 | return; |
264 | 351 | ||
265 | if (authctxt->failures++ > AUTH_FAIL_MAX) | 352 | if (authctxt->failures++ > AUTH_FAIL_MAX) { |
266 | packet_disconnect(AUTH_FAIL_MSG, authctxt->user); | 353 | packet_disconnect(AUTH_FAIL_MSG, authctxt->user); |
354 | } | ||
267 | 355 | ||
268 | packet_start(SSH_SMSG_FAILURE); | 356 | packet_start(SSH_SMSG_FAILURE); |
269 | packet_send(); | 357 | packet_send(); |
@@ -292,6 +380,16 @@ do_authentication(void) | |||
292 | if ((style = strchr(user, ':')) != NULL) | 380 | if ((style = strchr(user, ':')) != NULL) |
293 | *style++ = '\0'; | 381 | *style++ = '\0'; |
294 | 382 | ||
383 | #ifdef KRB5 | ||
384 | /* XXX - SSH.com Kerberos v5 braindeath. */ | ||
385 | if ((datafellows & SSH_BUG_K5USER) && | ||
386 | options.kerberos_authentication) { | ||
387 | char *p; | ||
388 | if ((p = strchr(user, '@')) != NULL) | ||
389 | *p = '\0'; | ||
390 | } | ||
391 | #endif | ||
392 | |||
295 | authctxt = authctxt_new(); | 393 | authctxt = authctxt_new(); |
296 | authctxt->user = user; | 394 | authctxt->user = user; |
297 | authctxt->style = style; | 395 | authctxt->style = style; |
@@ -299,17 +397,14 @@ do_authentication(void) | |||
299 | /* Verify that the user is a valid user. */ | 397 | /* Verify that the user is a valid user. */ |
300 | if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) | 398 | if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) |
301 | authctxt->valid = 1; | 399 | authctxt->valid = 1; |
302 | else { | 400 | else |
303 | debug("do_authentication: illegal user %s", user); | 401 | debug("do_authentication: illegal user %s", user); |
304 | authctxt->pw = fakepw(); | ||
305 | } | ||
306 | 402 | ||
307 | setproctitle("%s%s", authctxt->pw ? user : "unknown", | 403 | setproctitle("%s%s", authctxt->pw ? user : "unknown", |
308 | use_privsep ? " [net]" : ""); | 404 | use_privsep ? " [net]" : ""); |
309 | 405 | ||
310 | #ifdef USE_PAM | 406 | #ifdef USE_PAM |
311 | if (options.use_pam) | 407 | PRIVSEP(start_pam(authctxt->pw == NULL ? "NOUSER" : user)); |
312 | PRIVSEP(start_pam(user)); | ||
313 | #endif | 408 | #endif |
314 | 409 | ||
315 | /* | 410 | /* |