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