View | Details | Raw Unified | Return to bug 2081 | Differences between
and this patch

Collapse All | Expand All

(-)a/auth2-pubkey.c (-12 / +71 lines)
Lines 496-501 user_key_allowed2(struct passwd *pw, Key *key, char *file) Link Here
496
	return found_key;
496
	return found_key;
497
}
497
}
498
498
499
static const char *
500
argv_to_string(char *argv[])
501
{
502
	static char buf[4096];
503
	int i, rem = sizeof(buf);
504
505
	buf[0] = '\0';
506
	for (i = 0; argv[i] != NULL && rem > 0; i++) {
507
		if (i > 0)
508
			strncat(buf, " ", --rem);
509
		strncat(buf, argv[i], rem - 1);
510
		rem -= strlen(argv[i]);
511
	}
512
	return buf;
513
}
514
499
/*
515
/*
500
 * Checks whether key is allowed in output of command.
516
 * Checks whether key is allowed in output of command.
501
 * returns 1 if the key is allowed or 0 otherwise.
517
 * returns 1 if the key is allowed or 0 otherwise.
Lines 507-515 user_key_command_allowed2(struct passwd *user_pw, Key *key) Link Here
507
	int ok, found_key = 0;
523
	int ok, found_key = 0;
508
	struct passwd *pw;
524
	struct passwd *pw;
509
	struct stat st;
525
	struct stat st;
510
	int status, devnull, p[2], i;
526
	int status, devnull, p[2], i, argc;
511
	pid_t pid;
527
	pid_t pid;
512
	char *username, errmsg[512];
528
	char *username, errmsg[512];
529
	char *command, *cp, **argv;
530
	char *key_fp = NULL, *keytext = NULL;
531
	char *authorized_keys_command_path;
532
	size_t keytextlen;
513
533
514
	if (options.authorized_keys_command == NULL ||
534
	if (options.authorized_keys_command == NULL ||
515
	    options.authorized_keys_command[0] != '/')
535
	    options.authorized_keys_command[0] != '/')
Lines 533-544 user_key_command_allowed2(struct passwd *user_pw, Key *key) Link Here
533
553
534
	temporarily_use_uid(pw);
554
	temporarily_use_uid(pw);
535
555
536
	if (stat(options.authorized_keys_command, &st) < 0) {
556
	if (strstr(options.authorized_keys_command, "%f") != NULL) {
557
		key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
558
		if (key_fp == NULL) {
559
			error("AuthorizedKeysCommand %%f parameter expansion failed");
560
			return 0;
561
		}
562
	}
563
	if (strstr(options.authorized_keys_command, "%k") != NULL) {
564
		if (key_to_base64(key, &keytext, &keytextlen) != 0) {
565
			error("AuthorizedKeysCommand %%k parameter expansion failed");
566
			free(key_fp);
567
			return 0;
568
		}
569
	}
570
	command = cp = percent_expand(options.authorized_keys_command,
571
	    "u", user_pw->pw_name, "t", key_ssh_name(key),
572
	    "f", key_fp == NULL ? "" : key_fp,
573
	    "k", keytext == NULL ? "" : keytext, (char *)NULL);
574
	if (keytext != NULL)
575
		free(keytext);
576
	if (key_fp != NULL)
577
		free(key_fp);
578
579
	argv = xcalloc(argc = 6, sizeof(char *));
580
	argv[0] = authorized_keys_command_path = strdelim(&cp);
581
	for (i = 1; cp != NULL; i++) {
582
		/* Ensure the last argv[] position remains unused for NULL */
583
		if (i + 1 == argc)
584
			argv = xrealloc(argv, argc += 10, sizeof(char *));
585
		argv[i] = strdelim(&cp);
586
	}
587
	if (i == 1)
588
		argv[i] = user_pw->pw_name;
589
	else
590
		argv[i] = NULL;
591
592
	if (stat(authorized_keys_command_path, &st) < 0) {
537
		error("Could not stat AuthorizedKeysCommand \"%s\": %s",
593
		error("Could not stat AuthorizedKeysCommand \"%s\": %s",
538
		    options.authorized_keys_command, strerror(errno));
594
		    authorized_keys_command_path, strerror(errno));
539
		goto out;
595
		goto out;
540
	}
596
	}
541
	if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
597
	if (auth_secure_path(authorized_keys_command_path, &st, NULL, 0,
542
	    errmsg, sizeof(errmsg)) != 0) {
598
	    errmsg, sizeof(errmsg)) != 0) {
543
		error("Unsafe AuthorizedKeysCommand: %s", errmsg);
599
		error("Unsafe AuthorizedKeysCommand: %s", errmsg);
544
		goto out;
600
		goto out;
Lines 549-556 user_key_command_allowed2(struct passwd *user_pw, Key *key) Link Here
549
		goto out;
605
		goto out;
550
	}
