4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 #include <auth_attr.h>
29 #include <auth_list.h>
38 #include <sys/param.h>
39 #include <sys/types.h>
45 #include "libnwam_impl.h"
46 #include <libnwam_priv.h>
50 * Communicate with and implement library backend (running in netcfgd) to
51 * retrieve or change NWAM configuration.
54 static int backend_door_client_fd
= -1;
57 * Check if uid has proper auths. flags is used to check auths for
58 * enable/disable of profiles and manipulation of Known WLANs.
61 nwam_check_auths(uid_t uid
, boolean_t write
, uint64_t flags
)
64 nwam_error_t err
= NWAM_SUCCESS
;
66 if ((pwd
= getpwuid(uid
)) == NULL
) {
68 return (NWAM_PERMISSION_DENIED
);
71 if (flags
& NWAM_FLAG_ENTITY_ENABLE
) {
72 /* Enabling/disabling profile - need SELECT auth */
73 if (chkauthattr(AUTOCONF_SELECT_AUTH
, pwd
->pw_name
) == 0)
74 err
= NWAM_PERMISSION_DENIED
;
76 } else if (flags
& NWAM_FLAG_ENTITY_KNOWN_WLAN
) {
77 /* Known WLAN activity - need WLAN auth */
78 if (chkauthattr(AUTOCONF_WLAN_AUTH
, pwd
->pw_name
) == 0)
79 err
= NWAM_PERMISSION_DENIED
;
83 * First, check for WRITE, since it implies READ. If this
84 * auth is not present, and write is true, fail, otherwise
87 if (chkauthattr(AUTOCONF_WRITE_AUTH
, pwd
->pw_name
) == 0) {
89 err
= NWAM_PERMISSION_DENIED
;
91 if (chkauthattr(AUTOCONF_READ_AUTH
,
93 err
= NWAM_PERMISSION_DENIED
;
103 nwam_create_backend_door_arg(nwam_backend_door_cmd_t cmd
,
104 const char *dbname
, const char *objname
, uint64_t flags
,
105 void *obj
, nwam_backend_door_arg_t
*arg
)
112 case NWAM_BACKEND_DOOR_CMD_READ_REQ
:
114 * For a read request, we want the full buffer to be
115 * available for the backend door to write to.
117 datalen
= NWAM_BACKEND_DOOR_ARG_SIZE
;
120 case NWAM_BACKEND_DOOR_CMD_UPDATE_REQ
:
122 * An update request may either specify an object list
123 * (which we pack into the buffer immediately after the
124 * backend door request) or may not specify an object
125 * (signifying a request to create the container of the
132 /* Data immediately follows the descriptor */
133 dataptr
= (caddr_t
)arg
+ sizeof (nwam_backend_door_arg_t
);
134 datalen
= NWAM_BACKEND_DOOR_ARG_SIZE
;
135 /* pack object list for update request, adjusting datalen */
136 if ((err
= nwam_pack_object_list(obj
, (char **)&dataptr
,
137 &datalen
)) != NWAM_SUCCESS
)
141 case NWAM_BACKEND_DOOR_CMD_REMOVE_REQ
:
142 /* A remove request has no associated object list. */
147 return (NWAM_INVALID_ARG
);
150 arg
->nwbda_cmd
= cmd
;
151 arg
->nwbda_flags
= flags
;
152 arg
->nwbda_datalen
= datalen
;
153 arg
->nwbda_result
= NWAM_SUCCESS
;
156 (void) strlcpy(arg
->nwbda_dbname
, dbname
, MAXPATHLEN
);
158 arg
->nwbda_dbname
[0] = '\0';
161 (void) strlcpy(arg
->nwbda_object
, objname
, NWAM_MAX_NAME_LEN
);
163 arg
->nwbda_object
[0] = '\0';
165 return (NWAM_SUCCESS
);
169 * If the arg datalen is non-zero, unpack the object list associated with
170 * the backend door argument.
173 nwam_read_object_from_backend_door_arg(nwam_backend_door_arg_t
*arg
,
174 char *dbname
, char *name
, void *objp
)
177 caddr_t dataptr
= (caddr_t
)arg
+ sizeof (nwam_backend_door_arg_t
);
179 if (arg
->nwbda_result
!= NWAM_SUCCESS
)
180 return (arg
->nwbda_result
);
182 if (arg
->nwbda_datalen
> 0) {
183 if ((err
= nwam_unpack_object_list((char *)dataptr
,
184 arg
->nwbda_datalen
, objp
)) != NWAM_SUCCESS
)
187 *((char **)objp
) = NULL
;
191 * If "dbname" and "name" are non-NULL, copy in the actual dbname
192 * and name values from the door arg since both may have been changed
193 * from case-insensitive to case-sensitive matches. They will be the
194 * same length as they only differ in case.
196 if (dbname
!= NULL
&& strcmp(dbname
, arg
->nwbda_dbname
) != 0)
197 (void) strlcpy(dbname
, arg
->nwbda_dbname
, strlen(dbname
) + 1);
198 if (name
!= NULL
&& strcmp(name
, arg
->nwbda_object
) != 0)
199 (void) strlcpy(name
, arg
->nwbda_object
, strlen(name
) + 1);
201 return (NWAM_SUCCESS
);
206 nwam_backend_door_server(void *cookie
, char *arg
, size_t arg_size
,
207 door_desc_t
*dp
, uint_t ndesc
)
209 /* LINTED: alignment */
210 nwam_backend_door_arg_t
*req
= (nwam_backend_door_arg_t
*)arg
;
212 void *obj
, *newobj
= NULL
;
215 boolean_t write
= B_TRUE
;
218 if (arg_size
< sizeof (nwam_backend_door_arg_t
)) {
219 req
->nwbda_result
= NWAM_INVALID_ARG
;
220 (void) door_return((char *)req
,
221 sizeof (nwam_backend_door_arg_t
), NULL
, 0);
224 if (door_ucred(&ucr
) != 0) {
225 req
->nwbda_result
= NWAM_ERROR_INTERNAL
;
226 (void) door_return((char *)req
, arg_size
, NULL
, 0);
230 uid
= ucred_getruid(ucr
);
232 if (req
->nwbda_cmd
== NWAM_BACKEND_DOOR_CMD_READ_REQ
)
234 if ((err
= nwam_check_auths(uid
, write
, req
->nwbda_flags
))
236 req
->nwbda_result
= err
;
240 switch (req
->nwbda_cmd
) {
241 case NWAM_BACKEND_DOOR_CMD_READ_REQ
:
242 if ((req
->nwbda_result
= nwam_read_object_from_files_backend
243 (strlen(req
->nwbda_dbname
) > 0 ? req
->nwbda_dbname
: NULL
,
244 strlen(req
->nwbda_object
) > 0 ? req
->nwbda_object
: NULL
,
245 req
->nwbda_flags
, &newobj
)) != NWAM_SUCCESS
) {
248 if (newobj
!= NULL
) {
249 size_t datalen
= arg_size
-
250 sizeof (nwam_backend_door_arg_t
);
251 caddr_t dataptr
= (caddr_t
)req
+
252 sizeof (nwam_backend_door_arg_t
);
254 if ((req
->nwbda_result
= nwam_pack_object_list(newobj
,
255 (char **)&dataptr
, &datalen
)) != NWAM_SUCCESS
)
256 req
->nwbda_datalen
= 0;
258 req
->nwbda_datalen
= datalen
;
259 nwam_free_object_list(newobj
);
261 req
->nwbda_datalen
= 0;
265 case NWAM_BACKEND_DOOR_CMD_UPDATE_REQ
:
266 if (req
->nwbda_datalen
== 0) {
269 if ((req
->nwbda_result
=
270 nwam_read_object_from_backend_door_arg
271 (req
, NULL
, NULL
, &obj
)) != NWAM_SUCCESS
)
274 req
->nwbda_result
= nwam_update_object_in_files_backend(
275 req
->nwbda_dbname
[0] == 0 ? NULL
: req
->nwbda_dbname
,
276 req
->nwbda_object
[0] == 0 ? NULL
: req
->nwbda_object
,
277 req
->nwbda_flags
, obj
);
278 nwam_free_object_list(obj
);
279 if (req
->nwbda_result
== NWAM_SUCCESS
) {
280 req
->nwbda_datalen
= 0;
284 case NWAM_BACKEND_DOOR_CMD_REMOVE_REQ
:
285 req
->nwbda_result
= nwam_remove_object_from_files_backend
286 (strlen(req
->nwbda_dbname
) > 0 ? req
->nwbda_dbname
: NULL
,
287 strlen(req
->nwbda_object
) > 0 ? req
->nwbda_object
: NULL
,
292 req
->nwbda_result
= NWAM_INVALID_ARG
;
299 (void) door_return((char *)req
, arg_size
, NULL
, 0);
302 static int backend_door_fd
= -1;
305 nwam_backend_fini(void)
307 if (backend_door_fd
!= -1) {
308 (void) door_revoke(backend_door_fd
);
309 backend_door_fd
= -1;
311 (void) unlink(NWAM_BACKEND_DOOR_FILE
);
315 nwam_backend_init(void)
320 /* Create the door directory if it doesn't already exist */
321 if (stat(NWAM_DOOR_DIR
, &statbuf
) < 0) {
322 if (mkdir(NWAM_DOOR_DIR
, (mode_t
)0755) < 0)
323 return (NWAM_ERROR_BACKEND_INIT
);
325 if ((statbuf
.st_mode
& S_IFMT
) != S_IFDIR
)
326 return (NWAM_ERROR_BACKEND_INIT
);
329 if (chmod(NWAM_DOOR_DIR
, 0755) < 0 ||
330 chown(NWAM_DOOR_DIR
, UID_NETADM
, GID_NETADM
) < 0)
331 return (NWAM_ERROR_BACKEND_INIT
);
333 /* Do a low-overhead "touch" on the file that will be the door node. */
334 did
= open(NWAM_BACKEND_DOOR_FILE
,
335 O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
| O_NONBLOCK
,
336 S_IRUSR
| S_IRGRP
| S_IROTH
);
340 else if (errno
!= EEXIST
)
341 return (NWAM_ERROR_BACKEND_INIT
);
343 /* Create the door. */
344 backend_door_fd
= door_create(nwam_backend_door_server
, NULL
,
346 if (backend_door_fd
== -1)
347 return (NWAM_ERROR_BACKEND_INIT
);
349 /* Attach the door to the file. */
350 (void) fdetach(NWAM_BACKEND_DOOR_FILE
);
351 if (fattach(backend_door_fd
, NWAM_BACKEND_DOOR_FILE
) == -1) {
352 (void) door_revoke(backend_door_fd
);
353 return (NWAM_ERROR_BACKEND_INIT
);
356 return (NWAM_SUCCESS
);
360 nwam_backend_door_call(nwam_backend_door_cmd_t cmd
, char *dbname
,
361 char *objname
, uint64_t flags
, void *obj
)
363 uchar_t reqbuf
[NWAM_BACKEND_DOOR_ARG_SIZE
];
364 /* LINTED: alignment */
365 nwam_backend_door_arg_t
*req
= (nwam_backend_door_arg_t
*)&reqbuf
;
366 nwam_error_t err
, reserr
;
368 if ((err
= nwam_create_backend_door_arg(cmd
, dbname
, objname
, flags
,
369 obj
, req
)) != NWAM_SUCCESS
)
372 if (nwam_make_door_call(NWAM_BACKEND_DOOR_FILE
, &backend_door_client_fd
,
373 req
, sizeof (reqbuf
)) != 0)
374 return (NWAM_ERROR_BIND
);
376 reserr
= req
->nwbda_result
;
378 if (cmd
== NWAM_BACKEND_DOOR_CMD_READ_REQ
) {
379 err
= nwam_read_object_from_backend_door_arg(req
, dbname
,
383 return (err
== NWAM_SUCCESS
? reserr
: err
);
387 * Read object specified by objname from backend dbname, retrieving an object
388 * list representation.
390 * If dbname is NULL, obj is a list of string arrays consisting of the list
391 * of backend dbnames.
393 * If objname is NULL, read all objects in the specified dbname and create
394 * an object list containing a string array which represents each object.
396 * Otherwise obj will point to a list of the properties for the object
397 * specified by objname in the backend dbname.
401 nwam_read_object_from_backend(char *dbname
, char *objname
,
402 uint64_t flags
, void *obj
)
404 nwam_error_t err
= nwam_check_auths(getuid(), B_FALSE
, flags
);
406 if (err
!= NWAM_SUCCESS
)
409 return (nwam_backend_door_call(NWAM_BACKEND_DOOR_CMD_READ_REQ
,
410 dbname
, objname
, flags
, obj
));
414 * Read in all objects from backend dbname and update object corresponding
415 * to objname with properties recorded in proplist, writing the results to
416 * the backend dbname.
419 nwam_update_object_in_backend(char *dbname
, char *objname
,
420 uint64_t flags
, void *obj
)
422 nwam_error_t err
= nwam_check_auths(getuid(), B_TRUE
, flags
);
424 if (err
!= NWAM_SUCCESS
)
427 return (nwam_backend_door_call(NWAM_BACKEND_DOOR_CMD_UPDATE_REQ
,
428 dbname
, objname
, flags
, obj
));
432 * Remove specified object from backend by reading in the list of objects,
433 * removing objname and writing the remainder.
435 * If objname is NULL, remove the backend dbname.
438 nwam_remove_object_from_backend(char *dbname
, char *objname
, uint64_t flags
)
440 nwam_error_t err
= nwam_check_auths(getuid(), B_TRUE
, flags
);
442 if (err
!= NWAM_SUCCESS
)
445 return (nwam_backend_door_call(NWAM_BACKEND_DOOR_CMD_REMOVE_REQ
,
446 dbname
, objname
, flags
, NULL
));