1/* 2 Unix SMB/CIFS implementation. 3 4 security descriptror utility functions 5 6 Copyright (C) Andrew Tridgell 2004 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "libcli/security/security_descriptor.h" 24#include "libcli/security/dom_sid.h" 25 26/* 27 return a blank security descriptor (no owners, dacl or sacl) 28*/ 29struct security_descriptor *security_descriptor_initialise(TALLOC_CTX *mem_ctx) 30{ 31 struct security_descriptor *sd; 32 33 sd = talloc(mem_ctx, struct security_descriptor); 34 if (!sd) { 35 return NULL; 36 } 37 38 sd->revision = SD_REVISION; 39 /* we mark as self relative, even though it isn't while it remains 40 a pointer in memory because this simplifies the ndr code later. 41 All SDs that we store/emit are in fact SELF_RELATIVE 42 */ 43 sd->type = SEC_DESC_SELF_RELATIVE; 44 45 sd->owner_sid = NULL; 46 sd->group_sid = NULL; 47 sd->sacl = NULL; 48 sd->dacl = NULL; 49 50 return sd; 51} 52 53struct security_acl *security_acl_dup(TALLOC_CTX *mem_ctx, 54 const struct security_acl *oacl) 55{ 56 struct security_acl *nacl; 57 58 nacl = talloc (mem_ctx, struct security_acl); 59 if (nacl == NULL) { 60 return NULL; 61 } 62 63 nacl->aces = (struct security_ace *)talloc_memdup (nacl, oacl->aces, sizeof(struct security_ace) * oacl->num_aces); 64 if ((nacl->aces == NULL) && (oacl->num_aces > 0)) { 65 goto failed; 66 } 67 68 nacl->revision = oacl->revision; 69 nacl->size = oacl->size; 70 nacl->num_aces = oacl->num_aces; 71 72 return nacl; 73 74 failed: 75 talloc_free (nacl); 76 return NULL; 77 78} 79 80struct security_acl *security_acl_concatenate(TALLOC_CTX *mem_ctx, 81 const struct security_acl *acl1, 82 const struct security_acl *acl2) 83{ 84 struct security_acl *nacl; 85 int i; 86 87 if (!acl1 && !acl2) 88 return NULL; 89 90 if (!acl1){ 91 nacl = security_acl_dup(mem_ctx, acl2); 92 return nacl; 93 } 94 95 if (!acl2){ 96 nacl = security_acl_dup(mem_ctx, acl1); 97 return nacl; 98 } 99 100 nacl = talloc (mem_ctx, struct security_acl); 101 if (nacl == NULL) { 102 return NULL; 103 } 104 105 nacl->revision = acl1->revision; 106 nacl->size = acl1->size + acl2->size; 107 nacl->num_aces = acl1->num_aces + acl2->num_aces; 108 109 if (nacl->num_aces == 0) 110 return nacl; 111 112 nacl->aces = (struct security_ace *)talloc_array (mem_ctx, struct security_ace, acl1->num_aces+acl2->num_aces); 113 if ((nacl->aces == NULL) && (nacl->num_aces > 0)) { 114 goto failed; 115 } 116 117 for (i = 0; i < acl1->num_aces; i++) 118 nacl->aces[i] = acl1->aces[i]; 119 for (i = 0; i < acl2->num_aces; i++) 120 nacl->aces[i + acl1->num_aces] = acl2->aces[i]; 121 122 return nacl; 123 124 failed: 125 talloc_free (nacl); 126 return NULL; 127 128} 129 130/* 131 talloc and copy a security descriptor 132 */ 133struct security_descriptor *security_descriptor_copy(TALLOC_CTX *mem_ctx, 134 const struct security_descriptor *osd) 135{ 136 struct security_descriptor *nsd; 137 138 nsd = talloc_zero(mem_ctx, struct security_descriptor); 139 if (!nsd) { 140 return NULL; 141 } 142 143 if (osd->owner_sid) { 144 nsd->owner_sid = dom_sid_dup(nsd, osd->owner_sid); 145 if (nsd->owner_sid == NULL) { 146 goto failed; 147 } 148 } 149 150 if (osd->group_sid) { 151 nsd->group_sid = dom_sid_dup(nsd, osd->group_sid); 152 if (nsd->group_sid == NULL) { 153 goto failed; 154 } 155 } 156 157 if (osd->sacl) { 158 nsd->sacl = security_acl_dup(nsd, osd->sacl); 159 if (nsd->sacl == NULL) { 160 goto failed; 161 } 162 } 163 164 if (osd->dacl) { 165 nsd->dacl = security_acl_dup(nsd, osd->dacl); 166 if (nsd->dacl == NULL) { 167 goto failed; 168 } 169 } 170 171 nsd->revision = osd->revision; 172 nsd->type = osd->type; 173 174 return nsd; 175 176 failed: 177 talloc_free(nsd); 178 179 return NULL; 180} 181 182/* 183 add an ACE to an ACL of a security_descriptor 184*/ 185 186static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd, 187 bool add_to_sacl, 188 const struct security_ace *ace) 189{ 190 struct security_acl *acl = NULL; 191 192 if (add_to_sacl) { 193 acl = sd->sacl; 194 } else { 195 acl = sd->dacl; 196 } 197 198 if (acl == NULL) { 199 acl = talloc(sd, struct security_acl); 200 if (acl == NULL) { 201 return NT_STATUS_NO_MEMORY; 202 } 203 acl->revision = SECURITY_ACL_REVISION_NT4; 204 acl->size = 0; 205 acl->num_aces = 0; 206 acl->aces = NULL; 207 } 208 209 acl->aces = talloc_realloc(acl, acl->aces, 210 struct security_ace, acl->num_aces+1); 211 if (acl->aces == NULL) { 212 return NT_STATUS_NO_MEMORY; 213 } 214 215 acl->aces[acl->num_aces] = *ace; 216 217 switch (acl->aces[acl->num_aces].type) { 218 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: 219 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: 220 case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: 221 case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: 222 acl->revision = SECURITY_ACL_REVISION_ADS; 223 break; 224 default: 225 break; 226 } 227 228 acl->num_aces++; 229 230 if (add_to_sacl) { 231 sd->sacl = acl; 232 sd->type |= SEC_DESC_SACL_PRESENT; 233 } else { 234 sd->dacl = acl; 235 sd->type |= SEC_DESC_DACL_PRESENT; 236 } 237 238 return NT_STATUS_OK; 239} 240 241/* 242 add an ACE to the SACL of a security_descriptor 243*/ 244 245NTSTATUS security_descriptor_sacl_add(struct security_descriptor *sd, 246 const struct security_ace *ace) 247{ 248 return security_descriptor_acl_add(sd, true, ace); 249} 250 251/* 252 add an ACE to the DACL of a security_descriptor 253*/ 254 255NTSTATUS security_descriptor_dacl_add(struct security_descriptor *sd, 256 const struct security_ace *ace) 257{ 258 return security_descriptor_acl_add(sd, false, ace); 259} 260 261/* 262 delete the ACE corresponding to the given trustee in an ACL of a 263 security_descriptor 264*/ 265 266static NTSTATUS security_descriptor_acl_del(struct security_descriptor *sd, 267 bool sacl_del, 268 const struct dom_sid *trustee) 269{ 270 int i; 271 bool found = false; 272 struct security_acl *acl = NULL; 273 274 if (sacl_del) { 275 acl = sd->sacl; 276 } else { 277 acl = sd->dacl; 278 } 279 280 if (acl == NULL) { 281 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 282 } 283 284 /* there can be multiple ace's for one trustee */ 285 for (i=0;i<acl->num_aces;i++) { 286 if (dom_sid_equal(trustee, &acl->aces[i].trustee)) { 287 memmove(&acl->aces[i], &acl->aces[i+1], 288 sizeof(acl->aces[i]) * (acl->num_aces - (i+1))); 289 acl->num_aces--; 290 if (acl->num_aces == 0) { 291 acl->aces = NULL; 292 } 293 found = true; 294 } 295 } 296 297 if (!found) { 298 return NT_STATUS_OBJECT_NAME_NOT_FOUND; 299 } 300 301 acl->revision = SECURITY_ACL_REVISION_NT4; 302 303 for (i=0;i<acl->num_aces;i++) { 304 switch (acl->aces[i].type) { 305 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: 306 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: 307 case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: 308 case SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT: 309 acl->revision = SECURITY_ACL_REVISION_ADS; 310 return NT_STATUS_OK; 311 default: 312 break; /* only for the switch statement */ 313 } 314 } 315 316 return NT_STATUS_OK; 317} 318 319/* 320 delete the ACE corresponding to the given trustee in the DACL of a 321 security_descriptor 322*/ 323 324NTSTATUS security_descriptor_dacl_del(struct security_descriptor *sd, 325 const struct dom_sid *trustee) 326{ 327 return security_descriptor_acl_del(sd, false, trustee); 328} 329 330/* 331 delete the ACE corresponding to the given trustee in the SACL of a 332 security_descriptor 333*/ 334 335NTSTATUS security_descriptor_sacl_del(struct security_descriptor *sd, 336 const struct dom_sid *trustee) 337{ 338 return security_descriptor_acl_del(sd, true, trustee); 339} 340 341/* 342 compare two security ace structures 343*/ 344bool security_ace_equal(const struct security_ace *ace1, 345 const struct security_ace *ace2) 346{ 347 if (ace1 == ace2) return true; 348 if (!ace1 || !ace2) return false; 349 if (ace1->type != ace2->type) return false; 350 if (ace1->flags != ace2->flags) return false; 351 if (ace1->access_mask != ace2->access_mask) return false; 352 if (!dom_sid_equal(&ace1->trustee, &ace2->trustee)) return false; 353 354 return true; 355} 356 357 358/* 359 compare two security acl structures 360*/ 361bool security_acl_equal(const struct security_acl *acl1, 362 const struct security_acl *acl2) 363{ 364 int i; 365 366 if (acl1 == acl2) return true; 367 if (!acl1 || !acl2) return false; 368 if (acl1->revision != acl2->revision) return false; 369 if (acl1->num_aces != acl2->num_aces) return false; 370 371 for (i=0;i<acl1->num_aces;i++) { 372 if (!security_ace_equal(&acl1->aces[i], &acl2->aces[i])) return false; 373 } 374 return true; 375} 376 377/* 378 compare two security descriptors. 379*/ 380bool security_descriptor_equal(const struct security_descriptor *sd1, 381 const struct security_descriptor *sd2) 382{ 383 if (sd1 == sd2) return true; 384 if (!sd1 || !sd2) return false; 385 if (sd1->revision != sd2->revision) return false; 386 if (sd1->type != sd2->type) return false; 387 388 if (!dom_sid_equal(sd1->owner_sid, sd2->owner_sid)) return false; 389 if (!dom_sid_equal(sd1->group_sid, sd2->group_sid)) return false; 390 if (!security_acl_equal(sd1->sacl, sd2->sacl)) return false; 391 if (!security_acl_equal(sd1->dacl, sd2->dacl)) return false; 392 393 return true; 394} 395 396/* 397 compare two security descriptors, but allow certain (missing) parts 398 to be masked out of the comparison 399*/ 400bool security_descriptor_mask_equal(const struct security_descriptor *sd1, 401 const struct security_descriptor *sd2, 402 uint32_t mask) 403{ 404 if (sd1 == sd2) return true; 405 if (!sd1 || !sd2) return false; 406 if (sd1->revision != sd2->revision) return false; 407 if ((sd1->type & mask) != (sd2->type & mask)) return false; 408 409 if (!dom_sid_equal(sd1->owner_sid, sd2->owner_sid)) return false; 410 if (!dom_sid_equal(sd1->group_sid, sd2->group_sid)) return false; 411 if ((mask & SEC_DESC_DACL_PRESENT) && !security_acl_equal(sd1->dacl, sd2->dacl)) return false; 412 if ((mask & SEC_DESC_SACL_PRESENT) && !security_acl_equal(sd1->sacl, sd2->sacl)) return false; 413 414 return true; 415} 416 417 418static struct security_descriptor *security_descriptor_appendv(struct security_descriptor *sd, 419 bool add_ace_to_sacl, 420 va_list ap) 421{ 422 const char *sidstr; 423 424 while ((sidstr = va_arg(ap, const char *))) { 425 struct dom_sid *sid; 426 struct security_ace *ace = talloc_zero(sd, struct security_ace); 427 NTSTATUS status; 428 429 if (ace == NULL) { 430 talloc_free(sd); 431 return NULL; 432 } 433 ace->type = va_arg(ap, unsigned int); 434 ace->access_mask = va_arg(ap, unsigned int); 435 ace->flags = va_arg(ap, unsigned int); 436 sid = dom_sid_parse_talloc(ace, sidstr); 437 if (sid == NULL) { 438 talloc_free(sd); 439 return NULL; 440 } 441 ace->trustee = *sid; 442 if (add_ace_to_sacl) { 443 status = security_descriptor_sacl_add(sd, ace); 444 } else { 445 status = security_descriptor_dacl_add(sd, ace); 446 } 447 /* TODO: check: would talloc_free(ace) here be correct? */ 448 if (!NT_STATUS_IS_OK(status)) { 449 talloc_free(sd); 450 return NULL; 451 } 452 } 453 454 return sd; 455} 456 457struct security_descriptor *security_descriptor_append(struct security_descriptor *sd, 458 ...) 459{ 460 va_list ap; 461 462 va_start(ap, sd); 463 sd = security_descriptor_appendv(sd, false, ap); 464 va_end(ap); 465 466 return sd; 467} 468 469static struct security_descriptor *security_descriptor_createv(TALLOC_CTX *mem_ctx, 470 uint16_t sd_type, 471 const char *owner_sid, 472 const char *group_sid, 473 bool add_ace_to_sacl, 474 va_list ap) 475{ 476 struct security_descriptor *sd; 477 478 sd = security_descriptor_initialise(mem_ctx); 479 if (sd == NULL) { 480 return NULL; 481 } 482 483 sd->type |= sd_type; 484 485 if (owner_sid) { 486 sd->owner_sid = dom_sid_parse_talloc(sd, owner_sid); 487 if (sd->owner_sid == NULL) { 488 talloc_free(sd); 489 return NULL; 490 } 491 } 492 if (group_sid) { 493 sd->group_sid = dom_sid_parse_talloc(sd, group_sid); 494 if (sd->group_sid == NULL) { 495 talloc_free(sd); 496 return NULL; 497 } 498 } 499 500 return security_descriptor_appendv(sd, add_ace_to_sacl, ap); 501} 502 503/* 504 create a security descriptor using string SIDs. This is used by the 505 torture code to allow the easy creation of complex ACLs 506 This is a varargs function. The list of DACL ACEs ends with a NULL sid. 507 508 Each ACE contains a set of 4 parameters: 509 SID, ACCESS_TYPE, MASK, FLAGS 510 511 a typical call would be: 512 513 sd = security_descriptor_dacl_create(mem_ctx, 514 sd_type_flags, 515 mysid, 516 mygroup, 517 SID_NT_AUTHENTICATED_USERS, 518 SEC_ACE_TYPE_ACCESS_ALLOWED, 519 SEC_FILE_ALL, 520 SEC_ACE_FLAG_OBJECT_INHERIT, 521 NULL); 522 that would create a sd with one DACL ACE 523*/ 524 525struct security_descriptor *security_descriptor_dacl_create(TALLOC_CTX *mem_ctx, 526 uint16_t sd_type, 527 const char *owner_sid, 528 const char *group_sid, 529 ...) 530{ 531 struct security_descriptor *sd = NULL; 532 va_list ap; 533 va_start(ap, group_sid); 534 sd = security_descriptor_createv(mem_ctx, sd_type, owner_sid, 535 group_sid, false, ap); 536 va_end(ap); 537 538 return sd; 539} 540 541struct security_descriptor *security_descriptor_sacl_create(TALLOC_CTX *mem_ctx, 542 uint16_t sd_type, 543 const char *owner_sid, 544 const char *group_sid, 545 ...) 546{ 547 struct security_descriptor *sd = NULL; 548 va_list ap; 549 va_start(ap, group_sid); 550 sd = security_descriptor_createv(mem_ctx, sd_type, owner_sid, 551 group_sid, true, ap); 552 va_end(ap); 553 554 return sd; 555} 556 557struct security_ace *security_ace_create(TALLOC_CTX *mem_ctx, 558 const char *sid_str, 559 enum security_ace_type type, 560 uint32_t access_mask, 561 uint8_t flags) 562 563{ 564 struct dom_sid *sid; 565 struct security_ace *ace; 566 567 ace = talloc_zero(mem_ctx, struct security_ace); 568 if (ace == NULL) { 569 return NULL; 570 } 571 572 sid = dom_sid_parse_talloc(ace, sid_str); 573 if (sid == NULL) { 574 talloc_free(ace); 575 return NULL; 576 } 577 578 ace->trustee = *sid; 579 ace->type = type; 580 ace->access_mask = access_mask; 581 ace->flags = flags; 582 583 return ace; 584} 585