version 1.51, 2010/05/07 11:30:29 |
version 1.52, 2010/05/20 23:46:02 |
|
|
return 0; |
return 0; |
} |
} |
|
|
/* |
#define OPTIONS_CRITICAL 1 |
* Set options from critical certificate options. These supersede user key |
#define OPTIONS_EXTENSIONS 2 |
* options so this must be called after auth_parse_options(). |
static int |
*/ |
parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, |
int |
u_int which, int crit, |
auth_cert_options(Key *k, struct passwd *pw) |
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_char *name = NULL, *data_blob = NULL; |
u_int nlen, dlen, clen; |
u_int nlen, dlen, clen; |
Buffer c, data; |
Buffer c, data; |
int ret = -1; |
int ret = -1, found; |
|
|
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; |
|
|
|
buffer_init(&data); |
buffer_init(&data); |
|
|
/* Make copy to avoid altering original */ |
/* Make copy to avoid altering original */ |
buffer_init(&c); |
buffer_init(&c); |
buffer_append(&c, |
buffer_append(&c, optblob, optblob_len); |
buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical)); |
|
|
|
while (buffer_len(&c) > 0) { |
while (buffer_len(&c) > 0) { |
if ((name = buffer_get_string_ret(&c, &nlen)) == NULL || |
if ((name = buffer_get_string_ret(&c, &nlen)) == NULL || |
|
|
goto out; |
goto out; |
} |
} |
buffer_append(&data, data_blob, dlen); |
buffer_append(&data, data_blob, dlen); |
debug3("found certificate constraint \"%.100s\" len %u", |
debug3("found certificate option \"%.100s\" len %u", |
name, dlen); |
name, dlen); |
if (strlen(name) != nlen) { |
if (strlen(name) != nlen) { |
error("Certificate constraint name contains \\0"); |
error("Certificate constraint name contains \\0"); |
goto out; |
goto out; |
} |
} |
if (strcmp(name, "permit-X11-forwarding") == 0) |
found = 0; |
cert_no_x11_forwarding_flag = 0; |
if ((which & OPTIONS_EXTENSIONS) != 0) { |
else if (strcmp(name, "permit-agent-forwarding") == 0) |
if (strcmp(name, "permit-X11-forwarding") == 0) { |
cert_no_agent_forwarding_flag = 0; |
*cert_no_x11_forwarding_flag = 0; |
else if (strcmp(name, "permit-port-forwarding") == 0) |
found = 1; |
cert_no_port_forwarding_flag = 0; |
} else if (strcmp(name, |
else if (strcmp(name, "permit-pty") == 0) |
"permit-agent-forwarding") == 0) { |
cert_no_pty_flag = 0; |
*cert_no_agent_forwarding_flag = 0; |
else if (strcmp(name, "permit-user-rc") == 0) |
found = 1; |
cert_no_user_rc = 0; |
} else if (strcmp(name, |
else if (strcmp(name, "force-command") == 0) { |
"permit-port-forwarding") == 0) { |
char *command = buffer_get_string_ret(&data, &clen); |
*cert_no_port_forwarding_flag = 0; |
|
found = 1; |
if (command == NULL) { |
} else if (strcmp(name, "permit-pty") == 0) { |
error("Certificate constraint \"%s\" corrupt", |
*cert_no_pty_flag = 0; |
name); |
found = 1; |
goto out; |
} else if (strcmp(name, "permit-user-rc") == 0) { |
|
*cert_no_user_rc = 0; |
|
found = 1; |
} |
} |
if (strlen(command) != clen) { |
} |
error("force-command constraint contains \\0"); |
if (!found && (which & OPTIONS_CRITICAL) != 0) { |
goto out; |
if (strcmp(name, "force-command") == 0) { |
|
if ((command = buffer_get_string_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 (cert_forced_command != NULL) { |
if (strcmp(name, "source-address") == 0) { |
error("Certificate has multiple " |
if ((allowed = buffer_get_string_ret(&data, |
"force-command options"); |
&clen)) == NULL) { |
xfree(command); |
error("Certificate constraint " |
goto out; |
"\"%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; |
} |
} |
cert_forced_command = command; |
|
} else if (strcmp(name, "source-address") == 0) { |
|
char *allowed = buffer_get_string_ret(&data, &clen); |
|
const char *remote_ip = get_remote_ipaddr(); |
|
|
|
if (allowed == 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; |
|
} |
|
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; |
|
} |
|
} else { |
|
error("Certificate constraint \"%s\" is not supported", |
|
name); |
|
goto out; |
|
} |
} |
|
|
if (buffer_len(&data) != 0) { |
if (!found) { |
error("Certificate constraint \"%s\" corrupt " |
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); |
"(extra data)", name); |
goto out; |
goto out; |
} |
} |
|
|
xfree(data_blob); |
xfree(data_blob); |
name = data_blob = NULL; |
name = data_blob = NULL; |
} |
} |
|
|
/* successfully parsed all options */ |
/* successfully parsed all options */ |
ret = 0; |
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; |
|
} |
|
|
|
/* |
|
* 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_port_forwarding_flag |= cert_no_port_forwarding_flag; |
no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; |
no_agent_forwarding_flag |= cert_no_agent_forwarding_flag; |
no_x11_forwarding_flag |= cert_no_x11_forwarding_flag; |
no_x11_forwarding_flag |= cert_no_x11_forwarding_flag; |
|
|
xfree(forced_command); |
xfree(forced_command); |
forced_command = cert_forced_command; |
forced_command = cert_forced_command; |
} |
} |
|
return 0; |
out: |
|
if (name != NULL) |
|
xfree(name); |
|
if (data_blob != NULL) |
|
xfree(data_blob); |
|
buffer_free(&data); |
|
buffer_free(&c); |
|
return ret; |
|
} |
} |
|
|