xref: /illumos-gate/usr/src/cmd/nscd/nscd_door.c (revision 7d7551bc)
1cb5caa98Sdjl /*
2cb5caa98Sdjl  * CDDL HEADER START
3cb5caa98Sdjl  *
4cb5caa98Sdjl  * The contents of this file are subject to the terms of the
5cb5caa98Sdjl  * Common Development and Distribution License (the "License").
6cb5caa98Sdjl  * You may not use this file except in compliance with the License.
7cb5caa98Sdjl  *
8cb5caa98Sdjl  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9cb5caa98Sdjl  * or http://www.opensolaris.org/os/licensing.
10cb5caa98Sdjl  * See the License for the specific language governing permissions
11cb5caa98Sdjl  * and limitations under the License.
12cb5caa98Sdjl  *
13cb5caa98Sdjl  * When distributing Covered Code, include this CDDL HEADER in each
14cb5caa98Sdjl  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15cb5caa98Sdjl  * If applicable, add the following below this CDDL HEADER, with the
16cb5caa98Sdjl  * fields enclosed by brackets "[]" replaced with your own identifying
17cb5caa98Sdjl  * information: Portions Copyright [yyyy] [name of copyright owner]
18cb5caa98Sdjl  *
19cb5caa98Sdjl  * CDDL HEADER END
20cb5caa98Sdjl  */
21cb5caa98Sdjl 
22cb5caa98Sdjl /*
23606f6aa3Smichen  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24cb5caa98Sdjl  * Use is subject to license terms.
25*7d7551bcSMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
26cb5caa98Sdjl  */
27cb5caa98Sdjl 
28cb5caa98Sdjl #include <sys/param.h>
29cb5caa98Sdjl #include <string.h>
30cb5caa98Sdjl #include <door.h>
31cb5caa98Sdjl #include <sys/mman.h>
32cb5caa98Sdjl #include "nscd_door.h"
33cb5caa98Sdjl #include "nscd_log.h"
34cb5caa98Sdjl #include <getxby_door.h>
35cb5caa98Sdjl #include <sys/types.h>
36cb5caa98Sdjl #include <errno.h>
37cb5caa98Sdjl #include <fcntl.h>
38cb5caa98Sdjl 
39cb5caa98Sdjl static void
initdoor(void * buf,int * doorfd)40cb5caa98Sdjl initdoor(void *buf, int *doorfd)
41cb5caa98Sdjl {
42cb5caa98Sdjl 	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
43cb5caa98Sdjl 	door_info_t 	doori;
44cb5caa98Sdjl 	char		*me = "initdoor";
45cb5caa98Sdjl 
46cb5caa98Sdjl 	*doorfd = open64(NAME_SERVICE_DOOR, O_RDONLY, 0);
47cb5caa98Sdjl 
48cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
49cb5caa98Sdjl 		(me, "door is %s (fd is %d)\n", NAME_SERVICE_DOOR,
50*7d7551bcSMilan Jurik 		    *doorfd);
51cb5caa98Sdjl 
52*7d7551bcSMilan Jurik 	if (*doorfd == -1) {
53*7d7551bcSMilan Jurik 		NSCD_SET_STATUS(phdr, NSS_ERROR, errno);
54*7d7551bcSMilan Jurik 		return;
55*7d7551bcSMilan Jurik 	}
56cb5caa98Sdjl 
57cb5caa98Sdjl 	if (door_info(*doorfd, &doori) < 0 ||
58*7d7551bcSMilan Jurik 	    (doori.di_attributes & DOOR_REVOKED) ||
59*7d7551bcSMilan Jurik 	    doori.di_data != (uintptr_t)NAME_SERVICE_DOOR_COOKIE) {
60cb5caa98Sdjl 
61cb5caa98Sdjl 		/*
62cb5caa98Sdjl 		 * we should close doorfd because we just opened it
63cb5caa98Sdjl 		 */
64cb5caa98Sdjl 		(void) close(*doorfd);
65cb5caa98Sdjl 
66cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
67cb5caa98Sdjl 		(me, "door %d not valid\n", *doorfd);
68cb5caa98Sdjl 
69*7d7551bcSMilan Jurik 		NSCD_SET_STATUS(phdr, NSS_ERROR, ECONNREFUSED);
70*7d7551bcSMilan Jurik 		return;
71cb5caa98Sdjl 	}
72cb5caa98Sdjl 
73*7d7551bcSMilan Jurik 	NSCD_SET_STATUS_SUCCESS(phdr);
74cb5caa98Sdjl }
75cb5caa98Sdjl 
76cb5caa98Sdjl /* general door call functions used by nscd */
77cb5caa98Sdjl 
78cb5caa98Sdjl static nss_status_t
copy_output(void * outdata,int outdlen,nss_pheader_t * phdr,nss_pheader_t * outphdr)79cb5caa98Sdjl copy_output(void *outdata, int outdlen,
80cb5caa98Sdjl 	nss_pheader_t *phdr, nss_pheader_t *outphdr)
81cb5caa98Sdjl {
82cb5caa98Sdjl 	void		*dp;
83cb5caa98Sdjl 	nss_status_t	ret = NSS_SUCCESS;
84cb5caa98Sdjl 	char		*me = "copy_output";
85cb5caa98Sdjl 
86cb5caa98Sdjl 	if (outdata != NULL && phdr->data_off > 0 && phdr->data_len > 0) {
87cb5caa98Sdjl 		if (phdr->data_len <= outdlen) {
88cb5caa98Sdjl 			dp = (char *)phdr + phdr->data_off;
89cb5caa98Sdjl 			(void) memmove(outdata, dp, phdr->data_len);
90cb5caa98Sdjl 		} else {
91cb5caa98Sdjl 
92*7d7551bcSMilan Jurik 			_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
93cb5caa98Sdjl 			(me, "output buffer not large enough "
94*7d7551bcSMilan Jurik 			    " should be > %d but is %d\n",
95*7d7551bcSMilan Jurik 			    phdr->data_len, outdlen);
96cb5caa98Sdjl 
97cb5caa98Sdjl 			if (outphdr != NULL) {
98cb5caa98Sdjl 				NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV,
99*7d7551bcSMilan Jurik 				    0, NSCD_INVALID_ARGUMENT);
100cb5caa98Sdjl 				NSCD_COPY_STATUS(outphdr, phdr);
101cb5caa98Sdjl 			}
102cb5caa98Sdjl 			ret = NSS_NSCD_PRIV;
103cb5caa98Sdjl 		}
104cb5caa98Sdjl 	}
105cb5caa98Sdjl 
106cb5caa98Sdjl 	return (ret);
107cb5caa98Sdjl }
108cb5caa98Sdjl 
109cb5caa98Sdjl nss_status_t
_nscd_doorcall(int callnum)110cb5caa98Sdjl _nscd_doorcall(int callnum)
111cb5caa98Sdjl {
112606f6aa3Smichen 	size_t		buflen;
113606f6aa3Smichen 	nss_pheader_t	*phdr;
114cb5caa98Sdjl 	void		*dptr;
115cb5caa98Sdjl 	size_t		ndata;
116cb5caa98Sdjl 	size_t		adata;
117cb5caa98Sdjl 	int		ret;
118cb5caa98Sdjl 	char		*me = "_nscd_doorcall";
119cb5caa98Sdjl 
120cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
121cb5caa98Sdjl 	(me, "processing door call %d ...\n", callnum);
122cb5caa98Sdjl 
123606f6aa3Smichen 	/* allocate door buffer from the stack */
124606f6aa3Smichen 	NSCD_ALLOC_DOORBUF(callnum, 0, dptr, buflen);
125606f6aa3Smichen 	ndata = buflen;
126606f6aa3Smichen 	adata = buflen;
127606f6aa3Smichen 
128cb5caa98Sdjl 	ret = _nsc_trydoorcall(&dptr, &ndata, &adata);
129cb5caa98Sdjl 
130cb5caa98Sdjl 	if (ret != NSS_SUCCESS) {
131606f6aa3Smichen 		phdr = (nss_pheader_t *)dptr;
132cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
133cb5caa98Sdjl 		(me, "door call (%d) failed (status = %d, error = %s)\n",
134*7d7551bcSMilan Jurik 		    callnum, ret, strerror(NSCD_GET_ERRNO(phdr)));
135cb5caa98Sdjl 	}
136cb5caa98Sdjl 
137cb5caa98Sdjl 	return (ret);
138cb5caa98Sdjl }
139cb5caa98Sdjl 
140606f6aa3Smichen 
141cb5caa98Sdjl nss_status_t
_nscd_doorcall_data(int callnum,void * indata,int indlen,void * outdata,int outdlen,nss_pheader_t * phdr)142cb5caa98Sdjl _nscd_doorcall_data(int callnum, void *indata, int indlen,
143cb5caa98Sdjl 	void *outdata, int outdlen, nss_pheader_t *phdr)
144cb5caa98Sdjl {
145cb5caa98Sdjl 	void		*uptr;
146cb5caa98Sdjl 	size_t		buflen;
147cb5caa98Sdjl 	void		*dptr;
148cb5caa98Sdjl 	void		*datap;
149cb5caa98Sdjl 	size_t		ndata;
150cb5caa98Sdjl 	size_t		adata;
151cb5caa98Sdjl 	nss_pheader_t	*phdr_d;
152cb5caa98Sdjl 	int		ret;
153cb5caa98Sdjl 	char		*me = "_nscd_doorcall_data";
154cb5caa98Sdjl 
155cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
156cb5caa98Sdjl 	(me, "processing door call %d ...\n", callnum);
157cb5caa98Sdjl 
158cb5caa98Sdjl 	/* allocate door buffer from the stack */
159cb5caa98Sdjl 	NSCD_ALLOC_DOORBUF(callnum, indlen, uptr, buflen);
160cb5caa98Sdjl 	dptr = uptr;
161cb5caa98Sdjl 	ndata = buflen;
162cb5caa98Sdjl 	adata = buflen;
163cb5caa98Sdjl 	datap = NSCD_N2N_DOOR_DATA(void, dptr);
164cb5caa98Sdjl 	if (indata != NULL)
165cb5caa98Sdjl 		(void) memmove(datap, indata, indlen);
166cb5caa98Sdjl 
167cb5caa98Sdjl 	ret = _nsc_trydoorcall(&dptr, &ndata, &adata);
168cb5caa98Sdjl 
169cb5caa98Sdjl 	phdr_d = (nss_pheader_t *)dptr;
170cb5caa98Sdjl 	if (ret != NSS_SUCCESS) {
171cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
172cb5caa98Sdjl 		(me, "door call (%d) failed (status = %d, error = %s)\n",
173*7d7551bcSMilan Jurik 		    callnum, ret, strerror(NSCD_GET_ERRNO(phdr_d)));
174cb5caa98Sdjl 	} else {
175cb5caa98Sdjl 		if (phdr != NULL) {
176cb5caa98Sdjl 			NSCD_COPY_STATUS(phdr, phdr_d);
177cb5caa98Sdjl 		}
178cb5caa98Sdjl 		ret = copy_output(outdata, outdlen, phdr_d, phdr);
179cb5caa98Sdjl 	}
180cb5caa98Sdjl 
181cb5caa98Sdjl 	/* if new buffer allocated for this door call, free it */
182cb5caa98Sdjl 	if (dptr != uptr)
183cb5caa98Sdjl 		(void) munmap(dptr, ndata);
184cb5caa98Sdjl 
185cb5caa98Sdjl 	return (ret);
186cb5caa98Sdjl }
187cb5caa98Sdjl 
188cb5caa98Sdjl nss_status_t
_nscd_doorcall_fd(int fd,int callnum,void * indata,int indlen,void * outdata,int outdlen,nss_pheader_t * phdr)189cb5caa98Sdjl _nscd_doorcall_fd(int fd, int callnum, void *indata, int indlen,
190cb5caa98Sdjl 	void *outdata, int outdlen, nss_pheader_t *phdr)
191cb5caa98Sdjl {
192cb5caa98Sdjl 	void		*uptr;
193cb5caa98Sdjl 	void		*dptr;
194cb5caa98Sdjl 	void		*datap;
195cb5caa98Sdjl 	size_t		ndata;
196cb5caa98Sdjl 	size_t		adata;
197cb5caa98Sdjl 	size_t		buflen;
198cb5caa98Sdjl 	door_arg_t	param;
199cb5caa98Sdjl 	int		ret, errnum;
200cb5caa98Sdjl 	nss_pheader_t	*phdr_d;
201cb5caa98Sdjl 	char		*me = "_nscd_doorcall_fd";
202cb5caa98Sdjl 
203cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
204cb5caa98Sdjl 	(me, "processing door call %d (fd = %d)...\n", callnum, fd);
205cb5caa98Sdjl 
206cb5caa98Sdjl 	/* allocate door buffer from the stack */
207cb5caa98Sdjl 	NSCD_ALLOC_DOORBUF(callnum, indlen, uptr, buflen);
208cb5caa98Sdjl 	dptr = uptr;
209cb5caa98Sdjl 	ndata = buflen;
210cb5caa98Sdjl 	adata = buflen;
211cb5caa98Sdjl 	datap = NSCD_N2N_DOOR_DATA(void, dptr);
212cb5caa98Sdjl 	if (indata != NULL)
213cb5caa98Sdjl 		(void) memmove(datap, indata, indlen);
214cb5caa98Sdjl 
215cb5caa98Sdjl 	param.rbuf = (char *)dptr;
216cb5caa98Sdjl 	param.rsize = ndata;
217cb5caa98Sdjl 	param.data_ptr = (char *)dptr;
218cb5caa98Sdjl 	param.data_size = adata;
219cb5caa98Sdjl 	param.desc_ptr = NULL;
220cb5caa98Sdjl 	param.desc_num = 0;
221cb5caa98Sdjl 	ret = door_call(fd, &param);
222cb5caa98Sdjl 	if (ret < 0) {
223cb5caa98Sdjl 		errnum = errno;
224cb5caa98Sdjl 		/*
225cb5caa98Sdjl 		 * door call did not get through, return errno
226cb5caa98Sdjl 		 * if requested
227cb5caa98Sdjl 		 */
228cb5caa98Sdjl 		if (phdr != NULL) {
229cb5caa98Sdjl 			NSCD_SET_STATUS(phdr, NSS_ERROR, errnum);
230cb5caa98Sdjl 		}
231cb5caa98Sdjl 
232cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
233cb5caa98Sdjl 		(me, "door call (%d to %d) did not get through (%s)\n",
234*7d7551bcSMilan Jurik 		    callnum, fd, strerror(errnum));
235cb5caa98Sdjl 
236cb5caa98Sdjl 		return (NSS_ERROR);
237cb5caa98Sdjl 	}
238cb5caa98Sdjl 	ndata = param.rsize;
239cb5caa98Sdjl 	dptr = (void *)param.data_ptr;
240cb5caa98Sdjl 
241cb5caa98Sdjl 	/*
242cb5caa98Sdjl 	 * door call got through, check if operation failed.
243cb5caa98Sdjl 	 * if so, return error info if requested
244cb5caa98Sdjl 	 */
245cb5caa98Sdjl 	phdr_d = (nss_pheader_t *)dptr;
246cb5caa98Sdjl 	ret = NSCD_GET_STATUS(phdr_d);
247cb5caa98Sdjl 	if (ret != NSS_SUCCESS) {
248cb5caa98Sdjl 		if (phdr != NULL) {
249cb5caa98Sdjl 			NSCD_COPY_STATUS(phdr, phdr_d);
250cb5caa98Sdjl 		}
251cb5caa98Sdjl 
252cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
253cb5caa98Sdjl 		(me, "door call (%d to %d) failed: p_status = %d, "
254*7d7551bcSMilan Jurik 		    "p_errno = %s, nscd status = %d\n", callnum, fd,
255*7d7551bcSMilan Jurik 		    ret, strerror(NSCD_GET_ERRNO(phdr_d)),
256*7d7551bcSMilan Jurik 		    NSCD_GET_NSCD_STATUS(phdr_d));
257cb5caa98Sdjl 	} else
258cb5caa98Sdjl 		ret = copy_output(outdata, outdlen, phdr_d, phdr);
259cb5caa98Sdjl 
260cb5caa98Sdjl 	/* if new buffer allocated for this door call, free it */
261cb5caa98Sdjl 	if (dptr != uptr)
262cb5caa98Sdjl 		(void) munmap(dptr, param.rsize);
263cb5caa98Sdjl 
264cb5caa98Sdjl 
265cb5caa98Sdjl 	return (ret);
266cb5caa98Sdjl }
267cb5caa98Sdjl 
268cb5caa98Sdjl static void
send_doorfd(void ** dptr,size_t * ndata,size_t * adata,door_desc_t * pdesc)269cb5caa98Sdjl send_doorfd(void **dptr, size_t *ndata, size_t *adata,
270cb5caa98Sdjl 	door_desc_t *pdesc)
271cb5caa98Sdjl {
272cb5caa98Sdjl 	nss_pheader_t	*phdr = (nss_pheader_t *)*dptr;
273cb5caa98Sdjl 	door_arg_t	param;
274cb5caa98Sdjl 	int		ret;
275cb5caa98Sdjl 	int		doorfd;
276cb5caa98Sdjl 	int		errnum;
277cb5caa98Sdjl 	char		*me = "send_doorfd";
278cb5caa98Sdjl 
279cb5caa98Sdjl 	initdoor(*dptr, &doorfd);
280cb5caa98Sdjl 	if (NSCD_STATUS_IS_NOT_OK(phdr))
281cb5caa98Sdjl 		return;
282cb5caa98Sdjl 
283cb5caa98Sdjl 	param.rbuf = (char *)*dptr;
284cb5caa98Sdjl 	param.rsize = *ndata;
285cb5caa98Sdjl 	param.data_ptr = (char *)*dptr;
286cb5caa98Sdjl 	param.data_size = *adata;
287cb5caa98Sdjl 	param.desc_ptr = pdesc;
288cb5caa98Sdjl 	param.desc_num = 1;
289cb5caa98Sdjl 	ret = door_call(doorfd, &param);
290cb5caa98Sdjl 	if (ret < 0) {
291cb5caa98Sdjl 		errnum = errno;
292cb5caa98Sdjl 
293cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
294cb5caa98Sdjl 		(me, "door call (to fd %d) failed (%s)\n",
295*7d7551bcSMilan Jurik 		    doorfd, strerror(errnum));
296cb5caa98Sdjl 		(void) close(doorfd);
297*7d7551bcSMilan Jurik 		NSCD_SET_STATUS(phdr, NSS_ERROR, errnum);
298*7d7551bcSMilan Jurik 		return;
299cb5caa98Sdjl 	}
300cb5caa98Sdjl 	*adata = param.data_size;
301cb5caa98Sdjl 	*ndata = param.rsize;
302cb5caa98Sdjl 	*dptr = (void *)param.data_ptr;
303cb5caa98Sdjl 
304cb5caa98Sdjl 	if (*adata == 0 || *dptr == NULL) {
305cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
306cb5caa98Sdjl 		(me, "no data\n");
307cb5caa98Sdjl 
308*7d7551bcSMilan Jurik 		NSCD_SET_STATUS(phdr, NSS_ERROR, ENOTCONN);
309cb5caa98Sdjl 	}
310cb5caa98Sdjl 
311cb5caa98Sdjl 	(void) close(doorfd);
312cb5caa98Sdjl }
313cb5caa98Sdjl 
314cb5caa98Sdjl nss_status_t
_nscd_doorcall_sendfd(int fd,int callnum,void * indata,int indlen,nss_pheader_t * phdr)315cb5caa98Sdjl _nscd_doorcall_sendfd(int fd, int callnum, void *indata, int indlen,
316cb5caa98Sdjl 	nss_pheader_t *phdr)
317cb5caa98Sdjl {
318cb5caa98Sdjl 	void		*uptr;
319cb5caa98Sdjl 	void		*dptr;
320cb5caa98Sdjl 	void		*datap;
321cb5caa98Sdjl 	size_t		ndata;
322cb5caa98Sdjl 	size_t		adata;
323cb5caa98Sdjl 	size_t		buflen;
324cb5caa98Sdjl 	nss_pheader_t	*phdr_d;
325cb5caa98Sdjl 	door_desc_t	desc;
326cb5caa98Sdjl 	char		*me = "_nscd_doorcall_sendfd";
327cb5caa98Sdjl 
328cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
329cb5caa98Sdjl 	(me, "processing door call %d (fd = %d)...\n", callnum, fd);
330cb5caa98Sdjl 
331cb5caa98Sdjl 	/* allocate door buffer from the stack */
332cb5caa98Sdjl 	NSCD_ALLOC_DOORBUF(callnum, indlen, uptr, buflen);
333cb5caa98Sdjl 	dptr = uptr;
334cb5caa98Sdjl 	ndata = buflen;
335cb5caa98Sdjl 	adata = buflen;
336cb5caa98Sdjl 	datap = NSCD_N2N_DOOR_DATA(void, dptr);
337cb5caa98Sdjl 	if (indata != NULL)
338cb5caa98Sdjl 		(void) memmove(datap, indata, indlen);
339cb5caa98Sdjl 	desc.d_attributes = DOOR_DESCRIPTOR;
340cb5caa98Sdjl 	desc.d_data.d_desc.d_descriptor = fd;
341cb5caa98Sdjl 
342cb5caa98Sdjl 	send_doorfd(&dptr, &ndata, &adata, &desc);
343cb5caa98Sdjl 
344cb5caa98Sdjl 	phdr_d = (nss_pheader_t *)dptr;
345cb5caa98Sdjl 	if (NSCD_STATUS_IS_NOT_OK(phdr_d)) {
346cb5caa98Sdjl 		if (phdr != NULL)
347cb5caa98Sdjl 			*phdr = *phdr_d;
348cb5caa98Sdjl 
349cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG)
350cb5caa98Sdjl 		(me, "door call (%d) failed (status = %d, error = %s)\n",
351*7d7551bcSMilan Jurik 		    callnum, NSCD_GET_STATUS(phdr_d),
352*7d7551bcSMilan Jurik 		    strerror(NSCD_GET_ERRNO(phdr_d)));
353cb5caa98Sdjl 	}
354cb5caa98Sdjl 
355cb5caa98Sdjl 	return (NSCD_GET_STATUS(phdr_d));
356cb5caa98Sdjl }
357