diff options
Diffstat (limited to 'auth-options.c')
-rw-r--r-- | auth-options.c | 169 |
1 files changed, 161 insertions, 8 deletions
diff --git a/auth-options.c b/auth-options.c index ab085c233..129301765 100644 --- a/auth-options.c +++ b/auth-options.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-options.c,v 1.44 2009/01/22 10:09:16 djm Exp $ */ | 1 | /* $OpenBSD: auth-options.c,v 1.48 2010/03/07 11:57:13 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -44,6 +44,7 @@ int no_agent_forwarding_flag = 0; | |||
44 | int no_x11_forwarding_flag = 0; | 44 | int no_x11_forwarding_flag = 0; |
45 | int no_pty_flag = 0; | 45 | int no_pty_flag = 0; |
46 | int no_user_rc = 0; | 46 | int no_user_rc = 0; |
47 | int key_is_cert_authority = 0; | ||
47 | 48 | ||
48 | /* "command=" option. */ | 49 | /* "command=" option. */ |
49 | char *forced_command = NULL; | 50 | char *forced_command = NULL; |
@@ -64,6 +65,7 @@ auth_clear_options(void) | |||
64 | no_pty_flag = 0; | 65 | no_pty_flag = 0; |
65 | no_x11_forwarding_flag = 0; | 66 | no_x11_forwarding_flag = 0; |
66 | no_user_rc = 0; | 67 | no_user_rc = 0; |
68 | key_is_cert_authority = 0; | ||
67 | while (custom_environment) { | 69 | while (custom_environment) { |
68 | struct envstring *ce = custom_environment; | 70 | struct envstring *ce = custom_environment; |
69 | custom_environment = ce->next; | 71 | custom_environment = ce->next; |
@@ -76,7 +78,6 @@ auth_clear_options(void) | |||
76 | } | 78 | } |
77 | forced_tun_device = -1; | 79 | forced_tun_device = -1; |
78 | channel_clear_permitted_opens(); | 80 | channel_clear_permitted_opens(); |
79 | auth_debug_reset(); | ||
80 | } | 81 | } |
81 | 82 | ||
82 | /* | 83 | /* |
@@ -96,6 +97,12 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) | |||
96 | return 1; | 97 | return 1; |
97 | 98 | ||
98 | while (*opts && *opts != ' ' && *opts != '\t') { | 99 | while (*opts && *opts != ' ' && *opts != '\t') { |
100 | cp = "cert-authority"; | ||
101 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { | ||
102 | key_is_cert_authority = 1; | ||
103 | opts += strlen(cp); | ||
104 | goto next_option; | ||
105 | } | ||
99 | cp = "no-port-forwarding"; | 106 | cp = "no-port-forwarding"; |
100 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { | 107 | if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
101 | auth_debug_add("Port forwarding disabled."); | 108 | auth_debug_add("Port forwarding disabled."); |
@@ -356,9 +363,6 @@ next_option: | |||
356 | /* Process the next option. */ | 363 | /* Process the next option. */ |
357 | } | 364 | } |
358 | 365 | ||
359 | if (!use_privsep) | ||
360 | auth_debug_send(); | ||
361 | |||
362 | /* grant access */ | 366 | /* grant access */ |
363 | return 1; | 367 | return 1; |
364 | 368 | ||
@@ -368,9 +372,158 @@ bad_option: | |||
368 | auth_debug_add("Bad options in %.100s file, line %lu: %.50s", | 372 | auth_debug_add("Bad options in %.100s file, line %lu: %.50s", |
369 | file, linenum, opts); | 373 | file, linenum, opts); |
370 | 374 | ||
371 | if (!use_privsep) | ||
372 | auth_debug_send(); | ||
373 | |||
374 | /* deny access */ | 375 | /* deny access */ |
375 | return 0; | 376 | return 0; |
376 | } | 377 | } |
378 | |||
379 | /* | ||
380 | * Set options from certificate constraints. These supersede user key options | ||
381 | * so this must be called after auth_parse_options(). | ||
382 | */ | ||
383 | int | ||
384 | auth_cert_constraints(Buffer *c_orig, struct passwd *pw) | ||
385 | { | ||
386 | u_char *name = NULL, *data_blob = NULL; | ||
387 | u_int nlen, dlen, clen; | ||
388 | Buffer c, data; | ||
389 | int ret = -1; | ||
390 | |||
391 | int cert_no_port_forwarding_flag = 1; | ||
392 | int cert_no_agent_forwarding_flag = 1; | ||
393 | int cert_no_x11_forwarding_flag = 1; | ||
394 | int cert_no_pty_flag = 1; | ||
395 | int cert_no_user_rc = 1; | ||
396 | char *cert_forced_command = NULL; | ||
397 | int cert_source_address_done = 0; | ||
398 | |||
399 | buffer_init(&data); | ||
400 | |||
401 | /* Make copy to avoid altering original */ | ||
402 | buffer_init(&c); | ||
403 | buffer_append(&c, buffer_ptr(c_orig), buffer_len(c_orig)); | ||
404 | |||
405 | while (buffer_len(&c) > 0) { | ||
406 | if ((name = buffer_get_string_ret(&c, &nlen)) == NULL || | ||
407 | (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) { | ||
408 | error("Certificate constraints corrupt"); | ||
409 | goto out; | ||
410 | } | ||
411 | buffer_append(&data, data_blob, dlen); | ||
412 | debug3("found certificate constraint \"%.100s\" len %u", | ||
413 | name, dlen); | ||
414 | if (strlen(name) != nlen) { | ||
415 | error("Certificate constraint name contains \\0"); | ||
416 | goto out; | ||
417 | } | ||
418 | if (strcmp(name, "permit-X11-forwarding") == 0) | ||
419 | cert_no_x11_forwarding_flag = 0; | ||
420 | else if (strcmp(name, "permit-agent-forwarding") == 0) | ||
421 | cert_no_agent_forwarding_flag = 0; | ||
422 | else if (strcmp(name, "permit-port-forwarding") == 0) | ||
423 | cert_no_port_forwarding_flag = 0; | ||
424 | else if (strcmp(name, "permit-pty") == 0) | ||
425 | cert_no_pty_flag = 0; | ||
426 | else if (strcmp(name, "permit-user-rc") == 0) | ||
427 | cert_no_user_rc = 0; | ||
428 | else if (strcmp(name, "force-command") == 0) { | ||
429 | char *command = buffer_get_string_ret(&data, &clen); | ||
430 | |||
431 | if (command == NULL) { | ||
432 | error("Certificate constraint \"%s\" corrupt", | ||
433 | name); | ||
434 | goto out; | ||
435 | } | ||
436 | if (strlen(command) != clen) { | ||
437 | error("force-command constrain contains \\0"); | ||
438 | goto out; | ||
439 | } | ||
440 | if (cert_forced_command != NULL) { | ||
441 | error("Certificate has multiple " | ||
442 | "force-command constraints"); | ||
443 | xfree(command); | ||
444 | goto out; | ||
445 | } | ||
446 | cert_forced_command = command; | ||
447 | } else if (strcmp(name, "source-address") == 0) { | ||
448 | char *allowed = buffer_get_string_ret(&data, &clen); | ||
449 | const char *remote_ip = get_remote_ipaddr(); | ||
450 | |||
451 | if (allowed == NULL) { | ||
452 | error("Certificate constraint \"%s\" corrupt", | ||
453 | name); | ||
454 | goto out; | ||
455 | } | ||
456 | if (strlen(allowed) != clen) { | ||
457 | error("source-address constrain contains \\0"); | ||
458 | goto out; | ||
459 | } | ||
460 | if (cert_source_address_done++) { | ||
461 | error("Certificate has multiple " | ||
462 | "source-address constraints"); | ||
463 | xfree(allowed); | ||
464 | goto out; | ||
465 | } | ||
466 | switch (addr_match_cidr_list(remote_ip, allowed)) { | ||
467 | case 1: | ||
468 | /* accepted */ | ||
469 | xfree(allowed); | ||
470 | break; | ||
471 | case 0: | ||
472 | /* no match */ | ||
473 | logit("Authentication tried for %.100s with " | ||
474 | "valid certificate but not from a " | ||
475 | "permitted host (ip=%.200s).", | ||
476 | pw->pw_name, remote_ip); | ||
477 | auth_debug_add("Your address '%.200s' is not " | ||
478 | "permitted to use this certificate for " | ||
479 | "login.", remote_ip); | ||
480 | xfree(allowed); | ||
481 | goto out; | ||
482 | case -1: | ||
483 | error("Certificate source-address contents " | ||
484 | "invalid"); | ||
485 | xfree(allowed); | ||
486 | goto out; | ||
487 | } | ||
488 | } else { | ||
489 | error("Certificate constraint \"%s\" is not supported", | ||
490 | name); | ||
491 | goto out; | ||
492 | } | ||
493 | |||
494 | if (buffer_len(&data) != 0) { | ||
495 | error("Certificate constraint \"%s\" corrupt " | ||
496 | "(extra data)", name); | ||
497 | goto out; | ||
498 | } | ||
499 | buffer_clear(&data); | ||
500 | xfree(name); | ||
501 | xfree(data_blob); | ||
502 | name = data_blob = NULL; | ||
503 | } | ||
504 | |||
505 | /* successfully parsed all constraints */ | ||
506 | ret = 0; | ||
507 | |||
508 | no_port_forwarding_flag |= cert_no_port_forwarding_flag; | ||
509 | no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; | ||
510 | no_x11_forwarding_flag |= cert_no_x11_forwarding_flag; | ||
511 | no_pty_flag |= cert_no_pty_flag; | ||
512 | no_user_rc |= cert_no_user_rc; | ||
513 | /* CA-specified forced command supersedes key option */ | ||
514 | if (cert_forced_command != NULL) { | ||
515 | if (forced_command != NULL) | ||
516 | xfree(forced_command); | ||
517 | forced_command = cert_forced_command; | ||
518 | } | ||
519 | |||
520 | out: | ||
521 | if (name != NULL) | ||
522 | xfree(name); | ||
523 | if (data_blob != NULL) | ||
524 | xfree(data_blob); | ||
525 | buffer_free(&data); | ||
526 | buffer_free(&c); | ||
527 | return ret; | ||
528 | } | ||
529 | |||