Example #1
0
/* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */
int
sshkey_load_private_type(int type, const char *filename, const char *passphrase,
    struct sshkey **keyp, char **commentp, int *perm_ok)
{
	int fd, r;

	*keyp = NULL;
	if (commentp != NULL)
		*commentp = NULL;

	if ((fd = open(filename, O_RDONLY)) < 0) {
		if (perm_ok != NULL)
			*perm_ok = 0;
		return SSH_ERR_SYSTEM_ERROR;
	}
	if (sshkey_perm_ok(fd, filename) != 0) {
		if (perm_ok != NULL)
			*perm_ok = 0;
		r = SSH_ERR_KEY_BAD_PERMISSIONS;
		goto out;
	}
	if (perm_ok != NULL)
		*perm_ok = 1;

	r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp);
 out:
	close(fd);
	return r;
}
Example #2
0
int
main(int argc, char **argv)
{
	struct sshbuf *b;
	Options options;
#define NUM_KEYTYPES 4
	struct sshkey *keys[NUM_KEYTYPES], *key = NULL;
	struct passwd *pw;
	int r, key_fd[NUM_KEYTYPES], i, found, version = 2, fd;
	u_char *signature, *data, rver;
	char *host, *fp;
	size_t slen, dlen;
#ifdef WITH_OPENSSL
	u_int32_t rnd[256];
#endif

	if (pledge("stdio rpath getpw dns id", NULL) != 0)
		fatal("%s: pledge: %s", __progname, strerror(errno));

	/* Ensure that stdin and stdout are connected */
	if ((fd = open(_PATH_DEVNULL, O_RDWR)) < 2)
		exit(1);
	/* Leave /dev/null fd iff it is attached to stderr */
	if (fd > 2)
		close(fd);

	i = 0;
	/* XXX This really needs to read sshd_config for the paths */
	key_fd[i++] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY);
	key_fd[i++] = open(_PATH_HOST_ECDSA_KEY_FILE, O_RDONLY);
	key_fd[i++] = open(_PATH_HOST_ED25519_KEY_FILE, O_RDONLY);
	key_fd[i++] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY);

	original_real_uid = getuid();	/* XXX readconf.c needs this */
	if ((pw = getpwuid(original_real_uid)) == NULL)
		fatal("getpwuid failed");
	pw = pwcopy(pw);

	permanently_set_uid(pw);

	seed_rng();

#ifdef DEBUG_SSH_KEYSIGN
	log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0);
#endif

	/* verify that ssh-keysign is enabled by the admin */
	initialize_options(&options);
	(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "", &options, 0);
	fill_default_options(&options);
	if (options.enable_ssh_keysign != 1)
		fatal("ssh-keysign not enabled in %s",
		    _PATH_HOST_CONFIG_FILE);

	for (i = found = 0; i < NUM_KEYTYPES; i++) {
		if (key_fd[i] != -1)
			found = 1;
	}
	if (found == 0)
		fatal("could not open any host key");

#ifdef WITH_OPENSSL
	OpenSSL_add_all_algorithms();
	arc4random_buf(rnd, sizeof(rnd));
	RAND_seed(rnd, sizeof(rnd));
