Move secacl to top-level.
[ira/wip.git] / libcli / security / secacl.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  SEC_ACL handling routines
4  *  Copyright (C) Andrew Tridgell              1992-1998,
5  *  Copyright (C) Jeremy R. Allison            1995-2003.
6  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
7  *  Copyright (C) Paul Ashton                  1997-1998.
8  *  
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 3 of the License, or
12  *  (at your option) any later version.
13  *  
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *  
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include "includes.h"
24 #include "libcli/security/security.h"
25
26 #define  SEC_ACL_HEADER_SIZE (2 * sizeof(uint16_t) + sizeof(uint32_t))
27
28 /*******************************************************************
29  Create a SEC_ACL structure.  
30 ********************************************************************/
31
32 struct security_acl *make_sec_acl(TALLOC_CTX *ctx, 
33                                                                   enum security_acl_revision revision,
34                                                                   int num_aces, struct security_ace *ace_list)
35 {
36         struct security_acl *dst;
37         int i;
38
39         if((dst = talloc_zero(ctx, struct security_acl)) == NULL)
40                 return NULL;
41
42         dst->revision = revision;
43         dst->num_aces = num_aces;
44         dst->size = SEC_ACL_HEADER_SIZE;
45
46         /* Now we need to return a non-NULL address for the ace list even
47            if the number of aces required is zero.  This is because there
48            is a distinct difference between a NULL ace and an ace with zero
49            entries in it.  This is achieved by checking that num_aces is a
50            positive number. */
51
52         if ((num_aces) && 
53             ((dst->aces = talloc_array(ctx, struct security_ace, num_aces)) 
54              == NULL)) {
55                 return NULL;
56         }
57         
58         for (i = 0; i < num_aces; i++) {
59                 dst->aces[i] = ace_list[i]; /* Structure copy. */
60                 dst->size += ace_list[i].size;
61         }
62
63         return dst;
64 }
65
66 /*******************************************************************
67  Duplicate a SEC_ACL structure.  
68 ********************************************************************/
69
70 struct security_acl *dup_sec_acl(TALLOC_CTX *ctx, struct security_acl *src)
71 {
72         if(src == NULL)
73                 return NULL;
74
75         return make_sec_acl(ctx, src->revision, src->num_aces, src->aces);
76 }
77
78 /*******************************************************************
79  Compares two SEC_ACL structures
80 ********************************************************************/
81
82 bool sec_acl_equal(struct security_acl *s1, struct security_acl *s2)
83 {
84         unsigned int i, j;
85
86         /* Trivial cases */
87
88         if (!s1 && !s2) return true;
89         if (!s1 || !s2) return false;
90
91         /* Check top level stuff */
92
93         if (s1->revision != s2->revision) {
94                 DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n",
95                            s1->revision, s2->revision));
96                 return false;
97         }
98
99         if (s1->num_aces != s2->num_aces) {
100                 DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n",
101                            s1->revision, s2->revision));
102                 return false;
103         }
104
105         /* The ACEs could be in any order so check each ACE in s1 against 
106            each ACE in s2. */
107
108         for (i = 0; i < s1->num_aces; i++) {
109                 bool found = false;
110
111                 for (j = 0; j < s2->num_aces; j++) {
112                         if (sec_ace_equal(&s1->aces[i], &s2->aces[j])) {
113                                 found = true;
114                                 break;
115                         }
116                 }
117
118                 if (!found) return false;
119         }
120
121         return true;
122 }