Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : CLDAP server - netlogon handling
5 :
6 : Copyright (C) Andrew Tridgell 2005
7 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include <ldb.h>
25 : #include <ldb_errors.h>
26 : #include "lib/events/events.h"
27 : #include "samba/service_task.h"
28 : #include "librpc/gen_ndr/ndr_misc.h"
29 : #include "libcli/ldap/ldap_ndr.h"
30 : #include "libcli/security/security.h"
31 : #include "dsdb/samdb/samdb.h"
32 : #include "dsdb/samdb/ldb_modules/util.h"
33 : #include "auth/auth.h"
34 : #include "ldb_wrap.h"
35 : #include "system/network.h"
36 : #include "lib/socket/netif.h"
37 : #include "param/param.h"
38 : #include "../lib/tsocket/tsocket.h"
39 : #include "libds/common/flag_mapping.h"
40 : #include "lib/util/util_net.h"
41 :
42 : #undef strcasecmp
43 :
44 : /*
45 : fill in the cldap netlogon union for a given version
46 : */
47 3277 : NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
48 : TALLOC_CTX *mem_ctx,
49 : const char *domain,
50 : const char *netbios_domain,
51 : struct dom_sid *domain_sid,
52 : const char *domain_guid,
53 : const char *user,
54 : uint32_t acct_control,
55 : const char *src_address,
56 : uint32_t version,
57 : struct loadparm_context *lp_ctx,
58 : struct netlogon_samlogon_response *netlogon,
59 : bool fill_on_blank_request)
60 : {
61 3277 : const char *dom_attrs[] = {"objectGUID", NULL};
62 3277 : const char *none_attrs[] = {NULL};
63 3277 : struct ldb_result *dom_res = NULL;
64 62 : int ret;
65 3277 : const char **services = lpcfg_server_services(lp_ctx);
66 62 : uint32_t server_type;
67 62 : const char *pdc_name;
68 62 : struct GUID domain_uuid;
69 62 : const char *dns_domain;
70 62 : const char *forest_domain;
71 62 : const char *pdc_dns_name;
72 62 : const char *flatname;
73 62 : const char *server_site;
74 62 : const char *client_site;
75 62 : const char *pdc_ip;
76 3277 : struct ldb_dn *domain_dn = NULL;
77 62 : struct interface *ifaces;
78 3277 : bool user_known = false, am_rodc = false;
79 3277 : uint32_t uac = 0;
80 62 : int dc_level;
81 62 : NTSTATUS status;
82 :
83 : /* the domain parameter could have an optional trailing "." */
84 3277 : if (domain && domain[strlen(domain)-1] == '.') {
85 150 : domain = talloc_strndup(mem_ctx, domain, strlen(domain)-1);
86 150 : NT_STATUS_HAVE_NO_MEMORY(domain);
87 : }
88 :
89 : /* Lookup using long or short domainname */
90 3277 : if (domain && (strcasecmp_m(domain, lpcfg_dnsdomain(lp_ctx)) == 0)) {
91 3008 : domain_dn = ldb_get_default_basedn(sam_ctx);
92 : }
93 3277 : if (netbios_domain && (strcasecmp_m(netbios_domain, lpcfg_sam_name(lp_ctx)) == 0)) {
94 118 : domain_dn = ldb_get_default_basedn(sam_ctx);
95 : }
96 3277 : if (domain_dn) {
97 3183 : const char *domain_identifier = domain != NULL ? domain
98 3126 : : netbios_domain;
99 3126 : ret = ldb_search(sam_ctx, mem_ctx, &dom_res,
100 : domain_dn, LDB_SCOPE_BASE, dom_attrs,
101 : "objectClass=domain");
102 3126 : if (ret != LDB_SUCCESS) {
103 0 : DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n",
104 : domain_identifier,
105 : ldb_dn_get_linearized(domain_dn),
106 : ldb_errstring(sam_ctx)));
107 0 : return NT_STATUS_NO_SUCH_DOMAIN;
108 : }
109 3126 : if (dom_res->count != 1) {
110 0 : DEBUG(2,("Error finding domain '%s'/'%s' in sam\n",
111 : domain_identifier,
112 : ldb_dn_get_linearized(domain_dn)));
113 0 : return NT_STATUS_NO_SUCH_DOMAIN;
114 : }
115 : }
116 :
117 : /* Lookup using GUID or SID */
118 3277 : if ((dom_res == NULL) && (domain_guid || domain_sid)) {
119 8 : if (domain_guid) {
120 0 : struct GUID binary_guid;
121 0 : struct ldb_val guid_val;
122 :
123 : /* By this means, we ensure we don't have funny stuff in the GUID */
124 :
125 8 : status = GUID_from_string(domain_guid, &binary_guid);
126 8 : if (!NT_STATUS_IS_OK(status)) {
127 0 : return status;
128 : }
129 :
130 : /* And this gets the result into the binary format we want anyway */
131 8 : status = GUID_to_ndr_blob(&binary_guid, mem_ctx, &guid_val);
132 8 : if (!NT_STATUS_IS_OK(status)) {
133 0 : return status;
134 : }
135 8 : ret = ldb_search(sam_ctx, mem_ctx, &dom_res,
136 : NULL, LDB_SCOPE_SUBTREE,
137 : dom_attrs,
138 : "(&(objectCategory=DomainDNS)(objectGUID=%s))",
139 : ldb_binary_encode(mem_ctx, guid_val));
140 : } else { /* domain_sid case */
141 0 : ret = ldb_search(sam_ctx, mem_ctx, &dom_res,
142 : NULL, LDB_SCOPE_SUBTREE,
143 : dom_attrs,
144 : "(&(objectCategory=DomainDNS)(objectSid=%s))",
145 : dom_sid_string(mem_ctx, domain_sid));
146 : }
147 :
148 8 : if (ret != LDB_SUCCESS) {
149 0 : DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam: %s\n",
150 : domain_guid, dom_sid_string(mem_ctx, domain_sid),
151 : ldb_errstring(sam_ctx)));
152 0 : return NT_STATUS_NO_SUCH_DOMAIN;
153 8 : } else if (dom_res->count == 1) {
154 : /* Ok, now just check it is our domain */
155 4 : if (ldb_dn_compare(ldb_get_default_basedn(sam_ctx),
156 4 : dom_res->msgs[0]->dn) != 0) {
157 0 : DEBUG(2,("The GUID '%s' or SID '%s' doesn't identify our domain\n",
158 : domain_guid,
159 : dom_sid_string(mem_ctx, domain_sid)));
160 0 : return NT_STATUS_NO_SUCH_DOMAIN;
161 : }
162 : } else {
163 4 : DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam\n",
164 : domain_guid, dom_sid_string(mem_ctx, domain_sid)));
165 4 : return NT_STATUS_NO_SUCH_DOMAIN;
166 : }
167 : }
168 :
169 3273 : if (dom_res == NULL && fill_on_blank_request) {
170 : /* blank inputs gives our domain - tested against
171 : w2k8r2. Without this ADUC on Win7 won't start */
172 141 : domain_dn = ldb_get_default_basedn(sam_ctx);
173 141 : ret = ldb_search(sam_ctx, mem_ctx, &dom_res,
174 : domain_dn, LDB_SCOPE_BASE, dom_attrs,
175 : "objectClass=domain");
176 141 : if (ret != LDB_SUCCESS) {
177 0 : DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n",
178 : lpcfg_dnsdomain(lp_ctx),
179 : ldb_dn_get_linearized(domain_dn),
180 : ldb_errstring(sam_ctx)));
181 0 : return NT_STATUS_NO_SUCH_DOMAIN;
182 : }
183 : }
184 :
185 3273 : if (dom_res == NULL) {
186 2 : DEBUG(2,(__location__ ": Unable to get domain information with no inputs\n"));
187 2 : return NT_STATUS_NO_SUCH_DOMAIN;
188 : }
189 :
190 : /* work around different inputs for not-specified users */
191 3271 : if (!user) {
192 2331 : user = "";
193 : }
194 :
195 : /* Enquire about any valid username with just a CLDAP packet -
196 : * if kerberos didn't also do this, the security folks would
197 : * scream... */
198 3271 : if (user[0]) {
199 : /* Only allow some bits to be enquired: [MS-ATDS] 7.3.3.2 */
200 937 : if (acct_control == (uint32_t)-1) {
201 740 : acct_control = 0;
202 : }
203 : /*
204 : * ACB_AUTOLOCK/UF_LOCKOUT seems to be a special
205 : * hack for SEC_CHAN_DNS_DOMAIN.
206 : *
207 : * It's used together with user = "example.com."
208 : */
209 937 : if (acct_control != ACB_AUTOLOCK) {
210 865 : acct_control &= (ACB_TEMPDUP | ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST);
211 : }
212 937 : uac = ds_acb2uf(acct_control);
213 : }
214 :
215 3212 : if (uac == UF_LOCKOUT) {
216 72 : struct ldb_message *tdo_msg = NULL;
217 :
218 : /*
219 : * ACB_AUTOLOCK/UF_LOCKOUT seems to be a special
220 : * hack for SEC_CHAN_DNS_DOMAIN.
221 : *
222 : * It's used together with user = "example.com."
223 : */
224 72 : status = dsdb_trust_search_tdo_by_type(sam_ctx,
225 : SEC_CHAN_DNS_DOMAIN,
226 : user, none_attrs,
227 : mem_ctx, &tdo_msg);
228 72 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
229 0 : user_known = false;
230 72 : } else if (NT_STATUS_IS_OK(status)) {
231 72 : TALLOC_FREE(tdo_msg);
232 72 : user_known = true;
233 : } else {
234 0 : DEBUG(2,("Unable to find reference to TDO '%s' - %s\n",
235 : user, nt_errstr(status)));
236 0 : return status;
237 : }
238 3199 : } else if (user[0]) {
239 865 : struct ldb_result *user_res = NULL;
240 865 : const char *user_encoded = NULL;
241 :
242 865 : user_encoded = ldb_binary_encode_string(mem_ctx, user);
243 865 : if (user_encoded == NULL) {
244 0 : return NT_STATUS_NO_MEMORY;
245 : }
246 :
247 : /* We must exclude disabled accounts, but otherwise do the bitwise match the client asked for */
248 868 : ret = ldb_search(sam_ctx, mem_ctx, &user_res,
249 865 : dom_res->msgs[0]->dn, LDB_SCOPE_SUBTREE,
250 : none_attrs,
251 : "(&(objectClass=user)(samAccountName=%s)"
252 : "(!(userAccountControl:" LDB_OID_COMPARATOR_AND ":=%u))"
253 : "(userAccountControl:" LDB_OID_COMPARATOR_OR ":=%u))",
254 : user_encoded,
255 : UF_ACCOUNTDISABLE, uac);
256 865 : if (ret != LDB_SUCCESS) {
257 0 : DEBUG(2,("Unable to find reference to user '%s' with ACB 0x%8x under %s: %s\n",
258 : user, acct_control, ldb_dn_get_linearized(dom_res->msgs[0]->dn),
259 : ldb_errstring(sam_ctx)));
260 0 : return NT_STATUS_NO_SUCH_USER;
261 865 : } else if (user_res->count == 1) {
262 97 : user_known = true;
263 : } else {
264 765 : user_known = false;
265 : }
266 865 : TALLOC_FREE(user_res);
267 : } else {
268 2275 : user_known = true;
269 : }
270 :
271 3271 : server_type = DS_SERVER_DS;
272 :
273 3271 : if (samdb_is_pdc(sam_ctx)) {
274 3215 : server_type |= DS_SERVER_PDC;
275 : }
276 :
277 3271 : if (samdb_is_gc(sam_ctx)) {
278 3271 : server_type |= DS_SERVER_GC;
279 : }
280 :
281 3271 : if (str_list_check(services, "ldap")) {
282 3271 : server_type |= DS_SERVER_LDAP;
283 : }
284 :
285 3271 : if (str_list_check(services, "kdc")) {
286 3271 : server_type |= DS_SERVER_KDC;
287 : }
288 :
289 3271 : if (str_list_check(services, "ntp_signd")) {
290 3271 : server_type |= DS_SERVER_TIMESERV | DS_SERVER_GOOD_TIMESERV;
291 : }
292 :
293 3271 : if (samdb_rodc(sam_ctx, &am_rodc) == LDB_SUCCESS && !am_rodc) {
294 3271 : server_type |= DS_SERVER_WRITABLE;
295 : }
296 :
297 3271 : dc_level = dsdb_dc_functional_level(sam_ctx);
298 3271 : if (dc_level >= DS_DOMAIN_FUNCTION_2008) {
299 3271 : if (server_type & DS_SERVER_WRITABLE) {
300 3271 : server_type |= DS_SERVER_FULL_SECRET_DOMAIN_6;
301 : } else {
302 0 : server_type |= DS_SERVER_SELECT_SECRET_DOMAIN_6;
303 : }
304 : }
305 :
306 3271 : if (dc_level >= DS_DOMAIN_FUNCTION_2012) {
307 2690 : server_type |= DS_SERVER_DS_8;
308 : }
309 :
310 3271 : if (dc_level >= DS_DOMAIN_FUNCTION_2012_R2) {
311 2690 : server_type |= DS_SERVER_DS_9;
312 : }
313 :
314 3271 : if (dc_level >= DS_DOMAIN_FUNCTION_2016) {
315 2690 : server_type |= DS_SERVER_DS_10;
316 : }
317 :
318 3271 : if (version & (NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) {
319 3056 : pdc_name = lpcfg_netbios_name(lp_ctx);
320 : } else {
321 215 : pdc_name = talloc_asprintf(mem_ctx, "\\\\%s",
322 : lpcfg_netbios_name(lp_ctx));
323 215 : NT_STATUS_HAVE_NO_MEMORY(pdc_name);
324 : }
325 3271 : domain_uuid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
326 3271 : dns_domain = lpcfg_dnsdomain(lp_ctx);
327 3271 : forest_domain = samdb_forest_name(sam_ctx, mem_ctx);
328 3271 : NT_STATUS_HAVE_NO_MEMORY(forest_domain);
329 3271 : pdc_dns_name = talloc_asprintf(mem_ctx, "%s.%s",
330 : strlower_talloc(mem_ctx,
331 : lpcfg_netbios_name(lp_ctx)),
332 : dns_domain);
333 3271 : NT_STATUS_HAVE_NO_MEMORY(pdc_dns_name);
334 3271 : flatname = lpcfg_workgroup(lp_ctx);
335 :
336 3271 : server_site = samdb_server_site_name(sam_ctx, mem_ctx);
337 3271 : NT_STATUS_HAVE_NO_MEMORY(server_site);
338 3271 : client_site = samdb_client_site_name(sam_ctx, mem_ctx,
339 : src_address, NULL,
340 : true);
341 3271 : NT_STATUS_HAVE_NO_MEMORY(client_site);
342 3271 : if (strcasecmp(server_site, client_site) == 0) {
343 3131 : server_type |= DS_SERVER_CLOSEST;
344 : }
345 :
346 3271 : load_interface_list(mem_ctx, lp_ctx, &ifaces);
347 3271 : if (src_address) {
348 3173 : pdc_ip = iface_list_best_ip(ifaces, src_address);
349 : } else {
350 98 : pdc_ip = iface_list_first_v4(ifaces);
351 : }
352 3271 : if (pdc_ip == NULL || !is_ipaddress_v4(pdc_ip)) {
353 : /* this matches windows behaviour */
354 475 : pdc_ip = "127.0.0.1";
355 : }
356 :
357 3271 : ZERO_STRUCTP(netlogon);
358 :
359 : /* check if either of these bits is present */
360 3271 : if (version & (NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) {
361 3056 : uint32_t extra_flags = 0;
362 3056 : netlogon->ntver = NETLOGON_NT_VERSION_5EX;
363 :
364 : /* could check if the user exists */
365 3056 : if (user_known) {
366 2494 : netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_RESPONSE_EX;
367 : } else {
368 562 : netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_USER_UNKNOWN_EX;
369 : }
370 3056 : netlogon->data.nt5_ex.pdc_name = pdc_name;
371 3056 : netlogon->data.nt5_ex.user_name = user;
372 3056 : netlogon->data.nt5_ex.domain_name = flatname;
373 3056 : netlogon->data.nt5_ex.domain_uuid = domain_uuid;
374 3056 : netlogon->data.nt5_ex.forest = forest_domain;
375 3056 : netlogon->data.nt5_ex.dns_domain = dns_domain;
376 3056 : netlogon->data.nt5_ex.pdc_dns_name = pdc_dns_name;
377 3056 : netlogon->data.nt5_ex.server_site = server_site;
378 3056 : netlogon->data.nt5_ex.client_site = client_site;
379 3056 : if (version & NETLOGON_NT_VERSION_5EX_WITH_IP) {
380 : /* note that this is always a IPV4 address */
381 559 : extra_flags = NETLOGON_NT_VERSION_5EX_WITH_IP;
382 559 : netlogon->data.nt5_ex.sockaddr.sockaddr_family = 2;
383 559 : netlogon->data.nt5_ex.sockaddr.pdc_ip = pdc_ip;
384 559 : netlogon->data.nt5_ex.sockaddr.remaining = data_blob_talloc_zero(mem_ctx, 8);
385 : }
386 3056 : netlogon->data.nt5_ex.server_type = server_type;
387 3056 : netlogon->data.nt5_ex.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5EX|extra_flags;
388 3056 : netlogon->data.nt5_ex.lmnt_token = 0xFFFF;
389 3056 : netlogon->data.nt5_ex.lm20_token = 0xFFFF;
390 :
391 215 : } else if (version & NETLOGON_NT_VERSION_5) {
392 73 : netlogon->ntver = NETLOGON_NT_VERSION_5;
393 :
394 : /* could check if the user exists */
395 73 : if (user_known) {
396 3 : netlogon->data.nt5.command = LOGON_SAM_LOGON_RESPONSE;
397 : } else {
398 70 : netlogon->data.nt5.command = LOGON_SAM_LOGON_USER_UNKNOWN;
399 : }
400 73 : netlogon->data.nt5.pdc_name = pdc_name;
401 73 : netlogon->data.nt5.user_name = user;
402 73 : netlogon->data.nt5.domain_name = flatname;
403 73 : netlogon->data.nt5.domain_uuid = domain_uuid;
404 73 : netlogon->data.nt5.forest = forest_domain;
405 73 : netlogon->data.nt5.dns_domain = dns_domain;
406 73 : netlogon->data.nt5.pdc_dns_name = pdc_dns_name;
407 73 : netlogon->data.nt5.pdc_ip = pdc_ip;
408 73 : netlogon->data.nt5.server_type = server_type;
409 73 : netlogon->data.nt5.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5;
410 73 : netlogon->data.nt5.lmnt_token = 0xFFFF;
411 73 : netlogon->data.nt5.lm20_token = 0xFFFF;
412 :
413 : } else /* (version & NETLOGON_NT_VERSION_1) and all other cases */ {
414 142 : netlogon->ntver = NETLOGON_NT_VERSION_1;
415 : /* could check if the user exists */
416 142 : if (user_known) {
417 9 : netlogon->data.nt4.command = LOGON_SAM_LOGON_RESPONSE;
418 : } else {
419 133 : netlogon->data.nt4.command = LOGON_SAM_LOGON_USER_UNKNOWN;
420 : }
421 142 : netlogon->data.nt4.pdc_name = pdc_name;
422 142 : netlogon->data.nt4.user_name = user;
423 142 : netlogon->data.nt4.domain_name = flatname;
424 142 : netlogon->data.nt4.nt_version = NETLOGON_NT_VERSION_1;
425 142 : netlogon->data.nt4.lmnt_token = 0xFFFF;
426 142 : netlogon->data.nt4.lm20_token = 0xFFFF;
427 : }
428 :
429 3271 : return NT_STATUS_OK;
430 : }
431 :
432 2960 : NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree,
433 : struct loadparm_context *lp_ctx,
434 : TALLOC_CTX *tmp_ctx,
435 : const char **domain,
436 : const char **host,
437 : const char **user,
438 : const char **domain_guid,
439 : struct dom_sid **domain_sid,
440 : int *acct_control,
441 : int *version)
442 : {
443 36 : unsigned int i;
444 :
445 2960 : *domain = NULL;
446 2960 : *host = NULL;
447 2960 : *user = NULL;
448 2960 : *domain_guid = NULL;
449 2960 : *domain_sid = NULL;
450 2960 : *acct_control = -1;
451 2960 : *version = NETLOGON_NT_VERSION_5;
452 :
453 2960 : if (tree->operation != LDB_OP_AND) goto failed;
454 :
455 : /* extract the query elements */
456 10888 : for (i=0;i<tree->u.list.num_elements;i++) {
457 7934 : struct ldb_parse_tree *t = tree->u.list.elements[i];
458 7934 : if (t->operation != LDB_OP_EQUALITY) goto failed;
459 7932 : if (strcasecmp(t->u.equality.attr, "DnsDomain") == 0) {
460 2226 : *domain = talloc_strndup(tmp_ctx,
461 2226 : (const char *)t->u.equality.value.data,
462 : t->u.equality.value.length);
463 : }
464 7932 : if (strcasecmp(t->u.equality.attr, "Host") == 0) {
465 606 : *host = talloc_strndup(tmp_ctx,
466 606 : (const char *)t->u.equality.value.data,
467 : t->u.equality.value.length);
468 : }
469 7932 : if (strcasecmp(t->u.equality.attr, "DomainGuid") == 0) {
470 0 : NTSTATUS enc_status;
471 0 : struct GUID guid;
472 20 : enc_status = ldap_decode_ndr_GUID(tmp_ctx,
473 : t->u.equality.value, &guid);
474 20 : if (NT_STATUS_IS_OK(enc_status)) {
475 20 : *domain_guid = GUID_string(tmp_ctx, &guid);
476 : }
477 : }
478 7932 : if (strcasecmp(t->u.equality.attr, "DomainSid") == 0) {
479 0 : enum ndr_err_code ndr_err;
480 :
481 0 : *domain_sid = talloc(tmp_ctx, struct dom_sid);
482 0 : if (*domain_sid == NULL) {
483 0 : goto failed;
484 : }
485 0 : ndr_err = ndr_pull_struct_blob(&t->u.equality.value,
486 : *domain_sid, *domain_sid,
487 : (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
488 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
489 0 : talloc_free(*domain_sid);
490 0 : goto failed;
491 : }
492 : }
493 7932 : if (strcasecmp(t->u.equality.attr, "User") == 0) {
494 886 : *user = talloc_strndup(tmp_ctx,
495 886 : (const char *)t->u.equality.value.data,
496 : t->u.equality.value.length);
497 : }
498 7932 : if (strcasecmp(t->u.equality.attr, "NtVer") == 0 &&
499 2955 : t->u.equality.value.length == 4) {
500 2955 : *version = IVAL(t->u.equality.value.data, 0);
501 : }
502 7932 : if (strcasecmp(t->u.equality.attr, "AAC") == 0 &&
503 1235 : t->u.equality.value.length == 4) {
504 1235 : *acct_control = IVAL(t->u.equality.value.data, 0);
505 : }
506 : }
507 :
508 2954 : if ((*domain == NULL) && (*domain_guid == NULL) && (*domain_sid == NULL)) {
509 724 : *domain = lpcfg_dnsdomain(lp_ctx);
510 : }
511 :
512 2954 : return NT_STATUS_OK;
513 :
514 6 : failed:
515 6 : return NT_STATUS_UNSUCCESSFUL;
516 : }
|