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 2009 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 34 static void smb_sd_set_sacl(smb_sd_t *, smb_acl_t *, boolean_t, int); 35 static void smb_sd_set_dacl(smb_sd_t *, smb_acl_t *, boolean_t, int); 36 static uint32_t smb_sd_fromfs(smb_fssd_t *, smb_sd_t *); 37 38 void 39 smb_sd_init(smb_sd_t *sd, uint8_t revision) 40 { 41 bzero(sd, sizeof (smb_sd_t)); 42 sd->sd_revision = revision; 43 } 44 45 /* 46 * smb_sd_term 47 * 48 * Free non-NULL members of 'sd' which has to be in 49 * absolute (pointer) form. 50 */ 51 void 52 smb_sd_term(smb_sd_t *sd) 53 { 54 ASSERT(sd); 55 ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); 56 57 smb_sid_free(sd->sd_owner); 58 smb_sid_free(sd->sd_group); 59 smb_acl_free(sd->sd_dacl); 60 smb_acl_free(sd->sd_sacl); 61 62 bzero(sd, sizeof (smb_sd_t)); 63 } 64 65 uint32_t 66 smb_sd_len(smb_sd_t *sd, uint32_t secinfo) 67 { 68 uint32_t length = SMB_SD_HDRSIZE; 69 70 if (secinfo & SMB_OWNER_SECINFO) 71 length += smb_sid_len(sd->sd_owner); 72 73 if (secinfo & SMB_GROUP_SECINFO) 74 length += smb_sid_len(sd->sd_group); 75 76 if (secinfo & SMB_DACL_SECINFO) 77 length += smb_acl_len(sd->sd_dacl); 78 79 if (secinfo & SMB_SACL_SECINFO) 80 length += smb_acl_len(sd->sd_sacl); 81 82 return (length); 83 } 84 85 /* 86 * smb_sd_get_secinfo 87 * 88 * Return the security information mask for the specified security 89 * descriptor. 90 */ 91 uint32_t 92 smb_sd_get_secinfo(smb_sd_t *sd) 93 { 94 uint32_t sec_info = 0; 95 96 if (sd == NULL) 97 return (0); 98 99 if (sd->sd_owner) 100 sec_info |= SMB_OWNER_SECINFO; 101 102 if (sd->sd_group) 103 sec_info |= SMB_GROUP_SECINFO; 104 105 if (sd->sd_dacl) 106 sec_info |= SMB_DACL_SECINFO; 107 108 if (sd->sd_sacl) 109 sec_info |= SMB_SACL_SECINFO; 110 111 return (sec_info); 112 } 113 114 /* 115 * smb_sd_read 116 * 117 * Read uid, gid and ACL from filesystem. The returned ACL from read 118 * routine is always in ZFS format. Convert the ZFS acl to a Win acl 119 * and return the Win SD in absolute form. 120 * 121 * NOTE: upon successful return caller MUST free the memory allocated 122 * for the returned SD by calling smb_sd_term(). 123 */ 124 uint32_t 125 smb_sd_read(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) 126 { 127 smb_fssd_t fs_sd; 128 smb_error_t smb_err; 129 smb_node_t *node; 130 uint32_t status = NT_STATUS_SUCCESS; 131 uint32_t sd_flags; 132 int error; 133 134 node = sr->fid_ofile->f_node; 135 sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0; 136 smb_fssd_init(&fs_sd, secinfo, sd_flags); 137 138 error = smb_fsop_sdread(sr, sr->user_cr, node, &fs_sd); 139 if (error) { 140 smbsr_map_errno(error, &smb_err); 141 return (smb_err.status); 142 } 143 144 status = smb_sd_fromfs(&fs_sd, sd); 145 smb_fssd_term(&fs_sd); 146 147 return (status); 148 } 149 150 /* 151 * smb_sd_write 152 * 153 * Takes a Win SD in absolute form, converts it to 154 * ZFS format and write it to filesystem. The write routine 155 * converts ZFS acl to Posix acl if required. 156 */ 157 uint32_t 158 smb_sd_write(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) 159 { 160 smb_node_t *node; 161 smb_fssd_t fs_sd; 162 smb_error_t smb_err; 163 uint32_t status; 164 uint32_t sd_flags; 165 int error; 166 167 node = sr->fid_ofile->f_node; 168 sd_flags = (node->vp->v_type == VDIR) ? SMB_FSSD_FLAGS_DIR : 0; 169 smb_fssd_init(&fs_sd, secinfo, sd_flags); 170 171 status = smb_sd_tofs(sd, &fs_sd); 172 if (status != NT_STATUS_SUCCESS) { 173 smb_fssd_term(&fs_sd); 174 return (status); 175 } 176 177 error = smb_fsop_sdwrite(sr, sr->user_cr, node, &fs_sd, 0); 178 smb_fssd_term(&fs_sd); 179 180 if (error) { 181 if (error == EBADE) 182 return (NT_STATUS_INVALID_OWNER); 183 smbsr_map_errno(error, &smb_err); 184 return (smb_err.status); 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 /* DACL */ 250 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { 251 if (sd->sd_control & SE_DACL_PRESENT) { 252 status = smb_acl_to_zfs(sd->sd_dacl, flags, 253 SMB_DACL_SECINFO, &fs_sd->sd_zdacl); 254 if (status != NT_STATUS_SUCCESS) 255 return (status); 256 } 257 else 258 return (NT_STATUS_INVALID_ACL); 259 } 260 261 /* SACL */ 262 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { 263 if (sd->sd_control & SE_SACL_PRESENT) { 264 status = smb_acl_to_zfs(sd->sd_sacl, flags, 265 SMB_SACL_SECINFO, &fs_sd->sd_zsacl); 266 if (status != NT_STATUS_SUCCESS) { 267 return (status); 268 } 269 } else { 270 return (NT_STATUS_INVALID_ACL); 271 } 272 } 273 274 return (status); 275 } 276 277 /* 278 * smb_sd_fromfs 279 * 280 * Makes an Windows style security descriptor in absolute form 281 * based on the given filesystem security information. 282 * 283 * Should call smb_sd_term() for the returned sd to free allocated 284 * members. 285 */ 286 static uint32_t 287 smb_sd_fromfs(smb_fssd_t *fs_sd, smb_sd_t *sd) 288 { 289 uint32_t status = NT_STATUS_SUCCESS; 290 smb_acl_t *acl = NULL; 291 smb_sid_t *sid; 292 idmap_stat idm_stat; 293 294 ASSERT(fs_sd); 295 ASSERT(sd); 296 297 smb_sd_init(sd, SECURITY_DESCRIPTOR_REVISION); 298 299 /* Owner */ 300 if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { 301 idm_stat = smb_idmap_getsid(fs_sd->sd_uid, 302 SMB_IDMAP_USER, &sid); 303 304 if (idm_stat != IDMAP_SUCCESS) { 305 smb_sd_term(sd); 306 return (NT_STATUS_NONE_MAPPED); 307 } 308 309 sd->sd_owner = sid; 310 } 311 312 /* Group */ 313 if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { 314 idm_stat = smb_idmap_getsid(fs_sd->sd_gid, 315 SMB_IDMAP_GROUP, &sid); 316 317 if (idm_stat != IDMAP_SUCCESS) { 318 smb_sd_term(sd); 319 return (NT_STATUS_NONE_MAPPED); 320 } 321 322 sd->sd_group = sid; 323 } 324 325 /* DACL */ 326 if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { 327 if (fs_sd->sd_zdacl != NULL) { 328 acl = smb_acl_from_zfs(fs_sd->sd_zdacl, fs_sd->sd_uid, 329 fs_sd->sd_gid); 330 if (acl == NULL) { 331 smb_sd_term(sd); 332 return (NT_STATUS_INTERNAL_ERROR); 333 } 334 335 /* 336 * Need to sort the ACL before send it to Windows 337 * clients. Winodws GUI is sensitive about the order 338 * of ACEs. 339 */ 340 smb_acl_sort(acl); 341 smb_sd_set_dacl(sd, acl, B_TRUE, 342 fs_sd->sd_zdacl->acl_flags); 343 } else { 344 smb_sd_set_dacl(sd, NULL, B_FALSE, 0); 345 } 346 } 347 348 /* SACL */ 349 if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { 350 if (fs_sd->sd_zsacl != NULL) { 351 acl = smb_acl_from_zfs(fs_sd->sd_zsacl, fs_sd->sd_uid, 352 fs_sd->sd_gid); 353 if (acl == NULL) { 354 smb_sd_term(sd); 355 return (NT_STATUS_INTERNAL_ERROR); 356 } 357 358 smb_sd_set_sacl(sd, acl, B_TRUE, 359 fs_sd->sd_zsacl->acl_flags); 360 } else { 361 smb_sd_set_sacl(sd, NULL, B_FALSE, 0); 362 } 363 } 364 365 return (status); 366 } 367 368 static void 369 smb_sd_set_dacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags) 370 { 371 ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); 372 373 sd->sd_dacl = acl; 374 375 if (flags & ACL_DEFAULTED) 376 sd->sd_control |= SE_DACL_DEFAULTED; 377 if (flags & ACL_AUTO_INHERIT) 378 sd->sd_control |= SE_DACL_AUTO_INHERITED; 379 if (flags & ACL_PROTECTED) 380 sd->sd_control |= SE_DACL_PROTECTED; 381 382 if (present) 383 sd->sd_control |= SE_DACL_PRESENT; 384 } 385 386 static void 387 smb_sd_set_sacl(smb_sd_t *sd, smb_acl_t *acl, boolean_t present, int flags) 388 { 389 ASSERT((sd->sd_control & SE_SELF_RELATIVE) == 0); 390 391 sd->sd_sacl = acl; 392 393 if (flags & ACL_DEFAULTED) 394 sd->sd_control |= SE_SACL_DEFAULTED; 395 if (flags & ACL_AUTO_INHERIT) 396 sd->sd_control |= SE_SACL_AUTO_INHERITED; 397 if (flags & ACL_PROTECTED) 398 sd->sd_control |= SE_SACL_PROTECTED; 399 400 if (present) 401 sd->sd_control |= SE_SACL_PRESENT; 402 } 403 404 /* 405 * smb_fssd_init 406 * 407 * Initializes the given FS SD structure. 408 */ 409 void 410 smb_fssd_init(smb_fssd_t *fs_sd, uint32_t secinfo, uint32_t flags) 411 { 412 bzero(fs_sd, sizeof (smb_fssd_t)); 413 fs_sd->sd_secinfo = secinfo; 414 fs_sd->sd_flags = flags; 415 } 416 417 /* 418 * smb_fssd_term 419 * 420 * Frees allocated memory for acl fields. 421 */ 422 void 423 smb_fssd_term(smb_fssd_t *fs_sd) 424 { 425 ASSERT(fs_sd); 426 427 smb_fsacl_free(fs_sd->sd_zdacl); 428 smb_fsacl_free(fs_sd->sd_zsacl); 429 bzero(fs_sd, sizeof (smb_fssd_t)); 430 } 431