Annotation of src/usr.bin/ssh/authfd.c, Revision 1.5
1.1 deraadt 1: /*
2:
3: authfd.c
4:
5: Author: Tatu Ylonen <ylo@cs.hut.fi>
6:
7: Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8: All rights reserved
9:
10: Created: Wed Mar 29 01:30:28 1995 ylo
11:
12: Functions for connecting the local authentication agent.
13:
14: */
15:
16: #include "includes.h"
1.5 ! deraadt 17: RCSID("$Id: authfd.c,v 1.4 1999/09/30 08:34:24 deraadt Exp $");
1.1 deraadt 18:
19: #include "ssh.h"
20: #include "rsa.h"
21: #include "authfd.h"
22: #include "buffer.h"
23: #include "bufaux.h"
24: #include "xmalloc.h"
25: #include "getput.h"
26:
1.2 provos 27: #include <ssl/rsa.h>
28:
1.1 deraadt 29: /* Returns the number of the authentication fd, or -1 if there is none. */
30:
1.2 provos 31: int
32: ssh_get_authentication_fd()
1.1 deraadt 33: {
34: const char *authfd, *authsocket;
35: int sock;
36: struct sockaddr_un sunaddr;
37:
38: /* Get the file descriptor number from environment. */
39: authfd = getenv(SSH_AUTHFD_ENV_NAME);
40:
41: /* Convert the value to an integer and return it if we got a value. */
42: if (authfd)
43: return atoi(authfd);
44:
45: authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
46: if (!authsocket)
47: return -1;
48:
49: sunaddr.sun_family = AF_UNIX;
1.3 deraadt 50: strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
1.1 deraadt 51:
52: sock = socket(AF_UNIX, SOCK_STREAM, 0);
53: if (sock < 0)
54: return -1;
55:
1.4 deraadt 56: if (connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0)
1.1 deraadt 57: {
58: close(sock);
59: return -1;
60: }
61:
62: return sock;
63: }
64:
65: /* Closes the agent socket if it should be closed (depends on how it was
66: obtained). The argument must have been returned by
67: ssh_get_authentication_fd(). */
68:
69: void ssh_close_authentication_socket(int sock)
70: {
71: if (getenv(SSH_AUTHSOCKET_ENV_NAME))
72: close(sock);
73: }
74:
75: /* Dummy alarm used to prevent waiting for connection from the
76: authentication agent indefinitely. */
77:
1.4 deraadt 78: static void dummy_alarm_handler(int sig)
1.1 deraadt 79: {
80: /* Do nothing; a cought signal will just cause accept to return. */
81: }
82:
83: /* Opens a socket to the authentication server. Returns the number of
84: that socket, or -1 if no connection could be made. */
85:
86: int ssh_get_authentication_connection_fd()
87: {
88: int authfd;
89: int listen_sock, sock, port, addrlen;
90: int old_timeout;
1.4 deraadt 91: void (*old_handler)();
1.1 deraadt 92: struct sockaddr_in sin;
93: char msg[3];
94:
95: /* Get the the socket number from the environment. This is the socket
96: used to obtain the real authentication socket. */
97: authfd = ssh_get_authentication_fd();
98: if (authfd == -1)
99: return -1;
100:
101: /* Create a local socket for listening. */
102: listen_sock = socket(AF_INET, SOCK_STREAM, 0);
103: if (listen_sock == -1)
104: {
105: ssh_close_authentication_socket(authfd);
106: return -1;
107: }
108:
109: /* Bind the socket to random unprivileged port. */
110: memset(&sin, 0, sizeof(sin));
111: sin.sin_family = AF_INET;
112: do
113: {
114: port = 32768 + (rand() % 30000);
115: sin.sin_port = htons(port);
116: }
117: while (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0 &&
118: errno == EADDRINUSE);
119:
120: /* Start listening for connections on the socket. */
121: if (listen(listen_sock, 1) < 0)
122: {
123: error("listen: %.100s", strerror(errno));
124: close(listen_sock);
125: ssh_close_authentication_socket(authfd);
126: return -1;
127: }
128:
129: /* Send a message to the authentication fd requesting the agent or its
130: local representative to connect to the given socket. Note that
131: we use send() to get the packet sent atomically (there can be several
132: clients trying to use the same authentication fd simultaneously). */
133: msg[0] = (char)SSH_AUTHFD_CONNECT;
134: PUT_16BIT(msg + 1, port);
135: if (send(authfd, msg, 3, 0) < 0)
136: {
1.5 ! deraadt 137: shutdown(listen_sock, SHUT_RDWR);
1.1 deraadt 138: close(listen_sock);
139: ssh_close_authentication_socket(authfd);
140: return -1;
141: }
142:
143: /* Setup a timeout so we won't wait for the connection indefinitely. */
144: old_timeout = alarm(120);
145: old_handler = signal(SIGALRM, dummy_alarm_handler);
146:
147: /* Wait for the connection from the agent or its representative. */
148: addrlen = sizeof(sin);
149: sock = accept(listen_sock, (struct sockaddr *)&sin, &addrlen);
150:
151: /* Remove the alarm (restore its old values). */
152: alarm(old_timeout);
153: signal(SIGALRM, old_handler);
154:
155: /* Close the socket we used for listening. It is no longer needed.
156: (The authentication fd and the new connection still remain open.) */
1.5 ! deraadt 157: shutdown(listen_sock, SHUT_RDWR);
1.1 deraadt 158: close(listen_sock);
159: ssh_close_authentication_socket(authfd);
160:
161: return sock;
162: }
163:
164: /* Opens and connects a private socket for communication with the
165: authentication agent. Returns the file descriptor (which must be
166: shut down and closed by the caller when no longer needed).
167: Returns NULL if an error occurred and the connection could not be
168: opened. */
169:
170: AuthenticationConnection *ssh_get_authentication_connection()
171: {
172: AuthenticationConnection *auth;
173: int sock;
174:
175: /* Get a connection to the authentication agent. */
176: sock = ssh_get_authentication_connection_fd();
177:
178: /* Fail if we couldn't obtain a connection. This happens if we exited
179: due to a timeout. */
180: if (sock < 0)
181: return NULL;
182:
183: /* Applocate the connection structure and initialize it. */
184: auth = xmalloc(sizeof(*auth));
185: auth->fd = sock;
186: buffer_init(&auth->packet);
187: buffer_init(&auth->identities);
188: auth->howmany = 0;
189:
190: return auth;
191: }
192:
193: /* Closes the connection to the authentication agent and frees any associated
194: memory. */
195:
196: void ssh_close_authentication_connection(AuthenticationConnection *ac)
197: {
198: buffer_free(&ac->packet);
199: buffer_free(&ac->identities);
200: close(ac->fd);
201: }
202:
203: /* Returns the first authentication identity held by the agent.
204: Returns true if an identity is available, 0 otherwise.
205: The caller must initialize the integers before the call, and free the
206: comment after a successful call (before calling ssh_get_next_identity). */
207:
1.2 provos 208: int
209: ssh_get_first_identity(AuthenticationConnection *auth,
210: int *bitsp, BIGNUM *e, BIGNUM *n, char **comment)
1.1 deraadt 211: {
212: unsigned char msg[8192];
213: int len, l;
214:
215: /* Send a message to the agent requesting for a list of the identities
216: it can represent. */
217: msg[0] = 0;
218: msg[1] = 0;
219: msg[2] = 0;
220: msg[3] = 1;
221: msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
222: if (write(auth->fd, msg, 5) != 5)
223: {
224: error("write auth->fd: %.100s", strerror(errno));
225: return 0;
226: }
227:
228: /* Read the length of the response. XXX implement timeouts here. */
229: len = 4;
230: while (len > 0)
231: {
232: l = read(auth->fd, msg + 4 - len, len);
233: if (l <= 0)
234: {
235: error("read auth->fd: %.100s", strerror(errno));
236: return 0;
237: }
238: len -= l;
239: }
240:
241: /* Extract the length, and check it for sanity. (We cannot trust
242: authentication agents). */
243: len = GET_32BIT(msg);
244: if (len < 1 || len > 256*1024)
245: fatal("Authentication reply message too long: %d\n", len);
246:
247: /* Read the packet itself. */
248: buffer_clear(&auth->identities);
249: while (len > 0)
250: {
251: l = len;
252: if (l > sizeof(msg))
253: l = sizeof(msg);
254: l = read(auth->fd, msg, l);
255: if (l <= 0)
256: fatal("Incomplete authentication reply.");
257: buffer_append(&auth->identities, (char *)msg, l);
258: len -= l;
259: }
260:
261: /* Get message type, and verify that we got a proper answer. */
262: buffer_get(&auth->identities, (char *)msg, 1);
263: if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
264: fatal("Bad authentication reply message type: %d", msg[0]);
265:
266: /* Get the number of entries in the response and check it for sanity. */
267: auth->howmany = buffer_get_int(&auth->identities);
268: if (auth->howmany > 1024)
269: fatal("Too many identities in authentication reply: %d\n", auth->howmany);
270:
271: /* Return the first entry (if any). */
272: return ssh_get_next_identity(auth, bitsp, e, n, comment);
273: }
274:
275: /* Returns the next authentication identity for the agent. Other functions
276: can be called between this and ssh_get_first_identity or two calls of this
277: function. This returns 0 if there are no more identities. The caller
278: must free comment after a successful return. */
279:
1.2 provos 280: int
281: ssh_get_next_identity(AuthenticationConnection *auth,
282: int *bitsp, BIGNUM *e, BIGNUM *n, char **comment)
1.1 deraadt 283: {
284: /* Return failure if no more entries. */
285: if (auth->howmany <= 0)
286: return 0;
287:
288: /* Get the next entry from the packet. These will abort with a fatal
289: error if the packet is too short or contains corrupt data. */
290: *bitsp = buffer_get_int(&auth->identities);
1.2 provos 291: buffer_get_bignum(&auth->identities, e);
292: buffer_get_bignum(&auth->identities, n);
1.1 deraadt 293: *comment = buffer_get_string(&auth->identities, NULL);
294:
295: /* Decrement the number of remaining entries. */
296: auth->howmany--;
297:
298: return 1;
299: }
300:
301: /* Generates a random challenge, sends it to the agent, and waits for response
302: from the agent. Returns true (non-zero) if the agent gave the correct
303: answer, zero otherwise. Response type selects the style of response
304: desired, with 0 corresponding to protocol version 1.0 (no longer supported)
305: and 1 corresponding to protocol version 1.1. */
306:
1.2 provos 307: int
308: ssh_decrypt_challenge(AuthenticationConnection *auth,
309: int bits, BIGNUM *e, BIGNUM *n, BIGNUM *challenge,
310: unsigned char session_id[16],
311: unsigned int response_type,
312: unsigned char response[16])
1.1 deraadt 313: {
314: Buffer buffer;
315: unsigned char buf[8192];
316: int len, l, i;
317:
318: /* Response type 0 is no longer supported. */
319: if (response_type == 0)
320: fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
321:
322: /* Format a message to the agent. */
323: buf[0] = SSH_AGENTC_RSA_CHALLENGE;
324: buffer_init(&buffer);
325: buffer_append(&buffer, (char *)buf, 1);
326: buffer_put_int(&buffer, bits);
1.2 provos 327: buffer_put_bignum(&buffer, e);
328: buffer_put_bignum(&buffer, n);
329: buffer_put_bignum(&buffer, challenge);
1.1 deraadt 330: buffer_append(&buffer, (char *)session_id, 16);
331: buffer_put_int(&buffer, response_type);
332:
333: /* Get the length of the message, and format it in the buffer. */
334: len = buffer_len(&buffer);
335: PUT_32BIT(buf, len);
336:
337: /* Send the length and then the packet to the agent. */
338: if (write(auth->fd, buf, 4) != 4 ||
339: write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
340: buffer_len(&buffer))
341: {
342: error("Error writing to authentication socket.");
343: error_cleanup:
344: buffer_free(&buffer);
345: return 0;
346: }
347:
348: /* Wait for response from the agent. First read the length of the
349: response packet. */
350: len = 4;
351: while (len > 0)
352: {
353: l = read(auth->fd, buf + 4 - len, len);
354: if (l <= 0)
355: {
356: error("Error reading response length from authentication socket.");
357: goto error_cleanup;
358: }
359: len -= l;
360: }
361:
362: /* Extract the length, and check it for sanity. */
363: len = GET_32BIT(buf);
364: if (len > 256*1024)
365: fatal("Authentication response too long: %d", len);
366:
367: /* Read the rest of the response in tothe buffer. */
368: buffer_clear(&buffer);
369: while (len > 0)
370: {
371: l = len;
372: if (l > sizeof(buf))
373: l = sizeof(buf);
374: l = read(auth->fd, buf, l);
375: if (l <= 0)
376: {
377: error("Error reading response from authentication socket.");
378: goto error_cleanup;
379: }
380: buffer_append(&buffer, (char *)buf, l);
381: len -= l;
382: }
383:
384: /* Get the type of the packet. */
385: buffer_get(&buffer, (char *)buf, 1);
386:
387: /* Check for agent failure message. */
388: if (buf[0] == SSH_AGENT_FAILURE)
389: {
390: log("Agent admitted failure to authenticate using the key.");
391: goto error_cleanup;
392: }
393:
394: /* Now it must be an authentication response packet. */
395: if (buf[0] != SSH_AGENT_RSA_RESPONSE)
396: fatal("Bad authentication response: %d", buf[0]);
397:
398: /* Get the response from the packet. This will abort with a fatal error
399: if the packet is corrupt. */
400: for (i = 0; i < 16; i++)
401: response[i] = buffer_get_char(&buffer);
402:
403: /* The buffer containing the packet is no longer needed. */
404: buffer_free(&buffer);
405:
406: /* Correct answer. */
407: return 1;
408: }
409:
410: /* Adds an identity to the authentication server. This call is not meant to
411: be used by normal applications. */
412:
413: int ssh_add_identity(AuthenticationConnection *auth,
1.2 provos 414: RSA *key, const char *comment)
1.1 deraadt 415: {
416: Buffer buffer;
417: unsigned char buf[8192];
418: int len, l, type;
419:
420: /* Format a message to the agent. */
421: buffer_init(&buffer);
422: buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
1.2 provos 423: buffer_put_int(&buffer, BN_num_bits(key->n));
424: buffer_put_bignum(&buffer, key->n);
425: buffer_put_bignum(&buffer, key->e);
426: buffer_put_bignum(&buffer, key->d);
427: /* To keep within the protocol: p < q for ssh. in SSL p > q */
428: buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */
429: buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */
430: buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */
1.1 deraadt 431: buffer_put_string(&buffer, comment, strlen(comment));
432:
433: /* Get the length of the message, and format it in the buffer. */
434: len = buffer_len(&buffer);
435: PUT_32BIT(buf, len);
436:
437: /* Send the length and then the packet to the agent. */
438: if (write(auth->fd, buf, 4) != 4 ||
439: write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
440: buffer_len(&buffer))
441: {
442: error("Error writing to authentication socket.");
443: error_cleanup:
444: buffer_free(&buffer);
445: return 0;
446: }
447:
448: /* Wait for response from the agent. First read the length of the
449: response packet. */
450: len = 4;
451: while (len > 0)
452: {
453: l = read(auth->fd, buf + 4 - len, len);
454: if (l <= 0)
455: {
456: error("Error reading response length from authentication socket.");
457: goto error_cleanup;
458: }
459: len -= l;
460: }
461:
462: /* Extract the length, and check it for sanity. */
463: len = GET_32BIT(buf);
464: if (len > 256*1024)
465: fatal("Add identity response too long: %d", len);
466:
467: /* Read the rest of the response in tothe buffer. */
468: buffer_clear(&buffer);
469: while (len > 0)
470: {
471: l = len;
472: if (l > sizeof(buf))
473: l = sizeof(buf);
474: l = read(auth->fd, buf, l);
475: if (l <= 0)
476: {
477: error("Error reading response from authentication socket.");
478: goto error_cleanup;
479: }
480: buffer_append(&buffer, (char *)buf, l);
481: len -= l;
482: }
483:
484: /* Get the type of the packet. */
485: type = buffer_get_char(&buffer);
486: switch (type)
487: {
488: case SSH_AGENT_FAILURE:
489: buffer_free(&buffer);
490: return 0;
491: case SSH_AGENT_SUCCESS:
492: buffer_free(&buffer);
493: return 1;
494: default:
495: fatal("Bad response to add identity from authentication agent: %d",
496: type);
497: }
498: /*NOTREACHED*/
499: return 0;
500: }
501:
502: /* Removes an identity from the authentication server. This call is not meant
503: to be used by normal applications. */
504:
1.2 provos 505: int ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
1.1 deraadt 506: {
507: Buffer buffer;
508: unsigned char buf[8192];
509: int len, l, type;
510:
511: /* Format a message to the agent. */
512: buffer_init(&buffer);
513: buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
1.2 provos 514: buffer_put_int(&buffer, BN_num_bits(key->n));
515: buffer_put_bignum(&buffer, key->e);
516: buffer_put_bignum(&buffer, key->n);
1.1 deraadt 517:
518: /* Get the length of the message, and format it in the buffer. */
519: len = buffer_len(&buffer);
520: PUT_32BIT(buf, len);
521:
522: /* Send the length and then the packet to the agent. */
523: if (write(auth->fd, buf, 4) != 4 ||
524: write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
525: buffer_len(&buffer))
526: {
527: error("Error writing to authentication socket.");
528: error_cleanup:
529: buffer_free(&buffer);
530: return 0;
531: }
532:
533: /* Wait for response from the agent. First read the length of the
534: response packet. */
535: len = 4;
536: while (len > 0)
537: {
538: l = read(auth->fd, buf + 4 - len, len);
539: if (l <= 0)
540: {
541: error("Error reading response length from authentication socket.");
542: goto error_cleanup;
543: }
544: len -= l;
545: }
546:
547: /* Extract the length, and check it for sanity. */
548: len = GET_32BIT(buf);
549: if (len > 256*1024)
550: fatal("Remove identity response too long: %d", len);
551:
552: /* Read the rest of the response in tothe buffer. */
553: buffer_clear(&buffer);
554: while (len > 0)
555: {
556: l = len;
557: if (l > sizeof(buf))
558: l = sizeof(buf);
559: l = read(auth->fd, buf, l);
560: if (l <= 0)
561: {
562: error("Error reading response from authentication socket.");
563: goto error_cleanup;
564: }
565: buffer_append(&buffer, (char *)buf, l);
566: len -= l;
567: }
568:
569: /* Get the type of the packet. */
570: type = buffer_get_char(&buffer);
571: switch (type)
572: {
573: case SSH_AGENT_FAILURE:
574: buffer_free(&buffer);
575: return 0;
576: case SSH_AGENT_SUCCESS:
577: buffer_free(&buffer);
578: return 1;
579: default:
580: fatal("Bad response to remove identity from authentication agent: %d",
581: type);
582: }
583: /*NOTREACHED*/
584: return 0;
585: }
586:
587: /* Removes all identities from the agent. This call is not meant
588: to be used by normal applications. */
589:
590: int ssh_remove_all_identities(AuthenticationConnection *auth)
591: {
592: Buffer buffer;
593: unsigned char buf[8192];
594: int len, l, type;
595:
596: /* Get the length of the message, and format it in the buffer. */
597: PUT_32BIT(buf, 1);
598: buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
599:
600: /* Send the length and then the packet to the agent. */
601: if (write(auth->fd, buf, 5) != 5)
602: {
603: error("Error writing to authentication socket.");
604: return 0;
605: }
606:
607: /* Wait for response from the agent. First read the length of the
608: response packet. */
609: len = 4;
610: while (len > 0)
611: {
612: l = read(auth->fd, buf + 4 - len, len);
613: if (l <= 0)
614: {
615: error("Error reading response length from authentication socket.");
616: return 0;
617: }
618: len -= l;
619: }
620:
621: /* Extract the length, and check it for sanity. */
622: len = GET_32BIT(buf);
623: if (len > 256*1024)
624: fatal("Remove identity response too long: %d", len);
625:
626: /* Read the rest of the response into the buffer. */
627: buffer_init(&buffer);
628: while (len > 0)
629: {
630: l = len;
631: if (l > sizeof(buf))
632: l = sizeof(buf);
633: l = read(auth->fd, buf, l);
634: if (l <= 0)
635: {
636: error("Error reading response from authentication socket.");
637: buffer_free(&buffer);
638: return 0;
639: }
640: buffer_append(&buffer, (char *)buf, l);
641: len -= l;
642: }
643:
644: /* Get the type of the packet. */
645: type = buffer_get_char(&buffer);
646: switch (type)
647: {
648: case SSH_AGENT_FAILURE:
649: buffer_free(&buffer);
650: return 0;
651: case SSH_AGENT_SUCCESS:
652: buffer_free(&buffer);
653: return 1;
654: default:
655: fatal("Bad response to remove identity from authentication agent: %d",
656: type);
657: }
658: /*NOTREACHED*/
659: return 0;
660: }
661:
662: /* Closes the connection to the authentication agent. */
663:
664: void ssh_close_authentication(AuthenticationConnection *auth)
665: {
666: /* Close the connection. */
1.5 ! deraadt 667: shutdown(auth->fd, SHUT_RDWR);
1.1 deraadt 668: close(auth->fd);
669:
670: /* Free the buffers. */
671: buffer_free(&auth->packet);
672: buffer_free(&auth->identities);
673:
674: /* Free the connection data structure. */
675: xfree(auth);
676: }