summaryrefslogtreecommitdiff
path: root/auth-options.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth-options.c')
-rw-r--r--auth-options.c328
1 files changed, 224 insertions, 104 deletions
diff --git a/auth-options.c b/auth-options.c
index 69b314fbd..a7040247f 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-options.c,v 1.49 2010/03/16 15:46:52 stevesk 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
@@ -27,10 +27,10 @@
27#include "canohost.h" 27#include "canohost.h"
28#include "buffer.h" 28#include "buffer.h"
29#include "channels.h" 29#include "channels.h"
30#include "auth-options.h"
31#include "servconf.h" 30#include "servconf.h"
32#include "misc.h" 31#include "misc.h"
33#include "key.h" 32#include "key.h"
33#include "auth-options.h"
34#include "hostfile.h" 34#include "hostfile.h"
35#include "auth.h" 35#include "auth.h"
36#ifdef GSSAPI 36#ifdef GSSAPI
@@ -55,6 +55,9 @@ struct envstring *custom_environment = NULL;
55/* "tunnel=" option. */ 55/* "tunnel=" option. */
56int forced_tun_device = -1; 56int forced_tun_device = -1;
57 57
58/* "principals=" option. */
59char *authorized_principals = NULL;
60
58extern ServerOptions options; 61extern ServerOptions options;
59 62
60void 63void
@@ -76,6 +79,10 @@ auth_clear_options(void)
76 xfree(forced_command); 79 xfree(forced_command);
77 forced_command = NULL; 80 forced_command = NULL;
78 } 81 }
82 if (authorized_principals) {
83 xfree(authorized_principals);
84 authorized_principals = NULL;
85 }
79 forced_tun_device = -1; 86 forced_tun_device = -1;
80 channel_clear_permitted_opens(); 87 channel_clear_permitted_opens();
81} 88}
@@ -141,6 +148,8 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
141 cp = "command=\""; 148 cp = "command=\"";
142 if (strncasecmp(opts, cp, strlen(cp)) == 0) { 149 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
143 opts += strlen(cp); 150 opts += strlen(cp);
151 if (forced_command != NULL)
152 xfree(forced_command);
144 forced_command = xmalloc(strlen(opts) + 1); 153 forced_command = xmalloc(strlen(opts) + 1);
145 i = 0; 154 i = 0;
146 while (*opts) { 155 while (*opts) {
@@ -167,6 +176,38 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
167 opts++; 176 opts++;
168 goto next_option; 177 goto next_option;
169 } 178 }
179 cp = "principals=\"";
180 if (strncasecmp(opts, cp, strlen(cp)) == 0) {
181 opts += strlen(cp);
182 if (authorized_principals != NULL)
183 xfree(authorized_principals);
184 authorized_principals = xmalloc(strlen(opts) + 1);
185 i = 0;
186 while (*opts) {
187 if (*opts == '"')
188 break;
189 if (*opts == '\\' && opts[1] == '"') {
190 opts += 2;
191 authorized_principals[i++] = '"';
192 continue;
193 }
194 authorized_principals[i++] = *opts++;
195 }
196 if (!*opts) {
197 debug("%.100s, line %lu: missing end quote",
198 file, linenum);
199 auth_debug_add("%.100s, line %lu: missing end quote",
200 file, linenum);
201 xfree(authorized_principals);
202 authorized_principals = NULL;
203 goto bad_option;
204 }
205 authorized_principals[i] = '\0';
206 auth_debug_add("principals: %.900s",
207 authorized_principals);
208 opts++;
209 goto next_option;
210 }
170 cp = "environment=\""; 211 cp = "environment=\"";
171 if (options.permit_user_env && 212 if (options.permit_user_env &&
172 strncasecmp(opts, cp, strlen(cp)) == 0) { 213 strncasecmp(opts, cp, strlen(cp)) == 0) {
@@ -376,123 +417,147 @@ bad_option:
376 return 0; 417 return 0;
377} 418}
378 419
379/* 420#define OPTIONS_CRITICAL 1
380 * Set options from certificate constraints. These supersede user key options 421#define OPTIONS_EXTENSIONS 2
381 * so this must be called after auth_parse_options(). 422static int
382 */ 423parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
383int 424 u_int which, int crit,
384auth_cert_constraints(Buffer *c_orig, 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)
385{ 432{
433 char *command, *allowed;
434 const char *remote_ip;
386 u_char *name = NULL, *data_blob = NULL; 435 u_char *name = NULL, *data_blob = NULL;
387 u_int nlen, dlen, clen; 436 u_int nlen, dlen, clen;
388 Buffer c, data; 437 Buffer c, data;
389 int ret = -1; 438 int ret = -1, found;
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 439
399 buffer_init(&data); 440 buffer_init(&data);
400 441
401 /* Make copy to avoid altering original */ 442 /* Make copy to avoid altering original */
402 buffer_init(&c); 443 buffer_init(&c);
403 buffer_append(&c, buffer_ptr(c_orig), buffer_len(c_orig)); 444 buffer_append(&c, optblob, optblob_len);
404 445
405 while (buffer_len(&c) > 0) { 446 while (buffer_len(&c) > 0) {
406 if ((name = buffer_get_string_ret(&c, &nlen)) == NULL || 447 if ((name = buffer_get_string_ret(&c, &nlen)) == NULL ||
407 (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) { 448 (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) {
408 error("Certificate constraints corrupt"); 449 error("Certificate options corrupt");
409 goto out; 450 goto out;
410 } 451 }
411 buffer_append(&data, data_blob, dlen); 452 buffer_append(&data, data_blob, dlen);
412 debug3("found certificate constraint \"%.100s\" len %u", 453 debug3("found certificate option \"%.100s\" len %u",
413 name, dlen); 454 name, dlen);
414 if (strlen(name) != nlen) { 455 if (strlen(name) != nlen) {
415 error("Certificate constraint name contains \\0"); 456 error("Certificate constraint name contains \\0");
416 goto out; 457 goto out;
417 } 458 }
418 if (strcmp(name, "permit-X11-forwarding") == 0) 459 found = 0;
419 cert_no_x11_forwarding_flag = 0; 460 if ((which & OPTIONS_EXTENSIONS) != 0) {
420 else if (strcmp(name, "permit-agent-forwarding") == 0) 461 if (strcmp(name, "permit-X11-forwarding") == 0) {
421 cert_no_agent_forwarding_flag = 0; 462 *cert_no_x11_forwarding_flag = 0;
422 else if (strcmp(name, "permit-port-forwarding") == 0) 463 found = 1;
423 cert_no_port_forwarding_flag = 0; 464 } else if (strcmp(name,
424 else if (strcmp(name, "permit-pty") == 0) 465 "permit-agent-forwarding") == 0) {
425 cert_no_pty_flag = 0; 466 *cert_no_agent_forwarding_flag = 0;
426 else if (strcmp(name, "permit-user-rc") == 0) 467 found = 1;
427 cert_no_user_rc = 0; 468 } else if (strcmp(name,
428 else if (strcmp(name, "force-command") == 0) { 469 "permit-port-forwarding") == 0) {
429 char *command = buffer_get_string_ret(&data, &clen); 470 *cert_no_port_forwarding_flag = 0;
430 471 found = 1;
431 if (command == NULL) { 472 } else if (strcmp(name, "permit-pty") == 0) {
432 error("Certificate constraint \"%s\" corrupt", 473 *cert_no_pty_flag = 0;
433 name); 474 found = 1;
434 goto out; 475 } else if (strcmp(name, "permit-user-rc") == 0) {
476 *cert_no_user_rc = 0;
477 found = 1;
435 } 478 }
436 if (strlen(command) != clen) { 479 }
437 error("force-command constraint contains \\0"); 480 if (!found && (which & OPTIONS_CRITICAL) != 0) {
438 goto out; 481 if (strcmp(name, "force-command") == 0) {
439 } 482 if ((command = buffer_get_string_ret(&data,
440 if (cert_forced_command != NULL) { 483 &clen)) == NULL) {
441 error("Certificate has multiple " 484 error("Certificate constraint \"%s\" "
442 "force-command constraints"); 485 "corrupt", name);
443 xfree(command); 486 goto out;
444 goto out; 487 }
445 } 488 if (strlen(command) != clen) {
446 cert_forced_command = command; 489 error("force-command constraint "
447 } else if (strcmp(name, "source-address") == 0) { 490 "contains \\0");
448 char *allowed = buffer_get_string_ret(&data, &clen); 491 goto out;
449 const char *remote_ip = get_remote_ipaddr(); 492 }
450 493 if (*cert_forced_command != NULL) {
451 if (allowed == NULL) { 494 error("Certificate has multiple "
452 error("Certificate constraint \"%s\" corrupt", 495 "force-command options");
453 name); 496 xfree(command);
454 goto out; 497 goto out;
455 } 498 }
456 if (strlen(allowed) != clen) { 499 *cert_forced_command = command;
457 error("source-address constraint contains \\0"); 500 found = 1;
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 } 501 }
466 switch (addr_match_cidr_list(remote_ip, allowed)) { 502 if (strcmp(name, "source-address") == 0) {
467 case 1: 503 if ((allowed = buffer_get_string_ret(&data,
468 /* accepted */ 504 &clen)) == NULL) {
469 xfree(allowed); 505 error("Certificate constraint "
470 break; 506 "\"%s\" corrupt", name);
471 case 0: 507 goto out;
472 /* no match */ 508 }
473 logit("Authentication tried for %.100s with " 509 if (strlen(allowed) != clen) {
474 "valid certificate but not from a " 510 error("source-address constraint "
475 "permitted host (ip=%.200s).", 511 "contains \\0");
476 pw->pw_name, remote_ip); 512 goto out;
477 auth_debug_add("Your address '%.200s' is not " 513 }
478 "permitted to use this certificate for " 514 if ((*cert_source_address_done)++) {
479 "login.", remote_ip); 515 error("Certificate has multiple "
480 xfree(allowed); 516 "source-address options");
481 goto out; 517 xfree(allowed);
482 case -1: 518 goto out;
483 error("Certificate source-address contents " 519 }
484 "invalid"); 520 remote_ip = get_remote_ipaddr();
485 xfree(allowed); 521 switch (addr_match_cidr_list(remote_ip,
486 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;
487 } 547 }
488 } else {
489 error("Certificate constraint \"%s\" is not supported",
490 name);
491 goto out;
492 } 548 }
493 549
494 if (buffer_len(&data) != 0) { 550 if (!found) {
495 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 "
496 "(extra data)", name); 561 "(extra data)", name);
497 goto out; 562 goto out;
498 } 563 }
@@ -501,10 +566,73 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw)
501 xfree(data_blob); 566 xfree(data_blob);
502 name = data_blob = NULL; 567 name = data_blob = NULL;
503 } 568 }
504 569 /* successfully parsed all options */
505 /* successfully parsed all constraints */
506 ret = 0; 570 ret = 0;
507 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
508 no_port_forwarding_flag |= cert_no_port_forwarding_flag; 636 no_port_forwarding_flag |= cert_no_port_forwarding_flag;
509 no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; 637 no_agent_forwarding_flag |= cert_no_agent_forwarding_flag;
510 no_x11_forwarding_flag |= cert_no_x11_forwarding_flag; 638 no_x11_forwarding_flag |= cert_no_x11_forwarding_flag;
@@ -516,14 +644,6 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw)
516 xfree(forced_command); 644 xfree(forced_command);
517 forced_command = cert_forced_command; 645 forced_command = cert_forced_command;
518 } 646 }
519 647 return 0;
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} 648}
529 649