Annotation of src/usr.bin/ssh/authfd.c, Revision 1.8
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.8 ! markus 17: RCSID("$Id: authfd.c,v 1.7 1999/10/05 22:18:52 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,
115: int *bitsp, 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). */
177: return ssh_get_next_identity(auth, bitsp, e, n, comment);
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,
187: int *bitsp, BIGNUM *e, BIGNUM *n, char **comment)
1.1 deraadt 188: {
189: /* Return failure if no more entries. */
190: if (auth->howmany <= 0)
191: return 0;
192:
193: /* Get the next entry from the packet. These will abort with a fatal
194: error if the packet is too short or contains corrupt data. */
195: *bitsp = buffer_get_int(&auth->identities);
1.2 provos 196: buffer_get_bignum(&auth->identities, e);
197: buffer_get_bignum(&auth->identities, n);
1.1 deraadt 198: *comment = buffer_get_string(&auth->identities, NULL);
199:
200: /* Decrement the number of remaining entries. */
201: auth->howmany--;
202:
203: return 1;
204: }
205:
206: /* Generates a random challenge, sends it to the agent, and waits for response
207: from the agent. Returns true (non-zero) if the agent gave the correct
208: answer, zero otherwise. Response type selects the style of response
209: desired, with 0 corresponding to protocol version 1.0 (no longer supported)
210: and 1 corresponding to protocol version 1.1. */
211:
1.2 provos 212: int
213: ssh_decrypt_challenge(AuthenticationConnection *auth,
214: int bits, BIGNUM *e, BIGNUM *n, BIGNUM *challenge,
215: unsigned char session_id[16],
216: unsigned int response_type,
217: unsigned char response[16])
1.1 deraadt 218: {
219: Buffer buffer;
220: unsigned char buf[8192];
221: int len, l, i;
222:
223: /* Response type 0 is no longer supported. */
224: if (response_type == 0)
225: fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
226:
227: /* Format a message to the agent. */
228: buf[0] = SSH_AGENTC_RSA_CHALLENGE;
229: buffer_init(&buffer);
230: buffer_append(&buffer, (char *)buf, 1);
231: buffer_put_int(&buffer, bits);
1.2 provos 232: buffer_put_bignum(&buffer, e);
233: buffer_put_bignum(&buffer, n);
234: buffer_put_bignum(&buffer, challenge);
1.1 deraadt 235: buffer_append(&buffer, (char *)session_id, 16);
236: buffer_put_int(&buffer, response_type);
237:
238: /* Get the length of the message, and format it in the buffer. */
239: len = buffer_len(&buffer);
240: PUT_32BIT(buf, len);
241:
242: /* Send the length and then the packet to the agent. */
243: if (write(auth->fd, buf, 4) != 4 ||
244: write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
245: buffer_len(&buffer))
246: {
247: error("Error writing to authentication socket.");
248: error_cleanup:
249: buffer_free(&buffer);
250: return 0;
251: }
252:
253: /* Wait for response from the agent. First read the length of the
254: response packet. */
255: len = 4;
256: while (len > 0)
257: {
258: l = read(auth->fd, buf + 4 - len, len);
259: if (l <= 0)
260: {
261: error("Error reading response length from authentication socket.");
262: goto error_cleanup;
263: }
264: len -= l;
265: }
266:
267: /* Extract the length, and check it for sanity. */
268: len = GET_32BIT(buf);
269: if (len > 256*1024)
270: fatal("Authentication response too long: %d", len);
271:
272: /* Read the rest of the response in tothe buffer. */
273: buffer_clear(&buffer);
274: while (len > 0)
275: {
276: l = len;
277: if (l > sizeof(buf))
278: l = sizeof(buf);
279: l = read(auth->fd, buf, l);
280: if (l <= 0)
281: {
282: error("Error reading response from authentication socket.");
283: goto error_cleanup;
284: }
285: buffer_append(&buffer, (char *)buf, l);
286: len -= l;
287: }
288:
289: /* Get the type of the packet. */
290: buffer_get(&buffer, (char *)buf, 1);
291:
292: /* Check for agent failure message. */
293: if (buf[0] == SSH_AGENT_FAILURE)
294: {
295: log("Agent admitted failure to authenticate using the key.");
296: goto error_cleanup;
297: }
298:
299: /* Now it must be an authentication response packet. */
300: if (buf[0] != SSH_AGENT_RSA_RESPONSE)
301: fatal("Bad authentication response: %d", buf[0]);
302:
303: /* Get the response from the packet. This will abort with a fatal error
304: if the packet is corrupt. */
305: for (i = 0; i < 16; i++)
306: response[i] = buffer_get_char(&buffer);
307:
308: /* The buffer containing the packet is no longer needed. */
309: buffer_free(&buffer);
310:
311: /* Correct answer. */
312: return 1;
313: }
314:
315: /* Adds an identity to the authentication server. This call is not meant to
316: be used by normal applications. */
317:
318: int ssh_add_identity(AuthenticationConnection *auth,
1.2 provos 319: RSA *key, const char *comment)
1.1 deraadt 320: {
321: Buffer buffer;
322: unsigned char buf[8192];
323: int len, l, type;
324:
325: /* Format a message to the agent. */
326: buffer_init(&buffer);
327: buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
1.2 provos 328: buffer_put_int(&buffer, BN_num_bits(key->n));
329: buffer_put_bignum(&buffer, key->n);
330: buffer_put_bignum(&buffer, key->e);
331: buffer_put_bignum(&buffer, key->d);
332: /* To keep within the protocol: p < q for ssh. in SSL p > q */
333: buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */
334: buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */
335: buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */
1.1 deraadt 336: buffer_put_string(&buffer, comment, strlen(comment));
337:
338: /* Get the length of the message, and format it in the buffer. */
339: len = buffer_len(&buffer);
340: PUT_32BIT(buf, len);
341:
342: /* Send the length and then the packet to the agent. */
343: if (write(auth->fd, buf, 4) != 4 ||
344: write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
345: buffer_len(&buffer))
346: {
347: error("Error writing to authentication socket.");
348: error_cleanup:
349: buffer_free(&buffer);
350: return 0;
351: }
352:
353: /* Wait for response from the agent. First read the length of the
354: response packet. */
355: len = 4;
356: while (len > 0)
357: {
358: l = read(auth->fd, buf + 4 - len, len);
359: if (l <= 0)
360: {
361: error("Error reading response length from authentication socket.");
362: goto error_cleanup;
363: }
364: len -= l;
365: }
366:
367: /* Extract the length, and check it for sanity. */
368: len = GET_32BIT(buf);
369: if (len > 256*1024)
370: fatal("Add identity response too long: %d", len);
371:
372: /* Read the rest of the response in tothe buffer. */
373: buffer_clear(&buffer);
374: while (len > 0)
375: {
376: l = len;
377: if (l > sizeof(buf))
378: l = sizeof(buf);
379: l = read(auth->fd, buf, l);
380: if (l <= 0)
381: {
382: error("Error reading response from authentication socket.");
383: goto error_cleanup;
384: }
385: buffer_append(&buffer, (char *)buf, l);
386: len -= l;
387: }
388:
389: /* Get the type of the packet. */
390: type = buffer_get_char(&buffer);
391: switch (type)
392: {
393: case SSH_AGENT_FAILURE:
394: buffer_free(&buffer);
395: return 0;
396: case SSH_AGENT_SUCCESS:
397: buffer_free(&buffer);
398: return 1;
399: default:
400: fatal("Bad response to add identity from authentication agent: %d",
401: type);
402: }
403: /*NOTREACHED*/
404: return 0;
405: }
406:
407: /* Removes an identity from the authentication server. This call is not meant
408: to be used by normal applications. */
409:
1.2 provos 410: int ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
1.1 deraadt 411: {
412: Buffer buffer;
413: unsigned char buf[8192];
414: int len, l, type;
415:
416: /* Format a message to the agent. */
417: buffer_init(&buffer);
418: buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
1.2 provos 419: buffer_put_int(&buffer, BN_num_bits(key->n));
420: buffer_put_bignum(&buffer, key->e);
421: buffer_put_bignum(&buffer, key->n);
1.1 deraadt 422:
423: /* Get the length of the message, and format it in the buffer. */
424: len = buffer_len(&buffer);
425: PUT_32BIT(buf, len);
426:
427: /* Send the length and then the packet to the agent. */
428: if (write(auth->fd, buf, 4) != 4 ||
429: write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
430: buffer_len(&buffer))
431: {
432: error("Error writing to authentication socket.");
433: error_cleanup:
434: buffer_free(&buffer);
435: return 0;
436: }
437:
438: /* Wait for response from the agent. First read the length of the
439: response packet. */
440: len = 4;
441: while (len > 0)
442: {
443: l = read(auth->fd, buf + 4 - len, len);
444: if (l <= 0)
445: {
446: error("Error reading response length from authentication socket.");
447: goto error_cleanup;
448: }
449: len -= l;
450: }
451:
452: /* Extract the length, and check it for sanity. */
453: len = GET_32BIT(buf);
454: if (len > 256*1024)
455: fatal("Remove identity response too long: %d", len);
456:
457: /* Read the rest of the response in tothe buffer. */
458: buffer_clear(&buffer);
459: while (len > 0)
460: {
461: l = len;
462: if (l > sizeof(buf))
463: l = sizeof(buf);
464: l = read(auth->fd, buf, l);
465: if (l <= 0)
466: {
467: error("Error reading response from authentication socket.");
468: goto error_cleanup;
469: }
470: buffer_append(&buffer, (char *)buf, l);
471: len -= l;
472: }
473:
474: /* Get the type of the packet. */
475: type = buffer_get_char(&buffer);
476: switch (type)
477: {
478: case SSH_AGENT_FAILURE:
479: buffer_free(&buffer);
480: return 0;
481: case SSH_AGENT_SUCCESS:
482: buffer_free(&buffer);
483: return 1;
484: default:
485: fatal("Bad response to remove identity from authentication agent: %d",
486: type);
487: }
488: /*NOTREACHED*/
489: return 0;
490: }
491:
492: /* Removes all identities from the agent. This call is not meant
493: to be used by normal applications. */
494:
495: int ssh_remove_all_identities(AuthenticationConnection *auth)
496: {
497: Buffer buffer;
498: unsigned char buf[8192];
499: int len, l, type;
500:
501: /* Get the length of the message, and format it in the buffer. */
502: PUT_32BIT(buf, 1);
503: buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
504:
505: /* Send the length and then the packet to the agent. */
506: if (write(auth->fd, buf, 5) != 5)
507: {
508: error("Error writing to authentication socket.");
509: return 0;
510: }
511:
512: /* Wait for response from the agent. First read the length of the
513: response packet. */
514: len = 4;
515: while (len > 0)
516: {
517: l = read(auth->fd, buf + 4 - len, len);
518: if (l <= 0)
519: {
520: error("Error reading response length from authentication socket.");
521: return 0;
522: }
523: len -= l;
524: }
525:
526: /* Extract the length, and check it for sanity. */
527: len = GET_32BIT(buf);
528: if (len > 256*1024)
529: fatal("Remove identity response too long: %d", len);
530:
531: /* Read the rest of the response into the buffer. */
532: buffer_init(&buffer);
533: while (len > 0)
534: {
535: l = len;
536: if (l > sizeof(buf))
537: l = sizeof(buf);
538: l = read(auth->fd, buf, l);
539: if (l <= 0)
540: {
541: error("Error reading response from authentication socket.");
542: buffer_free(&buffer);
543: return 0;
544: }
545: buffer_append(&buffer, (char *)buf, l);
546: len -= l;
547: }
548:
549: /* Get the type of the packet. */
550: type = buffer_get_char(&buffer);
551: switch (type)
552: {
553: case SSH_AGENT_FAILURE:
554: buffer_free(&buffer);
555: return 0;
556: case SSH_AGENT_SUCCESS:
557: buffer_free(&buffer);
558: return 1;
559: default:
560: fatal("Bad response to remove identity from authentication agent: %d",
561: type);
562: }
563: /*NOTREACHED*/
564: return 0;
565: }