r23779: Change from v2 or later to v3 or later.
[kai/samba.git] / source / 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25 NTSTATUS ndr_push_dom_sid(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *r)
26 {
27         uint32_t cntr_sub_auths_0;
28         if (ndr_flags & NDR_SCALARS) {
29                 NDR_CHECK(ndr_push_align(ndr, 4));
30                 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, r->sid_rev_num));
31                 NDR_CHECK(ndr_push_int8(ndr, NDR_SCALARS, r->num_auths));
32                 NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
33                 for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
34                         NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->sub_auths[cntr_sub_auths_0]));
35                 }
36         }
37         if (ndr_flags & NDR_BUFFERS) {
38         }
39         return NT_STATUS_OK;
40 }
41
42 NTSTATUS ndr_pull_dom_sid(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *r)
43 {
44         uint32_t cntr_sub_auths_0;
45         if (ndr_flags & NDR_SCALARS) {
46                 NDR_CHECK(ndr_pull_align(ndr, 4));
47                 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->sid_rev_num));
48                 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &r->num_auths));
49                 if (r->num_auths > 15) {
50                         return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
51                 }
52                 NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, r->id_auth, 6));
53                 for (cntr_sub_auths_0 = 0; cntr_sub_auths_0 < r->num_auths; cntr_sub_auths_0++) {
54                         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sub_auths[cntr_sub_auths_0]));
55                 }
56         }
57         if (ndr_flags & NDR_BUFFERS) {
58         }
59         return NT_STATUS_OK;
60 }
61
62 /*
63   convert a dom_sid to a string
64 */
65 char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid)
66 {
67         int i, ofs, maxlen;
68         uint32_t ia;
69         char *ret;
70         
71         if (!sid) {
72                 return talloc_strdup(mem_ctx, "(NULL SID)");
73         }
74
75         maxlen = sid->num_auths * 11 + 25;
76         ret = (char *)talloc_size(mem_ctx, maxlen);
77         if (!ret) return talloc_strdup(mem_ctx, "(SID ERR)");
78
79         ia = (sid->id_auth[5]) +
80                 (sid->id_auth[4] << 8 ) +
81                 (sid->id_auth[3] << 16) +
82                 (sid->id_auth[2] << 24);
83
84         ofs = snprintf(ret, maxlen, "S-%u-%lu", 
85                        (unsigned int)sid->sid_rev_num, (unsigned long)ia);
86
87         for (i = 0; i < sid->num_auths; i++) {
88                 ofs += snprintf(ret + ofs, maxlen - ofs, "-%lu", (unsigned long)sid->sub_auths[i]);
89         }
90         
91         return ret;
92 }
93
94 /*
95   parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
96 */
97 NTSTATUS ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
98 {
99         uint32_t num_auths;
100         if (!(ndr_flags & NDR_SCALARS)) {
101                 return NT_STATUS_OK;
102         }
103         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &num_auths));
104         NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid));
105         if (sid->num_auths != num_auths) {
106                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
107                                       "Bad array size %u should exceed %u", 
108                                       num_auths, sid->num_auths);
109         }
110         return NT_STATUS_OK;
111 }
112
113 /*
114   parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
115 */
116 NTSTATUS ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
117 {
118         if (!(ndr_flags & NDR_SCALARS)) {
119                 return NT_STATUS_OK;
120         }
121         NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, sid->num_auths));
122         return ndr_push_dom_sid(ndr, ndr_flags, sid);
123 }
124
125 /*
126   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
127 */
128 NTSTATUS ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
129 {
130         NTSTATUS status;
131         struct ndr_pull *subndr;
132
133         if (!(ndr_flags & NDR_SCALARS)) {
134                 return NT_STATUS_OK;
135         }
136
137         subndr = talloc_zero(ndr, struct ndr_pull);
138         NT_STATUS_HAVE_NO_MEMORY(subndr);
139         subndr->flags           = ndr->flags;
140         subndr->current_mem_ctx = ndr->current_mem_ctx;
141
142         subndr->data            = ndr->data + ndr->offset;
143         subndr->data_size       = 28;
144         subndr->offset          = 0;
145
146         NDR_CHECK(ndr_pull_advance(ndr, 28));
147
148         status = ndr_pull_dom_sid(subndr, ndr_flags, sid);
149         if (!NT_STATUS_IS_OK(status)) {
150                 /* handle a w2k bug which send random data in the buffer */
151                 ZERO_STRUCTP(sid);
152         }
153
154         return NT_STATUS_OK;
155 }
156
157 /*
158   push a dom_sid28 - this is a dom_sid in a 28 byte fixed buffer
159 */
160 NTSTATUS ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
161 {
162         uint32_t old_offset;
163         uint32_t padding;
164
165         if (!(ndr_flags & NDR_SCALARS)) {
166                 return NT_STATUS_OK;
167         }
168
169         if (sid->num_auths > 5) {
170                 return ndr_push_error(ndr, NDR_ERR_RANGE, 
171                                       "dom_sid28 allows only upto 5 sub auth [%u]", 
172                                       sid->num_auths);
173         }
174
175         old_offset = ndr->offset;
176         NDR_CHECK(ndr_push_dom_sid(ndr, ndr_flags, sid));
177
178         padding = 28 - (ndr->offset - old_offset);
179
180         if (padding > 0) {
181                 NDR_CHECK(ndr_push_zero(ndr, padding));
182         }
183
184         return NT_STATUS_OK;
185 }
186
187 NTSTATUS ndr_push_sec_desc_buf(struct ndr_push *ndr, int ndr_flags, const struct sec_desc_buf *r)
188 {
189         if (ndr_flags & NDR_SCALARS) {
190                 NDR_CHECK(ndr_push_align(ndr, 4));
191                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_size_security_descriptor(r->sd,ndr->flags)));
192                 NDR_CHECK(ndr_push_unique_ptr(ndr, r->sd));
193         }
194         if (ndr_flags & NDR_BUFFERS) {
195                 if (r->sd) {
196                         {
197                                 struct ndr_push *_ndr_sd;
198                                 NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_sd, 4, -1));
199                                 NDR_CHECK(ndr_push_security_descriptor(_ndr_sd, NDR_SCALARS|NDR_BUFFERS, r->sd));
200                                 NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_sd, 4, -1));
201                         }
202                 }
203         }
204         return NT_STATUS_OK;
205 }
206
207 NTSTATUS ndr_pull_sec_desc_buf(struct ndr_pull *ndr, int ndr_flags, struct sec_desc_buf *r)
208 {
209         uint32_t _ptr_sd;
210         TALLOC_CTX *_mem_save_sd_0;
211         if (ndr_flags & NDR_SCALARS) {
212                 NDR_CHECK(ndr_pull_align(ndr, 4));
213                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->sd_size));
214                 if (r->sd_size > 0x40000) { /* sd_size is unsigned */
215                         return ndr_pull_error(ndr, NDR_ERR_RANGE, "value out of range");
216                 }
217                 NDR_CHECK(ndr_pull_generic_ptr(ndr, &_ptr_sd));
218                 if (_ptr_sd) {
219                         NDR_PULL_ALLOC(ndr, r->sd);
220                 } else {
221                         r->sd = NULL;
222                 }
223         }
224         if (ndr_flags & NDR_BUFFERS) {
225                 if (r->sd) {
226                         _mem_save_sd_0 = NDR_PULL_GET_MEM_CTX(ndr);
227                         NDR_PULL_SET_MEM_CTX(ndr, r->sd, 0);
228                         {
229                                 struct ndr_pull *_ndr_sd;
230                                 NDR_CHECK(ndr_pull_subcontext_start(ndr, &_ndr_sd, 4, -1));
231                                 NDR_CHECK(ndr_pull_security_descriptor(_ndr_sd, NDR_SCALARS|NDR_BUFFERS, r->sd));
232                                 NDR_CHECK(ndr_pull_subcontext_end(ndr, _ndr_sd, 4, -1));
233                         }
234                         NDR_PULL_SET_MEM_CTX(ndr, _mem_save_sd_0, 0);
235                 }
236         }
237         return NT_STATUS_OK;
238 }
239
240 void ndr_print_sec_desc_buf(struct ndr_print *ndr, const char *name, const struct sec_desc_buf *r)
241 {
242         ndr_print_struct(ndr, name, "sec_desc_buf");
243         ndr->depth++;
244         ndr_print_uint32(ndr, "sd_size", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?ndr_size_security_descriptor(r->sd,ndr->flags):r->sd_size);
245         ndr_print_ptr(ndr, "sd", r->sd);
246         ndr->depth++;
247         if (r->sd) {
248                 ndr_print_security_descriptor(ndr, "sd", r->sd);
249         }
250         ndr->depth--;
251         ndr->depth--;
252 }