summaryrefslogtreecommitdiff
path: root/other/ssharp/sshconnect2.c
diff options
context:
space:
mode:
authorSkyperTHC2026-03-03 06:28:55 +0000
committerSkyperTHC2026-03-03 06:28:55 +0000
commit5d3573ef7a109ee70416fe94db098fe6a769a798 (patch)
treedc2d5b294c9db8ab2db7433511f94e1c4bb8b698 /other/ssharp/sshconnect2.c
parentc6c59dc73cc4586357f93ab38ecf459e98675cc5 (diff)
packetstorm sync
Diffstat (limited to 'other/ssharp/sshconnect2.c')
-rw-r--r--other/ssharp/sshconnect2.c991
1 files changed, 991 insertions, 0 deletions
diff --git a/other/ssharp/sshconnect2.c b/other/ssharp/sshconnect2.c
new file mode 100644
index 0000000..b46a064
--- /dev/null
+++ b/other/ssharp/sshconnect2.c
@@ -0,0 +1,991 @@
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.
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"
26RCSID("$OpenBSD: sshconnect2.c,v 1.72 2001/04/18 23:43:26 markus Exp $");
27
28#include <openssl/bn.h>
29#include <openssl/md5.h>
30#include <openssl/dh.h>
31#include <openssl/hmac.h>
32
33#include "ssh.h"
34#include "ssh2.h"
35#include "xmalloc.h"
36#include "rsa.h"
37#include "buffer.h"
38#include "packet.h"
39#include "uidswap.h"
40#include "compat.h"
41#include "bufaux.h"
42#include "cipher.h"
43#include "kex.h"
44#include "myproposal.h"
45#include "key.h"
46#include "sshconnect.h"
47#include "authfile.h"
48#include "cli.h"
49#include "dh.h"
50#include "authfd.h"
51#include "log.h"
52#include "readconf.h"
53#include "readpass.h"
54#include "match.h"
55#include "dispatch.h"
56#include "canohost.h"
57
58/* import */
59extern char *client_version_string;
60extern char *server_version_string;
61extern Options options;
62
63/*
64 * SSH2 key exchange
65 */
66
67u_char *session_id2 = NULL;
68int session_id2_len = 0;
69
70char *xxx_host;
71struct sockaddr *xxx_hostaddr;
72
73Kex *xxx_kex = NULL;
74
75int
76check_host_key_callback(Key *hostkey)
77{
78 /* SSHARP: dummy */
79 return 0;
80}
81
82void
83ssh_kex2(char *host, struct sockaddr *hostaddr)
84{
85 Kex *kex;
86
87 xxx_host = host;
88 xxx_hostaddr = hostaddr;
89
90 if (options.ciphers == (char *)-1) {
91 log("No valid ciphers for protocol version 2 given, using defaults.");
92 options.ciphers = NULL;
93 }
94 if (options.ciphers != NULL) {
95 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
96 myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
97 }
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]);
102 if (options.compression) {
103 myproposal[PROPOSAL_COMP_ALGS_CTOS] =
104 myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
105 } else {
106 myproposal[PROPOSAL_COMP_ALGS_CTOS] =
107 myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
108 }
109 if (options.macs != NULL) {
110 myproposal[PROPOSAL_MAC_ALGS_CTOS] =
111 myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
112 }
113 if (options.hostkeyalgorithms != NULL)
114 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
115 options.hostkeyalgorithms;
116
117 /* start key exchange */
118 kex = kex_setup(myproposal);
119 kex->client_version_string=client_version_string;
120 kex->server_version_string=server_version_string;
121 kex->check_host_key=&check_host_key_callback;
122
123 xxx_kex = kex;
124
125 dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
126
127 session_id2 = kex->session_id;
128 session_id2_len = kex->session_id_len;
129
130#ifdef DEBUG_KEXDH
131 /* send 1st encrypted/maced/compressed message */
132 packet_start(SSH2_MSG_IGNORE);
133 packet_put_cstring("markus");
134 packet_send();
135 packet_write_wait();
136#endif
137 debug("done: ssh_kex2.");
138}
139
140/*
141 * Authenticate user
142 */
143
144typedef struct Authctxt Authctxt;
145typedef struct Authmethod Authmethod;
146
147typedef int sign_cb_fn(
148 Authctxt *authctxt, Key *key,
149 u_char **sigp, int *lenp, u_char *data, int datalen);
150
151struct Authctxt {
152 const char *server_user;
153 const char *local_user;
154 const char *pass;
155 const char *host;
156 const char *service;
157 Authmethod *method;
158 int success;
159 char *authlist;
160 /* pubkey */
161 Key *last_key;
162 sign_cb_fn *last_key_sign;
163 int last_key_hint;
164 AuthenticationConnection *agent;
165 /* hostbased */
166 Key **keys;
167 int nkeys;
168};
169struct Authmethod {
170 char *name; /* string to compare against server's list */
171 int (*userauth)(Authctxt *authctxt);
172 int *enabled; /* flag in option struct that enables method */
173 int *batch_flag; /* flag in option struct that disables method */
174};
175
176void input_userauth_success(int type, int plen, void *ctxt);
177void input_userauth_failure(int type, int plen, void *ctxt);
178void input_userauth_banner(int type, int plen, void *ctxt);
179void input_userauth_error(int type, int plen, void *ctxt);
180void input_userauth_info_req(int type, int plen, void *ctxt);
181void input_userauth_pk_ok(int type, int plen, void *ctxt);
182
183int userauth_none(Authctxt *authctxt);
184int userauth_pubkey(Authctxt *authctxt);
185int userauth_passwd(Authctxt *authctxt);
186int userauth_kbdint(Authctxt *authctxt);
187int userauth_hostbased(Authctxt *authctxt);
188
189void userauth(Authctxt *authctxt, char *authlist);
190
191int
192sign_and_send_pubkey(Authctxt *authctxt, Key *k,
193 sign_cb_fn *sign_callback);
194void clear_auth_state(Authctxt *authctxt);
195
196Authmethod *authmethod_get(char *authlist);
197Authmethod *authmethod_lookup(const char *name);
198char *authmethods_get(void);
199
200Authmethod authmethods[] = {
201 {"publickey",
202 userauth_pubkey,
203 &options.pubkey_authentication,
204 NULL},
205 {"password",
206 userauth_passwd,
207 &options.password_authentication,
208 &options.batch_mode},
209 {"keyboard-interactive",
210 userauth_kbdint,
211 &options.kbd_interactive_authentication,
212 &options.batch_mode},
213 {"hostbased",
214 userauth_hostbased,
215 &options.hostbased_authentication,
216 NULL},
217 {"none",
218 userauth_none,
219 NULL,
220 NULL},
221 {NULL, NULL, NULL, NULL}
222};
223
224void
225ssh_userauth2(const char *login, const char *pass, char *host,
226 Key **keys, int nkeys)
227{
228 Authctxt authctxt;
229 int type;
230 int plen;
231
232 if (options.challenge_reponse_authentication)
233 options.kbd_interactive_authentication = 1;
234
235 debug("send SSH2_MSG_SERVICE_REQUEST");
236 packet_start(SSH2_MSG_SERVICE_REQUEST);
237 packet_put_cstring("ssh-userauth");
238 packet_send();
239 packet_write_wait();
240 type = packet_read(&plen);
241 if (type != SSH2_MSG_SERVICE_ACCEPT) {
242 fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type);
243 }
244 if (packet_remaining() > 0) {
245 char *reply = packet_get_string(&plen);
246 debug("service_accept: %s", reply);
247 xfree(reply);
248 } else {
249 debug("buggy server: service_accept w/o service");
250 }
251 packet_done();
252 debug("got SSH2_MSG_SERVICE_ACCEPT");
253
254 if (options.preferred_authentications == NULL)
255 options.preferred_authentications = authmethods_get();
256
257 /* setup authentication context */
258 authctxt.agent = ssh_get_authentication_connection();
259 authctxt.server_user = login;
260 authctxt.local_user = login;
261 authctxt.pass = strdup(pass);
262 authctxt.host = host;
263
264 authctxt.service = "ssh-connection"; /* service name */
265 authctxt.success = 0;
266 authctxt.method = authmethod_lookup("none");
267 authctxt.authlist = NULL;
268 authctxt.keys = keys;
269 authctxt.nkeys = nkeys;
270 if (authctxt.method == NULL)
271 fatal("ssh_userauth2: internal error: cannot send userauth none request");
272
273 /* initial userauth request */
274 userauth_none(&authctxt);
275
276 dispatch_init(&input_userauth_error);
277 dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
278 dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
279 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
280 dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
281
282 if (authctxt.agent != NULL)
283 ssh_close_authentication_connection(authctxt.agent);
284
285 debug("ssh-userauth2 successful: method %s", authctxt.method->name);
286}
287void
288userauth(Authctxt *authctxt, char *authlist)
289{
290 if (authlist == NULL) {
291 authlist = authctxt->authlist;
292 } else {
293 if (authctxt->authlist)
294 xfree(authctxt->authlist);
295 authctxt->authlist = authlist;
296 }
297 for (;;) {
298 Authmethod *method = authmethod_get(authlist);
299 if (method == NULL)
300 fatal("Permission denied (%s).", authlist);
301 authctxt->method = method;
302 if (method->userauth(authctxt) != 0) {
303 debug2("we sent a %s packet, wait for reply", method->name);
304 break;
305 } else {
306 debug2("we did not send a packet, disable method");
307 method->enabled = NULL;
308 }
309 }
310}
311void
312input_userauth_error(int type, int plen, void *ctxt)
313{
314 fatal("input_userauth_error: bad message during authentication: "
315 "type %d", type);
316}
317void
318input_userauth_banner(int type, int plen, void *ctxt)
319{
320 char *msg, *lang;
321 debug3("input_userauth_banner");
322 msg = packet_get_string(NULL);
323 lang = packet_get_string(NULL);
324 fprintf(stderr, "%s", msg);
325 xfree(msg);
326 xfree(lang);
327}
328void
329input_userauth_success(int type, int plen, void *ctxt)
330{
331 Authctxt *authctxt = ctxt;
332 if (authctxt == NULL)
333 fatal("input_userauth_success: no authentication context");
334 if (authctxt->authlist)
335 xfree(authctxt->authlist);
336 clear_auth_state(authctxt);
337 authctxt->success = 1; /* break out */
338}
339void
340input_userauth_failure(int type, int plen, void *ctxt)
341{
342 Authctxt *authctxt = ctxt;
343 char *authlist = NULL;
344 int partial;
345
346 if (authctxt == NULL)
347 fatal("input_userauth_failure: no authentication context");
348
349 authlist = packet_get_string(NULL);
350 partial = packet_get_char();
351 packet_done();
352
353 if (partial != 0)
354 log("Authenticated with partial success.");
355 debug("authentications that can continue: %s", authlist);
356
357 clear_auth_state(authctxt);
358 userauth(authctxt, authlist);
359}
360void
361input_userauth_pk_ok(int type, int plen, void *ctxt)
362{
363 Authctxt *authctxt = ctxt;
364 Key *key = NULL;
365 Buffer b;
366 int alen, blen, sent = 0;
367 char *pkalg, *pkblob, *fp;
368
369 if (authctxt == NULL)
370 fatal("input_userauth_pk_ok: no authentication context");
371 if (datafellows & SSH_BUG_PKOK) {
372 /* this is similar to SSH_BUG_PKAUTH */
373 debug2("input_userauth_pk_ok: SSH_BUG_PKOK");
374 pkblob = packet_get_string(&blen);
375 buffer_init(&b);
376 buffer_append(&b, pkblob, blen);
377 pkalg = buffer_get_string(&b, &alen);
378 buffer_free(&b);
379 } else {
380 pkalg = packet_get_string(&alen);
381 pkblob = packet_get_string(&blen);
382 }
383 packet_done();
384
385 debug("input_userauth_pk_ok: pkalg %s blen %d lastkey %p hint %d",
386 pkalg, blen, authctxt->last_key, authctxt->last_key_hint);
387
388 do {
389 if (authctxt->last_key == NULL ||
390 authctxt->last_key_sign == NULL) {
391 debug("no last key or no sign cb");
392 break;
393 }
394 if (key_type_from_name(pkalg) == KEY_UNSPEC) {
395 debug("unknown pkalg %s", pkalg);
396 break;
397 }
398 if ((key = key_from_blob(pkblob, blen)) == NULL) {
399 debug("no key from blob. pkalg %s", pkalg);
400 break;
401 }
402 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
403 debug2("input_userauth_pk_ok: fp %s", fp);
404 xfree(fp);
405 if (!key_equal(key, authctxt->last_key)) {
406 debug("key != last_key");
407 break;
408 }
409 sent = sign_and_send_pubkey(authctxt, key,
410 authctxt->last_key_sign);
411 } while(0);
412
413 if (key != NULL)
414 key_free(key);
415 xfree(pkalg);
416 xfree(pkblob);
417
418 /* unregister */
419 clear_auth_state(authctxt);
420 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, NULL);
421
422 /* try another method if we did not send a packet*/
423 if (sent == 0)
424 userauth(authctxt, NULL);
425
426}
427
428int
429userauth_none(Authctxt *authctxt)
430{
431 /* initial userauth request */
432 packet_start(SSH2_MSG_USERAUTH_REQUEST);
433 packet_put_cstring(authctxt->server_user);
434 packet_put_cstring(authctxt->service);
435 packet_put_cstring(authctxt->method->name);
436 packet_send();
437 return 1;
438}
439
440int
441userauth_passwd(Authctxt *authctxt)
442{
443 static int attempt = 0;
444 const char *password;
445
446 if (attempt++ >= options.number_of_password_prompts)
447 return 0;
448
449 if(attempt != 1)
450 error("Permission denied, please try again.");
451
452 password = authctxt->pass;
453 packet_start(SSH2_MSG_USERAUTH_REQUEST);
454 packet_put_cstring(authctxt->server_user);
455 packet_put_cstring(authctxt->service);
456 packet_put_cstring(authctxt->method->name);
457 packet_put_char(0);
458 packet_put_cstring(password);
459 packet_inject_ignore(64);
460 packet_send();
461 return 1;
462}
463
464void
465clear_auth_state(Authctxt *authctxt)
466{
467 /* XXX clear authentication state */
468 if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) {
469 debug3("clear_auth_state: key_free %p", authctxt->last_key);
470 key_free(authctxt->last_key);
471 }
472 authctxt->last_key = NULL;
473 authctxt->last_key_hint = -2;
474 authctxt->last_key_sign = NULL;
475}
476
477int
478sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
479{
480 Buffer b;
481 u_char *blob, *signature;
482 int bloblen, slen;
483 int skip = 0;
484 int ret = -1;
485 int have_sig = 1;
486
487 debug3("sign_and_send_pubkey");
488
489 if (key_to_blob(k, &blob, &bloblen) == 0) {
490 /* we cannot handle this key */
491 debug3("sign_and_send_pubkey: cannot handle key");
492 return 0;
493 }
494 /* data to be signed */
495 buffer_init(&b);
496 if (datafellows & SSH_OLD_SESSIONID) {
497 buffer_append(&b, session_id2, session_id2_len);
498 skip = session_id2_len;
499 } else {
500 buffer_put_string(&b, session_id2, session_id2_len);
501 skip = buffer_len(&b);
502 }
503 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
504 buffer_put_cstring(&b, authctxt->server_user);
505 buffer_put_cstring(&b,
506 datafellows & SSH_BUG_PKSERVICE ?
507 "ssh-userauth" :
508 authctxt->service);
509 if (datafellows & SSH_BUG_PKAUTH) {
510 buffer_put_char(&b, have_sig);
511 } else {
512 buffer_put_cstring(&b, authctxt->method->name);
513 buffer_put_char(&b, have_sig);
514 buffer_put_cstring(&b, key_ssh_name(k));
515 }
516 buffer_put_string(&b, blob, bloblen);
517
518 /* generate signature */
519 ret = (*sign_callback)(authctxt, k, &signature, &slen,
520 buffer_ptr(&b), buffer_len(&b));
521 if (ret == -1) {
522 xfree(blob);
523 buffer_free(&b);
524 return 0;
525 }
526#ifdef DEBUG_PK
527 buffer_dump(&b);
528#endif
529 if (datafellows & SSH_BUG_PKSERVICE) {
530 buffer_clear(&b);
531 buffer_append(&b, session_id2, session_id2_len);
532 skip = session_id2_len;
533 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
534 buffer_put_cstring(&b, authctxt->server_user);
535 buffer_put_cstring(&b, authctxt->service);
536 buffer_put_cstring(&b, authctxt->method->name);
537 buffer_put_char(&b, have_sig);
538 if (!(datafellows & SSH_BUG_PKAUTH))
539 buffer_put_cstring(&b, key_ssh_name(k));
540 buffer_put_string(&b, blob, bloblen);
541 }
542 xfree(blob);
543
544 /* append signature */
545 buffer_put_string(&b, signature, slen);
546 xfree(signature);
547
548 /* skip session id and packet type */
549 if (buffer_len(&b) < skip + 1)
550 fatal("userauth_pubkey: internal error");
551 buffer_consume(&b, skip + 1);
552
553 /* put remaining data from buffer into packet */
554 packet_start(SSH2_MSG_USERAUTH_REQUEST);
555 packet_put_raw(buffer_ptr(&b), buffer_len(&b));
556 buffer_free(&b);
557 packet_send();
558
559 return 1;
560}
561
562int
563send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback,
564 int hint)
565{
566 u_char *blob;
567 int bloblen, have_sig = 0;
568
569 debug3("send_pubkey_test");
570
571 if (key_to_blob(k, &blob, &bloblen) == 0) {
572 /* we cannot handle this key */
573 debug3("send_pubkey_test: cannot handle key");
574 return 0;
575 }
576 /* register callback for USERAUTH_PK_OK message */
577 authctxt->last_key_sign = sign_callback;
578 authctxt->last_key_hint = hint;
579 authctxt->last_key = k;
580 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
581
582 packet_start(SSH2_MSG_USERAUTH_REQUEST);
583 packet_put_cstring(authctxt->server_user);
584 packet_put_cstring(authctxt->service);
585 packet_put_cstring(authctxt->method->name);
586 packet_put_char(have_sig);
587 if (!(datafellows & SSH_BUG_PKAUTH))
588 packet_put_cstring(key_ssh_name(k));
589 packet_put_string(blob, bloblen);
590 xfree(blob);
591 packet_send();
592 return 1;
593}
594
595Key *
596load_identity_file(char *filename)
597{
598 Key *private;
599 char prompt[300], *passphrase;
600 int quit, i;
601 struct stat st;
602
603 if (stat(filename, &st) < 0) {
604 debug3("no such identity: %s", filename);
605 return NULL;
606 }
607 private = key_load_private_type(KEY_UNSPEC, filename, "", NULL);
608 if (private == NULL) {
609 if (options.batch_mode)
610 return NULL;
611 snprintf(prompt, sizeof prompt,
612 "Enter passphrase for key '%.100s': ", filename);
613 for (i = 0; i < options.number_of_password_prompts; i++) {
614 passphrase = read_passphrase(prompt, 0);
615 if (strcmp(passphrase, "") != 0) {
616 private = key_load_private_type(KEY_UNSPEC, filename,
617 passphrase, NULL);
618 quit = 0;
619 } else {
620 debug2("no passphrase given, try next key");
621 quit = 1;
622 }
623 memset(passphrase, 0, strlen(passphrase));
624 xfree(passphrase);
625 if (private != NULL || quit)
626 break;
627 debug2("bad passphrase given, try again...");
628 }
629 }
630 return private;
631}
632
633int
634identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
635 u_char *data, int datalen)
636{
637 Key *private;
638 int idx, ret;
639
640 idx = authctxt->last_key_hint;
641 if (idx < 0)
642 return -1;
643 private = load_identity_file(options.identity_files[idx]);
644 if (private == NULL)
645 return -1;
646 ret = key_sign(private, sigp, lenp, data, datalen);
647 key_free(private);
648 return ret;
649}
650
651int agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
652 u_char *data, int datalen)
653{
654 return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen);
655}
656
657int key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
658 u_char *data, int datalen)
659{
660 return key_sign(key, sigp, lenp, data, datalen);
661}
662
663int
664userauth_pubkey_agent(Authctxt *authctxt)
665{
666 static int called = 0;
667 int ret = 0;
668 char *comment;
669 Key *k;
670
671 if (called == 0) {
672 if (ssh_get_num_identities(authctxt->agent, 2) == 0)
673 debug2("userauth_pubkey_agent: no keys at all");
674 called = 1;
675 }
676 k = ssh_get_next_identity(authctxt->agent, &comment, 2);
677 if (k == NULL) {
678 debug2("userauth_pubkey_agent: no more keys");
679 } else {
680 debug("userauth_pubkey_agent: testing agent key %s", comment);
681 xfree(comment);
682 ret = send_pubkey_test(authctxt, k, agent_sign_cb, -1);
683 if (ret == 0)
684 key_free(k);
685 }
686 if (ret == 0)
687 debug2("userauth_pubkey_agent: no message sent");
688 return ret;
689}
690
691int
692userauth_pubkey(Authctxt *authctxt)
693{
694 static int idx = 0;
695 int sent = 0;
696 Key *key;
697 char *filename;
698
699 if (authctxt->agent != NULL) {
700 do {
701 sent = userauth_pubkey_agent(authctxt);
702 } while(!sent && authctxt->agent->howmany > 0);
703 }
704 while (!sent && idx < options.num_identity_files) {
705 key = options.identity_keys[idx];
706 filename = options.identity_files[idx];
707 if (key == NULL) {
708 debug("try privkey: %s", filename);
709 key = load_identity_file(filename);
710 if (key != NULL) {
711 sent = sign_and_send_pubkey(authctxt, key,
712 key_sign_cb);
713 key_free(key);
714 }
715 } else if (key->type != KEY_RSA1) {
716 debug("try pubkey: %s", filename);
717 sent = send_pubkey_test(authctxt, key,
718 identity_sign_cb, idx);
719 }
720 idx++;
721 }
722 return sent;
723}
724
725/*
726 * Send userauth request message specifying keyboard-interactive method.
727 */
728int
729userauth_kbdint(Authctxt *authctxt)
730{
731 static int attempt = 0;
732
733 if (attempt++ >= options.number_of_password_prompts)
734 return 0;
735
736 debug2("userauth_kbdint");
737 packet_start(SSH2_MSG_USERAUTH_REQUEST);
738 packet_put_cstring(authctxt->server_user);
739 packet_put_cstring(authctxt->service);
740 packet_put_cstring(authctxt->method->name);
741 packet_put_cstring(""); /* lang */
742 packet_put_cstring(options.kbd_interactive_devices ?
743 options.kbd_interactive_devices : "");
744 packet_send();
745
746 dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
747 return 1;
748}
749
750/*
751 * parse INFO_REQUEST, prompt user and send INFO_RESPONSE
752 */
753void
754input_userauth_info_req(int type, int plen, void *ctxt)
755{
756 Authctxt *authctxt = ctxt;
757 char *name, *inst, *lang, *prompt, *response;
758 u_int num_prompts, i;
759 int echo = 0;
760
761 debug2("input_userauth_info_req");
762
763 if (authctxt == NULL)
764 fatal("input_userauth_info_req: no authentication context");
765
766 name = packet_get_string(NULL);
767 inst = packet_get_string(NULL);
768 lang = packet_get_string(NULL);
769 if (strlen(name) > 0)
770 cli_mesg(name);
771 if (strlen(inst) > 0)
772 cli_mesg(inst);
773 xfree(name);
774 xfree(inst);
775 xfree(lang);
776
777 num_prompts = packet_get_int();
778 /*
779 * Begin to build info response packet based on prompts requested.
780 * We commit to providing the correct number of responses, so if
781 * further on we run into a problem that prevents this, we have to
782 * be sure and clean this up and send a correct error response.
783 */
784 packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
785 packet_put_int(num_prompts);
786
787 for (i = 0; i < num_prompts; i++) {
788 prompt = packet_get_string(NULL);
789 echo = packet_get_char();
790
791 response = cli_prompt(prompt, echo);
792
793 packet_put_cstring(response);
794 memset(response, 0, strlen(response));
795 xfree(response);
796 xfree(prompt);
797 }
798 packet_done(); /* done with parsing incoming message. */
799
800 packet_inject_ignore(64);
801 packet_send();
802}
803
804/*
805 * this will be move to an external program (ssh-keysign) ASAP. ssh-keysign
806 * will be setuid-root and the sbit can be removed from /usr/bin/ssh.
807 */
808int
809userauth_hostbased(Authctxt *authctxt)
810{
811 Key *private = NULL;
812 Buffer b;
813 u_char *signature, *blob;
814 char *chost, *pkalg, *p;
815 const char *service;
816 u_int blen, slen;
817 int ok, i, len, found = 0;
818
819 p = get_local_name(packet_get_connection_in());
820 if (p == NULL) {
821 error("userauth_hostbased: cannot get local ipaddr/name");
822 return 0;
823 }
824 len = strlen(p) + 2;
825 chost = xmalloc(len);
826 strlcpy(chost, p, len);
827 strlcat(chost, ".", len);
828 debug2("userauth_hostbased: chost %s", chost);
829 /* check for a useful key */
830 for (i = 0; i < authctxt->nkeys; i++) {
831 private = authctxt->keys[i];
832 if (private && private->type != KEY_RSA1) {
833 found = 1;
834 /* we take and free the key */
835 authctxt->keys[i] = NULL;
836 break;
837 }
838 }
839 if (!found) {
840 xfree(chost);
841 return 0;
842 }
843 if (key_to_blob(private, &blob, &blen) == 0) {
844 key_free(private);
845 xfree(chost);
846 return 0;
847 }
848 service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
849 authctxt->service;
850 pkalg = xstrdup(key_ssh_name(private));
851 buffer_init(&b);
852 /* construct data */
853 buffer_put_string(&b, session_id2, session_id2_len);
854 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
855 buffer_put_cstring(&b, authctxt->server_user);
856 buffer_put_cstring(&b, service);
857 buffer_put_cstring(&b, authctxt->method->name);
858 buffer_put_cstring(&b, pkalg);
859 buffer_put_string(&b, blob, blen);
860 buffer_put_cstring(&b, chost);
861 buffer_put_cstring(&b, authctxt->local_user);
862#ifdef DEBUG_PK
863 buffer_dump(&b);
864#endif
865 debug2("xxx: chost %s", chost);
866 ok = key_sign(private, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
867 key_free(private);
868 buffer_free(&b);
869 if (ok != 0) {
870 error("key_sign failed");
871 xfree(chost);
872 xfree(pkalg);
873 return 0;
874 }
875 packet_start(SSH2_MSG_USERAUTH_REQUEST);
876 packet_put_cstring(authctxt->server_user);
877 packet_put_cstring(authctxt->service);
878 packet_put_cstring(authctxt->method->name);
879 packet_put_cstring(pkalg);
880 packet_put_string(blob, blen);
881 packet_put_cstring(chost);
882 packet_put_cstring(authctxt->local_user);
883 packet_put_string(signature, slen);
884 memset(signature, 's', slen);
885 xfree(signature);
886 xfree(chost);
887 xfree(pkalg);
888
889 packet_send();
890 return 1;
891}
892
893/* find auth method */
894
895/*
896 * given auth method name, if configurable options permit this method fill
897 * in auth_ident field and return true, otherwise return false.
898 */
899int
900authmethod_is_enabled(Authmethod *method)
901{
902 if (method == NULL)
903 return 0;
904 /* return false if options indicate this method is disabled */
905 if (method->enabled == NULL || *method->enabled == 0)
906 return 0;
907 /* return false if batch mode is enabled but method needs interactive mode */
908 if (method->batch_flag != NULL && *method->batch_flag != 0)
909 return 0;
910 return 1;
911}
912
913Authmethod *
914authmethod_lookup(const char *name)
915{
916 Authmethod *method = NULL;
917 if (name != NULL)
918 for (method = authmethods; method->name != NULL; method++)
919 if (strcmp(name, method->name) == 0)
920 return method;
921 debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
922 return NULL;
923}
924
925/* XXX internal state */
926static Authmethod *current = NULL;
927static char *supported = NULL;
928static char *preferred = NULL;
929/*
930 * Given the authentication method list sent by the server, return the
931 * next method we should try. If the server initially sends a nil list,
932 * use a built-in default list.
933 */
934Authmethod *
935authmethod_get(char *authlist)
936{
937
938 char *name = NULL;
939 int next;
940
941 /* Use a suitable default if we're passed a nil list. */
942 if (authlist == NULL || strlen(authlist) == 0)
943 authlist = options.preferred_authentications;
944
945 if (supported == NULL || strcmp(authlist, supported) != 0) {
946 debug3("start over, passed a different list %s", authlist);
947 if (supported != NULL)
948 xfree(supported);
949 supported = xstrdup(authlist);
950 preferred = options.preferred_authentications;
951 debug3("preferred %s", preferred);
952 current = NULL;
953 } else if (current != NULL && authmethod_is_enabled(current))
954 return current;
955
956 for (;;) {
957 if ((name = match_list(preferred, supported, &next)) == NULL) {
958 debug("no more auth methods to try");
959 current = NULL;
960 return NULL;
961 }
962 preferred += next;
963 debug3("authmethod_lookup %s", name);
964 debug3("remaining preferred: %s", preferred);
965 if ((current = authmethod_lookup(name)) != NULL &&
966 authmethod_is_enabled(current)) {
967 debug3("authmethod_is_enabled %s", name);
968 debug("next auth method to try is %s", name);
969 return current;
970 }
971 }
972}
973
974
975#define DELIM ","
976char *
977authmethods_get(void)
978{
979 Authmethod *method = NULL;
980 char buf[1024];
981
982 buf[0] = '\0';
983 for (method = authmethods; method->name != NULL; method++) {
984 if (authmethod_is_enabled(method)) {
985 if (buf[0] != '\0')
986 strlcat(buf, DELIM, sizeof buf);
987 strlcat(buf, method->name, sizeof buf);
988 }
989 }
990 return xstrdup(buf);
991}