1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2021 Tintri by DDN, Inc. All rights reserved. 26 */ 27 28 /* 29 * This module provides Security Descriptor handling functions. 30 */ 31 32 #include <smbsrv/smb_kproto.h> 33 #include <smbsrv/smb_fsops.h> 34 #include <smbsrv/smb_idmap.h> 35 36 static void smb_sd_set_sacl(smb_sd_t *, smb_acl_t *, boolean_t, int); 37 static void smb_sd_set_dacl(smb_sd_t *, smb_acl_t *, boolean_t, int); 38 static uint32_t smb_sd_fromfs(smb_fssd_t *, smb_sd_t *); 39 40 void 41 smb_sd_init(smb_sd_t *sd, uint8_t revision) 42 { 43 bzero(sd, sizeof (smb_sd_t)); 44 sd->sd_revision = revision; 45 } 46 47 /* 48 * smb_sd_term 49 * 50 * Free non-NULL members of 'sd' which has to be in 51 * absolute (pointer) form. 52 */ 53 void 54 smb_sd_term(smb_sd_t *sd) 55 { 56 ASSERT(sd); 57 ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); 58 59 smb_sid_free(sd->sd_owner); 60 smb_sid_free(sd->sd_group); 61 smb_acl_free(sd->sd_dacl); 62 smb_acl_free(sd->sd_sacl); 63 64 bzero(sd, sizeof (smb_sd_t)); 65 } 66 67 uint32_t 68 smb_sd_len(smb_sd_t *sd, uint32_t secinfo) 69 { 70 uint32_t length = SMB_SD_HDRSIZE; 71 72 if (secinfo & SMB_OWNER_SECINFO) 73 length += smb_sid_len(sd->sd_owner); 74 75 if (secinfo & SMB_GROUP_SECINFO) 76 length += smb_sid_len(sd->sd_group); 77 78 if (secinfo & SMB_DACL_SECINFO) 79 length += smb_acl_len(sd->sd_dacl); 80 81 if (secinfo & SMB_SACL_SECINFO) 82 length += smb_acl_len(sd->sd_sacl); 83 84 return (length); 85 } 86 87 /* 88 * smb_sd_get_secinfo 89 * 90 * Return the security information mask for the specified security 91 * descriptor. 92 * 93 * Note: This is used for 'create-with-sd'. 'set-security-info' provides the 94 * secinfo as part of the request, but create does not, so we must infer it. 95 */ 96 uint32_t 97 smb_sd_get_secinfo(smb_sd_t *sd) 98 { 99 uint32_t sec_info = 0; 100 101 if (sd == NULL) 102 return (0); 103 104 if (sd->sd_owner) 105 sec_info |= SMB_OWNER_SECINFO; 106 107 if (sd->sd_group) 108 sec_info |= SMB_GROUP_SECINFO; 109 110 if ((sd->sd_control & SE_DACL_PRESENT) != 0) 111 sec_info |= SMB_DACL_SECINFO; 112 113 if ((sd->sd_control & SE_SACL_PRESENT) != 0) 114 sec_info |= SMB_SACL_SECINFO; 115 116 return (sec_info); 117 } 118 119 /* 120 * smb_sd_read 121 * 122 * Read uid, gid and ACL from filesystem. The returned ACL from read 123 * routine is always in ZFS format. Convert the ZFS acl to a Win acl 124 * and return the Win SD in absolute form. 125 * 126 * NOTE: upon successful return caller MUST free the memory allocated 127 * for the returned SD by calling smb_sd_term(). 128 */ 129 uint32_t 130 smb_sd_read(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) 131 { 132 smb_fssd_t fs_sd; 133 smb_node_t *node; 134 uint32_t status = NT_STATUS_SUCCESS; 135 uint32_t sd_flags; 136 int error; 137 138 node = sr->fid_ofile->f_node; 139 sd_flags = smb_node_is_dir(node) ? SMB_FSSD_FLAGS_DIR : 0; 140 smb_fssd_init(&fs_sd, secinfo, sd_flags); 141 142 error = smb_fsop_sdread(sr, sr->user_cr, node, &fs_sd); 143 if (error) 144 return (smb_errno2status(error)); 145 146 status = smb_sd_fromfs(&fs_sd, sd); 147 smb_fssd_term(&fs_sd); 148 149 return (status); 150 } 151 152 /* 153 * smb_sd_write 154 * 155 * Takes a Win SD in absolute form, converts it to 156 * ZFS format and write it to filesystem. The write routine 157 * converts ZFS acl to Posix acl if required. 158 */ 159 uint32_t 160 smb_sd_write(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) 161 { 162 smb_node_t *node; 163 smb_fssd_t fs_sd; 164 uint32_t status; 165 uint32_t sd_flags; 166 int error; 167 168 node = sr->fid_ofile->f_node; 169 sd_flags = smb_node_is_dir(node) ? SMB_FSSD_FLAGS_DIR : 0; 170 smb_fssd_init(&fs_sd, secinfo, sd_flags); 171 172 status = smb_sd_tofs(sd, &fs_sd); 173 if (status != NT_STATUS_SUCCESS) { 174 smb_fssd_term(&fs_sd); 175 return (status); 176 } 177 178 error = smb_fsop_sdwrite(sr, sr->user_cr, node, &fs_sd, 0); 179 smb_fssd_term(&fs_sd); 180 181 if (error) { 182 if (error == EBADE) 183 return (NT_STATUS_INVALID_OWNER); 184 return (smb_errno2status(error)); 185 } 186 187 return (NT_STATUS_SUCCESS); 188 } 189 190 191 /* 192 * smb_sd_tofs 193 * 194 * Creates a filesystem security structure based on the given 195 * Windows security descriptor. 196 */ 197 uint32_t 198 smb_sd_tofs(smb_sd_t *sd, smb_fssd_t *fs_sd) 199 { 200 smb_sid_t *sid; 201 uint32_t status = NT_STATUS_SUCCESS; 202 uint16_t sd_control; 203 idmap_stat idm_stat; 204 int idtype; 205 int flags = 0; 206 207 sd_control = sd->sd_control; 208 209 /* 210 * ZFS only has one set of flags so for now only 211 * Windows DACL flags are taken into account. 212 */ 213 if (sd_control & SE_DACL_DEFAULTED) 214 flags |= ACL_DEFAULTED; 215 if (sd_control & SE_DACL_AUTO_INHERITED) 216 flags |= ACL_AUTO_INHERIT; 217 if (sd_control & SE_DACL_PROTECTED) 218 flags |= ACL_PROTECTED; 219 220 if (fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR) 221 flags |= ACL_IS_DIR; 222 223 /* Owner */ 224 if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { 225 sid = sd->sd_owner; 226 if (!smb_sid_isvalid(sid)) 227 return (NT_STATUS_INVALID_SID); 228 229 idtype = SMB_IDMAP_USER; 230 idm_stat = smb_idmap_getid(sid, &fs_sd->sd_uid, &idtype); 231 if (idm_stat != IDMAP_SUCCESS) { 232 return (NT_STATUS_NONE_MAPPED); 233 } 234 } 235 236 /* Group */ 237 if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { 238 sid = sd->sd_group; 239 if (!smb_sid_isvalid(sid)) 240 return (NT_STATUS_INVALID_SID); 241 242 idtype = SMB_IDMAP_GROUP; 243 idm_stat = smb_idmap_getid(sid, &fs_sd->sd_gid, &idtype); 244 if (idm_stat != IDMAP_SUCCESS) { 245 return (NT_STATUS_NONE_MAPPED); 246 } 247 } 248 249 /* 250 * In SMB, the 'secinfo' determines which parts of the SD the client 251 * intends to change. Notably, this includes changing the DACL_PRESENT 252 * and SACL_PRESENT control bits. The client can specify e.g. 253 * SACL_SECINFO, but not SACL_PRESENT, and this means the client intends 254 * to remove the SACL. 255 * 256 * Note that Windows behavior differs from that described in [MS-DTYP]. 257 * MS-DTYP states that the offset is nonzero if-and-only-if the PRESENT 258 * bit is set. It also states that a DACL that is marked non-present 259 * is equivalent to 'no security', but one that is marked present and 260 * provides no ACEs is equivalent to 'no access'. 261 * 262 * Windows, on the other hand, allows the offset to be 0 even when 263 * the PRESENT bit is set, and only provides security when the DACL 264 * offset is non-zero. It will also convert an SD where the DACL is 265 * marked not-present to one where the PRESENT bit is set and the 266 * offset is 0. 267 * 268 * If the *_PRESENT bit isn't set, then the respective ACL will be NULL. 269 * For the fssd, we allow the SACL to be NULL, but we MUST have a DACL. 270 * If the DACL is NULL, that's equivalent to "everyone:full_set:allow". 271 * 272 * The IMPLY's should be enforced by smb_decode_sd(). 273 */ 274 275 /* DACL */ 276 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { 277 IMPLY(sd->sd_dacl != NULL, 278 (sd->sd_control & SE_DACL_PRESENT) != 0); 279 status = smb_acl_to_zfs(sd->sd_dacl, flags, 280 SMB_DACL_SECINFO, &fs_sd->sd_zdacl); 281 if (status != NT_STATUS_SUCCESS) 282 return (status); 283 } 284 285 /* SACL */ 286 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { 287 IMPLY(sd->sd_sacl != NULL, 288 (sd->sd_control & SE_SACL_PRESENT) != 0); 289 if (sd->sd_control & SE_SACL_PRESENT) { 290 status = smb_acl_to_zfs(sd->sd_sacl, flags, 291 SMB_SACL_SECINFO, &fs_sd->sd_zsacl); 292 if (status != NT_STATUS_SUCCESS) { 293 return (status); 294 } 295 } 296 } 297 298 return (status); 299 } 300 301 /* 302 * smb_sd_fromfs 303 * 304 * Makes an Windows style security descriptor in absolute form 305 * based on the given filesystem security information. 306 * 307 * Should call smb_sd_term() for the returned sd to free allocated 308 * members. 309 */ 310 static uint32_t 311 smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd) 312 { 313 uint32_t status = NT_STATUS_SUCCESS; 314 smb_acl_t *acl = NULL; 315 smb_sid_t *sid; 316 idmap_stat idm_stat; 317 318 ASSERT(fs_sd); 319 ASSERT(sd); 320 321 smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION); 322 323 /* Owner */ 324 if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { 325 idm_stat = smb_idmap_getsid(fs_sd->sd_uid, 326 SMB_IDMAP_USER, &sid); 327 328 if (idm_stat != IDMAP_SUCCESS) { 329 smb_sd_term(sd); 330 return (NT_STATUS_NONE_MAPPED); 331 } 332 333 sd->sd_owner = sid; 334 } 335 336 /* Group */ 337 if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { 338 idm_stat = smb_idmap_getsid(fs_sd->sd_gid, 339 SMB_IDMAP_GROUP, &sid); 340 341 if (idm_stat != IDMAP_SUCCESS) { 342 smb_sd_term(sd); 343 return (NT_STATUS_NONE_MAPPED); 344 } 345 346 sd->sd_group = sid; 347 } 348 349 /* DACL */ 350 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { 351 if (fs_sd->sd_zdacl != NULL) { 352 acl = smb_acl_from_zfs(fs_sd->sd_zdacl); 353 if (acl == NULL) { 354 smb_sd_term(sd); 355 return (NT_STATUS_INTERNAL_ERROR); 356 } 357 358 /* 359 * Need to sort the ACL before send it to Windows 360 * clients. Winodws GUI is sensitive about the order 361 * of ACEs. 362 */ 363 smb_acl_sort(acl); 364 smb_sd_set_dacl(sd, acl, B_TRUE, 365 fs_sd->sd_zdacl->acl_flags); 366 } else { 367 smb_sd_set_dacl(sd, NULL, B_FALSE, 0); 368 } 369 } 370 371 /* SACL */ 372 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { 373 if (fs_sd->sd_zsacl != NULL) { 374 acl = smb_acl_from_zfs(fs_sd->sd_zsacl); 375 if (acl == NULL) { 376 smb_sd_term(sd); 377 return (NT_STATUS_INTERNAL_ERROR); 378 } 379 380 smb_sd_set_sacl(sd, acl, B_TRUE, 381 fs_sd->sd_zsacl->acl_flags); 382 } else { 383 smb_sd_set_sacl(sd, NULL, B_FALSE, 0); 384 } 385 } 386 387 return (status); 388 } 389 390 static void 391 smb_sd_set_dacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags) 392 { 393 ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); 394 395 sd->sd_dacl = acl; 396 397 if (flags & ACL_DEFAULTED) 398 sd->sd_control |= SE_DACL_DEFAULTED; 399 if (flags & ACL_AUTO_INHERIT) 400 sd->sd_control |= SE_DACL_AUTO_INHERITED; 401 if (flags & ACL_PROTECTED) 402 sd->sd_control |= SE_DACL_PROTECTED; 403 404 if (present) 405 sd->sd_control |= SE_DACL_PRESENT; 406 } 407 408 static void 409 smb_sd_set_sacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags) 410 { 411 ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); 412 413 sd->sd_sacl = acl; 414 415 if (flags & ACL_DEFAULTED) 416 sd->sd_control |= SE_SACL_DEFAULTED; 417 if (flags & ACL_AUTO_INHERIT) 418 sd->sd_control |= SE_SACL_AUTO_INHERITED; 419 if (flags & ACL_PROTECTED) 420 sd->sd_control |= SE_SACL_PROTECTED; 421 422 if (present) 423 sd->sd_control |= SE_SACL_PRESENT; 424 } 425 426 /* 427 * smb_fssd_init 428 * 429 * Initializes the given FS SD structure. 430 */ 431 void 432 smb_fssd_init(smb_fssd_t *fs_sd, uint32_t secinfo, uint32_t flags) 433 { 434 bzero(fs_sd, sizeof (smb_fssd_t)); 435 fs_sd->sd_secinfo = secinfo; 436 fs_sd->sd_flags = flags; 437 } 438 439 /* 440 * smb_fssd_term 441 * 442 * Frees allocated memory for acl fields. 443 */ 444 void 445 smb_fssd_term(smb_fssd_t *fs_sd) 446 { 447 ASSERT(fs_sd); 448 449 smb_fsacl_free(fs_sd->sd_zdacl); 450 smb_fsacl_free(fs_sd->sd_zsacl); 451 bzero(fs_sd, sizeof (smb_fssd_t)); 452 } 453