static int agent_talk(struct ssh_session_struct *session, struct ssh_buffer_struct *request, struct ssh_buffer_struct *reply) { uint32_t len = 0; uint8_t payload[1024] = {0}; len = buffer_get_len(request); ssh_log(session, SSH_LOG_PACKET, "agent_talk - len of request: %u", len); agent_put_u32(payload, len); /* send length and then the request packet */ if (atomicio(session->agent->sock, payload, 4, 0) == 4) { if (atomicio(session->agent->sock, buffer_get_rest(request), len, 0) != len) { ssh_log(session, SSH_LOG_PACKET, "atomicio sending request failed: %s", strerror(errno)); return -1; } } else { ssh_log(session, SSH_LOG_PACKET, "atomicio sending request length failed: %s", strerror(errno)); return -1; } /* wait for response, read the length of the response packet */ if (atomicio(session->agent->sock, payload, 4, 1) != 4) { ssh_log(session, SSH_LOG_PACKET, "atomicio read response length failed: %s", strerror(errno)); return -1; } len = agent_get_u32(payload); if (len > 256 * 1024) { ssh_set_error(session, SSH_FATAL, "Authentication response too long: %u", len); return -1; } ssh_log(session, SSH_LOG_PACKET, "agent_talk - response length: %u", len); while (len > 0) { size_t n = len; if (n > sizeof(payload)) { n = sizeof(payload); } if (atomicio(session->agent->sock, payload, n, 1) != n) { ssh_log(session, SSH_LOG_RARE, "Error reading response from authentication socket."); return -1; } if (buffer_add_data(reply, payload, n) < 0) { ssh_log(session, SSH_LOG_FUNCTIONS, "Not enough space"); return -1; } len -= n; } return 0; }
int ssh_agent_get_ident_count(struct ssh_session_struct *session) { ssh_buffer request = NULL; ssh_buffer reply = NULL; unsigned int type = 0; unsigned int c1 = 0, c2 = 0; uint32_t buf = 0; switch (session->version) { case 1: c1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; c2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; break; case 2: c1 = SSH2_AGENTC_REQUEST_IDENTITIES; c2 = SSH2_AGENT_IDENTITIES_ANSWER; break; default: return 0; } /* send message to the agent requesting the list of identities */ request = ssh_buffer_new(); if (buffer_add_u8(request, c1) < 0) { ssh_set_error(session, SSH_FATAL, "Not enough space"); return -1; } reply = ssh_buffer_new(); if (reply == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); return -1; } if (agent_talk(session, request, reply) < 0) { ssh_buffer_free(request); return 0; } ssh_buffer_free(request); /* get message type and verify the answer */ buffer_get_u8(reply, (uint8_t *) &type); SSH_LOG(session, SSH_LOG_WARN, "Answer type: %d, expected answer: %d", type, c2); if (agent_failed(type)) { return 0; } else if (type != c2) { ssh_set_error(session, SSH_FATAL, "Bad authentication reply message type: %d", type); return -1; } buffer_get_u32(reply, &buf); session->agent->count = agent_get_u32((uint8_t*)&buf); SSH_LOG(session, SSH_LOG_DEBUG, "Agent count: %d", session->agent->count); if (session->agent->count > 1024) { ssh_set_error(session, SSH_FATAL, "Too many identities in authentication reply: %d", session->agent->count); ssh_buffer_free(reply); return -1; } if (session->agent->ident) { buffer_reinit(session->agent->ident); } session->agent->ident = reply; return session->agent->count; }