xref: /onnv-gate/usr/src/lib/libnwam/common/libnwam_backend.c (revision 11767:8f30d0e611c6)
1*11767SAnurag.Maskey@Sun.COM /*
2*11767SAnurag.Maskey@Sun.COM  * CDDL HEADER START
3*11767SAnurag.Maskey@Sun.COM  *
4*11767SAnurag.Maskey@Sun.COM  * The contents of this file are subject to the terms of the
5*11767SAnurag.Maskey@Sun.COM  * Common Development and Distribution License (the "License").
6*11767SAnurag.Maskey@Sun.COM  * You may not use this file except in compliance with the License.
7*11767SAnurag.Maskey@Sun.COM  *
8*11767SAnurag.Maskey@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*11767SAnurag.Maskey@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*11767SAnurag.Maskey@Sun.COM  * See the License for the specific language governing permissions
11*11767SAnurag.Maskey@Sun.COM  * and limitations under the License.
12*11767SAnurag.Maskey@Sun.COM  *
13*11767SAnurag.Maskey@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*11767SAnurag.Maskey@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*11767SAnurag.Maskey@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*11767SAnurag.Maskey@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*11767SAnurag.Maskey@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*11767SAnurag.Maskey@Sun.COM  *
19*11767SAnurag.Maskey@Sun.COM  * CDDL HEADER END
20*11767SAnurag.Maskey@Sun.COM  */
21*11767SAnurag.Maskey@Sun.COM 
22*11767SAnurag.Maskey@Sun.COM /*
23*11767SAnurag.Maskey@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*11767SAnurag.Maskey@Sun.COM  * Use is subject to license terms.
25*11767SAnurag.Maskey@Sun.COM  */
26*11767SAnurag.Maskey@Sun.COM 
27*11767SAnurag.Maskey@Sun.COM #include <assert.h>
28*11767SAnurag.Maskey@Sun.COM #include <auth_attr.h>
29*11767SAnurag.Maskey@Sun.COM #include <auth_list.h>
30*11767SAnurag.Maskey@Sun.COM #include <bsm/adt.h>
31*11767SAnurag.Maskey@Sun.COM #include <bsm/adt_event.h>
32*11767SAnurag.Maskey@Sun.COM #include <ctype.h>
33*11767SAnurag.Maskey@Sun.COM #include <errno.h>
34*11767SAnurag.Maskey@Sun.COM #include <fcntl.h>
35*11767SAnurag.Maskey@Sun.COM #include <libgen.h>
36*11767SAnurag.Maskey@Sun.COM #include <pwd.h>
37*11767SAnurag.Maskey@Sun.COM #include <secdb.h>
38*11767SAnurag.Maskey@Sun.COM #include <stdlib.h>
39*11767SAnurag.Maskey@Sun.COM #include <sys/param.h>
40*11767SAnurag.Maskey@Sun.COM #include <sys/types.h>
41*11767SAnurag.Maskey@Sun.COM #include <sys/stat.h>
42*11767SAnurag.Maskey@Sun.COM #include <stdio.h>
43*11767SAnurag.Maskey@Sun.COM #include <strings.h>
44*11767SAnurag.Maskey@Sun.COM #include <unistd.h>
45*11767SAnurag.Maskey@Sun.COM 
46*11767SAnurag.Maskey@Sun.COM #include "libnwam_impl.h"
47*11767SAnurag.Maskey@Sun.COM #include <libnwam_priv.h>
48*11767SAnurag.Maskey@Sun.COM #include <libnwam.h>
49*11767SAnurag.Maskey@Sun.COM 
50*11767SAnurag.Maskey@Sun.COM /*
51*11767SAnurag.Maskey@Sun.COM  * Communicate with and implement library backend (running in netcfgd) to
52*11767SAnurag.Maskey@Sun.COM  * retrieve or change NWAM configuration.
53*11767SAnurag.Maskey@Sun.COM  */
54*11767SAnurag.Maskey@Sun.COM 
55*11767SAnurag.Maskey@Sun.COM static int backend_door_client_fd = -1;
56*11767SAnurag.Maskey@Sun.COM 
57*11767SAnurag.Maskey@Sun.COM /*
58*11767SAnurag.Maskey@Sun.COM  * Check if uid has proper auths.  flags is used to check auths for
59*11767SAnurag.Maskey@Sun.COM  * enable/disable of profiles and manipulation of Known WLANs.
60*11767SAnurag.Maskey@Sun.COM  */
61*11767SAnurag.Maskey@Sun.COM static nwam_error_t
nwam_check_auths(uid_t uid,boolean_t write,uint64_t flags)62*11767SAnurag.Maskey@Sun.COM nwam_check_auths(uid_t uid, boolean_t write, uint64_t flags)
63*11767SAnurag.Maskey@Sun.COM {
64*11767SAnurag.Maskey@Sun.COM 	struct passwd *pwd;
65*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err = NWAM_SUCCESS;
66*11767SAnurag.Maskey@Sun.COM 
67*11767SAnurag.Maskey@Sun.COM 	if ((pwd = getpwuid(uid)) == NULL) {
68*11767SAnurag.Maskey@Sun.COM 		endpwent();
69*11767SAnurag.Maskey@Sun.COM 		return (NWAM_PERMISSION_DENIED);
70*11767SAnurag.Maskey@Sun.COM 	}
71*11767SAnurag.Maskey@Sun.COM 
72*11767SAnurag.Maskey@Sun.COM 	if (flags & NWAM_FLAG_ENTITY_ENABLE) {
73*11767SAnurag.Maskey@Sun.COM 		/* Enabling/disabling profile - need SELECT auth */
74*11767SAnurag.Maskey@Sun.COM 		if (chkauthattr(AUTOCONF_SELECT_AUTH, pwd->pw_name) == 0)
75*11767SAnurag.Maskey@Sun.COM 			err = NWAM_PERMISSION_DENIED;
76*11767SAnurag.Maskey@Sun.COM 
77*11767SAnurag.Maskey@Sun.COM 	} else if (flags & NWAM_FLAG_ENTITY_KNOWN_WLAN) {
78*11767SAnurag.Maskey@Sun.COM 		/* Known WLAN activity - need WLAN auth */
79*11767SAnurag.Maskey@Sun.COM 		if (chkauthattr(AUTOCONF_WLAN_AUTH, pwd->pw_name) == 0)
80*11767SAnurag.Maskey@Sun.COM 			err = NWAM_PERMISSION_DENIED;
81*11767SAnurag.Maskey@Sun.COM 
82*11767SAnurag.Maskey@Sun.COM 	} else {
83*11767SAnurag.Maskey@Sun.COM 		/*
84*11767SAnurag.Maskey@Sun.COM 		 * First, check for WRITE, since it implies READ.  If this
85*11767SAnurag.Maskey@Sun.COM 		 * auth is not present, and write is true, fail, otherwise
86*11767SAnurag.Maskey@Sun.COM 		 * check for READ.
87*11767SAnurag.Maskey@Sun.COM 		 */
88*11767SAnurag.Maskey@Sun.COM 		if (chkauthattr(AUTOCONF_WRITE_AUTH, pwd->pw_name) == 0) {
89*11767SAnurag.Maskey@Sun.COM 			if (write) {
90*11767SAnurag.Maskey@Sun.COM 				err = NWAM_PERMISSION_DENIED;
91*11767SAnurag.Maskey@Sun.COM 			} else {
92*11767SAnurag.Maskey@Sun.COM 				if (chkauthattr(AUTOCONF_READ_AUTH,
93*11767SAnurag.Maskey@Sun.COM 				    pwd->pw_name) == 0)
94*11767SAnurag.Maskey@Sun.COM 					err = NWAM_PERMISSION_DENIED;
95*11767SAnurag.Maskey@Sun.COM 			}
96*11767SAnurag.Maskey@Sun.COM 		}
97*11767SAnurag.Maskey@Sun.COM 	}
98*11767SAnurag.Maskey@Sun.COM 
99*11767SAnurag.Maskey@Sun.COM 	endpwent();
100*11767SAnurag.Maskey@Sun.COM 	return (err);
101*11767SAnurag.Maskey@Sun.COM }
102*11767SAnurag.Maskey@Sun.COM 
103*11767SAnurag.Maskey@Sun.COM static nwam_error_t
nwam_create_backend_door_arg(nwam_backend_door_cmd_t cmd,const char * dbname,const char * objname,uint64_t flags,void * obj,nwam_backend_door_arg_t * arg)104*11767SAnurag.Maskey@Sun.COM nwam_create_backend_door_arg(nwam_backend_door_cmd_t cmd,
105*11767SAnurag.Maskey@Sun.COM     const char *dbname, const char *objname, uint64_t flags,
106*11767SAnurag.Maskey@Sun.COM     void *obj, nwam_backend_door_arg_t *arg)
107*11767SAnurag.Maskey@Sun.COM {
108*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
109*11767SAnurag.Maskey@Sun.COM 	size_t datalen = 0;
110*11767SAnurag.Maskey@Sun.COM 	caddr_t dataptr;
111*11767SAnurag.Maskey@Sun.COM 
112*11767SAnurag.Maskey@Sun.COM 	switch (cmd) {
113*11767SAnurag.Maskey@Sun.COM 	case NWAM_BACKEND_DOOR_CMD_READ_REQ:
114*11767SAnurag.Maskey@Sun.COM 		/*
115*11767SAnurag.Maskey@Sun.COM 		 * For a read request,  we want the full buffer to be
116*11767SAnurag.Maskey@Sun.COM 		 * available for the backend door to write to.
117*11767SAnurag.Maskey@Sun.COM 		 */
118*11767SAnurag.Maskey@Sun.COM 		datalen = NWAM_BACKEND_DOOR_ARG_SIZE;
119*11767SAnurag.Maskey@Sun.COM 		break;
120*11767SAnurag.Maskey@Sun.COM 
121*11767SAnurag.Maskey@Sun.COM 	case NWAM_BACKEND_DOOR_CMD_UPDATE_REQ:
122*11767SAnurag.Maskey@Sun.COM 		/*
123*11767SAnurag.Maskey@Sun.COM 		 * An update request may either specify an object list
124*11767SAnurag.Maskey@Sun.COM 		 * (which we pack into the buffer immediately after the
125*11767SAnurag.Maskey@Sun.COM 		 * backend door request) or may not specify an object
126*11767SAnurag.Maskey@Sun.COM 		 * (signifying a request to create the container of the
127*11767SAnurag.Maskey@Sun.COM 		 * object).
128*11767SAnurag.Maskey@Sun.COM 		 */
129*11767SAnurag.Maskey@Sun.COM 		if (obj == NULL) {
130*11767SAnurag.Maskey@Sun.COM 			datalen = 0;
131*11767SAnurag.Maskey@Sun.COM 			break;
132*11767SAnurag.Maskey@Sun.COM 		}
133*11767SAnurag.Maskey@Sun.COM 		/* Data immediately follows the descriptor */
134*11767SAnurag.Maskey@Sun.COM 		dataptr = (caddr_t)arg + sizeof (nwam_backend_door_arg_t);
135*11767SAnurag.Maskey@Sun.COM 		datalen = NWAM_BACKEND_DOOR_ARG_SIZE;
136*11767SAnurag.Maskey@Sun.COM 		/* pack object list for update request,  adjusting datalen */
137*11767SAnurag.Maskey@Sun.COM 		if ((err = nwam_pack_object_list(obj, (char **)&dataptr,
138*11767SAnurag.Maskey@Sun.COM 		    &datalen)) != NWAM_SUCCESS)
139*11767SAnurag.Maskey@Sun.COM 			return (err);
140*11767SAnurag.Maskey@Sun.COM 		break;
141*11767SAnurag.Maskey@Sun.COM 
142*11767SAnurag.Maskey@Sun.COM 	case NWAM_BACKEND_DOOR_CMD_REMOVE_REQ:
143*11767SAnurag.Maskey@Sun.COM 		/* A remove request has no associated object list. */
144*11767SAnurag.Maskey@Sun.COM 		datalen = 0;
145*11767SAnurag.Maskey@Sun.COM 		break;
146*11767SAnurag.Maskey@Sun.COM 
147*11767SAnurag.Maskey@Sun.COM 	default:
148*11767SAnurag.Maskey@Sun.COM 		return (NWAM_INVALID_ARG);
149*11767SAnurag.Maskey@Sun.COM 	}
150*11767SAnurag.Maskey@Sun.COM 
151*11767SAnurag.Maskey@Sun.COM 	arg->nwbda_cmd = cmd;
152*11767SAnurag.Maskey@Sun.COM 	arg->nwbda_flags = flags;
153*11767SAnurag.Maskey@Sun.COM 	arg->nwbda_datalen = datalen;
154*11767SAnurag.Maskey@Sun.COM 	arg->nwbda_result = NWAM_SUCCESS;
155*11767SAnurag.Maskey@Sun.COM 
156*11767SAnurag.Maskey@Sun.COM 	if (dbname != NULL)
157*11767SAnurag.Maskey@Sun.COM 		(void) strlcpy(arg->nwbda_dbname, dbname, MAXPATHLEN);
158*11767SAnurag.Maskey@Sun.COM 	else
159*11767SAnurag.Maskey@Sun.COM 		arg->nwbda_dbname[0] = '\0';
160*11767SAnurag.Maskey@Sun.COM 
161*11767SAnurag.Maskey@Sun.COM 	if (objname != NULL)
162*11767SAnurag.Maskey@Sun.COM 		(void) strlcpy(arg->nwbda_object, objname, NWAM_MAX_NAME_LEN);
163*11767SAnurag.Maskey@Sun.COM 	else
164*11767SAnurag.Maskey@Sun.COM 		arg->nwbda_object[0] = '\0';
165*11767SAnurag.Maskey@Sun.COM 
166*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
167*11767SAnurag.Maskey@Sun.COM }
168*11767SAnurag.Maskey@Sun.COM 
169*11767SAnurag.Maskey@Sun.COM /*
170*11767SAnurag.Maskey@Sun.COM  * If the arg datalen is non-zero,  unpack the object list associated with
171*11767SAnurag.Maskey@Sun.COM  * the backend door argument.
172*11767SAnurag.Maskey@Sun.COM  */
173*11767SAnurag.Maskey@Sun.COM static nwam_error_t
nwam_read_object_from_backend_door_arg(nwam_backend_door_arg_t * arg,char * dbname,char * name,void * objp)174*11767SAnurag.Maskey@Sun.COM nwam_read_object_from_backend_door_arg(nwam_backend_door_arg_t *arg,
175*11767SAnurag.Maskey@Sun.COM     char *dbname, char *name, void *objp)
176*11767SAnurag.Maskey@Sun.COM {
177*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
178*11767SAnurag.Maskey@Sun.COM 	caddr_t dataptr = (caddr_t)arg + sizeof (nwam_backend_door_arg_t);
179*11767SAnurag.Maskey@Sun.COM 
180*11767SAnurag.Maskey@Sun.COM 	if (arg->nwbda_result != NWAM_SUCCESS)
181*11767SAnurag.Maskey@Sun.COM 		return (arg->nwbda_result);
182*11767SAnurag.Maskey@Sun.COM 
183*11767SAnurag.Maskey@Sun.COM 	if (arg->nwbda_datalen > 0) {
184*11767SAnurag.Maskey@Sun.COM 		if ((err = nwam_unpack_object_list((char *)dataptr,
185*11767SAnurag.Maskey@Sun.COM 		    arg->nwbda_datalen, objp)) != NWAM_SUCCESS)
186*11767SAnurag.Maskey@Sun.COM 			return (err);
187*11767SAnurag.Maskey@Sun.COM 	} else {
188*11767SAnurag.Maskey@Sun.COM 		*((char **)objp) = NULL;
189*11767SAnurag.Maskey@Sun.COM 	}
190*11767SAnurag.Maskey@Sun.COM 
191*11767SAnurag.Maskey@Sun.COM 	/*
192*11767SAnurag.Maskey@Sun.COM 	 * If "dbname" and "name" are non-NULL, copy in the actual dbname
193*11767SAnurag.Maskey@Sun.COM 	 * and name values from the door arg since both may have been changed
194*11767SAnurag.Maskey@Sun.COM 	 * from case-insensitive to case-sensitive matches.  They will be the
195*11767SAnurag.Maskey@Sun.COM 	 * same length as they only differ in case.
196*11767SAnurag.Maskey@Sun.COM 	 */
197*11767SAnurag.Maskey@Sun.COM 	if (dbname != NULL && strcmp(dbname, arg->nwbda_dbname) != 0)
198*11767SAnurag.Maskey@Sun.COM 		(void) strlcpy(dbname, arg->nwbda_dbname, strlen(dbname) + 1);
199*11767SAnurag.Maskey@Sun.COM 	if (name != NULL && strcmp(name, arg->nwbda_object) != 0)
200*11767SAnurag.Maskey@Sun.COM 		(void) strlcpy(name, arg->nwbda_object, strlen(name) + 1);
201*11767SAnurag.Maskey@Sun.COM 
202*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
203*11767SAnurag.Maskey@Sun.COM }
204*11767SAnurag.Maskey@Sun.COM 
205*11767SAnurag.Maskey@Sun.COM /* ARGSUSED */
206*11767SAnurag.Maskey@Sun.COM void
nwam_backend_door_server(void * cookie,char * arg,size_t arg_size,door_desc_t * dp,uint_t ndesc)207*11767SAnurag.Maskey@Sun.COM nwam_backend_door_server(void *cookie, char *arg, size_t arg_size,
208*11767SAnurag.Maskey@Sun.COM     door_desc_t *dp, uint_t ndesc)
209*11767SAnurag.Maskey@Sun.COM {
210*11767SAnurag.Maskey@Sun.COM 	/* LINTED: alignment */
211*11767SAnurag.Maskey@Sun.COM 	nwam_backend_door_arg_t *req = (nwam_backend_door_arg_t *)arg;
212*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err;
213*11767SAnurag.Maskey@Sun.COM 	void *obj, *newobj = NULL;
214*11767SAnurag.Maskey@Sun.COM 	ucred_t *ucr = NULL;
215*11767SAnurag.Maskey@Sun.COM 	uid_t uid;
216*11767SAnurag.Maskey@Sun.COM 	boolean_t write = B_TRUE;
217*11767SAnurag.Maskey@Sun.COM 
218*11767SAnurag.Maskey@Sun.COM 	/* Check arg size */
219*11767SAnurag.Maskey@Sun.COM 	if (arg_size < sizeof (nwam_backend_door_arg_t)) {
220*11767SAnurag.Maskey@Sun.COM 		req->nwbda_result = NWAM_INVALID_ARG;
221*11767SAnurag.Maskey@Sun.COM 		(void) door_return((char *)req,
222*11767SAnurag.Maskey@Sun.COM 		    sizeof (nwam_backend_door_arg_t), NULL, 0);
223*11767SAnurag.Maskey@Sun.COM 	}
224*11767SAnurag.Maskey@Sun.COM 
225*11767SAnurag.Maskey@Sun.COM 	if (door_ucred(&ucr) != 0) {
226*11767SAnurag.Maskey@Sun.COM 		req->nwbda_result = NWAM_ERROR_INTERNAL;
227*11767SAnurag.Maskey@Sun.COM 		(void) door_return((char *)req, arg_size, NULL, 0);
228*11767SAnurag.Maskey@Sun.COM 	}
229*11767SAnurag.Maskey@Sun.COM 
230*11767SAnurag.Maskey@Sun.COM 	/* Check auths */
231*11767SAnurag.Maskey@Sun.COM 	uid = ucred_getruid(ucr);
232*11767SAnurag.Maskey@Sun.COM 
233*11767SAnurag.Maskey@Sun.COM 	if (req->nwbda_cmd == NWAM_BACKEND_DOOR_CMD_READ_REQ)
234*11767SAnurag.Maskey@Sun.COM 		write = B_FALSE;
235*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_check_auths(uid, write, req->nwbda_flags))
236*11767SAnurag.Maskey@Sun.COM 	    != NWAM_SUCCESS) {
237*11767SAnurag.Maskey@Sun.COM 		if (write) {
238*11767SAnurag.Maskey@Sun.COM 			nwam_record_audit_event(ucr,
239*11767SAnurag.Maskey@Sun.COM 			    req->nwbda_cmd == NWAM_BACKEND_DOOR_CMD_UPDATE_REQ ?
240*11767SAnurag.Maskey@Sun.COM 			    ADT_netcfg_update : ADT_netcfg_remove,
241*11767SAnurag.Maskey@Sun.COM 			    (char *)req->nwbda_object,
242*11767SAnurag.Maskey@Sun.COM 			    (char *)req->nwbda_dbname, ADT_FAILURE,
243*11767SAnurag.Maskey@Sun.COM 			    ADT_FAIL_VALUE_AUTH);
244*11767SAnurag.Maskey@Sun.COM 		}
245*11767SAnurag.Maskey@Sun.COM 		req->nwbda_result = err;
246*11767SAnurag.Maskey@Sun.COM 		goto door_return;
247*11767SAnurag.Maskey@Sun.COM 	}
248*11767SAnurag.Maskey@Sun.COM 
249*11767SAnurag.Maskey@Sun.COM 	switch (req->nwbda_cmd) {
250*11767SAnurag.Maskey@Sun.COM 	case NWAM_BACKEND_DOOR_CMD_READ_REQ:
251*11767SAnurag.Maskey@Sun.COM 		if ((req->nwbda_result = nwam_read_object_from_files_backend
252*11767SAnurag.Maskey@Sun.COM 		    (strlen(req->nwbda_dbname) > 0 ? req->nwbda_dbname : NULL,
253*11767SAnurag.Maskey@Sun.COM 		    strlen(req->nwbda_object) > 0 ? req->nwbda_object : NULL,
254*11767SAnurag.Maskey@Sun.COM 		    req->nwbda_flags, &newobj)) != NWAM_SUCCESS) {
255*11767SAnurag.Maskey@Sun.COM 			break;
256*11767SAnurag.Maskey@Sun.COM 		}
257*11767SAnurag.Maskey@Sun.COM 		if (newobj != NULL) {
258*11767SAnurag.Maskey@Sun.COM 			size_t datalen = arg_size -
259*11767SAnurag.Maskey@Sun.COM 			    sizeof (nwam_backend_door_arg_t);
260*11767SAnurag.Maskey@Sun.COM 			caddr_t dataptr = (caddr_t)req +
261*11767SAnurag.Maskey@Sun.COM 			    sizeof (nwam_backend_door_arg_t);
262*11767SAnurag.Maskey@Sun.COM 
263*11767SAnurag.Maskey@Sun.COM 			if ((req->nwbda_result = nwam_pack_object_list(newobj,
264*11767SAnurag.Maskey@Sun.COM 			    (char **)&dataptr, &datalen)) != NWAM_SUCCESS)
265*11767SAnurag.Maskey@Sun.COM 				req->nwbda_datalen = 0;
266*11767SAnurag.Maskey@Sun.COM 			else
267*11767SAnurag.Maskey@Sun.COM 				req->nwbda_datalen = datalen;
268*11767SAnurag.Maskey@Sun.COM 			nwam_free_object_list(newobj);
269*11767SAnurag.Maskey@Sun.COM 		} else {
270*11767SAnurag.Maskey@Sun.COM 			req->nwbda_datalen = 0;
271*11767SAnurag.Maskey@Sun.COM 		}
272*11767SAnurag.Maskey@Sun.COM 		break;
273*11767SAnurag.Maskey@Sun.COM 
274*11767SAnurag.Maskey@Sun.COM 	case NWAM_BACKEND_DOOR_CMD_UPDATE_REQ:
275*11767SAnurag.Maskey@Sun.COM 		if (req->nwbda_datalen == 0) {
276*11767SAnurag.Maskey@Sun.COM 			obj = NULL;
277*11767SAnurag.Maskey@Sun.COM 		} else {
278*11767SAnurag.Maskey@Sun.COM 			if ((req->nwbda_result =
279*11767SAnurag.Maskey@Sun.COM 			    nwam_read_object_from_backend_door_arg
280*11767SAnurag.Maskey@Sun.COM 			    (req, NULL, NULL, &obj)) != NWAM_SUCCESS)
281*11767SAnurag.Maskey@Sun.COM 				break;
282*11767SAnurag.Maskey@Sun.COM 		}
283*11767SAnurag.Maskey@Sun.COM 		req->nwbda_result = nwam_update_object_in_files_backend(
284*11767SAnurag.Maskey@Sun.COM 		    req->nwbda_dbname[0] == 0 ? NULL : req->nwbda_dbname,
285*11767SAnurag.Maskey@Sun.COM 		    req->nwbda_object[0] == 0 ? NULL : req->nwbda_object,
286*11767SAnurag.Maskey@Sun.COM 		    req->nwbda_flags, obj);
287*11767SAnurag.Maskey@Sun.COM 		nwam_free_object_list(obj);
288*11767SAnurag.Maskey@Sun.COM 		if (req->nwbda_result == NWAM_SUCCESS) {
289*11767SAnurag.Maskey@Sun.COM 			req->nwbda_datalen = 0;
290*11767SAnurag.Maskey@Sun.COM 			nwam_record_audit_event(ucr, ADT_netcfg_update,
291*11767SAnurag.Maskey@Sun.COM 			    (char *)req->nwbda_object,
292*11767SAnurag.Maskey@Sun.COM 			    (char *)req->nwbda_dbname, ADT_SUCCESS,
293*11767SAnurag.Maskey@Sun.COM 			    ADT_SUCCESS);
294*11767SAnurag.Maskey@Sun.COM 		}
295*11767SAnurag.Maskey@Sun.COM 		break;
296*11767SAnurag.Maskey@Sun.COM 
297*11767SAnurag.Maskey@Sun.COM 	case NWAM_BACKEND_DOOR_CMD_REMOVE_REQ:
298*11767SAnurag.Maskey@Sun.COM 		req->nwbda_result = nwam_remove_object_from_files_backend
299*11767SAnurag.Maskey@Sun.COM 		    (strlen(req->nwbda_dbname) > 0 ? req->nwbda_dbname : NULL,
300*11767SAnurag.Maskey@Sun.COM 		    strlen(req->nwbda_object) > 0 ? req->nwbda_object : NULL,
301*11767SAnurag.Maskey@Sun.COM 		    req->nwbda_flags);
302*11767SAnurag.Maskey@Sun.COM 		if (req->nwbda_result == NWAM_SUCCESS) {
303*11767SAnurag.Maskey@Sun.COM 			nwam_record_audit_event(ucr, ADT_netcfg_update,
304*11767SAnurag.Maskey@Sun.COM 			    (char *)req->nwbda_object,
305*11767SAnurag.Maskey@Sun.COM 			    (char *)req->nwbda_dbname, ADT_SUCCESS,
306*11767SAnurag.Maskey@Sun.COM 			    ADT_SUCCESS);
307*11767SAnurag.Maskey@Sun.COM 		}
308*11767SAnurag.Maskey@Sun.COM 		break;
309*11767SAnurag.Maskey@Sun.COM 
310*11767SAnurag.Maskey@Sun.COM 	default:
311*11767SAnurag.Maskey@Sun.COM 		req->nwbda_result = NWAM_INVALID_ARG;
312*11767SAnurag.Maskey@Sun.COM 		break;
313*11767SAnurag.Maskey@Sun.COM 	}
314*11767SAnurag.Maskey@Sun.COM 
315*11767SAnurag.Maskey@Sun.COM door_return:
316*11767SAnurag.Maskey@Sun.COM 	ucred_free(ucr);
317*11767SAnurag.Maskey@Sun.COM 
318*11767SAnurag.Maskey@Sun.COM 	(void) door_return((char *)req, arg_size, NULL, 0);
319*11767SAnurag.Maskey@Sun.COM }
320*11767SAnurag.Maskey@Sun.COM 
321*11767SAnurag.Maskey@Sun.COM static int backend_door_fd = -1;
322*11767SAnurag.Maskey@Sun.COM 
323*11767SAnurag.Maskey@Sun.COM void
nwam_backend_fini(void)324*11767SAnurag.Maskey@Sun.COM nwam_backend_fini(void)
325*11767SAnurag.Maskey@Sun.COM {
326*11767SAnurag.Maskey@Sun.COM 	if (backend_door_fd != -1) {
327*11767SAnurag.Maskey@Sun.COM 		(void) door_revoke(backend_door_fd);
328*11767SAnurag.Maskey@Sun.COM 		backend_door_fd = -1;
329*11767SAnurag.Maskey@Sun.COM 	}
330*11767SAnurag.Maskey@Sun.COM 	(void) unlink(NWAM_BACKEND_DOOR_FILE);
331*11767SAnurag.Maskey@Sun.COM }
332*11767SAnurag.Maskey@Sun.COM 
333*11767SAnurag.Maskey@Sun.COM nwam_error_t
nwam_backend_init(void)334*11767SAnurag.Maskey@Sun.COM nwam_backend_init(void)
335*11767SAnurag.Maskey@Sun.COM {
336*11767SAnurag.Maskey@Sun.COM 	int did;
337*11767SAnurag.Maskey@Sun.COM 	struct stat statbuf;
338*11767SAnurag.Maskey@Sun.COM 
339*11767SAnurag.Maskey@Sun.COM 	/* Create the door directory if it doesn't already exist */
340*11767SAnurag.Maskey@Sun.COM 	if (stat(NWAM_DOOR_DIR, &statbuf) < 0) {
341*11767SAnurag.Maskey@Sun.COM 		if (mkdir(NWAM_DOOR_DIR, (mode_t)0755) < 0)
342*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ERROR_BACKEND_INIT);
343*11767SAnurag.Maskey@Sun.COM 	} else {
344*11767SAnurag.Maskey@Sun.COM 		if ((statbuf.st_mode & S_IFMT) != S_IFDIR)
345*11767SAnurag.Maskey@Sun.COM 			return (NWAM_ERROR_BACKEND_INIT);
346*11767SAnurag.Maskey@Sun.COM 	}
347*11767SAnurag.Maskey@Sun.COM 
348*11767SAnurag.Maskey@Sun.COM 	if (chmod(NWAM_DOOR_DIR, 0755) < 0 ||
349*11767SAnurag.Maskey@Sun.COM 	    chown(NWAM_DOOR_DIR, UID_NETADM, GID_NETADM) < 0)
350*11767SAnurag.Maskey@Sun.COM 		return (NWAM_ERROR_BACKEND_INIT);
351*11767SAnurag.Maskey@Sun.COM 
352*11767SAnurag.Maskey@Sun.COM 	/* Do a low-overhead "touch" on the file that will be the door node. */
353*11767SAnurag.Maskey@Sun.COM 	did = open(NWAM_BACKEND_DOOR_FILE,
354*11767SAnurag.Maskey@Sun.COM 	    O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_NONBLOCK,
355*11767SAnurag.Maskey@Sun.COM 	    S_IRUSR | S_IRGRP | S_IROTH);
356*11767SAnurag.Maskey@Sun.COM 
357*11767SAnurag.Maskey@Sun.COM 	if (did != -1)
358*11767SAnurag.Maskey@Sun.COM 		(void) close(did);
359*11767SAnurag.Maskey@Sun.COM 	else if (errno != EEXIST)
360*11767SAnurag.Maskey@Sun.COM 		return (NWAM_ERROR_BACKEND_INIT);
361*11767SAnurag.Maskey@Sun.COM 
362*11767SAnurag.Maskey@Sun.COM 	/* Create the door. */
363*11767SAnurag.Maskey@Sun.COM 	backend_door_fd = door_create(nwam_backend_door_server, NULL,
364*11767SAnurag.Maskey@Sun.COM 	    DOOR_REFUSE_DESC);
365*11767SAnurag.Maskey@Sun.COM 	if (backend_door_fd == -1)
366*11767SAnurag.Maskey@Sun.COM 		return (NWAM_ERROR_BACKEND_INIT);
367*11767SAnurag.Maskey@Sun.COM 
368*11767SAnurag.Maskey@Sun.COM 	/* Attach the door to the file. */
369*11767SAnurag.Maskey@Sun.COM 	(void) fdetach(NWAM_BACKEND_DOOR_FILE);
370*11767SAnurag.Maskey@Sun.COM 	if (fattach(backend_door_fd, NWAM_BACKEND_DOOR_FILE) == -1) {
371*11767SAnurag.Maskey@Sun.COM 		(void) door_revoke(backend_door_fd);
372*11767SAnurag.Maskey@Sun.COM 		return (NWAM_ERROR_BACKEND_INIT);
373*11767SAnurag.Maskey@Sun.COM 	}
374*11767SAnurag.Maskey@Sun.COM 
375*11767SAnurag.Maskey@Sun.COM 	return (NWAM_SUCCESS);
376*11767SAnurag.Maskey@Sun.COM }
377*11767SAnurag.Maskey@Sun.COM 
378*11767SAnurag.Maskey@Sun.COM static nwam_error_t
nwam_backend_door_call(nwam_backend_door_cmd_t cmd,char * dbname,char * objname,uint64_t flags,void * obj)379*11767SAnurag.Maskey@Sun.COM nwam_backend_door_call(nwam_backend_door_cmd_t cmd, char *dbname,
380*11767SAnurag.Maskey@Sun.COM     char *objname, uint64_t flags, void *obj)
381*11767SAnurag.Maskey@Sun.COM {
382*11767SAnurag.Maskey@Sun.COM 	uchar_t reqbuf[NWAM_BACKEND_DOOR_ARG_SIZE];
383*11767SAnurag.Maskey@Sun.COM 	/* LINTED: alignment */
384*11767SAnurag.Maskey@Sun.COM 	nwam_backend_door_arg_t *req = (nwam_backend_door_arg_t *)&reqbuf;
385*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err, reserr;
386*11767SAnurag.Maskey@Sun.COM 
387*11767SAnurag.Maskey@Sun.COM 	if ((err = nwam_create_backend_door_arg(cmd, dbname, objname, flags,
388*11767SAnurag.Maskey@Sun.COM 	    obj, req)) != NWAM_SUCCESS)
389*11767SAnurag.Maskey@Sun.COM 		return (err);
390*11767SAnurag.Maskey@Sun.COM 
391*11767SAnurag.Maskey@Sun.COM 	if (nwam_make_door_call(NWAM_BACKEND_DOOR_FILE, &backend_door_client_fd,
392*11767SAnurag.Maskey@Sun.COM 	    req, sizeof (reqbuf)) != 0)
393*11767SAnurag.Maskey@Sun.COM 		return (NWAM_ERROR_BIND);
394*11767SAnurag.Maskey@Sun.COM 
395*11767SAnurag.Maskey@Sun.COM 	reserr = req->nwbda_result;
396*11767SAnurag.Maskey@Sun.COM 
397*11767SAnurag.Maskey@Sun.COM 	if (cmd == NWAM_BACKEND_DOOR_CMD_READ_REQ) {
398*11767SAnurag.Maskey@Sun.COM 		err = nwam_read_object_from_backend_door_arg(req, dbname,
399*11767SAnurag.Maskey@Sun.COM 		    objname, obj);
400*11767SAnurag.Maskey@Sun.COM 	}
401*11767SAnurag.Maskey@Sun.COM 
402*11767SAnurag.Maskey@Sun.COM 	return (err == NWAM_SUCCESS ? reserr : err);
403*11767SAnurag.Maskey@Sun.COM }
404*11767SAnurag.Maskey@Sun.COM 
405*11767SAnurag.Maskey@Sun.COM /*
406*11767SAnurag.Maskey@Sun.COM  * Read object specified by objname from backend dbname, retrieving an object
407*11767SAnurag.Maskey@Sun.COM  * list representation.
408*11767SAnurag.Maskey@Sun.COM  *
409*11767SAnurag.Maskey@Sun.COM  * If dbname is NULL, obj is a list of string arrays consisting of the list
410*11767SAnurag.Maskey@Sun.COM  * of backend dbnames.
411*11767SAnurag.Maskey@Sun.COM  *
412*11767SAnurag.Maskey@Sun.COM  * If objname is NULL, read all objects in the specified dbname and create
413*11767SAnurag.Maskey@Sun.COM  * an object list containing a string array which represents each object.
414*11767SAnurag.Maskey@Sun.COM  *
415*11767SAnurag.Maskey@Sun.COM  * Otherwise obj will point to a list of the properties for the object
416*11767SAnurag.Maskey@Sun.COM  * specified by objname in the backend dbname.
417*11767SAnurag.Maskey@Sun.COM  */
418*11767SAnurag.Maskey@Sun.COM /* ARGSUSED2 */
419*11767SAnurag.Maskey@Sun.COM nwam_error_t
nwam_read_object_from_backend(char * dbname,char * objname,uint64_t flags,void * obj)420*11767SAnurag.Maskey@Sun.COM nwam_read_object_from_backend(char *dbname, char *objname,
421*11767SAnurag.Maskey@Sun.COM     uint64_t flags, void *obj)
422*11767SAnurag.Maskey@Sun.COM {
423*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err = nwam_check_auths(getuid(), B_FALSE, flags);
424*11767SAnurag.Maskey@Sun.COM 
425*11767SAnurag.Maskey@Sun.COM 	if (err != NWAM_SUCCESS)
426*11767SAnurag.Maskey@Sun.COM 		return (err);
427*11767SAnurag.Maskey@Sun.COM 
428*11767SAnurag.Maskey@Sun.COM 	return (nwam_backend_door_call(NWAM_BACKEND_DOOR_CMD_READ_REQ,
429*11767SAnurag.Maskey@Sun.COM 	    dbname, objname, flags, obj));
430*11767SAnurag.Maskey@Sun.COM }
431*11767SAnurag.Maskey@Sun.COM 
432*11767SAnurag.Maskey@Sun.COM /*
433*11767SAnurag.Maskey@Sun.COM  * Read in all objects from backend dbname and update object corresponding
434*11767SAnurag.Maskey@Sun.COM  * to objname with properties recorded in proplist, writing the results to
435*11767SAnurag.Maskey@Sun.COM  * the backend dbname.
436*11767SAnurag.Maskey@Sun.COM  */
437*11767SAnurag.Maskey@Sun.COM nwam_error_t
nwam_update_object_in_backend(char * dbname,char * objname,uint64_t flags,void * obj)438*11767SAnurag.Maskey@Sun.COM nwam_update_object_in_backend(char *dbname, char *objname,
439*11767SAnurag.Maskey@Sun.COM     uint64_t flags, void *obj)
440*11767SAnurag.Maskey@Sun.COM {
441*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err = nwam_check_auths(getuid(), B_TRUE, flags);
442*11767SAnurag.Maskey@Sun.COM 
443*11767SAnurag.Maskey@Sun.COM 	if (err != NWAM_SUCCESS)
444*11767SAnurag.Maskey@Sun.COM 		return (err);
445*11767SAnurag.Maskey@Sun.COM 
446*11767SAnurag.Maskey@Sun.COM 	return (nwam_backend_door_call(NWAM_BACKEND_DOOR_CMD_UPDATE_REQ,
447*11767SAnurag.Maskey@Sun.COM 	    dbname, objname, flags, obj));
448*11767SAnurag.Maskey@Sun.COM }
449*11767SAnurag.Maskey@Sun.COM 
450*11767SAnurag.Maskey@Sun.COM /*
451*11767SAnurag.Maskey@Sun.COM  * Remove specified object from backend by reading in the list of objects,
452*11767SAnurag.Maskey@Sun.COM  * removing objname and writing the remainder.
453*11767SAnurag.Maskey@Sun.COM  *
454*11767SAnurag.Maskey@Sun.COM  * If objname is NULL, remove the backend dbname.
455*11767SAnurag.Maskey@Sun.COM  */
456*11767SAnurag.Maskey@Sun.COM nwam_error_t
nwam_remove_object_from_backend(char * dbname,char * objname,uint64_t flags)457*11767SAnurag.Maskey@Sun.COM nwam_remove_object_from_backend(char *dbname, char *objname, uint64_t flags)
458*11767SAnurag.Maskey@Sun.COM {
459*11767SAnurag.Maskey@Sun.COM 	nwam_error_t err = nwam_check_auths(getuid(), B_TRUE, flags);
460*11767SAnurag.Maskey@Sun.COM 
461*11767SAnurag.Maskey@Sun.COM 	if (err != NWAM_SUCCESS)
462*11767SAnurag.Maskey@Sun.COM 		return (err);
463*11767SAnurag.Maskey@Sun.COM 
464*11767SAnurag.Maskey@Sun.COM 	return (nwam_backend_door_call(NWAM_BACKEND_DOOR_CMD_REMOVE_REQ,
465*11767SAnurag.Maskey@Sun.COM 	    dbname, objname, flags, NULL));
466*11767SAnurag.Maskey@Sun.COM }
467