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 2014 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             request.gts_toktime, 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 }