]> andersk Git - openssh.git/blame - auth2.c
That shouldn't be here yet
[openssh.git] / auth2.c
CommitLineData
a306f2dd 1/*
2 * Copyright (c) 2000 Markus Friedl. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
a306f2dd 12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
bcbf86ec 24
a306f2dd 25#include "includes.h"
c66f9d0e 26RCSID("$OpenBSD: auth2.c,v 1.85 2002/02/24 19:14:59 markus Exp $");
94ec8c6b 27
a306f2dd 28#include <openssl/evp.h>
29
42f11eb2 30#include "ssh2.h"
a306f2dd 31#include "xmalloc.h"
32#include "rsa.h"
1729c161 33#include "sshpty.h"
a306f2dd 34#include "packet.h"
35#include "buffer.h"
42f11eb2 36#include "log.h"
a306f2dd 37#include "servconf.h"
38#include "compat.h"
a5efa1bb 39#include "channels.h"
a306f2dd 40#include "bufaux.h"
a306f2dd 41#include "auth.h"
42#include "session.h"
43#include "dispatch.h"
a306f2dd 44#include "key.h"
b0e305c9 45#include "cipher.h"
a306f2dd 46#include "kex.h"
42f11eb2 47#include "pathnames.h"
a306f2dd 48#include "uidswap.h"
38c295d6 49#include "auth-options.h"
3b1a83df 50#include "misc.h"
8002af61 51#include "hostfile.h"
52#include "canohost.h"
5ba55ada 53#include "match.h"
91885a4d 54#include "monitor.h"
55#include "monitor_wrap.h"
a306f2dd 56
57/* import */
91885a4d 58extern int use_privsep;
59extern int mm_recvfd;
60
a306f2dd 61extern ServerOptions options;
1e3b8b07 62extern u_char *session_id2;
a306f2dd 63extern int session_id2_len;
64
94ec8c6b 65static Authctxt *x_authctxt = NULL;
66static int one = 1;
67
68typedef struct Authmethod Authmethod;
69struct Authmethod {
70 char *name;
71 int (*userauth)(Authctxt *authctxt);
72 int *enabled;
73};
74
a306f2dd 75/* protocol */
76
7819b5c3 77static void input_service_request(int, u_int32_t, void *);
78static void input_userauth_request(int, u_int32_t, void *);
a306f2dd 79
a306f2dd 80/* helper */
396c147e 81static Authmethod *authmethod_lookup(const char *);
ffb215be 82static char *authmethods_get(void);
91885a4d 83int user_key_allowed(struct passwd *, Key *);
84int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
a306f2dd 85
94ec8c6b 86/* auth */
396c147e 87static void userauth_banner(void);
88static int userauth_none(Authctxt *);
89static int userauth_passwd(Authctxt *);
90static int userauth_pubkey(Authctxt *);
91static int userauth_hostbased(Authctxt *);
92static int userauth_kbdint(Authctxt *);
94ec8c6b 93
94Authmethod authmethods[] = {
95 {"none",
96 userauth_none,
97 &one},
98 {"publickey",
99 userauth_pubkey,
fa08c86b 100 &options.pubkey_authentication},
94ec8c6b 101 {"password",
102 userauth_passwd,
103 &options.password_authentication},
c845316f 104 {"keyboard-interactive",
105 userauth_kbdint,
106 &options.kbd_interactive_authentication},
8002af61 107 {"hostbased",
108 userauth_hostbased,
109 &options.hostbased_authentication},
94ec8c6b 110 {NULL, NULL, NULL}
a306f2dd 111};
a306f2dd 112
113/*
94ec8c6b 114 * loop until authctxt->success == TRUE
a306f2dd 115 */
116
91885a4d 117Authctxt *
d5bb9418 118do_authentication2(void)
a306f2dd 119{
59c97189 120 Authctxt *authctxt = authctxt_new();
121
94ec8c6b 122 x_authctxt = authctxt; /*XXX*/
123
aa8003d6 124 /* challenge-response is implemented via keyboard interactive */
5ba55ada 125 if (options.challenge_response_authentication)
d464095c 126 options.kbd_interactive_authentication = 1;
10f72868 127 if (options.pam_authentication_via_kbd_int)
128 options.kbd_interactive_authentication = 1;
d464095c 129
6367063f 130 dispatch_init(&dispatch_protocol_error);
a306f2dd 131 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
94ec8c6b 132 dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
91885a4d 133
134 return(authctxt);
a306f2dd 135}
136
396c147e 137static void
7819b5c3 138input_service_request(int type, u_int32_t seq, void *ctxt)
a306f2dd 139{
94ec8c6b 140 Authctxt *authctxt = ctxt;
1e3b8b07 141 u_int len;
a306f2dd 142 int accept = 0;
143 char *service = packet_get_string(&len);
95500969 144 packet_check_eom();
a306f2dd 145
94ec8c6b 146 if (authctxt == NULL)
147 fatal("input_service_request: no authctxt");
148
a306f2dd 149 if (strcmp(service, "ssh-userauth") == 0) {
94ec8c6b 150 if (!authctxt->success) {
a306f2dd 151 accept = 1;
152 /* now we can handle user-auth requests */
153 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
154 }
155 }
156 /* XXX all other service requests are denied */
157
158 if (accept) {
159 packet_start(SSH2_MSG_SERVICE_ACCEPT);
160 packet_put_cstring(service);
161 packet_send();
162 packet_write_wait();
163 } else {
164 debug("bad service request %s", service);
165 packet_disconnect("bad service request %s", service);
166 }
167 xfree(service);
168}
169
396c147e 170static void
7819b5c3 171input_userauth_request(int type, u_int32_t seq, void *ctxt)
a306f2dd 172{
94ec8c6b 173 Authctxt *authctxt = ctxt;
174 Authmethod *m = NULL;
59c97189 175 char *user, *service, *method, *style = NULL;
a306f2dd 176 int authenticated = 0;
a306f2dd 177
94ec8c6b 178 if (authctxt == NULL)
179 fatal("input_userauth_request: no authctxt");
a306f2dd 180
94ec8c6b 181 user = packet_get_string(NULL);
182 service = packet_get_string(NULL);
183 method = packet_get_string(NULL);
184 debug("userauth-request for user %s service %s method %s", user, service, method);
8abcdba4 185 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
94ec8c6b 186
59c97189 187 if ((style = strchr(user, ':')) != NULL)
188 *style++ = 0;
189
2b87da3b 190 if (authctxt->attempt++ == 0) {
91885a4d 191 /* setup auth context */
192 int allowed;
94ec8c6b 193 struct passwd *pw = NULL;
91885a4d 194 if (!use_privsep) {
195 pw = getpwnam(user);
196 allowed = pw ? allowed_user(pw) : 0;
197 } else
198 pw = mm_getpwnamallow(mm_recvfd, user, &allowed);
199 if (pw && allowed && strcmp(service, "ssh-connection")==0) {
94ec8c6b 200 authctxt->pw = pwcopy(pw);
201 authctxt->valid = 1;
202 debug2("input_userauth_request: setting up authctxt for %s", user);
203#ifdef USE_PAM
04fc7a67 204 start_pam(pw->pw_name);
94ec8c6b 205#endif
206 } else {
207 log("input_userauth_request: illegal user %s", user);
04fc7a67 208#ifdef USE_PAM
209 start_pam("NOUSER");
210#endif
94ec8c6b 211 }
91885a4d 212 /* Free memory */
213 if (use_privsep)
214 pwfree(pw);
215
216 setproctitle("%s%s", use_privsep ? " [net]" : "",
217 pw ? user : "unknown");
94ec8c6b 218 authctxt->user = xstrdup(user);
219 authctxt->service = xstrdup(service);
2a6a054e 220 authctxt->style = style ? xstrdup(style) : NULL;
91885a4d 221
222 if (use_privsep)
223 mm_inform_authserv(mm_recvfd, service, style);
2a6a054e 224 } else if (strcmp(user, authctxt->user) != 0 ||
225 strcmp(service, authctxt->service) != 0) {
226 packet_disconnect("Change of username or service not allowed: "
227 "(%s,%s) -> (%s,%s)",
228 authctxt->user, authctxt->service, user, service);
a306f2dd 229 }
59c97189 230 /* reset state */
2f293d43 231 auth2_challenge_stop(authctxt);
59c97189 232 authctxt->postponed = 0;
9cd45ea4 233
59c97189 234 /* try to authenticate user */
94ec8c6b 235 m = authmethod_lookup(method);
236 if (m != NULL) {
237 debug2("input_userauth_request: try method %s", method);
238 authenticated = m->userauth(authctxt);
9cd45ea4 239 }
d9cd3575 240 userauth_finish(authctxt, authenticated, method);
241
242 xfree(service);
243 xfree(user);
244 xfree(method);
245}
246
247void
248userauth_finish(Authctxt *authctxt, int authenticated, char *method)
249{
4e81159c 250 char *methods;
251
59c97189 252 if (!authctxt->valid && authenticated)
253 fatal("INTERNAL ERROR: authenticated invalid user %s",
254 authctxt->user);
9cd45ea4 255
94ec8c6b 256 /* Special handling for root */
15853e93 257 if (authenticated && authctxt->pw->pw_uid == 0 &&
258 !auth_root_allowed(method))
a306f2dd 259 authenticated = 0;
a306f2dd 260
261#ifdef USE_PAM
edef62bf 262 if (authenticated && authctxt->user && !do_pam_account(authctxt->user,
263 NULL))
9cd45ea4 264 authenticated = 0;
a306f2dd 265#endif /* USE_PAM */
266
94ec8c6b 267 /* Log before sending the reply */
59c97189 268 auth_log(authctxt, authenticated, method, " ssh2");
269
4e81159c 270 if (authctxt->postponed)
271 return;
272
273 /* XXX todo: check if multiple auth methods are needed */
274 if (authenticated == 1) {
275 /* turn off userauth */
6367063f 276 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
4e81159c 277 packet_start(SSH2_MSG_USERAUTH_SUCCESS);
278 packet_send();
279 packet_write_wait();
280 /* now we can break out */
281 authctxt->success = 1;
282 } else {
19e810f6 283 if (authctxt->failures++ > AUTH_FAIL_MAX) {
284#ifdef WITH_AIXAUTHENTICATE
285 loginfailed(authctxt->user,
983784a1 286 get_canonical_hostname(options.verify_reverse_mapping),
19e810f6 287 "ssh");
288#endif /* WITH_AIXAUTHENTICATE */
4e81159c 289 packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
19e810f6 290 }
4e81159c 291 methods = authmethods_get();
292 packet_start(SSH2_MSG_USERAUTH_FAILURE);
293 packet_put_cstring(methods);
294 packet_put_char(0); /* XXX partial success, unused */
295 packet_send();
296 packet_write_wait();
297 xfree(methods);
298 }
94ec8c6b 299}
300
396c147e 301static void
eea39c02 302userauth_banner(void)
303{
304 struct stat st;
305 char *banner = NULL;
306 off_t len, n;
307 int fd;
308
309 if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
310 return;
0715ec6c 311 if ((fd = open(options.banner, O_RDONLY)) < 0)
eea39c02 312 return;
eea39c02 313 if (fstat(fd, &st) < 0)
314 goto done;
315 len = st.st_size;
316 banner = xmalloc(len + 1);
317 if ((n = read(fd, banner, len)) < 0)
318 goto done;
319 banner[n] = '\0';
320 packet_start(SSH2_MSG_USERAUTH_BANNER);
321 packet_put_cstring(banner);
322 packet_put_cstring(""); /* language, unused */
323 packet_send();
324 debug("userauth_banner: sent");
325done:
326 if (banner)
327 xfree(banner);
328 close(fd);
329 return;
330}
94ec8c6b 331
396c147e 332static int
94ec8c6b 333userauth_none(Authctxt *authctxt)
a306f2dd 334{
91885a4d 335 int res = 0;
336
94ec8c6b 337 /* disable method "none", only allowed one time */
338 Authmethod *m = authmethod_lookup("none");
339 if (m != NULL)
340 m->enabled = NULL;
95500969 341 packet_check_eom();
2b87da3b 342 userauth_banner();
4d33e531 343
94ec8c6b 344 if (authctxt->valid == 0)
345 return(0);
91885a4d 346 if (!authctxt->valid)
347 return (0);
348 if (use_privsep)
349#if defined(USE_PAM) || defined(HAVE_OSF_SIA)
350#error NOT IMPLEMENTED FOR PRIVSEP
94ec8c6b 351#endif
91885a4d 352 res = mm_auth_password(mm_recvfd, "");
353 else
354 res = auth_password(authctxt, "");
355 return (res);
a306f2dd 356}
94ec8c6b 357
396c147e 358static int
94ec8c6b 359userauth_passwd(Authctxt *authctxt)
a306f2dd 360{
361 char *password;
362 int authenticated = 0;
363 int change;
1e3b8b07 364 u_int len;
a306f2dd 365 change = packet_get_char();
366 if (change)
367 log("password change not supported");
368 password = packet_get_string(&len);
95500969 369 packet_check_eom();
91885a4d 370
371#if defined(HAVE_CYGWIN) || defined(USE_PAM) || defined(HAVE_OSF_SIA)
372#error NOT IMPLEMENTED FOR PRIVSEP
94ec8c6b 373#endif
91885a4d 374 if (authctxt->valid) {
375 if (use_privsep)
376 authenticated = mm_auth_password(mm_recvfd, password);
377 else
378 authenticated = auth_password(authctxt, password);
379 }
a306f2dd 380 memset(password, 0, len);
381 xfree(password);
382 return authenticated;
383}
94ec8c6b 384
396c147e 385static int
94ec8c6b 386userauth_kbdint(Authctxt *authctxt)
387{
388 int authenticated = 0;
5ba55ada 389 char *lang, *devs;
94ec8c6b 390
391 lang = packet_get_string(NULL);
392 devs = packet_get_string(NULL);
95500969 393 packet_check_eom();
94ec8c6b 394
5ba55ada 395 debug("keyboard-interactive devs %s", devs);
59c97189 396
5ba55ada 397 if (options.challenge_response_authentication)
d464095c 398 authenticated = auth2_challenge(authctxt, devs);
59c97189 399
8c9fe09e 400#ifdef USE_PAM
10f72868 401 if (authenticated == 0 && options.pam_authentication_via_kbd_int)
8c9fe09e 402 authenticated = auth2_pam(authctxt);
94ec8c6b 403#endif
94ec8c6b 404 xfree(devs);
5ba55ada 405 xfree(lang);
94ec8c6b 406#ifdef HAVE_CYGWIN
e9571a2c 407 if (check_nt_auth(0, authctxt->pw) == 0)
94ec8c6b 408 return(0);
409#endif
410 return authenticated;
411}
412
396c147e 413static int
94ec8c6b 414userauth_pubkey(Authctxt *authctxt)
a306f2dd 415{
416 Buffer b;
67fa09f5 417 Key *key = NULL;
c66f9d0e 418 char *pkalg;
419 u_char *pkblob, *sig;
1e3b8b07 420 u_int alen, blen, slen;
fa08c86b 421 int have_sig, pktype;
a306f2dd 422 int authenticated = 0;
423
94ec8c6b 424 if (!authctxt->valid) {
425 debug2("userauth_pubkey: disabled because of invalid user");
a306f2dd 426 return 0;
427 }
428 have_sig = packet_get_char();
cbc5abf9 429 if (datafellows & SSH_BUG_PKAUTH) {
430 debug2("userauth_pubkey: SSH_BUG_PKAUTH");
431 /* no explicit pkalg given */
432 pkblob = packet_get_string(&blen);
433 buffer_init(&b);
434 buffer_append(&b, pkblob, blen);
435 /* so we have to extract the pkalg from the pkblob */
436 pkalg = buffer_get_string(&b, &alen);
437 buffer_free(&b);
438 } else {
439 pkalg = packet_get_string(&alen);
440 pkblob = packet_get_string(&blen);
441 }
fa08c86b 442 pktype = key_type_from_name(pkalg);
443 if (pktype == KEY_UNSPEC) {
cbc5abf9 444 /* this is perfectly legal */
67fa09f5 445 log("userauth_pubkey: unsupported public key algorithm: %s",
446 pkalg);
447 goto done;
a306f2dd 448 }
fa08c86b 449 key = key_from_blob(pkblob, blen);
67fa09f5 450 if (key == NULL) {
451 error("userauth_pubkey: cannot decode key: %s", pkalg);
452 goto done;
453 }
454 if (key->type != pktype) {
455 error("userauth_pubkey: type mismatch for decoded key "
456 "(received %d, expected %d)", key->type, pktype);
457 goto done;
458 }
459 if (have_sig) {
460 sig = packet_get_string(&slen);
461 packet_check_eom();
462 buffer_init(&b);
463 if (datafellows & SSH_OLD_SESSIONID) {
464 buffer_append(&b, session_id2, session_id2_len);
465 } else {
466 buffer_put_string(&b, session_id2, session_id2_len);
467 }
468 /* reconstruct packet */
469 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
470 buffer_put_cstring(&b, authctxt->user);
471 buffer_put_cstring(&b,
472 datafellows & SSH_BUG_PKSERVICE ?
473 "ssh-userauth" :
474 authctxt->service);
475 if (datafellows & SSH_BUG_PKAUTH) {
476 buffer_put_char(&b, have_sig);
477 } else {
478 buffer_put_cstring(&b, "publickey");
479 buffer_put_char(&b, have_sig);
480 buffer_put_cstring(&b, pkalg);
481 }
482 buffer_put_string(&b, pkblob, blen);
fa08c86b 483#ifdef DEBUG_PK
67fa09f5 484 buffer_dump(&b);
a306f2dd 485#endif
67fa09f5 486 /* test for correct signature */
91885a4d 487 authenticated = 0;
488 if (use_privsep) {
489 if (mm_user_key_allowed(mm_recvfd, key) &&
490 mm_key_verify(mm_recvfd,
491 MM_USERKEY, NULL, NULL, key, sig, slen,
492 buffer_ptr(&b), buffer_len(&b)) == 1)
493 authenticated = 1;
494 } else {
495 if (user_key_allowed(authctxt->pw, key) &&
496 key_verify(key, sig, slen, buffer_ptr(&b),
497 buffer_len(&b)) == 1)
498 authenticated = 1;
499 }
67fa09f5 500 buffer_clear(&b);
501 xfree(sig);
502 } else {
91885a4d 503 int res = 0;
67fa09f5 504 debug("test whether pkalg/pkblob are acceptable");
505 packet_check_eom();
506
507 /* XXX fake reply and always send PK_OK ? */
508 /*
509 * XXX this allows testing whether a user is allowed
510 * to login: if you happen to have a valid pubkey this
511 * message is sent. the message is NEVER sent at all
512 * if a user is not allowed to login. is this an
513 * issue? -markus
514 */
91885a4d 515 if (use_privsep)
516 res = mm_user_key_allowed(mm_recvfd, key);
517 else
518 res = user_key_allowed(authctxt->pw, key);
519 if (res) {
67fa09f5 520 packet_start(SSH2_MSG_USERAUTH_PK_OK);
521 packet_put_string(pkalg, alen);
522 packet_put_string(pkblob, blen);
523 packet_send();
524 packet_write_wait();
525 authctxt->postponed = 1;
a306f2dd 526 }
a306f2dd 527 }
67fa09f5 528 if (authenticated != 1)
529 auth_clear_options();
530done:
fa08c86b 531 debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
67fa09f5 532 if (key != NULL)
533 key_free(key);
a306f2dd 534 xfree(pkalg);
535 xfree(pkblob);
94ec8c6b 536#ifdef HAVE_CYGWIN
e9571a2c 537 if (check_nt_auth(0, authctxt->pw) == 0)
94ec8c6b 538 return(0);
539#endif
a306f2dd 540 return authenticated;
541}
542
396c147e 543static int
8002af61 544userauth_hostbased(Authctxt *authctxt)
545{
546 Buffer b;
67fa09f5 547 Key *key = NULL;
c66f9d0e 548 char *pkalg, *cuser, *chost, *service;
549 u_char *pkblob, *sig;
8002af61 550 u_int alen, blen, slen;
551 int pktype;
552 int authenticated = 0;
553
554 if (!authctxt->valid) {
555 debug2("userauth_hostbased: disabled because of invalid user");
556 return 0;
557 }
558 pkalg = packet_get_string(&alen);
559 pkblob = packet_get_string(&blen);
560 chost = packet_get_string(NULL);
561 cuser = packet_get_string(NULL);
562 sig = packet_get_string(&slen);
563
564 debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
565 cuser, chost, pkalg, slen);
566#ifdef DEBUG_PK
567 debug("signature:");
568 buffer_init(&b);
569 buffer_append(&b, sig, slen);
570 buffer_dump(&b);
571 buffer_free(&b);
572#endif
573 pktype = key_type_from_name(pkalg);
574 if (pktype == KEY_UNSPEC) {
575 /* this is perfectly legal */
576 log("userauth_hostbased: unsupported "
577 "public key algorithm: %s", pkalg);
578 goto done;
579 }
580 key = key_from_blob(pkblob, blen);
581 if (key == NULL) {
67fa09f5 582 error("userauth_hostbased: cannot decode key: %s", pkalg);
583 goto done;
584 }
585 if (key->type != pktype) {
586 error("userauth_hostbased: type mismatch for decoded key "
587 "(received %d, expected %d)", key->type, pktype);
8002af61 588 goto done;
589 }
8dddf799 590 service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
591 authctxt->service;
8002af61 592 buffer_init(&b);
8dddf799 593 buffer_put_string(&b, session_id2, session_id2_len);
8002af61 594 /* reconstruct packet */
595 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
596 buffer_put_cstring(&b, authctxt->user);
8dddf799 597 buffer_put_cstring(&b, service);
8002af61 598 buffer_put_cstring(&b, "hostbased");
599 buffer_put_string(&b, pkalg, alen);
600 buffer_put_string(&b, pkblob, blen);
601 buffer_put_cstring(&b, chost);
602 buffer_put_cstring(&b, cuser);
603#ifdef DEBUG_PK
604 buffer_dump(&b);
605#endif
606 /* test for allowed key and correct signature */
91885a4d 607 authenticated = 0;
608 if (use_privsep) {
609 if (mm_hostbased_key_allowed(mm_recvfd, cuser, chost, key) &&
610 mm_key_verify(mm_recvfd, MM_HOSTKEY, cuser, chost, key,
611 sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
612 authenticated = 1;
613 } else {
614 if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) &&
615 key_verify(key, sig, slen, buffer_ptr(&b),
616 buffer_len(&b)) == 1)
617 authenticated = 1;
618 }
8002af61 619
620 buffer_clear(&b);
8002af61 621done:
622 debug2("userauth_hostbased: authenticated %d", authenticated);
67fa09f5 623 if (key != NULL)
624 key_free(key);
8002af61 625 xfree(pkalg);
626 xfree(pkblob);
627 xfree(cuser);
628 xfree(chost);
629 xfree(sig);
630 return authenticated;
631}
632
94ec8c6b 633/* get current user */
a306f2dd 634
635struct passwd*
636auth_get_user(void)
637{
94ec8c6b 638 return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL;
a306f2dd 639}
640
94ec8c6b 641#define DELIM ","
642
ffb215be 643static char *
94ec8c6b 644authmethods_get(void)
a306f2dd 645{
94ec8c6b 646 Authmethod *method = NULL;
3469eac4 647 Buffer b;
94ec8c6b 648 char *list;
649
3469eac4 650 buffer_init(&b);
94ec8c6b 651 for (method = authmethods; method->name != NULL; method++) {
652 if (strcmp(method->name, "none") == 0)
653 continue;
654 if (method->enabled != NULL && *(method->enabled) != 0) {
3469eac4 655 if (buffer_len(&b) > 0)
656 buffer_append(&b, ",", 1);
657 buffer_append(&b, method->name, strlen(method->name));
a306f2dd 658 }
659 }
3469eac4 660 buffer_append(&b, "\0", 1);
661 list = xstrdup(buffer_ptr(&b));
662 buffer_free(&b);
94ec8c6b 663 return list;
664}
665
396c147e 666static Authmethod *
94ec8c6b 667authmethod_lookup(const char *name)
668{
669 Authmethod *method = NULL;
670 if (name != NULL)
671 for (method = authmethods; method->name != NULL; method++)
672 if (method->enabled != NULL &&
673 *(method->enabled) != 0 &&
674 strcmp(name, method->name) == 0)
675 return method;
676 debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
677 return NULL;
a306f2dd 678}
679
680/* return 1 if user allows given key */
396c147e 681static int
96a7b0cc 682user_key_allowed2(struct passwd *pw, Key *key, char *file)
a306f2dd 683{
96a7b0cc 684 char line[8192];
a306f2dd 685 int found_key = 0;
a306f2dd 686 FILE *f;
1e3b8b07 687 u_long linenum = 0;
a306f2dd 688 struct stat st;
689 Key *found;
306feb91 690 char *fp;
a306f2dd 691
94ec8c6b 692 if (pw == NULL)
693 return 0;
694
a306f2dd 695 /* Temporarily use the user's uid. */
63bd8c36 696 temporarily_use_uid(pw);
a306f2dd 697
c8445989 698 debug("trying public key file %s", file);
a306f2dd 699
700 /* Fail quietly if file does not exist */
701 if (stat(file, &st) < 0) {
702 /* Restore the privileged uid. */
703 restore_uid();
704 return 0;
705 }
706 /* Open the file containing the authorized keys. */
707 f = fopen(file, "r");
708 if (!f) {
709 /* Restore the privileged uid. */
710 restore_uid();
711 return 0;
712 }
c8445989 713 if (options.strict_modes &&
0c9664c2 714 secure_filename(f, file, pw, line, sizeof(line)) != 0) {
c8445989 715 fclose(f);
716 log("Authentication refused: %s", line);
717 restore_uid();
718 return 0;
a306f2dd 719 }
c8445989 720
a306f2dd 721 found_key = 0;
de273eef 722 found = key_new(key->type);
a306f2dd 723
724 while (fgets(line, sizeof(line), f)) {
38c295d6 725 char *cp, *options = NULL;
a306f2dd 726 linenum++;
727 /* Skip leading whitespace, empty and comment lines. */
728 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
729 ;
730 if (!*cp || *cp == '\n' || *cp == '#')
731 continue;
38c295d6 732
ddcfed57 733 if (key_read(found, &cp) != 1) {
38c295d6 734 /* no key? check if there are options for this key */
735 int quoted = 0;
fa08c86b 736 debug2("user_key_allowed: check options: '%s'", cp);
38c295d6 737 options = cp;
738 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
739 if (*cp == '\\' && cp[1] == '"')
740 cp++; /* Skip both */
741 else if (*cp == '"')
742 quoted = !quoted;
743 }
744 /* Skip remaining whitespace. */
745 for (; *cp == ' ' || *cp == '\t'; cp++)
746 ;
ddcfed57 747 if (key_read(found, &cp) != 1) {
fa08c86b 748 debug2("user_key_allowed: advance: '%s'", cp);
38c295d6 749 /* still no key? advance to next line*/
750 continue;
751 }
752 }
753 if (key_equal(found, key) &&
42f11eb2 754 auth_parse_options(pw, options, file, linenum) == 1) {
a306f2dd 755 found_key = 1;
1bdee08c 756 debug("matching key found: file %s, line %lu",
a306f2dd 757 file, linenum);
306feb91 758 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
759 verbose("Found matching %s key: %s",
184eed6a 760 key_type(found), fp);
306feb91 761 xfree(fp);
a306f2dd 762 break;
763 }
764 }
765 restore_uid();
766 fclose(f);
767 key_free(found);
539af7f5 768 if (!found_key)
769 debug2("key not found");
a306f2dd 770 return found_key;
771}
8002af61 772
96a7b0cc 773/* check whether given key is in .ssh/authorized_keys* */
91885a4d 774int
96a7b0cc 775user_key_allowed(struct passwd *pw, Key *key)
776{
777 int success;
778 char *file;
779
780 file = authorized_keys_file(pw);
781 success = user_key_allowed2(pw, key, file);
782 xfree(file);
783 if (success)
784 return success;
785
786 /* try suffix "2" for backward compat, too */
787 file = authorized_keys_file2(pw);
788 success = user_key_allowed2(pw, key, file);
789 xfree(file);
790 return success;
791}
792
8002af61 793/* return 1 if given hostkey is allowed */
91885a4d 794int
57a5edd8 795hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
8002af61 796 Key *key)
797{
8002af61 798 const char *resolvedname, *ipaddr, *lookup;
17a3011c 799 HostStatus host_status;
800 int len;
8002af61 801
bf4c5edc 802 resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
8002af61 803 ipaddr = get_remote_ipaddr();
804
f98c3421 805 debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
806 chost, resolvedname, ipaddr);
8002af61 807
808 if (options.hostbased_uses_name_from_packet_only) {
809 if (auth_rhosts2(pw, cuser, chost, chost) == 0)
810 return 0;
811 lookup = chost;
812 } else {
f98c3421 813 if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
814 debug2("stripping trailing dot from chost %s", chost);
815 chost[len - 1] = '\0';
816 }
8002af61 817 if (strcasecmp(resolvedname, chost) != 0)
818 log("userauth_hostbased mismatch: "
819 "client sends %s, but we resolve %s to %s",
820 chost, ipaddr, resolvedname);
821 if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
822 return 0;
823 lookup = resolvedname;
824 }
825 debug2("userauth_hostbased: access allowed by auth_rhosts2");
826
d0c8ca5c 827 host_status = check_key_in_hostfiles(pw, key, lookup,
828 _PATH_SSH_SYSTEM_HOSTFILE,
73473230 829 options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
d0c8ca5c 830
831 /* backward compat if no key has been found. */
832 if (host_status == HOST_NEW)
833 host_status = check_key_in_hostfiles(pw, key, lookup,
834 _PATH_SSH_SYSTEM_HOSTFILE2,
73473230 835 options.ignore_user_known_hosts ? NULL :
836 _PATH_SSH_USER_HOSTFILE2);
8002af61 837
8002af61 838 return (host_status == HOST_OK);
839}
This page took 0.249668 seconds and 5 git commands to generate.