Coverage Report

Created: 2026-04-01 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/dsdb/samdb/ldb_modules/netlogon.c
Line
Count
Source
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
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
0
{
61
0
  const char *dom_attrs[] = {"objectGUID", NULL};
62
0
  const char *none_attrs[] = {NULL};
63
0
  struct ldb_result *dom_res = NULL;
64
0
  int ret;
65
0
  const char **services = lpcfg_server_services(lp_ctx);
66
0
  uint32_t server_type;
67
0
  const char *pdc_name;
68
0
  struct GUID domain_uuid;
69
0
  const char *dns_domain;
70
0
  const char *forest_domain;
71
0
  const char *pdc_dns_name;
72
0
  const char *flatname;
73
0
  const char *server_site;
74
0
  const char *client_site;
75
0
  const char *pdc_ip;
76
0
  struct ldb_dn *domain_dn = NULL;
77
0
  struct interface *ifaces;
78
0
  bool user_known = false, am_rodc = false;
79
0
  uint32_t uac = 0;
80
0
  int dc_level;
81
0
  NTSTATUS status;
82
83
  /* the domain parameter could have an optional trailing "." */
84
0
  if (domain && domain[strlen(domain)-1] == '.') {
85
0
    domain = talloc_strndup(mem_ctx, domain, strlen(domain)-1);
86
0
    NT_STATUS_HAVE_NO_MEMORY(domain);
87
0
  }
88
89
  /* Lookup using long or short domainname */
90
0
  if (domain && (strcasecmp_m(domain, lpcfg_dnsdomain(lp_ctx)) == 0)) {
91
0
    domain_dn = ldb_get_default_basedn(sam_ctx);
92
0
  }
93
0
  if (netbios_domain && (strcasecmp_m(netbios_domain, lpcfg_sam_name(lp_ctx)) == 0)) {
94
0
    domain_dn = ldb_get_default_basedn(sam_ctx);
95
0
  }
96
0
  if (domain_dn) {
97
0
    const char *domain_identifier = domain != NULL ? domain
98
0
              : netbios_domain;
99
0
    ret = ldb_search(sam_ctx, mem_ctx, &dom_res,
100
0
         domain_dn, LDB_SCOPE_BASE, dom_attrs,
101
0
         "objectClass=domain");
102
0
    if (ret != LDB_SUCCESS) {
103
0
      DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n",
104
0
         domain_identifier,
105
0
         ldb_dn_get_linearized(domain_dn),
106
0
         ldb_errstring(sam_ctx)));
107
0
      return NT_STATUS_NO_SUCH_DOMAIN;
108
0
    }
109
0
    if (dom_res->count != 1) {
110
0
      DEBUG(2,("Error finding domain '%s'/'%s' in sam\n",
111
0
         domain_identifier,
112
0
         ldb_dn_get_linearized(domain_dn)));
113
0
      return NT_STATUS_NO_SUCH_DOMAIN;
114
0
    }
115
0
  }
116
117
  /* Lookup using GUID or SID */
118
0
  if ((dom_res == NULL) && (domain_guid || domain_sid)) {
119
0
    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
0
      status = GUID_from_string(domain_guid, &binary_guid);
126
0
      if (!NT_STATUS_IS_OK(status)) {
127
0
        return status;
128
0
      }
129
130
      /* And this gets the result into the binary format we want anyway */
131
0
      status = GUID_to_ndr_blob(&binary_guid, mem_ctx, &guid_val);
132
0
      if (!NT_STATUS_IS_OK(status)) {
133
0
        return status;
134
0
      }
135
0
      ret = ldb_search(sam_ctx, mem_ctx, &dom_res,
136
0
             NULL, LDB_SCOPE_SUBTREE, 
137
0
             dom_attrs, 
138
0
             "(&(objectCategory=DomainDNS)(objectGUID=%s))", 
139
0
             ldb_binary_encode(mem_ctx, guid_val));
140
0
    } else { /* domain_sid case */
141
0
      ret = ldb_search(sam_ctx, mem_ctx, &dom_res,
142
0
           NULL, LDB_SCOPE_SUBTREE,
143
0
           dom_attrs,
144
0
           "(&(objectCategory=DomainDNS)(objectSid=%s))",
145
0
           dom_sid_string(mem_ctx, domain_sid));
146
0
    }
