Annotation of src/usr.bin/ssh/authfd.c, Revision 1.13
1.1 deraadt 1: /*
1.13 ! deraadt 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: */
1.1 deraadt 15:
16: #include "includes.h"
1.13 ! deraadt 17: RCSID("$Id: authfd.c,v 1.12 1999/11/23 22:25: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.12 markus 34: const char *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;
43: strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
44:
45: sock = socket(AF_UNIX, SOCK_STREAM, 0);
46: if (sock < 0)
47: return -1;
48:
49: /* close on exec */
50: if (fcntl(sock, F_SETFD, 1) == -1) {
51: close(sock);
52: return -1;
53: }
54: if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
55: close(sock);
56: return -1;
57: }
58: return sock;
1.1 deraadt 59: }
60:
61: /* Closes the agent socket if it should be closed (depends on how it was
1.12 markus 62: obtained). The argument must have been returned by
1.8 markus 63: ssh_get_authentication_socket(). */
1.1 deraadt 64:
1.12 markus 65: void
66: ssh_close_authentication_socket(int sock)
1.1 deraadt 67: {
1.12 markus 68: if (getenv(SSH_AUTHSOCKET_ENV_NAME))
69: close(sock);
1.1 deraadt 70: }
71:
72: /* Opens and connects a private socket for communication with the
73: authentication agent. Returns the file descriptor (which must be
74: shut down and closed by the caller when no longer needed).
75: Returns NULL if an error occurred and the connection could not be
76: opened. */
77:
1.12 markus 78: AuthenticationConnection *
79: ssh_get_authentication_connection()
1.1 deraadt 80: {
1.12 markus 81: AuthenticationConnection *auth;
82: int sock;
1.1 deraadt 83:
1.12 markus 84: sock = ssh_get_authentication_socket();
85:
86: /* Fail if we couldn't obtain a connection. This happens if we
87: exited due to a timeout. */
88: if (sock < 0)
89: return NULL;
90:
91: /* Applocate the connection structure and initialize it. */
92: auth = xmalloc(sizeof(*auth));
93: auth->fd = sock;
94: buffer_init(&auth->packet);
95: buffer_init(&auth->identities);
96: auth->howmany = 0;
97:
98: return auth;
1.1 deraadt 99: }
100:
101: /* Closes the connection to the authentication agent and frees any associated
102: memory. */
103:
1.12 markus 104: void
105: ssh_close_authentication_connection(AuthenticationConnection *ac)
1.1 deraadt 106: {
1.12 markus 107: buffer_free(&ac->packet);
108: buffer_free(&ac->identities);
109: close(ac->fd);
110: xfree(ac);
1.1 deraadt 111: }
112:
113: /* Returns the first authentication identity held by the agent.
114: Returns true if an identity is available, 0 otherwise.
115: The caller must initialize the integers before the call, and free the
116: comment after a successful call (before calling ssh_get_next_identity). */
117:
1.2 provos 118: int
119: ssh_get_first_identity(AuthenticationConnection *auth,
1.9 markus 120: BIGNUM *e, BIGNUM *n, char **comment)
1.1 deraadt 121: {
1.12 markus 122: unsigned char msg[8192];
123: int len, l;
1.1 deraadt 124:
1.12 markus 125: /* Send a message to the agent requesting for a list of the
126: identities it can represent. */
127: msg[0] = 0;
128: msg[1] = 0;
129: msg[2] = 0;
130: msg[3] = 1;
131: msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
132: if (write(auth->fd, msg, 5) != 5) {
133: error("write auth->fd: %.100s", strerror(errno));
134: return 0;
135: }
136: /* Read the length of the response. XXX implement timeouts here. */
137: len = 4;
138: while (len > 0) {
139: l = read(auth->fd, msg + 4 - len, len);
140: if (l <= 0) {
141: error("read auth->fd: %.100s", strerror(errno));
142: return 0;
143: }
144: len -= l;
145: }
146:
147: /* Extract the length, and check it for sanity. (We cannot trust
148: authentication agents). */
149: len = GET_32BIT(msg);
150: if (len < 1 || len > 256 * 1024)
151: fatal("Authentication reply message too long: %d\n", len);
152:
153: /* Read the packet itself. */
154: buffer_clear(&auth->identities);
155: while (len > 0) {
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: }
1.1 deraadt 165:
1.12 markus 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, 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.12 markus 189: unsigned int bits;
1.9 markus 190:
1.12 markus 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
196: fatal error if the packet is too short or contains corrupt data. */
197: bits = buffer_get_int(&auth->identities);
198: buffer_get_bignum(&auth->identities, e);
199: buffer_get_bignum(&auth->identities, n);
200: *comment = buffer_get_string(&auth->identities, NULL);
201:
202: if (bits != BN_num_bits(n))
203: error("Warning: keysize mismatch: actual %d, announced %u",
204: BN_num_bits(n), bits);
1.9 markus 205:
1.12 markus 206: /* Decrement the number of remaining entries. */
207: auth->howmany--;
1.1 deraadt 208:
1.12 markus 209: return 1;
1.1 deraadt 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.12 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: {
1.12 markus 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);
237: buffer_put_int(&buffer, BN_num_bits(n));
238: buffer_put_bignum(&buffer, e);
239: buffer_put_bignum(&buffer, n);
240: buffer_put_bignum(&buffer, challenge);
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: error("Error writing to authentication socket.");
253: error_cleanup:
254: buffer_free(&buffer);
255: return 0;
256: }
257: /* Wait for response from the agent. First read the length of the
258: response packet. */
259: len = 4;
260: while (len > 0) {
261: l = read(auth->fd, buf + 4 - len, len);
262: if (l <= 0) {
263: error("Error reading response length from authentication socket.");
264: goto error_cleanup;
265: }
266: len -= l;
267: }
268:
269: /* Extract the length, and check it for sanity. */
270: len = GET_32BIT(buf);
271: if (len > 256 * 1024)
272: fatal("Authentication response too long: %d", len);
273:
274: /* Read the rest of the response in tothe buffer. */
275: buffer_clear(&buffer);
276: while (len > 0) {
277: l = len;
278: if (l > sizeof(buf))
279: l = sizeof(buf);
280: l = read(auth->fd, buf, l);
281: if (l <= 0) {
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: log("Agent admitted failure to authenticate using the key.");
295: goto error_cleanup;
296: }
297: /* Now it must be an authentication response packet. */
298: if (buf[0] != SSH_AGENT_RSA_RESPONSE)
299: fatal("Bad authentication response: %d", buf[0]);
300:
301: /* Get the response from the packet. This will abort with a fatal
302: error if the packet is corrupt. */
303: for (i = 0; i < 16; i++)
304: response[i] = buffer_get_char(&buffer);
305:
306: /* The buffer containing the packet is no longer needed. */
307: buffer_free(&buffer);
308:
309: /* Correct answer. */
310: return 1;
311: }
1.1 deraadt 312:
313: /* Adds an identity to the authentication server. This call is not meant to
314: be used by normal applications. */
315:
1.12 markus 316: int
317: ssh_add_identity(AuthenticationConnection *auth,
318: RSA * key, const char *comment)
1.1 deraadt 319: {
1.12 markus 320: Buffer buffer;
321: unsigned char buf[8192];
322: int len, l, type;
323:
324: /* Format a message to the agent. */
325: buffer_init(&buffer);
326: buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
327: buffer_put_int(&buffer, BN_num_bits(key->n));
328: buffer_put_bignum(&buffer, key->n);
329: buffer_put_bignum(&buffer, key->e);
330: buffer_put_bignum(&buffer, key->d);
331: /* To keep within the protocol: p < q for ssh. in SSL p > q */
332: buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */
333: buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */
334: buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */
335: buffer_put_string(&buffer, comment, strlen(comment));
336:
337: /* Get the length of the message, and format it in the buffer. */
338: len = buffer_len(&buffer);
339: PUT_32BIT(buf, len);
340:
341: /* Send the length and then the packet to the agent. */
342: if (write(auth->fd, buf, 4) != 4 ||
343: write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
344: buffer_len(&buffer)) {
345: error("Error writing to authentication socket.");
346: error_cleanup:
347: buffer_free(&buffer);
348: return 0;
349: }
350: /* Wait for response from the agent. First read the length of the
351: response packet. */
352: len = 4;
353: while (len > 0) {
354: l = read(auth->fd, buf + 4 - len, len);
355: if (l <= 0) {
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("Add identity 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: l = len;
371: if (l > sizeof(buf))
372: l = sizeof(buf);
373: l = read(auth->fd, buf, l);
374: if (l <= 0) {
375: error("Error reading response from authentication socket.");
376: goto error_cleanup;
377: }
378: buffer_append(&buffer, (char *) buf, l);
379: len -= l;
380: }
381:
382: /* Get the type of the packet. */
383: type = buffer_get_char(&buffer);
384: switch (type) {
385: case SSH_AGENT_FAILURE:
386: buffer_free(&buffer);
387: return 0;
388: case SSH_AGENT_SUCCESS:
389: buffer_free(&buffer);
390: return 1;
391: default:
392: fatal("Bad response to add identity from authentication agent: %d",
393: type);
394: }
395: /* NOTREACHED */
396: return 0;
397: }
1.1 deraadt 398:
1.12 markus 399: /* Removes an identity from the authentication server. This call is not meant
1.1 deraadt 400: to be used by normal applications. */
401:
1.12 markus 402: int
403: ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
1.1 deraadt 404: {
1.12 markus 405: Buffer buffer;
406: unsigned char buf[8192];
407: int len, l, type;
408:
409: /* Format a message to the agent. */
410: buffer_init(&buffer);
411: buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
412: buffer_put_int(&buffer, BN_num_bits(key->n));
413: buffer_put_bignum(&buffer, key->e);
414: buffer_put_bignum(&buffer, key->n);
415:
416: /* Get the length of the message, and format it in the buffer. */
417: len = buffer_len(&buffer);
418: PUT_32BIT(buf, len);
419:
420: /* Send the length and then the packet to the agent. */
421: if (write(auth->fd, buf, 4) != 4 ||
422: write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
423: buffer_len(&buffer)) {
424: error("Error writing to authentication socket.");
425: error_cleanup:
426: buffer_free(&buffer);
427: return 0;
428: }
429: /* Wait for response from the agent. First read the length of the
430: response packet. */
431: len = 4;
432: while (len > 0) {
433: l = read(auth->fd, buf + 4 - len, len);
434: if (l <= 0) {
435: error("Error reading response length from authentication socket.");
436: goto error_cleanup;
437: }
438: len -= l;
439: }
440:
441: /* Extract the length, and check it for sanity. */
442: len = GET_32BIT(buf);
443: if (len > 256 * 1024)
444: fatal("Remove identity response too long: %d", len);
445:
446: /* Read the rest of the response in tothe buffer. */
447: buffer_clear(&buffer);
448: while (len > 0) {
449: l = len;
450: if (l > sizeof(buf))
451: l = sizeof(buf);
452: l = read(auth->fd, buf, l);
453: if (l <= 0) {
454: error("Error reading response from authentication socket.");
455: goto error_cleanup;
456: }
457: buffer_append(&buffer, (char *) buf, l);
458: len -= l;
459: }
1.1 deraadt 460:
1.12 markus 461: /* Get the type of the packet. */
462: type = buffer_get_char(&buffer);
463: switch (type) {
464: case SSH_AGENT_FAILURE:
465: buffer_free(&buffer);
466: return 0;
467: case SSH_AGENT_SUCCESS:
468: buffer_free(&buffer);
469: return 1;
470: default:
471: fatal("Bad response to remove identity from authentication agent: %d",
472: type);
473: }
474: /* NOTREACHED */
475: return 0;
476: }
477:
478: /* Removes all identities from the agent. This call is not meant
1.1 deraadt 479: to be used by normal applications. */
480:
1.12 markus 481: int
482: ssh_remove_all_identities(AuthenticationConnection *auth)
1.1 deraadt 483: {
1.12 markus 484: Buffer buffer;
485: unsigned char buf[8192];
486: int len, l, type;
487:
488: /* Get the length of the message, and format it in the buffer. */
489: PUT_32BIT(buf, 1);
490: buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
491:
492: /* Send the length and then the packet to the agent. */
493: if (write(auth->fd, buf, 5) != 5) {
494: error("Error writing to authentication socket.");
495: return 0;
496: }
497: /* Wait for response from the agent. First read the length of the
498: response packet. */
499: len = 4;
500: while (len > 0) {
501: l = read(auth->fd, buf + 4 - len, len);
502: if (l <= 0) {
503: error("Error reading response length from authentication socket.");
504: return 0;
505: }
506: len -= l;
507: }
508:
509: /* Extract the length, and check it for sanity. */
510: len = GET_32BIT(buf);
511: if (len > 256 * 1024)
512: fatal("Remove identity response too long: %d", len);
513:
514: /* Read the rest of the response into the buffer. */
515: buffer_init(&buffer);
516: while (len > 0) {
517: l = len;
518: if (l > sizeof(buf))
519: l = sizeof(buf);
520: l = read(auth->fd, buf, l);
521: if (l <= 0) {
522: error("Error reading response from authentication socket.");
523: buffer_free(&buffer);
524: return 0;
525: }
526: buffer_append(&buffer, (char *) buf, l);
527: len -= l;
528: }
529:
530: /* Get the type of the packet. */
531: type = buffer_get_char(&buffer);
532: switch (type) {
533: case SSH_AGENT_FAILURE:
534: buffer_free(&buffer);
535: return 0;
536: case SSH_AGENT_SUCCESS:
537: buffer_free(&buffer);
538: return 1;
539: default:
540: fatal("Bad response to remove identity from authentication agent: %d",
541: type);
542: }
543: /* NOTREACHED */
544: return 0;
545: }