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 2020 Nexenta 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 uint32_t 94 smb_sd_get_secinfo(smb_sd_t *sd) 95 { 96 uint32_t sec_info = 0; 97 98 if (sd == NULL) 99 return (0); 100 101 if (sd->sd_owner) 102 sec_info |= SMB_OWNER_SECINFO; 103 104 if (sd->sd_group) 105 sec_info |= SMB_GROUP_SECINFO; 106 107 if (sd->sd_dacl) 108 sec_info |= SMB_DACL_SECINFO; 109 110 if (sd->sd_sacl) 111 sec_info |= SMB_SACL_SECINFO; 112 113 return (sec_info); 114 } 115 116 /* 117 * smb_sd_read 118 * 119 * Read uid, gid and ACL from filesystem. The returned ACL from read 120 * routine is always in ZFS format. Convert the ZFS acl to a Win acl 121 * and return the Win SD in absolute form. 122 * 123 * NOTE: upon successful return caller MUST free the memory allocated 124 * for the returned SD by calling smb_sd_term(). 125 */ 126 uint32_t 127 smb_sd_read(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) 128 { 129 smb_fssd_t fs_sd; 130 smb_node_t *node; 131 uint32_t status = NT_STATUS_SUCCESS; 132 uint32_t sd_flags; 133 int error; 134 135 node = sr->fid_ofile->f_node; 136 sd_flags = smb_node_is_dir(node) ? SMB_FSSD_FLAGS_DIR : 0; 137 smb_fssd_init(&fs_sd, secinfo, sd_flags); 138 139 error = smb_fsop_sdread(sr, sr->user_cr, node, &fs_sd); 140 if (error) 141 return (smb_errno2status(error)); 142 143 status = smb_sd_fromfs(&fs_sd, sd); 144 smb_fssd_term(&fs_sd); 145 146 return (status); 147 } 148 149 /* 150 * smb_sd_write 151 * 152 * Takes a Win SD in absolute form, converts it to 153 * ZFS format and write it to filesystem. The write routine 154 * converts ZFS acl to Posix acl if required. 155 */ 156 uint32_t 157 smb_sd_write(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) 158 { 159 smb_node_t *node; 160 smb_fssd_t fs_sd; 161 uint32_t status; 162 uint32_t sd_flags; 163 int error; 164 165 node = sr->fid_ofile->f_node; 166 sd_flags = smb_node_is_dir(node) ? SMB_FSSD_FLAGS_DIR : 0; 167 smb_fssd_init(&fs_sd, secinfo, sd_flags); 168 169 status = smb_sd_tofs(sd, &fs_sd); 170 if (status != NT_STATUS_SUCCESS) { 171 smb_fssd_term(&fs_sd); 172 return (status); 173 } 174 175 error = smb_fsop_sdwrite(sr, sr->user_cr, node, &fs_sd, 0); 176 smb_fssd_term(&fs_sd); 177 178 if (error) { 179 if (error == EBADE) 180 return (NT_STATUS_INVALID_OWNER); 181 return (smb_errno2status(error)); 182 } 183 184 return (NT_STATUS_SUCCESS); 185 } 186 187 188 /* 189 * smb_sd_tofs 190 * 191 * Creates a filesystem security structure based on the given 192 * Windows security descriptor. 193 */ 194 uint32_t 195 smb_sd_tofs(smb_sd_t *sd, smb_fssd_t *fs_sd) 196 { 197 smb_sid_t *sid; 198 uint32_t status = NT_STATUS_SUCCESS; 199 uint16_t sd_control; 200 idmap_stat idm_stat; 201 int idtype; 202 int flags = 0; 203 204 sd_control = sd->sd_control; 205 206 /* 207 * ZFS only has one set of flags so for now only 208 * Windows DACL flags are taken into account. 209 */ 210 if (sd_control & SE_DACL_DEFAULTED) 211 flags |= ACL_DEFAULTED; 212 if (sd_control & SE_DACL_AUTO_INHERITED) 213 flags |= ACL_AUTO_INHERIT; 214 if (sd_control & SE_DACL_PROTECTED) 215 flags |= ACL_PROTECTED; 216 217 if (fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR) 218 flags |= ACL_IS_DIR; 219 220 /* Owner */ 221 if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { 222 sid = sd->sd_owner; 223 if (!smb_sid_isvalid(sid)) 224 return (NT_STATUS_INVALID_SID); 225 226 idtype = SMB_IDMAP_USER; 227 idm_stat = smb_idmap_getid(sid, &fs_sd->sd_uid, &idtype); 228 if (idm_stat != IDMAP_SUCCESS) { 229 return (NT_STATUS_NONE_MAPPED); 230 } 231 } 232 233 /* Group */ 234 if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { 235 sid = sd->sd_group; 236 if (!smb_sid_isvalid(sid)) 237 return (NT_STATUS_INVALID_SID); 238 239 idtype = SMB_IDMAP_GROUP; 240 idm_stat = smb_idmap_getid(sid, &fs_sd->sd_gid, &idtype); 241 if (idm_stat != IDMAP_SUCCESS) { 242 return (NT_STATUS_NONE_MAPPED); 243 } 244 } 245 246 /* 247 * In SMB, the 'secinfo' determines which parts of the SD the client 248 * intends to change. Notably, this includes changing the DACL_PRESENT 249 * and SACL_PRESENT control bits. The client can specify e.g. 250 * SACL_SECINFO, but not SACL_PRESENT, and this means the client intends 251 * to remove the SACL. 252 * 253 * If the *_PRESENT bit isn't set, then the respective ACL will be NULL. 254 * [MS-DTYP] disallows providing an ACL when the PRESENT bit isn't set. 255 * This is enforced by smb_decode_sd(). 256 * 257 * We allow the SACL to be NULL, but we MUST have a DACL. 258 * If the DACL is NULL, that's equivalent to "everyone:full_set:allow". 259 */ 260 261 /* DACL */ 262 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { 263 ASSERT3U(((sd->sd_control & SE_DACL_PRESENT) != 0), ==, 264 (sd->sd_dacl != NULL)); 265 status = smb_acl_to_zfs(sd->sd_dacl, flags, 266 SMB_DACL_SECINFO, &fs_sd->sd_zdacl); 267 if (status != NT_STATUS_SUCCESS) 268 return (status); 269 } 270 271 /* SACL */ 272 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { 273 if (sd->sd_control & SE_SACL_PRESENT) { 274 status = smb_acl_to_zfs(sd->sd_sacl, flags, 275 SMB_SACL_SECINFO, &fs_sd->sd_zsacl); 276 if (status != NT_STATUS_SUCCESS) { 277 return (status); 278 } 279 } 280 } 281 282 return (status); 283 } 284 285 /* 286 * smb_sd_fromfs 287 * 288 * Makes an Windows style security descriptor in absolute form 289 * based on the given filesystem security information. 290 * 291 * Should call smb_sd_term() for the returned sd to free allocated 292 * members. 293 */ 294 static uint32_t 295 smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd) 296 { 297 uint32_t status = NT_STATUS_SUCCESS; 298 smb_acl_t *acl = NULL; 299 smb_sid_t *sid; 300 idmap_stat idm_stat; 301 302 ASSERT(fs_sd); 303 ASSERT(sd); 304 305 smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION); 306 307 /* Owner */ 308 if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { 309 idm_stat = smb_idmap_getsid(fs_sd->sd_uid, 310 SMB_IDMAP_USER, &sid); 311 312 if (idm_stat != IDMAP_SUCCESS) { 313 smb_sd_term(sd); 314 return (NT_STATUS_NONE_MAPPED); 315 } 316 317 sd->sd_owner = sid; 318 } 319 320 /* Group */ 321 if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { 322 idm_stat = smb_idmap_getsid(fs_sd->sd_gid, 323 SMB_IDMAP_GROUP, &sid); 324 325 if (idm_stat != IDMAP_SUCCESS) { 326 smb_sd_term(sd); 327 return (NT_STATUS_NONE_MAPPED); 328 } 329 330 sd->sd_group = sid; 331 } 332 333 /* DACL */ 334 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { 335 if (fs_sd->sd_zdacl != NULL) { 336 acl = smb_acl_from_zfs(fs_sd->sd_zdacl); 337 if (acl == NULL) { 338 smb_sd_term(sd); 339 return (NT_STATUS_INTERNAL_ERROR); 340 } 341 342 /* 343 * Need to sort the ACL before send it to Windows 344 * clients. Winodws GUI is sensitive about the order 345 * of ACEs. 346 */ 347 smb_acl_sort(acl); 348 smb_sd_set_dacl(sd, acl, B_TRUE, 349 fs_sd->sd_zdacl->acl_flags); 350 } else { 351 smb_sd_set_dacl(sd, NULL, B_FALSE, 0); 352 } 353 } 354 355 /* SACL */ 356 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { 357 if (fs_sd->sd_zsacl != NULL) { 358 acl = smb_acl_from_zfs(fs_sd->sd_zsacl); 359 if (acl == NULL) { 360 smb_sd_term(sd); 361 return (NT_STATUS_INTERNAL_ERROR); 362 } 363 364 smb_sd_set_sacl(sd, acl, B_TRUE, 365 fs_sd->sd_zsacl->acl_flags); 366 } else { 367 smb_sd_set_sacl(sd, NULL, B_FALSE, 0); 368 } 369 } 370 371 return (status); 372 } 373 374 static void 375 smb_sd_set_dacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags) 376 { 377 ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); 378 379 sd->sd_dacl = acl; 380 381 if (flags & ACL_DEFAULTED) 382 sd->sd_control |= SE_DACL_DEFAULTED; 383 if (flags & ACL_AUTO_INHERIT) 384 sd->sd_control |= SE_DACL_AUTO_INHERITED; 385 if (flags & ACL_PROTECTED) 386 sd->sd_control |= SE_DACL_PROTECTED; 387 388 if (present) 389 sd->sd_control |= SE_DACL_PRESENT; 390 } 391 392 static void 393 smb_sd_set_sacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags) 394 { 395 ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); 396 397 sd->sd_sacl = acl; 398 399 if (flags & ACL_DEFAULTED) 400 sd->sd_control |= SE_SACL_DEFAULTED; 401 if (flags & ACL_AUTO_INHERIT) 402 sd->sd_control |= SE_SACL_AUTO_INHERITED; 403 if (flags & ACL_PROTECTED) 404 sd->sd_control |= SE_SACL_PROTECTED; 405 406 if (present) 407 sd->sd_control |= SE_SACL_PRESENT; 408 } 409 410 /* 411 * smb_fssd_init 412 * 413 * Initializes the given FS SD structure. 414 */ 415 void 416 smb_fssd_init(smb_fssd_t *fs_sd, uint32_t secinfo, uint32_t flags) 417 { 418 bzero(fs_sd, sizeof (smb_fssd_t)); 419 fs_sd->sd_secinfo = secinfo; 420 fs_sd->sd_flags = flags; 421 } 422 423 /* 424 * smb_fssd_term 425 * 426 * Frees allocated memory for acl fields. 427 */ 428 void 429 smb_fssd_term(smb_fssd_t *fs_sd) 430 { 431 ASSERT(fs_sd); 432 433 smb_fsacl_free(fs_sd->sd_zdacl); 434 smb_fsacl_free(fs_sd->sd_zsacl); 435 bzero(fs_sd, sizeof (smb_fssd_t)); 436 } 437