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/