#endif

	found = 0;
	for (i = 0; i < NUM_KEYTYPES; i++) {
		keys[i] = NULL;
		if (key_fd[i] == -1)
			continue;
		r = sshkey_load_private_type_fd(key_fd[i], KEY_UNSPEC,
		    NULL, &key, NULL);
		close(key_fd[i]);
		if (r != 0)
			debug("parse key %d: %s", i, ssh_err(r));
		else if (key != NULL) {
			keys[i] = key;
			found = 1;
		}
	}
	if (!found)
		fatal("no hostkey found");

	if (pledge("stdio dns", NULL) != 0)
		fatal("%s: pledge: %s", __progname, strerror(errno));

	if ((b = sshbuf_new()) == NULL)
		fatal("%s: sshbuf_new failed", __progname);
	if (ssh_msg_recv(STDIN_FILENO, b) < 0)
		fatal("ssh_msg_recv failed");
	if ((r = sshbuf_get_u8(b, &rver)) != 0)
		fatal("%s: buffer error: %s", __progname, ssh_err(r));
	if (rver != version)
		fatal("bad version: received %d, expected %d", rver, version);
	if ((r = sshbuf_get_u32(b, (u_int *)&fd)) != 0)
		fatal("%s: buffer error: %s", __progname, ssh_err(r));
	if (fd < 0 || fd == STDIN_FILENO || fd == STDOUT_FILENO)
		fatal("bad fd");
	if ((host = get_local_name(fd)) == NULL)
		fatal("cannot get local name for fd");

	if ((r = sshbuf_get_string(b, &data, &dlen)) != 0)
		fatal("%s: buffer error: %s", __progname, ssh_err(r));
	if (valid_request(pw, host, &key, data, dlen) < 0)
		fatal("not a valid request");
	free(host);

	found = 0;
	for (i = 0; i < NUM_KEYTYPES; i++) {
		if (keys[i] != NULL &&
		    sshkey_equal_public(key, keys[i])) {
			found = 1;
			break;
		}
	}
	if (!found) {
		if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
		    SSH_FP_DEFAULT)) == NULL)
			fatal("%s: sshkey_fingerprint failed", __progname);
		fatal("no matching hostkey found for key %s %s",
		    sshkey_type(key), fp ? fp : "");
	}

	if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, NULL, 0))
	    != 0)
		fatal("sshkey_sign failed: %s", ssh_err(r));
	free(data);

	/* send reply */
	sshbuf_reset(b);
	if ((r = sshbuf_put_string(b, signature, slen)) != 0)
		fatal("%s: buffer error: %s", __progname, ssh_err(r));
	if (ssh_msg_send(STDOUT_FILENO, version, b) == -1)
		fatal("ssh_msg_send failed");

	return (0);
}
Example #3
0
int
main(int argc, char **argv)
{
	int ch, fd, r;
	int count_flag = 0, dump_flag = 0, replace_flag = 0;
	int packet_index = -1, direction = -1;
	int s2c = 0, c2s = 0; /* packet counts */
	const char *kex = NULL, *kpath = NULL, *data_path = NULL;
	struct sshkey *key = NULL;
	struct sshbuf *replace_data = NULL;

	setvbuf(stdout, NULL, _IONBF, 0);
	while ((ch = getopt(argc, argv, "hcdrvD:f:K:k:i:")) != -1) {
		switch (ch) {
		case 'h':
			usage();
			return 0;
		case 'c':
			count_flag = 1;
			break;
		case 'd':
			dump_flag = 1;
			break;
		case 'r':
			replace_flag = 1;
			break;
		case 'v':
			do_debug = 1;
			break;

		case 'D':
			if (strcasecmp(optarg, "s2c") == 0)
				direction = S2C;
			else if (strcasecmp(optarg, "c2s") == 0)
				direction = C2S;
			else
				badusage("Invalid direction (-D)");
			break;
		case 'f':
			data_path = optarg;
			break;
		case 'K':
			kex = optarg;
			break;
		case 'k':
			kpath = optarg;
			break;
		case 'i':
			packet_index = atoi(optarg);
			if (packet_index < 0)
				badusage("Invalid packet index");
			break;
		default:
			badusage("unsupported flag");
		}
	}
	argc -= optind;
	argv += optind;

	/* Must select a single mode */
	if ((count_flag + dump_flag + replace_flag) != 1)
		badusage("Must select one mode: -c, -d or -r");
	/* KEX type is mandatory */
	if (kex == NULL || !kex_names_valid(kex) || strchr(kex, ',') != NULL)
		badusage("Missing or invalid kex type (-K flag)");
	/* Valid key is mandatory */
	if (kpath == NULL)
		badusage("Missing private key (-k flag)");
	if ((fd = open(kpath, O_RDONLY)) == -1)
		err(1, "open %s", kpath);
	if ((r = sshkey_load_private_type_fd(fd, KEY_UNSPEC, NULL,
	    &key, NULL)) != 0)
		errx(1, "Unable to load key %s: %s", kpath, ssh_err(r));
	close(fd);
	/* XXX check that it is a private key */
	/* XXX support certificates */
	if (key == NULL || key->type == KEY_UNSPEC || key->type == KEY_RSA1)
		badusage("Invalid key file (-k flag)");

	/* Replace (fuzz) mode */
	if (replace_flag) {
		if (packet_index == -1 || direction == -1 || data_path == NULL)
			badusage("Replace (-r) mode must specify direction "
			    "(-D) packet index (-i) and data path (-f)");
		if ((fd = open(data_path, O_RDONLY)) == -1)
			err(1, "open %s", data_path);
		replace_data = sshbuf_new();
		if ((r = sshkey_load_file(fd, replace_data)) != 0)
			errx(1, "read %s: %s", data_path, ssh_err(r));
		close(fd);
	}

	/* Dump mode */
	if (dump_flag) {
		if (packet_index == -1 || direction == -1 || data_path == NULL)
			badusage("Dump (-d) mode must specify direction "
			    "(-D), packet index (-i) and data path (-f)");
	}

	/* Count mode needs no further flags */

	do_kex_with_key(kex, key, &c2s, &s2c,
	    direction, packet_index,
	    dump_flag ? data_path : NULL,
	    replace_flag ? replace_data : NULL);
	sshkey_free(key);
	sshbuf_free(replace_data);

	if (count_flag) {
		printf("S2C: %d\n", s2c);
		printf("C2S: %d\n", c2s);
	}

	return 0;
}