summaryrefslogtreecommitdiff
path: root/auth-options.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2010-05-21 14:58:32 +1000
committerDamien Miller <djm@mindrot.org>2010-05-21 14:58:32 +1000
commitd0e4a8e2e0bc6fcee6cd8486fbcdffaf7d037aed (patch)
treea5e02fcbb2a55a16b877e960edd2b8f1adde8389 /auth-options.c
parent84399555f0a3c78b96c3e5a56ce9c83eaa814228 (diff)
downloadopenssh-git-d0e4a8e2e0bc6fcee6cd8486fbcdffaf7d037aed.tar.gz
- djm@cvs.openbsd.org 2010/05/20 23:46:02
[PROTOCOL.certkeys auth-options.c ssh-keygen.c] Move the permit-* options to the non-critical "extensions" field for v01 certificates. The logic is that if another implementation fails to implement them then the connection just loses features rather than fails outright. ok markus@
Diffstat (limited to 'auth-options.c')
-rw-r--r--auth-options.c282
1 files changed, 180 insertions, 102 deletions
diff --git a/auth-options.c b/auth-options.c
index 57a67ec7..a7040247 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-options.c,v 1.51 2010/05/07 11:30:29 djm Exp $ */
+/* $OpenBSD: auth-options.c,v 1.52 2010/05/20 23:46:02 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -417,32 +417,31 @@ bad_option:
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(Key *k, struct passwd *pw)
+#define OPTIONS_CRITICAL 1
+#define OPTIONS_EXTENSIONS 2
+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;
-
- 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;
+ int ret = -1, found;
buffer_init(&data);
/* Make copy to avoid altering original */
buffer_init(&c);
- buffer_append(&c,
- buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical));
+ buffer_append(&c, optblob, optblob_len);
while (buffer_len(&c) > 0) {
if ((name = buffer_get_string_ret(&c, &nlen)) == NULL ||
@@ -451,90 +450,114 @@ auth_cert_options(Key *k, struct passwd *pw)
goto out;
}
buffer_append(&data, data_blob, dlen);
- debug3("found certificate constraint \"%.100s\" len %u",
+ debug3("found certificate option \"%.100s\" len %u",
name, dlen);
if (strlen(name) != nlen) {
error("Certificate constraint name contains \\0");
goto out;
}
- if (strcmp(name, "permit-X11-forwarding") == 0)
- cert_no_x11_forwarding_flag = 0;
- else if (strcmp(name, "permit-agent-forwarding") == 0)
- cert_no_agent_forwarding_flag = 0;
- else if (strcmp(name, "permit-port-forwarding") == 0)
- cert_no_port_forwarding_flag = 0;
- else if (strcmp(name, "permit-pty") == 0)
- cert_no_pty_flag = 0;
- else if (strcmp(name, "permit-user-rc") == 0)
- cert_no_user_rc = 0;
- else if (strcmp(name, "force-command") == 0) {
- char *command = buffer_get_string_ret(&data, &clen);
-
- if (command == 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;
- } 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;
+ 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 (cert_source_address_done++) {
- error("Certificate has multiple "
- "source-address options");
- xfree(allowed);
- goto out;
+ }
+ if (!found && (which & OPTIONS_CRITICAL) != 0) {
+ 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;
}
- 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;
+ if (strcmp(name, "source-address") == 0) {
+ if ((allowed = buffer_get_string_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;
}
- } else {
- error("Certificate constraint \"%s\" is not supported",
- name);
- goto out;
}
- if (buffer_len(&data) != 0) {
- error("Certificate constraint \"%s\" corrupt "
+ 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;
}
@@ -543,10 +566,73 @@ auth_cert_options(Key *k, struct passwd *pw)
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;
+}
+
+/*
+ * 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;
@@ -558,14 +644,6 @@ auth_cert_options(Key *k, struct passwd *pw)
xfree(forced_command);
forced_command = cert_forced_command;
}
-
- out:
- if (name != NULL)
- xfree(name);
- if (data_blob != NULL)
- xfree(data_blob);
- buffer_free(&data);
- buffer_free(&c);
- return ret;
+ return 0;
}