diff options
Diffstat (limited to 'ssh-agent.c')
-rw-r--r-- | ssh-agent.c | 561 |
1 files changed, 339 insertions, 222 deletions
diff --git a/ssh-agent.c b/ssh-agent.c index 25f10c549..aeda656ac 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.190 2014/07/25 21:22:03 dtucker Exp $ */ | 1 | /* $OpenBSD: ssh-agent.c,v 1.199 2015/03/04 21:12:59 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -36,6 +36,7 @@ | |||
36 | 36 | ||
37 | #include "includes.h" | 37 | #include "includes.h" |
38 | 38 | ||
39 | #include <sys/param.h> /* MIN MAX */ | ||
39 | #include <sys/types.h> | 40 | #include <sys/types.h> |
40 | #include <sys/param.h> | 41 | #include <sys/param.h> |
41 | #include <sys/resource.h> | 42 | #include <sys/resource.h> |
@@ -56,6 +57,7 @@ | |||
56 | 57 | ||
57 | #include <errno.h> | 58 | #include <errno.h> |
58 | #include <fcntl.h> | 59 | #include <fcntl.h> |
60 | #include <limits.h> | ||
59 | #ifdef HAVE_PATHS_H | 61 | #ifdef HAVE_PATHS_H |
60 | # include <paths.h> | 62 | # include <paths.h> |
61 | #endif | 63 | #endif |
@@ -67,16 +69,20 @@ | |||
67 | #include <string.h> | 69 | #include <string.h> |
68 | #include <unistd.h> | 70 | #include <unistd.h> |
69 | 71 | ||
72 | #include "key.h" /* XXX for typedef */ | ||
73 | #include "buffer.h" /* XXX for typedef */ | ||
74 | |||
70 | #include "xmalloc.h" | 75 | #include "xmalloc.h" |
71 | #include "ssh.h" | 76 | #include "ssh.h" |
72 | #include "rsa.h" | 77 | #include "rsa.h" |
73 | #include "buffer.h" | 78 | #include "sshbuf.h" |
74 | #include "key.h" | 79 | #include "sshkey.h" |
75 | #include "authfd.h" | 80 | #include "authfd.h" |
76 | #include "compat.h" | 81 | #include "compat.h" |
77 | #include "log.h" | 82 | #include "log.h" |
78 | #include "misc.h" | 83 | #include "misc.h" |
79 | #include "digest.h" | 84 | #include "digest.h" |
85 | #include "ssherr.h" | ||
80 | 86 | ||
81 | #ifdef ENABLE_PKCS11 | 87 | #ifdef ENABLE_PKCS11 |
82 | #include "ssh-pkcs11.h" | 88 | #include "ssh-pkcs11.h" |
@@ -95,9 +101,9 @@ typedef enum { | |||
95 | typedef struct { | 101 | typedef struct { |
96 | int fd; | 102 | int fd; |
97 | sock_type type; | 103 | sock_type type; |
98 | Buffer input; | 104 | struct sshbuf *input; |
99 | Buffer output; | 105 | struct sshbuf *output; |
100 | Buffer request; | 106 | struct sshbuf *request; |
101 | } SocketEntry; | 107 | } SocketEntry; |
102 | 108 | ||
103 | u_int sockets_alloc = 0; | 109 | u_int sockets_alloc = 0; |
@@ -105,7 +111,7 @@ SocketEntry *sockets = NULL; | |||
105 | 111 | ||
106 | typedef struct identity { | 112 | typedef struct identity { |
107 | TAILQ_ENTRY(identity) next; | 113 | TAILQ_ENTRY(identity) next; |
108 | Key *key; | 114 | struct sshkey *key; |
109 | char *comment; | 115 | char *comment; |
110 | char *provider; | 116 | char *provider; |
111 | time_t death; | 117 | time_t death; |
@@ -130,8 +136,8 @@ time_t parent_alive_interval = 0; | |||
130 | pid_t cleanup_pid = 0; | 136 | pid_t cleanup_pid = 0; |
131 | 137 | ||
132 | /* pathname and directory for AUTH_SOCKET */ | 138 | /* pathname and directory for AUTH_SOCKET */ |
133 | char socket_name[MAXPATHLEN]; | 139 | char socket_name[PATH_MAX]; |
134 | char socket_dir[MAXPATHLEN]; | 140 | char socket_dir[PATH_MAX]; |
135 | 141 | ||
136 | /* locking */ | 142 | /* locking */ |
137 | int locked = 0; | 143 | int locked = 0; |
@@ -142,15 +148,17 @@ extern char *__progname; | |||
142 | /* Default lifetime in seconds (0 == forever) */ | 148 | /* Default lifetime in seconds (0 == forever) */ |
143 | static long lifetime = 0; | 149 | static long lifetime = 0; |
144 | 150 | ||
151 | static int fingerprint_hash = SSH_FP_HASH_DEFAULT; | ||
152 | |||
145 | static void | 153 | static void |
146 | close_socket(SocketEntry *e) | 154 | close_socket(SocketEntry *e) |
147 | { | 155 | { |
148 | close(e->fd); | 156 | close(e->fd); |
149 | e->fd = -1; | 157 | e->fd = -1; |
150 | e->type = AUTH_UNUSED; | 158 | e->type = AUTH_UNUSED; |
151 | buffer_free(&e->input); | 159 | sshbuf_free(e->input); |
152 | buffer_free(&e->output); | 160 | sshbuf_free(e->output); |
153 | buffer_free(&e->request); | 161 | sshbuf_free(e->request); |
154 | } | 162 | } |
155 | 163 | ||
156 | static void | 164 | static void |
@@ -176,7 +184,7 @@ idtab_lookup(int version) | |||
176 | static void | 184 | static void |
177 | free_identity(Identity *id) | 185 | free_identity(Identity *id) |
178 | { | 186 | { |
179 | key_free(id->key); | 187 | sshkey_free(id->key); |
180 | free(id->provider); | 188 | free(id->provider); |
181 | free(id->comment); | 189 | free(id->comment); |
182 | free(id); | 190 | free(id); |
@@ -184,13 +192,13 @@ free_identity(Identity *id) | |||
184 | 192 | ||
185 | /* return matching private key for given public key */ | 193 | /* return matching private key for given public key */ |
186 | static Identity * | 194 | static Identity * |
187 | lookup_identity(Key *key, int version) | 195 | lookup_identity(struct sshkey *key, int version) |
188 | { | 196 | { |
189 | Identity *id; | 197 | Identity *id; |
190 | 198 | ||
191 | Idtab *tab = idtab_lookup(version); | 199 | Idtab *tab = idtab_lookup(version); |
192 | TAILQ_FOREACH(id, &tab->idlist, next) { | 200 | TAILQ_FOREACH(id, &tab->idlist, next) { |
193 | if (key_equal(key, id->key)) | 201 | if (sshkey_equal(key, id->key)) |
194 | return (id); | 202 | return (id); |
195 | } | 203 | } |
196 | return (NULL); | 204 | return (NULL); |
@@ -203,8 +211,9 @@ confirm_key(Identity *id) | |||
203 | char *p; | 211 | char *p; |
204 | int ret = -1; | 212 | int ret = -1; |
205 | 213 | ||
206 | p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); | 214 | p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT); |
207 | if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", | 215 | if (p != NULL && |
216 | ask_permission("Allow use of key %s?\nKey fingerprint %s.", | ||
208 | id->comment, p)) | 217 | id->comment, p)) |
209 | ret = 0; | 218 | ret = 0; |
210 | free(p); | 219 | free(p); |
@@ -212,37 +221,65 @@ confirm_key(Identity *id) | |||
212 | return (ret); | 221 | return (ret); |
213 | } | 222 | } |
214 | 223 | ||
224 | static void | ||
225 | send_status(SocketEntry *e, int success) | ||
226 | { | ||
227 | int r; | ||
228 | |||
229 | if ((r = sshbuf_put_u32(e->output, 1)) != 0 || | ||
230 | (r = sshbuf_put_u8(e->output, success ? | ||
231 | SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0) | ||
232 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
233 | } | ||
234 | |||
215 | /* send list of supported public keys to 'client' */ | 235 | /* send list of supported public keys to 'client' */ |
216 | static void | 236 | static void |
217 | process_request_identities(SocketEntry *e, int version) | 237 | process_request_identities(SocketEntry *e, int version) |
218 | { | 238 | { |
219 | Idtab *tab = idtab_lookup(version); | 239 | Idtab *tab = idtab_lookup(version); |
220 | Identity *id; | 240 | Identity *id; |
221 | Buffer msg; | 241 | struct sshbuf *msg; |
222 | 242 | int r; | |
223 | buffer_init(&msg); | 243 | |
224 | buffer_put_char(&msg, (version == 1) ? | 244 | if ((msg = sshbuf_new()) == NULL) |
225 | SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); | 245 | fatal("%s: sshbuf_new failed", __func__); |
226 | buffer_put_int(&msg, tab->nentries); | 246 | if ((r = sshbuf_put_u8(msg, (version == 1) ? |
247 | SSH_AGENT_RSA_IDENTITIES_ANSWER : | ||
248 | SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || | ||
249 | (r = sshbuf_put_u32(msg, tab->nentries)) != 0) | ||
250 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
227 | TAILQ_FOREACH(id, &tab->idlist, next) { | 251 | TAILQ_FOREACH(id, &tab->idlist, next) { |
228 | if (id->key->type == KEY_RSA1) { | 252 | if (id->key->type == KEY_RSA1) { |
229 | #ifdef WITH_SSH1 | 253 | #ifdef WITH_SSH1 |
230 | buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); | 254 | if ((r = sshbuf_put_u32(msg, |
231 | buffer_put_bignum(&msg, id->key->rsa->e); | 255 | BN_num_bits(id->key->rsa->n))) != 0 || |
232 | buffer_put_bignum(&msg, id->key->rsa->n); | 256 | (r = sshbuf_put_bignum1(msg, |
257 | id->key->rsa->e)) != 0 || | ||
258 | (r = sshbuf_put_bignum1(msg, | ||
259 | id->key->rsa->n)) != 0) | ||
260 | fatal("%s: buffer error: %s", | ||
261 | __func__, ssh_err(r)); | ||
233 | #endif | 262 | #endif |
234 | } else { | 263 | } else { |
235 | u_char *blob; | 264 | u_char *blob; |
236 | u_int blen; | 265 | size_t blen; |
237 | key_to_blob(id->key, &blob, &blen); | 266 | |
238 | buffer_put_string(&msg, blob, blen); | 267 | if ((r = sshkey_to_blob(id->key, &blob, &blen)) != 0) { |
268 | error("%s: sshkey_to_blob: %s", __func__, | ||
269 | ssh_err(r)); | ||
270 | continue; | ||
271 | } | ||
272 | if ((r = sshbuf_put_string(msg, blob, blen)) != 0) | ||
273 | fatal("%s: buffer error: %s", | ||
274 | __func__, ssh_err(r)); | ||
239 | free(blob); | 275 | free(blob); |
240 | } | 276 | } |
241 | buffer_put_cstring(&msg, id->comment); | 277 | if ((r = sshbuf_put_cstring(msg, id->comment)) != 0) |
278 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
242 | } | 279 | } |
243 | buffer_put_int(&e->output, buffer_len(&msg)); | 280 | if ((r = sshbuf_put_stringb(e->output, msg)) != 0) |
244 | buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); | 281 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
245 | buffer_free(&msg); | 282 | sshbuf_free(msg); |
246 | } | 283 | } |
247 | 284 | ||
248 | #ifdef WITH_SSH1 | 285 | #ifdef WITH_SSH1 |
@@ -254,40 +291,48 @@ process_authentication_challenge1(SocketEntry *e) | |||
254 | u_int response_type; | 291 | u_int response_type; |
255 | BIGNUM *challenge; | 292 | BIGNUM *challenge; |
256 | Identity *id; | 293 | Identity *id; |
257 | int i, len; | 294 | int r, len; |
258 | Buffer msg; | 295 | struct sshbuf *msg; |
259 | struct ssh_digest_ctx *md; | 296 | struct ssh_digest_ctx *md; |
260 | Key *key; | 297 | struct sshkey *key; |
261 | 298 | ||
262 | buffer_init(&msg); | 299 | if ((msg = sshbuf_new()) == NULL) |
263 | key = key_new(KEY_RSA1); | 300 | fatal("%s: sshbuf_new failed", __func__); |
301 | if ((key = sshkey_new(KEY_RSA1)) == NULL) | ||
302 | fatal("%s: sshkey_new failed", __func__); | ||
264 | if ((challenge = BN_new()) == NULL) | 303 | if ((challenge = BN_new()) == NULL) |
265 | fatal("process_authentication_challenge1: BN_new failed"); | 304 | fatal("%s: BN_new failed", __func__); |
266 | 305 | ||
267 | (void) buffer_get_int(&e->request); /* ignored */ | 306 | if ((r = sshbuf_get_u32(e->request, NULL)) != 0 || /* ignored */ |
268 | buffer_get_bignum(&e->request, key->rsa->e); | 307 | (r = sshbuf_get_bignum1(e->request, key->rsa->e)) != 0 || |
269 | buffer_get_bignum(&e->request, key->rsa->n); | 308 | (r = sshbuf_get_bignum1(e->request, key->rsa->n)) != 0 || |
270 | buffer_get_bignum(&e->request, challenge); | 309 | (r = sshbuf_get_bignum1(e->request, challenge))) |
310 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
271 | 311 | ||
272 | /* Only protocol 1.1 is supported */ | 312 | /* Only protocol 1.1 is supported */ |
273 | if (buffer_len(&e->request) == 0) | 313 | if (sshbuf_len(e->request) == 0) |
274 | goto failure; | 314 | goto failure; |
275 | buffer_get(&e->request, session_id, 16); | 315 | if ((r = sshbuf_get(e->request, session_id, sizeof(session_id))) != 0 || |
276 | response_type = buffer_get_int(&e->request); | 316 | (r = sshbuf_get_u32(e->request, &response_type)) != 0) |
317 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
277 | if (response_type != 1) | 318 | if (response_type != 1) |
278 | goto failure; | 319 | goto failure; |
279 | 320 | ||
280 | id = lookup_identity(key, 1); | 321 | id = lookup_identity(key, 1); |
281 | if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { | 322 | if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { |
282 | Key *private = id->key; | 323 | struct sshkey *private = id->key; |
283 | /* Decrypt the challenge using the private key. */ | 324 | /* Decrypt the challenge using the private key. */ |
284 | if (rsa_private_decrypt(challenge, challenge, private->rsa) != 0) | 325 | if ((r = rsa_private_decrypt(challenge, challenge, |
285 | goto failure; | 326 | private->rsa) != 0)) { |
327 | fatal("%s: rsa_public_encrypt: %s", __func__, | ||
328 | ssh_err(r)); | ||
329 | goto failure; /* XXX ? */ | ||
330 | } | ||
286 | 331 | ||
287 | /* The response is MD5 of decrypted challenge plus session id. */ | 332 | /* The response is MD5 of decrypted challenge plus session id */ |
288 | len = BN_num_bytes(challenge); | 333 | len = BN_num_bytes(challenge); |
289 | if (len <= 0 || len > 32) { | 334 | if (len <= 0 || len > 32) { |
290 | logit("process_authentication_challenge: bad challenge length %d", len); | 335 | logit("%s: bad challenge length %d", __func__, len); |
291 | goto failure; | 336 | goto failure; |
292 | } | 337 | } |
293 | memset(buf, 0, 32); | 338 | memset(buf, 0, 32); |
@@ -300,21 +345,22 @@ process_authentication_challenge1(SocketEntry *e) | |||
300 | ssh_digest_free(md); | 345 | ssh_digest_free(md); |
301 | 346 | ||
302 | /* Send the response. */ | 347 | /* Send the response. */ |
303 | buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE); | 348 | if ((r = sshbuf_put_u8(msg, SSH_AGENT_RSA_RESPONSE)) != 0 || |
304 | for (i = 0; i < 16; i++) | 349 | (r = sshbuf_put(msg, mdbuf, sizeof(mdbuf))) != 0) |
305 | buffer_put_char(&msg, mdbuf[i]); | 350 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
306 | goto send; | 351 | goto send; |
307 | } | 352 | } |
308 | 353 | ||
309 | failure: | 354 | failure: |
310 | /* Unknown identity or protocol error. Send failure. */ | 355 | /* Unknown identity or protocol error. Send failure. */ |
311 | buffer_put_char(&msg, SSH_AGENT_FAILURE); | 356 | if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) |
312 | send: | 357 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
313 | buffer_put_int(&e->output, buffer_len(&msg)); | 358 | send: |
314 | buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); | 359 | if ((r = sshbuf_put_stringb(e->output, msg)) != 0) |
315 | key_free(key); | 360 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
361 | sshkey_free(key); | ||
316 | BN_clear_free(challenge); | 362 | BN_clear_free(challenge); |
317 | buffer_free(&msg); | 363 | sshbuf_free(msg); |
318 | } | 364 | } |
319 | #endif | 365 | #endif |
320 | 366 | ||
@@ -323,54 +369,65 @@ static void | |||
323 | process_sign_request2(SocketEntry *e) | 369 | process_sign_request2(SocketEntry *e) |
324 | { | 370 | { |
325 | u_char *blob, *data, *signature = NULL; | 371 | u_char *blob, *data, *signature = NULL; |
326 | u_int blen, dlen, slen = 0; | 372 | size_t blen, dlen, slen = 0; |
327 | extern int datafellows; | 373 | u_int compat = 0, flags; |
328 | int odatafellows; | 374 | int r, ok = -1; |
329 | int ok = -1, flags; | 375 | struct sshbuf *msg; |
330 | Buffer msg; | 376 | struct sshkey *key; |
331 | Key *key; | 377 | struct identity *id; |
332 | 378 | ||
333 | datafellows = 0; | 379 | if ((msg = sshbuf_new()) == NULL) |
334 | 380 | fatal("%s: sshbuf_new failed", __func__); | |
335 | blob = buffer_get_string(&e->request, &blen); | 381 | if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0 || |
336 | data = buffer_get_string(&e->request, &dlen); | 382 | (r = sshbuf_get_string(e->request, &data, &dlen)) != 0 || |
337 | 383 | (r = sshbuf_get_u32(e->request, &flags)) != 0) | |
338 | flags = buffer_get_int(&e->request); | 384 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
339 | odatafellows = datafellows; | ||
340 | if (flags & SSH_AGENT_OLD_SIGNATURE) | 385 | if (flags & SSH_AGENT_OLD_SIGNATURE) |
341 | datafellows = SSH_BUG_SIGBLOB; | 386 | compat = SSH_BUG_SIGBLOB; |
342 | 387 | if ((r = sshkey_from_blob(blob, blen, &key)) != 0) { | |
343 | key = key_from_blob(blob, blen); | 388 | error("%s: cannot parse key blob: %s", __func__, ssh_err(ok)); |
344 | if (key != NULL) { | 389 | goto send; |
345 | Identity *id = lookup_identity(key, 2); | ||
346 | if (id != NULL && (!id->confirm || confirm_key(id) == 0)) | ||
347 | ok = key_sign(id->key, &signature, &slen, data, dlen); | ||
348 | key_free(key); | ||
349 | } | 390 | } |
350 | buffer_init(&msg); | 391 | if ((id = lookup_identity(key, 2)) == NULL) { |
351 | if (ok == 0) { | 392 | verbose("%s: %s key not found", __func__, sshkey_type(key)); |
352 | buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); | 393 | goto send; |
353 | buffer_put_string(&msg, signature, slen); | ||
354 | } else { | ||
355 | buffer_put_char(&msg, SSH_AGENT_FAILURE); | ||
356 | } | 394 | } |
357 | buffer_put_int(&e->output, buffer_len(&msg)); | 395 | if (id->confirm && confirm_key(id) != 0) { |
358 | buffer_append(&e->output, buffer_ptr(&msg), | 396 | verbose("%s: user refused key", __func__); |
359 | buffer_len(&msg)); | 397 | goto send; |
360 | buffer_free(&msg); | 398 | } |
399 | if ((r = sshkey_sign(id->key, &signature, &slen, | ||
400 | data, dlen, compat)) != 0) { | ||
401 | error("%s: sshkey_sign: %s", __func__, ssh_err(ok)); | ||
402 | goto send; | ||
403 | } | ||
404 | /* Success */ | ||
405 | ok = 0; | ||
406 | send: | ||
407 | sshkey_free(key); | ||
408 | if (ok == 0) { | ||
409 | if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 || | ||
410 | (r = sshbuf_put_string(msg, signature, slen)) != 0) | ||
411 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
412 | } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) | ||
413 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
414 | |||
415 | if ((r = sshbuf_put_stringb(e->output, msg)) != 0) | ||
416 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
417 | |||
418 | sshbuf_free(msg); | ||
361 | free(data); | 419 | free(data); |
362 | free(blob); | 420 | free(blob); |
363 | free(signature); | 421 | free(signature); |
364 | datafellows = odatafellows; | ||
365 | } | 422 | } |
366 | 423 | ||
367 | /* shared */ | 424 | /* shared */ |
368 | static void | 425 | static void |
369 | process_remove_identity(SocketEntry *e, int version) | 426 | process_remove_identity(SocketEntry *e, int version) |
370 | { | 427 | { |
371 | u_int blen; | 428 | size_t blen; |
372 | int success = 0; | 429 | int r, success = 0; |
373 | Key *key = NULL; | 430 | struct sshkey *key = NULL; |
374 | u_char *blob; | 431 | u_char *blob; |
375 | #ifdef WITH_SSH1 | 432 | #ifdef WITH_SSH1 |
376 | u_int bits; | 433 | u_int bits; |
@@ -379,19 +436,27 @@ process_remove_identity(SocketEntry *e, int version) | |||
379 | switch (version) { | 436 | switch (version) { |
380 | #ifdef WITH_SSH1 | 437 | #ifdef WITH_SSH1 |
381 | case 1: | 438 | case 1: |
382 | key = key_new(KEY_RSA1); | 439 | if ((key = sshkey_new(KEY_RSA1)) == NULL) { |
383 | bits = buffer_get_int(&e->request); | 440 | error("%s: sshkey_new failed", __func__); |
384 | buffer_get_bignum(&e->request, key->rsa->e); | 441 | return; |
385 | buffer_get_bignum(&e->request, key->rsa->n); | 442 | } |
386 | 443 | if ((r = sshbuf_get_u32(e->request, &bits)) != 0 || | |
387 | if (bits != key_size(key)) | 444 | (r = sshbuf_get_bignum1(e->request, key->rsa->e)) != 0 || |
388 | logit("Warning: identity keysize mismatch: actual %u, announced %u", | 445 | (r = sshbuf_get_bignum1(e->request, key->rsa->n)) != 0) |
389 | key_size(key), bits); | 446 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
447 | |||
448 | if (bits != sshkey_size(key)) | ||
449 | logit("Warning: identity keysize mismatch: " | ||
450 | "actual %u, announced %u", | ||
451 | sshkey_size(key), bits); | ||
390 | break; | 452 | break; |
391 | #endif /* WITH_SSH1 */ | 453 | #endif /* WITH_SSH1 */ |
392 | case 2: | 454 | case 2: |
393 | blob = buffer_get_string(&e->request, &blen); | 455 | if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0) |
394 | key = key_from_blob(blob, blen); | 456 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
457 | if ((r = sshkey_from_blob(blob, blen, &key)) != 0) | ||
458 | error("%s: sshkey_from_blob failed: %s", | ||
459 | __func__, ssh_err(r)); | ||
395 | free(blob); | 460 | free(blob); |
396 | break; | 461 | break; |
397 | } | 462 | } |
@@ -415,11 +480,9 @@ process_remove_identity(SocketEntry *e, int version) | |||
415 | tab->nentries--; | 480 | tab->nentries--; |
416 | success = 1; | 481 | success = 1; |
417 | } | 482 | } |
418 | key_free(key); | 483 | sshkey_free(key); |
419 | } | 484 | } |
420 | buffer_put_int(&e->output, 1); | 485 | send_status(e, success); |
421 | buffer_put_char(&e->output, | ||
422 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); | ||
423 | } | 486 | } |
424 | 487 | ||
425 | static void | 488 | static void |
@@ -439,8 +502,7 @@ process_remove_all_identities(SocketEntry *e, int version) | |||
439 | tab->nentries = 0; | 502 | tab->nentries = 0; |
440 | 503 | ||
441 | /* Send success. */ | 504 | /* Send success. */ |
442 | buffer_put_int(&e->output, 1); | 505 | send_status(e, 1); |
443 | buffer_put_char(&e->output, SSH_AGENT_SUCCESS); | ||
444 | } | 506 | } |
445 | 507 | ||
446 | /* removes expired keys and returns number of seconds until the next expiry */ | 508 | /* removes expired keys and returns number of seconds until the next expiry */ |
@@ -474,71 +536,106 @@ reaper(void) | |||
474 | return (deadline - now); | 536 | return (deadline - now); |
475 | } | 537 | } |
476 | 538 | ||
539 | /* | ||
540 | * XXX this and the corresponding serialisation function probably belongs | ||
541 | * in key.c | ||
542 | */ | ||
543 | #ifdef WITH_SSH1 | ||
544 | static int | ||
545 | agent_decode_rsa1(struct sshbuf *m, struct sshkey **kp) | ||
546 | { | ||
547 | struct sshkey *k = NULL; | ||
548 | int r = SSH_ERR_INTERNAL_ERROR; | ||
549 | |||
550 | *kp = NULL; | ||
551 | if ((k = sshkey_new_private(KEY_RSA1)) == NULL) | ||
552 | return SSH_ERR_ALLOC_FAIL; | ||
553 | |||
554 | if ((r = sshbuf_get_u32(m, NULL)) != 0 || /* ignored */ | ||
555 | (r = sshbuf_get_bignum1(m, k->rsa->n)) != 0 || | ||
556 | (r = sshbuf_get_bignum1(m, k->rsa->e)) != 0 || | ||
557 | (r = sshbuf_get_bignum1(m, k->rsa->d)) != 0 || | ||
558 | (r = sshbuf_get_bignum1(m, k->rsa->iqmp)) != 0 || | ||
559 | /* SSH1 and SSL have p and q swapped */ | ||
560 | (r = sshbuf_get_bignum1(m, k->rsa->q)) != 0 || /* p */ | ||
561 | (r = sshbuf_get_bignum1(m, k->rsa->p)) != 0) /* q */ | ||
562 | goto out; | ||
563 | |||
564 | /* Generate additional parameters */ | ||
565 | if ((r = rsa_generate_additional_parameters(k->rsa)) != 0) | ||
566 | goto out; | ||
567 | /* enable blinding */ | ||
568 | if (RSA_blinding_on(k->rsa, NULL) != 1) { | ||
569 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
570 | goto out; | ||
571 | } | ||
572 | |||
573 | r = 0; /* success */ | ||
574 | out: | ||
575 | if (r == 0) | ||
576 | *kp = k; | ||
577 | else | ||
578 | sshkey_free(k); | ||
579 | return r; | ||
580 | } | ||
581 | #endif /* WITH_SSH1 */ | ||
582 | |||
477 | static void | 583 | static void |
478 | process_add_identity(SocketEntry *e, int version) | 584 | process_add_identity(SocketEntry *e, int version) |
479 | { | 585 | { |
480 | Idtab *tab = idtab_lookup(version); | 586 | Idtab *tab = idtab_lookup(version); |
481 | Identity *id; | 587 | Identity *id; |
482 | int type, success = 0, confirm = 0; | 588 | int success = 0, confirm = 0; |
483 | char *comment; | 589 | u_int seconds; |
590 | char *comment = NULL; | ||
484 | time_t death = 0; | 591 | time_t death = 0; |
485 | Key *k = NULL; | 592 | struct sshkey *k = NULL; |
593 | u_char ctype; | ||
594 | int r = SSH_ERR_INTERNAL_ERROR; | ||
486 | 595 | ||
487 | switch (version) { | 596 | switch (version) { |
488 | #ifdef WITH_SSH1 | 597 | #ifdef WITH_SSH1 |
489 | case 1: | 598 | case 1: |
490 | k = key_new_private(KEY_RSA1); | 599 | r = agent_decode_rsa1(e->request, &k); |
491 | (void) buffer_get_int(&e->request); /* ignored */ | ||
492 | buffer_get_bignum(&e->request, k->rsa->n); | ||
493 | buffer_get_bignum(&e->request, k->rsa->e); | ||
494 | buffer_get_bignum(&e->request, k->rsa->d); | ||
495 | buffer_get_bignum(&e->request, k->rsa->iqmp); | ||
496 | |||
497 | /* SSH and SSL have p and q swapped */ | ||
498 | buffer_get_bignum(&e->request, k->rsa->q); /* p */ | ||
499 | buffer_get_bignum(&e->request, k->rsa->p); /* q */ | ||
500 | |||
501 | /* Generate additional parameters */ | ||
502 | if (rsa_generate_additional_parameters(k->rsa) != 0) | ||
503 | fatal("%s: rsa_generate_additional_parameters " | ||
504 | "error", __func__); | ||
505 | |||
506 | /* enable blinding */ | ||
507 | if (RSA_blinding_on(k->rsa, NULL) != 1) { | ||
508 | error("process_add_identity: RSA_blinding_on failed"); | ||
509 | key_free(k); | ||
510 | goto send; | ||
511 | } | ||
512 | break; | 600 | break; |
513 | #endif /* WITH_SSH1 */ | 601 | #endif /* WITH_SSH1 */ |
514 | case 2: | 602 | case 2: |
515 | k = key_private_deserialize(&e->request); | 603 | r = sshkey_private_deserialize(e->request, &k); |
516 | if (k == NULL) { | ||
517 | buffer_clear(&e->request); | ||
518 | goto send; | ||
519 | } | ||
520 | break; | 604 | break; |
521 | } | 605 | } |
522 | if (k == NULL) | 606 | if (r != 0 || k == NULL || |
523 | goto send; | 607 | (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { |
524 | comment = buffer_get_string(&e->request, NULL); | 608 | error("%s: decode private key: %s", __func__, ssh_err(r)); |
609 | goto err; | ||
610 | } | ||
525 | 611 | ||
526 | while (buffer_len(&e->request)) { | 612 | while (sshbuf_len(e->request)) { |
527 | switch ((type = buffer_get_char(&e->request))) { | 613 | if ((r = sshbuf_get_u8(e->request, &ctype)) != 0) { |
614 | error("%s: buffer error: %s", __func__, ssh_err(r)); | ||
615 | goto err; | ||
616 | } | ||
617 | switch (ctype) { | ||
528 | case SSH_AGENT_CONSTRAIN_LIFETIME: | 618 | case SSH_AGENT_CONSTRAIN_LIFETIME: |
529 | death = monotime() + buffer_get_int(&e->request); | 619 | if ((r = sshbuf_get_u32(e->request, &seconds)) != 0) { |
620 | error("%s: bad lifetime constraint: %s", | ||
621 | __func__, ssh_err(r)); | ||
622 | goto err; | ||
623 | } | ||
624 | death = monotime() + seconds; | ||
530 | break; | 625 | break; |
531 | case SSH_AGENT_CONSTRAIN_CONFIRM: | 626 | case SSH_AGENT_CONSTRAIN_CONFIRM: |
532 | confirm = 1; | 627 | confirm = 1; |
533 | break; | 628 | break; |
534 | default: | 629 | default: |
535 | error("process_add_identity: " | 630 | error("%s: Unknown constraint %d", __func__, ctype); |
536 | "Unknown constraint type %d", type); | 631 | err: |
632 | sshbuf_reset(e->request); | ||
537 | free(comment); | 633 | free(comment); |
538 | key_free(k); | 634 | sshkey_free(k); |
539 | goto send; | 635 | goto send; |
540 | } | 636 | } |
541 | } | 637 | } |
638 | |||
542 | success = 1; | 639 | success = 1; |
543 | if (lifetime && !death) | 640 | if (lifetime && !death) |
544 | death = monotime() + lifetime; | 641 | death = monotime() + lifetime; |
@@ -549,26 +646,25 @@ process_add_identity(SocketEntry *e, int version) | |||
549 | /* Increment the number of identities. */ | 646 | /* Increment the number of identities. */ |
550 | tab->nentries++; | 647 | tab->nentries++; |
551 | } else { | 648 | } else { |
552 | key_free(k); | 649 | sshkey_free(k); |
553 | free(id->comment); | 650 | free(id->comment); |
554 | } | 651 | } |
555 | id->comment = comment; | 652 | id->comment = comment; |
556 | id->death = death; | 653 | id->death = death; |
557 | id->confirm = confirm; | 654 | id->confirm = confirm; |
558 | send: | 655 | send: |
559 | buffer_put_int(&e->output, 1); | 656 | send_status(e, success); |
560 | buffer_put_char(&e->output, | ||
561 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); | ||
562 | } | 657 | } |
563 | 658 | ||
564 | /* XXX todo: encrypt sensitive data with passphrase */ | 659 | /* XXX todo: encrypt sensitive data with passphrase */ |
565 | static void | 660 | static void |
566 | process_lock_agent(SocketEntry *e, int lock) | 661 | process_lock_agent(SocketEntry *e, int lock) |
567 | { | 662 | { |
568 | int success = 0; | 663 | int r, success = 0; |
569 | char *passwd; | 664 | char *passwd; |
570 | 665 | ||
571 | passwd = buffer_get_string(&e->request, NULL); | 666 | if ((r = sshbuf_get_cstring(e->request, &passwd, NULL)) != 0) |
667 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
572 | if (locked && !lock && strcmp(passwd, lock_passwd) == 0) { | 668 | if (locked && !lock && strcmp(passwd, lock_passwd) == 0) { |
573 | locked = 0; | 669 | locked = 0; |
574 | explicit_bzero(lock_passwd, strlen(lock_passwd)); | 670 | explicit_bzero(lock_passwd, strlen(lock_passwd)); |
@@ -582,25 +678,25 @@ process_lock_agent(SocketEntry *e, int lock) | |||
582 | } | 678 | } |
583 | explicit_bzero(passwd, strlen(passwd)); | 679 | explicit_bzero(passwd, strlen(passwd)); |
584 | free(passwd); | 680 | free(passwd); |
585 | 681 | send_status(e, success); | |
586 | buffer_put_int(&e->output, 1); | ||
587 | buffer_put_char(&e->output, | ||
588 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); | ||
589 | } | 682 | } |
590 | 683 | ||
591 | static void | 684 | static void |
592 | no_identities(SocketEntry *e, u_int type) | 685 | no_identities(SocketEntry *e, u_int type) |
593 | { | 686 | { |
594 | Buffer msg; | 687 | struct sshbuf *msg; |
688 | int r; | ||
595 | 689 | ||
596 | buffer_init(&msg); | 690 | if ((msg = sshbuf_new()) == NULL) |
597 | buffer_put_char(&msg, | 691 | fatal("%s: sshbuf_new failed", __func__); |
692 | if ((r = sshbuf_put_u8(msg, | ||
598 | (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ? | 693 | (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ? |
599 | SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); | 694 | SSH_AGENT_RSA_IDENTITIES_ANSWER : |
600 | buffer_put_int(&msg, 0); | 695 | SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || |
601 | buffer_put_int(&e->output, buffer_len(&msg)); | 696 | (r = sshbuf_put_u32(msg, 0)) != 0 || |
602 | buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); | 697 | (r = sshbuf_put_stringb(e->output, msg)) != 0) |
603 | buffer_free(&msg); | 698 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
699 | sshbuf_free(msg); | ||
604 | } | 700 | } |
605 | 701 | ||
606 | #ifdef ENABLE_PKCS11 | 702 | #ifdef ENABLE_PKCS11 |
@@ -608,19 +704,27 @@ static void | |||
608 | process_add_smartcard_key(SocketEntry *e) | 704 | process_add_smartcard_key(SocketEntry *e) |
609 | { | 705 | { |
610 | char *provider = NULL, *pin; | 706 | char *provider = NULL, *pin; |
611 | int i, type, version, count = 0, success = 0, confirm = 0; | 707 | int r, i, version, count = 0, success = 0, confirm = 0; |
708 | u_int seconds; | ||
612 | time_t death = 0; | 709 | time_t death = 0; |
613 | Key **keys = NULL, *k; | 710 | u_char type; |
711 | struct sshkey **keys = NULL, *k; | ||
614 | Identity *id; | 712 | Identity *id; |
615 | Idtab *tab; | 713 | Idtab *tab; |
616 | 714 | ||
617 | provider = buffer_get_string(&e->request, NULL); | 715 | if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || |
618 | pin = buffer_get_string(&e->request, NULL); | 716 | (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) |
717 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
619 | 718 | ||
620 | while (buffer_len(&e->request)) { | 719 | while (sshbuf_len(e->request)) { |
621 | switch ((type = buffer_get_char(&e->request))) { | 720 | if ((r = sshbuf_get_u8(e->request, &type)) != 0) |
721 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
722 | switch (type) { | ||
622 | case SSH_AGENT_CONSTRAIN_LIFETIME: | 723 | case SSH_AGENT_CONSTRAIN_LIFETIME: |
623 | death = monotime() + buffer_get_int(&e->request); | 724 | if ((r = sshbuf_get_u32(e->request, &seconds)) != 0) |
725 | fatal("%s: buffer error: %s", | ||
726 | __func__, ssh_err(r)); | ||
727 | death = monotime() + seconds; | ||
624 | break; | 728 | break; |
625 | case SSH_AGENT_CONSTRAIN_CONFIRM: | 729 | case SSH_AGENT_CONSTRAIN_CONFIRM: |
626 | confirm = 1; | 730 | confirm = 1; |
@@ -650,7 +754,7 @@ process_add_smartcard_key(SocketEntry *e) | |||
650 | tab->nentries++; | 754 | tab->nentries++; |
651 | success = 1; | 755 | success = 1; |
652 | } else { | 756 | } else { |
653 | key_free(k); | 757 | sshkey_free(k); |
654 | } | 758 | } |
655 | keys[i] = NULL; | 759 | keys[i] = NULL; |
656 | } | 760 | } |
@@ -658,21 +762,20 @@ send: | |||
658 | free(pin); | 762 | free(pin); |
659 | free(provider); | 763 | free(provider); |
660 | free(keys); | 764 | free(keys); |
661 | buffer_put_int(&e->output, 1); | 765 | send_status(e, success); |
662 | buffer_put_char(&e->output, | ||
663 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); | ||
664 | } | 766 | } |
665 | 767 | ||
666 | static void | 768 | static void |
667 | process_remove_smartcard_key(SocketEntry *e) | 769 | process_remove_smartcard_key(SocketEntry *e) |
668 | { | 770 | { |
669 | char *provider = NULL, *pin = NULL; | 771 | char *provider = NULL, *pin = NULL; |
670 | int version, success = 0; | 772 | int r, version, success = 0; |
671 | Identity *id, *nxt; | 773 | Identity *id, *nxt; |
672 | Idtab *tab; | 774 | Idtab *tab; |
673 | 775 | ||
674 | provider = buffer_get_string(&e->request, NULL); | 776 | if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || |
675 | pin = buffer_get_string(&e->request, NULL); | 777 | (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) |
778 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
676 | free(pin); | 779 | free(pin); |
677 | 780 | ||
678 | for (version = 1; version < 3; version++) { | 781 | for (version = 1; version < 3; version++) { |
@@ -695,9 +798,7 @@ process_remove_smartcard_key(SocketEntry *e) | |||
695 | error("process_remove_smartcard_key:" | 798 | error("process_remove_smartcard_key:" |
696 | " pkcs11_del_provider failed"); | 799 | " pkcs11_del_provider failed"); |
697 | free(provider); | 800 | free(provider); |
698 | buffer_put_int(&e->output, 1); | 801 | send_status(e, success); |
699 | buffer_put_char(&e->output, | ||
700 | success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); | ||
701 | } | 802 | } |
702 | #endif /* ENABLE_PKCS11 */ | 803 | #endif /* ENABLE_PKCS11 */ |
703 | 804 | ||
@@ -706,30 +807,31 @@ process_remove_smartcard_key(SocketEntry *e) | |||
706 | static void | 807 | static void |
707 | process_message(SocketEntry *e) | 808 | process_message(SocketEntry *e) |
708 | { | 809 | { |
709 | u_int msg_len, type; | 810 | u_int msg_len; |
710 | u_char *cp; | 811 | u_char type; |
812 | const u_char *cp; | ||
813 | int r; | ||
711 | 814 | ||
712 | if (buffer_len(&e->input) < 5) | 815 | if (sshbuf_len(e->input) < 5) |
713 | return; /* Incomplete message. */ | 816 | return; /* Incomplete message. */ |
714 | cp = buffer_ptr(&e->input); | 817 | cp = sshbuf_ptr(e->input); |
715 | msg_len = get_u32(cp); | 818 | msg_len = PEEK_U32(cp); |
716 | if (msg_len > 256 * 1024) { | 819 | if (msg_len > 256 * 1024) { |
717 | close_socket(e); | 820 | close_socket(e); |
718 | return; | 821 | return; |
719 | } | 822 | } |
720 | if (buffer_len(&e->input) < msg_len + 4) | 823 | if (sshbuf_len(e->input) < msg_len + 4) |
721 | return; | 824 | return; |
722 | 825 | ||
723 | /* move the current input to e->request */ | 826 | /* move the current input to e->request */ |
724 | buffer_consume(&e->input, 4); | 827 | sshbuf_reset(e->request); |
725 | buffer_clear(&e->request); | 828 | if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 || |
726 | buffer_append(&e->request, buffer_ptr(&e->input), msg_len); | 829 | (r = sshbuf_get_u8(e->request, &type)) != 0) |
727 | buffer_consume(&e->input, msg_len); | 830 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
728 | type = buffer_get_char(&e->request); | ||
729 | 831 | ||
730 | /* check wheter agent is locked */ | 832 | /* check wheter agent is locked */ |
731 | if (locked && type != SSH_AGENTC_UNLOCK) { | 833 | if (locked && type != SSH_AGENTC_UNLOCK) { |
732 | buffer_clear(&e->request); | 834 | sshbuf_reset(e->request); |
733 | switch (type) { | 835 | switch (type) { |
734 | case SSH_AGENTC_REQUEST_RSA_IDENTITIES: | 836 | case SSH_AGENTC_REQUEST_RSA_IDENTITIES: |
735 | case SSH2_AGENTC_REQUEST_IDENTITIES: | 837 | case SSH2_AGENTC_REQUEST_IDENTITIES: |
@@ -738,8 +840,7 @@ process_message(SocketEntry *e) | |||
738 | break; | 840 | break; |
739 | default: | 841 | default: |
740 | /* send a fail message for all other request types */ | 842 | /* send a fail message for all other request types */ |
741 | buffer_put_int(&e->output, 1); | 843 | send_status(e, 0); |
742 | buffer_put_char(&e->output, SSH_AGENT_FAILURE); | ||
743 | } | 844 | } |
744 | return; | 845 | return; |
745 | } | 846 | } |
@@ -765,10 +866,10 @@ process_message(SocketEntry *e) | |||
765 | case SSH_AGENTC_REMOVE_RSA_IDENTITY: | 866 | case SSH_AGENTC_REMOVE_RSA_IDENTITY: |
766 | process_remove_identity(e, 1); | 867 | process_remove_identity(e, 1); |
767 | break; | 868 | break; |
869 | #endif | ||
768 | case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: | 870 | case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: |
769 | process_remove_all_identities(e, 1); | 871 | process_remove_all_identities(e, 1); /* safe for !WITH_SSH1 */ |
770 | break; | 872 | break; |
771 | #endif | ||
772 | /* ssh2 */ | 873 | /* ssh2 */ |
773 | case SSH2_AGENTC_SIGN_REQUEST: | 874 | case SSH2_AGENTC_SIGN_REQUEST: |
774 | process_sign_request2(e); | 875 | process_sign_request2(e); |
@@ -798,9 +899,8 @@ process_message(SocketEntry *e) | |||
798 | default: | 899 | default: |
799 | /* Unknown message. Respond with failure. */ | 900 | /* Unknown message. Respond with failure. */ |
800 | error("Unknown message %d", type); | 901 | error("Unknown message %d", type); |
801 | buffer_clear(&e->request); | 902 | sshbuf_reset(e->request); |
802 | buffer_put_int(&e->output, 1); | 903 | send_status(e, 0); |
803 | buffer_put_char(&e->output, SSH_AGENT_FAILURE); | ||
804 | break; | 904 | break; |
805 | } | 905 | } |
806 | } | 906 | } |
@@ -818,9 +918,12 @@ new_socket(sock_type type, int fd) | |||
818 | for (i = 0; i < sockets_alloc; i++) | 918 | for (i = 0; i < sockets_alloc; i++) |
819 | if (sockets[i].type == AUTH_UNUSED) { | 919 | if (sockets[i].type == AUTH_UNUSED) { |
820 | sockets[i].fd = fd; | 920 | sockets[i].fd = fd; |
821 | buffer_init(&sockets[i].input); | 921 | if ((sockets[i].input = sshbuf_new()) == NULL) |
822 | buffer_init(&sockets[i].output); | 922 | fatal("%s: sshbuf_new failed", __func__); |
823 | buffer_init(&sockets[i].request); | 923 | if ((sockets[i].output = sshbuf_new()) == NULL) |
924 | fatal("%s: sshbuf_new failed", __func__); | ||
925 | if ((sockets[i].request = sshbuf_new()) == NULL) | ||
926 | fatal("%s: sshbuf_new failed", __func__); | ||
824 | sockets[i].type = type; | 927 | sockets[i].type = type; |
825 | return; | 928 | return; |
826 | } | 929 | } |
@@ -831,9 +934,12 @@ new_socket(sock_type type, int fd) | |||
831 | sockets[i].type = AUTH_UNUSED; | 934 | sockets[i].type = AUTH_UNUSED; |
832 | sockets_alloc = new_alloc; | 935 | sockets_alloc = new_alloc; |
833 | sockets[old_alloc].fd = fd; | 936 | sockets[old_alloc].fd = fd; |
834 | buffer_init(&sockets[old_alloc].input); | 937 | if ((sockets[old_alloc].input = sshbuf_new()) == NULL) |
835 | buffer_init(&sockets[old_alloc].output); | 938 | fatal("%s: sshbuf_new failed", __func__); |
836 | buffer_init(&sockets[old_alloc].request); | 939 | if ((sockets[old_alloc].output = sshbuf_new()) == NULL) |
940 | fatal("%s: sshbuf_new failed", __func__); | ||
941 | if ((sockets[old_alloc].request = sshbuf_new()) == NULL) | ||
942 | fatal("%s: sshbuf_new failed", __func__); | ||
837 | sockets[old_alloc].type = type; | 943 | sockets[old_alloc].type = type; |
838 | } | 944 | } |
839 | 945 | ||
@@ -879,7 +985,7 @@ prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, | |||
879 | case AUTH_SOCKET: | 985 | case AUTH_SOCKET: |
880 | case AUTH_CONNECTION: | 986 | case AUTH_CONNECTION: |
881 | FD_SET(sockets[i].fd, *fdrp); | 987 | FD_SET(sockets[i].fd, *fdrp); |
882 | if (buffer_len(&sockets[i].output) > 0) | 988 | if (sshbuf_len(sockets[i].output) > 0) |
883 | FD_SET(sockets[i].fd, *fdwp); | 989 | FD_SET(sockets[i].fd, *fdwp); |
884 | break; | 990 | break; |
885 | default: | 991 | default: |
@@ -906,7 +1012,7 @@ after_select(fd_set *readset, fd_set *writeset) | |||
906 | struct sockaddr_un sunaddr; | 1012 | struct sockaddr_un sunaddr; |
907 | socklen_t slen; | 1013 | socklen_t slen; |
908 | char buf[1024]; | 1014 | char buf[1024]; |
909 | int len, sock; | 1015 | int len, sock, r; |
910 | u_int i, orig_alloc; | 1016 | u_int i, orig_alloc; |
911 | uid_t euid; | 1017 | uid_t euid; |
912 | gid_t egid; | 1018 | gid_t egid; |
@@ -942,11 +1048,11 @@ after_select(fd_set *readset, fd_set *writeset) | |||
942 | } | 1048 | } |
943 | break; | 1049 | break; |
944 | case AUTH_CONNECTION: | 1050 | case AUTH_CONNECTION: |
945 | if (buffer_len(&sockets[i].output) > 0 && | 1051 | if (sshbuf_len(sockets[i].output) > 0 && |
946 | FD_ISSET(sockets[i].fd, writeset)) { | 1052 | FD_ISSET(sockets[i].fd, writeset)) { |
947 | len = write(sockets[i].fd, | 1053 | len = write(sockets[i].fd, |
948 | buffer_ptr(&sockets[i].output), | 1054 | sshbuf_ptr(sockets[i].output), |
949 | buffer_len(&sockets[i].output)); | 1055 | sshbuf_len(sockets[i].output)); |
950 | if (len == -1 && (errno == EAGAIN || | 1056 | if (len == -1 && (errno == EAGAIN || |
951 | errno == EWOULDBLOCK || | 1057 | errno == EWOULDBLOCK || |
952 | errno == EINTR)) | 1058 | errno == EINTR)) |
@@ -955,7 +1061,10 @@ after_select(fd_set *readset, fd_set *writeset) | |||
955 | close_socket(&sockets[i]); | 1061 | close_socket(&sockets[i]); |
956 | break; | 1062 | break; |
957 | } | 1063 | } |
958 | buffer_consume(&sockets[i].output, len); | 1064 | if ((r = sshbuf_consume(sockets[i].output, |
1065 | len)) != 0) | ||
1066 | fatal("%s: buffer error: %s", | ||
1067 | __func__, ssh_err(r)); | ||
959 | } | 1068 | } |
960 | if (FD_ISSET(sockets[i].fd, readset)) { | 1069 | if (FD_ISSET(sockets[i].fd, readset)) { |
961 | len = read(sockets[i].fd, buf, sizeof(buf)); | 1070 | len = read(sockets[i].fd, buf, sizeof(buf)); |
@@ -967,7 +1076,10 @@ after_select(fd_set *readset, fd_set *writeset) | |||
967 | close_socket(&sockets[i]); | 1076 | close_socket(&sockets[i]); |
968 | break; | 1077 | break; |
969 | } | 1078 | } |
970 | buffer_append(&sockets[i].input, buf, len); | 1079 | if ((r = sshbuf_put(sockets[i].input, |
1080 | buf, len)) != 0) | ||
1081 | fatal("%s: buffer error: %s", | ||
1082 | __func__, ssh_err(r)); | ||
971 | explicit_bzero(buf, sizeof(buf)); | 1083 | explicit_bzero(buf, sizeof(buf)); |
972 | process_message(&sockets[i]); | 1084 | process_message(&sockets[i]); |
973 | } | 1085 | } |
@@ -1025,8 +1137,8 @@ static void | |||
1025 | usage(void) | 1137 | usage(void) |
1026 | { | 1138 | { |
1027 | fprintf(stderr, | 1139 | fprintf(stderr, |
1028 | "usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-t life]\n" | 1140 | "usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-E fingerprint_hash]\n" |
1029 | " [command [arg ...]]\n" | 1141 | " [-t life] [command [arg ...]]\n" |
1030 | " ssh-agent [-c | -s] -k\n"); | 1142 | " ssh-agent [-c | -s] -k\n"); |
1031 | exit(1); | 1143 | exit(1); |
1032 | } | 1144 | } |
@@ -1069,8 +1181,13 @@ main(int ac, char **av) | |||
1069 | __progname = ssh_get_progname(av[0]); | 1181 | __progname = ssh_get_progname(av[0]); |
1070 | seed_rng(); | 1182 | seed_rng(); |
1071 | 1183 | ||
1072 | while ((ch = getopt(ac, av, "cdksa:t:")) != -1) { | 1184 | while ((ch = getopt(ac, av, "cdksE:a:t:")) != -1) { |
1073 | switch (ch) { | 1185 | switch (ch) { |
1186 | case 'E': | ||
1187 | fingerprint_hash = ssh_digest_alg_by_name(optarg); | ||
1188 | if (fingerprint_hash == -1) | ||
1189 | fatal("Invalid hash algorithm \"%s\"", optarg); | ||
1190 | break; | ||
1074 | case 'c': | 1191 | case 'c': |
1075 | if (s_flag) | 1192 | if (s_flag) |
1076 | usage(); | 1193 | usage(); |