xref: /titanic_44/usr/src/cmd/ssh/sshd/altprivsep.c (revision 8b0ef7ed9d02af20a3d5106d84a4fc6aa0d7dd9f)
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
altprivsep_start_monitor(Authctxt ** authctxt)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
altprivsep_get_pipe_fd(void)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
altprivsep_rekey(int type,u_int32_t seq,void * ctxt)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
altprivsep_process_input(fd_set * rset)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
altprivsep_do_monitor(Authctxt * authctxt,pid_t child_pid)401 altprivsep_do_monitor(Authctxt *authctxt, pid_t child_pid)
402 {
403 	aps_monitor_loop(authctxt, child_pid);
404 }
405 
406 static int
altprivsep_started(void)407 altprivsep_started(void)
408 {
409 	return (aps_started);
410 }
411 
412 static int
altprivsep_is_monitor(void)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
altprivsep_shutdown_sock(void * arg)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
altprivsep_fwd_packet(u_char type)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
altprivsep_get_newkeys(enum kex_modes mode)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
altprivsep_record_login(pid_t pid,const char * ttyname)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
altprivsep_record_logout(pid_t pid)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
altprivsep_start_rekex(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
altprivsep_send_auth_context(Authctxt * authctxt)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
aps_input_altpriv_msg(int type,u_int32_t seq,void * ctxt)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
aps_send_newkeys(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
aps_record_login(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
aps_record_logout(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
aps_start_rekex(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 *
aps_read_auth_context(void)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
altprivsep_packet_start(u_char type)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
altprivsep_packet_put_char(int ch)822 altprivsep_packet_put_char(int ch)
823 {
824 	buffer_put_char(&to_monitor, ch);
825 }
826 
827 static void
altprivsep_packet_put_int(u_int value)828 altprivsep_packet_put_int(u_int value)
829 {
830 	buffer_put_int(&to_monitor, value);
831 }
832 
833 static void
altprivsep_packet_put_cstring(const char * str)834 altprivsep_packet_put_cstring(const char *str)
835 {
836 	buffer_put_cstring(&to_monitor, str);
837 }
838 
839 static void
altprivsep_packet_put_raw(const void * buf,u_int len)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
altprivsep_packet_send(void)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
altprivsep_packet_read(void)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
altprivsep_packet_read_expect(int expected)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
altprivsep_packet_get_char(void)1032 altprivsep_packet_get_char(void)
1033 {
1034 	return (buffer_get_char(&from_monitor));
1035 }
1036 void
altprivsep_packet_get_raw(u_int * length_ptr)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
altprivsep_packet_get_string(u_int * length_ptr)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
altprivsep_start_and_do_monitor(int use_engine,int inetd,int newsock,int statup_pipe)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 }
1188