]> andersk Git - openssh.git/blame - sshconnect2.c
- markus@cvs.openbsd.org 2001/04/04 00:06:54
[openssh.git] / sshconnect2.c
CommitLineData
a306f2dd 1/*
2 * Copyright (c) 2000 Markus Friedl. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
a306f2dd 12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "includes.h"
e092ce67 26RCSID("$OpenBSD: sshconnect2.c,v 1.63 2001/04/04 00:06:54 markus Exp $");
a306f2dd 27
28#include <openssl/bn.h>
a306f2dd 29#include <openssl/md5.h>
30#include <openssl/dh.h>
31#include <openssl/hmac.h>
32
33#include "ssh.h"
42f11eb2 34#include "ssh2.h"
a306f2dd 35#include "xmalloc.h"
36#include "rsa.h"
37#include "buffer.h"
38#include "packet.h"
a306f2dd 39#include "uidswap.h"
40#include "compat.h"
a306f2dd 41#include "bufaux.h"
42f11eb2 42#include "cipher.h"
a306f2dd 43#include "kex.h"
44#include "myproposal.h"
45#include "key.h"
a306f2dd 46#include "sshconnect.h"
47#include "authfile.h"
94ec8c6b 48#include "cli.h"
db1cd2f3 49#include "dh.h"
2e73a022 50#include "authfd.h"
42f11eb2 51#include "log.h"
52#include "readconf.h"
53#include "readpass.h"
cab80f75 54#include "match.h"
a5c9ffdb 55#include "dispatch.h"
94ec8c6b 56
a306f2dd 57/* import */
58extern char *client_version_string;
59extern char *server_version_string;
60extern Options options;
61
62/*
63 * SSH2 key exchange
64 */
65
1e3b8b07 66u_char *session_id2 = NULL;
a306f2dd 67int session_id2_len = 0;
68
a5c9ffdb 69char *xxx_host;
70struct sockaddr *xxx_hostaddr;
71
e092ce67 72Kex *xxx_kex = NULL;
73
a5c9ffdb 74int
75check_host_key_callback(Key *hostkey)
76{
77 check_host_key(xxx_host, xxx_hostaddr, hostkey,
78 options.user_hostfile2, options.system_hostfile2);
79 return 0;
80}
81
a306f2dd 82void
94ec8c6b 83ssh_kex2(char *host, struct sockaddr *hostaddr)
84{
94ec8c6b 85 Kex *kex;
a5c9ffdb 86
87 xxx_host = host;
88 xxx_hostaddr = hostaddr;
94ec8c6b 89
c523303b 90 if (options.ciphers == (char *)-1) {
91 log("No valid ciphers for protocol version 2 given, using defaults.");
92 options.ciphers = NULL;
94ec8c6b 93 }
94 if (options.ciphers != NULL) {
95 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
96 myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
97 }
1ad64a93 98 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
99 compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
100 myproposal[PROPOSAL_ENC_ALGS_STOC] =
101 compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
94ec8c6b 102 if (options.compression) {
b2552997 103 myproposal[PROPOSAL_COMP_ALGS_CTOS] =
94ec8c6b 104 myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
105 } else {
b2552997 106 myproposal[PROPOSAL_COMP_ALGS_CTOS] =
94ec8c6b 107 myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
108 }
b2552997 109 if (options.macs != NULL) {
110 myproposal[PROPOSAL_MAC_ALGS_CTOS] =
111 myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
112 }
94ec8c6b 113
a5c9ffdb 114 kex = kex_start(myproposal);
115 kex->client_version_string=client_version_string;
116 kex->server_version_string=server_version_string;
117 kex->check_host_key=&check_host_key_callback;
94ec8c6b 118
e092ce67 119 xxx_kex = kex;
120
a5c9ffdb 121 /* start key exchange */
122 dispatch_run(DISPATCH_BLOCK, &kex->newkeys, kex);
94ec8c6b 123
d1ac6175 124 session_id2 = kex->session_id;
125 session_id2_len = kex->session_id_len;
126
94ec8c6b 127#ifdef DEBUG_KEXDH
128 /* send 1st encrypted/maced/compressed message */
129 packet_start(SSH2_MSG_IGNORE);
130 packet_put_cstring("markus");
131 packet_send();
132 packet_write_wait();
133#endif
a5c9ffdb 134 debug("done: ssh_kex2.");
a306f2dd 135}
71276795 136
a306f2dd 137/*
138 * Authenticate user
139 */
188adeb2 140
141typedef struct Authctxt Authctxt;
142typedef struct Authmethod Authmethod;
143
144typedef int sign_cb_fn(
145 Authctxt *authctxt, Key *key,
1e3b8b07 146 u_char **sigp, int *lenp, u_char *data, int datalen);
188adeb2 147
148struct Authctxt {
149 const char *server_user;
150 const char *host;
151 const char *service;
152 AuthenticationConnection *agent;
188adeb2 153 Authmethod *method;
94ec8c6b 154 int success;
fee56204 155 char *authlist;
156 Key *last_key;
157 sign_cb_fn *last_key_sign;
158 int last_key_hint;
188adeb2 159};
160struct Authmethod {
161 char *name; /* string to compare against server's list */
162 int (*userauth)(Authctxt *authctxt);
163 int *enabled; /* flag in option struct that enables method */
164 int *batch_flag; /* flag in option struct that disables method */
165};
166
167void input_userauth_success(int type, int plen, void *ctxt);
168void input_userauth_failure(int type, int plen, void *ctxt);
9616313f 169void input_userauth_banner(int type, int plen, void *ctxt);
188adeb2 170void input_userauth_error(int type, int plen, void *ctxt);
94ec8c6b 171void input_userauth_info_req(int type, int plen, void *ctxt);
fee56204 172void input_userauth_pk_ok(int type, int plen, void *ctxt);
94ec8c6b 173
174int userauth_none(Authctxt *authctxt);
188adeb2 175int userauth_pubkey(Authctxt *authctxt);
176int userauth_passwd(Authctxt *authctxt);
94ec8c6b 177int userauth_kbdint(Authctxt *authctxt);
188adeb2 178
fee56204 179void userauth(Authctxt *authctxt, char *authlist);
180
181int
182sign_and_send_pubkey(Authctxt *authctxt, Key *k,
183 sign_cb_fn *sign_callback);
184void clear_auth_state(Authctxt *authctxt);
185
94ec8c6b 186Authmethod *authmethod_get(char *authlist);
187Authmethod *authmethod_lookup(const char *name);
cab80f75 188char *authmethods_get(void);
188adeb2 189
190Authmethod authmethods[] = {
191 {"publickey",
192 userauth_pubkey,
fa08c86b 193 &options.pubkey_authentication,
188adeb2 194 NULL},
195 {"password",
196 userauth_passwd,
197 &options.password_authentication,
198 &options.batch_mode},
94ec8c6b 199 {"keyboard-interactive",
200 userauth_kbdint,
201 &options.kbd_interactive_authentication,
202 &options.batch_mode},
203 {"none",
204 userauth_none,
205 NULL,
206 NULL},
188adeb2 207 {NULL, NULL, NULL, NULL}
208};
209
210void
211ssh_userauth2(const char *server_user, char *host)
212{
213 Authctxt authctxt;
214 int type;
215 int plen;
a5c9ffdb 216 int i;
188adeb2 217
d464095c 218 if (options.challenge_reponse_authentication)
219 options.kbd_interactive_authentication = 1;
220
188adeb2 221 debug("send SSH2_MSG_SERVICE_REQUEST");
222 packet_start(SSH2_MSG_SERVICE_REQUEST);
223 packet_put_cstring("ssh-userauth");
224 packet_send();
225 packet_write_wait();
226 type = packet_read(&plen);
227 if (type != SSH2_MSG_SERVICE_ACCEPT) {
228 fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type);
229 }
230 if (packet_remaining() > 0) {
231 char *reply = packet_get_string(&plen);
232 debug("service_accept: %s", reply);
233 xfree(reply);
188adeb2 234 } else {
235 debug("buggy server: service_accept w/o service");
236 }
237 packet_done();
238 debug("got SSH2_MSG_SERVICE_ACCEPT");
239
cab80f75 240 if (options.preferred_authentications == NULL)
241 options.preferred_authentications = authmethods_get();
242
188adeb2 243 /* setup authentication context */
244 authctxt.agent = ssh_get_authentication_connection();
245 authctxt.server_user = server_user;
246 authctxt.host = host;
247 authctxt.service = "ssh-connection"; /* service name */
248 authctxt.success = 0;
94ec8c6b 249 authctxt.method = authmethod_lookup("none");
fee56204 250 authctxt.authlist = NULL;
94ec8c6b 251 if (authctxt.method == NULL)
252 fatal("ssh_userauth2: internal error: cannot send userauth none request");
188adeb2 253
254 /* initial userauth request */
94ec8c6b 255 userauth_none(&authctxt);
188adeb2 256
a5c9ffdb 257 //dispatch_init(&input_userauth_error);
258 for (i = 50; i <= 254; i++) {
259 dispatch_set(i, &input_userauth_error);
260 }
188adeb2 261 dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
262 dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
9616313f 263 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
188adeb2 264 dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
265
266 if (authctxt.agent != NULL)
267 ssh_close_authentication_connection(authctxt.agent);
268
8abcdba4 269 debug("ssh-userauth2 successful: method %s", authctxt.method->name);
188adeb2 270}
271void
fee56204 272userauth(Authctxt *authctxt, char *authlist)
273{
274 if (authlist == NULL) {
275 authlist = authctxt->authlist;
276 } else {
277 if (authctxt->authlist)
278 xfree(authctxt->authlist);
279 authctxt->authlist = authlist;
280 }
281 for (;;) {
282 Authmethod *method = authmethod_get(authlist);
283 if (method == NULL)
284 fatal("Permission denied (%s).", authlist);
285 authctxt->method = method;
286 if (method->userauth(authctxt) != 0) {
287 debug2("we sent a %s packet, wait for reply", method->name);
288 break;
289 } else {
290 debug2("we did not send a packet, disable method");
291 method->enabled = NULL;
292 }
293 }
294}
295void
188adeb2 296input_userauth_error(int type, int plen, void *ctxt)
297{
9616313f 298 fatal("input_userauth_error: bad message during authentication: "
299 "type %d", type);
300}
301void
302input_userauth_banner(int type, int plen, void *ctxt)
303{
304 char *msg, *lang;
305 debug3("input_userauth_banner");
306 msg = packet_get_string(NULL);
307 lang = packet_get_string(NULL);
308 fprintf(stderr, "%s", msg);
309 xfree(msg);
310 xfree(lang);
188adeb2 311}
312void
313input_userauth_success(int type, int plen, void *ctxt)
314{
315 Authctxt *authctxt = ctxt;
316 if (authctxt == NULL)
317 fatal("input_userauth_success: no authentication context");
fee56204 318 if (authctxt->authlist)
319 xfree(authctxt->authlist);
320 clear_auth_state(authctxt);
188adeb2 321 authctxt->success = 1; /* break out */
322}
323void
324input_userauth_failure(int type, int plen, void *ctxt)
325{
188adeb2 326 Authctxt *authctxt = ctxt;
327 char *authlist = NULL;
328 int partial;
188adeb2 329
330 if (authctxt == NULL)
331 fatal("input_userauth_failure: no authentication context");
332
94ec8c6b 333 authlist = packet_get_string(NULL);
188adeb2 334 partial = packet_get_char();
335 packet_done();
336
337 if (partial != 0)
f72e01a5 338 log("Authenticated with partial success.");
188adeb2 339 debug("authentications that can continue: %s", authlist);
340
fee56204 341 clear_auth_state(authctxt);
342 userauth(authctxt, authlist);
343}
344void
345input_userauth_pk_ok(int type, int plen, void *ctxt)
346{
347 Authctxt *authctxt = ctxt;
348 Key *key = NULL;
349 Buffer b;
350 int alen, blen, pktype, sent = 0;
22138a36 351 char *pkalg, *pkblob, *fp;
fee56204 352
353 if (authctxt == NULL)
354 fatal("input_userauth_pk_ok: no authentication context");
355 if (datafellows & SSH_BUG_PKOK) {
356 /* this is similar to SSH_BUG_PKAUTH */
357 debug2("input_userauth_pk_ok: SSH_BUG_PKOK");
358 pkblob = packet_get_string(&blen);
359 buffer_init(&b);
360 buffer_append(&b, pkblob, blen);
361 pkalg = buffer_get_string(&b, &alen);
362 buffer_free(&b);
363 } else {
364 pkalg = packet_get_string(&alen);
365 pkblob = packet_get_string(&blen);
366 }
367 packet_done();
368
369 debug("input_userauth_pk_ok: pkalg %s blen %d lastkey %p hint %d",
370 pkalg, blen, authctxt->last_key, authctxt->last_key_hint);
371
372 do {
373 if (authctxt->last_key == NULL ||
374 authctxt->last_key_sign == NULL) {
375 debug("no last key or no sign cb");
188adeb2 376 break;
188adeb2 377 }
fee56204 378 if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
379 debug("unknown pkalg %s", pkalg);
380 break;
381 }
382 if ((key = key_from_blob(pkblob, blen)) == NULL) {
383 debug("no key from blob. pkalg %s", pkalg);
384 break;
385 }
22138a36 386 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
387 debug2("input_userauth_pk_ok: fp %s", fp);
388 xfree(fp);
fee56204 389 if (!key_equal(key, authctxt->last_key)) {
390 debug("key != last_key");
391 break;
392 }
393 sent = sign_and_send_pubkey(authctxt, key,
394 authctxt->last_key_sign);
395 } while(0);
396
397 if (key != NULL)
398 key_free(key);
399 xfree(pkalg);
400 xfree(pkblob);
401
402 /* unregister */
403 clear_auth_state(authctxt);
404 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, NULL);
405
406 /* try another method if we did not send a packet*/
407 if (sent == 0)
408 userauth(authctxt, NULL);
409
188adeb2 410}
411
94ec8c6b 412int
413userauth_none(Authctxt *authctxt)
414{
415 /* initial userauth request */
416 packet_start(SSH2_MSG_USERAUTH_REQUEST);
417 packet_put_cstring(authctxt->server_user);
418 packet_put_cstring(authctxt->service);
419 packet_put_cstring(authctxt->method->name);
420 packet_send();
94ec8c6b 421 return 1;
422}
423
a306f2dd 424int
188adeb2 425userauth_passwd(Authctxt *authctxt)
a306f2dd 426{
1d1ffb87 427 static int attempt = 0;
a306f2dd 428 char prompt[80];
429 char *password;
430
fa649821 431 if (attempt++ >= options.number_of_password_prompts)
1d1ffb87 432 return 0;
433
fa649821 434 if(attempt != 1)
435 error("Permission denied, please try again.");
436
f72e01a5 437 snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
188adeb2 438 authctxt->server_user, authctxt->host);
a306f2dd 439 password = read_passphrase(prompt, 0);
440 packet_start(SSH2_MSG_USERAUTH_REQUEST);
188adeb2 441 packet_put_cstring(authctxt->server_user);
442 packet_put_cstring(authctxt->service);
94ec8c6b 443 packet_put_cstring(authctxt->method->name);
a306f2dd 444 packet_put_char(0);
a6215e53 445 packet_put_cstring(password);
a306f2dd 446 memset(password, 0, strlen(password));
447 xfree(password);
a6215e53 448 packet_inject_ignore(64);
a306f2dd 449 packet_send();
a306f2dd 450 return 1;
451}
452
fee56204 453void
454clear_auth_state(Authctxt *authctxt)
455{
456 /* XXX clear authentication state */
457 if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) {
458 debug3("clear_auth_state: key_free %p", authctxt->last_key);
459 key_free(authctxt->last_key);
460 }
461 authctxt->last_key = NULL;
462 authctxt->last_key_hint = -2;
463 authctxt->last_key_sign = NULL;
464}
465
2e73a022 466int
188adeb2 467sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
a306f2dd 468{
469 Buffer b;
1e3b8b07 470 u_char *blob, *signature;
a306f2dd 471 int bloblen, slen;
74fc9186 472 int skip = 0;
2e73a022 473 int ret = -1;
94ec8c6b 474 int have_sig = 1;
a306f2dd 475
cbc5abf9 476 debug3("sign_and_send_pubkey");
fee56204 477
fa08c86b 478 if (key_to_blob(k, &blob, &bloblen) == 0) {
479 /* we cannot handle this key */
cbc5abf9 480 debug3("sign_and_send_pubkey: cannot handle key");
fa08c86b 481 return 0;
482 }
a306f2dd 483 /* data to be signed */
484 buffer_init(&b);
33de75a3 485 if (datafellows & SSH_OLD_SESSIONID) {
74fc9186 486 buffer_append(&b, session_id2, session_id2_len);
2b87da3b 487 skip = session_id2_len;
33de75a3 488 } else {
489 buffer_put_string(&b, session_id2, session_id2_len);
490 skip = buffer_len(&b);
74fc9186 491 }
a306f2dd 492 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
188adeb2 493 buffer_put_cstring(&b, authctxt->server_user);
d0c832f3 494 buffer_put_cstring(&b,
cbc5abf9 495 datafellows & SSH_BUG_PKSERVICE ?
d0c832f3 496 "ssh-userauth" :
188adeb2 497 authctxt->service);
cbc5abf9 498 if (datafellows & SSH_BUG_PKAUTH) {
499 buffer_put_char(&b, have_sig);
500 } else {
501 buffer_put_cstring(&b, authctxt->method->name);
502 buffer_put_char(&b, have_sig);
2b87da3b 503 buffer_put_cstring(&b, key_ssh_name(k));
cbc5abf9 504 }
a306f2dd 505 buffer_put_string(&b, blob, bloblen);
a306f2dd 506
507 /* generate signature */
fee56204 508 ret = (*sign_callback)(authctxt, k, &signature, &slen,
509 buffer_ptr(&b), buffer_len(&b));
2e73a022 510 if (ret == -1) {
511 xfree(blob);
512 buffer_free(&b);
513 return 0;
514 }
fa08c86b 515#ifdef DEBUG_PK
a306f2dd 516 buffer_dump(&b);
517#endif
cbc5abf9 518 if (datafellows & SSH_BUG_PKSERVICE) {
d0c832f3 519 buffer_clear(&b);
520 buffer_append(&b, session_id2, session_id2_len);
fee56204 521 skip = session_id2_len;
d0c832f3 522 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
188adeb2 523 buffer_put_cstring(&b, authctxt->server_user);
524 buffer_put_cstring(&b, authctxt->service);
94ec8c6b 525 buffer_put_cstring(&b, authctxt->method->name);
526 buffer_put_char(&b, have_sig);
cbc5abf9 527 if (!(datafellows & SSH_BUG_PKAUTH))
2b87da3b 528 buffer_put_cstring(&b, key_ssh_name(k));
d0c832f3 529 buffer_put_string(&b, blob, bloblen);
530 }
531 xfree(blob);
fee56204 532
a306f2dd 533 /* append signature */
534 buffer_put_string(&b, signature, slen);
535 xfree(signature);
536
537 /* skip session id and packet type */
74fc9186 538 if (buffer_len(&b) < skip + 1)
188adeb2 539 fatal("userauth_pubkey: internal error");
74fc9186 540 buffer_consume(&b, skip + 1);
a306f2dd 541
542 /* put remaining data from buffer into packet */
543 packet_start(SSH2_MSG_USERAUTH_REQUEST);
544 packet_put_raw(buffer_ptr(&b), buffer_len(&b));
545 buffer_free(&b);
a306f2dd 546 packet_send();
2e73a022 547
548 return 1;
4c8722d9 549}
550
551int
fee56204 552send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback,
553 int hint)
4c8722d9 554{
fee56204 555 u_char *blob;
556 int bloblen, have_sig = 0;
4c8722d9 557
fee56204 558 debug3("send_pubkey_test");
559
560 if (key_to_blob(k, &blob, &bloblen) == 0) {
561 /* we cannot handle this key */
562 debug3("send_pubkey_test: cannot handle key");
4c8722d9 563 return 0;
564 }
fee56204 565 /* register callback for USERAUTH_PK_OK message */
566 authctxt->last_key_sign = sign_callback;
567 authctxt->last_key_hint = hint;
568 authctxt->last_key = k;
569 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
4c8722d9 570
fee56204 571 packet_start(SSH2_MSG_USERAUTH_REQUEST);
572 packet_put_cstring(authctxt->server_user);
573 packet_put_cstring(authctxt->service);
574 packet_put_cstring(authctxt->method->name);
575 packet_put_char(have_sig);
576 if (!(datafellows & SSH_BUG_PKAUTH))
577 packet_put_cstring(key_ssh_name(k));
578 packet_put_string(blob, bloblen);
579 xfree(blob);
580 packet_send();
581 return 1;
582}
583
584Key *
585load_identity_file(char *filename)
586{
587 Key *private;
588 char prompt[300], *passphrase;
aeaa3d9e 589 int quit, i;
d156519a 590 struct stat st;
fee56204 591
d156519a 592 if (stat(filename, &st) < 0) {
593 debug3("no such identity: %s", filename);
594 return NULL;
595 }
aeaa3d9e 596 private = key_load_private_type(KEY_UNSPEC, filename, "", NULL);
597 if (private == NULL) {
598 if (options.batch_mode)
fee56204 599 return NULL;
4c8722d9 600 snprintf(prompt, sizeof prompt,
fa08c86b 601 "Enter passphrase for key '%.100s': ", filename);
188adeb2 602 for (i = 0; i < options.number_of_password_prompts; i++) {
603 passphrase = read_passphrase(prompt, 0);
604 if (strcmp(passphrase, "") != 0) {
aeaa3d9e 605 private = key_load_private_type(KEY_UNSPEC, filename,
606 passphrase, NULL);
fee56204 607 quit = 0;
188adeb2 608 } else {
609 debug2("no passphrase given, try next key");
fee56204 610 quit = 1;
188adeb2 611 }
612 memset(passphrase, 0, strlen(passphrase));
613 xfree(passphrase);
aeaa3d9e 614 if (private != NULL || quit)
188adeb2 615 break;
616 debug2("bad passphrase given, try again...");
617 }
4c8722d9 618 }
fee56204 619 return private;
620}
621
622int
623identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
624 u_char *data, int datalen)
625{
626 Key *private;
627 int idx, ret;
628
629 idx = authctxt->last_key_hint;
630 if (idx < 0)
631 return -1;
632 private = load_identity_file(options.identity_files[idx]);
633 if (private == NULL)
634 return -1;
635 ret = key_sign(private, sigp, lenp, data, datalen);
636 key_free(private);
2e73a022 637 return ret;
638}
639
1e3b8b07 640int agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
641 u_char *data, int datalen)
2e73a022 642{
188adeb2 643 return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen);
2e73a022 644}
645
fee56204 646int key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
647 u_char *data, int datalen)
648{
649 return key_sign(key, sigp, lenp, data, datalen);
650}
651
2e73a022 652int
188adeb2 653userauth_pubkey_agent(Authctxt *authctxt)
2e73a022 654{
655 static int called = 0;
fa08c86b 656 int ret = 0;
2e73a022 657 char *comment;
658 Key *k;
2e73a022 659
660 if (called == 0) {
fa08c86b 661 if (ssh_get_num_identities(authctxt->agent, 2) == 0)
662 debug2("userauth_pubkey_agent: no keys at all");
188adeb2 663 called = 1;
2e73a022 664 }
fa08c86b 665 k = ssh_get_next_identity(authctxt->agent, &comment, 2);
188adeb2 666 if (k == NULL) {
fa08c86b 667 debug2("userauth_pubkey_agent: no more keys");
668 } else {
fee56204 669 debug("userauth_pubkey_agent: testing agent key %s", comment);
fa08c86b 670 xfree(comment);
fee56204 671 ret = send_pubkey_test(authctxt, k, agent_sign_cb, -1);
672 if (ret == 0)
673 key_free(k);
188adeb2 674 }
fa08c86b 675 if (ret == 0)
676 debug2("userauth_pubkey_agent: no message sent");
2e73a022 677 return ret;
a306f2dd 678}
679
188adeb2 680int
681userauth_pubkey(Authctxt *authctxt)
a306f2dd 682{
188adeb2 683 static int idx = 0;
684 int sent = 0;
fee56204 685 Key *key;
686 char *filename;
188adeb2 687
fa08c86b 688 if (authctxt->agent != NULL) {
689 do {
690 sent = userauth_pubkey_agent(authctxt);
691 } while(!sent && authctxt->agent->howmany > 0);
692 }
693 while (!sent && idx < options.num_identity_files) {
fee56204 694 key = options.identity_keys[idx];
695 filename = options.identity_files[idx];
696 if (key == NULL) {
697 debug("try privkey: %s", filename);
698 key = load_identity_file(filename);
699 if (key != NULL) {
700 sent = sign_and_send_pubkey(authctxt, key,
701 key_sign_cb);
702 key_free(key);
703 }
704 } else if (key->type != KEY_RSA1) {
705 debug("try pubkey: %s", filename);
706 sent = send_pubkey_test(authctxt, key,
707 identity_sign_cb, idx);
708 }
fa08c86b 709 idx++;
710 }
188adeb2 711 return sent;
712}
a306f2dd 713
94ec8c6b 714/*
715 * Send userauth request message specifying keyboard-interactive method.
716 */
717int
718userauth_kbdint(Authctxt *authctxt)
719{
720 static int attempt = 0;
721
722 if (attempt++ >= options.number_of_password_prompts)
723 return 0;
724
725 debug2("userauth_kbdint");
726 packet_start(SSH2_MSG_USERAUTH_REQUEST);
727 packet_put_cstring(authctxt->server_user);
728 packet_put_cstring(authctxt->service);
729 packet_put_cstring(authctxt->method->name);
730 packet_put_cstring(""); /* lang */
731 packet_put_cstring(options.kbd_interactive_devices ?
732 options.kbd_interactive_devices : "");
733 packet_send();
94ec8c6b 734
735 dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
736 return 1;
737}
738
739/*
f72e01a5 740 * parse INFO_REQUEST, prompt user and send INFO_RESPONSE
94ec8c6b 741 */
742void
743input_userauth_info_req(int type, int plen, void *ctxt)
744{
745 Authctxt *authctxt = ctxt;
f72e01a5 746 char *name, *inst, *lang, *prompt, *response;
1e3b8b07 747 u_int num_prompts, i;
94ec8c6b 748 int echo = 0;
749
750 debug2("input_userauth_info_req");
751
752 if (authctxt == NULL)
753 fatal("input_userauth_info_req: no authentication context");
754
755 name = packet_get_string(NULL);
756 inst = packet_get_string(NULL);
757 lang = packet_get_string(NULL);
94ec8c6b 758 if (strlen(name) > 0)
759 cli_mesg(name);
94ec8c6b 760 if (strlen(inst) > 0)
761 cli_mesg(inst);
f72e01a5 762 xfree(name);
94ec8c6b 763 xfree(inst);
f72e01a5 764 xfree(lang);
94ec8c6b 765
766 num_prompts = packet_get_int();
767 /*
768 * Begin to build info response packet based on prompts requested.
769 * We commit to providing the correct number of responses, so if
770 * further on we run into a problem that prevents this, we have to
771 * be sure and clean this up and send a correct error response.
772 */
773 packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
774 packet_put_int(num_prompts);
775
776 for (i = 0; i < num_prompts; i++) {
777 prompt = packet_get_string(NULL);
778 echo = packet_get_char();
779
780 response = cli_prompt(prompt, echo);
781
a6215e53 782 packet_put_cstring(response);
94ec8c6b 783 memset(response, 0, strlen(response));
784 xfree(response);
785 xfree(prompt);
786 }
787 packet_done(); /* done with parsing incoming message. */
788
a6215e53 789 packet_inject_ignore(64);
94ec8c6b 790 packet_send();
94ec8c6b 791}
a306f2dd 792
188adeb2 793/* find auth method */
794
188adeb2 795/*
796 * given auth method name, if configurable options permit this method fill
797 * in auth_ident field and return true, otherwise return false.
798 */
799int
800authmethod_is_enabled(Authmethod *method)
801{
802 if (method == NULL)
803 return 0;
804 /* return false if options indicate this method is disabled */
805 if (method->enabled == NULL || *method->enabled == 0)
806 return 0;
807 /* return false if batch mode is enabled but method needs interactive mode */
808 if (method->batch_flag != NULL && *method->batch_flag != 0)
809 return 0;
810 return 1;
811}
a306f2dd 812
188adeb2 813Authmethod *
814authmethod_lookup(const char *name)
815{
816 Authmethod *method = NULL;
817 if (name != NULL)
818 for (method = authmethods; method->name != NULL; method++)
819 if (strcmp(name, method->name) == 0)
820 return method;
821 debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
822 return NULL;
823}
824
cab80f75 825/* XXX internal state */
826static Authmethod *current = NULL;
827static char *supported = NULL;
828static char *preferred = NULL;
188adeb2 829/*
830 * Given the authentication method list sent by the server, return the
831 * next method we should try. If the server initially sends a nil list,
cab80f75 832 * use a built-in default list.
2b87da3b 833 */
188adeb2 834Authmethod *
835authmethod_get(char *authlist)
836{
cab80f75 837
838 char *name = NULL;
839 int next;
2b87da3b 840
188adeb2 841 /* Use a suitable default if we're passed a nil list. */
842 if (authlist == NULL || strlen(authlist) == 0)
cab80f75 843 authlist = options.preferred_authentications;
844
845 if (supported == NULL || strcmp(authlist, supported) != 0) {
846 debug3("start over, passed a different list %s", authlist);
847 if (supported != NULL)
848 xfree(supported);
849 supported = xstrdup(authlist);
850 preferred = options.preferred_authentications;
851 debug3("preferred %s", preferred);
852 current = NULL;
853 } else if (current != NULL && authmethod_is_enabled(current))
854 return current;
188adeb2 855
cab80f75 856 for (;;) {
857 if ((name = match_list(preferred, supported, &next)) == NULL) {
858 debug("no more auth methods to try");
859 current = NULL;
860 return NULL;
861 }
862 preferred += next;
94ec8c6b 863 debug3("authmethod_lookup %s", name);
cab80f75 864 debug3("remaining preferred: %s", preferred);
865 if ((current = authmethod_lookup(name)) != NULL &&
866 authmethod_is_enabled(current)) {
94ec8c6b 867 debug3("authmethod_is_enabled %s", name);
cab80f75 868 debug("next auth method to try is %s", name);
869 return current;
94ec8c6b 870 }
a306f2dd 871 }
cab80f75 872}
a22aff1f 873
a22aff1f 874
cab80f75 875#define DELIM ","
876char *
877authmethods_get(void)
878{
879 Authmethod *method = NULL;
880 char buf[1024];
881
882 buf[0] = '\0';
883 for (method = authmethods; method->name != NULL; method++) {
884 if (authmethod_is_enabled(method)) {
885 if (buf[0] != '\0')
886 strlcat(buf, DELIM, sizeof buf);
887 strlcat(buf, method->name, sizeof buf);
888 }
889 }
890 return xstrdup(buf);
a306f2dd 891}
This page took 0.231105 seconds and 5 git commands to generate.