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