Annotation of src/usr.bin/ssh/sshconnect2.c, Revision 1.60
1.1 markus 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"
1.60 ! stevesk 26: RCSID("$OpenBSD: sshconnect2.c,v 1.59 2001/03/29 14:24:59 provos Exp $");
1.1 markus 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"
1.37 markus 34: #include "ssh2.h"
1.1 markus 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"
1.37 markus 42: #include "cipher.h"
1.1 markus 43: #include "kex.h"
44: #include "myproposal.h"
45: #include "key.h"
46: #include "sshconnect.h"
47: #include "authfile.h"
1.23 markus 48: #include "cli.h"
1.57 provos 49: #include "dh.h"
1.20 markus 50: #include "dispatch.h"
1.17 markus 51: #include "authfd.h"
1.37 markus 52: #include "log.h"
53: #include "readconf.h"
54: #include "readpass.h"
1.53 markus 55: #include "match.h"
1.1 markus 56:
1.22 provos 57: void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
58: void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
59:
1.1 markus 60: /* import */
61: extern char *client_version_string;
62: extern char *server_version_string;
63: extern Options options;
64:
65: /*
66: * SSH2 key exchange
67: */
68:
1.32 markus 69: u_char *session_id2 = NULL;
1.1 markus 70: int session_id2_len = 0;
71:
72: void
1.22 provos 73: ssh_kex2(char *host, struct sockaddr *hostaddr)
74: {
75: int i, plen;
76: Kex *kex;
77: Buffer *client_kexinit, *server_kexinit;
78: char *sprop[PROPOSAL_MAX];
79:
1.29 markus 80: if (options.ciphers == (char *)-1) {
81: log("No valid ciphers for protocol version 2 given, using defaults.");
82: options.ciphers = NULL;
1.24 markus 83: }
1.22 provos 84: if (options.ciphers != NULL) {
85: myproposal[PROPOSAL_ENC_ALGS_CTOS] =
86: myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
87: }
1.60 ! stevesk 88: myproposal[PROPOSAL_ENC_ALGS_CTOS] =
! 89: compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
! 90: myproposal[PROPOSAL_ENC_ALGS_STOC] =
! 91: compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
1.22 provos 92: if (options.compression) {
1.47 markus 93: myproposal[PROPOSAL_COMP_ALGS_CTOS] =
1.22 provos 94: myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
95: } else {
1.47 markus 96: myproposal[PROPOSAL_COMP_ALGS_CTOS] =
1.22 provos 97: myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
1.47 markus 98: }
99: if (options.macs != NULL) {
100: myproposal[PROPOSAL_MAC_ALGS_CTOS] =
101: myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
1.22 provos 102: }
103:
104: /* buffers with raw kexinit messages */
105: server_kexinit = xmalloc(sizeof(*server_kexinit));
106: buffer_init(server_kexinit);
107: client_kexinit = kex_init(myproposal);
108:
109: /* algorithm negotiation */
110: kex_exchange_kexinit(client_kexinit, server_kexinit, sprop);
111: kex = kex_choose_conf(myproposal, sprop, 0);
112: for (i = 0; i < PROPOSAL_MAX; i++)
113: xfree(sprop[i]);
114:
115: /* server authentication and session key agreement */
116: switch(kex->kex_type) {
117: case DH_GRP1_SHA1:
118: ssh_dh1_client(kex, host, hostaddr,
119: client_kexinit, server_kexinit);
120: break;
121: case DH_GEX_SHA1:
122: ssh_dhgex_client(kex, host, hostaddr, client_kexinit,
123: server_kexinit);
124: break;
125: default:
126: fatal("Unsupported key exchange %d", kex->kex_type);
127: }
128:
129: buffer_free(client_kexinit);
130: buffer_free(server_kexinit);
131: xfree(client_kexinit);
132: xfree(server_kexinit);
133:
134: debug("Wait SSH2_MSG_NEWKEYS.");
135: packet_read_expect(&plen, SSH2_MSG_NEWKEYS);
136: packet_done();
137: debug("GOT SSH2_MSG_NEWKEYS.");
138:
139: debug("send SSH2_MSG_NEWKEYS.");
140: packet_start(SSH2_MSG_NEWKEYS);
141: packet_send();
142: packet_write_wait();
143: debug("done: send SSH2_MSG_NEWKEYS.");
144:
145: #ifdef DEBUG_KEXDH
146: /* send 1st encrypted/maced/compressed message */
147: packet_start(SSH2_MSG_IGNORE);
148: packet_put_cstring("markus");
149: packet_send();
150: packet_write_wait();
151: #endif
152: debug("done: KEX2.");
153: }
154:
155: /* diffie-hellman-group1-sha1 */
156:
157: void
1.41 stevesk 158: ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr,
1.22 provos 159: Buffer *client_kexinit, Buffer *server_kexinit)
1.1 markus 160: {
1.19 markus 161: #ifdef DEBUG_KEXDH
162: int i;
163: #endif
1.11 markus 164: int plen, dlen;
1.32 markus 165: u_int klen, kout;
1.1 markus 166: char *signature = NULL;
1.32 markus 167: u_int slen;
1.1 markus 168: char *server_host_key_blob = NULL;
169: Key *server_host_key;
1.32 markus 170: u_int sbloblen;
1.1 markus 171: DH *dh;
172: BIGNUM *dh_server_pub = 0;
173: BIGNUM *shared_secret = 0;
1.32 markus 174: u_char *kbuf;
175: u_char *hash;
1.1 markus 176:
177: debug("Sending SSH2_MSG_KEXDH_INIT.");
178: /* generate and send 'e', client DH public key */
179: dh = dh_new_group1();
1.50 markus 180: dh_gen_key(dh, kex->we_need * 8);
1.1 markus 181: packet_start(SSH2_MSG_KEXDH_INIT);
182: packet_put_bignum2(dh->pub_key);
183: packet_send();
184: packet_write_wait();
185:
186: #ifdef DEBUG_KEXDH
187: fprintf(stderr, "\np= ");
1.19 markus 188: BN_print_fp(stderr, dh->p);
1.1 markus 189: fprintf(stderr, "\ng= ");
1.19 markus 190: BN_print_fp(stderr, dh->g);
1.1 markus 191: fprintf(stderr, "\npub= ");
1.19 markus 192: BN_print_fp(stderr, dh->pub_key);
1.1 markus 193: fprintf(stderr, "\n");
194: DHparams_print_fp(stderr, dh);
195: #endif
196:
197: debug("Wait SSH2_MSG_KEXDH_REPLY.");
198:
1.11 markus 199: packet_read_expect(&plen, SSH2_MSG_KEXDH_REPLY);
1.1 markus 200:
201: debug("Got SSH2_MSG_KEXDH_REPLY.");
202:
203: /* key, cert */
204: server_host_key_blob = packet_get_string(&sbloblen);
1.28 markus 205: server_host_key = key_from_blob(server_host_key_blob, sbloblen);
1.1 markus 206: if (server_host_key == NULL)
207: fatal("cannot decode server_host_key_blob");
208:
209: check_host_key(host, hostaddr, server_host_key,
1.22 provos 210: options.user_hostfile2, options.system_hostfile2);
1.1 markus 211:
212: /* DH paramter f, server public DH key */
213: dh_server_pub = BN_new();
214: if (dh_server_pub == NULL)
215: fatal("dh_server_pub == NULL");
216: packet_get_bignum2(dh_server_pub, &dlen);
217:
218: #ifdef DEBUG_KEXDH
219: fprintf(stderr, "\ndh_server_pub= ");
1.19 markus 220: BN_print_fp(stderr, dh_server_pub);
1.1 markus 221: fprintf(stderr, "\n");
222: debug("bits %d", BN_num_bits(dh_server_pub));
223: #endif
224:
225: /* signed H */
226: signature = packet_get_string(&slen);
227: packet_done();
228:
229: if (!dh_pub_is_valid(dh, dh_server_pub))
230: packet_disconnect("bad server public DH value");
231:
232: klen = DH_size(dh);
233: kbuf = xmalloc(klen);
234: kout = DH_compute_key(kbuf, dh_server_pub, dh);
235: #ifdef DEBUG_KEXDH
236: debug("shared secret: len %d/%d", klen, kout);
237: fprintf(stderr, "shared secret == ");
238: for (i = 0; i< kout; i++)
239: fprintf(stderr, "%02x", (kbuf[i])&0xff);
240: fprintf(stderr, "\n");
241: #endif
242: shared_secret = BN_new();
243:
244: BN_bin2bn(kbuf, kout, shared_secret);
245: memset(kbuf, 0, klen);
246: xfree(kbuf);
247:
248: /* calc and verify H */
249: hash = kex_hash(
250: client_version_string,
251: server_version_string,
252: buffer_ptr(client_kexinit), buffer_len(client_kexinit),
253: buffer_ptr(server_kexinit), buffer_len(server_kexinit),
254: server_host_key_blob, sbloblen,
255: dh->pub_key,
256: dh_server_pub,
257: shared_secret
258: );
1.3 markus 259: xfree(server_host_key_blob);
1.11 markus 260: DH_free(dh);
1.38 stevesk 261: BN_free(dh_server_pub);
1.1 markus 262: #ifdef DEBUG_KEXDH
263: fprintf(stderr, "hash == ");
264: for (i = 0; i< 20; i++)
265: fprintf(stderr, "%02x", (hash[i])&0xff);
266: fprintf(stderr, "\n");
267: #endif
1.32 markus 268: if (key_verify(server_host_key, (u_char *)signature, slen, hash, 20) != 1)
1.28 markus 269: fatal("key_verify failed for server_host_key");
1.1 markus 270: key_free(server_host_key);
1.38 stevesk 271: xfree(signature);
1.1 markus 272:
273: kex_derive_keys(kex, hash, shared_secret);
1.38 stevesk 274: BN_clear_free(shared_secret);
1.1 markus 275: packet_set_kex(kex);
276:
277: /* save session id */
278: session_id2_len = 20;
279: session_id2 = xmalloc(session_id2_len);
280: memcpy(session_id2, hash, session_id2_len);
1.11 markus 281: }
282:
1.22 provos 283: /* diffie-hellman-group-exchange-sha1 */
284:
285: /*
286: * Estimates the group order for a Diffie-Hellman group that has an
287: * attack complexity approximately the same as O(2**bits). Estimate
288: * with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
289: */
290:
291: int
292: dh_estimate(int bits)
293: {
1.41 stevesk 294:
1.22 provos 295: if (bits < 64)
296: return (512); /* O(2**63) */
297: if (bits < 128)
298: return (1024); /* O(2**86) */
299: if (bits < 192)
300: return (2048); /* O(2**116) */
301: return (4096); /* O(2**156) */
302: }
303:
1.11 markus 304: void
1.22 provos 305: ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
306: Buffer *client_kexinit, Buffer *server_kexinit)
1.11 markus 307: {
1.22 provos 308: #ifdef DEBUG_KEXDH
309: int i;
310: #endif
311: int plen, dlen;
1.32 markus 312: u_int klen, kout;
1.22 provos 313: char *signature = NULL;
1.57 provos 314: u_int slen, nbits, min, max;
1.22 provos 315: char *server_host_key_blob = NULL;
316: Key *server_host_key;
1.32 markus 317: u_int sbloblen;
1.22 provos 318: DH *dh;
319: BIGNUM *dh_server_pub = 0;
320: BIGNUM *shared_secret = 0;
321: BIGNUM *p = 0, *g = 0;
1.32 markus 322: u_char *kbuf;
323: u_char *hash;
1.22 provos 324:
1.50 markus 325: nbits = dh_estimate(kex->we_need * 8);
1.22 provos 326:
1.57 provos 327: if (datafellows & SSH_OLD_DHGEX) {
328: debug("Sending SSH2_MSG_KEX_DH_GEX_REQUEST_OLD.");
329:
330: /* Old GEX request */
331: packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
332: packet_put_int(nbits);
333: min = DH_GRP_MIN;
334: max = DH_GRP_MAX;
335: } else {
336: debug("Sending SSH2_MSG_KEX_DH_GEX_REQUEST.");
337:
338: /* New GEX request */
339: min = DH_GRP_MIN;
1.59 provos 340: max = DH_GRP_MAX;
1.57 provos 341:
342: packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
343: packet_put_int(min);
344: packet_put_int(nbits);
345: packet_put_int(max);
346: }
1.22 provos 347: packet_send();
348: packet_write_wait();
1.11 markus 349:
1.22 provos 350: #ifdef DEBUG_KEXDH
1.57 provos 351: fprintf(stderr, "\nmin = %d, nbits = %d, max = %d", min, nbits, max);
1.22 provos 352: #endif
1.11 markus 353:
1.22 provos 354: debug("Wait SSH2_MSG_KEX_DH_GEX_GROUP.");
1.11 markus 355:
1.22 provos 356: packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_GROUP);
1.11 markus 357:
1.22 provos 358: debug("Got SSH2_MSG_KEX_DH_GEX_GROUP.");
1.11 markus 359:
1.22 provos 360: if ((p = BN_new()) == NULL)
361: fatal("BN_new");
362: packet_get_bignum2(p, &dlen);
363: if ((g = BN_new()) == NULL)
364: fatal("BN_new");
365: packet_get_bignum2(g, &dlen);
1.57 provos 366:
367: if (BN_num_bits(p) < min || BN_num_bits(p) > max)
368: fatal("DH_GEX group out of range: %d !< %d !< %d",
369: min, BN_num_bits(p), max);
370:
1.36 stevesk 371: dh = dh_new_group(g, p);
1.31 provos 372:
1.50 markus 373: dh_gen_key(dh, kex->we_need * 8);
1.1 markus 374:
1.22 provos 375: #ifdef DEBUG_KEXDH
376: fprintf(stderr, "\np= ");
377: BN_print_fp(stderr, dh->p);
378: fprintf(stderr, "\ng= ");
379: BN_print_fp(stderr, dh->g);
380: fprintf(stderr, "\npub= ");
381: BN_print_fp(stderr, dh->pub_key);
382: fprintf(stderr, "\n");
383: DHparams_print_fp(stderr, dh);
384: #endif
1.1 markus 385:
1.22 provos 386: debug("Sending SSH2_MSG_KEX_DH_GEX_INIT.");
387: /* generate and send 'e', client DH public key */
388: packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
389: packet_put_bignum2(dh->pub_key);
1.1 markus 390: packet_send();
391: packet_write_wait();
392:
1.22 provos 393: debug("Wait SSH2_MSG_KEX_DH_GEX_REPLY.");
394:
395: packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_REPLY);
396:
397: debug("Got SSH2_MSG_KEXDH_REPLY.");
398:
399: /* key, cert */
400: server_host_key_blob = packet_get_string(&sbloblen);
1.28 markus 401: server_host_key = key_from_blob(server_host_key_blob, sbloblen);
1.22 provos 402: if (server_host_key == NULL)
403: fatal("cannot decode server_host_key_blob");
404:
405: check_host_key(host, hostaddr, server_host_key,
406: options.user_hostfile2, options.system_hostfile2);
407:
408: /* DH paramter f, server public DH key */
409: dh_server_pub = BN_new();
410: if (dh_server_pub == NULL)
411: fatal("dh_server_pub == NULL");
412: packet_get_bignum2(dh_server_pub, &dlen);
413:
414: #ifdef DEBUG_KEXDH
415: fprintf(stderr, "\ndh_server_pub= ");
416: BN_print_fp(stderr, dh_server_pub);
417: fprintf(stderr, "\n");
418: debug("bits %d", BN_num_bits(dh_server_pub));
419: #endif
420:
421: /* signed H */
422: signature = packet_get_string(&slen);
423: packet_done();
424:
425: if (!dh_pub_is_valid(dh, dh_server_pub))
426: packet_disconnect("bad server public DH value");
427:
428: klen = DH_size(dh);
429: kbuf = xmalloc(klen);
430: kout = DH_compute_key(kbuf, dh_server_pub, dh);
431: #ifdef DEBUG_KEXDH
432: debug("shared secret: len %d/%d", klen, kout);
433: fprintf(stderr, "shared secret == ");
434: for (i = 0; i< kout; i++)
435: fprintf(stderr, "%02x", (kbuf[i])&0xff);
436: fprintf(stderr, "\n");
437: #endif
438: shared_secret = BN_new();
439:
440: BN_bin2bn(kbuf, kout, shared_secret);
441: memset(kbuf, 0, klen);
442: xfree(kbuf);
443:
1.58 provos 444: if (datafellows & SSH_OLD_DHGEX) {
445: /* These values are not included in the hash */
446: min = -1;
447: max = -1;
448: }
449:
1.22 provos 450: /* calc and verify H */
451: hash = kex_hash_gex(
452: client_version_string,
453: server_version_string,
454: buffer_ptr(client_kexinit), buffer_len(client_kexinit),
455: buffer_ptr(server_kexinit), buffer_len(server_kexinit),
456: server_host_key_blob, sbloblen,
1.58 provos 457: min, nbits, max,
458: dh->p, dh->g,
1.22 provos 459: dh->pub_key,
460: dh_server_pub,
461: shared_secret
462: );
463: xfree(server_host_key_blob);
464: DH_free(dh);
1.38 stevesk 465: BN_free(dh_server_pub);
1.1 markus 466: #ifdef DEBUG_KEXDH
1.22 provos 467: fprintf(stderr, "hash == ");
468: for (i = 0; i< 20; i++)
469: fprintf(stderr, "%02x", (hash[i])&0xff);
470: fprintf(stderr, "\n");
1.1 markus 471: #endif
1.32 markus 472: if (key_verify(server_host_key, (u_char *)signature, slen, hash, 20) != 1)
1.28 markus 473: fatal("key_verify failed for server_host_key");
1.22 provos 474: key_free(server_host_key);
1.38 stevesk 475: xfree(signature);
1.22 provos 476:
477: kex_derive_keys(kex, hash, shared_secret);
1.38 stevesk 478: BN_clear_free(shared_secret);
1.22 provos 479: packet_set_kex(kex);
480:
481: /* save session id */
482: session_id2_len = 20;
483: session_id2 = xmalloc(session_id2_len);
484: memcpy(session_id2, hash, session_id2_len);
1.1 markus 485: }
1.11 markus 486:
1.1 markus 487: /*
488: * Authenticate user
489: */
1.20 markus 490:
491: typedef struct Authctxt Authctxt;
492: typedef struct Authmethod Authmethod;
493:
494: typedef int sign_cb_fn(
495: Authctxt *authctxt, Key *key,
1.32 markus 496: u_char **sigp, int *lenp, u_char *data, int datalen);
1.20 markus 497:
498: struct Authctxt {
499: const char *server_user;
500: const char *host;
501: const char *service;
502: AuthenticationConnection *agent;
1.23 markus 503: Authmethod *method;
1.20 markus 504: int success;
1.51 markus 505: char *authlist;
506: Key *last_key;
507: sign_cb_fn *last_key_sign;
508: int last_key_hint;
1.20 markus 509: };
510: struct Authmethod {
511: char *name; /* string to compare against server's list */
512: int (*userauth)(Authctxt *authctxt);
513: int *enabled; /* flag in option struct that enables method */
514: int *batch_flag; /* flag in option struct that disables method */
515: };
516:
517: void input_userauth_success(int type, int plen, void *ctxt);
518: void input_userauth_failure(int type, int plen, void *ctxt);
1.35 markus 519: void input_userauth_banner(int type, int plen, void *ctxt);
1.20 markus 520: void input_userauth_error(int type, int plen, void *ctxt);
1.23 markus 521: void input_userauth_info_req(int type, int plen, void *ctxt);
1.51 markus 522: void input_userauth_pk_ok(int type, int plen, void *ctxt);
1.23 markus 523:
524: int userauth_none(Authctxt *authctxt);
1.20 markus 525: int userauth_pubkey(Authctxt *authctxt);
526: int userauth_passwd(Authctxt *authctxt);
1.23 markus 527: int userauth_kbdint(Authctxt *authctxt);
1.20 markus 528:
1.51 markus 529: void userauth(Authctxt *authctxt, char *authlist);
530:
531: int
532: sign_and_send_pubkey(Authctxt *authctxt, Key *k,
533: sign_cb_fn *sign_callback);
534: void clear_auth_state(Authctxt *authctxt);
535:
1.23 markus 536: Authmethod *authmethod_get(char *authlist);
537: Authmethod *authmethod_lookup(const char *name);
1.53 markus 538: char *authmethods_get(void);
1.20 markus 539:
540: Authmethod authmethods[] = {
541: {"publickey",
542: userauth_pubkey,
1.28 markus 543: &options.pubkey_authentication,
1.20 markus 544: NULL},
545: {"password",
546: userauth_passwd,
547: &options.password_authentication,
548: &options.batch_mode},
1.23 markus 549: {"keyboard-interactive",
550: userauth_kbdint,
551: &options.kbd_interactive_authentication,
552: &options.batch_mode},
553: {"none",
554: userauth_none,
555: NULL,
556: NULL},
1.20 markus 557: {NULL, NULL, NULL, NULL}
558: };
559:
560: void
561: ssh_userauth2(const char *server_user, char *host)
562: {
563: Authctxt authctxt;
564: int type;
565: int plen;
1.39 markus 566:
567: if (options.challenge_reponse_authentication)
568: options.kbd_interactive_authentication = 1;
1.20 markus 569:
570: debug("send SSH2_MSG_SERVICE_REQUEST");
571: packet_start(SSH2_MSG_SERVICE_REQUEST);
572: packet_put_cstring("ssh-userauth");
573: packet_send();
574: packet_write_wait();
575: type = packet_read(&plen);
576: if (type != SSH2_MSG_SERVICE_ACCEPT) {
577: fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type);
578: }
579: if (packet_remaining() > 0) {
580: char *reply = packet_get_string(&plen);
581: debug("service_accept: %s", reply);
582: xfree(reply);
583: } else {
584: debug("buggy server: service_accept w/o service");
585: }
586: packet_done();
587: debug("got SSH2_MSG_SERVICE_ACCEPT");
588:
1.53 markus 589: if (options.preferred_authentications == NULL)
590: options.preferred_authentications = authmethods_get();
591:
1.20 markus 592: /* setup authentication context */
593: authctxt.agent = ssh_get_authentication_connection();
594: authctxt.server_user = server_user;
595: authctxt.host = host;
596: authctxt.service = "ssh-connection"; /* service name */
597: authctxt.success = 0;
1.23 markus 598: authctxt.method = authmethod_lookup("none");
1.51 markus 599: authctxt.authlist = NULL;
1.23 markus 600: if (authctxt.method == NULL)
601: fatal("ssh_userauth2: internal error: cannot send userauth none request");
1.20 markus 602:
603: /* initial userauth request */
1.23 markus 604: userauth_none(&authctxt);
1.20 markus 605:
606: dispatch_init(&input_userauth_error);
607: dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
608: dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
1.35 markus 609: dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
1.20 markus 610: dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
611:
612: if (authctxt.agent != NULL)
613: ssh_close_authentication_connection(authctxt.agent);
614:
1.34 markus 615: debug("ssh-userauth2 successful: method %s", authctxt.method->name);
1.20 markus 616: }
617: void
1.51 markus 618: userauth(Authctxt *authctxt, char *authlist)
619: {
620: if (authlist == NULL) {
621: authlist = authctxt->authlist;
622: } else {
623: if (authctxt->authlist)
624: xfree(authctxt->authlist);
625: authctxt->authlist = authlist;
626: }
627: for (;;) {
628: Authmethod *method = authmethod_get(authlist);
629: if (method == NULL)
630: fatal("Permission denied (%s).", authlist);
631: authctxt->method = method;
632: if (method->userauth(authctxt) != 0) {
633: debug2("we sent a %s packet, wait for reply", method->name);
634: break;
635: } else {
636: debug2("we did not send a packet, disable method");
637: method->enabled = NULL;
638: }
639: }
640: }
641: void
1.20 markus 642: input_userauth_error(int type, int plen, void *ctxt)
643: {
1.35 markus 644: fatal("input_userauth_error: bad message during authentication: "
645: "type %d", type);
646: }
647: void
648: input_userauth_banner(int type, int plen, void *ctxt)
649: {
650: char *msg, *lang;
651: debug3("input_userauth_banner");
652: msg = packet_get_string(NULL);
653: lang = packet_get_string(NULL);
654: fprintf(stderr, "%s", msg);
655: xfree(msg);
656: xfree(lang);
1.20 markus 657: }
658: void
659: input_userauth_success(int type, int plen, void *ctxt)
660: {
661: Authctxt *authctxt = ctxt;
662: if (authctxt == NULL)
663: fatal("input_userauth_success: no authentication context");
1.51 markus 664: if (authctxt->authlist)
665: xfree(authctxt->authlist);
666: clear_auth_state(authctxt);
1.20 markus 667: authctxt->success = 1; /* break out */
668: }
669: void
670: input_userauth_failure(int type, int plen, void *ctxt)
671: {
672: Authctxt *authctxt = ctxt;
673: char *authlist = NULL;
674: int partial;
675:
676: if (authctxt == NULL)
677: fatal("input_userauth_failure: no authentication context");
678:
1.23 markus 679: authlist = packet_get_string(NULL);
1.20 markus 680: partial = packet_get_char();
681: packet_done();
682:
683: if (partial != 0)
1.45 markus 684: log("Authenticated with partial success.");
1.20 markus 685: debug("authentications that can continue: %s", authlist);
686:
1.51 markus 687: clear_auth_state(authctxt);
688: userauth(authctxt, authlist);
689: }
690: void
691: input_userauth_pk_ok(int type, int plen, void *ctxt)
692: {
693: Authctxt *authctxt = ctxt;
694: Key *key = NULL;
695: Buffer b;
696: int alen, blen, pktype, sent = 0;
1.54 markus 697: char *pkalg, *pkblob, *fp;
1.51 markus 698:
699: if (authctxt == NULL)
700: fatal("input_userauth_pk_ok: no authentication context");
701: if (datafellows & SSH_BUG_PKOK) {
702: /* this is similar to SSH_BUG_PKAUTH */
703: debug2("input_userauth_pk_ok: SSH_BUG_PKOK");
704: pkblob = packet_get_string(&blen);
705: buffer_init(&b);
706: buffer_append(&b, pkblob, blen);
707: pkalg = buffer_get_string(&b, &alen);
708: buffer_free(&b);
709: } else {
710: pkalg = packet_get_string(&alen);
711: pkblob = packet_get_string(&blen);
712: }
713: packet_done();
714:
715: debug("input_userauth_pk_ok: pkalg %s blen %d lastkey %p hint %d",
716: pkalg, blen, authctxt->last_key, authctxt->last_key_hint);
717:
718: do {
719: if (authctxt->last_key == NULL ||
720: authctxt->last_key_sign == NULL) {
721: debug("no last key or no sign cb");
722: break;
723: }
724: if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
725: debug("unknown pkalg %s", pkalg);
726: break;
727: }
728: if ((key = key_from_blob(pkblob, blen)) == NULL) {
729: debug("no key from blob. pkalg %s", pkalg);
730: break;
731: }
1.54 markus 732: fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
733: debug2("input_userauth_pk_ok: fp %s", fp);
734: xfree(fp);
1.51 markus 735: if (!key_equal(key, authctxt->last_key)) {
736: debug("key != last_key");
1.20 markus 737: break;
738: }
1.51 markus 739: sent = sign_and_send_pubkey(authctxt, key,
740: authctxt->last_key_sign);
741: } while(0);
742:
743: if (key != NULL)
744: key_free(key);
745: xfree(pkalg);
746: xfree(pkblob);
747:
748: /* unregister */
749: clear_auth_state(authctxt);
750: dispatch_set(SSH2_MSG_USERAUTH_PK_OK, NULL);
751:
752: /* try another method if we did not send a packet*/
753: if (sent == 0)
754: userauth(authctxt, NULL);
755:
1.20 markus 756: }
757:
1.1 markus 758: int
1.23 markus 759: userauth_none(Authctxt *authctxt)
760: {
761: /* initial userauth request */
762: packet_start(SSH2_MSG_USERAUTH_REQUEST);
763: packet_put_cstring(authctxt->server_user);
764: packet_put_cstring(authctxt->service);
765: packet_put_cstring(authctxt->method->name);
766: packet_send();
767: return 1;
768: }
769:
770: int
1.20 markus 771: userauth_passwd(Authctxt *authctxt)
1.1 markus 772: {
1.6 markus 773: static int attempt = 0;
1.1 markus 774: char prompt[80];
775: char *password;
1.6 markus 776:
1.13 todd 777: if (attempt++ >= options.number_of_password_prompts)
1.6 markus 778: return 0;
1.13 todd 779:
780: if(attempt != 1)
781: error("Permission denied, please try again.");
1.1 markus 782:
1.43 itojun 783: snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
1.20 markus 784: authctxt->server_user, authctxt->host);
1.1 markus 785: password = read_passphrase(prompt, 0);
786: packet_start(SSH2_MSG_USERAUTH_REQUEST);
1.20 markus 787: packet_put_cstring(authctxt->server_user);
788: packet_put_cstring(authctxt->service);
1.23 markus 789: packet_put_cstring(authctxt->method->name);
1.1 markus 790: packet_put_char(0);
1.49 markus 791: packet_put_cstring(password);
1.1 markus 792: memset(password, 0, strlen(password));
793: xfree(password);
1.49 markus 794: packet_inject_ignore(64);
1.1 markus 795: packet_send();
796: return 1;
797: }
798:
1.51 markus 799: void
800: clear_auth_state(Authctxt *authctxt)
801: {
802: /* XXX clear authentication state */
803: if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) {
804: debug3("clear_auth_state: key_free %p", authctxt->last_key);
805: key_free(authctxt->last_key);
806: }
807: authctxt->last_key = NULL;
808: authctxt->last_key_hint = -2;
809: authctxt->last_key_sign = NULL;
810: }
811:
1.17 markus 812: int
1.20 markus 813: sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
1.1 markus 814: {
815: Buffer b;
1.32 markus 816: u_char *blob, *signature;
1.1 markus 817: int bloblen, slen;
1.14 markus 818: int skip = 0;
1.17 markus 819: int ret = -1;
1.23 markus 820: int have_sig = 1;
1.1 markus 821:
1.30 markus 822: debug3("sign_and_send_pubkey");
1.51 markus 823:
1.28 markus 824: if (key_to_blob(k, &blob, &bloblen) == 0) {
825: /* we cannot handle this key */
1.30 markus 826: debug3("sign_and_send_pubkey: cannot handle key");
1.28 markus 827: return 0;
828: }
1.1 markus 829: /* data to be signed */
830: buffer_init(&b);
1.26 markus 831: if (datafellows & SSH_OLD_SESSIONID) {
832: buffer_append(&b, session_id2, session_id2_len);
1.41 stevesk 833: skip = session_id2_len;
1.26 markus 834: } else {
1.14 markus 835: buffer_put_string(&b, session_id2, session_id2_len);
836: skip = buffer_len(&b);
837: }
1.1 markus 838: buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
1.20 markus 839: buffer_put_cstring(&b, authctxt->server_user);
1.10 markus 840: buffer_put_cstring(&b,
1.30 markus 841: datafellows & SSH_BUG_PKSERVICE ?
1.10 markus 842: "ssh-userauth" :
1.20 markus 843: authctxt->service);
1.30 markus 844: if (datafellows & SSH_BUG_PKAUTH) {
845: buffer_put_char(&b, have_sig);
846: } else {
847: buffer_put_cstring(&b, authctxt->method->name);
848: buffer_put_char(&b, have_sig);
1.41 stevesk 849: buffer_put_cstring(&b, key_ssh_name(k));
1.30 markus 850: }
1.1 markus 851: buffer_put_string(&b, blob, bloblen);
852:
853: /* generate signature */
1.51 markus 854: ret = (*sign_callback)(authctxt, k, &signature, &slen,
855: buffer_ptr(&b), buffer_len(&b));
1.17 markus 856: if (ret == -1) {
857: xfree(blob);
858: buffer_free(&b);
859: return 0;
860: }
1.28 markus 861: #ifdef DEBUG_PK
1.1 markus 862: buffer_dump(&b);
863: #endif
1.30 markus 864: if (datafellows & SSH_BUG_PKSERVICE) {
1.10 markus 865: buffer_clear(&b);
866: buffer_append(&b, session_id2, session_id2_len);
1.51 markus 867: skip = session_id2_len;
1.10 markus 868: buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
1.20 markus 869: buffer_put_cstring(&b, authctxt->server_user);
870: buffer_put_cstring(&b, authctxt->service);
1.23 markus 871: buffer_put_cstring(&b, authctxt->method->name);
872: buffer_put_char(&b, have_sig);
1.30 markus 873: if (!(datafellows & SSH_BUG_PKAUTH))
1.41 stevesk 874: buffer_put_cstring(&b, key_ssh_name(k));
1.10 markus 875: buffer_put_string(&b, blob, bloblen);
876: }
877: xfree(blob);
1.51 markus 878:
1.1 markus 879: /* append signature */
880: buffer_put_string(&b, signature, slen);
881: xfree(signature);
882:
883: /* skip session id and packet type */
1.14 markus 884: if (buffer_len(&b) < skip + 1)
1.20 markus 885: fatal("userauth_pubkey: internal error");
1.14 markus 886: buffer_consume(&b, skip + 1);
1.1 markus 887:
888: /* put remaining data from buffer into packet */
889: packet_start(SSH2_MSG_USERAUTH_REQUEST);
890: packet_put_raw(buffer_ptr(&b), buffer_len(&b));
891: buffer_free(&b);
892: packet_send();
1.17 markus 893:
894: return 1;
1.16 markus 895: }
896:
1.51 markus 897: int
898: send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback,
899: int hint)
1.20 markus 900: {
1.51 markus 901: u_char *blob;
902: int bloblen, have_sig = 0;
1.20 markus 903:
1.51 markus 904: debug3("send_pubkey_test");
1.16 markus 905:
1.51 markus 906: if (key_to_blob(k, &blob, &bloblen) == 0) {
907: /* we cannot handle this key */
908: debug3("send_pubkey_test: cannot handle key");
1.16 markus 909: return 0;
910: }
1.51 markus 911: /* register callback for USERAUTH_PK_OK message */
912: authctxt->last_key_sign = sign_callback;
913: authctxt->last_key_hint = hint;
914: authctxt->last_key = k;
915: dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
916:
917: packet_start(SSH2_MSG_USERAUTH_REQUEST);
918: packet_put_cstring(authctxt->server_user);
919: packet_put_cstring(authctxt->service);
920: packet_put_cstring(authctxt->method->name);
921: packet_put_char(have_sig);
922: if (!(datafellows & SSH_BUG_PKAUTH))
923: packet_put_cstring(key_ssh_name(k));
924: packet_put_string(blob, bloblen);
925: xfree(blob);
926: packet_send();
927: return 1;
928: }
929:
930: Key *
931: load_identity_file(char *filename)
932: {
933: Key *private;
934: char prompt[300], *passphrase;
1.56 markus 935: int quit, i;
1.52 markus 936: struct stat st;
1.16 markus 937:
1.52 markus 938: if (stat(filename, &st) < 0) {
939: debug3("no such identity: %s", filename);
940: return NULL;
941: }
1.56 markus 942: private = key_load_private_type(KEY_UNSPEC, filename, "", NULL);
943: if (private == NULL) {
944: if (options.batch_mode)
1.51 markus 945: return NULL;
1.16 markus 946: snprintf(prompt, sizeof prompt,
1.28 markus 947: "Enter passphrase for key '%.100s': ", filename);
1.20 markus 948: for (i = 0; i < options.number_of_password_prompts; i++) {
949: passphrase = read_passphrase(prompt, 0);
950: if (strcmp(passphrase, "") != 0) {
1.56 markus 951: private = key_load_private_type(KEY_UNSPEC, filename,
952: passphrase, NULL);
1.51 markus 953: quit = 0;
1.20 markus 954: } else {
955: debug2("no passphrase given, try next key");
1.51 markus 956: quit = 1;
1.20 markus 957: }
958: memset(passphrase, 0, strlen(passphrase));
959: xfree(passphrase);
1.56 markus 960: if (private != NULL || quit)
1.20 markus 961: break;
962: debug2("bad passphrase given, try again...");
1.16 markus 963: }
964: }
1.51 markus 965: return private;
966: }
967:
968: int
969: identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
970: u_char *data, int datalen)
971: {
972: Key *private;
973: int idx, ret;
974:
975: idx = authctxt->last_key_hint;
976: if (idx < 0)
977: return -1;
978: private = load_identity_file(options.identity_files[idx]);
979: if (private == NULL)
980: return -1;
981: ret = key_sign(private, sigp, lenp, data, datalen);
982: key_free(private);
1.17 markus 983: return ret;
984: }
985:
1.32 markus 986: int agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
987: u_char *data, int datalen)
1.17 markus 988: {
1.20 markus 989: return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen);
1.17 markus 990: }
991:
1.51 markus 992: int key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
993: u_char *data, int datalen)
994: {
995: return key_sign(key, sigp, lenp, data, datalen);
996: }
997:
1.17 markus 998: int
1.20 markus 999: userauth_pubkey_agent(Authctxt *authctxt)
1.17 markus 1000: {
1001: static int called = 0;
1.28 markus 1002: int ret = 0;
1.17 markus 1003: char *comment;
1004: Key *k;
1005:
1006: if (called == 0) {
1.28 markus 1007: if (ssh_get_num_identities(authctxt->agent, 2) == 0)
1008: debug2("userauth_pubkey_agent: no keys at all");
1.20 markus 1009: called = 1;
1.17 markus 1010: }
1.28 markus 1011: k = ssh_get_next_identity(authctxt->agent, &comment, 2);
1.20 markus 1012: if (k == NULL) {
1.28 markus 1013: debug2("userauth_pubkey_agent: no more keys");
1014: } else {
1.51 markus 1015: debug("userauth_pubkey_agent: testing agent key %s", comment);
1.28 markus 1016: xfree(comment);
1.51 markus 1017: ret = send_pubkey_test(authctxt, k, agent_sign_cb, -1);
1018: if (ret == 0)
1019: key_free(k);
1.20 markus 1020: }
1.28 markus 1021: if (ret == 0)
1022: debug2("userauth_pubkey_agent: no message sent");
1.17 markus 1023: return ret;
1.1 markus 1024: }
1025:
1.20 markus 1026: int
1027: userauth_pubkey(Authctxt *authctxt)
1028: {
1029: static int idx = 0;
1030: int sent = 0;
1.51 markus 1031: Key *key;
1032: char *filename;
1.20 markus 1033:
1.28 markus 1034: if (authctxt->agent != NULL) {
1035: do {
1036: sent = userauth_pubkey_agent(authctxt);
1037: } while(!sent && authctxt->agent->howmany > 0);
1038: }
1039: while (!sent && idx < options.num_identity_files) {
1.51 markus 1040: key = options.identity_keys[idx];
1041: filename = options.identity_files[idx];
1042: if (key == NULL) {
1043: debug("try privkey: %s", filename);
1044: key = load_identity_file(filename);
1045: if (key != NULL) {
1046: sent = sign_and_send_pubkey(authctxt, key,
1047: key_sign_cb);
1048: key_free(key);
1049: }
1050: } else if (key->type != KEY_RSA1) {
1051: debug("try pubkey: %s", filename);
1052: sent = send_pubkey_test(authctxt, key,
1053: identity_sign_cb, idx);
1054: }
1.28 markus 1055: idx++;
1056: }
1.20 markus 1057: return sent;
1058: }
1059:
1.23 markus 1060: /*
1061: * Send userauth request message specifying keyboard-interactive method.
1062: */
1063: int
1064: userauth_kbdint(Authctxt *authctxt)
1065: {
1066: static int attempt = 0;
1067:
1068: if (attempt++ >= options.number_of_password_prompts)
1069: return 0;
1070:
1071: debug2("userauth_kbdint");
1072: packet_start(SSH2_MSG_USERAUTH_REQUEST);
1073: packet_put_cstring(authctxt->server_user);
1074: packet_put_cstring(authctxt->service);
1075: packet_put_cstring(authctxt->method->name);
1076: packet_put_cstring(""); /* lang */
1077: packet_put_cstring(options.kbd_interactive_devices ?
1078: options.kbd_interactive_devices : "");
1079: packet_send();
1080:
1081: dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
1082: return 1;
1083: }
1084:
1085: /*
1.46 markus 1086: * parse INFO_REQUEST, prompt user and send INFO_RESPONSE
1.23 markus 1087: */
1088: void
1089: input_userauth_info_req(int type, int plen, void *ctxt)
1090: {
1091: Authctxt *authctxt = ctxt;
1.46 markus 1092: char *name, *inst, *lang, *prompt, *response;
1.32 markus 1093: u_int num_prompts, i;
1.23 markus 1094: int echo = 0;
1095:
1096: debug2("input_userauth_info_req");
1097:
1098: if (authctxt == NULL)
1099: fatal("input_userauth_info_req: no authentication context");
1100:
1101: name = packet_get_string(NULL);
1102: inst = packet_get_string(NULL);
1103: lang = packet_get_string(NULL);
1104: if (strlen(name) > 0)
1105: cli_mesg(name);
1106: if (strlen(inst) > 0)
1107: cli_mesg(inst);
1.46 markus 1108: xfree(name);
1.23 markus 1109: xfree(inst);
1.46 markus 1110: xfree(lang);
1.23 markus 1111:
1112: num_prompts = packet_get_int();
1113: /*
1114: * Begin to build info response packet based on prompts requested.
1115: * We commit to providing the correct number of responses, so if
1116: * further on we run into a problem that prevents this, we have to
1117: * be sure and clean this up and send a correct error response.
1118: */
1119: packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
1120: packet_put_int(num_prompts);
1121:
1122: for (i = 0; i < num_prompts; i++) {
1123: prompt = packet_get_string(NULL);
1124: echo = packet_get_char();
1125:
1126: response = cli_prompt(prompt, echo);
1127:
1.49 markus 1128: packet_put_cstring(response);
1.23 markus 1129: memset(response, 0, strlen(response));
1130: xfree(response);
1131: xfree(prompt);
1132: }
1133: packet_done(); /* done with parsing incoming message. */
1134:
1.49 markus 1135: packet_inject_ignore(64);
1.23 markus 1136: packet_send();
1137: }
1.20 markus 1138:
1139: /* find auth method */
1140:
1141: /*
1142: * given auth method name, if configurable options permit this method fill
1143: * in auth_ident field and return true, otherwise return false.
1144: */
1145: int
1146: authmethod_is_enabled(Authmethod *method)
1147: {
1148: if (method == NULL)
1149: return 0;
1150: /* return false if options indicate this method is disabled */
1151: if (method->enabled == NULL || *method->enabled == 0)
1152: return 0;
1153: /* return false if batch mode is enabled but method needs interactive mode */
1154: if (method->batch_flag != NULL && *method->batch_flag != 0)
1155: return 0;
1156: return 1;
1157: }
1158:
1159: Authmethod *
1160: authmethod_lookup(const char *name)
1.1 markus 1161: {
1.20 markus 1162: Authmethod *method = NULL;
1163: if (name != NULL)
1164: for (method = authmethods; method->name != NULL; method++)
1165: if (strcmp(name, method->name) == 0)
1166: return method;
1167: debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
1168: return NULL;
1169: }
1.1 markus 1170:
1.53 markus 1171: /* XXX internal state */
1172: static Authmethod *current = NULL;
1173: static char *supported = NULL;
1174: static char *preferred = NULL;
1.20 markus 1175: /*
1176: * Given the authentication method list sent by the server, return the
1177: * next method we should try. If the server initially sends a nil list,
1.53 markus 1178: * use a built-in default list.
1.41 stevesk 1179: */
1.20 markus 1180: Authmethod *
1181: authmethod_get(char *authlist)
1182: {
1.53 markus 1183:
1184: char *name = NULL;
1185: int next;
1.41 stevesk 1186:
1.20 markus 1187: /* Use a suitable default if we're passed a nil list. */
1188: if (authlist == NULL || strlen(authlist) == 0)
1.53 markus 1189: authlist = options.preferred_authentications;
1.20 markus 1190:
1.53 markus 1191: if (supported == NULL || strcmp(authlist, supported) != 0) {
1192: debug3("start over, passed a different list %s", authlist);
1193: if (supported != NULL)
1194: xfree(supported);
1195: supported = xstrdup(authlist);
1196: preferred = options.preferred_authentications;
1197: debug3("preferred %s", preferred);
1198: current = NULL;
1199: } else if (current != NULL && authmethod_is_enabled(current))
1200: return current;
1.20 markus 1201:
1.53 markus 1202: for (;;) {
1203: if ((name = match_list(preferred, supported, &next)) == NULL) {
1204: debug("no more auth methods to try");
1205: current = NULL;
1206: return NULL;
1207: }
1208: preferred += next;
1.23 markus 1209: debug3("authmethod_lookup %s", name);
1.53 markus 1210: debug3("remaining preferred: %s", preferred);
1211: if ((current = authmethod_lookup(name)) != NULL &&
1212: authmethod_is_enabled(current)) {
1.23 markus 1213: debug3("authmethod_is_enabled %s", name);
1.53 markus 1214: debug("next auth method to try is %s", name);
1215: return current;
1.23 markus 1216: }
1.1 markus 1217: }
1.53 markus 1218: }
1.1 markus 1219:
1.27 provos 1220:
1.53 markus 1221: #define DELIM ","
1222: char *
1223: authmethods_get(void)
1224: {
1225: Authmethod *method = NULL;
1226: char buf[1024];
1.27 provos 1227:
1.53 markus 1228: buf[0] = '\0';
1229: for (method = authmethods; method->name != NULL; method++) {
1230: if (authmethod_is_enabled(method)) {
1231: if (buf[0] != '\0')
1232: strlcat(buf, DELIM, sizeof buf);
1233: strlcat(buf, method->name, sizeof buf);
1234: }
1235: }
1236: return xstrdup(buf);
1.1 markus 1237: }