606
	}
551
607
552
	debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",
608
	debug3("Running AuthorizedKeysCommand: \"%s\" as \"%s\"",
553
	    options.authorized_keys_command, user_pw->pw_name, pw->pw_name);
609
	    argv_to_string(argv), pw->pw_name);
554
610
555
	/*
611
	/*
556
	 * Don't want to call this in the child, where it can fatal() and
612
	 * Don't want to call this in the child, where it can fatal() and
Lines 563-568 user_key_command_allowed2(struct passwd *user_pw, Key *key) Link Here
563
		error("%s: fork: %s", __func__, strerror(errno));
619
		error("%s: fork: %s", __func__, strerror(errno));
564
		close(p[0]);
620
		close(p[0]);
565
		close(p[1]);
621
		close(p[1]);
622
		free(argv);
623
		free(command);
566
		return 0;
624
		return 0;
567
	case 0: /* child */
625
	case 0: /* child */
568
		for (i = 0; i < NSIG; i++)
626
		for (i = 0; i < NSIG; i++)
Lines 598-608 user_key_command_allowed2(struct passwd *user_pw, Key *key) Link Here
598
			_exit(1);
656
			_exit(1);
599
		}
657
		}
600
658
601
		execl(options.authorized_keys_command,
659
		execv(authorized_keys_command_path, argv);
602
		    options.authorized_keys_command, user_pw->pw_name, NULL);
603
660
604
		error("AuthorizedKeysCommand %s exec failed: %s",
661
		error("AuthorizedKeysCommand %s exec failed: %s",
605
		    options.authorized_keys_command, strerror(errno));
662
		    authorized_keys_command_path, strerror(errno));
606
		_exit(127);
663
		_exit(127);
607
	default: /* parent */
664
	default: /* parent */
608
		break;
665
		break;
Lines 620-626 user_key_command_allowed2(struct passwd *user_pw, Key *key) Link Here
620
			;
677
			;
621
		goto out;
678
		goto out;
622
	}
679
	}
623
	ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
680
	ok = check_authkeys_file(f, authorized_keys_command_path, key, pw);
624
	fclose(f);
681
	fclose(f);
625
682
626
	while (waitpid(pid, &status, 0) == -1) {
683
	while (waitpid(pid, &status, 0) == -1) {
Lines 631-645 user_key_command_allowed2(struct passwd *user_pw, Key *key) Link Here
631
	}
688
	}
632
	if (WIFSIGNALED(status)) {
689
	if (WIFSIGNALED(status)) {
633
		error("AuthorizedKeysCommand %s exited on signal %d",
690
		error("AuthorizedKeysCommand %s exited on signal %d",
634
		    options.authorized_keys_command, WTERMSIG(status));
691
		    authorized_keys_command_path, WTERMSIG(status));
635
		goto out;
692
		goto out;
636
	} else if (WEXITSTATUS(status) != 0) {
693
	} else if (WEXITSTATUS(status) != 0) {
637
		error("AuthorizedKeysCommand %s returned status %d",
694
		error("AuthorizedKeysCommand %s returned status %d",
638
		    options.authorized_keys_command, WEXITSTATUS(status));
695
		    authorized_keys_command_path, WEXITSTATUS(status));
639
		goto out;
696
		goto out;
640
	}
697
	}
641
	found_key = ok;
698
	found_key = ok;
642
 out:
699
 out:
700
	free(argv);
701
	free(command);
643
	restore_uid();
702
	restore_uid();
644
	return found_key;
703
	return found_key;
645
}
704
}
(-)a/key.h (+1 lines)
Lines 61-66 typedef struct sshkey Key; Link Here
61
#define key_dump_ec_point	sshkey_dump_ec_point
61
#define key_dump_ec_point	sshkey_dump_ec_point
62
#define key_dump_ec_key		sshkey_dump_ec_key
62
#define key_dump_ec_key		sshkey_dump_ec_key
63
#define key_fingerprint		sshkey_fingerprint
63
#define key_fingerprint		sshkey_fingerprint
64
#define key_to_base64		sshkey_to_base64
64
#endif
65
#endif
65
66
66
void	 key_add_private(Key *);
67
void	 key_add_private(Key *);
(-)a/sshd_config.5 (-1 / +6 lines)
Lines 220-226 of a single authentication method is sufficient. Link Here
220
Specifies a program to be used to look up the user's public keys.
220
Specifies a program to be used to look up the user's public keys.
221
The program must be owned by root and not writable by group or others.
221
The program must be owned by root and not writable by group or others.
222
It will be invoked with a single argument of the username
222
It will be invoked with a single argument of the username
223
being authenticated, and should produce on standard output zero or
223
being authenticated, unless any of the following tokens, which are
224
expanded at runtime, are provided: %u is replaced by the username
225
being authenticated, %t is replaced with the key type offered for
226
authentication, %f is replaced with the fingerprint of the key, and
227
%k is replaced with the key being offered for authentication.
228
The program should produce on standard output zero or
224
more lines of authorized_keys output (see AUTHORIZED_KEYS in
229
more lines of authorized_keys output (see AUTHORIZED_KEYS in
225
.Xr sshd 8 ) .
230
.Xr sshd 8 ) .
226
If a key supplied by AuthorizedKeysCommand does not successfully authenticate
231
If a key supplied by AuthorizedKeysCommand does not successfully authenticate
(-)a/sshkey.c (+72 lines)
Lines 1427-1432 sshkey_write(const struct sshkey *key, FILE *f) Link Here
1427
	return ret;
