1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  *
  21  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  22  */
  23 
  24 #include <fcntl.h>
  25 #include <sys/types.h>
  26 #include <sys/types.h>
  27 #include <sys/stat.h>
  28 #include <sys/socket.h>
  29 
  30 #include <pwd.h>
  31 
  32 #include "includes.h"
  33 #include "atomicio.h"
  34 #include "auth.h"
  35 #include "bufaux.h"
  36 #include "buffer.h"
  37 #include "cipher.h"
  38 #include "compat.h"
  39 #include "dispatch.h"
  40 #include "getput.h"
  41 #include "kex.h"
  42 #include "log.h"
  43 #include "mac.h"
  44 #include "packet.h"
  45 #include "uidswap.h"
  46 #include "ssh2.h"
  47 #include "sshlogin.h"
  48 #include "xmalloc.h"
  49 #include "altprivsep.h"
  50 #include "canohost.h"
  51 #include "engine.h"
  52 #include "servconf.h"
  53 
  54 #ifdef HAVE_BSM
  55 #include "bsmaudit.h"
  56 adt_session_data_t *ah = NULL;
  57 #endif /* HAVE_BSM */
  58 
  59 #ifdef GSSAPI
  60 #include "ssh-gss.h"
  61 extern Gssctxt *xxx_gssctxt;
  62 #endif /* GSSAPI */
  63 
  64 extern Kex *xxx_kex;
  65 extern u_char *session_id2;
  66 extern int session_id2_len;
  67 
  68 static Buffer to_monitor;
  69 static Buffer from_monitor;
  70 
  71 /*
  72  * Sun's Alternative Privilege Separation basics:
  73  *
  74  * Abstract
  75  * --------
  76  *
  77  * sshd(1M) fork()s and drops privs in the child while retaining privs
  78  * in the parent (a.k.a., the monitor).  The unprivileged sshd and the
  79  * monitor talk over a pipe using a simple protocol.
  80  *
  81  * The monitor protocol is all about having the monitor carry out the
  82  * only operations that require privileges OR access to privileged
  83  * resources.  These are: utmpx/wtmpx record keeping, auditing, and
  84  * SSHv2 re-keying.
  85  *
  86  * Re-Keying
  87  * ---------
  88  *
  89  * Re-keying is the only protocol version specific aspect of sshd in
  90  * which the monitor gets involved.
  91  *
  92  * The monitor processes all SSHv2 re-key protocol packets, but the
  93  * unprivileged sshd process does the transport layer crypto for those
  94  * packets.
  95  *
  96  * The monitor and its unprivileged sshd child process treat
  97  * SSH_MSG_NEWKEYS SSH2 messages specially: a) the monitor does not call
  98  * set_newkeys(), but b) the child asks the monitor for the set of
  99  * negotiated algorithms, key, IV and what not for the relevant
 100  * transport direction and then calls set_newkeys().
 101  *
 102  * Monitor Protocol
 103  * ----------------
 104  *
 105  * Monitor IPC message formats are similar to SSHv2 messages, minus
 106  * compression, encryption, padding and MACs:
 107  *
 108  *  - 4 octet message length
 109  *  - message data
 110  *     - 1 octet message type
 111  *     - message data
 112  *
 113  * In broad strokes:
 114  *
 115  *  - IPC: pipe, exit(2)/wait4(2)
 116  *
 117  *  - threads: the monitor and child are single-threaded
 118  *
 119  *  - monitor main loop: a variant of server_loop2(), for re-keying only
 120  *  - unpriv child main loop: server_loop2(), as usual
 121  *
 122  *  - protocol:
 123  *     - key exchange packets are always forwarded as is to the monitor
 124  *     - newkeys, record_login(), record_logout() are special packets
 125  *     using the packet type range reserved for local extensions
 126  *
 127  *  - the child drops privs and runs like a normal sshd, except that it
 128  *  sets dispatch handlers for key exchange packets that forward the
 129  *  packets to the monitor
 130  *
 131  * Event loops:
 132  *
 133  *  - all monitor protocols are synchronous: because the SSHv2 rekey
 134  *  protocols are synchronous and because the other monitor operations
 135  *  are synchronous (or have no replies),
 136  *
 137  *  - server_loop2() is modified to check the monitor pipe for rekey
 138  *  packets to forward to the client
 139  *
 140  *  - and dispatch handlers are set, upon receipt of KEXINIT (and reset
 141  *  when NEWKEYS is sent out) to forward incoming rekey packets to the
 142  *  monitor.
 143  *
 144  *  - the monitor runs an event loop not unlike server_loop2() and runs
 145  *  key exchanges almost exactly as a pre-altprivsep sshd would
 146  *
 147  *  - unpriv sshd exit -> monitor cleanup (including audit logout) and exit
 148  *
 149  *  - fatal() in monitor -> forcibly shutdown() socket and kill/wait for
 150  *  child (so that the audit event for the logout better reflects
 151  *  reality -- i.e., logged out means logged out, but for bg jobs)
 152  *
 153  * Message formats:
 154  *
 155  *  - key exchange packets/replies forwarded "as is"
 156  *
 157  *  - all other monitor requests are sent as SSH2_PRIV_MSG_ALTPRIVSEP and have a
 158  *  sub-type identifier (one octet)
 159  *  - private request sub-types include:
 160  *     - get new shared secret from last re-key
 161  *     - record login  (utmpx/wtmpx), request data contains three arguments:
 162  *     pid, ttyname, program name
 163  *     - record logout (utmpx/wtmpx), request data contains one argument: pid
 164  *
 165  * Reply sub-types include:
 166  *
 167  *  - NOP (for record_login/logout)
 168  *  - new shared secret from last re-key
 169  */
 170 
 171 static int aps_started = 0;
 172 static int is_monitor = 0;
 173 
 174 static pid_t monitor_pid, child_pid;
 175 static int pipe_fds[2];
 176 static int pipe_fd = -1;
 177 static Buffer input_pipe, output_pipe; /* for pipe I/O */
 178 
 179 static Authctxt *xxx_authctxt;
 180 
 181 /* Monitor functions */
 182 extern void aps_monitor_loop(Authctxt *authctxt, pid_t child_pid);
 183 static void aps_record_login(void);
 184 static void aps_record_logout(void);
 185 static void aps_start_rekex(void);
 186 Authctxt *aps_read_auth_context(void);
 187 
 188 /* main functions for handling the monitor */
 189 static pid_t    altprivsep_start_monitor(Authctxt **authctxt);
 190 static void     altprivsep_do_monitor(Authctxt *authctxt, pid_t child_pid);
 191 static int      altprivsep_started(void);
 192 static int      altprivsep_is_monitor(void);
 193 
 194 /* calls _to_ monitor from unprivileged process */
 195 static void     altprivsep_get_newkeys(enum kex_modes mode);
 196 
 197 /* monitor-side fatal_cleanup callbacks */
 198 static void     altprivsep_shutdown_sock(void *arg);
 199 
 200 /* Altprivsep packet utilities for communication with the monitor */
 201 static void     altprivsep_packet_start(u_char);
 202 static int      altprivsep_packet_send(void);
 203 static int      altprivsep_fwd_packet(u_char type);
 204 
 205 static int      altprivsep_packet_read(void);
 206 static void     altprivsep_packet_read_expect(int type);
 207 
 208 static void     altprivsep_packet_put_char(int ch);
 209 static void     altprivsep_packet_put_int(u_int value);
 210 static void     altprivsep_packet_put_cstring(const char *str);
 211 static void     altprivsep_packet_put_raw(const void *buf, u_int len);
 212 
 213 static u_int     altprivsep_packet_get_char(void);
 214 static void     *altprivsep_packet_get_raw(u_int *length_ptr);
 215 static void     *altprivsep_packet_get_string(u_int *length_ptr);
 216 
 217 Kex             *prepare_for_ssh2_kex(void);
 218 
 219 /*
 220  * Start monitor from privileged sshd process.
 221  *
 222  * Return values are like fork(2); the parent is the monitor.  The caller should
 223  * fatal() on error.
 224  *
 225  * Note that the monitor waits until the still privileged child finishes the
 226  * authentication. The child drops its privileges after the authentication.
 227  */
 228 static pid_t
 229 altprivsep_start_monitor(Authctxt **authctxt)
 230 {
 231         pid_t pid;
 232         int junk;
 233 
 234         if (aps_started)
 235                 fatal("Monitor startup failed: missing state");
 236 
 237         buffer_init(&output_pipe);
 238         buffer_init(&input_pipe);
 239 
 240         if (pipe(pipe_fds) != 0) {
 241                 error("Monitor startup failure: could not create pipes: %s",
 242                         strerror(errno));
 243                 return (-1);
 244         }
 245 
 246         (void) fcntl(pipe_fds[0], F_SETFD, FD_CLOEXEC);
 247         (void) fcntl(pipe_fds[1], F_SETFD, FD_CLOEXEC);
 248 
 249         monitor_pid = getpid();
 250 
 251         if ((pid = fork()) > 0) {
 252                 /*
 253                  * From now on, all debug messages from monitor will have prefix
 254                  * "monitor "
 255                  */
 256                 set_log_txt_prefix("monitor ");
 257                 (void) prepare_for_ssh2_kex();
 258                 packet_set_server();
 259                 /* parent */
 260                 child_pid = pid;
 261 
 262                 debug2("Monitor pid %ld, unprivileged child pid %ld",
 263                         monitor_pid, child_pid);
 264 
 265                 (void) close(pipe_fds[1]);
 266                 pipe_fd = pipe_fds[0];
 267 
 268                 /*
 269                  * Signal readiness of the monitor and then read the
 270                  * authentication context from the child.
 271                  */
 272                 (void) write(pipe_fd, &pid, sizeof (pid));
 273                 packet_set_monitor(pipe_fd);
 274                 xxx_authctxt = *authctxt = aps_read_auth_context();
 275 
 276                 if (fcntl(pipe_fd, F_SETFL, O_NONBLOCK) < 0)
 277                         error("fcntl O_NONBLOCK: %.100s", strerror(errno));
 278 
 279                 aps_started = 1;
 280                 is_monitor = 1;
 281 
 282                 debug2("Monitor started");
 283 
 284                 return (pid);
 285         }
 286 
 287         if (pid < 0) {
 288                 debug2("Monitor startup failure: could not fork unprivileged"
 289                         " process:  %s", strerror(errno));
 290                 return (pid);
 291         }
 292 
 293         /* this is the child that will later drop privileges */
 294 
 295         /* note that Solaris has bi-directional pipes so one pipe is enough */
 296         (void) close(pipe_fds[0]);
 297         pipe_fd = pipe_fds[1];
 298 
 299         /* wait for monitor to be ready */
 300         debug2("Waiting for monitor");
 301         (void) read(pipe_fd, &junk, sizeof (junk));
 302         debug2("Monitor signalled readiness");
 303 
 304         buffer_init(&to_monitor);
 305         buffer_init(&from_monitor);
 306 
 307         /* AltPrivSep interfaces are set up */
 308         aps_started = 1;
 309         return (pid);
 310 }
 311 
 312 int
 313 altprivsep_get_pipe_fd(void)
 314 {
 315         return (pipe_fd);
 316 }
 317 
 318 /*
 319  * This function is used in the unprivileged child for all packets in the range
 320  * between SSH2_MSG_KEXINIT and SSH2_MSG_TRANSPORT_MAX.
 321  */
 322 void
 323 altprivsep_rekey(int type, u_int32_t seq, void *ctxt)
 324 {
 325         Kex *kex = (Kex *)ctxt;
 326 
 327         if (kex == NULL)
 328                 fatal("Missing key exchange context in unprivileged process");
 329 
 330         if (type != SSH2_MSG_NEWKEYS) {
 331                 debug2("Forwarding re-key packet (%d) to monitor", type);
 332                 if (!altprivsep_fwd_packet(type))
 333                         fatal("altprivsep_rekey: Monitor not responding");
 334         }
 335 
 336         /* tell server_loop2() that we're re-keying */
 337         kex->done = 0;
 338 
 339         /* NEWKEYS is special: get the new keys for client->server direction */
 340         if (type == SSH2_MSG_NEWKEYS) {
 341                 debug2("received SSH2_MSG_NEWKEYS packet - "
 342                     "getting new inbound keys from the monitor");
 343                 altprivsep_get_newkeys(MODE_IN);
 344                 kex->done = 1;
 345         }
 346 }
 347 
 348 void
 349 altprivsep_process_input(fd_set *rset)
 350 {
 351         void    *data;
 352         int      type;
 353         u_int    dlen;
 354 
 355         if (pipe_fd == -1)
 356                 return;
 357 
 358         if (!FD_ISSET(pipe_fd, rset))
 359                 return;
 360 
 361         debug2("reading from pipe to monitor (%d)", pipe_fd);
 362         if ((type = altprivsep_packet_read()) == -1)
 363                 fatal("altprivsep_process_input: Monitor not responding");
 364 
 365         if (!compat20)
 366                 return; /* shouldn't happen! but be safe */
 367 
 368         if (type == 0)
 369                 return; /* EOF -- nothing to do here */
 370 
 371         if (type >= SSH2_MSG_MAX)
 372                 fatal("Received garbage from monitor");
 373 
 374         debug2("Read packet type %d from pipe to monitor", (u_int)type);
 375 
 376         if (type == SSH2_PRIV_MSG_ALTPRIVSEP)
 377                 return; /* shouldn't happen! */
 378 
 379         /* NEWKEYS is special: get the new keys for server->client direction */
 380         if (type == SSH2_MSG_NEWKEYS) {
 381                 debug2("forwarding SSH2_MSG_NEWKEYS packet we got from monitor to "
 382                     "the client");
 383                 packet_start(SSH2_MSG_NEWKEYS);
 384                 packet_send();
 385                 debug2("getting new outbound keys from the monitor");
 386                 altprivsep_get_newkeys(MODE_OUT);
 387                 return;
 388         }
 389 
 390         data = altprivsep_packet_get_raw(&dlen);
 391 
 392         packet_start((u_char)type);
 393 
 394         if (data != NULL && dlen > 0)
 395                 packet_put_raw(data, dlen);
 396 
 397         packet_send();
 398 }
 399 
 400 static void
 401 altprivsep_do_monitor(Authctxt *authctxt, pid_t child_pid)
 402 {
 403         aps_monitor_loop(authctxt, child_pid);
 404 }
 405 
 406 static int
 407 altprivsep_started(void)
 408 {
 409         return (aps_started);
 410 }
 411 
 412 static int
 413 altprivsep_is_monitor(void)
 414 {
 415         return (is_monitor);
 416 }
 417 
 418 /*
 419  * A fatal cleanup function to forcibly shutdown the connection socket
 420  */
 421 static void
 422 altprivsep_shutdown_sock(void *arg)
 423 {
 424         int sock;
 425 
 426         if (arg == NULL)
 427                 return;
 428 
 429         sock = *(int *)arg;
 430 
 431         (void) shutdown(sock, SHUT_RDWR);
 432 }
 433 
 434 /* Calls _to_ monitor from unprivileged process */
 435 static int
 436 altprivsep_fwd_packet(u_char type)
 437 {
 438         u_int len;
 439         void  *data;
 440 
 441         altprivsep_packet_start(type);
 442         data = packet_get_raw(&len);
 443         altprivsep_packet_put_raw(data, len);
 444 
 445         /* packet_send()s any replies from the monitor to the client */
 446         return (altprivsep_packet_send());
 447 }
 448 
 449 extern Newkeys *current_keys[MODE_MAX];
 450 
 451 /* To be called from packet.c:set_newkeys() before referencing current_keys */
 452 static void
 453 altprivsep_get_newkeys(enum kex_modes mode)
 454 {
 455         Newkeys *newkeys;
 456         Comp    *comp;
 457         Enc     *enc;
 458         Mac     *mac;
 459         u_int    len;
 460 
 461         if (!altprivsep_started())
 462                 return;
 463 
 464         if (altprivsep_is_monitor())
 465                 return; /* shouldn't happen */
 466 
 467         /* request new keys */
 468         altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
 469         altprivsep_packet_put_char(APS_MSG_NEWKEYS_REQ);
 470         altprivsep_packet_put_int((u_int)mode);
 471         altprivsep_packet_send();
 472         altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP);
 473         if (altprivsep_packet_get_char() != APS_MSG_NEWKEYS_REP)
 474                 fatal("Received garbage from monitor during re-keying");
 475 
 476         newkeys = xmalloc(sizeof (*newkeys));
 477         memset(newkeys, 0, sizeof (*newkeys));
 478 
 479         enc = &newkeys->enc;
 480         mac = &newkeys->mac;
 481         comp = &newkeys->comp;
 482 
 483         /* Cipher name, key, IV */
 484         enc->name = altprivsep_packet_get_string(NULL);
 485         if ((enc->cipher = cipher_by_name(enc->name)) == NULL)
 486                 fatal("Monitor negotiated an unknown cipher during re-key");
 487 
 488         enc->key = altprivsep_packet_get_string(&enc->key_len);
 489         enc->iv = altprivsep_packet_get_string(&enc->block_size);
 490 
 491         /* MAC name */
 492         mac->name = altprivsep_packet_get_string(NULL);
 493         if (mac_setup(mac, mac->name) < 0)
 494                 fatal("Monitor negotiated an unknown MAC algorithm "
 495                         "during re-key");
 496 
 497         mac->key = altprivsep_packet_get_string(&len);
 498         if (len > mac->key_len)
 499                 fatal("%s: bad mac key length: %d > %d", __func__, len,
 500                         mac->key_len);
 501 
 502         /* Compression algorithm name */
 503         comp->name = altprivsep_packet_get_string(NULL);
 504         if (strcmp(comp->name, "zlib") != 0 && strcmp(comp->name, "none") != 0)
 505                 fatal("Monitor negotiated an unknown compression "
 506                         "algorithm during re-key");
 507 
 508         comp->type = 0;
 509         comp->enabled = 0; /* forces compression re-init, as per-spec */
 510         if (strcmp(comp->name, "zlib") == 0)
 511                 comp->type = 1;
 512 
 513         /*
 514          * Now install new keys
 515          *
 516          * For now abuse kex.c/packet.c non-interfaces.  Someday, when
 517          * the many internal interfaces are parametrized, made reentrant
 518          * and thread-safe, made more consistent, and when necessary-but-
 519          * currently-missing interfaces are added then this bit of
 520          * ugliness can be revisited.
 521          *
 522          * The ugliness is in the set_newkeys(), its name and the lack
 523          * of a (Newkeys *) parameter, which forces us to pass the
 524          * newkeys through current_keys[mode].  But this saves us some
 525          * lines of code for now, though not comments.
 526          *
 527          * Also, we've abused, in the code above, knowledge of what
 528          * set_newkeys() expects the current_keys[mode] to contain.
 529          */
 530         current_keys[mode] = newkeys;
 531         set_newkeys(mode);
 532 
 533 }
 534 
 535 void
 536 altprivsep_record_login(pid_t pid, const char *ttyname)
 537 {
 538         altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
 539         altprivsep_packet_put_char(APS_MSG_RECORD_LOGIN);
 540         altprivsep_packet_put_int(pid);
 541         altprivsep_packet_put_cstring(ttyname);
 542         altprivsep_packet_send();
 543         altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP);
 544 }
 545 
 546 void
 547 altprivsep_record_logout(pid_t pid)
 548 {
 549         altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
 550         altprivsep_packet_put_char(APS_MSG_RECORD_LOGOUT);
 551         altprivsep_packet_put_int(pid);
 552         altprivsep_packet_send();
 553         altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP);
 554 }
 555 
 556 void
 557 altprivsep_start_rekex(void)
 558 {
 559         altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
 560         altprivsep_packet_put_char(APS_MSG_START_REKEX);
 561         altprivsep_packet_send();
 562         altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP);
 563 }
 564 
 565 /*
 566  * The monitor needs some information that its child learns during the
 567  * authentication process. Since the child was forked before the key exchange
 568  * and authentication started it must send some context to the monitor after the
 569  * authentication is finished. Less obvious part - monitor needs the session ID
 570  * since it is used in the key generation process after the key (re-)exchange is
 571  * finished.
 572  */
 573 void
 574 altprivsep_send_auth_context(Authctxt *authctxt)
 575 {
 576         debug("sending auth context to the monitor");
 577         altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
 578         altprivsep_packet_put_char(APS_MSG_AUTH_CONTEXT);
 579         altprivsep_packet_put_int(authctxt->pw->pw_uid);
 580         altprivsep_packet_put_int(authctxt->pw->pw_gid);
 581         altprivsep_packet_put_cstring(authctxt->pw->pw_name);
 582         altprivsep_packet_put_raw(session_id2, session_id2_len);
 583         debug("will send %d bytes of auth context to the monitor",
 584             buffer_len(&to_monitor));
 585         altprivsep_packet_send();
 586         altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP);
 587 }
 588 
 589 static void aps_send_newkeys(void);
 590 
 591 /* Monitor side dispatch handler for SSH2_PRIV_MSG_ALTPRIVSEP */
 592 /* ARGSUSED */
 593 void
 594 aps_input_altpriv_msg(int type, u_int32_t seq, void *ctxt)
 595 {
 596         u_char req_type;
 597 
 598         req_type = packet_get_char();
 599 
 600         switch (req_type) {
 601         case APS_MSG_NEWKEYS_REQ:
 602                 aps_send_newkeys();
 603                 break;
 604         case APS_MSG_RECORD_LOGIN:
 605                 aps_record_login();
 606                 break;
 607         case APS_MSG_RECORD_LOGOUT:
 608                 aps_record_logout();
 609                 break;
 610         case APS_MSG_START_REKEX:
 611                 aps_start_rekex();
 612                 break;
 613         default:
 614                 break;
 615         }
 616 }
 617 
 618 /* Monitor-side handlers for APS_MSG_* */
 619 static
 620 void
 621 aps_send_newkeys(void)
 622 {
 623         Newkeys *newkeys;
 624         Enc *enc;
 625         Mac *mac;
 626         Comp *comp;
 627         enum kex_modes mode;
 628 
 629         /* get direction for which newkeys are wanted */
 630         mode = (enum kex_modes) packet_get_int();
 631         packet_check_eom();
 632 
 633         /* get those newkeys */
 634         newkeys = kex_get_newkeys(mode);
 635         enc = &newkeys->enc;
 636         mac = &newkeys->mac;
 637         comp = &newkeys->comp;
 638 
 639         /*
 640          * Negotiated algorithms, client->server and server->client, for
 641          * cipher, mac and compression.
 642          */
 643         packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
 644         packet_put_char(APS_MSG_NEWKEYS_REP);
 645         packet_put_cstring(enc->name);
 646         packet_put_string(enc->key, enc->key_len);
 647         packet_put_string(enc->iv, enc->block_size);
 648         packet_put_cstring(mac->name);
 649         packet_put_string(mac->key, mac->key_len);
 650         packet_put_cstring(comp->name);
 651 
 652         packet_send();
 653         free_keys(newkeys);
 654 }
 655 
 656 struct _aps_login_rec {
 657         pid_t                   lr_pid;
 658         char                    *lr_tty;
 659         struct _aps_login_rec   *next;
 660 };
 661 
 662 typedef struct _aps_login_rec aps_login_rec;
 663 
 664 static aps_login_rec *aps_login_list = NULL;
 665 
 666 static
 667 void
 668 aps_record_login(void)
 669 {
 670         aps_login_rec   *new_rec;
 671         struct stat      sbuf;
 672         size_t           proc_path_len;
 673         char            *proc_path;
 674 
 675         new_rec = xmalloc(sizeof (aps_login_rec));
 676         memset(new_rec, 0, sizeof (aps_login_rec));
 677 
 678         new_rec->lr_pid = packet_get_int();
 679         new_rec->lr_tty = packet_get_string(NULL);
 680 
 681         proc_path_len = snprintf(NULL, 0, "/proc/%d", new_rec->lr_pid);
 682         proc_path = xmalloc(proc_path_len + 1);
 683         (void) snprintf(proc_path, proc_path_len + 1, "/proc/%d",
 684                         new_rec->lr_pid);
 685 
 686         if (stat(proc_path, &sbuf) ||
 687             sbuf.st_uid != xxx_authctxt->pw->pw_uid ||
 688             stat(new_rec->lr_tty, &sbuf) < 0 ||
 689             sbuf.st_uid != xxx_authctxt->pw->pw_uid) {
 690                 debug2("Spurious record_login request from unprivileged sshd");
 691                 xfree(proc_path);
 692                 xfree(new_rec->lr_tty);
 693                 xfree(new_rec);
 694                 return;
 695         }
 696 
 697         /* Insert new record on list */
 698         new_rec->next = aps_login_list;
 699         aps_login_list = new_rec;
 700 
 701         record_login(new_rec->lr_pid, new_rec->lr_tty, NULL,
 702                 xxx_authctxt->user);
 703 
 704         packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
 705         packet_send();
 706 
 707         xfree(proc_path);
 708 }
 709 
 710 static
 711 void
 712 aps_record_logout(void)
 713 {
 714         aps_login_rec   **p, *q;
 715         pid_t            pid;
 716 
 717         pid = packet_get_int();
 718         packet_check_eom();
 719 
 720         for (p = &aps_login_list; *p != NULL; p = &q->next) {
 721                 q = *p;
 722                 if (q->lr_pid == pid) {
 723                         record_logout(q->lr_pid, q->lr_tty, NULL,
 724                                 xxx_authctxt->user);
 725 
 726                         /* dequeue */
 727                         *p = q->next;
 728                         xfree(q->lr_tty);
 729                         xfree(q);
 730                         break;
 731                 }
 732         }
 733 
 734         packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
 735         packet_send();
 736 }
 737 
 738 static
 739 void
 740 aps_start_rekex(void)
 741 {
 742         /*
 743          * Send confirmation. We could implement it without that but it doesn't
 744          * bring any harm to do that and we are consistent with other subtypes
 745          * of our private SSH2_PRIV_MSG_ALTPRIVSEP message type.
 746          */
 747         packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
 748         packet_send();
 749 
 750         /*
 751          * KEX_INIT message could be the one that reached the limit. In that
 752          * case, it was already forwarded to us from the unnprivileged child,
 753          * and maybe even acted upon. Obviously we must not send another
 754          * KEX_INIT message.
 755          */
 756         if (!(xxx_kex->flags & KEX_INIT_SENT))
 757                 kex_send_kexinit(xxx_kex);
 758         else
 759                 debug2("rekeying already in progress");
 760 }
 761 
 762 /*
 763  * This is the monitor side of altprivsep_send_auth_context().
 764  */
 765 Authctxt *
 766 aps_read_auth_context(void)
 767 {
 768         unsigned char *tmp;
 769         Authctxt *authctxt;
 770         
 771         /*
 772          * After the successful authentication we get the context. Getting
 773          * end-of-file means that authentication failed and we can exit as well.
 774          */
 775         debug("reading the context from the child");
 776         packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP);
 777         debug3("got SSH2_PRIV_MSG_ALTPRIVSEP");
 778         if (packet_get_char() != APS_MSG_AUTH_CONTEXT) {
 779                 fatal("APS_MSG_AUTH_CONTEXT message subtype expected.");
 780         }
 781 
 782         authctxt = xcalloc(1, sizeof(Authctxt));
 783         authctxt->pw = xcalloc(1, sizeof(struct passwd));
 784 
 785         /* uid_t and gid_t are integers (UNIX spec) */
 786         authctxt->pw->pw_uid = packet_get_int();
 787         authctxt->pw->pw_gid = packet_get_int();
 788         authctxt->pw->pw_name = packet_get_string(NULL);
 789         authctxt->user = xstrdup(authctxt->pw->pw_name);
 790         debug3("uid/gid/username %d/%d/%s", authctxt->pw->pw_uid,
 791             authctxt->pw->pw_gid, authctxt->user);
 792         session_id2 = (unsigned char *)packet_get_raw((unsigned int*)&session_id2_len);
 793 
 794         /* we don't have this for SSH1. In that case, session_id2_len is 0. */
 795         if (session_id2_len > 0) {
 796                 tmp = (unsigned char *)xmalloc(session_id2_len);
 797                 memcpy(tmp, session_id2, session_id2_len);
 798                 session_id2 = tmp;
 799                 debug3("read session ID (%d B)", session_id2_len);
 800                 xxx_kex->session_id = tmp;
 801                 xxx_kex->session_id_len = session_id2_len;
 802         }
 803         debug("finished reading the context");
 804 
 805         /* send confirmation */
 806         packet_start(SSH2_PRIV_MSG_ALTPRIVSEP);
 807         packet_send();
 808 
 809         return (authctxt);
 810 }
 811 
 812 
 813 /* Utilities for communication with the monitor */
 814 static void
 815 altprivsep_packet_start(u_char type)
 816 {
 817         buffer_clear(&to_monitor);
 818         buffer_put_char(&to_monitor, type);
 819 }
 820 
 821 static void
 822 altprivsep_packet_put_char(int ch)
 823 {
 824         buffer_put_char(&to_monitor, ch);
 825 }
 826 
 827 static void
 828 altprivsep_packet_put_int(u_int value)
 829 {
 830         buffer_put_int(&to_monitor, value);
 831 }
 832 
 833 static void
 834 altprivsep_packet_put_cstring(const char *str)
 835 {
 836         buffer_put_cstring(&to_monitor, str);
 837 }
 838 
 839 static void
 840 altprivsep_packet_put_raw(const void *buf, u_int len)
 841 {
 842         buffer_append(&to_monitor, buf, len);
 843 }
 844 
 845 /*
 846  * Send a monitor packet to the monitor.  This function is blocking.
 847  *
 848  * Returns -1 if the monitor pipe has been closed earlier, fatal()s if
 849  * there's any other problems.
 850  */
 851 static int
 852 altprivsep_packet_send(void)
 853 {
 854         ssize_t len;
 855         u_int32_t plen; /* packet length */
 856         u_char  plen_buf[sizeof (plen)];
 857         u_char padlen;  /* padding length */
 858         fd_set *setp;
 859         int err;
 860 
 861         if (pipe_fd == -1)
 862                 return (-1);
 863 
 864         if ((plen = buffer_len(&to_monitor)) == 0)
 865                 return (0);
 866 
 867         /*
 868          * We talk the SSHv2 binary packet protocol to the monitor,
 869          * using the none cipher, mac and compression algorithms.
 870          *
 871          * But, interestingly, the none cipher has a block size of 8
 872          * bytes, thus we must pad the packet.
 873          *
 874          * Also, encryption includes the packet length, so the padding
 875          * must account for that field.  I.e., (sizeof (packet length) +
 876          * sizeof (padding length) + packet length + padding length) %
 877          * block_size must == 0.
 878          *
 879          * Also, there must be at least four (4) bytes of padding.
 880          */
 881         padlen = (8 - ((plen + sizeof (plen) + sizeof (padlen)) % 8)) % 8;
 882         if (padlen < 4)
 883                 padlen += 8;
 884 
 885         /* packet length counts padding and padding length field */
 886         plen += padlen + sizeof (padlen);
 887 
 888         PUT_32BIT(plen_buf, plen);
 889 
 890         setp = xmalloc(howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask));
 891         memset(setp, 0, howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask));
 892         FD_SET(pipe_fd, setp);
 893 
 894         while (select(pipe_fd + 1, NULL, setp, NULL, NULL) == -1) {
 895                 if (errno == EAGAIN || errno == EINTR)
 896                         continue;
 897                 else
 898                         goto pipe_gone;
 899         }
 900 
 901         xfree(setp);
 902 
 903         /* packet length field */
 904         len = atomicio(write, pipe_fd, plen_buf, sizeof (plen));
 905 
 906         if (len != sizeof (plen))
 907                 goto pipe_gone;
 908 
 909         /* padding length field */
 910         len = atomicio(write, pipe_fd, &padlen, sizeof (padlen));
 911 
 912         if (len != sizeof (padlen))
 913                 goto pipe_gone;
 914 
 915         len = atomicio(write, pipe_fd, buffer_ptr(&to_monitor), plen - 1);
 916 
 917         if (len != (plen - 1))
 918                 goto pipe_gone;
 919 
 920         buffer_clear(&to_monitor);
 921 
 922         return (1);
 923 
 924 pipe_gone:
 925         
 926         err = errno;
 927 
 928         (void) close(pipe_fd);
 929 
 930         pipe_fd = -1;
 931 
 932         fatal("altprvsep_packet_send: Monitor not responding: %.100s",
 933             strerror(err));
 934 
 935         /* NOTREACHED */
 936         return (0);
 937 }
 938 
 939 /*
 940  * Read a monitor packet from the monitor.  This function is blocking.
 941  */
 942 static int
 943 altprivsep_packet_read(void)
 944 {
 945         ssize_t len = -1;
 946         u_int32_t plen;
 947         u_char plen_buf[sizeof (plen)];
 948         u_char padlen;
 949         fd_set *setp;
 950         int err;
 951 
 952         if (pipe_fd == -1)
 953                 return (-1);
 954 
 955         setp = xmalloc(howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask));
 956         memset(setp, 0, howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask));
 957         FD_SET(pipe_fd, setp);
 958 
 959         while (select(pipe_fd + 1, setp, NULL, NULL, NULL) == -1) {
 960                 if (errno == EAGAIN || errno == EINTR)
 961                         continue;
 962                 else
 963                         goto pipe_gone;
 964         }
 965 
 966         xfree(setp);
 967 
 968         /* packet length field */
 969         len = atomicio(read, pipe_fd, plen_buf, sizeof (plen));
 970 
 971         plen = GET_32BIT(plen_buf);
 972 
 973         if (len != sizeof (plen))
 974                 goto pipe_gone;
 975 
 976         /* padding length field */
 977         len = atomicio(read, pipe_fd, &padlen, sizeof (padlen));
 978 
 979         if (len != sizeof (padlen))
 980                 goto pipe_gone;
 981 
 982         plen -= sizeof (padlen);
 983 
 984         buffer_clear(&from_monitor);
 985         buffer_append_space(&from_monitor, plen);
 986 
 987         /* packet data + padding */
 988         len = atomicio(read, pipe_fd, buffer_ptr(&from_monitor), plen);
 989 
 990         if (len != plen)
 991                 goto pipe_gone;
 992 
 993         /* remove padding */
 994         if (padlen > 0)
 995                 buffer_consume_end(&from_monitor, padlen);
 996 
 997         /* packet type */
 998         return (buffer_get_char(&from_monitor));
 999 
