Annotation of src/usr.bin/ssh/authfd.c, Revision 1.22
1.1 deraadt 1: /*
1.18 markus 2: *
1.13 deraadt 3: * authfd.c
1.18 markus 4: *
1.13 deraadt 5: * Author: Tatu Ylonen <ylo@cs.hut.fi>
1.18 markus 6: *
1.13 deraadt 7: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8: * All rights reserved
1.18 markus 9: *
1.13 deraadt 10: * Created: Wed Mar 29 01:30:28 1995 ylo
1.18 markus 11: *
1.13 deraadt 12: * Functions for connecting the local authentication agent.
1.18 markus 13: *
1.13 deraadt 14: */
1.1 deraadt 15:
16: #include "includes.h"
1.21 markus 17: RCSID("$OpenBSD: authfd.c,v 1.20 2000/06/20 01:39:38 markus Exp $");
1.1 deraadt 18:
19: #include "ssh.h"
20: #include "rsa.h"
21: #include "buffer.h"
22: #include "bufaux.h"
23: #include "xmalloc.h"
24: #include "getput.h"
25:
1.17 markus 26: #include <openssl/rsa.h>
1.22 ! markus 27: #include <openssl/dsa.h>
! 28: #include <openssl/evp.h>
! 29: #include "key.h"
! 30: #include "authfd.h"
! 31: #include "kex.h"
1.2 provos 32:
1.21 markus 33: /* helper */
34: int ssh_agent_get_reply(AuthenticationConnection *auth);
35:
1.1 deraadt 36: /* Returns the number of the authentication fd, or -1 if there is none. */
37:
1.2 provos 38: int
1.8 markus 39: ssh_get_authentication_socket()
1.1 deraadt 40: {
1.12 markus 41: const char *authsocket;
42: int sock;
43: struct sockaddr_un sunaddr;
44:
45: authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
46: if (!authsocket)
47: return -1;
48:
49: sunaddr.sun_family = AF_UNIX;
50: strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
51:
52: sock = socket(AF_UNIX, SOCK_STREAM, 0);
53: if (sock < 0)
54: return -1;
55:
56: /* close on exec */
57: if (fcntl(sock, F_SETFD, 1) == -1) {
58: close(sock);
59: return -1;
60: }
61: if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
62: close(sock);
63: return -1;
64: }
65: return sock;
1.1 deraadt 66: }
67:
1.14 markus 68: /*
69: * Closes the agent socket if it should be closed (depends on how it was
70: * obtained). The argument must have been returned by
71: * ssh_get_authentication_socket().
72: */
1.1 deraadt 73:
1.18 markus 74: void
1.12 markus 75: ssh_close_authentication_socket(int sock)
1.1 deraadt 76: {
1.12 markus 77: if (getenv(SSH_AUTHSOCKET_ENV_NAME))
78: close(sock);
1.1 deraadt 79: }
80:
1.14 markus 81: /*
82: * Opens and connects a private socket for communication with the
83: * authentication agent. Returns the file descriptor (which must be
84: * shut down and closed by the caller when no longer needed).
85: * Returns NULL if an error occurred and the connection could not be
86: * opened.
87: */
1.1 deraadt 88:
1.12 markus 89: AuthenticationConnection *
90: ssh_get_authentication_connection()
1.1 deraadt 91: {
1.12 markus 92: AuthenticationConnection *auth;
93: int sock;
1.1 deraadt 94:
1.12 markus 95: sock = ssh_get_authentication_socket();
96:
1.14 markus 97: /*
98: * Fail if we couldn't obtain a connection. This happens if we
99: * exited due to a timeout.
100: */
1.12 markus 101: if (sock < 0)
102: return NULL;
103:
104: auth = xmalloc(sizeof(*auth));
105: auth->fd = sock;
106: buffer_init(&auth->packet);
107: buffer_init(&auth->identities);
108: auth->howmany = 0;
109:
110: return auth;
1.1 deraadt 111: }
112:
1.14 markus 113: /*
114: * Closes the connection to the authentication agent and frees any associated
115: * memory.
116: */
1.1 deraadt 117:
1.18 markus 118: void
1.12 markus 119: ssh_close_authentication_connection(AuthenticationConnection *ac)
1.1 deraadt 120: {
1.12 markus 121: buffer_free(&ac->packet);
122: buffer_free(&ac->identities);
123: close(ac->fd);
124: xfree(ac);
1.1 deraadt 125: }
126:
1.14 markus 127: /*
128: * Returns the first authentication identity held by the agent.
129: * Returns true if an identity is available, 0 otherwise.
130: * The caller must initialize the integers before the call, and free the
131: * comment after a successful call (before calling ssh_get_next_identity).
132: */
1.1 deraadt 133:
1.2 provos 134: int
135: ssh_get_first_identity(AuthenticationConnection *auth,
1.9 markus 136: BIGNUM *e, BIGNUM *n, char **comment)
1.1 deraadt 137: {
1.12 markus 138: unsigned char msg[8192];
139: int len, l;
1.1 deraadt 140:
1.14 markus 141: /*
142: * Send a message to the agent requesting for a list of the
143: * identities it can represent.
144: */
1.22 ! markus 145: PUT_32BIT(msg, 1);
1.12 markus 146: msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
1.15 deraadt 147: if (atomicio(write, auth->fd, msg, 5) != 5) {
1.12 markus 148: error("write auth->fd: %.100s", strerror(errno));
149: return 0;
150: }
151: /* Read the length of the response. XXX implement timeouts here. */
152: len = 4;
153: while (len > 0) {
154: l = read(auth->fd, msg + 4 - len, len);
155: if (l <= 0) {
156: error("read auth->fd: %.100s", strerror(errno));
157: return 0;
158: }
159: len -= l;
160: }
161:
1.14 markus 162: /*
163: * Extract the length, and check it for sanity. (We cannot trust
164: * authentication agents).
165: */
1.12 markus 166: len = GET_32BIT(msg);
167: if (len < 1 || len > 256 * 1024)
168: fatal("Authentication reply message too long: %d\n", len);
169:
170: /* Read the packet itself. */
171: buffer_clear(&auth->identities);
172: while (len > 0) {
173: l = len;
174: if (l > sizeof(msg))
175: l = sizeof(msg);
176: l = read(auth->fd, msg, l);
177: if (l <= 0)
178: fatal("Incomplete authentication reply.");
179: buffer_append(&auth->identities, (char *) msg, l);
180: len -= l;
181: }
1.1 deraadt 182:
1.12 markus 183: /* Get message type, and verify that we got a proper answer. */
184: buffer_get(&auth->identities, (char *) msg, 1);
185: if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
186: fatal("Bad authentication reply message type: %d", msg[0]);
187:
188: /* Get the number of entries in the response and check it for sanity. */
189: auth->howmany = buffer_get_int(&auth->identities);
190: if (auth->howmany > 1024)
191: fatal("Too many identities in authentication reply: %d\n", auth->howmany);
192:
193: /* Return the first entry (if any). */
194: return ssh_get_next_identity(auth, e, n, comment);
1.1 deraadt 195: }
196:
1.14 markus 197: /*
198: * Returns the next authentication identity for the agent. Other functions
199: * can be called between this and ssh_get_first_identity or two calls of this
200: * function. This returns 0 if there are no more identities. The caller
201: * must free comment after a successful return.
202: */
1.1 deraadt 203:
1.2 provos 204: int
205: ssh_get_next_identity(AuthenticationConnection *auth,
1.9 markus 206: BIGNUM *e, BIGNUM *n, char **comment)
1.1 deraadt 207: {
1.12 markus 208: unsigned int bits;
1.9 markus 209:
1.12 markus 210: /* Return failure if no more entries. */
211: if (auth->howmany <= 0)
212: return 0;
213:
1.14 markus 214: /*
215: * Get the next entry from the packet. These will abort with a fatal
216: * error if the packet is too short or contains corrupt data.
217: */
1.12 markus 218: bits = buffer_get_int(&auth->identities);
219: buffer_get_bignum(&auth->identities, e);
220: buffer_get_bignum(&auth->identities, n);
221: *comment = buffer_get_string(&auth->identities, NULL);
222:
223: if (bits != BN_num_bits(n))
1.19 markus 224: log("Warning: identity keysize mismatch: actual %d, announced %u",
225: BN_num_bits(n), bits);
1.9 markus 226:
1.12 markus 227: /* Decrement the number of remaining entries. */
228: auth->howmany--;
1.1 deraadt 229:
1.12 markus 230: return 1;
1.1 deraadt 231: }
232:
1.14 markus 233: /*
234: * Generates a random challenge, sends it to the agent, and waits for
235: * response from the agent. Returns true (non-zero) if the agent gave the
236: * correct answer, zero otherwise. Response type selects the style of
237: * response desired, with 0 corresponding to protocol version 1.0 (no longer
238: * supported) and 1 corresponding to protocol version 1.1.
239: */
1.1 deraadt 240:
1.2 provos 241: int
242: ssh_decrypt_challenge(AuthenticationConnection *auth,
1.12 markus 243: BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
1.2 provos 244: unsigned char session_id[16],
245: unsigned int response_type,
246: unsigned char response[16])
1.1 deraadt 247: {
1.12 markus 248: Buffer buffer;
249: unsigned char buf[8192];
250: int len, l, i;
251:
252: /* Response type 0 is no longer supported. */
253: if (response_type == 0)
254: fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
255:
256: /* Format a message to the agent. */
257: buf[0] = SSH_AGENTC_RSA_CHALLENGE;
258: buffer_init(&buffer);
259: buffer_append(&buffer, (char *) buf, 1);
260: buffer_put_int(&buffer, BN_num_bits(n));
261: buffer_put_bignum(&buffer, e);
262: buffer_put_bignum(&buffer, n);
263: buffer_put_bignum(&buffer, challenge);
264: buffer_append(&buffer, (char *) session_id, 16);
265: buffer_put_int(&buffer, response_type);
266:
267: /* Get the length of the message, and format it in the buffer. */
268: len = buffer_len(&buffer);
269: PUT_32BIT(buf, len);
270:
271: /* Send the length and then the packet to the agent. */
1.15 deraadt 272: if (atomicio(write, auth->fd, buf, 4) != 4 ||
273: atomicio(write, auth->fd, buffer_ptr(&buffer),
274: buffer_len(&buffer)) != buffer_len(&buffer)) {
1.12 markus 275: error("Error writing to authentication socket.");
276: error_cleanup:
277: buffer_free(&buffer);
278: return 0;
279: }
1.14 markus 280: /*
281: * Wait for response from the agent. First read the length of the
282: * response packet.
283: */
1.12 markus 284: len = 4;
285: while (len > 0) {
286: l = read(auth->fd, buf + 4 - len, len);
287: if (l <= 0) {
288: error("Error reading response length from authentication socket.");
289: goto error_cleanup;
290: }
291: len -= l;
292: }
293:
294: /* Extract the length, and check it for sanity. */
295: len = GET_32BIT(buf);
296: if (len > 256 * 1024)
297: fatal("Authentication response too long: %d", len);
298:
299: /* Read the rest of the response in tothe buffer. */
300: buffer_clear(&buffer);
301: while (len > 0) {
302: l = len;
303: if (l > sizeof(buf))
304: l = sizeof(buf);
305: l = read(auth->fd, buf, l);
306: if (l <= 0) {
307: error("Error reading response from authentication socket.");
308: goto error_cleanup;
309: }
310: buffer_append(&buffer, (char *) buf, l);
311: len -= l;
312: }
313:
314: /* Get the type of the packet. */
315: buffer_get(&buffer, (char *) buf, 1);
316:
317: /* Check for agent failure message. */
318: if (buf[0] == SSH_AGENT_FAILURE) {
319: log("Agent admitted failure to authenticate using the key.");
320: goto error_cleanup;
321: }
322: /* Now it must be an authentication response packet. */
323: if (buf[0] != SSH_AGENT_RSA_RESPONSE)
324: fatal("Bad authentication response: %d", buf[0]);
325:
1.14 markus 326: /*
327: * Get the response from the packet. This will abort with a fatal
328: * error if the packet is corrupt.
329: */
1.12 markus 330: for (i = 0; i < 16; i++)
331: response[i] = buffer_get_char(&buffer);
332:
333: /* The buffer containing the packet is no longer needed. */
334: buffer_free(&buffer);
335:
336: /* Correct answer. */
337: return 1;
338: }
1.1 deraadt 339:
1.22 ! markus 340: /* Encode key for a message to the agent. */
! 341:
! 342: void
! 343: ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment)
! 344: {
! 345: buffer_clear(b);
! 346: buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY);
! 347: buffer_put_int(b, BN_num_bits(key->n));
! 348: buffer_put_bignum(b, key->n);
! 349: buffer_put_bignum(b, key->e);
! 350: buffer_put_bignum(b, key->d);
! 351: /* To keep within the protocol: p < q for ssh. in SSL p > q */
! 352: buffer_put_bignum(b, key->iqmp); /* ssh key->u */
! 353: buffer_put_bignum(b, key->q); /* ssh key->p, SSL key->q */
! 354: buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */
! 355: buffer_put_string(b, comment, strlen(comment));
! 356: }
! 357:
! 358: void
! 359: ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment)
! 360: {
! 361: buffer_clear(b);
! 362: buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY);
! 363: buffer_put_cstring(b, KEX_DSS);
! 364: buffer_put_bignum2(b, key->p);
! 365: buffer_put_bignum2(b, key->q);
! 366: buffer_put_bignum2(b, key->g);
! 367: buffer_put_bignum2(b, key->pub_key);
! 368: buffer_put_bignum2(b, key->priv_key);
! 369: buffer_put_string(b, comment, strlen(comment));
! 370: }
! 371:
1.14 markus 372: /*
373: * Adds an identity to the authentication server. This call is not meant to
374: * be used by normal applications.
375: */
1.1 deraadt 376:
1.18 markus 377: int
1.22 ! markus 378: ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
1.1 deraadt 379: {
1.12 markus 380: Buffer buffer;
381: unsigned char buf[8192];
1.21 markus 382: int len;
1.12 markus 383:
384: buffer_init(&buffer);
1.22 ! markus 385:
! 386: switch (key->type) {
! 387: case KEY_RSA:
! 388: ssh_encode_identity_rsa(&buffer, key->rsa, comment);
! 389: break;
! 390: case KEY_DSA:
! 391: ssh_encode_identity_dsa(&buffer, key->dsa, comment);
! 392: break;
! 393: default:
! 394: buffer_free(&buffer);
! 395: return 0;
! 396: break;
! 397: }
1.12 markus 398:
399: /* Get the length of the message, and format it in the buffer. */
400: len = buffer_len(&buffer);
401: PUT_32BIT(buf, len);
402:
403: /* Send the length and then the packet to the agent. */
1.15 deraadt 404: if (atomicio(write, auth->fd, buf, 4) != 4 ||
405: atomicio(write, auth->fd, buffer_ptr(&buffer),
406: buffer_len(&buffer)) != buffer_len(&buffer)) {
1.12 markus 407: error("Error writing to authentication socket.");
408: buffer_free(&buffer);
409: return 0;
410: }
1.21 markus 411: buffer_free(&buffer);
412: return ssh_agent_get_reply(auth);
1.12 markus 413: }
1.1 deraadt 414:
1.14 markus 415: /*
416: * Removes an identity from the authentication server. This call is not
417: * meant to be used by normal applications.
418: */
1.1 deraadt 419:
1.18 markus 420: int
1.12 markus 421: ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
1.1 deraadt 422: {
1.12 markus 423: Buffer buffer;
1.21 markus 424: unsigned char buf[5];
425: int len;
1.12 markus 426:
427: /* Format a message to the agent. */
428: buffer_init(&buffer);
429: buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
430: buffer_put_int(&buffer, BN_num_bits(key->n));
431: buffer_put_bignum(&buffer, key->e);
432: buffer_put_bignum(&buffer, key->n);
433:
434: /* Get the length of the message, and format it in the buffer. */
435: len = buffer_len(&buffer);
436: PUT_32BIT(buf, len);
437:
438: /* Send the length and then the packet to the agent. */
1.15 deraadt 439: if (atomicio(write, auth->fd, buf, 4) != 4 ||
440: atomicio(write, auth->fd, buffer_ptr(&buffer),
441: buffer_len(&buffer)) != buffer_len(&buffer)) {
1.12 markus 442: error("Error writing to authentication socket.");
443: buffer_free(&buffer);
444: return 0;
445: }
1.21 markus 446: buffer_free(&buffer);
447: return ssh_agent_get_reply(auth);
1.12 markus 448: }
449:
1.14 markus 450: /*
451: * Removes all identities from the agent. This call is not meant to be used
452: * by normal applications.
453: */
1.1 deraadt 454:
1.18 markus 455: int
1.12 markus 456: ssh_remove_all_identities(AuthenticationConnection *auth)
1.1 deraadt 457: {
1.21 markus 458: unsigned char buf[5];
1.12 markus 459:
460: /* Get the length of the message, and format it in the buffer. */
461: PUT_32BIT(buf, 1);
462: buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
463:
464: /* Send the length and then the packet to the agent. */
1.15 deraadt 465: if (atomicio(write, auth->fd, buf, 5) != 5) {
1.12 markus 466: error("Error writing to authentication socket.");
467: return 0;
468: }
1.21 markus 469: return ssh_agent_get_reply(auth);
470: }
471:
472: /*
473: * Read for reply from agent. returns 1 for success, 0 on error
474: */
475:
476: int
477: ssh_agent_get_reply(AuthenticationConnection *auth)
478: {
479: Buffer buffer;
480: unsigned char buf[8192];
481: int len, l, type;
482:
1.14 markus 483: /*
484: * Wait for response from the agent. First read the length of the
485: * response packet.
486: */
1.12 markus 487: len = 4;
488: while (len > 0) {
489: l = read(auth->fd, buf + 4 - len, len);
490: if (l <= 0) {
491: error("Error reading response length from authentication socket.");
1.21 markus 492: buffer_free(&buffer);
1.12 markus 493: return 0;
494: }
495: len -= l;
496: }
497:
498: /* Extract the length, and check it for sanity. */
499: len = GET_32BIT(buf);
500: if (len > 256 * 1024)
1.21 markus 501: fatal("Response from agent too long: %d", len);
1.12 markus 502:
1.21 markus 503: /* Read the rest of the response in to the buffer. */
1.12 markus 504: buffer_init(&buffer);
505: while (len > 0) {
506: l = len;
507: if (l > sizeof(buf))
508: l = sizeof(buf);
509: l = read(auth->fd, buf, l);
510: if (l <= 0) {
511: error("Error reading response from authentication socket.");
512: buffer_free(&buffer);
513: return 0;
514: }
515: buffer_append(&buffer, (char *) buf, l);
516: len -= l;
517: }
518:
519: /* Get the type of the packet. */
520: type = buffer_get_char(&buffer);
1.21 markus 521: buffer_free(&buffer);
1.12 markus 522: switch (type) {
523: case SSH_AGENT_FAILURE:
1.22 ! markus 524: log("SSH_AGENT_FAILURE");
1.12 markus 525: return 0;
526: case SSH_AGENT_SUCCESS:
527: return 1;
528: default:
1.21 markus 529: fatal("Bad response from authentication agent: %d", type);
1.12 markus 530: }
531: /* NOTREACHED */
532: return 0;
533: }