Annotation of src/usr.bin/ssh/monitor.c, Revision 1.1
1.1 ! provos 1: /*
! 2: * Copyright 2002 Niels Provos <provos@citi.umich.edu>
! 3: * Copyright 2002 Markus Friedl <markus@openbsd.org>
! 4: * All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 17: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 18: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 19: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 20: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 21: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 22: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 23: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 24: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26:
! 27: #include "includes.h"
! 28: RCSID("$OpenBSD$");
! 29:
! 30: #include <openssl/dh.h>
! 31:
! 32: #ifdef SKEY
! 33: #include <skey.h>
! 34: #endif
! 35:
! 36: #include "ssh.h"
! 37: #include "auth.h"
! 38: #include "kex.h"
! 39: #include "dh.h"
! 40: #include "zlib.h"
! 41: #include "packet.h"
! 42: #include "auth-options.h"
! 43: #include "sshpty.h"
! 44: #include "channels.h"
! 45: #include "session.h"
! 46: #include "sshlogin.h"
! 47: #include "canohost.h"
! 48: #include "log.h"
! 49: #include "servconf.h"
! 50: #include "monitor.h"
! 51: #include "monitor_mm.h"
! 52: #include "monitor_wrap.h"
! 53: #include "monitor_fdpass.h"
! 54: #include "xmalloc.h"
! 55: #include "misc.h"
! 56: #include "buffer.h"
! 57: #include "bufaux.h"
! 58: #include "compat.h"
! 59: #include "ssh2.h"
! 60: #include "mpaux.h"
! 61:
! 62: /* Imports */
! 63: extern ServerOptions options;
! 64: extern u_int utmp_len;
! 65: extern Newkeys *current_keys[];
! 66: extern z_stream incoming_stream;
! 67: extern z_stream outgoing_stream;
! 68: extern u_char session_id[];
! 69: extern Buffer input, output;
! 70: extern Buffer auth_debug;
! 71: extern int auth_debug_init;
! 72:
! 73: /* State exported from the child */
! 74:
! 75: struct {
! 76: z_stream incoming;
! 77: z_stream outgoing;
! 78: u_char *keyin;
! 79: u_int keyinlen;
! 80: u_char *keyout;
! 81: u_int keyoutlen;
! 82: u_char *ivin;
! 83: u_int ivinlen;
! 84: u_char *ivout;
! 85: u_int ivoutlen;
! 86: int ssh1cipher;
! 87: int ssh1protoflags;
! 88: u_char *input;
! 89: u_int ilen;
! 90: u_char *output;
! 91: u_int olen;
! 92: } child_state;
! 93:
! 94: /* Prototypes for request sending and receiving */
! 95: void mm_request_send(int, enum monitor_reqtype, Buffer *);
! 96: void mm_request_receive(int, Buffer *);
! 97: void mm_request_receive_expect(int, enum monitor_reqtype, Buffer *);
! 98:
! 99: /* Prototypes for authentication functions */
! 100: int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
! 101: int bsdauth_respond(void *, u_int, char **);
! 102: int skey_query(void *, char **, char **, u_int *, char ***, u_int **);
! 103: int skey_respond(void *, u_int, char **);
! 104:
! 105: int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
! 106: int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
! 107: int user_key_allowed(struct passwd *, Key *);
! 108: Key *get_hostkey_by_index(int);
! 109: Key *get_hostkey_by_type(int);
! 110: int get_hostkey_index(Key *);
! 111: int ssh1_session_key(BIGNUM *);
! 112: int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
! 113: int auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
! 114: BIGNUM *auth_rsa_generate_challenge(Key *);
! 115:
! 116: void session_pty_cleanup2(void *);
! 117: Session *session_by_tty(char *);
! 118:
! 119: /* Functions on the montior that answer unprivileged requests */
! 120:
! 121: int mm_answer_moduli(int, Buffer *);
! 122: int mm_answer_sign(int, Buffer *);
! 123: int mm_answer_pwnamallow(int, Buffer *);
! 124: int mm_answer_authserv(int, Buffer *);
! 125: int mm_answer_authpassword(int, Buffer *);
! 126: int mm_answer_bsdauthquery(int, Buffer *);
! 127: int mm_answer_bsdauthrespond(int, Buffer *);
! 128: int mm_answer_skeyquery(int, Buffer *);
! 129: int mm_answer_skeyrespond(int, Buffer *);
! 130: int mm_answer_keyallowed(int, Buffer *);
! 131: int mm_answer_keyverify(int, Buffer *);
! 132: int mm_answer_pty(int, Buffer *);
! 133: int mm_answer_pty_cleanup(int, Buffer *);
! 134: int mm_answer_term(int, Buffer *);
! 135: int mm_answer_rsa_keyallowed(int, Buffer *);
! 136: int mm_answer_rsa_challenge(int, Buffer *);
! 137: int mm_answer_rsa_response(int, Buffer *);
! 138: int mm_answer_sesskey(int, Buffer *);
! 139: int mm_answer_sessid(int, Buffer *);
! 140:
! 141: static Authctxt *authctxt;
! 142: static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */
! 143:
! 144: /* local state for key verify */
! 145: static u_char *key_blob = NULL;
! 146: static u_int key_bloblen = 0;
! 147: static int key_blobtype = MM_NOKEY;
! 148: static u_char *hostbased_cuser = NULL;
! 149: static u_char *hostbased_chost = NULL;
! 150: static char *auth_method = "unknown";
! 151:
! 152: struct mon_table {
! 153: enum monitor_reqtype type;
! 154: int flags;
! 155: int (*f)(int, Buffer *);
! 156: };
! 157:
! 158: #define MON_ISAUTH 0x0004 /* Required for Authentication */
! 159: #define MON_AUTHDECIDE 0x0008 /* Decides Authentication */
! 160: #define MON_ONCE 0x0010 /* Disable after calling */
! 161:
! 162: #define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE)
! 163:
! 164: #define MON_PERMIT 0x1000 /* Request is permitted */
! 165:
! 166: struct mon_table mon_dispatch_proto20[] = {
! 167: {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
! 168: {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
! 169: {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
! 170: {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
! 171: {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
! 172: #ifdef BSD_AUTH
! 173: {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
! 174: {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond},
! 175: #endif
! 176: #ifdef SKEY
! 177: {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
! 178: {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
! 179: #endif
! 180: {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
! 181: {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
! 182: {0, 0, NULL}
! 183: };
! 184:
! 185: struct mon_table mon_dispatch_postauth20[] = {
! 186: {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
! 187: {MONITOR_REQ_SIGN, 0, mm_answer_sign},
! 188: {MONITOR_REQ_PTY, 0, mm_answer_pty},
! 189: {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
! 190: {MONITOR_REQ_TERM, 0, mm_answer_term},
! 191: {0, 0, NULL}
! 192: };
! 193:
! 194: struct mon_table mon_dispatch_proto15[] = {
! 195: {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
! 196: {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
! 197: {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
! 198: {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
! 199: {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH, mm_answer_rsa_keyallowed},
! 200: {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
! 201: {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge},
! 202: {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response},
! 203: #ifdef BSD_AUTH
! 204: {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
! 205: {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond},
! 206: #endif
! 207: #ifdef SKEY
! 208: {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
! 209: {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
! 210: #endif
! 211: {0, 0, NULL}
! 212: };
! 213:
! 214: struct mon_table mon_dispatch_postauth15[] = {
! 215: {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
! 216: {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
! 217: {MONITOR_REQ_TERM, 0, mm_answer_term},
! 218: {0, 0, NULL}
! 219: };
! 220:
! 221: struct mon_table *mon_dispatch;
! 222:
! 223: /* Specifies if a certain message is allowed at the moment */
! 224:
! 225: static void
! 226: monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit)
! 227: {
! 228: while (ent->f != NULL) {
! 229: if (ent->type == type) {
! 230: ent->flags &= ~MON_PERMIT;
! 231: ent->flags |= permit ? MON_PERMIT : 0;
! 232: return;
! 233: }
! 234: ent++;
! 235: }
! 236: }
! 237:
! 238: static void
! 239: monitor_permit_authentications(int permit)
! 240: {
! 241: struct mon_table *ent = mon_dispatch;
! 242:
! 243: while (ent->f != NULL) {
! 244: if (ent->flags & MON_AUTH) {
! 245: ent->flags &= ~MON_PERMIT;
! 246: ent->flags |= permit ? MON_PERMIT : 0;
! 247: }
! 248: ent++;
! 249: }
! 250: }
! 251:
! 252: Authctxt *
! 253: monitor_child_preauth(struct monitor *monitor)
! 254: {
! 255: struct mon_table *ent;
! 256: int authenticated = 0;
! 257:
! 258: debug3("preauth child monitor started");
! 259:
! 260: if (compat20) {
! 261: mon_dispatch = mon_dispatch_proto20;
! 262:
! 263: /* Permit requests for moduli and signatures */
! 264: monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
! 265: monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
! 266: } else {
! 267: mon_dispatch = mon_dispatch_proto15;
! 268:
! 269: monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
! 270: }
! 271:
! 272: authctxt = authctxt_new();
! 273:
! 274: /* The first few requests do not require asynchronous access */
! 275: while (!authenticated) {
! 276: authenticated = monitor_read(monitor, mon_dispatch, &ent);
! 277: if (authenticated) {
! 278: if (!(ent->flags & MON_AUTHDECIDE))
! 279: fatal("%s: unexpected authentication from %d",
! 280: __FUNCTION__, ent->type);
! 281: if (authctxt->pw->pw_uid == 0 &&
! 282: !auth_root_allowed(auth_method))
! 283: authenticated = 0;
! 284: }
! 285:
! 286: if (ent->flags & MON_AUTHDECIDE) {
! 287: auth_log(authctxt, authenticated, auth_method,
! 288: compat20 ? " ssh2" : "");
! 289: if (!authenticated)
! 290: authctxt->failures++;
! 291: }
! 292: }
! 293:
! 294: if (!authctxt->valid)
! 295: fatal("%s: authenticated invalid user", __FUNCTION__);
! 296:
! 297: debug("%s: %s has been authenticated by privileged process",
! 298: __FUNCTION__, authctxt->user);
! 299:
! 300: mm_get_keystate(monitor);
! 301:
! 302: return (authctxt);
! 303: }
! 304:
! 305: void
! 306: monitor_child_postauth(struct monitor *monitor)
! 307: {
! 308: if (compat20) {
! 309: mon_dispatch = mon_dispatch_postauth20;
! 310:
! 311: /* Permit requests for moduli and signatures */
! 312: monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
! 313: monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
! 314: monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
! 315:
! 316: } else {
! 317: mon_dispatch = mon_dispatch_postauth15;
! 318: monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
! 319: }
! 320: if (!no_pty_flag) {
! 321: monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
! 322: monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
! 323: }
! 324:
! 325: for (;;)
! 326: monitor_read(monitor, mon_dispatch, NULL);
! 327: }
! 328:
! 329: void
! 330: monitor_sync(struct monitor *monitor)
! 331: {
! 332: /* The member allocation is not visible, so sync it */
! 333: mm_share_sync(&monitor->m_zlib, &monitor->m_zback);
! 334: }
! 335:
! 336: int
! 337: monitor_read(struct monitor *monitor, struct mon_table *ent,
! 338: struct mon_table **pent)
! 339: {
! 340: Buffer m;
! 341: int ret;
! 342: u_char type;
! 343:
! 344: buffer_init(&m);
! 345:
! 346: mm_request_receive(monitor->m_sendfd, &m);
! 347: type = buffer_get_char(&m);
! 348:
! 349: debug3("%s: checking request %d", __FUNCTION__, type);
! 350:
! 351: while (ent->f != NULL) {
! 352: if (ent->type == type)
! 353: break;
! 354: ent++;
! 355: }
! 356:
! 357: if (ent->f != NULL) {
! 358: if (!(ent->flags & MON_PERMIT))
! 359: fatal("%s: unpermitted request %d", __FUNCTION__,
! 360: type);
! 361: ret = (*ent->f)(monitor->m_sendfd, &m);
! 362: buffer_free(&m);
! 363:
! 364: /* The child may use this request only once, disable it */
! 365: if (ent->flags & MON_ONCE) {
! 366: debug2("%s: %d used once, disabling now", __FUNCTION__,
! 367: type);
! 368: ent->flags &= ~MON_PERMIT;
! 369: }
! 370:
! 371: if (pent != NULL)
! 372: *pent = ent;
! 373:
! 374: return ret;
! 375: }
! 376:
! 377: fatal("%s: unsupported request: %d\n", __FUNCTION__, type);
! 378:
! 379: /* NOTREACHED */
! 380: return (-1);
! 381: }
! 382:
! 383: /* allowed key state */
! 384: static int
! 385: monitor_allowed_key(u_char *blob, u_int bloblen)
! 386: {
! 387: /* make sure key is allowed */
! 388: if (key_blob == NULL || key_bloblen != bloblen ||
! 389: memcmp(key_blob, blob, key_bloblen))
! 390: return (0);
! 391: return (1);
! 392: }
! 393:
! 394: static void
! 395: monitor_reset_key_state(void)
! 396: {
! 397: /* reset state */
! 398: if (key_blob != NULL)
! 399: xfree(key_blob);
! 400: if (hostbased_cuser != NULL)
! 401: xfree(hostbased_cuser);
! 402: if (hostbased_chost != NULL)
! 403: xfree(hostbased_chost);
! 404: key_blob = NULL;
! 405: key_bloblen = 0;
! 406: key_blobtype = MM_NOKEY;
! 407: hostbased_cuser = NULL;
! 408: hostbased_chost = NULL;
! 409: }
! 410:
! 411: int
! 412: mm_answer_moduli(int socket, Buffer *m)
! 413: {
! 414: DH *dh;
! 415: int min, want, max;
! 416:
! 417: min = buffer_get_int(m);
! 418: want = buffer_get_int(m);
! 419: max = buffer_get_int(m);
! 420:
! 421: debug3("%s: got parameters: %d %d %d",
! 422: __FUNCTION__, min, want, max);
! 423: /* We need to check here, too, in case the child got corrupted */
! 424: if (max < min || want < min || max < want)
! 425: fatal("%s: bad parameters: %d %d %d",
! 426: __FUNCTION__, min, want, max);
! 427:
! 428: buffer_clear(m);
! 429:
! 430: dh = choose_dh(min, want, max);
! 431: if (dh == NULL) {
! 432: buffer_put_char(m, 0);
! 433: return (0);
! 434: } else {
! 435: /* Send first bignum */
! 436: buffer_put_char(m, 1);
! 437: buffer_put_bignum2(m, dh->p);
! 438: buffer_put_bignum2(m, dh->g);
! 439:
! 440: DH_free(dh);
! 441: }
! 442: mm_request_send(socket, MONITOR_ANS_MODULI, m);
! 443: return (0);
! 444: }
! 445:
! 446: int
! 447: mm_answer_sign(int socket, Buffer *m)
! 448: {
! 449: Key *key;
! 450: u_char *p;
! 451: u_char *signature;
! 452: u_int siglen, datlen;
! 453: int keyid;
! 454:
! 455: debug3("%s", __FUNCTION__);
! 456:
! 457: keyid = buffer_get_int(m);
! 458: p = buffer_get_string(m, &datlen);
! 459:
! 460: if (datlen != 20)
! 461: fatal("%s: data length incorrect: %d", __FUNCTION__, datlen);
! 462:
! 463: if ((key = get_hostkey_by_index(keyid)) == NULL)
! 464: fatal("%s: no hostkey from index %d", __FUNCTION__, keyid);
! 465: if (key_sign(key, &signature, &siglen, p, datlen) < 0)
! 466: fatal("%s: key_sign failed", __FUNCTION__);
! 467:
! 468: debug3("%s: signature %p(%d)", __FUNCTION__, signature, siglen);
! 469:
! 470: buffer_clear(m);
! 471: buffer_put_string(m, signature, siglen);
! 472:
! 473: xfree(p);
! 474: xfree(signature);
! 475:
! 476: mm_request_send(socket, MONITOR_ANS_SIGN, m);
! 477:
! 478: /* Turn on permissions for getpwnam */
! 479: monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
! 480:
! 481: return (0);
! 482: }
! 483:
! 484: /* Retrieves the password entry and also checks if the user is permitted */
! 485:
! 486: int
! 487: mm_answer_pwnamallow(int socket, Buffer *m)
! 488: {
! 489: char *login;
! 490: struct passwd *pwent;
! 491: int allowed = 0;
! 492:
! 493: debug3("%s", __FUNCTION__);
! 494:
! 495: if (authctxt->attempt++ != 0)
! 496: fatal("%s: multiple attempts for getpwnam", __FUNCTION__);
! 497:
! 498: login = buffer_get_string(m, NULL);
! 499:
! 500: pwent = getpwnamallow(login);
! 501:
! 502: authctxt->user = xstrdup(login);
! 503: setproctitle("%s [priv]", pwent ? login : "unknown");
! 504: xfree(login);
! 505:
! 506: buffer_clear(m);
! 507:
! 508: if (pwent == NULL) {
! 509: buffer_put_char(m, 0);
! 510: goto out;
! 511: }
! 512:
! 513: allowed = 1;
! 514: authctxt->pw = pwcopy(pwent);
! 515: authctxt->valid = 1;
! 516:
! 517: buffer_put_char(m, 1);
! 518: buffer_put_string(m, pwent, sizeof(struct passwd));
! 519: buffer_put_cstring(m, pwent->pw_name);
! 520: buffer_put_cstring(m, "*");
! 521: buffer_put_cstring(m, pwent->pw_gecos);
! 522: buffer_put_cstring(m, pwent->pw_class);
! 523: buffer_put_cstring(m, pwent->pw_dir);
! 524: buffer_put_cstring(m, pwent->pw_shell);
! 525:
! 526: out:
! 527: debug3("%s: sending MONITOR_ANS_PWNAM: %d", __FUNCTION__, allowed);
! 528: mm_request_send(socket, MONITOR_ANS_PWNAM, m);
! 529:
! 530: /* For SSHv1 allow authentication now */
! 531: if (!compat20)
! 532: monitor_permit_authentications(1);
! 533: else
! 534: /* Allow service/style information on the auth context */
! 535: monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
! 536:
! 537:
! 538: return (0);
! 539: }
! 540:
! 541: int
! 542: mm_answer_authserv(int socket, Buffer *m)
! 543: {
! 544: monitor_permit_authentications(1);
! 545:
! 546: authctxt->service = buffer_get_string(m, NULL);
! 547: authctxt->style = buffer_get_string(m, NULL);
! 548: if (strlen(authctxt->style) == 0) {
! 549: xfree(authctxt->style);
! 550: authctxt->style = NULL;
! 551: }
! 552:
! 553: debug3("%s: service=%s, style=%s",
! 554: __FUNCTION__, authctxt->service, authctxt->style);
! 555:
! 556: return (0);
! 557: }
! 558:
! 559: int
! 560: mm_answer_authpassword(int socket, Buffer *m)
! 561: {
! 562: static int call_count;
! 563: char *passwd;
! 564: int authenticated, plen;
! 565:
! 566: passwd = buffer_get_string(m, &plen);
! 567: /* Only authenticate if the context is valid */
! 568: authenticated = authctxt->valid && auth_password(authctxt, passwd);
! 569: memset(passwd, 0, strlen(passwd));
! 570: xfree(passwd);
! 571:
! 572: buffer_clear(m);
! 573: buffer_put_int(m, authenticated);
! 574:
! 575: debug3("%s: sending result %d", __FUNCTION__, authenticated);
! 576: mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m);
! 577:
! 578: call_count++;
! 579: if (plen == 0 && call_count == 1)
! 580: auth_method = "none";
! 581: else
! 582: auth_method = "password";
! 583:
! 584: /* Causes monitor loop to terminate if authenticated */
! 585: return (authenticated);
! 586: }
! 587:
! 588: #ifdef BSD_AUTH
! 589: int
! 590: mm_answer_bsdauthquery(int socket, Buffer *m)
! 591: {
! 592: char *name, *infotxt;
! 593: u_int numprompts;
! 594: u_int *echo_on;
! 595: char **prompts;
! 596: int res;
! 597:
! 598: res = bsdauth_query(authctxt, &name, &infotxt, &numprompts,
! 599: &prompts, &echo_on);
! 600:
! 601: buffer_clear(m);
! 602: buffer_put_int(m, res);
! 603: if (res != -1)
! 604: buffer_put_cstring(m, prompts[0]);
! 605:
! 606: debug3("%s: sending challenge res: %d", __FUNCTION__, res);
! 607: mm_request_send(socket, MONITOR_ANS_BSDAUTHQUERY, m);
! 608:
! 609: if (res != -1) {
! 610: xfree(name);
! 611: xfree(infotxt);
! 612: xfree(prompts);
! 613: xfree(echo_on);
! 614: }
! 615:
! 616: return (0);
! 617: }
! 618:
! 619: int
! 620: mm_answer_bsdauthrespond(int socket, Buffer *m)
! 621: {
! 622: char *response;
! 623: int authok;
! 624:
! 625: if (authctxt->as == 0)
! 626: fatal("%s: no bsd auth session", __FUNCTION__);
! 627:
! 628: response = buffer_get_string(m, NULL);
! 629: authok = auth_userresponse(authctxt->as, response, 0);
! 630: authctxt->as = NULL;
! 631: debug3("%s: <%s> = <%d>", __FUNCTION__, response, authok);
! 632: xfree(response);
! 633:
! 634: buffer_clear(m);
! 635: buffer_put_int(m, authok);
! 636:
! 637: debug3("%s: sending authenticated: %d", __FUNCTION__, authok);
! 638: mm_request_send(socket, MONITOR_ANS_BSDAUTHRESPOND, m);
! 639:
! 640: auth_method = "bsdauth";
! 641:
! 642: return (authok != 0);
! 643: }
! 644: #endif
! 645:
! 646: #ifdef SKEY
! 647: int
! 648: mm_answer_skeyquery(int socket, Buffer *m)
! 649: {
! 650: struct skey skey;
! 651: char challenge[1024];
! 652: int res;
! 653:
! 654: res = skeychallenge(&skey, authctxt->user, challenge);
! 655:
! 656: buffer_clear(m);
! 657: buffer_put_int(m, res);
! 658: if (res != -1)
! 659: buffer_put_cstring(m, challenge);
! 660:
! 661: debug3("%s: sending challenge res: %d", __FUNCTION__, res);
! 662: mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m);
! 663:
! 664: return (0);
! 665: }
! 666:
! 667: int
! 668: mm_answer_skeyrespond(int socket, Buffer *m)
! 669: {
! 670: char *response;
! 671: int authok;
! 672:
! 673: response = buffer_get_string(m, NULL);
! 674:
! 675: authok = (authctxt->valid &&
! 676: skey_haskey(authctxt->pw->pw_name) == 0 &&
! 677: skey_passcheck(authctxt->pw->pw_name, response) != -1);
! 678:
! 679: xfree(response);
! 680:
! 681: buffer_clear(m);
! 682: buffer_put_int(m, authok);
! 683:
! 684: debug3("%s: sending authenticated: %d", __FUNCTION__, authok);
! 685: mm_request_send(socket, MONITOR_ANS_SKEYRESPOND, m);
! 686:
! 687: auth_method = "skey";
! 688:
! 689: return (authok != 0);
! 690: }
! 691: #endif
! 692:
! 693: void
! 694: mm_append_debug(Buffer *m)
! 695: {
! 696: if (auth_debug_init && buffer_len(&auth_debug)) {
! 697: debug3("%s: Appending debug messages for child", __FUNCTION__);
! 698: buffer_append(m, buffer_ptr(&auth_debug),
! 699: buffer_len(&auth_debug));
! 700: buffer_clear(&auth_debug);
! 701: }
! 702: }
! 703:
! 704: int
! 705: mm_answer_keyallowed(int socket, Buffer *m)
! 706: {
! 707: Key *key;
! 708: u_char *cuser, *chost, *blob;
! 709: u_int bloblen;
! 710: enum mm_keytype type = 0;
! 711: int allowed = 0;
! 712:
! 713: debug3("%s entering", __FUNCTION__);
! 714:
! 715: type = buffer_get_int(m);
! 716: cuser = buffer_get_string(m, NULL);
! 717: chost = buffer_get_string(m, NULL);
! 718: blob = buffer_get_string(m, &bloblen);
! 719:
! 720: key = key_from_blob(blob, bloblen);
! 721:
! 722: if ((compat20 && type == MM_RSAHOSTKEY) ||
! 723: (!compat20 && type != MM_RSAHOSTKEY))
! 724: fatal("%s: key type and protocol mismatch", __FUNCTION__);
! 725:
! 726: debug3("%s: key_from_blob: %p", __FUNCTION__, key);
! 727:
! 728: if (key != NULL && authctxt->pw != NULL) {
! 729: switch(type) {
! 730: case MM_USERKEY:
! 731: allowed = user_key_allowed(authctxt->pw, key);
! 732: break;
! 733: case MM_HOSTKEY:
! 734: allowed = hostbased_key_allowed(authctxt->pw,
! 735: cuser, chost, key);
! 736: break;
! 737: case MM_RSAHOSTKEY:
! 738: key->type = KEY_RSA1; /* XXX */
! 739: allowed = auth_rhosts_rsa_key_allowed(authctxt->pw,
! 740: cuser, chost, key);
! 741: break;
! 742: default:
! 743: fatal("%s: unknown key type %d", __FUNCTION__, type);
! 744: break;
! 745: }
! 746: key_free(key);
! 747: }
! 748:
! 749: /* clear temporarily storage (used by verify) */
! 750: monitor_reset_key_state();
! 751:
! 752: if (allowed) {
! 753: /* Save temporarily for comparison in verify */
! 754: key_blob = blob;
! 755: key_bloblen = bloblen;
! 756: key_blobtype = type;
! 757: hostbased_cuser = cuser;
! 758: hostbased_chost = chost;
! 759: }
! 760:
! 761: debug3("%s: key %p is %s",
! 762: __FUNCTION__, key, allowed ? "allowed" : "disallowed");
! 763:
! 764: buffer_clear(m);
! 765: buffer_put_int(m, allowed);
! 766:
! 767: mm_append_debug(m);
! 768:
! 769: mm_request_send(socket, MONITOR_ANS_KEYALLOWED, m);
! 770:
! 771: if (type == MM_RSAHOSTKEY)
! 772: monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
! 773:
! 774: return (0);
! 775: }
! 776:
! 777: static int
! 778: monitor_valid_userblob(u_char *data, u_int datalen)
! 779: {
! 780: Buffer b;
! 781: u_char *p;
! 782: u_int len;
! 783: int fail = 0;
! 784: int session_id2_len = 20 /*XXX should get from [net] */;
! 785:
! 786: buffer_init(&b);
! 787: buffer_append(&b, data, datalen);
! 788:
! 789: if (datafellows & SSH_OLD_SESSIONID) {
! 790: buffer_consume(&b, session_id2_len);
! 791: } else {
! 792: xfree(buffer_get_string(&b, &len));
! 793: if (len != session_id2_len)
! 794: fail++;
! 795: }
! 796: if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
! 797: fail++;
! 798: p = buffer_get_string(&b, NULL);
! 799: if (strcmp(authctxt->user, p) != 0) {
! 800: log("wrong user name passed to monitor: expected %s != %.100s",
! 801: authctxt->user, p);
! 802: fail++;
! 803: }
! 804: xfree(p);
! 805: buffer_skip_string(&b);
! 806: if (datafellows & SSH_BUG_PKAUTH) {
! 807: if (!buffer_get_char(&b))
! 808: fail++;
! 809: } else {
! 810: p = buffer_get_string(&b, NULL);
! 811: if (strcmp("publickey", p) != 0)
! 812: fail++;
! 813: xfree(p);
! 814: if (!buffer_get_char(&b))
! 815: fail++;
! 816: buffer_skip_string(&b);
! 817: }
! 818: buffer_skip_string(&b);
! 819: if (buffer_len(&b) != 0)
! 820: fail++;
! 821: buffer_free(&b);
! 822: return (fail == 0);
! 823: }
! 824:
! 825: static int
! 826: monitor_valid_hostbasedblob(u_char *data, u_int datalen, u_char *cuser,
! 827: u_char *chost)
! 828: {
! 829: Buffer b;
! 830: u_char *p;
! 831: u_int len;
! 832: int fail = 0;
! 833: int session_id2_len = 20 /*XXX should get from [net] */;
! 834:
! 835: buffer_init(&b);
! 836: buffer_append(&b, data, datalen);
! 837:
! 838: xfree(buffer_get_string(&b, &len));
! 839: if (len != session_id2_len)
! 840: fail++;
! 841: if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
! 842: fail++;
! 843: p = buffer_get_string(&b, NULL);
! 844: if (strcmp(authctxt->user, p) != 0) {
! 845: log("wrong user name passed to monitor: expected %s != %.100s",
! 846: authctxt->user, p);
! 847: fail++;
! 848: }
! 849: xfree(p);
! 850: buffer_skip_string(&b); /* service */
! 851: p = buffer_get_string(&b, NULL);
! 852: if (strcmp(p, "hostbased") != 0)
! 853: fail++;
! 854: xfree(p);
! 855: buffer_skip_string(&b); /* pkalg */
! 856: buffer_skip_string(&b); /* pkblob */
! 857:
! 858: /* verify client host, strip trailing dot if necessary */
! 859: p = buffer_get_string(&b, NULL);
! 860: if (((len = strlen(p)) > 0) && p[len - 1] == '.')
! 861: p[len - 1] = '\0';
! 862: if (strcmp(p, chost) != 0)
! 863: fail++;
! 864: xfree(p);
! 865:
! 866: /* verify client user */
! 867: p = buffer_get_string(&b, NULL);
! 868: if (strcmp(p, cuser) != 0)
! 869: fail++;
! 870: xfree(p);
! 871:
! 872: if (buffer_len(&b) != 0)
! 873: fail++;
! 874: buffer_free(&b);
! 875: return (fail == 0);
! 876: }
! 877:
! 878: int
! 879: mm_answer_keyverify(int socket, Buffer *m)
! 880: {
! 881: Key *key;
! 882: u_char *signature, *data, *blob;
! 883: u_int signaturelen, datalen, bloblen;
! 884: int verified = 0;
! 885: int valid_data = 0;
! 886:
! 887: blob = buffer_get_string(m, &bloblen);
! 888: signature = buffer_get_string(m, &signaturelen);
! 889: data = buffer_get_string(m, &datalen);
! 890:
! 891: if (hostbased_cuser == NULL || hostbased_chost == NULL ||
! 892: monitor_allowed_key(blob, bloblen) == NULL)
! 893: fatal("%s: bad key, not previously allowed", __FUNCTION__);
! 894:
! 895: key = key_from_blob(blob, bloblen);
! 896: if (key == NULL)
! 897: fatal("%s: bad public key blob", __FUNCTION__);
! 898:
! 899: switch (key_blobtype) {
! 900: case MM_USERKEY:
! 901: valid_data = monitor_valid_userblob(data, datalen);
! 902: break;
! 903: case MM_HOSTKEY:
! 904: valid_data = monitor_valid_hostbasedblob(data, datalen,
! 905: hostbased_cuser, hostbased_chost);
! 906: break;
! 907: default:
! 908: valid_data = 0;
! 909: break;
! 910: }
! 911: if (!valid_data)
! 912: fatal("%s: bad signature data blob", __FUNCTION__);
! 913:
! 914: verified = key_verify(key, signature, signaturelen, data, datalen);
! 915: debug3("%s: key %p signature %s",
! 916: __FUNCTION__, key, verified ? "verified" : "unverified");
! 917:
! 918: key_free(key);
! 919: xfree(blob);
! 920: xfree(signature);
! 921: xfree(data);
! 922:
! 923: monitor_reset_key_state();
! 924:
! 925: buffer_clear(m);
! 926: buffer_put_int(m, verified);
! 927: mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m);
! 928:
! 929: auth_method = "publickey";
! 930:
! 931: return (verified);
! 932: }
! 933:
! 934: void
! 935: mm_record_login(Session *s, struct passwd *pw)
! 936: {
! 937: socklen_t fromlen;
! 938: struct sockaddr_storage from;
! 939:
! 940: /*
! 941: * Get IP address of client. If the connection is not a socket, let
! 942: * the address be 0.0.0.0.
! 943: */
! 944: memset(&from, 0, sizeof(from));
! 945: if (packet_connection_is_on_socket()) {
! 946: fromlen = sizeof(from);
! 947: if (getpeername(packet_get_connection_in(),
! 948: (struct sockaddr *) & from, &fromlen) < 0) {
! 949: debug("getpeername: %.100s", strerror(errno));
! 950: fatal_cleanup();
! 951: }
! 952: }
! 953: /* Record that there was a login on that tty from the remote host. */
! 954: record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
! 955: get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
! 956: (struct sockaddr *)&from);
! 957: }
! 958:
! 959: static void
! 960: mm_session_close(Session *s)
! 961: {
! 962: debug3("%s: session %d pid %d", __FUNCTION__, s->self, s->pid);
! 963: if (s->ttyfd != -1) {
! 964: debug3("%s: tty %s ptyfd %d", __FUNCTION__, s->tty, s->ptyfd);
! 965: fatal_remove_cleanup(session_pty_cleanup2, (void *)s);
! 966: session_pty_cleanup2(s);
! 967: }
! 968: s->used = 0;
! 969: }
! 970:
! 971: int
! 972: mm_answer_pty(int socket, Buffer *m)
! 973: {
! 974: extern struct monitor *monitor;
! 975: Session *s;
! 976: int res, fd0;
! 977:
! 978: debug3("%s entering", __FUNCTION__);
! 979:
! 980: buffer_clear(m);
! 981: s = session_new();
! 982: if (s == NULL)
! 983: goto error;
! 984: s->authctxt = authctxt;
! 985: s->pw = authctxt->pw;
! 986: s->pid = monitor->m_pid;
! 987: res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
! 988: if (res == 0)
! 989: goto error;
! 990: fatal_add_cleanup(session_pty_cleanup2, (void *)s);
! 991: pty_setowner(authctxt->pw, s->tty);
! 992:
! 993: buffer_put_int(m, 1);
! 994: buffer_put_cstring(m, s->tty);
! 995: mm_request_send(socket, MONITOR_ANS_PTY, m);
! 996:
! 997: mm_send_fd(socket, s->ptyfd);
! 998: mm_send_fd(socket, s->ttyfd);
! 999:
! 1000: /* We need to trick ttyslot */
! 1001: if (dup2(s->ttyfd, 0) == -1)
! 1002: fatal("%s: dup2", __FUNCTION__);
! 1003:
! 1004: mm_record_login(s, authctxt->pw);
! 1005:
! 1006: /* Now we can close the file descriptor again */
! 1007: close(0);
! 1008:
! 1009: /* make sure nothing uses fd 0 */
! 1010: if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
! 1011: fatal("%s: open(/dev/null): %s", __FUNCTION__, strerror(errno));
! 1012: if (fd0 != 0)
! 1013: error("%s: fd0 %d != 0", __FUNCTION__, fd0);
! 1014:
! 1015: /* slave is not needed */
! 1016: close(s->ttyfd);
! 1017: s->ttyfd = s->ptyfd;
! 1018: /* no need to dup() because nobody closes ptyfd */
! 1019: s->ptymaster = s->ptyfd;
! 1020:
! 1021: debug3("%s: tty %s ptyfd %d", __FUNCTION__, s->tty, s->ttyfd);
! 1022:
! 1023: return (0);
! 1024:
! 1025: error:
! 1026: if (s != NULL)
! 1027: mm_session_close(s);
! 1028: buffer_put_int(m, 0);
! 1029: mm_request_send(socket, MONITOR_ANS_PTY, m);
! 1030: return (0);
! 1031: }
! 1032:
! 1033: int
! 1034: mm_answer_pty_cleanup(int socket, Buffer *m)
! 1035: {
! 1036: Session *s;
! 1037: char *tty;
! 1038:
! 1039: debug3("%s entering", __FUNCTION__);
! 1040:
! 1041: tty = buffer_get_string(m, NULL);
! 1042: if ((s = session_by_tty(tty)) != NULL)
! 1043: mm_session_close(s);
! 1044: buffer_clear(m);
! 1045: xfree(tty);
! 1046: return (0);
! 1047: }
! 1048:
! 1049: int
! 1050: mm_answer_sesskey(int socket, Buffer *m)
! 1051: {
! 1052: BIGNUM *p;
! 1053: int rsafail;
! 1054:
! 1055: /* Turn off permissions */
! 1056: monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
! 1057:
! 1058: if ((p = BN_new()) == NULL)
! 1059: fatal("%s: BN_new", __FUNCTION__);
! 1060:
! 1061: buffer_get_bignum2(m, p);
! 1062:
! 1063: rsafail = ssh1_session_key(p);
! 1064:
! 1065: buffer_clear(m);
! 1066: buffer_put_int(m, rsafail);
! 1067: buffer_put_bignum2(m, p);
! 1068:
! 1069: BN_clear_free(p);
! 1070:
! 1071: mm_request_send(socket, MONITOR_ANS_SESSKEY, m);
! 1072:
! 1073: /* Turn on permissions for sessid passing */
! 1074: monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1);
! 1075:
! 1076: return (0);
! 1077: }
! 1078:
! 1079: int
! 1080: mm_answer_sessid(int socket, Buffer *m)
! 1081: {
! 1082: int i;
! 1083:
! 1084: debug3("%s entering", __FUNCTION__);
! 1085:
! 1086: if (buffer_len(m) != 16)
! 1087: fatal("%s: bad ssh1 session id", __FUNCTION__);
! 1088: for (i = 0; i < 16; i++)
! 1089: session_id[i] = buffer_get_char(m);
! 1090:
! 1091: /* Turn on permissions for getpwnam */
! 1092: monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
! 1093:
! 1094: return (0);
! 1095: }
! 1096:
! 1097: int
! 1098: mm_answer_rsa_keyallowed(int socket, Buffer *m)
! 1099: {
! 1100: BIGNUM *client_n;
! 1101: Key *key = NULL;
! 1102: u_char *blob = NULL;
! 1103: u_int blen = 0;
! 1104: int allowed = 0;
! 1105:
! 1106: debug3("%s entering", __FUNCTION__);
! 1107:
! 1108: if (authctxt->valid) {
! 1109: if ((client_n = BN_new()) == NULL)
! 1110: fatal("%s: BN_new", __FUNCTION__);
! 1111: buffer_get_bignum2(m, client_n);
! 1112: allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key);
! 1113: BN_clear_free(client_n);
! 1114: }
! 1115: buffer_clear(m);
! 1116: buffer_put_int(m, allowed);
! 1117:
! 1118: /* clear temporarily storage (used by generate challenge) */
! 1119: monitor_reset_key_state();
! 1120:
! 1121: if (allowed && key != NULL) {
! 1122: key->type = KEY_RSA; /* cheat for key_to_blob */
! 1123: if (key_to_blob(key, &blob, &blen) == 0)
! 1124: fatal("%s: key_to_blob failed", __FUNCTION__);
! 1125: buffer_put_string(m, blob, blen);
! 1126:
! 1127: /* Save temporarily for comparison in verify */
! 1128: key_blob = blob;
! 1129: key_bloblen = blen;
! 1130: key_blobtype = MM_RSAUSERKEY;
! 1131: key_free(key);
! 1132: }
! 1133:
! 1134: mm_append_debug(m);
! 1135:
! 1136: mm_request_send(socket, MONITOR_ANS_RSAKEYALLOWED, m);
! 1137:
! 1138: monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
! 1139: monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0);
! 1140: return (0);
! 1141: }
! 1142:
! 1143: int
! 1144: mm_answer_rsa_challenge(int socket, Buffer *m)
! 1145: {
! 1146: Key *key = NULL;
! 1147: u_char *blob;
! 1148: u_int blen;
! 1149:
! 1150: debug3("%s entering", __FUNCTION__);
! 1151:
! 1152: if (!authctxt->valid)
! 1153: fatal("%s: authctxt not valid", __FUNCTION__);
! 1154: blob = buffer_get_string(m, &blen);
! 1155: if (!monitor_allowed_key(blob, blen))
! 1156: fatal("%s: bad key, not previously allowed", __FUNCTION__);
! 1157: if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
! 1158: fatal("%s: key type mismatch", __FUNCTION__);
! 1159: if ((key = key_from_blob(blob, blen)) == NULL)
! 1160: fatal("%s: received bad key", __FUNCTION__);
! 1161:
! 1162: if (ssh1_challenge)
! 1163: BN_clear_free(ssh1_challenge);
! 1164: ssh1_challenge = auth_rsa_generate_challenge(key);
! 1165:
! 1166: buffer_clear(m);
! 1167: buffer_put_bignum2(m, ssh1_challenge);
! 1168:
! 1169: debug3("%s sending reply", __FUNCTION__);
! 1170: mm_request_send(socket, MONITOR_ANS_RSACHALLENGE, m);
! 1171:
! 1172:
! 1173: monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1);
! 1174: return (0);
! 1175: }
! 1176:
! 1177: int
! 1178: mm_answer_rsa_response(int socket, Buffer *m)
! 1179: {
! 1180: Key *key = NULL;
! 1181: u_char *blob, *response;
! 1182: u_int blen, len;
! 1183: int success;
! 1184:
! 1185: debug3("%s entering", __FUNCTION__);
! 1186:
! 1187: if (!authctxt->valid)
! 1188: fatal("%s: authctxt not valid", __FUNCTION__);
! 1189: if (ssh1_challenge == NULL)
! 1190: fatal("%s: no ssh1_challenge", __FUNCTION__);
! 1191:
! 1192: blob = buffer_get_string(m, &blen);
! 1193: if (!monitor_allowed_key(blob, blen))
! 1194: fatal("%s: bad key, not previously allowed", __FUNCTION__);
! 1195: if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
! 1196: fatal("%s: key type mismatch: %d", __FUNCTION__, key_blobtype);
! 1197: if ((key = key_from_blob(blob, blen)) == NULL)
! 1198: fatal("%s: received bad key", __FUNCTION__);
! 1199: response = buffer_get_string(m, &len);
! 1200: if (len != 16)
! 1201: fatal("%s: received bad response to challenge", __FUNCTION__);
! 1202: success = auth_rsa_verify_response(key, ssh1_challenge, response);
! 1203:
! 1204: key_free(key);
! 1205: xfree(response);
! 1206:
! 1207: auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa";
! 1208:
! 1209: /* reset state */
! 1210: BN_clear_free(ssh1_challenge);
! 1211: ssh1_challenge = NULL;
! 1212: monitor_reset_key_state();
! 1213:
! 1214: buffer_clear(m);
! 1215: buffer_put_int(m, success);
! 1216: mm_request_send(socket, MONITOR_ANS_RSARESPONSE, m);
! 1217:
! 1218: return (success);
! 1219: }
! 1220:
! 1221: int
! 1222: mm_answer_term(int socket, Buffer *req)
! 1223: {
! 1224: extern struct monitor *monitor;
! 1225: int res, status;
! 1226:
! 1227: debug3("%s: tearing down sessions", __FUNCTION__);
! 1228:
! 1229: /* The child is terminating */
! 1230: session_destroy_all(&mm_session_close);
! 1231:
! 1232: if (waitpid(monitor->m_pid, &status, 0) == -1)
! 1233: exit(1);
! 1234:
! 1235: res = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
! 1236:
! 1237: /* Terminate process */
! 1238: exit (res);
! 1239: }
! 1240:
! 1241: void
! 1242: monitor_apply_keystate(struct monitor *monitor)
! 1243: {
! 1244: if (compat20) {
! 1245: set_newkeys(MODE_IN);
! 1246: set_newkeys(MODE_OUT);
! 1247: } else {
! 1248: u_char key[256];
! 1249: packet_set_protocol_flags(child_state.ssh1protoflags);
! 1250: packet_set_encryption_key(key, SSH_SESSION_KEY_LENGTH,
! 1251: child_state.ssh1cipher);
! 1252: }
! 1253:
! 1254: packet_set_keycontext(MODE_OUT, child_state.keyout);
! 1255: xfree(child_state.keyout);
! 1256: packet_set_keycontext(MODE_IN, child_state.keyin);
! 1257: xfree(child_state.keyin);
! 1258:
! 1259: if (!compat20) {
! 1260: packet_set_iv(MODE_OUT, child_state.ivout);
! 1261: xfree(child_state.ivout);
! 1262: packet_set_iv(MODE_IN, child_state.ivin);
! 1263: xfree(child_state.ivin);
! 1264: }
! 1265:
! 1266: memcpy(&incoming_stream, &child_state.incoming,
! 1267: sizeof(incoming_stream));
! 1268: memcpy(&outgoing_stream, &child_state.outgoing,
! 1269: sizeof(outgoing_stream));
! 1270:
! 1271: /* Update with new address */
! 1272: mm_init_compression(monitor->m_zlib);
! 1273:
! 1274: /* Network I/O buffers */
! 1275: /* XXX inefficient for large buffers, need: buffer_init_from_string */
! 1276: buffer_clear(&input);
! 1277: buffer_append(&input, child_state.input, child_state.ilen);
! 1278: memset(child_state.input, 0, child_state.ilen);
! 1279: xfree(child_state.input);
! 1280:
! 1281: buffer_clear(&output);
! 1282: buffer_append(&output, child_state.output, child_state.olen);
! 1283: memset(child_state.output, 0, child_state.olen);
! 1284: xfree(child_state.output);
! 1285: }
! 1286:
! 1287: Kex *
! 1288: mm_get_kex(Buffer *m)
! 1289: {
! 1290: Kex *kex;
! 1291: void *blob;
! 1292: u_int bloblen;
! 1293:
! 1294: kex = xmalloc(sizeof(*kex));
! 1295: memset(kex, 0, sizeof(*kex));
! 1296: kex->session_id = buffer_get_string(m, &kex->session_id_len);
! 1297: kex->we_need = buffer_get_int(m);
! 1298: kex->server = 1;
! 1299: kex->hostkey_type = buffer_get_int(m);
! 1300: kex->kex_type = buffer_get_int(m);
! 1301: blob = buffer_get_string(m, &bloblen);
! 1302: buffer_init(&kex->my);
! 1303: buffer_append(&kex->my, blob, bloblen);
! 1304: xfree(blob);
! 1305: blob = buffer_get_string(m, &bloblen);
! 1306: buffer_init(&kex->peer);
! 1307: buffer_append(&kex->peer, blob, bloblen);
! 1308: xfree(blob);
! 1309: kex->done = 1;
! 1310: kex->flags = buffer_get_int(m);
! 1311: kex->client_version_string = buffer_get_string(m, NULL);
! 1312: kex->server_version_string = buffer_get_string(m, NULL);
! 1313: kex->load_host_key=&get_hostkey_by_type;
! 1314: kex->host_key_index=&get_hostkey_index;
! 1315:
! 1316: return (kex);
! 1317: }
! 1318:
! 1319: /* This function requries careful sanity checking */
! 1320:
! 1321: void
! 1322: mm_get_keystate(struct monitor *monitor)
! 1323: {
! 1324: Buffer m;
! 1325: u_char *blob, *p;
! 1326: u_int bloblen, plen;
! 1327:
! 1328: debug3("%s: Waiting for new keys", __FUNCTION__);
! 1329:
! 1330: buffer_init(&m);
! 1331: mm_request_receive_expect(monitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m);
! 1332: if (!compat20) {
! 1333: child_state.ssh1protoflags = buffer_get_int(&m);
! 1334: child_state.ssh1cipher = buffer_get_int(&m);
! 1335: child_state.ivout = buffer_get_string(&m,
! 1336: &child_state.ivoutlen);
! 1337: child_state.ivin = buffer_get_string(&m, &child_state.ivinlen);
! 1338: goto skip;
! 1339: } else {
! 1340: /* Get the Kex for rekeying */
! 1341: *monitor->m_pkex = mm_get_kex(&m);
! 1342: }
! 1343:
! 1344: blob = buffer_get_string(&m, &bloblen);
! 1345: current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
! 1346: xfree(blob);
! 1347:
! 1348: debug3("%s: Waiting for second key", __FUNCTION__);
! 1349: blob = buffer_get_string(&m, &bloblen);
! 1350: current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
! 1351: xfree(blob);
! 1352:
! 1353: /* Now get sequence numbers for the packets */
! 1354: packet_set_seqnr(MODE_OUT, buffer_get_int(&m));
! 1355: packet_set_seqnr(MODE_IN, buffer_get_int(&m));
! 1356:
! 1357: skip:
! 1358: /* Get the key context */
! 1359: child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);
! 1360: child_state.keyin = buffer_get_string(&m, &child_state.keyinlen);
! 1361:
! 1362: debug3("%s: Getting compression state", __FUNCTION__);
! 1363: /* Get compression state */
! 1364: p = buffer_get_string(&m, &plen);
! 1365: if (plen != sizeof(child_state.outgoing))
! 1366: fatal("%s: bad request size", __FUNCTION__);
! 1367: memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));
! 1368: xfree(p);
! 1369:
! 1370: p = buffer_get_string(&m, &plen);
! 1371: if (plen != sizeof(child_state.incoming))
! 1372: fatal("%s: bad request size", __FUNCTION__);
! 1373: memcpy(&child_state.incoming, p, sizeof(child_state.incoming));
! 1374: xfree(p);
! 1375:
! 1376: /* Network I/O buffers */
! 1377: debug3("%s: Getting Network I/O buffers", __FUNCTION__);
! 1378: child_state.input = buffer_get_string(&m, &child_state.ilen);
! 1379: child_state.output = buffer_get_string(&m, &child_state.olen);
! 1380:
! 1381: buffer_free(&m);
! 1382: }
! 1383:
! 1384:
! 1385: /* Allocation functions for zlib */
! 1386: void *
! 1387: mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
! 1388: {
! 1389: void *address;
! 1390:
! 1391: address = mm_malloc(mm, size * ncount);
! 1392:
! 1393: return (address);
! 1394: }
! 1395:
! 1396: void
! 1397: mm_zfree(struct mm_master *mm, void *address)
! 1398: {
! 1399: mm_free(mm, address);
! 1400: }
! 1401:
! 1402: void
! 1403: mm_init_compression(struct mm_master *mm)
! 1404: {
! 1405: outgoing_stream.zalloc = (alloc_func)mm_zalloc;
! 1406: outgoing_stream.zfree = (free_func)mm_zfree;
! 1407: outgoing_stream.opaque = mm;
! 1408:
! 1409: incoming_stream.zalloc = (alloc_func)mm_zalloc;
! 1410: incoming_stream.zfree = (free_func)mm_zfree;
! 1411: incoming_stream.opaque = mm;
! 1412: }
! 1413:
! 1414: /* XXX */
! 1415:
! 1416: #define FD_CLOSEONEXEC(x) do { \
! 1417: if (fcntl(x, F_SETFD, 1) == -1) \
! 1418: fatal("fcntl(%d, F_SETFD)", x); \
! 1419: } while (0)
! 1420:
! 1421: void
! 1422: monitor_socketpair(int *pair)
! 1423: {
! 1424: if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
! 1425: fatal("%s: socketpair", __FUNCTION__);
! 1426: FD_CLOSEONEXEC(pair[0]);
! 1427: FD_CLOSEONEXEC(pair[1]);
! 1428: }
! 1429:
! 1430: #define MM_MEMSIZE 65536
! 1431:
! 1432: struct monitor *
! 1433: monitor_init(void)
! 1434: {
! 1435: struct monitor *mon;
! 1436: int pair[2];
! 1437:
! 1438: mon = xmalloc(sizeof(*mon));
! 1439:
! 1440: monitor_socketpair(pair);
! 1441:
! 1442: mon->m_recvfd = pair[0];
! 1443: mon->m_sendfd = pair[1];
! 1444:
! 1445: /* Used to share zlib space across processes */
! 1446: mon->m_zback = mm_create(NULL, MM_MEMSIZE);
! 1447: mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE);
! 1448:
! 1449: /* Compression needs to share state across borders */
! 1450: mm_init_compression(mon->m_zlib);
! 1451:
! 1452: return mon;
! 1453: }
! 1454:
! 1455: void
! 1456: monitor_reinit(struct monitor *mon)
! 1457: {
! 1458: int pair[2];
! 1459:
! 1460: monitor_socketpair(pair);
! 1461:
! 1462: mon->m_recvfd = pair[0];
! 1463: mon->m_sendfd = pair[1];
! 1464: }