Ejemplo n.º 1
0
SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, size_t *psize, uint32 def_access)
{
	uint32_t sa;
	SEC_ACE ace;
	SEC_ACL *psa = NULL;
	SEC_DESC *psd = NULL;
	uint32 spec_access = def_access;

	se_map_generic(&spec_access, &file_generic_mapping);

	sa = (def_access | spec_access );
	init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0);

	if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &ace)) != NULL) {
		psd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
				    SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
				    psa, psize);
	}

	if (!psd) {
		DEBUG(0,("get_share_security: Failed to make SEC_DESC.\n"));
		return NULL;
	}

	return psd;
}
Ejemplo n.º 2
0
void str_to_ace(SEC_ACE *ace, char *ace_str)
{
	SEC_ACCESS sa;
	struct dom_sid sid;
	uint32 mask;
	uint8 type, flags;

	init_sec_access(&sa, mask);
	init_sec_ace(ace, &sid, type, sa, flags);
}
Ejemplo n.º 3
0
struct security_descriptor* svcctl_gen_service_sd(TALLOC_CTX *mem_ctx)
{
	struct security_descriptor *sd = NULL;
	struct security_acl *theacl = NULL;
	struct security_ace ace[4];
	size_t sd_size;
	size_t i = 0;

	/* Basic access for everyone */
	init_sec_ace(&ace[i++], &global_sid_World,
		SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_READ_ACCESS, 0);

	init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users,
			SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_EXECUTE_ACCESS, 0);

	init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators,
		SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_ALL_ACCESS, 0);
	init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
		SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_ALL_ACCESS, 0);

	/* Create the security descriptor */
	theacl = make_sec_acl(mem_ctx,
			      NT4_ACL_REVISION,
			      i,
			      ace);
	if (theacl == NULL) {
		return NULL;
	}

	sd = make_sec_desc(mem_ctx,
			   SECURITY_DESCRIPTOR_REVISION_1,
			   SEC_DESC_SELF_RELATIVE,
			   NULL,
			   NULL,
			   NULL,
			   theacl,
			   &sd_size);
	if (sd == NULL) {
		return NULL;
	}

	return sd;
}
Ejemplo n.º 4
0
static WERROR construct_registry_sd(TALLOC_CTX *ctx, struct security_descriptor **psd)
{
	struct security_ace ace[3];
	size_t i = 0;
	struct security_descriptor *sd;
	struct security_acl *theacl;
	size_t sd_size;

	/* basic access for Everyone */

	init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
		     REG_KEY_READ, 0);

	/* Full Access 'BUILTIN\Administrators' */

	init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
		     SEC_ACE_TYPE_ACCESS_ALLOWED, REG_KEY_ALL, 0);

	/* Full Access 'NT Authority\System' */

	init_sec_ace(&ace[i++], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED,
		     REG_KEY_ALL, 0);

	/* create the security descriptor */

	theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace);
	if (theacl == NULL) {
		return WERR_NOMEM;
	}

	sd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
			   &global_sid_Builtin_Administrators,
			   &global_sid_System, NULL, theacl,
			   &sd_size);
	if (sd == NULL) {
		return WERR_NOMEM;
	}

	*psd = sd;
	return WERR_OK;
}
Ejemplo n.º 5
0
static struct security_descriptor *default_file_sd(TALLOC_CTX *mem_ctx,
						SMB_STRUCT_STAT *psbuf)
{
	struct dom_sid owner_sid, group_sid;
	size_t sd_size;
	struct security_ace *pace = NULL;
	struct security_acl *pacl = NULL;

	uid_to_sid(&owner_sid, psbuf->st_uid);
	gid_to_sid(&group_sid, psbuf->st_gid);

	pace = TALLOC_ARRAY(mem_ctx, struct security_ace, 2);
	if (!pace) {
		return NULL;
	}

	init_sec_ace(&pace[0], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
			SEC_RIGHTS_FILE_ALL, 0);
	init_sec_ace(&pace[1], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED,
			SEC_RIGHTS_FILE_ALL, 0);

	pacl = make_sec_acl(mem_ctx,
				NT4_ACL_REVISION,
				2,
				pace);
	if (!pacl) {
		return NULL;
	}
	return make_sec_desc(mem_ctx,
			SECURITY_DESCRIPTOR_REVISION_1,
			SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
			&owner_sid,
			&group_sid,
			NULL,
                        pacl,
			&sd_size);
}
Ejemplo n.º 6
0
SEC_ACL *build_acl(struct ace_entry *ace_list)
{
	SEC_ACE *aces = NULL;
	SEC_ACL *result;
	int num_aces = 0;

	if (ace_list == NULL) return NULL;

	/* Create aces */

	while(ace_list->sid) {
		SEC_ACCESS sa;
		struct dom_sid sid;

		/* Create memory for new ACE */

		if (!(aces = Realloc(aces, 
				     sizeof(SEC_ACE) * (num_aces + 1)))) {
			return NULL;
		}

		/* Create ace */

		init_sec_access(&sa, ace_list->mask);

		char_to_sid(&sid, ace_list->sid);
		init_sec_ace(&aces[num_aces], &sid, ace_list->type,
			     sa, ace_list->flags);

		num_aces++;
		ace_list++;
	}

	/* Create ACL from list of ACEs */

	result = make_sec_acl(ACL_REVISION, num_aces, aces);
	free(aces);

	return result;
}
Ejemplo n.º 7
0
/* parse an ACE in the same format as print_ace() */
static BOOL parse_ace(SEC_ACE *ace, char *str)
{
	char *p;
	const char *cp;
	fstring tok;
	unsigned atype, aflags, amask;
	DOM_SID sid;
	SEC_ACCESS mask;
	struct perm_value *v;

	ZERO_STRUCTP(ace);
	p = strchr(str,':');
	if (!p) return False;
	*p = '\0';
	p++;

	/* Try to parse numeric form */

	if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 &&
	    StringToSid(&sid, str)) {
		goto done;
	}

	/* Try to parse text form */

	if (!StringToSid(&sid, str)) {
		return False;
	}

	cp = p;
	if (!next_token(&cp, tok, "/", sizeof(fstring))) {
		return False;
	}

	if (strncmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
		atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
	} else if (strncmp(tok, "DENIED", strlen("DENIED")) == 0) {
		atype = SEC_ACE_TYPE_ACCESS_DENIED;
	} else {
		return False;
	}

	/* Only numeric form accepted for flags at present */

	if (!(next_token(&cp, tok, "/", sizeof(fstring)) &&
	      sscanf(tok, "%i", &aflags))) {
		return False;
	}

	if (!next_token(&cp, tok, "/", sizeof(fstring))) {
		return False;
	}

	if (strncmp(tok, "0x", 2) == 0) {
		if (sscanf(tok, "%i", &amask) != 1) {
			return False;
		}
		goto done;
	}

	for (v = standard_values; v->perm; v++) {
		if (strcmp(tok, v->perm) == 0) {
			amask = v->mask;
			goto done;
		}
	}

	p = tok;

	while(*p) {
		BOOL found = False;

		for (v = special_values; v->perm; v++) {
			if (v->perm[0] == *p) {
				amask |= v->mask;
				found = True;
			}
		}

		if (!found) return False;
		p++;
	}

	if (*p) {
		return False;
	}

 done:
	mask.mask = amask;
	init_sec_ace(ace, &sid, atype, mask, aflags);
	return True;
}
Ejemplo n.º 8
0
static void add_directory_inheritable_components(vfs_handle_struct *handle,
                                const char *name,
				SMB_STRUCT_STAT *psbuf,
				struct security_descriptor *psd)
{
	struct connection_struct *conn = handle->conn;
	int num_aces = (psd->dacl ? psd->dacl->num_aces : 0);
	struct smb_filename smb_fname;
	enum security_ace_type acltype;
	uint32_t access_mask;
	mode_t dir_mode;
	mode_t file_mode;
	mode_t mode;
	struct security_ace *new_ace_list = TALLOC_ZERO_ARRAY(talloc_tos(),
						struct security_ace,
						num_aces + 3);

