summaryrefslogtreecommitdiff
path: root/auth2-pubkey.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2010-05-10 11:58:03 +1000
committerDamien Miller <djm@mindrot.org>2010-05-10 11:58:03 +1000
commit30da3447d2ef3329cb0eb083cdddf84532659454 (patch)
tree02537d2355d77cc15d1bf9d266d474e660848012 /auth2-pubkey.c
parent099fc1634e1cc0f96b77a811e554bf9d796def8f (diff)
- djm@cvs.openbsd.org 2010/05/07 11:30:30
[auth-options.c auth-options.h auth.c auth.h auth2-pubkey.c] [key.c servconf.c servconf.h sshd.8 sshd_config.5] add some optional indirection to matching of principal names listed in certificates. Currently, a certificate must include the a user's name to be accepted for authentication. This change adds the ability to specify a list of certificate principal names that are acceptable. When authenticating using a CA trusted through ~/.ssh/authorized_keys, this adds a new principals="name1[,name2,...]" key option. For CAs listed through sshd_config's TrustedCAKeys option, a new config option "AuthorizedPrincipalsFile" specifies a per-user file containing the list of acceptable names. If either option is absent, the current behaviour of requiring the username to appear in principals continues to apply. These options are useful for role accounts, disjoint account namespaces and "user@realm"-style naming policies in certificates. feedback and ok markus@
Diffstat (limited to 'auth2-pubkey.c')
-rw-r--r--auth2-pubkey.c102
1 files changed, 94 insertions, 8 deletions
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 83ecd6590..6b4a99725 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-pubkey.c,v 1.23 2010/04/16 01:47:26 djm Exp $ */ 1/* $OpenBSD: auth2-pubkey.c,v 1.24 2010/05/07 11:30:29 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -57,6 +57,7 @@
57#include "monitor_wrap.h" 57#include "monitor_wrap.h"
58#include "misc.h" 58#include "misc.h"
59#include "authfile.h" 59#include "authfile.h"
60#include "match.h"
60 61
61/* import */ 62/* import */
62extern ServerOptions options; 63extern ServerOptions options;
@@ -176,6 +177,63 @@ done:
176 return authenticated; 177 return authenticated;
177} 178}
178 179
180static int
181match_principals_option(const char *principal_list, struct KeyCert *cert)
182{
183 char *result;
184 u_int i;
185
186 /* XXX percent_expand() sequences for authorized_principals? */
187
188 for (i = 0; i < cert->nprincipals; i++) {
189 if ((result = match_list(cert->principals[i],
190 principal_list, NULL)) != NULL) {
191 debug3("matched principal from key options \"%.100s\"",
192 result);
193 xfree(result);
194 return 1;
195 }
196 }
197 return 0;
198}
199
200static int
201match_principals_file(const char *file, struct passwd *pw, struct KeyCert *cert)
202{
203 FILE *f;
204 char line[SSH_MAX_PUBKEY_BYTES], *cp;
205 u_long linenum = 0;
206 u_int i;
207
208 temporarily_use_uid(pw);
209 debug("trying authorized principals file %s", file);
210 if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) {
211 restore_uid();
212 return 0;
213 }
214 while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
215 /* Skip leading whitespace, empty and comment lines. */
216 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
217 ;
218 if (!*cp || *cp == '\n' || *cp == '#')
219 continue;
220 line[strcspn(line, "\n")] = '\0';
221
222 for (i = 0; i < cert->nprincipals; i++) {
223 if (strcmp(cp, cert->principals[i]) == 0) {
224 debug3("matched principal from file \"%.100s\"",
225 cert->principals[i]);
226 fclose(f);
227 restore_uid();
228 return 1;
229 }
230 }
231 }
232 fclose(f);
233 restore_uid();
234 return 0;
235}
236
179/* return 1 if user allows given key */ 237/* return 1 if user allows given key */
180static int 238static int
181user_key_allowed2(struct passwd *pw, Key *key, char *file) 239user_key_allowed2(struct passwd *pw, Key *key, char *file)
@@ -244,13 +302,26 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
244 SSH_FP_HEX); 302 SSH_FP_HEX);
245 debug("matching CA found: file %s, line %lu, %s %s", 303 debug("matching CA found: file %s, line %lu, %s %s",
246 file, linenum, key_type(found), fp); 304 file, linenum, key_type(found), fp);
247 if (key_cert_check_authority(key, 0, 0, pw->pw_name, 305 /*
248 &reason) != 0) { 306 * If the user has specified a list of principals as
307 * a key option, then prefer that list to matching
308 * their username in the certificate principals list.
309 */
310 if (authorized_principals != NULL &&
311 !match_principals_option(authorized_principals,
312 key->cert)) {
313 reason = "Certificate does not contain an "
314 "authorized principal";
315 fail_reason:
249 xfree(fp); 316 xfree(fp);
250 error("%s", reason); 317 error("%s", reason);
251 auth_debug_add("%s", reason); 318 auth_debug_add("%s", reason);
252 continue; 319 continue;
253 } 320 }
321 if (key_cert_check_authority(key, 0, 0,
322 authorized_principals == NULL ? pw->pw_name : NULL,
323 &reason) != 0)
324 goto fail_reason;
254 if (auth_cert_options(key, pw) != 0) { 325 if (auth_cert_options(key, pw) != 0) {
255 xfree(fp); 326 xfree(fp);
256 continue; 327 continue;
@@ -284,7 +355,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
284static int 355static int
285user_cert_trusted_ca(struct passwd *pw, Key *key) 356user_cert_trusted_ca(struct passwd *pw, Key *key)
286{ 357{
287 char *ca_fp; 358 char *ca_fp, *principals_file = NULL;
288 const char *reason; 359 const char *reason;
289 int ret = 0; 360 int ret = 0;
290 361
@@ -301,11 +372,24 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
301 options.trusted_user_ca_keys); 372 options.trusted_user_ca_keys);
302 goto out; 373 goto out;
303 } 374 }
304 if (key_cert_check_authority(key, 0, 1, pw->pw_name, &reason) != 0) { 375 /*
305 error("%s", reason); 376 * If AuthorizedPrincipals is in use, then compare the certificate
306 auth_debug_add("%s", reason); 377 * principals against the names in that file rather than matching
307 goto out; 378 * against the username.
379 */
380 if ((principals_file = authorized_principals_file(pw)) != NULL) {
381 if (!match_principals_file(principals_file, pw, key->cert)) {
382 reason = "Certificate does not contain an "
383 "authorized principal";
384 fail_reason:
385 error("%s", reason);
386 auth_debug_add("%s", reason);
387 goto out;
388 }
308 } 389 }
390 if (key_cert_check_authority(key, 0, 1,
391 principals_file == NULL ? pw->pw_name : NULL, &reason) != 0)
392 goto fail_reason;
309 if (auth_cert_options(key, pw) != 0) 393 if (auth_cert_options(key, pw) != 0)
310 goto out; 394 goto out;
311 395
@@ -315,6 +399,8 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
315 ret = 1; 399 ret = 1;
316 400
317 out: 401 out:
402 if (principals_file != NULL)
403 xfree(principals_file);
318 if (ca_fp != NULL) 404 if (ca_fp != NULL)
319 xfree(ca_fp); 405 xfree(ca_fp);
320 return ret; 406 return ret;