]> andersk Git - gssapi-openssh.git/blame - openssh/sshconnect2.c
Initial revision
[gssapi-openssh.git] / openssh / sshconnect2.c
CommitLineData
3c0ef626 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"
2ce0bfe4 26RCSID("$OpenBSD: sshconnect2.c,v 1.142 2005/08/30 22:08:05 djm Exp $");
7cac2b65 27
28#include "openbsd-compat/sys-queue.h"
3c0ef626 29
30#include "ssh.h"
31#include "ssh2.h"
32#include "xmalloc.h"
3c0ef626 33#include "buffer.h"
34#include "packet.h"
3c0ef626 35#include "compat.h"
36#include "bufaux.h"
37#include "cipher.h"
38#include "kex.h"
39#include "myproposal.h"
3c0ef626 40#include "sshconnect.h"
41#include "authfile.h"
42#include "dh.h"
43#include "authfd.h"
44#include "log.h"
45#include "readconf.h"
7e82606e 46#include "misc.h"
3c0ef626 47#include "match.h"
48#include "dispatch.h"
49#include "canohost.h"
44a053a3 50#include "msg.h"
51#include "pathnames.h"
3c0ef626 52
5598e598 53#ifdef GSSAPI
54#include "ssh-gss.h"
55#endif
56
3c0ef626 57/* import */
58extern char *client_version_string;
59extern char *server_version_string;
60extern Options options;
473db5ab 61extern Kex *xxx_kex;
62
63/* tty_flag is set in ssh.c. use this in ssh_userauth2 */
64/* if it is set then prevent the switch to the null cipher */
65
66extern int tty_flag;
3c0ef626 67
68/*
69 * SSH2 key exchange
70 */
71
72u_char *session_id2 = NULL;
7cac2b65 73u_int session_id2_len = 0;
3c0ef626 74
75char *xxx_host;
76struct sockaddr *xxx_hostaddr;
77
78Kex *xxx_kex = NULL;
79
80static int
81verify_host_key_callback(Key *hostkey)
82{
83 if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1)
84 fatal("Host key verification failed.");
85 return 0;
86}
87
88void
89ssh_kex2(char *host, struct sockaddr *hostaddr)
90{
91 Kex *kex;
fe4ad273 92
1e608e42 93#ifdef GSSAPI
fe4ad273 94 char *orig = NULL, *gss = NULL;
1e608e42 95 int len;
fe4ad273 96 char *gss_host = NULL;
1e608e42 97#endif
3c0ef626 98
99 xxx_host = host;
100 xxx_hostaddr = hostaddr;
101
5598e598 102#ifdef GSSAPI
7a056ed1 103 if (options.gss_keyex) {
1e608e42 104 /* Add the GSSAPI mechanisms currently supported on this client to
105 * the key exchange algorithm proposal */
106 orig = myproposal[PROPOSAL_KEX_ALGS];
fe4ad273 107 if (options.gss_trust_dns)
108 gss_host = (char *)get_canonical_hostname(1);
109 else
110 gss_host = host;
111
112 gss = ssh_gssapi_client_mechanisms(gss_host);
1e608e42 113 if (gss) {
fe4ad273 114 debug("Offering GSSAPI proposal: %s", gss);
115 len = strlen(orig) + strlen(gss) + 2;
116 myproposal[PROPOSAL_KEX_ALGS] = xmalloc(len);
117 snprintf(myproposal[PROPOSAL_KEX_ALGS], len, "%s,%s", gss,
118 orig);
5598e598 119 }
7a056ed1 120 }
5598e598 121#endif
122
3c0ef626 123 if (options.ciphers == (char *)-1) {
7cac2b65 124 logit("No valid ciphers for protocol version 2 given, using defaults.");
3c0ef626 125 options.ciphers = NULL;
126 }
127 if (options.ciphers != NULL) {
128 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
129 myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
130 }
131 myproposal[PROPOSAL_ENC_ALGS_CTOS] =
132 compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
133 myproposal[PROPOSAL_ENC_ALGS_STOC] =
134 compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
135 if (options.compression) {
136 myproposal[PROPOSAL_COMP_ALGS_CTOS] =
2ce0bfe4 137 myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib@openssh.com,zlib,none";
3c0ef626 138 } else {
139 myproposal[PROPOSAL_COMP_ALGS_CTOS] =
2ce0bfe4 140 myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com,zlib";
3c0ef626 141 }
142 if (options.macs != NULL) {
143 myproposal[PROPOSAL_MAC_ALGS_CTOS] =
144 myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
145 }
146 if (options.hostkeyalgorithms != NULL)
1e608e42 147 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
3c0ef626 148 options.hostkeyalgorithms;
149
1e608e42 150#ifdef GSSAPI
fe4ad273 151 /* If we've got GSSAPI algorithms, then we also support the
152 * 'null' hostkey, as a last resort */
7a056ed1 153 if (options.gss_keyex && gss) {
fe4ad273 154 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
155 len = strlen(orig) + sizeof(",null");
156 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xmalloc(len);
157 snprintf(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], len,
158 "%s,null", orig);
1e608e42 159 }
160#endif
7cac2b65 161
162 if (options.rekey_limit)
163 packet_set_rekey_limit(options.rekey_limit);
164
3c0ef626 165 /* start key exchange */
166 kex = kex_setup(myproposal);
bfe49944 167 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
7e82606e 168 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
bfe49944 169 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
170#ifdef GSSAPI
171 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
fe4ad273 172 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
bfe49944 173#endif
3c0ef626 174 kex->client_version_string=client_version_string;
175 kex->server_version_string=server_version_string;
176 kex->verify_host_key=&verify_host_key_callback;
5598e598 177#ifdef GSSAPI
178 kex->options.gss_deleg_creds=options.gss_deleg_creds;
179#endif
7cac2b65 180
fe4ad273 181#ifdef GSSAPI
182 kex->gss_deleg_creds = options.gss_deleg_creds;
183 kex->gss_trust_dns = options.gss_trust_dns;
184 kex->gss_host = gss_host;
185#endif
186
3c0ef626 187 xxx_kex = kex;
188
189 dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
190
191 session_id2 = kex->session_id;
192 session_id2_len = kex->session_id_len;
193
194#ifdef DEBUG_KEXDH
195 /* send 1st encrypted/maced/compressed message */
196 packet_start(SSH2_MSG_IGNORE);
197 packet_put_cstring("markus");
198 packet_send();
199 packet_write_wait();
200#endif
3c0ef626 201}
202
203/*
204 * Authenticate user
205 */
206
207typedef struct Authctxt Authctxt;
208typedef struct Authmethod Authmethod;
7cac2b65 209typedef struct identity Identity;
210typedef struct idlist Idlist;
211
212struct identity {
213 TAILQ_ENTRY(identity) next;
214 AuthenticationConnection *ac; /* set if agent supports key */
215 Key *key; /* public/private key */
216 char *filename; /* comment for agent-only keys */
217 int tried;
218 int isprivate; /* key points to the private key */
219};
220TAILQ_HEAD(idlist, identity);
3c0ef626 221
222struct Authctxt {
223 const char *server_user;
224 const char *local_user;
225 const char *host;
226 const char *service;
227 Authmethod *method;
228 int success;
229 char *authlist;
230 /* pubkey */
7cac2b65 231 Idlist keys;
3c0ef626 232 AuthenticationConnection *agent;
233 /* hostbased */
44a053a3 234 Sensitive *sensitive;
3c0ef626 235 /* kbd-interactive */
236 int info_req_seen;
5598e598 237 /* generic */
238 void *methoddata;
3c0ef626 239};
240struct Authmethod {
241 char *name; /* string to compare against server's list */
242 int (*userauth)(Authctxt *authctxt);
243 int *enabled; /* flag in option struct that enables method */
244 int *batch_flag; /* flag in option struct that disables method */
245};
246
1e608e42 247void input_userauth_success(int, u_int32_t, void *);
248void input_userauth_failure(int, u_int32_t, void *);
249void input_userauth_banner(int, u_int32_t, void *);
250void input_userauth_error(int, u_int32_t, void *);
251void input_userauth_info_req(int, u_int32_t, void *);
252void input_userauth_pk_ok(int, u_int32_t, void *);
510132b6 253void input_userauth_passwd_changereq(int, u_int32_t, void *);
3c0ef626 254
1e608e42 255int userauth_none(Authctxt *);
256int userauth_pubkey(Authctxt *);
257int userauth_passwd(Authctxt *);
258int userauth_kbdint(Authctxt *);
259int userauth_hostbased(Authctxt *);
7cac2b65 260int userauth_kerberos(Authctxt *);
261
5598e598 262#ifdef GSSAPI
1e608e42 263int userauth_external(Authctxt *authctxt);
264int userauth_gssapi(Authctxt *authctxt);
540d72c3 265int userauth_gssapi_with_mic(Authctxt *authctxt);
266int userauth_gssapi_without_mic(Authctxt *authctxt);
e23e524c 267void input_gssapi_response(int type, u_int32_t, void *);
268void input_gssapi_token(int type, u_int32_t, void *);
269void input_gssapi_hash(int type, u_int32_t, void *);
23987cb8 270void input_gssapi_error(int, u_int32_t, void *);
e23e524c 271void input_gssapi_errtok(int, u_int32_t, void *);
fe4ad273 272int userauth_gsskeyex(Authctxt *authctxt);
5598e598 273#endif
274
1e608e42 275void userauth(Authctxt *, char *);
3c0ef626 276
7cac2b65 277static int sign_and_send_pubkey(Authctxt *, Identity *);
278static void pubkey_prepare(Authctxt *);
279static void pubkey_cleanup(Authctxt *);
280static Key *load_identity_file(char *);
3c0ef626 281
282static Authmethod *authmethod_get(char *authlist);
283static Authmethod *authmethod_lookup(const char *name);
284static char *authmethods_get(void);
285
286Authmethod authmethods[] = {
5598e598 287#ifdef GSSAPI
fe4ad273 288 {"gssapi-keyex",
289 userauth_gsskeyex,
290 &options.gss_authentication,
291 NULL},
5598e598 292 {"external-keyx",
293 userauth_external,
294 &options.gss_authentication,
295 NULL},
540d72c3 296 {"gssapi-with-mic",
51b9ca75 297 userauth_gssapi,
540d72c3 298 &options.gss_authentication,
299 NULL},
5598e598 300 {"gssapi",
51b9ca75 301 userauth_gssapi,
5598e598 302 &options.gss_authentication,
303 NULL},
304#endif
3c0ef626 305 {"hostbased",
306 userauth_hostbased,
307 &options.hostbased_authentication,
308 NULL},
309 {"publickey",
310 userauth_pubkey,
311 &options.pubkey_authentication,
312 NULL},
313 {"keyboard-interactive",
314 userauth_kbdint,
315 &options.kbd_interactive_authentication,
316 &options.batch_mode},
317 {"password",
318 userauth_passwd,
319 &options.password_authentication,
320 &options.batch_mode},
321 {"none",
322 userauth_none,
323 NULL,
324 NULL},
325 {NULL, NULL, NULL, NULL}
326};
327
328void
329ssh_userauth2(const char *local_user, const char *server_user, char *host,
44a053a3 330 Sensitive *sensitive)
3c0ef626 331{
332 Authctxt authctxt;
333 int type;
3c0ef626 334
335 if (options.challenge_response_authentication)
336 options.kbd_interactive_authentication = 1;
337
3c0ef626 338 packet_start(SSH2_MSG_SERVICE_REQUEST);
339 packet_put_cstring("ssh-userauth");
340 packet_send();
bfe49944 341 debug("SSH2_MSG_SERVICE_REQUEST sent");
3c0ef626 342 packet_write_wait();
1e608e42 343 type = packet_read();
bfe49944 344 if (type != SSH2_MSG_SERVICE_ACCEPT)
345 fatal("Server denied authentication request: %d", type);
3c0ef626 346 if (packet_remaining() > 0) {
1e608e42 347 char *reply = packet_get_string(NULL);
bfe49944 348 debug2("service_accept: %s", reply);
3c0ef626 349 xfree(reply);
350 } else {
bfe49944 351 debug2("buggy server: service_accept w/o service");
3c0ef626 352 }
1e608e42 353 packet_check_eom();
bfe49944 354 debug("SSH2_MSG_SERVICE_ACCEPT received");
3c0ef626 355
356 if (options.preferred_authentications == NULL)
357 options.preferred_authentications = authmethods_get();
358
359 /* setup authentication context */
360 memset(&authctxt, 0, sizeof(authctxt));
7cac2b65 361 pubkey_prepare(&authctxt);
3c0ef626 362 authctxt.server_user = server_user;
363 authctxt.local_user = local_user;
364 authctxt.host = host;
365 authctxt.service = "ssh-connection"; /* service name */
366 authctxt.success = 0;
367 authctxt.method = authmethod_lookup("none");
368 authctxt.authlist = NULL;
5598e598 369 authctxt.methoddata = NULL;
44a053a3 370 authctxt.sensitive = sensitive;
3c0ef626 371 authctxt.info_req_seen = 0;
372 if (authctxt.method == NULL)
373 fatal("ssh_userauth2: internal error: cannot send userauth none request");
374
375 /* initial userauth request */
376 userauth_none(&authctxt);
377
378 dispatch_init(&input_userauth_error);
379 dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
380 dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
381 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
382 dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
383
7cac2b65 384 pubkey_cleanup(&authctxt);
385 dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL);
473db5ab 386 if ((options.none_switch == 1) && !tty_flag) /* no null on tty sessions */
387 {
388 debug("Requesting none rekeying...");
389 myproposal[PROPOSAL_ENC_ALGS_STOC] = "none";
390 myproposal[PROPOSAL_ENC_ALGS_CTOS] = "none";
391 kex_prop2buf(&xxx_kex->my,myproposal);
392 packet_request_rekeying();
393 fprintf(stderr, "WARNING: ENABLED NULL CIPHER\n");
394 }
bfe49944 395 debug("Authentication succeeded (%s).", authctxt.method->name);
3c0ef626 396}
7cac2b65 397
3c0ef626 398void
399userauth(Authctxt *authctxt, char *authlist)
400{
7cac2b65 401 if (authctxt->methoddata) {
5598e598 402 xfree(authctxt->methoddata);
7cac2b65 403 authctxt->methoddata = NULL;
5598e598 404 }
3c0ef626 405 if (authlist == NULL) {
406 authlist = authctxt->authlist;
407 } else {
408 if (authctxt->authlist)
409 xfree(authctxt->authlist);
410 authctxt->authlist = authlist;
411 }
412 for (;;) {
413 Authmethod *method = authmethod_get(authlist);
414 if (method == NULL)
415 fatal("Permission denied (%s).", authlist);
416 authctxt->method = method;
7cac2b65 417
418 /* reset the per method handler */
419 dispatch_range(SSH2_MSG_USERAUTH_PER_METHOD_MIN,
420 SSH2_MSG_USERAUTH_PER_METHOD_MAX, NULL);
421
422 /* and try new method */
3c0ef626 423 if (method->userauth(authctxt) != 0) {
424 debug2("we sent a %s packet, wait for reply", method->name);
425 break;
426 } else {
427 debug2("we did not send a packet, disable method");
428 method->enabled = NULL;
429 }
430 }
431}
276b07a3 432
3c0ef626 433void
1e608e42 434input_userauth_error(int type, u_int32_t seq, void *ctxt)
3c0ef626 435{
436 fatal("input_userauth_error: bad message during authentication: "
2ce0bfe4 437 "type %d", type);
3c0ef626 438}
276b07a3 439
3c0ef626 440void
1e608e42 441input_userauth_banner(int type, u_int32_t seq, void *ctxt)
3c0ef626 442{
443 char *msg, *lang;
540d72c3 444
3c0ef626 445 debug3("input_userauth_banner");
446 msg = packet_get_string(NULL);
447 lang = packet_get_string(NULL);
540d72c3 448 if (options.log_level > SYSLOG_LEVEL_QUIET)
449 fprintf(stderr, "%s", msg);
3c0ef626 450 xfree(msg);
451 xfree(lang);
452}
276b07a3 453
3c0ef626 454void
1e608e42 455input_userauth_success(int type, u_int32_t seq, void *ctxt)
3c0ef626 456{
457 Authctxt *authctxt = ctxt;
458 if (authctxt == NULL)
459 fatal("input_userauth_success: no authentication context");
540d72c3 460 if (authctxt->authlist) {
3c0ef626 461 xfree(authctxt->authlist);
540d72c3 462 authctxt->authlist = NULL;
463 }
464 if (authctxt->methoddata) {
5598e598 465 xfree(authctxt->methoddata);
540d72c3 466 authctxt->methoddata = NULL;
467 }
3c0ef626 468 authctxt->success = 1; /* break out */
469}
276b07a3 470
3c0ef626 471void
1e608e42 472input_userauth_failure(int type, u_int32_t seq, void *ctxt)
3c0ef626 473{
474 Authctxt *authctxt = ctxt;
475 char *authlist = NULL;
476 int partial;
477
478 if (authctxt == NULL)
479 fatal("input_userauth_failure: no authentication context");
480
481 authlist = packet_get_string(NULL);
482 partial = packet_get_char();
1e608e42 483 packet_check_eom();
3c0ef626 484
485 if (partial != 0)
7cac2b65 486 logit("Authenticated with partial success.");
bfe49944 487 debug("Authentications that can continue: %s", authlist);
3c0ef626 488
3c0ef626 489 userauth(authctxt, authlist);
490}
491void
1e608e42 492input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
3c0ef626 493{
494 Authctxt *authctxt = ctxt;
495 Key *key = NULL;
7cac2b65 496 Identity *id = NULL;
3c0ef626 497 Buffer b;
1e608e42 498 int pktype, sent = 0;
499 u_int alen, blen;
500 char *pkalg, *fp;
501 u_char *pkblob;
3c0ef626 502
503 if (authctxt == NULL)
504 fatal("input_userauth_pk_ok: no authentication context");
505 if (datafellows & SSH_BUG_PKOK) {
506 /* this is similar to SSH_BUG_PKAUTH */
507 debug2("input_userauth_pk_ok: SSH_BUG_PKOK");
508 pkblob = packet_get_string(&blen);
509 buffer_init(&b);
510 buffer_append(&b, pkblob, blen);
511 pkalg = buffer_get_string(&b, &alen);
512 buffer_free(&b);
513 } else {
514 pkalg = packet_get_string(&alen);
515 pkblob = packet_get_string(&blen);
516 }
1e608e42 517 packet_check_eom();
3c0ef626 518
7cac2b65 519 debug("Server accepts key: pkalg %s blen %u", pkalg, blen);
3c0ef626 520
7cac2b65 521 if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
522 debug("unknown pkalg %s", pkalg);
523 goto done;
524 }
525 if ((key = key_from_blob(pkblob, blen)) == NULL) {
526 debug("no key from blob. pkalg %s", pkalg);
527 goto done;
528 }
529 if (key->type != pktype) {
530 error("input_userauth_pk_ok: type mismatch "
531 "for decoded key (received %d, expected %d)",
532 key->type, pktype);
533 goto done;
534 }
535 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
536 debug2("input_userauth_pk_ok: fp %s", fp);
537 xfree(fp);
538
540d72c3 539 /*
540 * search keys in the reverse order, because last candidate has been
541 * moved to the end of the queue. this also avoids confusion by
542 * duplicate keys
543 */
7e82606e 544 TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) {
7cac2b65 545 if (key_equal(key, id->key)) {
546 sent = sign_and_send_pubkey(authctxt, id);
3c0ef626 547 break;
548 }
7cac2b65 549 }
550done:
3c0ef626 551 if (key != NULL)
552 key_free(key);
553 xfree(pkalg);
554 xfree(pkblob);
555
d03f4262 556 /* try another method if we did not send a packet */
3c0ef626 557 if (sent == 0)
558 userauth(authctxt, NULL);
3c0ef626 559}
560
5598e598 561#ifdef GSSAPI
540d72c3 562int
5598e598 563userauth_gssapi(Authctxt *authctxt)
564{
23987cb8 565 Gssctxt *gssctxt = NULL;
540d72c3 566 static gss_OID_set gss_supported = NULL;
2ce0bfe4 567 static u_int mech = 0;
23987cb8 568 OM_uint32 min;
7cac2b65 569 int ok = 0;
fe4ad273 570 char *gss_host = NULL;
23987cb8 571
35094e47 572 if (!options.gss_authentication) {
573 verbose("GSSAPI authentication disabled.");
574 return 0;
575 }
576
fe4ad273 577 if (options.gss_trust_dns)
578 gss_host = (char *)get_canonical_hostname(1);
579 else
580 gss_host = (char *)authctxt->host;
581
7cac2b65 582 /* Try one GSSAPI method at a time, rather than sending them all at
583 * once. */
5598e598 584
540d72c3 585 if (gss_supported == NULL)
586 gss_indicate_mechs(&min, &gss_supported);
b59afbfe 587
7cac2b65 588 /* Check to see if the mechanism is usable before we offer it */
540d72c3 589 while (mech < gss_supported->count && !ok) {
7cac2b65 590 if (gssctxt)
591 ssh_gssapi_delete_ctx(&gssctxt);
23987cb8 592 ssh_gssapi_build_ctx(&gssctxt);
540d72c3 593 ssh_gssapi_set_oid(gssctxt, &gss_supported->elements[mech]);
23987cb8 594
7cac2b65 595 /* My DER encoding requires length<128 */
540d72c3 596 if (gss_supported->elements[mech].length < 128 &&
f1c93965 597 ssh_gssapi_check_mechanism(&gss_supported->elements[mech],
fe4ad273 598 gss_host) &&
23987cb8 599 !GSS_ERROR(ssh_gssapi_import_name(gssctxt,
fe4ad273 600 gss_host))) {
7cac2b65 601 ok = 1; /* Mechanism works */
23987cb8 602 } else {
603 mech++;
604 }
5598e598 605 }
7cac2b65 606
2ce0bfe4 607 if (!ok)
608 return 0;
7cac2b65 609
5598e598 610 authctxt->methoddata=(void *)gssctxt;
7cac2b65 611
5598e598 612 packet_start(SSH2_MSG_USERAUTH_REQUEST);
23987cb8 613 packet_put_cstring(authctxt->server_user);
5598e598 614 packet_put_cstring(authctxt->service);
7cac2b65 615 packet_put_cstring(authctxt->method->name);
616
23987cb8 617 packet_put_int(1);
5598e598 618
dfddba3d 619 packet_put_int((gss_supported->elements[mech].length) + 2);
620 packet_put_char(SSH_GSS_OIDTYPE);
621 packet_put_char(gss_supported->elements[mech].length);
622 packet_put_raw(gss_supported->elements[mech].elements,
623 gss_supported->elements[mech].length);
91a31bec 624
7cac2b65 625 packet_send();
626
627 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response);
628 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
629 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error);
630 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
5598e598 631
23987cb8 632 mech++; /* Move along to next candidate */
91a31bec 633
7cac2b65 634 return 1;
5598e598 635}
636
540d72c3 637static OM_uint32
638process_gssapi_token(void *ctxt, gss_buffer_t recv_tok)
639{
640 Authctxt *authctxt = ctxt;
641 Gssctxt *gssctxt = authctxt->methoddata;
642 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
2ce0bfe4 643 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
644 gss_buffer_desc gssbuf;
540d72c3 645 OM_uint32 status, ms, flags;
646 Buffer b;
647
648 status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
649 recv_tok, &send_tok, &flags);
650
651 if (send_tok.length > 0) {
652 if (GSS_ERROR(status))
653 packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
654 else
655 packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
656
657 packet_put_string(send_tok.value, send_tok.length);
658 packet_send();
659 gss_release_buffer(&ms, &send_tok);
660 }
661
662 if (status == GSS_S_COMPLETE) {
663 /* send either complete or MIC, depending on mechanism */
51b9ca75 664 if (strcmp(authctxt->method->name,"gssapi")==0 ||
665 (!(flags & GSS_C_INTEG_FLAG))) {
540d72c3 666 packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
667 packet_send();
668 } else {
669 ssh_gssapi_buildmic(&b, authctxt->server_user,
670 authctxt->service, "gssapi-with-mic");
671
672 gssbuf.value = buffer_ptr(&b);
673 gssbuf.length = buffer_len(&b);
674
675 status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic);
676
677 if (!GSS_ERROR(status)) {
678 packet_start(SSH2_MSG_USERAUTH_GSSAPI_MIC);
679 packet_put_string(mic.value, mic.length);
680
681 packet_send();
682 }
683
684 buffer_free(&b);
685 gss_release_buffer(&ms, &mic);
686 }
687 }
688
689 return status;
690}
691
5598e598 692void
7cac2b65 693input_gssapi_response(int type, u_int32_t plen, void *ctxt)
5598e598 694{
695 Authctxt *authctxt = ctxt;
696 Gssctxt *gssctxt;
fe4ad273 697 unsigned int oidlen;
698 unsigned char *oidv;
7cac2b65 699
5598e598 700 if (authctxt == NULL)
701 fatal("input_gssapi_response: no authentication context");
702 gssctxt = authctxt->methoddata;
7cac2b65 703
5598e598 704 /* Setup our OID */
7cac2b65 705 oidv = packet_get_string(&oidlen);
706
dfddba3d 707 if (oidlen <= 2 ||
708 oidv[0] != SSH_GSS_OIDTYPE ||
709 oidv[1] != oidlen - 2) {
710 xfree(oidv);
711 debug("Badly encoded mechanism OID received");
712 userauth(authctxt, NULL);
713 return;
23987cb8 714 }
7cac2b65 715
dfddba3d 716 if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2))
717 fatal("Server returned different OID than expected");
718
1e608e42 719 packet_check_eom();
7cac2b65 720
721 xfree(oidv);
722
540d72c3 723 if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) {
5598e598 724 /* Start again with next method on list */
725 debug("Trying to start again");
7cac2b65 726 userauth(authctxt, NULL);
5598e598 727 return;
728 }
5598e598 729}
730
731void
1e608e42 732input_gssapi_token(int type, u_int32_t plen, void *ctxt)
5598e598 733{
734 Authctxt *authctxt = ctxt;
7cac2b65 735 gss_buffer_desc recv_tok;
540d72c3 736 OM_uint32 status;
007914b3 737 u_int slen;
7cac2b65 738
5598e598 739 if (authctxt == NULL)
7cac2b65 740 fatal("input_gssapi_response: no authentication context");
5598e598 741
7cac2b65 742 recv_tok.value = packet_get_string(&slen);
743 recv_tok.length = slen; /* safe typecast */
5598e598 744
1e608e42 745 packet_check_eom();
7cac2b65 746
540d72c3 747 status = process_gssapi_token(ctxt, &recv_tok);
7cac2b65 748
749 xfree(recv_tok.value);
750
5598e598 751 if (GSS_ERROR(status)) {
752 /* Start again with the next method in the list */
7cac2b65 753 userauth(authctxt, NULL);
5598e598 754 return;
755 }
5598e598 756}
757
e23e524c 758void
759input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
760{
761 Authctxt *authctxt = ctxt;
762 Gssctxt *gssctxt;
7cac2b65 763 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
764 gss_buffer_desc recv_tok;
765 OM_uint32 status, ms;
766 u_int len;
767
e23e524c 768 if (authctxt == NULL)
769 fatal("input_gssapi_response: no authentication context");
770 gssctxt = authctxt->methoddata;
e23e524c 771
7cac2b65 772 recv_tok.value = packet_get_string(&len);
773 recv_tok.length = len;
e23e524c 774
775 packet_check_eom();
7cac2b65 776
777 /* Stick it into GSSAPI and see what it says */
778 status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
2ce0bfe4 779 &recv_tok, &send_tok, NULL);
7cac2b65 780
781 xfree(recv_tok.value);
782 gss_release_buffer(&ms, &send_tok);
783
784 /* Server will be returning a failed packet after this one */
e23e524c 785}
786
23987cb8 787void
788input_gssapi_error(int type, u_int32_t plen, void *ctxt)
789{
7cac2b65 790 OM_uint32 maj, min;
23987cb8 791 char *msg;
792 char *lang;
7cac2b65 793
23987cb8 794 maj=packet_get_int();
795 min=packet_get_int();
796 msg=packet_get_string(NULL);
797 lang=packet_get_string(NULL);
798
799 packet_check_eom();
7cac2b65 800
801 debug("Server GSSAPI Error:\n%s\n", msg);
23987cb8 802 xfree(msg);
803 xfree(lang);
804}
805
fe4ad273 806#ifdef GSI
807extern
808const gss_OID_desc * const gss_mech_globus_gssapi_openssl;
809#define is_gsi_oid(oid) \
810 (oid->length == gss_mech_globus_gssapi_openssl->length && \
811 (memcmp(oid->elements, gss_mech_globus_gssapi_openssl->elements, \
812 oid->length) == 0))
813#endif
814
5598e598 815int
816userauth_external(Authctxt *authctxt)
817{
7cac2b65 818 static int attempt = 0;
5598e598 819
820 if (attempt++ >= 1)
821 return 0;
822
41cbd9f8 823 /* The client MUST NOT try this method if initial key exchange
824 was not performed using a GSSAPI-based key exchange
825 method. */
fe4ad273 826 if (gss_kex_context == NULL) {
41cbd9f8 827 debug2("gsskex not performed, skipping external-keyx");
828 return 0;
829 }
830
5598e598 831 debug2("userauth_external");
832 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1baa1dac 833#ifdef GSI
fe4ad273 834 if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
835 packet_put_cstring("");
2e9d2d36 836 } else {
1baa1dac 837#endif
fe4ad273 838 packet_put_cstring(authctxt->server_user);
1baa1dac 839#ifdef GSI
2e9d2d36 840 }
1baa1dac 841#endif
5598e598 842 packet_put_cstring(authctxt->service);
843 packet_put_cstring(authctxt->method->name);
844 packet_send();
845 packet_write_wait();
846 return 1;
847}
fe4ad273 848int
849userauth_gsskeyex(Authctxt *authctxt)
850{
851 Buffer b;
852 gss_buffer_desc gssbuf;
853 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
854 OM_uint32 ms;
855
856 static int attempt = 0;
857 if (attempt++ >= 1)
858 return (0);
859
860 if (gss_kex_context == NULL) {
861 debug("No valid Key exchange context");
862 return (0);
863 }
864
865#ifdef GSI
866 if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
867 ssh_gssapi_buildmic(&b, "", authctxt->service, "gssapi-keyex");
868 } else {
869#endif
870 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
871 "gssapi-keyex");
872#ifdef GSI
873 }
874#endif
875
876 gssbuf.value = buffer_ptr(&b);
877 gssbuf.length = buffer_len(&b);
878
879 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
880 buffer_free(&b);
881 return (0);
882 }
883
884 packet_start(SSH2_MSG_USERAUTH_REQUEST);
885#ifdef GSI
886 if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
887 packet_put_cstring("");
888 } else {
889#endif
890 packet_put_cstring(authctxt->server_user);
891#ifdef GSI
892 }
893#endif
894 packet_put_cstring(authctxt->service);
895 packet_put_cstring(authctxt->method->name);
896 packet_put_string(mic.value, mic.length);
897 packet_send();
898
899 buffer_free(&b);
900 gss_release_buffer(&ms, &mic);
901
902 return (1);
903}
904
5598e598 905#endif /* GSSAPI */
906
3c0ef626 907int
908userauth_none(Authctxt *authctxt)
909{
910 /* initial userauth request */
911 packet_start(SSH2_MSG_USERAUTH_REQUEST);
912 packet_put_cstring(authctxt->server_user);
913 packet_put_cstring(authctxt->service);
914 packet_put_cstring(authctxt->method->name);
915 packet_send();
916 return 1;
917}
918
919int
920userauth_passwd(Authctxt *authctxt)
921{
922 static int attempt = 0;
510132b6 923 char prompt[150];
3c0ef626 924 char *password;
925
926 if (attempt++ >= options.number_of_password_prompts)
927 return 0;
928
1e608e42 929 if (attempt != 1)
3c0ef626 930 error("Permission denied, please try again.");
931
932 snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
933 authctxt->server_user, authctxt->host);
934 password = read_passphrase(prompt, 0);
935 packet_start(SSH2_MSG_USERAUTH_REQUEST);
936 packet_put_cstring(authctxt->server_user);
937 packet_put_cstring(authctxt->service);
938 packet_put_cstring(authctxt->method->name);
939 packet_put_char(0);
940 packet_put_cstring(password);
941 memset(password, 0, strlen(password));
942 xfree(password);
943 packet_add_padding(64);
944 packet_send();
510132b6 945
44a053a3 946 dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
510132b6 947 &input_userauth_passwd_changereq);
948
3c0ef626 949 return 1;
950}
510132b6 951/*
952 * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST
953 */
954void
955input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
956{
957 Authctxt *authctxt = ctxt;
958 char *info, *lang, *password = NULL, *retype = NULL;
959 char prompt[150];
960
961 debug2("input_userauth_passwd_changereq");
962
963 if (authctxt == NULL)
964 fatal("input_userauth_passwd_changereq: "
965 "no authentication context");
966
967 info = packet_get_string(NULL);
968 lang = packet_get_string(NULL);
969 if (strlen(info) > 0)
7cac2b65 970 logit("%s", info);
510132b6 971 xfree(info);
972 xfree(lang);
973 packet_start(SSH2_MSG_USERAUTH_REQUEST);
974 packet_put_cstring(authctxt->server_user);
975 packet_put_cstring(authctxt->service);
976 packet_put_cstring(authctxt->method->name);
977 packet_put_char(1); /* additional info */
44a053a3 978 snprintf(prompt, sizeof(prompt),
510132b6 979 "Enter %.30s@%.128s's old password: ",
980 authctxt->server_user, authctxt->host);
981 password = read_passphrase(prompt, 0);
982 packet_put_cstring(password);
983 memset(password, 0, strlen(password));
984 xfree(password);
985 password = NULL;
986 while (password == NULL) {
44a053a3 987 snprintf(prompt, sizeof(prompt),
510132b6 988 "Enter %.30s@%.128s's new password: ",
989 authctxt->server_user, authctxt->host);
990 password = read_passphrase(prompt, RP_ALLOW_EOF);
991 if (password == NULL) {
992 /* bail out */
993 return;
994 }
44a053a3 995 snprintf(prompt, sizeof(prompt),
510132b6 996 "Retype %.30s@%.128s's new password: ",
997 authctxt->server_user, authctxt->host);
998 retype = read_passphrase(prompt, 0);
999 if (strcmp(password, retype) != 0) {
1000 memset(password, 0, strlen(password));
1001 xfree(password);
7cac2b65 1002 logit("Mismatch; try again, EOF to quit.");
510132b6 1003 password = NULL;
1004 }
1005 memset(retype, 0, strlen(retype));
1006 xfree(retype);
1007 }
1008 packet_put_cstring(password);
1009 memset(password, 0, strlen(password));
1010 xfree(password);
1011 packet_add_padding(64);
1012 packet_send();
44a053a3 1013
1014 dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
510132b6 1015 &input_userauth_passwd_changereq);
1016}
3c0ef626 1017
7cac2b65 1018static int
1019identity_sign(Identity *id, u_char **sigp, u_int *lenp,
1020 u_char *data, u_int datalen)
3c0ef626 1021{
7cac2b65 1022 Key *prv;
1023 int ret;
1024
1025 /* the agent supports this key */
1026 if (id->ac)
1027 return (ssh_agent_sign(id->ac, id->key, sigp, lenp,
1028 data, datalen));
1029 /*
1030 * we have already loaded the private key or
1031 * the private key is stored in external hardware
1032 */
1033 if (id->isprivate || (id->key->flags & KEY_FLAG_EXT))
1034 return (key_sign(id->key, sigp, lenp, data, datalen));
1035 /* load the private key from the file */
1036 if ((prv = load_identity_file(id->filename)) == NULL)
1037 return (-1);
1038 ret = key_sign(prv, sigp, lenp, data, datalen);
1039 key_free(prv);
1040 return (ret);
3c0ef626 1041}
1042
1043static int
7cac2b65 1044sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
3c0ef626 1045{
1046 Buffer b;
1047 u_char *blob, *signature;
1e608e42 1048 u_int bloblen, slen;
7cac2b65 1049 u_int skip = 0;
3c0ef626 1050 int ret = -1;
1051 int have_sig = 1;
1052
1053 debug3("sign_and_send_pubkey");
1054
7cac2b65 1055 if (key_to_blob(id->key, &blob, &bloblen) == 0) {
3c0ef626 1056 /* we cannot handle this key */
1057 debug3("sign_and_send_pubkey: cannot handle key");
1058 return 0;
1059 }
1060 /* data to be signed */
1061 buffer_init(&b);
1062 if (datafellows & SSH_OLD_SESSIONID) {
1063 buffer_append(&b, session_id2, session_id2_len);
1064 skip = session_id2_len;
1065 } else {
1066 buffer_put_string(&b, session_id2, session_id2_len);
1067 skip = buffer_len(&b);
1068 }
1069 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
1070 buffer_put_cstring(&b, authctxt->server_user);
1071 buffer_put_cstring(&b,
1072 datafellows & SSH_BUG_PKSERVICE ?
1073 "ssh-userauth" :
1074 authctxt->service);
1075 if (datafellows & SSH_BUG_PKAUTH) {
1076 buffer_put_char(&b, have_sig);
1077 } else {
1078 buffer_put_cstring(&b, authctxt->method->name);
1079 buffer_put_char(&b, have_sig);
7cac2b65 1080 buffer_put_cstring(&b, key_ssh_name(id->key));
3c0ef626 1081 }
1082 buffer_put_string(&b, blob, bloblen);
1083
1084 /* generate signature */
7cac2b65 1085 ret = identity_sign(id, &signature, &slen,
3c0ef626 1086 buffer_ptr(&b), buffer_len(&b));
1087 if (ret == -1) {
1088 xfree(blob);
1089 buffer_free(&b);
1090 return 0;
1091 }
1092#ifdef DEBUG_PK
1093 buffer_dump(&b);
1094#endif
1095 if (datafellows & SSH_BUG_PKSERVICE) {
1096 buffer_clear(&b);
1097 buffer_append(&b, session_id2, session_id2_len);
1098 skip = session_id2_len;
1099 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
1100 buffer_put_cstring(&b, authctxt->server_user);
1101 buffer_put_cstring(&b, authctxt->service);
1102 buffer_put_cstring(&b, authctxt->method->name);
1103 buffer_put_char(&b, have_sig);
1104 if (!(datafellows & SSH_BUG_PKAUTH))
7cac2b65 1105 buffer_put_cstring(&b, key_ssh_name(id->key));
3c0ef626 1106 buffer_put_string(&b, blob, bloblen);
1107 }
1108 xfree(blob);
1109
1110 /* append signature */
1111 buffer_put_string(&b, signature, slen);
1112 xfree(signature);
1113
1114 /* skip session id and packet type */
1115 if (buffer_len(&b) < skip + 1)
1116 fatal("userauth_pubkey: internal error");
1117 buffer_consume(&b, skip + 1);
1118
1119 /* put remaining data from buffer into packet */
1120 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1121 packet_put_raw(buffer_ptr(&b), buffer_len(&b));
1122 buffer_free(&b);
1123 packet_send();
1124
1125 return 1;
1126}
1127
1128static int
7cac2b65 1129send_pubkey_test(Authctxt *authctxt, Identity *id)
3c0ef626 1130{
1131 u_char *blob;
1e608e42 1132 u_int bloblen, have_sig = 0;
3c0ef626 1133
1134 debug3("send_pubkey_test");
1135
7cac2b65 1136 if (key_to_blob(id->key, &blob, &bloblen) == 0) {
3c0ef626 1137 /* we cannot handle this key */
1138 debug3("send_pubkey_test: cannot handle key");
1139 return 0;
1140 }
1141 /* register callback for USERAUTH_PK_OK message */
3c0ef626 1142 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
1143
1144 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1145 packet_put_cstring(authctxt->server_user);
1146 packet_put_cstring(authctxt->service);
1147 packet_put_cstring(authctxt->method->name);
1148 packet_put_char(have_sig);
1149 if (!(datafellows & SSH_BUG_PKAUTH))
7cac2b65 1150 packet_put_cstring(key_ssh_name(id->key));
3c0ef626 1151 packet_put_string(blob, bloblen);
1152 xfree(blob);
1153 packet_send();
1154 return 1;
1155}
1156
1157static Key *
1158load_identity_file(char *filename)
1159{
1160 Key *private;
1161 char prompt[300], *passphrase;
1162 int quit, i;
1163 struct stat st;
1164
1165 if (stat(filename, &st) < 0) {
1166 debug3("no such identity: %s", filename);
1167 return NULL;
1168 }
1169 private = key_load_private_type(KEY_UNSPEC, filename, "", NULL);
1170 if (private == NULL) {
1171 if (options.batch_mode)
1172 return NULL;
1173 snprintf(prompt, sizeof prompt,
1e608e42 1174 "Enter passphrase for key '%.100s': ", filename);
3c0ef626 1175 for (i = 0; i < options.number_of_password_prompts; i++) {
1176 passphrase = read_passphrase(prompt, 0);
1177 if (strcmp(passphrase, "") != 0) {
1178 private = key_load_private_type(KEY_UNSPEC, filename,
1179 passphrase, NULL);
1180 quit = 0;
1181 } else {
1182 debug2("no passphrase given, try next key");
1183 quit = 1;
1184 }
1185 memset(passphrase, 0, strlen(passphrase));
1186 xfree(passphrase);
1187 if (private != NULL || quit)
1188 break;
1189 debug2("bad passphrase given, try again...");
1190 }
1191 }
1192 return private;
1193}
1194
7cac2b65 1195/*
1196 * try keys in the following order:
1197 * 1. agent keys that are found in the config file
1198 * 2. other agent keys
1199 * 3. keys that are only listed in the config file
1200 */
1201static void
1202pubkey_prepare(Authctxt *authctxt)
3c0ef626 1203{
7cac2b65 1204 Identity *id;
1205 Idlist agent, files, *preferred;
1206 Key *key;
1207 AuthenticationConnection *ac;
1208 char *comment;
1209 int i, found;
1210
1211 TAILQ_INIT(&agent); /* keys from the agent */
1212 TAILQ_INIT(&files); /* keys from the config file */
1213 preferred = &authctxt->keys;
1214 TAILQ_INIT(preferred); /* preferred order of keys */
1215
1216 /* list of keys stored in the filesystem */
1217 for (i = 0; i < options.num_identity_files; i++) {
1218 key = options.identity_keys[i];
1219 if (key && key->type == KEY_RSA1)
1220 continue;
1221 options.identity_keys[i] = NULL;
1222 id = xmalloc(sizeof(*id));
1223 memset(id, 0, sizeof(*id));
1224 id->key = key;
1225 id->filename = xstrdup(options.identity_files[i]);
1226 TAILQ_INSERT_TAIL(&files, id, next);
1227 }
1228 /* list of keys supported by the agent */
1229 if ((ac = ssh_get_authentication_connection())) {
1230 for (key = ssh_get_first_identity(ac, &comment, 2);
1231 key != NULL;
1232 key = ssh_get_next_identity(ac, &comment, 2)) {
1233 found = 0;
1234 TAILQ_FOREACH(id, &files, next) {
540d72c3 1235 /* agent keys from the config file are preferred */
7cac2b65 1236 if (key_equal(key, id->key)) {
1237 key_free(key);
1238 xfree(comment);
1239 TAILQ_REMOVE(&files, id, next);
1240 TAILQ_INSERT_TAIL(preferred, id, next);
1241 id->ac = ac;
1242 found = 1;
1243 break;
1244 }
1245 }
12a403af 1246 if (!found && !options.identities_only) {
7cac2b65 1247 id = xmalloc(sizeof(*id));
1248 memset(id, 0, sizeof(*id));
1249 id->key = key;
1250 id->filename = comment;
1251 id->ac = ac;
1252 TAILQ_INSERT_TAIL(&agent, id, next);
1253 }
1254 }
1255 /* append remaining agent keys */
1256 for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
1257 TAILQ_REMOVE(&agent, id, next);
1258 TAILQ_INSERT_TAIL(preferred, id, next);
1259 }
1260 authctxt->agent = ac;
1261 }
1262 /* append remaining keys from the config file */
1263 for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
1264 TAILQ_REMOVE(&files, id, next);
1265 TAILQ_INSERT_TAIL(preferred, id, next);
1266 }
1267 TAILQ_FOREACH(id, preferred, next) {
1268 debug2("key: %s (%p)", id->filename, id->key);
1269 }
3c0ef626 1270}
1271
7cac2b65 1272static void
1273pubkey_cleanup(Authctxt *authctxt)
3c0ef626 1274{
7cac2b65 1275 Identity *id;
1276
1277 if (authctxt->agent != NULL)
1278 ssh_close_authentication_connection(authctxt->agent);
1279 for (id = TAILQ_FIRST(&authctxt->keys); id;
1280 id = TAILQ_FIRST(&authctxt->keys)) {
1281 TAILQ_REMOVE(&authctxt->keys, id, next);
1282 if (id->key)
1283 key_free(id->key);
1284 if (id->filename)
1285 xfree(id->filename);
1286 xfree(id);
3c0ef626 1287 }
3c0ef626 1288}
1289
1290int
1291userauth_pubkey(Authctxt *authctxt)
1292{
7cac2b65 1293 Identity *id;
3c0ef626 1294 int sent = 0;
3c0ef626 1295
7cac2b65 1296 while ((id = TAILQ_FIRST(&authctxt->keys))) {
1297 if (id->tried++)
1298 return (0);
540d72c3 1299 /* move key to the end of the queue */
7cac2b65 1300 TAILQ_REMOVE(&authctxt->keys, id, next);
1301 TAILQ_INSERT_TAIL(&authctxt->keys, id, next);
1302 /*
1303 * send a test message if we have the public key. for
1304 * encrypted keys we cannot do this and have to load the
1305 * private key instead
1306 */
1307 if (id->key && id->key->type != KEY_RSA1) {
1308 debug("Offering public key: %s", id->filename);
1309 sent = send_pubkey_test(authctxt, id);
1310 } else if (id->key == NULL) {
1311 debug("Trying private key: %s", id->filename);
1312 id->key = load_identity_file(id->filename);
1313 if (id->key != NULL) {
1314 id->isprivate = 1;
1315 sent = sign_and_send_pubkey(authctxt, id);
1316 key_free(id->key);
1317 id->key = NULL;
3c0ef626 1318 }
3c0ef626 1319 }
7cac2b65 1320 if (sent)
1321 return (sent);
3c0ef626 1322 }
7cac2b65 1323 return (0);
3c0ef626 1324}
1325
1326/*
1327 * Send userauth request message specifying keyboard-interactive method.
1328 */
1329int
1330userauth_kbdint(Authctxt *authctxt)
1331{
1332 static int attempt = 0;
1333
1334 if (attempt++ >= options.number_of_password_prompts)
1335 return 0;
1336 /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */
1337 if (attempt > 1 && !authctxt->info_req_seen) {
1338 debug3("userauth_kbdint: disable: no info_req_seen");
1339 dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL);
1340 return 0;
1341 }
1342
1343 debug2("userauth_kbdint");
1344 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1345 packet_put_cstring(authctxt->server_user);
1346 packet_put_cstring(authctxt->service);
1347 packet_put_cstring(authctxt->method->name);
1348 packet_put_cstring(""); /* lang */
1349 packet_put_cstring(options.kbd_interactive_devices ?
1350 options.kbd_interactive_devices : "");
1351 packet_send();
1352
1353 dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
1354 return 1;
1355}
1356
1357/*
1358 * parse INFO_REQUEST, prompt user and send INFO_RESPONSE
1359 */
1360void
1e608e42 1361input_userauth_info_req(int type, u_int32_t seq, void *ctxt)
3c0ef626 1362{
1363 Authctxt *authctxt = ctxt;
1364 char *name, *inst, *lang, *prompt, *response;
1365 u_int num_prompts, i;
1366 int echo = 0;
1367
1368 debug2("input_userauth_info_req");
1369
1370 if (authctxt == NULL)
1371 fatal("input_userauth_info_req: no authentication context");
1372
1373 authctxt->info_req_seen = 1;
1374
1375 name = packet_get_string(NULL);
1376 inst = packet_get_string(NULL);
1377 lang = packet_get_string(NULL);
1378 if (strlen(name) > 0)
7cac2b65 1379 logit("%s", name);
3c0ef626 1380 if (strlen(inst) > 0)
7cac2b65 1381 logit("%s", inst);
3c0ef626 1382 xfree(name);
1383 xfree(inst);
1384 xfree(lang);
1385
1386 num_prompts = packet_get_int();
1387 /*
1388 * Begin to build info response packet based on prompts requested.
1389 * We commit to providing the correct number of responses, so if
1390 * further on we run into a problem that prevents this, we have to
1391 * be sure and clean this up and send a correct error response.
1392 */
1393 packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
1394 packet_put_int(num_prompts);
1395
1396 debug2("input_userauth_info_req: num_prompts %d", num_prompts);
1397 for (i = 0; i < num_prompts; i++) {
1398 prompt = packet_get_string(NULL);
1399 echo = packet_get_char();
1400
1401 response = read_passphrase(prompt, echo ? RP_ECHO : 0);
1402
1403 packet_put_cstring(response);
1404 memset(response, 0, strlen(response));
1405 xfree(response);
1406 xfree(prompt);
1407 }
1e608e42 1408 packet_check_eom(); /* done with parsing incoming message. */
3c0ef626 1409
1410 packet_add_padding(64);
1411 packet_send();
1412}
1413
44a053a3 1414static int
276b07a3 1415ssh_keysign(Key *key, u_char **sigp, u_int *lenp,
44a053a3 1416 u_char *data, u_int datalen)
1417{
1418 Buffer b;
1419 struct stat st;
1420 pid_t pid;
1421 int to[2], from[2], status, version = 2;
1422
bfe49944 1423 debug2("ssh_keysign called");
44a053a3 1424
1425 if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) {
1426 error("ssh_keysign: no installed: %s", strerror(errno));
1427 return -1;
1428 }
1429 if (fflush(stdout) != 0)
1430 error("ssh_keysign: fflush: %s", strerror(errno));
1431 if (pipe(to) < 0) {
1432 error("ssh_keysign: pipe: %s", strerror(errno));
1433 return -1;
1434 }
1435 if (pipe(from) < 0) {
1436 error("ssh_keysign: pipe: %s", strerror(errno));
1437 return -1;
1438 }
1439 if ((pid = fork()) < 0) {
1440 error("ssh_keysign: fork: %s", strerror(errno));
1441 return -1;
1442 }
1443 if (pid == 0) {
1444 seteuid(getuid());
1445 setuid(getuid());
1446 close(from[0]);
1447 if (dup2(from[1], STDOUT_FILENO) < 0)
1448 fatal("ssh_keysign: dup2: %s", strerror(errno));
1449 close(to[1]);
1450 if (dup2(to[0], STDIN_FILENO) < 0)
1451 fatal("ssh_keysign: dup2: %s", strerror(errno));
1452 close(from[1]);
1453 close(to[0]);
1454 execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0);
1455 fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN,
1456 strerror(errno));
1457 }
1458 close(from[1]);
1459 close(to[0]);
1460
1461 buffer_init(&b);
1462 buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */
1463 buffer_put_string(&b, data, datalen);
540d72c3 1464 if (ssh_msg_send(to[1], version, &b) == -1)
1465 fatal("ssh_keysign: couldn't send request");
44a053a3 1466
d03f4262 1467 if (ssh_msg_recv(from[0], &b) < 0) {
44a053a3 1468 error("ssh_keysign: no reply");
540d72c3 1469 buffer_free(&b);
44a053a3 1470 return -1;
1471 }
1472 close(from[0]);
1473 close(to[1]);
1474
1475 while (waitpid(pid, &status, 0) < 0)
1476 if (errno != EINTR)
1477 break;
1478
1479 if (buffer_get_char(&b) != version) {
1480 error("ssh_keysign: bad version");
540d72c3 1481 buffer_free(&b);
44a053a3 1482 return -1;
1483 }
1484 *sigp = buffer_get_string(&b, lenp);
540d72c3 1485 buffer_free(&b);
44a053a3 1486
1487 return 0;
1488}
1489
3c0ef626 1490int
1491userauth_hostbased(Authctxt *authctxt)
1492{
1493 Key *private = NULL;
44a053a3 1494 Sensitive *sensitive = authctxt->sensitive;
3c0ef626 1495 Buffer b;
1496 u_char *signature, *blob;
1497 char *chost, *pkalg, *p;
1498 const char *service;
1499 u_int blen, slen;
1500 int ok, i, len, found = 0;
1501
1502 /* check for a useful key */
44a053a3 1503 for (i = 0; i < sensitive->nkeys; i++) {
1504 private = sensitive->keys[i];
3c0ef626 1505 if (private && private->type != KEY_RSA1) {
1506 found = 1;
1507 /* we take and free the key */
44a053a3 1508 sensitive->keys[i] = NULL;
3c0ef626 1509 break;
1510 }
1511 }
1512 if (!found) {
bfe49944 1513 debug("No more client hostkeys for hostbased authentication.");
3c0ef626 1514 return 0;
1515 }
1516 if (key_to_blob(private, &blob, &blen) == 0) {
1517 key_free(private);
1518 return 0;
1519 }
1520 /* figure out a name for the client host */
1521 p = get_local_name(packet_get_connection_in());
1522 if (p == NULL) {
1523 error("userauth_hostbased: cannot get local ipaddr/name");
1524 key_free(private);
1525 return 0;
1526 }
1527 len = strlen(p) + 2;
1528 chost = xmalloc(len);
1529 strlcpy(chost, p, len);
1530 strlcat(chost, ".", len);
1531 debug2("userauth_hostbased: chost %s", chost);
bfe49944 1532 xfree(p);
3c0ef626 1533
1534 service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
1535 authctxt->service;
1536 pkalg = xstrdup(key_ssh_name(private));
1537 buffer_init(&b);
1538 /* construct data */
1539 buffer_put_string(&b, session_id2, session_id2_len);
1540 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
1541 buffer_put_cstring(&b, authctxt->server_user);
1542 buffer_put_cstring(&b, service);
1543 buffer_put_cstring(&b, authctxt->method->name);
1544 buffer_put_cstring(&b, pkalg);
1545 buffer_put_string(&b, blob, blen);
1546 buffer_put_cstring(&b, chost);
1547 buffer_put_cstring(&b, authctxt->local_user);
1548#ifdef DEBUG_PK
1549 buffer_dump(&b);
1550#endif
44a053a3 1551 if (sensitive->external_keysign)
1552 ok = ssh_keysign(private, &signature, &slen,
1553 buffer_ptr(&b), buffer_len(&b));
1554 else
1555 ok = key_sign(private, &signature, &slen,
1556 buffer_ptr(&b), buffer_len(&b));
3c0ef626 1557 key_free(private);
1558 buffer_free(&b);
1559 if (ok != 0) {
1560 error("key_sign failed");
1561 xfree(chost);
1562 xfree(pkalg);
1563 return 0;
1564 }
1565 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1566 packet_put_cstring(authctxt->server_user);
1567 packet_put_cstring(authctxt->service);
1568 packet_put_cstring(authctxt->method->name);
1569 packet_put_cstring(pkalg);
1570 packet_put_string(blob, blen);
1571 packet_put_cstring(chost);
1572 packet_put_cstring(authctxt->local_user);
1573 packet_put_string(signature, slen);
1574 memset(signature, 's', slen);
1575 xfree(signature);
1576 xfree(chost);
1577 xfree(pkalg);
1578
1579 packet_send();
1580 return 1;
1581}
1582
1583/* find auth method */
1584
1585/*
1586 * given auth method name, if configurable options permit this method fill
1587 * in auth_ident field and return true, otherwise return false.
1588 */
1589static int
1590authmethod_is_enabled(Authmethod *method)
1591{
1592 if (method == NULL)
1593 return 0;
1594 /* return false if options indicate this method is disabled */
1595 if (method->enabled == NULL || *method->enabled == 0)
1596 return 0;
1597 /* return false if batch mode is enabled but method needs interactive mode */
1598 if (method->batch_flag != NULL && *method->batch_flag != 0)
1599 return 0;
1600 return 1;
1601}
1602
1603static Authmethod *
1604authmethod_lookup(const char *name)
1605{
1606 Authmethod *method = NULL;
1607 if (name != NULL)
1608 for (method = authmethods; method->name != NULL; method++)
1609 if (strcmp(name, method->name) == 0)
1610 return method;
1611 debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
1612 return NULL;
1613}
1614
1615/* XXX internal state */
1616static Authmethod *current = NULL;
1617static char *supported = NULL;
1618static char *preferred = NULL;
276b07a3 1619
3c0ef626 1620/*
1621 * Given the authentication method list sent by the server, return the
1622 * next method we should try. If the server initially sends a nil list,
1623 * use a built-in default list.
1624 */
1625static Authmethod *
1626authmethod_get(char *authlist)
1627{
3c0ef626 1628 char *name = NULL;
1e608e42 1629 u_int next;
3c0ef626 1630
1631 /* Use a suitable default if we're passed a nil list. */
1632 if (authlist == NULL || strlen(authlist) == 0)
1633 authlist = options.preferred_authentications;
1634
1635 if (supported == NULL || strcmp(authlist, supported) != 0) {
1636 debug3("start over, passed a different list %s", authlist);
1637 if (supported != NULL)
1638 xfree(supported);
1639 supported = xstrdup(authlist);
1640 preferred = options.preferred_authentications;
1641 debug3("preferred %s", preferred);
1642 current = NULL;
1643 } else if (current != NULL && authmethod_is_enabled(current))
1644 return current;
1645
1646 for (;;) {
1647 if ((name = match_list(preferred, supported, &next)) == NULL) {
bfe49944 1648 debug("No more authentication methods to try.");
3c0ef626 1649 current = NULL;
1650 return NULL;
1651 }
1652 preferred += next;
1653 debug3("authmethod_lookup %s", name);
1654 debug3("remaining preferred: %s", preferred);
1655 if ((current = authmethod_lookup(name)) != NULL &&
1656 authmethod_is_enabled(current)) {
1657 debug3("authmethod_is_enabled %s", name);
bfe49944 1658 debug("Next authentication method: %s", name);
3c0ef626 1659 return current;
1660 }
1661 }
1662}
1663
3c0ef626 1664static char *
1665authmethods_get(void)
1666{
1667 Authmethod *method = NULL;
1e608e42 1668 Buffer b;
1669 char *list;
3c0ef626 1670
1e608e42 1671 buffer_init(&b);
3c0ef626 1672 for (method = authmethods; method->name != NULL; method++) {
1673 if (authmethod_is_enabled(method)) {
1e608e42 1674 if (buffer_len(&b) > 0)
1675 buffer_append(&b, ",", 1);
1676 buffer_append(&b, method->name, strlen(method->name));
3c0ef626 1677 }
1678 }
1e608e42 1679 buffer_append(&b, "\0", 1);
1680 list = xstrdup(buffer_ptr(&b));
1681 buffer_free(&b);
1682 return list;
3c0ef626 1683}
This page took 4.579747 seconds and 5 git commands to generate.