	if (new_ace_list == NULL) {
		return;
	}

	/* Fake a quick smb_filename. */
	ZERO_STRUCT(smb_fname);
	smb_fname.st = *psbuf;
	smb_fname.base_name = CONST_DISCARD(char *, name);

	dir_mode = unix_mode(conn,
			FILE_ATTRIBUTE_DIRECTORY, &smb_fname, NULL);
	file_mode = unix_mode(conn,
			FILE_ATTRIBUTE_ARCHIVE, &smb_fname, NULL);

	mode = dir_mode | file_mode;

	DEBUG(10, ("add_directory_inheritable_components: directory %s, "
		"mode = 0%o\n",
		name,
		(unsigned int)mode ));

	if (num_aces) {
		memcpy(new_ace_list, psd->dacl->aces,
			num_aces * sizeof(struct security_ace));
	}
	access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
				mode & 0700, false);

	init_sec_ace(&new_ace_list[num_aces],
			&global_sid_Creator_Owner,
			acltype,
			access_mask,
			SEC_ACE_FLAG_CONTAINER_INHERIT|
				SEC_ACE_FLAG_OBJECT_INHERIT|
				SEC_ACE_FLAG_INHERIT_ONLY);
	access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
				(mode << 3) & 0700, false);
	init_sec_ace(&new_ace_list[num_aces+1],
			&global_sid_Creator_Group,
			acltype,
			access_mask,
			SEC_ACE_FLAG_CONTAINER_INHERIT|
				SEC_ACE_FLAG_OBJECT_INHERIT|
				SEC_ACE_FLAG_INHERIT_ONLY);
	access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
				(mode << 6) & 0700, false);
	init_sec_ace(&new_ace_list[num_aces+2],
			&global_sid_World,
			acltype,
			access_mask,
			SEC_ACE_FLAG_CONTAINER_INHERIT|
				SEC_ACE_FLAG_OBJECT_INHERIT|
				SEC_ACE_FLAG_INHERIT_ONLY);
	psd->dacl->aces = new_ace_list;
	psd->dacl->num_aces += 3;
}
Ejemplo n.º 9
0
BOOL parse_usershare_acl(TALLOC_CTX *ctx, const char *acl_str, SEC_DESC **ppsd)
{
	size_t s_size = 0;
	const char *pacl = acl_str;
	int num_aces = 0;
	SEC_ACE *ace_list = NULL;
	SEC_ACL *psa = NULL;
	SEC_DESC *psd = NULL;
	size_t sd_size = 0;
	int i;

	*ppsd = NULL;

	/* If the acl string is blank return "Everyone:R" */
	if (!*acl_str) {
		SEC_DESC *default_psd = get_share_security_default(ctx, &s_size, GENERIC_READ_ACCESS);
		if (!default_psd) {
			return False;
		}
		*ppsd = default_psd;
		return True;
	}

	num_aces = 1;

	/* Add the number of ',' characters to get the number of aces. */
	num_aces += count_chars(pacl,',');

	ace_list = TALLOC_ARRAY(ctx, SEC_ACE, num_aces);
	if (!ace_list) {
		return False;
	}

	for (i = 0; i < num_aces; i++) {
		SEC_ACCESS sa;
		uint32 g_access;
		uint32 s_access;
		DOM_SID sid;
		fstring sidstr;
		uint8 type = SEC_ACE_TYPE_ACCESS_ALLOWED;

		if (!next_token(&pacl, sidstr, ":", sizeof(sidstr))) {
			DEBUG(0,("parse_usershare_acl: malformed usershare acl looking "
				"for ':' in string '%s'\n", pacl));
			return False;
		}

		if (!string_to_sid(&sid, sidstr)) {
			DEBUG(0,("parse_usershare_acl: failed to convert %s to sid.\n",
				sidstr ));
			return False;
		}

		switch (*pacl) {
			case 'F': /* Full Control, ie. R+W */
			case 'f': /* Full Control, ie. R+W */
				s_access = g_access = GENERIC_ALL_ACCESS;
				break;
			case 'R': /* Read only. */
			case 'r': /* Read only. */
				s_access = g_access = GENERIC_READ_ACCESS;
				break;
			case 'D': /* Deny all to this SID. */
			case 'd': /* Deny all to this SID. */
				type = SEC_ACE_TYPE_ACCESS_DENIED;
				s_access = g_access = GENERIC_ALL_ACCESS;
				break;
			default:
				DEBUG(0,("parse_usershare_acl: unknown acl type at %s.\n",
					pacl ));
				return False;
		}

		pacl++;
		if (*pacl && *pacl != ',') {
			DEBUG(0,("parse_usershare_acl: bad acl string at %s.\n",
				pacl ));
			return False;
		}
		pacl++; /* Go past any ',' */

		se_map_generic(&s_access, &file_generic_mapping);
		init_sec_access(&sa, g_access | s_access );
		init_sec_ace(&ace_list[i], &sid, type, sa, 0);
	}

	if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, num_aces, ace_list)) != NULL) {
		psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, &sd_size);
	}

	if (!psd) {
		DEBUG(0,("parse_usershare_acl: Failed to make SEC_DESC.\n"));
		return False;
	}

	*ppsd = psd;
	return True;
}
Ejemplo n.º 10
0
int psec_setsec(char *printer)
{
	DOM_SID user_sid, group_sid;
	SEC_ACE *ace_list = NULL;
	SEC_ACL *dacl = NULL;
	SEC_DESC *sd;
	SEC_DESC_BUF *sdb = NULL;
	int result = 0, num_aces = 0;
	fstring line, keystr, tdb_path;
	size_t size;
	prs_struct ps;
	TALLOC_CTX *mem_ctx = NULL;
	BOOL has_user_sid = False, has_group_sid = False;

	ZERO_STRUCT(ps);

	/* Open tdb for reading */

	slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb", 
		 lp_lockdir());

	tdb = tdb_open(tdb_path, 0, 0, O_RDWR, 0600);

	if (!tdb) {
		printf("psec: failed to open nt drivers database: %s\n",
		       sys_errlist[errno]);
		result = 1;
		goto done;
	}

	/* Read owner and group sid */

	fgets(line, sizeof(fstring), stdin);
	if (line[0] != '\n') {
		string_to_sid(&user_sid, line);
		has_user_sid = True;
	}

	fgets(line, sizeof(fstring), stdin);
	if (line[0] != '\n') {
		string_to_sid(&group_sid, line);
		has_group_sid = True;
	}

	/* Read ACEs from standard input for discretionary ACL */

	while(fgets(line, sizeof(fstring), stdin)) {
		int ace_type, ace_flags;
		uint32 ace_mask;
		fstring sidstr;
		DOM_SID sid;
		SEC_ACCESS sa;

		if (sscanf(line, "%d %d 0x%x %s", &ace_type, &ace_flags, 
			   &ace_mask, sidstr) != 4) {
			continue;
		}

		string_to_sid(&sid, sidstr);
		
		ace_list = Realloc(ace_list, sizeof(SEC_ACE) * 
				   (num_aces + 1));
		
		init_sec_access(&sa, ace_mask);
		init_sec_ace(&ace_list[num_aces], &sid, ace_type, sa, 
			     ace_flags);

		num_aces++;
	}

	dacl = make_sec_acl(ACL_REVISION, num_aces, ace_list);
	free(ace_list);

	/* Create security descriptor */

	sd = make_sec_desc(SEC_DESC_REVISION,
			   has_user_sid ? &user_sid : NULL, 
			   has_group_sid ? &group_sid : NULL,
			   NULL, /* System ACL */
			   dacl, /* Discretionary ACL */
			   &size);

	free_sec_acl(&dacl);

	sdb = make_sec_desc_buf(size, sd);

	free_sec_desc(&sd);

	/* Write security descriptor to tdb */

	mem_ctx = talloc_init();

	if (!mem_ctx) {
		printf("memory allocation error\n");
		result = 1;
		goto done;
	}

	prs_init(&ps, (uint32)sec_desc_size(sdb->sec) + 
		 sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);

	if (!sec_io_desc_buf("nt_printing_setsec", &sdb, &ps, 1)) {
		printf("sec_io_desc_buf failed\n");
		goto done;
	}

	slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);

	if (!tdb_prs_store(tdb, keystr, &ps)==0) {
		printf("Failed to store secdesc for %s\n", printer);
		goto done;
	}

 done:
	if (tdb) tdb_close(tdb);
	if (sdb) free_sec_desc_buf(&sdb);
	if (mem_ctx) talloc_destroy(mem_ctx);
	prs_mem_free(&ps);

	return result;
}
Ejemplo n.º 11
0
static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx,
                             smbacl4_vfs_params *params,
                             SMB4ACL_T *theacl, /* in */
                             struct dom_sid *psid_owner, /* in */
                             struct dom_sid *psid_group, /* in */
                             bool is_directory, /* in */
                             struct security_ace **ppnt_ace_list, /* out */
                             int *pgood_aces /* out */
                            )
{
    SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)theacl;
    SMB_ACE4_INT_T *aceint;
    struct security_ace *nt_ace_list = NULL;
    int good_aces = 0;

    DEBUG(10, ("smbacl_nfs42win entered\n"));

    aclint = get_validated_aclint(theacl);
    /* We do not check for naces being 0 or theacl being NULL here
       because it is done upstream in smb_get_nt_acl_nfs4().
       We reserve twice the number of input aces because one nfs4
       ace might result in 2 nt aces.*/
    nt_ace_list = (struct security_ace *)TALLOC_ZERO_SIZE(
                      mem_ctx, 2 * aclint->naces * sizeof(struct security_ace));
    if (nt_ace_list==NULL)
    {
        DEBUG(10, ("talloc error"));
        errno = ENOMEM;
        return false;
    }

    for (aceint=aclint->first;
            aceint!=NULL;
            aceint=(SMB_ACE4_INT_T *)aceint->next) {
        uint32_t mask;
        struct dom_sid sid;
        SMB_ACE4PROP_T	*ace = &aceint->prop;
        uint32_t win_ace_flags;

        DEBUG(10, ("magic: 0x%x, type: %d, iflags: %x, flags: %x, "
                   "mask: %x, who: %d\n",
                   aceint->magic, ace->aceType, ace->flags,
                   ace->aceFlags, ace->aceMask, ace->who.id));

        SMB_ASSERT(aceint->magic==SMB_ACE4_INT_MAGIC);

        if (ace->flags & SMB_ACE4_ID_SPECIAL) {
            switch (ace->who.special_id) {
            case SMB_ACE4_WHO_OWNER:
                sid_copy(&sid, psid_owner);
                break;
            case SMB_ACE4_WHO_GROUP:
                sid_copy(&sid, psid_group);
                break;
            case SMB_ACE4_WHO_EVERYONE:
                sid_copy(&sid, &global_sid_World);
                break;
            default:
                DEBUG(8, ("invalid special who id %d "
                          "ignored\n", ace->who.special_id));
                continue;
            }
        } else {
            if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
                gid_to_sid(&sid, ace->who.gid);
            } else {
                uid_to_sid(&sid, ace->who.uid);
            }
        }
        DEBUG(10, ("mapped %d to %s\n", ace->who.id,
                   sid_string_dbg(&sid)));

        if (is_directory && (ace->aceMask & SMB_ACE4_ADD_FILE)) {
            ace->aceMask |= SMB_ACE4_DELETE_CHILD;
        }

        if (!is_directory && params->map_full_control) {
            /*
             * Do we have all access except DELETE_CHILD
             * (not caring about the delete bit).
             */
            uint32_t test_mask = ((ace->aceMask|SMB_ACE4_DELETE|SMB_ACE4_DELETE_CHILD) &
                                  SMB_ACE4_ALL_MASKS);
            if (test_mask == SMB_ACE4_ALL_MASKS) {
                ace->aceMask |= SMB_ACE4_DELETE_CHILD;
            }
        }

        win_ace_flags = map_nfs4_ace_flags_to_windows_ace_flags(
                            ace->aceFlags);
        if (!is_directory &&
                (win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
                                  SEC_ACE_FLAG_CONTAINER_INHERIT))) {
            /*
             * GPFS sets inherits dir_inhert and file_inherit flags
             * to files, too, which confuses windows, and seems to
             * be wrong anyways. ==> Map these bits away for files.
             */
            DEBUG(10, ("removing inherit flags from nfs4 ace\n"));
            win_ace_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|
                               SEC_ACE_FLAG_CONTAINER_INHERIT);
        }
        DEBUG(10, ("Windows mapped ace flags: 0x%x => 0x%x\n",
                   ace->aceFlags, win_ace_flags));

        mask = ace->aceMask;
        /* Windows clients expect SYNC on acls to
           correctly allow rename. See bug #7909. */
        /* But not on DENY ace entries. See
           bug #8442. */
        if(ace->aceType == SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE) {
            mask = ace->aceMask | SMB_ACE4_SYNCHRONIZE;
        }

        /* Mapping of owner@ and group@ to creator owner and
           creator group. Keep old behavior in mode special. */
        if (params->mode != e_special &&
                ace->flags & SMB_ACE4_ID_SPECIAL &&
                (ace->who.special_id == SMB_ACE4_WHO_OWNER ||
                 ace->who.special_id == SMB_ACE4_WHO_GROUP)) {
            DEBUG(10, ("Map special entry\n"));
            if (!(win_ace_flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
                uint32_t win_ace_flags_current;
                DEBUG(10, ("Map current sid\n"));
                win_ace_flags_current = win_ace_flags &
                                        ~(SEC_ACE_FLAG_OBJECT_INHERIT |
                                          SEC_ACE_FLAG_CONTAINER_INHERIT);
                init_sec_ace(&nt_ace_list[good_aces++], &sid,
                             ace->aceType, mask,
                             win_ace_flags_current);
            }
            if (ace->who.special_id == SMB_ACE4_WHO_OWNER &&
                    win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
                                     SEC_ACE_FLAG_CONTAINER_INHERIT)) {
                uint32_t win_ace_flags_creator;
                DEBUG(10, ("Map creator owner\n"));
                win_ace_flags_creator = win_ace_flags |
                                        SMB_ACE4_INHERIT_ONLY_ACE;
                init_sec_ace(&nt_ace_list[good_aces++],
                             &global_sid_Creator_Owner,
                             ace->aceType, mask,
                             win_ace_flags_creator);
            }
            if (ace->who.special_id == SMB_ACE4_WHO_GROUP &&
                    win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
                                     SEC_ACE_FLAG_CONTAINER_INHERIT)) {
                uint32_t win_ace_flags_creator;
                DEBUG(10, ("Map creator owner group\n"));
                win_ace_flags_creator = win_ace_flags |
                                        SMB_ACE4_INHERIT_ONLY_ACE;
                init_sec_ace(&nt_ace_list[good_aces++],
                             &global_sid_Creator_Group,
                             ace->aceType, mask,
                             win_ace_flags_creator);
            }
        } else {
            DEBUG(10, ("Map normal sid\n"));
            init_sec_ace(&nt_ace_list[good_aces++], &sid,
                         ace->aceType, mask,
                         win_ace_flags);
        }
    }

    nt_ace_list = (struct security_ace *)TALLOC_REALLOC(mem_ctx,
                  nt_ace_list,
                  good_aces * sizeof(struct security_ace));
    if (nt_ace_list == NULL) {
        errno = ENOMEM;
        return false;
    }

    *ppnt_ace_list = nt_ace_list;
    *pgood_aces = good_aces;

    return true;
}
Ejemplo n.º 12
0
SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, 
				      bool child_container)
{
	SEC_DESC_BUF *sdb;
	SEC_DESC *sd;
	SEC_ACL *new_dacl, *the_acl;
	SEC_ACE *new_ace_list = NULL;
	unsigned int new_ace_list_ndx = 0, i;
	size_t size;

	/* Currently we only process the dacl when creating the child.  The
	   sacl should also be processed but this is left out as sacls are
	   not implemented in Samba at the moment.*/

	the_acl = parent_ctr->dacl;

	if (the_acl->num_aces) {
		if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE, the_acl->num_aces))) 
			return NULL;
	} else {
		new_ace_list = NULL;
	}

	for (i = 0; i < the_acl->num_aces; i++) {
		SEC_ACE *ace = &the_acl->aces[i];
		SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
		uint8 new_flags = 0;
		bool inherit = False;

		/* The OBJECT_INHERIT_ACE flag causes the ACE to be
		   inherited by non-container children objects.  Container
		   children objects will inherit it as an INHERIT_ONLY
		   ACE. */

		if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {

			if (!child_container) {
				new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
			} else {
				new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
			}

			inherit = True;
		}

		/* The CONAINER_INHERIT_ACE flag means all child container
		   objects will inherit and use the ACE. */

		if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
			if (!child_container) {
				inherit = False;
			} else {
				new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
			}
		}

		/* The INHERIT_ONLY_ACE is not used by the se_access_check()
		   function for the parent container, but is inherited by
		   all child objects as a normal ACE. */

		if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
			/* Move along, nothing to see here */
		}

		/* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
		   is inherited by child objects but not grandchildren
		   objects.  We clear the object inherit and container
		   inherit flags in the inherited ACE. */

		if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
			new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
				       SEC_ACE_FLAG_CONTAINER_INHERIT);
		}

		/* Add ACE to ACE list */

		if (!inherit)
			continue;

		init_sec_access(&new_ace->access_mask, ace->access_mask);
		init_sec_ace(new_ace, &ace->trustee, ace->type,
			     new_ace->access_mask, new_flags);

		DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
			  " inherited as %s:%d/0x%02x/0x%08x\n",
			  sid_string_dbg(&ace->trustee),
			  ace->type, ace->flags, ace->access_mask,
			  sid_string_dbg(&ace->trustee),
			  new_ace->type, new_ace->flags,
			  new_ace->access_mask));

		new_ace_list_ndx++;
	}

	/* Create child security descriptor to return */
	
	new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);

	/* Use the existing user and group sids.  I don't think this is
	   correct.  Perhaps the user and group should be passed in as
	   parameters by the caller? */

	sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
			   SEC_DESC_SELF_RELATIVE,
			   parent_ctr->owner_sid,
			   parent_ctr->group_sid,
			   parent_ctr->sacl,
			   new_dacl, &size);

	sdb = make_sec_desc_buf(ctx, size, sd);

	return sdb;
}
Ejemplo n.º 13
0
static bool parse_ace(SEC_ACE *ace, const char *orig_str)
{
	char *p;
	const char *cp;
	char *tok;
	unsigned int atype = 0;
	unsigned int aflags = 0;
	unsigned int amask = 0;
	DOM_SID sid;
	SEC_ACCESS mask;
	const struct perm_value *v;
	char *str = SMB_STRDUP(orig_str);
	TALLOC_CTX *frame = talloc_stackframe();

	if (!str) {
		TALLOC_FREE(frame);
		return False;
	}

	ZERO_STRUCTP(ace);
	p = strchr_m(str,':');
	if (!p) {
		printf("ACE '%s': missing ':'.\n", orig_str);
		SAFE_FREE(str);
		TALLOC_FREE(frame);
		return False;
	}
	*p = '\0';
	p++;
	/* Try to parse numeric form */

	if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 &&
	    string_to_sid(&sid, str)) {
		goto done;
	}

	/* Try to parse text form */

	if (!string_to_sid(&sid, str)) {
		printf("ACE '%s': failed to convert '%s' to SID\n",
			orig_str, str);
		SAFE_FREE(str);
		TALLOC_FREE(frame);
		return False;
	}

	cp = p;
	if (!next_token_talloc(frame, &cp, &tok, "/")) {
		printf("ACE '%s': failed to find '/' character.\n",
			orig_str);
		SAFE_FREE(str);
		TALLOC_FREE(frame);
		return False;
	}

	if (strncmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
		atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
	} else if (strncmp(tok, "DENIED", strlen("DENIED")) == 0) {
		atype = SEC_ACE_TYPE_ACCESS_DENIED;
	} else {
		printf("ACE '%s': missing 'ALLOWED' or 'DENIED' entry at '%s'\n",
			orig_str, tok);
		SAFE_FREE(str);
		TALLOC_FREE(frame);
		return False;
	}

	/* Only numeric form accepted for flags at present */
	/* no flags on share permissions */

	if (!(next_token_talloc(frame, &cp, &tok, "/") &&
	      sscanf(tok, "%i", &aflags) && aflags == 0)) {
		printf("ACE '%s': bad integer flags entry at '%s'\n",
			orig_str, tok);
		SAFE_FREE(str);
		TALLOC_FREE(frame);
		return False;
	}

	if (!next_token_talloc(frame, &cp, &tok, "/")) {
		printf("ACE '%s': missing / at '%s'\n",
			orig_str, tok);
		SAFE_FREE(str);
		TALLOC_FREE(frame);
		return False;
	}

	if (strncmp(tok, "0x", 2) == 0) {
		if (sscanf(tok, "%i", &amask) != 1) {
			printf("ACE '%s': bad hex number at '%s'\n",
				orig_str, tok);
			TALLOC_FREE(frame);
			SAFE_FREE(str);
			return False;
		}
		goto done;
	}

	for (v = standard_values; v->perm; v++) {
		if (strcmp(tok, v->perm) == 0) {
			amask = v->mask;
			goto done;
		}
	}

	p = tok;

	while(*p) {
		bool found = False;

		for (v = special_values; v->perm; v++) {
			if (v->perm[0] == *p) {
				amask |= v->mask;
				found = True;
			}
		}

		if (!found) {
			printf("ACE '%s': bad permission value at '%s'\n",
				orig_str, p);
			TALLOC_FREE(frame);
			SAFE_FREE(str);
		 	return False;
		}
		p++;
	}

	if (*p) {
		TALLOC_FREE(frame);
		SAFE_FREE(str);
		return False;
	}

 done:
	mask = amask;
	init_sec_ace(ace, &sid, atype, mask, aflags);
	SAFE_FREE(str);
	TALLOC_FREE(frame);
	return True;
}
Ejemplo n.º 14
0
int psec_setsec(char *printer)
{
	struct dom_sid user_sid, group_sid;
	SEC_ACE *ace_list = NULL;
	SEC_ACL *dacl = NULL;
	SEC_DESC *sd;
	SEC_DESC_BUF *sdb = NULL;
	int result = 0, num_aces = 0;
	fstring line, keystr, tdb_path;
	size_t size;
	prs_struct ps;
	TALLOC_CTX *mem_ctx = NULL;
	BOOL has_user_sid = False, has_group_sid = False;

	ZERO_STRUCT(ps);

	/* Open tdb for reading */

	slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb", 
		 lp_lockdir());

	tdb = tdb_open(tdb_path, 0, 0, O_RDWR, 0600);

	if (!tdb) {
		printf("psec: failed to open nt drivers database: %s\n",
		       sys_errlist[errno]);
		result = 1;
		goto done;
	}

	/* Read owner and group sid */

	fgets(line, sizeof(fstring), stdin);
	if (line[0] != '\n') {
		string_to_sid(&user_sid, line);
		has_user_sid = True;
	}

	fgets(line, sizeof(fstring), stdin);
	if (line[0] != '\n') {
		string_to_sid(&group_sid, line);
		has_group_sid = True;
	}

	/* Read ACEs from standard input for discretionary ACL */

	while(fgets(line, sizeof(fstring), stdin)) {
		int ace_type, ace_flags;
		uint32 ace_mask;
		fstring sidstr;
		struct dom_sid sid;
		SEC_ACCESS sa;

		if (sscanf(line, "%d %d 0x%x %s", &ace_type, &ace_flags, 
			   &ace_mask, sidstr) != 4) {
			continue;
		}

		string_to_sid(&sid, sidstr);
		
		ace_list = Realloc(ace_list, sizeof(SEC_ACE) * 
				   (num_aces + 1));
		
		init_sec_access(&sa, ace_mask);
		init_sec_ace(&ace_list[num_aces], &sid, ace_type, sa, 
			     ace_flags);

		num_aces++;
	}

	dacl = make_sec_acl(ACL_REVISION, num_aces, ace_list);
	free(ace_list);

	/* Create security descriptor */

	sd = make_sec_desc(SEC_DESC_REVISION,
			   has_user_sid ? &user_sid : NULL, 
			   has_group_sid ? &group_sid : NULL
Ejemplo n.º 15
0
static size_t afs_to_nt_acl(struct afs_acl *afs_acl, 
			    struct files_struct *fsp,
			    uint32 security_info,
			    struct security_descriptor **ppdesc)
{
	SEC_ACE *nt_ace_list;
	DOM_SID owner_sid, group_sid;
	SEC_ACCESS mask;
	SMB_STRUCT_STAT sbuf;
	SEC_ACL *psa = NULL;
	int good_aces;
	size_t sd_size;
	TALLOC_CTX *mem_ctx = main_loop_talloc_get();

	struct afs_ace *afs_ace;

	if (fsp->is_directory || fsp->fh->fd == -1) {
		/* Get the stat struct for the owner info. */
		if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) {
			return 0;
		}
	} else {
		if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
			return 0;
		}
	}

	uid_to_sid(&owner_sid, sbuf.st_uid);
	gid_to_sid(&group_sid, sbuf.st_gid);

	if (afs_acl->num_aces) {
		nt_ace_list = TALLOC_ARRAY(mem_ctx, SEC_ACE, afs_acl->num_aces);

		if (nt_ace_list == NULL)
			return 0;
	} else {
		nt_ace_list = NULL;
	}

	afs_ace = afs_acl->acelist;
	good_aces = 0;

	while (afs_ace != NULL) {
		uint32 nt_rights;
		uint8 flag = SEC_ACE_FLAG_OBJECT_INHERIT |
			SEC_ACE_FLAG_CONTAINER_INHERIT;

		if (afs_ace->type == SID_NAME_UNKNOWN) {
			DEBUG(10, ("Ignoring unknown name %s\n",
				   afs_ace->name));
			afs_ace = afs_ace->next;
			continue;
		}

		if (fsp->is_directory)
			afs_to_nt_dir_rights(afs_ace->rights, &nt_rights,
					     &flag);
		else
			nt_rights = afs_to_nt_file_rights(afs_ace->rights);

		init_sec_access(&mask, nt_rights);
		init_sec_ace(&nt_ace_list[good_aces++], &(afs_ace->sid),
			     SEC_ACE_TYPE_ACCESS_ALLOWED, mask, flag);
		afs_ace = afs_ace->next;
	}

	psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION,
			   good_aces, nt_ace_list);
	if (psa == NULL)
		return 0;

	
	*ppdesc = make_sec_desc(mem_ctx, SEC_DESC_REVISION,
				SEC_DESC_SELF_RELATIVE,
				(security_info & OWNER_SECURITY_INFORMATION)
				? &owner_sid : NULL,
				(security_info & GROUP_SECURITY_INFORMATION)
				? &group_sid : NULL,
				NULL, psa, &sd_size);

	return sd_size;
}
Ejemplo n.º 16
0
WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
				      struct spoolss_security_descriptor **secdesc)
{
	struct security_ace ace[7];	/* max number of ace entries */
	int i = 0;
	uint32_t sa;
	struct security_acl *psa = NULL;
	struct security_descriptor *psd = NULL;
	struct dom_sid adm_sid;
	size_t sd_size;

