authfd.c revision 65674
1148456Spjd/* 2148456Spjd * Author: Tatu Ylonen <ylo@cs.hut.fi> 3148456Spjd * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4148456Spjd * All rights reserved 5148456Spjd * Functions for connecting the local authentication agent. 6148456Spjd * 7148456Spjd * As far as I am concerned, the code I have written for this software 8148456Spjd * can be used freely for any purpose. Any derived versions of this 9148456Spjd * software must be clearly marked as such, and if the derived work is 10148456Spjd * incompatible with the protocol description in the RFC file, it must be 11148456Spjd * called by a name other than "ssh" or "Secure Shell". 12148456Spjd * 13148456Spjd * SSH2 implementation, 14148456Spjd * Copyright (c) 2000 Markus Friedl. All rights reserved. 15148456Spjd * 16148456Spjd * Redistribution and use in source and binary forms, with or without 17148456Spjd * modification, are permitted provided that the following conditions 18148456Spjd * are met: 19148456Spjd * 1. Redistributions of source code must retain the above copyright 20148456Spjd * notice, this list of conditions and the following disclaimer. 21148456Spjd * 2. Redistributions in binary form must reproduce the above copyright 22148456Spjd * notice, this list of conditions and the following disclaimer in the 23148456Spjd * documentation and/or other materials provided with the distribution. 24148456Spjd * 25148456Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26148456Spjd * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27148456Spjd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28148456Spjd * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29148456Spjd * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30148456Spjd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31148456Spjd * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32148456Spjd * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33148456Spjd * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34148456Spjd * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35148456Spjd */ 36148456Spjd 37148456Spjd#include "includes.h" 38148456SpjdRCSID("$OpenBSD: authfd.c,v 1.27 2000/09/07 20:27:49 deraadt Exp $"); 39148456SpjdRCSID("$FreeBSD: head/crypto/openssh/authfd.c 65674 2000-09-10 09:35:38Z kris $"); 40148456Spjd 41148456Spjd#include "ssh.h" 42148456Spjd#include "rsa.h" 43148456Spjd#include "buffer.h" 44148867Spjd#include "bufaux.h" 45148456Spjd#include "xmalloc.h" 46148456Spjd#include "getput.h" 47148456Spjd 48148456Spjd#include <openssl/rsa.h> 49148456Spjd#include <openssl/dsa.h> 50148456Spjd#include <openssl/evp.h> 51148456Spjd#include "key.h" 52148456Spjd#include "authfd.h" 53148456Spjd#include "kex.h" 54148456Spjd#include "dsa.h" 55148456Spjd 56148456Spjd/* helper */ 57148456Spjdint decode_reply(int type); 58148456Spjd 59148456Spjd/* Returns the number of the authentication fd, or -1 if there is none. */ 60148456Spjd 61148456Spjdint 62148456Spjdssh_get_authentication_socket() 63148456Spjd{ 64148456Spjd const char *authsocket; 65148456Spjd int sock, len; 66148456Spjd struct sockaddr_un sunaddr; 67148456Spjd 68148456Spjd authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); 69148456Spjd if (!authsocket) 70148456Spjd return -1; 71148456Spjd 72148456Spjd sunaddr.sun_family = AF_UNIX; 73148456Spjd strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); 74148456Spjd sunaddr.sun_len = len = SUN_LEN(&sunaddr)+1; 75148456Spjd 76148456Spjd sock = socket(AF_UNIX, SOCK_STREAM, 0); 77148456Spjd if (sock < 0) 78148456Spjd return -1; 79148456Spjd 80148456Spjd /* close on exec */ 81148456Spjd if (fcntl(sock, F_SETFD, 1) == -1) { 82148456Spjd close(sock); 83148456Spjd return -1; 84148456Spjd } 85148456Spjd if (connect(sock, (struct sockaddr *) & sunaddr, len) < 0) { 86148456Spjd close(sock); 87148456Spjd return -1; 88148456Spjd } 89148456Spjd return sock; 90148456Spjd} 91148456Spjd 92148456Spjdint 93148456Spjdssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply) 94148456Spjd{ 95148456Spjd int l, len; 96148456Spjd char buf[1024]; 97148456Spjd 98148456Spjd /* Get the length of the message, and format it in the buffer. */ 99148456Spjd len = buffer_len(request); 100148456Spjd PUT_32BIT(buf, len); 101148456Spjd 102148456Spjd /* Send the length and then the packet to the agent. */ 103148456Spjd if (atomicio(write, auth->fd, buf, 4) != 4 || 104148456Spjd atomicio(write, auth->fd, buffer_ptr(request), 105148456Spjd buffer_len(request)) != buffer_len(request)) { 106148456Spjd error("Error writing to authentication socket."); 107148456Spjd return 0; 108148456Spjd } 109148456Spjd /* 110148456Spjd * Wait for response from the agent. First read the length of the 111148456Spjd * response packet. 112148456Spjd */ 113148456Spjd len = 4; 114148456Spjd while (len > 0) { 115148456Spjd l = read(auth->fd, buf + 4 - len, len); 116148456Spjd if (l <= 0) { 117148456Spjd error("Error reading response length from authentication socket."); 118148456Spjd return 0; 119148456Spjd } 120148456Spjd len -= l; 121148456Spjd } 122148456Spjd 123148456Spjd /* Extract the length, and check it for sanity. */ 124148456Spjd len = GET_32BIT(buf); 125148456Spjd if (len > 256 * 1024) 126148456Spjd fatal("Authentication response too long: %d", len); 127148456Spjd 128148456Spjd /* Read the rest of the response in to the buffer. */ 129148456Spjd buffer_clear(reply); 130148456Spjd while (len > 0) { 131148456Spjd l = len; 132148456Spjd if (l > sizeof(buf)) 133148456Spjd l = sizeof(buf); 134148456Spjd l = read(auth->fd, buf, l); 135148456Spjd if (l <= 0) { 136148456Spjd error("Error reading response from authentication socket."); 137148456Spjd return 0; 138148456Spjd } 139148456Spjd buffer_append(reply, (char *) buf, l); 140148456Spjd len -= l; 141148456Spjd } 142148456Spjd return 1; 143148456Spjd} 144148456Spjd 145148456Spjd/* 146148456Spjd * Closes the agent socket if it should be closed (depends on how it was 147148456Spjd * obtained). The argument must have been returned by 148148456Spjd * ssh_get_authentication_socket(). 149148456Spjd */ 150148456Spjd 151149303Spjdvoid 152148456Spjdssh_close_authentication_socket(int sock) 153148456Spjd{ 154148456Spjd if (getenv(SSH_AUTHSOCKET_ENV_NAME)) 155148456Spjd close(sock); 156148456Spjd} 157148456Spjd 158148456Spjd/* 159148456Spjd * Opens and connects a private socket for communication with the 160148456Spjd * authentication agent. Returns the file descriptor (which must be 161148456Spjd * shut down and closed by the caller when no longer needed). 162148456Spjd * Returns NULL if an error occurred and the connection could not be 163148456Spjd * opened. 164148456Spjd */ 165148456Spjd 166148456SpjdAuthenticationConnection * 167148456Spjdssh_get_authentication_connection() 168148456Spjd{ 169148456Spjd AuthenticationConnection *auth; 170148456Spjd int sock; 171148456Spjd 172148456Spjd sock = ssh_get_authentication_socket(); 173148456Spjd 174148456Spjd /* 175148456Spjd * Fail if we couldn't obtain a connection. This happens if we 176148456Spjd * exited due to a timeout. 177148456Spjd */ 178148456Spjd if (sock < 0) 179148456Spjd return NULL; 180148456Spjd 181148456Spjd auth = xmalloc(sizeof(*auth)); 182148456Spjd auth->fd = sock; 183148456Spjd buffer_init(&auth->identities); 184148456Spjd auth->howmany = 0; 185148456Spjd 186148456Spjd return auth; 187148456Spjd} 188148456Spjd 189148456Spjd/* 190148456Spjd * Closes the connection to the authentication agent and frees any associated 191148456Spjd * memory. 192148456Spjd */ 193148456Spjd 194148456Spjdvoid 195148456Spjdssh_close_authentication_connection(AuthenticationConnection *auth) 196148456Spjd{ 197148456Spjd buffer_free(&auth->identities); 198148456Spjd close(auth->fd); 199148456Spjd xfree(auth); 200148456Spjd} 201148456Spjd 202148456Spjd/* 203148456Spjd * Returns the first authentication identity held by the agent. 204148456Spjd */ 205148456Spjd 206148456SpjdKey * 207148456Spjdssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version) 208148456Spjd{ 209148456Spjd int type, code1 = 0, code2 = 0; 210148456Spjd Buffer request; 211148456Spjd 212148456Spjd switch(version){ 213148456Spjd case 1: 214148456Spjd code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; 215148456Spjd code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; 216148456Spjd break; 217148456Spjd case 2: 218148456Spjd code1 = SSH2_AGENTC_REQUEST_IDENTITIES; 219148456Spjd code2 = SSH2_AGENT_IDENTITIES_ANSWER; 220148456Spjd break; 221148456Spjd default: 222148456Spjd return NULL; 223148456Spjd } 224148456Spjd 225148456Spjd /* 226148456Spjd * Send a message to the agent requesting for a list of the 227148867Spjd * identities it can represent. 228148456Spjd */ 229148867Spjd buffer_init(&request); 230148456Spjd buffer_put_char(&request, code1); 231148867Spjd 232148456Spjd buffer_clear(&auth->identities); 233148867Spjd if (ssh_request_reply(auth, &request, &auth->identities) == 0) { 234148456Spjd buffer_free(&request); 235148456Spjd return NULL; 236148456Spjd } 237148456Spjd buffer_free(&request); 238148456Spjd 239148456Spjd /* Get message type, and verify that we got a proper answer. */ 240148456Spjd type = buffer_get_char(&auth->identities); 241148456Spjd if (type == SSH_AGENT_FAILURE) { 242148456Spjd return NULL; 243148456Spjd } else if (type != code2) { 244148456Spjd fatal("Bad authentication reply message type: %d", type); 245148456Spjd } 246148456Spjd 247148456Spjd /* Get the number of entries in the response and check it for sanity. */ 248148456Spjd auth->howmany = buffer_get_int(&auth->identities); 249148456Spjd if (auth->howmany > 1024) 250148456Spjd fatal("Too many identities in authentication reply: %d\n", 251148456Spjd auth->howmany); 252148456Spjd 253148456Spjd /* Return the first entry (if any). */ 254148456Spjd return ssh_get_next_identity(auth, comment, version); 255148456Spjd} 256148456Spjd 257148456SpjdKey * 258148456Spjdssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version) 259148456Spjd{ 260148456Spjd unsigned int bits; 261148456Spjd unsigned char *blob; 262148456Spjd unsigned int blen; 263148456Spjd Key *key = NULL; 264148456Spjd 265148456Spjd /* Return failure if no more entries. */ 266148456Spjd if (auth->howmany <= 0) 267148456Spjd return NULL; 268148456Spjd 269148456Spjd /* 270148456Spjd * Get the next entry from the packet. These will abort with a fatal 271148456Spjd * error if the packet is too short or contains corrupt data. 272148456Spjd */ 273148456Spjd switch(version){ 274148456Spjd case 1: 275148456Spjd key = key_new(KEY_RSA); 276149303Spjd bits = buffer_get_int(&auth->identities); 277148456Spjd buffer_get_bignum(&auth->identities, key->rsa->e); 278148456Spjd buffer_get_bignum(&auth->identities, key->rsa->n); 279148456Spjd *comment = buffer_get_string(&auth->identities, NULL); 280148456Spjd if (bits != BN_num_bits(key->rsa->n)) 281148456Spjd log("Warning: identity keysize mismatch: actual %d, announced %u", 282148456Spjd BN_num_bits(key->rsa->n), bits); 283148456Spjd break; 284148456Spjd case 2: 285148456Spjd blob = buffer_get_string(&auth->identities, &blen); 286148456Spjd *comment = buffer_get_string(&auth->identities, NULL); 287148456Spjd key = dsa_key_from_blob(blob, blen); 288149303Spjd xfree(blob); 289148456Spjd break; 290148456Spjd default: 291148456Spjd return NULL; 292148456Spjd break; 293148456Spjd } 294148456Spjd /* Decrement the number of remaining entries. */ 295148456Spjd auth->howmany--; 296148456Spjd return key; 297148456Spjd} 298148456Spjd 299148456Spjd/* 300148456Spjd * Generates a random challenge, sends it to the agent, and waits for 301148456Spjd * response from the agent. Returns true (non-zero) if the agent gave the 302148456Spjd * correct answer, zero otherwise. Response type selects the style of 303148456Spjd * response desired, with 0 corresponding to protocol version 1.0 (no longer 304148456Spjd * supported) and 1 corresponding to protocol version 1.1. 305148456Spjd */ 306148456Spjd 307148456Spjdint 308148456Spjdssh_decrypt_challenge(AuthenticationConnection *auth, 309148456Spjd Key* key, BIGNUM *challenge, 310148456Spjd unsigned char session_id[16], 311148456Spjd unsigned int response_type, 312148456Spjd unsigned char response[16]) 313148456Spjd{ 314148456Spjd Buffer buffer; 315148456Spjd int success = 0; 316148456Spjd int i; 317148456Spjd int type; 318148456Spjd 319148456Spjd if (key->type != KEY_RSA) 320148456Spjd return 0; 321148456Spjd if (response_type == 0) { 322148456Spjd log("Compatibility with ssh protocol version 1.0 no longer supported."); 323148456Spjd return 0; 324148456Spjd } 325148456Spjd buffer_init(&buffer); 326148456Spjd buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE); 327148456Spjd buffer_put_int(&buffer, BN_num_bits(key->rsa->n)); 328148456Spjd buffer_put_bignum(&buffer, key->rsa->e); 329148456Spjd buffer_put_bignum(&buffer, key->rsa->n); 330148456Spjd buffer_put_bignum(&buffer, challenge); 331148456Spjd buffer_append(&buffer, (char *) session_id, 16); 332148456Spjd buffer_put_int(&buffer, response_type); 333148456Spjd 334148456Spjd if (ssh_request_reply(auth, &buffer, &buffer) == 0) { 335148456Spjd buffer_free(&buffer); 336148456Spjd return 0; 337148456Spjd } 338148456Spjd type = buffer_get_char(&buffer); 339148456Spjd 340148456Spjd if (type == SSH_AGENT_FAILURE) { 341148456Spjd log("Agent admitted failure to authenticate using the key."); 342148456Spjd } else if (type != SSH_AGENT_RSA_RESPONSE) { 343148456Spjd fatal("Bad authentication response: %d", type); 344148456Spjd } else { 345148456Spjd success = 1; 346148456Spjd /* 347148456Spjd * Get the response from the packet. This will abort with a 348148456Spjd * fatal error if the packet is corrupt. 349148456Spjd */ 350148456Spjd for (i = 0; i < 16; i++) 351148456Spjd response[i] = buffer_get_char(&buffer); 352148456Spjd } 353148456Spjd buffer_free(&buffer); 354148456Spjd return success; 355148456Spjd} 356148456Spjd 357148456Spjd/* ask agent to sign data, returns -1 on error, 0 on success */ 358148456Spjdint 359148456Spjdssh_agent_sign(AuthenticationConnection *auth, 360148456Spjd Key *key, 361148456Spjd unsigned char **sigp, int *lenp, 362148456Spjd unsigned char *data, int datalen) 363148456Spjd{ 364148456Spjd Buffer msg; 365148456Spjd unsigned char *blob; 366148456Spjd unsigned int blen; 367148456Spjd int type; 368 int ret = -1; 369 370 if (dsa_make_key_blob(key, &blob, &blen) == 0) 371 return -1; 372 373 buffer_init(&msg); 374 buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST); 375 buffer_put_string(&msg, blob, blen); 376 buffer_put_string(&msg, data, datalen); 377 buffer_put_int(&msg, 0); /* flags, unused */ 378 xfree(blob); 379 380 if (ssh_request_reply(auth, &msg, &msg) == 0) { 381 buffer_free(&msg); 382 return -1; 383 } 384 type = buffer_get_char(&msg); 385 if (type == SSH_AGENT_FAILURE) { 386 log("Agent admitted failure to sign using the key."); 387 } else if (type != SSH2_AGENT_SIGN_RESPONSE) { 388 fatal("Bad authentication response: %d", type); 389 } else { 390 ret = 0; 391 *sigp = buffer_get_string(&msg, lenp); 392 } 393 buffer_free(&msg); 394 return ret; 395} 396 397/* Encode key for a message to the agent. */ 398 399void 400ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment) 401{ 402 buffer_clear(b); 403 buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY); 404 buffer_put_int(b, BN_num_bits(key->n)); 405 buffer_put_bignum(b, key->n); 406 buffer_put_bignum(b, key->e); 407 buffer_put_bignum(b, key->d); 408 /* To keep within the protocol: p < q for ssh. in SSL p > q */ 409 buffer_put_bignum(b, key->iqmp); /* ssh key->u */ 410 buffer_put_bignum(b, key->q); /* ssh key->p, SSL key->q */ 411 buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */ 412 buffer_put_string(b, comment, strlen(comment)); 413} 414 415void 416ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment) 417{ 418 buffer_clear(b); 419 buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY); 420 buffer_put_cstring(b, KEX_DSS); 421 buffer_put_bignum2(b, key->p); 422 buffer_put_bignum2(b, key->q); 423 buffer_put_bignum2(b, key->g); 424 buffer_put_bignum2(b, key->pub_key); 425 buffer_put_bignum2(b, key->priv_key); 426 buffer_put_string(b, comment, strlen(comment)); 427} 428 429/* 430 * Adds an identity to the authentication server. This call is not meant to 431 * be used by normal applications. 432 */ 433 434int 435ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) 436{ 437 Buffer msg; 438 int type; 439 440 buffer_init(&msg); 441 442 switch (key->type) { 443 case KEY_RSA: 444 ssh_encode_identity_rsa(&msg, key->rsa, comment); 445 break; 446 case KEY_DSA: 447 ssh_encode_identity_dsa(&msg, key->dsa, comment); 448 break; 449 default: 450 buffer_free(&msg); 451 return 0; 452 break; 453 } 454 if (ssh_request_reply(auth, &msg, &msg) == 0) { 455 buffer_free(&msg); 456 return 0; 457 } 458 type = buffer_get_char(&msg); 459 buffer_free(&msg); 460 return decode_reply(type); 461} 462 463/* 464 * Removes an identity from the authentication server. This call is not 465 * meant to be used by normal applications. 466 */ 467 468int 469ssh_remove_identity(AuthenticationConnection *auth, Key *key) 470{ 471 Buffer msg; 472 int type; 473 unsigned char *blob; 474 unsigned int blen; 475 476 buffer_init(&msg); 477 478 if (key->type == KEY_RSA) { 479 buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY); 480 buffer_put_int(&msg, BN_num_bits(key->rsa->n)); 481 buffer_put_bignum(&msg, key->rsa->e); 482 buffer_put_bignum(&msg, key->rsa->n); 483 } else if (key->type == KEY_DSA) { 484 dsa_make_key_blob(key, &blob, &blen); 485 buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); 486 buffer_put_string(&msg, blob, blen); 487 xfree(blob); 488 } else { 489 buffer_free(&msg); 490 return 0; 491 } 492 if (ssh_request_reply(auth, &msg, &msg) == 0) { 493 buffer_free(&msg); 494 return 0; 495 } 496 type = buffer_get_char(&msg); 497 buffer_free(&msg); 498 return decode_reply(type); 499} 500 501/* 502 * Removes all identities from the agent. This call is not meant to be used 503 * by normal applications. 504 */ 505 506int 507ssh_remove_all_identities(AuthenticationConnection *auth, int version) 508{ 509 Buffer msg; 510 int type; 511 int code = (version==1) ? 512 SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES : 513 SSH2_AGENTC_REMOVE_ALL_IDENTITIES; 514 515 buffer_init(&msg); 516 buffer_put_char(&msg, code); 517 518 if (ssh_request_reply(auth, &msg, &msg) == 0) { 519 buffer_free(&msg); 520 return 0; 521 } 522 type = buffer_get_char(&msg); 523 buffer_free(&msg); 524 return decode_reply(type); 525} 526 527int 528decode_reply(int type) 529{ 530 switch (type) { 531 case SSH_AGENT_FAILURE: 532 log("SSH_AGENT_FAILURE"); 533 return 0; 534 case SSH_AGENT_SUCCESS: 535 return 1; 536 default: 537 fatal("Bad response from authentication agent: %d", type); 538 } 539 /* NOTREACHED */ 540 return 0; 541} 542