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