static void send_status(u_int32_t id, u_int32_t status) { struct sshbuf *msg; int r; debug3("request %u: sent status %u", id, status); if (log_level > SYSLOG_LEVEL_VERBOSE || (status != SSH2_FX_OK && status != SSH2_FX_EOF)) logit("sent status %s", status_to_message(status)); if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u8(msg, SSH2_FXP_STATUS)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_u32(msg, status)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (version >= 3) { if ((r = sshbuf_put_cstring(msg, status_to_message(status))) != 0 || (r = sshbuf_put_cstring(msg, "")) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } send_msg(msg); sshbuf_free(msg); }
static void process_init(void) { struct sshbuf *msg; int r; if ((r = sshbuf_get_u32(iqueue, &version)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); verbose("received client version %u", version); if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u8(msg, SSH2_FXP_VERSION)) != 0 || (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0 || /* POSIX rename extension */ (r = sshbuf_put_cstring(msg, "*****@*****.**")) != 0 || (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ /* statvfs extension */ (r = sshbuf_put_cstring(msg, "*****@*****.**")) != 0 || (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */ /* fstatvfs extension */ (r = sshbuf_put_cstring(msg, "*****@*****.**")) != 0 || (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */ /* hardlink extension */ (r = sshbuf_put_cstring(msg, "*****@*****.**")) != 0 || (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ /* fsync extension */ (r = sshbuf_put_cstring(msg, "*****@*****.**")) != 0 || (r = sshbuf_put_cstring(msg, "1")) != 0) /* version */ fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(msg); sshbuf_free(msg); }
/* * Add/remove an token-based identity from the authentication server. * This call is intended only for use by ssh-add(1) and like applications. */ int ssh_update_card(int sock, int add, const char *reader_id, const char *pin, u_int life, u_int confirm) { struct sshbuf *msg; int r, constrained = (life || confirm); u_char type; if (add) { type = constrained ? SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED : SSH_AGENTC_ADD_SMARTCARD_KEY; } else type = SSH_AGENTC_REMOVE_SMARTCARD_KEY; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = sshbuf_put_cstring(msg, reader_id)) != 0 || (r = sshbuf_put_cstring(msg, pin)) != 0) goto out; if (constrained && (r = encode_constraints(msg, life, confirm)) != 0) goto out; if ((r = ssh_request_reply(sock, msg, msg)) != 0) goto out; if ((r = sshbuf_get_u8(msg, &type)) != 0) goto out; r = decode_reply(type); out: sshbuf_free(msg); return r; }
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); }
int kexgex_hash( int hash_alg, const char *client_version_string, const char *server_version_string, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, int min, int wantbits, int max, const BIGNUM *prime, const BIGNUM *gen, const BIGNUM *client_dh_pub, const BIGNUM *server_dh_pub, const BIGNUM *shared_secret, u_char **hash, size_t *hashlen) { struct sshbuf *b; static u_char digest[SSH_DIGEST_MAX_LENGTH]; int r; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || (r = sshbuf_put_cstring(b, server_version_string)) != 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || (min != -1 && (r = sshbuf_put_u32(b, min)) != 0) || (r = sshbuf_put_u32(b, wantbits)) != 0 || (max != -1 && (r = sshbuf_put_u32(b, max)) != 0) || (r = sshbuf_put_bignum2(b, prime)) != 0 || (r = sshbuf_put_bignum2(b, gen)) != 0 || (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 || (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 || (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { sshbuf_free(b); return r; } #ifdef DEBUG_KEXDH sshbuf_dump(b, stderr); #endif if (ssh_digest_buffer(hash_alg, b, digest, sizeof(digest)) != 0) { sshbuf_free(b); return SSH_ERR_LIBCRYPTO_ERROR; } sshbuf_free(b); *hash = digest; *hashlen = ssh_digest_bytes(hash_alg); #ifdef DEBUG_KEXDH dump_digest("hash", digest, *hashlen); #endif return 0; }
int kex_ecdh_hash( const EVP_MD *evp_md, const EC_GROUP *ec_group, const char *client_version_string, const char *server_version_string, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, const EC_POINT *client_dh_pub, const EC_POINT *server_dh_pub, const BIGNUM *shared_secret, u_char **hash, size_t *hashlen) { struct sshbuf *b; EVP_MD_CTX md; static u_char digest[EVP_MAX_MD_SIZE]; int r; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || (r = sshbuf_put_cstring(b, server_version_string)) != 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 || (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 || (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { sshbuf_free(b); return r; } #ifdef DEBUG_KEX sshbuf_dump(b, stderr); #endif if (EVP_DigestInit(&md, evp_md) != 1 || EVP_DigestUpdate(&md, sshbuf_ptr(b), sshbuf_len(b)) != 1 || EVP_DigestFinal(&md, digest, NULL) != 1) { sshbuf_free(b); return SSH_ERR_LIBCRYPTO_ERROR; } sshbuf_free(b); #ifdef DEBUG_KEX dump_digest("hash", digest, EVP_MD_size(evp_md)); #endif *hash = digest; *hashlen = EVP_MD_size(evp_md); return 0; }
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 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); }
int kex_ecdh_hash( int hash_alg, const EC_GROUP *ec_group, const char *client_version_string, const char *server_version_string, const u_char *ckexinit, size_t ckexinitlen, const u_char *skexinit, size_t skexinitlen, const u_char *serverhostkeyblob, size_t sbloblen, const EC_POINT *client_dh_pub, const EC_POINT *server_dh_pub, const BIGNUM *shared_secret, u_char *hash, size_t *hashlen) { struct sshbuf *b; int r; if (*hashlen < ssh_digest_bytes(hash_alg)) return SSH_ERR_INVALID_ARGUMENT; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || (r = sshbuf_put_cstring(b, server_version_string)) != 0 || /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 || (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 || (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 || (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 || (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 || (r = sshbuf_put_bignum2(b, shared_secret)) != 0) { sshbuf_free(b); return r; } #ifdef DEBUG_KEX sshbuf_dump(b, stderr); #endif if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { sshbuf_free(b); return SSH_ERR_LIBCRYPTO_ERROR; } sshbuf_free(b); *hashlen = ssh_digest_bytes(hash_alg); #ifdef DEBUG_KEX dump_digest("hash", hash, *hashlen); #endif return 0; }
void ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, const char *context) { int r; sshbuf_reset(b); if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshbuf_put_cstring(b, user)) != 0 || (r = sshbuf_put_cstring(b, service)) != 0 || (r = sshbuf_put_cstring(b, context)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); }
/* put algorithm proposal into buffer */ int kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) { u_int i; int r; sshbuf_reset(b); /* * add a dummy cookie, the cookie will be overwritten by * kex_send_kexinit(), each time a kexinit is set */ for (i = 0; i < KEX_COOKIE_LEN; i++) { if ((r = sshbuf_put_u8(b, 0)) != 0) return r; } for (i = 0; i < PROPOSAL_MAX; i++) { if ((r = sshbuf_put_cstring(b, proposal[i])) != 0) return r; } if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */ (r = sshbuf_put_u32(b, 0)) != 0) /* uint32 reserved */ return r; return 0; }
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; }
int mm_answer_bsdauthquery(int sock, struct sshbuf *m) { char *name, *infotxt, **prompts; u_int numprompts, *echo_on, success; int r; success = bsdauth_query(authctxt, &name, &infotxt, &numprompts, &prompts, &echo_on) < 0 ? 0 : 1; sshbuf_reset(m); if ((r = sshbuf_put_u32(m, success)) != 0 || (success && (r = sshbuf_put_cstring(m, prompts[0])) != 0)) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("%s: sending challenge success: %u", __func__, success); mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m); if (success) { free(name); free(infotxt); free(prompts); free(echo_on); } return (0); }
void buffer_put_cstring(Buffer *buffer, const char *s) { int ret; if ((ret = sshbuf_put_cstring(buffer, s)) != 0) fatal("%s: %s", __func__, ssh_err(ret)); }
int ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat) { u_char *sig = NULL; size_t slen = 0, len; unsigned long long smlen; int r, ret; struct sshbuf *b = NULL; if (lenp != NULL) *lenp = 0; if (sigp != NULL) *sigp = NULL; if (key == NULL || sshkey_type_plain(key->type) != KEY_ED25519 || key->ed25519_sk == NULL || datalen >= INT_MAX - crypto_sign_ed25519_BYTES) return SSH_ERR_INVALID_ARGUMENT; smlen = slen = datalen + crypto_sign_ed25519_BYTES; if ((sig = malloc(slen)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen, key->ed25519_sk)) != 0 || smlen <= datalen) { r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */ goto out; } /* encode signature */ if ((b = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put_cstring(b, "ssh-ed25519")) != 0 || (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0) goto out; len = sshbuf_len(b); if (sigp != NULL) { if ((*sigp = malloc(len)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(*sigp, sshbuf_ptr(b), len); } if (lenp != NULL) *lenp = len; /* success */ r = 0; out: sshbuf_free(b); if (sig != NULL) { explicit_bzero(sig, slen); free(sig); } return r; }
int pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp) { struct sshkey *k; int r; u_char *blob; size_t blen; u_int nkeys, i; struct sshbuf *msg; if (fd < 0 && pkcs11_start_helper() < 0) return (-1); if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u8(msg, SSH_AGENTC_ADD_SMARTCARD_KEY)) != 0 || (r = sshbuf_put_cstring(msg, name)) != 0 || (r = sshbuf_put_cstring(msg, pin)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(msg); sshbuf_reset(msg); if (recv_msg(msg) == SSH2_AGENT_IDENTITIES_ANSWER) { if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); for (i = 0; i < nkeys; i++) { /* XXX clean up properly instead of fatal() */ if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || (r = sshbuf_skip_string(msg)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if ((r = sshkey_from_blob(blob, blen, &k)) != 0) fatal("%s: bad key: %s", __func__, ssh_err(r)); wrap_key(k->rsa); (*keysp)[i] = k; xfree(blob); } } else { nkeys = -1; } sshbuf_free(msg); return (nkeys); }
static int serialise_nullable_string(struct sshbuf *m, const char *s) { int r; if ((r = sshbuf_put_u8(m, s == NULL)) != 0 || (r = sshbuf_put_cstring(m, s)) != 0) return r; return 0; }
/* XXX - see also comment in auth-chall.c:verify_response */ static int sshpam_respond(void *ctx, u_int num, char **resp) { struct sshbuf *buffer; struct pam_ctxt *ctxt = ctx; char *fake; int r; debug2("PAM: %s entering, %u responses", __func__, num); switch (ctxt->pam_done) { case 1: sshpam_authenticated = 1; return (0); case 0: break; default: return (-1); } if (num != 1) { error("PAM: expected one response, got %u", num); return (-1); } if ((buffer = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if (sshpam_authctxt->valid && (sshpam_authctxt->pw->pw_uid != 0 || options.permit_root_login == PERMIT_YES)) { if ((r = sshbuf_put_cstring(buffer, *resp)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } else { fake = fake_password(*resp); if ((r = sshbuf_put_cstring(buffer, fake)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); free(fake); } if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, buffer) == -1) { sshbuf_free(buffer); return (-1); } sshbuf_free(buffer); return (1); }
static int ssh_encode_identity_ssh2(struct sshbuf *b, struct sshkey *key, const char *comment) { int r; if ((r = sshkey_private_serialize(key, b)) != 0 || (r = sshbuf_put_cstring(b, comment)) != 0) return r; return 0; }
int pkcs11_del_provider(char *name) { int r, ret = -1; struct sshbuf *msg; if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u8(msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY)) != 0 || (r = sshbuf_put_cstring(msg, name)) != 0 || (r = sshbuf_put_cstring(msg, "")) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(msg); sshbuf_reset(msg); if (recv_msg(msg) == SSH_AGENT_SUCCESS) ret = 0; sshbuf_free(msg); return (ret); }
/* * Derive fake salt as H(username || first_private_host_key) * This provides relatively stable fake salts for non-existent * users and avoids the jpake method becoming an account validity * oracle. */ static void derive_rawsalt(const char *username, u_char *rawsalt, u_int len) { u_char *digest; u_int digest_len; struct sshbuf *b; struct sshkey *k; int r; if ((b = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_cstring(b, username)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if ((k = get_hostkey_by_index(0)) == NULL || (k->flags & SSHKEY_FLAG_EXT)) fatal("%s: no hostkeys", __func__); switch (k->type) { case KEY_RSA1: case KEY_RSA: if (k->rsa->p == NULL || k->rsa->q == NULL) fatal("%s: RSA key missing p and/or q", __func__); if ((r = sshbuf_put_bignum2(b, k->rsa->p)) != 0 || (r = sshbuf_put_bignum2(b, k->rsa->q)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); break; case KEY_DSA: if (k->dsa->priv_key == NULL) fatal("%s: DSA key missing priv_key", __func__); if ((r = sshbuf_put_bignum2(b, k->dsa->priv_key)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); break; case KEY_ECDSA: if (EC_KEY_get0_private_key(k->ecdsa) == NULL) fatal("%s: ECDSA key missing priv_key", __func__); if ((r = sshbuf_put_bignum2(b, EC_KEY_get0_private_key(k->ecdsa))) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); break; default: fatal("%s: unknown key type %d", __func__, k->type); } if (hash_buffer(sshbuf_ptr(b), sshbuf_len(b), EVP_sha256(), &digest, &digest_len) != 0) fatal("%s: hash_buffer", __func__); sshbuf_free(b); if (len > digest_len) fatal("%s: not enough bytes for rawsalt (want %u have %u)", __func__, len, digest_len); memcpy(rawsalt, digest, len); bzero(digest, digest_len); xfree(digest); }
static void send_names(u_int32_t id, int count, const Stat *stats) { struct sshbuf *msg; int i, r; if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u8(msg, SSH2_FXP_NAME)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_u32(msg, count)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug("request %u: sent names count %d", id, count); for (i = 0; i < count; i++) { if ((r = sshbuf_put_cstring(msg, stats[i].name)) != 0 || (r = sshbuf_put_cstring(msg, stats[i].long_name)) != 0 || (r = encode_attrib(msg, &stats[i].attrib)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } send_msg(msg); sshbuf_free(msg); }
int mm_answer_auth2_read_banner(int sock, struct sshbuf *m) { char *banner; int r; sshbuf_reset(m); banner = auth2_read_banner(); if ((r = sshbuf_put_cstring(m, banner != NULL ? banner : "")) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m); free(banner); return (0); }
int sshkey_xmss_serialize_enc_key(const struct sshkey *k, struct sshbuf *b) { struct ssh_xmss_state *state = k->xmss_state; int r; if (state == NULL || state->enc_keyiv == NULL || state->enc_ciphername == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshbuf_put_cstring(b, state->enc_ciphername)) != 0 || (r = sshbuf_put_string(b, state->enc_keyiv, state->enc_keyiv_len)) != 0) return r; return 0; }
void auth_debug_add(const char *fmt,...) { char buf[1024]; va_list args; int r; if (auth_debug == NULL) return; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); if ((r = sshbuf_put_cstring(auth_debug, buf)) != 0) fatal("%s: sshbuf_put_cstring: %s", __func__, ssh_err(r)); }
static int ssh_encode_identity_rsa1(struct sshbuf *b, RSA *key, const char *comment) { int r; /* To keep within the protocol: p < q for ssh. in SSL p > q */ if ((r = sshbuf_put_u32(b, BN_num_bits(key->n))) != 0 || (r = sshbuf_put_bignum1(b, key->n)) != 0 || (r = sshbuf_put_bignum1(b, key->e)) != 0 || (r = sshbuf_put_bignum1(b, key->d)) != 0 || (r = sshbuf_put_bignum1(b, key->iqmp)) != 0 || (r = sshbuf_put_bignum1(b, key->q)) != 0 || (r = sshbuf_put_bignum1(b, key->p)) != 0 || (r = sshbuf_put_cstring(b, comment)) != 0) return r; return 0; }
/* Lock/unlock agent */ int ssh_lock_agent(int sock, int lock, const char *password) { int r; u_char type = lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK; struct sshbuf *msg; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = sshbuf_put_cstring(msg, password)) != 0) goto out; if ((r = ssh_request_reply(sock, msg, msg)) != 0) goto out; if ((r = sshbuf_get_u8(msg, &type)) != 0) goto out; r = decode_reply(type); out: sshbuf_free(msg); return r; }
int sshkey_xmss_serialize_state(const struct sshkey *k, struct sshbuf *b) { struct ssh_xmss_state *state = k->xmss_state; treehash_inst *th; u_int32_t i, node; int r; if (state == NULL) return SSH_ERR_INVALID_ARGUMENT; if (state->stack == NULL) return SSH_ERR_INVALID_ARGUMENT; state->stackoffset = state->bds.stackoffset; /* copy back */ if ((r = sshbuf_put_cstring(b, SSH_XMSS_K2_MAGIC)) != 0 || (r = sshbuf_put_u32(b, state->idx)) != 0 || (r = sshbuf_put_string(b, state->stack, num_stack(state))) != 0 || (r = sshbuf_put_u32(b, state->stackoffset)) != 0 || (r = sshbuf_put_string(b, state->stacklevels, num_stacklevels(state))) != 0 || (r = sshbuf_put_string(b, state->auth, num_auth(state))) != 0 || (r = sshbuf_put_string(b, state->keep, num_keep(state))) != 0 || (r = sshbuf_put_string(b, state->th_nodes, num_th_nodes(state))) != 0 || (r = sshbuf_put_string(b, state->retain, num_retain(state))) != 0 || (r = sshbuf_put_u32(b, num_treehash(state))) != 0) return r; for (i = 0; i < num_treehash(state); i++) { th = &state->treehash[i]; node = th->node - state->th_nodes; if ((r = sshbuf_put_u32(b, th->h)) != 0 || (r = sshbuf_put_u32(b, th->next_idx)) != 0 || (r = sshbuf_put_u32(b, th->stackusage)) != 0 || (r = sshbuf_put_u8(b, th->completed)) != 0 || (r = sshbuf_put_u32(b, node)) != 0) return r; } return 0; }
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ int ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg_ident) { u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; size_t slen; u_int dlen, len; int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL; if (lenp != NULL) *lenp = 0; if (sigp != NULL) *sigp = NULL; if (alg_ident == NULL || strlen(alg_ident) == 0 || strncmp(alg_ident, "ssh-rsa-cert", strlen("ssh-rsa-cert")) == 0) hash_alg = SSH_DIGEST_SHA1; else hash_alg = rsa_hash_alg_from_ident(alg_ident); if (key == NULL || key->rsa == NULL || hash_alg == -1 || sshkey_type_plain(key->type) != KEY_RSA || BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) return SSH_ERR_INVALID_ARGUMENT; slen = RSA_size(key->rsa); if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) return SSH_ERR_INVALID_ARGUMENT; /* hash the data */ nid = rsa_hash_alg_nid(hash_alg); if ((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 = malloc(slen)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (len < slen) { size_t diff = slen - len; memmove(sig + diff, sig, len); explicit_bzero(sig, diff); } else if (len > slen) { ret = SSH_ERR_INTERNAL_ERROR; goto out; } /* encode signature */ if ((b = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 || (ret = sshbuf_put_string(b, sig, slen)) != 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 (sig != NULL) { explicit_bzero(sig, slen); free(sig); } sshbuf_free(b); return ret; }
int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat) { DSA_SIG *sig = NULL; u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); struct sshbuf *b = NULL; int ret = SSH_ERR_INVALID_ARGUMENT; if (lenp != NULL) *lenp = 0; if (sigp != NULL) *sigp = NULL; if (key == NULL || key->dsa == NULL || sshkey_type_plain(key->type) != KEY_DSA) return SSH_ERR_INVALID_ARGUMENT; if (dlen == 0) return SSH_ERR_INTERNAL_ERROR; if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, digest, sizeof(digest))) != 0) goto out; if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } rlen = BN_num_bytes(sig->r); slen = BN_num_bytes(sig->s); if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { ret = SSH_ERR_INTERNAL_ERROR; goto out; } explicit_bzero(sigblob, SIGBLOB_LEN); BN_bn2bin(sig->r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); BN_bn2bin(sig->s, sigblob + SIGBLOB_LEN - slen); if (compat & SSH_BUG_SIGBLOB) { if (sigp != NULL) { if ((*sigp = malloc(SIGBLOB_LEN)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(*sigp, sigblob, SIGBLOB_LEN); } if (lenp != NULL) *lenp = SIGBLOB_LEN; ret = 0; } else { /* ietf-drafts */ if ((b = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 || (ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 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 (sig != NULL) DSA_SIG_free(sig); sshbuf_free(b); return ret; }