	/* Create an ACE where Everyone is allowed to print */

	sa = PRINTER_ACE_PRINT;
	init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
		     sa, SEC_ACE_FLAG_CONTAINER_INHERIT);

	/* Add the domain admins group if we are a DC */

	if ( IS_DC ) {
		struct dom_sid domadmins_sid;

		sid_compose(&domadmins_sid, get_global_sam_sid(),
			    DOMAIN_RID_ADMINS);

		sa = PRINTER_ACE_FULL_CONTROL;
		init_sec_ace(&ace[i++], &domadmins_sid,
			SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
			SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
		init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
			sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
	}
	else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
		sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);

		sa = PRINTER_ACE_FULL_CONTROL;
		init_sec_ace(&ace[i++], &adm_sid,
			SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
			SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
		init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
			sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
	}

	/* add BUILTIN\Administrators as FULL CONTROL */

	sa = PRINTER_ACE_FULL_CONTROL;
	init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
		SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
		SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
	init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
		SEC_ACE_TYPE_ACCESS_ALLOWED,
		sa, SEC_ACE_FLAG_CONTAINER_INHERIT);

	/* add BUILTIN\Print Operators as FULL CONTROL */

	sa = PRINTER_ACE_FULL_CONTROL;
	init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
		SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
		SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
	init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
		SEC_ACE_TYPE_ACCESS_ALLOWED,
		sa, SEC_ACE_FLAG_CONTAINER_INHERIT);

	/* Make the security descriptor owned by the BUILTIN\Administrators */

	/* The ACL revision number in rpc_secdesc.h differs from the one
	   created by NT when setting ACE entries in printer
	   descriptors.  NT4 complains about the property being edited by a
	   NT5 machine. */

	if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
		psd = make_sec_desc(mem_ctx,
				    SD_REVISION,
				    SEC_DESC_SELF_RELATIVE,
				    &global_sid_Builtin_Administrators,
				    &global_sid_Builtin_Administrators,
				    NULL,
				    psa,
				    &sd_size);
	}

	if (psd == NULL) {
		DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
		return WERR_NOMEM;
	}

	DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
		 (unsigned int)sd_size));

	*secdesc = psd;

	return WERR_OK;
}
Ejemplo n.º 17
0
static WERROR gp_reg_generate_sd(TALLOC_CTX *mem_ctx,
				 const struct dom_sid *sid,
				 struct security_descriptor **sd,
				 size_t *sd_size)
{
	struct security_ace ace[6];
	uint32_t mask;

	struct security_acl *theacl = NULL;

	uint8_t inherit_flags;

	mask = REG_KEY_ALL;
	init_sec_ace(&ace[0],
		     &global_sid_System,
		     SEC_ACE_TYPE_ACCESS_ALLOWED,
		     mask, 0);

	mask = REG_KEY_ALL;
	init_sec_ace(&ace[1],
		     &global_sid_Builtin_Administrators,
		     SEC_ACE_TYPE_ACCESS_ALLOWED,
		     mask, 0);

	mask = REG_KEY_READ;
	init_sec_ace(&ace[2],
		     sid ? sid : &global_sid_Authenticated_Users,
		     SEC_ACE_TYPE_ACCESS_ALLOWED,
		     mask, 0);

	inherit_flags = SEC_ACE_FLAG_OBJECT_INHERIT |
			SEC_ACE_FLAG_CONTAINER_INHERIT |
			SEC_ACE_FLAG_INHERIT_ONLY;

	mask = REG_KEY_ALL;
	init_sec_ace(&ace[3],
		     &global_sid_System,
		     SEC_ACE_TYPE_ACCESS_ALLOWED,
		     mask, inherit_flags);

	mask = REG_KEY_ALL;
	init_sec_ace(&ace[4],
		     &global_sid_Builtin_Administrators,
		     SEC_ACE_TYPE_ACCESS_ALLOWED,
		     mask, inherit_flags);

	mask = REG_KEY_READ;
	init_sec_ace(&ace[5],
		     sid ? sid : &global_sid_Authenticated_Users,
		     SEC_ACE_TYPE_ACCESS_ALLOWED,
		     mask, inherit_flags);

	theacl = make_sec_acl(mem_ctx, NT4_ACL_REVISION, 6, ace);
	W_ERROR_HAVE_NO_MEMORY(theacl);

	*sd = make_sec_desc(mem_ctx, SD_REVISION,
			    SEC_DESC_SELF_RELATIVE |
			    SEC_DESC_DACL_AUTO_INHERITED | /* really ? */
			    SEC_DESC_DACL_AUTO_INHERIT_REQ, /* really ? */
			    NULL, NULL, NULL,
			    theacl, sd_size);
	W_ERROR_HAVE_NO_MEMORY(*sd);

	return WERR_OK;
}
Ejemplo n.º 18
0
static size_t afs_to_nt_acl_common(struct afs_acl *afs_acl,
				   SMB_STRUCT_STAT *psbuf,
				   uint32 security_info,
				   struct security_descriptor **ppdesc)
{
	SEC_ACE *nt_ace_list;
	DOM_SID owner_sid, group_sid;
	SEC_ACL *psa = NULL;
	int good_aces;
	size_t sd_size;
	TALLOC_CTX *mem_ctx = talloc_tos();

