Revert "libcli/security: Convert some strtol calls to strtoul"
[ira/wip.git] / libcli / security / dom_sid.c
1 /*
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4
5    Copyright (C) Stefan (metze) Metzmacher      2002-2004
6    Copyright (C) Andrew Tridgell                1992-2004
7    Copyright (C) Jeremy Allison                 1999
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 "librpc/gen_ndr/security.h"
25 #include "dom_sid.h"
26
27 /*****************************************************************
28  Compare the auth portion of two sids.
29 *****************************************************************/
30
31 static int dom_sid_compare_auth(const struct dom_sid *sid1,
32                                 const struct dom_sid *sid2)
33 {
34         int i;
35
36         if (sid1 == sid2)
37                 return 0;
38         if (!sid1)
39                 return -1;
40         if (!sid2)
41                 return 1;
42
43         if (sid1->sid_rev_num != sid2->sid_rev_num)
44                 return sid1->sid_rev_num - sid2->sid_rev_num;
45
46         for (i = 0; i < 6; i++)
47                 if (sid1->id_auth[i] != sid2->id_auth[i])
48                         return sid1->id_auth[i] - sid2->id_auth[i];
49
50         return 0;
51 }
52
53 /*****************************************************************
54  Compare two sids.
55 *****************************************************************/
56
57 int dom_sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2)
58 {
59         int i;
60
61         if (sid1 == sid2)
62                 return 0;
63         if (!sid1)
64                 return -1;
65         if (!sid2)
66                 return 1;
67
68         /* Compare most likely different rids, first: i.e start at end */
69         if (sid1->num_auths != sid2->num_auths)
70                 return sid1->num_auths - sid2->num_auths;
71
72         for (i = sid1->num_auths-1; i >= 0; --i)
73                 if (sid1->sub_auths[i] != sid2->sub_auths[i])
74                         return sid1->sub_auths[i] - sid2->sub_auths[i];
75
76         return dom_sid_compare_auth(sid1, sid2);
77 }
78
79 /*****************************************************************
80  Compare two sids.
81 *****************************************************************/
82
83 bool dom_sid_equal(const struct dom_sid *sid1, const struct dom_sid *sid2)
84 {
85         return dom_sid_compare(sid1, sid2) == 0;
86 }
87
88 bool dom_sid_parse(const char *sidstr, struct dom_sid *ret)
89 {
90         uint_t rev, ia, num_sub_auths, i;
91         char *p;
92
93         if ((sidstr[0] != 'S' && sidstr[0] != 's') || sidstr[1] != '-') {
94                 return false;
95         }
96
97         sidstr += 2;
98
99         rev = strtol(sidstr, &p, 10);
100         if (*p != '-') {
101                 return false;
102         }
103         sidstr = p+1;
104
105         ia = strtol(sidstr, &p, 10);
106         if (p == sidstr) {
107                 return false;
108         }
109         sidstr = p;
110
111         num_sub_auths = 0;
112         for (i=0;sidstr[i];i++) {
113                 if (sidstr[i] == '-') num_sub_auths++;
114         }
115
116         ret->sid_rev_num = rev;
117         ret->id_auth[0] = 0;
118         ret->id_auth[1] = 0;
119         ret->id_auth[2] = ia >> 24;
120         ret->id_auth[3] = ia >> 16;
121         ret->id_auth[4] = ia >> 8;
122         ret->id_auth[5] = ia;
123         ret->num_auths = num_sub_auths;
124
125         for (i=0;i<num_sub_auths;i++) {
126                 if (sidstr[0] != '-') {
127                         return false;
128                 }
129                 sidstr++;
130                 ret->sub_auths[i] = strtoul(sidstr, &p, 10);
131                 if (p == sidstr) {
132                         return false;
133                 }
134                 sidstr = p;
135         }
136
137         return true;
138 }
139
140 /*
141   convert a string to a dom_sid, returning a talloc'd dom_sid
142 */
143 struct dom_sid *dom_sid_parse_talloc(TALLOC_CTX *mem_ctx, const char *sidstr)
144 {
145         struct dom_sid *ret;
146         ret = talloc(mem_ctx, struct dom_sid);
147         if (!ret) {
148                 return NULL;
149         }
150         if (!dom_sid_parse(sidstr, ret)) {
151                 talloc_free(ret);
152                 return NULL;
153         }
154
155         return ret;
156 }
157
158 /*
159   convert a string to a dom_sid, returning a talloc'd dom_sid
160 */
161 struct dom_sid *dom_sid_parse_length(TALLOC_CTX *mem_ctx, const DATA_BLOB *sid)
162 {
163         struct dom_sid *ret;
164         char *p = talloc_strndup(mem_ctx, (char *)sid->data, sid->length);
165         if (!p) {
166                 return NULL;
167         }
168         ret = dom_sid_parse_talloc(mem_ctx, p);
169         talloc_free(p);
170         return ret;
171 }
172
173 /*
174   copy a dom_sid structure
175 */
176 struct dom_sid *dom_sid_dup(TALLOC_CTX *mem_ctx, const struct dom_sid *dom_sid)
177 {
178         struct dom_sid *ret;
179         int i;
180
181         if (!dom_sid) {
182                 return NULL;
183         }
184
185         ret = talloc(mem_ctx, struct dom_sid);
186         if (!ret) {
187                 return NULL;
188         }
189
190         ret->sid_rev_num = dom_sid->sid_rev_num;
191         ret->id_auth[0] = dom_sid->id_auth[0];
192         ret->id_auth[1] = dom_sid->id_auth[1];
193         ret->id_auth[2] = dom_sid->id_auth[2];
194         ret->id_auth[3] = dom_sid->id_auth[3];
195         ret->id_auth[4] = dom_sid->id_auth[4];
196         ret->id_auth[5] = dom_sid->id_auth[5];
197         ret->num_auths = dom_sid->num_auths;
198
199         for (i=0;i<dom_sid->num_auths;i++) {
200                 ret->sub_auths[i] = dom_sid->sub_auths[i];
201         }
202
203         return ret;
204 }
205
206 /*
207   add a rid to a domain dom_sid to make a full dom_sid. This function
208   returns a new sid in the supplied memory context
209 */
210 struct dom_sid *dom_sid_add_rid(TALLOC_CTX *mem_ctx,
211                                 const struct dom_sid *domain_sid,
212                                 uint32_t rid)
213 {
214         struct dom_sid *sid;
215
216         sid = talloc(mem_ctx, struct dom_sid);
217         if (!sid) return NULL;
218
219         *sid = *domain_sid;
220
221         sid->sub_auths[sid->num_auths] = rid;
222         sid->num_auths++;
223
224         return sid;
225 }
226
227 /*
228   Split up a SID into its domain and RID part
229 */
230 NTSTATUS dom_sid_split_rid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
231                            struct dom_sid **domain, uint32_t *rid)
232 {
233         if (sid->num_auths == 0) {
234                 return NT_STATUS_INVALID_PARAMETER;
235         }
236
237         if (domain) {
238                 if (!(*domain = dom_sid_dup(mem_ctx, sid))) {
239                         return NT_STATUS_NO_MEMORY;
240                 }
241
242                 (*domain)->num_auths -= 1;
243         }
244
245         if (rid) {
246                 *rid = sid->sub_auths[sid->num_auths - 1];
247         }
248
249         return NT_STATUS_OK;
250 }
251
252 /*
253   return true if the 2nd sid is in the domain given by the first sid
254 */
255 bool dom_sid_in_domain(const struct dom_sid *domain_sid,
256                        const struct dom_sid *sid)
257 {
258         int i;
259
260         if (!domain_sid || !sid) {
261                 return false;
262         }
263
264         if (domain_sid->num_auths > sid->num_auths) {
265                 return false;
266         }
267
268         for (i = domain_sid->num_auths-1; i >= 0; --i) {
269                 if (domain_sid->sub_auths[i] != sid->sub_auths[i]) {
270                         return false;
271                 }
272         }
273
274         return dom_sid_compare_auth(domain_sid, sid) == 0;
275 }
276
277 /*
278   convert a dom_sid to a string
279 */
280 char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid)
281 {
282         int i, ofs, maxlen;
283         uint32_t ia;
284         char *ret;
285
286         if (!sid) {
287                 return talloc_strdup(mem_ctx, "(NULL SID)");
288         }
289
290         maxlen = sid->num_auths * 11 + 25;
291         ret = talloc_array(mem_ctx, char, maxlen);
292         if (!ret) return talloc_strdup(mem_ctx, "(SID ERR)");
293
294         ia = (sid->id_auth[5]) +
295                 (sid->id_auth[4] << 8 ) +
296                 (sid->id_auth[3] << 16) +
297                 (sid->id_auth[2] << 24);
298
299         ofs = snprintf(ret, maxlen, "S-%u-%lu",
300                        (unsigned int)sid->sid_rev_num, (unsigned long)ia);
301
302         for (i = 0; i < sid->num_auths; i++) {
303                 ofs += snprintf(ret + ofs, maxlen - ofs, "-%lu",
304                                 (unsigned long)sid->sub_auths[i]);
305         }
306
307         return ret;
308 }