147
    
148
0
    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
0
         domain_guid, dom_sid_string(mem_ctx, domain_sid),
151
0
         ldb_errstring(sam_ctx)));
152
0
      return NT_STATUS_NO_SUCH_DOMAIN;
153
0
    } else if (dom_res->count == 1) {
154
      /* Ok, now just check it is our domain */
155
0
      if (ldb_dn_compare(ldb_get_default_basedn(sam_ctx),
156
0
             dom_res->msgs[0]->dn) != 0) {
157
0
        DEBUG(2,("The GUID '%s' or SID '%s' doesn't identify our domain\n",
158
0
           domain_guid,
159
0
           dom_sid_string(mem_ctx, domain_sid)));
160
0
        return NT_STATUS_NO_SUCH_DOMAIN;
161
0
      }
162
0
    } else {
163
0
      DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam\n",
164
0
         domain_guid, dom_sid_string(mem_ctx, domain_sid)));
165
0
      return NT_STATUS_NO_SUCH_DOMAIN;
166
0
    }
167
0
  }
168
169
0
  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
0
    domain_dn = ldb_get_default_basedn(sam_ctx);
173
0
    ret = ldb_search(sam_ctx, mem_ctx, &dom_res,
174
0
         domain_dn, LDB_SCOPE_BASE, dom_attrs,
175
0
         "objectClass=domain");
176
0
    if (ret != LDB_SUCCESS) {
177
0
      DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n",
178
0
         lpcfg_dnsdomain(lp_ctx),
179
0
         ldb_dn_get_linearized(domain_dn),
180
0
         ldb_errstring(sam_ctx)));
181
0
      return NT_STATUS_NO_SUCH_DOMAIN;
182
0
    }
183
0
  }
184
185
0
        if (dom_res == NULL) {
186
0
    DEBUG(2,(__location__ ": Unable to get domain information with no inputs\n"));
187
0
    return NT_STATUS_NO_SUCH_DOMAIN;
188
0
  }
189
190
  /* work around different inputs for not-specified users */
191
0
  if (!user) {
192
0
    user = "";
193
0
  }
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
0
  if (user[0]) {
199
    /* Only allow some bits to be enquired:  [MS-ATDS] 7.3.3.2 */
200
0
    if (acct_control == (uint32_t)-1) {
201
0
      acct_control = 0;
202
0
    }
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
0
    if (acct_control != ACB_AUTOLOCK) {
210
0
      acct_control &= (ACB_TEMPDUP | ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST);
211
0
    }
212
0
    uac = ds_acb2uf(acct_control);
213
0
  }
214
215
0
  if (uac == UF_LOCKOUT) {
216
0
    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
0
    status = dsdb_trust_search_tdo_by_type(sam_ctx,
225
0
                   SEC_CHAN_DNS_DOMAIN,
226
0
                   user, none_attrs,
227
0
                   mem_ctx, &tdo_msg);
228
0
    if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
229
0
      user_known = false;
230
0
    } else if (NT_STATUS_IS_OK(status)) {
231
0
      TALLOC_FREE(tdo_msg);
232
0
      user_known = true;
233
0
    } else {
234
0
      DEBUG(2,("Unable to find reference to TDO '%s' - %s\n",
235
0
         user, nt_errstr(status)));
236
0
      return status;
237
0
    }
238
0
  } else if (user[0]) {
239
0
    struct ldb_result *user_res = NULL;
240
0
    const char *user_encoded = NULL;
241
242
0
    user_encoded = ldb_binary_encode_string(mem_ctx, user);
243
0
    if (user_encoded == NULL) {
244
0
      return NT_STATUS_NO_MEMORY;
245
0
    }
246
247
    /* We must exclude disabled accounts, but otherwise do the bitwise match the client asked for */
248
0
    ret = ldb_search(sam_ctx, mem_ctx, &user_res,
249
0
           dom_res->msgs[0]->dn, LDB_SCOPE_SUBTREE, 
250
0
           none_attrs, 
251
0
           "(&(objectClass=user)(samAccountName=%s)"
252
0
           "(!(userAccountControl:" LDB_OID_COMPARATOR_AND ":=%u))"
253
0
           "(userAccountControl:" LDB_OID_COMPARATOR_OR ":=%u))", 
254
0
           user_encoded,
255
0
           UF_ACCOUNTDISABLE, uac);
256
0
    if (ret != LDB_SUCCESS) {
257
0
      DEBUG(2,("Unable to find reference to user '%s' with ACB 0x%8x under %s: %s\n",
258
0
         user, acct_control, ldb_dn_get_linearized(dom_res->msgs[0]->dn),
259
0
         ldb_errstring(sam_ctx)));
260
0
      return NT_STATUS_NO_SUCH_USER;
261
0
    } else if (user_res->count == 1) {
262
0
      user_known = true;
263
0
    } else {
264
0
      user_known = false;
265
0
    }
266
0
    TALLOC_FREE(user_res);
267
0
  } else {
268
0
    user_known = true;
269
0
  }
