char * buffer_get_cstring(Buffer *buffer, u_int *length_ptr) { char *ret; if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL) fatal("%s: buffer error", __func__); return ret; }
static int parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, u_int which, int crit, int *cert_no_port_forwarding_flag, int *cert_no_agent_forwarding_flag, int *cert_no_x11_forwarding_flag, int *cert_no_pty_flag, int *cert_no_user_rc, char **cert_forced_command, int *cert_source_address_done) { char *command, *allowed; const char *remote_ip; u_char *name = NULL, *data_blob = NULL; u_int nlen, dlen, clen; Buffer c, data; int ret = -1, found; buffer_init(&data); /* Make copy to avoid altering original */ buffer_init(&c); buffer_append(&c, optblob, optblob_len); while (buffer_len(&c) > 0) { if ((name = buffer_get_cstring_ret(&c, &nlen)) == NULL || (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) { error("Certificate options corrupt"); goto out; } buffer_append(&data, data_blob, dlen); debug3("found certificate option \"%.100s\" len %u", name, dlen); if (strlen(name) != nlen) { error("Certificate constraint name contains \\0"); goto out; } found = 0; if ((which & OPTIONS_EXTENSIONS) != 0) { if (strcmp(name, "permit-X11-forwarding") == 0) { *cert_no_x11_forwarding_flag = 0; found = 1; } else if (strcmp(name, "permit-agent-forwarding") == 0) { *cert_no_agent_forwarding_flag = 0; found = 1; } else if (strcmp(name, "permit-port-forwarding") == 0) { *cert_no_port_forwarding_flag = 0; found = 1; } else if (strcmp(name, "permit-pty") == 0) { *cert_no_pty_flag = 0; found = 1; } else if (strcmp(name, "permit-user-rc") == 0) { *cert_no_user_rc = 0; found = 1; } } if (!found && (which & OPTIONS_CRITICAL) != 0) { if (strcmp(name, "force-command") == 0) { if ((command = buffer_get_cstring_ret(&data, &clen)) == NULL) { error("Certificate constraint \"%s\" " "corrupt", name); goto out; } if (strlen(command) != clen) { error("force-command constraint " "contains \\0"); goto out; } if (*cert_forced_command != NULL) { error("Certificate has multiple " "force-command options"); xfree(command); goto out; } *cert_forced_command = command; found = 1; } if (strcmp(name, "source-address") == 0) { if ((allowed = buffer_get_cstring_ret(&data, &clen)) == NULL) { error("Certificate constraint " "\"%s\" corrupt", name); goto out; } if (strlen(allowed) != clen) { error("source-address constraint " "contains \\0"); goto out; } if ((*cert_source_address_done)++) { error("Certificate has multiple " "source-address options"); xfree(allowed); goto out; } remote_ip = get_remote_ipaddr(); switch (addr_match_cidr_list(remote_ip, allowed)) { case 1: /* accepted */ xfree(allowed); break; case 0: /* no match */ logit("Authentication tried for %.100s " "with valid certificate but not " "from a permitted host " "(ip=%.200s).", pw->pw_name, remote_ip); auth_debug_add("Your address '%.200s' " "is not permitted to use this " "certificate for login.", remote_ip); xfree(allowed); goto out; case -1: error("Certificate source-address " "contents invalid"); xfree(allowed); goto out; } found = 1; } } if (!found) { if (crit) { error("Certificate critical option \"%s\" " "is not supported", name); goto out; } else { logit("Certificate extension \"%s\" " "is not supported", name); } } else if (buffer_len(&data) != 0) { error("Certificate option \"%s\" corrupt " "(extra data)", name); goto out; } buffer_clear(&data); xfree(name); xfree(data_blob); name = data_blob = NULL; } /* successfully parsed all options */ ret = 0; out: if (ret != 0 && cert_forced_command != NULL && *cert_forced_command != NULL) { xfree(*cert_forced_command); *cert_forced_command = NULL; } if (name != NULL) xfree(name); if (data_blob != NULL) xfree(data_blob); buffer_free(&data); buffer_free(&c); return ret; }