Annotation of src/usr.bin/ssh/sshconnect2.c, Revision 1.117
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.117 ! markus 26: RCSID("$OpenBSD: sshconnect2.c,v 1.116 2003/04/08 20:21:29 itojun Exp $");
1.1 markus 27:
28: #include "ssh.h"
1.37 markus 29: #include "ssh2.h"
1.1 markus 30: #include "xmalloc.h"
31: #include "buffer.h"
32: #include "packet.h"
33: #include "compat.h"
34: #include "bufaux.h"
1.37 markus 35: #include "cipher.h"
1.1 markus 36: #include "kex.h"
37: #include "myproposal.h"
38: #include "sshconnect.h"
39: #include "authfile.h"
1.57 provos 40: #include "dh.h"
1.17 markus 41: #include "authfd.h"
1.37 markus 42: #include "log.h"
43: #include "readconf.h"
44: #include "readpass.h"
1.53 markus 45: #include "match.h"
1.61 markus 46: #include "dispatch.h"
1.68 markus 47: #include "canohost.h"
1.100 markus 48: #include "msg.h"
49: #include "pathnames.h"
1.22 provos 50:
1.1 markus 51: /* import */
52: extern char *client_version_string;
53: extern char *server_version_string;
54: extern Options options;
55:
56: /*
57: * SSH2 key exchange
58: */
59:
1.32 markus 60: u_char *session_id2 = NULL;
1.1 markus 61: int session_id2_len = 0;
62:
1.61 markus 63: char *xxx_host;
64: struct sockaddr *xxx_hostaddr;
65:
1.63 markus 66: Kex *xxx_kex = NULL;
67:
1.76 itojun 68: static int
1.75 markus 69: verify_host_key_callback(Key *hostkey)
1.61 markus 70: {
1.75 markus 71: if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1)
1.83 markus 72: fatal("Host key verification failed.");
1.61 markus 73: return 0;
74: }
75:
1.1 markus 76: void
1.22 provos 77: ssh_kex2(char *host, struct sockaddr *hostaddr)
78: {
79: Kex *kex;
1.61 markus 80:
81: xxx_host = host;
82: xxx_hostaddr = hostaddr;
1.22 provos 83:
1.29 markus 84: if (options.ciphers == (char *)-1) {
1.116 itojun 85: logit("No valid ciphers for protocol version 2 given, using defaults.");
1.29 markus 86: options.ciphers = NULL;
1.24 markus 87: }
1.22 provos 88: if (options.ciphers != NULL) {
89: myproposal[PROPOSAL_ENC_ALGS_CTOS] =
90: myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
91: }
1.60 stevesk 92: myproposal[PROPOSAL_ENC_ALGS_CTOS] =
93: compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
94: myproposal[PROPOSAL_ENC_ALGS_STOC] =
95: compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
1.22 provos 96: if (options.compression) {
1.47 markus 97: myproposal[PROPOSAL_COMP_ALGS_CTOS] =
1.107 markus 98: myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib,none";
1.22 provos 99: } else {
1.47 markus 100: myproposal[PROPOSAL_COMP_ALGS_CTOS] =
1.107 markus 101: myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib";
1.47 markus 102: }
103: if (options.macs != NULL) {
104: myproposal[PROPOSAL_MAC_ALGS_CTOS] =
105: myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
1.22 provos 106: }
1.70 markus 107: if (options.hostkeyalgorithms != NULL)
1.88 deraadt 108: myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
1.70 markus 109: options.hostkeyalgorithms;
1.115 markus 110:
111: if (options.rekey_limit)
112: packet_set_rekey_limit(options.rekey_limit);
1.22 provos 113:
1.65 markus 114: /* start key exchange */
1.64 markus 115: kex = kex_setup(myproposal);
1.111 markus 116: kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
117: kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
1.61 markus 118: kex->client_version_string=client_version_string;
119: kex->server_version_string=server_version_string;
1.75 markus 120: kex->verify_host_key=&verify_host_key_callback;
1.63 markus 121:
122: xxx_kex = kex;
1.22 provos 123:
1.66 markus 124: dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
1.62 markus 125:
126: session_id2 = kex->session_id;
127: session_id2_len = kex->session_id_len;
1.22 provos 128:
129: #ifdef DEBUG_KEXDH
130: /* send 1st encrypted/maced/compressed message */
131: packet_start(SSH2_MSG_IGNORE);
132: packet_put_cstring("markus");
133: packet_send();
134: packet_write_wait();
135: #endif
1.1 markus 136: }
1.11 markus 137:
1.1 markus 138: /*
139: * Authenticate user
140: */
1.20 markus 141:
142: typedef struct Authctxt Authctxt;
143: typedef struct Authmethod Authmethod;
1.117 ! markus 144: typedef struct identity Identity;
! 145: typedef struct idlist Idlist;
1.20 markus 146:
1.117 ! markus 147: struct identity {
! 148: TAILQ_ENTRY(identity) next;
! 149: AuthenticationConnection *ac; /* set if agent supports key */
! 150: Key *key; /* public/private key */
! 151: char *filename; /* comment for agent-only keys */
! 152: int tried;
! 153: int isprivate; /* key points to the private key */
! 154: };
! 155: TAILQ_HEAD(idlist, identity);
1.20 markus 156:
157: struct Authctxt {
158: const char *server_user;
1.68 markus 159: const char *local_user;
1.20 markus 160: const char *host;
161: const char *service;
1.23 markus 162: Authmethod *method;
1.20 markus 163: int success;
1.51 markus 164: char *authlist;
1.68 markus 165: /* pubkey */
1.117 ! markus 166: Idlist keys;
1.68 markus 167: AuthenticationConnection *agent;
168: /* hostbased */
1.100 markus 169: Sensitive *sensitive;
1.82 markus 170: /* kbd-interactive */
171: int info_req_seen;
1.20 markus 172: };
173: struct Authmethod {
174: char *name; /* string to compare against server's list */
175: int (*userauth)(Authctxt *authctxt);
176: int *enabled; /* flag in option struct that enables method */
177: int *batch_flag; /* flag in option struct that disables method */
178: };
179:
1.92 markus 180: void input_userauth_success(int, u_int32_t, void *);
181: void input_userauth_failure(int, u_int32_t, void *);
182: void input_userauth_banner(int, u_int32_t, void *);
183: void input_userauth_error(int, u_int32_t, void *);
184: void input_userauth_info_req(int, u_int32_t, void *);
185: void input_userauth_pk_ok(int, u_int32_t, void *);
1.99 markus 186: void input_userauth_passwd_changereq(int, u_int32_t, void *);
1.86 itojun 187:
188: int userauth_none(Authctxt *);
189: int userauth_pubkey(Authctxt *);
190: int userauth_passwd(Authctxt *);
191: int userauth_kbdint(Authctxt *);
192: int userauth_hostbased(Authctxt *);
1.20 markus 193:
1.86 itojun 194: void userauth(Authctxt *, char *);
1.51 markus 195:
1.117 ! markus 196: static int sign_and_send_pubkey(Authctxt *, Identity *);
1.76 itojun 197: static void clear_auth_state(Authctxt *);
1.117 ! markus 198: static void pubkey_prepare(Authctxt *);
! 199: static void pubkey_cleanup(Authctxt *);
! 200: static Key *load_identity_file(char *);
1.76 itojun 201:
202: static Authmethod *authmethod_get(char *authlist);
203: static Authmethod *authmethod_lookup(const char *name);
204: static char *authmethods_get(void);
1.20 markus 205:
206: Authmethod authmethods[] = {
1.81 markus 207: {"hostbased",
208: userauth_hostbased,
209: &options.hostbased_authentication,
210: NULL},
1.20 markus 211: {"publickey",
212: userauth_pubkey,
1.28 markus 213: &options.pubkey_authentication,
1.20 markus 214: NULL},
1.81 markus 215: {"keyboard-interactive",
216: userauth_kbdint,
217: &options.kbd_interactive_authentication,
218: &options.batch_mode},
1.20 markus 219: {"password",
220: userauth_passwd,
221: &options.password_authentication,
1.23 markus 222: &options.batch_mode},
223: {"none",
224: userauth_none,
225: NULL,
226: NULL},
1.20 markus 227: {NULL, NULL, NULL, NULL}
228: };
229:
230: void
1.68 markus 231: ssh_userauth2(const char *local_user, const char *server_user, char *host,
1.100 markus 232: Sensitive *sensitive)
1.20 markus 233: {
234: Authctxt authctxt;
235: int type;
1.39 markus 236:
1.73 markus 237: if (options.challenge_response_authentication)
1.39 markus 238: options.kbd_interactive_authentication = 1;
1.20 markus 239:
240: packet_start(SSH2_MSG_SERVICE_REQUEST);
241: packet_put_cstring("ssh-userauth");
242: packet_send();
1.108 markus 243: debug("SSH2_MSG_SERVICE_REQUEST sent");
1.20 markus 244: packet_write_wait();
1.91 markus 245: type = packet_read();
1.108 markus 246: if (type != SSH2_MSG_SERVICE_ACCEPT)
247: fatal("Server denied authentication request: %d", type);
1.20 markus 248: if (packet_remaining() > 0) {
1.91 markus 249: char *reply = packet_get_string(NULL);
1.108 markus 250: debug2("service_accept: %s", reply);
1.20 markus 251: xfree(reply);
252: } else {
1.109 markus 253: debug2("buggy server: service_accept w/o service");
1.20 markus 254: }
1.90 markus 255: packet_check_eom();
1.108 markus 256: debug("SSH2_MSG_SERVICE_ACCEPT received");
1.20 markus 257:
1.53 markus 258: if (options.preferred_authentications == NULL)
259: options.preferred_authentications = authmethods_get();
260:
1.20 markus 261: /* setup authentication context */
1.82 markus 262: memset(&authctxt, 0, sizeof(authctxt));
1.117 ! markus 263: pubkey_prepare(&authctxt);
1.20 markus 264: authctxt.server_user = server_user;
1.68 markus 265: authctxt.local_user = local_user;
1.20 markus 266: authctxt.host = host;
267: authctxt.service = "ssh-connection"; /* service name */
268: authctxt.success = 0;
1.23 markus 269: authctxt.method = authmethod_lookup("none");
1.51 markus 270: authctxt.authlist = NULL;
1.100 markus 271: authctxt.sensitive = sensitive;
1.82 markus 272: authctxt.info_req_seen = 0;
1.23 markus 273: if (authctxt.method == NULL)
274: fatal("ssh_userauth2: internal error: cannot send userauth none request");
1.20 markus 275:
276: /* initial userauth request */
1.23 markus 277: userauth_none(&authctxt);
1.20 markus 278:
1.65 markus 279: dispatch_init(&input_userauth_error);
1.20 markus 280: dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
281: dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
1.35 markus 282: dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
1.20 markus 283: dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
284:
1.117 ! markus 285: pubkey_cleanup(&authctxt);
1.109 markus 286: debug("Authentication succeeded (%s).", authctxt.method->name);
1.20 markus 287: }
288: void
1.51 markus 289: userauth(Authctxt *authctxt, char *authlist)
290: {
291: if (authlist == NULL) {
292: authlist = authctxt->authlist;
293: } else {
294: if (authctxt->authlist)
295: xfree(authctxt->authlist);
296: authctxt->authlist = authlist;
297: }
298: for (;;) {
299: Authmethod *method = authmethod_get(authlist);
300: if (method == NULL)
301: fatal("Permission denied (%s).", authlist);
302: authctxt->method = method;
303: if (method->userauth(authctxt) != 0) {
304: debug2("we sent a %s packet, wait for reply", method->name);
305: break;
306: } else {
307: debug2("we did not send a packet, disable method");
308: method->enabled = NULL;
309: }
310: }
311: }
1.105 deraadt 312:
1.51 markus 313: void
1.92 markus 314: input_userauth_error(int type, u_int32_t seq, void *ctxt)
1.20 markus 315: {
1.35 markus 316: fatal("input_userauth_error: bad message during authentication: "
317: "type %d", type);
318: }
1.105 deraadt 319:
1.35 markus 320: void
1.92 markus 321: input_userauth_banner(int type, u_int32_t seq, void *ctxt)
1.35 markus 322: {
323: char *msg, *lang;
324: debug3("input_userauth_banner");
325: msg = packet_get_string(NULL);
326: lang = packet_get_string(NULL);
327: fprintf(stderr, "%s", msg);
328: xfree(msg);
329: xfree(lang);
1.20 markus 330: }
1.105 deraadt 331:
1.20 markus 332: void
1.92 markus 333: input_userauth_success(int type, u_int32_t seq, void *ctxt)
1.20 markus 334: {
335: Authctxt *authctxt = ctxt;
336: if (authctxt == NULL)
337: fatal("input_userauth_success: no authentication context");
1.51 markus 338: if (authctxt->authlist)
339: xfree(authctxt->authlist);
340: clear_auth_state(authctxt);
1.20 markus 341: authctxt->success = 1; /* break out */
342: }
1.105 deraadt 343:
1.20 markus 344: void
1.92 markus 345: input_userauth_failure(int type, u_int32_t seq, void *ctxt)
1.20 markus 346: {
347: Authctxt *authctxt = ctxt;
348: char *authlist = NULL;
349: int partial;
350:
351: if (authctxt == NULL)
352: fatal("input_userauth_failure: no authentication context");
353:
1.23 markus 354: authlist = packet_get_string(NULL);
1.20 markus 355: partial = packet_get_char();
1.90 markus 356: packet_check_eom();
1.20 markus 357:
358: if (partial != 0)
1.116 itojun 359: logit("Authenticated with partial success.");
1.109 markus 360: debug("Authentications that can continue: %s", authlist);
1.20 markus 361:
1.51 markus 362: clear_auth_state(authctxt);
363: userauth(authctxt, authlist);
364: }
365: void
1.92 markus 366: input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
1.51 markus 367: {
368: Authctxt *authctxt = ctxt;
369: Key *key = NULL;
1.117 ! markus 370: Identity *id = NULL;
1.51 markus 371: Buffer b;
1.96 markus 372: int pktype, sent = 0;
373: u_int alen, blen;
374: char *pkalg, *fp;
375: u_char *pkblob;
1.51 markus 376:
377: if (authctxt == NULL)
378: fatal("input_userauth_pk_ok: no authentication context");
379: if (datafellows & SSH_BUG_PKOK) {
380: /* this is similar to SSH_BUG_PKAUTH */
381: debug2("input_userauth_pk_ok: SSH_BUG_PKOK");
382: pkblob = packet_get_string(&blen);
383: buffer_init(&b);
384: buffer_append(&b, pkblob, blen);
385: pkalg = buffer_get_string(&b, &alen);
386: buffer_free(&b);
387: } else {
388: pkalg = packet_get_string(&alen);
389: pkblob = packet_get_string(&blen);
390: }
1.90 markus 391: packet_check_eom();
1.51 markus 392:
1.117 ! markus 393: debug("Server accepts key: pkalg %s blen %u", pkalg, blen);
1.51 markus 394:
1.117 ! markus 395: if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
! 396: debug("unknown pkalg %s", pkalg);
! 397: goto done;
! 398: }
! 399: if ((key = key_from_blob(pkblob, blen)) == NULL) {
! 400: debug("no key from blob. pkalg %s", pkalg);
! 401: goto done;
! 402: }
! 403: if (key->type != pktype) {
! 404: error("input_userauth_pk_ok: type mismatch "
! 405: "for decoded key (received %d, expected %d)",
! 406: key->type, pktype);
! 407: goto done;
! 408: }
! 409: fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
! 410: debug2("input_userauth_pk_ok: fp %s", fp);
! 411: xfree(fp);
! 412:
! 413: TAILQ_FOREACH(id, &authctxt->keys, next) {
! 414: if (key_equal(key, id->key)) {
! 415: sent = sign_and_send_pubkey(authctxt, id);
1.51 markus 416: break;
417: }
1.117 ! markus 418: }
! 419: done:
1.51 markus 420: if (key != NULL)
421: key_free(key);
422: xfree(pkalg);
423: xfree(pkblob);
424:
425: /* unregister */
426: clear_auth_state(authctxt);
427: dispatch_set(SSH2_MSG_USERAUTH_PK_OK, NULL);
428:
1.106 deraadt 429: /* try another method if we did not send a packet */
1.51 markus 430: if (sent == 0)
431: userauth(authctxt, NULL);
1.20 markus 432: }
433:
1.1 markus 434: int
1.23 markus 435: userauth_none(Authctxt *authctxt)
436: {
437: /* initial userauth request */
438: packet_start(SSH2_MSG_USERAUTH_REQUEST);
439: packet_put_cstring(authctxt->server_user);
440: packet_put_cstring(authctxt->service);
441: packet_put_cstring(authctxt->method->name);
442: packet_send();
443: return 1;
444: }
445:
446: int
1.20 markus 447: userauth_passwd(Authctxt *authctxt)
1.1 markus 448: {
1.6 markus 449: static int attempt = 0;
1.99 markus 450: char prompt[150];
1.1 markus 451: char *password;
1.6 markus 452:
1.13 todd 453: if (attempt++ >= options.number_of_password_prompts)
1.6 markus 454: return 0;
1.13 todd 455:
1.87 deraadt 456: if (attempt != 1)
1.13 todd 457: error("Permission denied, please try again.");
1.1 markus 458:
1.43 itojun 459: snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
1.20 markus 460: authctxt->server_user, authctxt->host);
1.1 markus 461: password = read_passphrase(prompt, 0);
462: packet_start(SSH2_MSG_USERAUTH_REQUEST);
1.20 markus 463: packet_put_cstring(authctxt->server_user);
464: packet_put_cstring(authctxt->service);
1.23 markus 465: packet_put_cstring(authctxt->method->name);
1.1 markus 466: packet_put_char(0);
1.49 markus 467: packet_put_cstring(password);
1.1 markus 468: memset(password, 0, strlen(password));
469: xfree(password);
1.85 markus 470: packet_add_padding(64);
1.1 markus 471: packet_send();
1.99 markus 472:
1.104 deraadt 473: dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
1.99 markus 474: &input_userauth_passwd_changereq);
475:
1.1 markus 476: return 1;
477: }
1.99 markus 478: /*
479: * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST
480: */
481: void
482: input_userauth_passwd_changereq(int type, uint32_t seqnr, void *ctxt)
483: {
484: Authctxt *authctxt = ctxt;
485: char *info, *lang, *password = NULL, *retype = NULL;
486: char prompt[150];
487:
488: debug2("input_userauth_passwd_changereq");
489:
490: if (authctxt == NULL)
491: fatal("input_userauth_passwd_changereq: "
492: "no authentication context");
493:
494: info = packet_get_string(NULL);
495: lang = packet_get_string(NULL);
496: if (strlen(info) > 0)
1.116 itojun 497: logit("%s", info);
1.99 markus 498: xfree(info);
499: xfree(lang);
500: packet_start(SSH2_MSG_USERAUTH_REQUEST);
501: packet_put_cstring(authctxt->server_user);
502: packet_put_cstring(authctxt->service);
503: packet_put_cstring(authctxt->method->name);
504: packet_put_char(1); /* additional info */
1.104 deraadt 505: snprintf(prompt, sizeof(prompt),
1.99 markus 506: "Enter %.30s@%.128s's old password: ",
507: authctxt->server_user, authctxt->host);
508: password = read_passphrase(prompt, 0);
509: packet_put_cstring(password);
510: memset(password, 0, strlen(password));
511: xfree(password);
512: password = NULL;
513: while (password == NULL) {
1.104 deraadt 514: snprintf(prompt, sizeof(prompt),
1.99 markus 515: "Enter %.30s@%.128s's new password: ",
516: authctxt->server_user, authctxt->host);
517: password = read_passphrase(prompt, RP_ALLOW_EOF);
518: if (password == NULL) {
519: /* bail out */
520: return;
521: }
1.104 deraadt 522: snprintf(prompt, sizeof(prompt),
1.99 markus 523: "Retype %.30s@%.128s's new password: ",
524: authctxt->server_user, authctxt->host);
525: retype = read_passphrase(prompt, 0);
526: if (strcmp(password, retype) != 0) {
527: memset(password, 0, strlen(password));
528: xfree(password);
1.116 itojun 529: logit("Mismatch; try again, EOF to quit.");
1.99 markus 530: password = NULL;
531: }
532: memset(retype, 0, strlen(retype));
533: xfree(retype);
534: }
535: packet_put_cstring(password);
536: memset(password, 0, strlen(password));
537: xfree(password);
538: packet_add_padding(64);
539: packet_send();
1.104 deraadt 540:
541: dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
1.99 markus 542: &input_userauth_passwd_changereq);
543: }
1.1 markus 544:
1.79 stevesk 545: static void
1.51 markus 546: clear_auth_state(Authctxt *authctxt)
547: {
548: /* XXX clear authentication state */
1.99 markus 549: dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, NULL);
1.117 ! markus 550: }
! 551:
! 552: static int
! 553: identity_sign(Identity *id, u_char **sigp, u_int *lenp,
! 554: u_char *data, u_int datalen)
! 555: {
! 556: Key *prv;
! 557: int ret;
1.99 markus 558:
1.117 ! markus 559: /* the agent supports this key */
! 560: if (id->ac)
! 561: return (ssh_agent_sign(id->ac, id->key, sigp, lenp,
! 562: data, datalen));
! 563: /*
! 564: * we have already loaded the private key or
! 565: * the private key is stored in external hardware
! 566: */
! 567: if (id->isprivate || (id->key->flags & KEY_FLAG_EXT))
! 568: return (key_sign(id->key, sigp, lenp, data, datalen));
! 569: /* load the private key from the file */
! 570: if ((prv = load_identity_file(id->filename)) == NULL)
! 571: return (-1);
! 572: ret = key_sign(prv, sigp, lenp, data, datalen);
! 573: key_free(prv);
! 574: return (ret);
1.51 markus 575: }
576:
1.76 itojun 577: static int
1.117 ! markus 578: sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
1.1 markus 579: {
580: Buffer b;
1.32 markus 581: u_char *blob, *signature;
1.96 markus 582: u_int bloblen, slen;
1.14 markus 583: int skip = 0;
1.17 markus 584: int ret = -1;
1.23 markus 585: int have_sig = 1;
1.1 markus 586:
1.30 markus 587: debug3("sign_and_send_pubkey");
1.51 markus 588:
1.117 ! markus 589: if (key_to_blob(id->key, &blob, &bloblen) == 0) {
1.28 markus 590: /* we cannot handle this key */
1.30 markus 591: debug3("sign_and_send_pubkey: cannot handle key");
1.28 markus 592: return 0;
593: }
1.1 markus 594: /* data to be signed */
595: buffer_init(&b);
1.26 markus 596: if (datafellows & SSH_OLD_SESSIONID) {
597: buffer_append(&b, session_id2, session_id2_len);
1.41 stevesk 598: skip = session_id2_len;
1.26 markus 599: } else {
1.14 markus 600: buffer_put_string(&b, session_id2, session_id2_len);
601: skip = buffer_len(&b);
602: }
1.1 markus 603: buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
1.20 markus 604: buffer_put_cstring(&b, authctxt->server_user);
1.10 markus 605: buffer_put_cstring(&b,
1.30 markus 606: datafellows & SSH_BUG_PKSERVICE ?
1.10 markus 607: "ssh-userauth" :
1.20 markus 608: authctxt->service);
1.30 markus 609: if (datafellows & SSH_BUG_PKAUTH) {
610: buffer_put_char(&b, have_sig);
611: } else {
612: buffer_put_cstring(&b, authctxt->method->name);
613: buffer_put_char(&b, have_sig);
1.117 ! markus 614: buffer_put_cstring(&b, key_ssh_name(id->key));
1.30 markus 615: }
1.1 markus 616: buffer_put_string(&b, blob, bloblen);
617:
618: /* generate signature */
1.117 ! markus 619: ret = identity_sign(id, &signature, &slen,
1.51 markus 620: buffer_ptr(&b), buffer_len(&b));
1.17 markus 621: if (ret == -1) {
622: xfree(blob);
623: buffer_free(&b);
624: return 0;
625: }
1.28 markus 626: #ifdef DEBUG_PK
1.1 markus 627: buffer_dump(&b);
628: #endif
1.30 markus 629: if (datafellows & SSH_BUG_PKSERVICE) {
1.10 markus 630: buffer_clear(&b);
631: buffer_append(&b, session_id2, session_id2_len);
1.51 markus 632: skip = session_id2_len;
1.10 markus 633: buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
1.20 markus 634: buffer_put_cstring(&b, authctxt->server_user);
635: buffer_put_cstring(&b, authctxt->service);
1.23 markus 636: buffer_put_cstring(&b, authctxt->method->name);
637: buffer_put_char(&b, have_sig);
1.30 markus 638: if (!(datafellows & SSH_BUG_PKAUTH))
1.117 ! markus 639: buffer_put_cstring(&b, key_ssh_name(id->key));
1.10 markus 640: buffer_put_string(&b, blob, bloblen);
641: }
642: xfree(blob);
1.51 markus 643:
1.1 markus 644: /* append signature */
645: buffer_put_string(&b, signature, slen);
646: xfree(signature);
647:
648: /* skip session id and packet type */
1.14 markus 649: if (buffer_len(&b) < skip + 1)
1.20 markus 650: fatal("userauth_pubkey: internal error");
1.14 markus 651: buffer_consume(&b, skip + 1);
1.1 markus 652:
653: /* put remaining data from buffer into packet */
654: packet_start(SSH2_MSG_USERAUTH_REQUEST);
655: packet_put_raw(buffer_ptr(&b), buffer_len(&b));
656: buffer_free(&b);
657: packet_send();
1.17 markus 658:
659: return 1;
1.16 markus 660: }
661:
1.76 itojun 662: static int
1.117 ! markus 663: send_pubkey_test(Authctxt *authctxt, Identity *id)
1.20 markus 664: {
1.51 markus 665: u_char *blob;
1.97 markus 666: u_int bloblen, have_sig = 0;
1.20 markus 667:
1.51 markus 668: debug3("send_pubkey_test");
1.16 markus 669:
1.117 ! markus 670: if (key_to_blob(id->key, &blob, &bloblen) == 0) {
1.51 markus 671: /* we cannot handle this key */
672: debug3("send_pubkey_test: cannot handle key");
1.16 markus 673: return 0;
674: }
1.51 markus 675: /* register callback for USERAUTH_PK_OK message */
676: dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
677:
678: packet_start(SSH2_MSG_USERAUTH_REQUEST);
679: packet_put_cstring(authctxt->server_user);
680: packet_put_cstring(authctxt->service);
681: packet_put_cstring(authctxt->method->name);
682: packet_put_char(have_sig);
683: if (!(datafellows & SSH_BUG_PKAUTH))
1.117 ! markus 684: packet_put_cstring(key_ssh_name(id->key));
1.51 markus 685: packet_put_string(blob, bloblen);
686: xfree(blob);
687: packet_send();
688: return 1;
689: }
690:
1.76 itojun 691: static Key *
1.51 markus 692: load_identity_file(char *filename)
693: {
694: Key *private;
695: char prompt[300], *passphrase;
1.56 markus 696: int quit, i;
1.52 markus 697: struct stat st;
1.16 markus 698:
1.52 markus 699: if (stat(filename, &st) < 0) {
700: debug3("no such identity: %s", filename);
701: return NULL;
702: }
1.56 markus 703: private = key_load_private_type(KEY_UNSPEC, filename, "", NULL);
704: if (private == NULL) {
705: if (options.batch_mode)
1.51 markus 706: return NULL;
1.16 markus 707: snprintf(prompt, sizeof prompt,
1.88 deraadt 708: "Enter passphrase for key '%.100s': ", filename);
1.20 markus 709: for (i = 0; i < options.number_of_password_prompts; i++) {
710: passphrase = read_passphrase(prompt, 0);
711: if (strcmp(passphrase, "") != 0) {
1.56 markus 712: private = key_load_private_type(KEY_UNSPEC, filename,
713: passphrase, NULL);
1.51 markus 714: quit = 0;
1.20 markus 715: } else {
716: debug2("no passphrase given, try next key");
1.51 markus 717: quit = 1;
1.20 markus 718: }
719: memset(passphrase, 0, strlen(passphrase));
720: xfree(passphrase);
1.56 markus 721: if (private != NULL || quit)
1.20 markus 722: break;
723: debug2("bad passphrase given, try again...");
1.16 markus 724: }
725: }
1.51 markus 726: return private;
727: }
728:
1.117 ! markus 729: /*
! 730: * try keys in the following order:
! 731: * 1. agent keys that are found in the config file
! 732: * 2. other agent keys
! 733: * 3. keys that are only listed in the config file
! 734: */
! 735: static void
! 736: pubkey_prepare(Authctxt *authctxt)
1.51 markus 737: {
1.117 ! markus 738: Identity *id;
! 739: Idlist agent, files, *preferred;
! 740: Key *key;
! 741: AuthenticationConnection *ac;
! 742: char *comment;
! 743: int i, found;
1.51 markus 744:
1.117 ! markus 745: TAILQ_INIT(&agent); /* keys from the agent */
! 746: TAILQ_INIT(&files); /* keys from the config file */
! 747: preferred = &authctxt->keys;
! 748: TAILQ_INIT(preferred); /* preferred order of keys */
! 749:
! 750: /* list of keys stored in the filesystem */
! 751: for (i = 0; i < options.num_identity_files; i++) {
! 752: key = options.identity_keys[i];
! 753: if (key && key->type == KEY_RSA1)
! 754: continue;
! 755: options.identity_keys[i] = NULL;
! 756: id = xmalloc(sizeof(*id));
! 757: memset(id, 0, sizeof(*id));
! 758: id->key = key;
! 759: id->filename = xstrdup(options.identity_files[i]);
! 760: TAILQ_INSERT_TAIL(&files, id, next);
! 761: }
! 762: /* list of keys supported by the agent */
! 763: if ((ac = ssh_get_authentication_connection())) {
! 764: for (key = ssh_get_first_identity(ac, &comment, 2);
! 765: key != NULL;
! 766: key = ssh_get_next_identity(ac, &comment, 2)) {
! 767: found = 0;
! 768: TAILQ_FOREACH(id, &files, next) {
! 769: /* agent keys from the config file are preferred */
! 770: if (key_equal(key, id->key)) {
! 771: key_free(key);
! 772: xfree(comment);
! 773: TAILQ_REMOVE(&files, id, next);
! 774: TAILQ_INSERT_TAIL(preferred, id, next);
! 775: id->ac = ac;
! 776: found = 1;
! 777: break;
! 778: }
! 779: }
! 780: if (!found) {
! 781: id = xmalloc(sizeof(*id));
! 782: memset(id, 0, sizeof(*id));
! 783: id->key = key;
! 784: id->filename = comment;
! 785: id->ac = ac;
! 786: TAILQ_INSERT_TAIL(&agent, id, next);
! 787: }
! 788: }
! 789: /* append remaining agent keys */
! 790: for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
! 791: TAILQ_REMOVE(&agent, id, next);
! 792: TAILQ_INSERT_TAIL(preferred, id, next);
! 793: }
! 794: authctxt->agent = ac;
! 795: }
! 796: /* append remaining keys from the config file */
! 797: for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
! 798: TAILQ_REMOVE(&files, id, next);
! 799: TAILQ_INSERT_TAIL(preferred, id, next);
! 800: }
! 801: TAILQ_FOREACH(id, preferred, next) {
! 802: debug2("key: %s (%p)", id->filename, id->key);
! 803: }
1.17 markus 804: }
805:
1.117 ! markus 806: static void
! 807: pubkey_cleanup(Authctxt *authctxt)
1.51 markus 808: {
1.117 ! markus 809: Identity *id;
1.51 markus 810:
1.117 ! markus 811: if (authctxt->agent != NULL)
! 812: ssh_close_authentication_connection(authctxt->agent);
! 813: for (id = TAILQ_FIRST(&authctxt->keys); id;
! 814: id = TAILQ_FIRST(&authctxt->keys)) {
! 815: TAILQ_REMOVE(&authctxt->keys, id, next);
! 816: if (id->key)
! 817: key_free(id->key);
! 818: if (id->filename)
! 819: xfree(id->filename);
! 820: xfree(id);
! 821: }
1.1 markus 822: }
823:
1.20 markus 824: int
825: userauth_pubkey(Authctxt *authctxt)
826: {
1.117 ! markus 827: Identity *id;
1.20 markus 828: int sent = 0;
829:
1.117 ! markus 830: while ((id = TAILQ_FIRST(&authctxt->keys))) {
! 831: if (id->tried++)
! 832: return (0);
! 833: TAILQ_REMOVE(&authctxt->keys, id, next);
! 834: TAILQ_INSERT_TAIL(&authctxt->keys, id, next);
! 835: /*
! 836: * send a test message if we have the public key. for
! 837: * encrypted keys we cannot do this and have to load the
! 838: * private key instead
! 839: */
! 840: if (id->key && id->key->type != KEY_RSA1) {
! 841: debug("Offering public key: %s", id->filename);
! 842: sent = send_pubkey_test(authctxt, id);
! 843: } else if (id->key == NULL) {
! 844: debug("Trying private key: %s", id->filename);
! 845: id->key = load_identity_file(id->filename);
! 846: if (id->key != NULL) {
! 847: id->isprivate = 1;
! 848: sent = sign_and_send_pubkey(authctxt, id);
! 849: key_free(id->key);
! 850: id->key = NULL;
1.51 markus 851: }
852: }
1.117 ! markus 853: if (sent)
! 854: return (sent);
1.28 markus 855: }
1.117 ! markus 856: return (0);
1.20 markus 857: }
858:
1.23 markus 859: /*
860: * Send userauth request message specifying keyboard-interactive method.
861: */
862: int
863: userauth_kbdint(Authctxt *authctxt)
864: {
865: static int attempt = 0;
866:
867: if (attempt++ >= options.number_of_password_prompts)
868: return 0;
1.82 markus 869: /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */
870: if (attempt > 1 && !authctxt->info_req_seen) {
871: debug3("userauth_kbdint: disable: no info_req_seen");
872: dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL);
873: return 0;
874: }
1.23 markus 875:
876: debug2("userauth_kbdint");
877: packet_start(SSH2_MSG_USERAUTH_REQUEST);
878: packet_put_cstring(authctxt->server_user);
879: packet_put_cstring(authctxt->service);
880: packet_put_cstring(authctxt->method->name);
881: packet_put_cstring(""); /* lang */
882: packet_put_cstring(options.kbd_interactive_devices ?
883: options.kbd_interactive_devices : "");
884: packet_send();
885:
886: dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
887: return 1;
888: }
889:
890: /*
1.46 markus 891: * parse INFO_REQUEST, prompt user and send INFO_RESPONSE
1.23 markus 892: */
893: void
1.92 markus 894: input_userauth_info_req(int type, u_int32_t seq, void *ctxt)
1.23 markus 895: {
896: Authctxt *authctxt = ctxt;
1.46 markus 897: char *name, *inst, *lang, *prompt, *response;
1.32 markus 898: u_int num_prompts, i;
1.23 markus 899: int echo = 0;
900:
901: debug2("input_userauth_info_req");
902:
903: if (authctxt == NULL)
904: fatal("input_userauth_info_req: no authentication context");
1.82 markus 905:
906: authctxt->info_req_seen = 1;
1.23 markus 907:
908: name = packet_get_string(NULL);
909: inst = packet_get_string(NULL);
910: lang = packet_get_string(NULL);
911: if (strlen(name) > 0)
1.116 itojun 912: logit("%s", name);
1.23 markus 913: if (strlen(inst) > 0)
1.116 itojun 914: logit("%s", inst);
1.46 markus 915: xfree(name);
1.23 markus 916: xfree(inst);
1.46 markus 917: xfree(lang);
1.23 markus 918:
919: num_prompts = packet_get_int();
920: /*
921: * Begin to build info response packet based on prompts requested.
922: * We commit to providing the correct number of responses, so if
923: * further on we run into a problem that prevents this, we have to
924: * be sure and clean this up and send a correct error response.
925: */
926: packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
927: packet_put_int(num_prompts);
928:
1.73 markus 929: debug2("input_userauth_info_req: num_prompts %d", num_prompts);
1.23 markus 930: for (i = 0; i < num_prompts; i++) {
931: prompt = packet_get_string(NULL);
932: echo = packet_get_char();
933:
1.77 markus 934: response = read_passphrase(prompt, echo ? RP_ECHO : 0);
1.23 markus 935:
1.49 markus 936: packet_put_cstring(response);
1.23 markus 937: memset(response, 0, strlen(response));
938: xfree(response);
939: xfree(prompt);
940: }
1.90 markus 941: packet_check_eom(); /* done with parsing incoming message. */
1.23 markus 942:
1.85 markus 943: packet_add_padding(64);
1.23 markus 944: packet_send();
1.68 markus 945: }
946:
1.100 markus 947: static int
1.105 deraadt 948: ssh_keysign(Key *key, u_char **sigp, u_int *lenp,
1.100 markus 949: u_char *data, u_int datalen)
950: {
951: Buffer b;
1.101 markus 952: struct stat st;
1.100 markus 953: pid_t pid;
1.103 markus 954: int to[2], from[2], status, version = 2;
1.100 markus 955:
1.109 markus 956: debug2("ssh_keysign called");
1.100 markus 957:
1.101 markus 958: if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) {
959: error("ssh_keysign: no installed: %s", strerror(errno));
960: return -1;
961: }
1.100 markus 962: if (fflush(stdout) != 0)
963: error("ssh_keysign: fflush: %s", strerror(errno));
964: if (pipe(to) < 0) {
965: error("ssh_keysign: pipe: %s", strerror(errno));
966: return -1;
967: }
968: if (pipe(from) < 0) {
969: error("ssh_keysign: pipe: %s", strerror(errno));
970: return -1;
971: }
972: if ((pid = fork()) < 0) {
973: error("ssh_keysign: fork: %s", strerror(errno));
974: return -1;
975: }
976: if (pid == 0) {
977: seteuid(getuid());
978: setuid(getuid());
979: close(from[0]);
980: if (dup2(from[1], STDOUT_FILENO) < 0)
981: fatal("ssh_keysign: dup2: %s", strerror(errno));
982: close(to[1]);
983: if (dup2(to[0], STDIN_FILENO) < 0)
984: fatal("ssh_keysign: dup2: %s", strerror(errno));
1.103 markus 985: close(from[1]);
986: close(to[0]);
1.102 markus 987: execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0);
1.100 markus 988: fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN,
989: strerror(errno));
990: }
991: close(from[1]);
992: close(to[0]);
993:
994: buffer_init(&b);
1.103 markus 995: buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */
1.100 markus 996: buffer_put_string(&b, data, datalen);
1.110 djm 997: ssh_msg_send(to[1], version, &b);
1.100 markus 998:
1.110 djm 999: if (ssh_msg_recv(from[0], &b) < 0) {
1.101 markus 1000: error("ssh_keysign: no reply");
1.100 markus 1001: buffer_clear(&b);
1002: return -1;
1003: }
1.101 markus 1004: close(from[0]);
1005: close(to[1]);
1006:
1.103 markus 1007: while (waitpid(pid, &status, 0) < 0)
1008: if (errno != EINTR)
1009: break;
1.101 markus 1010:
1.100 markus 1011: if (buffer_get_char(&b) != version) {
1.101 markus 1012: error("ssh_keysign: bad version");
1.100 markus 1013: buffer_clear(&b);
1014: return -1;
1015: }
1016: *sigp = buffer_get_string(&b, lenp);
1017: buffer_clear(&b);
1018:
1019: return 0;
1020: }
1021:
1.68 markus 1022: int
1023: userauth_hostbased(Authctxt *authctxt)
1024: {
1025: Key *private = NULL;
1.100 markus 1026: Sensitive *sensitive = authctxt->sensitive;
1.68 markus 1027: Buffer b;
1028: u_char *signature, *blob;
1029: char *chost, *pkalg, *p;
1.72 markus 1030: const char *service;
1.68 markus 1031: u_int blen, slen;
1.71 markus 1032: int ok, i, len, found = 0;
1.68 markus 1033:
1034: /* check for a useful key */
1.100 markus 1035: for (i = 0; i < sensitive->nkeys; i++) {
1036: private = sensitive->keys[i];
1.68 markus 1037: if (private && private->type != KEY_RSA1) {
1038: found = 1;
1039: /* we take and free the key */
1.100 markus 1040: sensitive->keys[i] = NULL;
1.68 markus 1041: break;
1042: }
1043: }
1044: if (!found) {
1.109 markus 1045: debug("No more client hostkeys for hostbased authentication.");
1.68 markus 1046: return 0;
1047: }
1048: if (key_to_blob(private, &blob, &blen) == 0) {
1049: key_free(private);
1050: return 0;
1051: }
1.84 markus 1052: /* figure out a name for the client host */
1053: p = get_local_name(packet_get_connection_in());
1054: if (p == NULL) {
1055: error("userauth_hostbased: cannot get local ipaddr/name");
1056: key_free(private);
1057: return 0;
1058: }
1059: len = strlen(p) + 2;
1060: chost = xmalloc(len);
1061: strlcpy(chost, p, len);
1062: strlcat(chost, ".", len);
1063: debug2("userauth_hostbased: chost %s", chost);
1.112 markus 1064: xfree(p);
1.84 markus 1065:
1.72 markus 1066: service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
1067: authctxt->service;
1.68 markus 1068: pkalg = xstrdup(key_ssh_name(private));
1069: buffer_init(&b);
1070: /* construct data */
1.72 markus 1071: buffer_put_string(&b, session_id2, session_id2_len);
1.68 markus 1072: buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
1073: buffer_put_cstring(&b, authctxt->server_user);
1.72 markus 1074: buffer_put_cstring(&b, service);
1.68 markus 1075: buffer_put_cstring(&b, authctxt->method->name);
1076: buffer_put_cstring(&b, pkalg);
1077: buffer_put_string(&b, blob, blen);
1078: buffer_put_cstring(&b, chost);
1079: buffer_put_cstring(&b, authctxt->local_user);
1080: #ifdef DEBUG_PK
1081: buffer_dump(&b);
1082: #endif
1.100 markus 1083: if (sensitive->external_keysign)
1084: ok = ssh_keysign(private, &signature, &slen,
1085: buffer_ptr(&b), buffer_len(&b));
1086: else
1087: ok = key_sign(private, &signature, &slen,
1088: buffer_ptr(&b), buffer_len(&b));
1.68 markus 1089: key_free(private);
1090: buffer_free(&b);
1091: if (ok != 0) {
1092: error("key_sign failed");
1093: xfree(chost);
1094: xfree(pkalg);
1095: return 0;
1096: }
1097: packet_start(SSH2_MSG_USERAUTH_REQUEST);
1098: packet_put_cstring(authctxt->server_user);
1099: packet_put_cstring(authctxt->service);
1100: packet_put_cstring(authctxt->method->name);
1101: packet_put_cstring(pkalg);
1102: packet_put_string(blob, blen);
1103: packet_put_cstring(chost);
1104: packet_put_cstring(authctxt->local_user);
1105: packet_put_string(signature, slen);
1106: memset(signature, 's', slen);
1107: xfree(signature);
1108: xfree(chost);
1109: xfree(pkalg);
1110:
1111: packet_send();
1112: return 1;
1.23 markus 1113: }
1.20 markus 1114:
1115: /* find auth method */
1116:
1117: /*
1118: * given auth method name, if configurable options permit this method fill
1119: * in auth_ident field and return true, otherwise return false.
1120: */
1.76 itojun 1121: static int
1.20 markus 1122: authmethod_is_enabled(Authmethod *method)
1123: {
1124: if (method == NULL)
1125: return 0;
1126: /* return false if options indicate this method is disabled */
1127: if (method->enabled == NULL || *method->enabled == 0)
1128: return 0;
1129: /* return false if batch mode is enabled but method needs interactive mode */
1130: if (method->batch_flag != NULL && *method->batch_flag != 0)
1131: return 0;
1132: return 1;
1133: }
1134:
1.76 itojun 1135: static Authmethod *
1.20 markus 1136: authmethod_lookup(const char *name)
1.1 markus 1137: {
1.20 markus 1138: Authmethod *method = NULL;
1139: if (name != NULL)
1140: for (method = authmethods; method->name != NULL; method++)
1141: if (strcmp(name, method->name) == 0)
1142: return method;
1143: debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
1144: return NULL;
1145: }
1.1 markus 1146:
1.53 markus 1147: /* XXX internal state */
1148: static Authmethod *current = NULL;
1149: static char *supported = NULL;
1150: static char *preferred = NULL;
1.105 deraadt 1151:
1.20 markus 1152: /*
1153: * Given the authentication method list sent by the server, return the
1154: * next method we should try. If the server initially sends a nil list,
1.67 markus 1155: * use a built-in default list.
1.41 stevesk 1156: */
1.76 itojun 1157: static Authmethod *
1.20 markus 1158: authmethod_get(char *authlist)
1159: {
1.53 markus 1160: char *name = NULL;
1.97 markus 1161: u_int next;
1.41 stevesk 1162:
1.20 markus 1163: /* Use a suitable default if we're passed a nil list. */
1164: if (authlist == NULL || strlen(authlist) == 0)
1.53 markus 1165: authlist = options.preferred_authentications;
1.20 markus 1166:
1.53 markus 1167: if (supported == NULL || strcmp(authlist, supported) != 0) {
1168: debug3("start over, passed a different list %s", authlist);
1169: if (supported != NULL)
1170: xfree(supported);
1171: supported = xstrdup(authlist);
1172: preferred = options.preferred_authentications;
1173: debug3("preferred %s", preferred);
1174: current = NULL;
1175: } else if (current != NULL && authmethod_is_enabled(current))
1176: return current;
1.20 markus 1177:
1.53 markus 1178: for (;;) {
1179: if ((name = match_list(preferred, supported, &next)) == NULL) {
1.109 markus 1180: debug("No more authentication methods to try.");
1.53 markus 1181: current = NULL;
1182: return NULL;
1183: }
1184: preferred += next;
1.23 markus 1185: debug3("authmethod_lookup %s", name);
1.53 markus 1186: debug3("remaining preferred: %s", preferred);
1187: if ((current = authmethod_lookup(name)) != NULL &&
1188: authmethod_is_enabled(current)) {
1.23 markus 1189: debug3("authmethod_is_enabled %s", name);
1.109 markus 1190: debug("Next authentication method: %s", name);
1.53 markus 1191: return current;
1.23 markus 1192: }
1.1 markus 1193: }
1.53 markus 1194: }
1.1 markus 1195:
1.79 stevesk 1196: static char *
1.53 markus 1197: authmethods_get(void)
1198: {
1199: Authmethod *method = NULL;
1.93 markus 1200: Buffer b;
1201: char *list;
1.27 provos 1202:
1.93 markus 1203: buffer_init(&b);
1.53 markus 1204: for (method = authmethods; method->name != NULL; method++) {
1205: if (authmethod_is_enabled(method)) {
1.93 markus 1206: if (buffer_len(&b) > 0)
1207: buffer_append(&b, ",", 1);
1208: buffer_append(&b, method->name, strlen(method->name));
1.53 markus 1209: }
1210: }
1.93 markus 1211: buffer_append(&b, "\0", 1);
1212: list = xstrdup(buffer_ptr(&b));
1213: buffer_free(&b);
1214: return list;
1.1 markus 1215: }