270
271
0
  server_type = DS_SERVER_DS;
272
273
0
  if (samdb_is_pdc(sam_ctx)) {
274
0
    server_type |= DS_SERVER_PDC;
275
0
  }
276
277
0
  if (samdb_is_gc(sam_ctx)) {
278
0
    server_type |= DS_SERVER_GC;
279
0
  }
280
281
0
  if (str_list_check(services, "ldap")) {
282
0
    server_type |= DS_SERVER_LDAP;
283
0
  }
284
285
0
  if (str_list_check(services, "kdc")) {
286
0
    server_type |= DS_SERVER_KDC;
287
0
  }
288
289
0
  if (str_list_check(services, "ntp_signd")) {
290
0
    server_type |= DS_SERVER_TIMESERV | DS_SERVER_GOOD_TIMESERV;
291
0
  }
292
293
0
  if (samdb_rodc(sam_ctx, &am_rodc) == LDB_SUCCESS && !am_rodc) {
294
0
    server_type |= DS_SERVER_WRITABLE;
295
0
  }
296
297
0
  dc_level = dsdb_dc_functional_level(sam_ctx);
298
0
  if (dc_level >= DS_DOMAIN_FUNCTION_2008) {
299
0
    if (server_type & DS_SERVER_WRITABLE) {
300
0
      server_type |= DS_SERVER_FULL_SECRET_DOMAIN_6;
301
0
    } else {
302
0
      server_type |= DS_SERVER_SELECT_SECRET_DOMAIN_6;
303
0
    }
304
0
  }
305
306
0
  if (dc_level >= DS_DOMAIN_FUNCTION_2012) {
307
0
    server_type |= DS_SERVER_DS_8;
308
0
  }
309
310
0
  if (dc_level >= DS_DOMAIN_FUNCTION_2012_R2) {
311
0
    server_type |= DS_SERVER_DS_9;
312
0
  }
313
314
0
  if (dc_level >= DS_DOMAIN_FUNCTION_2016) {
315
0
    server_type |= DS_SERVER_DS_10;
316
0
  }
