agent.c | agent.c | |||
---|---|---|---|---|
skipping to change at line 53 | skipping to change at line 53 | |||
#include <poll.h> | #include <poll.h> | |||
#include <unistd.h> | #include <unistd.h> | |||
#ifndef _WIN32 | #ifndef _WIN32 | |||
#include <arpa/inet.h> | #include <arpa/inet.h> | |||
#endif | #endif | |||
#include "libssh/agent.h" | #include "libssh/agent.h" | |||
#include "libssh/priv.h" | #include "libssh/priv.h" | |||
#include "libssh/socket.h" | ||||
#include "libssh/buffer.h" | ||||
#include "libssh/session.h" | ||||
#include "libssh/keys.h" | ||||
/* macro to check for "agent failure" message */ | /* macro to check for "agent failure" message */ | |||
#define agent_failed(x) \ | #define agent_failed(x) \ | |||
(((x) == SSH_AGENT_FAILURE) || ((x) == SSH_COM_AGENT2_FAILURE) || \ | (((x) == SSH_AGENT_FAILURE) || ((x) == SSH_COM_AGENT2_FAILURE) || \ | |||
((x) == SSH2_AGENT_FAILURE)) | ((x) == SSH2_AGENT_FAILURE)) | |||
static u32 agent_get_u32(const void *vp) { | static uint32_t agent_get_u32(const void *vp) { | |||
const u8 *p = (const u8 *)vp; | const uint8_t *p = (const uint8_t *)vp; | |||
u32 v; | uint32_t v; | |||
v = (u32)p[0] << 24; | v = (uint32_t)p[0] << 24; | |||
v |= (u32)p[1] << 16; | v |= (uint32_t)p[1] << 16; | |||
v |= (u32)p[2] << 8; | v |= (uint32_t)p[2] << 8; | |||
v |= (u32)p[3]; | v |= (uint32_t)p[3]; | |||
return v; | return v; | |||
} | } | |||
static void agent_put_u32(void *vp, u32 v) { | static void agent_put_u32(void *vp, uint32_t v) { | |||
u8 *p = (u8 *)vp; | uint8_t *p = (uint8_t *)vp; | |||
p[0] = (u8)(v >> 24) & 0xff; | p[0] = (uint8_t)(v >> 24) & 0xff; | |||
p[1] = (u8)(v >> 16) & 0xff; | p[1] = (uint8_t)(v >> 16) & 0xff; | |||
p[2] = (u8)(v >> 8) & 0xff; | p[2] = (uint8_t)(v >> 8) & 0xff; | |||
p[3] = (u8)v & 0xff; | p[3] = (uint8_t)v & 0xff; | |||
} | } | |||
static size_t atomicio(struct socket *s, void *buf, size_t n, int do_read) { | static size_t atomicio(struct socket *s, void *buf, size_t n, int do_read) { | |||
char *b = buf; | char *b = buf; | |||
size_t pos = 0; | size_t pos = 0; | |||
ssize_t res; | ssize_t res; | |||
struct pollfd pfd; | struct pollfd pfd; | |||
int fd = ssh_socket_get_fd(s); | int fd = ssh_socket_get_fd(s); | |||
pfd.fd = fd; | pfd.fd = fd; | |||
skipping to change at line 121 | skipping to change at line 125 | |||
errno = EPIPE; | errno = EPIPE; | |||
return pos; | return pos; | |||
default: | default: | |||
pos += (size_t) res; | pos += (size_t) res; | |||
} | } | |||
} | } | |||
return pos; | return pos; | |||
} | } | |||
AGENT *agent_new(struct ssh_session *session) { | ssh_agent agent_new(struct ssh_session_struct *session) { | |||
AGENT *agent = NULL; | ssh_agent agent = NULL; | |||
agent = malloc(sizeof(AGENT)); | agent = malloc(sizeof(struct ssh_agent_struct)); | |||
if (agent == NULL) { | if (agent == NULL) { | |||
return NULL; | return NULL; | |||
} | } | |||
ZERO_STRUCTP(agent); | ZERO_STRUCTP(agent); | |||
agent->count = 0; | agent->count = 0; | |||
agent->sock = ssh_socket_new(session); | agent->sock = ssh_socket_new(session); | |||
if (agent->sock == NULL) { | if (agent->sock == NULL) { | |||
SAFE_FREE(agent); | SAFE_FREE(agent); | |||
return NULL; | return NULL; | |||
} | } | |||
return agent; | return agent; | |||
} | } | |||
void agent_close(struct agent_struct *agent) { | void agent_close(struct ssh_agent_struct *agent) { | |||
if (agent == NULL) { | if (agent == NULL) { | |||
return; | return; | |||
} | } | |||
if (getenv("SSH_AUTH_SOCK")) { | if (getenv("SSH_AUTH_SOCK")) { | |||
ssh_socket_close(agent->sock); | ssh_socket_close(agent->sock); | |||
} | } | |||
} | } | |||
void agent_free(AGENT *agent) { | void agent_free(ssh_agent agent) { | |||
if (agent) { | if (agent) { | |||
if (agent->ident) { | if (agent->ident) { | |||
buffer_free(agent->ident); | buffer_free(agent->ident); | |||
} | } | |||
if (agent->sock) { | if (agent->sock) { | |||
agent_close(agent); | agent_close(agent); | |||
ssh_socket_free(agent->sock); | ssh_socket_free(agent->sock); | |||
} | } | |||
SAFE_FREE(agent); | SAFE_FREE(agent); | |||
} | } | |||
} | } | |||
static int agent_connect(SSH_SESSION *session) { | static int agent_connect(ssh_session session) { | |||
const char *auth_sock = NULL; | const char *auth_sock = NULL; | |||
if (session == NULL || session->agent == NULL) { | if (session == NULL || session->agent == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
auth_sock = getenv("SSH_AUTH_SOCK"); | auth_sock = getenv("SSH_AUTH_SOCK"); | |||
if (auth_sock && *auth_sock) { | if (auth_sock && *auth_sock) { | |||
if (ssh_socket_unix(session->agent->sock, auth_sock) < 0) { | if (ssh_socket_unix(session->agent->sock, auth_sock) < 0) { | |||
return -1; | return -1; | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
return -1; | return -1; | |||
} | } | |||
#if 0 | #if 0 | |||
static int agent_decode_reply(struct ssh_session *session, int type) { | static int agent_decode_reply(struct ssh_session_struct *session, int type) { | |||
switch (type) { | switch (type) { | |||
case SSH_AGENT_FAILURE: | case SSH_AGENT_FAILURE: | |||
case SSH2_AGENT_FAILURE: | case SSH2_AGENT_FAILURE: | |||
case SSH_COM_AGENT2_FAILURE: | case SSH_COM_AGENT2_FAILURE: | |||
ssh_log(session, SSH_LOG_RARE, "SSH_AGENT_FAILURE"); | ssh_log(session, SSH_LOG_RARE, "SSH_AGENT_FAILURE"); | |||
return 0; | return 0; | |||
case SSH_AGENT_SUCCESS: | case SSH_AGENT_SUCCESS: | |||
return 1; | return 1; | |||
default: | default: | |||
ssh_set_error(session, SSH_FATAL, | ssh_set_error(session, SSH_FATAL, | |||
"Bad response from authentication agent: %d", type); | "Bad response from authentication agent: %d", type); | |||
break; | break; | |||
} | } | |||
return -1; | return -1; | |||
} | } | |||
#endif | #endif | |||
static int agent_talk(struct ssh_session *session, | static int agent_talk(struct ssh_session_struct *session, | |||
struct buffer_struct *request, struct buffer_struct *reply) { | struct ssh_buffer_struct *request, struct ssh_buffer_struct *reply) { | |||
u32 len = 0; | uint32_t len = 0; | |||
u8 payload[1024] = {0}; | uint8_t payload[1024] = {0}; | |||
len = buffer_get_len(request); | len = buffer_get_len(request); | |||
ssh_log(session, SSH_LOG_PACKET, "agent_talk - len of request: %u", len); | ssh_log(session, SSH_LOG_PACKET, "agent_talk - len of request: %u", len); | |||
agent_put_u32(payload, len); | agent_put_u32(payload, len); | |||
/* send length and then the request packet */ | /* send length and then the request packet */ | |||
if (atomicio(session->agent->sock, payload, 4, 0) == 4) { | if (atomicio(session->agent->sock, payload, 4, 0) == 4) { | |||
if (atomicio(session->agent->sock, buffer_get_rest(request), len, 0) | if (atomicio(session->agent->sock, buffer_get_rest(request), len, 0) | |||
!= len) { | != len) { | |||
ssh_log(session, SSH_LOG_PACKET, "atomicio sending request failed: %s ", | ssh_log(session, SSH_LOG_PACKET, "atomicio sending request failed: %s ", | |||
skipping to change at line 262 | skipping to change at line 266 | |||
ssh_log(session, SSH_LOG_FUNCTIONS, | ssh_log(session, SSH_LOG_FUNCTIONS, | |||
"Not enough space"); | "Not enough space"); | |||
return -1; | return -1; | |||
} | } | |||
len -= n; | len -= n; | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
int agent_get_ident_count(struct ssh_session *session) { | int agent_get_ident_count(struct ssh_session_struct *session) { | |||
BUFFER *request = NULL; | ssh_buffer request = NULL; | |||
BUFFER *reply = NULL; | ssh_buffer reply = NULL; | |||
unsigned int type = 0; | unsigned int type = 0; | |||
unsigned int c1 = 0, c2 = 0; | unsigned int c1 = 0, c2 = 0; | |||
u8 buf[4] = {0}; | uint8_t buf[4] = {0}; | |||
switch (session->version) { | switch (session->version) { | |||
case 1: | case 1: | |||
c1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; | c1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; | |||
c2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; | c2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; | |||
break; | break; | |||
case 2: | case 2: | |||
c1 = SSH2_AGENTC_REQUEST_IDENTITIES; | c1 = SSH2_AGENTC_REQUEST_IDENTITIES; | |||
c2 = SSH2_AGENT_IDENTITIES_ANSWER; | c2 = SSH2_AGENT_IDENTITIES_ANSWER; | |||
break; | break; | |||
skipping to change at line 302 | skipping to change at line 306 | |||
return -1; | return -1; | |||
} | } | |||
if (agent_talk(session, request, reply) < 0) { | if (agent_talk(session, request, reply) < 0) { | |||
buffer_free(request); | buffer_free(request); | |||
return 0; | return 0; | |||
} | } | |||
buffer_free(request); | buffer_free(request); | |||
/* get message type and verify the answer */ | /* get message type and verify the answer */ | |||
buffer_get_u8(reply, (u8 *) &type); | buffer_get_u8(reply, (uint8_t *) &type); | |||
ssh_log(session, SSH_LOG_PACKET, | ssh_log(session, SSH_LOG_PACKET, | |||
"agent_ident_count - answer type: %d, expected answer: %d", | "agent_ident_count - answer type: %d, expected answer: %d", | |||
type, c2); | type, c2); | |||
if (agent_failed(type)) { | if (agent_failed(type)) { | |||
return 0; | return 0; | |||
} else if (type != c2) { | } else if (type != c2) { | |||
ssh_set_error(session, SSH_FATAL, | ssh_set_error(session, SSH_FATAL, | |||
"Bad authentication reply message type: %d", type); | "Bad authentication reply message type: %d", type); | |||
return -1; | return -1; | |||
} | } | |||
buffer_get_u32(reply, (u32 *) buf); | buffer_get_u32(reply, (uint32_t *) buf); | |||
session->agent->count = agent_get_u32(buf); | session->agent->count = agent_get_u32(buf); | |||
ssh_log(session, SSH_LOG_PACKET, "agent_ident_count - count: %d", | ssh_log(session, SSH_LOG_PACKET, "agent_ident_count - count: %d", | |||
session->agent->count); | session->agent->count); | |||
if (session->agent->count > 1024) { | if (session->agent->count > 1024) { | |||
ssh_set_error(session, SSH_FATAL, | ssh_set_error(session, SSH_FATAL, | |||
"Too many identities in authentication reply: %d", | "Too many identities in authentication reply: %d", | |||
session->agent->count); | session->agent->count); | |||
buffer_free(reply); | buffer_free(reply); | |||
return -1; | return -1; | |||
} | } | |||
if (session->agent->ident) { | if (session->agent->ident) { | |||
buffer_reinit(session->agent->ident); | buffer_reinit(session->agent->ident); | |||
} | } | |||
session->agent->ident = reply; | session->agent->ident = reply; | |||
return session->agent->count; | return session->agent->count; | |||
} | } | |||
/* caller has to free commment */ | /* caller has to free commment */ | |||
struct public_key_struct *agent_get_first_ident(struct ssh_session *session , | struct ssh_public_key_struct *agent_get_first_ident(struct ssh_session_stru ct *session, | |||
char **comment) { | char **comment) { | |||
if (agent_get_ident_count(session) > 0) { | if (agent_get_ident_count(session) > 0) { | |||
return agent_get_next_ident(session, comment); | return agent_get_next_ident(session, comment); | |||
} | } | |||
return NULL; | return NULL; | |||
} | } | |||
/* caller has to free commment */ | /* caller has to free commment */ | |||
struct public_key_struct *agent_get_next_ident(struct ssh_session *session, | struct ssh_public_key_struct *agent_get_next_ident(struct ssh_session_struc t *session, | |||
char **comment) { | char **comment) { | |||
struct public_key_struct *pubkey = NULL; | struct ssh_public_key_struct *pubkey = NULL; | |||
struct string_struct *blob = NULL; | struct ssh_string_struct *blob = NULL; | |||
struct string_struct *tmp = NULL; | struct ssh_string_struct *tmp = NULL; | |||
if (session->agent->count == 0) { | if (session->agent->count == 0) { | |||
return NULL; | return NULL; | |||
} | } | |||
switch(session->version) { | switch(session->version) { | |||
case 1: | case 1: | |||
return NULL; | return NULL; | |||
case 2: | case 2: | |||
/* get the blob */ | /* get the blob */ | |||
skipping to change at line 394 | skipping to change at line 398 | |||
pubkey = publickey_from_string(session, blob); | pubkey = publickey_from_string(session, blob); | |||
string_free(blob); | string_free(blob); | |||
break; | break; | |||
default: | default: | |||
return NULL; | return NULL; | |||
} | } | |||
return pubkey; | return pubkey; | |||
} | } | |||
STRING *agent_sign_data(struct ssh_session *session, | ssh_string agent_sign_data(struct ssh_session_struct *session, | |||
struct buffer_struct *data, | struct ssh_buffer_struct *data, | |||
struct public_key_struct *pubkey) { | struct ssh_public_key_struct *pubkey) { | |||
struct string_struct *blob = NULL; | struct ssh_string_struct *blob = NULL; | |||
struct string_struct *sig = NULL; | struct ssh_string_struct *sig = NULL; | |||
struct buffer_struct *request = NULL; | struct ssh_buffer_struct *request = NULL; | |||
struct buffer_struct *reply = NULL; | struct ssh_buffer_struct *reply = NULL; | |||
int type = SSH2_AGENT_FAILURE; | int type = SSH2_AGENT_FAILURE; | |||
int flags = 0; | int flags = 0; | |||
u32 dlen = 0; | uint32_t dlen = 0; | |||
/* create blob from the pubkey */ | /* create blob from the pubkey */ | |||
blob = publickey_to_string(pubkey); | blob = publickey_to_string(pubkey); | |||
request = buffer_new(); | request = buffer_new(); | |||
if (request == NULL) { | if (request == NULL) { | |||
goto error; | goto error; | |||
} | } | |||
/* create request */ | /* create request */ | |||
skipping to change at line 451 | skipping to change at line 455 | |||
} | } | |||
/* send the request */ | /* send the request */ | |||
if (agent_talk(session, request, reply) < 0) { | if (agent_talk(session, request, reply) < 0) { | |||
buffer_free(request); | buffer_free(request); | |||
return NULL; | return NULL; | |||
} | } | |||
buffer_free(request); | buffer_free(request); | |||
/* check if reply is valid */ | /* check if reply is valid */ | |||
if (buffer_get_u8(reply, (u8 *) &type) < 0) { | if (buffer_get_u8(reply, (uint8_t *) &type) != sizeof(uint8_t)) { | |||
goto error; | goto error; | |||
} | } | |||
if (agent_failed(type)) { | if (agent_failed(type)) { | |||
ssh_log(session, SSH_LOG_RARE, "Agent reports failure in signing the ke y"); | ssh_log(session, SSH_LOG_RARE, "Agent reports failure in signing the ke y"); | |||
buffer_free(reply); | buffer_free(reply); | |||
return NULL; | return NULL; | |||
} else if (type != SSH2_AGENT_SIGN_RESPONSE) { | } else if (type != SSH2_AGENT_SIGN_RESPONSE) { | |||
ssh_set_error(session, SSH_FATAL, "Bad authentication response: %d", ty pe); | ssh_set_error(session, SSH_FATAL, "Bad authentication response: %d", ty pe); | |||
buffer_free(reply); | buffer_free(reply); | |||
return NULL; | return NULL; | |||
skipping to change at line 478 | skipping to change at line 482 | |||
return sig; | return sig; | |||
error: | error: | |||
ssh_set_error(session, SSH_FATAL, "Not enough memory"); | ssh_set_error(session, SSH_FATAL, "Not enough memory"); | |||
string_free(blob); | string_free(blob); | |||
buffer_free(request); | buffer_free(request); | |||
buffer_free(reply); | buffer_free(reply); | |||
return NULL; | return NULL; | |||
} | } | |||
int agent_is_running(SSH_SESSION *session) { | int agent_is_running(ssh_session session) { | |||
if (session == NULL || session->agent == NULL) { | if (session == NULL || session->agent == NULL) { | |||
return 0; | return 0; | |||
} | } | |||
if (ssh_socket_is_open(session->agent->sock)) { | if (ssh_socket_is_open(session->agent->sock)) { | |||
return 1; | return 1; | |||
} else { | } else { | |||
if (agent_connect(session) < 0) { | if (agent_connect(session) < 0) { | |||
return 0; | return 0; | |||
} else { | } else { | |||
End of changes. 22 change blocks. | ||||
46 lines changed or deleted | 50 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |