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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 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 #include <smbsrv/ntstatus.h> 36 37 static void smb_sd_set_sacl(smb_sd_t *, smb_acl_t *, boolean_t, int); 38 static void smb_sd_set_dacl(smb_sd_t *, smb_acl_t *, boolean_t, int); 39 static uint32_t smb_sd_fromfs(smb_fssd_t *, smb_sd_t *); 40 41 void 42 smb_sd_init(smb_sd_t *sd, uint8_t revision) 43 { 44 bzero(sd, sizeof (smb_sd_t)); 45 sd->sd_revision = revision; 46 } 47 48 /* 49 * smb_sd_term 50 * 51 * Free non-NULL members of 'sd' which has to be in 52 * absolute (pointer) form. 53 */ 54 void 55 smb_sd_term(smb_sd_t *sd) 56 { 57 ASSERT(sd); 58 ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); 59 60 if (sd->sd_owner) 61 MEM_FREE("libnt", sd->sd_owner); 62 63 if (sd->sd_group) 64 MEM_FREE("libnt", sd->sd_group); 65 66 smb_acl_free(sd->sd_dacl); 67 smb_acl_free(sd->sd_sacl); 68 69 bzero(sd, sizeof (smb_sd_t)); 70 } 71 72 uint32_t 73 smb_sd_len(smb_sd_t *sd, uint32_t secinfo) 74 { 75 uint32_t length = SMB_SD_HDRSIZE; 76 77 if (secinfo & SMB_OWNER_SECINFO) 78 length += nt_sid_length(sd->sd_owner); 79 80 if (secinfo & SMB_GROUP_SECINFO) 81 length += nt_sid_length(sd->sd_group); 82 83 if (secinfo & SMB_DACL_SECINFO) 84 length += smb_acl_len(sd->sd_dacl); 85 86 if (secinfo & SMB_SACL_SECINFO) 87 length += smb_acl_len(sd->sd_sacl); 88 89 return (length); 90 } 91 92 /* 93 * smb_sd_get_secinfo 94 * 95 * Return the security information mask for the specified security 96 * descriptor. 97 */ 98 uint32_t 99 smb_sd_get_secinfo(smb_sd_t *sd) 100 { 101 uint32_t sec_info = 0; 102 103 if (sd == NULL) 104 return (0); 105 106 if (sd->sd_owner) 107 sec_info |= SMB_OWNER_SECINFO; 108 109 if (sd->sd_group) 110 sec_info |= SMB_GROUP_SECINFO; 111 112 if (sd->sd_dacl) 113 sec_info |= SMB_DACL_SECINFO; 114 115 if (sd->sd_sacl) 116 sec_info |= SMB_SACL_SECINFO; 117 118 return (sec_info); 119 } 120 121 /* 122 * smb_sd_read 123 * 124 * Read uid, gid and ACL from filesystem. The returned ACL from read 125 * routine is always in ZFS format. Convert the ZFS acl to a Win acl 126 * and return the Win SD in absolute form. 127 * 128 * NOTE: upon successful return caller MUST free the memory allocated 129 * for the returned SD by calling smb_sd_term(). 130 */ 131 uint32_t 132 smb_sd_read(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) 133 { 134 smb_fssd_t fs_sd; 135 smb_error_t smb_err; 136 smb_node_t *node; 137 uint32_t status = NT_STATUS_SUCCESS; 138 uint32_t sd_flags; 139 int error; 140 141 node = sr->fid_ofile->f_node; 142 sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0; 143 smb_fssd_init(&fs_sd, secinfo, sd_flags); 144 145 error = smb_fsop_sdread(sr, sr->user_cr, node, &fs_sd); 146 if (error) { 147 smbsr_map_errno(error, &smb_err); 148 return (smb_err.status); 149 } 150 151 status = smb_sd_fromfs(&fs_sd, sd); 152 smb_fssd_term(&fs_sd); 153 154 return (status); 155 } 156 157 /* 158 * smb_sd_write 159 * 160 * Takes a Win SD in absolute form, converts it to 161 * ZFS format and write it to filesystem. The write routine 162 * converts ZFS acl to Posix acl if required. 163 */ 164 uint32_t 165 smb_sd_write(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) 166 { 167 smb_node_t *node; 168 smb_fssd_t fs_sd; 169 smb_error_t smb_err; 170 uint32_t status; 171 uint32_t sd_flags; 172 int error; 173 174 node = sr->fid_ofile->f_node; 175 sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0; 176 smb_fssd_init(&fs_sd, secinfo, sd_flags); 177 178 status = smb_sd_tofs(sd, &fs_sd); 179 if (status != NT_STATUS_SUCCESS) { 180 smb_fssd_term(&fs_sd); 181 return (status); 182 } 183 184 error = smb_fsop_sdwrite(sr, sr->user_cr, node, &fs_sd, 0); 185 smb_fssd_term(&fs_sd); 186 187 if (error) { 188 smbsr_map_errno(error, &smb_err); 189 return (smb_err.status); 190 } 191 192 return (NT_STATUS_SUCCESS); 193 } 194 195 196 /* 197 * smb_sd_tofs 198 * 199 * Creates a filesystem security structure based on the given 200 * Windows security descriptor. 201 */ 202 uint32_t 203 smb_sd_tofs(smb_sd_t *sd, smb_fssd_t *fs_sd) 204 { 205 nt_sid_t *sid; 206 uint32_t status = NT_STATUS_SUCCESS; 207 uint16_t sd_control; 208 idmap_stat idm_stat; 209 int idtype; 210 int flags = 0; 211 212 sd_control = sd->sd_control; 213 214 /* 215 * ZFS only has one set of flags so for now only 216 * Windows DACL flags are taken into account. 217 */ 218 if (sd_control & SE_DACL_DEFAULTED) 219 flags |= ACL_DEFAULTED; 220 if (sd_control & SE_DACL_AUTO_INHERITED) 221 flags |= ACL_AUTO_INHERIT; 222 if (sd_control & SE_DACL_PROTECTED) 223 flags |= ACL_PROTECTED; 224 225 if (fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR) 226 flags |= ACL_IS_DIR; 227 228 /* Owner */ 229 if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { 230 sid = sd->sd_owner; 231 if (nt_sid_is_valid(sid) == 0) { 232 return (NT_STATUS_INVALID_SID); 233 } 234 235 idtype = SMB_IDMAP_UNKNOWN; 236 idm_stat = smb_idmap_getid(sid, &fs_sd->sd_uid, &idtype); 237 if (idm_stat != IDMAP_SUCCESS) { 238 return (NT_STATUS_NONE_MAPPED); 239 } 240 } 241 242 /* Group */ 243 if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { 244 sid = sd->sd_group; 245 if (nt_sid_is_valid(sid) == 0) { 246 return (NT_STATUS_INVALID_SID); 247 } 248 249 idtype = SMB_IDMAP_UNKNOWN; 250 idm_stat = smb_idmap_getid(sid, &fs_sd->sd_gid, &idtype); 251 if (idm_stat != IDMAP_SUCCESS) { 252 return (NT_STATUS_NONE_MAPPED); 253 } 254 } 255 256 /* DACL */ 257 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { 258 if (sd->sd_control & SE_DACL_PRESENT) { 259 status = smb_acl_to_zfs(sd->sd_dacl, flags, 260 SMB_DACL_SECINFO, &fs_sd->sd_zdacl); 261 if (status != NT_STATUS_SUCCESS) 262 return (status); 263 } 264 else 265 return (NT_STATUS_INVALID_ACL); 266 } 267 268 /* SACL */ 269 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { 270 if (sd->sd_control & SE_SACL_PRESENT) { 271 status = smb_acl_to_zfs(sd->sd_sacl, flags, 272 SMB_SACL_SECINFO, &fs_sd->sd_zsacl); 273 if (status != NT_STATUS_SUCCESS) { 274 return (status); 275 } 276 } else { 277 return (NT_STATUS_INVALID_ACL); 278 } 279 } 280 281 return (status); 282 } 283 284 /* 285 * smb_sd_fromfs 286 * 287 * Makes an Windows style security descriptor in absolute form 288 * based on the given filesystem security information. 289 * 290 * Should call smb_sd_term() for the returned sd to free allocated 291 * members. 292 */ 293 static uint32_t 294 smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd) 295 { 296 uint32_t status = NT_STATUS_SUCCESS; 297 smb_acl_t *acl = NULL; 298 nt_sid_t *sid; 299 idmap_stat idm_stat; 300 301 ASSERT(fs_sd); 302 ASSERT(sd); 303 304 smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION); 305 306 /* Owner */ 307 if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { 308 idm_stat = smb_idmap_getsid(fs_sd->sd_uid, 309 SMB_IDMAP_USER, &sid); 310 311 if (idm_stat != IDMAP_SUCCESS) { 312 smb_sd_term(sd); 313 return (NT_STATUS_NONE_MAPPED); 314 } 315 316 sd->sd_owner = sid; 317 } 318 319 /* Group */ 320 if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { 321 idm_stat = smb_idmap_getsid(fs_sd->sd_gid, 322 SMB_IDMAP_GROUP, &sid); 323 324 if (idm_stat != IDMAP_SUCCESS) { 325 smb_sd_term(sd); 326 return (NT_STATUS_NONE_MAPPED); 327 } 328 329 sd->sd_group = sid; 330 } 331 332 /* DACL */ 333 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { 334 if (fs_sd->sd_zdacl != NULL) { 335 acl = smb_acl_from_zfs(fs_sd->sd_zdacl, fs_sd->sd_uid, 336 fs_sd->sd_gid); 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, fs_sd->sd_uid, 359 fs_sd->sd_gid); 360 if (acl == NULL) { 361 smb_sd_term(sd); 362 return (NT_STATUS_INTERNAL_ERROR); 363 } 364 365 smb_sd_set_sacl(sd, acl, B_TRUE, 366 fs_sd->sd_zsacl->acl_flags); 367 } else { 368 smb_sd_set_sacl(sd, NULL, B_FALSE, 0); 369 } 370 } 371 372 return (status); 373 } 374 375 static void 376 smb_sd_set_dacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags) 377 { 378 ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); 379 380 sd->sd_dacl = acl; 381 382 if (flags & ACL_DEFAULTED) 383 sd->sd_control |= SE_DACL_DEFAULTED; 384 if (flags & ACL_AUTO_INHERIT) 385 sd->sd_control |= SE_DACL_AUTO_INHERITED; 386 if (flags & ACL_PROTECTED) 387 sd->sd_control |= SE_DACL_PROTECTED; 388 389 if (present) 390 sd->sd_control |= SE_DACL_PRESENT; 391 } 392 393 static void 394 smb_sd_set_sacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags) 395 { 396 ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); 397 398 sd->sd_sacl = acl; 399 400 if (flags & ACL_DEFAULTED) 401 sd->sd_control |= SE_SACL_DEFAULTED; 402 if (flags & ACL_AUTO_INHERIT) 403 sd->sd_control |= SE_SACL_AUTO_INHERITED; 404 if (flags & ACL_PROTECTED) 405 sd->sd_control |= SE_SACL_PROTECTED; 406 407 if (present) 408 sd->sd_control |= SE_SACL_PRESENT; 409 } 410 411 /* 412 * smb_fssd_init 413 * 414 * Initializes the given FS SD structure. 415 */ 416 void 417 smb_fssd_init(smb_fssd_t *fs_sd, uint32_t secinfo, uint32_t flags) 418 { 419 bzero(fs_sd, sizeof (smb_fssd_t)); 420 fs_sd->sd_secinfo = secinfo; 421 fs_sd->sd_flags = flags; 422 } 423 424 /* 425 * smb_fssd_term 426 * 427 * Frees allocated memory for acl fields. 428 */ 429 void 430 smb_fssd_term(smb_fssd_t *fs_sd) 431 { 432 ASSERT(fs_sd); 433 434 smb_fsacl_free(fs_sd->sd_zdacl); 435 smb_fsacl_free(fs_sd->sd_zsacl); 436 bzero(fs_sd, sizeof (smb_fssd_t)); 437 } 438