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