Changeset 745 for trunk/server/source4/cldap_server/netlogon.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/cldap_server/netlogon.c
r414 r745 22 22 23 23 #include "includes.h" 24 #include "lib/ldb/include/ldb.h"25 #include "lib/ldb/include/ldb_errors.h"24 #include <ldb.h> 25 #include <ldb_errors.h> 26 26 #include "lib/events/events.h" 27 27 #include "smbd/service_task.h" … … 37 37 #include "param/param.h" 38 38 #include "../lib/tsocket/tsocket.h" 39 #include "libds/common/flag_mapping.h" 39 40 40 41 /* … … 52 53 uint32_t version, 53 54 struct loadparm_context *lp_ctx, 54 struct netlogon_samlogon_response *netlogon) 55 struct netlogon_samlogon_response *netlogon, 56 bool fill_on_blank_request) 55 57 { 56 58 const char *dom_attrs[] = {"objectGUID", NULL}; … … 58 60 struct ldb_result *dom_res = NULL, *user_res = NULL; 59 61 int ret; 60 const char **services = lp _server_services(lp_ctx);62 const char **services = lpcfg_server_services(lp_ctx); 61 63 uint32_t server_type; 62 64 const char *pdc_name; 63 65 struct GUID domain_uuid; 64 const char *realm;65 66 const char *dns_domain; 67 const char *forest_domain; 66 68 const char *pdc_dns_name; 67 69 const char *flatname; … … 71 73 struct ldb_dn *domain_dn = NULL; 72 74 struct interface *ifaces; 73 bool user_known ;75 bool user_known, am_rodc; 74 76 NTSTATUS status; 75 77 76 /* the domain has an optional trailing .*/78 /* the domain parameter could have an optional trailing "." */ 77 79 if (domain && domain[strlen(domain)-1] == '.') { 78 80 domain = talloc_strndup(mem_ctx, domain, strlen(domain)-1); 79 } 80 81 if (domain && strcasecmp_m(domain, lp_realm(lp_ctx)) == 0) { 81 NT_STATUS_HAVE_NO_MEMORY(domain); 82 } 83 84 /* Lookup using long or short domainname */ 85 if (domain && (strcasecmp_m(domain, lpcfg_dnsdomain(lp_ctx)) == 0)) { 82 86 domain_dn = ldb_get_default_basedn(sam_ctx); 83 87 } 84 85 if (netbios_domain && strcasecmp_m(domain, lp_sam_name(lp_ctx))) { 88 if (netbios_domain && (strcasecmp_m(netbios_domain, lpcfg_sam_name(lp_ctx)) == 0)) { 86 89 domain_dn = ldb_get_default_basedn(sam_ctx); 87 90 } 88 89 91 if (domain_dn) { 92 const char *domain_identifier = domain != NULL ? domain 93 : netbios_domain; 90 94 ret = ldb_search(sam_ctx, mem_ctx, &dom_res, 91 95 domain_dn, LDB_SCOPE_BASE, dom_attrs, 92 96 "objectClass=domain"); 93 97 if (ret != LDB_SUCCESS) { 94 DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", domain, ldb_dn_get_linearized(domain_dn), ldb_errstring(sam_ctx))); 98 DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", 99 domain_identifier, 100 ldb_dn_get_linearized(domain_dn), 101 ldb_errstring(sam_ctx))); 95 102 return NT_STATUS_NO_SUCH_DOMAIN; 96 103 } 97 104 if (dom_res->count != 1) { 98 DEBUG(2,("Error finding domain '%s'/'%s' in sam\n", domain, ldb_dn_get_linearized(domain_dn))); 105 DEBUG(2,("Error finding domain '%s'/'%s' in sam\n", 106 domain_identifier, 107 ldb_dn_get_linearized(domain_dn))); 99 108 return NT_STATUS_NO_SUCH_DOMAIN; 100 109 } 101 110 } 102 111 103 if ((dom_res == NULL || dom_res->count == 0) && (domain_guid || domain_sid)) {104 112 /* Lookup using GUID or SID */ 113 if ((dom_res == NULL) && (domain_guid || domain_sid)) { 105 114 if (domain_guid) { 106 115 struct GUID binary_guid; 107 116 struct ldb_val guid_val; 108 enum ndr_err_code ndr_err;109 117 110 118 /* By this means, we ensure we don't have funny stuff in the GUID */ … … 116 124 117 125 /* And this gets the result into the binary format we want anyway */ 118 ndr_err = ndr_push_struct_blob(&guid_val, mem_ctx, NULL, &binary_guid, 119 (ndr_push_flags_fn_t)ndr_push_GUID); 120 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 121 return NT_STATUS_INVALID_PARAMETER; 126 status = GUID_to_ndr_blob(&binary_guid, mem_ctx, &guid_val); 127 if (!NT_STATUS_IS_OK(status)) { 128 return status; 122 129 } 123 130 ret = ldb_search(sam_ctx, mem_ctx, &dom_res, … … 132 139 133 140 /* Rather than go via the string, just push into the NDR form */ 134 ndr_err = ndr_push_struct_blob(&sid_val, mem_ctx, NULL,&sid,141 ndr_err = ndr_push_struct_blob(&sid_val, mem_ctx, &sid, 135 142 (ndr_push_flags_fn_t)ndr_push_dom_sid); 136 143 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { … … 141 148 NULL, LDB_SCOPE_SUBTREE, 142 149 dom_attrs, 143 "(&(objectCategory=DomainDNS)(objectS ID=%s))",150 "(&(objectCategory=DomainDNS)(objectSid=%s))", 144 151 ldb_binary_encode(mem_ctx, sid_val)); 145 152 } 146 153 147 154 if (ret != LDB_SUCCESS) { 148 DEBUG(2,("Unable to find referece to GUID '%s' or SID %sin sam: %s\n",155 DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam: %s\n", 149 156 domain_guid, dom_sid_string(mem_ctx, domain_sid), 150 157 ldb_errstring(sam_ctx))); … … 152 159 } else if (dom_res->count == 1) { 153 160 /* Ok, now just check it is our domain */ 154 155 if (ldb_dn_compare(ldb_get_default_basedn(sam_ctx), dom_res->msgs[0]->dn) != 0) { 161 if (ldb_dn_compare(ldb_get_default_basedn(sam_ctx), 162 dom_res->msgs[0]->dn) != 0) { 163 DEBUG(2,("The GUID '%s' or SID '%s' doesn't identify our domain\n", 164 domain_guid, 165 dom_sid_string(mem_ctx, domain_sid))); 156 166 return NT_STATUS_NO_SUCH_DOMAIN; 157 167 } 158 } else if (dom_res->count > 1) { 168 } else { 169 DEBUG(2,("Unable to find a correct reference to GUID '%s' or SID '%s' in sam\n", 170 domain_guid, dom_sid_string(mem_ctx, domain_sid))); 159 171 return NT_STATUS_NO_SUCH_DOMAIN; 160 172 } 161 173 } 162 174 163 164 if ((dom_res == NULL || dom_res->count == 0)) { 165 DEBUG(2,("Unable to find domain with name %s or GUID {%s}\n", domain, domain_guid)); 175 if (dom_res == NULL && fill_on_blank_request) { 176 /* blank inputs gives our domain - tested against 177 w2k8r2. Without this ADUC on Win7 won't start */ 178 domain_dn = ldb_get_default_basedn(sam_ctx); 179 ret = ldb_search(sam_ctx, mem_ctx, &dom_res, 180 domain_dn, LDB_SCOPE_BASE, dom_attrs, 181 "objectClass=domain"); 182 if (ret != LDB_SUCCESS) { 183 DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", 184 lpcfg_dnsdomain(lp_ctx), 185 ldb_dn_get_linearized(domain_dn), 186 ldb_errstring(sam_ctx))); 187 return NT_STATUS_NO_SUCH_DOMAIN; 188 } 189 } 190 191 if (dom_res == NULL) { 192 DEBUG(2,(__location__ ": Unable to get domain information with no inputs\n")); 166 193 return NT_STATUS_NO_SUCH_DOMAIN; 167 194 } … … 192 219 UF_ACCOUNTDISABLE, ds_acb2uf(acct_control)); 193 220 if (ret != LDB_SUCCESS) { 194 DEBUG(2,("Unable to find refere ce to user '%s' with ACB 0x%8x under %s: %s\n",221 DEBUG(2,("Unable to find reference to user '%s' with ACB 0x%8x under %s: %s\n", 195 222 user, acct_control, ldb_dn_get_linearized(dom_res->msgs[0]->dn), 196 223 ldb_errstring(sam_ctx))); … … 207 234 208 235 server_type = 209 NBT_SERVER_DS | NBT_SERVER_TIMESERV | 210 NBT_SERVER_CLOSEST | NBT_SERVER_WRITABLE | 211 NBT_SERVER_GOOD_TIMESERV | DS_DNS_CONTROLLER | 212 DS_DNS_DOMAIN; 236 DS_SERVER_DS | DS_SERVER_TIMESERV | 237 DS_SERVER_CLOSEST | 238 DS_SERVER_GOOD_TIMESERV; 239 240 #if 0 241 /* w2k8-r2 as a DC does not claim these */ 242 server_type |= DS_DNS_CONTROLLER | DS_DNS_DOMAIN; 243 #endif 213 244 214 245 if (samdb_is_pdc(sam_ctx)) { 215 int *domainFunctionality; 216 server_type |= NBT_SERVER_PDC; 217 domainFunctionality = talloc_get_type(ldb_get_opaque(sam_ctx, "domainFunctionality"), int); 218 if (domainFunctionality && *domainFunctionality >= DS_DOMAIN_FUNCTION_2008) { 219 server_type |= NBT_SERVER_FULL_SECRET_DOMAIN_6; 220 } 246 server_type |= DS_SERVER_PDC; 247 } 248 249 if (dsdb_functional_level(sam_ctx) >= DS_DOMAIN_FUNCTION_2008) { 250 server_type |= DS_SERVER_FULL_SECRET_DOMAIN_6; 221 251 } 222 252 223 253 if (samdb_is_gc(sam_ctx)) { 224 server_type |= NBT_SERVER_GC;254 server_type |= DS_SERVER_GC; 225 255 } 226 256 227 257 if (str_list_check(services, "ldap")) { 228 server_type |= NBT_SERVER_LDAP;258 server_type |= DS_SERVER_LDAP; 229 259 } 230 260 231 261 if (str_list_check(services, "kdc")) { 232 server_type |= NBT_SERVER_KDC; 233 } 234 262 server_type |= DS_SERVER_KDC; 263 } 264 265 if (samdb_rodc(sam_ctx, &am_rodc) == LDB_SUCCESS && !am_rodc) { 266 server_type |= DS_SERVER_WRITABLE; 267 } 268 269 #if 0 270 /* w2k8-r2 as a sole DC does not claim this */ 235 271 if (ldb_dn_compare(ldb_get_root_basedn(sam_ctx), ldb_get_default_basedn(sam_ctx)) == 0) { 236 server_type |= DS_DNS_FOREST; 237 } 238 239 pdc_name = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name(lp_ctx)); 272 server_type |= DS_DNS_FOREST_ROOT; 273 } 274 #endif 275 276 pdc_name = talloc_asprintf(mem_ctx, "\\\\%s", 277 lpcfg_netbios_name(lp_ctx)); 278 NT_STATUS_HAVE_NO_MEMORY(pdc_name); 240 279 domain_uuid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); 241 realm = lp_realm(lp_ctx); 242 dns_domain = lp_realm(lp_ctx); 280 dns_domain = lpcfg_dnsdomain(lp_ctx); 281 forest_domain = samdb_forest_name(sam_ctx, mem_ctx); 282 NT_STATUS_HAVE_NO_MEMORY(forest_domain); 243 283 pdc_dns_name = talloc_asprintf(mem_ctx, "%s.%s", 244 284 strlower_talloc(mem_ctx, 245 lp _netbios_name(lp_ctx)),285 lpcfg_netbios_name(lp_ctx)), 246 286 dns_domain); 247 248 flatname = lp_sam_name(lp_ctx); 249 /* FIXME: Hardcoded site names */ 250 server_site = "Default-First-Site-Name"; 251 client_site = "Default-First-Site-Name"; 252 load_interfaces(mem_ctx, lp_interfaces(lp_ctx), &ifaces); 253 pdc_ip = iface_best_ip(ifaces, src_address); 254 287 NT_STATUS_HAVE_NO_MEMORY(pdc_dns_name); 288 flatname = lpcfg_workgroup(lp_ctx); 289 server_site = samdb_server_site_name(sam_ctx, mem_ctx); 290 NT_STATUS_HAVE_NO_MEMORY(server_site); 291 client_site = samdb_client_site_name(sam_ctx, mem_ctx, 292 src_address, NULL); 293 NT_STATUS_HAVE_NO_MEMORY(client_site); 294 load_interfaces(mem_ctx, lpcfg_interfaces(lp_ctx), &ifaces); 295 /* 296 * TODO: the caller should pass the address which the client 297 * used to trigger this call, as the client is able to reach 298 * this ip. 299 */ 300 if (src_address) { 301 pdc_ip = iface_best_ip(ifaces, src_address); 302 } else { 303 pdc_ip = iface_n_ip(ifaces, 0); 304 } 255 305 ZERO_STRUCTP(netlogon); 256 306 … … 266 316 netlogon->data.nt5_ex.command = LOGON_SAM_LOGON_USER_UNKNOWN_EX; 267 317 } 268 netlogon->data.nt5_ex.server_type = server_type; 318 netlogon->data.nt5_ex.pdc_name = pdc_name; 319 netlogon->data.nt5_ex.user_name = user; 320 netlogon->data.nt5_ex.domain_name = flatname; 269 321 netlogon->data.nt5_ex.domain_uuid = domain_uuid; 270 netlogon->data.nt5_ex.forest = realm;322 netlogon->data.nt5_ex.forest = forest_domain; 271 323 netlogon->data.nt5_ex.dns_domain = dns_domain; 272 324 netlogon->data.nt5_ex.pdc_dns_name = pdc_dns_name; 273 netlogon->data.nt5_ex.domain = flatname;274 netlogon->data.nt5_ex.pdc_name = lp_netbios_name(lp_ctx);275 netlogon->data.nt5_ex.user_name = user;276 325 netlogon->data.nt5_ex.server_site = server_site; 277 326 netlogon->data.nt5_ex.client_site = client_site; 278 279 327 if (version & NETLOGON_NT_VERSION_5EX_WITH_IP) { 280 328 /* Clearly this needs to be fixed up for IPv6 */ … … 284 332 netlogon->data.nt5_ex.sockaddr.remaining = data_blob_talloc_zero(mem_ctx, 8); 285 333 } 334 netlogon->data.nt5_ex.server_type = server_type; 286 335 netlogon->data.nt5_ex.nt_version = NETLOGON_NT_VERSION_1|NETLOGON_NT_VERSION_5EX|extra_flags; 287 336 netlogon->data.nt5_ex.lmnt_token = 0xFFFF; … … 301 350 netlogon->data.nt5.domain_name = flatname; 302 351 netlogon->data.nt5.domain_uuid = domain_uuid; 303 netlogon->data.nt5.forest = realm;352 netlogon->data.nt5.forest = forest_domain; 304 353 netlogon->data.nt5.dns_domain = dns_domain; 305 354 netlogon->data.nt5.pdc_dns_name = pdc_dns_name; … … 318 367 netlogon->data.nt4.command = LOGON_SAM_LOGON_USER_UNKNOWN; 319 368 } 320 netlogon->data.nt4. server= pdc_name;369 netlogon->data.nt4.pdc_name = pdc_name; 321 370 netlogon->data.nt4.user_name = user; 322 netlogon->data.nt4.domain 371 netlogon->data.nt4.domain_name = flatname; 323 372 netlogon->data.nt4.nt_version = NETLOGON_NT_VERSION_1; 324 373 netlogon->data.nt4.lmnt_token = 0xFFFF; … … 340 389 struct tsocket_address *src) 341 390 { 342 int i;391 unsigned int i; 343 392 const char *domain = NULL; 344 393 const char *host = NULL; 345 394 const char *user = NULL; 346 395 const char *domain_guid = NULL; 347 const char*domain_sid = NULL;396 struct dom_sid *domain_sid = NULL; 348 397 int acct_control = -1; 349 398 int version = -1; … … 377 426 } 378 427 if (strcasecmp(t->u.equality.attr, "DomainSid") == 0) { 379 domain_sid = talloc_strndup(tmp_ctx, 380 (const char *)t->u.equality.value.data, 381 t->u.equality.value.length); 428 enum ndr_err_code ndr_err; 429 430 domain_sid = talloc(tmp_ctx, struct dom_sid); 431 if (domain_sid == NULL) { 432 goto failed; 433 } 434 ndr_err = ndr_pull_struct_blob(&t->u.equality.value, 435 domain_sid, domain_sid, 436 (ndr_pull_flags_fn_t)ndr_pull_dom_sid); 437 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 438 talloc_free(domain_sid); 439 goto failed; 440 } 382 441 } 383 442 if (strcasecmp(t->u.equality.attr, "User") == 0) { … … 396 455 } 397 456 398 if ( domain_guid == NULL && domain == NULL) {399 domain = lp _realm(cldapd->task->lp_ctx);457 if ((domain == NULL) && (domain_guid == NULL) && (domain_sid == NULL)) { 458 domain = lpcfg_dnsdomain(cldapd->task->lp_ctx); 400 459 } 401 460 … … 407 466 domain, host, user, version, domain_guid)); 408 467 409 status = fill_netlogon_samlogon_response(cldapd->samctx, tmp_ctx, domain, NULL, NULL, domain_guid, 468 status = fill_netlogon_samlogon_response(cldapd->samctx, tmp_ctx, 469 domain, NULL, domain_sid, 470 domain_guid, 410 471 user, acct_control, 411 472 tsocket_address_inet_addr_string(src, tmp_ctx), 412 version, cldapd->task->lp_ctx, &netlogon); 473 version, cldapd->task->lp_ctx, 474 &netlogon, false); 413 475 if (!NT_STATUS_IS_OK(status)) { 414 476 goto failed; 415 477 } 416 478 417 status = cldap_netlogon_reply(cldap, 418 lp_iconv_convenience(cldapd->task->lp_ctx), 419 message_id, src, version, 420 &netlogon); 479 status = cldap_netlogon_reply(cldap, message_id, src, version, &netlogon); 421 480 if (!NT_STATUS_IS_OK(status)) { 422 481 goto failed;
Note:
See TracChangeset
for help on using the changeset viewer.