Annotation of src/usr.bin/ssh/sshconnect2.c, Revision 1.10.2.3
1.1 markus 1: /*
2: * Copyright (c) 2000 Markus Friedl. All rights reserved.
3: *
4: * Redistribution and use in source and binary forms, with or without
5: * modification, are permitted provided that the following conditions
6: * are met:
7: * 1. Redistributions of source code must retain the above copyright
8: * notice, this list of conditions and the following disclaimer.
9: * 2. Redistributions in binary form must reproduce the above copyright
10: * notice, this list of conditions and the following disclaimer in the
11: * documentation and/or other materials provided with the distribution.
12: *
13: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23: */
24:
25: #include "includes.h"
1.10.2.3! jason 26: RCSID("$OpenBSD: sshconnect2.c,v 1.27 2000/10/19 16:45:16 provos Exp $");
1.1 markus 27:
28: #include <openssl/bn.h>
29: #include <openssl/rsa.h>
30: #include <openssl/dsa.h>
31: #include <openssl/md5.h>
32: #include <openssl/dh.h>
33: #include <openssl/hmac.h>
34:
35: #include "ssh.h"
36: #include "xmalloc.h"
37: #include "rsa.h"
38: #include "buffer.h"
39: #include "packet.h"
40: #include "uidswap.h"
41: #include "compat.h"
42: #include "readconf.h"
43: #include "bufaux.h"
44: #include "ssh2.h"
45: #include "kex.h"
46: #include "myproposal.h"
47: #include "key.h"
48: #include "dsa.h"
49: #include "sshconnect.h"
50: #include "authfile.h"
1.10.2.3! jason 51: #include "cli.h"
! 52: #include "dispatch.h"
1.10.2.2 jason 53: #include "authfd.h"
1.1 markus 54:
1.10.2.3! jason 55: void ssh_dh1_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
! 56: void ssh_dhgex_client(Kex *, char *, struct sockaddr *, Buffer *, Buffer *);
! 57:
1.1 markus 58: /* import */
59: extern char *client_version_string;
60: extern char *server_version_string;
61: extern Options options;
62:
63: /*
64: * SSH2 key exchange
65: */
66:
67: unsigned char *session_id2 = NULL;
68: int session_id2_len = 0;
69:
70: void
1.10.2.3! jason 71: ssh_kex2(char *host, struct sockaddr *hostaddr)
1.1 markus 72: {
1.10.2.3! jason 73: int i, plen;
! 74: Kex *kex;
! 75: Buffer *client_kexinit, *server_kexinit;
! 76: char *sprop[PROPOSAL_MAX];
! 77:
! 78: if (options.ciphers == NULL) {
! 79: if (options.cipher == SSH_CIPHER_3DES) {
! 80: options.ciphers = "3des-cbc";
! 81: } else if (options.cipher == SSH_CIPHER_BLOWFISH) {
! 82: options.ciphers = "blowfish-cbc";
! 83: } else if (options.cipher == SSH_CIPHER_DES) {
! 84: fatal("cipher DES not supported for protocol version 2");
! 85: }
! 86: }
! 87: if (options.ciphers != NULL) {
! 88: myproposal[PROPOSAL_ENC_ALGS_CTOS] =
! 89: myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
! 90: }
! 91: if (options.compression) {
! 92: myproposal[PROPOSAL_COMP_ALGS_CTOS] = "zlib";
! 93: myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
! 94: } else {
! 95: myproposal[PROPOSAL_COMP_ALGS_CTOS] = "none";
! 96: myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
! 97: }
! 98:
! 99: /* buffers with raw kexinit messages */
! 100: server_kexinit = xmalloc(sizeof(*server_kexinit));
! 101: buffer_init(server_kexinit);
! 102: client_kexinit = kex_init(myproposal);
! 103:
! 104: /* algorithm negotiation */
! 105: kex_exchange_kexinit(client_kexinit, server_kexinit, sprop);
! 106: kex = kex_choose_conf(myproposal, sprop, 0);
! 107: for (i = 0; i < PROPOSAL_MAX; i++)
! 108: xfree(sprop[i]);
! 109:
! 110: /* server authentication and session key agreement */
! 111: switch(kex->kex_type) {
! 112: case DH_GRP1_SHA1:
! 113: ssh_dh1_client(kex, host, hostaddr,
! 114: client_kexinit, server_kexinit);
! 115: break;
! 116: case DH_GEX_SHA1:
! 117: ssh_dhgex_client(kex, host, hostaddr, client_kexinit,
! 118: server_kexinit);
! 119: break;
! 120: default:
! 121: fatal("Unsupported key exchange %d", kex->kex_type);
! 122: }
! 123:
! 124: buffer_free(client_kexinit);
! 125: buffer_free(server_kexinit);
! 126: xfree(client_kexinit);
! 127: xfree(server_kexinit);
! 128:
! 129: debug("Wait SSH2_MSG_NEWKEYS.");
! 130: packet_read_expect(&plen, SSH2_MSG_NEWKEYS);
! 131: packet_done();
! 132: debug("GOT SSH2_MSG_NEWKEYS.");
! 133:
! 134: debug("send SSH2_MSG_NEWKEYS.");
! 135: packet_start(SSH2_MSG_NEWKEYS);
! 136: packet_send();
! 137: packet_write_wait();
! 138: debug("done: send SSH2_MSG_NEWKEYS.");
! 139:
! 140: #ifdef DEBUG_KEXDH
! 141: /* send 1st encrypted/maced/compressed message */
! 142: packet_start(SSH2_MSG_IGNORE);
! 143: packet_put_cstring("markus");
! 144: packet_send();
! 145: packet_write_wait();
! 146: #endif
! 147: debug("done: KEX2.");
! 148: }
! 149:
! 150: /* diffie-hellman-group1-sha1 */
! 151:
! 152: void
! 153: ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr,
! 154: Buffer *client_kexinit, Buffer *server_kexinit)
! 155: {
! 156: #ifdef DEBUG_KEXDH
! 157: int i;
! 158: #endif
1.10.2.1 jason 159: int plen, dlen;
1.1 markus 160: unsigned int klen, kout;
161: char *signature = NULL;
162: unsigned int slen;
163: char *server_host_key_blob = NULL;
164: Key *server_host_key;
165: unsigned int sbloblen;
166: DH *dh;
167: BIGNUM *dh_server_pub = 0;
168: BIGNUM *shared_secret = 0;
169: unsigned char *kbuf;
170: unsigned char *hash;
171:
172: debug("Sending SSH2_MSG_KEXDH_INIT.");
173: /* generate and send 'e', client DH public key */
174: dh = dh_new_group1();
175: packet_start(SSH2_MSG_KEXDH_INIT);
176: packet_put_bignum2(dh->pub_key);
177: packet_send();
178: packet_write_wait();
179:
180: #ifdef DEBUG_KEXDH
181: fprintf(stderr, "\np= ");
1.10.2.3! jason 182: BN_print_fp(stderr, dh->p);
1.1 markus 183: fprintf(stderr, "\ng= ");
1.10.2.3! jason 184: BN_print_fp(stderr, dh->g);
1.1 markus 185: fprintf(stderr, "\npub= ");
1.10.2.3! jason 186: BN_print_fp(stderr, dh->pub_key);
1.1 markus 187: fprintf(stderr, "\n");
188: DHparams_print_fp(stderr, dh);
189: #endif
190:
191: debug("Wait SSH2_MSG_KEXDH_REPLY.");
192:
1.10.2.1 jason 193: packet_read_expect(&plen, SSH2_MSG_KEXDH_REPLY);
1.1 markus 194:
195: debug("Got SSH2_MSG_KEXDH_REPLY.");
196:
197: /* key, cert */
198: server_host_key_blob = packet_get_string(&sbloblen);
199: server_host_key = dsa_key_from_blob(server_host_key_blob, sbloblen);
200: if (server_host_key == NULL)
201: fatal("cannot decode server_host_key_blob");
202:
203: check_host_key(host, hostaddr, server_host_key,
1.10.2.3! jason 204: options.user_hostfile2, options.system_hostfile2);
1.1 markus 205:
206: /* DH paramter f, server public DH key */
207: dh_server_pub = BN_new();
208: if (dh_server_pub == NULL)
209: fatal("dh_server_pub == NULL");
210: packet_get_bignum2(dh_server_pub, &dlen);
211:
212: #ifdef DEBUG_KEXDH
213: fprintf(stderr, "\ndh_server_pub= ");
1.10.2.3! jason 214: BN_print_fp(stderr, dh_server_pub);
1.1 markus 215: fprintf(stderr, "\n");
216: debug("bits %d", BN_num_bits(dh_server_pub));
217: #endif
218:
219: /* signed H */
220: signature = packet_get_string(&slen);
221: packet_done();
222:
223: if (!dh_pub_is_valid(dh, dh_server_pub))
224: packet_disconnect("bad server public DH value");
225:
226: klen = DH_size(dh);
227: kbuf = xmalloc(klen);
228: kout = DH_compute_key(kbuf, dh_server_pub, dh);
229: #ifdef DEBUG_KEXDH
230: debug("shared secret: len %d/%d", klen, kout);
231: fprintf(stderr, "shared secret == ");
232: for (i = 0; i< kout; i++)
233: fprintf(stderr, "%02x", (kbuf[i])&0xff);
234: fprintf(stderr, "\n");
235: #endif
236: shared_secret = BN_new();
237:
238: BN_bin2bn(kbuf, kout, shared_secret);
239: memset(kbuf, 0, klen);
240: xfree(kbuf);
241:
242: /* calc and verify H */
243: hash = kex_hash(
244: client_version_string,
245: server_version_string,
246: buffer_ptr(client_kexinit), buffer_len(client_kexinit),
247: buffer_ptr(server_kexinit), buffer_len(server_kexinit),
248: server_host_key_blob, sbloblen,
249: dh->pub_key,
250: dh_server_pub,
251: shared_secret
252: );
1.3 markus 253: xfree(server_host_key_blob);
1.10.2.1 jason 254: DH_free(dh);
1.1 markus 255: #ifdef DEBUG_KEXDH
256: fprintf(stderr, "hash == ");
257: for (i = 0; i< 20; i++)
258: fprintf(stderr, "%02x", (hash[i])&0xff);
259: fprintf(stderr, "\n");
260: #endif
261: if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
262: fatal("dsa_verify failed for server_host_key");
263: key_free(server_host_key);
264:
265: kex_derive_keys(kex, hash, shared_secret);
266: packet_set_kex(kex);
267:
268: /* save session id */
269: session_id2_len = 20;
270: session_id2 = xmalloc(session_id2_len);
271: memcpy(session_id2, hash, session_id2_len);
1.10.2.1 jason 272: }
273:
1.10.2.3! jason 274: /* diffie-hellman-group-exchange-sha1 */
! 275:
! 276: /*
! 277: * Estimates the group order for a Diffie-Hellman group that has an
! 278: * attack complexity approximately the same as O(2**bits). Estimate
! 279: * with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
! 280: */
! 281:
! 282: int
! 283: dh_estimate(int bits)
! 284: {
! 285:
! 286: if (bits < 64)
! 287: return (512); /* O(2**63) */
! 288: if (bits < 128)
! 289: return (1024); /* O(2**86) */
! 290: if (bits < 192)
! 291: return (2048); /* O(2**116) */
! 292: return (4096); /* O(2**156) */
! 293: }
! 294:
1.10.2.1 jason 295: void
1.10.2.3! jason 296: ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
! 297: Buffer *client_kexinit, Buffer *server_kexinit)
1.10.2.1 jason 298: {
1.10.2.3! jason 299: #ifdef DEBUG_KEXDH
! 300: int i;
! 301: #endif
! 302: int plen, dlen;
! 303: unsigned int klen, kout;
! 304: char *signature = NULL;
! 305: unsigned int slen, nbits;
! 306: char *server_host_key_blob = NULL;
! 307: Key *server_host_key;
! 308: unsigned int sbloblen;
! 309: DH *dh;
! 310: BIGNUM *dh_server_pub = 0;
! 311: BIGNUM *shared_secret = 0;
! 312: BIGNUM *p = 0, *g = 0;
! 313: unsigned char *kbuf;
! 314: unsigned char *hash;
1.10.2.1 jason 315:
1.10.2.3! jason 316: nbits = dh_estimate(kex->enc[MODE_OUT].cipher->key_len * 8);
1.10.2.1 jason 317:
1.10.2.3! jason 318: debug("Sending SSH2_MSG_KEX_DH_GEX_REQUEST.");
! 319: packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
! 320: packet_put_int(nbits);
! 321: packet_send();
! 322: packet_write_wait();
1.10.2.1 jason 323:
1.10.2.3! jason 324: #ifdef DEBUG_KEXDH
! 325: fprintf(stderr, "\nnbits = %d", nbits);
! 326: #endif
1.10.2.1 jason 327:
1.10.2.3! jason 328: debug("Wait SSH2_MSG_KEX_DH_GEX_GROUP.");
1.10.2.1 jason 329:
1.10.2.3! jason 330: packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_GROUP);
1.1 markus 331:
1.10.2.3! jason 332: debug("Got SSH2_MSG_KEX_DH_GEX_GROUP.");
1.1 markus 333:
1.10.2.3! jason 334: if ((p = BN_new()) == NULL)
! 335: fatal("BN_new");
! 336: packet_get_bignum2(p, &dlen);
! 337: if ((g = BN_new()) == NULL)
! 338: fatal("BN_new");
! 339: packet_get_bignum2(g, &dlen);
! 340: if ((dh = dh_new_group(g, p)) == NULL)
! 341: fatal("dh_new_group");
1.1 markus 342:
343: #ifdef DEBUG_KEXDH
1.10.2.3! jason 344: fprintf(stderr, "\np= ");
! 345: BN_print_fp(stderr, dh->p);
! 346: fprintf(stderr, "\ng= ");
! 347: BN_print_fp(stderr, dh->g);
! 348: fprintf(stderr, "\npub= ");
! 349: BN_print_fp(stderr, dh->pub_key);
! 350: fprintf(stderr, "\n");
! 351: DHparams_print_fp(stderr, dh);
! 352: #endif
! 353:
! 354: debug("Sending SSH2_MSG_KEX_DH_GEX_INIT.");
! 355: /* generate and send 'e', client DH public key */
! 356: packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
! 357: packet_put_bignum2(dh->pub_key);
1.1 markus 358: packet_send();
359: packet_write_wait();
1.10.2.3! jason 360:
! 361: debug("Wait SSH2_MSG_KEX_DH_GEX_REPLY.");
! 362:
! 363: packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_REPLY);
! 364:
! 365: debug("Got SSH2_MSG_KEXDH_REPLY.");
! 366:
! 367: /* key, cert */
! 368: server_host_key_blob = packet_get_string(&sbloblen);
! 369: server_host_key = dsa_key_from_blob(server_host_key_blob, sbloblen);
! 370: if (server_host_key == NULL)
! 371: fatal("cannot decode server_host_key_blob");
! 372:
! 373: check_host_key(host, hostaddr, server_host_key,
! 374: options.user_hostfile2, options.system_hostfile2);
! 375:
! 376: /* DH paramter f, server public DH key */
! 377: dh_server_pub = BN_new();
! 378: if (dh_server_pub == NULL)
! 379: fatal("dh_server_pub == NULL");
! 380: packet_get_bignum2(dh_server_pub, &dlen);
! 381:
! 382: #ifdef DEBUG_KEXDH
! 383: fprintf(stderr, "\ndh_server_pub= ");
! 384: BN_print_fp(stderr, dh_server_pub);
! 385: fprintf(stderr, "\n");
! 386: debug("bits %d", BN_num_bits(dh_server_pub));
1.1 markus 387: #endif
1.10.2.3! jason 388:
! 389: /* signed H */
! 390: signature = packet_get_string(&slen);
! 391: packet_done();
! 392:
! 393: if (!dh_pub_is_valid(dh, dh_server_pub))
! 394: packet_disconnect("bad server public DH value");
! 395:
! 396: klen = DH_size(dh);
! 397: kbuf = xmalloc(klen);
! 398: kout = DH_compute_key(kbuf, dh_server_pub, dh);
! 399: #ifdef DEBUG_KEXDH
! 400: debug("shared secret: len %d/%d", klen, kout);
! 401: fprintf(stderr, "shared secret == ");
! 402: for (i = 0; i< kout; i++)
! 403: fprintf(stderr, "%02x", (kbuf[i])&0xff);
! 404: fprintf(stderr, "\n");
! 405: #endif
! 406: shared_secret = BN_new();
! 407:
! 408: BN_bin2bn(kbuf, kout, shared_secret);
! 409: memset(kbuf, 0, klen);
! 410: xfree(kbuf);
! 411:
! 412: /* calc and verify H */
! 413: hash = kex_hash_gex(
! 414: client_version_string,
! 415: server_version_string,
! 416: buffer_ptr(client_kexinit), buffer_len(client_kexinit),
! 417: buffer_ptr(server_kexinit), buffer_len(server_kexinit),
! 418: server_host_key_blob, sbloblen,
! 419: nbits, dh->p, dh->g,
! 420: dh->pub_key,
! 421: dh_server_pub,
! 422: shared_secret
! 423: );
! 424: xfree(server_host_key_blob);
! 425: DH_free(dh);
! 426: #ifdef DEBUG_KEXDH
! 427: fprintf(stderr, "hash == ");
! 428: for (i = 0; i< 20; i++)
! 429: fprintf(stderr, "%02x", (hash[i])&0xff);
! 430: fprintf(stderr, "\n");
! 431: #endif
! 432: if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
! 433: fatal("dsa_verify failed for server_host_key");
! 434: key_free(server_host_key);
! 435:
! 436: kex_derive_keys(kex, hash, shared_secret);
! 437: packet_set_kex(kex);
! 438:
! 439: /* save session id */
! 440: session_id2_len = 20;
! 441: session_id2 = xmalloc(session_id2_len);
! 442: memcpy(session_id2, hash, session_id2_len);
1.1 markus 443: }
1.10.2.1 jason 444:
1.1 markus 445: /*
446: * Authenticate user
447: */
1.10.2.3! jason 448:
! 449: typedef struct Authctxt Authctxt;
! 450: typedef struct Authmethod Authmethod;
! 451:
! 452: typedef int sign_cb_fn(
! 453: Authctxt *authctxt, Key *key,
! 454: unsigned char **sigp, int *lenp, unsigned char *data, int datalen);
! 455:
! 456: struct Authctxt {
! 457: const char *server_user;
! 458: const char *host;
! 459: const char *service;
! 460: AuthenticationConnection *agent;
! 461: Authmethod *method;
! 462: int success;
! 463: };
! 464: struct Authmethod {
! 465: char *name; /* string to compare against server's list */
! 466: int (*userauth)(Authctxt *authctxt);
! 467: int *enabled; /* flag in option struct that enables method */
! 468: int *batch_flag; /* flag in option struct that disables method */
! 469: };
! 470:
! 471: void input_userauth_success(int type, int plen, void *ctxt);
! 472: void input_userauth_failure(int type, int plen, void *ctxt);
! 473: void input_userauth_error(int type, int plen, void *ctxt);
! 474: void input_userauth_info_req(int type, int plen, void *ctxt);
! 475:
! 476: int userauth_none(Authctxt *authctxt);
! 477: int userauth_pubkey(Authctxt *authctxt);
! 478: int userauth_passwd(Authctxt *authctxt);
! 479: int userauth_kbdint(Authctxt *authctxt);
! 480:
! 481: void authmethod_clear();
! 482: Authmethod *authmethod_get(char *authlist);
! 483: Authmethod *authmethod_lookup(const char *name);
! 484:
! 485: Authmethod authmethods[] = {
! 486: {"publickey",
! 487: userauth_pubkey,
! 488: &options.dsa_authentication,
! 489: NULL},
! 490: {"password",
! 491: userauth_passwd,
! 492: &options.password_authentication,
! 493: &options.batch_mode},
! 494: {"keyboard-interactive",
! 495: userauth_kbdint,
! 496: &options.kbd_interactive_authentication,
! 497: &options.batch_mode},
! 498: {"none",
! 499: userauth_none,
! 500: NULL,
! 501: NULL},
! 502: {NULL, NULL, NULL, NULL}
! 503: };
! 504:
! 505: void
! 506: ssh_userauth2(const char *server_user, char *host)
! 507: {
! 508: Authctxt authctxt;
! 509: int type;
! 510: int plen;
! 511:
! 512: debug("send SSH2_MSG_SERVICE_REQUEST");
! 513: packet_start(SSH2_MSG_SERVICE_REQUEST);
! 514: packet_put_cstring("ssh-userauth");
! 515: packet_send();
! 516: packet_write_wait();
! 517: type = packet_read(&plen);
! 518: if (type != SSH2_MSG_SERVICE_ACCEPT) {
! 519: fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type);
! 520: }
! 521: if (packet_remaining() > 0) {
! 522: char *reply = packet_get_string(&plen);
! 523: debug("service_accept: %s", reply);
! 524: xfree(reply);
! 525: packet_done();
! 526: } else {
! 527: debug("buggy server: service_accept w/o service");
! 528: }
! 529: packet_done();
! 530: debug("got SSH2_MSG_SERVICE_ACCEPT");
! 531:
! 532: /* setup authentication context */
! 533: authctxt.agent = ssh_get_authentication_connection();
! 534: authctxt.server_user = server_user;
! 535: authctxt.host = host;
! 536: authctxt.service = "ssh-connection"; /* service name */
! 537: authctxt.success = 0;
! 538: authctxt.method = authmethod_lookup("none");
! 539: if (authctxt.method == NULL)
! 540: fatal("ssh_userauth2: internal error: cannot send userauth none request");
! 541: authmethod_clear();
! 542:
! 543: /* initial userauth request */
! 544: userauth_none(&authctxt);
! 545:
! 546: dispatch_init(&input_userauth_error);
! 547: dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
! 548: dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
! 549: dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
! 550:
! 551: if (authctxt.agent != NULL)
! 552: ssh_close_authentication_connection(authctxt.agent);
! 553:
! 554: debug("ssh-userauth2 successfull: method %s", authctxt.method->name);
! 555: }
! 556: void
! 557: input_userauth_error(int type, int plen, void *ctxt)
! 558: {
! 559: fatal("input_userauth_error: bad message during authentication");
! 560: }
! 561: void
! 562: input_userauth_success(int type, int plen, void *ctxt)
! 563: {
! 564: Authctxt *authctxt = ctxt;
! 565: if (authctxt == NULL)
! 566: fatal("input_userauth_success: no authentication context");
! 567: authctxt->success = 1; /* break out */
! 568: }
! 569: void
! 570: input_userauth_failure(int type, int plen, void *ctxt)
! 571: {
! 572: Authmethod *method = NULL;
! 573: Authctxt *authctxt = ctxt;
! 574: char *authlist = NULL;
! 575: int partial;
! 576:
! 577: if (authctxt == NULL)
! 578: fatal("input_userauth_failure: no authentication context");
! 579:
! 580: authlist = packet_get_string(NULL);
! 581: partial = packet_get_char();
! 582: packet_done();
! 583:
! 584: if (partial != 0)
! 585: debug("partial success");
! 586: debug("authentications that can continue: %s", authlist);
! 587:
! 588: for (;;) {
! 589: method = authmethod_get(authlist);
! 590: if (method == NULL)
! 591: fatal("Unable to find an authentication method");
! 592: authctxt->method = method;
! 593: if (method->userauth(authctxt) != 0) {
! 594: debug2("we sent a %s packet, wait for reply", method->name);
! 595: break;
! 596: } else {
! 597: debug2("we did not send a packet, disable method");
! 598: method->enabled = NULL;
! 599: }
! 600: }
! 601: xfree(authlist);
! 602: }
! 603:
1.1 markus 604: int
1.10.2.3! jason 605: userauth_none(Authctxt *authctxt)
! 606: {
! 607: /* initial userauth request */
! 608: packet_start(SSH2_MSG_USERAUTH_REQUEST);
! 609: packet_put_cstring(authctxt->server_user);
! 610: packet_put_cstring(authctxt->service);
! 611: packet_put_cstring(authctxt->method->name);
! 612: packet_send();
! 613: packet_write_wait();
! 614: return 1;
! 615: }
! 616:
! 617: int
! 618: userauth_passwd(Authctxt *authctxt)
1.1 markus 619: {
1.6 markus 620: static int attempt = 0;
1.1 markus 621: char prompt[80];
622: char *password;
1.6 markus 623:
1.10.2.1 jason 624: if (attempt++ >= options.number_of_password_prompts)
1.6 markus 625: return 0;
1.10.2.1 jason 626:
627: if(attempt != 1)
628: error("Permission denied, please try again.");
1.1 markus 629:
630: snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ",
1.10.2.3! jason 631: authctxt->server_user, authctxt->host);
1.1 markus 632: password = read_passphrase(prompt, 0);
633: packet_start(SSH2_MSG_USERAUTH_REQUEST);
1.10.2.3! jason 634: packet_put_cstring(authctxt->server_user);
! 635: packet_put_cstring(authctxt->service);
! 636: packet_put_cstring(authctxt->method->name);
1.1 markus 637: packet_put_char(0);
638: packet_put_cstring(password);
639: memset(password, 0, strlen(password));
640: xfree(password);
641: packet_send();
642: packet_write_wait();
643: return 1;
644: }
645:
646: int
1.10.2.3! jason 647: sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
1.1 markus 648: {
649: Buffer b;
650: unsigned char *blob, *signature;
651: int bloblen, slen;
1.10.2.2 jason 652: int skip = 0;
653: int ret = -1;
1.10.2.3! jason 654: int have_sig = 1;
1.1 markus 655:
656: dsa_make_key_blob(k, &blob, &bloblen);
657:
658: /* data to be signed */
659: buffer_init(&b);
1.10.2.3! jason 660: if (datafellows & SSH_OLD_SESSIONID) {
1.10.2.2 jason 661: buffer_append(&b, session_id2, session_id2_len);
662: skip = session_id2_len;
1.10.2.3! jason 663: } else {
! 664: buffer_put_string(&b, session_id2, session_id2_len);
! 665: skip = buffer_len(&b);
1.10.2.2 jason 666: }
1.1 markus 667: buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
1.10.2.3! jason 668: buffer_put_cstring(&b, authctxt->server_user);
1.10 markus 669: buffer_put_cstring(&b,
670: datafellows & SSH_BUG_PUBKEYAUTH ?
671: "ssh-userauth" :
1.10.2.3! jason 672: authctxt->service);
! 673: buffer_put_cstring(&b, authctxt->method->name);
! 674: buffer_put_char(&b, have_sig);
1.1 markus 675: buffer_put_cstring(&b, KEX_DSS);
676: buffer_put_string(&b, blob, bloblen);
677:
678: /* generate signature */
1.10.2.3! jason 679: ret = (*sign_callback)(authctxt, k, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
1.10.2.2 jason 680: if (ret == -1) {
681: xfree(blob);
682: buffer_free(&b);
683: return 0;
684: }
1.1 markus 685: #ifdef DEBUG_DSS
686: buffer_dump(&b);
687: #endif
1.10 markus 688: if (datafellows & SSH_BUG_PUBKEYAUTH) {
689: buffer_clear(&b);
690: buffer_append(&b, session_id2, session_id2_len);
691: buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
1.10.2.3! jason 692: buffer_put_cstring(&b, authctxt->server_user);
! 693: buffer_put_cstring(&b, authctxt->service);
! 694: buffer_put_cstring(&b, authctxt->method->name);
! 695: buffer_put_char(&b, have_sig);
1.10 markus 696: buffer_put_cstring(&b, KEX_DSS);
697: buffer_put_string(&b, blob, bloblen);
698: }
699: xfree(blob);
1.1 markus 700: /* append signature */
701: buffer_put_string(&b, signature, slen);
702: xfree(signature);
703:
704: /* skip session id and packet type */
1.10.2.2 jason 705: if (buffer_len(&b) < skip + 1)
1.10.2.3! jason 706: fatal("userauth_pubkey: internal error");
1.10.2.2 jason 707: buffer_consume(&b, skip + 1);
1.1 markus 708:
709: /* put remaining data from buffer into packet */
710: packet_start(SSH2_MSG_USERAUTH_REQUEST);
711: packet_put_raw(buffer_ptr(&b), buffer_len(&b));
712: buffer_free(&b);
713:
714: /* send */
715: packet_send();
716: packet_write_wait();
1.10.2.2 jason 717:
1.1 markus 718: return 1;
719: }
720:
1.10.2.3! jason 721: /* sign callback */
! 722: int dsa_sign_cb(Authctxt *authctxt, Key *key, unsigned char **sigp, int *lenp,
! 723: unsigned char *data, int datalen)
! 724: {
! 725: return dsa_sign(key, sigp, lenp, data, datalen);
! 726: }
! 727:
1.10.2.2 jason 728: int
1.10.2.3! jason 729: userauth_pubkey_identity(Authctxt *authctxt, char *filename)
1.10.2.2 jason 730: {
731: Key *k;
1.10.2.3! jason 732: int i, ret, try_next;
1.10.2.2 jason 733: struct stat st;
734:
735: if (stat(filename, &st) != 0) {
736: debug("key does not exist: %s", filename);
737: return 0;
738: }
739: debug("try pubkey: %s", filename);
740:
741: k = key_new(KEY_DSA);
742: if (!load_private_key(filename, "", k, NULL)) {
743: int success = 0;
744: char *passphrase;
745: char prompt[300];
746: snprintf(prompt, sizeof prompt,
1.10.2.3! jason 747: "Enter passphrase for %s key '%.100s': ",
! 748: key_type(k), filename);
! 749: for (i = 0; i < options.number_of_password_prompts; i++) {
! 750: passphrase = read_passphrase(prompt, 0);
! 751: if (strcmp(passphrase, "") != 0) {
! 752: success = load_private_key(filename, passphrase, k, NULL);
! 753: try_next = 0;
! 754: } else {
! 755: debug2("no passphrase given, try next key");
! 756: try_next = 1;
! 757: }
! 758: memset(passphrase, 0, strlen(passphrase));
! 759: xfree(passphrase);
! 760: if (success || try_next)
! 761: break;
! 762: debug2("bad passphrase given, try again...");
! 763: }
1.10.2.2 jason 764: if (!success) {
765: key_free(k);
766: return 0;
767: }
768: }
1.10.2.3! jason 769: ret = sign_and_send_pubkey(authctxt, k, dsa_sign_cb);
1.10.2.2 jason 770: key_free(k);
771: return ret;
772: }
773:
1.10.2.3! jason 774: /* sign callback */
! 775: int agent_sign_cb(Authctxt *authctxt, Key *key, unsigned char **sigp, int *lenp,
1.10.2.2 jason 776: unsigned char *data, int datalen)
777: {
1.10.2.3! jason 778: return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen);
1.10.2.2 jason 779: }
780:
781: int
1.10.2.3! jason 782: userauth_pubkey_agent(Authctxt *authctxt)
1.10.2.2 jason 783: {
784: static int called = 0;
785: char *comment;
786: Key *k;
787: int ret;
788:
789: if (called == 0) {
1.10.2.3! jason 790: k = ssh_get_first_identity(authctxt->agent, &comment, 2);
! 791: called = 1;
1.10.2.2 jason 792: } else {
1.10.2.3! jason 793: k = ssh_get_next_identity(authctxt->agent, &comment, 2);
1.10.2.2 jason 794: }
1.10.2.3! jason 795: if (k == NULL) {
! 796: debug2("no more DSA keys from agent");
1.10.2.2 jason 797: return 0;
1.10.2.3! jason 798: }
1.10.2.2 jason 799: debug("trying DSA agent key %s", comment);
800: xfree(comment);
1.10.2.3! jason 801: ret = sign_and_send_pubkey(authctxt, k, agent_sign_cb);
1.10.2.2 jason 802: key_free(k);
803: return ret;
804: }
805:
1.10.2.3! jason 806: int
! 807: userauth_pubkey(Authctxt *authctxt)
1.1 markus 808: {
1.10.2.3! jason 809: static int idx = 0;
! 810: int sent = 0;
1.1 markus 811:
1.10.2.3! jason 812: if (authctxt->agent != NULL)
! 813: sent = userauth_pubkey_agent(authctxt);
! 814: while (sent == 0 && idx < options.num_identity_files2)
! 815: sent = userauth_pubkey_identity(authctxt, options.identity_files2[idx++]);
! 816: return sent;
! 817: }
! 818:
! 819: /*
! 820: * Send userauth request message specifying keyboard-interactive method.
! 821: */
! 822: int
! 823: userauth_kbdint(Authctxt *authctxt)
! 824: {
! 825: static int attempt = 0;
! 826:
! 827: if (attempt++ >= options.number_of_password_prompts)
! 828: return 0;
! 829:
! 830: debug2("userauth_kbdint");
! 831: packet_start(SSH2_MSG_USERAUTH_REQUEST);
! 832: packet_put_cstring(authctxt->server_user);
! 833: packet_put_cstring(authctxt->service);
! 834: packet_put_cstring(authctxt->method->name);
! 835: packet_put_cstring(""); /* lang */
! 836: packet_put_cstring(options.kbd_interactive_devices ?
! 837: options.kbd_interactive_devices : "");
1.1 markus 838: packet_send();
839: packet_write_wait();
840:
1.10.2.3! jason 841: dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
! 842: return 1;
! 843: }
! 844:
! 845: /*
! 846: * parse SSH2_MSG_USERAUTH_INFO_REQUEST, prompt user and send
! 847: * SSH2_MSG_USERAUTH_INFO_RESPONSE
! 848: */
! 849: void
! 850: input_userauth_info_req(int type, int plen, void *ctxt)
! 851: {
! 852: Authctxt *authctxt = ctxt;
! 853: char *name = NULL;
! 854: char *inst = NULL;
! 855: char *lang = NULL;
! 856: char *prompt = NULL;
! 857: char *response = NULL;
! 858: unsigned int num_prompts, i;
! 859: int echo = 0;
! 860:
! 861: debug2("input_userauth_info_req");
! 862:
! 863: if (authctxt == NULL)
! 864: fatal("input_userauth_info_req: no authentication context");
! 865:
! 866: name = packet_get_string(NULL);
! 867: inst = packet_get_string(NULL);
! 868: lang = packet_get_string(NULL);
! 869:
! 870: if (strlen(name) > 0)
! 871: cli_mesg(name);
! 872: xfree(name);
! 873:
! 874: if (strlen(inst) > 0)
! 875: cli_mesg(inst);
! 876: xfree(inst);
! 877: xfree(lang); /* unused */
! 878:
! 879: num_prompts = packet_get_int();
! 880: /*
! 881: * Begin to build info response packet based on prompts requested.
! 882: * We commit to providing the correct number of responses, so if
! 883: * further on we run into a problem that prevents this, we have to
! 884: * be sure and clean this up and send a correct error response.
! 885: */
! 886: packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
! 887: packet_put_int(num_prompts);
! 888:
! 889: for (i = 0; i < num_prompts; i++) {
! 890: prompt = packet_get_string(NULL);
! 891: echo = packet_get_char();
! 892:
! 893: response = cli_prompt(prompt, echo);
! 894:
! 895: packet_put_cstring(response);
! 896: memset(response, 0, strlen(response));
! 897: xfree(response);
! 898: xfree(prompt);
1.1 markus 899: }
1.10.2.3! jason 900: packet_done(); /* done with parsing incoming message. */
1.1 markus 901:
902: packet_send();
903: packet_write_wait();
1.10.2.3! jason 904: }
1.1 markus 905:
1.10.2.3! jason 906: /* find auth method */
! 907:
! 908: #define DELIM ","
! 909:
! 910: static char *def_authlist = "publickey,password";
! 911: static char *authlist_current = NULL; /* clean copy used for comparison */
! 912: static char *authname_current = NULL; /* last used auth method */
! 913: static char *authlist_working = NULL; /* copy that gets modified by strtok_r() */
! 914: static char *authlist_state = NULL; /* state variable for strtok_r() */
! 915:
! 916: /*
! 917: * Before starting to use a new authentication method list sent by the
! 918: * server, reset internal variables. This should also be called when
! 919: * finished processing server list to free resources.
! 920: */
! 921: void
! 922: authmethod_clear()
! 923: {
! 924: if (authlist_current != NULL) {
! 925: xfree(authlist_current);
! 926: authlist_current = NULL;
! 927: }
! 928: if (authlist_working != NULL) {
! 929: xfree(authlist_working);
! 930: authlist_working = NULL;
! 931: }
! 932: if (authname_current != NULL) {
! 933: xfree(authname_current);
! 934: authlist_state = NULL;
! 935: }
! 936: if (authlist_state != NULL)
! 937: authlist_state = NULL;
! 938: return;
! 939: }
! 940:
! 941: /*
! 942: * given auth method name, if configurable options permit this method fill
! 943: * in auth_ident field and return true, otherwise return false.
! 944: */
! 945: int
! 946: authmethod_is_enabled(Authmethod *method)
! 947: {
! 948: if (method == NULL)
! 949: return 0;
! 950: /* return false if options indicate this method is disabled */
! 951: if (method->enabled == NULL || *method->enabled == 0)
! 952: return 0;
! 953: /* return false if batch mode is enabled but method needs interactive mode */
! 954: if (method->batch_flag != NULL && *method->batch_flag != 0)
! 955: return 0;
! 956: return 1;
! 957: }
! 958:
! 959: Authmethod *
! 960: authmethod_lookup(const char *name)
! 961: {
! 962: Authmethod *method = NULL;
! 963: if (name != NULL)
! 964: for (method = authmethods; method->name != NULL; method++)
! 965: if (strcmp(name, method->name) == 0)
! 966: return method;
! 967: debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
! 968: return NULL;
! 969: }
! 970:
! 971: /*
! 972: * Given the authentication method list sent by the server, return the
! 973: * next method we should try. If the server initially sends a nil list,
! 974: * use a built-in default list. If the server sends a nil list after
! 975: * previously sending a valid list, continue using the list originally
! 976: * sent.
! 977: */
! 978:
! 979: Authmethod *
! 980: authmethod_get(char *authlist)
! 981: {
! 982: char *name = NULL, *authname_old;
! 983: Authmethod *method = NULL;
! 984:
! 985: /* Use a suitable default if we're passed a nil list. */
! 986: if (authlist == NULL || strlen(authlist) == 0)
! 987: authlist = def_authlist;
! 988:
! 989: if (authlist_current == NULL || strcmp(authlist, authlist_current) != 0) {
! 990: /* start over if passed a different list */
! 991: debug3("start over, passed a different list");
! 992: authmethod_clear();
! 993: authlist_current = xstrdup(authlist);
! 994: authlist_working = xstrdup(authlist);
! 995: name = strtok_r(authlist_working, DELIM, &authlist_state);
! 996: } else {
! 997: /*
! 998: * try to use previously used authentication method
! 999: * or continue to use previously passed list
! 1000: */
! 1001: name = (authname_current != NULL) ?
! 1002: authname_current : strtok_r(NULL, DELIM, &authlist_state);
! 1003: }
! 1004:
! 1005: while (name != NULL) {
! 1006: debug3("authmethod_lookup %s", name);
! 1007: method = authmethod_lookup(name);
! 1008: if (method != NULL && authmethod_is_enabled(method)) {
! 1009: debug3("authmethod_is_enabled %s", name);
1.1 markus 1010: break;
1011: }
1.10.2.3! jason 1012: name = strtok_r(NULL, DELIM, &authlist_state);
! 1013: method = NULL;
1.1 markus 1014: }
1.10.2.3! jason 1015:
! 1016: authname_old = authname_current;
! 1017: if (method != NULL) {
! 1018: debug("next auth method to try is %s", name);
! 1019: authname_current = xstrdup(name);
! 1020: } else {
! 1021: debug("no more auth methods to try");
! 1022: authname_current = NULL;
! 1023: }
! 1024:
! 1025: if (authname_old != NULL)
! 1026: xfree(authname_old);
! 1027:
! 1028: return (method);
1.1 markus 1029: }