blob: 36b4d6ce4242c77330c105fa15b77eda34189c46 [file] [log] [blame]
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001/*
Damien Miller4af51302000-04-16 11:18:38 +10002 *
Damien Miller95def091999-11-25 00:26:21 +11003 * authfd.c
Damien Miller4af51302000-04-16 11:18:38 +10004 *
Damien Miller95def091999-11-25 00:26:21 +11005 * Author: Tatu Ylonen <ylo@cs.hut.fi>
Damien Miller4af51302000-04-16 11:18:38 +10006 *
Damien Miller95def091999-11-25 00:26:21 +11007 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 * All rights reserved
Damien Miller4af51302000-04-16 11:18:38 +10009 *
Damien Miller95def091999-11-25 00:26:21 +110010 * Created: Wed Mar 29 01:30:28 1995 ylo
Damien Miller4af51302000-04-16 11:18:38 +100011 *
Damien Miller95def091999-11-25 00:26:21 +110012 * Functions for connecting the local authentication agent.
Damien Miller4af51302000-04-16 11:18:38 +100013 *
Damien Miller95def091999-11-25 00:26:21 +110014 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100015
16#include "includes.h"
Damien Millerbd483e72000-04-30 10:00:53 +100017RCSID("$Id: authfd.c,v 1.14 2000/04/30 00:00:53 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
27#include <openssl/rsa.h>
Damien Millerd4a8b7e1999-10-27 13:42:43 +100028
29/* Returns the number of the authentication fd, or -1 if there is none. */
30
31int
32ssh_get_authentication_socket()
33{
Damien Miller95def091999-11-25 00:26:21 +110034 const char *authsocket;
35 int sock;
36 struct sockaddr_un sunaddr;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100037
Damien Miller95def091999-11-25 00:26:21 +110038 authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
39 if (!authsocket)
40 return -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100041
Damien Miller95def091999-11-25 00:26:21 +110042 sunaddr.sun_family = AF_UNIX;
43 strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
Damien Miller10f6f6b1999-11-17 17:29:08 +110044
Damien Miller95def091999-11-25 00:26:21 +110045 sock = socket(AF_UNIX, SOCK_STREAM, 0);
46 if (sock < 0)
47 return -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100048
Damien Miller95def091999-11-25 00:26:21 +110049 /* 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;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100059}
60
Damien Miller5428f641999-11-25 11:54:57 +110061/*
62 * Closes the agent socket if it should be closed (depends on how it was
63 * obtained). The argument must have been returned by
64 * ssh_get_authentication_socket().
65 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100066
Damien Miller4af51302000-04-16 11:18:38 +100067void
Damien Miller95def091999-11-25 00:26:21 +110068ssh_close_authentication_socket(int sock)
Damien Millerd4a8b7e1999-10-27 13:42:43 +100069{
Damien Miller95def091999-11-25 00:26:21 +110070 if (getenv(SSH_AUTHSOCKET_ENV_NAME))
71 close(sock);
Damien Millerd4a8b7e1999-10-27 13:42:43 +100072}
73
Damien Miller5428f641999-11-25 11:54:57 +110074/*
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 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100081
Damien Miller95def091999-11-25 00:26:21 +110082AuthenticationConnection *
83ssh_get_authentication_connection()
Damien Millerd4a8b7e1999-10-27 13:42:43 +100084{
Damien Miller95def091999-11-25 00:26:21 +110085 AuthenticationConnection *auth;
86 int sock;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100087
Damien Miller95def091999-11-25 00:26:21 +110088 sock = ssh_get_authentication_socket();
Damien Millerd4a8b7e1999-10-27 13:42:43 +100089
Damien Miller5428f641999-11-25 11:54:57 +110090 /*
91 * Fail if we couldn't obtain a connection. This happens if we
92 * exited due to a timeout.
93 */
Damien Miller95def091999-11-25 00:26:21 +110094 if (sock < 0)
95 return NULL;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100096
Damien Miller95def091999-11-25 00:26:21 +110097 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
Damien Miller5428f641999-11-25 11:54:57 +1100106/*
107 * Closes the connection to the authentication agent and frees any associated
108 * memory.
109 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000110
Damien Miller4af51302000-04-16 11:18:38 +1000111void
Damien Miller95def091999-11-25 00:26:21 +1100112ssh_close_authentication_connection(AuthenticationConnection *ac)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000113{
Damien Miller95def091999-11-25 00:26:21 +1100114 buffer_free(&ac->packet);
115 buffer_free(&ac->identities);
116 close(ac->fd);
117 xfree(ac);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000118}
119
Damien Miller5428f641999-11-25 11:54:57 +1100120/*
121 * Returns the first authentication identity held by the agent.
122 * Returns true if an identity is available, 0 otherwise.
123 * The caller must initialize the integers before the call, and free the
124 * comment after a successful call (before calling ssh_get_next_identity).
125 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000126
127int
128ssh_get_first_identity(AuthenticationConnection *auth,
Damien Miller7e8e8201999-11-16 13:37:16 +1100129 BIGNUM *e, BIGNUM *n, char **comment)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000130{
Damien Miller95def091999-11-25 00:26:21 +1100131 unsigned char msg[8192];
132 int len, l;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000133
Damien Miller5428f641999-11-25 11:54:57 +1100134 /*
135 * Send a message to the agent requesting for a list of the
136 * identities it can represent.
137 */
Damien Miller95def091999-11-25 00:26:21 +1100138 msg[0] = 0;
139 msg[1] = 0;
140 msg[2] = 0;
141 msg[3] = 1;
142 msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
Damien Miller037a0dc1999-12-07 15:38:31 +1100143 if (atomicio(write, auth->fd, msg, 5) != 5) {
Damien Miller95def091999-11-25 00:26:21 +1100144 error("write auth->fd: %.100s", strerror(errno));
145 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000146 }
Damien Miller95def091999-11-25 00:26:21 +1100147 /* Read the length of the response. XXX implement timeouts here. */
148 len = 4;
149 while (len > 0) {
150 l = read(auth->fd, msg + 4 - len, len);
151 if (l <= 0) {
152 error("read auth->fd: %.100s", strerror(errno));
153 return 0;
154 }
155 len -= l;
156 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000157
Damien Miller5428f641999-11-25 11:54:57 +1100158 /*
159 * Extract the length, and check it for sanity. (We cannot trust
160 * authentication agents).
161 */
Damien Miller95def091999-11-25 00:26:21 +1100162 len = GET_32BIT(msg);
163 if (len < 1 || len > 256 * 1024)
164 fatal("Authentication reply message too long: %d\n", len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000165
Damien Miller95def091999-11-25 00:26:21 +1100166 /* Read the packet itself. */
167 buffer_clear(&auth->identities);
168 while (len > 0) {
169 l = len;
170 if (l > sizeof(msg))
171 l = sizeof(msg);
172 l = read(auth->fd, msg, l);
173 if (l <= 0)
174 fatal("Incomplete authentication reply.");
175 buffer_append(&auth->identities, (char *) msg, l);
176 len -= l;
177 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000178
Damien Miller95def091999-11-25 00:26:21 +1100179 /* Get message type, and verify that we got a proper answer. */
180 buffer_get(&auth->identities, (char *) msg, 1);
181 if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
182 fatal("Bad authentication reply message type: %d", msg[0]);
183
184 /* Get the number of entries in the response and check it for sanity. */
185 auth->howmany = buffer_get_int(&auth->identities);
186 if (auth->howmany > 1024)
187 fatal("Too many identities in authentication reply: %d\n", auth->howmany);
188
189 /* Return the first entry (if any). */
190 return ssh_get_next_identity(auth, e, n, comment);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000191}
192
Damien Miller5428f641999-11-25 11:54:57 +1100193/*
194 * Returns the next authentication identity for the agent. Other functions
195 * can be called between this and ssh_get_first_identity or two calls of this
196 * function. This returns 0 if there are no more identities. The caller
197 * must free comment after a successful return.
198 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000199
200int
201ssh_get_next_identity(AuthenticationConnection *auth,
Damien Miller7e8e8201999-11-16 13:37:16 +1100202 BIGNUM *e, BIGNUM *n, char **comment)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000203{
Damien Miller95def091999-11-25 00:26:21 +1100204 unsigned int bits;
Damien Miller7e8e8201999-11-16 13:37:16 +1100205
Damien Miller95def091999-11-25 00:26:21 +1100206 /* Return failure if no more entries. */
207 if (auth->howmany <= 0)
208 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000209
Damien Miller5428f641999-11-25 11:54:57 +1100210 /*
211 * Get the next entry from the packet. These will abort with a fatal
212 * error if the packet is too short or contains corrupt data.
213 */
Damien Miller95def091999-11-25 00:26:21 +1100214 bits = buffer_get_int(&auth->identities);
215 buffer_get_bignum(&auth->identities, e);
216 buffer_get_bignum(&auth->identities, n);
217 *comment = buffer_get_string(&auth->identities, NULL);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000218
Damien Miller95def091999-11-25 00:26:21 +1100219 if (bits != BN_num_bits(n))
Damien Millerbd483e72000-04-30 10:00:53 +1000220 log("Warning: identity keysize mismatch: actual %d, announced %u",
221 BN_num_bits(n), bits);
Damien Miller7e8e8201999-11-16 13:37:16 +1100222
Damien Miller95def091999-11-25 00:26:21 +1100223 /* Decrement the number of remaining entries. */
224 auth->howmany--;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000225
Damien Miller95def091999-11-25 00:26:21 +1100226 return 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000227}
228
Damien Miller5428f641999-11-25 11:54:57 +1100229/*
230 * Generates a random challenge, sends it to the agent, and waits for
231 * response from the agent. Returns true (non-zero) if the agent gave the
232 * correct answer, zero otherwise. Response type selects the style of
233 * response desired, with 0 corresponding to protocol version 1.0 (no longer
234 * supported) and 1 corresponding to protocol version 1.1.
235 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000236
237int
238ssh_decrypt_challenge(AuthenticationConnection *auth,
Damien Miller95def091999-11-25 00:26:21 +1100239 BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000240 unsigned char session_id[16],
241 unsigned int response_type,
242 unsigned char response[16])
243{
Damien Miller95def091999-11-25 00:26:21 +1100244 Buffer buffer;
245 unsigned char buf[8192];
246 int len, l, i;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000247
Damien Miller95def091999-11-25 00:26:21 +1100248 /* Response type 0 is no longer supported. */
249 if (response_type == 0)
250 fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000251
Damien Miller95def091999-11-25 00:26:21 +1100252 /* Format a message to the agent. */
253 buf[0] = SSH_AGENTC_RSA_CHALLENGE;
254 buffer_init(&buffer);
255 buffer_append(&buffer, (char *) buf, 1);
256 buffer_put_int(&buffer, BN_num_bits(n));
257 buffer_put_bignum(&buffer, e);
258 buffer_put_bignum(&buffer, n);
259 buffer_put_bignum(&buffer, challenge);
260 buffer_append(&buffer, (char *) session_id, 16);
261 buffer_put_int(&buffer, response_type);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000262
Damien Miller95def091999-11-25 00:26:21 +1100263 /* Get the length of the message, and format it in the buffer. */
264 len = buffer_len(&buffer);
265 PUT_32BIT(buf, len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000266
Damien Miller95def091999-11-25 00:26:21 +1100267 /* Send the length and then the packet to the agent. */
Damien Miller037a0dc1999-12-07 15:38:31 +1100268 if (atomicio(write, auth->fd, buf, 4) != 4 ||
269 atomicio(write, auth->fd, buffer_ptr(&buffer),
270 buffer_len(&buffer)) != buffer_len(&buffer)) {
Damien Miller95def091999-11-25 00:26:21 +1100271 error("Error writing to authentication socket.");
272error_cleanup:
273 buffer_free(&buffer);
274 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000275 }
Damien Miller5428f641999-11-25 11:54:57 +1100276 /*
277 * Wait for response from the agent. First read the length of the
278 * response packet.
279 */
Damien Miller95def091999-11-25 00:26:21 +1100280 len = 4;
281 while (len > 0) {
282 l = read(auth->fd, buf + 4 - len, len);
283 if (l <= 0) {
284 error("Error reading response length from authentication socket.");
285 goto error_cleanup;
286 }
287 len -= l;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000288 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000289
Damien Miller95def091999-11-25 00:26:21 +1100290 /* Extract the length, and check it for sanity. */
291 len = GET_32BIT(buf);
292 if (len > 256 * 1024)
293 fatal("Authentication response too long: %d", len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000294
Damien Miller95def091999-11-25 00:26:21 +1100295 /* Read the rest of the response in tothe buffer. */
296 buffer_clear(&buffer);
297 while (len > 0) {
298 l = len;
299 if (l > sizeof(buf))
300 l = sizeof(buf);
301 l = read(auth->fd, buf, l);
302 if (l <= 0) {
303 error("Error reading response from authentication socket.");
304 goto error_cleanup;
305 }
306 buffer_append(&buffer, (char *) buf, l);
307 len -= l;
308 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000309
Damien Miller95def091999-11-25 00:26:21 +1100310 /* Get the type of the packet. */
311 buffer_get(&buffer, (char *) buf, 1);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000312
Damien Miller95def091999-11-25 00:26:21 +1100313 /* Check for agent failure message. */
314 if (buf[0] == SSH_AGENT_FAILURE) {
315 log("Agent admitted failure to authenticate using the key.");
316 goto error_cleanup;
317 }
318 /* Now it must be an authentication response packet. */
319 if (buf[0] != SSH_AGENT_RSA_RESPONSE)
320 fatal("Bad authentication response: %d", buf[0]);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000321
Damien Miller5428f641999-11-25 11:54:57 +1100322 /*
323 * Get the response from the packet. This will abort with a fatal
324 * error if the packet is corrupt.
325 */
Damien Miller95def091999-11-25 00:26:21 +1100326 for (i = 0; i < 16; i++)
327 response[i] = buffer_get_char(&buffer);
328
329 /* The buffer containing the packet is no longer needed. */
330 buffer_free(&buffer);
331
332 /* Correct answer. */
333 return 1;
334}
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000335
Damien Miller5428f641999-11-25 11:54:57 +1100336/*
337 * Adds an identity to the authentication server. This call is not meant to
338 * be used by normal applications.
339 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000340
Damien Miller4af51302000-04-16 11:18:38 +1000341int
Damien Miller95def091999-11-25 00:26:21 +1100342ssh_add_identity(AuthenticationConnection *auth,
343 RSA * key, const char *comment)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000344{
Damien Miller95def091999-11-25 00:26:21 +1100345 Buffer buffer;
346 unsigned char buf[8192];
347 int len, l, type;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000348
Damien Miller95def091999-11-25 00:26:21 +1100349 /* Format a message to the agent. */
350 buffer_init(&buffer);
351 buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
352 buffer_put_int(&buffer, BN_num_bits(key->n));
353 buffer_put_bignum(&buffer, key->n);
354 buffer_put_bignum(&buffer, key->e);
355 buffer_put_bignum(&buffer, key->d);
356 /* To keep within the protocol: p < q for ssh. in SSL p > q */
357 buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */
358 buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */
359 buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */
360 buffer_put_string(&buffer, comment, strlen(comment));
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000361
Damien Miller95def091999-11-25 00:26:21 +1100362 /* Get the length of the message, and format it in the buffer. */
363 len = buffer_len(&buffer);
364 PUT_32BIT(buf, len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000365
Damien Miller95def091999-11-25 00:26:21 +1100366 /* Send the length and then the packet to the agent. */
Damien Miller037a0dc1999-12-07 15:38:31 +1100367 if (atomicio(write, auth->fd, buf, 4) != 4 ||
368 atomicio(write, auth->fd, buffer_ptr(&buffer),
369 buffer_len(&buffer)) != buffer_len(&buffer)) {
Damien Miller95def091999-11-25 00:26:21 +1100370 error("Error writing to authentication socket.");
371error_cleanup:
372 buffer_free(&buffer);
373 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000374 }
Damien Miller95def091999-11-25 00:26:21 +1100375 /* Wait for response from the agent. First read the length of the
376 response packet. */
377 len = 4;
378 while (len > 0) {
379 l = read(auth->fd, buf + 4 - len, len);
380 if (l <= 0) {
381 error("Error reading response length from authentication socket.");
382 goto error_cleanup;
383 }
384 len -= l;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000385 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000386
Damien Miller95def091999-11-25 00:26:21 +1100387 /* Extract the length, and check it for sanity. */
388 len = GET_32BIT(buf);
389 if (len > 256 * 1024)
390 fatal("Add identity response too long: %d", len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000391
Damien Miller95def091999-11-25 00:26:21 +1100392 /* Read the rest of the response in tothe buffer. */
393 buffer_clear(&buffer);
394 while (len > 0) {
395 l = len;
396 if (l > sizeof(buf))
397 l = sizeof(buf);
398 l = read(auth->fd, buf, l);
399 if (l <= 0) {
400 error("Error reading response from authentication socket.");
401 goto error_cleanup;
402 }
403 buffer_append(&buffer, (char *) buf, l);
404 len -= l;
405 }
406
407 /* Get the type of the packet. */
408 type = buffer_get_char(&buffer);
409 switch (type) {
410 case SSH_AGENT_FAILURE:
411 buffer_free(&buffer);
412 return 0;
413 case SSH_AGENT_SUCCESS:
414 buffer_free(&buffer);
415 return 1;
416 default:
417 fatal("Bad response to add identity from authentication agent: %d",
418 type);
419 }
420 /* NOTREACHED */
421 return 0;
422}
423
Damien Miller5428f641999-11-25 11:54:57 +1100424/*
425 * Removes an identity from the authentication server. This call is not
426 * meant to be used by normal applications.
427 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000428
Damien Miller4af51302000-04-16 11:18:38 +1000429int
Damien Miller95def091999-11-25 00:26:21 +1100430ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000431{
Damien Miller95def091999-11-25 00:26:21 +1100432 Buffer buffer;
433 unsigned char buf[8192];
434 int len, l, type;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000435
Damien Miller95def091999-11-25 00:26:21 +1100436 /* Format a message to the agent. */
437 buffer_init(&buffer);
438 buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
439 buffer_put_int(&buffer, BN_num_bits(key->n));
440 buffer_put_bignum(&buffer, key->e);
441 buffer_put_bignum(&buffer, key->n);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000442
Damien Miller95def091999-11-25 00:26:21 +1100443 /* Get the length of the message, and format it in the buffer. */
444 len = buffer_len(&buffer);
445 PUT_32BIT(buf, len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000446
Damien Miller95def091999-11-25 00:26:21 +1100447 /* Send the length and then the packet to the agent. */
Damien Miller037a0dc1999-12-07 15:38:31 +1100448 if (atomicio(write, auth->fd, buf, 4) != 4 ||
449 atomicio(write, auth->fd, buffer_ptr(&buffer),
450 buffer_len(&buffer)) != buffer_len(&buffer)) {
Damien Miller95def091999-11-25 00:26:21 +1100451 error("Error writing to authentication socket.");
452error_cleanup:
453 buffer_free(&buffer);
454 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000455 }
Damien Miller5428f641999-11-25 11:54:57 +1100456 /*
457 * Wait for response from the agent. First read the length of the
458 * response packet.
459 */
Damien Miller95def091999-11-25 00:26:21 +1100460 len = 4;
461 while (len > 0) {
462 l = read(auth->fd, buf + 4 - len, len);
463 if (l <= 0) {
464 error("Error reading response length from authentication socket.");
465 goto error_cleanup;
466 }
467 len -= l;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000468 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000469
Damien Miller95def091999-11-25 00:26:21 +1100470 /* Extract the length, and check it for sanity. */
471 len = GET_32BIT(buf);
472 if (len > 256 * 1024)
473 fatal("Remove identity response too long: %d", len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000474
Damien Miller95def091999-11-25 00:26:21 +1100475 /* Read the rest of the response in tothe buffer. */
476 buffer_clear(&buffer);
477 while (len > 0) {
478 l = len;
479 if (l > sizeof(buf))
480 l = sizeof(buf);
481 l = read(auth->fd, buf, l);
482 if (l <= 0) {
483 error("Error reading response from authentication socket.");
484 goto error_cleanup;
485 }
486 buffer_append(&buffer, (char *) buf, l);
487 len -= l;
488 }
489
490 /* Get the type of the packet. */
491 type = buffer_get_char(&buffer);
492 switch (type) {
493 case SSH_AGENT_FAILURE:
494 buffer_free(&buffer);
495 return 0;
496 case SSH_AGENT_SUCCESS:
497 buffer_free(&buffer);
498 return 1;
499 default:
500 fatal("Bad response to remove identity from authentication agent: %d",
501 type);
502 }
503 /* NOTREACHED */
504 return 0;
505}
506
Damien Miller5428f641999-11-25 11:54:57 +1100507/*
508 * Removes all identities from the agent. This call is not meant to be used
509 * by normal applications.
510 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000511
Damien Miller4af51302000-04-16 11:18:38 +1000512int
Damien Miller95def091999-11-25 00:26:21 +1100513ssh_remove_all_identities(AuthenticationConnection *auth)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000514{
Damien Miller95def091999-11-25 00:26:21 +1100515 Buffer buffer;
516 unsigned char buf[8192];
517 int len, l, type;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000518
Damien Miller95def091999-11-25 00:26:21 +1100519 /* Get the length of the message, and format it in the buffer. */
520 PUT_32BIT(buf, 1);
521 buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000522
Damien Miller95def091999-11-25 00:26:21 +1100523 /* Send the length and then the packet to the agent. */
Damien Miller037a0dc1999-12-07 15:38:31 +1100524 if (atomicio(write, auth->fd, buf, 5) != 5) {
Damien Miller95def091999-11-25 00:26:21 +1100525 error("Error writing to authentication socket.");
526 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000527 }
Damien Miller5428f641999-11-25 11:54:57 +1100528 /*
529 * Wait for response from the agent. First read the length of the
530 * response packet.
531 */
Damien Miller95def091999-11-25 00:26:21 +1100532 len = 4;
533 while (len > 0) {
534 l = read(auth->fd, buf + 4 - len, len);
535 if (l <= 0) {
536 error("Error reading response length from authentication socket.");
537 return 0;
538 }
539 len -= l;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000540 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000541
Damien Miller95def091999-11-25 00:26:21 +1100542 /* Extract the length, and check it for sanity. */
543 len = GET_32BIT(buf);
544 if (len > 256 * 1024)
545 fatal("Remove identity response too long: %d", len);
546
547 /* Read the rest of the response into the buffer. */
548 buffer_init(&buffer);
549 while (len > 0) {
550 l = len;
551 if (l > sizeof(buf))
552 l = sizeof(buf);
553 l = read(auth->fd, buf, l);
554 if (l <= 0) {
555 error("Error reading response from authentication socket.");
556 buffer_free(&buffer);
557 return 0;
558 }
559 buffer_append(&buffer, (char *) buf, l);
560 len -= l;
561 }
562
563 /* Get the type of the packet. */
564 type = buffer_get_char(&buffer);
565 switch (type) {
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}