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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <auth_attr.h> 28 #include <auth_list.h> 29 #include <bsm/adt.h> 30 #include <bsm/adt_event.h> 31 #include <door.h> 32 #include <errno.h> 33 #include <fcntl.h> 34 #include <libnwam_priv.h> 35 #include <libuutil.h> 36 #include <pthread.h> 37 #include <pwd.h> 38 #include <stdlib.h> 39 #include <sys/stat.h> 40 41 #include <sys/mman.h> 42 #include <syslog.h> 43 #include <unistd.h> 44 45 #include "conditions.h" 46 #include "events.h" 47 #include "ncp.h" 48 #include "ncu.h" 49 #include "objects.h" 50 #include "util.h" 51 52 /* 53 * door_if.c 54 * This file contains functions which implement the command interface to 55 * nwam via the door NWAM_DOOR. Doors provide a LPC mechanism that allows 56 * for threads in one process to cause code to execute in another process. 57 * Doors also provide the ability to pass data and file descriptors. See 58 * libdoor(3LIB) for more information. 59 * 60 * This file exports two functions, nwamd_door_initialize() (which sets up 61 * the door) and nwamd_door_fini(), which removes it. 62 * 63 * It sets up the static routine nwamd_door_switch() to be called when a client 64 * calls the door (via door_call(3C)). The structure nwam_request_t is 65 * passed as data and contains data to specify the type of action requested 66 * and any data need to meet that request. A table consisting of entries 67 * for each door request, the associated authorization and the function to 68 * process that request is used to handle the various requests. 69 */ 70 71 struct nwamd_door_req_entry 72 { 73 int ndre_type; 74 char *ndre_auth; 75 nwam_error_t (*ndre_fn)(nwamd_door_arg_t *, ucred_t *, struct passwd *); 76 }; 77 78 static nwam_error_t nwamd_door_req_event_register(nwamd_door_arg_t *, 79 ucred_t *, struct passwd *); 80 static nwam_error_t nwamd_door_req_event_unregister(nwamd_door_arg_t *, 81 ucred_t *, struct passwd *); 82 static nwam_error_t nwamd_door_req_wlan_scan(nwamd_door_arg_t *, 83 ucred_t *, struct passwd *); 84 static nwam_error_t nwamd_door_req_wlan_scan_results(nwamd_door_arg_t *, 85 ucred_t *, struct passwd *); 86 static nwam_error_t nwamd_door_req_wlan_select(nwamd_door_arg_t *, 87 ucred_t *, struct passwd *); 88 static nwam_error_t nwamd_door_req_wlan_set_key(nwamd_door_arg_t *, 89 ucred_t *, struct passwd *); 90 static nwam_error_t nwamd_door_req_action(nwamd_door_arg_t *, 91 ucred_t *, struct passwd *); 92 static nwam_error_t nwamd_door_req_state(nwamd_door_arg_t *, 93 ucred_t *, struct passwd *); 94 static nwam_error_t nwamd_door_req_priority_group(nwamd_door_arg_t *, 95 ucred_t *, struct passwd *); 96 97 /* 98 * This table defines the set of door commands available, the required 99 * authorizations for each command, and the function that carries out 100 * each command. 101 */ 102 struct nwamd_door_req_entry door_req_table[] = 103 { 104 105 { NWAM_REQUEST_TYPE_EVENT_REGISTER, AUTOCONF_READ_AUTH, 106 nwamd_door_req_event_register }, 107 { NWAM_REQUEST_TYPE_EVENT_UNREGISTER, AUTOCONF_READ_AUTH, 108 nwamd_door_req_event_unregister }, 109 { NWAM_REQUEST_TYPE_WLAN_SCAN, AUTOCONF_WLAN_AUTH, 110 nwamd_door_req_wlan_scan }, 111 { NWAM_REQUEST_TYPE_WLAN_SCAN_RESULTS, AUTOCONF_READ_AUTH, 112 nwamd_door_req_wlan_scan_results }, 113 { NWAM_REQUEST_TYPE_WLAN_SELECT, AUTOCONF_WLAN_AUTH, 114 nwamd_door_req_wlan_select }, 115 { NWAM_REQUEST_TYPE_WLAN_SET_KEY, AUTOCONF_WLAN_AUTH, 116 nwamd_door_req_wlan_set_key }, 117 /* Requires WRITE, SELECT or WLAN auth depending on action */ 118 { NWAM_REQUEST_TYPE_ACTION, NULL, nwamd_door_req_action }, 119 { NWAM_REQUEST_TYPE_STATE, AUTOCONF_READ_AUTH, 120 nwamd_door_req_state }, 121 { NWAM_REQUEST_TYPE_PRIORITY_GROUP, AUTOCONF_READ_AUTH, 122 nwamd_door_req_priority_group }, 123 }; 124 125 int doorfd = -1; 126 127 /* ARGSUSED */ 128 static nwam_error_t 129 nwamd_door_req_event_register(nwamd_door_arg_t *req, ucred_t *ucr, 130 struct passwd *pwd) 131 { 132 nwam_error_t err; 133 134 err = nwam_event_queue_init 135 (req->nwda_data.nwdad_register_info.nwdad_name); 136 if (err != NWAM_SUCCESS) { 137 nlog(LOG_ERR, "nwamd_door_req_event_register: " 138 "could not register events for %s", 139 req->nwda_data.nwdad_register_info.nwdad_name); 140 } 141 142 return (err); 143 } 144 145 /* ARGSUSED */ 146 static nwam_error_t 147 nwamd_door_req_event_unregister(nwamd_door_arg_t *req, ucred_t *ucr, 148 struct passwd *pwd) 149 { 150 nwam_event_queue_fini(req->nwda_data.nwdad_register_info.nwdad_name); 151 152 return (NWAM_SUCCESS); 153 } 154 155 /* ARGSUSED1 */ 156 static nwam_error_t 157 nwamd_door_req_wlan_scan(nwamd_door_arg_t *req, ucred_t *ucr, 158 struct passwd *pwd) 159 { 160 nlog(LOG_DEBUG, 161 "nwamd_door_req_wlan_scan: processing WLAN scan request: " 162 "link %s", req->nwda_data.nwdad_wlan_info.nwdad_name); 163 164 return (nwamd_wlan_scan(req->nwda_data.nwdad_wlan_info.nwdad_name)); 165 } 166 167 /* ARGSUSED */ 168 static nwam_error_t 169 nwamd_door_req_wlan_scan_results(nwamd_door_arg_t *req, ucred_t *ucr, 170 struct passwd *pwd) 171 { 172 nwamd_object_t obj; 173 nwamd_ncu_t *ncu; 174 nwamd_link_t *link; 175 uint_t num_wlans; 176 177 nlog(LOG_DEBUG, "nwamd_door_req_wlan_scan_results: processing WLAN " 178 "scan results request: link %s", 179 req->nwda_data.nwdad_wlan_info.nwdad_name); 180 181 obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_LINK, 182 req->nwda_data.nwdad_wlan_info.nwdad_name); 183 if (obj == NULL) { 184 nlog(LOG_ERR, 185 "nwamd_door_req_wlan_scan_results: link %s not found", 186 req->nwda_data.nwdad_wlan_info.nwdad_name); 187 return (NWAM_ENTITY_NOT_FOUND); 188 } 189 190 ncu = obj->nwamd_object_data; 191 link = &ncu->ncu_node.u_link; 192 num_wlans = link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr_num; 193 194 if (num_wlans > 0) { 195 (void) memcpy 196 (req->nwda_data.nwdad_wlan_info.nwdad_wlans, 197 link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr, 198 num_wlans * sizeof (nwam_wlan_t)); 199 } 200 req->nwda_data.nwdad_wlan_info.nwdad_num_wlans = num_wlans; 201 nlog(LOG_DEBUG, 202 "nwamd_door_req_wlan_scan_results: returning %d scan results", 203 num_wlans); 204 nwamd_object_release(obj); 205 206 return (NWAM_SUCCESS); 207 } 208 209 /* ARGSUSED */ 210 static nwam_error_t 211 nwamd_door_req_wlan_select(nwamd_door_arg_t *req, ucred_t *ucr, 212 struct passwd *pwd) 213 { 214 nlog(LOG_DEBUG, 215 "nwamd_door_req_wlan_select: processing WLAN selection : " 216 "link %s ESSID %s , BSSID %s", 217 req->nwda_data.nwdad_wlan_info.nwdad_name, 218 req->nwda_data.nwdad_wlan_info.nwdad_essid, 219 req->nwda_data.nwdad_wlan_info.nwdad_bssid); 220 return (nwamd_wlan_select 221 (req->nwda_data.nwdad_wlan_info.nwdad_name, 222 req->nwda_data.nwdad_wlan_info.nwdad_essid, 223 req->nwda_data.nwdad_wlan_info.nwdad_bssid, 224 req->nwda_data.nwdad_wlan_info.nwdad_security_mode, 225 req->nwda_data.nwdad_wlan_info.nwdad_add_to_known_wlans)); 226 } 227 228 /* ARGSUSED */ 229 static nwam_error_t 230 nwamd_door_req_wlan_set_key(nwamd_door_arg_t *req, ucred_t *ucr, 231 struct passwd *pwd) 232 { 233 nlog(LOG_DEBUG, 234 "nwamd_door_req_wlan_set_key: processing WLAN key input : " 235 "link %s ESSID %s BSSID %s", 236 req->nwda_data.nwdad_wlan_info.nwdad_name, 237 req->nwda_data.nwdad_wlan_info.nwdad_essid, 238 req->nwda_data.nwdad_wlan_info.nwdad_bssid); 239 return (nwamd_wlan_set_key 240 (req->nwda_data.nwdad_wlan_info.nwdad_name, 241 req->nwda_data.nwdad_wlan_info.nwdad_essid, NULL, 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