diff options
author | Damien Miller <djm@mindrot.org> | 2000-08-18 13:59:06 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2000-08-18 13:59:06 +1000 |
commit | 942da039d2a05e6f491883f50b516175a6dbb20f (patch) | |
tree | 0ac91ba19e494a3cb054d34db0c3b65660bd7375 /authfd.c | |
parent | 11fa2cc3839b1e7fed1d85aa1158cce4d498bc58 (diff) |
- (djm) OpenBSD CVS changes:
- markus@cvs.openbsd.org 2000/07/22 03:14:37
[servconf.c servconf.h sshd.8 sshd.c sshd_config]
random early drop; ok theo, niels
- deraadt@cvs.openbsd.org 2000/07/26 11:46:51
[ssh.1]
typo
- deraadt@cvs.openbsd.org 2000/08/01 11:46:11
[sshd.8]
many fixes from pepper@mail.reppep.com
- provos@cvs.openbsd.org 2000/08/01 13:01:42
[Makefile.in util.c aux.c]
rename aux.c to util.c to help with cygwin port
- deraadt@cvs.openbsd.org 2000/08/02 00:23:31
[authfd.c]
correct sun_len; Alexander@Leidinger.net
- provos@cvs.openbsd.org 2000/08/02 10:27:17
[readconf.c sshd.8]
disable kerberos authentication by default
- provos@cvs.openbsd.org 2000/08/02 11:27:05
[sshd.8 readconf.c auth-krb4.c]
disallow kerberos authentication if we can't verify the TGT; from
dugsong@
kerberos authentication is on by default only if you have a srvtab.
- markus@cvs.openbsd.org 2000/08/04 14:30:07
[auth.c]
unused
- markus@cvs.openbsd.org 2000/08/04 14:30:35
[sshd_config]
MaxStartups
- markus@cvs.openbsd.org 2000/08/15 13:20:46
[authfd.c]
cleanup; ok niels@
- markus@cvs.openbsd.org 2000/08/17 14:05:10
[session.c]
cleanup login(1)-like jobs, no duplicate utmp entries
- markus@cvs.openbsd.org 2000/08/17 14:06:34
[session.c sshd.8 sshd.c]
sshd -u len, similar to telnetd
Diffstat (limited to 'authfd.c')
-rw-r--r-- | authfd.c | 325 |
1 files changed, 121 insertions, 204 deletions
@@ -14,7 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "includes.h" | 16 | #include "includes.h" |
17 | RCSID("$OpenBSD: authfd.c,v 1.22 2000/07/16 08:27:20 markus Exp $"); | 17 | RCSID("$OpenBSD: authfd.c,v 1.24 2000/08/15 19:20:46 markus Exp $"); |
18 | 18 | ||
19 | #include "ssh.h" | 19 | #include "ssh.h" |
20 | #include "rsa.h" | 20 | #include "rsa.h" |
@@ -31,7 +31,7 @@ RCSID("$OpenBSD: authfd.c,v 1.22 2000/07/16 08:27:20 markus Exp $"); | |||
31 | #include "kex.h" | 31 | #include "kex.h" |
32 | 32 | ||
33 | /* helper */ | 33 | /* helper */ |
34 | int ssh_agent_get_reply(AuthenticationConnection *auth); | 34 | int decode_reply(int type); |
35 | 35 | ||
36 | /* Returns the number of the authentication fd, or -1 if there is none. */ | 36 | /* Returns the number of the authentication fd, or -1 if there is none. */ |
37 | 37 | ||
@@ -39,7 +39,7 @@ int | |||
39 | ssh_get_authentication_socket() | 39 | ssh_get_authentication_socket() |
40 | { | 40 | { |
41 | const char *authsocket; | 41 | const char *authsocket; |
42 | int sock; | 42 | int sock, len; |
43 | struct sockaddr_un sunaddr; | 43 | struct sockaddr_un sunaddr; |
44 | 44 | ||
45 | authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); | 45 | authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); |
@@ -48,6 +48,11 @@ ssh_get_authentication_socket() | |||
48 | 48 | ||
49 | sunaddr.sun_family = AF_UNIX; | 49 | sunaddr.sun_family = AF_UNIX; |
50 | strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); | 50 | strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); |
51 | #ifdef HAVE_SUN_LEN_IN_SOCKADDR_UN | ||
52 | sunaddr.sun_len = len = SUN_LEN(&sunaddr)+1; | ||
53 | #else /* HAVE_SUN_LEN_IN_SOCKADDR_UN */ | ||
54 | len = SUN_LEN(&sunaddr)+1; | ||
55 | #endif /* HAVE_SUN_LEN_IN_SOCKADDR_UN */ | ||
51 | 56 | ||
52 | sock = socket(AF_UNIX, SOCK_STREAM, 0); | 57 | sock = socket(AF_UNIX, SOCK_STREAM, 0); |
53 | if (sock < 0) | 58 | if (sock < 0) |
@@ -58,13 +63,67 @@ ssh_get_authentication_socket() | |||
58 | close(sock); | 63 | close(sock); |
59 | return -1; | 64 | return -1; |
60 | } | 65 | } |
61 | if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) { | 66 | if (connect(sock, (struct sockaddr *) & sunaddr, len) < 0) { |
62 | close(sock); | 67 | close(sock); |
63 | return -1; | 68 | return -1; |
64 | } | 69 | } |
65 | return sock; | 70 | return sock; |
66 | } | 71 | } |
67 | 72 | ||
73 | int | ||
74 | ssh_request_reply(AuthenticationConnection *auth, | ||
75 | Buffer *request, Buffer *reply) | ||
76 | { | ||
77 | int l, len; | ||
78 | char buf[1024]; | ||
79 | |||
80 | /* Get the length of the message, and format it in the buffer. */ | ||
81 | len = buffer_len(request); | ||
82 | PUT_32BIT(buf, len); | ||
83 | |||
84 | /* Send the length and then the packet to the agent. */ | ||
85 | if (atomicio(write, auth->fd, buf, 4) != 4 || | ||
86 | atomicio(write, auth->fd, buffer_ptr(request), | ||
87 | buffer_len(request)) != buffer_len(request)) { | ||
88 | error("Error writing to authentication socket."); | ||
89 | return 0; | ||
90 | } | ||
91 | /* | ||
92 | * Wait for response from the agent. First read the length of the | ||
93 | * response packet. | ||
94 | */ | ||
95 | len = 4; | ||
96 | while (len > 0) { | ||
97 | l = read(auth->fd, buf + 4 - len, len); | ||
98 | if (l <= 0) { | ||
99 | error("Error reading response length from authentication socket."); | ||
100 | return 0; | ||
101 | } | ||
102 | len -= l; | ||
103 | } | ||
104 | |||
105 | /* Extract the length, and check it for sanity. */ | ||
106 | len = GET_32BIT(buf); | ||
107 | if (len > 256 * 1024) | ||
108 | fatal("Authentication response too long: %d", len); | ||
109 | |||
110 | /* Read the rest of the response in to the buffer. */ | ||
111 | buffer_clear(reply); | ||
112 | while (len > 0) { | ||
113 | l = len; | ||
114 | if (l > sizeof(buf)) | ||
115 | l = sizeof(buf); | ||
116 | l = read(auth->fd, buf, l); | ||
117 | if (l <= 0) { | ||
118 | error("Error reading response from authentication socket."); | ||
119 | return 0; | ||
120 | } | ||
121 | buffer_append(reply, (char *) buf, l); | ||
122 | len -= l; | ||
123 | } | ||
124 | return 1; | ||
125 | } | ||
126 | |||
68 | /* | 127 | /* |
69 | * Closes the agent socket if it should be closed (depends on how it was | 128 | * Closes the agent socket if it should be closed (depends on how it was |
70 | * obtained). The argument must have been returned by | 129 | * obtained). The argument must have been returned by |
@@ -133,62 +192,35 @@ ssh_close_authentication_connection(AuthenticationConnection *ac) | |||
133 | 192 | ||
134 | int | 193 | int |
135 | ssh_get_first_identity(AuthenticationConnection *auth, | 194 | ssh_get_first_identity(AuthenticationConnection *auth, |
136 | BIGNUM *e, BIGNUM *n, char **comment) | 195 | BIGNUM *e, BIGNUM *n, char **comment) |
137 | { | 196 | { |
138 | unsigned char msg[8192]; | 197 | Buffer request; |
139 | int len, l; | 198 | int type; |
140 | 199 | ||
141 | /* | 200 | /* |
142 | * Send a message to the agent requesting for a list of the | 201 | * Send a message to the agent requesting for a list of the |
143 | * identities it can represent. | 202 | * identities it can represent. |
144 | */ | 203 | */ |
145 | PUT_32BIT(msg, 1); | 204 | buffer_init(&request); |
146 | msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES; | 205 | buffer_put_char(&request, SSH_AGENTC_REQUEST_RSA_IDENTITIES); |
147 | if (atomicio(write, auth->fd, msg, 5) != 5) { | ||
148 | error("write auth->fd: %.100s", strerror(errno)); | ||
149 | return 0; | ||
150 | } | ||
151 | /* Read the length of the response. XXX implement timeouts here. */ | ||
152 | len = 4; | ||
153 | while (len > 0) { | ||
154 | l = read(auth->fd, msg + 4 - len, len); | ||
155 | if (l <= 0) { | ||
156 | error("read auth->fd: %.100s", strerror(errno)); | ||
157 | return 0; | ||
158 | } | ||
159 | len -= l; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * Extract the length, and check it for sanity. (We cannot trust | ||
164 | * authentication agents). | ||
165 | */ | ||
166 | len = GET_32BIT(msg); | ||
167 | if (len < 1 || len > 256 * 1024) | ||
168 | fatal("Authentication reply message too long: %d\n", len); | ||
169 | 206 | ||
170 | /* Read the packet itself. */ | ||
171 | buffer_clear(&auth->identities); | 207 | buffer_clear(&auth->identities); |
172 | while (len > 0) { | 208 | if (ssh_request_reply(auth, &request, &auth->identities) == 0) { |
173 | l = len; | 209 | buffer_free(&request); |
174 | if (l > sizeof(msg)) | 210 | return 0; |
175 | l = sizeof(msg); | ||
176 | l = read(auth->fd, msg, l); | ||
177 | if (l <= 0) | ||
178 | fatal("Incomplete authentication reply."); | ||
179 | buffer_append(&auth->identities, (char *) msg, l); | ||
180 | len -= l; | ||
181 | } | 211 | } |
212 | buffer_free(&request); | ||
182 | 213 | ||
183 | /* Get message type, and verify that we got a proper answer. */ | 214 | /* Get message type, and verify that we got a proper answer. */ |
184 | buffer_get(&auth->identities, (char *) msg, 1); | 215 | type = buffer_get_char(&auth->identities); |
185 | if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER) | 216 | if (type != SSH_AGENT_RSA_IDENTITIES_ANSWER) |
186 | fatal("Bad authentication reply message type: %d", msg[0]); | 217 | fatal("Bad authentication reply message type: %d", type); |
187 | 218 | ||
188 | /* Get the number of entries in the response and check it for sanity. */ | 219 | /* Get the number of entries in the response and check it for sanity. */ |
189 | auth->howmany = buffer_get_int(&auth->identities); | 220 | auth->howmany = buffer_get_int(&auth->identities); |
190 | if (auth->howmany > 1024) | 221 | if (auth->howmany > 1024) |
191 | fatal("Too many identities in authentication reply: %d\n", auth->howmany); | 222 | fatal("Too many identities in authentication reply: %d\n", |
223 | auth->howmany); | ||
192 | 224 | ||
193 | /* Return the first entry (if any). */ | 225 | /* Return the first entry (if any). */ |
194 | return ssh_get_next_identity(auth, e, n, comment); | 226 | return ssh_get_next_identity(auth, e, n, comment); |
@@ -203,7 +235,7 @@ ssh_get_first_identity(AuthenticationConnection *auth, | |||
203 | 235 | ||
204 | int | 236 | int |
205 | ssh_get_next_identity(AuthenticationConnection *auth, | 237 | ssh_get_next_identity(AuthenticationConnection *auth, |
206 | BIGNUM *e, BIGNUM *n, char **comment) | 238 | BIGNUM *e, BIGNUM *n, char **comment) |
207 | { | 239 | { |
208 | unsigned int bits; | 240 | unsigned int bits; |
209 | 241 | ||
@@ -240,23 +272,22 @@ ssh_get_next_identity(AuthenticationConnection *auth, | |||
240 | 272 | ||
241 | int | 273 | int |
242 | ssh_decrypt_challenge(AuthenticationConnection *auth, | 274 | ssh_decrypt_challenge(AuthenticationConnection *auth, |
243 | BIGNUM* e, BIGNUM *n, BIGNUM *challenge, | 275 | BIGNUM* e, BIGNUM *n, BIGNUM *challenge, |
244 | unsigned char session_id[16], | 276 | unsigned char session_id[16], |
245 | unsigned int response_type, | 277 | unsigned int response_type, |
246 | unsigned char response[16]) | 278 | unsigned char response[16]) |
247 | { | 279 | { |
248 | Buffer buffer; | 280 | Buffer buffer; |
249 | unsigned char buf[8192]; | 281 | int success = 0; |
250 | int len, l, i; | 282 | int i; |
283 | int type; | ||
251 | 284 | ||
252 | /* Response type 0 is no longer supported. */ | ||
253 | if (response_type == 0) | 285 | if (response_type == 0) |
254 | fatal("Compatibility with ssh protocol version 1.0 no longer supported."); | 286 | fatal("Compatibility with ssh protocol version " |
287 | "1.0 no longer supported."); | ||
255 | 288 | ||
256 | /* Format a message to the agent. */ | ||
257 | buf[0] = SSH_AGENTC_RSA_CHALLENGE; | ||
258 | buffer_init(&buffer); | 289 | buffer_init(&buffer); |
259 | buffer_append(&buffer, (char *) buf, 1); | 290 | buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE); |
260 | buffer_put_int(&buffer, BN_num_bits(n)); | 291 | buffer_put_int(&buffer, BN_num_bits(n)); |
261 | buffer_put_bignum(&buffer, e); | 292 | buffer_put_bignum(&buffer, e); |
262 | buffer_put_bignum(&buffer, n); | 293 | buffer_put_bignum(&buffer, n); |
@@ -264,77 +295,27 @@ ssh_decrypt_challenge(AuthenticationConnection *auth, | |||
264 | buffer_append(&buffer, (char *) session_id, 16); | 295 | buffer_append(&buffer, (char *) session_id, 16); |
265 | buffer_put_int(&buffer, response_type); | 296 | buffer_put_int(&buffer, response_type); |
266 | 297 | ||
267 | /* Get the length of the message, and format it in the buffer. */ | 298 | if (ssh_request_reply(auth, &buffer, &buffer) == 0) { |
268 | len = buffer_len(&buffer); | ||
269 | PUT_32BIT(buf, len); | ||
270 | |||
271 | /* Send the length and then the packet to the agent. */ | ||
272 | if (atomicio(write, auth->fd, buf, 4) != 4 || | ||
273 | atomicio(write, auth->fd, buffer_ptr(&buffer), | ||
274 | buffer_len(&buffer)) != buffer_len(&buffer)) { | ||
275 | error("Error writing to authentication socket."); | ||
276 | error_cleanup: | ||
277 | buffer_free(&buffer); | 299 | buffer_free(&buffer); |
278 | return 0; | 300 | return 0; |
279 | } | 301 | } |
280 | /* | 302 | type = buffer_get_char(&buffer); |
281 | * Wait for response from the agent. First read the length of the | ||
282 | * response packet. | ||
283 | */ | ||
284 | len = 4; | ||
285 | while (len > 0) { | ||
286 | l = read(auth->fd, buf + 4 - len, len); | ||
287 | if (l <= 0) { | ||
288 | error("Error reading response length from authentication socket."); | ||
289 | goto error_cleanup; | ||
290 | } | ||
291 | len -= l; | ||
292 | } | ||
293 | |||
294 | /* Extract the length, and check it for sanity. */ | ||
295 | len = GET_32BIT(buf); | ||
296 | if (len > 256 * 1024) | ||
297 | fatal("Authentication response too long: %d", len); | ||
298 | |||
299 | /* Read the rest of the response in tothe buffer. */ | ||
300 | buffer_clear(&buffer); | ||
301 | while (len > 0) { | ||
302 | l = len; | ||
303 | if (l > sizeof(buf)) | ||
304 | l = sizeof(buf); | ||
305 | l = read(auth->fd, buf, l); | ||
306 | if (l <= 0) { | ||
307 | error("Error reading response from authentication socket."); | ||
308 | goto error_cleanup; | ||
309 | } | ||
310 | buffer_append(&buffer, (char *) buf, l); | ||
311 | len -= l; | ||
312 | } | ||
313 | |||
314 | /* Get the type of the packet. */ | ||
315 | buffer_get(&buffer, (char *) buf, 1); | ||
316 | 303 | ||
317 | /* Check for agent failure message. */ | 304 | if (type == SSH_AGENT_FAILURE) { |
318 | if (buf[0] == SSH_AGENT_FAILURE) { | ||
319 | log("Agent admitted failure to authenticate using the key."); | 305 | log("Agent admitted failure to authenticate using the key."); |
320 | goto error_cleanup; | 306 | } else if (type != SSH_AGENT_RSA_RESPONSE) { |
307 | fatal("Bad authentication response: %d", type); | ||
308 | } else { | ||
309 | success = 1; | ||
310 | /* | ||
311 | * Get the response from the packet. This will abort with a | ||
312 | * fatal error if the packet is corrupt. | ||
313 | */ | ||
314 | for (i = 0; i < 16; i++) | ||
315 | response[i] = buffer_get_char(&buffer); | ||
321 | } | 316 | } |
322 | /* Now it must be an authentication response packet. */ | ||
323 | if (buf[0] != SSH_AGENT_RSA_RESPONSE) | ||
324 | fatal("Bad authentication response: %d", buf[0]); | ||
325 | |||
326 | /* | ||
327 | * Get the response from the packet. This will abort with a fatal | ||
328 | * error if the packet is corrupt. | ||
329 | */ | ||
330 | for (i = 0; i < 16; i++) | ||
331 | response[i] = buffer_get_char(&buffer); | ||
332 | |||
333 | /* The buffer containing the packet is no longer needed. */ | ||
334 | buffer_free(&buffer); | 317 | buffer_free(&buffer); |
335 | 318 | return success; | |
336 | /* Correct answer. */ | ||
337 | return 1; | ||
338 | } | 319 | } |
339 | 320 | ||
340 | /* Encode key for a message to the agent. */ | 321 | /* Encode key for a message to the agent. */ |
@@ -378,8 +359,7 @@ int | |||
378 | ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) | 359 | ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) |
379 | { | 360 | { |
380 | Buffer buffer; | 361 | Buffer buffer; |
381 | unsigned char buf[8192]; | 362 | int type; |
382 | int len; | ||
383 | 363 | ||
384 | buffer_init(&buffer); | 364 | buffer_init(&buffer); |
385 | 365 | ||
@@ -395,21 +375,13 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) | |||
395 | return 0; | 375 | return 0; |
396 | break; | 376 | break; |
397 | } | 377 | } |
398 | 378 | if (ssh_request_reply(auth, &buffer, &buffer) == 0) { | |
399 | /* Get the length of the message, and format it in the buffer. */ | ||
400 | len = buffer_len(&buffer); | ||
401 | PUT_32BIT(buf, len); | ||
402 | |||
403 | /* Send the length and then the packet to the agent. */ | ||
404 | if (atomicio(write, auth->fd, buf, 4) != 4 || | ||
405 | atomicio(write, auth->fd, buffer_ptr(&buffer), | ||
406 | buffer_len(&buffer)) != buffer_len(&buffer)) { | ||
407 | error("Error writing to authentication socket."); | ||
408 | buffer_free(&buffer); | 379 | buffer_free(&buffer); |
409 | return 0; | 380 | return 0; |
410 | } | 381 | } |
382 | type = buffer_get_char(&buffer); | ||
411 | buffer_free(&buffer); | 383 | buffer_free(&buffer); |
412 | return ssh_agent_get_reply(auth); | 384 | return decode_reply(type); |
413 | } | 385 | } |
414 | 386 | ||
415 | /* | 387 | /* |
@@ -421,30 +393,21 @@ int | |||
421 | ssh_remove_identity(AuthenticationConnection *auth, RSA *key) | 393 | ssh_remove_identity(AuthenticationConnection *auth, RSA *key) |
422 | { | 394 | { |
423 | Buffer buffer; | 395 | Buffer buffer; |
424 | unsigned char buf[5]; | 396 | int type; |
425 | int len; | ||
426 | 397 | ||
427 | /* Format a message to the agent. */ | ||
428 | buffer_init(&buffer); | 398 | buffer_init(&buffer); |
429 | buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY); | 399 | buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY); |
430 | buffer_put_int(&buffer, BN_num_bits(key->n)); | 400 | buffer_put_int(&buffer, BN_num_bits(key->n)); |
431 | buffer_put_bignum(&buffer, key->e); | 401 | buffer_put_bignum(&buffer, key->e); |
432 | buffer_put_bignum(&buffer, key->n); | 402 | buffer_put_bignum(&buffer, key->n); |
433 | 403 | ||
434 | /* Get the length of the message, and format it in the buffer. */ | 404 | if (ssh_request_reply(auth, &buffer, &buffer) == 0) { |
435 | len = buffer_len(&buffer); | ||
436 | PUT_32BIT(buf, len); | ||
437 | |||
438 | /* Send the length and then the packet to the agent. */ | ||
439 | if (atomicio(write, auth->fd, buf, 4) != 4 || | ||
440 | atomicio(write, auth->fd, buffer_ptr(&buffer), | ||
441 | buffer_len(&buffer)) != buffer_len(&buffer)) { | ||
442 | error("Error writing to authentication socket."); | ||
443 | buffer_free(&buffer); | 405 | buffer_free(&buffer); |
444 | return 0; | 406 | return 0; |
445 | } | 407 | } |
408 | type = buffer_get_char(&buffer); | ||
446 | buffer_free(&buffer); | 409 | buffer_free(&buffer); |
447 | return ssh_agent_get_reply(auth); | 410 | return decode_reply(type); |
448 | } | 411 | } |
449 | 412 | ||
450 | /* | 413 | /* |
@@ -455,73 +418,27 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key) | |||
455 | int | 418 | int |
456 | ssh_remove_all_identities(AuthenticationConnection *auth) | 419 | ssh_remove_all_identities(AuthenticationConnection *auth) |
457 | { | 420 | { |
458 | unsigned char buf[5]; | 421 | Buffer buffer; |
422 | int type; | ||
459 | 423 | ||
460 | /* Get the length of the message, and format it in the buffer. */ | 424 | buffer_init(&buffer); |
461 | PUT_32BIT(buf, 1); | 425 | buffer_put_char(&buffer, SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES); |
462 | buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES; | ||
463 | 426 | ||
464 | /* Send the length and then the packet to the agent. */ | 427 | if (ssh_request_reply(auth, &buffer, &buffer) == 0) { |
465 | if (atomicio(write, auth->fd, buf, 5) != 5) { | 428 | buffer_free(&buffer); |
466 | error("Error writing to authentication socket."); | ||
467 | return 0; | 429 | return 0; |
468 | } | 430 | } |
469 | return ssh_agent_get_reply(auth); | 431 | type = buffer_get_char(&buffer); |
432 | buffer_free(&buffer); | ||
433 | return decode_reply(type); | ||
470 | } | 434 | } |
471 | 435 | ||
472 | /* | ||
473 | * Read for reply from agent. returns 1 for success, 0 on error | ||
474 | */ | ||
475 | |||
476 | int | 436 | int |
477 | ssh_agent_get_reply(AuthenticationConnection *auth) | 437 | decode_reply(int type) |
478 | { | 438 | { |
479 | Buffer buffer; | ||
480 | unsigned char buf[8192]; | ||
481 | int len, l, type; | ||
482 | |||
483 | /* | ||
484 | * Wait for response from the agent. First read the length of the | ||
485 | * response packet. | ||
486 | */ | ||
487 | len = 4; | ||
488 | while (len > 0) { | ||
489 | l = read(auth->fd, buf + 4 - len, len); | ||
490 | if (l <= 0) { | ||
491 | error("Error reading response length from authentication socket."); | ||
492 | buffer_free(&buffer); | ||
493 | return 0; | ||
494 | } | ||
495 | len -= l; | ||
496 | } | ||
497 | |||
498 | /* Extract the length, and check it for sanity. */ | ||
499 | len = GET_32BIT(buf); | ||
500 | if (len > 256 * 1024) | ||
501 | fatal("Response from agent too long: %d", len); | ||
502 | |||
503 | /* Read the rest of the response in to the buffer. */ | ||
504 | buffer_init(&buffer); | ||
505 | while (len > 0) { | ||
506 | l = len; | ||
507 | if (l > sizeof(buf)) | ||
508 | l = sizeof(buf); | ||
509 | l = read(auth->fd, buf, l); | ||
510 | if (l <= 0) { | ||
511 | error("Error reading response from authentication socket."); | ||
512 | buffer_free(&buffer); | ||
513 | return 0; | ||
514 | } | ||
515 | buffer_append(&buffer, (char *) buf, l); | ||
516 | len -= l; | ||
517 | } | ||
518 | |||
519 | /* Get the type of the packet. */ | ||
520 | type = buffer_get_char(&buffer); | ||
521 | buffer_free(&buffer); | ||
522 | switch (type) { | 439 | switch (type) { |
523 | case SSH_AGENT_FAILURE: | 440 | case SSH_AGENT_FAILURE: |
524 | log("SSH_AGENT_FAILURE"); | 441 | log("SSH_AGENT_FAILURE"); |
525 | return 0; | 442 | return 0; |
526 | case SSH_AGENT_SUCCESS: | 443 | case SSH_AGENT_SUCCESS: |
527 | return 1; | 444 | return 1; |