1427
	return ret;
1428
}
1428
}
1429
1429
1430
int
1431
sshkey_to_base64(const struct sshkey *key, char **blobp, size_t *lenp)
1432
{
1433
	int ret = SSH_ERR_INTERNAL_ERROR;
1434
	struct sshbuf *b = NULL, *bb = NULL;
1435
	char *uu = NULL;
1436
	size_t len;
1437
1438
	if (lenp != NULL)
1439
		*lenp = 0;
1440
	if (blobp != NULL)
1441
		*blobp = NULL;
1442
1443
	if (sshkey_is_cert(key)) {
1444
		if (key->cert == NULL)
1445
			return SSH_ERR_EXPECTED_CERT;
1446
		if (sshbuf_len(key->cert->certblob) == 0)
1447
			return SSH_ERR_KEY_LACKS_CERTBLOB;
1448
	}
1449
	if ((b = sshbuf_new()) == NULL)
1450
		return SSH_ERR_ALLOC_FAIL;
1451
	switch (key->type) {
1452
#ifdef WITH_OPENSSL
1453
	case KEY_DSA:
1454
	case KEY_DSA_CERT_V00:
1455
	case KEY_DSA_CERT:
1456
	case KEY_ECDSA:
1457
	case KEY_ECDSA_CERT:
1458
	case KEY_RSA:
1459
	case KEY_RSA_CERT_V00:
1460
	case KEY_RSA_CERT:
1461
#endif /* WITH_OPENSSL */
1462
	case KEY_ED25519:
1463
	case KEY_ED25519_CERT:
1464
		if ((bb = sshbuf_new()) == NULL) {
1465
			ret = SSH_ERR_ALLOC_FAIL;
1466
			goto out;
1467
		}
1468
		if ((ret = sshkey_to_blob_buf(key, bb)) != 0)
1469
			goto out;
1470
		if ((uu = sshbuf_dtob64(bb)) == NULL) {
1471
			ret = SSH_ERR_ALLOC_FAIL;
1472
			goto out;
1473
		}
1474
		if ((ret = sshbuf_put(b, uu, strlen(uu))) != 0)
1475
			goto out;
1476
		break;
1477
	default:
1478
		ret = SSH_ERR_KEY_TYPE_UNKNOWN;
1479
		goto out;
1480
	}
1481
	len = sshbuf_len(b);
1482
	if (lenp != NULL)
1483
		*lenp = len;
1484
	if (blobp != NULL) {
1485
		if ((*blobp = malloc(len)) == NULL) {
1486
			ret = SSH_ERR_ALLOC_FAIL;
1487
			goto out;
1488
		}
1489
		memcpy(*blobp, sshbuf_ptr(b), len);
1490
	}
1491
	ret = 0;
1492
 out:
1493
	if (b != NULL)
1494
		sshbuf_free(b);
1495
	if (bb != NULL)
1496
		sshbuf_free(bb);
1497
	if (uu != NULL)
1498
		free(uu);
1499
	return ret;
1500
}
1501
1430
const char *
1502
const char *
1431
sshkey_cert_type(const struct sshkey *k)
1503
sshkey_cert_type(const struct sshkey *k)
1432
{
1504
{
(-)a/sshkey.h (-1 / +2 lines)
Lines 167-172 int sshkey_to_blob(const struct sshkey *, u_char **, size_t *); Link Here
167
int	 sshkey_plain_to_blob_buf(const struct sshkey *, struct sshbuf *);
167
int	 sshkey_plain_to_blob_buf(const struct sshkey *, struct sshbuf *);
168
int	 sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *);
168
int	 sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *);
169
169
170
int	 sshkey_to_base64(const struct sshkey *, char **, size_t *);
171
170
int	 sshkey_sign(const struct sshkey *, u_char **, size_t *,
172
int	 sshkey_sign(const struct sshkey *, u_char **, size_t *,
171
    const u_char *, size_t, u_int);
173
    const u_char *, size_t, u_int);
172
int	 sshkey_verify(const struct sshkey *, const u_char *, size_t,
174
int	 sshkey_verify(const struct sshkey *, const u_char *, size_t,
173
- 

Return to bug 2081