Key * key_load_private(const char *filename, const char *passphrase, char **commentp) { Key *pub, *prv; int fd; fd = open(filename, O_RDONLY); if (fd < 0) return NULL; if (!key_perm_ok(fd, filename)) { error("bad permissions: ignore key: %s", filename); close(fd); return NULL; } pub = key_load_public_rsa1(fd, filename, commentp); lseek(fd, (off_t) 0, SEEK_SET); /* rewind */ if (pub == NULL) { /* closes fd */ prv = key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL); /* use the filename as a comment for PEM */ if (commentp && prv) *commentp = xstrdup(filename); } else { /* it's a SSH v1 key if the public key part is readable */ key_free(pub); /* closes fd */ prv = key_load_private_rsa1(fd, filename, passphrase, NULL); } return prv; }
Key * key_load_private_type(int type, const char *filename, const char *passphrase, char **commentp) { int fd; fd = open(filename, O_RDONLY); if (fd < 0) return NULL; if (!key_perm_ok(fd, filename)) { error("bad permissions: ignore key: %s", filename); close(fd); return NULL; } switch (type) { case KEY_RSA1: return key_load_private_rsa1(fd, filename, passphrase, commentp); /* closes fd */ break; case KEY_DSA: case KEY_RSA: case KEY_UNSPEC: return key_load_private_pem(fd, type, passphrase, commentp); /* closes fd */ break; default: close(fd); break; } return NULL; }
int main(int argc, char **argv) { Buffer b; Options options; #define NUM_KEYTYPES 3 Key *keys[NUM_KEYTYPES], *key = NULL; struct passwd *pw; int key_fd[NUM_KEYTYPES], i, found, version = 2, fd; u_char *signature, *data; char *host; u_int slen, dlen; u_int32_t rnd[256]; /* 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; 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_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); #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, "", &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"); OpenSSL_add_all_algorithms(); for (i = 0; i < 256; i++) rnd[i] = arc4random(); RAND_seed(rnd, sizeof(rnd)); found = 0; for (i = 0; i < NUM_KEYTYPES; i++) { keys[i] = NULL; if (key_fd[i] == -1) continue; keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC, NULL, NULL); close(key_fd[i]); if (keys[i] != NULL) found = 1; } if (!found) fatal("no hostkey found"); buffer_init(&b); if (ssh_msg_recv(STDIN_FILENO, &b) < 0) fatal("ssh_msg_recv failed"); if (buffer_get_char(&b) != version) fatal("bad version"); fd = buffer_get_int(&b); if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO)) fatal("bad fd"); if ((host = get_local_name(fd)) == NULL) fatal("cannot get local name for fd"); data = buffer_get_string(&b, &dlen); if (valid_request(pw, host, &key, data, dlen) < 0) fatal("not a valid request"); xfree(host); found = 0; for (i = 0; i < NUM_KEYTYPES; i++) { if (keys[i] != NULL && key_equal_public(key, keys[i])) { found = 1; break; } } if (!found) fatal("no matching hostkey found"); if (key_sign(keys[i], &signature, &slen, data, dlen) != 0) fatal("key_sign failed"); xfree(data); /* send reply */ buffer_clear(&b); buffer_put_string(&b, signature, slen); if (ssh_msg_send(STDOUT_FILENO, version, &b) == -1) fatal("ssh_msg_send failed"); return (0); }