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