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, 241 req->nwda_data.nwdad_wlan_info.nwdad_bssid, 242 req->nwda_data.nwdad_wlan_info.nwdad_security_mode, 243 req->nwda_data.nwdad_wlan_info.nwdad_keyslot, 244 req->nwda_data.nwdad_wlan_info.nwdad_key)); 245 } 246 247 static nwam_error_t 248 nwamd_door_req_action(nwamd_door_arg_t *req, ucred_t *ucr, struct passwd *pwd) 249 { 250 char name[NWAM_MAX_NAME_LEN]; 251 char parent[NWAM_MAX_NAME_LEN]; 252 nwam_action_t action = req->nwda_data.nwdad_object_action.nwdad_action; 253 nwam_object_type_t object_type = 254 req->nwda_data.nwdad_object_action.nwdad_object_type; 255 char *obj_type_str = (char *)nwam_object_type_to_string(object_type); 256 nwam_error_t err; 257 258 /* Check for name, parent overrun */ 259 if (strlcpy(name, req->nwda_data.nwdad_object_action.nwdad_name, 260 sizeof (name)) == NWAM_MAX_NAME_LEN || 261 strlcpy(parent, req->nwda_data.nwdad_object_action.nwdad_parent, 262 sizeof (parent)) == NWAM_MAX_NAME_LEN) 263 return (NWAM_INVALID_ARG); 264 265 /* 266 * Check authorizations against actions. 267 * - ENABLE/DISABLE requires SELECT auth 268 * - ADD/DESTROY/REFRESH on Known WLANs requires WLAN auth 269 * - ADD/DESTROY on other objects requires WRITE auth 270 * - REFRESH on other objects requires either WRITE or SELECT auth 271 */ 272 if (action == NWAM_ACTION_ENABLE || action == NWAM_ACTION_DISABLE) { 273 if (chkauthattr(AUTOCONF_SELECT_AUTH, pwd->pw_name) == 0) { 274 nwam_record_audit_event(ucr, 275 action == NWAM_ACTION_ENABLE ? 276 ADT_nwam_enable : ADT_nwam_disable, name, 277 obj_type_str, ADT_FAILURE, ADT_FAIL_VALUE_AUTH); 278 nlog(LOG_ERR, "nwamd_door_req_action: " 279 "need %s for %s action", AUTOCONF_SELECT_AUTH, 280 nwam_action_to_string(action)); 281 return (NWAM_PERMISSION_DENIED); 282 } 283 } else if (object_type == NWAM_OBJECT_TYPE_KNOWN_WLAN) { 284 if (chkauthattr(AUTOCONF_WLAN_AUTH, pwd->pw_name) == 0) { 285 nlog(LOG_ERR, "nwamd_door_req_action: " 286 "need %s for %s action on Known WLAN", 287 AUTOCONF_WLAN_AUTH, nwam_action_to_string(action)); 288 return (NWAM_PERMISSION_DENIED); 289 } 290 } else if (action == NWAM_ACTION_ADD || action == NWAM_ACTION_DESTROY) { 291 if (chkauthattr(AUTOCONF_WRITE_AUTH, pwd->pw_name) == 0) { 292 nlog(LOG_ERR, "nwamd_door_req_action: " 293 "need %s for %s action", AUTOCONF_WRITE_AUTH, 294 nwam_action_to_string(action)); 295 return (NWAM_PERMISSION_DENIED); 296 } 297 } else if (action == NWAM_ACTION_REFRESH) { 298 if (chkauthattr(AUTOCONF_WRITE_AUTH, pwd->pw_name) == 0 && 299 chkauthattr(AUTOCONF_SELECT_AUTH, pwd->pw_name) == 0) { 300 nlog(LOG_ERR, "nwamd_door_req_action: " 301 "need either %s or %s for %s action", 302 AUTOCONF_WRITE_AUTH, AUTOCONF_SELECT_AUTH, 303 nwam_action_to_string(action)); 304 return (NWAM_PERMISSION_DENIED); 305 } 306 } else { 307 nlog(LOG_ERR, "nwamd_door_req_action: received unknown " 308 "action %d (%s)", action, nwam_action_to_string(action)); 309 return (NWAM_INVALID_ARG); 310 } 311 312 switch (action) { 313 case NWAM_ACTION_ENABLE: 314 case NWAM_ACTION_DISABLE: 315 nwam_record_audit_event(ucr, 316 action == NWAM_ACTION_ENABLE ? 317 ADT_nwam_enable : ADT_nwam_disable, name, 318 obj_type_str, ADT_SUCCESS, ADT_SUCCESS); 319 320 nlog(LOG_DEBUG, "nwamd_door_req_action: %s %s", 321 action == NWAM_ACTION_ENABLE ? "enabling" : "disabling", 322 name); 323 324 switch (object_type) { 325 case NWAM_OBJECT_TYPE_ENM: 326 err = nwamd_enm_action(name, action); 327 break; 328 case NWAM_OBJECT_TYPE_LOC: 329 err = nwamd_loc_action(name, action); 330 break; 331 case NWAM_OBJECT_TYPE_NCU: 332 err = nwamd_ncu_action(name, parent, action); 333 break; 334 case NWAM_OBJECT_TYPE_NCP: 335 if (action == NWAM_ACTION_DISABLE) { 336 nlog(LOG_ERR, "nwamd_door_req_action: " 337 "NCPs cannot be disabled"); 338 err = NWAM_INVALID_ARG; 339 } else { 340 err = nwamd_ncp_action(name, action); 341 } 342 break; 343 default: 344 nlog(LOG_ERR, "nwamd_door_req_action: received invalid " 345 "object type %d (%s)", object_type, 346 nwam_object_type_to_string(object_type)); 347 return (NWAM_INVALID_ARG); 348 } 349 break; 350 351 case NWAM_ACTION_ADD: 352 case NWAM_ACTION_REFRESH: 353 /* 354 * Called whenever an object is committed in the library. 355 * Reread that committed object into nwamd. 356 */ 357 nlog(LOG_DEBUG, "door_switch: refreshing %s", name); 358 359 switch (object_type) { 360 case NWAM_OBJECT_TYPE_ENM: 361 err = nwamd_enm_action(name, action); 362 break; 363 case NWAM_OBJECT_TYPE_LOC: 364 err = nwamd_loc_action(name, action); 365 break; 366 case NWAM_OBJECT_TYPE_KNOWN_WLAN: 367 err = nwamd_known_wlan_action(name, action); 368 break; 369 case NWAM_OBJECT_TYPE_NCU: 370 err = nwamd_ncu_action(name, parent, action); 371 break; 372 case NWAM_OBJECT_TYPE_NCP: 373 err = nwamd_ncp_action(name, action); 374 break; 375 default: 376 nlog(LOG_ERR, "nwamd_door_req_action: received invalid " 377 "object type %d (%s)", object_type, 378 nwam_object_type_to_string(object_type)); 379 err = NWAM_INVALID_ARG; 380 break; 381 } 382 break; 383 384 case NWAM_ACTION_DESTROY: 385 /* Object was destroyed, remove from nwamd */ 386 nlog(LOG_DEBUG, "door_switch: removing %s", name); 387 388 switch (object_type) { 389 case NWAM_OBJECT_TYPE_ENM: 390 err = nwamd_enm_action(name, NWAM_ACTION_DESTROY); 391 break; 392 case NWAM_OBJECT_TYPE_LOC: 393 err = nwamd_loc_action(name, NWAM_ACTION_DESTROY); 394 break; 395 case NWAM_OBJECT_TYPE_KNOWN_WLAN: 396 err = nwamd_known_wlan_action(name, 397 NWAM_ACTION_DESTROY); 398 break; 399 case NWAM_OBJECT_TYPE_NCU: 400 err = nwamd_ncu_action(name, parent, 401 NWAM_ACTION_DESTROY); 402 break; 403 case NWAM_OBJECT_TYPE_NCP: 404 (void) pthread_mutex_lock(&active_ncp_mutex); 405 if (strcmp(name, active_ncp) == 0) { 406 nlog(LOG_ERR, "nwamd_door_req_action: %s is " 407 "active, cannot destroy", parent); 408 err = NWAM_ENTITY_IN_USE; 409 } else { 410 err = nwamd_ncp_action(name, 411 NWAM_ACTION_DESTROY); 412 } 413 (void) pthread_mutex_unlock(&active_ncp_mutex); 414 break; 415 default: 416 nlog(LOG_ERR, "nwamd_door_req_action: received invalid " 417 "object type %d (%s)", object_type, 418 nwam_object_type_to_string(object_type)); 419 err = NWAM_INVALID_ARG; 420 break; 421 } 422 break; 423 424 default: 425 nlog(LOG_ERR, "nwamd_door_req_action: received unknown " 426 "action %d (%s)", action, nwam_action_to_string(action)); 427 err = NWAM_INVALID_ARG; 428 break; 429 } 430 431 if (err == NWAM_SUCCESS) { 432 /* 433 * At this point, we've successfully carried out an action. 434 * Configuration may have changed, so we need to recheck 435 * conditions, however we want to avoid a flurry of condition 436 * check events, so we enqueue a triggered condition check 437 * if none is due in the next few seconds. 438 */ 439 nwamd_create_triggered_condition_check_event(NEXT_FEW_SECONDS); 440 } else { 441 nlog(LOG_ERR, "nwamd_door_req_action: could not carry out " 442 "%s action on %s: %s", nwam_action_to_string(action), 443 name, nwam_strerror(err)); 444 } 445 446 return (err); 447 } 448 449 /* ARGSUSED */ 450 static nwam_error_t 451 nwamd_door_req_state(nwamd_door_arg_t *req, ucred_t *ucr, struct passwd *pwd) 452 { 453 char name[NWAM_MAX_NAME_LEN]; 454 nwamd_object_t obj; 455 nwam_object_type_t object_type = 456 req->nwda_data.nwdad_object_state.nwdad_object_type; 457 boolean_t is_active = B_FALSE; 458 459 /* Check for name, parent overrun */ 460 if (strlcpy(name, req->nwda_data.nwdad_object_state.nwdad_name, 461 sizeof (name)) == NWAM_MAX_NAME_LEN) 462 return (NWAM_INVALID_ARG); 463 464 switch (object_type) { 465 case NWAM_OBJECT_TYPE_NCP: 466 (void) pthread_mutex_lock(&active_ncp_mutex); 467 is_active = (strcmp(active_ncp, name) == 0); 468 (void) pthread_mutex_unlock(&active_ncp_mutex); 469 if (is_active) { 470 req->nwda_data.nwdad_object_state.nwdad_state = 471 NWAM_STATE_ONLINE; 472 req->nwda_data.nwdad_object_state. 473 nwdad_aux_state = NWAM_AUX_STATE_ACTIVE; 474 nlog(LOG_DEBUG, 475 "nwamd_door_req_state: NCP %s is active", name); 476 } else { 477 req->nwda_data.nwdad_object_state.nwdad_state = 478 NWAM_STATE_DISABLED; 479 req->nwda_data.nwdad_object_state. 480 nwdad_aux_state = 481 NWAM_AUX_STATE_MANUAL_DISABLE; 482 nlog(LOG_DEBUG, "nwamd_door_req_state: " 483 "NCP %s is inactive", name); 484 } 485 break; 486 487 case NWAM_OBJECT_TYPE_LOC: 488 case NWAM_OBJECT_TYPE_NCU: 489 case NWAM_OBJECT_TYPE_ENM: 490 obj = nwamd_object_find(object_type, name); 491 if (obj == NULL) { 492 nlog(LOG_ERR, "nwamd_door_req_state: %s %s not found", 493 nwam_object_type_to_string(object_type), name); 494 return (NWAM_ENTITY_NOT_FOUND); 495 } 496 nlog(LOG_DEBUG, "nwamd_door_req_state: %s %s is %s", 497 nwam_object_type_to_string(object_type), name, 498 nwam_state_to_string(obj->nwamd_object_state)); 499 req->nwda_data.nwdad_object_state.nwdad_state = 500 obj->nwamd_object_state; 501 req->nwda_data.nwdad_object_state.nwdad_aux_state = 502 obj->nwamd_object_aux_state; 503 nwamd_object_release(obj); 504 break; 505 506 default: 507 nlog(LOG_ERR, "nwamd_door_req_state: received invalid " 508 "object type %d (%s)", object_type, 509 nwam_object_type_to_string(object_type)); 510 req->nwda_status = NWAM_REQUEST_STATUS_UNKNOWN; 511 return (NWAM_INVALID_ARG); 512 } 513 514 return (NWAM_SUCCESS); 515 } 516 517 /* ARGSUSED */ 518 static nwam_error_t 519 nwamd_door_req_priority_group(nwamd_door_arg_t *req, ucred_t *ucr, 520 struct passwd *pwd) 521 { 522 (void) pthread_mutex_lock(&active_ncp_mutex); 523 nlog(LOG_DEBUG, "nwamd_door_req_priority_group: " 524 "retrieving active priority-group: %d", 525 current_ncu_priority_group); 526 req->nwda_data.nwdad_priority_group_info.nwdad_priority = 527 current_ncu_priority_group; 528 (void) pthread_mutex_unlock(&active_ncp_mutex); 529 530 return (NWAM_SUCCESS); 531 } 532 533 /* ARGSUSED */ 534 static void 535 nwamd_door_switch(void *cookie, char *argp, size_t arg_size, door_desc_t *dp, 536 uint_t n_desc) 537 { 538 nwamd_door_arg_t *req; 539 ucred_t *ucr = NULL; 540 uid_t uid; 541 struct passwd *pwd = NULL; 542 boolean_t found = B_FALSE; 543 int i; 544 545 /* LINTED E_BAD_PTR_CAST_ALIGN */ 546 req = (nwamd_door_arg_t *)argp; 547 req->nwda_error = NWAM_SUCCESS; 548 549 if (door_ucred(&ucr) != 0) { 550 nlog(LOG_ERR, "nwamd_door_switch: door_ucred failed: %s", 551 strerror(errno)); 552 req->nwda_error = NWAM_ERROR_INTERNAL; 553 req->nwda_status = NWAM_REQUEST_STATUS_FAILED; 554 goto done; 555 } 556 uid = ucred_getruid(ucr); 557 558 if ((pwd = getpwuid(uid)) == NULL) { 559 nlog(LOG_ERR, "nwamd_door_switch: getpwuid failed: %s", 560 strerror(errno)); 561 endpwent(); 562 req->nwda_error = NWAM_ERROR_INTERNAL; 563 req->nwda_status = NWAM_REQUEST_STATUS_FAILED; 564 goto done; 565 } 566 567 /* 568 * Find door request entry in table, check auths and call the function 569 * handling the request. 570 */ 571 for (i = 0; 572 i < sizeof (door_req_table) / sizeof (struct nwamd_door_req_entry); 573 i++) { 574 if (req->nwda_type != door_req_table[i].ndre_type) 575 continue; 576 577 found = B_TRUE; 578 579 if (door_req_table[i].ndre_auth != NULL && 580 chkauthattr(door_req_table[i].ndre_auth, 581 pwd->pw_name) == 0) { 582 nlog(LOG_ERR, 583 "nwamd_door_switch: need %s for request type %d", 584 door_req_table[i].ndre_auth, req->nwda_type); 585 req->nwda_error = NWAM_PERMISSION_DENIED; 586 break; 587 } 588 req->nwda_error = door_req_table[i].ndre_fn(req, ucr, pwd); 589 break; 590 } 591 if (!found) { 592 nlog(LOG_ERR, 593 "nwamd_door_switch: received unknown request type %d", 594 req->nwda_type); 595 req->nwda_status = NWAM_REQUEST_STATUS_UNKNOWN; 596 } else { 597 if (req->nwda_error == NWAM_SUCCESS) 598 req->nwda_status = NWAM_REQUEST_STATUS_OK; 599 else 600 req->nwda_status = NWAM_REQUEST_STATUS_FAILED; 601 } 602 603 done: 604 ucred_free(ucr); 605 endpwent(); 606 607 if (door_return((char *)req, sizeof (nwamd_door_arg_t), NULL, 0) 608 == -1) { 609 nlog(LOG_ERR, "door_switch: type %d door_return failed: %s", 610 req->nwda_type, strerror(errno)); 611 } 612 } 613 614 /* 615 * We initialize the nwamd door here. Failure to have this happen is critical 616 * to the daemon so we log a message and pass up notice to the caller who 617 * will most likely abort trying to start. This routine is meant to only 618 * be called once. 619 */ 620 void 621 nwamd_door_init(void) 622 { 623 const int door_mode = 0644; 624 struct stat buf; 625 626 if ((doorfd = door_create(nwamd_door_switch, NULL, 627 DOOR_NO_CANCEL | DOOR_REFUSE_DESC)) == -1) 628 pfail("Unable to create door: %s", strerror(errno)); 629 630 if (stat(NWAM_DOOR, &buf) < 0) { 631 int nwam_door_fd; 632 633 if ((nwam_door_fd = creat(NWAM_DOOR, door_mode)) < 0) { 634 int err = errno; 635 (void) door_revoke(doorfd); 636 doorfd = -1; 637 pfail("Couldn't create door: %s", strerror(err)); 638 } 639 (void) close(nwam_door_fd); 640 } else { 641 if (buf.st_mode != door_mode) { 642 if (chmod(NWAM_DOOR, door_mode) == -1) { 643 nlog(LOG_ERR, "couldn't change mode of %s: %s", 644 NWAM_DOOR, strerror(errno)); 645 } 646 } 647 } 648 /* cleanup anything hanging around from a previous invocation */ 649 (void) fdetach(NWAM_DOOR); 650 651 /* Place our door in the file system so that others can find us. */ 652 if (fattach(doorfd, NWAM_DOOR) < 0) { 653 int err = errno; 654 (void) door_revoke(doorfd); 655 doorfd = -1; 656 pfail("Couldn't attach door: %s", strerror(err)); 657 } 658 } 659 660 void 661 nwamd_door_fini(void) 662 { 663 if (doorfd != -1) { 664 nlog(LOG_DEBUG, "nwamd_door_fini: closing door"); 665 (void) door_revoke(doorfd); 666 doorfd = -1; 667 } 668 (void) unlink(NWAM_DOOR); 669 } 670