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 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 24 */ 25 26 #include <sys/list.h> 27 #include <assert.h> 28 #include <alloca.h> 29 #include <door.h> 30 #include <errno.h> 31 #include <syslog.h> 32 #include <unistd.h> 33 #include <stdio.h> 34 #include <synch.h> 35 #include <string.h> 36 #include <stdlib.h> 37 #include <sys/stat.h> 38 #include <fcntl.h> 39 #include <pthread.h> 40 #include <strings.h> 41 #include <note.h> 42 #include <smbsrv/smb_door.h> 43 #include <smbsrv/smb_xdr.h> 44 #include <smbsrv/smb_token.h> 45 #include <smbsrv/libmlsvc.h> 46 #include <smbsrv/libsmbns.h> 47 #include "smbd.h" 48 49 /* 50 * The list contains asynchronous requests that have been initiated 51 * but have not yet been collected (via smbd_dop_async_response). 52 */ 53 typedef struct smbd_doorsvc { 54 mutex_t sd_mutex; 55 cond_t sd_cv; 56 list_t sd_async_list; 57 uint32_t sd_async_count; 58 } smbd_doorsvc_t; 59 60 static int smbd_dop_null(smbd_arg_t *); 61 static int smbd_dop_async_response(smbd_arg_t *); 62 static int smbd_dop_user_auth_logon(smbd_arg_t *); 63 static int smbd_dop_user_nonauth_logon(smbd_arg_t *); 64 static int smbd_dop_user_auth_logoff(smbd_arg_t *); 65 static int smbd_dop_lookup_sid(smbd_arg_t *); 66 static int smbd_dop_lookup_name(smbd_arg_t *); 67 static int smbd_dop_join(smbd_arg_t *); 68 static int smbd_dop_get_dcinfo(smbd_arg_t *); 69 static int smbd_dop_vss_get_count(smbd_arg_t *); 70 static int smbd_dop_vss_get_snapshots(smbd_arg_t *); 71 static int smbd_dop_vss_map_gmttoken(smbd_arg_t *); 72 static int smbd_dop_ads_find_host(smbd_arg_t *); 73 static int smbd_dop_quota_query(smbd_arg_t *); 74 static int smbd_dop_quota_set(smbd_arg_t *); 75 static int smbd_dop_dfs_get_referrals(smbd_arg_t *); 76 static int smbd_dop_shr_hostaccess(smbd_arg_t *); 77 static int smbd_dop_shr_exec(smbd_arg_t *); 78 static int smbd_dop_notify_dc_changed(smbd_arg_t *); 79 80 typedef int (*smbd_dop_t)(smbd_arg_t *); 81 82 typedef struct smbd_doorop { 83 smb_dopcode_t opcode; 84 smbd_dop_t op; 85 } smbd_doorop_t; 86 87 smbd_doorop_t smbd_doorops[] = { 88 { SMB_DR_NULL, smbd_dop_null }, 89 { SMB_DR_ASYNC_RESPONSE, smbd_dop_async_response }, 90 { SMB_DR_USER_AUTH_LOGON, smbd_dop_user_auth_logon }, 91 { SMB_DR_USER_NONAUTH_LOGON, smbd_dop_user_nonauth_logon }, 92 { SMB_DR_USER_AUTH_LOGOFF, smbd_dop_user_auth_logoff }, 93 { SMB_DR_LOOKUP_SID, smbd_dop_lookup_sid }, 94 { SMB_DR_LOOKUP_NAME, smbd_dop_lookup_name }, 95 { SMB_DR_JOIN, smbd_dop_join }, 96 { SMB_DR_GET_DCINFO, smbd_dop_get_dcinfo }, 97 { SMB_DR_VSS_GET_COUNT, smbd_dop_vss_get_count }, 98 { SMB_DR_VSS_GET_SNAPSHOTS, smbd_dop_vss_get_snapshots }, 99 { SMB_DR_VSS_MAP_GMTTOKEN, smbd_dop_vss_map_gmttoken }, 100 { SMB_DR_ADS_FIND_HOST, smbd_dop_ads_find_host }, 101 { SMB_DR_QUOTA_QUERY, smbd_dop_quota_query }, 102 { SMB_DR_QUOTA_SET, smbd_dop_quota_set }, 103 { SMB_DR_DFS_GET_REFERRALS, smbd_dop_dfs_get_referrals }, 104 { SMB_DR_SHR_HOSTACCESS, smbd_dop_shr_hostaccess }, 105 { SMB_DR_SHR_EXEC, smbd_dop_shr_exec }, 106 { SMB_DR_NOTIFY_DC_CHANGED, smbd_dop_notify_dc_changed } 107 }; 108 109 static int smbd_ndoorop = (sizeof (smbd_doorops) / sizeof (smbd_doorops[0])); 110 111 static smbd_doorsvc_t smbd_doorsvc; 112 static int smbd_door_fd = -1; 113 static int smbd_door_cookie = 0x534D4244; /* SMBD */ 114 static smbd_door_t smbd_door_sdh; 115 static char *smbd_door_name = NULL; 116 117 static void smbd_door_dispatch(void *, char *, size_t, door_desc_t *, uint_t); 118 static int smbd_door_dispatch_async(smbd_arg_t *); 119 static void smbd_door_release_async(smbd_arg_t *); 120 121 /* 122 * Start the smbd door service. Create and bind to a door. 123 * Returns 0 on success. Otherwise, -1. 124 */ 125 int 126 smbd_door_start(void) 127 { 128 int newfd; 129 130 (void) mutex_lock(&smbd_doorsvc.sd_mutex); 131 132 if (smbd_door_fd != -1) { 133 (void) fprintf(stderr, "smb_doorsrv_start: already started"); 134 (void) mutex_unlock(&smbd_doorsvc.sd_mutex); 135 return (-1); 136 } 137 138 smbd_door_name = getenv("SMBD_DOOR_NAME"); 139 if (smbd_door_name == NULL) 140 smbd_door_name = SMBD_DOOR_NAME; 141 142 smbd_door_init(&smbd_door_sdh, "doorsrv"); 143 144 list_create(&smbd_doorsvc.sd_async_list, sizeof (smbd_arg_t), 145 offsetof(smbd_arg_t, lnd)); 146 smbd_doorsvc.sd_async_count = 0; 147 148 if ((smbd_door_fd = door_create(smbd_door_dispatch, 149 &smbd_door_cookie, DOOR_UNREF)) < 0) { 150 (void) fprintf(stderr, "smb_doorsrv_start: door_create: %s", 151 strerror(errno)); 152 smbd_door_fd = -1; 153 (void) mutex_unlock(&smbd_doorsvc.sd_mutex); 154 return (-1); 155 } 156 157 (void) unlink(smbd_door_name); 158 159 if ((newfd = creat(smbd_door_name, 0644)) < 0) { 160 (void) fprintf(stderr, "smb_doorsrv_start: open: %s", 161 strerror(errno)); 162 (void) door_revoke(smbd_door_fd); 163 smbd_door_fd = -1; 164 (void) mutex_unlock(&smbd_doorsvc.sd_mutex); 165 return (-1); 166 } 167 168 (void) close(newfd); 169 (void) fdetach(smbd_door_name); 170 171 if (fattach(smbd_door_fd, smbd_door_name) < 0) { 172 (void) fprintf(stderr, "smb_doorsrv_start: fattach: %s", 173 strerror(errno)); 174 (void) door_revoke(smbd_door_fd); 175 smbd_door_fd = -1; 176 (void) mutex_unlock(&smbd_doorsvc.sd_mutex); 177 return (-1); 178 } 179 180 (void) mutex_unlock(&smbd_doorsvc.sd_mutex); 181 return (smbd_door_fd); 182 } 183 184 /* 185 * Stop the smbd door service. 186 */ 187 void 188 smbd_door_stop(void) 189 { 190 (void) mutex_lock(&smbd_doorsvc.sd_mutex); 191 192 smbd_door_fini(&smbd_door_sdh); 193 194 if (smbd_door_name) 195 (void) fdetach(smbd_door_name); 196 197 if (smbd_door_fd != -1) { 198 (void) door_revoke(smbd_door_fd); 199 smbd_door_fd = -1; 200 } 201 202 (void) mutex_unlock(&smbd_doorsvc.sd_mutex); 203 } 204 205 /*ARGSUSED*/ 206 static void 207 smbd_door_dispatch(void *cookie, char *argp, size_t arg_size, door_desc_t *dp, 208 uint_t n_desc) 209 { 210 smbd_arg_t dop_arg; 211 smb_doorhdr_t *hdr; 212 size_t hdr_size; 213 char *rbuf = NULL; 214 215 smbd_door_enter(&smbd_door_sdh); 216 217 if (!smbd_online()) 218 smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0); 219 220 bzero(&dop_arg, sizeof (smbd_arg_t)); 221 hdr = &dop_arg.hdr; 222 hdr_size = xdr_sizeof(smb_doorhdr_xdr, hdr); 223 224 if ((cookie != &smbd_door_cookie) || (argp == NULL) || 225 (arg_size < hdr_size)) { 226 smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0); 227 } 228 229 if (smb_doorhdr_decode(hdr, (uint8_t *)argp, hdr_size) == -1) { 230 syslog(LOG_DEBUG, "smbd_door_dispatch: header decode failed"); 231 smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0); 232 } 233 234 if ((hdr->dh_magic != SMB_DOOR_HDR_MAGIC) || (hdr->dh_txid == 0)) { 235 syslog(LOG_DEBUG, "smbd_door_dispatch: invalid header"); 236 smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0); 237 } 238 239 dop_arg.opname = smb_doorhdr_opname(hdr->dh_op); 240 dop_arg.data = argp + hdr_size; 241 dop_arg.datalen = hdr->dh_datalen; 242 243 if (hdr->dh_op == SMB_DR_ASYNC_RESPONSE) { 244 /* 245 * ASYNC_RESPONSE is used to collect the response 246 * to an async call; it cannot be an async call. 247 */ 248 hdr->dh_flags &= ~SMB_DF_ASYNC; 249 } 250 251 if (hdr->dh_flags & SMB_DF_ASYNC) { 252 if (smbd_door_dispatch_async(&dop_arg) == 0) 253 hdr->dh_door_rc = SMB_DOP_SUCCESS; 254 else 255 hdr->dh_door_rc = SMB_DOP_NOT_CALLED; 256 } else { 257 (void) smbd_door_dispatch_op(&dop_arg); 258 } 259 260 if ((rbuf = (char *)alloca(dop_arg.rsize + hdr_size)) == NULL) { 261 errno = ENOMEM; 262 syslog(LOG_DEBUG, "smbd_door_dispatch[%s]: alloca %m", 263 dop_arg.opname); 264 smbd_door_return(&smbd_door_sdh, NULL, 0, NULL, 0); 265 } 266 267 if (dop_arg.rbuf != NULL) { 268 (void) memcpy(rbuf + hdr_size, dop_arg.rbuf, dop_arg.rsize); 269 free(dop_arg.rbuf); 270 } 271 272 hdr->dh_datalen = dop_arg.rsize; 273 (void) smb_doorhdr_encode(hdr, (uint8_t *)rbuf, hdr_size); 274 dop_arg.rsize += hdr_size; 275 276 smbd_door_return(&smbd_door_sdh, rbuf, dop_arg.rsize, NULL, 0); 277 /*NOTREACHED*/ 278 } 279 280 /* 281 * Launch a thread to process an asynchronous door call. 282 */ 283 static int 284 smbd_door_dispatch_async(smbd_arg_t *req_arg) 285 { 286 smbd_arg_t *arg = NULL; 287 char *data = NULL; 288 pthread_attr_t attr; 289 pthread_t tid; 290 int rc; 291 292 if ((req_arg->hdr.dh_flags & SMB_DF_ASYNC) == 0) { 293 errno = EINVAL; 294 return (-1); 295 } 296 297 if ((arg = malloc(sizeof (smbd_arg_t))) == NULL) { 298 syslog(LOG_DEBUG, "smbd_door_dispatch_async[%s]: %m", 299 req_arg->opname); 300 return (-1); 301 } 302 303 (void) memcpy(arg, req_arg, sizeof (smbd_arg_t)); 304 arg->data = NULL; 305 306 if (req_arg->datalen != 0) { 307 if ((data = malloc(req_arg->datalen)) == NULL) { 308 free(arg); 309 syslog(LOG_DEBUG, "smbd_door_dispatch_async[%s]: %m", 310 req_arg->opname); 311 return (-1); 312 } 313 314 (void) memcpy(data, req_arg->data, req_arg->datalen); 315 arg->data = data; 316 } 317 318 (void) mutex_lock(&smbd_doorsvc.sd_mutex); 319 arg->magic = SMBD_ARG_MAGIC; 320 list_insert_tail(&smbd_doorsvc.sd_async_list, arg); 321 ++smbd_doorsvc.sd_async_count; 322 (void) mutex_unlock(&smbd_doorsvc.sd_mutex); 323 324 (void) pthread_attr_init(&attr); 325 (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 326 rc = pthread_create(&tid, &attr, smbd_door_dispatch_op, arg); 327 (void) pthread_attr_destroy(&attr); 328 329 if (rc != 0) { 330 (void) mutex_lock(&smbd_doorsvc.sd_mutex); 331 smbd_door_release_async(arg); 332 (void) mutex_unlock(&smbd_doorsvc.sd_mutex); 333 } 334 335 return (rc); 336 } 337 338 /* 339 * Remove an entry from the async response pending list and free 340 * the arg and associated data. 341 * 342 * Must only be called while holding the smbd_doorsvc mutex. 343 */ 344 static void 345 smbd_door_release_async(smbd_arg_t *arg) 346 { 347 if (arg != NULL) { 348 assert(arg->magic == SMBD_ARG_MAGIC); 349 arg->magic = (uint32_t)~SMBD_ARG_MAGIC; 350 351 list_remove(&smbd_doorsvc.sd_async_list, arg); 352 --smbd_doorsvc.sd_async_count; 353 free(arg->data); 354 arg->data = NULL; 355 free(arg); 356 } 357 } 358 359 /* 360 * All door calls are processed here: synchronous or asynchronous: 361 * - synchronous calls are invoked by direct function call 362 * - asynchronous calls are invoked from a launched thread 363 * 364 * If the kernel has attempted to collect a response before the op 365 * has completed, the arg will have been marked as response_abort 366 * and we can discard the response data and release the arg. 367 * 368 * We send a notification when asynchronous (ASYNC) door calls 369 * from the kernel (SYSSPACE) have completed. 370 */ 371 void * 372 smbd_door_dispatch_op(void *thread_arg) 373 { 374 smbd_arg_t *arg = (smbd_arg_t *)thread_arg; 375 smbd_doorop_t *doorop; 376 smb_doorhdr_t *hdr; 377 int i; 378 379 if ((!smbd_online()) || arg == NULL) 380 return (NULL); 381 382 hdr = &arg->hdr; 383 arg->opname = smb_doorhdr_opname(hdr->dh_op); 384 385 for (i = 0; i < smbd_ndoorop; ++i) { 386 doorop = &smbd_doorops[i]; 387 388 if (hdr->dh_op == doorop->opcode) { 389 hdr->dh_door_rc = doorop->op(arg); 390 hdr->dh_status = arg->status; 391 392 if ((hdr->dh_flags & SMB_DF_SYSSPACE) && 393 (hdr->dh_flags & SMB_DF_ASYNC)) { 394 assert(hdr->dh_op != SMB_DR_ASYNC_RESPONSE); 395 396 (void) mutex_lock(&smbd_doorsvc.sd_mutex); 397 if (arg->response_abort) { 398 free(arg->rbuf); 399 arg->rbuf = NULL; 400 smbd_door_release_async(arg); 401 } else { 402 arg->response_ready = B_TRUE; 403 } 404 (void) mutex_unlock(&smbd_doorsvc.sd_mutex); 405 406 (void) smb_kmod_event_notify(hdr->dh_txid); 407 } 408 409 return (NULL); 410 } 411 } 412 413 syslog(LOG_ERR, "smbd_door_dispatch_op[%s]: invalid op %u", 414 arg->opname, hdr->dh_op); 415 return (NULL); 416 } 417 418 /* 419 * Wrapper for door_return. smbd_door_enter() increments a reference count 420 * when a door call is dispatched and smbd_door_return() decrements the 421 * reference count when it completes. 422 * 423 * The reference counting is used in smbd_door_fini() to wait for active 424 * calls to complete before closing the door. 425 */ 426 void 427 smbd_door_init(smbd_door_t *sdh, const char *name) 428 { 429 (void) strlcpy(sdh->sd_name, name, sizeof (sdh->sd_name)); 430 } 431 432 void 433 smbd_door_enter(smbd_door_t *sdh) 434 { 435 (void) mutex_lock(&sdh->sd_mutex); 436 ++sdh->sd_ncalls; 437 (void) mutex_unlock(&sdh->sd_mutex); 438 } 439 440 /* 441 * We have two calls to door_return because the first call (with data) 442 * can fail, which can leave the door call blocked here. The second 443 * call (with NULL) is guaranteed to unblock and return to the caller. 444 */ 445 void 446 smbd_door_return(smbd_door_t *sdh, char *data_ptr, size_t data_size, 447 door_desc_t *desc_ptr, uint_t num_desc) 448 { 449 (void) mutex_lock(&sdh->sd_mutex); 450 451 if (sdh->sd_ncalls == 0) 452 syslog(LOG_ERR, "smbd_door_return[%s]: unexpected count=0", 453 sdh->sd_name); 454 else 455 --sdh->sd_ncalls; 456 457 (void) cond_broadcast(&sdh->sd_cv); 458 (void) mutex_unlock(&sdh->sd_mutex); 459 460 (void) door_return(data_ptr, data_size, desc_ptr, num_desc); 461 (void) door_return(NULL, 0, NULL, 0); 462 /* NOTREACHED */ 463 } 464 465 /* 466 * A door service is about to terminate. 467 * Give active requests a small grace period to complete. 468 */ 469 void 470 smbd_door_fini(smbd_door_t *sdh) 471 { 472 timestruc_t delay; 473 int rc = 0; 474 475 (void) mutex_lock(&sdh->sd_mutex); 476 477 while (rc != ETIME && sdh->sd_ncalls != 0) { 478 delay.tv_sec = 1; 479 delay.tv_nsec = 0; 480 rc = cond_reltimedwait(&sdh->sd_cv, &sdh->sd_mutex, &delay); 481 } 482 483 if (sdh->sd_ncalls != 0) 484 syslog(LOG_NOTICE, "smbd_door_fini[%s]: %d remaining", 485 sdh->sd_name, sdh->sd_ncalls); 486 487 (void) mutex_unlock(&sdh->sd_mutex); 488 } 489 490 /* 491 * Null door operation: always returns success. 492 * Assumes no request or response data. 493 */ 494 /*ARGSUSED*/ 495 static int 496 smbd_dop_null(smbd_arg_t *arg) 497 { 498 return (SMB_DOP_SUCCESS); 499 } 500 501 /* 502 * Async response handler: setup the rbuf and rsize for the specified 503 * transaction. This function is used by the kernel to collect the 504 * response half of an asynchronous door call. 505 * 506 * If a door client attempts to collect a response before the op has 507 * completed (!response_ready), mark the arg as response_abort and 508 * set an error. The response will be discarded when the op completes. 509 */ 510 static int 511 smbd_dop_async_response(smbd_arg_t *rsp_arg) 512 { 513 list_t *arg_list = &smbd_doorsvc.sd_async_list; 514 smbd_arg_t *arg; 515 516 (void) mutex_lock(&smbd_doorsvc.sd_mutex); 517 arg = list_head(arg_list); 518 519 while (arg != NULL) { 520 assert(arg->magic == SMBD_ARG_MAGIC); 521 522 if (arg->hdr.dh_txid == rsp_arg->hdr.dh_txid) { 523 if (!arg->response_ready) { 524 arg->response_abort = B_TRUE; 525 rsp_arg->hdr.dh_door_rc = SMB_DOP_NOT_CALLED; 526 syslog(LOG_NOTICE, "doorsvc[%s]: %u not ready", 527 arg->opname, arg->hdr.dh_txid); 528 break; 529 } 530 531 rsp_arg->rbuf = arg->rbuf; 532 rsp_arg->rsize = arg->rsize; 533 arg->rbuf = NULL; 534 arg->rsize = 0; 535 smbd_door_release_async(arg); 536 break; 537 } 538 539 arg = list_next(arg_list, arg); 540 } 541 542 (void) mutex_unlock(&smbd_doorsvc.sd_mutex); 543 return (SMB_DOP_SUCCESS); 544 } 545 546 static int 547 smbd_dop_user_nonauth_logon(smbd_arg_t *arg) 548 { 549 uint32_t sid = 0; 550 551 if (smb_common_decode(arg->data, arg->datalen, 552 xdr_uint32_t, &sid) != 0) 553 return (SMB_DOP_DECODE_ERROR); 554 555 smbd_user_nonauth_logon(sid); 556 return (SMB_DOP_SUCCESS); 557 } 558 559 static int 560 smbd_dop_user_auth_logoff(smbd_arg_t *arg) 561 { 562 uint32_t sid = 0; 563 564 if (smb_common_decode(arg->data, arg->datalen, 565 xdr_uint32_t, &sid) != 0) 566 return (SMB_DOP_DECODE_ERROR); 567 568 smbd_user_auth_logoff(sid); 569 return (SMB_DOP_SUCCESS); 570 } 571 572 /* 573 * Obtains an access token on successful user authentication. 574 */ 575 static int 576 smbd_dop_user_auth_logon(smbd_arg_t *arg) 577 { 578 _NOTE(ARGUNUSED(arg)) 579 580 /* No longer used */ 581 return (SMB_DOP_EMPTYBUF); 582 } 583 584 static int 585 smbd_dop_lookup_name(smbd_arg_t *arg) 586 { 587 smb_domain_t dinfo; 588 smb_account_t ainfo; 589 lsa_account_t acct; 590 char buf[MAXNAMELEN]; 591 592 bzero(&acct, sizeof (lsa_account_t)); 593 594 if (smb_common_decode(arg->data, arg->datalen, 595 lsa_account_xdr, &acct) != 0) 596 return (SMB_DOP_DECODE_ERROR); 597 598 if (*acct.a_domain == '\0') 599 (void) snprintf(buf, MAXNAMELEN, "%s", acct.a_name); 600 else if (strchr(acct.a_domain, '.') != NULL) 601 (void) snprintf(buf, MAXNAMELEN, "%s@%s", acct.a_name, 602 acct.a_domain); 603 else 604 (void) snprintf(buf, MAXNAMELEN, "%s\\%s", acct.a_domain, 605 acct.a_name); 606 607 acct.a_status = lsa_lookup_name(buf, acct.a_sidtype, &ainfo); 608 if (acct.a_status == NT_STATUS_SUCCESS) { 609 acct.a_sidtype = ainfo.a_type; 610 smb_sid_tostr(ainfo.a_sid, acct.a_sid); 611 (void) strlcpy(acct.a_name, ainfo.a_name, MAXNAMELEN); 612 613 if (smb_domain_lookup_name(ainfo.a_domain, &dinfo)) 614 (void) strlcpy(acct.a_domain, dinfo.di_fqname, 615 MAXNAMELEN); 616 else 617 (void) strlcpy(acct.a_domain, ainfo.a_domain, 618 MAXNAMELEN); 619 smb_account_free(&ainfo); 620 } 621 622 arg->rbuf = smb_common_encode(&acct, lsa_account_xdr, &arg->rsize); 623 624 if (arg->rbuf == NULL) 625 return (SMB_DOP_ENCODE_ERROR); 626 return (SMB_DOP_SUCCESS); 627 } 628 629 static int 630 smbd_dop_lookup_sid(smbd_arg_t *arg) 631 { 632 smb_domain_t dinfo; 633 smb_account_t ainfo; 634 lsa_account_t acct; 635 smb_sid_t *sid; 636 637 bzero(&acct, sizeof (lsa_account_t)); 638 639 if (smb_common_decode(arg->data, arg->datalen, 640 lsa_account_xdr, &acct) != 0) 641 return (SMB_DOP_DECODE_ERROR); 642 643 sid = smb_sid_fromstr(acct.a_sid); 644 acct.a_status = lsa_lookup_sid(sid, &ainfo); 645 smb_sid_free(sid); 646 647 if (acct.a_status == NT_STATUS_SUCCESS) { 648 acct.a_sidtype = ainfo.a_type; 649 smb_sid_tostr(ainfo.a_sid, acct.a_sid); 650 (void) strlcpy(acct.a_name, ainfo.a_name, MAXNAMELEN); 651 652 if (smb_domain_lookup_name(ainfo.a_domain, &dinfo)) 653 (void) strlcpy(acct.a_domain, dinfo.di_fqname, 654 MAXNAMELEN); 655 else 656 (void) strlcpy(acct.a_domain, ainfo.a_domain, 657 MAXNAMELEN); 658 659 smb_account_free(&ainfo); 660 } 661 662 arg->rbuf = smb_common_encode(&acct, lsa_account_xdr, &arg->rsize); 663 664 if (arg->rbuf == NULL) 665 return (SMB_DOP_ENCODE_ERROR); 666 return (SMB_DOP_SUCCESS); 667 } 668 669 static int 670 smbd_dop_join(smbd_arg_t *arg) 671 { 672 smb_joininfo_t jdi; 673 smb_joinres_t jdres; 674 675 bzero(&jdi, sizeof (smb_joininfo_t)); 676 bzero(&jdres, sizeof (smb_joinres_t)); 677 678 if (smb_common_decode(arg->data, arg->datalen, 679 smb_joininfo_xdr, &jdi) != 0) 680 return (SMB_DOP_DECODE_ERROR); 681 682 smbd_join(&jdi, &jdres); 683 684 arg->rbuf = smb_common_encode(&jdres, smb_joinres_xdr, &arg->rsize); 685 686 if (arg->rbuf == NULL) 687 return (SMB_DOP_ENCODE_ERROR); 688 return (SMB_DOP_SUCCESS); 689 } 690 691 static int 692 smbd_dop_get_dcinfo(smbd_arg_t *arg) 693 { 694 smb_domainex_t dxi; 695 696 if (!smb_domain_getinfo(&dxi)) 697 return (SMB_DOP_EMPTYBUF); 698 699 arg->rbuf = smb_string_encode(dxi.d_dci.dc_name, &arg->rsize); 700 701 if (arg->rbuf == NULL) 702 return (SMB_DOP_ENCODE_ERROR); 703 return (SMB_DOP_SUCCESS); 704 } 705 706 /* 707 * Return the number of snapshots for a dataset 708 */ 709 static int 710 smbd_dop_vss_get_count(smbd_arg_t *arg) 711 { 712 smb_string_t path; 713 uint32_t count; 714 715 bzero(&path, sizeof (smb_string_t)); 716 arg->rbuf = NULL; 717 718 if (smb_string_decode(&path, arg->data, arg->datalen) != 0) 719 return (SMB_DOP_DECODE_ERROR); 720 721 if (smbd_vss_get_count(path.buf, &count) == 0) 722 arg->rbuf = smb_common_encode(&count, xdr_uint32_t, 723 &arg->rsize); 724 725 xdr_free(smb_string_xdr, (char *)&path); 726 727 if (arg->rbuf == NULL) 728 return (SMB_DOP_ENCODE_ERROR); 729 return (SMB_DOP_SUCCESS); 730 } 731 732 /* 733 * Return the count and list of snapshots. 734 * The list is in @GMT token format. 735 */ 736 static int 737 smbd_dop_vss_get_snapshots(smbd_arg_t *arg) 738 { 739 char **gmtp; 740 smb_gmttoken_query_t request; 741 smb_gmttoken_response_t reply; 742 uint_t i; 743 744 bzero(&request, sizeof (smb_gmttoken_query_t)); 745 bzero(&reply, sizeof (smb_gmttoken_response_t)); 746 747 if (smb_common_decode(arg->data, arg->datalen, 748 smb_gmttoken_query_xdr, &request) != 0) 749 return (SMB_DOP_DECODE_ERROR); 750 751 reply.gtr_gmttokens.gtr_gmttokens_val = malloc(request.gtq_count * 752 sizeof (char *)); 753 bzero(reply.gtr_gmttokens.gtr_gmttokens_val, request.gtq_count * 754 sizeof (char *)); 755 756 if (reply.gtr_gmttokens.gtr_gmttokens_val == NULL) { 757 xdr_free(smb_gmttoken_query_xdr, (char *)&request); 758 return (SMB_DOP_EMPTYBUF); 759 } 760 761 smbd_vss_get_snapshots(request.gtq_path, request.gtq_count, 762 &reply.gtr_count, 763 &reply.gtr_gmttokens.gtr_gmttokens_len, 764 reply.gtr_gmttokens.gtr_gmttokens_val); 765 766 arg->rbuf = smb_common_encode(&reply, smb_gmttoken_response_xdr, 767 &arg->rsize); 768 if (arg->rbuf == NULL) { 769 xdr_free(smb_gmttoken_query_xdr, (char *)&request); 770 return (SMB_DOP_ENCODE_ERROR); 771 } 772 773 for (i = 0, gmtp = reply.gtr_gmttokens.gtr_gmttokens_val; 774 (i < request.gtq_count); i++) { 775 if (*gmtp) 776 free(*gmtp); 777 gmtp++; 778 } 779 780 free(reply.gtr_gmttokens.gtr_gmttokens_val); 781 xdr_free(smb_gmttoken_query_xdr, (char *)&request); 782 return (SMB_DOP_SUCCESS); 783 } 784 785 /* 786 * Return the name of the snapshot that matches the dataset path 787 * and @GMT token. 788 */ 789 static int 790 smbd_dop_vss_map_gmttoken(smbd_arg_t *arg) 791 { 792 char *snapname; 793 smb_gmttoken_snapname_t request; 794 795 bzero(&request, sizeof (smb_gmttoken_snapname_t)); 796 797 if (smb_common_decode(arg->data, arg->datalen, 798 smb_gmttoken_snapname_xdr, &request) != 0) { 799 xdr_free(smb_gmttoken_snapname_xdr, (char *)&request); 800 return (SMB_DOP_DECODE_ERROR); 801 } 802 803 if ((snapname = malloc(MAXPATHLEN)) == NULL) { 804 xdr_free(smb_gmttoken_snapname_xdr, (char *)&request); 805 return (NULL); 806 } 807 808 if ((smbd_vss_map_gmttoken(request.gts_path, request.gts_gmttoken, 809 snapname) != 0)) { 810 *snapname = '\0'; 811 } 812 813 arg->rbuf = smb_string_encode(snapname, &arg->rsize); 814 xdr_free(smb_gmttoken_snapname_xdr, (char *)&request); 815 free(snapname); 816 817 if (arg->rbuf == NULL) 818 return (SMB_DOP_ENCODE_ERROR); 819 return (SMB_DOP_SUCCESS); 820 } 821 822 static int 823 smbd_dop_ads_find_host(smbd_arg_t *arg) 824 { 825 smb_ads_host_info_t *hinfo = NULL; 826 char *hostname = ""; 827 smb_string_t fqdn; 828 829 bzero(&fqdn, sizeof (smb_string_t)); 830 831 if (smb_string_decode(&fqdn, arg->data, arg->datalen) != 0) 832 return (SMB_DOP_DECODE_ERROR); 833 834 if ((hinfo = smb_ads_find_host(fqdn.buf)) != NULL) 835 hostname = hinfo->name; 836 837 xdr_free(smb_string_xdr, (char *)&fqdn); 838 839 arg->rbuf = smb_string_encode(hostname, &arg->rsize); 840 free(hinfo); 841 842 if (arg->rbuf == NULL) 843 return (SMB_DOP_ENCODE_ERROR); 844 return (SMB_DOP_SUCCESS); 845 } 846 847 /* 848 * Query the list of user/group quota entries for a given filesystem. 849 */ 850 static int 851 smbd_dop_quota_query(smbd_arg_t *arg) 852 { 853 smb_quota_query_t request; 854 smb_quota_response_t reply; 855 uint32_t status; 856 857 bzero(&request, sizeof (smb_quota_query_t)); 858 bzero(&reply, sizeof (smb_quota_response_t)); 859 860 if (smb_common_decode(arg->data, arg->datalen, 861 smb_quota_query_xdr, &request) != 0) 862 return (SMB_DOP_DECODE_ERROR); 863 864 status = smb_quota_query(&request, &reply); 865 reply.qr_status = status; 866 867 arg->rbuf = smb_common_encode(&reply, smb_quota_response_xdr, 868 &arg->rsize); 869 870 xdr_free(smb_quota_query_xdr, (char *)&request); 871 smb_quota_free(&reply); 872 873 if (arg->rbuf == NULL) 874 return (SMB_DOP_ENCODE_ERROR); 875 return (SMB_DOP_SUCCESS); 876 } 877 878 /* 879 * Set a list of user/group quota entries for a given filesystem. 880 */ 881 static int 882 smbd_dop_quota_set(smbd_arg_t *arg) 883 { 884 smb_quota_set_t request; 885 uint32_t status = 0; 886 887 bzero(&request, sizeof (smb_quota_set_t)); 888 889 if (smb_common_decode(arg->data, arg->datalen, 890 smb_quota_set_xdr, &request) != 0) 891 return (SMB_DOP_DECODE_ERROR); 892 893 status = smb_quota_set(&request); 894 895 arg->rbuf = smb_common_encode(&status, xdr_uint32_t, &arg->rsize); 896 xdr_free(smb_quota_set_xdr, (char *)&request); 897 898 if (arg->rbuf == NULL) 899 return (SMB_DOP_ENCODE_ERROR); 900 return (SMB_DOP_SUCCESS); 901 } 902 903 static int 904 smbd_dop_dfs_get_referrals(smbd_arg_t *arg) 905 { 906 dfs_referral_query_t request; 907 dfs_referral_response_t reply; 908 909 bzero(&request, sizeof (request)); 910 bzero(&reply, sizeof (reply)); 911 912 if (smb_common_decode(arg->data, arg->datalen, 913 dfs_referral_query_xdr, &request) != 0) 914 return (SMB_DOP_DECODE_ERROR); 915 916 reply.rp_status = dfs_get_referrals((const char *)request.rq_path, 917 request.rq_type, &reply.rp_referrals); 918 919 if (reply.rp_status != ERROR_SUCCESS) 920 bzero(&reply.rp_referrals, sizeof (dfs_info_t)); 921 922 arg->rbuf = smb_common_encode(&reply, dfs_referral_response_xdr, 923 &arg->rsize); 924 925 if (reply.rp_status == ERROR_SUCCESS) 926 dfs_info_free(&reply.rp_referrals); 927 928 xdr_free(dfs_referral_query_xdr, (char *)&request); 929 930 if (arg->rbuf == NULL) 931 return (SMB_DOP_ENCODE_ERROR); 932 return (SMB_DOP_SUCCESS); 933 } 934 935 static int 936 smbd_dop_shr_hostaccess(smbd_arg_t *arg) 937 { 938 smb_shr_hostaccess_query_t request; 939 uint32_t reply; 940 941 bzero(&request, sizeof (request)); 942 bzero(&reply, sizeof (reply)); 943 944 if (smb_common_decode(arg->data, arg->datalen, 945 smb_shr_hostaccess_query_xdr, &request) != 0) 946 return (SMB_DOP_DECODE_ERROR); 947 948 reply = smb_shr_hostaccess(&request.shq_ipaddr, request.shq_none, 949 request.shq_ro, request.shq_rw, request.shq_flag); 950 951 arg->rbuf = smb_common_encode(&reply, xdr_uint32_t, &arg->rsize); 952 953 xdr_free(smb_shr_hostaccess_query_xdr, (char *)&request); 954 955 if (arg->rbuf == NULL) 956 return (SMB_DOP_ENCODE_ERROR); 957 return (SMB_DOP_SUCCESS); 958 } 959 960 static int 961 smbd_dop_shr_exec(smbd_arg_t *arg) 962 { 963 smb_shr_execinfo_t request; 964 int reply; 965 966 bzero(&request, sizeof (request)); 967 bzero(&reply, sizeof (reply)); 968 969 if (smb_common_decode(arg->data, arg->datalen, 970 smb_shr_execinfo_xdr, &request) != 0) 971 return (SMB_DOP_DECODE_ERROR); 972 973 reply = smb_shr_exec(&request); 974 975 if (reply != 0) 976 syslog(LOG_NOTICE, "Failed to execute %s command", 977 (request.e_type == SMB_EXEC_MAP) ? "map" : "unmap"); 978 979 arg->rbuf = smb_common_encode(&reply, xdr_int, &arg->rsize); 980 981 xdr_free(smb_shr_execinfo_xdr, (char *)&request); 982 983 if (arg->rbuf == NULL) 984 return (SMB_DOP_ENCODE_ERROR); 985 return (SMB_DOP_SUCCESS); 986 } 987 988 /* ARGSUSED */ 989 static int 990 smbd_dop_notify_dc_changed(smbd_arg_t *arg) 991 { 992 993 smbd_dc_monitor_refresh(); 994 995 return (SMB_DOP_SUCCESS); 996 } 997