/* 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; }
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; }
/* * Encodes terminal modes for the terminal referenced by fd * or tiop in a portable manner, and appends the modes to a packet * being constructed. */ void ssh_tty_make_modes(struct ssh *ssh, int fd, struct termios *tiop) { struct termios tio; struct sshbuf *buf; int r, ibaud, obaud; if ((buf = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if (tiop == NULL) { if (fd == -1) { debug("%s: no fd or tio", __func__); goto end; } if (tcgetattr(fd, &tio) == -1) { logit("tcgetattr: %.100s", strerror(errno)); goto end; } } else tio = *tiop; /* Store input and output baud rates. */ obaud = speed_to_baud(cfgetospeed(&tio)); ibaud = speed_to_baud(cfgetispeed(&tio)); if ((r = sshbuf_put_u8(buf, TTY_OP_OSPEED)) != 0 || (r = sshbuf_put_u32(buf, obaud)) != 0 || (r = sshbuf_put_u8(buf, TTY_OP_ISPEED)) != 0 || (r = sshbuf_put_u32(buf, ibaud)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); /* Store values of mode flags. */ #define TTYCHAR(NAME, OP) \ if ((r = sshbuf_put_u8(buf, OP)) != 0 || \ (r = sshbuf_put_u32(buf, tio.c_cc[NAME])) != 0) \ fatal("%s: buffer error: %s", __func__, ssh_err(r)); \ #define SSH_TTYMODE_IUTF8 42 /* for SSH_BUG_UTF8TTYMODE */ #define TTYMODE(NAME, FIELD, OP) \ if (OP == SSH_TTYMODE_IUTF8 && (datafellows & SSH_BUG_UTF8TTYMODE)) { \ debug3("%s: SSH_BUG_UTF8TTYMODE", __func__); \ } else if ((r = sshbuf_put_u8(buf, OP)) != 0 || \ (r = sshbuf_put_u32(buf, ((tio.FIELD & NAME) != 0))) != 0) \ fatal("%s: buffer error: %s", __func__, ssh_err(r)); \ #include "ttymodes.h" #undef TTYCHAR #undef TTYMODE end: /* Mark end of mode data. */ if ((r = sshbuf_put_u8(buf, TTY_OP_END)) != 0 || (r = sshpkt_put_stringb(ssh, buf)) != 0) fatal("%s: packet error: %s", __func__, ssh_err(r)); sshbuf_free(buf); }
/* * Adds an identity to the authentication server. * This call is intended only for use by ssh-add(1) and like applications. */ int ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment, u_int life, u_int confirm) { struct sshbuf *msg; int r, constrained = (life || confirm); u_char type; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; switch (key->type) { #ifdef WITH_SSH1 case KEY_RSA1: type = constrained ? SSH_AGENTC_ADD_RSA_ID_CONSTRAINED : SSH_AGENTC_ADD_RSA_IDENTITY; if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = ssh_encode_identity_rsa1(msg, key->rsa, comment)) != 0) goto out; break; #endif #ifdef WITH_OPENSSL case KEY_RSA: case KEY_RSA_CERT: case KEY_RSA_CERT_V00: case KEY_DSA: case KEY_DSA_CERT: case KEY_DSA_CERT_V00: case KEY_ECDSA: case KEY_ECDSA_CERT: #endif case KEY_ED25519: case KEY_ED25519_CERT: type = constrained ? SSH2_AGENTC_ADD_ID_CONSTRAINED : SSH2_AGENTC_ADD_IDENTITY; if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = ssh_encode_identity_ssh2(msg, key, comment)) != 0) goto out; break; default: r = SSH_ERR_INVALID_ARGUMENT; 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; }
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; }
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; }
char * ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status, OM_uint32 *minor_status) { OM_uint32 lmin; gss_buffer_desc msg = GSS_C_EMPTY_BUFFER; OM_uint32 ctx; struct sshbuf *b; char *ret; int r; if ((b = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if (major_status != NULL) *major_status = ctxt->major; if (minor_status != NULL) *minor_status = ctxt->minor; ctx = 0; /* The GSSAPI error */ do { gss_display_status(&lmin, ctxt->major, GSS_C_GSS_CODE, ctxt->oid, &ctx, &msg); if ((r = sshbuf_put(b, msg.value, msg.length)) != 0 || (r = sshbuf_put_u8(b, '\n')) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); gss_release_buffer(&lmin, &msg); } while (ctx != 0); /* The mechanism specific error */ do { gss_display_status(&lmin, ctxt->minor, GSS_C_MECH_CODE, ctxt->oid, &ctx, &msg); if ((r = sshbuf_put(b, msg.value, msg.length)) != 0 || (r = sshbuf_put_u8(b, '\n')) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); gss_release_buffer(&lmin, &msg); } while (ctx != 0); if ((r = sshbuf_put_u8(b, '\n')) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); ret = xstrdup((const char *)sshbuf_ptr(b)); sshbuf_free(b); return (ret); }
static struct kbdintctxt * kbdint_alloc(const char *devs) { struct kbdintctxt *kbdintctxt; struct sshbuf *b; int i, r; kbdintctxt = xcalloc(1, sizeof(struct kbdintctxt)); if (strcmp(devs, "") == 0) { if ((b = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); for (i = 0; devices[i]; i++) { if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) ? "," : "", devices[i]->name)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } if ((r = sshbuf_put_u8(b, 0)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); kbdintctxt->devices = xstrdup((const char *)sshbuf_ptr(b)); sshbuf_free(b); } else { kbdintctxt->devices = xstrdup(devs); } debug("kbdint_alloc: devices '%s'", kbdintctxt->devices); kbdintctxt->ctxt = NULL; kbdintctxt->device = NULL; kbdintctxt->nreq = 0; return kbdintctxt; }
/* * 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 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); }
static void send_statvfs(u_int32_t id, struct statvfs *st) { struct sshbuf *msg; u_int64_t flag; int r; flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0; flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0; if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_u64(msg, st->f_bsize)) != 0 || (r = sshbuf_put_u64(msg, st->f_frsize)) != 0 || (r = sshbuf_put_u64(msg, st->f_blocks)) != 0 || (r = sshbuf_put_u64(msg, st->f_bfree)) != 0 || (r = sshbuf_put_u64(msg, st->f_bavail)) != 0 || (r = sshbuf_put_u64(msg, st->f_files)) != 0 || (r = sshbuf_put_u64(msg, st->f_ffree)) != 0 || (r = sshbuf_put_u64(msg, st->f_favail)) != 0 || (r = sshbuf_put_u64(msg, FSID_TO_ULONG(st->f_fsid))) != 0 || (r = sshbuf_put_u64(msg, flag)) != 0 || (r = sshbuf_put_u64(msg, st->f_namemax)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(msg); sshbuf_free(msg); }
int sshkey_xmss_serialize_state_opt(const struct sshkey *k, struct sshbuf *b, enum sshkey_serialize_rep opts) { struct ssh_xmss_state *state = k->xmss_state; int r = SSH_ERR_INVALID_ARGUMENT; if (state == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshbuf_put_u8(b, opts)) != 0) return r; switch (opts) { case SSHKEY_SERIALIZE_STATE: r = sshkey_xmss_serialize_state(k, b); break; case SSHKEY_SERIALIZE_FULL: if ((r = sshkey_xmss_serialize_enc_key(k, b)) != 0) break; r = sshkey_xmss_serialize_state(k, b); break; case SSHKEY_SERIALIZE_DEFAULT: r = 0; break; default: r = SSH_ERR_INVALID_ARGUMENT; break; } return r; }
static char * authmethods_get(struct authctxt *authctxt) { struct sshbuf *b; char *list; int i, r; if ((b = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); for (i = 0; authmethods[i] != NULL; i++) { if (strcmp(authmethods[i]->name, "none") == 0) continue; if (authmethods[i]->enabled == NULL || *(authmethods[i]->enabled) == 0) continue; if (!auth2_method_allowed(authctxt, authmethods[i]->name, NULL)) continue; if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) ? "," : "", authmethods[i]->name)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } if ((r = sshbuf_put_u8(b, 0)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); list = xstrdup((const char *)sshbuf_ptr(b)); sshbuf_free(b); return list; }
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); }
void buffer_put_char(Buffer *buffer, int value) { int ret; if ((ret = sshbuf_put_u8(buffer, value)) != 0) fatal("%s: %s", __func__, ssh_err(ret)); }
/* * Removes an identity from the authentication server. * This call is intended only for use by ssh-add(1) and like applications. */ int ssh_remove_identity(int sock, struct sshkey *key) { struct sshbuf *msg; int r; u_char type, *blob = NULL; size_t blen; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; #ifdef WITH_SSH1 if (key->type == KEY_RSA1) { if ((r = sshbuf_put_u8(msg, SSH_AGENTC_REMOVE_RSA_IDENTITY)) != 0 || (r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 || (r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 || (r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0) goto out; } else #endif if (key->type != KEY_UNSPEC) { if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) goto out; if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_REMOVE_IDENTITY)) != 0 || (r = sshbuf_put_string(msg, blob, blen)) != 0) goto out; } else { r = SSH_ERR_INVALID_ARGUMENT; 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: if (blob != NULL) { explicit_bzero(blob, blen); free(blob); } sshbuf_free(msg); return r; }
static int encode_constraints(struct sshbuf *m, u_int life, u_int confirm) { int r; if (life != 0) { if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_LIFETIME)) != 0 || (r = sshbuf_put_u32(m, life)) != 0) goto out; } if (confirm != 0) { if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_CONFIRM)) != 0) goto out; } r = 0; out: return r; }
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; }
/* ask agent to sign data, returns err.h code on error, 0 on success */ int ssh_agent_sign(int sock, struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat) { struct sshbuf *msg; u_char *blob = NULL, type; size_t blen = 0, len = 0; u_int flags = 0; int r = SSH_ERR_INTERNAL_ERROR; if (sigp != NULL) *sigp = NULL; if (lenp != NULL) *lenp = 0; if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; if (compat & SSH_BUG_SIGBLOB) flags |= SSH_AGENT_OLD_SIGNATURE; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) goto out; if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || (r = sshbuf_put_string(msg, blob, blen)) != 0 || (r = sshbuf_put_string(msg, data, datalen)) != 0 || (r = sshbuf_put_u32(msg, flags)) != 0) goto out; if ((r = ssh_request_reply(sock, msg, msg) != 0)) goto out; if ((r = sshbuf_get_u8(msg, &type)) != 0) goto out; if (agent_failed(type)) { r = SSH_ERR_AGENT_FAILURE; goto out; } else if (type != SSH2_AGENT_SIGN_RESPONSE) { r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_get_string(msg, sigp, &len)) != 0) goto out; *lenp = len; r = 0; out: if (blob != NULL) { explicit_bzero(blob, blen); free(blob); } sshbuf_free(msg); return r; }
/* * Updates authctxt->session_info with details of authentication. Should be * whenever an authentication method succeeds. */ void auth2_update_session_info(Authctxt *authctxt, const char *method, const char *submethod) { int r; if (authctxt->session_info == NULL) { if ((authctxt->session_info = sshbuf_new()) == NULL) fatal("%s: sshbuf_new", __func__); } /* Append method[/submethod] */ if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s", method, submethod == NULL ? "" : "/", submethod == NULL ? "" : submethod)) != 0) fatal("%s: append method: %s", __func__, ssh_err(r)); /* Append key if present */ if (authctxt->auth_method_key != NULL) { if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 || (r = sshkey_format_text(authctxt->auth_method_key, authctxt->session_info)) != 0) fatal("%s: append key: %s", __func__, ssh_err(r)); } if (authctxt->auth_method_info != NULL) { /* Ensure no ambiguity here */ if (strchr(authctxt->auth_method_info, '\n') != NULL) fatal("%s: auth_method_info contains \\n", __func__); if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 || (r = sshbuf_putf(authctxt->session_info, "%s", authctxt->auth_method_info)) != 0) { fatal("%s: append method info: %s", __func__, ssh_err(r)); } } if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0) fatal("%s: append: %s", __func__, ssh_err(r)); }
int mm_answer_moduli(int sock, struct sshbuf *m) { DH *dh; int r; u_int min, want, max; if ((r = sshbuf_get_u32(m, &min)) != 0 || (r = sshbuf_get_u32(m, &want)) != 0 || (r = sshbuf_get_u32(m, &max)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("%s: got parameters: %d %d %d", __func__, min, want, max); /* We need to check here, too, in case the child got corrupted */ if (max < min || want < min || max < want) fatal("%s: bad parameters: %d %d %d", __func__, min, want, max); sshbuf_reset(m); dh = choose_dh(min, want, max); if (dh == NULL) { if ((r = sshbuf_put_u8(m, 0)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); return (0); } else { /* Send first bignum */ if ((r = sshbuf_put_u8(m, 1)) != 0 || (r = sshbuf_put_bignum2(m, dh->p)) != 0 || (r = sshbuf_put_bignum2(m, dh->g)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); DH_free(dh); } mm_request_send(sock, MONITOR_ANS_MODULI, m); 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)); }
static void send_data_or_handle(char type, u_int32_t id, const u_char *data, int dlen) { struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_string(msg, data, dlen)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(msg); sshbuf_free(msg); }
static void send_attrib(u_int32_t id, const Attrib *a) { struct sshbuf *msg; int r; debug("request %u: sent attrib have 0x%x", id, a->flags); if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u8(msg, SSH2_FXP_ATTRS)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = encode_attrib(msg, a)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(msg); sshbuf_free(msg); }
int sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m, int untrusted) { int r = SSH_ERR_INTERNAL_ERROR; /* Flag and simple integer options */ if ((r = sshbuf_put_u8(m, opts->permit_port_forwarding_flag)) != 0 || (r = sshbuf_put_u8(m, opts->permit_agent_forwarding_flag)) != 0 || (r = sshbuf_put_u8(m, opts->permit_x11_forwarding_flag)) != 0 || (r = sshbuf_put_u8(m, opts->permit_pty_flag)) != 0 || (r = sshbuf_put_u8(m, opts->permit_user_rc)) != 0 || (r = sshbuf_put_u8(m, opts->restricted)) != 0 || (r = sshbuf_put_u8(m, opts->cert_authority)) != 0 || (r = sshbuf_put_u64(m, opts->valid_before)) != 0) return r; /* tunnel number can be negative to indicate "unset" */ if ((r = sshbuf_put_u8(m, opts->force_tun_device == -1)) != 0 || (r = sshbuf_put_u32(m, (opts->force_tun_device < 0) ? 0 : (u_int)opts->force_tun_device)) != 0) return r; /* String options; these may be NULL */ if ((r = serialise_nullable_string(m, untrusted ? "yes" : opts->cert_principals)) != 0 || (r = serialise_nullable_string(m, untrusted ? "true" : opts->force_command)) != 0 || (r = serialise_nullable_string(m, untrusted ? NULL : opts->required_from_host_cert)) != 0 || (r = serialise_nullable_string(m, untrusted ? NULL : opts->required_from_host_keys)) != 0) return r; /* Array options */ if ((r = serialise_array(m, opts->env, untrusted ? 0 : opts->nenv)) != 0 || (r = serialise_array(m, opts->permitopen, untrusted ? 0 : opts->npermitopen)) != 0) return r; /* success */ return 0; }
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); }
/* * Reassemble an argument vector into a string, quoting and escaping as * necessary. Caller must free returned string. */ static char * assemble_argv(int argc, char **argv) { int i, j, ws, r; char c, *ret; struct sshbuf *buf, *arg; if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); for (i = 0; i < argc; i++) { ws = 0; sshbuf_reset(arg); for (j = 0; argv[i][j] != '\0'; j++) { r = 0; c = argv[i][j]; switch (c) { case ' ': case '\t': ws = 1; r = sshbuf_put_u8(arg, c); break; case '\\': case '\'': case '"': if ((r = sshbuf_put_u8(arg, '\\')) != 0) break; /* FALLTHROUGH */ default: r = sshbuf_put_u8(arg, c); break; } if (r != 0) fatal("%s: sshbuf_put_u8: %s", __func__, ssh_err(r)); } if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) || (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) || (r = sshbuf_putb(buf, arg)) != 0 || (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0)) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL) fatal("%s: malloc failed", __func__); memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf)); ret[sshbuf_len(buf)] = '\0'; sshbuf_free(buf); sshbuf_free(arg); return ret; }
struct sshbuf * load_text_file(const char *name) { struct sshbuf *ret = load_file(name); const u_char *p; /* Trim whitespace at EOL */ for (p = sshbuf_ptr(ret); sshbuf_len(ret) > 0;) { if (p[sshbuf_len(ret) - 1] == '\r' || p[sshbuf_len(ret) - 1] == '\t' || p[sshbuf_len(ret) - 1] == ' ' || p[sshbuf_len(ret) - 1] == '\n') ASSERT_INT_EQ(sshbuf_consume_end(ret, 1), 0); else break; } /* \0 terminate */ ASSERT_INT_EQ(sshbuf_put_u8(ret, 0), 0); return ret; }
int sshkey_xmss_serialize_pk_info(const struct sshkey *k, struct sshbuf *b, enum sshkey_serialize_rep opts) { struct ssh_xmss_state *state = k->xmss_state; u_char have_info = 1; u_int32_t idx; int r; if (state == NULL) return SSH_ERR_INVALID_ARGUMENT; if (opts != SSHKEY_SERIALIZE_INFO) return 0; idx = k->xmss_sk ? PEEK_U32(k->xmss_sk) : state->idx; if ((r = sshbuf_put_u8(b, have_info)) != 0 || (r = sshbuf_put_u32(b, idx)) != 0 || (r = sshbuf_put_u32(b, state->maxidx)) != 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); }