1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <pwd.h>
31*7c478bd9Sstevel@tonic-gate #include <stdio.h>
32*7c478bd9Sstevel@tonic-gate #include <synch.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
34*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
35*7c478bd9Sstevel@tonic-gate #include <unistd.h>
36*7c478bd9Sstevel@tonic-gate #include "ns_cache_door.h"
37*7c478bd9Sstevel@tonic-gate #include <door.h>
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #if defined(PIC) || defined(lint)
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate /*
42*7c478bd9Sstevel@tonic-gate  *
43*7c478bd9Sstevel@tonic-gate  * Routine that actually performs the door call.
44*7c478bd9Sstevel@tonic-gate  * Note that we cache a file descriptor.  We do
45*7c478bd9Sstevel@tonic-gate  * the following to prevent disasters:
46*7c478bd9Sstevel@tonic-gate  *
47*7c478bd9Sstevel@tonic-gate  * 1) Never use 0,1 or 2; if we get this from the open
48*7c478bd9Sstevel@tonic-gate  *    we dup it upwards.
49*7c478bd9Sstevel@tonic-gate  *
50*7c478bd9Sstevel@tonic-gate  * 2) Set the close on exec flags so descriptor remains available
51*7c478bd9Sstevel@tonic-gate  *    to child processes.
52*7c478bd9Sstevel@tonic-gate  *
53*7c478bd9Sstevel@tonic-gate  * 3) Verify that the door is still the same one we had before
54*7c478bd9Sstevel@tonic-gate  *    by using door_info on the client side.
55*7c478bd9Sstevel@tonic-gate  *
56*7c478bd9Sstevel@tonic-gate  *	Note that we never close the file descriptor if it isn't one
57*7c478bd9Sstevel@tonic-gate  *	we allocated; we check this with door info.  The rather tricky
58*7c478bd9Sstevel@tonic-gate  *	logic is designed to be fast in the normal case (fd is already
59*7c478bd9Sstevel@tonic-gate  *	allocated and is ok) while handling the case where the application
60*7c478bd9Sstevel@tonic-gate  *	closed it underneath us or where the nscd dies or re-execs itself
61*7c478bd9Sstevel@tonic-gate  *	and we're a multi-threaded application.  Note that we cannot protect
62*7c478bd9Sstevel@tonic-gate  *	the application if it closes the fd and it is multi-threaded.
63*7c478bd9Sstevel@tonic-gate  *
64*7c478bd9Sstevel@tonic-gate  *  int _cache_trydoorcall(void *dptr, int *bufsize, int *actualsize);
65*7c478bd9Sstevel@tonic-gate  *
66*7c478bd9Sstevel@tonic-gate  *      *dptr           IN: points to arg buffer OUT: points to results buffer
67*7c478bd9Sstevel@tonic-gate  *      *bufsize        IN: overall size of buffer OUT: overall size of buffer
68*7c478bd9Sstevel@tonic-gate  *      *actualsize     IN: size of call data OUT: size of return data
69*7c478bd9Sstevel@tonic-gate  *
70*7c478bd9Sstevel@tonic-gate  *  Note that *dptr may change if provided space as defined by *bufsize is
71*7c478bd9Sstevel@tonic-gate  *  inadequate.  In this case the door call mmaps more space and places
72*7c478bd9Sstevel@tonic-gate  *  the answer there and sets dptr to contain a pointer to the space, which
73*7c478bd9Sstevel@tonic-gate  *  should be freed with munmap.
74*7c478bd9Sstevel@tonic-gate  *
75*7c478bd9Sstevel@tonic-gate  *  Returns 0 if the door call reached the server, -1 if contact was not made.
76*7c478bd9Sstevel@tonic-gate  *
77*7c478bd9Sstevel@tonic-gate  */
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate extern int errno;
80*7c478bd9Sstevel@tonic-gate static mutex_t	_door_lock = DEFAULTMUTEX;
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate int
83*7c478bd9Sstevel@tonic-gate __ns_ldap_trydoorcall(ldap_data_t **dptr, int *ndata, int *adata)
84*7c478bd9Sstevel@tonic-gate {
85*7c478bd9Sstevel@tonic-gate 	static	int 		doorfd = -1;
86*7c478bd9Sstevel@tonic-gate 	static	door_info_t 	real_door;
87*7c478bd9Sstevel@tonic-gate 	door_info_t 		my_door;
88*7c478bd9Sstevel@tonic-gate 	door_arg_t		param;
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	/*
91*7c478bd9Sstevel@tonic-gate 	 * the first time in we try and open and validate the door.
92*7c478bd9Sstevel@tonic-gate 	 * the validations are that the door must have been
93*7c478bd9Sstevel@tonic-gate 	 * created with the name service door cookie and
94*7c478bd9Sstevel@tonic-gate 	 * that the file attached to the door is owned by root
95*7c478bd9Sstevel@tonic-gate 	 * and readonly by user, group and other.  If any of these
96*7c478bd9Sstevel@tonic-gate 	 * validations fail we refuse to use the door.
97*7c478bd9Sstevel@tonic-gate 	 */
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&_door_lock);
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate try_again:
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 	if (doorfd == -1) {
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 		int		tbc[3];
106*7c478bd9Sstevel@tonic-gate 		int		i;
107*7c478bd9Sstevel@tonic-gate 		if ((doorfd = open(LDAP_CACHE_DOOR, O_RDONLY, 0))
108*7c478bd9Sstevel@tonic-gate 		    == -1) {
109*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&_door_lock);
110*7c478bd9Sstevel@tonic-gate 			return (NOSERVER);
111*7c478bd9Sstevel@tonic-gate 		}
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 		/*
114*7c478bd9Sstevel@tonic-gate 		 * dup up the file descriptor if we have 0 - 2
115*7c478bd9Sstevel@tonic-gate 		 * to avoid problems with shells stdin/out/err
116*7c478bd9Sstevel@tonic-gate 		 */
117*7c478bd9Sstevel@tonic-gate 		i = 0;
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 		while (doorfd < 3) { /* we have a reserved fd */
120*7c478bd9Sstevel@tonic-gate 			tbc[i++] = doorfd;
121*7c478bd9Sstevel@tonic-gate 			if ((doorfd = dup(doorfd)) < 0) {
122*7c478bd9Sstevel@tonic-gate 				while (i--)
123*7c478bd9Sstevel@tonic-gate 				    (void) close(tbc[i]);
124*7c478bd9Sstevel@tonic-gate 				doorfd = -1;
125*7c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&_door_lock);
126*7c478bd9Sstevel@tonic-gate 				return (NOSERVER);
127*7c478bd9Sstevel@tonic-gate 			}
128*7c478bd9Sstevel@tonic-gate 		}
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 		while (i--)
131*7c478bd9Sstevel@tonic-gate 		    (void) close(tbc[i]);
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 		/*
134*7c478bd9Sstevel@tonic-gate 		 * mark this door descriptor as close on exec
135*7c478bd9Sstevel@tonic-gate 		 */
136*7c478bd9Sstevel@tonic-gate 		(void) fcntl(doorfd, F_SETFD, FD_CLOEXEC);
137*7c478bd9Sstevel@tonic-gate 		if (door_info(doorfd, &real_door) == -1) {
138*7c478bd9Sstevel@tonic-gate 			/*
139*7c478bd9Sstevel@tonic-gate 			 * we should close doorfd because we just opened it
140*7c478bd9Sstevel@tonic-gate 			 */
141*7c478bd9Sstevel@tonic-gate 			(void) close(doorfd);
142*7c478bd9Sstevel@tonic-gate 			doorfd = -1;
143*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&_door_lock);
144*7c478bd9Sstevel@tonic-gate 			return (NOSERVER);
145*7c478bd9Sstevel@tonic-gate 		}
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 		if ((real_door.di_attributes & DOOR_REVOKED) ||
148*7c478bd9Sstevel@tonic-gate 		    (real_door.di_data !=
149*7c478bd9Sstevel@tonic-gate 		    (door_ptr_t)LDAP_CACHE_DOOR_COOKIE)) {
150*7c478bd9Sstevel@tonic-gate 			(void) close(doorfd);
151*7c478bd9Sstevel@tonic-gate 			doorfd = -1;
152*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&_door_lock);
153*7c478bd9Sstevel@tonic-gate 			return (NOSERVER);
154*7c478bd9Sstevel@tonic-gate 		}
155*7c478bd9Sstevel@tonic-gate 	} else {
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 		if ((door_info(doorfd, &my_door) == -1) ||
158*7c478bd9Sstevel@tonic-gate 		    (my_door.di_data != (door_ptr_t)LDAP_CACHE_DOOR_COOKIE) ||
159*7c478bd9Sstevel@tonic-gate 			(my_door.di_uniquifier != real_door.di_uniquifier)) {
160*7c478bd9Sstevel@tonic-gate 				/*
161*7c478bd9Sstevel@tonic-gate 				 * don't close it -
162*7c478bd9Sstevel@tonic-gate 				 * someone else has clobbered fd
163*7c478bd9Sstevel@tonic-gate 				 */
164*7c478bd9Sstevel@tonic-gate 				doorfd = -1;
165*7c478bd9Sstevel@tonic-gate 				goto try_again;
166*7c478bd9Sstevel@tonic-gate 			}
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 		if (my_door.di_attributes & DOOR_REVOKED) {
169*7c478bd9Sstevel@tonic-gate 			(void) close(doorfd);
170*7c478bd9Sstevel@tonic-gate 			doorfd = -1;	/* try and restart connection */
171*7c478bd9Sstevel@tonic-gate 			goto try_again;
172*7c478bd9Sstevel@tonic-gate 		}
173*7c478bd9Sstevel@tonic-gate 	}
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&_door_lock);
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	param.rbuf = (char *)*dptr;
178*7c478bd9Sstevel@tonic-gate 	param.rsize = *ndata;
179*7c478bd9Sstevel@tonic-gate 	param.data_ptr = (char *)*dptr;
180*7c478bd9Sstevel@tonic-gate 	param.data_size = *adata;
181*7c478bd9Sstevel@tonic-gate 	param.desc_ptr = NULL;
182*7c478bd9Sstevel@tonic-gate 	param.desc_num = 0;
183*7c478bd9Sstevel@tonic-gate 	if (door_call(doorfd, &param) == -1) {
184*7c478bd9Sstevel@tonic-gate 		return (NOSERVER);
185*7c478bd9Sstevel@tonic-gate 	}
186*7c478bd9Sstevel@tonic-gate 	*adata = (int)param.data_size;
187*7c478bd9Sstevel@tonic-gate 	*ndata = (int)param.rsize;
188*7c478bd9Sstevel@tonic-gate 	*dptr = (ldap_data_t *)param.data_ptr;
189*7c478bd9Sstevel@tonic-gate 	if (*adata == 0 || *dptr == NULL) {
190*7c478bd9Sstevel@tonic-gate 		return (NOSERVER);
191*7c478bd9Sstevel@tonic-gate 	}
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	return ((*dptr)->ldap_ret.ldap_return_code);
194*7c478bd9Sstevel@tonic-gate }
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate /*
197*7c478bd9Sstevel@tonic-gate  *  routine to check if server is already running
198*7c478bd9Sstevel@tonic-gate  */
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate int
201*7c478bd9Sstevel@tonic-gate __ns_ldap_cache_ping()
202*7c478bd9Sstevel@tonic-gate {
203*7c478bd9Sstevel@tonic-gate 	ldap_data_t data;
204*7c478bd9Sstevel@tonic-gate 	ldap_data_t *dptr;
205*7c478bd9Sstevel@tonic-gate 	int ndata;
206*7c478bd9Sstevel@tonic-gate 	int adata;
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	data.ldap_call.ldap_callnumber = NULLCALL;
209*7c478bd9Sstevel@tonic-gate 	ndata = sizeof (data);
210*7c478bd9Sstevel@tonic-gate 	adata = sizeof (data);
211*7c478bd9Sstevel@tonic-gate 	dptr = &data;
212*7c478bd9Sstevel@tonic-gate 	return (__ns_ldap_trydoorcall(&dptr, &ndata, &adata));
213*7c478bd9Sstevel@tonic-gate }
214*7c478bd9Sstevel@tonic-gate 
215*7c478bd9Sstevel@tonic-gate #endif /* PIC */
216