diff options
-rw-r--r-- | source3/nmbd/nmbd_processlogon.c | 1042 |
1 files changed, 519 insertions, 523 deletions
diff --git a/source3/nmbd/nmbd_processlogon.c b/source3/nmbd/nmbd_processlogon.c index d9e3ea8c9c..357d00b413 100644 --- a/source3/nmbd/nmbd_processlogon.c +++ b/source3/nmbd/nmbd_processlogon.c @@ -351,585 +351,581 @@ logons are not enabled.\n", inet_ntoa(p->ip) )); DEBUG(4,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code)); switch (code) { - case 0: - { - fstring mach_str, user_str, getdc_str; - char *q = buf + 2; - char *machine = q; - char *user = skip_string(buf,len,machine); - - if (!user || PTR_DIFF(user, buf) >= len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } - getdc = skip_string(buf,len,user); + case 0: { + fstring mach_str, user_str, getdc_str; + char *q = buf + 2; + char *machine = q; + char *user = skip_string(buf,len,machine); + + if (!user || PTR_DIFF(user, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + getdc = skip_string(buf,len,user); - if (!getdc || PTR_DIFF(getdc, buf) >= len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } - q = skip_string(buf,len,getdc); + if (!getdc || PTR_DIFF(getdc, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + q = skip_string(buf,len,getdc); - if (!q || PTR_DIFF(q + 5, buf) > len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } - token = SVAL(q,3); + if (!q || PTR_DIFF(q + 5, buf) > len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + token = SVAL(q,3); - fstrcpy(reply_name,my_name); + fstrcpy(reply_name,my_name); - pull_ascii_fstring(mach_str, machine); - pull_ascii_fstring(user_str, user); - pull_ascii_fstring(getdc_str, getdc); + pull_ascii_fstring(mach_str, machine); + pull_ascii_fstring(user_str, user); + pull_ascii_fstring(getdc_str, getdc); - DEBUG(5,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n", - mach_str,inet_ntoa(p->ip),user_str,token)); + DEBUG(5,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n", + mach_str,inet_ntoa(p->ip),user_str,token)); - q = outbuf; - SSVAL(q, 0, 6); - q += 2; + q = outbuf; + SSVAL(q, 0, 6); + q += 2; - fstrcpy(reply_name, "\\\\"); - fstrcat(reply_name, my_name); - size = push_ascii(q,reply_name, - sizeof(outbuf)-PTR_DIFF(q, outbuf), - STR_TERMINATE); - if (size == (size_t)-1) { - return; - } - q = skip_string(outbuf,sizeof(outbuf),q); /* PDC name */ + fstrcpy(reply_name, "\\\\"); + fstrcat(reply_name, my_name); + size = push_ascii(q,reply_name, + sizeof(outbuf)-PTR_DIFF(q, outbuf), + STR_TERMINATE); + if (size == (size_t)-1) { + return; + } + q = skip_string(outbuf,sizeof(outbuf),q); /* PDC name */ - SSVAL(q, 0, token); - q += 2; + SSVAL(q, 0, token); + q += 2; - dump_data(4, (uint8 *)outbuf, PTR_DIFF(q, outbuf)); + dump_data(4, (uint8 *)outbuf, PTR_DIFF(q, outbuf)); - send_mailslot(True, getdc_str, - outbuf,PTR_DIFF(q,outbuf), - global_myname(), 0x0, - mach_str, - dgram->source_name.name_type, - p->ip, ip, p->port); - break; - } + send_mailslot(True, getdc_str, + outbuf,PTR_DIFF(q,outbuf), + global_myname(), 0x0, + mach_str, + dgram->source_name.name_type, + p->ip, ip, p->port); + break; + } - case LOGON_PRIMARY_QUERY: - { - fstring mach_str, getdc_str; - fstring source_name; - char *q = buf + 2; - char *machine = q; + case LOGON_PRIMARY_QUERY: { + fstring mach_str, getdc_str; + fstring source_name; + char *q = buf + 2; + char *machine = q; - if (!lp_domain_master()) { - /* We're not Primary Domain Controller -- ignore this */ - return; - } + if (!lp_domain_master()) { + /* We're not Primary Domain Controller -- ignore this */ + return; + } - getdc = skip_string(buf,len,machine); + getdc = skip_string(buf,len,machine); - if (!getdc || PTR_DIFF(getdc, buf) >= len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } - q = skip_string(buf,len,getdc); + if (!getdc || PTR_DIFF(getdc, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + q = skip_string(buf,len,getdc); - if (!q || PTR_DIFF(q, buf) >= len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } - q = ALIGN2(q, buf); - - /* At this point we can work out if this is a W9X or NT style - request. Experiments show that the difference is wether the - packet ends here. For a W9X request we now end with a pair of - bytes (usually 0xFE 0xFF) whereas with NT we have two further - strings - the following is a simple way of detecting this */ - - if (len - PTR_DIFF(q, buf) <= 3) { - short_request = True; - } else { - unicomp = q; - - if (PTR_DIFF(q, buf) >= len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } - - /* A full length (NT style) request */ - q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp)); - - if (PTR_DIFF(q, buf) >= len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } - - if (len - PTR_DIFF(q, buf) > 8) { - /* with NT5 clients we can sometimes - get additional data - a length specificed string - containing the domain name, then 16 bytes of - data (no idea what it is) */ - int dom_len = CVAL(q, 0); - q++; - if (dom_len != 0) { - q += dom_len + 1; - } - q += 16; - } - - if (PTR_DIFF(q + 8, buf) > len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } - - ntversion = IVAL(q, 0); - lmnttoken = SVAL(q, 4); - lm20token = SVAL(q, 6); - } + if (!q || PTR_DIFF(q, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + q = ALIGN2(q, buf); - /* Construct reply. */ - q = outbuf; - SSVAL(q, 0, NETLOGON_RESPONSE_FROM_PDC); - q += 2; + /* At this point we can work out if this is a W9X or NT style + request. Experiments show that the difference is wether the + packet ends here. For a W9X request we now end with a pair of + bytes (usually 0xFE 0xFF) whereas with NT we have two further + strings - the following is a simple way of detecting this */ - fstrcpy(reply_name,my_name); - size = push_ascii(q, reply_name, - sizeof(outbuf)-PTR_DIFF(q, outbuf), - STR_TERMINATE); - if (size == (size_t)-1) { - return; - } - q = skip_string(outbuf,sizeof(outbuf),q); /* PDC name */ - - /* PDC and domain name */ - if (!short_request) { - /* Make a full reply */ - q = ALIGN2(q, outbuf); - - q += dos_PutUniCode(q, my_name, - sizeof(outbuf) - PTR_DIFF(q, outbuf), - True); /* PDC name */ - q += dos_PutUniCode(q, lp_workgroup(), - sizeof(outbuf) - PTR_DIFF(q, outbuf), - True); /* Domain name*/ - if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 8) { - return; - } - SIVAL(q, 0, 1); /* our nt version */ - SSVAL(q, 4, 0xffff); /* our lmnttoken */ - SSVAL(q, 6, 0xffff); /* our lm20token */ - q += 8; - } + if (len - PTR_DIFF(q, buf) <= 3) { + short_request = True; + } else { + unicomp = q; - /* RJS, 21-Feb-2000, we send a short reply if the request was short */ + if (PTR_DIFF(q, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } - pull_ascii_fstring(mach_str, machine); + /* A full length (NT style) request */ + q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp)); - DEBUG(5,("process_logon_packet: GETDC request from %s at IP %s, \ -reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", - mach_str,inet_ntoa(p->ip), reply_name, lp_workgroup(), - NETLOGON_RESPONSE_FROM_PDC, (uint32)ntversion, (uint32)lmnttoken, - (uint32)lm20token )); + if (PTR_DIFF(q, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + + if (len - PTR_DIFF(q, buf) > 8) { + /* with NT5 clients we can sometimes + get additional data - a length specificed string + containing the domain name, then 16 bytes of + data (no idea what it is) */ + int dom_len = CVAL(q, 0); + q++; + if (dom_len != 0) { + q += dom_len + 1; + } + q += 16; + } + + if (PTR_DIFF(q + 8, buf) > len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } - dump_data(4, (uint8 *)outbuf, PTR_DIFF(q, outbuf)); + ntversion = IVAL(q, 0); + lmnttoken = SVAL(q, 4); + lm20token = SVAL(q, 6); + } - pull_ascii_fstring(getdc_str, getdc); - pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name); + /* Construct reply. */ + q = outbuf; + SSVAL(q, 0, NETLOGON_RESPONSE_FROM_PDC); + q += 2; - send_mailslot(True, getdc_str, - outbuf,PTR_DIFF(q,outbuf), - global_myname(), 0x0, - source_name, - dgram->source_name.name_type, - p->ip, ip, p->port); + fstrcpy(reply_name,my_name); + size = push_ascii(q, reply_name, + sizeof(outbuf)-PTR_DIFF(q, outbuf), + STR_TERMINATE); + if (size == (size_t)-1) { + return; + } + q = skip_string(outbuf,sizeof(outbuf),q); /* PDC name */ + + /* PDC and domain name */ + if (!short_request) { + /* Make a full reply */ + q = ALIGN2(q, outbuf); + + q += dos_PutUniCode(q, my_name, + sizeof(outbuf) - PTR_DIFF(q, outbuf), + True); /* PDC name */ + q += dos_PutUniCode(q, lp_workgroup(), + sizeof(outbuf) - PTR_DIFF(q, outbuf), + True); /* Domain name*/ + if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 8) { return; } + SIVAL(q, 0, 1); /* our nt version */ + SSVAL(q, 4, 0xffff); /* our lmnttoken */ + SSVAL(q, 6, 0xffff); /* our lm20token */ + q += 8; + } - case LOGON_SAM_LOGON_REQUEST: + /* RJS, 21-Feb-2000, we send a short reply if the request was short */ - { - fstring getdc_str; - fstring source_name; - char *source_addr; - char *q = buf + 2; - fstring asccomp; + pull_ascii_fstring(mach_str, machine); - if (global_nmbd_proxy_logon) { - nmbd_proxy_logon(global_nmbd_proxy_logon, - ip, p, (uint8_t *)buf, len); - return; - } + DEBUG(5,("process_logon_packet: GETDC request from %s at IP %s, \ +reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", + mach_str,inet_ntoa(p->ip), reply_name, lp_workgroup(), + NETLOGON_RESPONSE_FROM_PDC, (uint32)ntversion, (uint32)lmnttoken, + (uint32)lm20token )); - q += 2; + dump_data(4, (uint8 *)outbuf, PTR_DIFF(q, outbuf)); - if (PTR_DIFF(q, buf) >= len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } + pull_ascii_fstring(getdc_str, getdc); + pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name); - unicomp = q; - uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp)); + send_mailslot(True, getdc_str, + outbuf,PTR_DIFF(q,outbuf), + global_myname(), 0x0, + source_name, + dgram->source_name.name_type, + p->ip, ip, p->port); + return; + } - if (PTR_DIFF(uniuser, buf) >= len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } + case LOGON_SAM_LOGON_REQUEST: { + fstring getdc_str; + fstring source_name; + char *source_addr; + char *q = buf + 2; + fstring asccomp; - getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser)); + if (global_nmbd_proxy_logon) { + nmbd_proxy_logon(global_nmbd_proxy_logon, + ip, p, (uint8_t *)buf, len); + return; + } - if (PTR_DIFF(getdc, buf) >= len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } + q += 2; - q = skip_string(buf,len,getdc); + if (PTR_DIFF(q, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } - if (!q || PTR_DIFF(q + 8, buf) >= len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } + unicomp = q; + uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp)); - q += 4; /* Account Control Bits - indicating username type */ - domainsidsize = IVAL(q, 0); - q += 4; + if (PTR_DIFF(uniuser, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } - DEBUG(5,("process_logon_packet: LOGON_SAM_LOGON_REQUEST sidsize %d, len = %d\n", domainsidsize, len)); + getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser)); - if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) { - q += domainsidsize; - q = ALIGN4(q, buf); - } + if (PTR_DIFF(getdc, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } - DEBUG(5,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %ld\n", len, (unsigned long)PTR_DIFF(q, buf) )); - - if (len - PTR_DIFF(q, buf) > 8) { - /* with NT5 clients we can sometimes - get additional data - a length specificed string - containing the domain name, then 16 bytes of - data (no idea what it is) */ - int dom_len = CVAL(q, 0); - q++; - if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) { - q += dom_len + 1; - } - q += 16; - } + q = skip_string(buf,len,getdc); - if (PTR_DIFF(q + 8, buf) > len) { - DEBUG(0,("process_logon_packet: bad packet\n")); - return; - } + if (!q || PTR_DIFF(q + 8, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } - ntversion = IVAL(q, 0); - lmnttoken = SVAL(q, 4); - lm20token = SVAL(q, 6); - q += 8; - - DEBUG(3,("process_logon_packet: LOGON_SAM_LOGON_REQUEST sidsize %d ntv %d\n", domainsidsize, ntversion)); - - /* - * we respond regadless of whether the machine is in our password - * database. If it isn't then we let smbd send an appropriate error. - * Let's ignore the SID. - */ - pull_ucs2_fstring(ascuser, uniuser); - pull_ucs2_fstring(asccomp, unicomp); - DEBUG(5,("process_logon_packet: LOGON_SAM_LOGON_REQUEST user %s\n", ascuser)); - - fstrcpy(reply_name, "\\\\"); /* Here it wants \\LOGONSERVER. */ - fstrcat(reply_name, my_name); - - 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", - asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(), - LOGON_SAM_LOGON_RESPONSE ,lmnttoken)); - - /* Construct reply. */ - - q = outbuf; - /* we want the simple version unless we are an ADS PDC..which means */ - /* never, at least for now */ - if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) { - if (SVAL(uniuser, 0) == 0) { - SSVAL(q, 0, LOGON_SAM_LOGON_USER_UNKNOWN); /* user unknown */ - } else { - SSVAL(q, 0, LOGON_SAM_LOGON_RESPONSE); - } - - q += 2; - - q += dos_PutUniCode(q, reply_name, - sizeof(outbuf) - PTR_DIFF(q, outbuf), - True); - q += dos_PutUniCode(q, ascuser, - sizeof(outbuf) - PTR_DIFF(q, outbuf), - True); - q += dos_PutUniCode(q, lp_workgroup(), - sizeof(outbuf) - PTR_DIFF(q, outbuf), - True); - } + q += 4; /* Account Control Bits - indicating username type */ + domainsidsize = IVAL(q, 0); + q += 4; + + DEBUG(5,("process_logon_packet: LOGON_SAM_LOGON_REQUEST sidsize %d, len = %d\n", domainsidsize, len)); + + if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) { + q += domainsidsize; + q = ALIGN4(q, buf); + } + + DEBUG(5,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %ld\n", len, (unsigned long)PTR_DIFF(q, buf) )); + + if (len - PTR_DIFF(q, buf) > 8) { + /* with NT5 clients we can sometimes + get additional data - a length specificed string + containing the domain name, then 16 bytes of + data (no idea what it is) */ + int dom_len = CVAL(q, 0); + q++; + if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) { + q += dom_len + 1; + } + q += 16; + } + + if (PTR_DIFF(q + 8, buf) > len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + + ntversion = IVAL(q, 0); + lmnttoken = SVAL(q, 4); + lm20token = SVAL(q, 6); + q += 8; + + DEBUG(3,("process_logon_packet: LOGON_SAM_LOGON_REQUEST sidsize %d ntv %d\n", domainsidsize, ntversion)); + + /* + * we respond regadless of whether the machine is in our password + * database. If it isn't then we let smbd send an appropriate error. + * Let's ignore the SID. + */ + pull_ucs2_fstring(ascuser, uniuser); + pull_ucs2_fstring(asccomp, unicomp); + DEBUG(5,("process_logon_packet: LOGON_SAM_LOGON_REQUEST user %s\n", ascuser)); + + fstrcpy(reply_name, "\\\\"); /* Here it wants \\LOGONSERVER. */ + fstrcat(reply_name, my_name); + + 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", + asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(), + LOGON_SAM_LOGON_RESPONSE ,lmnttoken)); + + /* Construct reply. */ + + q = outbuf; + /* we want the simple version unless we are an ADS PDC..which means */ + /* never, at least for now */ + if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) { + if (SVAL(uniuser, 0) == 0) { + SSVAL(q, 0, LOGON_SAM_LOGON_USER_UNKNOWN); /* user unknown */ + } else { + SSVAL(q, 0, LOGON_SAM_LOGON_RESPONSE); + } + + q += 2; + + q += dos_PutUniCode(q, reply_name, + sizeof(outbuf) - PTR_DIFF(q, outbuf), + True); + q += dos_PutUniCode(q, ascuser, + sizeof(outbuf) - PTR_DIFF(q, outbuf), + True); + q += dos_PutUniCode(q, lp_workgroup(), + sizeof(outbuf) - PTR_DIFF(q, outbuf), + True); + } #ifdef HAVE_ADS - else { - struct GUID domain_guid; - UUID_FLAT flat_guid; - char *domain; - char *hostname; - char *component, *dc, *q1; - char *q_orig = q; - int str_offset; - char *saveptr = NULL; - - domain = get_mydnsdomname(talloc_tos()); - if (!domain) { - DEBUG(2, - ("get_mydnsdomname failed.\n")); - return; - } - hostname = get_myname(talloc_tos()); - if (!hostname) { - DEBUG(2, - ("get_myname failed.\n")); - return; - } - - if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 8) { - return; - } - if (SVAL(uniuser, 0) == 0) { - SIVAL(q, 0, LOGON_SAM_LOGON_USER_UNKNOWN_EX); /* user unknown */ - } else { - SIVAL(q, 0, LOGON_SAM_LOGON_RESPONSE_EX); - } - q += 4; - - SIVAL(q, 0, NBT_SERVER_PDC|NBT_SERVER_GC|NBT_SERVER_LDAP|NBT_SERVER_DS| - NBT_SERVER_KDC|NBT_SERVER_TIMESERV|NBT_SERVER_CLOSEST|NBT_SERVER_WRITABLE); - q += 4; - - /* Push Domain GUID */ - if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < UUID_FLAT_SIZE) { - return; - } - if (False == secrets_fetch_domain_guid(domain, &domain_guid)) { - DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain)); - return; - } - - smb_uuid_pack(domain_guid, &flat_guid); - memcpy(q, &flat_guid.info, UUID_FLAT_SIZE); - q += UUID_FLAT_SIZE; - - /* Forest */ - str_offset = q - q_orig; - dc = domain; - q1 = q; - while ((component = strtok_r(dc, ".", &saveptr)) != NULL) { - dc = NULL; - if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 1) { - return; - } - size = push_ascii(&q[1], component, - sizeof(outbuf) - PTR_DIFF(q+1, outbuf), - 0); - if (size == (size_t)-1 || size > 0xff) { - return; - } - SCVAL(q, 0, size); - q += (size + 1); - } - - /* Unk0 */ - if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 4) { - return; - } - SCVAL(q, 0, 0); - q++; - - /* Domain */ - SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); - SCVAL(q, 1, str_offset & 0xFF); - q += 2; - - /* Hostname */ - size = push_ascii(&q[1], hostname, - sizeof(outbuf) - PTR_DIFF(q+1, outbuf), - 0); - if (size == (size_t)-1 || size > 0xff) { - return; - } - SCVAL(q, 0, size); - q += (size + 1); - - if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 3) { - return; - } - - SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); - SCVAL(q, 1, str_offset & 0xFF); - q += 2; - - /* NETBIOS of domain */ - size = push_ascii(&q[1], lp_workgroup(), - sizeof(outbuf) - PTR_DIFF(q+1, outbuf), - STR_UPPER); - if (size == (size_t)-1 || size > 0xff) { - return; - } - SCVAL(q, 0, size); - q += (size + 1); - - /* Unk1 */ - if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 2) { - return; - } - - SCVAL(q, 0, 0); - q++; - - /* NETBIOS of hostname */ - size = push_ascii(&q[1], my_name, - sizeof(outbuf) - PTR_DIFF(q+1, outbuf), - 0); - if (size == (size_t)-1 || size > 0xff) { - return; - } - SCVAL(q, 0, size); - q += (size + 1); - - /* Unk2 */ - if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 4) { - return; - } - - SCVAL(q, 0, 0); - q++; - - /* User name */ - if (SVAL(uniuser, 0) != 0) { - size = push_ascii(&q[1], ascuser, - sizeof(outbuf) - PTR_DIFF(q+1, outbuf), - 0); - if (size == (size_t)-1 || size > 0xff) { - return; - } - SCVAL(q, 0, size); - q += (size + 1); - } - - q_orig = q; - /* Site name */ - if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 1) { - return; - } - size = push_ascii(&q[1], "Default-First-Site-Name", - sizeof(outbuf) - PTR_DIFF(q+1, outbuf), - 0); - if (size == (size_t)-1 || size > 0xff) { - return; - } - SCVAL(q, 0, size); - q += (size + 1); - - if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 18) { - return; - } - - /* Site name (2) */ - str_offset = q - q_orig; - SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); - SCVAL(q, 1, str_offset & 0xFF); - q += 2; - - SCVAL(q, 0, PTR_DIFF(q,q1)); - SCVAL(q, 1, 0x10); /* unknown */ - - SIVAL(q, 0, 0x00000002); - q += 4; /* unknown */ - SIVAL(q, 0, ntohl(ip.s_addr)); - q += 4; - SIVAL(q, 0, 0x00000000); - q += 4; /* unknown */ - SIVAL(q, 0, 0x00000000); - q += 4; /* unknown */ - } -#endif + else { + struct GUID domain_guid; + UUID_FLAT flat_guid; + char *domain; + char *hostname; + char *component, *dc, *q1; + char *q_orig = q; + int str_offset; + char *saveptr = NULL; + + domain = get_mydnsdomname(talloc_tos()); + if (!domain) { + DEBUG(2, + ("get_mydnsdomname failed.\n")); + return; + } + hostname = get_myname(talloc_tos()); + if (!hostname) { + DEBUG(2, + ("get_myname failed.\n")); + return; + } - if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 8) { + if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 8) { + return; + } + if (SVAL(uniuser, 0) == 0) { + SIVAL(q, 0, LOGON_SAM_LOGON_USER_UNKNOWN_EX); /* user unknown */ + } else { + SIVAL(q, 0, LOGON_SAM_LOGON_RESPONSE_EX); + } + q += 4; + + SIVAL(q, 0, NBT_SERVER_PDC|NBT_SERVER_GC|NBT_SERVER_LDAP|NBT_SERVER_DS| + NBT_SERVER_KDC|NBT_SERVER_TIMESERV|NBT_SERVER_CLOSEST|NBT_SERVER_WRITABLE); + q += 4; + + /* Push Domain GUID */ + if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < UUID_FLAT_SIZE) { + return; + } + if (False == secrets_fetch_domain_guid(domain, &domain_guid)) { + DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain)); + return; + } + + smb_uuid_pack(domain_guid, &flat_guid); + memcpy(q, &flat_guid.info, UUID_FLAT_SIZE); + q += UUID_FLAT_SIZE; + + /* Forest */ + str_offset = q - q_orig; + dc = domain; + q1 = q; + while ((component = strtok_r(dc, ".", &saveptr)) != NULL) { + dc = NULL; + if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 1) { return; } - - /* tell the client what version we are */ - SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13); - /* our ntversion */ - SSVAL(q, 4, 0xffff); /* our lmnttoken */ - SSVAL(q, 6, 0xffff); /* our lm20token */ - q += 8; - - dump_data(4, (uint8 *)outbuf, PTR_DIFF(q, outbuf)); - - pull_ascii_fstring(getdc_str, getdc); - pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name); - source_addr = SMB_STRDUP(inet_ntoa(dgram->header.source_ip)); - if (source_addr == NULL) { - DEBUG(3, ("out of memory copying client" - " address string\n")); + size = push_ascii(&q[1], component, + sizeof(outbuf) - PTR_DIFF(q+1, outbuf), + 0); + if (size == (size_t)-1 || size > 0xff) { return; } + SCVAL(q, 0, size); + q += (size + 1); + } + + /* Unk0 */ + if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 4) { + return; + } + SCVAL(q, 0, 0); + q++; + + /* Domain */ + SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); + SCVAL(q, 1, str_offset & 0xFF); + q += 2; + + /* Hostname */ + size = push_ascii(&q[1], hostname, + sizeof(outbuf) - PTR_DIFF(q+1, outbuf), + 0); + if (size == (size_t)-1 || size > 0xff) { + return; + } + SCVAL(q, 0, size); + q += (size + 1); + + if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 3) { + return; + } - /* - * handle delay. - * packets requeued after delay are marked as - * locked. - */ - if ((p->locked == False) && - (strlen(ascuser) == 0) && - delay_logon(source_name, source_addr)) - { - struct timeval when; - - DEBUG(3, ("process_logon_packet: " - "delaying initial logon " - "reply for client %s(%s) for " - "%u milliseconds\n", - source_name, source_addr, - lp_init_logon_delay())); - - when = timeval_current_ofs(0, - lp_init_logon_delay() * 1000); - p->locked = true; - event_add_timed(nmbd_event_context(), - NULL, - when, - delayed_init_logon_handler, - p); - } else { - DEBUG(3, ("process_logon_packet: " - "processing delayed initial " - "logon reply for client " - "%s(%s)\n", - source_name, source_addr)); - - p->locked = false; - send_mailslot(true, getdc, - outbuf,PTR_DIFF(q,outbuf), - global_myname(), 0x0, - source_name, - dgram->source_name.name_type, - p->ip, ip, p->port); + SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); + SCVAL(q, 1, str_offset & 0xFF); + q += 2; + + /* NETBIOS of domain */ + size = push_ascii(&q[1], lp_workgroup(), + sizeof(outbuf) - PTR_DIFF(q+1, outbuf), + STR_UPPER); + if (size == (size_t)-1 || size > 0xff) { + return; + } + SCVAL(q, 0, size); + q += (size + 1); + + /* Unk1 */ + if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 2) { + return; + } + + SCVAL(q, 0, 0); + q++; + + /* NETBIOS of hostname */ + size = push_ascii(&q[1], my_name, + sizeof(outbuf) - PTR_DIFF(q+1, outbuf), + 0); + if (size == (size_t)-1 || size > 0xff) { + return; + } + SCVAL(q, 0, size); + q += (size + 1); + + /* Unk2 */ + if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 4) { + return; + } + + SCVAL(q, 0, 0); + q++; + + /* User name */ + if (SVAL(uniuser, 0) != 0) { + size = push_ascii(&q[1], ascuser, + sizeof(outbuf) - PTR_DIFF(q+1, outbuf), + 0); + if (size == (size_t)-1 || size > 0xff) { + return; } + SCVAL(q, 0, size); + q += (size + 1); + } - SAFE_FREE(source_addr); + q_orig = q; + /* Site name */ + if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 1) { + return; + } + size = push_ascii(&q[1], "Default-First-Site-Name", + sizeof(outbuf) - PTR_DIFF(q+1, outbuf), + 0); + if (size == (size_t)-1 || size > 0xff) { + return; + } + SCVAL(q, 0, size); + q += (size + 1); - break; + if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 18) { + return; } - /* Announce change to UAS or SAM. Send by the domain controller when a - replication event is required. */ + /* Site name (2) */ + str_offset = q - q_orig; + SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); + SCVAL(q, 1, str_offset & 0xFF); + q += 2; + + SCVAL(q, 0, PTR_DIFF(q,q1)); + SCVAL(q, 1, 0x10); /* unknown */ + + SIVAL(q, 0, 0x00000002); + q += 4; /* unknown */ + SIVAL(q, 0, ntohl(ip.s_addr)); + q += 4; + SIVAL(q, 0, 0x00000000); + q += 4; /* unknown */ + SIVAL(q, 0, 0x00000000); + q += 4; /* unknown */ + } +#endif - case NETLOGON_ANNOUNCE_UAS: - DEBUG(5, ("Got NETLOGON_ANNOUNCE_UAS\n")); - break; + if (sizeof(outbuf) - PTR_DIFF(q, outbuf) < 8) { + return; + } - default: - DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code)); + /* tell the client what version we are */ + SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13); + /* our ntversion */ + SSVAL(q, 4, 0xffff); /* our lmnttoken */ + SSVAL(q, 6, 0xffff); /* our lm20token */ + q += 8; + + dump_data(4, (uint8 *)outbuf, PTR_DIFF(q, outbuf)); + + pull_ascii_fstring(getdc_str, getdc); + pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name); + source_addr = SMB_STRDUP(inet_ntoa(dgram->header.source_ip)); + if (source_addr == NULL) { + DEBUG(3, ("out of memory copying client" + " address string\n")); return; + } + + /* + * handle delay. + * packets requeued after delay are marked as + * locked. + */ + if ((p->locked == False) && + (strlen(ascuser) == 0) && + delay_logon(source_name, source_addr)) + { + struct timeval when; + + DEBUG(3, ("process_logon_packet: " + "delaying initial logon " + "reply for client %s(%s) for " + "%u milliseconds\n", + source_name, source_addr, + lp_init_logon_delay())); + + when = timeval_current_ofs(0, + lp_init_logon_delay() * 1000); + p->locked = true; + event_add_timed(nmbd_event_context(), + NULL, + when, + delayed_init_logon_handler, + p); + } else { + DEBUG(3, ("process_logon_packet: " + "processing delayed initial " + "logon reply for client " + "%s(%s)\n", + source_name, source_addr)); + + p->locked = false; + send_mailslot(true, getdc, + outbuf,PTR_DIFF(q,outbuf), + global_myname(), 0x0, + source_name, + dgram->source_name.name_type, + p->ip, ip, p->port); + } + + SAFE_FREE(source_addr); + + break; + } + + /* Announce change to UAS or SAM. Send by the domain controller when a + replication event is required. */ + + case NETLOGON_ANNOUNCE_UAS: + DEBUG(5, ("Got NETLOGON_ANNOUNCE_UAS\n")); + break; + + default: + DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code)); + return; } } |