1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <auth_attr.h> 27 #include <auth_list.h> 28 #include <bsm/adt.h> 29 #include <bsm/adt_event.h> 30 #include <door.h> 31 #include <errno.h> 32 #include <fcntl.h> 33 #include <libnwam_priv.h> 34 #include <libuutil.h> 35 #include <pthread.h> 36 #include <pwd.h> 37 #include <stdlib.h> 38 #include <sys/stat.h> 39 40 #include <sys/mman.h> 41 #include <syslog.h> 42 #include <unistd.h> 43 44 #include "conditions.h" 45 #include "events.h" 46 #include "ncp.h" 47 #include "ncu.h" 48 #include "objects.h" 49 #include "util.h" 50 51 /* 52 * door_if.c 53 * This file contains functions which implement the command interface to 54 * nwam via the door NWAM_DOOR. Doors provide a LPC mechanism that allows 55 * for threads in one process to cause code to execute in another process. 56 * Doors also provide the ability to pass data and file descriptors. See 57 * libdoor(3LIB) for more information. 58 * 59 * This file exports two functions, nwamd_door_initialize() (which sets up 60 * the door) and nwamd_door_fini(), which removes it. 61 * 62 * It sets up the static routine nwamd_door_switch() to be called when a client 63 * calls the door (via door_call(3C)). The structure nwam_request_t is 64 * passed as data and contains data to specify the type of action requested 65 * and any data need to meet that request. A table consisting of entries 66 * for each door request, the associated authorization and the function to 67 * process that request is used to handle the various requests. 68 */ 69 70 struct nwamd_door_req_entry 71 { 72 int ndre_type; 73 char *ndre_auth; 74 nwam_error_t (*ndre_fn)(nwamd_door_arg_t *, ucred_t *, struct passwd *); 75 }; 76 77 static nwam_error_t nwamd_door_req_event_register(nwamd_door_arg_t *, 78 ucred_t *, struct passwd *); 79 static nwam_error_t nwamd_door_req_event_unregister(nwamd_door_arg_t *, 80 ucred_t *, struct passwd *); 81 static nwam_error_t nwamd_door_req_wlan_scan(nwamd_door_arg_t *, 82 ucred_t *, struct passwd *); 83 static nwam_error_t nwamd_door_req_wlan_scan_results(nwamd_door_arg_t *, 84 ucred_t *, struct passwd *); 85 static nwam_error_t nwamd_door_req_wlan_select(nwamd_door_arg_t *, 86 ucred_t *, struct passwd *); 87 static nwam_error_t nwamd_door_req_wlan_set_key(nwamd_door_arg_t *, 88 ucred_t *, struct passwd *); 89 static nwam_error_t nwamd_door_req_action(nwamd_door_arg_t *, 90 ucred_t *, struct passwd *); 91 static nwam_error_t nwamd_door_req_state(nwamd_door_arg_t *, 92 ucred_t *, struct passwd *); 93 static nwam_error_t nwamd_door_req_priority_group(nwamd_door_arg_t *, 94 ucred_t *, struct passwd *); 95 96 /* 97 * This table defines the set of door commands available, the required 98 * authorizations for each command, and the function that carries out 99 * each command. 100 */ 101 struct nwamd_door_req_entry door_req_table[] = 102 { 103 104 { NWAM_REQUEST_TYPE_EVENT_REGISTER, AUTOCONF_READ_AUTH, 105 nwamd_door_req_event_register }, 106 { NWAM_REQUEST_TYPE_EVENT_UNREGISTER, AUTOCONF_READ_AUTH, 107 nwamd_door_req_event_unregister }, 108 { NWAM_REQUEST_TYPE_WLAN_SCAN, AUTOCONF_WLAN_AUTH, 109 nwamd_door_req_wlan_scan }, 110 { NWAM_REQUEST_TYPE_WLAN_SCAN_RESULTS, AUTOCONF_READ_AUTH, 111 nwamd_door_req_wlan_scan_results }, 112 { NWAM_REQUEST_TYPE_WLAN_SELECT, AUTOCONF_WLAN_AUTH, 113 nwamd_door_req_wlan_select }, 114 { NWAM_REQUEST_TYPE_WLAN_SET_KEY, AUTOCONF_WLAN_AUTH, 115 nwamd_door_req_wlan_set_key }, 116 /* Requires WRITE, SELECT or WLAN auth depending on action */ 117 { NWAM_REQUEST_TYPE_ACTION, NULL, nwamd_door_req_action }, 118 { NWAM_REQUEST_TYPE_STATE, AUTOCONF_READ_AUTH, 119 nwamd_door_req_state }, 120 { NWAM_REQUEST_TYPE_PRIORITY_GROUP, AUTOCONF_READ_AUTH, 121 nwamd_door_req_priority_group }, 122 }; 123 124 int doorfd = -1; 125 126 /* ARGSUSED */ 127 static nwam_error_t 128 nwamd_door_req_event_register(nwamd_door_arg_t *req, ucred_t *ucr, 129 struct passwd *pwd) 130 { 131 nwam_error_t err; 132 133 err = nwam_event_queue_init 134 (req->nwda_data.nwdad_register_info.nwdad_name); 135 if (err != NWAM_SUCCESS) { 136 nlog(LOG_ERR, "nwamd_door_req_event_register: " 137 "could not register events for %s", 138 req->nwda_data.nwdad_register_info.nwdad_name); 139 } 140 141 return (err); 142 } 143 144 /* ARGSUSED */ 145 static nwam_error_t 146 nwamd_door_req_event_unregister(nwamd_door_arg_t *req, ucred_t *ucr, 147 struct passwd *pwd) 148 { 149 nwam_event_queue_fini(req->nwda_data.nwdad_register_info.nwdad_name); 150 151 return (NWAM_SUCCESS); 152 } 153 154 /* ARGSUSED1 */ 155 static nwam_error_t 156 nwamd_door_req_wlan_scan(nwamd_door_arg_t *req, ucred_t *ucr, 157 struct passwd *pwd) 158 { 159 nlog(LOG_DEBUG, 160 "nwamd_door_req_wlan_scan: processing WLAN scan request: " 161 "link %s", req->nwda_data.nwdad_wlan_info.nwdad_name); 162 163 return (nwamd_wlan_scan(req->nwda_data.nwdad_wlan_info.nwdad_name)); 164 } 165 166 /* ARGSUSED */ 167 static nwam_error_t 168 nwamd_door_req_wlan_scan_results(nwamd_door_arg_t *req, ucred_t *ucr, 169 struct passwd *pwd) 170 { 171 nwamd_object_t obj; 172 nwamd_ncu_t *ncu; 173 nwamd_link_t *link; 174 uint_t num_wlans; 175 176 nlog(LOG_DEBUG, "nwamd_door_req_wlan_scan_results: processing WLAN " 177 "scan results request: link %s", 178 req->nwda_data.nwdad_wlan_info.nwdad_name); 179 180 obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_LINK, 181 req->nwda_data.nwdad_wlan_info.nwdad_name); 182 if (obj == NULL) { 183 nlog(LOG_ERR, 184 "nwamd_door_req_wlan_scan_results: link %s not found", 185 req->nwda_data.nwdad_wlan_info.nwdad_name); 186 return (NWAM_ENTITY_NOT_FOUND); 187 } 188 189 ncu = obj->nwamd_object_data; 190 link = &ncu->ncu_link; 191 num_wlans = link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr_num; 192 193 if (num_wlans > 0) { 194 (void) memcpy 195 (req->nwda_data.nwdad_wlan_info.nwdad_wlans, 196 link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr, 197 num_wlans * sizeof (nwam_wlan_t)); 198 } 199 req->nwda_data.nwdad_wlan_info.nwdad_num_wlans = num_wlans; 200 nlog(LOG_DEBUG, 201 "nwamd_door_req_wlan_scan_results: returning %d scan results", 202 num_wlans); 203 nwamd_object_release(obj); 204 205 return (NWAM_SUCCESS); 206 } 207 208 /* ARGSUSED */ 209 static nwam_error_t 210 nwamd_door_req_wlan_select(nwamd_door_arg_t *req, ucred_t *ucr, 211 struct passwd *pwd) 212 { 213 nlog(LOG_DEBUG, 214 "nwamd_door_req_wlan_select: processing WLAN selection : " 215 "link %s ESSID %s , BSSID %s", 216 req->nwda_data.nwdad_wlan_info.nwdad_name, 217 req->nwda_data.nwdad_wlan_info.nwdad_essid, 218 req->nwda_data.nwdad_wlan_info.nwdad_bssid); 219 return (nwamd_wlan_select 220 (req->nwda_data.nwdad_wlan_info.nwdad_name, 221 req->nwda_data.nwdad_wlan_info.nwdad_essid, 222 req->nwda_data.nwdad_wlan_info.nwdad_bssid, 223 req->nwda_data.nwdad_wlan_info.nwdad_security_mode, 224 req->nwda_data.nwdad_wlan_info.nwdad_add_to_known_wlans)); 225 } 226 227 /* ARGSUSED */ 228 static nwam_error_t 229 nwamd_door_req_wlan_set_key(nwamd_door_arg_t *req, ucred_t *ucr, 230 struct passwd *pwd) 231 { 232 nlog(LOG_DEBUG, 233 "nwamd_door_req_wlan_set_key: processing WLAN key input : " 234 "link %s ESSID %s BSSID %s", 235 req->nwda_data.nwdad_wlan_info.nwdad_name, 236 req->nwda_data.nwdad_wlan_info.nwdad_essid, 237 req->nwda_data.nwdad_wlan_info.nwdad_bssid); 238 return (nwamd_wlan_set_key 239 (req->nwda_data.nwdad_wlan_info.nwdad_name, 240 req->nwda_data.nwdad_wlan_info.nwdad_essid, NULL, 241 req->nwda_data.nwdad_wlan_info.nwdad_security_mode, 242 req->nwda_data.nwdad_wlan_info.nwdad_keyslot, 243 req->nwda_data.nwdad_wlan_info.nwdad_key)); 244 } 245 246 static nwam_error_t 247 nwamd_door_req_action(nwamd_door_arg_t *req, ucred_t *ucr, struct passwd *pwd) 248 { 249 char name[NWAM_MAX_NAME_LEN]; 250 char parent[NWAM_MAX_NAME_LEN]; 251 nwam_action_t action = req->nwda_data.nwdad_object_action.nwdad_action; 252 nwam_object_type_t object_type = 253 req->nwda_data.nwdad_object_action.nwdad_object_type; 254 char *obj_type_str = (char *)nwam_object_type_to_string(object_type); 255 nwam_error_t err; 256 257 /* Check for name, parent overrun */ 258 if (strlcpy(name, req->nwda_data.nwdad_object_action.nwdad_name, 259 sizeof (name)) == NWAM_MAX_NAME_LEN || 260 strlcpy(parent, req->nwda_data.nwdad_object_action.nwdad_parent, 261 sizeof (parent)) == NWAM_MAX_NAME_LEN) 262 return (NWAM_INVALID_ARG); 263 264 /* 265 * Check authorizations against actions. 266 * - ENABLE/DISABLE requires SELECT auth 267 * - ADD/DESTROY/REFRESH on Known WLANs requires WLAN auth 268 * - ADD/DESTROY on other objects requires WRITE auth 269 * - REFRESH on other objects requires either WRITE or SELECT auth 270 */ 271 if (action == NWAM_ACTION_ENABLE || action == NWAM_ACTION_DISABLE) { 272 if (chkauthattr(AUTOCONF_SELECT_AUTH, pwd->pw_name) == 0) { 273 nwam_record_audit_event(ucr, 274 action == NWAM_ACTION_ENABLE ? 275 ADT_nwam_enable : ADT_nwam_disable, name, 276 obj_type_str, ADT_FAILURE, ADT_FAIL_VALUE_AUTH); 277 nlog(LOG_ERR, "nwamd_door_req_action: " 278 "need %s for %s action", AUTOCONF_SELECT_AUTH, 279 nwam_action_to_string(action)); 280 return (NWAM_PERMISSION_DENIED); 281 } 282 } else if (object_type == NWAM_OBJECT_TYPE_KNOWN_WLAN) { 283 if (chkauthattr(AUTOCONF_WLAN_AUTH, pwd->pw_name) == 0) { 284 nlog(LOG_ERR, "nwamd_door_req_action: " 285 "need %s for %s action on Known WLAN", 286 AUTOCONF_WLAN_AUTH, nwam_action_to_string(action)); 287 return (NWAM_PERMISSION_DENIED); 288 } 289 } else if (action == NWAM_ACTION_ADD || action == NWAM_ACTION_DESTROY) { 290 if (chkauthattr(AUTOCONF_WRITE_AUTH, pwd->pw_name) == 0) { 291 nlog(LOG_ERR, "nwamd_door_req_action: " 292 "need %s for %s action", AUTOCONF_WRITE_AUTH, 293 nwam_action_to_string(action)); 294 return (NWAM_PERMISSION_DENIED); 295 } 296 } else if (action == NWAM_ACTION_REFRESH) { 297 if (chkauthattr(AUTOCONF_WRITE_AUTH, pwd->pw_name) == 0 && 298 chkauthattr(AUTOCONF_SELECT_AUTH, pwd->pw_name) == 0) { 299 nlog(LOG_ERR, "nwamd_door_req_action: " 300 "need either %s or %s for %s action", 301 AUTOCONF_WRITE_AUTH, AUTOCONF_SELECT_AUTH, 302 nwam_action_to_string(action)); 303 return (NWAM_PERMISSION_DENIED); 304 } 305 } else { 306 nlog(LOG_ERR, "nwamd_door_req_action: received unknown " 307 "action %d (%s)", action, nwam_action_to_string(action)); 308 return (NWAM_INVALID_ARG); 309 } 310 311 switch (action) { 312 case NWAM_ACTION_ENABLE: 313 case NWAM_ACTION_DISABLE: 314 nwam_record_audit_event(ucr, 315 action == NWAM_ACTION_ENABLE ? 316 ADT_nwam_enable : ADT_nwam_disable, name, 317 obj_type_str, ADT_SUCCESS, ADT_SUCCESS); 318 319 nlog(LOG_DEBUG, "nwamd_door_req_action: %s %s", 320 action == NWAM_ACTION_ENABLE ? "enabling" : "disabling", 321 name); 322 323 switch (object_type) { 324 case NWAM_OBJECT_TYPE_ENM: 325 err = nwamd_enm_action(name, action); 326 break; 327 case NWAM_OBJECT_TYPE_LOC: 328 err = nwamd_loc_action(name, action); 329 break; 330 case NWAM_OBJECT_TYPE_NCU: 331 err = nwamd_ncu_action(name, parent, action); 332 break; 333 case NWAM_OBJECT_TYPE_NCP: 334 if (action == NWAM_ACTION_DISABLE) { 335 nlog(LOG_ERR, "nwamd_door_req_action: " 336 "NCPs cannot be disabled"); 337 err = NWAM_INVALID_ARG; 338 } else { 339 err = nwamd_ncp_action(name, action); 340 } 341 break; 342 default: 343 nlog(LOG_ERR, "nwamd_door_req_action: received invalid " 344 "object type %d (%s)", object_type, 345 nwam_object_type_to_string(object_type)); 346 return (NWAM_INVALID_ARG); 347 } 348 break; 349 350 case NWAM_ACTION_ADD: 351 case NWAM_ACTION_REFRESH: 352 /* 353 * Called whenever an object is committed in the library. 354 * Reread that committed object into nwamd. 355 */ 356 nlog(LOG_DEBUG, "door_switch: refreshing %s", name); 357 358 switch (object_type) { 359 case NWAM_OBJECT_TYPE_ENM: 360 err = nwamd_enm_action(name, action); 361 break; 362 case NWAM_OBJECT_TYPE_LOC: 363 err = nwamd_loc_action(name, action); 364 break; 365 case NWAM_OBJECT_TYPE_KNOWN_WLAN: 366 err = nwamd_known_wlan_action(name, action); 367 break; 368 case NWAM_OBJECT_TYPE_NCU: 369 err = nwamd_ncu_action(name, parent, action); 370 break; 371 case NWAM_OBJECT_TYPE_NCP: 372 err = nwamd_ncp_action(name, action); 373 break; 374 default: 375 nlog(LOG_ERR, "nwamd_door_req_action: received invalid " 376 "object type %d (%s)", object_type, 377 nwam_object_type_to_string(object_type)); 378 err = NWAM_INVALID_ARG; 379 break; 380 } 381 break; 382 383 case NWAM_ACTION_DESTROY: 384 /* Object was destroyed, remove from nwamd */ 385 nlog(LOG_DEBUG, "door_switch: removing %s", name); 386 387 switch (object_type) { 388 case NWAM_OBJECT_TYPE_ENM: 389 err = nwamd_enm_action(name, NWAM_ACTION_DESTROY); 390 break; 391 case NWAM_OBJECT_TYPE_LOC: 392 err = nwamd_loc_action(name, NWAM_ACTION_DESTROY); 393 break; 394 case NWAM_OBJECT_TYPE_KNOWN_WLAN: 395 err = nwamd_known_wlan_action(name, 396 NWAM_ACTION_DESTROY); 397 break; 398 case NWAM_OBJECT_TYPE_NCU: 399 err = nwamd_ncu_action(name, parent, 400 NWAM_ACTION_DESTROY); 401 break; 402 case NWAM_OBJECT_TYPE_NCP: 403 (void) pthread_mutex_lock(&active_ncp_mutex); 404 if (strcmp(name, active_ncp) == 0) { 405 nlog(LOG_ERR, "nwamd_door_req_action: %s is " 406 "active, cannot destroy", parent); 407 err = NWAM_ENTITY_IN_USE; 408 } else { 409 err = nwamd_ncp_action(name, 410 NWAM_ACTION_DESTROY); 411 } 412 (void) pthread_mutex_unlock(&active_ncp_mutex); 413 break; 414 default: 415 nlog(LOG_ERR, "nwamd_door_req_action: received invalid " 416 "object type %d (%s)", object_type, 417 nwam_object_type_to_string(object_type)); 418 err = NWAM_INVALID_ARG; 419 break; 420 } 421 break; 422 423 default: 424 nlog(LOG_ERR, "nwamd_door_req_action: received unknown " 425 "action %d (%s)", action, nwam_action_to_string(action)); 426 err = NWAM_INVALID_ARG; 427 break; 428 } 429 430 if (err == NWAM_SUCCESS) { 431 /* 432 * At this point, we've successfully carried out an action. 433 * Configuration may have changed, so we need to recheck 434 * conditions, however we want to avoid a flurry of condition 435 * check events, so we enqueue a triggered condition check 436 * if none is due in the next few seconds. 437 */ 438 nwamd_create_triggered_condition_check_event(NEXT_FEW_SECONDS); 439 } else { 440 nlog(LOG_ERR, "nwamd_door_req_action: could not carry out " 441 "%s action on %s: %s", nwam_action_to_string(action), 442 name, nwam_strerror(err)); 443 } 444 445 return (err); 446 } 447 448 /* ARGSUSED */ 449 static nwam_error_t 450 nwamd_door_req_state(nwamd_door_arg_t *req, ucred_t *ucr, struct passwd *pwd) 451 { 452 char name[NWAM_MAX_NAME_LEN]; 453 nwamd_object_t obj; 454 nwam_object_type_t object_type = 455 req->nwda_data.nwdad_object_state.nwdad_object_type; 456 boolean_t is_active = B_FALSE; 457 458 /* Check for name, parent overrun */ 459 if (strlcpy(name, req->nwda_data.nwdad_object_state.nwdad_name, 460 sizeof (name)) == NWAM_MAX_NAME_LEN) 461 return (NWAM_INVALID_ARG); 462 463 switch (object_type) { 464 case NWAM_OBJECT_TYPE_NCP: 465 (void) pthread_mutex_lock(&active_ncp_mutex); 466 is_active = (strcmp(active_ncp, name) == 0); 467 (void) pthread_mutex_unlock(&active_ncp_mutex); 468 if (is_active) { 469 req->nwda_data.nwdad_object_state.nwdad_state = 470 NWAM_STATE_ONLINE; 471 req->nwda_data.nwdad_object_state. 472 nwdad_aux_state = NWAM_AUX_STATE_ACTIVE; 473 nlog(LOG_DEBUG, 474 "nwamd_door_req_state: NCP %s is active", name); 475 } else { 476 req->nwda_data.nwdad_object_state.nwdad_state = 477 NWAM_STATE_DISABLED; 478 req->nwda_data.nwdad_object_state. 479 nwdad_aux_state = 480 NWAM_AUX_STATE_MANUAL_DISABLE; 481 nlog(LOG_DEBUG, "nwamd_door_req_state: " 482 "NCP %s is inactive", name); 483 } 484 break; 485 486 case NWAM_OBJECT_TYPE_LOC: 487 case NWAM_OBJECT_TYPE_NCU: 488 case NWAM_OBJECT_TYPE_ENM: 489 obj = nwamd_object_find(object_type, name); 490 if (obj == NULL) { 491 nlog(LOG_ERR, "nwamd_door_req_state: %s %s not found", 492 nwam_object_type_to_string(object_type), name); 493 return (NWAM_ENTITY_NOT_FOUND); 494 } 495 nlog(LOG_DEBUG, "nwamd_door_req_state: %s %s is %s", 496 nwam_object_type_to_string(object_type), name, 497 nwam_state_to_string(obj->nwamd_object_state)); 498 req->nwda_data.nwdad_object_state.nwdad_state = 499 obj->nwamd_object_state; 500 req->nwda_data.nwdad_object_state.nwdad_aux_state = 501 obj->nwamd_object_aux_state; 502 nwamd_object_release(obj); 503 break; 504 505 default: 506 nlog(LOG_ERR, "nwamd_door_req_state: received invalid " 507 "object type %d (%s)", object_type, 508 nwam_object_type_to_string(object_type)); 509 req->nwda_status = NWAM_REQUEST_STATUS_UNKNOWN; 510 return (NWAM_INVALID_ARG); 511 } 512 513 return (NWAM_SUCCESS); 514 } 515 516 /* ARGSUSED */ 517 static nwam_error_t 518 nwamd_door_req_priority_group(nwamd_door_arg_t *req, ucred_t *ucr, 519 struct passwd *pwd) 520 { 521 (void) pthread_mutex_lock(&active_ncp_mutex); 522 nlog(LOG_DEBUG, "nwamd_door_req_priority_group: " 523 "retrieving active priority-group: %d", 524 current_ncu_priority_group); 525 req->nwda_data.nwdad_priority_group_info.nwdad_priority = 526 current_ncu_priority_group; 527 (void) pthread_mutex_unlock(&active_ncp_mutex); 528 529 return (NWAM_SUCCESS); 530 } 531 532 /* ARGSUSED */ 533 static void 534 nwamd_door_switch(void *cookie, char *argp, size_t arg_size, door_desc_t *dp, 535 uint_t n_desc) 536 { 537 nwamd_door_arg_t *req; 538 ucred_t *ucr = NULL; 539 uid_t uid; 540 struct passwd *pwd = NULL; 541 boolean_t found = B_FALSE; 542 int i; 543 544 /* LINTED E_BAD_PTR_CAST_ALIGN */ 545 req = (nwamd_door_arg_t *)argp; 546 req->nwda_error = NWAM_SUCCESS; 547 548 if (door_ucred(&ucr) != 0) { 549 nlog(LOG_ERR, "nwamd_door_switch: door_ucred failed: %s", 550 strerror(errno)); 551 req->nwda_error = NWAM_ERROR_INTERNAL; 552 req->nwda_status = NWAM_REQUEST_STATUS_FAILED; 553 goto done; 554 } 555 uid = ucred_getruid(ucr); 556 557 if ((pwd = getpwuid(uid)) == NULL) { 558 nlog(LOG_ERR, "nwamd_door_switch: getpwuid failed: %s", 559 strerror(errno)); 560 endpwent(); 561 req->nwda_error = NWAM_ERROR_INTERNAL; 562 req->nwda_status = NWAM_REQUEST_STATUS_FAILED; 563 goto done; 564 } 565 566 /* 567 * Find door request entry in table, check auths and call the function 568 * handling the request. 569 */ 570 for (i = 0; 571 i < sizeof (door_req_table) / sizeof (struct nwamd_door_req_entry); 572 i++) { 573 if (req->nwda_type != door_req_table[i].ndre_type) 574 continue; 575 576 found = B_TRUE; 577 578 if (door_req_table[i].ndre_auth != NULL && 579 chkauthattr(door_req_table[i].ndre_auth, 580 pwd->pw_name) == 0) { 581 nlog(LOG_ERR, 582 "nwamd_door_switch: need %s for request type %d", 583 door_req_table[i].ndre_auth, req->nwda_type); 584 req->nwda_error = NWAM_PERMISSION_DENIED; 585 break; 586 } 587 req->nwda_error = door_req_table[i].ndre_fn(req, ucr, pwd); 588 break; 589 } 590 if (!found) { 591 nlog(LOG_ERR, 592 "nwamd_door_switch: received unknown request type %d", 593 req->nwda_type); 594 req->nwda_status = NWAM_REQUEST_STATUS_UNKNOWN; 595 } else { 596 if (req->nwda_error == NWAM_SUCCESS) 597 req->nwda_status = NWAM_REQUEST_STATUS_OK; 598 else 599 req->nwda_status = NWAM_REQUEST_STATUS_FAILED; 600 } 601 602 done: 603 ucred_free(ucr); 604 endpwent(); 605 606 if (door_return((char *)req, sizeof (nwamd_door_arg_t), NULL, 0) 607 == -1) { 608 nlog(LOG_ERR, "door_switch: type %d door_return failed: %s", 609 req->nwda_type, strerror(errno)); 610 } 611 } 612 613 /* 614 * We initialize the nwamd door here. Failure to have this happen is critical 615 * to the daemon so we log a message and pass up notice to the caller who 616 * will most likely abort trying to start. This routine is meant to only 617 * be called once. 618 */ 619 void 620 nwamd_door_init(void) 621 { 622 const int door_mode = 0644; 623 struct stat buf; 624 625 if ((doorfd = door_create(nwamd_door_switch, NULL, 626 DOOR_NO_CANCEL | DOOR_REFUSE_DESC)) == -1) 627 pfail("Unable to create door: %s", strerror(errno)); 628 629 if (stat(NWAM_DOOR, &buf) < 0) { 630 int nwam_door_fd; 631 632 if ((nwam_door_fd = creat(NWAM_DOOR, door_mode)) < 0) { 633 int err = errno; 634 (void) door_revoke(doorfd); 635 doorfd = -1; 636 pfail("Couldn't create door: %s", strerror(err)); 637 } 638 (void) close(nwam_door_fd); 639 } else { 640 if (buf.st_mode != door_mode) { 641 if (chmod(NWAM_DOOR, door_mode) == -1) { 642 nlog(LOG_ERR, "couldn't change mode of %s: %s", 643 NWAM_DOOR, strerror(errno)); 644 } 645 } 646 } 647 /* cleanup anything hanging around from a previous invocation */ 648 (void) fdetach(NWAM_DOOR); 649 650 /* Place our door in the file system so that others can find us. */ 651 if (fattach(doorfd, NWAM_DOOR) < 0) { 652 int err = errno; 653 (void) door_revoke(doorfd); 654 doorfd = -1; 655 pfail("Couldn't attach door: %s", strerror(err)); 656 } 657 } 658 659 void 660 nwamd_door_fini(void) 661 { 662 if (doorfd != -1) { 663 nlog(LOG_DEBUG, "nwamd_door_fini: closing door"); 664 (void) door_revoke(doorfd); 665 doorfd = -1; 666 } 667 (void) unlink(NWAM_DOOR); 668 } 669