r18193: Not quite to autogenerated NDR but closer thanks to Jelmer's
[kai/samba.git] / source3 / librpc / ndr / ndr_sec_helper.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    fast routines for getting the wire size of security objects
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 2 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
24 #include "includes.h"
25
26 /*
27   return the wire size of a dom_sid
28 */
29 size_t ndr_size_dom_sid(const struct dom_sid *sid, int flags)
30 {
31         if (!sid) return 0;
32         return 8 + 4*sid->num_auths;
33 }
34
35 /*
36   return the wire size of a security_ace
37 */
38 size_t ndr_size_security_ace(const struct security_ace *ace, int flags)
39 {
40         if (!ace) return 0;
41         return 8 + ndr_size_dom_sid(&ace->trustee, flags);
42 }
43
44
45 /*
46   return the wire size of a security_acl
47 */
48 size_t ndr_size_security_acl(const struct security_acl *acl, int flags)
49 {
50         size_t ret;
51         int i;
52         if (!acl) return 0;
53         ret = 8;
54         for (i=0;i<acl->num_aces;i++) {
55                 ret += ndr_size_security_ace(&acl->aces[i], flags);
56         }
57         return ret;
58 }
59
60 /*
61   return the wire size of a security descriptor
62 */
63 size_t ndr_size_security_descriptor(const struct security_descriptor *sd, int flags)
64 {
65         size_t ret;
66         if (!sd) return 0;
67         
68         ret = 20;
69         ret += ndr_size_dom_sid(sd->owner_sid, flags);
70         ret += ndr_size_dom_sid(sd->group_sid, flags);
71         ret += ndr_size_security_acl(sd->dacl, flags);
72         ret += ndr_size_security_acl(sd->sacl, flags);
73         return ret;
74 }
75
76 /*
77   print a dom_sid
78 */
79 void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
80 {
81         ndr->print(ndr, "%-25s: %s", name, dom_sid_string(ndr, sid));
82 }
83
84 void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
85 {
86         ndr_print_dom_sid(ndr, name, sid);
87 }
88
89 void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid)
90 {
91         ndr_print_dom_sid(ndr, name, sid);
92 }
93
94
95 /*
96   parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
97 */
98 NTSTATUS ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
99 {
100         uint32_t num_auths;
101         if (!(ndr_flags & NDR_SCALARS)) {
102                 return NT_STATUS_OK;
103         }
104         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &num_auths));
105         NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid));
106         if (sid->num_auths != num_auths) {
107                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, 
108                                       "Bad array size %u should exceed %u", 
109                                       num_auths, sid->num_auths);
110         }
111         return NT_STATUS_OK;
112 }
113
114 /*
115   parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field
116 */
117 NTSTATUS ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
118 {
119         if (!(ndr_flags & NDR_SCALARS)) {
120                 return NT_STATUS_OK;
121         }
122         NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, sid->num_auths));
123         return ndr_push_dom_sid(ndr, ndr_flags, sid);
124 }
125
126 /*
127   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
128 */
129 NTSTATUS ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid)
130 {
131         NTSTATUS status;
132         struct ndr_pull *subndr;
133
134         if (!(ndr_flags & NDR_SCALARS)) {
135                 return NT_STATUS_OK;
136         }
137
138         subndr = talloc_zero(ndr, struct ndr_pull);
139         NT_STATUS_HAVE_NO_MEMORY(subndr);
140         subndr->flags           = ndr->flags;
141         subndr->current_mem_ctx = ndr->current_mem_ctx;
142
143         subndr->data            = ndr->data + ndr->offset;
144         subndr->data_size       = 28;
145         subndr->offset          = 0;
146
147         NDR_CHECK(ndr_pull_advance(ndr, 28));
148
149         status = ndr_pull_dom_sid(subndr, ndr_flags, sid);
150         if (!NT_STATUS_IS_OK(status)) {
151                 /* handle a w2k bug which send random data in the buffer */
152                 ZERO_STRUCTP(sid);
153         }
154
155         return NT_STATUS_OK;
156 }
157
158 /*
159   push a dom_sid28 - this is a dom_sid in a 28 byte fixed buffer
160 */
161 NTSTATUS ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid)
162 {
163         uint32_t old_offset;
164         uint32_t padding;
165
166         if (!(ndr_flags & NDR_SCALARS)) {
167                 return NT_STATUS_OK;
168         }
169
170         if (sid->num_auths > 5) {
171                 return ndr_push_error(ndr, NDR_ERR_RANGE, 
172                                       "dom_sid28 allows only upto 5 sub auth [%u]", 
173                                       sid->num_auths);
174         }
175
176         old_offset = ndr->offset;
177         NDR_CHECK(ndr_push_dom_sid(ndr, ndr_flags, sid));
178
179         padding = 28 - (ndr->offset - old_offset);
180
181         if (padding > 0) {
182                 NDR_CHECK(ndr_push_zero(ndr, padding));
183         }
184
185         return NT_STATUS_OK;
186 }
187