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