View | Details | Raw Unified | Return to bug 1927
Collapse All | Expand All

(-)a/auth.c (+13 lines)
Lines 406-411 authorized_principals_file(struct passwd *pw) Link Here
406
	return expand_authorized_keys(options.authorized_principals_file, pw);
406
	return expand_authorized_keys(options.authorized_principals_file, pw);
407
}
407
}
408
408
409
char *
410
authorized_credentials_file(struct passwd *pw)
411
{
412
	return expand_authorized_keys(options.authorized_credentials_file, pw);
413
}
414
409
/* return ok if key exists in sysfile or userfile */
415
/* return ok if key exists in sysfile or userfile */
410
HostStatus
416
HostStatus
411
check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
417
check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
Lines 600-605 auth_openprincipals(const char *file, struct passwd *pw, int strict_modes) Link Here
600
	    "authorized principals");
606
	    "authorized principals");
601
}
607
}
602
608
609
FILE *
610
auth_opencredentialfile(const char *file, struct passwd *pw, int strict_modes)
611
{
612
	return auth_openfile(file, pw, strict_modes, 0,
613
	    "authorized credentials");
614
}
615
603
struct passwd *
616
struct passwd *
604
getpwnamallow(const char *user)
617
getpwnamallow(const char *user)
605
{
618
{
(-)a/auth.h (+2 lines)
Lines 192-200 void abandon_challenge_response(Authctxt *); Link Here
192
192
193
char	*expand_authorized_keys(const char *, struct passwd *pw);
193
char	*expand_authorized_keys(const char *, struct passwd *pw);
194
char	*authorized_principals_file(struct passwd *);
194
char	*authorized_principals_file(struct passwd *);
195
char	*authorized_credentials_file(struct passwd *);
195
196
196
FILE	*auth_openkeyfile(const char *, struct passwd *, int);
197
FILE	*auth_openkeyfile(const char *, struct passwd *, int);
197
FILE	*auth_openprincipals(const char *, struct passwd *, int);
198
FILE	*auth_openprincipals(const char *, struct passwd *, int);
199
FILE	*auth_opencredentialfile(const char *, struct passwd *, int);
198
int	 auth_key_is_revoked(Key *);
200
int	 auth_key_is_revoked(Key *);
199
201
200
HostStatus
202
HostStatus
(-)a/auth2-gss.c (-4 / +9 lines)
Lines 43-48 Link Here
43
#include "misc.h"
43
#include "misc.h"
44
#include "servconf.h"
44
#include "servconf.h"
45
#include "packet.h"
45
#include "packet.h"
46
#include "auth-options.h"
46
#include "ssh-gss.h"
47
#include "ssh-gss.h"
47
#include "monitor_wrap.h"
48
#include "monitor_wrap.h"
48
49
Lines 238-244 input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) Link Here
238
239
239
	packet_check_eom();
240
	packet_check_eom();
240
241
241
	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
242
	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt));
243
	if (authenticated != 1)
244
		auth_clear_options();
242
245
243
	authctxt->postponed = 0;
246
	authctxt->postponed = 0;
244
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
247
	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
Lines 273-281 input_gssapi_mic(int type, u_int32_t plen, void *ctxt) Link Here
273
	gssbuf.value = buffer_ptr(&b);
276
	gssbuf.value = buffer_ptr(&b);
274
	gssbuf.length = buffer_len(&b);
277
	gssbuf.length = buffer_len(&b);
275
278
276
	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
279
	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) {
277
		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
280
		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt));
278
	else
281
		if (authenticated != 1)
282
			auth_clear_options();
283
	} else
279
		logit("GSSAPI MIC check failed");
284
		logit("GSSAPI MIC check failed");
280
285
281
	buffer_free(&b);
286
	buffer_free(&b);
