summaryrefslogtreecommitdiff
path: root/auth2-pubkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth2-pubkey.c')
-rw-r--r--auth2-pubkey.c145
1 files changed, 128 insertions, 17 deletions
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index c4cadf4e7..35cf79c9f 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-pubkey.c,v 1.22 2010/03/10 23:27:17 djm Exp $ */ 1/* $OpenBSD: auth2-pubkey.c,v 1.26 2010/06/29 23:16:46 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,83 @@ 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(char *file, struct passwd *pw, struct KeyCert *cert)
202{
203 FILE *f;
204 char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
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. */
216 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
217 ;
218 /* Skip blank and comment lines. */
219 if ((ep = strchr(cp, '#')) != NULL)
220 *ep = '\0';
221 if (!*cp || *cp == '\n')
222 continue;
223 /* Trim trailing whitespace. */
224 ep = cp + strlen(cp) - 1;
225 while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
226 *ep-- = '\0';
227 /*
228 * If the line has internal whitespace then assume it has
229 * key options.
230 */
231 line_opts = NULL;
232 if ((ep = strrchr(cp, ' ')) != NULL ||
233 (ep = strrchr(cp, '\t')) != NULL) {
234 for (; *ep == ' ' || *ep == '\t'; ep++)
235 ;;
236 line_opts = cp;
237 cp = ep;
238 }
239 for (i = 0; i < cert->nprincipals; i++) {
240 if (strcmp(cp, cert->principals[i]) == 0) {
241 debug3("matched principal from file \"%.100s\"",
242 cert->principals[i]);
243 if (auth_parse_options(pw, line_opts,
244 file, linenum) != 1)
245 continue;
246 fclose(f);
247 restore_uid();
248 return 1;
249 }
250 }
251 }
252 fclose(f);
253 restore_uid();
254 return 0;
255}
256
179/* return 1 if user allows given key */ 257/* return 1 if user allows given key */
180static int 258static int
181user_key_allowed2(struct passwd *pw, Key *key, char *file) 259user_key_allowed2(struct passwd *pw, Key *key, char *file)
@@ -233,26 +311,39 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
233 continue; 311 continue;
234 } 312 }
235 } 313 }
236 if (auth_parse_options(pw, key_options, file, linenum) != 1) 314 if (key_is_cert(key)) {
237 continue;
238 if (key->type == KEY_RSA_CERT || key->type == KEY_DSA_CERT) {
239 if (!key_is_cert_authority)
240 continue;
241 if (!key_equal(found, key->cert->signature_key)) 315 if (!key_equal(found, key->cert->signature_key))
242 continue; 316 continue;
317 if (auth_parse_options(pw, key_options, file,
318 linenum) != 1)
319 continue;
320 if (!key_is_cert_authority)
321 continue;
243 fp = key_fingerprint(found, SSH_FP_MD5, 322 fp = key_fingerprint(found, SSH_FP_MD5,
244 SSH_FP_HEX); 323 SSH_FP_HEX);
245 debug("matching CA found: file %s, line %lu, %s %s", 324 debug("matching CA found: file %s, line %lu, %s %s",
246 file, linenum, key_type(found), fp); 325 file, linenum, key_type(found), fp);
247 if (key_cert_check_authority(key, 0, 0, pw->pw_name, 326 /*
248 &reason) != 0) { 327 * If the user has specified a list of principals as
328 * a key option, then prefer that list to matching
329 * their username in the certificate principals list.
330 */
331 if (authorized_principals != NULL &&
332 !match_principals_option(authorized_principals,
333 key->cert)) {
334 reason = "Certificate does not contain an "
335 "authorized principal";
336 fail_reason:
249 xfree(fp); 337 xfree(fp);
250 error("%s", reason); 338 error("%s", reason);
251 auth_debug_add("%s", reason); 339 auth_debug_add("%s", reason);
252 continue; 340 continue;
253 } 341 }
254 if (auth_cert_constraints(&key->cert->constraints, 342 if (key_cert_check_authority(key, 0, 0,
255 pw) != 0) { 343 authorized_principals == NULL ? pw->pw_name : NULL,
344 &reason) != 0)
345 goto fail_reason;
346 if (auth_cert_options(key, pw) != 0) {
256 xfree(fp); 347 xfree(fp);
257 continue; 348 continue;
258 } 349 }
@@ -262,7 +353,12 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
262 xfree(fp); 353 xfree(fp);
263 found_key = 1; 354 found_key = 1;
264 break; 355 break;
265 } else if (!key_is_cert_authority && key_equal(found, key)) { 356 } else if (key_equal(found, key)) {
357 if (auth_parse_options(pw, key_options, file,
358 linenum) != 1)
359 continue;
360 if (key_is_cert_authority)
361 continue;
266 found_key = 1; 362 found_key = 1;
267 debug("matching key found: file %s, line %lu", 363 debug("matching key found: file %s, line %lu",
268 file, linenum); 364 file, linenum);
@@ -285,7 +381,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
285static int 381static int
286user_cert_trusted_ca(struct passwd *pw, Key *key) 382user_cert_trusted_ca(struct passwd *pw, Key *key)
287{ 383{
288 char *ca_fp; 384 char *ca_fp, *principals_file = NULL;
289 const char *reason; 385 const char *reason;
290 int ret = 0; 386 int ret = 0;
291 387
@@ -302,12 +398,25 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
302 options.trusted_user_ca_keys); 398 options.trusted_user_ca_keys);
303 goto out; 399 goto out;
304 } 400 }
305 if (key_cert_check_authority(key, 0, 1, pw->pw_name, &reason) != 0) { 401 /*
306 error("%s", reason); 402 * If AuthorizedPrincipals is in use, then compare the certificate
307 auth_debug_add("%s", reason); 403 * principals against the names in that file rather than matching
308 goto out; 404 * against the username.
405 */
406 if ((principals_file = authorized_principals_file(pw)) != NULL) {
407 if (!match_principals_file(principals_file, pw, key->cert)) {
408 reason = "Certificate does not contain an "
409 "authorized principal";
410 fail_reason:
411 error("%s", reason);
412 auth_debug_add("%s", reason);
413 goto out;
414 }
309 } 415 }
310 if (auth_cert_constraints(&key->cert->constraints, pw) != 0) 416 if (key_cert_check_authority(key, 0, 1,
417 principals_file == NULL ? pw->pw_name : NULL, &reason) != 0)
418 goto fail_reason;
419 if (auth_cert_options(key, pw) != 0)
311 goto out; 420 goto out;
312 421
313 verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s", 422 verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s",
@@ -316,6 +425,8 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
316 ret = 1; 425 ret = 1;
317 426
318 out: 427 out:
428 if (principals_file != NULL)
429 xfree(principals_file);
319 if (ca_fp != NULL) 430 if (ca_fp != NULL)
320 xfree(ca_fp); 431 xfree(ca_fp);
321 return ret; 432 return ret;