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