]> andersk Git - gssapi-openssh.git/blob - openssh/auth1.c
Import of OpenSSH 3.6.1p1
[gssapi-openssh.git] / openssh / auth1.c
1 /*
2  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3  *                    All rights reserved
4  *
5  * As far as I am concerned, the code I have written for this software
6  * can be used freely for any purpose.  Any derived versions of this
7  * software must be clearly marked as such, and if the derived work is
8  * incompatible with the protocol description in the RFC file, it must be
9  * called by a name other than "ssh" or "Secure Shell".
10  */
11
12 #include "includes.h"
13 RCSID("$OpenBSD: auth1.c,v 1.47 2003/02/06 21:22:42 markus Exp $");
14
15 #include "xmalloc.h"
16 #include "rsa.h"
17 #include "ssh1.h"
18 #include "packet.h"
19 #include "buffer.h"
20 #include "mpaux.h"
21 #include "log.h"
22 #include "servconf.h"
23 #include "compat.h"
24 #include "auth.h"
25 #include "channels.h"
26 #include "session.h"
27 #include "uidswap.h"
28 #include "monitor_wrap.h"
29
30 /* import */
31 extern ServerOptions options;
32
33 /*
34  * convert ssh auth msg type into description
35  */
36 static char *
37 get_authname(int type)
38 {
39         static char buf[1024];
40         switch (type) {
41         case SSH_CMSG_AUTH_PASSWORD:
42                 return "password";
43         case SSH_CMSG_AUTH_RSA:
44                 return "rsa";
45         case SSH_CMSG_AUTH_RHOSTS_RSA:
46                 return "rhosts-rsa";
47         case SSH_CMSG_AUTH_RHOSTS:
48                 return "rhosts";
49         case SSH_CMSG_AUTH_TIS:
50         case SSH_CMSG_AUTH_TIS_RESPONSE:
51                 return "challenge-response";
52 #if defined(KRB4) || defined(KRB5)
53         case SSH_CMSG_AUTH_KERBEROS:
54                 return "kerberos";
55 #endif
56         }
57         snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
58         return buf;
59 }
60
61 /*
62  * read packets, try to authenticate the user and
63  * return only if authentication is successful
64  */
65 static void
66 do_authloop(Authctxt *authctxt)
67 {
68         int authenticated = 0;
69         u_int bits;
70         Key *client_host_key;
71         BIGNUM *n;
72         char *client_user, *password;
73         char info[1024];
74         u_int dlen;
75         u_int ulen;
76         int type = 0;
77         struct passwd *pw = authctxt->pw;
78
79         debug("Attempting authentication for %s%.100s.",
80             authctxt->valid ? "" : "illegal user ", authctxt->user);
81
82         /* If the user has no password, accept authentication immediately. */
83         if (options.password_authentication &&
84 #if defined(KRB4) || defined(KRB5)
85             (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
86 #endif
87             PRIVSEP(auth_password(authctxt, ""))) {
88                 auth_log(authctxt, 1, "without authentication", "");
89                 return;
90         }
91
92         /* Indicate that authentication is needed. */
93         packet_start(SSH_SMSG_FAILURE);
94         packet_send();
95         packet_write_wait();
96
97         client_user = NULL;
98
99         for (;;) {
100                 /* default to fail */
101                 authenticated = 0;
102
103                 info[0] = '\0';
104
105                 /* Get a packet from the client. */
106                 type = packet_read();
107
108                 /* Process the packet. */
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
204                 case SSH_CMSG_AUTH_RHOSTS_RSA:
205                         if (!options.rhosts_rsa_authentication) {
206                                 verbose("Rhosts with RSA authentication disabled.");
207                                 break;
208                         }
209                         /*
210                          * Get client user name.  Note that we just have to
211                          * trust the client; root on the client machine can
212                          * claim to be any user.
213                          */
214                         client_user = packet_get_string(&ulen);
215
216                         /* Get the client host key. */
217                         client_host_key = key_new(KEY_RSA1);
218                         bits = packet_get_int();
219                         packet_get_bignum(client_host_key->rsa->e);
220                         packet_get_bignum(client_host_key->rsa->n);
221
222                         if (bits != BN_num_bits(client_host_key->rsa->n))
223                                 verbose("Warning: keysize mismatch for client_host_key: "
224                                     "actual %d, announced %d",
225                                     BN_num_bits(client_host_key->rsa->n), bits);
226                         packet_check_eom();
227
228                         authenticated = auth_rhosts_rsa(pw, client_user,
229                             client_host_key);
230                         key_free(client_host_key);
231
232                         snprintf(info, sizeof info, " ruser %.100s", client_user);
233                         break;
234
235                 case SSH_CMSG_AUTH_RSA:
236                         if (!options.rsa_authentication) {
237                                 verbose("RSA authentication disabled.");
238                                 break;
239                         }
240                         /* RSA authentication requested. */
241                         if ((n = BN_new()) == NULL)
242                                 fatal("do_authloop: BN_new failed");
243                         packet_get_bignum(n);
244                         packet_check_eom();
245                         authenticated = auth_rsa(pw, n);
246                         BN_clear_free(n);
247                         break;
248
249                 case SSH_CMSG_AUTH_PASSWORD:
250                         if (!options.password_authentication) {
251                                 verbose("Password authentication disabled.");
252                                 break;
253                         }
254                         /*
255                          * Read user password.  It is in plain text, but was
256                          * transmitted over the encrypted channel so it is
257                          * not visible to an outside observer.
258                          */
259                         password = packet_get_string(&dlen);
260                         packet_check_eom();
261
262                         /* Try authentication with the password. */
263                         authenticated = PRIVSEP(auth_password(authctxt, password));
264
265                         memset(password, 0, strlen(password));
266                         xfree(password);
267                         break;
268
269                 case SSH_CMSG_AUTH_TIS:
270                         debug("rcvd SSH_CMSG_AUTH_TIS");
271                         if (options.challenge_response_authentication == 1) {
272                                 char *challenge = get_challenge(authctxt);
273                                 if (challenge != NULL) {
274                                         debug("sending challenge '%s'", challenge);
275                                         packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
276                                         packet_put_cstring(challenge);
277                                         xfree(challenge);
278                                         packet_send();
279                                         packet_write_wait();
280                                         continue;
281                                 }
282                         }
283                         break;
284                 case SSH_CMSG_AUTH_TIS_RESPONSE:
285                         debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
286                         if (options.challenge_response_authentication == 1) {
287                                 char *response = packet_get_string(&dlen);
288                                 packet_check_eom();
289                                 authenticated = verify_response(authctxt, response);
290                                 memset(response, 'r', dlen);
291                                 xfree(response);
292                         }
293                         break;
294
295                 default:
296                         /*
297                          * Any unknown messages will be ignored (and failure
298                          * returned) during authentication.
299                          */
300                         log("Unknown message during authentication: type %d", type);
301                         break;
302                 }
303 #ifdef BSD_AUTH
304                 if (authctxt->as) {
305                         auth_close(authctxt->as);
306                         authctxt->as = NULL;
307                 }
308 #endif
309                 if (!authctxt->valid && authenticated)
310                         fatal("INTERNAL ERROR: authenticated invalid user %s",
311                             authctxt->user);
312
313 #ifdef _UNICOS
314                 if (type == SSH_CMSG_AUTH_PASSWORD && !authenticated)
315                         cray_login_failure(authctxt->user, IA_UDBERR);
316                 if (authenticated && cray_access_denied(authctxt->user)) {
317                         authenticated = 0;
318                         fatal("Access denied for user %s.",authctxt->user);
319                 }
320 #endif /* _UNICOS */
321
322 #ifdef HAVE_CYGWIN
323                 if (authenticated &&
324                     !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, pw)) {
325                         packet_disconnect("Authentication rejected for uid %d.",
326                         pw == NULL ? -1 : pw->pw_uid);
327                         authenticated = 0;
328                 }
329 #else
330                 /* Special handling for root */
331                 if (authenticated && authctxt->pw->pw_uid == 0 &&
332                     !auth_root_allowed(get_authname(type)))
333                         authenticated = 0;
334 #endif
335 #ifdef USE_PAM
336                 if (!use_privsep && authenticated && 
337                     !do_pam_account(pw->pw_name, client_user))
338                         authenticated = 0;
339 #endif
340
341                 /* Log before sending the reply */
342                 auth_log(authctxt, authenticated, get_authname(type), info);
343
344                 if (client_user != NULL) {
345                         xfree(client_user);
346                         client_user = NULL;
347                 }
348
349                 if (authenticated)
350                         return;
351
352                 if (authctxt->failures++ > AUTH_FAIL_MAX) {
353                         packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
354                 }
355
356                 packet_start(SSH_SMSG_FAILURE);
357                 packet_send();
358                 packet_write_wait();
359         }
360 }
361
362 /*
363  * Performs authentication of an incoming connection.  Session key has already
364  * been exchanged and encryption is enabled.
365  */
366 Authctxt *
367 do_authentication(void)
368 {
369         Authctxt *authctxt;
370         u_int ulen;
371         char *user, *style = NULL;
372
373         /* Get the name of the user that we wish to log in as. */
374         packet_read_expect(SSH_CMSG_USER);
375
376         /* Get the user name. */
377         user = packet_get_string(&ulen);
378         packet_check_eom();
379
380         if ((style = strchr(user, ':')) != NULL)
381                 *style++ = '\0';
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
393         authctxt = authctxt_new();
394         authctxt->user = user;
395         authctxt->style = style;
396
397         /* Verify that the user is a valid user. */
398         if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
399                 authctxt->valid = 1;
400         else
401                 debug("do_authentication: illegal user %s", user);
402
403         setproctitle("%s%s", authctxt->pw ? user : "unknown",
404             use_privsep ? " [net]" : "");
405
406 #ifdef USE_PAM
407         PRIVSEP(start_pam(authctxt->pw == NULL ? "NOUSER" : user));
408 #endif
409
410         /*
411          * If we are not running as root, the user must have the same uid as
412          * the server. (Unless you are running Windows)
413          */
414 #ifndef HAVE_CYGWIN
415         if (!use_privsep && getuid() != 0 && authctxt->pw &&
416             authctxt->pw->pw_uid != getuid())
417                 packet_disconnect("Cannot change user when server not running as root.");
418 #endif
419
420         /*
421          * Loop until the user has been authenticated or the connection is
422          * closed, do_authloop() returns only if authentication is successful
423          */
424         do_authloop(authctxt);
425
426         /* The user has been authenticated and accepted. */
427         packet_start(SSH_SMSG_SUCCESS);
428         packet_send();
429         packet_write_wait();
430
431         return (authctxt);
432 }
This page took 0.143388 seconds and 5 git commands to generate.