1000 pipe_gone:
1001 
1002         err = errno;
1003 
1004         (void) close(pipe_fd);
1005 
1006         pipe_fd = -1;
1007 
1008         if (len < 0)
1009                 fatal("altpriv_packet_read: Monitor not responding %.100s",
1010                     strerror(err));
1011 
1012         debug2("Monitor pipe closed by monitor");
1013         return (0);
1014 }
1015 
1016 static void
1017 altprivsep_packet_read_expect(int expected)
1018 {
1019         int type;
1020 
1021         type = altprivsep_packet_read();
1022 
1023         if (type <= 0)
1024                 fatal("altprivsep_packet_read_expect: Monitor not responding");
1025 
1026         if (type != expected)
1027                 fatal("Protocol error in privilege separation; expected "
1028                         "packet type %d, got %d", expected, type);
1029 }
1030 
1031 static u_int
1032 altprivsep_packet_get_char(void)
1033 {
1034         return (buffer_get_char(&from_monitor));
1035 }
1036 void
1037 *altprivsep_packet_get_raw(u_int *length_ptr)
1038 {
1039         if (length_ptr != NULL)
1040                 *length_ptr = buffer_len(&from_monitor);
1041 
1042         return (buffer_ptr(&from_monitor));
1043 }
1044 void
1045 *altprivsep_packet_get_string(u_int *length_ptr)
1046 {
1047         return (buffer_get_string(&from_monitor, length_ptr));
1048 }
1049 
1050 /*
1051  * Start and execute the code for the monitor which never returns from this
1052  * function. The child will return and continue in the caller.
1053  */
1054 void
1055 altprivsep_start_and_do_monitor(int use_engine, int inetd, int newsock,
1056         int statup_pipe)
1057 {
1058         pid_t aps_child;
1059         Authctxt *authctxt;
1060 
1061         /*
1062          * The monitor will packet_close() in packet_set_monitor() called from
1063          * altprivsep_start_monitor() below to clean up the socket stuff before
1064          * it switches to pipes for communication to the child. The socket fd is
1065          * closed there so we must dup it here - monitor needs that socket to
1066          * shutdown the connection in case of any problem; see comments below.
1067          * Note that current newsock was assigned to connection_(in|out) which
1068          * are the variables used in packet_close() to close the communication
1069          * socket.
1070          */
1071         newsock = dup(newsock);
1072 
1073         if ((aps_child = altprivsep_start_monitor(&authctxt)) == -1)
1074                 fatal("Monitor could not be started.");
1075 
1076         if (aps_child > 0) {
1077                 /* ALTPRIVSEP Monitor */
1078 
1079                 /*
1080                  * The ALTPRIVSEP monitor here does:
1081                  *
1082                  *  - record keeping and auditing
1083                  *  - PAM cleanup
1084                  */
1085 
1086                 /* this is for MaxStartups and the child takes care of that */
1087                 (void) close(statup_pipe);
1088                 (void) pkcs11_engine_load(use_engine);
1089 
1090                 /*
1091                  * If the monitor fatal()s it will audit/record a logout, so
1092                  * we'd better do something to really mean it: shutdown the
1093                  * socket but leave the child alone -- it's been disconnected
1094                  * and we hope it exits, but killing any pid from a privileged
1095                  * monitor could be dangerous.
1096                  *
1097                  * NOTE: Order matters -- these fatal cleanups must come before
1098                  * the audit logout fatal cleanup as these functions are called
1099                  * in LIFO.
1100                  */
1101                 fatal_add_cleanup((void (*)(void *))altprivsep_shutdown_sock,
1102                         (void *)&newsock);
1103 
1104                 if (compat20) {
1105                         debug3("Recording SSHv2 session login in wtmpx");
1106                         /*
1107                          * record_login() relies on connection_in to be the
1108                          * socket to get the peer address. The problem is that
1109                          * connection_in had to be set to the pipe descriptor in
1110                          * altprivsep_start_monitor(). It's not nice but the
1111                          * easiest way to get the peer's address is to
1112                          * temporarily set connection_in to the socket's file
1113                          * descriptor.
1114                          */
1115                         packet_set_fds(inetd == 1 ? -1 : newsock, 0);
1116                         record_login(getpid(), NULL, "sshd", authctxt->user);
1117                         packet_set_fds(0, 1);
1118                 }
1119 
1120 #ifdef HAVE_BSM
1121                 /* Initialize the group list, audit sometimes needs it. */
1122                 if (initgroups(authctxt->pw->pw_name,
1123                     authctxt->pw->pw_gid) < 0) {
1124                         perror("initgroups");
1125                         exit (1);
1126                 }
1127 
1128                 /*
1129                  * The monitor process fork()ed before the authentication
1130                  * process started so at this point we have an unaudited
1131                  * context.  Thus we need to obtain the audit session data
1132                  * from the authentication process (aps_child) which will
1133                  * have the correct audit context for the user logging in.
1134                  * To do so we pass along the process-ID of the aps_child
1135                  * process so that it is referenced for this audit session
1136                  * rather than referencing the monitor's unaudited context.
1137                  */
1138                 audit_sshd_login(&ah, aps_child);
1139 
1140                 fatal_add_cleanup((void (*)(void *))audit_sshd_logout,
1141                     (void *)&ah);
1142 #endif /* HAVE_BSM */
1143 
1144 #ifdef GSSAPI
1145                 fatal_add_cleanup((void (*)(void *))ssh_gssapi_cleanup_creds,
1146                         (void *)&xxx_gssctxt);
1147 #endif /* GSSAPI */
1148 
1149                 altprivsep_do_monitor(authctxt, aps_child);
1150 
1151                 /* If we got here the connection is dead. */
1152                 fatal_remove_cleanup((void (*)(void *))altprivsep_shutdown_sock,
1153                         (void *)&newsock);
1154 
1155                 if (compat20) {
1156                         debug3("Recording SSHv2 session logout in wtmpx");
1157                         record_logout(getpid(), NULL, "sshd", authctxt->user);
1158                 }
1159 
1160                 /*
1161                  * Make sure the socket is closed. The monitor can't call
1162                  * packet_close here as it's done a packet_set_connection()
1163                  * with the pipe to the child instead of the socket.
1164                  */
1165                 (void) shutdown(newsock, SHUT_RDWR);
1166 
1167 #ifdef GSSAPI
1168                 fatal_remove_cleanup((void (*)(void *))ssh_gssapi_cleanup_creds,
1169                         &xxx_gssctxt);
1170                 ssh_gssapi_cleanup_creds(xxx_gssctxt);
1171                 ssh_gssapi_server_mechs(NULL); /* release cached mechs list */
1172 #endif /* GSSAPI */
1173 
1174 #ifdef HAVE_BSM
1175                 fatal_remove_cleanup((void (*)(void *))audit_sshd_logout, (void *)&ah);
1176                 audit_sshd_logout(&ah);
1177 #endif /* HAVE_BSM */
1178 
1179                 exit(0);
1180         } else {
1181                 /*
1182                  * This is the child, close the dup()ed file descriptor for a
1183                  * socket. It's not needed in the child.
1184                  */
1185                 close(newsock);
1186         }
1187 }