]> andersk Git - openssh.git/blob - auth1.c
- (bal) auth-chall.c auth-passwd.c auth.h auth1.c auth2.c session.c CVS ID
[openssh.git] / 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.20 2001/03/20 18:57:04 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 "session.h"
26 #include "misc.h"
27
28 /* import */
29 extern ServerOptions options;
30
31 #ifdef WITH_AIXAUTHENTICATE
32 extern char *aixloginmsg;
33 #endif /* WITH_AIXAUTHENTICATE */
34
35 /*
36  * convert ssh auth msg type into description
37  */
38 char *
39 get_authname(int type)
40 {
41         static char buf[1024];
42         switch (type) {
43         case SSH_CMSG_AUTH_PASSWORD:
44                 return "password";
45         case SSH_CMSG_AUTH_RSA:
46                 return "rsa";
47         case SSH_CMSG_AUTH_RHOSTS_RSA:
48                 return "rhosts-rsa";
49         case SSH_CMSG_AUTH_RHOSTS:
50                 return "rhosts";
51         case SSH_CMSG_AUTH_TIS:
52         case SSH_CMSG_AUTH_TIS_RESPONSE:
53                 return "challenge-response";
54 #ifdef KRB4
55         case SSH_CMSG_AUTH_KERBEROS:
56                 return "kerberos";
57 #endif
58         }
59         snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
60         return buf;
61 }
62
63 /*
64  * read packets, try to authenticate the user and
65  * return only if authentication is successful
66  */
67 void
68 do_authloop(Authctxt *authctxt)
69 {
70         int authenticated = 0;
71         u_int bits;
72         RSA *client_host_key;
73         BIGNUM *n;
74         char *client_user, *password;
75         char info[1024];
76         u_int dlen;
77         int plen, nlen, elen;
78         u_int ulen;
79         int type = 0;
80         struct passwd *pw = authctxt->pw;
81
82         debug("Attempting authentication for %s%.100s.",
83              authctxt->valid ? "" : "illegal user ", authctxt->user);
84
85         /* If the user has no password, accept authentication immediately. */
86         if (options.password_authentication &&
87 #ifdef KRB4
88             (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
89 #endif
90 #ifdef USE_PAM
91             auth_pam_password(pw, "")) {
92 #elif defined(HAVE_OSF_SIA)
93             0) {
94 #else
95             auth_password(authctxt, "")) {
96 #endif
97                 auth_log(authctxt, 1, "without authentication", "");
98                 return;
99         }
100
101         /* Indicate that authentication is needed. */
102         packet_start(SSH_SMSG_FAILURE);
103         packet_send();
104         packet_write_wait();
105
106         client_user = NULL;
107
108         for (;;) {
109                 /* default to fail */
110                 authenticated = 0;
111
112                 info[0] = '\0';
113
114                 /* Get a packet from the client. */
115                 type = packet_read(&plen);
116
117                 /* Process the packet. */
118                 switch (type) {
119 #ifdef AFS
120                 case SSH_CMSG_HAVE_KERBEROS_TGT:
121                         if (!options.kerberos_tgt_passing) {
122                                 verbose("Kerberos tgt passing disabled.");
123                                 break;
124                         } else {
125                                 /* Accept Kerberos tgt. */
126                                 char *tgt = packet_get_string(&dlen);
127                                 packet_integrity_check(plen, 4 + dlen, type);
128                                 if (!auth_kerberos_tgt(pw, tgt))
129                                         verbose("Kerberos tgt REFUSED for %.100s", authctxt->user);
130                                 xfree(tgt);
131                         }
132                         continue;
133
134                 case SSH_CMSG_HAVE_AFS_TOKEN:
135                         if (!options.afs_token_passing || !k_hasafs()) {
136                                 verbose("AFS token passing disabled.");
137                                 break;
138                         } else {
139                                 /* Accept AFS token. */
140                                 char *token_string = packet_get_string(&dlen);
141                                 packet_integrity_check(plen, 4 + dlen, type);
142                                 if (!auth_afs_token(pw, token_string))
143                                         verbose("AFS token REFUSED for %.100s", authctxt->user);
144                                 xfree(token_string);
145                         }
146                         continue;
147 #endif /* AFS */
148 #ifdef KRB4
149                 case SSH_CMSG_AUTH_KERBEROS:
150                         if (!options.kerberos_authentication) {
151                                 verbose("Kerberos authentication disabled.");
152                                 break;
153                         } else {
154                                 /* Try Kerberos v4 authentication. */
155                                 KTEXT_ST auth;
156                                 char *tkt_user = NULL;
157                                 char *kdata = packet_get_string((u_int *) &auth.length);
158                                 packet_integrity_check(plen, 4 + auth.length, type);
159
160                                 if (authctxt->valid) {
161                                         if (auth.length < MAX_KTXT_LEN)
162                                                 memcpy(auth.dat, kdata, auth.length);
163                                         authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
164                                         if (authenticated) {
165                                                 snprintf(info, sizeof info,
166                                                     " tktuser %.100s", tkt_user);
167                                                 xfree(tkt_user);
168                                         }
169                                 }
170                                 xfree(kdata);
171                         }
172                         break;
173 #endif /* KRB4 */
174
175                 case SSH_CMSG_AUTH_RHOSTS:
176                         if (!options.rhosts_authentication) {
177                                 verbose("Rhosts authentication disabled.");
178                                 break;
179                         }
180                         /*
181                          * Get client user name.  Note that we just have to
182                          * trust the client; this is one reason why rhosts
183                          * authentication is insecure. (Another is
184                          * IP-spoofing on a local network.)
185                          */
186                         client_user = packet_get_string(&ulen);
187                         packet_integrity_check(plen, 4 + ulen, type);
188
189                         /* Try to authenticate using /etc/hosts.equiv and .rhosts. */
190                         authenticated = auth_rhosts(pw, client_user);
191
192                         snprintf(info, sizeof info, " ruser %.100s", client_user);
193                         break;
194
195                 case SSH_CMSG_AUTH_RHOSTS_RSA:
196                         if (!options.rhosts_rsa_authentication) {
197                                 verbose("Rhosts with RSA authentication disabled.");
198                                 break;
199                         }
200                         /*
201                          * Get client user name.  Note that we just have to
202                          * trust the client; root on the client machine can
203                          * claim to be any user.
204                          */
205                         client_user = packet_get_string(&ulen);
206
207                         /* Get the client host key. */
208                         client_host_key = RSA_new();
209                         if (client_host_key == NULL)
210                                 fatal("RSA_new failed");
211                         client_host_key->e = BN_new();
212                         client_host_key->n = BN_new();
213                         if (client_host_key->e == NULL || client_host_key->n == NULL)
214                                 fatal("BN_new failed");
215                         bits = packet_get_int();
216                         packet_get_bignum(client_host_key->e, &elen);
217                         packet_get_bignum(client_host_key->n, &nlen);
218
219                         if (bits != BN_num_bits(client_host_key->n))
220                                 verbose("Warning: keysize mismatch for client_host_key: "
221                                     "actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
222                         packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
223
224                         authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
225                         RSA_free(client_host_key);
226
227                         snprintf(info, sizeof info, " ruser %.100s", client_user);
228                         break;
229
230                 case SSH_CMSG_AUTH_RSA:
231                         if (!options.rsa_authentication) {
232                                 verbose("RSA authentication disabled.");
233                                 break;
234                         }
235                         /* RSA authentication requested. */
236                         n = BN_new();
237                         packet_get_bignum(n, &nlen);
238                         packet_integrity_check(plen, nlen, type);
239                         authenticated = auth_rsa(pw, n);
240                         BN_clear_free(n);
241                         break;
242
243                 case SSH_CMSG_AUTH_PASSWORD:
244                         if (!options.password_authentication) {
245                                 verbose("Password authentication disabled.");
246                                 break;
247                         }
248                         /*
249                          * Read user password.  It is in plain text, but was
250                          * transmitted over the encrypted channel so it is
251                          * not visible to an outside observer.
252                          */
253                         password = packet_get_string(&dlen);
254                         packet_integrity_check(plen, 4 + dlen, type);
255
256 #ifdef USE_PAM
257                         /* Do PAM auth with password */
258                         authenticated = auth_pam_password(pw, password);
259 #elif defined(HAVE_OSF_SIA)
260                         /* Do SIA auth with password */
261                         authenticated = auth_sia_password(authctxt->user, 
262                             password);
263 #else /* !USE_PAM && !HAVE_OSF_SIA */
264                         /* Try authentication with the password. */
265                         authenticated = auth_password(authctxt, password);
266 #endif /* USE_PAM */
267
268                         memset(password, 0, strlen(password));
269                         xfree(password);
270                         break;
271
272                 case SSH_CMSG_AUTH_TIS:
273                         debug("rcvd SSH_CMSG_AUTH_TIS");
274                         if (options.challenge_reponse_authentication == 1) {
275                                 char *challenge = get_challenge(authctxt, authctxt->style);
276                                 if (challenge != NULL) {
277                                         debug("sending challenge '%s'", challenge);
278                                         packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
279                                         packet_put_cstring(challenge);
280                                         packet_send();
281                                         packet_write_wait();
282                                         continue;
283                                 }
284                         }
285                         break;
286                 case SSH_CMSG_AUTH_TIS_RESPONSE:
287                         debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
288                         if (options.challenge_reponse_authentication == 1) {
289                                 char *response = packet_get_string(&dlen);
290                                 debug("got response '%s'", response);
291                                 packet_integrity_check(plen, 4 + dlen, type);
292                                 authenticated = verify_response(authctxt, response);
293                                 memset(response, 'r', dlen);
294                                 xfree(response);
295                         }
296                         break;
297
298                 default:
299                         /*
300                          * Any unknown messages will be ignored (and failure
301                          * returned) during authentication.
302                          */
303                         log("Unknown message during authentication: type %d", type);
304                         break;
305                 }
306 #ifdef BSD_AUTH
307                 if (authctxt->as) {
308                         auth_close(authctxt->as);
309                         authctxt->as = NULL;
310                 }
311 #endif
312                 if (!authctxt->valid && authenticated)
313                         fatal("INTERNAL ERROR: authenticated invalid user %s",
314                             authctxt->user);
315
316 #ifdef HAVE_CYGWIN
317                 if (authenticated &&
318                     !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,pw->pw_uid)) {
319                         packet_disconnect("Authentication rejected for uid %d.",
320                         (int)pw->pw_uid);
321                         authenticated = 0;
322                 }
323 #else
324                 /* Special handling for root */
325                 if (authenticated && authctxt->pw->pw_uid == 0 &&
326                     !auth_root_allowed(get_authname(type)))
327                         authenticated = 0;
328 #endif
329 #ifdef USE_PAM
330                 if (authenticated && !do_pam_account(pw->pw_name, client_user))
331                         authenticated = 0;
332 #endif
333
334                 /* Log before sending the reply */
335                 auth_log(authctxt, authenticated, get_authname(type), info);
336
337                 if (client_user != NULL) {
338                         xfree(client_user);
339                         client_user = NULL;
340                 }
341
342                 if (authenticated)
343                         return;
344
345                 if (authctxt->failures++ > AUTH_FAIL_MAX) {
346 #ifdef WITH_AIXAUTHENTICATE
347                         loginfailed(authctxt->user,
348                             get_canonical_hostname(options.reverse_mapping_check),
349                             "ssh");
350 #endif /* WITH_AIXAUTHENTICATE */
351                         packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
352                 }
353
354                 packet_start(SSH_SMSG_FAILURE);
355                 packet_send();
356                 packet_write_wait();
357         }
358 }
359
360 /*
361  * Performs authentication of an incoming connection.  Session key has already
362  * been exchanged and encryption is enabled.
363  */
364 void
365 do_authentication()
366 {
367         Authctxt *authctxt;
368         struct passwd *pw;
369         int plen;
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(&plen, SSH_CMSG_USER);
375
376         /* Get the user name. */
377         user = packet_get_string(&ulen);
378         packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
379
380         if ((style = strchr(user, ':')) != NULL)
381                 *style++ = 0;
382
383         authctxt = authctxt_new();
384         authctxt->user = user;
385         authctxt->style = style;
386
387         /* Verify that the user is a valid user. */
388         pw = getpwnam(user);
389         if (pw && allowed_user(pw)) {
390                 authctxt->valid = 1;
391                 pw = pwcopy(pw);
392         } else {
393                 debug("do_authentication: illegal user %s", user);
394                 pw = NULL;
395         }
396         authctxt->pw = pw;
397
398         setproctitle("%s", pw ? user : "unknown");
399
400 #ifdef USE_PAM
401         if (pw)
402                 start_pam(user);
403 #endif
404
405         /*
406          * If we are not running as root, the user must have the same uid as
407          * the server. (Unless you are running Windows)
408          */
409 #ifndef HAVE_CYGWIN
410         if (getuid() != 0 && pw && pw->pw_uid != getuid())
411                 packet_disconnect("Cannot change user when server not running as root.");
412 #endif
413
414         /*
415          * Loop until the user has been authenticated or the connection is
416          * closed, do_authloop() returns only if authentication is successful
417          */
418         do_authloop(authctxt);
419
420         /* The user has been authenticated and accepted. */
421         packet_start(SSH_SMSG_SUCCESS);
422         packet_send();
423         packet_write_wait();
424
425 #ifdef WITH_AIXAUTHENTICATE
426         /* We don't have a pty yet, so just label the line as "ssh" */
427         if (loginsuccess(authctxt->user,
428             get_canonical_hostname(options.reverse_mapping_check),
429             "ssh", &aixloginmsg) < 0)
430                 aixloginmsg = NULL;
431 #endif /* WITH_AIXAUTHENTICATE */
432
433         xfree(authctxt->user);
434         xfree(authctxt);
435
436         /* Perform session preparation. */
437         do_authenticated(pw);
438 }
This page took 0.268224 seconds and 5 git commands to generate.