xref: /dflybsd-src/crypto/openssh/monitor_fdpass.c (revision 50a69bb51183a7916e776f2c9f5fa64c999f1a2f)
1*50a69bb5SSascha Wildner /* $OpenBSD: monitor_fdpass.c,v 1.22 2020/10/18 11:32:01 djm Exp $ */
218de8d7fSPeter Avalos /*
318de8d7fSPeter Avalos  * Copyright 2001 Niels Provos <provos@citi.umich.edu>
418de8d7fSPeter Avalos  * All rights reserved.
518de8d7fSPeter Avalos  *
618de8d7fSPeter Avalos  * Redistribution and use in source and binary forms, with or without
718de8d7fSPeter Avalos  * modification, are permitted provided that the following conditions
818de8d7fSPeter Avalos  * are met:
918de8d7fSPeter Avalos  * 1. Redistributions of source code must retain the above copyright
1018de8d7fSPeter Avalos  *    notice, this list of conditions and the following disclaimer.
1118de8d7fSPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
1218de8d7fSPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
1318de8d7fSPeter Avalos  *    documentation and/or other materials provided with the distribution.
1418de8d7fSPeter Avalos  *
1518de8d7fSPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1618de8d7fSPeter Avalos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1718de8d7fSPeter Avalos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1818de8d7fSPeter Avalos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1918de8d7fSPeter Avalos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2018de8d7fSPeter Avalos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2118de8d7fSPeter Avalos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2218de8d7fSPeter Avalos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2318de8d7fSPeter Avalos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2418de8d7fSPeter Avalos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2518de8d7fSPeter Avalos  */
2618de8d7fSPeter Avalos 
2718de8d7fSPeter Avalos #include "includes.h"
2818de8d7fSPeter Avalos 
2918de8d7fSPeter Avalos #include <sys/types.h>
3018de8d7fSPeter Avalos #include <sys/socket.h>
3118de8d7fSPeter Avalos #include <sys/uio.h>
3218de8d7fSPeter Avalos #ifdef HAVE_SYS_UN_H
3318de8d7fSPeter Avalos #include <sys/un.h>
3418de8d7fSPeter Avalos #endif
3518de8d7fSPeter Avalos 
3618de8d7fSPeter Avalos #include <errno.h>
3718de8d7fSPeter Avalos #include <string.h>
3818de8d7fSPeter Avalos #include <stdarg.h>
3918de8d7fSPeter Avalos 
4036e94dc5SPeter Avalos #ifdef HAVE_POLL_H
4136e94dc5SPeter Avalos # include <poll.h>
4236e94dc5SPeter Avalos #else
4336e94dc5SPeter Avalos # ifdef HAVE_SYS_POLL_H
4436e94dc5SPeter Avalos #  include <sys/poll.h>
4536e94dc5SPeter Avalos # endif
4636e94dc5SPeter Avalos #endif
4736e94dc5SPeter Avalos 
4818de8d7fSPeter Avalos #include "log.h"
4918de8d7fSPeter Avalos #include "monitor_fdpass.h"
5018de8d7fSPeter Avalos 
5118de8d7fSPeter Avalos int
mm_send_fd(int sock,int fd)5218de8d7fSPeter Avalos mm_send_fd(int sock, int fd)
5318de8d7fSPeter Avalos {
5418de8d7fSPeter Avalos #if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR))
5518de8d7fSPeter Avalos 	struct msghdr msg;
5618de8d7fSPeter Avalos #ifndef HAVE_ACCRIGHTS_IN_MSGHDR
5718de8d7fSPeter Avalos 	union {
5818de8d7fSPeter Avalos 		struct cmsghdr hdr;
5918de8d7fSPeter Avalos 		char buf[CMSG_SPACE(sizeof(int))];
6018de8d7fSPeter Avalos 	} cmsgbuf;
6118de8d7fSPeter Avalos 	struct cmsghdr *cmsg;
6218de8d7fSPeter Avalos #endif
63cb5eb4f1SPeter Avalos 	struct iovec vec;
64cb5eb4f1SPeter Avalos 	char ch = '\0';
65cb5eb4f1SPeter Avalos 	ssize_t n;
66856ea928SPeter Avalos 	struct pollfd pfd;
6718de8d7fSPeter Avalos 
6818de8d7fSPeter Avalos 	memset(&msg, 0, sizeof(msg));
6918de8d7fSPeter Avalos #ifdef HAVE_ACCRIGHTS_IN_MSGHDR
7018de8d7fSPeter Avalos 	msg.msg_accrights = (caddr_t)&fd;
7118de8d7fSPeter Avalos 	msg.msg_accrightslen = sizeof(fd);
7218de8d7fSPeter Avalos #else
73e9778795SPeter Avalos 	memset(&cmsgbuf, 0, sizeof(cmsgbuf));
7418de8d7fSPeter Avalos 	msg.msg_control = (caddr_t)&cmsgbuf.buf;
7518de8d7fSPeter Avalos 	msg.msg_controllen = sizeof(cmsgbuf.buf);
7618de8d7fSPeter Avalos 	cmsg = CMSG_FIRSTHDR(&msg);
7718de8d7fSPeter Avalos 	cmsg->cmsg_len = CMSG_LEN(sizeof(int));
7818de8d7fSPeter Avalos 	cmsg->cmsg_level = SOL_SOCKET;
7918de8d7fSPeter Avalos 	cmsg->cmsg_type = SCM_RIGHTS;
8018de8d7fSPeter Avalos 	*(int *)CMSG_DATA(cmsg) = fd;
8118de8d7fSPeter Avalos #endif
8218de8d7fSPeter Avalos 
8318de8d7fSPeter Avalos 	vec.iov_base = &ch;
8418de8d7fSPeter Avalos 	vec.iov_len = 1;
8518de8d7fSPeter Avalos 	msg.msg_iov = &vec;
8618de8d7fSPeter Avalos 	msg.msg_iovlen = 1;
8718de8d7fSPeter Avalos 
88856ea928SPeter Avalos 	pfd.fd = sock;
89856ea928SPeter Avalos 	pfd.events = POLLOUT;
90856ea928SPeter Avalos 	while ((n = sendmsg(sock, &msg, 0)) == -1 &&
91856ea928SPeter Avalos 	    (errno == EAGAIN || errno == EINTR)) {
92*50a69bb5SSascha Wildner 		debug3_f("sendmsg(%d): %s", fd, strerror(errno));
93856ea928SPeter Avalos 		(void)poll(&pfd, 1, -1);
94856ea928SPeter Avalos 	}
95cb5eb4f1SPeter Avalos 	if (n == -1) {
96*50a69bb5SSascha Wildner 		error_f("sendmsg(%d): %s", fd, strerror(errno));
9718de8d7fSPeter Avalos 		return -1;
9818de8d7fSPeter Avalos 	}
9918de8d7fSPeter Avalos 
10018de8d7fSPeter Avalos 	if (n != 1) {
101*50a69bb5SSascha Wildner 		error_f("sendmsg: expected sent 1 got %zd", n);
10218de8d7fSPeter Avalos 		return -1;
10318de8d7fSPeter Avalos 	}
10418de8d7fSPeter Avalos 	return 0;
10518de8d7fSPeter Avalos #else
10618de8d7fSPeter Avalos 	error("%s: file descriptor passing not supported", __func__);
10718de8d7fSPeter Avalos 	return -1;
10818de8d7fSPeter Avalos #endif
10918de8d7fSPeter Avalos }
11018de8d7fSPeter Avalos 
11118de8d7fSPeter Avalos int
mm_receive_fd(int sock)11218de8d7fSPeter Avalos mm_receive_fd(int sock)
11318de8d7fSPeter Avalos {
11418de8d7fSPeter Avalos #if defined(HAVE_RECVMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR))
11518de8d7fSPeter Avalos 	struct msghdr msg;
11618de8d7fSPeter Avalos #ifndef HAVE_ACCRIGHTS_IN_MSGHDR
11718de8d7fSPeter Avalos 	union {
11818de8d7fSPeter Avalos 		struct cmsghdr hdr;
11918de8d7fSPeter Avalos 		char buf[CMSG_SPACE(sizeof(int))];
12018de8d7fSPeter Avalos 	} cmsgbuf;
12118de8d7fSPeter Avalos 	struct cmsghdr *cmsg;
12218de8d7fSPeter Avalos #endif
123cb5eb4f1SPeter Avalos 	struct iovec vec;
124cb5eb4f1SPeter Avalos 	ssize_t n;
125cb5eb4f1SPeter Avalos 	char ch;
126cb5eb4f1SPeter Avalos 	int fd;
127856ea928SPeter Avalos 	struct pollfd pfd;
12818de8d7fSPeter Avalos 
12918de8d7fSPeter Avalos 	memset(&msg, 0, sizeof(msg));
13018de8d7fSPeter Avalos 	vec.iov_base = &ch;
13118de8d7fSPeter Avalos 	vec.iov_len = 1;
13218de8d7fSPeter Avalos 	msg.msg_iov = &vec;
13318de8d7fSPeter Avalos 	msg.msg_iovlen = 1;
13418de8d7fSPeter Avalos #ifdef HAVE_ACCRIGHTS_IN_MSGHDR
13518de8d7fSPeter Avalos 	msg.msg_accrights = (caddr_t)&fd;
13618de8d7fSPeter Avalos 	msg.msg_accrightslen = sizeof(fd);
13718de8d7fSPeter Avalos #else
138e9778795SPeter Avalos 	memset(&cmsgbuf, 0, sizeof(cmsgbuf));
13918de8d7fSPeter Avalos 	msg.msg_control = &cmsgbuf.buf;
14018de8d7fSPeter Avalos 	msg.msg_controllen = sizeof(cmsgbuf.buf);
14118de8d7fSPeter Avalos #endif
14218de8d7fSPeter Avalos 
143856ea928SPeter Avalos 	pfd.fd = sock;
144856ea928SPeter Avalos 	pfd.events = POLLIN;
145856ea928SPeter Avalos 	while ((n = recvmsg(sock, &msg, 0)) == -1 &&
146856ea928SPeter Avalos 	    (errno == EAGAIN || errno == EINTR)) {
147*50a69bb5SSascha Wildner 		debug3_f("recvmsg: %s", strerror(errno));
148856ea928SPeter Avalos 		(void)poll(&pfd, 1, -1);
149856ea928SPeter Avalos 	}
150cb5eb4f1SPeter Avalos 	if (n == -1) {
151*50a69bb5SSascha Wildner 		error_f("recvmsg: %s", strerror(errno));
15218de8d7fSPeter Avalos 		return -1;
15318de8d7fSPeter Avalos 	}
154cb5eb4f1SPeter Avalos 
15518de8d7fSPeter Avalos 	if (n != 1) {
156*50a69bb5SSascha Wildner 		error_f("recvmsg: expected received 1 got %zd", n);
15718de8d7fSPeter Avalos 		return -1;
15818de8d7fSPeter Avalos 	}
15918de8d7fSPeter Avalos 
16018de8d7fSPeter Avalos #ifdef HAVE_ACCRIGHTS_IN_MSGHDR
16118de8d7fSPeter Avalos 	if (msg.msg_accrightslen != sizeof(fd)) {
162*50a69bb5SSascha Wildner 		error_f("no fd");
16318de8d7fSPeter Avalos 		return -1;
16418de8d7fSPeter Avalos 	}
16518de8d7fSPeter Avalos #else
16618de8d7fSPeter Avalos 	cmsg = CMSG_FIRSTHDR(&msg);
16718de8d7fSPeter Avalos 	if (cmsg == NULL) {
168*50a69bb5SSascha Wildner 		error_f("no message header");
16918de8d7fSPeter Avalos 		return -1;
17018de8d7fSPeter Avalos 	}
171cb5eb4f1SPeter Avalos 
17218de8d7fSPeter Avalos #ifndef BROKEN_CMSG_TYPE
17318de8d7fSPeter Avalos 	if (cmsg->cmsg_type != SCM_RIGHTS) {
174*50a69bb5SSascha Wildner 		error_f("expected %d got %d", SCM_RIGHTS, cmsg->cmsg_type);
17518de8d7fSPeter Avalos 		return -1;
17618de8d7fSPeter Avalos 	}
17718de8d7fSPeter Avalos #endif
17818de8d7fSPeter Avalos 	fd = (*(int *)CMSG_DATA(cmsg));
17918de8d7fSPeter Avalos #endif
18018de8d7fSPeter Avalos 	return fd;
18118de8d7fSPeter Avalos #else
182*50a69bb5SSascha Wildner 	error_f("file descriptor passing not supported");
18318de8d7fSPeter Avalos 	return -1;
18418de8d7fSPeter Avalos #endif
18518de8d7fSPeter Avalos }
186