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