version 1.29.2.6, 2002/03/08 17:04:42 |
version 1.30, 2000/11/12 19:50:37 |
|
|
#include "includes.h" |
#include "includes.h" |
RCSID("$OpenBSD$"); |
RCSID("$OpenBSD$"); |
|
|
#include <openssl/evp.h> |
|
|
|
#include "ssh.h" |
#include "ssh.h" |
#include "rsa.h" |
#include "rsa.h" |
#include "buffer.h" |
#include "buffer.h" |
#include "bufaux.h" |
#include "bufaux.h" |
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "getput.h" |
#include "getput.h" |
|
|
|
#include <openssl/rsa.h> |
|
#include <openssl/dsa.h> |
|
#include <openssl/evp.h> |
#include "key.h" |
#include "key.h" |
#include "authfd.h" |
#include "authfd.h" |
#include "cipher.h" |
|
#include "kex.h" |
#include "kex.h" |
#include "compat.h" |
#include "compat.h" |
#include "log.h" |
|
#include "atomicio.h" |
|
|
|
/* helper */ |
/* helper */ |
int decode_reply(int type); |
int decode_reply(int type); |
|
|
/* 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)) |
|
|
|
/* Returns the number of the authentication fd, or -1 if there is none. */ |
/* Returns the number of the authentication fd, or -1 if there is none. */ |
|
|
int |
int |
ssh_get_authentication_socket(void) |
ssh_get_authentication_socket() |
{ |
{ |
const char *authsocket; |
const char *authsocket; |
int sock; |
int sock, len; |
struct sockaddr_un sunaddr; |
struct sockaddr_un sunaddr; |
|
|
authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); |
authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); |
|
|
|
|
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)); |
|
sunaddr.sun_len = len = SUN_LEN(&sunaddr)+1; |
|
|
sock = socket(AF_UNIX, SOCK_STREAM, 0); |
sock = socket(AF_UNIX, SOCK_STREAM, 0); |
if (sock < 0) |
if (sock < 0) |
|
|
close(sock); |
close(sock); |
return -1; |
return -1; |
} |
} |
if (connect(sock, (struct sockaddr *) &sunaddr, sizeof sunaddr) < 0) { |
if (connect(sock, (struct sockaddr *) & sunaddr, len) < 0) { |
close(sock); |
close(sock); |
return -1; |
return -1; |
} |
} |
return sock; |
return sock; |
} |
} |
|
|
static int |
int |
ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply) |
ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply) |
{ |
{ |
int l, len; |
int l, len; |
|
|
len = 4; |
len = 4; |
while (len > 0) { |
while (len > 0) { |
l = read(auth->fd, buf + 4 - len, len); |
l = read(auth->fd, buf + 4 - len, len); |
if (l == -1 && (errno == EAGAIN || errno == EINTR)) |
|
continue; |
|
if (l <= 0) { |
if (l <= 0) { |
error("Error reading response length from authentication socket."); |
error("Error reading response length from authentication socket."); |
return 0; |
return 0; |
|
|
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 == -1 && (errno == EAGAIN || errno == EINTR)) |
|
continue; |
|
if (l <= 0) { |
if (l <= 0) { |
error("Error reading response from authentication socket."); |
error("Error reading response from authentication socket."); |
return 0; |
return 0; |
|
|
*/ |
*/ |
|
|
AuthenticationConnection * |
AuthenticationConnection * |
ssh_get_authentication_connection(void) |
ssh_get_authentication_connection() |
{ |
{ |
AuthenticationConnection *auth; |
AuthenticationConnection *auth; |
int sock; |
int sock; |
|
|
int type, code1 = 0, code2 = 0; |
int type, code1 = 0, code2 = 0; |
Buffer request; |
Buffer request; |
|
|
switch (version) { |
switch(version){ |
case 1: |
case 1: |
code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; |
code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; |
code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; |
code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; |
|
|
/* Get the number of entries in the response and check it for sanity. */ |
/* Get the number of entries in the response and check it for sanity. */ |
auth->howmany = buffer_get_int(&auth->identities); |
auth->howmany = buffer_get_int(&auth->identities); |
if (auth->howmany > 1024) |
if (auth->howmany > 1024) |
fatal("Too many identities in authentication reply: %d", |
fatal("Too many identities in authentication reply: %d\n", |
auth->howmany); |
auth->howmany); |
|
|
return auth->howmany; |
return auth->howmany; |
|
|
Key * |
Key * |
ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version) |
ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version) |
{ |
{ |
u_int bits; |
unsigned int bits; |
u_char *blob; |
unsigned char *blob; |
u_int blen; |
unsigned int blen; |
Key *key = NULL; |
Key *key = NULL; |
|
|
/* Return failure if no more entries. */ |
/* Return failure if no more entries. */ |
|
|
* 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 fatal |
* error if the packet is too short or contains corrupt data. |
* error if the packet is too short or contains corrupt data. |
*/ |
*/ |
switch (version) { |
switch(version){ |
case 1: |
case 1: |
key = key_new(KEY_RSA1); |
key = key_new(KEY_RSA1); |
bits = buffer_get_int(&auth->identities); |
bits = buffer_get_int(&auth->identities); |
|
|
int |
int |
ssh_decrypt_challenge(AuthenticationConnection *auth, |
ssh_decrypt_challenge(AuthenticationConnection *auth, |
Key* key, BIGNUM *challenge, |
Key* key, BIGNUM *challenge, |
u_char session_id[16], |
unsigned char session_id[16], |
u_int response_type, |
unsigned int response_type, |
u_char response[16]) |
unsigned char response[16]) |
{ |
{ |
Buffer buffer; |
Buffer buffer; |
int success = 0; |
int success = 0; |
|
|
buffer_put_bignum(&buffer, key->rsa->e); |
buffer_put_bignum(&buffer, key->rsa->e); |
buffer_put_bignum(&buffer, key->rsa->n); |
buffer_put_bignum(&buffer, key->rsa->n); |
buffer_put_bignum(&buffer, challenge); |
buffer_put_bignum(&buffer, challenge); |
buffer_append(&buffer, session_id, 16); |
buffer_append(&buffer, (char *) session_id, 16); |
buffer_put_int(&buffer, response_type); |
buffer_put_int(&buffer, response_type); |
|
|
if (ssh_request_reply(auth, &buffer, &buffer) == 0) { |
if (ssh_request_reply(auth, &buffer, &buffer) == 0) { |
|
|
int |
int |
ssh_agent_sign(AuthenticationConnection *auth, |
ssh_agent_sign(AuthenticationConnection *auth, |
Key *key, |
Key *key, |
u_char **sigp, u_int *lenp, |
unsigned char **sigp, int *lenp, |
u_char *data, u_int datalen) |
unsigned char *data, int datalen) |
{ |
{ |
extern int datafellows; |
extern int datafellows; |
Buffer msg; |
Buffer msg; |
u_char *blob; |
unsigned char *blob; |
u_int blen; |
unsigned int blen; |
int type, flags = 0; |
int type, flags = 0; |
int ret = -1; |
int ret = -1; |
|
|
|
|
|
|
/* Encode key for a message to the agent. */ |
/* Encode key for a message to the agent. */ |
|
|
static void |
void |
ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment) |
ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment) |
{ |
{ |
buffer_clear(b); |
buffer_clear(b); |
|
|
buffer_put_bignum(b, key->iqmp); /* ssh key->u */ |
buffer_put_bignum(b, key->iqmp); /* ssh key->u */ |
buffer_put_bignum(b, key->q); /* ssh key->p, SSL key->q */ |
buffer_put_bignum(b, key->q); /* ssh key->p, SSL key->q */ |
buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */ |
buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */ |
buffer_put_cstring(b, comment); |
buffer_put_string(b, comment, strlen(comment)); |
} |
} |
|
|
static void |
void |
ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) |
ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) |
{ |
{ |
buffer_clear(b); |
buffer_clear(b); |
buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY); |
buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY); |
buffer_put_cstring(b, key_ssh_name(key)); |
buffer_put_cstring(b, key_ssh_name(key)); |
switch (key->type) { |
switch(key->type){ |
case KEY_RSA: |
case KEY_RSA: |
buffer_put_bignum2(b, key->rsa->n); |
buffer_put_bignum2(b, key->rsa->n); |
buffer_put_bignum2(b, key->rsa->e); |
buffer_put_bignum2(b, key->rsa->e); |
|
|
{ |
{ |
Buffer msg; |
Buffer msg; |
int type; |
int type; |
u_char *blob; |
unsigned char *blob; |
u_int blen; |
unsigned int blen; |
|
|
buffer_init(&msg); |
buffer_init(&msg); |
|
|
|
|
return decode_reply(type); |
return decode_reply(type); |
} |
} |
|
|
int |
|
ssh_update_card(AuthenticationConnection *auth, int add, const char *reader_id) |
|
{ |
|
Buffer msg; |
|
int type; |
|
|
|
buffer_init(&msg); |
|
buffer_put_char(&msg, add ? SSH_AGENTC_ADD_SMARTCARD_KEY : |
|
SSH_AGENTC_REMOVE_SMARTCARD_KEY); |
|
buffer_put_cstring(&msg, reader_id); |
|
if (ssh_request_reply(auth, &msg, &msg) == 0) { |
|
buffer_free(&msg); |
|
return 0; |
|
} |
|
type = buffer_get_char(&msg); |
|
buffer_free(&msg); |
|
return decode_reply(type); |
|
} |
|
|
|
/* |
/* |
* Removes all identities from the agent. This call is not meant to be used |
* Removes all identities from the agent. This call is not meant to be used |
* by normal applications. |
* by normal applications. |
|
|
return decode_reply(type); |
return decode_reply(type); |
} |
} |
|
|
int |
int |
decode_reply(int type) |
decode_reply(int type) |
{ |
{ |
switch (type) { |
switch (type) { |
case SSH_AGENT_FAILURE: |
case SSH_AGENT_FAILURE: |
case SSH_COM_AGENT2_FAILURE: |
case SSH_COM_AGENT2_FAILURE: |
case SSH2_AGENT_FAILURE: |
|
log("SSH_AGENT_FAILURE"); |
log("SSH_AGENT_FAILURE"); |
return 0; |
return 0; |
case SSH_AGENT_SUCCESS: |
case SSH_AGENT_SUCCESS: |