1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 #include <smbsrv/smb_kproto.h>
  28 #include <smbsrv/smb_fsops.h>
  29 #include <smbsrv/smb_share.h>
  30 #include <smbsrv/string.h>
  31 #include <smbsrv/nmpipes.h>
  32 #include <smbsrv/mailslot.h>
  33 #include <smbsrv/winioctl.h>
  34 
  35 /*
  36  * count of bytes in server response packet
  37  * except parameters and data. Note that setup
  38  * word count is zero.
  39  */
  40 #define RESP_HEADER_LEN         24
  41 
  42 /*
  43  * We started by using common functions for transaction/transaction2
  44  * and transaction_secondary/transaction2_secondary because they
  45  * are respectively so similar. However, it turned out to be a bad
  46  * idea because of quirky differences. Be sure if you modify one
  47  * of these four functions to check and see if the modification should
  48  * be applied to its peer.
  49  */
  50 
  51 static int smb_trans_ready(smb_xa_t *);
  52 static smb_sdrc_t smb_trans_dispatch(smb_request_t *, smb_xa_t *);
  53 static smb_sdrc_t smb_trans2_dispatch(smb_request_t *, smb_xa_t *);
  54 
  55 smb_sdrc_t
  56 smb_pre_transaction(smb_request_t *sr)
  57 {
  58         DTRACE_SMB_1(op__Transaction__start, smb_request_t *, sr);
  59         return (SDRC_SUCCESS);
  60 }
  61 
  62 void
  63 smb_post_transaction(smb_request_t *sr)
  64 {
  65         DTRACE_SMB_1(op__Transaction__done, smb_request_t *, sr);
  66 }
  67 
  68 smb_sdrc_t
  69 smb_com_transaction(smb_request_t *sr)
  70 {
  71         int             rc;
  72         unsigned char   msrcnt, suwcnt;
  73         uint16_t        tpscnt, tdscnt, mprcnt, mdrcnt, flags;
  74         uint16_t        pscnt, psoff, dscnt, dsoff;
  75         uint32_t        timeo;
  76         struct smb_xa *xa;
  77         char *stn;
  78         int ready;
  79 
  80         if (!STYPE_ISIPC(sr->tid_tree->t_res_type)) {
  81                 smbsr_error(sr, 0, ERRDOS, ERRnoaccess);
  82                 return (SDRC_ERROR);
  83         }
  84 
  85         rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT,
  86             &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags,
  87             &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt);
  88 
  89         if (rc != 0)
  90                 return (SDRC_ERROR);
  91 
  92         xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
  93             msrcnt, suwcnt);
  94         if (xa == NULL) {
  95                 smbsr_error(sr, 0, ERRSRV, ERRnoroom);
  96                 return (SDRC_ERROR);
  97         }
  98 
  99         /* Should be some alignment stuff here in SMB? */
 100         if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) {
 101                 rc = smbsr_decode_data(sr, "%.U", sr, &stn);
 102         } else {
 103                 rc = smbsr_decode_data(sr, "%s", sr,  &stn);
 104         }
 105         if (rc != 0) {
 106                 smb_xa_rele(sr->session, xa);
 107                 return (SDRC_ERROR);
 108         }
 109 
 110         xa->xa_pipe_name = smb_mem_strdup(stn);
 111         xa->smb_flags  = flags;
 112         xa->smb_timeout = timeo;
 113         xa->req_disp_param = pscnt;
 114         xa->req_disp_data  = dscnt;
 115 
 116         if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
 117             sr->smb_vwv.chain_offset, suwcnt * 2)) {
 118                 smb_xa_rele(sr->session, xa);
 119                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 120                 return (SDRC_ERROR);
 121         }
 122         if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
 123                 smb_xa_rele(sr->session, xa);
 124                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 125                 return (SDRC_ERROR);
 126         }
 127         if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
 128                 smb_xa_rele(sr->session, xa);
 129                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 130                 return (SDRC_ERROR);
 131         }
 132 
 133         ready = smb_trans_ready(xa);
 134 
 135         if (smb_xa_open(xa)) {
 136                 smb_xa_rele(sr->session, xa);
 137                 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
 138                 return (SDRC_ERROR);
 139         }
 140         sr->r_xa = xa;
 141 
 142         if (!ready) {
 143                 rc = smbsr_encode_empty_result(sr);
 144                 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 145         }
 146 
 147         if (!smb_xa_complete(xa)) {
 148                 smb_xa_close(xa);
 149                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 150                 return (SDRC_ERROR);
 151         }
 152 
 153         return (smb_trans_dispatch(sr, xa));
 154 }
 155 
 156 smb_sdrc_t
 157 smb_pre_transaction_secondary(smb_request_t *sr)
 158 {
 159         DTRACE_SMB_1(op__TransactionSecondary__start, smb_request_t *, sr);
 160         return (SDRC_SUCCESS);
 161 }
 162 
 163 void
 164 smb_post_transaction_secondary(smb_request_t *sr)
 165 {
 166         DTRACE_SMB_1(op__TransactionSecondary__done, smb_request_t *, sr);
 167 }
 168 
 169 smb_sdrc_t
 170 smb_com_transaction_secondary(smb_request_t *sr)
 171 {
 172         uint16_t tpscnt, tdscnt, pscnt, psdisp;
 173         uint16_t dscnt, dsoff, dsdisp, psoff;
 174         smb_xa_t *xa;
 175         int rc;
 176 
 177         if ((xa = smbsr_lookup_xa(sr)) == 0) {
 178                 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
 179                 return (SDRC_ERROR);
 180         }
 181 
 182         if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
 183                 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
 184                         smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 185                             ERRDOS, ERRnoaccess);
 186                         return (SDRC_ERROR);
 187                 }
 188         }
 189 
 190         if (xa->smb_com != SMB_COM_TRANSACTION) {
 191                 return (SDRC_DROP_VC);
 192         }
 193 
 194         rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt,
 195             &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp);
 196 
 197         if (rc != 0)
 198                 return (SDRC_ERROR);
 199 
 200         mutex_enter(&xa->xa_mutex);
 201         if (xa->smb_tpscnt > tpscnt)
 202                 xa->smb_tpscnt = tpscnt;
 203         if (xa->smb_tdscnt > tdscnt)
 204                 xa->smb_tdscnt = tdscnt;
 205         xa->req_disp_param = psdisp + pscnt;
 206         xa->req_disp_data  = dsdisp + dscnt;
 207 
 208         /*
 209          * The words psdisp, dsdisp, tell us what displacement
 210          * into the entire trans parameter and data buffers
 211          * where we should put the params & data that are
 212          * delivered by this request.  [MS-CIFS] says all the
 213          * parameters and data SHOULD be sent sequentially, so
 214          * so we can normally reassemble by simply appending.
 215          * However, the components MAY come out of order, so
 216          * check and set the current offset.  This is rare,
 217          * and we might like to know when this happens, so
 218          * fire some static dtrace probes when it does.
 219          */
 220         if (xa->req_param_mb.chain_offset != psdisp) {
 221                 DTRACE_PROBE2(trans_param_disp,
 222                     smb_xa_t *, xa, uint16_t, psdisp);
 223                 xa->req_param_mb.chain_offset = psdisp;
 224         }
 225         if (xa->req_data_mb.chain_offset != dsdisp) {
 226                 DTRACE_PROBE2(trans_data_disp,
 227                     smb_xa_t *, xa, uint16_t, dsdisp);
 228                 xa->req_data_mb.chain_offset = dsdisp;
 229         }
 230 
 231         if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
 232                 mutex_exit(&xa->xa_mutex);
 233                 smb_xa_close(xa);
 234                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 235                 return (SDRC_ERROR);
 236         }
 237         if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
 238                 mutex_exit(&xa->xa_mutex);
 239                 smb_xa_close(xa);
 240                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 241                 return (SDRC_ERROR);
 242         }
 243         mutex_exit(&xa->xa_mutex);
 244 
 245         if (!smb_trans_ready(xa))
 246                 return (SDRC_NO_REPLY);
 247 
 248         if (!smb_xa_complete(xa))
 249                 return (SDRC_NO_REPLY);
 250 
 251         return (smb_trans_dispatch(sr, xa));
 252 }
 253 
 254 smb_sdrc_t
 255 smb_pre_ioctl(smb_request_t *sr)
 256 {
 257         DTRACE_SMB_1(op__Ioctl__start, smb_request_t *, sr);
 258         return (SDRC_SUCCESS);
 259 }
 260 
 261 void
 262 smb_post_ioctl(smb_request_t *sr)
 263 {
 264         DTRACE_SMB_1(op__Ioctl__done, smb_request_t *, sr);
 265 }
 266 
 267 smb_sdrc_t
 268 smb_com_ioctl(smb_request_t *sr)
 269 {
 270         uint16_t fid, category, function, tpscnt, tdscnt, mprcnt;
 271         uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff;
 272         uint32_t timeout;
 273         int rc;
 274 
 275         rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function,
 276             &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt,
 277             &pdoff, &dscnt, &dsoff);
 278 
 279         if (rc != 0)
 280                 return (SDRC_ERROR);
 281 
 282         return (SDRC_NOT_IMPLEMENTED);
 283 }
 284 
 285 smb_sdrc_t
 286 smb_pre_transaction2(smb_request_t *sr)
 287 {
 288         DTRACE_SMB_1(op__Transaction2__start, smb_request_t *, sr);
 289         return (SDRC_SUCCESS);
 290 }
 291 
 292 void
 293 smb_post_transaction2(smb_request_t *sr)
 294 {
 295         DTRACE_SMB_1(op__Transaction2__done, smb_request_t *, sr);
 296 }
 297 
 298 smb_sdrc_t
 299 smb_com_transaction2(struct smb_request *sr)
 300 {
 301         unsigned char   msrcnt, suwcnt;
 302         uint16_t        tpscnt, tdscnt, mprcnt, mdrcnt, flags;
 303         uint16_t        pscnt, psoff, dscnt, dsoff;
 304         uint32_t        timeo;
 305         smb_xa_t *xa;
 306         int ready;
 307         int rc;
 308 
 309         rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt,
 310             &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt,
 311             &dsoff, &suwcnt);
 312 
 313         if (rc != 0)
 314                 return (SDRC_ERROR);
 315 
 316         xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
 317             msrcnt, suwcnt);
 318         if (xa == 0) {
 319                 smbsr_error(sr, 0, ERRSRV, ERRnoroom);
 320                 return (SDRC_ERROR);
 321         }
 322 
 323         xa->smb_flags  = flags;
 324         xa->smb_timeout = timeo;
 325         xa->req_disp_param = pscnt;
 326         xa->req_disp_data  = dscnt;
 327 
 328         if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
 329             sr->smb_vwv.chain_offset, suwcnt*2)) {
 330                 smb_xa_rele(sr->session, xa);
 331                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 332                 return (SDRC_ERROR);
 333         }
 334         if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
 335                 smb_xa_rele(sr->session, xa);
 336                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 337                 return (SDRC_ERROR);
 338         }
 339         if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
 340                 smb_xa_rele(sr->session, xa);
 341                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 342                 return (SDRC_ERROR);
 343         }
 344 
 345         ready = smb_trans_ready(xa);
 346 
 347         if (smb_xa_open(xa)) {
 348                 smb_xa_rele(sr->session, xa);
 349                 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
 350                 return (SDRC_ERROR);
 351         }
 352         sr->r_xa = xa;
 353 
 354         if (!ready) {
 355                 rc = smbsr_encode_empty_result(sr);
 356                 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 357         }
 358 
 359         if (!smb_xa_complete(xa)) {
 360                 smb_xa_close(xa);
 361                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 362                 return (SDRC_ERROR);
 363         }
 364 
 365         return (smb_trans2_dispatch(sr, xa));
 366 }
 367 
 368 smb_sdrc_t
 369 smb_pre_transaction2_secondary(smb_request_t *sr)
 370 {
 371         DTRACE_SMB_1(op__Transaction2Secondary__start, smb_request_t *, sr);
 372         return (SDRC_SUCCESS);
 373 }
 374 
 375 void
 376 smb_post_transaction2_secondary(smb_request_t *sr)
 377 {
 378         DTRACE_SMB_1(op__Transaction2Secondary__done, smb_request_t *, sr);
 379 }
 380 
 381 smb_sdrc_t
 382 smb_com_transaction2_secondary(smb_request_t *sr)
 383 {
 384         uint16_t tpscnt, tdscnt, fid;
 385         uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
 386         smb_xa_t *xa;
 387         int rc;
 388 
 389         if ((xa = smbsr_lookup_xa(sr)) == 0) {
 390                 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
 391                 return (SDRC_ERROR);
 392         }
 393 
 394         if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
 395                 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
 396                         smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 397                             ERRDOS, ERRnoaccess);
 398                         return (SDRC_ERROR);
 399                 }
 400         }
 401 
 402         if (xa->smb_com != SMB_COM_TRANSACTION2) {
 403                 return (SDRC_DROP_VC);
 404         }
 405 
 406         rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
 407             &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
 408 
 409         if (rc != 0)
 410                 return (SDRC_ERROR);
 411 
 412         mutex_enter(&xa->xa_mutex);
 413         if (xa->smb_tpscnt > tpscnt)
 414                 xa->smb_tpscnt = tpscnt;
 415         if (xa->smb_tdscnt > tdscnt)
 416                 xa->smb_tdscnt = tdscnt;
 417         if (fid != 0xFFFF)
 418                 xa->xa_smb_fid = fid;
 419         xa->req_disp_param = psdisp + pscnt;
 420         xa->req_disp_data  = dsdisp + dscnt;
 421 
 422         /*
 423          * See comment in smb_com_transaction_secondary
 424          */
 425         if (xa->req_param_mb.chain_offset != psdisp) {
 426                 DTRACE_PROBE2(trans_param_disp,
 427                     smb_xa_t *, xa, uint16_t, psdisp);
 428                 xa->req_param_mb.chain_offset = psdisp;
 429         }
 430         if (xa->req_data_mb.chain_offset != dsdisp) {
 431                 DTRACE_PROBE2(trans_data_disp,
 432                     smb_xa_t *, xa, uint16_t, dsdisp);
 433                 xa->req_data_mb.chain_offset = dsdisp;
 434         }
 435 
 436         if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
 437                 mutex_exit(&xa->xa_mutex);
 438                 smb_xa_close(xa);
 439                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 440                 return (SDRC_ERROR);
 441         }
 442         if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
 443                 mutex_exit(&xa->xa_mutex);
 444                 smb_xa_close(xa);
 445                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 446                 return (SDRC_ERROR);
 447         }
 448         mutex_exit(&xa->xa_mutex);
 449 
 450         if (!smb_trans_ready(xa))
 451                 return (SDRC_NO_REPLY);
 452 
 453         if (!smb_xa_complete(xa))
 454                 return (SDRC_NO_REPLY);
 455 
 456         return (smb_trans2_dispatch(sr, xa));
 457 }
 458 
 459 static smb_sdrc_t
 460 smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa)
 461 {
 462         int rc;
 463         int total_bytes, n_setup, n_param, n_data;
 464         int param_off, param_pad, data_off, data_pad;
 465 
 466         switch (xa->smb_func) {
 467         case NT_TRANSACT_CREATE:
 468                 if ((rc = smb_pre_nt_transact_create(sr, xa)) == 0)
 469                         rc = smb_nt_transact_create(sr, xa);
 470                 smb_post_nt_transact_create(sr, xa);
 471                 break;
 472         case NT_TRANSACT_NOTIFY_CHANGE:
 473                 rc = smb_nt_transact_notify_change(sr, xa);
 474                 break;
 475         case NT_TRANSACT_QUERY_SECURITY_DESC:
 476                 rc = smb_nt_transact_query_security_info(sr, xa);
 477                 break;
 478         case NT_TRANSACT_SET_SECURITY_DESC:
 479                 rc = smb_nt_transact_set_security_info(sr, xa);
 480                 break;
 481         case NT_TRANSACT_IOCTL:
 482                 rc = smb_nt_transact_ioctl(sr, xa);
 483                 break;
 484         case NT_TRANSACT_QUERY_QUOTA:
 485                 rc = smb_nt_transact_query_quota(sr, xa);
 486                 break;
 487         case NT_TRANSACT_SET_QUOTA:
 488                 rc = smb_nt_transact_set_quota(sr, xa);
 489                 break;
 490         case NT_TRANSACT_RENAME:
 491                 rc = smb_nt_transact_rename(sr, xa);
 492                 break;
 493 
 494         default:
 495                 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
 496                 return (SDRC_ERROR);
 497         }
 498 
 499         switch (rc) {
 500         case SDRC_SUCCESS:
 501                 break;
 502 
 503         case SDRC_DROP_VC:
 504         case SDRC_NO_REPLY:
 505         case SDRC_ERROR:
 506         case SDRC_SR_KEPT:
 507                 return (rc);
 508 
 509         case SDRC_NOT_IMPLEMENTED:
 510                 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
 511                 return (SDRC_ERROR);
 512 
 513         default:
 514                 break;
 515         }
 516 
 517         n_setup = MBC_LENGTH(&xa->rep_setup_mb);
 518         n_param = MBC_LENGTH(&xa->rep_param_mb);
 519         n_data  = MBC_LENGTH(&xa->rep_data_mb);
 520 
 521         if (xa->smb_msrcnt < n_setup ||
 522             xa->smb_mprcnt < n_param ||
 523             xa->smb_mdrcnt < n_data) {
 524                 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
 525                 return (SDRC_ERROR);
 526         }
 527 
 528         /* neato, blast it over there */
 529 
 530         n_setup = (n_setup + 1) / 2;            /* Conver to setup words */
 531         param_pad = 1;                          /* must be one */
 532         param_off = param_pad + 32 + 37 + (n_setup << 1) + 2;
 533         data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Pad to 4 byte */
 534         data_off = param_off + n_param + data_pad; /* Param off from hdr */
 535         total_bytes = param_pad + n_param + data_pad + n_data;
 536 
 537         rc = smbsr_encode_result(sr, 18+n_setup, total_bytes,
 538             "b3.llllllllbCw#.C#.C",
 539             18 + n_setup,               /* wct */
 540             n_param,                    /* Total Parameter Bytes */
 541             n_data,                     /* Total Data Bytes */
 542             n_param,                    /* Total Parameter Bytes this buffer */
 543             param_off,                  /* Param offset from header start */
 544             0,                          /* Param displacement */
 545             n_data,                     /* Total Data Bytes this buffer */
 546             data_off,                   /* Data offset from header start */
 547             0,                          /* Data displacement */
 548             n_setup,                    /* suwcnt */
 549             &xa->rep_setup_mb,           /* setup[] */
 550             total_bytes,                /* Total data bytes */
 551             param_pad,
 552             &xa->rep_param_mb,
 553             data_pad,
 554             &xa->rep_data_mb);
 555         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 556 }
 557 
 558 smb_sdrc_t
 559 smb_pre_nt_transact(smb_request_t *sr)
 560 {
 561         DTRACE_SMB_1(op__NtTransact__start, smb_request_t *, sr);
 562         return (SDRC_SUCCESS);
 563 }
 564 
 565 void
 566 smb_post_nt_transact(smb_request_t *sr)
 567 {
 568         DTRACE_SMB_1(op__NtTransact__done, smb_request_t *, sr);
 569 }
 570 
 571 smb_sdrc_t
 572 smb_com_nt_transact(struct smb_request *sr)
 573 {
 574         uint16_t        Function;
 575         unsigned char   MaxSetupCount, SetupCount;
 576         uint32_t        TotalParameterCount, TotalDataCount;
 577         uint32_t        MaxParameterCount, MaxDataCount, pscnt;
 578         uint32_t        psoff, dscnt, dsoff;
 579         smb_xa_t *xa;
 580         int ready;
 581         int rc;
 582 
 583         rc = smbsr_decode_vwv(sr, SMB_NT_TRANSHDR_ED_FMT, &MaxSetupCount,
 584             &TotalParameterCount, &TotalDataCount, &MaxParameterCount,
 585             &MaxDataCount, &pscnt, &psoff, &dscnt,
 586             &dsoff, &SetupCount, &Function);
 587 
 588         if (rc != 0)
 589                 return (SDRC_ERROR);
 590 
 591         xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount,
 592             MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount);
 593         if (xa == 0) {
 594                 smbsr_error(sr, 0, ERRSRV, ERRnoroom);
 595                 return (SDRC_ERROR);
 596         }
 597 
 598         xa->smb_flags  = 0;
 599         xa->smb_timeout = 0;
 600         xa->smb_func = Function;
 601         xa->req_disp_param = pscnt;
 602         xa->req_disp_data  = dscnt;
 603 
 604         if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
 605             sr->smb_vwv.chain_offset, SetupCount * 2)) {
 606                 smb_xa_rele(sr->session, xa);
 607                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 608                 return (SDRC_ERROR);
 609         }
 610         if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
 611                 smb_xa_rele(sr->session, xa);
 612                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 613                 return (SDRC_ERROR);
 614         }
 615         if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
 616                 smb_xa_rele(sr->session, xa);
 617                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 618                 return (SDRC_ERROR);
 619         }
 620 
 621         ready = smb_trans_ready(xa);
 622 
 623         if (smb_xa_open(xa)) {
 624                 smb_xa_rele(sr->session, xa);
 625                 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
 626                 return (SDRC_ERROR);
 627         }
 628         sr->r_xa = xa;
 629 
 630         if (!ready) {
 631                 rc = smbsr_encode_empty_result(sr);
 632                 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 633         }
 634 
 635         if (!smb_xa_complete(xa)) {
 636                 smb_xa_close(xa);
 637                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 638                 return (SDRC_ERROR);
 639         }
 640 
 641         return (smb_nt_trans_dispatch(sr, xa));
 642 }
 643 
 644 smb_sdrc_t
 645 smb_pre_nt_transact_secondary(smb_request_t *sr)
 646 {
 647         DTRACE_SMB_1(op__NtTransactSecondary__start, smb_request_t *, sr);
 648         return (SDRC_SUCCESS);
 649 }
 650 
 651 void
 652 smb_post_nt_transact_secondary(smb_request_t *sr)
 653 {
 654         DTRACE_SMB_1(op__NtTransactSecondary__done, smb_request_t *, sr);
 655 }
 656 
 657 smb_sdrc_t
 658 smb_com_nt_transact_secondary(struct smb_request *sr)
 659 {
 660         uint16_t tpscnt, tdscnt, fid;
 661         uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
 662         smb_xa_t *xa;
 663         int rc;
 664 
 665         if ((xa = smbsr_lookup_xa(sr)) == 0) {
 666                 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
 667                 return (SDRC_ERROR);
 668         }
 669 
 670         if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
 671                 if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
 672                         smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 673                             ERRDOS, ERRnoaccess);
 674                         return (SDRC_ERROR);
 675                 }
 676         }
 677 
 678         if (xa->smb_com != SMB_COM_TRANSACTION2) {
 679                 return (SDRC_DROP_VC);
 680         }
 681 
 682         rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
 683             &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
 684 
 685         if (rc != 0)
 686                 return (SDRC_ERROR);
 687 
 688         mutex_enter(&xa->xa_mutex);
 689         if (xa->smb_tpscnt > tpscnt)
 690                 xa->smb_tpscnt = tpscnt;
 691         if (xa->smb_tdscnt > tdscnt)
 692                 xa->smb_tdscnt = tdscnt;
 693         if (fid != 0xFFFF)
 694                 xa->xa_smb_fid = fid;
 695         xa->req_disp_param = psdisp + pscnt;
 696         xa->req_disp_data  = dsdisp + dscnt;
 697 
 698         /*
 699          * See comment in smb_com_transaction_secondary
 700          */
 701         if (xa->req_param_mb.chain_offset != psdisp) {
 702                 DTRACE_PROBE2(trans_param_disp,
 703                     smb_xa_t *, xa, uint16_t, psdisp);
 704                 xa->req_param_mb.chain_offset = psdisp;
 705         }
 706         if (xa->req_data_mb.chain_offset != dsdisp) {
 707                 DTRACE_PROBE2(trans_data_disp,
 708                     smb_xa_t *, xa, uint16_t, dsdisp);
 709                 xa->req_data_mb.chain_offset = dsdisp;
 710         }
 711 
 712         if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
 713                 mutex_exit(&xa->xa_mutex);
 714                 smb_xa_close(xa);
 715                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 716                 return (SDRC_ERROR);
 717         }
 718         if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
 719                 mutex_exit(&xa->xa_mutex);
 720                 smb_xa_close(xa);
 721                 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
 722                 return (SDRC_ERROR);
 723         }
 724         mutex_exit(&xa->xa_mutex);
 725 
 726         if (!smb_trans_ready(xa))
 727                 return (SDRC_NO_REPLY);
 728 
 729         if (!smb_xa_complete(xa))
 730                 return (SDRC_NO_REPLY);
 731 
 732         return (smb_nt_trans_dispatch(sr, xa));
 733 }
 734 
 735 static int
 736 smb_trans_ready(smb_xa_t *xa)
 737 {
 738         int rc;
 739 
 740         mutex_enter(&xa->xa_mutex);
 741         rc = xa->req_disp_data >= xa->smb_tdscnt &&
 742             xa->req_disp_param >= xa->smb_tpscnt;
 743         mutex_exit(&xa->xa_mutex);
 744 
 745         return (rc);
 746 }
 747 
 748 static void
 749 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text,
 750     char *oem_name, uint16_t type, char *comment)
 751 {
 752         (void) smb_mbc_encodef(output, "13c.wl", oem_name,
 753             type, MBC_LENGTH(text));
 754 
 755         (void) smb_mbc_encodef(text, "s", comment ? comment : "");
 756 }
 757 
 758 static void
 759 smb_encode_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text,
 760         smb_request_t *sr, char *oem_name, uint16_t type,
 761         char *comment, uint16_t access, char *path, char *password)
 762 {
 763         unsigned char pword[9];
 764 
 765         bzero(pword, sizeof (pword));
 766         (void) strncpy((char *)pword, password, sizeof (pword));
 767         smb_encode_SHARE_INFO_1(output, text, oem_name, type, comment);
 768         (void) smb_mbc_encodef(output, "wwwl9c.",
 769             access,
 770             sr->sr_cfg->skc_maxconnections,
 771             smb_server_get_session_count(sr->sr_server),
 772             MBC_LENGTH(text),
 773             pword);
 774         (void) smb_mbc_encodef(text, "s", path);
 775 }
 776 
 777 int
 778 smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
 779 {
 780         uint16_t pid_hi, pid_lo;
 781 
 782         /*
 783          * Number of data bytes that will
 784          * be sent in the current response
 785          */
 786         uint16_t data_scnt;
 787 
 788         /*
 789          * Total number of data bytes that
 790          * are sent till now. This is only
 791          * used for calculating current data
 792          * displacement
 793          */
 794         uint16_t tot_data_scnt;
 795 
 796         /*
 797          * Number of parameter bytes should
 798          * be sent for the current response.
 799          * It is 8 for the 1st response and
 800          * 0 for others
 801          */
 802         uint16_t param_scnt;
 803 
 804         /* number of setup and parameter bytes */
 805         uint16_t n_setup, n_param;
 806 
 807         /* data and parameter displacement */
 808         uint16_t data_disp, param_disp;
 809 
 810         /* parameter and data offset and pad */
 811         int param_off, param_pad, data_off, data_pad;
 812 
 813         /*
 814          * total bytes of parameters and data
 815          * in the packet, plus the pad bytes.
 816          */
 817         int tot_packet_bytes;
 818 
 819         boolean_t first_resp;
 820 
 821         char fmt[16];
 822         struct mbuf_chain reply;
 823 
 824         uint16_t level;
 825         uint16_t pkt_bufsize;
 826         smb_enumshare_info_t esi;
 827         char *sent_buf;
 828 
 829         ASSERT(sr->uid_user);
 830 
 831         if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level,
 832             &esi.es_bufsize) != 0)
 833                 return (SDRC_NOT_IMPLEMENTED);
 834 
 835         if (level != 1) {
 836                 /*
 837                  * Only level 1 is valid for NetShareEnum
 838                  * None of the error codes in the spec are meaningful
 839                  * here. This error code is returned by Windows.
 840                  */
 841                 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
 842                     ERROR_INVALID_LEVEL, 0, 0, 0);
 843                 return (SDRC_SUCCESS);
 844         }
 845 
 846         esi.es_buf = smb_srm_zalloc(sr, esi.es_bufsize);
 847         esi.es_posix_uid = crgetuid(sr->uid_user->u_cred);
 848         smb_kshare_enum(sr->sr_server, &esi);
 849 
 850         /* client buffer size is not big enough to hold any shares */
 851         if (esi.es_nsent == 0) {
 852                 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
 853                     ERROR_MORE_DATA, 0, esi.es_nsent, esi.es_ntotal);
 854                 return (SDRC_SUCCESS);
 855         }
 856 
 857         /*
 858          * Initialize the reply mbuf chain.  Note that we re-initialize
 859          * this on each pass through the loop below.
 860          */
 861         MBC_SETUP(&reply, smb_maxbufsize);
 862 
 863         /*
 864          * The rep_setup_mb is already initialized in smb_trans_dispatch().
 865          * Calling MBC_INIT() will initialized the structure and so the
 866          * pointer to the mbuf chains will be lost. Therefore, we need
 867          * to free the resources before calling MBC_INIT() again.
 868          */
 869         n_setup = 0;    /* Setup count for NetShareEnum SMB is 0 */
 870         MBC_FLUSH(&xa->rep_setup_mb);
 871 
 872         n_param = 8;
 873         pkt_bufsize = sr->session->smb_msg_size -
 874             (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param);
 875 
 876         tot_data_scnt = 0;
 877         sent_buf = esi.es_buf;
 878         first_resp = B_TRUE;
 879 
 880         while (tot_data_scnt < esi.es_datasize) {
 881                 data_scnt = esi.es_datasize - tot_data_scnt;
 882                 if (data_scnt > pkt_bufsize)
 883                         data_scnt = pkt_bufsize;
 884                 MBC_FLUSH(&xa->rep_data_mb);
 885 
 886                 (void) sprintf(fmt, "%dc", data_scnt);
 887                 (void) smb_mbc_encodef(&xa->rep_data_mb, fmt, sent_buf);
 888 
 889                 sent_buf += data_scnt;
 890                 tot_data_scnt += data_scnt;
 891 
 892                 /* Only the 1st response packet contains parameters */
 893                 param_scnt = (first_resp) ? n_param : 0;
 894                 param_pad = 1;                          /* always one */
 895                 param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN;
 896                 param_disp = (first_resp) ? 0 : n_param;
 897 
 898                 MBC_FLUSH(&xa->rep_param_mb);
 899 
 900                 if (first_resp) {
 901                         first_resp = B_FALSE;
 902                         (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
 903                             (esi.es_ntotal > esi.es_nsent)
 904                             ? ERROR_MORE_DATA : 0,
 905                             0, esi.es_nsent, esi.es_ntotal);
 906                 }
 907 
 908                 data_pad = (param_off + n_param) & 1;       /* Pad to short */
 909 
 910                 /* data off from hdr start */
 911                 data_off = param_off + param_scnt + data_pad;
 912                 data_disp = tot_data_scnt - data_scnt;
 913                 tot_packet_bytes = param_pad + param_scnt + data_pad +
 914                     data_scnt;
 915 
 916                 pid_hi = sr->smb_pid >> 16;
 917                 pid_lo = (uint16_t)sr->smb_pid;
 918 
 919                 MBC_FLUSH(&reply);
 920                 (void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT,
 921                     sr->first_smb_com,
 922                     sr->smb_rcls,
 923                     sr->smb_reh,
 924                     sr->smb_err,
 925                     sr->smb_flg | SMB_FLAGS_REPLY,
 926                     sr->smb_flg2,
 927                     pid_hi,
 928                     sr->smb_sig,
 929                     sr->smb_tid,
 930                     pid_lo,
 931                     sr->smb_uid,
 932                     sr->smb_mid);
 933 
 934                 (void) smb_mbc_encodef(&reply,
 935                     "bww2.wwwwwwb.Cw#.C#.C",
 936                     10 + n_setup,       /* wct */
 937                     n_param,            /* Total Parameter Bytes */
 938                     esi.es_datasize,    /* Total Data Bytes */
 939                     param_scnt,         /* Total Parameter Bytes this buffer */
 940                     param_off,          /* Param offset from header start */
 941                     param_disp,         /* Param displacement */
 942                     data_scnt,          /* Total Data Bytes this buffer */
 943                     data_off,           /* Data offset from header start */
 944                     data_disp,          /* Data displacement */
 945                     n_setup,            /* suwcnt */
 946                     &xa->rep_setup_mb,   /* setup[] */
 947                     tot_packet_bytes,   /* Total data bytes */
 948                     param_pad,
 949                     &xa->rep_param_mb,
 950                     data_pad,
 951                     &xa->rep_data_mb);
 952 
 953                 if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
 954                         smb_sign_reply(sr, &reply);
 955 
 956                 (void) smb_session_send(sr->session, 0, &reply);
 957 
 958         }
 959 
 960         m_freem(reply.chain);
 961 
 962         return (SDRC_NO_REPLY);
 963 }
 964 
 965 int
 966 smb_trans_net_share_getinfo(smb_request_t *sr, struct smb_xa *xa)
 967 {
 968         uint16_t                level, max_bytes, access;
 969         struct mbuf_chain       str_mb;
 970         char                    *share;
 971         char                    *password;
 972         smb_kshare_t            *si;
 973 
 974         if (smb_mbc_decodef(&xa->req_param_mb, "%sww", sr,
 975             &share, &level, &max_bytes) != 0)
 976                 return (SDRC_NOT_IMPLEMENTED);
 977 
 978         si = smb_kshare_lookup(sr->sr_server, share);
 979         if ((si == NULL) || (si->shr_oemname == NULL)) {
 980                 (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
 981                     NERR_NetNameNotFound, 0, 0);
 982                 if (si)
 983                         smb_kshare_release(sr->sr_server, si);
 984                 return (SDRC_SUCCESS);
 985         }
 986 
 987         access = SHARE_ACCESS_ALL;
 988         password = "";
 989 
 990         MBC_INIT(&str_mb, max_bytes);
 991 
 992         switch (level) {
 993         case 0 :
 994                 (void) smb_mbc_encodef(&xa->rep_data_mb, "13c",
 995                     si->shr_oemname);
 996                 break;
 997 
 998         case 1 :
 999                 smb_encode_SHARE_INFO_1(&xa->rep_data_mb, &str_mb,
1000                     si->shr_oemname, si->shr_type, si->shr_cmnt);
1001                 break;
1002 
1003         case 2 :
1004                 smb_encode_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr,
1005                     si->shr_oemname, si->shr_type, si->shr_cmnt, access,
1006                     si->shr_path, password);
1007                 break;
1008 
1009         default:
1010                 smb_kshare_release(sr->sr_server, si);
1011                 (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1012                     ERROR_INVALID_LEVEL, 0, 0);
1013                 m_freem(str_mb.chain);
1014                 return (SDRC_NOT_IMPLEMENTED);
1015         }
1016 
1017         smb_kshare_release(sr->sr_server, si);
1018         (void) smb_mbc_encodef(&xa->rep_param_mb, "www", NERR_Success,
1019             -MBC_LENGTH(&xa->rep_data_mb),
1020             MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
1021         (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1022         m_freem(str_mb.chain);
1023         return (SDRC_SUCCESS);
1024 }
1025 
1026 int
1027 smb_trans_net_workstation_getinfo(struct smb_request *sr, struct smb_xa *xa)
1028 {
1029         uint16_t                level, max_bytes;
1030         struct mbuf_chain       str_mb;
1031         char *domain;
1032         char *hostname;
1033 
1034         if ((smb_mbc_decodef(&xa->req_param_mb, "ww",
1035             &level, &max_bytes) != 0) ||
1036             (level != 10)) {
1037                 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
1038                     NERR_BadTransactConfig, 0, 0, 0);
1039                 return (SDRC_SUCCESS);
1040         }
1041 
1042         domain = sr->sr_cfg->skc_nbdomain;
1043         hostname = sr->sr_cfg->skc_hostname;
1044 
1045         MBC_INIT(&str_mb, max_bytes);
1046 
1047         (void) smb_mbc_encodef(&str_mb, "."); /* Prevent NULL pointers */
1048 
1049         (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1050         (void) smb_mbc_encodef(&str_mb, "s", hostname);
1051         (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1052         (void) smb_mbc_encodef(&str_mb, "s", "nobody");
1053         (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1054         (void) smb_mbc_encodef(&str_mb, "s", domain);
1055         (void) smb_mbc_encodef(&xa->rep_data_mb, "bbl",
1056             (uint8_t)sr->sr_cfg->skc_version.sv_major,
1057             (uint8_t)sr->sr_cfg->skc_version.sv_minor,
1058             MBC_LENGTH(&str_mb));
1059         (void) smb_mbc_encodef(&str_mb, "s", domain);
1060         (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1061         (void) smb_mbc_encodef(&str_mb, "s", domain);
1062 
1063         (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 0,
1064             -MBC_LENGTH(&xa->rep_data_mb),
1065             MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
1066         (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1067         m_freem(str_mb.chain);
1068         return (SDRC_SUCCESS);
1069 }
1070 
1071 int
1072 smb_trans_net_user_getinfo(struct smb_request *sr, struct smb_xa *xa)
1073 {
1074         uint16_t                level, max_bytes;
1075         unsigned char           *user;
1076         int rc;
1077 
1078         rc = smb_mbc_decodef(&xa->req_param_mb, "%sww", sr,
1079             &user,
1080             &level,
1081             &max_bytes);
1082 
1083         if (rc != 0)
1084                 return (SDRC_NOT_IMPLEMENTED);
1085 
1086         (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1087             NERR_UserNotFound, 0, 0);
1088         return (SDRC_SUCCESS);
1089 }
1090 
1091 smb_sdrc_t
1092 smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa)
1093 {
1094         uint16_t                level, buf_size;
1095         uint16_t                avail_data, max_data;
1096         char                    server_name[16];
1097         struct mbuf_chain       str_mb;
1098 
1099         if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, &buf_size) != 0)
1100                 return (SDRC_ERROR);
1101 
1102         max_data = MBC_MAXBYTES(&xa->rep_data_mb);
1103 
1104         MBC_INIT(&str_mb, buf_size);
1105 
1106         bzero(server_name, sizeof (server_name));
1107         (void) strncpy(server_name, sr->sr_cfg->skc_hostname,
1108             sizeof (server_name));
1109 
1110         /* valid levels are 0 and 1 */
1111         switch (level) {
1112         case 0:
1113                 (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", server_name);
1114                 break;
1115 
1116         case 1:
1117                 (void) smb_mbc_encodef(&str_mb, "s",
1118                     sr->sr_cfg->skc_system_comment);
1119                 (void) smb_mbc_encodef(&xa->rep_data_mb, "16cbbll", server_name,
1120                     (uint8_t)sr->sr_cfg->skc_version.sv_major,
1121                     (uint8_t)sr->sr_cfg->skc_version.sv_minor,
1122                     MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb));
1123                 break;
1124 
1125         default:
1126                 (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1127                     ERROR_INVALID_LEVEL, 0, 0);
1128                 m_freem(str_mb.chain);
1129                 return (SDRC_SUCCESS);
1130         }
1131 
1132         avail_data = MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb);
1133         (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1134             NERR_Success, max_data - avail_data, avail_data);
1135         (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1136         m_freem(str_mb.chain);
1137         return (SDRC_SUCCESS);
1138 }
1139 
1140 /*
1141  * 6.4 The NetServerEnum2 RAP Service
1142  *
1143  * The NetServerEnum2 RAP service lists all computers of the specified type
1144  * or types that are visible in the specified domains. It may also
1145  * enumerate domains.
1146  *
1147  * The following definition uses the notation and terminology defined in
1148  * the CIFS Remote Administration Protocol specification, which is required
1149  * in order to make it well-defined. The definition is:
1150  *
1151  *     uint16_t NetServerEnum2 (
1152  *         uint16_t  sLevel,
1153  *         RCVBUF          pbBuffer,
1154  *         RCVBUFLEN       cbBuffer,
1155  *         ENTCOUNT        pcEntriesRead,
1156  *         uint16_t  *pcTotalAvail,
1157  *         uint32_t   fServerType,
1158  *         char            *pszDomain,
1159  *     );
1160  *
1161  * where:
1162  *
1163  *    sLevel specifies the level of detail (0 or 1) requested.
1164  *
1165  *    pbBuffer points to the buffer to receive the returned data. If the
1166  *    function is successful, the buffer contains a sequence of
1167  *    server_info_x structures, where x is 0 or 1, depending on the
1168  *    level of detail requested.
1169  *
1170  *    cbBuffer specifies the size, in bytes, of the buffer pointed to by
1171  *    the pbBuffer parameter.
1172  *
1173  *    pcEntriesRead points to a 16 bit variable that receives a count of
1174  *    the number of servers enumerated in the buffer. This count is
1175  *    valid only if NetServerEnum2 returns the NERR_Success or
1176  *    ERROR_MORE_DATA values.
1177  *
1178  *    pcTotal Avail points to a 16 bit variable that receives a count of
1179  *    the total number of available entries. This count is valid only if
1180  *    NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values.
1181  *
1182  *     fServerType specifies the type or types of computers to enumerate.
1183  *     Computers that match at least one of the specified types are
1184  *     returned in the buffer. Possible values are defined in the request
1185  *     parameters section.
1186  *
1187  *    pszDomain points to a null-terminated string that contains the
1188  *    name of the workgroup in which to enumerate computers of the
1189  *    specified type or types. If the pszDomain parameter is a null
1190  *    string or a null pointer, servers are enumerated for the current
1191  *    domain of the computer.
1192  *
1193  * 6.4.1 Transaction Request Parameters section
1194  *
1195  * The Transaction request parameters section in this instance contains:
1196  * . The 16 bit function number for NetServerEnum2 which is 104.
1197  * . The parameter descriptor string which is "WrLehDz".
1198  * . The data descriptor string for the (returned) data which is "B16" for
1199  *   level detail 0 or "B16BBDz" for level detail 1.
1200  * . The actual parameters as described by the parameter descriptor
1201  *   string.
1202  *
1203  * The parameters are:
1204  * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in
1205  *   the parameter descriptor string. This represents the level of detail
1206  *   the server is expected to return
1207  * . A 16 bit integer that contains the size of the receive buffer.
1208  * . A 32 bit integer that represents the type of servers the function
1209  *   should enumerate. The possible values may be any of the following or
1210  *   a combination of the following:
1211  *
1212  * SV_TYPE_WORKSTATION        0x00000001 All workstations
1213  * SV_TYPE_SERVER             0x00000002 All servers
1214  * SV_TYPE_SQLSERVER          0x00000004 Any server running with SQL
1215  *                                       server
1216  * SV_TYPE_DOMAIN_CTRL        0x00000008 Primary domain controller
1217  * SV_TYPE_DOMAIN_BAKCTRL     0x00000010 Backup domain controller
1218  * SV_TYPE_TIME_SOURCE        0x00000020 Server running the timesource
1219  *                                       service
1220  * SV_TYPE_AFP                0x00000040 Apple File Protocol servers
1221  * SV_TYPE_NOVELL             0x00000080 Novell servers
1222  * SV_TYPE_DOMAIN_MEMBER      0x00000100 Domain Member
1223  * SV_TYPE_PRINTQ_SERVER      0x00000200 Server sharing print queue
1224  * SV_TYPE_DIALIN_SERVER      0x00000400 Server running dialin service.
1225  * SV_TYPE_XENIX_SERVER       0x00000800 Xenix server
1226  * SV_TYPE_NT                 0x00001000 NT server
1227  * SV_TYPE_WFW                0x00002000 Server running Windows for
1228  *                                       Workgroups
1229  * SV_TYPE_SERVER_NT          0x00008000 Windows NT non DC server
1230  * SV_TYPE_POTENTIAL_BROWSER  0x00010000 Server that can run the browser
1231  *                                       service
1232  * SV_TYPE_BACKUP_BROWSER     0x00020000 Backup browser server
1233  * SV_TYPE_MASTER_BROWSER     0x00040000 Master browser server
1234  * SV_TYPE_DOMAIN_MASTER      0x00080000 Domain Master Browser server
1235  * SV_TYPE_LOCAL_LIST_ONLY    0x40000000 Enumerate only entries marked
1236  *                                       "local"
1237  * SV_TYPE_DOMAIN_ENUM        0x80000000 Enumerate Domains. The pszDomain
1238  *                                       parameter must be NULL.
1239  *
1240  * . A null terminated ASCII string representing the pszDomain parameter
1241  *   described above
1242  *
1243  * 6.4.2 Transaction Request Data section
1244  *
1245  * There is no data or auxiliary data to send as part of the request.
1246  *
1247  * 6.4.3 Transaction Response Parameters section
1248  *
1249  * The transaction response parameters section consists of:
1250  * . A 16 bit word indicating the return status. The possible values are:
1251  *
1252  * Code                   Value  Description
1253  * NERR_Success           0      No errors encountered
1254  * ERROR_MORE_DATA        234    Additional data is available
1255  * NERR_ServerNotStarted  2114   The RAP service on the remote computer
1256  *                               is not running
1257  * NERR_BadTransactConfig 2141   The server is not configured for
1258  *                               transactions, IPC$ is not shared
1259  *
1260  * . A 16 bit "converter" word.
1261  * . A 16 bit number representing the number of entries returned.
1262  * . A 16 bit number representing the total number of available entries.
1263  *   If the supplied buffer is large enough, this will equal the number of
1264  *   entries returned.
1265  *
1266  * 6.4.4 Transaction Response Data section
1267  *
1268  * The return data section consists of a number of SERVER_INFO_1 structures.
1269  * The number of such structures present is determined by the third entry
1270  * (described above) in the return parameters section.
1271  *
1272  * At level detail 0, the Transaction response data section contains a
1273  * number of SERVER_INFO_0 data structure. The number of such structures is
1274  * equal to the 16 bit number returned by the server in the third parameter
1275  * in the Transaction response parameter section. The SERVER_INFO_0 data
1276  * structure is defined as:
1277  *
1278  *     struct SERVER_INFO_0 {
1279  *         char        sv0_name[16];
1280  *     };
1281  *
1282  *  where:
1283  *
1284  *    sv0_name is a null-terminated string that specifies the name of a
1285  *    computer or domain .
1286  *
1287  * At level detail 1, the Transaction response data section contains a
1288  * number of SERVER_INFO_1 data structure. The number of such structures is
1289  * equal to the 16 bit number returned by the server in the third parameter
1290  * in the Transaction response parameter section. The SERVER_INFO_1 data
1291  * structure is defined as:
1292  *
1293  *     struct SERVER_INFO_1 {
1294  *         char            sv1_name[16];
1295  *         char            sv1_version_major;
1296  *         char            sv1_version_minor;
1297  *         uint32_t   sv1_type;
1298  *         char        *sv1_comment_or_master_browser;
1299  *     };
1300  *
1301  *    sv1_name contains a null-terminated string that specifies the name
1302  *    of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in
1303  *    sv1_type.
1304  *
1305  *    sv1_version_major whatever was specified in the HostAnnouncement
1306  *    or DomainAnnouncement frame with which the entry was registered.
1307  *
1308  *    sv1_version_minor whatever was specified in the HostAnnouncement
1309  *    or DomainAnnouncement frame with which the entry was registered.
1310  *
1311  *    sv1_type specifies the type of software the computer is running.
1312  *    The member can be one or a combination of the values defined above
1313  *    in the Transaction request parameters section for fServerType.
1314  *
1315  *
1316  *    sv1_comment_or_master_browser points to a null-terminated string. If
1317  *    the sv1_type indicates that the entry is for a domain, this
1318  *    specifies the name of server running the domain master browser;
1319  *    otherwise, it specifies a comment describing the server. The comment
1320  *    can be a null string or the pointer may be a null pointer.
1321  *
1322  *    In case there are multiple SERVER_INFO_1 data structures to
1323  *    return, the server may put all these fixed length structures in
1324  *    the return buffer, leave some space and then put all the variable
1325  *    length data (the actual value of the sv1_comment strings) at the
1326  *    end of the buffer.
1327  *
1328  * There is no auxiliary data to receive.
1329  */
1330 
1331 int
1332 smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa)
1333 {
1334         uint16_t opcode, level, max_bytes;
1335         uint32_t server_type;
1336         unsigned char *domain;
1337         struct mbuf_chain str_mb;
1338         char *hostname, *s;
1339         smb_kmod_cfg_t *si;
1340 
1341         if (smb_mbc_decodef(&xa->req_param_mb,
1342             "%wsswwls", sr, &opcode, &s, &s,
1343             &level, &max_bytes, &server_type, &domain) != 0)
1344                 return (SDRC_NOT_IMPLEMENTED);
1345 
1346         si = sr->sr_cfg;
1347 
1348         if (smb_strcasecmp(si->skc_nbdomain, (char *)domain, 0) != 0) {
1349                 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1350                 return (SDRC_SUCCESS);
1351         }
1352 
1353         if ((server_type & MY_SERVER_TYPE) == 0) {
1354                 (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1355                 return (SDRC_SUCCESS);
1356         }
1357 
1358         MBC_INIT(&str_mb, max_bytes);
1359 
1360         hostname = si->skc_hostname;
1361 
1362         (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", hostname);
1363         if (level == 1) {
1364                 (void) smb_mbc_encodef(&xa->rep_data_mb, "bbll",
1365                     (uint8_t)sr->sr_cfg->skc_version.sv_major,
1366                     (uint8_t)sr->sr_cfg->skc_version.sv_minor,
1367                     MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
1368                 (void) smb_mbc_encodef(&str_mb, "s", si->skc_system_comment);
1369         }
1370 
1371         (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0,
1372             -MBC_LENGTH(&xa->rep_data_mb), 1, 1);
1373         (void) smb_mbc_encodef(&xa->rep_data_mb, "m", str_mb.chain);
1374         return (SDRC_SUCCESS);
1375 }
1376 
1377 static boolean_t
1378 is_supported_mailslot(const char *mailslot)
1379 {
1380         static char *mailslots[] = {
1381                 PIPE_LANMAN,
1382                 MAILSLOT_LANMAN,
1383                 MAILSLOT_BROWSE,
1384                 MAILSLOT_MSBROWSE
1385         };
1386 
1387         int i;
1388 
1389         for (i = 0; i < sizeof (mailslots)/sizeof (mailslots[0]); ++i)
1390                 if (smb_strcasecmp(mailslot, mailslots[i], 0) == 0)
1391                         return (B_TRUE);
1392 
1393         return (B_FALSE);
1394 }
1395 
1396 /*
1397  * smb_trans_nmpipe
1398  *
1399  * This is used for RPC bind and request transactions.
1400  *
1401  * If the data available from the pipe is larger than the maximum
1402  * data size requested by the client, return as much as requested.
1403  * The residual data remains in the pipe until the client comes back
1404  * with a read request or closes the pipe.
1405  *
1406  * When we read less than what's available, we MUST return the
1407  * status NT_STATUS_BUFFER_OVERFLOW (or ERRDOS/ERROR_MORE_DATA)
1408  */
1409 static smb_sdrc_t
1410 smb_trans_nmpipe(smb_request_t *sr, smb_xa_t *xa)
1411 {
1412         smb_fsctl_t fsctl;
1413         uint32_t status;
1414 
1415         smbsr_lookup_file(sr);
1416         if (sr->fid_ofile == NULL) {
1417                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
1418                     ERRDOS, ERRbadfid);
1419                 return (SDRC_ERROR);
1420         }
1421 
1422         /*
1423          * A little confusing perhaps, but the fsctl "input" is what we
1424          * write to the pipe (from the transaction "send" data), and the
1425          * fsctl "output" is what we read from the pipe (and becomes the
1426          * transaction receive data).
1427          */
1428         fsctl.CtlCode = FSCTL_PIPE_TRANSCEIVE;
1429         fsctl.InputCount = xa->smb_tdscnt; /* write count */
1430         fsctl.OutputCount = 0; /* minimum to read from the pipe */
1431         fsctl.MaxOutputResp = xa->smb_mdrcnt;        /* max to read */
1432         fsctl.in_mbc = &xa->req_data_mb; /* write from here */
1433         fsctl.out_mbc = &xa->rep_data_mb; /* read into here */
1434 
1435         status = smb_opipe_fsctl(sr, &fsctl);
1436         if (status) {
1437                 smbsr_status(sr, status, 0, 0);
1438                 if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR)
1439                         return (SDRC_ERROR);
1440                 /* Warnings like NT_STATUS_BUFFER_OVERFLOW are OK */
1441         }
1442 
1443         return (SDRC_SUCCESS);
1444 }
1445 
1446 static smb_sdrc_t
1447 smb_trans_dispatch(smb_request_t *sr, smb_xa_t *xa)
1448 {
1449         int             rc, pos;
1450         int             total_bytes, n_setup, n_param, n_data;
1451         int             param_off, param_pad, data_off, data_pad;
1452         uint16_t        opcode;
1453         uint16_t        devstate;
1454         char            *req_fmt;
1455         char            *rep_fmt;
1456 
1457         if (xa->smb_suwcnt > 0) {
1458                 rc = smb_mbc_decodef(&xa->req_setup_mb, "ww", &opcode,
1459                     &sr->smb_fid);
1460                 if (rc != 0)
1461                         goto trans_err_not_supported;
1462                 switch (opcode) {
1463                 case TRANS_SET_NMPIPE_STATE:
1464                         if ((rc = smb_mbc_decodef(&xa->req_param_mb, "w",
1465                             &devstate)) != 0)
1466                                 goto trans_err_not_supported;
1467 
1468                         rc = SDRC_SUCCESS;
1469                         break;
1470 
1471                 case TRANS_TRANSACT_NMPIPE:
1472                         rc = smb_trans_nmpipe(sr, xa);
1473                         break;
1474 
1475                 case TRANS_WAIT_NMPIPE:
1476                         delay(SEC_TO_TICK(1));
1477                         rc = SDRC_SUCCESS;
1478                         break;
1479 
1480                 default:
1481                         goto trans_err_not_supported;
1482                 }
1483         } else {
1484                 if (!is_supported_mailslot(xa->xa_pipe_name))
1485                         goto trans_err_not_supported;
1486 
1487                 if ((rc = smb_mbc_decodef(&xa->req_param_mb, "%wss", sr,
1488                     &opcode, &req_fmt, &rep_fmt)) != 0)
1489                         goto trans_err_not_supported;
1490 
1491                 switch (opcode) {
1492                 case API_WshareEnum:
1493                         rc = smb_trans_net_share_enum(sr, xa);
1494                         break;
1495 
1496                 case API_WshareGetInfo:
1497                         rc = smb_trans_net_share_getinfo(sr, xa);
1498                         break;
1499 
1500                 case API_WserverGetInfo:
1501                         rc = smb_trans_net_server_getinfo(sr, xa);
1502                         break;
1503 
1504                 case API_WUserGetInfo:
1505                         rc = smb_trans_net_user_getinfo(sr, xa);
1506                         break;
1507 
1508                 case API_WWkstaGetInfo:
1509                         rc = smb_trans_net_workstation_getinfo(sr, xa);
1510                         break;
1511 
1512                 case API_NetServerEnum2:
1513                         rc = smb_trans_net_server_enum2(sr, xa);
1514                         break;
1515 
1516                 default:
1517                         goto trans_err_not_supported;
1518                 }
1519         }
1520 
1521         switch (rc) {
1522         case SDRC_SUCCESS:
1523                 break;
1524 
1525         case SDRC_DROP_VC:
1526         case SDRC_NO_REPLY:
1527         case SDRC_ERROR:
1528                 return (rc);
1529 
1530         case SDRC_NOT_IMPLEMENTED:
1531                 goto trans_err_not_supported;
1532 
1533         default:
1534                 break;
1535         }
1536 
1537         n_setup = MBC_LENGTH(&xa->rep_setup_mb);
1538         n_param = MBC_LENGTH(&xa->rep_param_mb);
1539         n_data  = MBC_LENGTH(&xa->rep_data_mb);
1540 
1541         if (xa->smb_msrcnt < n_setup ||
1542             xa->smb_mprcnt < n_param ||
1543             xa->smb_mdrcnt < n_data) {
1544                 goto trans_err_too_small;
1545         }
1546 
1547         /* neato, blast it over there */
1548 
1549         n_setup = (n_setup + 1) / 2;            /* Convert to setup words */
1550         param_pad = 1;                          /* always one */
1551         param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
1552         data_pad = (param_off + n_param) & 1;       /* Pad to short */
1553         /* Param off from hdr start */
1554         data_off = param_off + n_param + data_pad;
1555         total_bytes = param_pad + n_param + data_pad + n_data;
1556 
1557         rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
1558             "bww2.wwwwwwb.Cw#.C#.C",
1559             10 + n_setup,               /* wct */
1560             n_param,                    /* Total Parameter Bytes */
1561             n_data,                     /* Total Data Bytes */
1562             n_param,                    /* Total Parameter Bytes this buffer */
1563             param_off,                  /* Param offset from header start */
1564             0,                          /* Param displacement */
1565             n_data,                     /* Total Data Bytes this buffer */
1566             data_off,                   /* Data offset from header start */
1567             0,                          /* Data displacement */
1568             n_setup,                    /* suwcnt */
1569             &xa->rep_setup_mb, /* setup[] */
1570             total_bytes,                /* Total data bytes */
1571             param_pad,
1572             &xa->rep_param_mb,
1573             data_pad,
1574             &xa->rep_data_mb);
1575         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1576 
1577 trans_err_too_small:
1578         rc = NERR_BufTooSmall;
1579         goto trans_err;
1580 
1581 trans_err_not_supported:
1582         rc = ERROR_NOT_SUPPORTED;
1583         goto trans_err;
1584 
1585 trans_err:
1586         pos = MBC_LENGTH(&sr->reply) + 23;
1587         rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www",
1588             10,         /* wct */
1589             4, 0,       /* tpscnt tdscnt */
1590             4, pos, 0,  /* pscnt psoff psdisp */
1591             0, 0, 0,    /* dscnt dsoff dsdisp */
1592             0,          /* suwcnt */
1593             4,          /* bcc */
1594             rc,
1595             0);         /* converter word? */
1596         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1597 }
1598 
1599 static smb_sdrc_t
1600 smb_trans2_dispatch(smb_request_t *sr, smb_xa_t *xa)
1601 {
1602         int             rc, pos;
1603         int             total_bytes, n_setup, n_param, n_data;
1604         int             param_off, param_pad, data_off;
1605         uint16_t        data_pad;
1606         uint16_t        opcode;
1607         uint16_t  nt_unknown_secret = 0x0100;
1608         char *fmt;
1609 
1610         n_data = xa->smb_mdrcnt;
1611 
1612         if (smb_mbc_decodef(&xa->req_setup_mb, "w", &opcode) != 0)
1613                 goto trans_err_not_supported;
1614 
1615         /*
1616          * Save this for /proc to read later.
1617          */
1618         xa->smb_func = opcode;
1619 
1620         /* for now, only respond to the */
1621         switch (opcode) {
1622         case TRANS2_OPEN2:
1623                 rc = smb_com_trans2_open2(sr, xa);
1624                 break;
1625 
1626         case TRANS2_CREATE_DIRECTORY:
1627                 rc = smb_com_trans2_create_directory(sr, xa);
1628                 break;
1629 
1630         case TRANS2_FIND_FIRST2:
1631                 /*
1632                  * Should have enough room to send the response
1633                  * data back to client.
1634                  */
1635                 if (n_data == 0) {
1636                         smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1637                             ERRDOS, ERROR_BAD_LENGTH);
1638                         return (SDRC_ERROR);
1639                 }
1640                 rc = smb_com_trans2_find_first2(sr, xa);
1641                 break;
1642 
1643         case TRANS2_FIND_NEXT2:
1644                 /*
1645                  * Should have enough room to send the response
1646                  * data back to client.
1647                  */
1648                 if (n_data == 0) {
1649                         smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1650                             ERRDOS, ERROR_BAD_LENGTH);
1651                         return (SDRC_ERROR);
1652                 }
1653                 rc = smb_com_trans2_find_next2(sr, xa);
1654                 break;
1655 
1656         case TRANS2_QUERY_FS_INFORMATION:
1657                 /*
1658                  * Should have enough room to send the response
1659                  * data back to client.
1660                  */
1661                 if (n_data == 0) {
1662                         smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1663                             ERRDOS, ERROR_BAD_LENGTH);
1664                         return (SDRC_ERROR);
1665                 }
1666                 rc = smb_com_trans2_query_fs_information(sr, xa);
1667                 break;
1668 
1669         case TRANS2_SET_FS_INFORMATION:
1670                 rc = smb_com_trans2_set_fs_information(sr, xa);
1671                 break;
1672 
1673         case TRANS2_QUERY_PATH_INFORMATION:
1674                 /*
1675                  * Should have enough room to send the response
1676                  * data back to client.
1677                  */
1678                 if (n_data == 0) {
1679                         smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1680                             ERRDOS, ERROR_BAD_LENGTH);
1681                         return (SDRC_ERROR);
1682                 }
1683                 rc = smb_com_trans2_query_path_information(sr, xa);
1684                 break;
1685 
1686         case TRANS2_QUERY_FILE_INFORMATION:
1687                 /*
1688                  * Should have enough room to send the response
1689                  * data back to client.
1690                  */
1691                 if (n_data == 0) {
1692                         smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1693                             ERRDOS, ERROR_BAD_LENGTH);
1694                         return (SDRC_ERROR);
1695                 }
1696                 rc = smb_com_trans2_query_file_information(sr, xa);
1697                 break;
1698 
1699         case TRANS2_SET_PATH_INFORMATION:
1700                 rc = smb_com_trans2_set_path_information(sr, xa);
1701                 break;
1702 
1703         case TRANS2_SET_FILE_INFORMATION:
1704                 rc = smb_com_trans2_set_file_information(sr, xa);
1705                 break;
1706 
1707         case TRANS2_GET_DFS_REFERRAL:
1708                 rc = smb_com_trans2_get_dfs_referral(sr, xa);
1709                 break;
1710 
1711         default:
1712                 (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
1713                 goto trans_err_not_supported;
1714         }
1715 
1716         switch (rc) {
1717         case SDRC_SUCCESS:
1718                 break;
1719 
1720         case SDRC_DROP_VC:
1721         case SDRC_NO_REPLY:
1722         case SDRC_ERROR:
1723                 return (rc);
1724 
1725         case SDRC_NOT_IMPLEMENTED:
1726                 goto trans_err_not_supported;
1727 
1728         default:
1729                 break;
1730         }
1731 
1732         n_setup = MBC_LENGTH(&xa->rep_setup_mb);
1733         n_param = MBC_LENGTH(&xa->rep_param_mb);
1734         n_data  = MBC_LENGTH(&xa->rep_data_mb);
1735 
1736         if (xa->smb_msrcnt < n_setup ||
1737             xa->smb_mprcnt < n_param ||
1738             xa->smb_mdrcnt < n_data) {
1739                 goto trans_err_too_small;
1740         }
1741 
1742         /* neato, blast it over there */
1743 
1744         n_setup = (n_setup + 1) / 2;            /* Conver to setup words */
1745         param_pad = 1;                          /* must be one */
1746         param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
1747 
1748         /*
1749          * Including the nt_unknown_secret value persuades netmon to
1750          * display the correct data format for QueryPathInfo and
1751          * QueryFileInfo.
1752          */
1753         if (opcode == TRANS2_QUERY_FILE_INFORMATION ||
1754             opcode == TRANS2_QUERY_PATH_INFORMATION) {
1755                 data_pad = sizeof (uint16_t);
1756                 data_off = param_off + n_param + data_pad;
1757                 fmt = "bww2.wwwwwwb.Cw#.CwC";
1758                 nt_unknown_secret = 0x0100;
1759         }
1760         else
1761         {
1762                 data_pad = (param_off + n_param) & 1; /* Pad to short */
1763                 /* Param off from hdr start */
1764                 data_off = param_off + n_param + data_pad;
1765                 fmt = "bww2.wwwwwwb.Cw#.C#.C";
1766                 nt_unknown_secret = data_pad;
1767         }
1768 
1769         total_bytes = param_pad + n_param + data_pad + n_data;
1770 
1771         rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
1772             fmt,
1773             10 + n_setup,               /* wct */
1774             n_param,                    /* Total Parameter Bytes */
1775             n_data /* + data_pad */,    /* Total Data Bytes */
1776             n_param,                    /* Total Parameter Bytes this buffer */
1777             param_off,                  /* Param offset from header start */
1778             0,                          /* Param displacement */
1779             n_data /* + data_pad */,    /* Total Data Bytes this buffer */
1780             data_off,                   /* Data offset from header start */
1781             0,                          /* Data displacement */
1782             n_setup,                    /* suwcnt */
1783             &xa->rep_setup_mb,           /* setup[] */
1784             total_bytes,                /* Total data bytes */
1785             param_pad,
1786             &xa->rep_param_mb,
1787             nt_unknown_secret,
1788             &xa->rep_data_mb);
1789         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1790 
1791 trans_err_too_small:
1792         rc = NERR_BufTooSmall;
1793         goto trans_err;
1794 
1795 trans_err_not_supported:
1796         rc = ERROR_NOT_SUPPORTED;
1797         goto trans_err;
1798 
1799 trans_err:
1800         pos = MBC_LENGTH(&sr->reply) + 23;
1801         rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www",
1802             10,         /* wct */
1803             4, 0,       /* tpscnt tdscnt */
1804             4, pos, 0,  /* pscnt psoff psdisp */
1805             0, 0, 0,    /* dscnt dsoff dsdisp */
1806             0,          /* suwcnt */
1807             4,          /* bcc */
1808             rc,
1809             0);         /* converter word? */
1810         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1811 }
1812 
1813 static uint32_t smb_xa_max_setup_count = 200;
1814 static uint32_t smb_xa_max_param_count = 32 * 1024;
1815 static uint32_t smb_xa_max_data_count  = 64 * 1024;
1816 
1817 smb_xa_t *
1818 smb_xa_create(
1819     smb_session_t       *session,
1820     smb_request_t       *sr,
1821     uint32_t            total_parameter_count,
1822     uint32_t            total_data_count,
1823     uint32_t            max_parameter_count,
1824     uint32_t            max_data_count,
1825     uint32_t            max_setup_count,
1826     uint32_t            setup_word_count)
1827 {
1828         smb_xa_t        *xa, *nxa;
1829         smb_llist_t     *xlist;
1830 
1831         /*
1832          * Sanity check what the client says it will send.
1833          * Caller handles NULL return as ERRnoroom.
1834          */
1835         if (setup_word_count > smb_xa_max_setup_count)
1836                 return (NULL);
1837         if (total_parameter_count > smb_xa_max_param_count)
1838                 return (NULL);
1839         if (total_data_count > smb_xa_max_data_count)
1840                 return (NULL);
1841 
1842         /*
1843          * Limit what the client asks us to allocate for
1844          * returned setup, params, data.
1845          */
1846         if (max_setup_count > smb_xa_max_setup_count)
1847                 max_setup_count = smb_xa_max_setup_count;
1848         if (max_parameter_count > smb_xa_max_param_count)
1849                 max_parameter_count = smb_xa_max_param_count;
1850         if (max_data_count > smb_xa_max_data_count)
1851                 max_data_count = smb_xa_max_data_count;
1852 
1853         xa = kmem_zalloc(sizeof (smb_xa_t), KM_SLEEP);
1854         xa->xa_refcnt = 1;
1855         xa->smb_com = sr->smb_com;
1856         xa->smb_flg = sr->smb_flg;
1857         xa->smb_flg2 = sr->smb_flg2;
1858         xa->smb_tid = sr->smb_tid;
1859         xa->smb_pid = sr->smb_pid;
1860         xa->smb_uid = sr->smb_uid;
1861         xa->xa_smb_mid = sr->smb_mid;
1862         xa->xa_smb_fid = 0xFFFF;
1863         xa->reply_seqnum = sr->reply_seqnum;
1864         xa->smb_tpscnt = total_parameter_count;
1865         xa->smb_tdscnt = total_data_count;
1866         xa->smb_mprcnt = max_parameter_count;
1867         xa->smb_mdrcnt = max_data_count;
1868         xa->smb_msrcnt = max_setup_count;
1869         xa->smb_suwcnt = setup_word_count;
1870         xa->xa_session = session;
1871         xa->xa_magic = SMB_XA_MAGIC;
1872 
1873         /* request parts */
1874         xa->req_setup_mb.max_bytes = setup_word_count * 2;
1875         xa->req_param_mb.max_bytes = total_parameter_count;
1876         xa->req_data_mb.max_bytes  = total_data_count;
1877 
1878         /* reply parts */
1879         xa->rep_setup_mb.max_bytes = max_setup_count * 2;
1880         xa->rep_param_mb.max_bytes = max_parameter_count;
1881         xa->rep_data_mb.max_bytes =  max_data_count;
1882 
1883         /*
1884          * The new xa structure is checked against the current list to see
1885          * if it exists already.
1886          */
1887         xlist = &session->s_xa_list;
1888         smb_llist_enter(xlist, RW_WRITER);
1889         nxa = smb_llist_head(xlist);
1890         while (nxa) {
1891                 ASSERT(nxa->xa_magic == SMB_XA_MAGIC);
1892                 if (nxa->xa_smb_mid == xa->xa_smb_mid &&
1893                     nxa->smb_pid == xa->smb_pid &&
1894                     !SMB_XA_CLOSED(nxa) &&
1895                     !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
1896                         smb_llist_exit(xlist);
1897                         kmem_free(xa, sizeof (smb_xa_t));
1898                         return (NULL);
1899                 }
1900                 nxa = smb_llist_next(xlist, nxa);
1901         }
1902         smb_llist_insert_tail(xlist, xa);
1903         smb_llist_exit(xlist);
1904         return (xa);
1905 }
1906 
1907 void
1908 smb_xa_delete(smb_xa_t *xa)
1909 {
1910         ASSERT(xa->xa_refcnt == 0);
1911         ASSERT(SMB_XA_CLOSED(xa));
1912 
1913         if (xa->xa_pipe_name)
1914                 smb_mem_free(xa->xa_pipe_name);
1915 
1916         /* request parts */
1917         if (xa->req_setup_mb.chain != NULL)
1918                 m_freem(xa->req_setup_mb.chain);
1919         if (xa->req_param_mb.chain != NULL)
1920                 m_freem(xa->req_param_mb.chain);
1921         if (xa->req_data_mb.chain != NULL)
1922                 m_freem(xa->req_data_mb.chain);
1923 
1924         /* reply parts */
1925         if (xa->rep_setup_mb.chain != NULL)
1926                 m_freem(xa->rep_setup_mb.chain);
1927         if (xa->rep_param_mb.chain != NULL)
1928                 m_freem(xa->rep_param_mb.chain);
1929         if (xa->rep_data_mb.chain != NULL)
1930                 m_freem(xa->rep_data_mb.chain);
1931 
1932         xa->xa_magic = (uint32_t)~SMB_XA_MAGIC;
1933         kmem_free(xa, sizeof (smb_xa_t));
1934 }
1935 
1936 smb_xa_t *
1937 smb_xa_hold(smb_xa_t *xa)
1938 {
1939         mutex_enter(&xa->xa_mutex);
1940         xa->xa_refcnt++;
1941         ASSERT(xa->xa_refcnt);
1942         mutex_exit(&xa->xa_mutex);
1943         return (xa);
1944 }
1945 
1946 void
1947 smb_xa_rele(smb_session_t *session, smb_xa_t *xa)
1948 {
1949         mutex_enter(&xa->xa_mutex);
1950         ASSERT(xa->xa_refcnt);
1951         xa->xa_refcnt--;
1952         if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) {
1953                 mutex_exit(&xa->xa_mutex);
1954                 smb_llist_enter(&session->s_xa_list, RW_WRITER);
1955                 smb_llist_remove(&session->s_xa_list, xa);
1956                 smb_llist_exit(&session->s_xa_list);
1957                 smb_xa_delete(xa);
1958                 return;
1959         }
1960         mutex_exit(&xa->xa_mutex);
1961 }
1962 
1963 int
1964 smb_xa_open(smb_xa_t *xa)
1965 {
1966         int rc;
1967 
1968         mutex_enter(&xa->xa_mutex);
1969 
1970         ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0);
1971 
1972         if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) {
1973                 xa->xa_flags |= SMB_XA_FLAG_OPEN;
1974                 rc = 0;
1975         } else {
1976                 rc = ERROR_INVALID_HANDLE;
1977         }
1978 
1979         mutex_exit(&xa->xa_mutex);
1980 
1981         return (rc);
1982 }
1983 
1984 void
1985 smb_xa_close(smb_xa_t *xa)
1986 {
1987         mutex_enter(&xa->xa_mutex);
1988         xa->xa_flags |= SMB_XA_FLAG_CLOSE;
1989         xa->xa_flags &= ~SMB_XA_FLAG_OPEN;
1990 
1991         if (xa->xa_refcnt == 0) {
1992                 mutex_exit(&xa->xa_mutex);
1993                 smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER);
1994                 smb_llist_remove(&xa->xa_session->s_xa_list, xa);
1995                 smb_llist_exit(&xa->xa_session->s_xa_list);
1996                 smb_xa_delete(xa);
1997                 return;
1998         }
1999 
2000         mutex_exit(&xa->xa_mutex);
2001 }
2002 
2003 int
2004 smb_xa_complete(smb_xa_t *xa)
2005 {
2006         int rc;
2007 
2008         mutex_enter(&xa->xa_mutex);
2009         if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) {
2010                 rc = 0; /* error ("not complete") */
2011         } else {
2012                 rc = 1; /* Yes, "complete" */
2013                 xa->xa_flags |= SMB_XA_FLAG_COMPLETE;
2014 
2015                 /*
2016                  * During trans & trans-secondary processing,
2017                  * we copied the request data into these.
2018                  * Now we want to parse them, so we need to
2019                  * move the "finger" back to the beginning.
2020                  */
2021                 xa->req_setup_mb.chain_offset = 0;
2022                 xa->req_param_mb.chain_offset = 0;
2023                 xa->req_data_mb.chain_offset  = 0;
2024         }
2025 
2026         mutex_exit(&xa->xa_mutex);
2027         return (rc);
2028 }
2029 
2030 smb_xa_t *
2031 smb_xa_find(
2032     smb_session_t       *session,
2033     uint32_t            pid,
2034     uint16_t            mid)
2035 {
2036         smb_xa_t        *xa;
2037         smb_llist_t     *xlist;
2038 
2039         xlist = &session->s_xa_list;
2040         smb_llist_enter(xlist, RW_READER);
2041         xa = smb_llist_head(xlist);
2042         while (xa) {
2043                 mutex_enter(&xa->xa_mutex);
2044                 if (xa->xa_smb_mid == mid &&
2045                     xa->smb_pid == pid &&
2046                     !SMB_XA_CLOSED(xa) &&
2047                     !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
2048                         xa->xa_refcnt++;
2049                         ASSERT(xa->xa_refcnt);
2050                         mutex_exit(&xa->xa_mutex);
2051                         break;
2052                 }
2053                 mutex_exit(&xa->xa_mutex);
2054                 xa = smb_llist_next(xlist, xa);
2055         }
2056         smb_llist_exit(xlist);
2057         return (xa);
2058 }