317
318
0
  if (version & (NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) {
319
0
    pdc_name = lpcfg_netbios_name(lp_ctx);
320
0
  } else {
321
0
    pdc_name = talloc_asprintf(mem_ctx, "\\\\%s",
322
0
             lpcfg_netbios_name(lp_ctx));
323
0
    NT_STATUS_HAVE_NO_MEMORY(pdc_name);
324
0
  }
325
0
  domain_uuid      = samdb_result_guid(dom_res->msgs[0], "objectGUID");
326
0
  dns_domain       = lpcfg_dnsdomain(lp_ctx);
327
0
  forest_domain    = samdb_forest_name(sam_ctx, mem_ctx);
328
0
  NT_STATUS_HAVE_NO_MEMORY(forest_domain);
329
0
  pdc_dns_name     = talloc_asprintf(mem_ctx, "%s.%s", 
330
0
             strlower_talloc(mem_ctx, 
331
0
                 lpcfg_netbios_name(lp_ctx)),
332
0
             dns_domain);
333
0
  NT_STATUS_HAVE_NO_MEMORY(pdc_dns_name);
334
0
  flatname         = lpcfg_workgroup(lp_ctx);
335
336
0
  server_site      = samdb_server_site_name(sam_ctx, mem_ctx);
337
0
  NT_STATUS_HAVE_NO_MEMORY(server_site);
338
0
  client_site      = samdb_client_site_name(sam_ctx, mem_ctx,
339
0
              src_address, NULL,
340
0
              true);
341
0
  NT_STATUS_HAVE_NO_MEMORY(client_site);
342
0
  if (strcasecmp(server_site, client_site) == 0) {
343
0
    server_type |= DS_SERVER_CLOSEST;
344
0
  }
345
346
0
  load_interface_list(mem_ctx, lp_ctx, &ifaces);
347
0
  if (src_address) {
348
0
    pdc_ip = iface_list_best_ip(ifaces, src_address);
349
0
  } else {
350
0
    pdc_ip = iface_list_first_v4(ifaces);
351
0
  }
352
0
  if (pdc_ip == NULL || !is_ipaddress_v4(pdc_ip)) {
353
    /* this matches windows behaviour */
354
0
    pdc_ip = "127.0.0.1";
355
0
  }
356
357
0
  ZERO_STRUCTP(netlogon);
358
359
  /* check if either of these bits is present */
360
0
  if (version & (NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_5EX_WITH_IP)) {
361
0
    uint32_t extra_flags = 0;
362
0
    netlogon->ntver = NETLOGON_NT_VERSION_5EX;
363
364
    /* could check if the user exists */
365
0
    if (user_known) {
366
0
      netlogon->data.nt5_ex.command      = LOGON_SAM_LOGON_RESPONSE_EX;
367
0
    } else {
368
0
      netlogon->data.nt5_ex.command      = LOGON_SAM_LOGON_USER_UNKNOWN_EX;
369
0
    }
370
0
    netlogon->data.nt5_ex.pdc_name     = pdc_name;
371
0
    netlogon->data.nt5_ex.user_name    = user;
372
0
    netlogon->data.nt5_ex.domain_name  = flatname;
373
0
    netlogon->data.nt5_ex.domain_uuid  = domain_uuid;
374
0
    netlogon->data.nt5_ex.forest       = forest_domain;
375
0
    netlogon->data.nt5_ex.dns_domain   = dns_domain;
376
0
    netlogon->data.nt5_ex.pdc_dns_name = pdc_dns_name;
377
0
    netlogon->data.nt5_ex.server_site  = server_site;
378
0
    netlogon->data.nt5_ex.client_site  = client_site;
379
0
    if (version & NETLOGON_NT_VERSION_5EX_WITH_IP) {
380
      /* note that this is always a IPV4 address */
381
0
      extra_flags = NETLOGON_NT_VERSION_5EX_WITH_IP;
382
0
      netlogon->data.nt5_ex.sockaddr.sockaddr_family    = 2;
383
0
      netlogon->data.nt5_ex.sockaddr.pdc_ip       = pdc_ip;
384
0
      netlogon->data.nt5_ex.sockaddr.remaining = data_blob_talloc_zero(mem_ctx, 8);
385
0
    }
386
0
    netlogon->data.nt5_ex.server_type  = server_type;
387
0
    netlogon->data.nt5_ex.nt_version   = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5EX|extra_flags;
388
0
    netlogon->data.nt5_ex.lmnt_token   = 0xFFFF;
389
0
    netlogon->data.nt5_ex.lm20_token   = 0xFFFF;
390
391
0
  } else if (version & NETLOGON_NT_VERSION_5) {
392
0
    netlogon->ntver = NETLOGON_NT_VERSION_5;
393
394
    /* could check if the user exists */
395
0
    if (user_known) {
396
0
      netlogon->data.nt5.command      = LOGON_SAM_LOGON_RESPONSE;
397
0
    } else {
398
0
      netlogon->data.nt5.command      = LOGON_SAM_LOGON_USER_UNKNOWN;
399
0
    }
400
0
    netlogon->data.nt5.pdc_name     = pdc_name;
401
0
    netlogon->data.nt5.user_name    = user;
402
0
    netlogon->data.nt5.domain_name  = flatname;
403
0
    netlogon->data.nt5.domain_uuid  = domain_uuid;
404
0
    netlogon->data.nt5.forest       = forest_domain;
405
0
    netlogon->data.nt5.dns_domain   = dns_domain;
406
0
    netlogon->data.nt5.pdc_dns_name = pdc_dns_name;
407
0
    netlogon->data.nt5.pdc_ip       = pdc_ip;
408
0
    netlogon->data.nt5.server_type  = server_type;
409
0
    netlogon->data.nt5.nt_version   = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5;
410
0
    netlogon->data.nt5.lmnt_token   = 0xFFFF;
411
0
    netlogon->data.nt5.lm20_token   = 0xFFFF;
412
413
0
  } else /* (version & NETLOGON_NT_VERSION_1) and all other cases */ {
414
0
    netlogon->ntver = NETLOGON_NT_VERSION_1;
415
    /* could check if the user exists */
416
0
    if (user_known) {
417
0
      netlogon->data.nt4.command      = LOGON_SAM_LOGON_RESPONSE;
418
0
    } else {
419
0
      netlogon->data.nt4.command      = LOGON_SAM_LOGON_USER_UNKNOWN;
420
0
    }
421
0
    netlogon->data.nt4.pdc_name    = pdc_name;
422
0
    netlogon->data.nt4.user_name   = user;
423
0
    netlogon->data.nt4.domain_name = flatname;
424
0
    netlogon->data.nt4.nt_version  = NETLOGON_NT_VERSION_1;
425
0
    netlogon->data.nt4.lmnt_token  = 0xFFFF;
426
0
    netlogon->data.nt4.lm20_token  = 0xFFFF;
427
0
  }
428
429
0
  return NT_STATUS_OK;
430
0
}
431
432
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
0
{
443
0
  unsigned int i;
444
445
0
  *domain = NULL;
446
0
  *host = NULL;
447
0
  *user = NULL;
448
0
  *domain_guid = NULL;
449
0
  *domain_sid = NULL;
450
0
  *acct_control = -1;
451
0
  *version = NETLOGON_NT_VERSION_5;
452
453
0
  if (tree->operation != LDB_OP_AND) goto failed;
454
455
  /* extract the query elements */
456
0
  for (i=0;i<tree->u.list.num_elements;i++) {
457
0
    struct ldb_parse_tree *t = tree->u.list.elements[i];
458
0
    if (t->operation != LDB_OP_EQUALITY) goto failed;
459
0
    if (strcasecmp(t->u.equality.attr, "DnsDomain") == 0) {
460
0
      *domain = talloc_strndup(tmp_ctx,
461
0
            (const char *)t->u.equality.value.data,
462
0
            t->u.equality.value.length);
463
0
    }
464
0
    if (strcasecmp(t->u.equality.attr, "Host") == 0) {
465
0
      *host = talloc_strndup(tmp_ctx,
466
0
                (const char *)t->u.equality.value.data,
467
0
                t->u.equality.value.length);
468
0
    }
469
0
    if (strcasecmp(t->u.equality.attr, "DomainGuid") == 0) {
470
0
      NTSTATUS enc_status;
471
0
      struct GUID guid;
472
0
      enc_status = ldap_decode_ndr_GUID(tmp_ctx, 
473
0
                t->u.equality.value, &guid);
474
0
      if (NT_STATUS_IS_OK(enc_status)) {
475
0
        *domain_guid = GUID_string(tmp_ctx, &guid);
476
0
      }
477
0
    }
478
0
    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
0
      }
485
0
      ndr_err = ndr_pull_struct_blob(&t->u.equality.value,
486
0
                   *domain_sid, *domain_sid,
487
0
                   (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
0
      }
492
0
    }
493
0
    if (strcasecmp(t->u.equality.attr, "User") == 0) {
494
0
      *user = talloc_strndup(tmp_ctx,
495
0
                 (const char *)t->u.equality.value.data,
496
0
                 t->u.equality.value.length);
497
0
    }
498
0
    if (strcasecmp(t->u.equality.attr, "NtVer") == 0 &&
499
0
        t->u.equality.value.length == 4) {
500
0
      *version = IVAL(t->u.equality.value.data, 0);
501
0
    }
502
0
    if (strcasecmp(t->u.equality.attr, "AAC") == 0 &&
503
0
        t->u.equality.value.length == 4) {
504
0
      *acct_control = IVAL(t->u.equality.value.data, 0);
505
0
    }
506
0
  }
507
508
0
  if ((*domain == NULL) && (*domain_guid == NULL) && (*domain_sid == NULL)) {
509
0
    *domain = lpcfg_dnsdomain(lp_ctx);
510
0
  }
511
512
0
  return NT_STATUS_OK;
513
514
0
failed:
515
0
  return NT_STATUS_UNSUCCESSFUL;
516
0
}