Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Samba utility functions
4 :
5 : Copyright (C) Andrew Tridgell 2009
6 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
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 : #include "dsdb/samdb/samdb.h"
24 : #include <ldb_module.h>
25 : #include "librpc/ndr/libndr.h"
26 : #include "libcli/security/dom_sid.h"
27 : #include "lib/util/smb_strtox.h"
28 :
29 47983031 : enum dsdb_dn_format dsdb_dn_oid_to_format(const char *oid)
30 : {
31 47983031 : if (strcmp(oid, LDB_SYNTAX_DN) == 0) {
32 13591453 : return DSDB_NORMAL_DN;
33 33903770 : } else if (strcmp(oid, DSDB_SYNTAX_BINARY_DN) == 0) {
34 7230022 : return DSDB_BINARY_DN;
35 26651507 : } else if (strcmp(oid, DSDB_SYNTAX_STRING_DN) == 0) {
36 21535 : return DSDB_STRING_DN;
37 26629624 : } else if (strcmp(oid, DSDB_SYNTAX_OR_NAME) == 0) {
38 0 : return DSDB_NORMAL_DN;
39 : } else {
40 26629621 : return DSDB_INVALID_DN;
41 : }
42 : }
43 :
44 13664727 : static struct dsdb_dn *dsdb_dn_construct_internal(TALLOC_CTX *mem_ctx,
45 : struct ldb_dn *dn,
46 : DATA_BLOB extra_part,
47 : enum dsdb_dn_format dn_format,
48 : const char *oid)
49 : {
50 13664727 : struct dsdb_dn *dsdb_dn = talloc(mem_ctx, struct dsdb_dn);
51 13664727 : if (!dsdb_dn) {
52 0 : return NULL;
53 : }
54 13664727 : dsdb_dn->dn = talloc_steal(dsdb_dn, dn);
55 13664727 : dsdb_dn->extra_part = extra_part;
56 13664727 : dsdb_dn->dn_format = dn_format;
57 : /* Look to see if this attributeSyntax is a DN */
58 13664727 : if (dsdb_dn->dn_format == DSDB_INVALID_DN) {
59 0 : talloc_free(dsdb_dn);
60 0 : return NULL;
61 : }
62 :
63 13664727 : dsdb_dn->oid = oid;
64 13664727 : talloc_steal(dsdb_dn, extra_part.data);
65 13664727 : return dsdb_dn;
66 : }
67 :
68 3649363 : struct dsdb_dn *dsdb_dn_construct(TALLOC_CTX *mem_ctx, struct ldb_dn *dn, DATA_BLOB extra_part,
69 : const char *oid)
70 : {
71 3649363 : enum dsdb_dn_format dn_format = dsdb_dn_oid_to_format(oid);
72 3649363 : return dsdb_dn_construct_internal(mem_ctx, dn, extra_part, dn_format, oid);
73 : }
74 :
75 13526858 : struct dsdb_dn *dsdb_dn_parse_trusted(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
76 : const struct ldb_val *dn_blob, const char *dn_oid)
77 : {
78 : struct dsdb_dn *dsdb_dn;
79 : struct ldb_dn *dn;
80 : size_t len;
81 : TALLOC_CTX *tmp_ctx;
82 : char *p1;
83 : char *p2;
84 : uint32_t blen;
85 : struct ldb_val bval;
86 : struct ldb_val dval;
87 : char *dn_str;
88 13526858 : int error = 0;
89 :
90 13526858 : enum dsdb_dn_format dn_format = dsdb_dn_oid_to_format(dn_oid);
91 :
92 13526858 : if (dn_blob == NULL || dn_blob->data == NULL || dn_blob->length == 0) {
93 1 : return NULL;
94 : }
95 :
96 13526857 : switch (dn_format) {
97 0 : case DSDB_INVALID_DN:
98 0 : return NULL;
99 10015365 : case DSDB_NORMAL_DN:
100 : {
101 10015365 : dn = ldb_dn_from_ldb_val(mem_ctx, ldb, dn_blob);
102 10015365 : if (!dn) {
103 1 : talloc_free(dn);
104 1 : return NULL;
105 : }
106 10015364 : return dsdb_dn_construct_internal(mem_ctx, dn, data_blob_null, dn_format, dn_oid);
107 : }
108 3511480 : case DSDB_BINARY_DN:
109 3511480 : if (dn_blob->length < 2 || dn_blob->data[0] != 'B' || dn_blob->data[1] != ':') {
110 11 : return NULL;
111 : }
112 3502278 : break;
113 12 : case DSDB_STRING_DN:
114 12 : if (dn_blob->length < 2 || dn_blob->data[0] != 'S' || dn_blob->data[1] != ':') {
115 0 : return NULL;
116 : }
117 0 : break;
118 0 : default:
119 0 : return NULL;
120 : }
121 :
122 3511478 : if (strlen((const char*)dn_blob->data) != dn_blob->length) {
123 : /* The RDN must not contain a character with value 0x0 */
124 0 : return NULL;
125 : }
126 :
127 3511477 : tmp_ctx = talloc_new(mem_ctx);
128 3511477 : if (tmp_ctx == NULL) {
129 0 : return NULL;
130 : }
131 :
132 3511477 : len = dn_blob->length - 2;
133 3511477 : p1 = talloc_strndup(tmp_ctx, (const char *)dn_blob->data + 2, len);
134 3511477 : if (!p1) {
135 0 : goto failed;
136 : }
137 :
138 3511477 : errno = 0;
139 3511477 : blen = smb_strtoul(p1, &p2, 10, &error, SMB_STR_STANDARD);
140 3511477 : if (error != 0) {
141 0 : DEBUG(10, (__location__ ": failed\n"));
142 0 : goto failed;
143 : }
144 3511477 : if (p2 == NULL) {
145 0 : DEBUG(10, (__location__ ": failed\n"));
146 0 : goto failed;
147 : }
148 3511477 : if (p2[0] != ':') {
149 0 : DEBUG(10, (__location__ ": failed\n"));
150 0 : goto failed;
151 : }
152 3511477 : len -= PTR_DIFF(p2,p1);//???
153 3511477 : p1 = p2+1;
154 3511477 : len--;
155 :
156 3511477 : if (blen >= len) {
157 12 : DEBUG(10, (__location__ ": blen=%u len=%u\n", (unsigned)blen, (unsigned)len));
158 11 : goto failed;
159 : }
160 :
161 3511465 : p2 = p1 + blen;
162 3511465 : if (p2[0] != ':') {
163 6 : DEBUG(10, (__location__ ": %s", p2));
164 0 : goto failed;
165 : }
166 3511459 : dn_str = p2+1;
167 :
168 :
169 3511459 : switch (dn_format) {
170 3511450 : case DSDB_BINARY_DN:
171 3511450 : if ((blen % 2 != 0)) {
172 0 : DEBUG(10, (__location__ ": blen=%u - not an even number\n", (unsigned)blen));
173 0 : goto failed;
174 : }
175 :
176 3511450 : if (blen >= 2) {
177 3511449 : bval.length = (blen/2)+1;
178 3511449 : bval.data = talloc_size(tmp_ctx, bval.length);
179 3511449 : if (bval.data == NULL) {
180 0 : DEBUG(10, (__location__ ": err\n"));
181 0 : goto failed;
182 : }
183 3511449 : bval.data[bval.length-1] = 0;
184 :
185 3511449 : bval.length = strhex_to_str((char *)bval.data, bval.length,
186 : p1, blen);
187 3511449 : if (bval.length != (blen / 2)) {
188 2 : DEBUG(10, (__location__ ": non hexadecimal characters found in binary prefix\n"));
189 0 : goto failed;
190 : }
191 : } else {
192 1 : bval = data_blob_null;
193 : }
194 :
195 3502267 : break;
196 9 : case DSDB_STRING_DN:
197 9 : bval = data_blob(p1, blen);
198 9 : break;
199 0 : default:
200 : /* never reached */
201 0 : return NULL;
202 : }
203 :
204 :
205 3511457 : dval.data = (uint8_t *)dn_str;
206 3511457 : dval.length = strlen(dn_str);
207 :
208 3511457 : dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &dval);
209 3511457 : if (!dn) {
210 0 : DEBUG(10, (__location__ ": err\n"));
211 0 : goto failed;
212 : }
213 :
214 3511457 : dsdb_dn = dsdb_dn_construct(mem_ctx, dn, bval, dn_oid);
215 :
216 3511457 : talloc_free(tmp_ctx);
217 3511457 : return dsdb_dn;
218 :
219 11 : failed:
220 20 : talloc_free(tmp_ctx);
221 20 : return NULL;
222 : }
223 :
224 1187780 : struct dsdb_dn *dsdb_dn_parse(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
225 : const struct ldb_val *dn_blob, const char *dn_oid)
226 : {
227 1187780 : struct dsdb_dn *dsdb_dn = dsdb_dn_parse_trusted(mem_ctx, ldb,
228 : dn_blob, dn_oid);
229 1187780 : if (dsdb_dn == NULL) {
230 23 : return NULL;
231 : }
232 1187743 : if (ldb_dn_validate(dsdb_dn->dn) == false) {
233 15 : DEBUG(10, ("could not parse %.*s as a %s DN",
234 : (int)dn_blob->length, dn_blob->data,
235 : dn_oid));
236 13 : return NULL;
237 : }
238 1077484 : return dsdb_dn;
239 : }
240 :
241 12436841 : static char *dsdb_dn_get_with_postfix(TALLOC_CTX *mem_ctx,
242 : struct dsdb_dn *dsdb_dn,
243 : const char *postfix)
244 : {
245 12436841 : if (!postfix) {
246 0 : return NULL;
247 : }
248 :
249 12436841 : switch (dsdb_dn->dn_format) {
250 8942898 : case DSDB_NORMAL_DN:
251 : {
252 8942898 : return talloc_strdup(mem_ctx, postfix);
253 : }
254 3493929 : case DSDB_BINARY_DN:
255 : {
256 3493929 : char *hexstr = data_blob_hex_string_upper(mem_ctx, &dsdb_dn->extra_part);
257 :
258 3493929 : char *p = talloc_asprintf(mem_ctx, "B:%u:%s:%s", (unsigned)(dsdb_dn->extra_part.length*2), hexstr,
259 : postfix);
260 3493929 : talloc_free(hexstr);
261 3493929 : return p;
262 : }
263 14 : case DSDB_STRING_DN:
264 : {
265 14 : return talloc_asprintf(mem_ctx, "S:%u:%*.*s:%s",
266 0 : (unsigned)(dsdb_dn->extra_part.length),
267 0 : (int)(dsdb_dn->extra_part.length),
268 14 : (int)(dsdb_dn->extra_part.length),
269 14 : (const char *)dsdb_dn->extra_part.data,
270 : postfix);
271 : }
272 0 : default:
273 0 : return NULL;
274 : }
275 : }
276 :
277 3753332 : char *dsdb_dn_get_linearized(TALLOC_CTX *mem_ctx,
278 : struct dsdb_dn *dsdb_dn)
279 : {
280 3753332 : const char *postfix = ldb_dn_get_linearized(dsdb_dn->dn);
281 3753332 : return dsdb_dn_get_with_postfix(mem_ctx, dsdb_dn, postfix);
282 : }
283 :
284 1082 : char *dsdb_dn_get_casefold(TALLOC_CTX *mem_ctx,
285 : struct dsdb_dn *dsdb_dn)
286 : {
287 1082 : const char *postfix = ldb_dn_get_casefold(dsdb_dn->dn);
288 1082 : return dsdb_dn_get_with_postfix(mem_ctx, dsdb_dn, postfix);
289 : }
290 :
291 8682427 : char *dsdb_dn_get_extended_linearized(TALLOC_CTX *mem_ctx,
292 : struct dsdb_dn *dsdb_dn,
293 : int mode)
294 : {
295 8682427 : char *postfix = ldb_dn_get_extended_linearized(mem_ctx, dsdb_dn->dn, mode);
296 8682427 : char *ret = dsdb_dn_get_with_postfix(mem_ctx, dsdb_dn, postfix);
297 8682427 : talloc_free(postfix);
298 8682427 : return ret;
299 : }
300 :
301 1091 : int dsdb_dn_binary_canonicalise(struct ldb_context *ldb, void *mem_ctx,
302 : const struct ldb_val *in, struct ldb_val *out)
303 : {
304 1091 : struct dsdb_dn *dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
305 :
306 1091 : if (!dsdb_dn) {
307 22 : return -1;
308 : }
309 1068 : *out = data_blob_string_const(dsdb_dn_get_casefold(mem_ctx, dsdb_dn));
310 1068 : talloc_free(dsdb_dn);
311 1068 : if (!out->data) {
312 0 : return -1;
313 : }
314 1068 : return 0;
315 : }
316 :
317 389 : int dsdb_dn_binary_comparison(struct ldb_context *ldb, void *mem_ctx,
318 : const struct ldb_val *v1,
319 : const struct ldb_val *v2)
320 : {
321 389 : return ldb_any_comparison(ldb, mem_ctx, dsdb_dn_binary_canonicalise, v1, v2);
322 : }
323 :
324 9 : int dsdb_dn_string_canonicalise(struct ldb_context *ldb, void *mem_ctx,
325 : const struct ldb_val *in, struct ldb_val *out)
326 : {
327 9 : struct dsdb_dn *dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_STRING_DN);
328 :
329 9 : if (!dsdb_dn) {
330 0 : return -1;
331 : }
332 8 : *out = data_blob_string_const(dsdb_dn_get_casefold(mem_ctx, dsdb_dn));
333 8 : talloc_free(dsdb_dn);
334 8 : if (!out->data) {
335 0 : return -1;
336 : }
337 8 : return 0;
338 : }
339 :
340 4 : int dsdb_dn_string_comparison(struct ldb_context *ldb, void *mem_ctx,
341 : const struct ldb_val *v1,
342 : const struct ldb_val *v2)
343 : {
344 4 : return ldb_any_comparison(ldb, mem_ctx, dsdb_dn_string_canonicalise, v1, v2);
345 : }
346 :
347 : /*
348 : format a drsuapi_DsReplicaObjectIdentifier naming context as a string
349 : */
350 25289 : char *drs_ObjectIdentifier_to_string(TALLOC_CTX *mem_ctx,
351 : struct drsuapi_DsReplicaObjectIdentifier *nc)
352 : {
353 25289 : char *ret = NULL;
354 25289 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
355 25289 : if (!GUID_all_zero(&nc->guid)) {
356 18540 : char *guid = GUID_string(tmp_ctx, &nc->guid);
357 18540 : if (guid) {
358 18540 : ret = talloc_asprintf_append(ret, "<GUID=%s>;", guid);
359 : }
360 : }
361 25289 : if (nc->__ndr_size_sid != 0 && nc->sid.sid_rev_num != 0) {
362 8738 : const char *sid = dom_sid_string(tmp_ctx, &nc->sid);
363 8738 : if (sid) {
364 8738 : ret = talloc_asprintf_append(ret, "<SID=%s>;", sid);
365 : }
366 : }
367 25289 : if (nc->__ndr_size_dn != 0 && nc->dn) {
368 25289 : ret = talloc_asprintf_append(ret, "%s", nc->dn);
369 : }
370 25289 : talloc_free(tmp_ctx);
371 25289 : talloc_steal(mem_ctx, ret);
372 25289 : return ret;
373 : }
374 :
375 25289 : struct ldb_dn *drs_ObjectIdentifier_to_dn(TALLOC_CTX *mem_ctx,
376 : struct ldb_context *ldb,
377 : struct drsuapi_DsReplicaObjectIdentifier *nc)
378 : {
379 25289 : char *dn_string = drs_ObjectIdentifier_to_string(mem_ctx, nc);
380 : struct ldb_dn *new_dn;
381 25289 : new_dn = ldb_dn_new(mem_ctx, ldb, dn_string);
382 25289 : talloc_free(dn_string);
383 25289 : return new_dn;
384 : }
|