blob: 17b0668be792b0db76cf93d9649095732cf2fdd8 [file] [log] [blame]
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001/*
Damien Miller95def091999-11-25 00:26:21 +11002 *
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 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100015
16#include "includes.h"
Damien Miller95def091999-11-25 00:26:21 +110017RCSID("$Id: authfd.c,v 1.7 1999/11/24 13:26:21 damien Exp $");
Damien Millerd4a8b7e1999-10-27 13:42:43 +100018
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
Damien Miller7f6ea021999-10-28 13:25:17 +100027#ifdef HAVE_OPENSSL
Damien Millerd4a8b7e1999-10-27 13:42:43 +100028#include <openssl/rsa.h>
Damien Miller7f6ea021999-10-28 13:25:17 +100029#endif
30#ifdef HAVE_SSL
31#include <ssl/rsa.h>
32#endif
Damien Millerd4a8b7e1999-10-27 13:42:43 +100033
34/* Returns the number of the authentication fd, or -1 if there is none. */
35
36int
37ssh_get_authentication_socket()
38{
Damien Miller95def091999-11-25 00:26:21 +110039 const char *authsocket;
40 int sock;
41 struct sockaddr_un sunaddr;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100042
Damien Miller95def091999-11-25 00:26:21 +110043 authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
44 if (!authsocket)
45 return -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100046
Damien Miller95def091999-11-25 00:26:21 +110047 sunaddr.sun_family = AF_UNIX;
48 strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
Damien Miller10f6f6b1999-11-17 17:29:08 +110049
Damien Miller95def091999-11-25 00:26:21 +110050 sock = socket(AF_UNIX, SOCK_STREAM, 0);
51 if (sock < 0)
52 return -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100053
Damien Miller95def091999-11-25 00:26:21 +110054 /* close on exec */
55 if (fcntl(sock, F_SETFD, 1) == -1) {
56 close(sock);
57 return -1;
58 }
59 if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
60 close(sock);
61 return -1;
62 }
63 return sock;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100064}
65
66/* Closes the agent socket if it should be closed (depends on how it was
Damien Miller95def091999-11-25 00:26:21 +110067 obtained). The argument must have been returned by
Damien Millerd4a8b7e1999-10-27 13:42:43 +100068 ssh_get_authentication_socket(). */
69
Damien Miller95def091999-11-25 00:26:21 +110070void
71ssh_close_authentication_socket(int sock)
Damien Millerd4a8b7e1999-10-27 13:42:43 +100072{
Damien Miller95def091999-11-25 00:26:21 +110073 if (getenv(SSH_AUTHSOCKET_ENV_NAME))
74 close(sock);
Damien Millerd4a8b7e1999-10-27 13:42:43 +100075}
76
77/* Opens and connects a private socket for communication with the
78 authentication agent. Returns the file descriptor (which must be
79 shut down and closed by the caller when no longer needed).
80 Returns NULL if an error occurred and the connection could not be
81 opened. */
82
Damien Miller95def091999-11-25 00:26:21 +110083AuthenticationConnection *
84ssh_get_authentication_connection()
Damien Millerd4a8b7e1999-10-27 13:42:43 +100085{
Damien Miller95def091999-11-25 00:26:21 +110086 AuthenticationConnection *auth;
87 int sock;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100088
Damien Miller95def091999-11-25 00:26:21 +110089 sock = ssh_get_authentication_socket();
Damien Millerd4a8b7e1999-10-27 13:42:43 +100090
Damien Miller95def091999-11-25 00:26:21 +110091 /* Fail if we couldn't obtain a connection. This happens if we
92 exited due to a timeout. */
93 if (sock < 0)
94 return NULL;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100095
Damien Miller95def091999-11-25 00:26:21 +110096 /* Applocate the connection structure and initialize it. */
97 auth = xmalloc(sizeof(*auth));
98 auth->fd = sock;
99 buffer_init(&auth->packet);
100 buffer_init(&auth->identities);
101 auth->howmany = 0;
102
103 return auth;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000104}
105
106/* Closes the connection to the authentication agent and frees any associated
107 memory. */
108
Damien Miller95def091999-11-25 00:26:21 +1100109void
110ssh_close_authentication_connection(AuthenticationConnection *ac)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000111{
Damien Miller95def091999-11-25 00:26:21 +1100112 buffer_free(&ac->packet);
113 buffer_free(&ac->identities);
114 close(ac->fd);
115 xfree(ac);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000116}
117
118/* Returns the first authentication identity held by the agent.
119 Returns true if an identity is available, 0 otherwise.
120 The caller must initialize the integers before the call, and free the
121 comment after a successful call (before calling ssh_get_next_identity). */
122
123int
124ssh_get_first_identity(AuthenticationConnection *auth,
Damien Miller7e8e8201999-11-16 13:37:16 +1100125 BIGNUM *e, BIGNUM *n, char **comment)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000126{
Damien Miller95def091999-11-25 00:26:21 +1100127 unsigned char msg[8192];
128 int len, l;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000129
Damien Miller95def091999-11-25 00:26:21 +1100130 /* Send a message to the agent requesting for a list of the
131 identities it can represent. */
132 msg[0] = 0;
133 msg[1] = 0;
134 msg[2] = 0;
135 msg[3] = 1;
136 msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
137 if (write(auth->fd, msg, 5) != 5) {
138 error("write auth->fd: %.100s", strerror(errno));
139 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000140 }
Damien Miller95def091999-11-25 00:26:21 +1100141 /* Read the length of the response. XXX implement timeouts here. */
142 len = 4;
143 while (len > 0) {
144 l = read(auth->fd, msg + 4 - len, len);
145 if (l <= 0) {
146 error("read auth->fd: %.100s", strerror(errno));
147 return 0;
148 }
149 len -= l;
150 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000151
Damien Miller95def091999-11-25 00:26:21 +1100152 /* Extract the length, and check it for sanity. (We cannot trust
153 authentication agents). */
154 len = GET_32BIT(msg);
155 if (len < 1 || len > 256 * 1024)
156 fatal("Authentication reply message too long: %d\n", len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000157
Damien Miller95def091999-11-25 00:26:21 +1100158 /* Read the packet itself. */
159 buffer_clear(&auth->identities);
160 while (len > 0) {
161 l = len;
162 if (l > sizeof(msg))
163 l = sizeof(msg);
164 l = read(auth->fd, msg, l);
165 if (l <= 0)
166 fatal("Incomplete authentication reply.");
167 buffer_append(&auth->identities, (char *) msg, l);
168 len -= l;
169 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000170
Damien Miller95def091999-11-25 00:26:21 +1100171 /* Get message type, and verify that we got a proper answer. */
172 buffer_get(&auth->identities, (char *) msg, 1);
173 if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
174 fatal("Bad authentication reply message type: %d", msg[0]);
175
176 /* Get the number of entries in the response and check it for sanity. */
177 auth->howmany = buffer_get_int(&auth->identities);
178 if (auth->howmany > 1024)
179 fatal("Too many identities in authentication reply: %d\n", auth->howmany);
180
181 /* Return the first entry (if any). */
182 return ssh_get_next_identity(auth, e, n, comment);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000183}
184
185/* Returns the next authentication identity for the agent. Other functions
186 can be called between this and ssh_get_first_identity or two calls of this
187 function. This returns 0 if there are no more identities. The caller
188 must free comment after a successful return. */
189
190int
191ssh_get_next_identity(AuthenticationConnection *auth,
Damien Miller7e8e8201999-11-16 13:37:16 +1100192 BIGNUM *e, BIGNUM *n, char **comment)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000193{
Damien Miller95def091999-11-25 00:26:21 +1100194 unsigned int bits;
Damien Miller7e8e8201999-11-16 13:37:16 +1100195
Damien Miller95def091999-11-25 00:26:21 +1100196 /* Return failure if no more entries. */
197 if (auth->howmany <= 0)
198 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000199
Damien Miller95def091999-11-25 00:26:21 +1100200 /* Get the next entry from the packet. These will abort with a
201 fatal error if the packet is too short or contains corrupt data. */
202 bits = buffer_get_int(&auth->identities);
203 buffer_get_bignum(&auth->identities, e);
204 buffer_get_bignum(&auth->identities, n);
205 *comment = buffer_get_string(&auth->identities, NULL);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000206
Damien Miller95def091999-11-25 00:26:21 +1100207 if (bits != BN_num_bits(n))
208 error("Warning: keysize mismatch: actual %d, announced %u",
209 BN_num_bits(n), bits);
Damien Miller7e8e8201999-11-16 13:37:16 +1100210
Damien Miller95def091999-11-25 00:26:21 +1100211 /* Decrement the number of remaining entries. */
212 auth->howmany--;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000213
Damien Miller95def091999-11-25 00:26:21 +1100214 return 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000215}
216
217/* Generates a random challenge, sends it to the agent, and waits for response
218 from the agent. Returns true (non-zero) if the agent gave the correct
219 answer, zero otherwise. Response type selects the style of response
220 desired, with 0 corresponding to protocol version 1.0 (no longer supported)
221 and 1 corresponding to protocol version 1.1. */
222
223int
224ssh_decrypt_challenge(AuthenticationConnection *auth,
Damien Miller95def091999-11-25 00:26:21 +1100225 BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000226 unsigned char session_id[16],
227 unsigned int response_type,
228 unsigned char response[16])
229{
Damien Miller95def091999-11-25 00:26:21 +1100230 Buffer buffer;
231 unsigned char buf[8192];
232 int len, l, i;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000233
Damien Miller95def091999-11-25 00:26:21 +1100234 /* Response type 0 is no longer supported. */
235 if (response_type == 0)
236 fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000237
Damien Miller95def091999-11-25 00:26:21 +1100238 /* Format a message to the agent. */
239 buf[0] = SSH_AGENTC_RSA_CHALLENGE;
240 buffer_init(&buffer);
241 buffer_append(&buffer, (char *) buf, 1);
242 buffer_put_int(&buffer, BN_num_bits(n));
243 buffer_put_bignum(&buffer, e);
244 buffer_put_bignum(&buffer, n);
245 buffer_put_bignum(&buffer, challenge);
246 buffer_append(&buffer, (char *) session_id, 16);
247 buffer_put_int(&buffer, response_type);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000248
Damien Miller95def091999-11-25 00:26:21 +1100249 /* Get the length of the message, and format it in the buffer. */
250 len = buffer_len(&buffer);
251 PUT_32BIT(buf, len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000252
Damien Miller95def091999-11-25 00:26:21 +1100253 /* Send the length and then the packet to the agent. */
254 if (write(auth->fd, buf, 4) != 4 ||
255 write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
256 buffer_len(&buffer)) {
257 error("Error writing to authentication socket.");
258error_cleanup:
259 buffer_free(&buffer);
260 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000261 }
Damien Miller95def091999-11-25 00:26:21 +1100262 /* Wait for response from the agent. First read the length of the
263 response packet. */
264 len = 4;
265 while (len > 0) {
266 l = read(auth->fd, buf + 4 - len, len);
267 if (l <= 0) {
268 error("Error reading response length from authentication socket.");
269 goto error_cleanup;
270 }
271 len -= l;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000272 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000273
Damien Miller95def091999-11-25 00:26:21 +1100274 /* Extract the length, and check it for sanity. */
275 len = GET_32BIT(buf);
276 if (len > 256 * 1024)
277 fatal("Authentication response too long: %d", len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000278
Damien Miller95def091999-11-25 00:26:21 +1100279 /* Read the rest of the response in tothe buffer. */
280 buffer_clear(&buffer);
281 while (len > 0) {
282 l = len;
283 if (l > sizeof(buf))
284 l = sizeof(buf);
285 l = read(auth->fd, buf, l);
286 if (l <= 0) {
287 error("Error reading response from authentication socket.");
288 goto error_cleanup;
289 }
290 buffer_append(&buffer, (char *) buf, l);
291 len -= l;
292 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000293
Damien Miller95def091999-11-25 00:26:21 +1100294 /* Get the type of the packet. */
295 buffer_get(&buffer, (char *) buf, 1);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000296
Damien Miller95def091999-11-25 00:26:21 +1100297 /* Check for agent failure message. */
298 if (buf[0] == SSH_AGENT_FAILURE) {
299 log("Agent admitted failure to authenticate using the key.");
300 goto error_cleanup;
301 }
302 /* Now it must be an authentication response packet. */
303 if (buf[0] != SSH_AGENT_RSA_RESPONSE)
304 fatal("Bad authentication response: %d", buf[0]);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000305
Damien Miller95def091999-11-25 00:26:21 +1100306 /* Get the response from the packet. This will abort with a fatal
307 error if the packet is corrupt. */
308 for (i = 0; i < 16; i++)
309 response[i] = buffer_get_char(&buffer);
310
311 /* The buffer containing the packet is no longer needed. */
312 buffer_free(&buffer);
313
314 /* Correct answer. */
315 return 1;
316}
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000317
318/* Adds an identity to the authentication server. This call is not meant to
319 be used by normal applications. */
320
Damien Miller95def091999-11-25 00:26:21 +1100321int
322ssh_add_identity(AuthenticationConnection *auth,
323 RSA * key, const char *comment)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000324{
Damien Miller95def091999-11-25 00:26:21 +1100325 Buffer buffer;
326 unsigned char buf[8192];
327 int len, l, type;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000328
Damien Miller95def091999-11-25 00:26:21 +1100329 /* Format a message to the agent. */
330 buffer_init(&buffer);
331 buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
332 buffer_put_int(&buffer, BN_num_bits(key->n));
333 buffer_put_bignum(&buffer, key->n);
334 buffer_put_bignum(&buffer, key->e);
335 buffer_put_bignum(&buffer, key->d);
336 /* To keep within the protocol: p < q for ssh. in SSL p > q */
337 buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */
338 buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */
339 buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */
340 buffer_put_string(&buffer, comment, strlen(comment));
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000341
Damien Miller95def091999-11-25 00:26:21 +1100342 /* Get the length of the message, and format it in the buffer. */
343 len = buffer_len(&buffer);
344 PUT_32BIT(buf, len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000345
Damien Miller95def091999-11-25 00:26:21 +1100346 /* Send the length and then the packet to the agent. */
347 if (write(auth->fd, buf, 4) != 4 ||
348 write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
349 buffer_len(&buffer)) {
350 error("Error writing to authentication socket.");
351error_cleanup:
352 buffer_free(&buffer);
353 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000354 }
Damien Miller95def091999-11-25 00:26:21 +1100355 /* Wait for response from the agent. First read the length of the
356 response packet. */
357 len = 4;
358 while (len > 0) {
359 l = read(auth->fd, buf + 4 - len, len);
360 if (l <= 0) {
361 error("Error reading response length from authentication socket.");
362 goto error_cleanup;
363 }
364 len -= l;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000365 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000366
Damien Miller95def091999-11-25 00:26:21 +1100367 /* 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);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000371
Damien Miller95def091999-11-25 00:26:21 +1100372 /* Read the rest of the response in tothe buffer. */
373 buffer_clear(&buffer);
374 while (len > 0) {
375 l = len;
376 if (l > sizeof(buf))
377 l = sizeof(buf);
378 l = read(auth->fd, buf, l);
379 if (l <= 0) {
380 error("Error reading response from authentication socket.");
381 goto error_cleanup;
382 }
383 buffer_append(&buffer, (char *) buf, l);
384 len -= l;
385 }
386
387 /* Get the type of the packet. */
388 type = buffer_get_char(&buffer);
389 switch (type) {
390 case SSH_AGENT_FAILURE:
391 buffer_free(&buffer);
392 return 0;
393 case SSH_AGENT_SUCCESS:
394 buffer_free(&buffer);
395 return 1;
396 default:
397 fatal("Bad response to add identity from authentication agent: %d",
398 type);
399 }
400 /* NOTREACHED */
401 return 0;
402}
403
404/* Removes an identity from the authentication server. This call is not meant
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000405 to be used by normal applications. */
406
Damien Miller95def091999-11-25 00:26:21 +1100407int
408ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000409{
Damien Miller95def091999-11-25 00:26:21 +1100410 Buffer buffer;
411 unsigned char buf[8192];
412 int len, l, type;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000413
Damien Miller95def091999-11-25 00:26:21 +1100414 /* Format a message to the agent. */
415 buffer_init(&buffer);
416 buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
417 buffer_put_int(&buffer, BN_num_bits(key->n));
418 buffer_put_bignum(&buffer, key->e);
419 buffer_put_bignum(&buffer, key->n);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000420
Damien Miller95def091999-11-25 00:26:21 +1100421 /* Get the length of the message, and format it in the buffer. */
422 len = buffer_len(&buffer);
423 PUT_32BIT(buf, len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000424
Damien Miller95def091999-11-25 00:26:21 +1100425 /* Send the length and then the packet to the agent. */
426 if (write(auth->fd, buf, 4) != 4 ||
427 write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
428 buffer_len(&buffer)) {
429 error("Error writing to authentication socket.");
430error_cleanup:
431 buffer_free(&buffer);
432 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000433 }
Damien Miller95def091999-11-25 00:26:21 +1100434 /* Wait for response from the agent. First read the length of the
435 response packet. */
436 len = 4;
437 while (len > 0) {
438 l = read(auth->fd, buf + 4 - len, len);
439 if (l <= 0) {
440 error("Error reading response length from authentication socket.");
441 goto error_cleanup;
442 }
443 len -= l;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000444 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000445
Damien Miller95def091999-11-25 00:26:21 +1100446 /* Extract the length, and check it for sanity. */
447 len = GET_32BIT(buf);
448 if (len > 256 * 1024)
449 fatal("Remove identity response too long: %d", len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000450
Damien Miller95def091999-11-25 00:26:21 +1100451 /* Read the rest of the response in tothe buffer. */
452 buffer_clear(&buffer);
453 while (len > 0) {
454 l = len;
455 if (l > sizeof(buf))
456 l = sizeof(buf);
457 l = read(auth->fd, buf, l);
458 if (l <= 0) {
459 error("Error reading response from authentication socket.");
460 goto error_cleanup;
461 }
462 buffer_append(&buffer, (char *) buf, l);
463 len -= l;
464 }
465
466 /* Get the type of the packet. */
467 type = buffer_get_char(&buffer);
468 switch (type) {
469 case SSH_AGENT_FAILURE:
470 buffer_free(&buffer);
471 return 0;
472 case SSH_AGENT_SUCCESS:
473 buffer_free(&buffer);
474 return 1;
475 default:
476 fatal("Bad response to remove identity from authentication agent: %d",
477 type);
478 }
479 /* NOTREACHED */
480 return 0;
481}
482
483/* Removes all identities from the agent. This call is not meant
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000484 to be used by normal applications. */
485
Damien Miller95def091999-11-25 00:26:21 +1100486int
487ssh_remove_all_identities(AuthenticationConnection *auth)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000488{
Damien Miller95def091999-11-25 00:26:21 +1100489 Buffer buffer;
490 unsigned char buf[8192];
491 int len, l, type;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000492
Damien Miller95def091999-11-25 00:26:21 +1100493 /* Get the length of the message, and format it in the buffer. */
494 PUT_32BIT(buf, 1);
495 buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000496
Damien Miller95def091999-11-25 00:26:21 +1100497 /* Send the length and then the packet to the agent. */
498 if (write(auth->fd, buf, 5) != 5) {
499 error("Error writing to authentication socket.");
500 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000501 }
Damien Miller95def091999-11-25 00:26:21 +1100502 /* Wait for response from the agent. First read the length of the
503 response packet. */
504 len = 4;
505 while (len > 0) {
506 l = read(auth->fd, buf + 4 - len, len);
507 if (l <= 0) {
508 error("Error reading response length from authentication socket.");
509 return 0;
510 }
511 len -= l;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000512 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000513
Damien Miller95def091999-11-25 00:26:21 +1100514 /* Extract the length, and check it for sanity. */
515 len = GET_32BIT(buf);
516 if (len > 256 * 1024)
517 fatal("Remove identity response too long: %d", len);
518
519 /* Read the rest of the response into the buffer. */
520 buffer_init(&buffer);
521 while (len > 0) {
522 l = len;
523 if (l > sizeof(buf))
524 l = sizeof(buf);
525 l = read(auth->fd, buf, l);
526 if (l <= 0) {
527 error("Error reading response from authentication socket.");
528 buffer_free(&buffer);
529 return 0;
530 }
531 buffer_append(&buffer, (char *) buf, l);
532 len -= l;
533 }
534
535 /* Get the type of the packet. */
536 type = buffer_get_char(&buffer);
537 switch (type) {
538 case SSH_AGENT_FAILURE:
539 buffer_free(&buffer);
540 return 0;
541 case SSH_AGENT_SUCCESS:
542 buffer_free(&buffer);
543 return 1;
544 default:
545 fatal("Bad response to remove identity from authentication agent: %d",
546 type);
547 }
548 /* NOTREACHED */
549 return 0;
550}