static int monitor_valid_userblob(u_char *data, u_int datalen) { Buffer b; u_char *p; char *userstyle, *cp; u_int len; int fail = 0; buffer_init(&b); buffer_append(&b, data, datalen); if (datafellows & SSH_OLD_SESSIONID) { p = buffer_ptr(&b); len = buffer_len(&b); if ((session_id2 == NULL) || (len < session_id2_len) || (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) fail++; buffer_consume(&b, session_id2_len); } else { p = buffer_get_string(&b, &len); if ((session_id2 == NULL) || (len != session_id2_len) || (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) fail++; free(p); } if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) fail++; cp = buffer_get_cstring(&b, NULL); xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); if (strcmp(userstyle, cp) != 0) { logit("wrong user name passed to monitor: " "expected %s != %.100s", userstyle, cp); fail++; } free(userstyle); free(cp); buffer_skip_string(&b); if (datafellows & SSH_BUG_PKAUTH) { if (!buffer_get_char(&b)) fail++; } else { cp = buffer_get_cstring(&b, NULL); if (strcmp("publickey", cp) != 0) fail++; free(cp); if (!buffer_get_char(&b)) fail++; buffer_skip_string(&b); } buffer_skip_string(&b); if (buffer_len(&b) != 0) fail++; buffer_free(&b); return (fail == 0); }
static int monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, char *chost) { Buffer b; char *p, *userstyle; u_int len; int fail = 0; buffer_init(&b); buffer_append(&b, data, datalen); p = buffer_get_string(&b, &len); if ((session_id2 == NULL) || (len != session_id2_len) || (timingsafe_bcmp(p, session_id2, session_id2_len) != 0)) fail++; free(p); if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) fail++; p = buffer_get_cstring(&b, NULL); xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); if (strcmp(userstyle, p) != 0) { logit("wrong user name passed to monitor: expected %s != %.100s", userstyle, p); fail++; } free(userstyle); free(p); buffer_skip_string(&b); /* service */ p = buffer_get_cstring(&b, NULL); if (strcmp(p, "hostbased") != 0) fail++; free(p); buffer_skip_string(&b); /* pkalg */ buffer_skip_string(&b); /* pkblob */ /* verify client host, strip trailing dot if necessary */ p = buffer_get_string(&b, NULL); if (((len = strlen(p)) > 0) && p[len - 1] == '.') p[len - 1] = '\0'; if (strcmp(p, chost) != 0) fail++; free(p); /* verify client user */ p = buffer_get_string(&b, NULL); if (strcmp(p, cuser) != 0) fail++; free(p); if (buffer_len(&b) != 0) fail++; buffer_free(&b); return (fail == 0); }
void decode_sa(Buffer *b, struct shaft_sa *sa) { sa->status = buffer_get_int(b); sa->src = buffer_get_cstring(b, NULL); sa->dst = buffer_get_cstring(b, NULL); sa->akey1 = buffer_get_cstring(b, NULL); sa->akey2 = buffer_get_cstring(b, NULL); sa->ekey1 = buffer_get_cstring(b, NULL); sa->ekey2 = buffer_get_cstring(b, NULL); sa->spi1 = buffer_get_cstring(b, NULL); sa->spi2 = buffer_get_cstring(b, NULL); }
struct shaft_conn * do_init(int fd_in, int fd_out, struct shaft_flow *flow) { u_int type, version; Buffer msg; struct shaft_conn *ret; buffer_init(&msg); buffer_put_char(&msg, SHAFT_INIT); buffer_put_int(&msg, SHAFT_VERSION); buffer_put_cstring(&msg, flow->local); send_msg(fd_out, &msg); buffer_clear(&msg); get_msg(fd_in, &msg); /* Expecting a VERSION reply */ if ((type = buffer_get_char(&msg)) != SHAFT_VERSION) { error("Invalid packet back from SHAFT_INIT (type %u)", version); buffer_free(&msg); return(NULL); } version = buffer_get_int(&msg); flow->dst = buffer_get_cstring(&msg, NULL); if (flow->dst == NULL) { error("Invalid packet back from SHAFT_INIT remote addr is null"); buffer_free(&msg); return(NULL); } debug2("Remote version: %u", version); debug2("Remote Address: %s", flow->dst); buffer_free(&msg); ret = xmalloc(sizeof(*ret)); ret->fd_in = fd_in; ret->fd_out = fd_out; ret->version = version; ret->msg_id = 1; return(ret); }
int ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { Buffer b; const EVP_MD *evp_md; EVP_MD_CTX md; char *ktype; u_char digest[EVP_MAX_MD_SIZE], *sigblob; u_int len, dlen, modlen; int rlen, ret, nid; if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA && key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00)) { error("ssh_rsa_verify: no RSA key"); return -1; } if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { error("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits", BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); return -1; } buffer_init(&b); buffer_append(&b, signature, signaturelen); ktype = buffer_get_cstring(&b, NULL); if (strcmp("ssh-rsa", ktype) != 0) { error("ssh_rsa_verify: cannot handle type %s", ktype); buffer_free(&b); free(ktype); return -1; } free(ktype); sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); buffer_free(&b); if (rlen != 0) { error("ssh_rsa_verify: remaining bytes in signature %d", rlen); free(sigblob); return -1; } /* RSA_verify expects a signature of RSA_size */ modlen = RSA_size(key->rsa); if (len > modlen) { error("ssh_rsa_verify: len %u > modlen %u", len, modlen); free(sigblob); return -1; } else if (len < modlen) { u_int diff = modlen - len; debug("ssh_rsa_verify: add padding: modlen %u > len %u", modlen, len); sigblob = xrealloc(sigblob, 1, modlen); memmove(sigblob + diff, sigblob, len); memset(sigblob, 0, diff); len = modlen; } nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid); free(sigblob); return -1; } EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); memset(digest, 'd', sizeof(digest)); memset(sigblob, 's', len); free(sigblob); debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); return ret; }
int ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { DSA_SIG *sig; const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; u_char digest[EVP_MAX_MD_SIZE], *sigblob; u_int len, dlen; int rlen, ret; Buffer b; if (key == NULL || key->dsa == NULL || (key->type != KEY_DSA && key->type != KEY_DSA_CERT && key->type != KEY_DSA_CERT_V00)) { error("ssh_dss_verify: no DSA key"); return -1; } /* fetch signature */ if (datafellows & SSH_BUG_SIGBLOB) { sigblob = xmalloc(signaturelen); memcpy(sigblob, signature, signaturelen); len = signaturelen; } else { /* ietf-drafts */ char *ktype; buffer_init(&b); buffer_append(&b, signature, signaturelen); ktype = buffer_get_cstring(&b, NULL); if (strcmp("ssh-dss", ktype) != 0) { error("ssh_dss_verify: cannot handle type %s", ktype); buffer_free(&b); xfree(ktype); return -1; } xfree(ktype); sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); buffer_free(&b); if (rlen != 0) { error("ssh_dss_verify: " "remaining bytes in signature %d", rlen); xfree(sigblob); return -1; } } if (len != SIGBLOB_LEN) { fatal("bad sigbloblen %u != SIGBLOB_LEN", len); } /* parse signature */ if ((sig = DSA_SIG_new()) == NULL) fatal("ssh_dss_verify: DSA_SIG_new failed"); if ((sig->r = BN_new()) == NULL) fatal("ssh_dss_verify: BN_new failed"); if ((sig->s = BN_new()) == NULL) fatal("ssh_dss_verify: BN_new failed"); if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) || (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) fatal("ssh_dss_verify: BN_bin2bn failed"); /* clean up */ memset(sigblob, 0, len); xfree(sigblob); /* sha1 the data */ EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = DSA_do_verify(digest, dlen, sig, key->dsa); memset(digest, 'd', sizeof(digest)); DSA_SIG_free(sig); debug("ssh_dss_verify: signature %s", ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); return ret; }
int ssh_ed25519_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { Buffer b; char *ktype; u_char *sigblob, *sm, *m; u_int len; unsigned long long smlen, mlen; int rlen, ret; if (key == NULL || key_type_plain(key->type) != KEY_ED25519 || key->ed25519_pk == NULL) { error("%s: no ED25519 key", __func__); return -1; } buffer_init(&b); buffer_append(&b, signature, signaturelen); ktype = buffer_get_cstring(&b, NULL); if (strcmp("ssh-ed25519", ktype) != 0) { error("%s: cannot handle type %s", __func__, ktype); buffer_free(&b); free(ktype); return -1; } free(ktype); sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); buffer_free(&b); if (rlen != 0) { error("%s: remaining bytes in signature %d", __func__, rlen); free(sigblob); return -1; } if (len > crypto_sign_ed25519_BYTES) { error("%s: len %u > crypto_sign_ed25519_BYTES %u", __func__, len, crypto_sign_ed25519_BYTES); free(sigblob); return -1; } smlen = len + datalen; sm = xmalloc(smlen); memcpy(sm, sigblob, len); memcpy(sm+len, data, datalen); mlen = smlen; m = xmalloc(mlen); if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen, key->ed25519_pk)) != 0) { debug2("%s: crypto_sign_ed25519_open failed: %d", __func__, ret); } if (ret == 0 && mlen != datalen) { debug2("%s: crypto_sign_ed25519_open " "mlen != datalen (%llu != %u)", __func__, mlen, datalen); ret = -1; } /* XXX compare 'm' and 'data' ? */ explicit_bzero(sigblob, len); explicit_bzero(sm, smlen); explicit_bzero(m, smlen); /* NB. mlen may be invalid if ret != 0 */ free(sigblob); free(sm); free(m); debug("%s: signature %scorrect", __func__, (ret != 0) ? "in" : ""); /* translate return code carefully */ return (ret == 0) ? 1 : -1; }
int ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { Buffer b; const EVP_MD *evp_md; EVP_MD_CTX md; char *ktype; u_char *sigblob; u_int len, modlen; #ifdef USE_LEGACY_RSA_VERIFY u_char digest[EVP_MAX_MD_SIZE]; u_int dlen; #endif int rlen, ret, nid; if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA && key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00)) { error("ssh_rsa_verify: no RSA key"); return -1; } if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { error("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits", BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); return -1; } buffer_init(&b); buffer_append(&b, signature, signaturelen); ktype = buffer_get_cstring(&b, NULL); if (strcmp("ssh-rsa", ktype) != 0) { error("ssh_rsa_verify: cannot handle type %s", ktype); buffer_free(&b); xfree(ktype); return -1; } xfree(ktype); sigblob = buffer_get_string(&b, &len); rlen = buffer_len(&b); buffer_free(&b); if (rlen != 0) { error("ssh_rsa_verify: remaining bytes in signature %d", rlen); xfree(sigblob); return -1; } /* RSA_verify expects a signature of RSA_size */ modlen = RSA_size(key->rsa); if (len > modlen) { error("ssh_rsa_verify: len %u > modlen %u", len, modlen); xfree(sigblob); return -1; } else if (len < modlen) { u_int diff = modlen - len; debug("ssh_rsa_verify: add padding: modlen %u > len %u", modlen, len); sigblob = xrealloc(sigblob, 1, modlen); memmove(sigblob + diff, sigblob, len); memset(sigblob, 0, diff); len = modlen; } nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid); xfree(sigblob); return -1; } #ifdef USE_LEGACY_RSA_VERIFY EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); memset(digest, 'd', sizeof(digest)); #else /*ndef USE_LEGACY_RSA_VERIFY*/ { EVP_PKEY *pkey; ret = -1; pkey = EVP_PKEY_new(); if (pkey == NULL) { error("%s: out of memory", __func__); goto done; } EVP_PKEY_set1_RSA(pkey, key->rsa); ssh_EVP_MD_CTX_init(&md); ret = ssh_EVP_VerifyInit(&md, evp_md); if (ret <= 0) { char ebuf[256]; error("%s: EVP_VerifyInit fail with errormsg='%.*s'" , __func__ , (int)sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); goto clean; } ret = ssh_EVP_VerifyUpdate(&md, data, datalen); if (ret <= 0) { char ebuf[256]; error("%s: EVP_VerifyUpdate fail with errormsg='%.*s'" , __func__ , (int)sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); goto clean; } ret = EVP_VerifyFinal(&md, sigblob, len, pkey); if (ret <= 0) { char ebuf[256]; error("%s: EVP_VerifyFinal fail with errormsg='%.*s'" , __func__ , (int)sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); goto clean; } clean: ssh_EVP_MD_CTX_cleanup(&md); done: if (pkey != NULL) EVP_PKEY_free(pkey); } #endif /*ndef USE_LEGACY_RSA_VERIFY*/ memset(sigblob, 's', len); xfree(sigblob); debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); return ret; }