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