/* * Set options from critical certificate options. These supersede user key * options so this must be called after auth_parse_options(). */ int auth_cert_options(Key *k, struct passwd *pw) { int cert_no_port_forwarding_flag = 1; int cert_no_agent_forwarding_flag = 1; int cert_no_x11_forwarding_flag = 1; int cert_no_pty_flag = 1; int cert_no_user_rc = 1; char *cert_forced_command = NULL; int cert_source_address_done = 0; if (key_cert_is_legacy(k)) { /* All options are in the one field for v00 certs */ if (parse_option_list(buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical), pw, OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1, &cert_no_port_forwarding_flag, &cert_no_agent_forwarding_flag, &cert_no_x11_forwarding_flag, &cert_no_pty_flag, &cert_no_user_rc, &cert_forced_command, &cert_source_address_done) == -1) return -1; } else { /* Separate options and extensions for v01 certs */ if (parse_option_list(buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical), pw, OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, &cert_forced_command, &cert_source_address_done) == -1) return -1; if (parse_option_list(buffer_ptr(&k->cert->extensions), buffer_len(&k->cert->extensions), pw, OPTIONS_EXTENSIONS, 1, &cert_no_port_forwarding_flag, &cert_no_agent_forwarding_flag, &cert_no_x11_forwarding_flag, &cert_no_pty_flag, &cert_no_user_rc, NULL, NULL) == -1) return -1; } no_port_forwarding_flag |= cert_no_port_forwarding_flag; no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; no_x11_forwarding_flag |= cert_no_x11_forwarding_flag; no_pty_flag |= cert_no_pty_flag; no_user_rc |= cert_no_user_rc; /* CA-specified forced command supersedes key option */ if (cert_forced_command != NULL) { if (forced_command != NULL) xfree(forced_command); forced_command = cert_forced_command; } return 0; }
/* * Set options from critical certificate options. These supersede user key * options so this must be called after auth_parse_options(). */ int auth_cert_options(struct sshkey *k, struct passwd *pw, const char **reason) { int cert_no_port_forwarding_flag = 1; int cert_no_agent_forwarding_flag = 1; int cert_no_x11_forwarding_flag = 1; int cert_no_pty_flag = 1; int cert_no_user_rc = 1; char *cert_forced_command = NULL; int cert_source_address_done = 0; *reason = "invalid certificate options"; /* Separate options and extensions for v01 certs */ if (parse_option_list(k->cert->critical, pw, OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, &cert_forced_command, &cert_source_address_done) == -1) return -1; if (parse_option_list(k->cert->extensions, pw, OPTIONS_EXTENSIONS, 0, &cert_no_port_forwarding_flag, &cert_no_agent_forwarding_flag, &cert_no_x11_forwarding_flag, &cert_no_pty_flag, &cert_no_user_rc, NULL, NULL) == -1) return -1; no_port_forwarding_flag |= cert_no_port_forwarding_flag; no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; no_x11_forwarding_flag |= cert_no_x11_forwarding_flag; no_pty_flag |= cert_no_pty_flag; no_user_rc |= cert_no_user_rc; /* * Only permit both CA and key option forced-command if they match. * Otherwise refuse the certificate. */ if (cert_forced_command != NULL && forced_command != NULL) { if (strcmp(forced_command, cert_forced_command) == 0) { free(forced_command); forced_command = cert_forced_command; } else { *reason = "certificate and key options forced command " "do not match"; free(cert_forced_command); return -1; } } else if (cert_forced_command != NULL) forced_command = cert_forced_command; /* success */ *reason = NULL; return 0; }
/* * Set options from critical certificate options. These supersede user key * options so this must be called after auth_parse_options(). */ int auth_cert_options(struct sshkey *k, struct passwd *pw) { int cert_no_port_forwarding_flag = 1; int cert_no_agent_forwarding_flag = 1; int cert_no_x11_forwarding_flag = 1; int cert_no_pty_flag = 1; int cert_no_user_rc = 1; char *cert_forced_command = NULL; int cert_source_address_done = 0; /* Separate options and extensions for v01 certs */ if (parse_option_list(k->cert->critical, pw, OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, &cert_forced_command, &cert_source_address_done) == -1) return -1; if (parse_option_list(k->cert->extensions, pw, OPTIONS_EXTENSIONS, 0, &cert_no_port_forwarding_flag, &cert_no_agent_forwarding_flag, &cert_no_x11_forwarding_flag, &cert_no_pty_flag, &cert_no_user_rc, NULL, NULL) == -1) return -1; no_port_forwarding_flag |= cert_no_port_forwarding_flag; no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; no_x11_forwarding_flag |= cert_no_x11_forwarding_flag; no_pty_flag |= cert_no_pty_flag; no_user_rc |= cert_no_user_rc; /* CA-specified forced command supersedes key option */ if (cert_forced_command != NULL) { free(forced_command); forced_command = cert_forced_command; } return 0; }
static void handle_configure(const char *req, int *req_index) { struct uart_config config = current_config; if (parse_option_list(req, req_index, &config) < 0) { send_error_response("einval"); return; } if (uart_configure(uart, &config) >= 0) { current_config = config; send_ok_response(); } else { send_error_response(uart_last_error()); } }
/* * Handle {name, kv_list} * * name is the serial port name * kv_list a list of configuration values (speed, parity, etc.) */ static void handle_open(const char *req, int *req_index) { int term_type; int term_size; if (ei_decode_tuple_header(req, req_index, &term_size) < 0 || term_size != 2) errx(EXIT_FAILURE, ":open requires a 2-tuple"); char name[32]; long binary_len; if (ei_get_type(req, req_index, &term_type, &term_size) < 0 || term_type != ERL_BINARY_EXT || term_size >= (int) sizeof(name) || ei_decode_binary(req, req_index, name, &binary_len) < 0) { // The name is almost certainly too long, so report that it // doesn't exist. send_error_response("enoent"); return; } name[term_size] = '\0'; struct uart_config config = current_config; if (parse_option_list(req, req_index, &config) < 0) { send_error_response("einval"); return; } // If the uart was already open, close and open it again if (uart_is_open(uart)) uart_close(uart); if (uart_open(uart, name, &config) >= 0) { current_config = config; send_ok_response(); } else { send_error_response(uart_last_error()); } }
/* * client-declaration :== * TOK_SEND option-decl | * TOK_DEFAULT option-decl | * TOK_SUPERSEDE option-decl | * TOK_APPEND option-decl | * TOK_PREPEND option-decl | * TOK_MEDIA string-list | * hardware-declaration | * TOK_REQUEST option-list | * TOK_REQUIRE option-list | * TOK_TIMEOUT number | * TOK_RETRY number | * TOK_SELECT_TIMEOUT number | * TOK_REBOOT number | * TOK_BACKOFF_CUTOFF number | * TOK_INITIAL_INTERVAL number | * TOK_SCRIPT string | * interface-declaration | * TOK_LEASE client-lease-statement | * TOK_ALIAS client-lease-statement | * TOK_REJECT reject-statement */ void parse_client_statement(FILE *cfile) { char *val; int token, code; switch (next_token(&val, cfile)) { case TOK_SEND: parse_option_decl(cfile, &config->send_options[0]); return; case TOK_DEFAULT: code = parse_option_decl(cfile, &config->defaults[0]); if (code != -1) config->default_actions[code] = ACTION_DEFAULT; return; case TOK_SUPERSEDE: code = parse_option_decl(cfile, &config->defaults[0]); if (code != -1) config->default_actions[code] = ACTION_SUPERSEDE; return; case TOK_APPEND: code = parse_option_decl(cfile, &config->defaults[0]); if (code != -1) config->default_actions[code] = ACTION_APPEND; return; case TOK_PREPEND: code = parse_option_decl(cfile, &config->defaults[0]); if (code != -1) config->default_actions[code] = ACTION_PREPEND; return; case TOK_MEDIA: parse_string_list(cfile, &config->media, 1); return; case TOK_HARDWARE: parse_hardware_param(cfile, &ifi->hw_address); return; case TOK_REQUEST: config->requested_option_count = parse_option_list(cfile, config->requested_options); return; case TOK_REQUIRE: memset(config->required_options, 0, sizeof(config->required_options)); parse_option_list(cfile, config->required_options); return; case TOK_LINK_TIMEOUT: parse_lease_time(cfile, &config->link_timeout); return; case TOK_TIMEOUT: parse_lease_time(cfile, &config->timeout); return; case TOK_RETRY: parse_lease_time(cfile, &config->retry_interval); return; case TOK_SELECT_TIMEOUT: parse_lease_time(cfile, &config->select_interval); return; case TOK_REBOOT: parse_lease_time(cfile, &config->reboot_timeout); return; case TOK_BACKOFF_CUTOFF: parse_lease_time(cfile, &config->backoff_cutoff); return; case TOK_INITIAL_INTERVAL: parse_lease_time(cfile, &config->initial_interval); return; case TOK_SCRIPT: config->script_name = parse_string(cfile); return; case TOK_INTERFACE: parse_interface_declaration(cfile); return; case TOK_LEASE: parse_client_lease_statement(cfile, 1); return; case TOK_ALIAS: parse_client_lease_statement(cfile, 2); return; case TOK_REJECT: parse_reject_statement(cfile); return; default: parse_warn("expecting a statement."); skip_to_semi(cfile); break; } token = next_token(&val, cfile); if (token != ';') { parse_warn("semicolon expected."); skip_to_semi(cfile); } }
/* * client-declaration :== * SEND option-decl | * DEFAULT option-decl | * SUPERSEDE option-decl | * PREPEND option-decl | * APPEND option-decl | * hardware-declaration | * REQUEST option-list | * REQUIRE option-list | * TIMEOUT number | * RETRY number | * REBOOT number | * SELECT_TIMEOUT number | * SCRIPT string | * interface-declaration | * LEASE client-lease-statement | * ALIAS client-lease-statement */ void parse_client_statement(FILE *cfile, struct interface_info *ip, struct client_config *config) { int token; char *val; struct option *option; switch (next_token(&val, cfile)) { case SEND: parse_option_decl(cfile, &config->send_options[0]); return; case DEFAULT: option = parse_option_decl(cfile, &config->defaults[0]); if (option) config->default_actions[option->code] = ACTION_DEFAULT; return; case SUPERSEDE: option = parse_option_decl(cfile, &config->defaults[0]); if (option) config->default_actions[option->code] = ACTION_SUPERSEDE; return; case APPEND: option = parse_option_decl(cfile, &config->defaults[0]); if (option) config->default_actions[option->code] = ACTION_APPEND; return; case PREPEND: option = parse_option_decl(cfile, &config->defaults[0]); if (option) config->default_actions[option->code] = ACTION_PREPEND; return; case MEDIA: parse_string_list(cfile, &config->media, 1); return; case HARDWARE: if (ip) parse_hardware_param(cfile, &ip->hw_address); else { parse_warn("hardware address parameter %s", "not allowed here."); skip_to_semi(cfile); } return; case REQUEST: config->requested_option_count = parse_option_list(cfile, config->requested_options); return; case REQUIRE: memset(config->required_options, 0, sizeof(config->required_options)); parse_option_list(cfile, config->required_options); return; case TIMEOUT: parse_lease_time(cfile, &config->timeout); return; case RETRY: parse_lease_time(cfile, &config->retry_interval); return; case SELECT_TIMEOUT: parse_lease_time(cfile, &config->select_interval); return; case REBOOT: parse_lease_time(cfile, &config->reboot_timeout); return; case BACKOFF_CUTOFF: parse_lease_time(cfile, &config->backoff_cutoff); return; case INITIAL_INTERVAL: parse_lease_time(cfile, &config->initial_interval); return; case SCRIPT: config->script_name = parse_string(cfile); return; case INTERFACE: if (ip) parse_warn("nested interface declaration."); parse_interface_declaration(cfile, config); return; case LEASE: parse_client_lease_statement(cfile, 1); return; case ALIAS: parse_client_lease_statement(cfile, 2); return; case REJECT: parse_reject_statement(cfile, config); return; default: parse_warn("expecting a statement."); skip_to_semi(cfile); break; } token = next_token(&val, cfile); if (token != SEMI) { parse_warn("semicolon expected."); skip_to_semi(cfile); } }