s3: security.idl: split of dom_sid stuff into dom_sid.idl
[samba.git] / source3 / librpc / ndr / sid.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    libndr interface
5
6    Copyright (C) Andrew Tridgell 2003
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
24 /*
25   return the wire size of a dom_sid
26 */
27 size_t ndr_size_dom_sid(const struct dom_sid *sid, int flags)
28 {
29         if (!sid) return 0;
30         return 8 + 4*sid->num_auths;
31 }
32
33 size_t ndr_size_dom_sid28(const struct dom_sid *sid, int flags)
34 {
35         struct dom_sid zero_sid;
36
37         if (!sid) return 0;
38
39         ZERO_STRUCT(zero_sid);
40
41         if (memcmp(&zero_sid, sid, sizeof(zero_sid)) == 0) {
42                 return 0;
43         }
44
45         return 8 + 4*sid->num_auths;
46 }
47
48 size_t ndr_size_dom_sid0(const struct dom_sid *sid, int flags)
49 {
50         return ndr_size_dom_sid28(sid, flags);
51 }
52
53 enum ndr_err_code ndr_push_dom_sid(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *r)
54 {
55         uint32_t cntr_sub_auths_0;
56         if (ndr_flags & NDR_SCALARS) {
57                 NDR_CHECK(ndr_push_align(ndr, 4));
58                 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->sid_rev_num));
59                 NDR_CHECK(ndr_push_int8(ndr, NDR_SCALARS, r->num_auths));
60                 NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
61                 for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
62                         NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->sub_auths[cntr_sub_auths_0]));
63                 }
64         }
65         if (ndr_flags & NDR_BUFFERS) {
66         }
67         return NDR_ERR_SUCCESS;
68 }
69
70 enum ndr_err_code ndr_pull_dom_sid(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *r)
71 {
72         uint32_t cntr_sub_auths_0;
73         if (ndr_flags & NDR_SCALARS) {
74                 NDR_CHECK(ndr_pull_align(ndr, 4));
75                 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sid_rev_num));
76                 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->num_auths));
77                 if (r->num_auths > 15) {
78                         return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
79                 }
80                 NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
81                 for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
82                         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sub_auths[cntr_sub_auths_0]));
83                 }
84         }
85         if (ndr_flags & NDR_BUFFERS) {
86         }
87         return NDR_ERR_SUCCESS;
88 }
89
90 /*
91   convert a dom_sid to a string
92 */
93 char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid)
94 {
95         int i, ofs, maxlen;
96         uint32_t ia;
97         char *ret;
98         
99         if (!sid) {
100                 return talloc_strdup(mem_ctx, "(NULL SID)");
101         }
102
103         maxlen = sid->num_auths * 11 + 25;
104         ret = (char *)talloc_size(mem_ctx, maxlen);
105         if (!ret) return talloc_strdup(mem_ctx, "(SID ERR)");
106
107         /*
108          * BIG NOTE: this function only does SIDS where the identauth is not
109          * >= ^32 in a range of 2^48.
110          */
111
112         ia = (sid->id_auth[5]) +
113                 (sid->id_auth[4] << 8 ) +
114                 (sid->id_auth[3] << 16) +
115                 (sid->id_auth[2] << 24);
116
117         ofs = snprintf(ret, maxlen, "S-%u-%lu", 
118                        (unsigned int)sid->sid_rev_num, (unsigned long)ia);
119
120         for (i = 0; i < sid->num_auths; i++) {
121                 ofs += snprintf(ret + ofs, maxlen - ofs, "-%lu", (unsigned long)sid->sub_auths[i]);
122         }
123         
124         return ret;
125 }
126
127 /*
128   parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
129 */
130 enum ndr_err_code ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
131 {
132         uint32_t num_auths;
133         if (!(ndr_flags & NDR_SCALARS)) {
134                 return NDR_ERR_SUCCESS;
135         }
136         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &num_auths));
137         NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid));
138         if (sid->num_auths != num_auths) {
139                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
140                                       "Bad array size %u should exceed %u", 
141                                       num_auths, sid->num_auths);
142         }
143         return NDR_ERR_SUCCESS;
144 }
145
146 /*
147   parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
148 */
149 enum ndr_err_code ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
150 {
151         if (!(ndr_flags & NDR_SCALARS)) {
152                 return NDR_ERR_SUCCESS;
153         }
154         NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, sid->num_auths));
155         return ndr_push_dom_sid(ndr, ndr_flags, sid);
156 }
157
158 /*
159   parse a dom_sid28 - this is a dom_sid in a fixed 28 byte buffer, so we need to ensure there are only upto 5 sub_auth
160 */
161 enum ndr_err_code ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
162 {
163         enum ndr_err_code status;
164         struct ndr_pull *subndr;
165
166         if (!(ndr_flags & NDR_SCALARS)) {
167                 return NDR_ERR_SUCCESS;
168         }
169
170         subndr = talloc_zero(ndr, struct ndr_pull);
171         NDR_ERR_HAVE_NO_MEMORY(subndr);
172         subndr->flags           = ndr->flags;
173         subndr->current_mem_ctx = ndr->current_mem_ctx;
174
175         subndr->data            = ndr->data + ndr->offset;
176         subndr->data_size       = 28;
177         subndr->offset          = 0;
178
179         NDR_CHECK(ndr_pull_advance(ndr, 28));
180
181         status = ndr_pull_dom_sid(subndr, ndr_flags, sid);
182         if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
183                 /* handle a w2k bug which send random data in the buffer */
184                 ZERO_STRUCTP(sid);
185         }
186
187         return NDR_ERR_SUCCESS;
188 }
189
190 /*
191   push a dom_sid28 - this is a dom_sid in a 28 byte fixed buffer
192 */
193 enum ndr_err_code ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
194 {
195         uint32_t old_offset;
196         uint32_t padding;
197
198         if (!(ndr_flags & NDR_SCALARS)) {
199                 return NDR_ERR_SUCCESS;
200         }
201
202         if (sid->num_auths > 5) {
203                 return ndr_push_error(ndr, NDR_ERR_RANGE, 
204                                       "dom_sid28 allows only upto 5 sub auth [%u]", 
205                                       sid->num_auths);
206         }
207
208         old_offset = ndr->offset;
209         NDR_CHECK(ndr_push_dom_sid(ndr, ndr_flags, sid));
210
211         padding = 28 - (ndr->offset - old_offset);
212
213         if (padding > 0) {
214                 NDR_CHECK(ndr_push_zero(ndr, padding));
215         }
216
217         return NDR_ERR_SUCCESS;
218 }
219
220 /*
221   parse a dom_sid0 - this is a dom_sid in a variable byte buffer, which is maybe empty
222 */
223 enum ndr_err_code ndr_pull_dom_sid0(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
224 {
225         if (!(ndr_flags & NDR_SCALARS)) {
226                 return NDR_ERR_SUCCESS;
227         }
228
229         if (ndr->data_size == ndr->offset) {
230                 ZERO_STRUCTP(sid);
231                 return NDR_ERR_SUCCESS;
232         }
233
234         return ndr_pull_dom_sid(ndr, ndr_flags, sid);
235 }
236
237 /*
238   push a dom_sid0 - this is a dom_sid in a variable byte buffer, which is maybe empty
239 */
240 enum ndr_err_code ndr_push_dom_sid0(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
241 {
242         struct dom_sid zero_sid;
243
244         if (!(ndr_flags & NDR_SCALARS)) {
245                 return NDR_ERR_SUCCESS;
246         }
247
248         if (!sid) {
249                 return NDR_ERR_SUCCESS;
250         }
251
252         ZERO_STRUCT(zero_sid);
253
254         if (memcmp(&zero_sid, sid, sizeof(zero_sid)) == 0) {
255                 return NDR_ERR_SUCCESS;
256         }
257
258         return ndr_push_dom_sid(ndr, ndr_flags, sid);
259 }
260
261 /*
262   print a dom_sid
263 */
264 void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
265 {
266         ndr->print(ndr, "%-25s: %s", name, dom_sid_string(ndr, sid));
267 }
268
269 void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
270 {
271         ndr_print_dom_sid(ndr, name, sid);
272 }
273
274 void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
275 {
276         ndr_print_dom_sid(ndr, name, sid);
277 }
278
279 void ndr_print_dom_sid0(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
280 {
281         ndr_print_dom_sid(ndr, name, sid);
282 }
283