(-)a/gss-serv.c (-2 / +194 lines)
Lines 33-45 Link Here
33
#include <stdarg.h>
33
#include <stdarg.h>
34
#include <string.h>
34
#include <string.h>
35
#include <unistd.h>
35
#include <unistd.h>
36
#include <krb5.h>
36
37
37
#include "openbsd-compat/sys-queue.h"
38
#include "openbsd-compat/sys-queue.h"
38
#include "xmalloc.h"
39
#include "xmalloc.h"
40
#include "ssh.h"
39
#include "buffer.h"
41
#include "buffer.h"
42
#include "log.h"
43
#include "misc.h"
44
#include "servconf.h"
40
#include "key.h"
45
#include "key.h"
41
#include "hostfile.h"
46
#include "hostfile.h"
42
#include "auth.h"
47
#include "auth.h"
48
#include "uidswap.h"
49
#include "auth-options.h"
43
#include "log.h"
50
#include "log.h"
44
#include "channels.h"
51
#include "channels.h"
45
#include "session.h"
52
#include "session.h"
Lines 47-52 Link Here
47
54
48
#include "ssh-gss.h"
55
#include "ssh-gss.h"
49
56
57
extern ServerOptions options;
58
50
static ssh_gssapi_client gssapi_client =
59
static ssh_gssapi_client gssapi_client =
51
    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
60
    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
52
    GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}};
61
    GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}};
Lines 345-354 ssh_gssapi_do_child(char ***envp, u_int *envsizep) Link Here
345
	}
354
	}
346
}
355
}
347
356
357
static int
358
credential_read(krb5_context context, krb5_principal *princ, char **cpp)
359
{
360
	char *cp;
361
	char *name;
362
	size_t len;
363
	krb5_error_code retval;
364
	cp = *cpp;
365
366
	len = strcspn(cp, " \t\n#");
367
	if (len == 0)
368
		return 0;
369
	name = strndup(cp, len);
370
	if (name == NULL)
371
		return 0;
372
	logit("%s(): cred \"%s\"", __func__, name);
373
	retval = krb5_parse_name_flags(context, name,
374
			KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, princ);
375
	if (retval) {
376
		debug("krb5_parse_name(\"%s\"): %.100s",
377
			name, krb5_get_err_text(context, retval));
378
		free(name);
379
		return 0;
380
	}
381
	*cpp += len;
382
383
	free(name);
384
	return 1;
385
}
386
387
static int
388
user_credential_allowed(Authctxt *authctxt, char *cred)
389
{
390
	char _line[SSH_MAX_PUBKEY_BYTES];
391
	krb5_context context = NULL;
392
	krb5_principal sprinc = NULL, aprinc = NULL;
393
	krb5_error_code retval;
394
	char *file;
395
	FILE *f;
396
	struct passwd *pw = authctxt->pw;
397
	int found_credential = 0;
398
	u_long linenum = 0;
399
	char *line = NULL;
400
	const char *sp_name = NULL, *sp_inst = NULL, *sp_realm = NULL;
401
402
	/* Temporarily use the user's uid. */
403
	temporarily_use_uid(pw);
404
405
	retval = krb5_init_context(&context);
406
	if (retval) {
407
		logit("%s: krb5_init_context(): %.100s", __func__,
408
			krb5_get_err_text(context, retval));
409
		restore_uid();
410
		return 0;
411
	}
412
413
	/* Session Principal */
414
	retval = krb5_parse_name_flags(context, cred,
415
			KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, &sprinc);
416
	if (retval) {
417
		logit("%s: krb5_parse_name(\"%s\"): %.100s", __func__,
418
			cred, krb5_get_err_text(context, retval));
419
		krb5_free_context(context);
420
		restore_uid();
421
		return 0;
422
	}
423
424
#ifdef HAVE_KRB5_PRINCIPAL_GET
425
	sp_name = krb5_principal_get_comp_string(context, sprinc, 0);
426
	sp_inst = krb5_principal_get_comp_string(context, sprinc, 1);
427
	sp_realm = krb5_principal_get_realm(context, sprinc);
428
#else
429
	krb5_data *tmp;
430
431
	tmp = krb5_princ_component(context, sprinc, 0);
432
	if (tmp)
433
		sp_name = tmp->data;
434
	tmp = krb5_princ_component(context, sprinc, 0);
435
	if (tmp)
436
		sp_inst = tmp->data;
437
	tmp = krb5_princ_realm(context, sprinc);
438
	if (tmp)
439
		sp_realm = tmp->data;
440
#endif
441
442
	logit("%s: %s/%s@%s", __func__, sp_name, sp_inst, sp_realm);
443
444
	file = authorized_credentials_file(pw);
445
	debug("trying allowed credentials file %s", file);
446
447
	f = auth_opencredentialfile(file, pw, options.strict_modes);
448
	if (!f) {
449
		krb5_free_principal(context, sprinc);
450
		krb5_free_context(context);
451
		restore_uid();
452
		return 0;
453
	}
454
455
	found_credential = 0;
456
	while (read_keyfile_line(f, file, _line, sizeof(_line), &linenum) != -1) {
457
		char *cp, *cred_options = NULL;
458
		int quoted = 0;
459
		int len = 0;
460
461
		if (line)
462
			free(line);
463
		line = percent_expand(_line,
464
			"c", cred,
465
			"h", pw->pw_dir,
466
			"u", pw->pw_name,
467
			"n", sp_name ? sp_name : "NONAME",
468
			"i", sp_inst ? sp_inst : "NOINST",
469
			"r", sp_realm ? sp_realm : "NOREALM",
470
			(char *)NULL);
471
472
		debug("original line: %s", _line);
473
		debug("expanded line: %s", line);
474
475
		auth_clear_options();
476
477
		/* Skip leading whitespace, empty and comment lines. */
478
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
479
			;
480
		if (!*cp || *cp == '\n' || *cp == '#')
481
			continue;
482
483
		cred_options = cp;
484
		for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
485
			if (*cp == '\\' && cp[1] == '"')
486
				cp++;	/* Skip both */
487
			else if (*cp == '"')
488
				quoted = !quoted;
489
		}
490
491
		if (*cp == '\n' || *cp == '\0') { /* No options, rewind */
492
			cp = cred_options;
493
			cred_options = NULL;
494
		} else {
495
			len = cp - cred_options;
496
			/* Skip remaining whitespace. */
497
			for (; *cp == ' ' || *cp == '\t'; cp++)
498
				;
499
		}
500
		debug("%lu: cred: \"%s\"", linenum, cp);
501
		if (cred_options)
502
			debug("%lu: options: \"%.*s\"",
503
				linenum, len, cred_options);
504
505
506
		if (credential_read(context, &aprinc, &cp) != 1) {
507
			debug2("%s: advance: '%s'", __func__, cp);
508
			continue;
509
		}
510
		debug("%lu: options \"%.*s\"", linenum, len, cred_options);
511
512
		if (auth_parse_options(pw, cred_options, file, linenum) != 1)
513
			continue;
514
515
		if (krb5_principal_compare(context, sprinc, aprinc)) {
516
			found_credential = 1;
517
			debug("matching credential found: file %s, line %lu",
518
				file, linenum);
519
			break;
520
		}
521
	}
