int mm_answer_keyverify(int sock, Buffer *m) { Key *key; u_char *signature, *data, *blob; u_int signaturelen, datalen, bloblen; int verified = 0; int valid_data = 0; blob = buffer_get_string(m, &bloblen); signature = buffer_get_string(m, &signaturelen); data = buffer_get_string(m, &datalen); if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) fatal("%s: bad key, not previously allowed", __func__); key = key_from_blob(blob, bloblen); if (key == NULL) fatal("%s: bad public key blob", __func__); switch (key_blobtype) { case MM_USERKEY: valid_data = monitor_valid_userblob(data, datalen); break; case MM_HOSTKEY: valid_data = monitor_valid_hostbasedblob(data, datalen, hostbased_cuser, hostbased_chost); break; default: valid_data = 0; break; } if (!valid_data) fatal("%s: bad signature data blob", __func__); verified = key_verify(key, signature, signaturelen, data, datalen); debug3("%s: key %p signature %s", __func__, key, (verified == 1) ? "verified" : "unverified"); /* If auth was successful then record key to ensure it isn't reused */ if (verified == 1 && key_blobtype == MM_USERKEY) auth2_record_userkey(authctxt, key); else key_free(key); free(blob); free(signature); free(data); auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; monitor_reset_key_state(); buffer_clear(m); buffer_put_int(m, verified); mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); return (verified == 1); }
int mm_answer_rsa_keyallowed(int sock, struct sshbuf *m) { BIGNUM *client_n; struct sshkey *key = NULL; u_char *blob = NULL; size_t blen = 0; int r, allowed = 0; debug3("%s entering", __func__); auth_method = "rsa"; if (options.rsa_authentication && authctxt->valid) { if ((client_n = BN_new()) == NULL) fatal("%s: BN_new", __func__); if ((r = sshbuf_get_bignum2(m, client_n)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key); BN_clear_free(client_n); } sshbuf_reset(m); if ((r = sshbuf_put_u32(m, allowed)) != 0 || (r = sshbuf_put_u32(m, forced_command != NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); /* clear temporarily storage (used by generate challenge) */ monitor_reset_key_state(); if (allowed && key != NULL) { key->type = KEY_RSA; /* cheat for key_to_blob */ if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) fatal("%s: key_to_blob failed: %s", __func__, ssh_err(r)); if ((r = sshbuf_put_string(m, blob, blen)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); /* Save temporarily for comparison in verify */ key_blob = blob; key_bloblen = blen; key_blobtype = MM_RSAUSERKEY; } if (key != NULL) sshkey_free(key); mm_request_send(sock, MONITOR_ANS_RSAKEYALLOWED, m); monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0); return (0); }
int mm_answer_rsa_response(int sock, struct sshbuf *m) { struct sshkey *key = NULL; u_char *blob, *response; size_t blen, len; int r, success; debug3("%s entering", __func__); if (!authctxt->valid) fatal("%s: authctxt not valid", __func__); if (ssh1_challenge == NULL) fatal("%s: no ssh1_challenge", __func__); if ((r = sshbuf_get_string(m, &blob, &blen)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (!monitor_allowed_key(blob, blen)) fatal("%s: bad key, not previously allowed", __func__); if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) fatal("%s: key type mismatch: %d", __func__, key_blobtype); if ((r = sshkey_from_blob(blob, blen, &key)) != 0) fatal("%s: received bad key: %s", __func__, ssh_err(r)); if ((r = sshbuf_get_string(m, &response, &len)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (len != 16) fatal("%s: received bad response to challenge", __func__); success = auth_rsa_verify_response(key, ssh1_challenge, response); free(blob); sshkey_free(key); free(response); auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; /* reset state */ BN_clear_free(ssh1_challenge); ssh1_challenge = NULL; monitor_reset_key_state(); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, success)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(sock, MONITOR_ANS_RSARESPONSE, m); return (success); }
int mm_answer_rsa_keyallowed(int socket, Buffer *m) { BIGNUM *client_n; Key *key = NULL; u_char *blob = NULL; u_int blen = 0; int allowed = 0; debug3("%s entering", __func__); if (options.rsa_authentication && authctxt->valid) { if ((client_n = BN_new()) == NULL) fatal("%s: BN_new", __func__); buffer_get_bignum2(m, client_n); allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key); BN_clear_free(client_n); } buffer_clear(m); buffer_put_int(m, allowed); /* clear temporarily storage (used by generate challenge) */ monitor_reset_key_state(); if (allowed && key != NULL) { key->type = KEY_RSA; /* cheat for key_to_blob */ if (key_to_blob(key, &blob, &blen) == 0) fatal("%s: key_to_blob failed", __func__); buffer_put_string(m, blob, blen); /* Save temporarily for comparison in verify */ key_blob = blob; key_bloblen = blen; key_blobtype = MM_RSAUSERKEY; key_free(key); } mm_append_debug(m); mm_request_send(socket, MONITOR_ANS_RSAKEYALLOWED, m); monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0); return (0); }
int mm_answer_rsa_response(int socket, Buffer *m) { Key *key = NULL; u_char *blob, *response; u_int blen, len; int success; debug3("%s entering", __func__); if (!authctxt->valid) fatal("%s: authctxt not valid", __func__); if (ssh1_challenge == NULL) fatal("%s: no ssh1_challenge", __func__); blob = buffer_get_string(m, &blen); if (!monitor_allowed_key(blob, blen)) fatal("%s: bad key, not previously allowed", __func__); if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) fatal("%s: key type mismatch: %d", __func__, key_blobtype); if ((key = key_from_blob(blob, blen)) == NULL) fatal("%s: received bad key", __func__); response = buffer_get_string(m, &len); if (len != 16) fatal("%s: received bad response to challenge", __func__); success = auth_rsa_verify_response(key, ssh1_challenge, response); xfree(blob); key_free(key); xfree(response); auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; /* reset state */ BN_clear_free(ssh1_challenge); ssh1_challenge = NULL; monitor_reset_key_state(); buffer_clear(m); buffer_put_int(m, success); mm_request_send(socket, MONITOR_ANS_RSARESPONSE, m); return (success); }
int mm_answer_keyallowed(int sock, Buffer *m) { Key *key; char *cuser, *chost; u_char *blob; u_int bloblen; enum mm_keytype type = 0; int allowed = 0; debug3("%s entering", __func__); type = buffer_get_int(m); cuser = buffer_get_string(m, NULL); chost = buffer_get_string(m, NULL); blob = buffer_get_string(m, &bloblen); key = key_from_blob(blob, bloblen); if ((compat20 && type == MM_RSAHOSTKEY) || (!compat20 && type != MM_RSAHOSTKEY)) fatal("%s: key type and protocol mismatch", __func__); debug3("%s: key_from_blob: %p", __func__, key); if (key != NULL && authctxt->valid) { switch (type) { case MM_USERKEY: allowed = options.pubkey_authentication && user_key_allowed(authctxt->pw, key); break; case MM_HOSTKEY: allowed = options.hostbased_authentication && hostbased_key_allowed(authctxt->pw, cuser, chost, key); break; case MM_RSAHOSTKEY: key->type = KEY_RSA1; /* XXX */ allowed = options.rhosts_rsa_authentication && auth_rhosts_rsa_key_allowed(authctxt->pw, cuser, chost, key); break; default: fatal("%s: unknown key type %d", __func__, type); break; } } if (key != NULL) key_free(key); /* clear temporarily storage (used by verify) */ monitor_reset_key_state(); if (allowed) { /* Save temporarily for comparison in verify */ key_blob = blob; key_bloblen = bloblen; key_blobtype = type; hostbased_cuser = cuser; hostbased_chost = chost; } debug3("%s: key %p is %s", __func__, key, allowed ? "allowed" : "disallowed"); buffer_clear(m); buffer_put_int(m, allowed); buffer_put_int(m, forced_command != NULL); mm_append_debug(m); mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); if (type == MM_RSAHOSTKEY) monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); return (0); }
int mm_answer_keyallowed(int sock, struct sshbuf *m) { struct ssh *ssh = active_state; /* XXX */ struct sshkey *key; char *cuser, *chost; u_char *blob; size_t bloblen; enum mm_keytype type = 0; int r, allowed = 0; debug3("%s entering", __func__); if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_cstring(m, &cuser, NULL)) != 0 || (r = sshbuf_get_cstring(m, &chost, NULL)) != 0 || (r = sshbuf_get_string(m, &blob, &bloblen)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) fatal("%s: cannot parse key: %s", __func__, ssh_err(r)); if ((compat20 && type == MM_RSAHOSTKEY) || (!compat20 && type != MM_RSAHOSTKEY)) fatal("%s: key type and protocol mismatch", __func__); if (key != NULL && authctxt->valid) { /* These should not make it past the privsep child */ if (sshkey_type_plain(key->type) == KEY_RSA && (ssh->compat & SSH_BUG_RSASIGMD5) != 0) fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__); switch (type) { case MM_USERKEY: allowed = options.pubkey_authentication && !auth2_userkey_already_used(authctxt, key) && match_pattern_list(sshkey_ssh_name(key), options.pubkey_key_types, strlen(options.pubkey_key_types), 0) == 1 && user_key_allowed(authctxt->pw, key); pubkey_auth_info(authctxt, key, NULL); auth_method = "publickey"; if (options.pubkey_authentication && allowed != 1) auth_clear_options(); break; case MM_HOSTKEY: allowed = options.hostbased_authentication && match_pattern_list(sshkey_ssh_name(key), options.hostbased_key_types, strlen(options.hostbased_key_types), 0) == 1 && hostbased_key_allowed(authctxt->pw, cuser, chost, key); pubkey_auth_info(authctxt, key, "client user \"%.100s\", client host \"%.100s\"", cuser, chost); auth_method = "hostbased"; break; #ifdef WITH_SSH1 case MM_RSAHOSTKEY: key->type = KEY_RSA1; /* XXX */ allowed = options.rhosts_rsa_authentication && auth_rhosts_rsa_key_allowed(authctxt->pw, cuser, chost, key); if (options.rhosts_rsa_authentication && allowed != 1) auth_clear_options(); auth_method = "rsa"; break; #endif default: fatal("%s: unknown key type %d", __func__, type); break; } } if (key != NULL) sshkey_free(key); /* clear temporarily storage (used by verify) */ monitor_reset_key_state(); if (allowed) { /* Save temporarily for comparison in verify */ key_blob = blob; key_bloblen = bloblen; key_blobtype = type; hostbased_cuser = cuser; hostbased_chost = chost; } else { /* Log failed attempt */ auth_log(authctxt, 0, 0, auth_method, NULL); free(blob); free(cuser); free(chost); } debug3("%s: key %p is %s", __func__, key, allowed ? "allowed" : "not allowed"); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, allowed)) != 0 || (r = sshbuf_put_u32(m, forced_command != NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); if (type == MM_RSAHOSTKEY) monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); return (0); }
int mm_answer_keyverify(int sock, struct sshbuf *m) { struct sshkey *key; u_char *signature, *data, *blob; size_t signaturelen, datalen, bloblen; int r, ret, valid_data = 0; if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || (r = sshbuf_get_string(m, &data, &datalen)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) fatal("%s: bad key, not previously allowed", __func__); if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) fatal("%s: bad public key blob: %s", __func__, ssh_err(r)); switch (key_blobtype) { case MM_USERKEY: valid_data = monitor_valid_userblob(data, datalen); break; case MM_HOSTKEY: valid_data = monitor_valid_hostbasedblob(data, datalen, hostbased_cuser, hostbased_chost); break; default: valid_data = 0; break; } if (!valid_data) fatal("%s: bad signature data blob", __func__); ret = sshkey_verify(key, signature, signaturelen, data, datalen, active_state->compat); debug3("%s: key %p signature %s", __func__, key, (r == 0) ? "verified" : "unverified"); /* If auth was successful then record key to ensure it isn't reused */ if (ret == 0) auth2_record_userkey(authctxt, key); else sshkey_free(key); free(blob); free(signature); free(data); auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; monitor_reset_key_state(); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, ret)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); return ret == 0; }
int mm_answer_keyverify(int sock, struct sshbuf *m) { struct sshkey *key; u_char *signature, *data, *blob; size_t signaturelen, datalen, bloblen; int r, ret, valid_data = 0, encoded_ret; if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || (r = sshbuf_get_string(m, &data, &datalen)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) fatal("%s: bad key, not previously allowed", __func__); /* XXX use sshkey_froms here; need to change key_blob, etc. */ if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0) fatal("%s: bad public key blob: %s", __func__, ssh_err(r)); switch (key_blobtype) { case MM_USERKEY: valid_data = monitor_valid_userblob(data, datalen); auth_method = "publickey"; break; case MM_HOSTKEY: valid_data = monitor_valid_hostbasedblob(data, datalen, hostbased_cuser, hostbased_chost); auth_method = "hostbased"; break; default: valid_data = 0; break; } if (!valid_data) fatal("%s: bad signature data blob", __func__); ret = sshkey_verify(key, signature, signaturelen, data, datalen, active_state->compat); debug3("%s: %s %p signature %s", __func__, auth_method, key, (ret == 0) ? "verified" : "unverified"); auth2_record_key(authctxt, ret == 0, key); free(blob); free(signature); free(data); monitor_reset_key_state(); sshkey_free(key); sshbuf_reset(m); /* encode ret != 0 as positive integer, since we're sending u32 */ encoded_ret = (ret != 0); if ((r = sshbuf_put_u32(m, encoded_ret)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); return ret == 0; }
int mm_answer_keyallowed(int sock, Buffer *m) { struct sshkey *key; char *cuser, *chost; u_char *blob; u_int bloblen, pubkey_auth_attempt; enum mm_keytype type = 0; int allowed = 0; debug3("%s entering", __func__); type = buffer_get_int(m); cuser = buffer_get_string(m, NULL); chost = buffer_get_string(m, NULL); blob = buffer_get_string(m, &bloblen); pubkey_auth_attempt = buffer_get_int(m); key = key_from_blob(blob, bloblen); debug3("%s: key_from_blob: %p", __func__, key); if (key != NULL && authctxt->valid) { /* These should not make it past the privsep child */ if (key_type_plain(key->type) == KEY_RSA && (datafellows & SSH_BUG_RSASIGMD5) != 0) fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__); switch (type) { case MM_USERKEY: allowed = options.pubkey_authentication && !auth2_key_already_used(authctxt, key) && match_pattern_list(sshkey_ssh_name(key), options.pubkey_key_types, 0) == 1 && user_key_allowed(authctxt->pw, key, pubkey_auth_attempt); auth_method = "publickey"; if (options.pubkey_authentication && (!pubkey_auth_attempt || allowed != 1)) auth_clear_options(); break; case MM_HOSTKEY: allowed = options.hostbased_authentication && !auth2_key_already_used(authctxt, key) && match_pattern_list(sshkey_ssh_name(key), options.hostbased_key_types, 0) == 1 && hostbased_key_allowed(authctxt->pw, cuser, chost, key); auth2_record_info(authctxt, "client user \"%.100s\", client host \"%.100s\"", cuser, chost); auth_method = "hostbased"; break; default: fatal("%s: unknown key type %d", __func__, type); break; } } debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed"); auth2_record_key(authctxt, 0, key); sshkey_free(key); /* clear temporarily storage (used by verify) */ monitor_reset_key_state(); if (allowed) { /* Save temporarily for comparison in verify */ key_blob = blob; key_bloblen = bloblen; key_blobtype = type; hostbased_cuser = cuser; hostbased_chost = chost; } else { /* Log failed attempt */ auth_log(authctxt, 0, 0, auth_method, NULL); free(blob); free(cuser); free(chost); } buffer_clear(m); buffer_put_int(m, allowed); buffer_put_int(m, forced_command != NULL); mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); return (0); }