1/* 2 Unix SMB/CIFS implementation. 3 NBT netbios routines and daemon - version 2 4 Copyright (C) Andrew Tridgell 1994-1998 5 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 6 Copyright (C) Jeremy Allison 1994-2003 7 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002 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 Revision History: 23 24*/ 25 26#include "includes.h" 27#include "../libcli/netlogon.h" 28#include "../libcli/cldap/cldap.h" 29#include "../lib/tsocket/tsocket.h" 30 31struct sam_database_info { 32 uint32 index; 33 uint32 serial_lo, serial_hi; 34 uint32 date_lo, date_hi; 35}; 36 37/** 38 * check whether the client belongs to the hosts 39 * for which initial logon should be delayed... 40 */ 41static bool delay_logon(const char *peer_name, const char *peer_addr) 42{ 43 const char **delay_list = lp_init_logon_delayed_hosts(); 44 const char *peer[2]; 45 46 if (delay_list == NULL) { 47 return False; 48 } 49 50 peer[0] = peer_name; 51 peer[1] = peer_addr; 52 53 return list_match(delay_list, (const char *)peer, client_match); 54} 55 56static void delayed_init_logon_handler(struct event_context *event_ctx, 57 struct timed_event *te, 58 struct timeval now, 59 void *private_data) 60{ 61 struct packet_struct *p = (struct packet_struct *)private_data; 62 63 DEBUG(10, ("delayed_init_logon_handler (%lx): re-queuing packet.\n", 64 (unsigned long)te)); 65 66 queue_packet(p); 67 68 TALLOC_FREE(te); 69} 70 71struct nmbd_proxy_logon_context { 72 struct cldap_socket *cldap_sock; 73}; 74 75static struct nmbd_proxy_logon_context *global_nmbd_proxy_logon; 76 77bool initialize_nmbd_proxy_logon(void) 78{ 79 const char *cldap_server = lp_parm_const_string(-1, "nmbd_proxy_logon", 80 "cldap_server", NULL); 81 struct nmbd_proxy_logon_context *ctx; 82 NTSTATUS status; 83 struct in_addr addr; 84 char addrstr[INET_ADDRSTRLEN]; 85 const char *server_str; 86 int ret; 87 struct tsocket_address *server_addr; 88 89 if (!cldap_server) { 90 return true; 91 } 92 93 addr = interpret_addr2(cldap_server); 94 server_str = inet_ntop(AF_INET, &addr, 95 addrstr, sizeof(addrstr)); 96 if (!server_str || strcmp("0.0.0.0", server_str) == 0) { 97 DEBUG(0,("Failed to resolve[%s] for nmbd_proxy_logon\n", 98 cldap_server)); 99 return false; 100 } 101 102 ctx = talloc_zero(nmbd_event_context(), 103 struct nmbd_proxy_logon_context); 104 if (!ctx) { 105 return false; 106 } 107 108 ret = tsocket_address_inet_from_strings(ctx, "ipv4", 109 server_str, LDAP_PORT, 110 &server_addr); 111 if (ret != 0) { 112 TALLOC_FREE(ctx); 113 status = map_nt_error_from_unix(errno); 114 DEBUG(0,("Failed to create cldap tsocket_address for %s - %s\n", 115 server_str, nt_errstr(status))); 116 return false; 117 } 118 119 /* we create a connected udp socket */ 120 status = cldap_socket_init(ctx, nmbd_event_context(), NULL, 121 server_addr, &ctx->cldap_sock); 122 TALLOC_FREE(server_addr); 123 if (!NT_STATUS_IS_OK(status)) { 124 TALLOC_FREE(ctx); 125 DEBUG(0,("failed to create cldap socket for %s: %s\n", 126 server_str, nt_errstr(status))); 127 return false; 128 } 129 130 global_nmbd_proxy_logon = ctx; 131 return true; 132} 133 134struct nmbd_proxy_logon_state { 135 struct in_addr local_ip; 136 struct packet_struct *p; 137 const char *remote_name; 138 uint8_t remote_name_type; 139 const char *remote_mailslot; 140 struct nbt_netlogon_packet req; 141 struct nbt_netlogon_response resp; 142 struct cldap_netlogon io; 143}; 144 145static int nmbd_proxy_logon_state_destructor(struct nmbd_proxy_logon_state *s) 146{ 147 s->p->locked = false; 148 free_packet(s->p); 149 return 0; 150} 151 152static void nmbd_proxy_logon_done(struct tevent_req *subreq); 153 154static void nmbd_proxy_logon(struct nmbd_proxy_logon_context *ctx, 155 struct in_addr local_ip, 156 struct packet_struct *p, 157 uint8_t *buf, 158 uint32_t len) 159{ 160 struct nmbd_proxy_logon_state *state; 161 enum ndr_err_code ndr_err; 162 DATA_BLOB blob = data_blob_const(buf, len); 163 const char *computer_name = NULL; 164 const char *mailslot_name = NULL; 165 const char *user_name = NULL; 166 const char *domain_sid = NULL; 167 uint32_t acct_control = 0; 168 uint32_t nt_version = 0; 169 struct tevent_req *subreq; 170 fstring source_name; 171 struct dgram_packet *dgram = &p->packet.dgram; 172 173 state = TALLOC_ZERO_P(ctx, struct nmbd_proxy_logon_state); 174 if (!state) { 175 DEBUG(0,("failed to allocate nmbd_proxy_logon_state\n")); 176 return; 177 } 178 179 pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name); 180 state->remote_name = talloc_strdup(state, source_name); 181 state->remote_name_type = dgram->source_name.name_type, 182 state->local_ip = local_ip; 183 state->p = p; 184 185 ndr_err = ndr_pull_struct_blob( 186 &blob, state, NULL, &state->req, 187 (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_packet); 188 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 189 NTSTATUS status = ndr_map_error2ntstatus(ndr_err); 190 DEBUG(0,("failed parse nbt_netlogon_packet: %s\n", 191 nt_errstr(status))); 192 TALLOC_FREE(state); 193 return; 194 } 195 196 if (DEBUGLEVEL >= 10) { 197 DEBUG(10, ("nmbd_proxy_logon:\n")); 198 NDR_PRINT_DEBUG(nbt_netlogon_packet, &state->req); 199 } 200 201 switch (state->req.command) { 202 case LOGON_SAM_LOGON_REQUEST: 203 computer_name = state->req.req.logon.computer_name; 204 user_name = state->req.req.logon.user_name; 205 mailslot_name = state->req.req.logon.mailslot_name; 206 acct_control = state->req.req.logon.acct_control; 207 if (state->req.req.logon.sid_size > 0) { 208 domain_sid = dom_sid_string(state, 209 &state->req.req.logon.sid); 210 if (!domain_sid) { 211 DEBUG(0,("failed to get a string for sid\n")); 212 TALLOC_FREE(state); 213 return; 214 } 215 } 216 nt_version = state->req.req.logon.nt_version; 217 break; 218 219 default: 220 /* this can't happen as the caller already checks the command */ 221 break; 222 } 223 224 state->remote_mailslot = mailslot_name; 225 226 if (user_name && strlen(user_name) == 0) { 227 user_name = NULL; 228 } 229 230 if (computer_name && strlen(computer_name) == 0) { 231 computer_name = NULL; 232 } 233 234 /* 235 * as the socket is connected, 236 * we don't need to specify the destination 237 */ 238 state->io.in.dest_address = NULL; 239 state->io.in.dest_port = 0; 240 state->io.in.realm = NULL; 241 state->io.in.host = computer_name; 242 state->io.in.user = user_name; 243 state->io.in.domain_guid = NULL; 244 state->io.in.domain_sid = domain_sid; 245 state->io.in.acct_control = acct_control; 246 state->io.in.version = nt_version; 247 state->io.in.map_response = false; 248 249 subreq = cldap_netlogon_send(state, 250 ctx->cldap_sock, 251 &state->io); 252 if (!subreq) { 253 DEBUG(0,("failed to send cldap netlogon call\n")); 254 TALLOC_FREE(state); 255 return; 256 } 257 tevent_req_set_callback(subreq, nmbd_proxy_logon_done, state); 258 259 /* we reply async */ 260 state->p->locked = true; 261 talloc_set_destructor(state, nmbd_proxy_logon_state_destructor); 262} 263 264static void nmbd_proxy_logon_done(struct tevent_req *subreq) 265{ 266 struct nmbd_proxy_logon_state *state = 267 tevent_req_callback_data(subreq, 268 struct nmbd_proxy_logon_state); 269 NTSTATUS status; 270 DATA_BLOB response = data_blob_null; 271 272 status = cldap_netlogon_recv(subreq, NULL, state, &state->io); 273 if (!NT_STATUS_IS_OK(status)) { 274 DEBUG(0,("failed to recv cldap netlogon call: %s\n", 275 nt_errstr(status))); 276 TALLOC_FREE(state); 277 return; 278 } 279 280 status = push_netlogon_samlogon_response(&response, state, NULL, 281 &state->io.out.netlogon); 282 if (!NT_STATUS_IS_OK(status)) { 283 DEBUG(0,("failed to push netlogon_samlogon_response: %s\n", 284 nt_errstr(status))); 285 TALLOC_FREE(state); 286 return; 287 } 288 289 send_mailslot(true, state->remote_mailslot, 290 (char *)response.data, response.length, 291 global_myname(), 0x0, 292 state->remote_name, 293 state->remote_name_type, 294 state->p->ip, 295 state->local_ip, 296 state->p->port); 297 TALLOC_FREE(state); 298} 299 300/**************************************************************************** 301Process a domain logon packet 302**************************************************************************/ 303 304void process_logon_packet(struct packet_struct *p, char *buf,int len, 305 const char *mailslot) 306{ 307 struct dgram_packet *dgram = &p->packet.dgram; 308 fstring my_name; 309 fstring reply_name; 310 char outbuf[1024]; 311 int code; 312 uint16 token = 0; 313 uint32 ntversion = 0; 314 uint16 lmnttoken = 0; 315 uint16 lm20token = 0; 316 uint32 domainsidsize; 317 bool short_request = False; 318 char *getdc; 319 char *uniuser; /* Unicode user name. */ 320 fstring ascuser; 321 char *unicomp; /* Unicode computer name. */ 322 size_t size; 323 struct sockaddr_storage ss; 324 const struct sockaddr_storage *pss; 325 struct in_addr ip; 326 327 in_addr_to_sockaddr_storage(&ss, p->ip); 328 pss = iface_ip((struct sockaddr *)&ss); 329 if (!pss) { 330 DEBUG(5,("process_logon_packet:can't find outgoing interface " 331 "for packet from IP %s\n", 332 inet_ntoa(p->ip) )); 333 return; 334 } 335 ip = ((struct sockaddr_in *)pss)->sin_addr; 336 337 memset(outbuf, 0, sizeof(outbuf)); 338 339 if (!lp_domain_logons()) { 340 DEBUG(5,("process_logon_packet: Logon packet received from IP %s and domain \ 341logons are not enabled.\n", inet_ntoa(p->ip) )); 342 return; 343 } 344 345 fstrcpy(my_name, global_myname()); 346 347 code = get_safe_SVAL(buf,len,buf,0,-1); 348 DEBUG(4,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code)); 349 350 switch (code) { 351 case 0: 352 { 353 fstring mach_str, user_str, getdc_str; 354 char *q = buf + 2; 355 char *machine = q; 356 char *user = skip_string(buf,len,machine); 357 358 if (!user || PTR_DIFF(user, buf) >= len) { 359 DEBUG(0,("process_logon_packet: bad packet\n")); 360 return; 361 } 362 getdc = skip_string(buf,len,user); 363 364 if (!getdc || PTR_DIFF(getdc, buf) >= len) { 365 DEBUG(0,("process_logon_packet: bad packet\n")); 366 return; 367 } 368 q = skip_string(buf,len,getdc); 369 370 if (!q || PTR_DIFF(q + 5, buf) > len) { 371 DEBUG(0,("process_logon_packet: bad packet\n")); 372 return; 373 } 374 token = SVAL(q,3); 375 376 fstrcpy(reply_name,my_name); 377 378 pull_ascii_fstring(mach_str, machine); 379 pull_ascii_fstring(user_str, user); 380 pull_ascii_fstring(getdc_str, getdc); 381 382 DEBUG(5,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n", 383 mach_str,inet_ntoa(p->ip),user_str,token)); 384 385 q = outbuf; 386 SSVAL(q, 0, 6); 387 q += 2; 388 389 fstrcpy(reply_name, "\\\\"); 390 fstrcat(reply_name, my_name); 391 size = push_ascii(q,reply_name, 392 sizeof(outbuf)-PTR_DIFF(q, outbuf), 393 STR_TERMINATE); 394 if (size == (size_t)-1) { 395 return; 396 } 397 q = skip_string(outbuf,sizeof(outbuf),q); /* PDC name */ 398 399 SSVAL(q, 0, token); 400 q += 2; 401 402 dump_data(4, (uint8 *)outbuf, PTR_DIFF(q, outbuf)); 403 404 send_mailslot(True, getdc_str, 405 outbuf,PTR_DIFF(q,outbuf), 406 global_myname(), 0x0, 407 mach_str, 408 dgram->source_name.name_type, 409 p->ip, ip, p->port); 410 break; 411 } 412 413 case LOGON_PRIMARY_QUERY: 414 { 415 fstring mach_str, getdc_str; 416 fstring source_name; 417 char *q = buf + 2; 418 char *machine = q; 419 420 if (!lp_domain_master()) { 421 /* We're not Primary Domain Controller -- ignore this */ 422 return; 423 } 424 425 getdc = skip_string(buf,len,machine); 426 427 if (!getdc || PTR_DIFF(getdc, buf) >= len) { 428 DEBUG(0,("process_logon_packet: bad packet\n")); 429 return; 430 } 431 q = skip_string(buf,len,getdc); 432 433 if (!q || PTR_DIFF(q, buf) >= len) { 434 DEBUG(0,("process_logon_packet: bad packet\n")); 435 return; 436 } 437 q = ALIGN2(q, buf); 438 439 /* At this point we can work out if this is a W9X or NT style 440 request. Experiments show that the difference is wether the 441 packet ends here. For a W9X request we now end with a pair of 442 bytes (usually 0xFE 0xFF) whereas with NT we have two further 443 strings - the following is a simple way of detecting this */ 444 445 if (len - PTR_DIFF(q, buf) <= 3) { 446 short_request = True; 447 } else { 448 unicomp = q; 449 450 if (PTR_DIFF(q, buf) >= len) { 451 DEBUG(0,("process_logon_packet: bad packet\n")); 452 return; 453 } 454 455 /* A full length (NT style) request */ 456 q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp)); 457 458 if (PTR_DIFF(q, buf) >= len) { 459 DEBUG(0,("process_logon_packet: bad packet\n")); 460 return; 461 } 462 463 if (len - PTR_DIFF(q, buf) > 8) { 464 /* with NT5 clients we can sometimes 465 get additional data - a length specificed string 466 containing the domain name, then 16 bytes of 467 data (no idea what it is) */ 468 int dom_len = CVAL(q, 0); 469 q++; 470 if (dom_len != 0) { 471 q += dom_len + 1; 472 } 473 q += 16; 474 } 475 476 if (PTR_DIFF(q + 8, buf) > len) { 477 DEBUG(0,("process_logon_packet: bad packet\n")); 478 return; 479 } 480 481 ntversion = IVAL(q, 0); 482 lmnttoken = SVAL(q, 4); 483 lm20token = SVAL(q, 6); 484 } 485 486 /* Construct reply. */ 487 q = outbuf; 488 SSVAL(q, 0, NETLOGON_RESPONSE_FROM_PDC); 489 q += 2; 490 491 fstrcpy(reply_name,my_name); 492 size = push_ascii(q, reply_name, 493 sizeof(outbuf)-PTR_DIFF(q, outbuf), 494 STR_TERMINATE); 495 if (size == (size_t)-1) { 496 return; 497 } 498 q = skip_string(outbuf,sizeof(outbuf),q); /* PDC name */ 499 500 /* PDC and domain name */ 501 if (!short_request) { 502 /* Make a full reply */ 503 q = ALIGN2(q, outbuf); 504 505 q += dos_PutUniCode(q, my_name, 506 sizeof(outbuf) - PTR_DIFF(q, outbuf), 507 True); /* PDC name */ 508 q += dos_PutUniCode(q, lp_workgroup(), 509 sizeof(outbuf) - PTR_DIFF(q, outbuf), 510 True); /* Domain name*/ 511 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 8) { 512 return; 513 } 514 SIVAL(q, 0, 1); /* our nt version */ 515 SSVAL(q, 4, 0xffff); /* our lmnttoken */ 516 SSVAL(q, 6, 0xffff); /* our lm20token */ 517 q += 8; 518 } 519 520 /* RJS, 21-Feb-2000, we send a short reply if the request was short */ 521 522 pull_ascii_fstring(mach_str, machine); 523 524 DEBUG(5,("process_logon_packet: GETDC request from %s at IP %s, \ 525reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", 526 mach_str,inet_ntoa(p->ip), reply_name, lp_workgroup(), 527 NETLOGON_RESPONSE_FROM_PDC, (uint32)ntversion, (uint32)lmnttoken, 528 (uint32)lm20token )); 529 530 dump_data(4, (uint8 *)outbuf, PTR_DIFF(q, outbuf)); 531 532 pull_ascii_fstring(getdc_str, getdc); 533 pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name); 534 535 send_mailslot(True, getdc_str, 536 outbuf,PTR_DIFF(q,outbuf), 537 global_myname(), 0x0, 538 source_name, 539 dgram->source_name.name_type, 540 p->ip, ip, p->port); 541 return; 542 } 543 544 case LOGON_SAM_LOGON_REQUEST: 545 546 { 547 fstring getdc_str; 548 fstring source_name; 549 char *source_addr; 550 char *q = buf + 2; 551 fstring asccomp; 552 553 if (global_nmbd_proxy_logon) { 554 nmbd_proxy_logon(global_nmbd_proxy_logon, 555 ip, p, (uint8_t *)buf, len); 556 return; 557 } 558 559 q += 2; 560 561 if (PTR_DIFF(q, buf) >= len) { 562 DEBUG(0,("process_logon_packet: bad packet\n")); 563 return; 564 } 565 566 unicomp = q; 567 uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp)); 568 569 if (PTR_DIFF(uniuser, buf) >= len) { 570 DEBUG(0,("process_logon_packet: bad packet\n")); 571 return; 572 } 573 574 getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser)); 575 576 if (PTR_DIFF(getdc, buf) >= len) { 577 DEBUG(0,("process_logon_packet: bad packet\n")); 578 return; 579 } 580 581 q = skip_string(buf,len,getdc); 582 583 if (!q || PTR_DIFF(q + 8, buf) >= len) { 584 DEBUG(0,("process_logon_packet: bad packet\n")); 585 return; 586 } 587 588 q += 4; /* Account Control Bits - indicating username type */ 589 domainsidsize = IVAL(q, 0); 590 q += 4; 591 592 DEBUG(5,("process_logon_packet: LOGON_SAM_LOGON_REQUEST sidsize %d, len = %d\n", domainsidsize, len)); 593 594 if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) { 595 q += domainsidsize; 596 q = ALIGN4(q, buf); 597 } 598 599 DEBUG(5,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %ld\n", len, (unsigned long)PTR_DIFF(q, buf) )); 600 601 if (len - PTR_DIFF(q, buf) > 8) { 602 /* with NT5 clients we can sometimes 603 get additional data - a length specificed string 604 containing the domain name, then 16 bytes of 605 data (no idea what it is) */ 606 int dom_len = CVAL(q, 0); 607 q++; 608 if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) { 609 q += dom_len + 1; 610 } 611 q += 16; 612 } 613 614 if (PTR_DIFF(q + 8, buf) > len) { 615 DEBUG(0,("process_logon_packet: bad packet\n")); 616 return; 617 } 618 619 ntversion = IVAL(q, 0); 620 lmnttoken = SVAL(q, 4); 621 lm20token = SVAL(q, 6); 622 q += 8; 623 624 DEBUG(3,("process_logon_packet: LOGON_SAM_LOGON_REQUEST sidsize %d ntv %d\n", domainsidsize, ntversion)); 625 626 /* 627 * we respond regadless of whether the machine is in our password 628 * database. If it isn't then we let smbd send an appropriate error. 629 * Let's ignore the SID. 630 */ 631 pull_ucs2_fstring(ascuser, uniuser); 632 pull_ucs2_fstring(asccomp, unicomp); 633 DEBUG(5,("process_logon_packet: LOGON_SAM_LOGON_REQUEST user %s\n", ascuser)); 634 635 fstrcpy(reply_name, "\\\\"); /* Here it wants \\LOGONSERVER. */ 636 fstrcat(reply_name, my_name); 637 638 DEBUG(5,("process_logon_packet: LOGON_SAM_LOGON_REQUEST request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n", 639 asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(), 640 LOGON_SAM_LOGON_RESPONSE ,lmnttoken)); 641 642 /* Construct reply. */ 643 644 q = outbuf; 645 /* we want the simple version unless we are an ADS PDC..which means */ 646 /* never, at least for now */ 647 if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) { 648 if (SVAL(uniuser, 0) == 0) { 649 SSVAL(q, 0, LOGON_SAM_LOGON_USER_UNKNOWN); /* user unknown */ 650 } else { 651 SSVAL(q, 0, LOGON_SAM_LOGON_RESPONSE); 652 } 653 654 q += 2; 655 656 q += dos_PutUniCode(q, reply_name, 657 sizeof(outbuf) - PTR_DIFF(q, outbuf), 658 True); 659 q += dos_PutUniCode(q, ascuser, 660 sizeof(outbuf) - PTR_DIFF(q, outbuf), 661 True); 662 q += dos_PutUniCode(q, lp_workgroup(), 663 sizeof(outbuf) - PTR_DIFF(q, outbuf), 664 True); 665 } 666#ifdef HAVE_ADS 667 else { 668 struct GUID domain_guid; 669 UUID_FLAT flat_guid; 670 char *domain; 671 char *hostname; 672 char *component, *dc, *q1; 673 char *q_orig = q; 674 int str_offset; 675 char *saveptr = NULL; 676 677 domain = get_mydnsdomname(talloc_tos()); 678 if (!domain) { 679 DEBUG(2, 680 ("get_mydnsdomname failed.\n")); 681 return; 682 } 683 hostname = get_myname(talloc_tos()); 684 if (!hostname) { 685 DEBUG(2, 686 ("get_myname failed.\n")); 687 return; 688 } 689 690 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 8) { 691 return; 692 } 693 if (SVAL(uniuser, 0) == 0) { 694 SIVAL(q, 0, LOGON_SAM_LOGON_USER_UNKNOWN_EX); /* user unknown */ 695 } else { 696 SIVAL(q, 0, LOGON_SAM_LOGON_RESPONSE_EX); 697 } 698 q += 4; 699 700 SIVAL(q, 0, NBT_SERVER_PDC|NBT_SERVER_GC|NBT_SERVER_LDAP|NBT_SERVER_DS| 701 NBT_SERVER_KDC|NBT_SERVER_TIMESERV|NBT_SERVER_CLOSEST|NBT_SERVER_WRITABLE); 702 q += 4; 703 704 /* Push Domain GUID */ 705 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < UUID_FLAT_SIZE) { 706 return; 707 } 708 if (False == secrets_fetch_domain_guid(domain, &domain_guid)) { 709 DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain)); 710 return; 711 } 712 713 smb_uuid_pack(domain_guid, &flat_guid); 714 memcpy(q, &flat_guid.info, UUID_FLAT_SIZE); 715 q += UUID_FLAT_SIZE; 716 717 /* Forest */ 718 str_offset = q - q_orig; 719 dc = domain; 720 q1 = q; 721 while ((component = strtok_r(dc, ".", &saveptr)) != NULL) { 722 dc = NULL; 723 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 1) { 724 return; 725 } 726 size = push_ascii(&q[1], component, 727 sizeof(outbuf) - PTR_DIFF(q+1, outbuf), 728 0); 729 if (size == (size_t)-1 || size > 0xff) { 730 return; 731 } 732 SCVAL(q, 0, size); 733 q += (size + 1); 734 } 735 736 /* Unk0 */ 737 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 4) { 738 return; 739 } 740 SCVAL(q, 0, 0); 741 q++; 742 743 /* Domain */ 744 SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); 745 SCVAL(q, 1, str_offset & 0xFF); 746 q += 2; 747 748 /* Hostname */ 749 size = push_ascii(&q[1], hostname, 750 sizeof(outbuf) - PTR_DIFF(q+1, outbuf), 751 0); 752 if (size == (size_t)-1 || size > 0xff) { 753 return; 754 } 755 SCVAL(q, 0, size); 756 q += (size + 1); 757 758 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 3) { 759 return; 760 } 761 762 SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); 763 SCVAL(q, 1, str_offset & 0xFF); 764 q += 2; 765 766 /* NETBIOS of domain */ 767 size = push_ascii(&q[1], lp_workgroup(), 768 sizeof(outbuf) - PTR_DIFF(q+1, outbuf), 769 STR_UPPER); 770 if (size == (size_t)-1 || size > 0xff) { 771 return; 772 } 773 SCVAL(q, 0, size); 774 q += (size + 1); 775 776 /* Unk1 */ 777 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 2) { 778 return; 779 } 780 781 SCVAL(q, 0, 0); 782 q++; 783 784 /* NETBIOS of hostname */ 785 size = push_ascii(&q[1], my_name, 786 sizeof(outbuf) - PTR_DIFF(q+1, outbuf), 787 0); 788 if (size == (size_t)-1 || size > 0xff) { 789 return; 790 } 791 SCVAL(q, 0, size); 792 q += (size + 1); 793 794 /* Unk2 */ 795 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 4) { 796 return; 797 } 798 799 SCVAL(q, 0, 0); 800 q++; 801 802 /* User name */ 803 if (SVAL(uniuser, 0) != 0) { 804 size = push_ascii(&q[1], ascuser, 805 sizeof(outbuf) - PTR_DIFF(q+1, outbuf), 806 0); 807 if (size == (size_t)-1 || size > 0xff) { 808 return; 809 } 810 SCVAL(q, 0, size); 811 q += (size + 1); 812 } 813 814 q_orig = q; 815 /* Site name */ 816 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 1) { 817 return; 818 } 819 size = push_ascii(&q[1], "Default-First-Site-Name", 820 sizeof(outbuf) - PTR_DIFF(q+1, outbuf), 821 0); 822 if (size == (size_t)-1 || size > 0xff) { 823 return; 824 } 825 SCVAL(q, 0, size); 826 q += (size + 1); 827 828 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 18) { 829 return; 830 } 831 832 /* Site name (2) */ 833 str_offset = q - q_orig; 834 SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); 835 SCVAL(q, 1, str_offset & 0xFF); 836 q += 2; 837 838 SCVAL(q, 0, PTR_DIFF(q,q1)); 839 SCVAL(q, 1, 0x10); /* unknown */ 840 841 SIVAL(q, 0, 0x00000002); 842 q += 4; /* unknown */ 843 SIVAL(q, 0, ntohl(ip.s_addr)); 844 q += 4; 845 SIVAL(q, 0, 0x00000000); 846 q += 4; /* unknown */ 847 SIVAL(q, 0, 0x00000000); 848 q += 4; /* unknown */ 849 } 850#endif 851 852 if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 8) { 853 return; 854 } 855 856 /* tell the client what version we are */ 857 SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13); 858 /* our ntversion */ 859 SSVAL(q, 4, 0xffff); /* our lmnttoken */ 860 SSVAL(q, 6, 0xffff); /* our lm20token */ 861 q += 8; 862 863 dump_data(4, (uint8 *)outbuf, PTR_DIFF(q, outbuf)); 864 865 pull_ascii_fstring(getdc_str, getdc); 866 pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name); 867 source_addr = SMB_STRDUP(inet_ntoa(dgram->header.source_ip)); 868 if (source_addr == NULL) { 869 DEBUG(3, ("out of memory copying client" 870 " address string\n")); 871 return; 872 } 873 874 /* 875 * handle delay. 876 * packets requeued after delay are marked as 877 * locked. 878 */ 879 if ((p->locked == False) && 880 (strlen(ascuser) == 0) && 881 delay_logon(source_name, source_addr)) 882 { 883 struct timeval when; 884 885 DEBUG(3, ("process_logon_packet: " 886 "delaying initial logon " 887 "reply for client %s(%s) for " 888 "%u milliseconds\n", 889 source_name, source_addr, 890 lp_init_logon_delay())); 891 892 when = timeval_current_ofs(0, 893 lp_init_logon_delay() * 1000); 894 p->locked = true; 895 event_add_timed(nmbd_event_context(), 896 NULL, 897 when, 898 delayed_init_logon_handler, 899 p); 900 } else { 901 DEBUG(3, ("process_logon_packet: " 902 "processing delayed initial " 903 "logon reply for client " 904 "%s(%s)\n", 905 source_name, source_addr)); 906 907 p->locked = false; 908 send_mailslot(true, getdc, 909 outbuf,PTR_DIFF(q,outbuf), 910 global_myname(), 0x0, 911 source_name, 912 dgram->source_name.name_type, 913 p->ip, ip, p->port); 914 } 915 916 SAFE_FREE(source_addr); 917 918 break; 919 } 920 921 /* Announce change to UAS or SAM. Send by the domain controller when a 922 replication event is required. */ 923 924 case NETLOGON_ANNOUNCE_UAS: 925 DEBUG(5, ("Got NETLOGON_ANNOUNCE_UAS\n")); 926 break; 927 928 default: 929 DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code)); 930 return; 931 } 932} 933