version 1.64, 2014/07/15 15:54:14 |
version 1.65, 2015/01/14 10:30:34 |
|
|
#include <stdio.h> |
#include <stdio.h> |
#include <stdarg.h> |
#include <stdarg.h> |
|
|
|
#include "key.h" /* XXX for typedef */ |
|
#include "buffer.h" /* XXX for typedef */ |
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "match.h" |
#include "match.h" |
|
#include "ssherr.h" |
#include "log.h" |
#include "log.h" |
#include "canohost.h" |
#include "canohost.h" |
#include "buffer.h" |
#include "sshbuf.h" |
#include "misc.h" |
#include "misc.h" |
#include "channels.h" |
#include "channels.h" |
#include "servconf.h" |
#include "servconf.h" |
#include "key.h" |
#include "sshkey.h" |
#include "auth-options.h" |
#include "auth-options.h" |
#include "hostfile.h" |
#include "hostfile.h" |
#include "auth.h" |
#include "auth.h" |
|
|
#define OPTIONS_CRITICAL 1 |
#define OPTIONS_CRITICAL 1 |
#define OPTIONS_EXTENSIONS 2 |
#define OPTIONS_EXTENSIONS 2 |
static int |
static int |
parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, |
parse_option_list(struct sshbuf *oblob, struct passwd *pw, |
u_int which, int crit, |
u_int which, int crit, |
int *cert_no_port_forwarding_flag, |
int *cert_no_port_forwarding_flag, |
int *cert_no_agent_forwarding_flag, |
int *cert_no_agent_forwarding_flag, |
|
|
char *command, *allowed; |
char *command, *allowed; |
const char *remote_ip; |
const char *remote_ip; |
char *name = NULL; |
char *name = NULL; |
u_char *data_blob = NULL; |
struct sshbuf *c = NULL, *data = NULL; |
u_int nlen, dlen, clen; |
int r, ret = -1, result, found; |
Buffer c, data; |
|
int ret = -1, result, found; |
|
|
|
buffer_init(&data); |
if ((c = sshbuf_fromb(oblob)) == NULL) { |
|
error("%s: sshbuf_fromb failed", __func__); |
|
goto out; |
|
} |
|
|
/* Make copy to avoid altering original */ |
while (sshbuf_len(c) > 0) { |
buffer_init(&c); |
sshbuf_free(data); |
buffer_append(&c, optblob, optblob_len); |
data = NULL; |
|
if ((r = sshbuf_get_cstring(c, &name, NULL)) != 0 || |
while (buffer_len(&c) > 0) { |
(r = sshbuf_froms(c, &data)) != 0) { |
if ((name = buffer_get_cstring_ret(&c, &nlen)) == NULL || |
error("Unable to parse certificate options: %s", |
(data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) { |
ssh_err(r)); |
error("Certificate options corrupt"); |
|
goto out; |
goto out; |
} |
} |
buffer_append(&data, data_blob, dlen); |
debug3("found certificate option \"%.100s\" len %zu", |
debug3("found certificate option \"%.100s\" len %u", |
name, sshbuf_len(data)); |
name, dlen); |
|
found = 0; |
found = 0; |
if ((which & OPTIONS_EXTENSIONS) != 0) { |
if ((which & OPTIONS_EXTENSIONS) != 0) { |
if (strcmp(name, "permit-X11-forwarding") == 0) { |
if (strcmp(name, "permit-X11-forwarding") == 0) { |
|
|
} |
} |
if (!found && (which & OPTIONS_CRITICAL) != 0) { |
if (!found && (which & OPTIONS_CRITICAL) != 0) { |
if (strcmp(name, "force-command") == 0) { |
if (strcmp(name, "force-command") == 0) { |
if ((command = buffer_get_cstring_ret(&data, |
if ((r = sshbuf_get_cstring(data, &command, |
&clen)) == NULL) { |
NULL)) != 0) { |
error("Certificate constraint \"%s\" " |
error("Unable to parse \"%s\" " |
"corrupt", name); |
"section: %s", name, ssh_err(r)); |
goto out; |
goto out; |
} |
} |
if (*cert_forced_command != NULL) { |
if (*cert_forced_command != NULL) { |
|
|
found = 1; |
found = 1; |
} |
} |
if (strcmp(name, "source-address") == 0) { |
if (strcmp(name, "source-address") == 0) { |
if ((allowed = buffer_get_cstring_ret(&data, |
if ((r = sshbuf_get_cstring(data, &allowed, |
&clen)) == NULL) { |
NULL)) != 0) { |
error("Certificate constraint " |
error("Unable to parse \"%s\" " |
"\"%s\" corrupt", name); |
"section: %s", name, ssh_err(r)); |
goto out; |
goto out; |
} |
} |
if ((*cert_source_address_done)++) { |
if ((*cert_source_address_done)++) { |
|
|
logit("Certificate extension \"%s\" " |
logit("Certificate extension \"%s\" " |
"is not supported", name); |
"is not supported", name); |
} |
} |
} else if (buffer_len(&data) != 0) { |
} else if (sshbuf_len(data) != 0) { |
error("Certificate option \"%s\" corrupt " |
error("Certificate option \"%s\" corrupt " |
"(extra data)", name); |
"(extra data)", name); |
goto out; |
goto out; |
} |
} |
buffer_clear(&data); |
|
free(name); |
free(name); |
free(data_blob); |
|
name = NULL; |
name = NULL; |
data_blob = NULL; |
|
} |
} |
/* successfully parsed all options */ |
/* successfully parsed all options */ |
ret = 0; |
ret = 0; |
|
|
} |
} |
if (name != NULL) |
if (name != NULL) |
free(name); |
free(name); |
if (data_blob != NULL) |
sshbuf_free(data); |
free(data_blob); |
sshbuf_free(c); |
buffer_free(&data); |
|
buffer_free(&c); |
|
return ret; |
return ret; |
} |
} |
|
|
|
|
* options so this must be called after auth_parse_options(). |
* options so this must be called after auth_parse_options(). |
*/ |
*/ |
int |
int |
auth_cert_options(Key *k, struct passwd *pw) |
auth_cert_options(struct sshkey *k, struct passwd *pw) |
{ |
{ |
int cert_no_port_forwarding_flag = 1; |
int cert_no_port_forwarding_flag = 1; |
int cert_no_agent_forwarding_flag = 1; |
int cert_no_agent_forwarding_flag = 1; |
|
|
char *cert_forced_command = NULL; |
char *cert_forced_command = NULL; |
int cert_source_address_done = 0; |
int cert_source_address_done = 0; |
|
|
if (key_cert_is_legacy(k)) { |
if (sshkey_cert_is_legacy(k)) { |
/* All options are in the one field for v00 certs */ |
/* All options are in the one field for v00 certs */ |
if (parse_option_list(buffer_ptr(k->cert->critical), |
if (parse_option_list(k->cert->critical, pw, |
buffer_len(k->cert->critical), pw, |
|
OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1, |
OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1, |
&cert_no_port_forwarding_flag, |
&cert_no_port_forwarding_flag, |
&cert_no_agent_forwarding_flag, |
&cert_no_agent_forwarding_flag, |
|
|
return -1; |
return -1; |
} else { |
} else { |
/* Separate options and extensions for v01 certs */ |
/* Separate options and extensions for v01 certs */ |
if (parse_option_list(buffer_ptr(k->cert->critical), |
if (parse_option_list(k->cert->critical, pw, |
buffer_len(k->cert->critical), pw, |
|
OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, |
OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, |
&cert_forced_command, |
&cert_forced_command, |
&cert_source_address_done) == -1) |
&cert_source_address_done) == -1) |
return -1; |
return -1; |
if (parse_option_list(buffer_ptr(k->cert->extensions), |
if (parse_option_list(k->cert->extensions, pw, |
buffer_len(k->cert->extensions), pw, |
|
OPTIONS_EXTENSIONS, 1, |
OPTIONS_EXTENSIONS, 1, |
&cert_no_port_forwarding_flag, |
&cert_no_port_forwarding_flag, |
&cert_no_agent_forwarding_flag, |
&cert_no_agent_forwarding_flag, |