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 2016 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 #include <smbsrv/smb_kproto.h>
  28 
  29 static void smb_encode_sacl(mbuf_chain_t *, smb_acl_t *);
  30 static void smb_encode_dacl(mbuf_chain_t *, smb_acl_t *);
  31 static smb_acl_t *smb_decode_acl(mbuf_chain_t *, uint32_t);
  32 
  33 /*
  34  * smb_nt_transact_query_security_info
  35  *
  36  * This command allows the client to retrieve the security descriptor
  37  * on a file. The result of the call is returned to the client in the
  38  * Data part of the transaction response.
  39  *
  40  * Some clients specify a non-zero maximum data return size (mdrcnt)
  41  * for the SD and some specify zero. In either case, if the mdrcnt is
  42  * too small we need to return NT_STATUS_BUFFER_TOO_SMALL and a buffer
  43  * size hint. The client should then retry with the appropriate buffer
  44  * size.
  45  *
  46  *  Client Parameter Block             Description
  47  *  ================================== =================================
  48  *
  49  *  USHORT Fid;                        FID of target
  50  *  USHORT Reserved;                   MBZ
  51  *  ULONG secinfo;                     Fields of descriptor to set
  52  *
  53  *   Data Block Encoding                Description
  54  *   ================================== ==================================
  55  *
  56  *   Data[TotalDataCount]               Security Descriptor information
  57  */
  58 
  59 smb_sdrc_t
  60 smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa)
  61 {
  62         smb_sd_t sd;
  63         uint32_t secinfo;
  64         uint32_t sdlen;
  65         uint32_t status;
  66         smb_error_t err;
  67 
  68         if (smb_mbc_decodef(&xa->req_param_mb, "w2.l",
  69             &sr->smb_fid, &secinfo) != 0) {
  70                 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
  71                 return (SDRC_ERROR);
  72         }
  73 
  74         smbsr_lookup_file(sr);
  75         if (sr->fid_ofile == NULL) {
  76                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
  77                 return (SDRC_ERROR);
  78         }
  79 
  80 
  81         if ((sr->fid_ofile->f_node == NULL) ||
  82             (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) {
  83                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
  84                     ERRDOS, ERROR_ACCESS_DENIED);
  85                 return (SDRC_ERROR);
  86         }
  87 
  88         sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
  89 
  90         if (sr->tid_tree->t_acltype != ACE_T) {
  91                 /*
  92                  * If target filesystem doesn't support ACE_T acls then
  93                  * don't process SACL
  94                  */
  95                 secinfo &= ~SMB_SACL_SECINFO;
  96         }
  97 
  98         status = smb_sd_read(sr, &sd, secinfo);
  99         if (status != NT_STATUS_SUCCESS) {
 100                 smbsr_error(sr, status, 0, 0);
 101                 return (SDRC_ERROR);
 102         }
 103 
 104         sdlen = smb_sd_len(&sd, secinfo);
 105         if (sdlen == 0) {
 106                 smb_sd_term(&sd);
 107                 smbsr_error(sr, NT_STATUS_INVALID_SECURITY_DESCR, 0, 0);
 108                 return (SDRC_ERROR);
 109         }
 110 
 111         if (sdlen > xa->smb_mdrcnt) {
 112                 /*
 113                  * The maximum data return count specified by the
 114                  * client is not big enough to hold the security
 115                  * descriptor. We have to return an error but we
 116                  * should provide a buffer size hint for the client.
 117                  */
 118                 (void) smb_mbc_encodef(&xa->rep_param_mb, "l", sdlen);
 119                 err.status   = NT_STATUS_BUFFER_TOO_SMALL;
 120                 err.errcls   = ERRDOS;
 121                 err.errcode  = ERROR_INSUFFICIENT_BUFFER;
 122                 smbsr_set_error(sr, &err);
 123                 smb_sd_term(&sd);
 124                 return (SDRC_SUCCESS);
 125         }
 126 
 127         smb_encode_sd(&xa->rep_data_mb, &sd, secinfo);
 128         (void) smb_mbc_encodef(&xa->rep_param_mb, "l", sdlen);
 129         smb_sd_term(&sd);
 130         return (SDRC_SUCCESS);
 131 }
 132 
 133 /*
 134  * smb_nt_transact_set_security_info
 135  *
 136  * This command allows the client to change the security descriptor on a
 137  * file. All we do here is decode the parameters and the data. The data
 138  * is passed directly to smb_nt_set_security_object, with the security
 139  * information describing the information to set. There are no response
 140  * parameters or data.
 141  *
 142  *   Client Parameter Block Encoding    Description
 143  *   ================================== ==================================
 144  *   USHORT Fid;                        FID of target
 145  *   USHORT Reserved;                   MBZ
 146  *   ULONG SecurityInformation;         Fields of SD that to set
 147  *
 148  *   Data Block Encoding                Description
 149  *   ================================== ==================================
 150  *   Data[TotalDataCount]               Security Descriptor information
 151  */
 152 smb_sdrc_t
 153 smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa)
 154 {
 155         smb_sd_t sd;
 156         uint32_t secinfo;
 157         uint32_t status;
 158 
 159         if (smb_mbc_decodef(&xa->req_param_mb, "w2.l",
 160             &sr->smb_fid, &secinfo) != 0) {
 161                 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
 162                 return (SDRC_ERROR);
 163         }
 164 
 165         smbsr_lookup_file(sr);
 166         if (sr->fid_ofile == NULL) {
 167                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
 168                 return (SDRC_ERROR);
 169         }
 170 
 171         if ((sr->fid_ofile->f_node == NULL) ||
 172             (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) {
 173                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 0, 0);
 174                 return (SDRC_ERROR);
 175         }
 176 
 177         sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
 178 
 179         if (SMB_TREE_IS_READONLY(sr)) {
 180                 smbsr_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED, 0, 0);
 181                 return (SDRC_ERROR);
 182         }
 183 
 184         if (sr->tid_tree->t_acltype != ACE_T) {
 185                 /*
 186                  * If target filesystem doesn't support ACE_T acls then
 187                  * don't process SACL
 188                  */
 189                 secinfo &= ~SMB_SACL_SECINFO;
 190         }
 191 
 192         if ((secinfo & SMB_ALL_SECINFO) == 0) {
 193                 return (NT_STATUS_SUCCESS);
 194         }
 195 
 196         status = smb_decode_sd(&xa->req_data_mb, &sd);
 197         if (status != NT_STATUS_SUCCESS) {
 198                 smbsr_error(sr, status, 0, 0);
 199                 return (SDRC_ERROR);
 200         }
 201 
 202         if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) ||
 203             ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) {
 204                 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
 205                 return (SDRC_ERROR);
 206         }
 207 
 208         if (!smb_node_is_system(sr->fid_ofile->f_node))
 209                 status = smb_sd_write(sr, &sd, secinfo);
 210 
 211         smb_sd_term(&sd);
 212         if (status != NT_STATUS_SUCCESS) {
 213                 smbsr_error(sr, status, 0, 0);
 214                 return (SDRC_ERROR);
 215         }
 216 
 217         return (SDRC_SUCCESS);
 218 }
 219 
 220 /*
 221  * smb_encode_sd
 222  *
 223  * Encodes given security descriptor in the reply buffer.
 224  */
 225 void
 226 smb_encode_sd(mbuf_chain_t *mbc, smb_sd_t *sd, uint32_t secinfo)
 227 {
 228         uint32_t offset = SMB_SD_HDRSIZE;
 229 
 230         /* encode header */
 231         (void) smb_mbc_encodef(mbc, "b.w",
 232             sd->sd_revision, sd->sd_control | SE_SELF_RELATIVE);
 233 
 234         /* owner offset */
 235         if (secinfo & SMB_OWNER_SECINFO) {
 236                 ASSERT(sd->sd_owner);
 237                 (void) smb_mbc_encodef(mbc, "l", offset);
 238                 offset += smb_sid_len(sd->sd_owner);
 239         } else {
 240                 (void) smb_mbc_encodef(mbc, "l", 0);
 241         }
 242 
 243         /* group offset */
 244         if (secinfo & SMB_GROUP_SECINFO) {
 245                 ASSERT(sd->sd_group);
 246                 (void) smb_mbc_encodef(mbc, "l", offset);
 247                 offset += smb_sid_len(sd->sd_group);
 248         } else {
 249                 (void) smb_mbc_encodef(mbc, "l", 0);
 250         }
 251 
 252         /* SACL offset */
 253         if ((secinfo & SMB_SACL_SECINFO) && (sd->sd_sacl)) {
 254                 (void) smb_mbc_encodef(mbc, "l", offset);
 255                 offset += smb_acl_len(sd->sd_sacl);
 256         } else {
 257                 (void) smb_mbc_encodef(mbc, "l", 0);
 258         }
 259 
 260         /* DACL offset */
 261         if ((secinfo & SMB_DACL_SECINFO) && (sd->sd_dacl))
 262                 (void) smb_mbc_encodef(mbc, "l", offset);
 263         else
 264                 (void) smb_mbc_encodef(mbc, "l", 0);
 265 
 266         if (secinfo & SMB_OWNER_SECINFO)
 267                 smb_encode_sid(mbc, sd->sd_owner);
 268 
 269         if (secinfo & SMB_GROUP_SECINFO)
 270                 smb_encode_sid(mbc, sd->sd_group);
 271 
 272         if (secinfo & SMB_SACL_SECINFO)
 273                 smb_encode_sacl(mbc, sd->sd_sacl);
 274 
 275         if (secinfo & SMB_DACL_SECINFO)
 276                 smb_encode_dacl(mbc, sd->sd_dacl);
 277 }
 278 
 279 /*
 280  * smb_encode_sid
 281  *
 282  * Encodes given SID in the reply buffer.
 283  */
 284 void
 285 smb_encode_sid(mbuf_chain_t *mbc, smb_sid_t *sid)
 286 {
 287         int i;
 288 
 289         (void) smb_mbc_encodef(mbc, "bb",
 290             sid->sid_revision, sid->sid_subauthcnt);
 291 
 292         for (i = 0; i < NT_SID_AUTH_MAX; i++) {
 293                 (void) smb_mbc_encodef(mbc, "b",
 294                     sid->sid_authority[i]);
 295         }
 296 
 297         for (i = 0; i < sid->sid_subauthcnt; i++) {
 298                 (void) smb_mbc_encodef(mbc, "l",
 299                     sid->sid_subauth[i]);
 300         }
 301 }
 302 
 303 /*
 304  * smb_encode_sacl
 305  *
 306  * Encodes given SACL in the reply buffer.
 307  */
 308 static void
 309 smb_encode_sacl(mbuf_chain_t *mbc, smb_acl_t *acl)
 310 {
 311         smb_ace_t *ace;
 312         int i;
 313 
 314         if (acl == NULL)
 315                 return;
 316 
 317         /* encode header */
 318         (void) smb_mbc_encodef(mbc, "b.ww2.", acl->sl_revision,
 319             acl->sl_bsize, acl->sl_acecnt);
 320 
 321         for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) {
 322                 (void) smb_mbc_encodef(mbc, "bbwl",
 323                     ace->se_hdr.se_type, ace->se_hdr.se_flags,
 324                     ace->se_hdr.se_bsize, ace->se_mask);
 325 
 326                 smb_encode_sid(mbc, ace->se_sid);
 327         }
 328 }
 329 
 330 /*
 331  * smb_encode_dacl
 332  *
 333  * Encodes given DACL in the reply buffer.
 334  */
 335 static void
 336 smb_encode_dacl(mbuf_chain_t *mbc, smb_acl_t *acl)
 337 {
 338         smb_ace_t *ace;
 339 
 340         if (acl == NULL)
 341                 return;
 342 
 343         /* encode header */
 344         (void) smb_mbc_encodef(mbc, "b.ww2.", acl->sl_revision,
 345             acl->sl_bsize, acl->sl_acecnt);
 346 
 347         ace = list_head(&acl->sl_sorted);
 348         while (ace) {
 349                 (void) smb_mbc_encodef(mbc, "bbwl",
 350                     ace->se_hdr.se_type, ace->se_hdr.se_flags,
 351                     ace->se_hdr.se_bsize, ace->se_mask);
 352 
 353                 smb_encode_sid(mbc, ace->se_sid);
 354                 ace = list_next(&acl->sl_sorted, ace);
 355         }
 356 }
 357 
 358 /*
 359  * smb_decode_sd
 360  *
 361  * Decodes the security descriptor in the request buffer
 362  * and set the fields of 'sd' appropraitely. Upon successful
 363  * return, caller must free allocated memories by calling
 364  * smb_sd_term().
 365  */
 366 uint32_t
 367 smb_decode_sd(mbuf_chain_t *mbc, smb_sd_t *sd)
 368 {
 369         struct mbuf_chain sdbuf;
 370         uint32_t owner_offs;
 371         uint32_t group_offs;
 372         uint32_t sacl_offs;
 373         uint32_t dacl_offs;
 374         int rc;
 375 
 376         smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION);
 377 
 378         (void) MBC_SHADOW_CHAIN(&sdbuf, mbc,
 379             mbc->chain_offset,
 380             mbc->max_bytes - mbc->chain_offset);
 381 
 382         rc = smb_mbc_decodef(&sdbuf, "b.wllll",
 383             &sd->sd_revision, &sd->sd_control,
 384             &owner_offs, &group_offs, &sacl_offs, &dacl_offs);
 385 
 386         /* Prevent disallowed flags in smb_sd_term. */
 387         sd->sd_control &= ~SE_SELF_RELATIVE;
 388         if (rc != 0)
 389                 goto decode_error;
 390 
 391         if (owner_offs != 0) {
 392                 if (owner_offs < SMB_SD_HDRSIZE)
 393                         goto decode_error;
 394 
 395                 sd->sd_owner = smb_decode_sid(mbc, owner_offs);
 396                 if (sd->sd_owner == NULL)
 397                         goto decode_error;
 398         }
 399 
 400         if (group_offs != 0) {
 401                 if (group_offs < SMB_SD_HDRSIZE)
 402                         goto decode_error;
 403 
 404                 sd->sd_group = smb_decode_sid(mbc, group_offs);
 405                 if (sd->sd_group == NULL)
 406                         goto decode_error;
 407         }
 408 
 409         if (sacl_offs != 0) {
 410                 if ((sd->sd_control & SE_SACL_PRESENT) == 0)
 411                         goto decode_error;
 412 
 413                 if (sacl_offs < SMB_SD_HDRSIZE)
 414                         goto decode_error;
 415 
 416                 sd->sd_sacl = smb_decode_acl(mbc, sacl_offs);
 417                 if (sd->sd_sacl == NULL)
 418                         goto decode_error;
 419         }
 420 
 421         if (dacl_offs != 0) {
 422                 if ((sd->sd_control & SE_DACL_PRESENT) == 0)
 423                         goto decode_error;
 424 
 425                 if (dacl_offs < SMB_SD_HDRSIZE)
 426                         goto decode_error;
 427 
 428                 sd->sd_dacl = smb_decode_acl(mbc, dacl_offs);
 429                 if (sd->sd_dacl == NULL)
 430                         goto decode_error;
 431         }
 432 
 433         return (NT_STATUS_SUCCESS);
 434 
 435 decode_error:
 436         smb_sd_term(sd);
 437         return (NT_STATUS_INVALID_SECURITY_DESCR);
 438 }
 439 
 440 /*
 441  * smb_decode_sid
 442  *
 443  * Allocates memory and decodes the SID in the request buffer
 444  * Upon successful return, caller must free the allocated memory
 445  * by calling smb_sid_free()
 446  */
 447 smb_sid_t *
 448 smb_decode_sid(mbuf_chain_t *mbc, uint32_t offset)
 449 {
 450         uint8_t revision;
 451         uint8_t subauth_cnt;
 452         struct mbuf_chain sidbuf;
 453         smb_sid_t *sid;
 454         int sidlen;
 455         int bytes_left;
 456         int i;
 457 
 458         offset += mbc->chain_offset;
 459         bytes_left = mbc->max_bytes - offset;
 460         if (bytes_left < (int)sizeof (smb_sid_t))
 461                 return (NULL);
 462 
 463         if (MBC_SHADOW_CHAIN(&sidbuf, mbc, offset, bytes_left) != 0)
 464                 return (NULL);
 465 
 466         if (smb_mbc_decodef(&sidbuf, "bb", &revision, &subauth_cnt))
 467                 return (NULL);
 468 
 469         sidlen = sizeof (smb_sid_t) - sizeof (uint32_t) +
 470             (subauth_cnt * sizeof (uint32_t));
 471         sid = kmem_alloc(sidlen, KM_SLEEP);
 472 
 473         sid->sid_revision = revision;
 474         sid->sid_subauthcnt = subauth_cnt;
 475 
 476         for (i = 0; i < NT_SID_AUTH_MAX; i++) {
 477                 if (smb_mbc_decodef(&sidbuf, "b", &sid->sid_authority[i]))
 478                         goto decode_err;
 479         }
 480 
 481         for (i = 0; i < sid->sid_subauthcnt; i++) {
 482                 if (smb_mbc_decodef(&sidbuf, "l", &sid->sid_subauth[i]))
 483                         goto decode_err;
 484         }
 485 
 486         return (sid);
 487 
 488 decode_err:
 489         kmem_free(sid, sidlen);
 490         return (NULL);
 491 }
 492 
 493 /*
 494  * smb_decode_acl
 495  *
 496  * Allocates memory and decodes the ACL in the request buffer
 497  * Upon successful return, caller must free the allocated memory
 498  * by calling smb_acl_free().
 499  */
 500 static smb_acl_t *
 501 smb_decode_acl(mbuf_chain_t *mbc, uint32_t offset)
 502 {
 503         struct mbuf_chain aclbuf;
 504         smb_acl_t *acl;
 505         smb_ace_t *ace;
 506         uint8_t revision;
 507         uint16_t size;
 508         uint16_t acecnt;
 509         int bytes_left;
 510         uint32_t sid_offs = offset;
 511         int sidlen;
 512         int i;
 513 
 514         offset += mbc->chain_offset;
 515         bytes_left = mbc->max_bytes - offset;
 516         if (bytes_left < SMB_ACL_HDRSIZE)
 517                 return (NULL);
 518 
 519         if (MBC_SHADOW_CHAIN(&aclbuf, mbc, offset, bytes_left) != 0)
 520                 return (NULL);
 521 
 522         if (smb_mbc_decodef(&aclbuf, "b.ww2.", &revision, &size, &acecnt))
 523                 return (NULL);
 524 
 525         if (size == 0)
 526                 return (NULL);
 527 
 528         acl = smb_acl_alloc(revision, size, acecnt);
 529 
 530         sid_offs += SMB_ACL_HDRSIZE;
 531         for (i = 0, ace = acl->sl_aces; i < acl->sl_acecnt; i++, ace++) {
 532                 if (smb_mbc_decodef(&aclbuf, "bbwl",
 533                     &ace->se_hdr.se_type, &ace->se_hdr.se_flags,
 534                     &ace->se_hdr.se_bsize, &ace->se_mask))
 535                         goto decode_error;
 536 
 537                 sid_offs += SMB_ACE_HDRSIZE + sizeof (ace->se_mask);
 538                 ace->se_sid = smb_decode_sid(mbc, sid_offs);
 539                 if (ace->se_sid == NULL)
 540                         goto decode_error;
 541                 /* This is SID length plus any paddings between ACEs */
 542                 sidlen = ace->se_hdr.se_bsize -
 543                     (SMB_ACE_HDRSIZE + sizeof (ace->se_mask));
 544                 aclbuf.chain_offset += sidlen;
 545                 sid_offs += sidlen;
 546         }
 547 
 548         return (acl);
 549 
 550 decode_error:
 551         smb_acl_free(acl);
 552         return (NULL);
 553 }