r12608: Remove some unused #include lines.
[abartlet/samba.git/.git] / source4 / lib / ldb / samba / ldif_handlers.c
1 /* 
2    ldb database library - ldif handlers for Samba
3
4    Copyright (C) Andrew Tridgell  2005
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 #include "includes.h"
26 #include "ldb/include/ldb.h"
27 #include "ldb/include/ldb_private.h"
28 #include "librpc/gen_ndr/ndr_misc.h"
29 #include "dsdb/samdb/samdb.h"
30
31 /*
32   convert a ldif formatted objectSid to a NDR formatted blob
33 */
34 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
35                                const struct ldb_val *in, struct ldb_val *out)
36 {
37         struct dom_sid *sid;
38         NTSTATUS status;
39         sid = dom_sid_parse_talloc(mem_ctx, (const char *)in->data);
40         if (sid == NULL) {
41                 return -1;
42         }
43         status = ndr_push_struct_blob(out, mem_ctx, sid, 
44                                       (ndr_push_flags_fn_t)ndr_push_dom_sid);
45         talloc_free(sid);
46         if (!NT_STATUS_IS_OK(status)) {
47                 return -1;
48         }
49         return 0;
50 }
51
52 /*
53   convert a NDR formatted blob to a ldif formatted objectSid
54 */
55 static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
56                                 const struct ldb_val *in, struct ldb_val *out)
57 {
58         struct dom_sid *sid;
59         NTSTATUS status;
60         sid = talloc(mem_ctx, struct dom_sid);
61         if (sid == NULL) {
62                 return -1;
63         }
64         status = ndr_pull_struct_blob(in, sid, sid, 
65                                       (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
66         if (!NT_STATUS_IS_OK(status)) {
67                 talloc_free(sid);
68                 return -1;
69         }
70         out->data = (uint8_t *)dom_sid_string(mem_ctx, sid);
71         talloc_free(sid);
72         if (out->data == NULL) {
73                 return -1;
74         }
75         out->length = strlen((const char *)out->data);
76         return 0;
77 }
78
79 static BOOL ldb_comparision_objectSid_isString(const struct ldb_val *v)
80 {
81         /* see if the input if null-terninated */
82         if (v->data[v->length] != '\0') return False;
83         
84         if (strncmp("S-", (const char *)v->data, 2) != 0) return False;
85         return True;
86 }
87
88 /*
89   compare two objectSids
90 */
91 static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
92                                     const struct ldb_val *v1, const struct ldb_val *v2)
93 {
94         if (ldb_comparision_objectSid_isString(v1)) {
95                 if (ldb_comparision_objectSid_isString(v1)) {
96                         return strcmp((const char *)v1->data, (const char *)v2->data);
97                 } else {
98                         struct ldb_val v;
99                         int ret;
100                         if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
101                                 return -1;
102                         }
103                         ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
104                         talloc_free(v.data);
105                         return ret;
106                 }
107         }
108         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
109 }
110
111 /*
112   canonicalise a objectSid
113 */
114 static int ldb_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
115                                       const struct ldb_val *in, struct ldb_val *out)
116 {
117         if (ldb_comparision_objectSid_isString(in)) {
118                 return ldif_read_objectSid(ldb, mem_ctx, in, out);
119         }
120         return ldb_handler_copy(ldb, mem_ctx, in, out);
121 }
122
123 /*
124   convert a ldif formatted objectGUID to a NDR formatted blob
125 */
126 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
127                                 const struct ldb_val *in, struct ldb_val *out)
128 {
129         struct GUID guid;
130         NTSTATUS status;
131
132         status = GUID_from_string((const char *)in->data, &guid);
133         if (!NT_STATUS_IS_OK(status)) {
134                 return -1;
135         }
136
137         status = ndr_push_struct_blob(out, mem_ctx, &guid,
138                                       (ndr_push_flags_fn_t)ndr_push_GUID);
139         if (!NT_STATUS_IS_OK(status)) {
140                 return -1;
141         }
142         return 0;
143 }
144
145 /*
146   convert a NDR formatted blob to a ldif formatted objectGUID
147 */
148 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
149                                  const struct ldb_val *in, struct ldb_val *out)
150 {
151         struct GUID guid;
152         NTSTATUS status;
153         status = ndr_pull_struct_blob(in, mem_ctx, &guid,
154                                       (ndr_pull_flags_fn_t)ndr_pull_GUID);
155         if (!NT_STATUS_IS_OK(status)) {
156                 return -1;
157         }
158         out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
159         if (out->data == NULL) {
160                 return -1;
161         }
162         out->length = strlen((const char *)out->data);
163         return 0;
164 }
165
166 static BOOL ldb_comparision_objectGUID_isString(const struct ldb_val *v)
167 {
168         struct GUID guid;
169         NTSTATUS status;
170
171         /* see if the input if null-terninated */
172         if (v->data[v->length] != '\0') return False;
173
174         status = GUID_from_string((const char *)v->data, &guid);
175         if (!NT_STATUS_IS_OK(status)) {
176                 return False;
177         }
178
179         return True;
180 }
181
182 /*
183   compare two objectGUIDs
184 */
185 static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
186                                      const struct ldb_val *v1, const struct ldb_val *v2)
187 {
188         if (ldb_comparision_objectGUID_isString(v1)) {
189                 if (ldb_comparision_objectGUID_isString(v2)) {
190                         return strcmp((const char *)v1->data, (const char *)v2->data);
191                 } else {
192                         struct ldb_val v;
193                         int ret;
194                         if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
195                                 return -1;
196                         }
197                         ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
198                         talloc_free(v.data);
199                         return ret;
200                 }
201         }
202         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
203 }
204
205 /*
206   canonicalise a objectGUID
207 */
208 static int ldb_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
209                                        const struct ldb_val *in, struct ldb_val *out)
210 {
211         if (ldb_comparision_objectGUID_isString(in)) {
212                 return ldif_read_objectGUID(ldb, mem_ctx, in, out);
213         }
214         return ldb_handler_copy(ldb, mem_ctx, in, out);
215 }
216
217
218 /*
219   convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
220 */
221 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
222                                           const struct ldb_val *in, struct ldb_val *out)
223 {
224         struct security_descriptor *sd;
225         NTSTATUS status;
226         const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
227         if (domain_sid == NULL) {
228                 return ldb_handler_copy(ldb, mem_ctx, in, out);
229         }
230         sd = sddl_decode(mem_ctx, (const char *)in->data, domain_sid);
231         if (sd == NULL) {
232                 return -1;
233         }
234         status = ndr_push_struct_blob(out, mem_ctx, sd, 
235                                       (ndr_push_flags_fn_t)ndr_push_security_descriptor);
236         talloc_free(sd);
237         if (!NT_STATUS_IS_OK(status)) {
238                 return -1;
239         }
240         return 0;
241 }
242
243 /*
244   convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
245 */
246 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
247                                            const struct ldb_val *in, struct ldb_val *out)
248 {
249         struct security_descriptor *sd;
250         NTSTATUS status;
251         const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
252
253         if (domain_sid == NULL) {
254                 return ldb_handler_copy(ldb, mem_ctx, in, out);
255         }
256
257         sd = talloc(mem_ctx, struct security_descriptor);
258         if (sd == NULL) {
259                 return -1;
260         }
261         status = ndr_pull_struct_blob(in, sd, sd, 
262                                       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
263         if (!NT_STATUS_IS_OK(status)) {
264                 talloc_free(sd);
265                 return -1;
266         }
267         out->data = (uint8_t *)sddl_encode(mem_ctx, sd, domain_sid);
268         talloc_free(sd);
269         if (out->data == NULL) {
270                 return -1;
271         }
272         out->length = strlen((const char *)out->data);
273         return 0;
274 }
275
276 static const struct ldb_attrib_handler samba_handlers[] = {
277         { 
278                 .attr            = "objectSid",
279                 .flags           = 0,
280                 .ldif_read_fn    = ldif_read_objectSid,
281                 .ldif_write_fn   = ldif_write_objectSid,
282                 .canonicalise_fn = ldb_canonicalise_objectSid,
283                 .comparison_fn   = ldb_comparison_objectSid
284         },
285         { 
286                 .attr            = "securityIdentifier",
287                 .flags           = 0,
288                 .ldif_read_fn    = ldif_read_objectSid,
289                 .ldif_write_fn   = ldif_write_objectSid,
290                 .canonicalise_fn = ldb_canonicalise_objectSid,
291                 .comparison_fn   = ldb_comparison_objectSid
292         },
293         { 
294                 .attr            = "ntSecurityDescriptor",
295                 .flags           = 0,
296                 .ldif_read_fn    = ldif_read_ntSecurityDescriptor,
297                 .ldif_write_fn   = ldif_write_ntSecurityDescriptor,
298                 .canonicalise_fn = ldb_handler_copy,
299                 .comparison_fn   = ldb_comparison_binary
300         },
301         { 
302                 .attr            = "objectGUID",
303                 .flags           = 0,
304                 .ldif_read_fn    = ldif_read_objectGUID,
305                 .ldif_write_fn   = ldif_write_objectGUID,
306                 .canonicalise_fn = ldb_canonicalise_objectGUID,
307                 .comparison_fn   = ldb_comparison_objectGUID
308         },
309         { 
310                 .attr            = "invocationId",
311                 .flags           = 0,
312                 .ldif_read_fn    = ldif_read_objectGUID,
313                 .ldif_write_fn   = ldif_write_objectGUID,
314                 .canonicalise_fn = ldb_canonicalise_objectGUID,
315                 .comparison_fn   = ldb_comparison_objectGUID
316         },
317         { 
318                 .attr            = "schemaIDGUID",
319                 .flags           = 0,
320                 .ldif_read_fn    = ldif_read_objectGUID,
321                 .ldif_write_fn   = ldif_write_objectGUID,
322                 .canonicalise_fn = ldb_canonicalise_objectGUID,
323                 .comparison_fn   = ldb_comparison_objectGUID
324         }
325 };
326
327 /*
328   register the samba ldif handlers
329 */
330 int ldb_register_samba_handlers(struct ldb_context *ldb)
331 {
332         return ldb_set_attrib_handlers(ldb, samba_handlers, ARRAY_SIZE(samba_handlers));
333 }