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