summaryrefslogtreecommitdiff
path: root/auth-options.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth-options.c')
-rw-r--r--auth-options.c282
1 files changed, 180 insertions, 102 deletions
diff --git a/auth-options.c b/auth-options.c
index 57a67ec79..a7040247f 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-options.c,v 1.51 2010/05/07 11:30:29 djm Exp $ */ 1/* $OpenBSD: auth-options.c,v 1.52 2010/05/20 23:46:02 djm 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
@@ -417,32 +417,31 @@ bad_option:
417 return 0; 417 return 0;
418} 418}
419 419
420/* 420#define OPTIONS_CRITICAL 1
421 * Set options from critical certificate options. These supersede user key 421#define OPTIONS_EXTENSIONS 2
422 * options so this must be called after auth_parse_options(). 422static int
423 */ 423parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
424int 424 u_int which, int crit,
425auth_cert_options(Key *k, struct passwd *pw) 425 int *cert_no_port_forwarding_flag,
426 int *cert_no_agent_forwarding_flag,
427 int *cert_no_x11_forwarding_flag,
428 int *cert_no_pty_flag,
429 int *cert_no_user_rc,
430 char **cert_forced_command,
431 int *cert_source_address_done)
426{ 432{
433 char *command, *allowed;
434 const char *remote_ip;
427 u_char *name = NULL, *data_blob = NULL; 435 u_char *name = NULL, *data_blob = NULL;
428 u_int nlen, dlen, clen; 436 u_int nlen, dlen, clen;
429 Buffer c, data; 437 Buffer c, data;
430 int ret = -1; 438 int ret = -1, found;
431
432 int cert_no_port_forwarding_flag = 1;
433 int cert_no_agent_forwarding_flag = 1;
434 int cert_no_x11_forwarding_flag = 1;
435 int cert_no_pty_flag = 1;
436 int cert_no_user_rc = 1;
437 char *cert_forced_command = NULL;
438 int cert_source_address_done = 0;
439 439
440 buffer_init(&data); 440 buffer_init(&data);
441 441
442 /* Make copy to avoid altering original */ 442 /* Make copy to avoid altering original */
443 buffer_init(&c); 443 buffer_init(&c);
444 buffer_append(&c, 444 buffer_append(&c, optblob, optblob_len);
445 buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical));
446 445
447 while (buffer_len(&c) > 0) { 446 while (buffer_len(&c) > 0) {
448 if ((name = buffer_get_string_ret(&c, &nlen)) == NULL || 447 if ((name = buffer_get_string_ret(&c, &nlen)) == NULL ||
@@ -451,90 +450,114 @@ auth_cert_options(Key *k, struct passwd *pw)
451 goto out; 450 goto out;
452 } 451 }
453 buffer_append(&data, data_blob, dlen); 452 buffer_append(&data, data_blob, dlen);
454 debug3("found certificate constraint \"%.100s\" len %u", 453 debug3("found certificate option \"%.100s\" len %u",
455 name, dlen); 454 name, dlen);
456 if (strlen(name) != nlen) { 455 if (strlen(name) != nlen) {
457 error("Certificate constraint name contains \\0"); 456 error("Certificate constraint name contains \\0");
458 goto out; 457 goto out;
459 } 458 }
460 if (strcmp(name, "permit-X11-forwarding") == 0) 459 found = 0;
461 cert_no_x11_forwarding_flag = 0; 460 if ((which & OPTIONS_EXTENSIONS) != 0) {
462 else if (strcmp(name, "permit-agent-forwarding") == 0) 461 if (strcmp(name, "permit-X11-forwarding") == 0) {
463 cert_no_agent_forwarding_flag = 0; 462 *cert_no_x11_forwarding_flag = 0;
464 else if (strcmp(name, "permit-port-forwarding") == 0) 463 found = 1;
465 cert_no_port_forwarding_flag = 0; 464 } else if (strcmp(name,
466 else if (strcmp(name, "permit-pty") == 0) 465 "permit-agent-forwarding") == 0) {
467 cert_no_pty_flag = 0; 466 *cert_no_agent_forwarding_flag = 0;
468 else if (strcmp(name, "permit-user-rc") == 0) 467 found = 1;
469 cert_no_user_rc = 0; 468 } else if (strcmp(name,
470 else if (strcmp(name, "force-command") == 0) { 469 "permit-port-forwarding") == 0) {
471 char *command = buffer_get_string_ret(&data, &clen); 470 *cert_no_port_forwarding_flag = 0;
472 471 found = 1;
473 if (command == NULL) { 472 } else if (strcmp(name, "permit-pty") == 0) {
474 error("Certificate constraint \"%s\" corrupt", 473 *cert_no_pty_flag = 0;
475 name); 474 found = 1;
476 goto out; 475 } else if (strcmp(name, "permit-user-rc") == 0) {
477 } 476 *cert_no_user_rc = 0;
478 if (strlen(command) != clen) { 477 found = 1;
479 error("force-command constraint contains \\0");
480 goto out;
481 }
482 if (cert_forced_command != NULL) {
483 error("Certificate has multiple "
484 "force-command options");
485 xfree(command);
486 goto out;
487 }
488 cert_forced_command = command;
489 } else if (strcmp(name, "source-address") == 0) {
490 char *allowed = buffer_get_string_ret(&data, &clen);
491 const char *remote_ip = get_remote_ipaddr();
492
493 if (allowed == NULL) {
494 error("Certificate constraint \"%s\" corrupt",
495 name);
496 goto out;
497 }
498 if (strlen(allowed) != clen) {
499 error("source-address constraint contains \\0");
500 goto out;
501 } 478 }
502 if (cert_source_address_done++) { 479 }
503 error("Certificate has multiple " 480 if (!found && (which & OPTIONS_CRITICAL) != 0) {
504 "source-address options"); 481 if (strcmp(name, "force-command") == 0) {
505 xfree(allowed); 482 if ((command = buffer_get_string_ret(&data,
506 goto out; 483 &clen)) == NULL) {
484 error("Certificate constraint \"%s\" "
485 "corrupt", name);
486 goto out;
487 }
488 if (strlen(command) != clen) {
489 error("force-command constraint "
490 "contains \\0");
491 goto out;
492 }
493 if (*cert_forced_command != NULL) {
494 error("Certificate has multiple "
495 "force-command options");
496 xfree(command);
497 goto out;
498 }
499 *cert_forced_command = command;
500 found = 1;
507 } 501 }
508 switch (addr_match_cidr_list(remote_ip, allowed)) { 502 if (strcmp(name, "source-address") == 0) {
509 case 1: 503 if ((allowed = buffer_get_string_ret(&data,
510 /* accepted */ 504 &clen)) == NULL) {
511 xfree(allowed); 505 error("Certificate constraint "
512 break; 506 "\"%s\" corrupt", name);
513 case 0: 507 goto out;
514 /* no match */ 508 }
515 logit("Authentication tried for %.100s with " 509 if (strlen(allowed) != clen) {
516 "valid certificate but not from a " 510 error("source-address constraint "
517 "permitted host (ip=%.200s).", 511 "contains \\0");
518 pw->pw_name, remote_ip); 512 goto out;
519 auth_debug_add("Your address '%.200s' is not " 513 }
520 "permitted to use this certificate for " 514 if ((*cert_source_address_done)++) {
521 "login.", remote_ip); 515 error("Certificate has multiple "
522 xfree(allowed); 516 "source-address options");
523 goto out; 517 xfree(allowed);
524 case -1: 518 goto out;
525 error("Certificate source-address contents " 519 }
526 "invalid"); 520 remote_ip = get_remote_ipaddr();
527 xfree(allowed); 521 switch (addr_match_cidr_list(remote_ip,
528 goto out; 522 allowed)) {
523 case 1:
524 /* accepted */
525 xfree(allowed);
526 break;
527 case 0:
528 /* no match */
529 logit("Authentication tried for %.100s "
530 "with valid certificate but not "
531 "from a permitted host "
532 "(ip=%.200s).", pw->pw_name,
533 remote_ip);
534 auth_debug_add("Your address '%.200s' "
535 "is not permitted to use this "
536 "certificate for login.",
537 remote_ip);
538 xfree(allowed);
539 goto out;
540 case -1:
541 error("Certificate source-address "
542 "contents invalid");
543 xfree(allowed);
544 goto out;
545 }
546 found = 1;
529 } 547 }
530 } else {
531 error("Certificate constraint \"%s\" is not supported",
532 name);
533 goto out;
534 } 548 }
535 549
536 if (buffer_len(&data) != 0) { 550 if (!found) {
537 error("Certificate constraint \"%s\" corrupt " 551 if (crit) {
552 error("Certificate critical option \"%s\" "
553 "is not supported", name);
554 goto out;
555 } else {
556 logit("Certificate extension \"%s\" "
557 "is not supported", name);
558 }
559 } else if (buffer_len(&data) != 0) {
560 error("Certificate option \"%s\" corrupt "
538 "(extra data)", name); 561 "(extra data)", name);
539 goto out; 562 goto out;
540 } 563 }
@@ -543,10 +566,73 @@ auth_cert_options(Key *k, struct passwd *pw)
543 xfree(data_blob); 566 xfree(data_blob);
544 name = data_blob = NULL; 567 name = data_blob = NULL;
545 } 568 }
546
547 /* successfully parsed all options */ 569 /* successfully parsed all options */
548 ret = 0; 570 ret = 0;
549 571
572 out:
573 if (ret != 0 &&
574 cert_forced_command != NULL &&
575 *cert_forced_command != NULL) {
576 xfree(*cert_forced_command);
577 *cert_forced_command = NULL;
578 }
579 if (name != NULL)
580 xfree(name);
581 if (data_blob != NULL)
582 xfree(data_blob);
583 buffer_free(&data);
584 buffer_free(&c);
585 return ret;
586}
587
588/*
589 * Set options from critical certificate options. These supersede user key
590 * options so this must be called after auth_parse_options().
591 */
592int
593auth_cert_options(Key *k, struct passwd *pw)
594{
595 int cert_no_port_forwarding_flag = 1;
596 int cert_no_agent_forwarding_flag = 1;
597 int cert_no_x11_forwarding_flag = 1;
598 int cert_no_pty_flag = 1;
599 int cert_no_user_rc = 1;
600 char *cert_forced_command = NULL;
601 int cert_source_address_done = 0;
602
603 if (key_cert_is_legacy(k)) {
604 /* All options are in the one field for v00 certs */
605 if (parse_option_list(buffer_ptr(&k->cert->critical),
606 buffer_len(&k->cert->critical), pw,
607 OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1,
608 &cert_no_port_forwarding_flag,
609 &cert_no_agent_forwarding_flag,
610 &cert_no_x11_forwarding_flag,
611 &cert_no_pty_flag,
612 &cert_no_user_rc,
613 &cert_forced_command,
614 &cert_source_address_done) == -1)
615 return -1;
616 } else {
617 /* Separate options and extensions for v01 certs */
618 if (parse_option_list(buffer_ptr(&k->cert->critical),
619 buffer_len(&k->cert->critical), pw,
620 OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
621 &cert_forced_command,
622 &cert_source_address_done) == -1)
623 return -1;
624 if (parse_option_list(buffer_ptr(&k->cert->extensions),
625 buffer_len(&k->cert->extensions), pw,
626 OPTIONS_EXTENSIONS, 1,
627 &cert_no_port_forwarding_flag,
628 &cert_no_agent_forwarding_flag,
629 &cert_no_x11_forwarding_flag,
630 &cert_no_pty_flag,
631 &cert_no_user_rc,
632 NULL, NULL) == -1)
633 return -1;
634 }
635
550 no_port_forwarding_flag |= cert_no_port_forwarding_flag; 636 no_port_forwarding_flag |= cert_no_port_forwarding_flag;
551 no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; 637 no_agent_forwarding_flag |= cert_no_agent_forwarding_flag;
552 no_x11_forwarding_flag |= cert_no_x11_forwarding_flag; 638 no_x11_forwarding_flag |= cert_no_x11_forwarding_flag;
@@ -558,14 +644,6 @@ auth_cert_options(Key *k, struct passwd *pw)
558 xfree(forced_command); 644 xfree(forced_command);
559 forced_command = cert_forced_command; 645 forced_command = cert_forced_command;
560 } 646 }
561 647 return 0;
562 out:
563 if (name != NULL)
564 xfree(name);
565 if (data_blob != NULL)
566 xfree(data_blob);
567 buffer_free(&data);
568 buffer_free(&c);
569 return ret;
570} 648}
571 649