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