]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssh/auth1.c
MFC r305065: Add refactored blacklist support to sshd
[FreeBSD/FreeBSD.git] / crypto / openssh / auth1.c
1 /* $OpenBSD: auth1.c,v 1.82 2014/07/15 15:54:14 millert Exp $ */
2 /*
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  *
6  * As far as I am concerned, the code I have written for this software
7  * can be used freely for any purpose.  Any derived versions of this
8  * software must be clearly marked as such, and if the derived work is
9  * incompatible with the protocol description in the RFC file, it must be
10  * called by a name other than "ssh" or "Secure Shell".
11  */
12
13 #include "includes.h"
14
15 #ifdef WITH_SSH1
16
17 #include <sys/types.h>
18
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <pwd.h>
24
25 #include "openbsd-compat/sys-queue.h"
26 #include "xmalloc.h"
27 #include "rsa.h"
28 #include "ssh1.h"
29 #include "packet.h"
30 #include "buffer.h"
31 #include "log.h"
32 #include "misc.h"
33 #include "servconf.h"
34 #include "compat.h"
35 #include "key.h"
36 #include "hostfile.h"
37 #include "auth.h"
38 #include "channels.h"
39 #include "session.h"
40 #include "uidswap.h"
41 #ifdef GSSAPI
42 #include "ssh-gss.h"
43 #endif
44 #include "monitor_wrap.h"
45 #include "buffer.h"
46 #include "blacklist_client.h"
47
48 /* import */
49 extern ServerOptions options;
50 extern Buffer loginmsg;
51
52 static int auth1_process_password(Authctxt *);
53 static int auth1_process_rsa(Authctxt *);
54 static int auth1_process_rhosts_rsa(Authctxt *);
55 static int auth1_process_tis_challenge(Authctxt *);
56 static int auth1_process_tis_response(Authctxt *);
57
58 static char *client_user = NULL;    /* Used to fill in remote user for PAM */
59
60 struct AuthMethod1 {
61         int type;
62         char *name;
63         int *enabled;
64         int (*method)(Authctxt *);
65 };
66
67 const struct AuthMethod1 auth1_methods[] = {
68         {
69                 SSH_CMSG_AUTH_PASSWORD, "password",
70                 &options.password_authentication, auth1_process_password
71         },
72         {
73                 SSH_CMSG_AUTH_RSA, "rsa",
74                 &options.rsa_authentication, auth1_process_rsa
75         },
76         {
77                 SSH_CMSG_AUTH_RHOSTS_RSA, "rhosts-rsa",
78                 &options.rhosts_rsa_authentication, auth1_process_rhosts_rsa
79         },
80         {
81                 SSH_CMSG_AUTH_TIS, "challenge-response",
82                 &options.challenge_response_authentication,
83                 auth1_process_tis_challenge
84         },
85         {
86                 SSH_CMSG_AUTH_TIS_RESPONSE, "challenge-response",
87                 &options.challenge_response_authentication,
88                 auth1_process_tis_response
89         },
90         { -1, NULL, NULL, NULL}
91 };
92
93 static const struct AuthMethod1
94 *lookup_authmethod1(int type)
95 {
96         int i;
97
98         for (i = 0; auth1_methods[i].name != NULL; i++)
99                 if (auth1_methods[i].type == type)
100                         return (&(auth1_methods[i]));
101
102         return (NULL);
103 }
104
105 static char *
106 get_authname(int type)
107 {
108         const struct AuthMethod1 *a;
109         static char buf[64];
110
111         if ((a = lookup_authmethod1(type)) != NULL)
112                 return (a->name);
113         snprintf(buf, sizeof(buf), "bad-auth-msg-%d", type);
114         return (buf);
115 }
116
117 /*ARGSUSED*/
118 static int
119 auth1_process_password(Authctxt *authctxt)
120 {
121         int authenticated = 0;
122         char *password;
123         u_int dlen;
124
125         /*
126          * Read user password.  It is in plain text, but was
127          * transmitted over the encrypted channel so it is
128          * not visible to an outside observer.
129          */
130         password = packet_get_string(&dlen);
131         packet_check_eom();
132
133         /* Try authentication with the password. */
134         authenticated = PRIVSEP(auth_password(authctxt, password));
135
136         explicit_bzero(password, dlen);
137         free(password);
138
139         return (authenticated);
140 }
141
142 /*ARGSUSED*/
143 static int
144 auth1_process_rsa(Authctxt *authctxt)
145 {
146         int authenticated = 0;
147         BIGNUM *n;
148
149         /* RSA authentication requested. */
150         if ((n = BN_new()) == NULL)
151                 fatal("do_authloop: BN_new failed");
152         packet_get_bignum(n);
153         packet_check_eom();
154         authenticated = auth_rsa(authctxt, n);
155         BN_clear_free(n);
156
157         return (authenticated);
158 }
159
160 /*ARGSUSED*/
161 static int
162 auth1_process_rhosts_rsa(Authctxt *authctxt)
163 {
164         int keybits, authenticated = 0;
165         u_int bits;
166         Key *client_host_key;
167         u_int ulen;
168
169         /*
170          * Get client user name.  Note that we just have to
171          * trust the client; root on the client machine can
172          * claim to be any user.
173          */
174         client_user = packet_get_cstring(&ulen);
175
176         /* Get the client host key. */
177         client_host_key = key_new(KEY_RSA1);
178         bits = packet_get_int();
179         packet_get_bignum(client_host_key->rsa->e);
180         packet_get_bignum(client_host_key->rsa->n);
181
182         keybits = BN_num_bits(client_host_key->rsa->n);
183         if (keybits < 0 || bits != (u_int)keybits) {
184                 verbose("Warning: keysize mismatch for client_host_key: "
185                     "actual %d, announced %d",
186                     BN_num_bits(client_host_key->rsa->n), bits);
187         }
188         packet_check_eom();
189
190         authenticated = auth_rhosts_rsa(authctxt, client_user,
191             client_host_key);
192         key_free(client_host_key);
193
194         auth_info(authctxt, "ruser %.100s", client_user);
195
196         return (authenticated);
197 }
198
199 /*ARGSUSED*/
200 static int
201 auth1_process_tis_challenge(Authctxt *authctxt)
202 {
203         char *challenge;
204
205         if ((challenge = get_challenge(authctxt)) == NULL)
206                 return (0);
207
208         debug("sending challenge '%s'", challenge);
209         packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
210         packet_put_cstring(challenge);
211         free(challenge);
212         packet_send();
213         packet_write_wait();
214
215         return (-1);
216 }
217
218 /*ARGSUSED*/
219 static int
220 auth1_process_tis_response(Authctxt *authctxt)
221 {
222         int authenticated = 0;
223         char *response;
224         u_int dlen;
225
226         response = packet_get_string(&dlen);
227         packet_check_eom();
228         authenticated = verify_response(authctxt, response);
229         explicit_bzero(response, dlen);
230         free(response);
231
232         return (authenticated);
233 }
234
235 /*
236  * read packets, try to authenticate the user and
237  * return only if authentication is successful
238  */
239 static void
240 do_authloop(Authctxt *authctxt)
241 {
242         int authenticated = 0;
243         int prev = 0, type = 0;
244         const struct AuthMethod1 *meth;
245
246         debug("Attempting authentication for %s%.100s.",
247             authctxt->valid ? "" : "invalid user ", authctxt->user);
248
249         /* If the user has no password, accept authentication immediately. */
250         if (options.permit_empty_passwd && options.password_authentication &&
251 #ifdef KRB5
252             (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
253 #endif
254             PRIVSEP(auth_password(authctxt, ""))) {
255 #ifdef USE_PAM
256                 if (options.use_pam && (PRIVSEP(do_pam_account())))
257 #endif
258                 {
259                         auth_log(authctxt, 1, 0, "without authentication",
260                             NULL);
261                         return;
262                 }
263         }
264
265         /* Indicate that authentication is needed. */
266         packet_start(SSH_SMSG_FAILURE);
267         packet_send();
268         packet_write_wait();
269
270         for (;;) {
271                 /* default to fail */
272                 authenticated = 0;
273
274
275                 /* Get a packet from the client. */
276                 prev = type;
277                 type = packet_read();
278
279                 /*
280                  * If we started challenge-response authentication but the
281                  * next packet is not a response to our challenge, release
282                  * the resources allocated by get_challenge() (which would
283                  * normally have been released by verify_response() had we
284                  * received such a response)
285                  */
286                 if (prev == SSH_CMSG_AUTH_TIS &&
287                     type != SSH_CMSG_AUTH_TIS_RESPONSE)
288                         abandon_challenge_response(authctxt);
289
290                 if (authctxt->failures >= options.max_authtries)
291                         goto skip;
292                 if ((meth = lookup_authmethod1(type)) == NULL) {
293                         logit("Unknown message during authentication: "
294                             "type %d", type);
295                         goto skip;
296                 }
297
298                 if (!*(meth->enabled)) {
299                         verbose("%s authentication disabled.", meth->name);
300                         goto skip;
301                 }
302
303                 authenticated = meth->method(authctxt);
304                 if (authenticated == -1)
305                         continue; /* "postponed" */
306
307 #ifdef BSD_AUTH
308                 if (authctxt->as) {
309                         auth_close(authctxt->as);
310                         authctxt->as = NULL;
311                 }
312 #endif
313                 if (!authctxt->valid && authenticated)
314                         fatal("INTERNAL ERROR: authenticated invalid user %s",
315                             authctxt->user);
316
317 #ifdef _UNICOS
318                 if (authenticated && cray_access_denied(authctxt->user)) {
319                         authenticated = 0;
320                         fatal("Access denied for user %s.",authctxt->user);
321                 }
322 #endif /* _UNICOS */
323
324 #ifndef HAVE_CYGWIN
325                 /* Special handling for root */
326                 if (authenticated && authctxt->pw->pw_uid == 0 &&
327                     !auth_root_allowed(meth->name)) {
328                         authenticated = 0;
329 # ifdef SSH_AUDIT_EVENTS
330                         PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
331 # endif
332                 }
333 #endif
334
335 #ifdef USE_PAM
336                 if (options.use_pam && authenticated &&
337                     !PRIVSEP(do_pam_account())) {
338                         char *msg;
339                         size_t len;
340
341                         BLACKLIST_NOTIFY(BLACKLIST_AUTH_FAIL);
342                         error("Access denied for user %s by PAM account "
343                             "configuration", authctxt->user);
344                         len = buffer_len(&loginmsg);
345                         buffer_append(&loginmsg, "\0", 1);
346                         msg = buffer_ptr(&loginmsg);
347                         /* strip trailing newlines */
348                         if (len > 0)
349                                 while (len > 0 && msg[--len] == '\n')
350                                         msg[len] = '\0';
351                         else
352                                 msg = "Access denied.";
353                         packet_disconnect("%s", msg);
354                 }
355 #endif
356
357  skip:
358                 /* Log before sending the reply */
359                 auth_log(authctxt, authenticated, 0, get_authname(type), NULL);
360
361                 free(client_user);
362                 client_user = NULL;
363
364                 if (authenticated)
365                         return;
366
367                 if (++authctxt->failures >= options.max_authtries) {
368 #ifdef SSH_AUDIT_EVENTS
369                         PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
370 #endif
371                         auth_maxtries_exceeded(authctxt);
372                 }
373
374                 packet_start(SSH_SMSG_FAILURE);
375                 packet_send();
376                 packet_write_wait();
377         }
378 }
379
380 /*
381  * Performs authentication of an incoming connection.  Session key has already
382  * been exchanged and encryption is enabled.
383  */
384 void
385 do_authentication(Authctxt *authctxt)
386 {
387         u_int ulen;
388         char *user, *style = NULL;
389
390         /* Get the name of the user that we wish to log in as. */
391         packet_read_expect(SSH_CMSG_USER);
392
393         /* Get the user name. */
394         user = packet_get_cstring(&ulen);
395         packet_check_eom();
396
397         if ((style = strchr(user, ':')) != NULL)
398                 *style++ = '\0';
399
400         authctxt->user = user;
401         authctxt->style = style;
402
403         /* Verify that the user is a valid user. */
404         if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
405                 authctxt->valid = 1;
406         else {
407                 debug("do_authentication: invalid user %s", user);
408                 authctxt->pw = fakepw();
409                 BLACKLIST_NOTIFY(BLACKLIST_AUTH_FAIL);
410         }
411
412         /* Configuration may have changed as a result of Match */
413         if (options.num_auth_methods != 0)
414                 fatal("AuthenticationMethods is not supported with SSH "
415                     "protocol 1");
416
417         setproctitle("%s%s", authctxt->valid ? user : "unknown",
418             use_privsep ? " [net]" : "");
419
420 #ifdef USE_PAM
421         if (options.use_pam)
422                 PRIVSEP(start_pam(authctxt));
423 #endif
424
425         /*
426          * If we are not running as root, the user must have the same uid as
427          * the server.
428          */
429 #ifndef HAVE_CYGWIN
430         if (!use_privsep && getuid() != 0 && authctxt->pw &&
431             authctxt->pw->pw_uid != getuid())
432                 packet_disconnect("Cannot change user when server not running as root.");
433 #endif
434
435         /*
436          * Loop until the user has been authenticated or the connection is
437          * closed, do_authloop() returns only if authentication is successful
438          */
439         do_authloop(authctxt);
440
441         /* The user has been authenticated and accepted. */
442         packet_start(SSH_SMSG_SUCCESS);
443         packet_send();
444         packet_write_wait();
445 }
446
447 #endif /* WITH_SSH1 */