522
	if (sprinc)
523
		krb5_free_principal(context, sprinc);
524
	if (aprinc)
525
		krb5_free_principal(context, aprinc);
526
	if (context)
527
		krb5_free_context(context);
528
	restore_uid();
529
	fclose(f);
530
	if (line)
531
		free(line);
532
	if (!found_credential)
533
		debug2("credential not found");
534
	return found_credential;
535
}
536
348
/* Privileged */
537
/* Privileged */
349
int
538
int
350
ssh_gssapi_userok(char *user)
539
ssh_gssapi_userok(Authctxt *authctxt)
351
{
540
{
541
	char *user = authctxt->user;
352
	OM_uint32 lmin;
542
	OM_uint32 lmin;
353
543
354
	if (gssapi_client.exportedname.length == 0 ||
544
	if (gssapi_client.exportedname.length == 0 ||
Lines 357-363 ssh_gssapi_userok(char *user) Link Here
357
		return 0;
547
		return 0;
358
	}
548
	}
359
	if (gssapi_client.mech && gssapi_client.mech->userok)
549
	if (gssapi_client.mech && gssapi_client.mech->userok)
360
		if ((*gssapi_client.mech->userok)(&gssapi_client, user))
550
		if (user_credential_allowed(authctxt,
551
			(char *)gssapi_client.displayname.value) ||
552
		    (*gssapi_client.mech->userok)(&gssapi_client, user))
361
			return 1;
553
			return 1;
362
		else {
554
		else {
363
			/* Destroy delegated credentials if userok fails */
555
			/* Destroy delegated credentials if userok fails */
(-)a/monitor.c (-1 / +1 lines)
Lines 2040-2046 mm_answer_gss_userok(int sock, Buffer *m) Link Here
2040
{
2040
{
2041
	int authenticated;
2041
	int authenticated;
2042
2042
2043
	authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
2043
	authenticated = authctxt->valid && ssh_gssapi_userok(authctxt);
2044
2044
2045
	buffer_clear(m);
2045
	buffer_clear(m);
2046
	buffer_put_int(m, authenticated);
2046
	buffer_put_int(m, authenticated);
(-)a/monitor_wrap.c (-1 / +1 lines)
Lines 1068-1074 mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) Link Here
1068
}
1068
}
1069
1069
1070
int
1070
int
1071
mm_ssh_gssapi_userok(char *user)
1071
mm_ssh_gssapi_userok(Authctxt *authctxt)
1072
{
1072
{
1073
	Buffer m;
1073
	Buffer m;
1074
	int authenticated = 0;
1074
	int authenticated = 0;
(-)a/monitor_wrap.h (-1 / +1 lines)
Lines 58-64 BIGNUM *mm_auth_rsa_generate_challenge(Key *); Link Here
58
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
58
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
59
OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
59
OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
60
   gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
60
   gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
61
int mm_ssh_gssapi_userok(char *user);
61
int mm_ssh_gssapi_userok(struct Authctxt *);
62
OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
62
OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
63
#endif
63
#endif
64
64
(-)a/pathnames.h (+6 lines)
Lines 102-107 Link Here
102
#define _PATH_SSH_USER_PERMITTED_KEYS2	_PATH_SSH_USER_DIR "/authorized_keys2"
102
#define _PATH_SSH_USER_PERMITTED_KEYS2	_PATH_SSH_USER_DIR "/authorized_keys2"
103
103
104
/*
104
/*
105
 * As above but containing a one per line list of credentials with
106
 * options.
107
 */
108
#define _PATH_SSH_USER_PERMITTED_CREDENTIALS	".ssh/authorized_credentials"
109
110
/*
105
 * Per-user and system-wide ssh "rc" files.  These files are executed with
111
 * Per-user and system-wide ssh "rc" files.  These files are executed with
106
 * /bin/sh before starting the shell or command if they exist.  They will be
112
 * /bin/sh before starting the shell or command if they exist.  They will be
107
 * passed "proto cookie" as arguments if X11 forwarding with spoofing is in
113
 * passed "proto cookie" as arguments if X11 forwarding with spoofing is in
(-)a/servconf.c (-1 / +14 lines)
Lines 159-164 initialize_server_options(ServerOptions *options) Link Here
159
	options->revoked_keys_file = NULL;
159
	options->revoked_keys_file = NULL;
160
	options->trusted_user_ca_keys = NULL;
160
	options->trusted_user_ca_keys = NULL;
161
	options->authorized_principals_file = NULL;
161
	options->authorized_principals_file = NULL;
162
	options->authorized_credentials_file = NULL;
162
	options->ip_qos_interactive = -1;
163
	options->ip_qos_interactive = -1;
163
	options->ip_qos_bulk = -1;
164
	options->ip_qos_bulk = -1;
164
	options->version_addendum = NULL;
165
	options->version_addendum = NULL;
Lines 321-326 fill_default_server_options(ServerOptions *options) Link Here
321
	}
322
	}
322
	if (options->permit_tun == -1)
323
	if (options->permit_tun == -1)
323
		options->permit_tun = SSH_TUNMODE_NO;
324
		options->permit_tun = SSH_TUNMODE_NO;
325
	if (options->authorized_credentials_file == NULL)
326
		options->authorized_credentials_file = 
327
			xstrdup(_PATH_SSH_USER_PERMITTED_CREDENTIALS);
324
	if (options->ip_qos_interactive == -1)
328
	if (options->ip_qos_interactive == -1)
325
		options->ip_qos_interactive = IPTOS_LOWDELAY;
329
		options->ip_qos_interactive = IPTOS_LOWDELAY;
326
	if (options->ip_qos_bulk == -1)
330
	if (options->ip_qos_bulk == -1)
Lines 396-401 typedef enum { Link Here
396
	sUsePrivilegeSeparation, sAllowAgentForwarding,
400
	sUsePrivilegeSeparation, sAllowAgentForwarding,
397
	sHostCertificate,
401
	sHostCertificate,
398
	sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
402
	sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
403
	sAuthorizedCredentialsFile,
399
	sKexAlgorithms, sIPQoS, sVersionAddendum,
404
	sKexAlgorithms, sIPQoS, sVersionAddendum,
400
	sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
405
	sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
401
	sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
406
	sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
Lines 524-529 static struct { Link Here
524
	{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
529
	{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
525
	{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
530
	{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
526
	{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
531
	{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
532
	{ "authorizedcredentialsfile", sAuthorizedCredentialsFile, SSHCFG_ALL },
527
	{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
533
	{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
528
	{ "ipqos", sIPQoS, SSHCFG_ALL },
534
	{ "ipqos", sIPQoS, SSHCFG_ALL },
529
	{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
535
	{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
Lines 1508-1514 process_server_config_line(ServerOptions *options, char *line, Link Here
1508
		return 0;
1514
		return 0;
1509
1515
1510
	case sAuthorizedPrincipalsFile:
1516
	case sAuthorizedPrincipalsFile:
1511
		charptr = &options->authorized_principals_file;
1517
	case sAuthorizedCredentialsFile:
1518
		charptr = (opcode == sAuthorizedPrincipalsFile) ?
1519
			&options->authorized_principals_file :
1520
			&options->authorized_credentials_file;
1521
1512
		arg = strdelim(&cp);
1522
		arg = strdelim(&cp);
1513
		if (!arg || *arg == '\0')
1523
		if (!arg || *arg == '\0')
1514
			fatal("%s line %d: missing file name.",
1524
			fatal("%s line %d: missing file name.",
Lines 2163-2168 dump_config(ServerOptions *o) Link Here
2163
	dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
2173
	dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
2164
	dump_cfg_string(sAuthorizedPrincipalsFile,
2174
	dump_cfg_string(sAuthorizedPrincipalsFile,
2165
	    o->authorized_principals_file);
2175
	    o->authorized_principals_file);
2176
	dump_cfg_string(sAuthorizedCredentialsFile,
2177
	    o->authorized_credentials_file);
2178
2166
	dump_cfg_string(sVersionAddendum, o->version_addendum);
2179
	dump_cfg_string(sVersionAddendum, o->version_addendum);
2167
	dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
2180
	dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
2168
	dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
2181
	dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
(-)a/servconf.h (+1 lines)
Lines 177-182 typedef struct { Link Here
177
	char   *revoked_keys_file;
177
	char   *revoked_keys_file;
178
	char   *trusted_user_ca_keys;
178
	char   *trusted_user_ca_keys;
179
	char   *authorized_principals_file;
179
	char   *authorized_principals_file;
180
	char   *authorized_credentials_file;
180
	char   *authorized_keys_command;
181
	char   *authorized_keys_command;
181
	char   *authorized_keys_command_user;
182
	char   *authorized_keys_command_user;
182
183
(-)a/ssh-gss.h (-1 / +2 lines)
Lines 123-129 int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); Link Here
123
123
124
/* In the server */
124
/* In the server */
125
OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
125
OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
126
int ssh_gssapi_userok(char *name);
126
struct Authctxt;
127
int ssh_gssapi_userok(struct Authctxt *);
127
OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
128
OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
128
void ssh_gssapi_do_child(char ***, u_int *);
129
void ssh_gssapi_do_child(char ***, u_int *);
129
void ssh_gssapi_cleanup_creds(void);
130
void ssh_gssapi_cleanup_creds(void);

Return to bug 1927