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; }
ssh_string ssh_agent_sign_data(ssh_session session, const ssh_key pubkey, struct ssh_buffer_struct *data) { ssh_buffer request; ssh_buffer reply; ssh_string key_blob; ssh_string sig_blob; int type = SSH2_AGENT_FAILURE; int flags = 0; uint32_t dlen; int rc; request = ssh_buffer_new(); if (request == NULL) { return NULL; } /* create request */ if (buffer_add_u8(request, SSH2_AGENTC_SIGN_REQUEST) < 0) { return NULL; } rc = ssh_pki_export_pubkey_blob(pubkey, &key_blob); if (rc < 0) { ssh_buffer_free(request); return NULL; } /* adds len + blob */ rc = buffer_add_ssh_string(request, key_blob); ssh_string_free(key_blob); if (rc < 0) { ssh_buffer_free(request); return NULL; } /* Add data */ dlen = buffer_get_rest_len(data); if (buffer_add_u32(request, htonl(dlen)) < 0) { ssh_buffer_free(request); return NULL; } if (buffer_add_data(request, buffer_get_rest(data), dlen) < 0) { ssh_buffer_free(request); return NULL; } if (buffer_add_u32(request, htonl(flags)) < 0) { ssh_buffer_free(request); return NULL; } reply = ssh_buffer_new(); if (reply == NULL) { ssh_buffer_free(request); return NULL; } /* send the request */ if (agent_talk(session, request, reply) < 0) { ssh_buffer_free(request); return NULL; } ssh_buffer_free(request); /* check if reply is valid */ if (buffer_get_u8(reply, (uint8_t *) &type) != sizeof(uint8_t)) { ssh_buffer_free(reply); return NULL; } if (agent_failed(type)) { SSH_LOG(session, SSH_LOG_WARN, "Agent reports failure in signing the key"); ssh_buffer_free(reply); return NULL; } else if (type != SSH2_AGENT_SIGN_RESPONSE) { ssh_set_error(session, SSH_FATAL, "Bad authentication response: %d", type); ssh_buffer_free(reply); return NULL; } sig_blob = buffer_get_ssh_string(reply); ssh_buffer_free(reply); return sig_blob; }
ssh_string agent_sign_data(struct ssh_session_struct *session, struct ssh_buffer_struct *data, struct ssh_public_key_struct *pubkey) { struct ssh_string_struct *blob = NULL; struct ssh_string_struct *sig = NULL; struct ssh_buffer_struct *request = NULL; struct ssh_buffer_struct *reply = NULL; int type = SSH2_AGENT_FAILURE; int flags = 0; uint32_t dlen = 0; /* create blob from the pubkey */ blob = publickey_to_string(pubkey); request = buffer_new(); if (request == NULL) { goto error; } /* create request */ if (buffer_add_u8(request, SSH2_AGENTC_SIGN_REQUEST) < 0) { goto error; } /* adds len + blob */ if (buffer_add_ssh_string(request, blob) < 0) { goto error; } /* Add data */ dlen = buffer_get_len(data); if (buffer_add_u32(request, htonl(dlen)) < 0) { goto error; } if (buffer_add_data(request, buffer_get(data), dlen) < 0) { goto error; } if (buffer_add_u32(request, htonl(flags)) < 0) { goto error; } string_free(blob); reply = buffer_new(); if (reply == NULL) { goto error; } /* send the request */ if (agent_talk(session, request, reply) < 0) { buffer_free(request); return NULL; } buffer_free(request); /* check if reply is valid */ if (buffer_get_u8(reply, (uint8_t *) &type) != sizeof(uint8_t)) { goto error; } if (agent_failed(type)) { ssh_log(session, SSH_LOG_RARE, "Agent reports failure in signing the key"); buffer_free(reply); return NULL; } else if (type != SSH2_AGENT_SIGN_RESPONSE) { ssh_set_error(session, SSH_FATAL, "Bad authentication response: %d", type); buffer_free(reply); return NULL; } sig = buffer_get_ssh_string(reply); buffer_free(reply); return sig; error: ssh_set_error(session, SSH_FATAL, "Not enough memory"); string_free(blob); buffer_free(request); buffer_free(reply); return NULL; }