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