1262566Sdes/* $OpenBSD: auth-options.c,v 1.62 2013/12/19 00:27:57 djm Exp $ */ 265668Skris/* 365668Skris * Author: Tatu Ylonen <ylo@cs.hut.fi> 465668Skris * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 565668Skris * All rights reserved 665668Skris * As far as I am concerned, the code I have written for this software 765668Skris * can be used freely for any purpose. Any derived versions of this 865668Skris * software must be clearly marked as such, and if the derived work is 965668Skris * incompatible with the protocol description in the RFC file, it must be 1065668Skris * called by a name other than "ssh" or "Secure Shell". 1165668Skris */ 1265668Skris 1365668Skris#include "includes.h" 1465668Skris 15162852Sdes#include <sys/types.h> 16162852Sdes 17162852Sdes#include <netdb.h> 18162852Sdes#include <pwd.h> 19162852Sdes#include <string.h> 20162852Sdes#include <stdio.h> 21162852Sdes#include <stdarg.h> 22162852Sdes 23181111Sdes#include "openbsd-compat/sys-queue.h" 2465668Skris#include "xmalloc.h" 2565668Skris#include "match.h" 2676259Sgreen#include "log.h" 2776259Sgreen#include "canohost.h" 28162852Sdes#include "buffer.h" 2976259Sgreen#include "channels.h" 3076259Sgreen#include "servconf.h" 3192555Sdes#include "misc.h" 32162852Sdes#include "key.h" 33215116Sdes#include "auth-options.h" 34162852Sdes#include "hostfile.h" 35162852Sdes#include "auth.h" 3665668Skris 3765668Skris/* Flags set authorized_keys flags */ 3865668Skrisint no_port_forwarding_flag = 0; 3965668Skrisint no_agent_forwarding_flag = 0; 4065668Skrisint no_x11_forwarding_flag = 0; 4165668Skrisint no_pty_flag = 0; 42181111Sdesint no_user_rc = 0; 43204917Sdesint key_is_cert_authority = 0; 4465668Skris 4565668Skris/* "command=" option. */ 4665668Skrischar *forced_command = NULL; 4765668Skris 4865668Skris/* "environment=" options. */ 4965668Skrisstruct envstring *custom_environment = NULL; 5065668Skris 51157016Sdes/* "tunnel=" option. */ 52157016Sdesint forced_tun_device = -1; 53157016Sdes 54215116Sdes/* "principals=" option. */ 55215116Sdeschar *authorized_principals = NULL; 56215116Sdes 5776259Sgreenextern ServerOptions options; 5876259Sgreen 5969587Sgreenvoid 6069587Sgreenauth_clear_options(void) 6169587Sgreen{ 6269587Sgreen no_agent_forwarding_flag = 0; 6369587Sgreen no_port_forwarding_flag = 0; 6469587Sgreen no_pty_flag = 0; 6569587Sgreen no_x11_forwarding_flag = 0; 66181111Sdes no_user_rc = 0; 67204917Sdes key_is_cert_authority = 0; 6869587Sgreen while (custom_environment) { 6969587Sgreen struct envstring *ce = custom_environment; 7069587Sgreen custom_environment = ce->next; 71255767Sdes free(ce->s); 72255767Sdes free(ce); 7369587Sgreen } 7469587Sgreen if (forced_command) { 75255767Sdes free(forced_command); 7669587Sgreen forced_command = NULL; 7769587Sgreen } 78215116Sdes if (authorized_principals) { 79255767Sdes free(authorized_principals); 80215116Sdes authorized_principals = NULL; 81215116Sdes } 82157016Sdes forced_tun_device = -1; 8376259Sgreen channel_clear_permitted_opens(); 8469587Sgreen} 8569587Sgreen 8676259Sgreen/* 8776259Sgreen * return 1 if access is granted, 0 if not. 8876259Sgreen * side effect: sets key option flags 8976259Sgreen */ 9065668Skrisint 9176259Sgreenauth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) 9265668Skris{ 9365668Skris const char *cp; 9476259Sgreen int i; 9569587Sgreen 9669587Sgreen /* reset options */ 9769587Sgreen auth_clear_options(); 9869587Sgreen 9976259Sgreen if (!opts) 10076259Sgreen return 1; 10176259Sgreen 10276259Sgreen while (*opts && *opts != ' ' && *opts != '\t') { 103204917Sdes cp = "cert-authority"; 104204917Sdes if (strncasecmp(opts, cp, strlen(cp)) == 0) { 105204917Sdes key_is_cert_authority = 1; 106204917Sdes opts += strlen(cp); 107204917Sdes goto next_option; 108204917Sdes } 10965668Skris cp = "no-port-forwarding"; 11076259Sgreen if (strncasecmp(opts, cp, strlen(cp)) == 0) { 11198675Sdes auth_debug_add("Port forwarding disabled."); 11265668Skris no_port_forwarding_flag = 1; 11376259Sgreen opts += strlen(cp); 11465668Skris goto next_option; 11565668Skris } 11665668Skris cp = "no-agent-forwarding"; 11776259Sgreen if (strncasecmp(opts, cp, strlen(cp)) == 0) { 11898675Sdes auth_debug_add("Agent forwarding disabled."); 11965668Skris no_agent_forwarding_flag = 1; 12076259Sgreen opts += strlen(cp); 12165668Skris goto next_option; 12265668Skris } 12365668Skris cp = "no-X11-forwarding"; 12476259Sgreen if (strncasecmp(opts, cp, strlen(cp)) == 0) { 12598675Sdes auth_debug_add("X11 forwarding disabled."); 12665668Skris no_x11_forwarding_flag = 1; 12776259Sgreen opts += strlen(cp); 12865668Skris goto next_option; 12965668Skris } 13065668Skris cp = "no-pty"; 13176259Sgreen if (strncasecmp(opts, cp, strlen(cp)) == 0) { 13298675Sdes auth_debug_add("Pty allocation disabled."); 13365668Skris no_pty_flag = 1; 13476259Sgreen opts += strlen(cp); 13565668Skris goto next_option; 13665668Skris } 137181111Sdes cp = "no-user-rc"; 138181111Sdes if (strncasecmp(opts, cp, strlen(cp)) == 0) { 139181111Sdes auth_debug_add("User rc file execution disabled."); 140181111Sdes no_user_rc = 1; 141181111Sdes opts += strlen(cp); 142181111Sdes goto next_option; 143181111Sdes } 14465668Skris cp = "command=\""; 14576259Sgreen if (strncasecmp(opts, cp, strlen(cp)) == 0) { 14676259Sgreen opts += strlen(cp); 147215116Sdes if (forced_command != NULL) 148255767Sdes free(forced_command); 14976259Sgreen forced_command = xmalloc(strlen(opts) + 1); 15065668Skris i = 0; 15176259Sgreen while (*opts) { 15276259Sgreen if (*opts == '"') 15365668Skris break; 15476259Sgreen if (*opts == '\\' && opts[1] == '"') { 15576259Sgreen opts += 2; 15665668Skris forced_command[i++] = '"'; 15765668Skris continue; 15865668Skris } 15976259Sgreen forced_command[i++] = *opts++; 16065668Skris } 16176259Sgreen if (!*opts) { 16265668Skris debug("%.100s, line %lu: missing end quote", 16376259Sgreen file, linenum); 16498675Sdes auth_debug_add("%.100s, line %lu: missing end quote", 16576259Sgreen file, linenum); 166255767Sdes free(forced_command); 16776259Sgreen forced_command = NULL; 16876259Sgreen goto bad_option; 16965668Skris } 170162852Sdes forced_command[i] = '\0'; 171221420Sdes auth_debug_add("Forced command."); 17276259Sgreen opts++; 17365668Skris goto next_option; 17465668Skris } 175215116Sdes cp = "principals=\""; 176215116Sdes if (strncasecmp(opts, cp, strlen(cp)) == 0) { 177215116Sdes opts += strlen(cp); 178215116Sdes if (authorized_principals != NULL) 179255767Sdes free(authorized_principals); 180215116Sdes authorized_principals = xmalloc(strlen(opts) + 1); 181215116Sdes i = 0; 182215116Sdes while (*opts) { 183215116Sdes if (*opts == '"') 184215116Sdes break; 185215116Sdes if (*opts == '\\' && opts[1] == '"') { 186215116Sdes opts += 2; 187215116Sdes authorized_principals[i++] = '"'; 188215116Sdes continue; 189215116Sdes } 190215116Sdes authorized_principals[i++] = *opts++; 191215116Sdes } 192215116Sdes if (!*opts) { 193215116Sdes debug("%.100s, line %lu: missing end quote", 194215116Sdes file, linenum); 195215116Sdes auth_debug_add("%.100s, line %lu: missing end quote", 196215116Sdes file, linenum); 197255767Sdes free(authorized_principals); 198215116Sdes authorized_principals = NULL; 199215116Sdes goto bad_option; 200215116Sdes } 201215116Sdes authorized_principals[i] = '\0'; 202215116Sdes auth_debug_add("principals: %.900s", 203215116Sdes authorized_principals); 204215116Sdes opts++; 205215116Sdes goto next_option; 206215116Sdes } 20765668Skris cp = "environment=\""; 208106121Sdes if (options.permit_user_env && 209106121Sdes strncasecmp(opts, cp, strlen(cp)) == 0) { 21065668Skris char *s; 21165668Skris struct envstring *new_envstring; 21276259Sgreen 21376259Sgreen opts += strlen(cp); 21476259Sgreen s = xmalloc(strlen(opts) + 1); 21565668Skris i = 0; 21676259Sgreen while (*opts) { 21776259Sgreen if (*opts == '"') 21865668Skris break; 21976259Sgreen if (*opts == '\\' && opts[1] == '"') { 22076259Sgreen opts += 2; 22165668Skris s[i++] = '"'; 22265668Skris continue; 22365668Skris } 22476259Sgreen s[i++] = *opts++; 22565668Skris } 22676259Sgreen if (!*opts) { 22765668Skris debug("%.100s, line %lu: missing end quote", 22876259Sgreen file, linenum); 22998675Sdes auth_debug_add("%.100s, line %lu: missing end quote", 23076259Sgreen file, linenum); 231255767Sdes free(s); 23276259Sgreen goto bad_option; 23365668Skris } 234162852Sdes s[i] = '\0'; 23598675Sdes auth_debug_add("Adding to environment: %.900s", s); 23665668Skris debug("Adding to environment: %.900s", s); 23776259Sgreen opts++; 238258343Sdes new_envstring = xcalloc(1, sizeof(struct envstring)); 23965668Skris new_envstring->s = s; 24065668Skris new_envstring->next = custom_environment; 24165668Skris custom_environment = new_envstring; 24265668Skris goto next_option; 24365668Skris } 24465668Skris cp = "from=\""; 24576259Sgreen if (strncasecmp(opts, cp, strlen(cp)) == 0) { 24676259Sgreen const char *remote_ip = get_remote_ipaddr(); 24776259Sgreen const char *remote_host = get_canonical_hostname( 248124208Sdes options.use_dns); 24976259Sgreen char *patterns = xmalloc(strlen(opts) + 1); 25076259Sgreen 25176259Sgreen opts += strlen(cp); 25265668Skris i = 0; 25376259Sgreen while (*opts) { 25476259Sgreen if (*opts == '"') 25565668Skris break; 25676259Sgreen if (*opts == '\\' && opts[1] == '"') { 25776259Sgreen opts += 2; 25865668Skris patterns[i++] = '"'; 25965668Skris continue; 26065668Skris } 26176259Sgreen patterns[i++] = *opts++; 26265668Skris } 26376259Sgreen if (!*opts) { 26465668Skris debug("%.100s, line %lu: missing end quote", 26576259Sgreen file, linenum); 26698675Sdes auth_debug_add("%.100s, line %lu: missing end quote", 26776259Sgreen file, linenum); 268255767Sdes free(patterns); 26976259Sgreen goto bad_option; 27065668Skris } 271162852Sdes patterns[i] = '\0'; 27276259Sgreen opts++; 273181111Sdes switch (match_host_and_ip(remote_host, remote_ip, 274181111Sdes patterns)) { 275181111Sdes case 1: 276255767Sdes free(patterns); 277181111Sdes /* Host name matches. */ 278181111Sdes goto next_option; 279181111Sdes case -1: 280181111Sdes debug("%.100s, line %lu: invalid criteria", 281181111Sdes file, linenum); 282181111Sdes auth_debug_add("%.100s, line %lu: " 283181111Sdes "invalid criteria", file, linenum); 284181111Sdes /* FALLTHROUGH */ 285181111Sdes case 0: 286255767Sdes free(patterns); 287124208Sdes logit("Authentication tried for %.100s with " 28876259Sgreen "correct key but not from a permitted " 28976259Sgreen "host (host=%.200s, ip=%.200s).", 29076259Sgreen pw->pw_name, remote_host, remote_ip); 29198675Sdes auth_debug_add("Your host '%.200s' is not " 29276259Sgreen "permitted to use this key for login.", 29376259Sgreen remote_host); 294181111Sdes break; 29565668Skris } 296181111Sdes /* deny access */ 297181111Sdes return 0; 29865668Skris } 29976259Sgreen cp = "permitopen=\""; 30076259Sgreen if (strncasecmp(opts, cp, strlen(cp)) == 0) { 301146998Sdes char *host, *p; 302192595Sdes int port; 30376259Sgreen char *patterns = xmalloc(strlen(opts) + 1); 30476259Sgreen 30576259Sgreen opts += strlen(cp); 30676259Sgreen i = 0; 30776259Sgreen while (*opts) { 30876259Sgreen if (*opts == '"') 30976259Sgreen break; 31076259Sgreen if (*opts == '\\' && opts[1] == '"') { 31176259Sgreen opts += 2; 31276259Sgreen patterns[i++] = '"'; 31376259Sgreen continue; 31476259Sgreen } 31576259Sgreen patterns[i++] = *opts++; 31676259Sgreen } 31776259Sgreen if (!*opts) { 31876259Sgreen debug("%.100s, line %lu: missing end quote", 31976259Sgreen file, linenum); 320146998Sdes auth_debug_add("%.100s, line %lu: missing " 321146998Sdes "end quote", file, linenum); 322255767Sdes free(patterns); 32376259Sgreen goto bad_option; 32476259Sgreen } 325162852Sdes patterns[i] = '\0'; 32676259Sgreen opts++; 327146998Sdes p = patterns; 328146998Sdes host = hpdelim(&p); 329146998Sdes if (host == NULL || strlen(host) >= NI_MAXHOST) { 330146998Sdes debug("%.100s, line %lu: Bad permitopen " 331147001Sdes "specification <%.100s>", file, linenum, 332146998Sdes patterns); 33398675Sdes auth_debug_add("%.100s, line %lu: " 334146998Sdes "Bad permitopen specification", file, 335146998Sdes linenum); 336255767Sdes free(patterns); 33776259Sgreen goto bad_option; 33876259Sgreen } 339147001Sdes host = cleanhostname(host); 340240075Sdes if (p == NULL || (port = permitopen_port(p)) < 0) { 341146998Sdes debug("%.100s, line %lu: Bad permitopen port " 342146998Sdes "<%.100s>", file, linenum, p ? p : ""); 34398675Sdes auth_debug_add("%.100s, line %lu: " 34492555Sdes "Bad permitopen port", file, linenum); 345255767Sdes free(patterns); 34676259Sgreen goto bad_option; 34776259Sgreen } 348248619Sdes if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) 34992555Sdes channel_add_permitted_opens(host, port); 350255767Sdes free(patterns); 35176259Sgreen goto next_option; 35276259Sgreen } 353157016Sdes cp = "tunnel=\""; 354157016Sdes if (strncasecmp(opts, cp, strlen(cp)) == 0) { 355157016Sdes char *tun = NULL; 356157016Sdes opts += strlen(cp); 357157016Sdes tun = xmalloc(strlen(opts) + 1); 358157016Sdes i = 0; 359157016Sdes while (*opts) { 360157016Sdes if (*opts == '"') 361157016Sdes break; 362157016Sdes tun[i++] = *opts++; 363157016Sdes } 364157016Sdes if (!*opts) { 365157016Sdes debug("%.100s, line %lu: missing end quote", 366157016Sdes file, linenum); 367157016Sdes auth_debug_add("%.100s, line %lu: missing end quote", 368157016Sdes file, linenum); 369255767Sdes free(tun); 370157016Sdes forced_tun_device = -1; 371157016Sdes goto bad_option; 372157016Sdes } 373162852Sdes tun[i] = '\0'; 374157016Sdes forced_tun_device = a2tun(tun, NULL); 375255767Sdes free(tun); 376157016Sdes if (forced_tun_device == SSH_TUNID_ERR) { 377157016Sdes debug("%.100s, line %lu: invalid tun device", 378157016Sdes file, linenum); 379157016Sdes auth_debug_add("%.100s, line %lu: invalid tun device", 380157016Sdes file, linenum); 381157016Sdes forced_tun_device = -1; 382157016Sdes goto bad_option; 383157016Sdes } 384157016Sdes auth_debug_add("Forced tun device: %d", forced_tun_device); 385157016Sdes opts++; 386157016Sdes goto next_option; 387157016Sdes } 38865668Skrisnext_option: 38965668Skris /* 39065668Skris * Skip the comma, and move to the next option 39165668Skris * (or break out if there are no more). 39265668Skris */ 39376259Sgreen if (!*opts) 39465668Skris fatal("Bugs in auth-options.c option processing."); 39576259Sgreen if (*opts == ' ' || *opts == '\t') 39665668Skris break; /* End of options. */ 39776259Sgreen if (*opts != ',') 39865668Skris goto bad_option; 39976259Sgreen opts++; 40065668Skris /* Process the next option. */ 40165668Skris } 40298675Sdes 40365668Skris /* grant access */ 40465668Skris return 1; 40565668Skris 40665668Skrisbad_option: 407124208Sdes logit("Bad options in %.100s file, line %lu: %.50s", 40876259Sgreen file, linenum, opts); 40998675Sdes auth_debug_add("Bad options in %.100s file, line %lu: %.50s", 41076259Sgreen file, linenum, opts); 41198675Sdes 41265668Skris /* deny access */ 41365668Skris return 0; 41465668Skris} 415204917Sdes 416215116Sdes#define OPTIONS_CRITICAL 1 417215116Sdes#define OPTIONS_EXTENSIONS 2 418215116Sdesstatic int 419215116Sdesparse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, 420215116Sdes u_int which, int crit, 421215116Sdes int *cert_no_port_forwarding_flag, 422215116Sdes int *cert_no_agent_forwarding_flag, 423215116Sdes int *cert_no_x11_forwarding_flag, 424215116Sdes int *cert_no_pty_flag, 425215116Sdes int *cert_no_user_rc, 426215116Sdes char **cert_forced_command, 427215116Sdes int *cert_source_address_done) 428204917Sdes{ 429215116Sdes char *command, *allowed; 430215116Sdes const char *remote_ip; 431255767Sdes char *name = NULL; 432255767Sdes u_char *data_blob = NULL; 433204917Sdes u_int nlen, dlen, clen; 434204917Sdes Buffer c, data; 435262566Sdes int ret = -1, result, found; 436204917Sdes 437204917Sdes buffer_init(&data); 438204917Sdes 439204917Sdes /* Make copy to avoid altering original */ 440204917Sdes buffer_init(&c); 441215116Sdes buffer_append(&c, optblob, optblob_len); 442204917Sdes 443204917Sdes while (buffer_len(&c) > 0) { 444221420Sdes if ((name = buffer_get_cstring_ret(&c, &nlen)) == NULL || 445204917Sdes (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) { 446215116Sdes error("Certificate options corrupt"); 447204917Sdes goto out; 448204917Sdes } 449204917Sdes buffer_append(&data, data_blob, dlen); 450215116Sdes debug3("found certificate option \"%.100s\" len %u", 451204917Sdes name, dlen); 452215116Sdes found = 0; 453215116Sdes if ((which & OPTIONS_EXTENSIONS) != 0) { 454215116Sdes if (strcmp(name, "permit-X11-forwarding") == 0) { 455215116Sdes *cert_no_x11_forwarding_flag = 0; 456215116Sdes found = 1; 457215116Sdes } else if (strcmp(name, 458215116Sdes "permit-agent-forwarding") == 0) { 459215116Sdes *cert_no_agent_forwarding_flag = 0; 460215116Sdes found = 1; 461215116Sdes } else if (strcmp(name, 462215116Sdes "permit-port-forwarding") == 0) { 463215116Sdes *cert_no_port_forwarding_flag = 0; 464215116Sdes found = 1; 465215116Sdes } else if (strcmp(name, "permit-pty") == 0) { 466215116Sdes *cert_no_pty_flag = 0; 467215116Sdes found = 1; 468215116Sdes } else if (strcmp(name, "permit-user-rc") == 0) { 469215116Sdes *cert_no_user_rc = 0; 470215116Sdes found = 1; 471204917Sdes } 472215116Sdes } 473215116Sdes if (!found && (which & OPTIONS_CRITICAL) != 0) { 474215116Sdes if (strcmp(name, "force-command") == 0) { 475221420Sdes if ((command = buffer_get_cstring_ret(&data, 476215116Sdes &clen)) == NULL) { 477215116Sdes error("Certificate constraint \"%s\" " 478215116Sdes "corrupt", name); 479215116Sdes goto out; 480215116Sdes } 481215116Sdes if (*cert_forced_command != NULL) { 482215116Sdes error("Certificate has multiple " 483215116Sdes "force-command options"); 484255767Sdes free(command); 485215116Sdes goto out; 486215116Sdes } 487215116Sdes *cert_forced_command = command; 488215116Sdes found = 1; 489204917Sdes } 490215116Sdes if (strcmp(name, "source-address") == 0) { 491221420Sdes if ((allowed = buffer_get_cstring_ret(&data, 492215116Sdes &clen)) == NULL) { 493215116Sdes error("Certificate constraint " 494215116Sdes "\"%s\" corrupt", name); 495215116Sdes goto out; 496215116Sdes } 497215116Sdes if ((*cert_source_address_done)++) { 498215116Sdes error("Certificate has multiple " 499215116Sdes "source-address options"); 500255767Sdes free(allowed); 501215116Sdes goto out; 502215116Sdes } 503215116Sdes remote_ip = get_remote_ipaddr(); 504262566Sdes result = addr_match_cidr_list(remote_ip, 505262566Sdes allowed); 506262566Sdes free(allowed); 507262566Sdes switch (result) { 508215116Sdes case 1: 509215116Sdes /* accepted */ 510215116Sdes break; 511215116Sdes case 0: 512215116Sdes /* no match */ 513215116Sdes logit("Authentication tried for %.100s " 514215116Sdes "with valid certificate but not " 515215116Sdes "from a permitted host " 516215116Sdes "(ip=%.200s).", pw->pw_name, 517215116Sdes remote_ip); 518215116Sdes auth_debug_add("Your address '%.200s' " 519215116Sdes "is not permitted to use this " 520215116Sdes "certificate for login.", 521215116Sdes remote_ip); 522215116Sdes goto out; 523215116Sdes case -1: 524262566Sdes default: 525215116Sdes error("Certificate source-address " 526215116Sdes "contents invalid"); 527215116Sdes goto out; 528215116Sdes } 529215116Sdes found = 1; 530204917Sdes } 531215116Sdes } 532215116Sdes 533215116Sdes if (!found) { 534215116Sdes if (crit) { 535215116Sdes error("Certificate critical option \"%s\" " 536215116Sdes "is not supported", name); 537204917Sdes goto out; 538215116Sdes } else { 539215116Sdes logit("Certificate extension \"%s\" " 540215116Sdes "is not supported", name); 541204917Sdes } 542215116Sdes } else if (buffer_len(&data) != 0) { 543215116Sdes error("Certificate option \"%s\" corrupt " 544204917Sdes "(extra data)", name); 545204917Sdes goto out; 546204917Sdes } 547204917Sdes buffer_clear(&data); 548255767Sdes free(name); 549255767Sdes free(data_blob); 550255767Sdes name = NULL; 551255767Sdes data_blob = NULL; 552204917Sdes } 553215116Sdes /* successfully parsed all options */ 554204917Sdes ret = 0; 555204917Sdes 556215116Sdes out: 557215116Sdes if (ret != 0 && 558215116Sdes cert_forced_command != NULL && 559215116Sdes *cert_forced_command != NULL) { 560255767Sdes free(*cert_forced_command); 561215116Sdes *cert_forced_command = NULL; 562215116Sdes } 563215116Sdes if (name != NULL) 564255767Sdes free(name); 565215116Sdes if (data_blob != NULL) 566255767Sdes free(data_blob); 567215116Sdes buffer_free(&data); 568215116Sdes buffer_free(&c); 569215116Sdes return ret; 570215116Sdes} 571215116Sdes 572215116Sdes/* 573215116Sdes * Set options from critical certificate options. These supersede user key 574215116Sdes * options so this must be called after auth_parse_options(). 575215116Sdes */ 576215116Sdesint 577215116Sdesauth_cert_options(Key *k, struct passwd *pw) 578215116Sdes{ 579215116Sdes int cert_no_port_forwarding_flag = 1; 580215116Sdes int cert_no_agent_forwarding_flag = 1; 581215116Sdes int cert_no_x11_forwarding_flag = 1; 582215116Sdes int cert_no_pty_flag = 1; 583215116Sdes int cert_no_user_rc = 1; 584215116Sdes char *cert_forced_command = NULL; 585215116Sdes int cert_source_address_done = 0; 586215116Sdes 587215116Sdes if (key_cert_is_legacy(k)) { 588215116Sdes /* All options are in the one field for v00 certs */ 589215116Sdes if (parse_option_list(buffer_ptr(&k->cert->critical), 590215116Sdes buffer_len(&k->cert->critical), pw, 591215116Sdes OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1, 592215116Sdes &cert_no_port_forwarding_flag, 593215116Sdes &cert_no_agent_forwarding_flag, 594215116Sdes &cert_no_x11_forwarding_flag, 595215116Sdes &cert_no_pty_flag, 596215116Sdes &cert_no_user_rc, 597215116Sdes &cert_forced_command, 598215116Sdes &cert_source_address_done) == -1) 599215116Sdes return -1; 600215116Sdes } else { 601215116Sdes /* Separate options and extensions for v01 certs */ 602215116Sdes if (parse_option_list(buffer_ptr(&k->cert->critical), 603215116Sdes buffer_len(&k->cert->critical), pw, 604215116Sdes OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, 605215116Sdes &cert_forced_command, 606215116Sdes &cert_source_address_done) == -1) 607215116Sdes return -1; 608215116Sdes if (parse_option_list(buffer_ptr(&k->cert->extensions), 609215116Sdes buffer_len(&k->cert->extensions), pw, 610215116Sdes OPTIONS_EXTENSIONS, 1, 611215116Sdes &cert_no_port_forwarding_flag, 612215116Sdes &cert_no_agent_forwarding_flag, 613215116Sdes &cert_no_x11_forwarding_flag, 614215116Sdes &cert_no_pty_flag, 615215116Sdes &cert_no_user_rc, 616215116Sdes NULL, NULL) == -1) 617215116Sdes return -1; 618215116Sdes } 619215116Sdes 620204917Sdes no_port_forwarding_flag |= cert_no_port_forwarding_flag; 621204917Sdes no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; 622204917Sdes no_x11_forwarding_flag |= cert_no_x11_forwarding_flag; 623204917Sdes no_pty_flag |= cert_no_pty_flag; 624204917Sdes no_user_rc |= cert_no_user_rc; 625204917Sdes /* CA-specified forced command supersedes key option */ 626204917Sdes if (cert_forced_command != NULL) { 627204917Sdes if (forced_command != NULL) 628255767Sdes free(forced_command); 629204917Sdes forced_command = cert_forced_command; 630204917Sdes } 631215116Sdes return 0; 632204917Sdes} 633204917Sdes 634