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