xref: /netbsd-src/crypto/external/bsd/openssh/dist/monitor_fdpass.c (revision 17418e98f281f84e3d22de9717222f9c2ee84d3a)
1*17418e98Schristos /*	$NetBSD: monitor_fdpass.c,v 1.9 2021/03/05 17:47:16 christos Exp $	*/
2*17418e98Schristos /* $OpenBSD: monitor_fdpass.c,v 1.22 2020/10/18 11:32:01 djm Exp $ */
3*17418e98Schristos 
4ca32bd8dSchristos /*
5ca32bd8dSchristos  * Copyright 2001 Niels Provos <provos@citi.umich.edu>
6ca32bd8dSchristos  * All rights reserved.
7ca32bd8dSchristos  *
8ca32bd8dSchristos  * Redistribution and use in source and binary forms, with or without
9ca32bd8dSchristos  * modification, are permitted provided that the following conditions
10ca32bd8dSchristos  * are met:
11ca32bd8dSchristos  * 1. Redistributions of source code must retain the above copyright
12ca32bd8dSchristos  *    notice, this list of conditions and the following disclaimer.
13ca32bd8dSchristos  * 2. Redistributions in binary form must reproduce the above copyright
14ca32bd8dSchristos  *    notice, this list of conditions and the following disclaimer in the
15ca32bd8dSchristos  *    documentation and/or other materials provided with the distribution.
16ca32bd8dSchristos  *
17ca32bd8dSchristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18ca32bd8dSchristos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19ca32bd8dSchristos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20ca32bd8dSchristos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21ca32bd8dSchristos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22ca32bd8dSchristos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23ca32bd8dSchristos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24ca32bd8dSchristos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25ca32bd8dSchristos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26ca32bd8dSchristos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27ca32bd8dSchristos  */
28ca32bd8dSchristos 
29313c6c94Schristos #include "includes.h"
30*17418e98Schristos __RCSID("$NetBSD: monitor_fdpass.c,v 1.9 2021/03/05 17:47:16 christos Exp $");
31ca32bd8dSchristos #include <sys/types.h>
32ca32bd8dSchristos #include <sys/socket.h>
33ca32bd8dSchristos #include <sys/uio.h>
34ca32bd8dSchristos 
35ca32bd8dSchristos #include <errno.h>
3634b27b53Sadam #include <poll.h>
37ca32bd8dSchristos #include <string.h>
38ca32bd8dSchristos #include <stdarg.h>
39ca32bd8dSchristos 
40ca32bd8dSchristos #include "log.h"
41ca32bd8dSchristos #include "monitor_fdpass.h"
42ca32bd8dSchristos 
43ca32bd8dSchristos int
mm_send_fd(int sock,int fd)44ca32bd8dSchristos mm_send_fd(int sock, int fd)
45ca32bd8dSchristos {
46ca32bd8dSchristos 	struct msghdr msg;
47ca32bd8dSchristos 	union {
48ca32bd8dSchristos 		struct cmsghdr hdr;
49313c6c94Schristos 		char buf[1024];
50ca32bd8dSchristos 	} cmsgbuf;
51ca32bd8dSchristos 	struct cmsghdr *cmsg;
52ca32bd8dSchristos 	struct iovec vec;
53ca32bd8dSchristos 	char ch = '\0';
54ca32bd8dSchristos 	ssize_t n;
5534b27b53Sadam 	struct pollfd pfd;
56ca32bd8dSchristos 
57313c6c94Schristos 	if (sizeof(cmsgbuf.buf) < CMSG_SPACE(sizeof(int))) {
58313c6c94Schristos 		error("%s: %zu < %zu, recompile", __func__,
59313c6c94Schristos 		    sizeof(cmsgbuf.buf), CMSG_SPACE(sizeof(int)));
60313c6c94Schristos 		return -1;
61313c6c94Schristos 	}
62313c6c94Schristos 
63ca32bd8dSchristos 	memset(&msg, 0, sizeof(msg));
64e4d43b82Schristos 	memset(&cmsgbuf, 0, sizeof(cmsgbuf));
65313c6c94Schristos 	msg.msg_control = &cmsgbuf.buf;
66313c6c94Schristos 	msg.msg_controllen = CMSG_SPACE(sizeof(int));
67ca32bd8dSchristos 	cmsg = CMSG_FIRSTHDR(&msg);
68ca32bd8dSchristos 	cmsg->cmsg_len = CMSG_LEN(sizeof(int));
69ca32bd8dSchristos 	cmsg->cmsg_level = SOL_SOCKET;
70ca32bd8dSchristos 	cmsg->cmsg_type = SCM_RIGHTS;
71ca32bd8dSchristos 	*(int *)CMSG_DATA(cmsg) = fd;
72313c6c94Schristos 	msg.msg_controllen = cmsg->cmsg_len;
73ca32bd8dSchristos 
74ca32bd8dSchristos 	vec.iov_base = &ch;
75ca32bd8dSchristos 	vec.iov_len = 1;
76ca32bd8dSchristos 	msg.msg_iov = &vec;
77ca32bd8dSchristos 	msg.msg_iovlen = 1;
78ca32bd8dSchristos 
7934b27b53Sadam 	pfd.fd = sock;
8034b27b53Sadam 	pfd.events = POLLOUT;
8134b27b53Sadam 	while ((n = sendmsg(sock, &msg, 0)) == -1 &&
8234b27b53Sadam 	    (errno == EAGAIN || errno == EINTR)) {
83*17418e98Schristos 		debug3_f("sendmsg(%d): %s", fd, strerror(errno));
8434b27b53Sadam 		(void)poll(&pfd, 1, -1);
8534b27b53Sadam 	}
86ca32bd8dSchristos 	if (n == -1) {
87*17418e98Schristos 		error_f("sendmsg(%d): %s", fd, strerror(errno));
88ca32bd8dSchristos 		return -1;
89ca32bd8dSchristos 	}
90ca32bd8dSchristos 
91ca32bd8dSchristos 	if (n != 1) {
92*17418e98Schristos 		error_f("sendmsg: expected sent 1 got %zd", n);
93ca32bd8dSchristos 		return -1;
94ca32bd8dSchristos 	}
95ca32bd8dSchristos 	return 0;
96ca32bd8dSchristos }
97ca32bd8dSchristos 
98ca32bd8dSchristos int
mm_receive_fd(int sock)99ca32bd8dSchristos mm_receive_fd(int sock)
100ca32bd8dSchristos {
101ca32bd8dSchristos 	struct msghdr msg;
102ca32bd8dSchristos 	union {
103ca32bd8dSchristos 		struct cmsghdr hdr;
104313c6c94Schristos 		char buf[1024];
105ca32bd8dSchristos 	} cmsgbuf;
106ca32bd8dSchristos 	struct cmsghdr *cmsg;
107ca32bd8dSchristos 	struct iovec vec;
108ca32bd8dSchristos 	ssize_t n;
109ca32bd8dSchristos 	char ch;
110ca32bd8dSchristos 	int fd;
11134b27b53Sadam 	struct pollfd pfd;
112ca32bd8dSchristos 
113313c6c94Schristos 	if (sizeof(cmsgbuf.buf) < CMSG_SPACE(sizeof(int))) {
114313c6c94Schristos 		error("%s: %zu < %zu, recompile", __func__,
115313c6c94Schristos 		    sizeof(cmsgbuf.buf), CMSG_SPACE(sizeof(int)));
116313c6c94Schristos 		return -1;
117313c6c94Schristos 	}
118313c6c94Schristos 
119ca32bd8dSchristos 	memset(&msg, 0, sizeof(msg));
120e4d43b82Schristos 	memset(&cmsgbuf, 0, sizeof(cmsgbuf));
121ca32bd8dSchristos 	vec.iov_base = &ch;
122ca32bd8dSchristos 	vec.iov_len = 1;
123ca32bd8dSchristos 	msg.msg_iov = &vec;
124ca32bd8dSchristos 	msg.msg_iovlen = 1;
125ca32bd8dSchristos 	msg.msg_control = &cmsgbuf.buf;
126313c6c94Schristos 	msg.msg_controllen = CMSG_SPACE(sizeof(int));
127ca32bd8dSchristos 
12834b27b53Sadam 	pfd.fd = sock;
12934b27b53Sadam 	pfd.events = POLLIN;
13034b27b53Sadam 	while ((n = recvmsg(sock, &msg, 0)) == -1 &&
13134b27b53Sadam 	    (errno == EAGAIN || errno == EINTR)) {
132*17418e98Schristos 		debug3_f("recvmsg: %s", strerror(errno));
13334b27b53Sadam 		(void)poll(&pfd, 1, -1);
13434b27b53Sadam 	}
135ca32bd8dSchristos 	if (n == -1) {
136*17418e98Schristos 		error_f("recvmsg: %s", strerror(errno));
137ca32bd8dSchristos 		return -1;
138ca32bd8dSchristos 	}
139ca32bd8dSchristos 
140ca32bd8dSchristos 	if (n != 1) {
141*17418e98Schristos 		error_f("recvmsg: expected received 1 got %zd", n);
142ca32bd8dSchristos 		return -1;
143ca32bd8dSchristos 	}
144ca32bd8dSchristos 
145ca32bd8dSchristos 	cmsg = CMSG_FIRSTHDR(&msg);
146ca32bd8dSchristos 	if (cmsg == NULL) {
147*17418e98Schristos 		error_f("no message header");
148ca32bd8dSchristos 		return -1;
149ca32bd8dSchristos 	}
150ca32bd8dSchristos 
151ca32bd8dSchristos 	if (cmsg->cmsg_type != SCM_RIGHTS) {
152*17418e98Schristos 		error_f("expected %d got %d", SCM_RIGHTS, cmsg->cmsg_type);
153ca32bd8dSchristos 		return -1;
154ca32bd8dSchristos 	}
155ca32bd8dSchristos 	fd = (*(int *)CMSG_DATA(cmsg));
156ca32bd8dSchristos 	return fd;
157ca32bd8dSchristos }
158