static void build_cert(struct sshbuf *b, const struct sshkey *k, const char *type, const struct sshkey *sign_key, const struct sshkey *ca_key, const char *sig_alg) { struct sshbuf *ca_buf, *pk, *principals, *critopts, *exts; u_char *sigblob; size_t siglen; ca_buf = sshbuf_new(); ASSERT_PTR_NE(ca_buf, NULL); ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0); /* * Get the public key serialisation by rendering the key and skipping * the type string. This is a bit of a hack :/ */ pk = sshbuf_new(); ASSERT_PTR_NE(pk, NULL); ASSERT_INT_EQ(sshkey_putb_plain(k, pk), 0); ASSERT_INT_EQ(sshbuf_skip_string(pk), 0); principals = sshbuf_new(); ASSERT_PTR_NE(principals, NULL); ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0); ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0); critopts = sshbuf_new(); ASSERT_PTR_NE(critopts, NULL); put_opt(critopts, "force-command", "/usr/local/bin/nethack"); put_opt(critopts, "source-address", "192.168.0.0/24,127.0.0.1,::1"); exts = sshbuf_new(); ASSERT_PTR_NE(exts, NULL); put_opt(critopts, "permit-X11-forwarding", NULL); ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0); ASSERT_INT_EQ(sshbuf_put_cstring(b, "noncenoncenonce!"), 0); /* nonce */ ASSERT_INT_EQ(sshbuf_putb(b, pk), 0); /* public key serialisation */ ASSERT_INT_EQ(sshbuf_put_u64(b, 1234), 0); /* serial */ ASSERT_INT_EQ(sshbuf_put_u32(b, SSH2_CERT_TYPE_USER), 0); /* type */ ASSERT_INT_EQ(sshbuf_put_cstring(b, "gregor"), 0); /* key ID */ ASSERT_INT_EQ(sshbuf_put_stringb(b, principals), 0); /* principals */ ASSERT_INT_EQ(sshbuf_put_u64(b, 0), 0); /* start */ ASSERT_INT_EQ(sshbuf_put_u64(b, 0xffffffffffffffffULL), 0); /* end */ ASSERT_INT_EQ(sshbuf_put_stringb(b, critopts), 0); /* options */ ASSERT_INT_EQ(sshbuf_put_stringb(b, exts), 0); /* extensions */ ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */ ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */ ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen, sshbuf_ptr(b), sshbuf_len(b), sig_alg, 0), 0); ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ free(sigblob); sshbuf_free(ca_buf); sshbuf_free(exts); sshbuf_free(critopts); sshbuf_free(principals); sshbuf_free(pk); }
static void build_cert(struct sshbuf *b, const struct sshkey *k, const char *type, const struct sshkey *sign_key, const struct sshkey *ca_key) { struct sshbuf *ca_buf, *pk, *principals, *critopts, *exts; u_char *sigblob; size_t siglen; ca_buf = sshbuf_new(); ASSERT_INT_EQ(sshkey_to_blob_buf(ca_key, ca_buf), 0); /* * Get the public key serialisation by rendering the key and skipping * the type string. This is a bit of a hack :/ */ pk = sshbuf_new(); ASSERT_INT_EQ(sshkey_plain_to_blob_buf(k, pk), 0); ASSERT_INT_EQ(sshbuf_skip_string(pk), 0); principals = sshbuf_new(); ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0); ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0); critopts = sshbuf_new(); /* XXX fill this in */ exts = sshbuf_new(); /* XXX fill this in */ ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0); ASSERT_INT_EQ(sshbuf_put_cstring(b, "noncenoncenonce!"), 0); /* nonce */ ASSERT_INT_EQ(sshbuf_putb(b, pk), 0); /* public key serialisation */ ASSERT_INT_EQ(sshbuf_put_u64(b, 1234), 0); /* serial */ ASSERT_INT_EQ(sshbuf_put_u32(b, SSH2_CERT_TYPE_USER), 0); /* type */ ASSERT_INT_EQ(sshbuf_put_cstring(b, "gregor"), 0); /* key ID */ ASSERT_INT_EQ(sshbuf_put_stringb(b, principals), 0); /* principals */ ASSERT_INT_EQ(sshbuf_put_u64(b, 0), 0); /* start */ ASSERT_INT_EQ(sshbuf_put_u64(b, 0xffffffffffffffffULL), 0); /* end */ ASSERT_INT_EQ(sshbuf_put_stringb(b, critopts), 0); /* options */ ASSERT_INT_EQ(sshbuf_put_stringb(b, exts), 0); /* extensions */ ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */ ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */ ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen, sshbuf_ptr(b), sshbuf_len(b), 0), 0); ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ free(sigblob); sshbuf_free(ca_buf); sshbuf_free(exts); sshbuf_free(critopts); sshbuf_free(principals); sshbuf_free(pk); }
static int serialise_array(struct sshbuf *m, char **a, size_t n) { struct sshbuf *b; size_t i; int r; if (n > INT_MAX) return SSH_ERR_INTERNAL_ERROR; if ((b = sshbuf_new()) == NULL) { return SSH_ERR_ALLOC_FAIL; } for (i = 0; i < n; i++) { if ((r = sshbuf_put_cstring(b, a[i])) != 0) { sshbuf_free(b); return r; } } if ((r = sshbuf_put_u32(m, n)) != 0 || (r = sshbuf_put_stringb(m, b)) != 0) { sshbuf_free(b); return r; } /* success */ return 0; }
static void send_msg(struct sshbuf *m) { int r; if ((r = sshbuf_put_stringb(oqueue, m)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); sshbuf_reset(m); }
static void put_opt(struct sshbuf *b, const char *name, const char *value) { struct sshbuf *sect; sect = sshbuf_new(); ASSERT_PTR_NE(sect, NULL); ASSERT_INT_EQ(sshbuf_put_cstring(b, name), 0); if (value != NULL) ASSERT_INT_EQ(sshbuf_put_cstring(sect, value), 0); ASSERT_INT_EQ(sshbuf_put_stringb(b, sect), 0); sshbuf_free(sect); }
/* ARGSUSED */ int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat) { ECDSA_SIG *sig = NULL; int hash_alg; u_char digest[SSH_DIGEST_MAX_LENGTH]; size_t len, dlen; struct sshbuf *b = NULL, *bb = NULL; int ret = SSH_ERR_INTERNAL_ERROR; if (lenp != NULL) *lenp = 0; if (sigp != NULL) *sigp = NULL; if (key == NULL || key->ecdsa == NULL || sshkey_type_plain(key->type) != KEY_ECDSA) return SSH_ERR_INVALID_ARGUMENT; if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || (dlen = ssh_digest_bytes(hash_alg)) == 0) return SSH_ERR_INTERNAL_ERROR; if ((ret = ssh_digest_memory(hash_alg, data, datalen, digest, sizeof(digest))) != 0) goto out; if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if ((ret = sshbuf_put_bignum2(bb, sig->r)) != 0 || (ret = sshbuf_put_bignum2(bb, sig->s)) != 0) goto out; if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 || (ret = sshbuf_put_stringb(b, bb)) != 0) goto out; len = sshbuf_len(b); if (sigp != NULL) { if ((*sigp = malloc(len)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(*sigp, sshbuf_ptr(b), len); } if (lenp != NULL) *lenp = len; ret = 0; out: explicit_bzero(digest, sizeof(digest)); if (b != NULL) sshbuf_free(b); if (bb != NULL) sshbuf_free(bb); if (sig != NULL) ECDSA_SIG_free(sig); return ret; }
int mm_answer_pty(int sock, struct sshbuf *m) { extern struct monitor *pmonitor; Session *s; int r, res, fd0; debug3("%s entering", __func__); sshbuf_reset(m); s = session_new(); if (s == NULL) goto error; s->authctxt = authctxt; s->pw = authctxt->pw; s->pid = pmonitor->m_pid; res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); if (res == 0) goto error; pty_setowner(authctxt->pw, s->tty); if ((r = sshbuf_put_u32(m, 1)) != 0 || (r = sshbuf_put_cstring(m, s->tty)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); /* We need to trick ttyslot */ if (dup2(s->ttyfd, 0) == -1) fatal("%s: dup2", __func__); mm_record_login(s, authctxt->pw); /* Now we can close the file descriptor again */ close(0); /* send messages generated by record_login */ if ((r = sshbuf_put_stringb(m, loginmsg)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); sshbuf_reset(loginmsg); mm_request_send(sock, MONITOR_ANS_PTY, m); if (mm_send_fd(sock, s->ptyfd) == -1 || mm_send_fd(sock, s->ttyfd) == -1) fatal("%s: send fds failed", __func__); /* make sure nothing uses fd 0 */ if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); if (fd0 != 0) error("%s: fd0 %d != 0", __func__, fd0); /* slave is not needed */ close(s->ttyfd); s->ttyfd = s->ptyfd; /* no need to dup() because nobody closes ptyfd */ s->ptymaster = s->ptyfd; debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); return (0); error: if (s != NULL) mm_session_close(s); if ((r = sshbuf_put_u32(m, 0)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(sock, MONITOR_ANS_PTY, m); return (0); }