	struct afs_ace *afs_ace;

	uid_to_sid(&owner_sid, psbuf->st_uid);
	gid_to_sid(&group_sid, psbuf->st_gid);

	if (afs_acl->num_aces) {
		nt_ace_list = TALLOC_ARRAY(mem_ctx, SEC_ACE, afs_acl->num_aces);

		if (nt_ace_list == NULL)
			return 0;
	} else {
		nt_ace_list = NULL;
	}

	afs_ace = afs_acl->acelist;
	good_aces = 0;

	while (afs_ace != NULL) {
		uint32_t nt_rights;
		uint8 flag = SEC_ACE_FLAG_OBJECT_INHERIT |
			SEC_ACE_FLAG_CONTAINER_INHERIT;

		if (afs_ace->type == SID_NAME_UNKNOWN) {
			DEBUG(10, ("Ignoring unknown name %s\n",
				   afs_ace->name));
			afs_ace = afs_ace->next;
			continue;
		}

		if (S_ISDIR(psbuf->st_mode))
			afs_to_nt_dir_rights(afs_ace->rights, &nt_rights,
					     &flag);
		else
			nt_rights = afs_to_nt_file_rights(afs_ace->rights);

		init_sec_ace(&nt_ace_list[good_aces++], &(afs_ace->sid),
			     SEC_ACE_TYPE_ACCESS_ALLOWED, nt_rights, flag);
		afs_ace = afs_ace->next;
	}

	psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION,
			   good_aces, nt_ace_list);
	if (psa == NULL)
		return 0;

	*ppdesc = make_sec_desc(mem_ctx, SEC_DESC_REVISION,
				SEC_DESC_SELF_RELATIVE,
				(security_info & OWNER_SECURITY_INFORMATION)
				? &owner_sid : NULL,
				(security_info & GROUP_SECURITY_INFORMATION)
				? &group_sid : NULL,
				NULL, psa, &sd_size);

	return sd_size;
}
Ejemplo n.º 19
0
NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
					SEC_DESC **ppsd,
					size_t *psize,
					const SEC_DESC *parent_ctr,
					const DOM_SID *owner_sid,
					const DOM_SID *group_sid,
					bool container)
{
	SEC_ACL *new_dacl = NULL, *the_acl = NULL;
	SEC_ACE *new_ace_list = NULL;
	unsigned int new_ace_list_ndx = 0, i;

	*ppsd = NULL;
	*psize = 0;

	/* Currently we only process the dacl when creating the child.  The
	   sacl should also be processed but this is left out as sacls are
	   not implemented in Samba at the moment.*/

	the_acl = parent_ctr->dacl;

	if (the_acl->num_aces) {
		if (2*the_acl->num_aces < the_acl->num_aces) {
			return NT_STATUS_NO_MEMORY;
		}

		if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE,
						2*the_acl->num_aces))) {
			return NT_STATUS_NO_MEMORY;
		}
	} else {
		new_ace_list = NULL;
	}

	for (i = 0; i < the_acl->num_aces; i++) {
		const SEC_ACE *ace = &the_acl->aces[i];
		SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
		const DOM_SID *ptrustee = &ace->trustee;
		const DOM_SID *creator = NULL;
		uint8 new_flags = ace->flags;

		if (!is_inheritable_ace(ace, container)) {
			continue;
		}

		/* see the RAW-ACLS inheritance test for details on these rules */
		if (!container) {
			new_flags = 0;
		} else {
			new_flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;

			if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
				new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
			}
			if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
				new_flags = 0;
			}
		}

		/* The CREATOR sids are special when inherited */
		if (sid_equal(ptrustee, &global_sid_Creator_Owner)) {
			creator = &global_sid_Creator_Owner;
			ptrustee = owner_sid;
		} else if (sid_equal(ptrustee, &global_sid_Creator_Group)) {
			creator = &global_sid_Creator_Group;
			ptrustee = group_sid;
		}

		if (creator && container &&
				(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {

			/* First add the regular ACE entry. */
			init_sec_ace(new_ace, ptrustee, ace->type,
			     	ace->access_mask, 0);

			DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
				" inherited as %s:%d/0x%02x/0x%08x\n",
				sid_string_dbg(&ace->trustee),
				ace->type, ace->flags, ace->access_mask,
				sid_string_dbg(&new_ace->trustee),
				new_ace->type, new_ace->flags,
				new_ace->access_mask));

			new_ace_list_ndx++;

			/* Now add the extra creator ACE. */
			new_ace = &new_ace_list[new_ace_list_ndx];

			ptrustee = creator;
			new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
		} else if (container &&
				!(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
			ptrustee = &ace->trustee;
		}

		init_sec_ace(new_ace, ptrustee, ace->type,
			     ace->access_mask, new_flags);

		DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
			  " inherited as %s:%d/0x%02x/0x%08x\n",
			  sid_string_dbg(&ace->trustee),
			  ace->type, ace->flags, ace->access_mask,
			  sid_string_dbg(&ace->trustee),
			  new_ace->type, new_ace->flags,
			  new_ace->access_mask));

		new_ace_list_ndx++;
	}

	/* Create child security descriptor to return */
	if (new_ace_list_ndx) {
		new_dacl = make_sec_acl(ctx,
				NT4_ACL_REVISION,
				new_ace_list_ndx,
				new_ace_list);

		if (!new_dacl) {
			return NT_STATUS_NO_MEMORY;
		}
	}

	*ppsd = make_sec_desc(ctx,
			SECURITY_DESCRIPTOR_REVISION_1,
			SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
			owner_sid,
			group_sid,
			NULL,
			new_dacl,
			psize);
	if (!*ppsd) {
		return NT_STATUS_NO_MEMORY;
	}
	return NT_STATUS_OK;
}