version 1.11, 1999/11/18 11:09:39 |
version 1.12, 1999/11/23 22:25:52 |
|
|
int |
int |
ssh_get_authentication_socket() |
ssh_get_authentication_socket() |
{ |
{ |
const char *authsocket; |
const char *authsocket; |
int sock; |
int sock; |
struct sockaddr_un sunaddr; |
struct sockaddr_un sunaddr; |
|
|
authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); |
authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); |
if (!authsocket) |
if (!authsocket) |
return -1; |
return -1; |
|
|
sunaddr.sun_family = AF_UNIX; |
sunaddr.sun_family = AF_UNIX; |
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); |
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); |
|
|
sock = socket(AF_UNIX, SOCK_STREAM, 0); |
|
if (sock < 0) |
|
return -1; |
|
|
|
/* close on exec */ |
sock = socket(AF_UNIX, SOCK_STREAM, 0); |
if (fcntl(sock, F_SETFD, 1) == -1) |
if (sock < 0) |
{ |
return -1; |
close(sock); |
|
return -1; |
|
} |
|
|
|
if (connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) |
|
{ |
|
close(sock); |
|
return -1; |
|
} |
|
|
|
return sock; |
/* close on exec */ |
|
if (fcntl(sock, F_SETFD, 1) == -1) { |
|
close(sock); |
|
return -1; |
|
} |
|
if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) { |
|
close(sock); |
|
return -1; |
|
} |
|
return sock; |
} |
} |
|
|
/* Closes the agent socket if it should be closed (depends on how it was |
/* Closes the agent socket if it should be closed (depends on how it was |
obtained). The argument must have been returned by |
obtained). The argument must have been returned by |
ssh_get_authentication_socket(). */ |
ssh_get_authentication_socket(). */ |
|
|
void ssh_close_authentication_socket(int sock) |
void |
|
ssh_close_authentication_socket(int sock) |
{ |
{ |
if (getenv(SSH_AUTHSOCKET_ENV_NAME)) |
if (getenv(SSH_AUTHSOCKET_ENV_NAME)) |
close(sock); |
close(sock); |
} |
} |
|
|
/* Opens and connects a private socket for communication with the |
/* Opens and connects a private socket for communication with the |
|
|
Returns NULL if an error occurred and the connection could not be |
Returns NULL if an error occurred and the connection could not be |
opened. */ |
opened. */ |
|
|
AuthenticationConnection *ssh_get_authentication_connection() |
AuthenticationConnection * |
|
ssh_get_authentication_connection() |
{ |
{ |
AuthenticationConnection *auth; |
AuthenticationConnection *auth; |
int sock; |
int sock; |
|
|
sock = ssh_get_authentication_socket(); |
|
|
|
/* Fail if we couldn't obtain a connection. This happens if we exited |
sock = ssh_get_authentication_socket(); |
due to a timeout. */ |
|
if (sock < 0) |
|
return NULL; |
|
|
|
/* Applocate the connection structure and initialize it. */ |
/* Fail if we couldn't obtain a connection. This happens if we |
auth = xmalloc(sizeof(*auth)); |
exited due to a timeout. */ |
auth->fd = sock; |
if (sock < 0) |
buffer_init(&auth->packet); |
return NULL; |
buffer_init(&auth->identities); |
|
auth->howmany = 0; |
|
|
|
return auth; |
/* Applocate the connection structure and initialize it. */ |
|
auth = xmalloc(sizeof(*auth)); |
|
auth->fd = sock; |
|
buffer_init(&auth->packet); |
|
buffer_init(&auth->identities); |
|
auth->howmany = 0; |
|
|
|
return auth; |
} |
} |
|
|
/* Closes the connection to the authentication agent and frees any associated |
/* Closes the connection to the authentication agent and frees any associated |
memory. */ |
memory. */ |
|
|
void ssh_close_authentication_connection(AuthenticationConnection *ac) |
void |
|
ssh_close_authentication_connection(AuthenticationConnection *ac) |
{ |
{ |
buffer_free(&ac->packet); |
buffer_free(&ac->packet); |
buffer_free(&ac->identities); |
buffer_free(&ac->identities); |
close(ac->fd); |
close(ac->fd); |
/* Free the connection data structure. */ |
xfree(ac); |
xfree(ac); |
|
} |
} |
|
|
/* Returns the first authentication identity held by the agent. |
/* Returns the first authentication identity held by the agent. |
|
|
ssh_get_first_identity(AuthenticationConnection *auth, |
ssh_get_first_identity(AuthenticationConnection *auth, |
BIGNUM *e, BIGNUM *n, char **comment) |
BIGNUM *e, BIGNUM *n, char **comment) |
{ |
{ |
unsigned char msg[8192]; |
unsigned char msg[8192]; |
int len, l; |
int len, l; |
|
|
/* Send a message to the agent requesting for a list of the identities |
/* Send a message to the agent requesting for a list of the |
it can represent. */ |
identities it can represent. */ |
msg[0] = 0; |
msg[0] = 0; |
msg[1] = 0; |
msg[1] = 0; |
msg[2] = 0; |
msg[2] = 0; |
msg[3] = 1; |
msg[3] = 1; |
msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES; |
msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES; |
if (write(auth->fd, msg, 5) != 5) |
if (write(auth->fd, msg, 5) != 5) { |
{ |
error("write auth->fd: %.100s", strerror(errno)); |
error("write auth->fd: %.100s", strerror(errno)); |
return 0; |
return 0; |
} |
} |
/* Read the length of the response. XXX implement timeouts here. */ |
|
len = 4; |
|
while (len > 0) { |
|
l = read(auth->fd, msg + 4 - len, len); |
|
if (l <= 0) { |
|
error("read auth->fd: %.100s", strerror(errno)); |
|
return 0; |
|
} |
|
len -= l; |
|
} |
|
|
/* Read the length of the response. XXX implement timeouts here. */ |
/* Extract the length, and check it for sanity. (We cannot trust |
len = 4; |
authentication agents). */ |
while (len > 0) |
len = GET_32BIT(msg); |
{ |
if (len < 1 || len > 256 * 1024) |
l = read(auth->fd, msg + 4 - len, len); |
fatal("Authentication reply message too long: %d\n", len); |
if (l <= 0) |
|
{ |
/* Read the packet itself. */ |
error("read auth->fd: %.100s", strerror(errno)); |
buffer_clear(&auth->identities); |
return 0; |
while (len > 0) { |
|
l = len; |
|
if (l > sizeof(msg)) |
|
l = sizeof(msg); |
|
l = read(auth->fd, msg, l); |
|
if (l <= 0) |
|
fatal("Incomplete authentication reply."); |
|
buffer_append(&auth->identities, (char *) msg, l); |
|
len -= l; |
} |
} |
len -= l; |
|
} |
|
|
|
/* Extract the length, and check it for sanity. (We cannot trust |
/* Get message type, and verify that we got a proper answer. */ |
authentication agents). */ |
buffer_get(&auth->identities, (char *) msg, 1); |
len = GET_32BIT(msg); |
if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER) |
if (len < 1 || len > 256*1024) |
fatal("Bad authentication reply message type: %d", msg[0]); |
fatal("Authentication reply message too long: %d\n", len); |
|
|
|
/* Read the packet itself. */ |
/* Get the number of entries in the response and check it for sanity. */ |
buffer_clear(&auth->identities); |
auth->howmany = buffer_get_int(&auth->identities); |
while (len > 0) |
if (auth->howmany > 1024) |
{ |
fatal("Too many identities in authentication reply: %d\n", auth->howmany); |
l = len; |
|
if (l > sizeof(msg)) |
|
l = sizeof(msg); |
|
l = read(auth->fd, msg, l); |
|
if (l <= 0) |
|
fatal("Incomplete authentication reply."); |
|
buffer_append(&auth->identities, (char *)msg, l); |
|
len -= l; |
|
} |
|
|
|
/* Get message type, and verify that we got a proper answer. */ |
|
buffer_get(&auth->identities, (char *)msg, 1); |
|
if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER) |
|
fatal("Bad authentication reply message type: %d", msg[0]); |
|
|
|
/* Get the number of entries in the response and check it for sanity. */ |
|
auth->howmany = buffer_get_int(&auth->identities); |
|
if (auth->howmany > 1024) |
|
fatal("Too many identities in authentication reply: %d\n", auth->howmany); |
|
|
|
/* Return the first entry (if any). */ |
/* Return the first entry (if any). */ |
return ssh_get_next_identity(auth, e, n, comment); |
return ssh_get_next_identity(auth, e, n, comment); |
} |
} |
|
|
/* Returns the next authentication identity for the agent. Other functions |
/* Returns the next authentication identity for the agent. Other functions |
|
|
ssh_get_next_identity(AuthenticationConnection *auth, |
ssh_get_next_identity(AuthenticationConnection *auth, |
BIGNUM *e, BIGNUM *n, char **comment) |
BIGNUM *e, BIGNUM *n, char **comment) |
{ |
{ |
unsigned int bits; |
unsigned int bits; |
|
|
/* Return failure if no more entries. */ |
/* Return failure if no more entries. */ |
if (auth->howmany <= 0) |
if (auth->howmany <= 0) |
return 0; |
return 0; |
|
|
/* Get the next entry from the packet. These will abort with a fatal |
/* Get the next entry from the packet. These will abort with a |
error if the packet is too short or contains corrupt data. */ |
fatal error if the packet is too short or contains corrupt data. */ |
bits = buffer_get_int(&auth->identities); |
bits = buffer_get_int(&auth->identities); |
buffer_get_bignum(&auth->identities, e); |
buffer_get_bignum(&auth->identities, e); |
buffer_get_bignum(&auth->identities, n); |
buffer_get_bignum(&auth->identities, n); |
*comment = buffer_get_string(&auth->identities, NULL); |
*comment = buffer_get_string(&auth->identities, NULL); |
|
|
if (bits != BN_num_bits(n)) |
if (bits != BN_num_bits(n)) |
error("Warning: keysize mismatch: actual %d, announced %u", |
error("Warning: keysize mismatch: actual %d, announced %u", |
BN_num_bits(n), bits); |
BN_num_bits(n), bits); |
|
|
/* Decrement the number of remaining entries. */ |
/* Decrement the number of remaining entries. */ |
auth->howmany--; |
auth->howmany--; |
|
|
return 1; |
return 1; |
} |
} |
|
|
/* Generates a random challenge, sends it to the agent, and waits for response |
/* Generates a random challenge, sends it to the agent, and waits for response |
|
|
|
|
int |
int |
ssh_decrypt_challenge(AuthenticationConnection *auth, |
ssh_decrypt_challenge(AuthenticationConnection *auth, |
BIGNUM *e, BIGNUM *n, BIGNUM *challenge, |
BIGNUM* e, BIGNUM *n, BIGNUM *challenge, |
unsigned char session_id[16], |
unsigned char session_id[16], |
unsigned int response_type, |
unsigned int response_type, |
unsigned char response[16]) |
unsigned char response[16]) |
{ |
{ |
Buffer buffer; |
Buffer buffer; |
unsigned char buf[8192]; |
unsigned char buf[8192]; |
int len, l, i; |
int len, l, i; |
|
|
/* Response type 0 is no longer supported. */ |
/* Response type 0 is no longer supported. */ |
if (response_type == 0) |
if (response_type == 0) |
fatal("Compatibility with ssh protocol version 1.0 no longer supported."); |
fatal("Compatibility with ssh protocol version 1.0 no longer supported."); |
|
|
/* Format a message to the agent. */ |
/* Format a message to the agent. */ |
buf[0] = SSH_AGENTC_RSA_CHALLENGE; |
buf[0] = SSH_AGENTC_RSA_CHALLENGE; |
buffer_init(&buffer); |
buffer_init(&buffer); |
buffer_append(&buffer, (char *)buf, 1); |
buffer_append(&buffer, (char *) buf, 1); |
buffer_put_int(&buffer, BN_num_bits(n)); |
buffer_put_int(&buffer, BN_num_bits(n)); |
buffer_put_bignum(&buffer, e); |
buffer_put_bignum(&buffer, e); |
buffer_put_bignum(&buffer, n); |
buffer_put_bignum(&buffer, n); |
buffer_put_bignum(&buffer, challenge); |
buffer_put_bignum(&buffer, challenge); |
buffer_append(&buffer, (char *)session_id, 16); |
buffer_append(&buffer, (char *) session_id, 16); |
buffer_put_int(&buffer, response_type); |
buffer_put_int(&buffer, response_type); |
|
|
/* Get the length of the message, and format it in the buffer. */ |
/* Get the length of the message, and format it in the buffer. */ |
len = buffer_len(&buffer); |
len = buffer_len(&buffer); |
PUT_32BIT(buf, len); |
PUT_32BIT(buf, len); |
|
|
/* Send the length and then the packet to the agent. */ |
/* Send the length and then the packet to the agent. */ |
if (write(auth->fd, buf, 4) != 4 || |
if (write(auth->fd, buf, 4) != 4 || |
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != |
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != |
buffer_len(&buffer)) |
buffer_len(&buffer)) { |
{ |
error("Error writing to authentication socket."); |
error("Error writing to authentication socket."); |
error_cleanup: |
error_cleanup: |
buffer_free(&buffer); |
buffer_free(&buffer); |
return 0; |
return 0; |
|
} |
|
|
|
/* Wait for response from the agent. First read the length of the |
|
response packet. */ |
|
len = 4; |
|
while (len > 0) |
|
{ |
|
l = read(auth->fd, buf + 4 - len, len); |
|
if (l <= 0) |
|
{ |
|
error("Error reading response length from authentication socket."); |
|
goto error_cleanup; |
|
} |
} |
len -= l; |
/* Wait for response from the agent. First read the length of the |
} |
response packet. */ |
|
len = 4; |
|
while (len > 0) { |
|
l = read(auth->fd, buf + 4 - len, len); |
|
if (l <= 0) { |
|
error("Error reading response length from authentication socket."); |
|
goto error_cleanup; |
|
} |
|
len -= l; |
|
} |
|
|
/* Extract the length, and check it for sanity. */ |
/* Extract the length, and check it for sanity. */ |
len = GET_32BIT(buf); |
len = GET_32BIT(buf); |
if (len > 256*1024) |
if (len > 256 * 1024) |
fatal("Authentication response too long: %d", len); |
fatal("Authentication response too long: %d", len); |
|
|
/* Read the rest of the response in tothe buffer. */ |
/* Read the rest of the response in tothe buffer. */ |
buffer_clear(&buffer); |
buffer_clear(&buffer); |
while (len > 0) |
while (len > 0) { |
{ |
l = len; |
l = len; |
if (l > sizeof(buf)) |
if (l > sizeof(buf)) |
l = sizeof(buf); |
l = sizeof(buf); |
l = read(auth->fd, buf, l); |
l = read(auth->fd, buf, l); |
if (l <= 0) { |
if (l <= 0) |
error("Error reading response from authentication socket."); |
{ |
goto error_cleanup; |
error("Error reading response from authentication socket."); |
} |
goto error_cleanup; |
buffer_append(&buffer, (char *) buf, l); |
|
len -= l; |
} |
} |
buffer_append(&buffer, (char *)buf, l); |
|
len -= l; |
|
} |
|
|
|
/* Get the type of the packet. */ |
/* Get the type of the packet. */ |
buffer_get(&buffer, (char *)buf, 1); |
buffer_get(&buffer, (char *) buf, 1); |
|
|
/* Check for agent failure message. */ |
/* Check for agent failure message. */ |
if (buf[0] == SSH_AGENT_FAILURE) |
if (buf[0] == SSH_AGENT_FAILURE) { |
{ |
log("Agent admitted failure to authenticate using the key."); |
log("Agent admitted failure to authenticate using the key."); |
goto error_cleanup; |
goto error_cleanup; |
} |
} |
/* Now it must be an authentication response packet. */ |
|
if (buf[0] != SSH_AGENT_RSA_RESPONSE) |
/* Now it must be an authentication response packet. */ |
fatal("Bad authentication response: %d", buf[0]); |
if (buf[0] != SSH_AGENT_RSA_RESPONSE) |
|
fatal("Bad authentication response: %d", buf[0]); |
|
|
|
/* Get the response from the packet. This will abort with a fatal error |
/* Get the response from the packet. This will abort with a fatal |
if the packet is corrupt. */ |
error if the packet is corrupt. */ |
for (i = 0; i < 16; i++) |
for (i = 0; i < 16; i++) |
response[i] = buffer_get_char(&buffer); |
response[i] = buffer_get_char(&buffer); |
|
|
/* The buffer containing the packet is no longer needed. */ |
/* The buffer containing the packet is no longer needed. */ |
buffer_free(&buffer); |
buffer_free(&buffer); |
|
|
/* Correct answer. */ |
/* Correct answer. */ |
return 1; |
return 1; |
} |
} |
|
|
/* Adds an identity to the authentication server. This call is not meant to |
/* Adds an identity to the authentication server. This call is not meant to |
be used by normal applications. */ |
be used by normal applications. */ |
|
|
int ssh_add_identity(AuthenticationConnection *auth, |
int |
RSA *key, const char *comment) |
ssh_add_identity(AuthenticationConnection *auth, |
|
RSA * key, const char *comment) |
{ |
{ |
Buffer buffer; |
Buffer buffer; |
unsigned char buf[8192]; |
unsigned char buf[8192]; |
int len, l, type; |
int len, l, type; |
|
|
/* Format a message to the agent. */ |
/* Format a message to the agent. */ |
buffer_init(&buffer); |
buffer_init(&buffer); |
buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY); |
buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY); |
buffer_put_int(&buffer, BN_num_bits(key->n)); |
buffer_put_int(&buffer, BN_num_bits(key->n)); |
buffer_put_bignum(&buffer, key->n); |
buffer_put_bignum(&buffer, key->n); |
buffer_put_bignum(&buffer, key->e); |
buffer_put_bignum(&buffer, key->e); |
buffer_put_bignum(&buffer, key->d); |
buffer_put_bignum(&buffer, key->d); |
/* To keep within the protocol: p < q for ssh. in SSL p > q */ |
/* To keep within the protocol: p < q for ssh. in SSL p > q */ |
buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */ |
buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */ |
buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */ |
buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */ |
buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */ |
buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */ |
buffer_put_string(&buffer, comment, strlen(comment)); |
buffer_put_string(&buffer, comment, strlen(comment)); |
|
|
/* Get the length of the message, and format it in the buffer. */ |
/* Get the length of the message, and format it in the buffer. */ |
len = buffer_len(&buffer); |
len = buffer_len(&buffer); |
PUT_32BIT(buf, len); |
PUT_32BIT(buf, len); |
|
|
/* Send the length and then the packet to the agent. */ |
/* Send the length and then the packet to the agent. */ |
if (write(auth->fd, buf, 4) != 4 || |
if (write(auth->fd, buf, 4) != 4 || |
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != |
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != |
buffer_len(&buffer)) |
buffer_len(&buffer)) { |
{ |
error("Error writing to authentication socket."); |
error("Error writing to authentication socket."); |
error_cleanup: |
error_cleanup: |
buffer_free(&buffer); |
buffer_free(&buffer); |
return 0; |
return 0; |
|
} |
|
|
|
/* Wait for response from the agent. First read the length of the |
|
response packet. */ |
|
len = 4; |
|
while (len > 0) |
|
{ |
|
l = read(auth->fd, buf + 4 - len, len); |
|
if (l <= 0) |
|
{ |
|
error("Error reading response length from authentication socket."); |
|
goto error_cleanup; |
|
} |
} |
len -= l; |
/* Wait for response from the agent. First read the length of the |
} |
response packet. */ |
|
len = 4; |
|
while (len > 0) { |
|
l = read(auth->fd, buf + 4 - len, len); |
|
if (l <= 0) { |
|
error("Error reading response length from authentication socket."); |
|
goto error_cleanup; |
|
} |
|
len -= l; |
|
} |
|
|
/* Extract the length, and check it for sanity. */ |
/* Extract the length, and check it for sanity. */ |
len = GET_32BIT(buf); |
len = GET_32BIT(buf); |
if (len > 256*1024) |
if (len > 256 * 1024) |
fatal("Add identity response too long: %d", len); |
fatal("Add identity response too long: %d", len); |
|
|
/* Read the rest of the response in tothe buffer. */ |
/* Read the rest of the response in tothe buffer. */ |
buffer_clear(&buffer); |
buffer_clear(&buffer); |
while (len > 0) |
while (len > 0) { |
{ |
l = len; |
l = len; |
if (l > sizeof(buf)) |
if (l > sizeof(buf)) |
l = sizeof(buf); |
l = sizeof(buf); |
l = read(auth->fd, buf, l); |
l = read(auth->fd, buf, l); |
if (l <= 0) { |
if (l <= 0) |
error("Error reading response from authentication socket."); |
{ |
goto error_cleanup; |
error("Error reading response from authentication socket."); |
} |
goto error_cleanup; |
buffer_append(&buffer, (char *) buf, l); |
|
len -= l; |
} |
} |
buffer_append(&buffer, (char *)buf, l); |
|
len -= l; |
|
} |
|
|
|
/* Get the type of the packet. */ |
/* Get the type of the packet. */ |
type = buffer_get_char(&buffer); |
type = buffer_get_char(&buffer); |
switch (type) |
switch (type) { |
{ |
case SSH_AGENT_FAILURE: |
case SSH_AGENT_FAILURE: |
buffer_free(&buffer); |
buffer_free(&buffer); |
return 0; |
return 0; |
case SSH_AGENT_SUCCESS: |
case SSH_AGENT_SUCCESS: |
buffer_free(&buffer); |
buffer_free(&buffer); |
return 1; |
return 1; |
default: |
default: |
fatal("Bad response to add identity from authentication agent: %d", |
fatal("Bad response to add identity from authentication agent: %d", |
type); |
type); |
} |
} |
/* NOTREACHED */ |
/*NOTREACHED*/ |
return 0; |
return 0; |
} |
} |
|
|
|
/* Removes an identity from the authentication server. This call is not meant |
/* Removes an identity from the authentication server. This call is not meant |
to be used by normal applications. */ |
to be used by normal applications. */ |
|
|
int ssh_remove_identity(AuthenticationConnection *auth, RSA *key) |
int |
|
ssh_remove_identity(AuthenticationConnection *auth, RSA *key) |
{ |
{ |
Buffer buffer; |
Buffer buffer; |
unsigned char buf[8192]; |
unsigned char buf[8192]; |
int len, l, type; |
int len, l, type; |
|
|
/* Format a message to the agent. */ |
/* Format a message to the agent. */ |
buffer_init(&buffer); |
buffer_init(&buffer); |
buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY); |
buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY); |
buffer_put_int(&buffer, BN_num_bits(key->n)); |
buffer_put_int(&buffer, BN_num_bits(key->n)); |
buffer_put_bignum(&buffer, key->e); |
buffer_put_bignum(&buffer, key->e); |
buffer_put_bignum(&buffer, key->n); |
buffer_put_bignum(&buffer, key->n); |
|
|
/* Get the length of the message, and format it in the buffer. */ |
/* Get the length of the message, and format it in the buffer. */ |
len = buffer_len(&buffer); |
len = buffer_len(&buffer); |
PUT_32BIT(buf, len); |
PUT_32BIT(buf, len); |
|
|
/* Send the length and then the packet to the agent. */ |
/* Send the length and then the packet to the agent. */ |
if (write(auth->fd, buf, 4) != 4 || |
if (write(auth->fd, buf, 4) != 4 || |
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != |
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) != |
buffer_len(&buffer)) |
buffer_len(&buffer)) { |
{ |
error("Error writing to authentication socket."); |
error("Error writing to authentication socket."); |
error_cleanup: |
error_cleanup: |
buffer_free(&buffer); |
buffer_free(&buffer); |
return 0; |
return 0; |
|
} |
|
|
|
/* Wait for response from the agent. First read the length of the |
|
response packet. */ |
|
len = 4; |
|
while (len > 0) |
|
{ |
|
l = read(auth->fd, buf + 4 - len, len); |
|
if (l <= 0) |
|
{ |
|
error("Error reading response length from authentication socket."); |
|
goto error_cleanup; |
|
} |
} |
len -= l; |
/* Wait for response from the agent. First read the length of the |
} |
response packet. */ |
|
len = 4; |
|
while (len > 0) { |
|
l = read(auth->fd, buf + 4 - len, len); |
|
if (l <= 0) { |
|
error("Error reading response length from authentication socket."); |
|
goto error_cleanup; |
|
} |
|
len -= l; |
|
} |
|
|
/* Extract the length, and check it for sanity. */ |
/* Extract the length, and check it for sanity. */ |
len = GET_32BIT(buf); |
len = GET_32BIT(buf); |
if (len > 256*1024) |
if (len > 256 * 1024) |
fatal("Remove identity response too long: %d", len); |
fatal("Remove identity response too long: %d", len); |
|
|
/* Read the rest of the response in tothe buffer. */ |
/* Read the rest of the response in tothe buffer. */ |
buffer_clear(&buffer); |
buffer_clear(&buffer); |
while (len > 0) |
while (len > 0) { |
{ |
l = len; |
l = len; |
if (l > sizeof(buf)) |
if (l > sizeof(buf)) |
l = sizeof(buf); |
l = sizeof(buf); |
l = read(auth->fd, buf, l); |
l = read(auth->fd, buf, l); |
if (l <= 0) { |
if (l <= 0) |
error("Error reading response from authentication socket."); |
{ |
goto error_cleanup; |
error("Error reading response from authentication socket."); |
} |
goto error_cleanup; |
buffer_append(&buffer, (char *) buf, l); |
|
len -= l; |
} |
} |
buffer_append(&buffer, (char *)buf, l); |
|
len -= l; |
|
} |
|
|
|
/* Get the type of the packet. */ |
/* Get the type of the packet. */ |
type = buffer_get_char(&buffer); |
type = buffer_get_char(&buffer); |
switch (type) |
switch (type) { |
{ |
case SSH_AGENT_FAILURE: |
case SSH_AGENT_FAILURE: |
buffer_free(&buffer); |
buffer_free(&buffer); |
return 0; |
return 0; |
case SSH_AGENT_SUCCESS: |
case SSH_AGENT_SUCCESS: |
buffer_free(&buffer); |
buffer_free(&buffer); |
return 1; |
return 1; |
default: |
default: |
fatal("Bad response to remove identity from authentication agent: %d", |
fatal("Bad response to remove identity from authentication agent: %d", |
type); |
type); |
} |
} |
/* NOTREACHED */ |
/*NOTREACHED*/ |
return 0; |
return 0; |
} |
} |
|
|
|
/* Removes all identities from the agent. This call is not meant |
/* Removes all identities from the agent. This call is not meant |
to be used by normal applications. */ |
to be used by normal applications. */ |
|
|
int ssh_remove_all_identities(AuthenticationConnection *auth) |
int |
|
ssh_remove_all_identities(AuthenticationConnection *auth) |
{ |
{ |
Buffer buffer; |
Buffer buffer; |
unsigned char buf[8192]; |
unsigned char buf[8192]; |
int len, l, type; |
int len, l, type; |
|
|
/* Get the length of the message, and format it in the buffer. */ |
/* Get the length of the message, and format it in the buffer. */ |
PUT_32BIT(buf, 1); |
PUT_32BIT(buf, 1); |
buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES; |
buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES; |
|
|
/* Send the length and then the packet to the agent. */ |
/* Send the length and then the packet to the agent. */ |
if (write(auth->fd, buf, 5) != 5) |
if (write(auth->fd, buf, 5) != 5) { |
{ |
error("Error writing to authentication socket."); |
error("Error writing to authentication socket."); |
return 0; |
return 0; |
|
} |
|
|
|
/* Wait for response from the agent. First read the length of the |
|
response packet. */ |
|
len = 4; |
|
while (len > 0) |
|
{ |
|
l = read(auth->fd, buf + 4 - len, len); |
|
if (l <= 0) |
|
{ |
|
error("Error reading response length from authentication socket."); |
|
return 0; |
|
} |
} |
len -= l; |
/* Wait for response from the agent. First read the length of the |
} |
response packet. */ |
|
len = 4; |
|
while (len > 0) { |
|
l = read(auth->fd, buf + 4 - len, len); |
|
if (l <= 0) { |
|
error("Error reading response length from authentication socket."); |
|
return 0; |
|
} |
|
len -= l; |
|
} |
|
|
/* Extract the length, and check it for sanity. */ |
/* Extract the length, and check it for sanity. */ |
len = GET_32BIT(buf); |
len = GET_32BIT(buf); |
if (len > 256*1024) |
if (len > 256 * 1024) |
fatal("Remove identity response too long: %d", len); |
fatal("Remove identity response too long: %d", len); |
|
|
/* Read the rest of the response into the buffer. */ |
/* Read the rest of the response into the buffer. */ |
buffer_init(&buffer); |
buffer_init(&buffer); |
while (len > 0) |
while (len > 0) { |
{ |
l = len; |
l = len; |
if (l > sizeof(buf)) |
if (l > sizeof(buf)) |
l = sizeof(buf); |
l = sizeof(buf); |
l = read(auth->fd, buf, l); |
l = read(auth->fd, buf, l); |
if (l <= 0) { |
if (l <= 0) |
error("Error reading response from authentication socket."); |
{ |
buffer_free(&buffer); |
error("Error reading response from authentication socket."); |
return 0; |
buffer_free(&buffer); |
} |
return 0; |
buffer_append(&buffer, (char *) buf, l); |
|
len -= l; |
} |
} |
buffer_append(&buffer, (char *)buf, l); |
|
len -= l; |
|
} |
|
|
|
/* Get the type of the packet. */ |
/* Get the type of the packet. */ |
type = buffer_get_char(&buffer); |
type = buffer_get_char(&buffer); |
switch (type) |
switch (type) { |
{ |
case SSH_AGENT_FAILURE: |
case SSH_AGENT_FAILURE: |
buffer_free(&buffer); |
buffer_free(&buffer); |
return 0; |
return 0; |
case SSH_AGENT_SUCCESS: |
case SSH_AGENT_SUCCESS: |
buffer_free(&buffer); |
buffer_free(&buffer); |
return 1; |
return 1; |
default: |
default: |
fatal("Bad response to remove identity from authentication agent: %d", |
fatal("Bad response to remove identity from authentication agent: %d", |
type); |
type); |
} |
} |
/* NOTREACHED */ |
/*NOTREACHED*/ |
return 0; |
return 0; |
} |
} |
|