mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
added suppport for unexpected udp/138 packets
I also fixed up the lookup_pdc_name() code so that it now works, even
with a NT server that insists on replying to udp/138.
The method I used to match packets was to use the mailslot string as a
datagram ID. The true dgm_id doesn't work as NT doesn't set it
correctly. uggh.
PS: Jeremy, I had to change your code quite a bit, are you sure this
worked with a Samba PDC?? The code looked broken, it got the offsets
wrong in the SMB portion of the packet and filled in the IP
incorrectly.
(This used to be commit 32f66f4ea6
)
This commit is contained in:
parent
8d1d27b43c
commit
632b4f806e
@ -626,7 +626,9 @@ BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2);
|
|||||||
int build_packet(char *buf, struct packet_struct *p);
|
int build_packet(char *buf, struct packet_struct *p);
|
||||||
BOOL send_packet(struct packet_struct *p);
|
BOOL send_packet(struct packet_struct *p);
|
||||||
struct packet_struct *receive_packet(int fd,enum packet_type type,int t);
|
struct packet_struct *receive_packet(int fd,enum packet_type type,int t);
|
||||||
struct packet_struct *receive_reply_packet(int fd, int t, int trn_id);
|
struct packet_struct *receive_nmb_packet(int fd, int t, int trn_id);
|
||||||
|
struct packet_struct *receive_dgram_packet(int fd, int t, char *mailslot_name);
|
||||||
|
BOOL match_mailslot_name(struct packet_struct *p, char *mailslot_name);
|
||||||
void sort_query_replies(char *data, int n, struct in_addr ip);
|
void sort_query_replies(char *data, int n, struct in_addr ip);
|
||||||
|
|
||||||
/*The following definitions come from libsmb/nterr.c */
|
/*The following definitions come from libsmb/nterr.c */
|
||||||
@ -682,7 +684,7 @@ char *smb_errstr(char *inbuf);
|
|||||||
|
|
||||||
void unexpected_packet(struct packet_struct *p);
|
void unexpected_packet(struct packet_struct *p);
|
||||||
void clear_unexpected(time_t t);
|
void clear_unexpected(time_t t);
|
||||||
struct packet_struct *receive_unexpected_137(int trn_id);
|
struct packet_struct *receive_unexpected(enum packet_type packet_type, int id, char *mailslot_name);
|
||||||
|
|
||||||
/*The following definitions come from locking/locking.c */
|
/*The following definitions come from locking/locking.c */
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ static BOOL internal_name_status(int fd,char *name,int name_type,BOOL recurse,
|
|||||||
retries--;
|
retries--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((p2=receive_reply_packet(fd,90,nmb->header.name_trn_id))) {
|
if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
|
||||||
struct nmb_packet *nmb2 = &p2->packet.nmb;
|
struct nmb_packet *nmb2 = &p2->packet.nmb;
|
||||||
debug_nmb_packet(p2);
|
debug_nmb_packet(p2);
|
||||||
|
|
||||||
@ -269,7 +269,7 @@ struct in_addr *name_query(int fd,const char *name,int name_type,
|
|||||||
retries--;
|
retries--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((p2=receive_reply_packet(fd,90,nmb->header.name_trn_id))) {
|
if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
|
||||||
struct nmb_packet *nmb2 = &p2->packet.nmb;
|
struct nmb_packet *nmb2 = &p2->packet.nmb;
|
||||||
debug_nmb_packet(p2);
|
debug_nmb_packet(p2);
|
||||||
|
|
||||||
@ -712,259 +712,189 @@ BOOL find_master_ip(char *group, struct in_addr *master_ip)
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************
|
|
||||||
Internal function to extract the MACHINE<0x20> name.
|
|
||||||
*********************************************************/
|
|
||||||
|
|
||||||
static void _lookup_pdc_name(char *p, char *master,char *rname)
|
|
||||||
{
|
|
||||||
int numnames = CVAL(p,0);
|
|
||||||
|
|
||||||
*rname = '\0';
|
|
||||||
|
|
||||||
p += 1;
|
|
||||||
while (numnames--) {
|
|
||||||
int type = CVAL(p,15);
|
|
||||||
if(type == 0x20) {
|
|
||||||
StrnCpy(rname,p,15);
|
|
||||||
trim_string(rname,NULL," ");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
p += 18;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
Lookup a PDC name given a Domain name and IP address.
|
Lookup a PDC name given a Domain name and IP address.
|
||||||
*********************************************************/
|
*********************************************************/
|
||||||
|
|
||||||
BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
|
BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
|
||||||
{
|
{
|
||||||
#if !defined(I_HATE_WINDOWS_REPLY_CODE)
|
int retries = 3;
|
||||||
|
int retry_time = 2000;
|
||||||
|
struct timeval tval;
|
||||||
|
struct packet_struct p;
|
||||||
|
struct dgram_packet *dgram = &p.packet.dgram;
|
||||||
|
char *ptr,*p2;
|
||||||
|
char tmp[4];
|
||||||
|
int len;
|
||||||
|
struct sockaddr_in sock_name;
|
||||||
|
int sock_len = sizeof(sock_name);
|
||||||
|
const char *mailslot = "\\MAILSLOT\\NET\\NETLOGON";
|
||||||
|
char *mailslot_name;
|
||||||
|
char buffer[1024];
|
||||||
|
char *bufp;
|
||||||
|
int dgm_id = generate_trn_id();
|
||||||
|
int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
|
||||||
|
|
||||||
|
if(sock == -1)
|
||||||
|
return False;
|
||||||
|
|
||||||
|
/* Find out the transient UDP port we have been allocated. */
|
||||||
|
if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
|
||||||
|
DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
|
||||||
|
strerror(errno)));
|
||||||
|
close(sock);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
fstring pdc_name;
|
/*
|
||||||
BOOL ret;
|
* Create the request data.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
memset(buffer,'\0',sizeof(buffer));
|
||||||
* Due to the fact win WinNT *sucks* we must do a node status
|
bufp = buffer;
|
||||||
* query here... JRA.
|
SSVAL(bufp,0,QUERYFORPDC);
|
||||||
*/
|
bufp += 2;
|
||||||
|
fstrcpy(bufp,srcname);
|
||||||
|
bufp += (strlen(bufp) + 1);
|
||||||
|
slprintf(bufp, sizeof(fstring), "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
|
||||||
|
mailslot_name = bufp;
|
||||||
|
bufp += (strlen(bufp) + 1);
|
||||||
|
bufp = align2(bufp, buffer);
|
||||||
|
dos_PutUniCode(bufp, srcname, sizeof(buffer) - (bufp - buffer) - 1);
|
||||||
|
bufp = skip_unicode_string(bufp, 1);
|
||||||
|
SIVAL(bufp,0,1);
|
||||||
|
SSVAL(bufp,4,0xFFFF);
|
||||||
|
SSVAL(bufp,6,0xFFFF);
|
||||||
|
bufp += 8;
|
||||||
|
len = PTR_DIFF(bufp,buffer);
|
||||||
|
|
||||||
int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
|
memset((char *)&p,'\0',sizeof(p));
|
||||||
|
|
||||||
if(sock == -1)
|
/* DIRECT GROUP or UNIQUE datagram. */
|
||||||
return False;
|
dgram->header.msg_type = 0x10;
|
||||||
|
dgram->header.flags.node_type = M_NODE;
|
||||||
|
dgram->header.flags.first = True;
|
||||||
|
dgram->header.flags.more = False;
|
||||||
|
dgram->header.dgm_id = dgm_id;
|
||||||
|
dgram->header.source_ip = *iface_ip(*pdc_ip);
|
||||||
|
dgram->header.source_port = ntohs(sock_name.sin_port);
|
||||||
|
dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
|
||||||
|
dgram->header.packet_offset = 0;
|
||||||
|
|
||||||
|
make_nmb_name(&dgram->source_name,srcname,0,scope);
|
||||||
|
make_nmb_name(&dgram->dest_name,domain,0x1B,scope);
|
||||||
|
|
||||||
|
ptr = &dgram->data[0];
|
||||||
|
|
||||||
|
/* Setup the smb part. */
|
||||||
|
ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
|
||||||
|
memcpy(tmp,ptr,4);
|
||||||
|
set_message(ptr,17,17 + len,True);
|
||||||
|
memcpy(ptr,tmp,4);
|
||||||
|
|
||||||
*pdc_name = '\0';
|
CVAL(ptr,smb_com) = SMBtrans;
|
||||||
|
SSVAL(ptr,smb_vwv1,len);
|
||||||
|
SSVAL(ptr,smb_vwv11,len);
|
||||||
|
SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
|
||||||
|
SSVAL(ptr,smb_vwv13,3);
|
||||||
|
SSVAL(ptr,smb_vwv14,1);
|
||||||
|
SSVAL(ptr,smb_vwv15,1);
|
||||||
|
SSVAL(ptr,smb_vwv16,2);
|
||||||
|
p2 = smb_buf(ptr);
|
||||||
|
pstrcpy(p2,mailslot);
|
||||||
|
p2 = skip_string(p2,1);
|
||||||
|
|
||||||
|
memcpy(p2,buffer,len);
|
||||||
|
p2 += len;
|
||||||
|
|
||||||
|
dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
|
||||||
|
|
||||||
|
p.ip = *pdc_ip;
|
||||||
|
p.port = DGRAM_PORT;
|
||||||
|
p.fd = sock;
|
||||||
|
p.timestamp = time(NULL);
|
||||||
|
p.packet_type = DGRAM_PACKET;
|
||||||
|
|
||||||
|
GetTimeOfDay(&tval);
|
||||||
|
|
||||||
|
if (!send_packet(&p)) {
|
||||||
|
DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
|
||||||
|
close(sock);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
retries--;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
struct timeval tval2;
|
||||||
|
struct packet_struct *p_ret;
|
||||||
|
|
||||||
|
GetTimeOfDay(&tval2);
|
||||||
|
if (TvalDiff(&tval,&tval2) > retry_time) {
|
||||||
|
if (!retries)
|
||||||
|
break;
|
||||||
|
if (!send_packet(&p)) {
|
||||||
|
DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
|
||||||
|
close(sock);
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
GetTimeOfDay(&tval);
|
||||||
|
retries--;
|
||||||
|
}
|
||||||
|
|
||||||
ret = internal_name_status(sock,"*SMBSERVER",0x20,True,
|
if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
|
||||||
*pdc_ip,NULL,pdc_name,False,
|
struct dgram_packet *dgram2 = &p_ret->packet.dgram;
|
||||||
_lookup_pdc_name);
|
char *buf;
|
||||||
|
char *buf2;
|
||||||
|
|
||||||
close(sock);
|
buf = &dgram2->data[0];
|
||||||
|
buf -= 4;
|
||||||
|
|
||||||
if(ret && *pdc_name) {
|
if (CVAL(buf,smb_com) != SMBtrans) {
|
||||||
fstrcpy(ret_name, pdc_name);
|
DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
|
||||||
return True;
|
CVAL(buf,smb_com), (unsigned int)SMBtrans ));
|
||||||
}
|
free_packet(p_ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = SVAL(buf,smb_vwv11);
|
||||||
|
buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
|
||||||
|
|
||||||
|
if (len <= 0) {
|
||||||
|
DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
|
||||||
|
free_packet(p_ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
return False;
|
DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
|
||||||
|
nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
|
||||||
|
inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
|
||||||
|
|
||||||
#else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
|
if(SVAL(buf2,0) != QUERYFORPDC_R) {
|
||||||
/*
|
DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
|
||||||
* Sigh. I *love* this code, it took me ages to get right and it's
|
(unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
|
||||||
* completely *USELESS* because NT 4.x refuses to send the mailslot
|
free_packet(p_ret);
|
||||||
* reply back to the correct port (it always uses 138).
|
continue;
|
||||||
* I hate NT when it does these things... JRA.
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
int retries = 3;
|
buf2 += 2;
|
||||||
int retry_time = 2000;
|
/* Note this is safe as it is a bounded strcpy. */
|
||||||
struct timeval tval;
|
fstrcpy(ret_name, buf2);
|
||||||
struct packet_struct p;
|
ret_name[sizeof(fstring)-1] = '\0';
|
||||||
struct dgram_packet *dgram = &p.packet.dgram;
|
close(sock);
|
||||||
char *ptr,*p2;
|
free_packet(p_ret);
|
||||||
char tmp[4];
|
return True;
|
||||||
int len;
|
}
|
||||||
struct sockaddr_in sock_name;
|
}
|
||||||
int sock_len = sizeof(sock_name);
|
|
||||||
const char *mailslot = "\\MAILSLOT\\NET\\NETLOGON";
|
close(sock);
|
||||||
char buffer[1024];
|
return False;
|
||||||
char *bufp;
|
|
||||||
int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
|
|
||||||
|
|
||||||
if(sock == -1)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
/* Find out the transient UDP port we have been allocated. */
|
|
||||||
if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
|
|
||||||
DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
|
|
||||||
strerror(errno)));
|
|
||||||
close(sock);
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create the request data.
|
|
||||||
*/
|
|
||||||
|
|
||||||
memset(buffer,'\0',sizeof(buffer));
|
|
||||||
bufp = buffer;
|
|
||||||
SSVAL(bufp,0,QUERYFORPDC);
|
|
||||||
bufp += 2;
|
|
||||||
fstrcpy(bufp,srcname);
|
|
||||||
bufp += (strlen(bufp) + 1);
|
|
||||||
fstrcpy(bufp,"\\MAILSLOT\\NET\\GETDC411");
|
|
||||||
bufp += (strlen(bufp) + 1);
|
|
||||||
bufp = align2(bufp, buffer);
|
|
||||||
dos_PutUniCode(bufp, srcname, sizeof(buffer) - (bufp - buffer) - 1);
|
|
||||||
bufp = skip_unicode_string(bufp, 1);
|
|
||||||
SIVAL(bufp,0,1);
|
|
||||||
SSVAL(bufp,4,0xFFFF);
|
|
||||||
SSVAL(bufp,6,0xFFFF);
|
|
||||||
bufp += 8;
|
|
||||||
len = PTR_DIFF(bufp,buffer);
|
|
||||||
|
|
||||||
memset((char *)&p,'\0',sizeof(p));
|
|
||||||
|
|
||||||
/* DIRECT GROUP or UNIQUE datagram. */
|
|
||||||
dgram->header.msg_type = 0x10;
|
|
||||||
dgram->header.flags.node_type = M_NODE;
|
|
||||||
dgram->header.flags.first = True;
|
|
||||||
dgram->header.flags.more = False;
|
|
||||||
dgram->header.dgm_id = generate_trn_id();
|
|
||||||
dgram->header.source_ip = sock_name.sin_addr;
|
|
||||||
dgram->header.source_port = ntohs(sock_name.sin_port);
|
|
||||||
dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
|
|
||||||
dgram->header.packet_offset = 0;
|
|
||||||
|
|
||||||
make_nmb_name(&dgram->source_name,srcname,0,scope);
|
|
||||||
make_nmb_name(&dgram->dest_name,domain,0x1B,scope);
|
|
||||||
|
|
||||||
ptr = &dgram->data[0];
|
|
||||||
|
|
||||||
/* Setup the smb part. */
|
|
||||||
ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
|
|
||||||
memcpy(tmp,ptr,4);
|
|
||||||
set_message(ptr,17,17 + len,True);
|
|
||||||
memcpy(ptr,tmp,4);
|
|
||||||
|
|
||||||
CVAL(ptr,smb_com) = SMBtrans;
|
|
||||||
SSVAL(ptr,smb_vwv1,len);
|
|
||||||
SSVAL(ptr,smb_vwv11,len);
|
|
||||||
SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
|
|
||||||
SSVAL(ptr,smb_vwv13,3);
|
|
||||||
SSVAL(ptr,smb_vwv14,1);
|
|
||||||
SSVAL(ptr,smb_vwv15,1);
|
|
||||||
SSVAL(ptr,smb_vwv16,2);
|
|
||||||
p2 = smb_buf(ptr);
|
|
||||||
pstrcpy(p2,mailslot);
|
|
||||||
p2 = skip_string(p2,1);
|
|
||||||
|
|
||||||
memcpy(p2,buffer,len);
|
|
||||||
p2 += len;
|
|
||||||
|
|
||||||
dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
|
|
||||||
|
|
||||||
p.ip = *pdc_ip;
|
|
||||||
p.port = DGRAM_PORT;
|
|
||||||
p.fd = sock;
|
|
||||||
p.timestamp = time(NULL);
|
|
||||||
p.packet_type = DGRAM_PACKET;
|
|
||||||
|
|
||||||
GetTimeOfDay(&tval);
|
|
||||||
|
|
||||||
if (!send_packet(&p)) {
|
|
||||||
DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
|
|
||||||
close(sock);
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
retries--;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
struct timeval tval2;
|
|
||||||
struct packet_struct *p_ret;
|
|
||||||
|
|
||||||
GetTimeOfDay(&tval2);
|
|
||||||
if (TvalDiff(&tval,&tval2) > retry_time) {
|
|
||||||
if (!retries)
|
|
||||||
break;
|
|
||||||
if (!send_packet(&p)) {
|
|
||||||
DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
|
|
||||||
close(sock);
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
GetTimeOfDay(&tval);
|
|
||||||
retries--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((p_ret = receive_packet(sock,NMB_PACKET,90))) {
|
|
||||||
struct nmb_packet *nmb2 = &p_ret->packet.nmb;
|
|
||||||
struct dgram_packet *dgram2 = &p_ret->packet.dgram;
|
|
||||||
char *buf;
|
|
||||||
char *buf2;
|
|
||||||
|
|
||||||
debug_nmb_packet(p_ret);
|
|
||||||
|
|
||||||
if (memcmp(&p.ip, &p_ret->ip, sizeof(p.ip))) {
|
|
||||||
/*
|
|
||||||
* Not for us.
|
|
||||||
*/
|
|
||||||
DEBUG(0,("lookup_pdc_name: datagram return IP %s doesn't match\n", inet_ntoa(p_ret->ip) ));
|
|
||||||
free_packet(p_ret);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = &dgram2->data[0];
|
|
||||||
buf -= 4;
|
|
||||||
|
|
||||||
if (CVAL(buf,smb_com) != SMBtrans) {
|
|
||||||
DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)CVAL(buf,smb_com),
|
|
||||||
(unsigned int)SMBtrans ));
|
|
||||||
free_packet(p_ret);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = SVAL(buf,smb_vwv11);
|
|
||||||
buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
|
|
||||||
|
|
||||||
if (len <= 0) {
|
|
||||||
DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
|
|
||||||
free_packet(p_ret);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
|
|
||||||
nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
|
|
||||||
inet_ntoa(p_ret->ip), smb_buf(buf),CVAL(buf2,0),len));
|
|
||||||
|
|
||||||
if(SVAL(buf,0) != QUERYFORPDC_R) {
|
|
||||||
DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
|
|
||||||
(unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
|
|
||||||
free_packet(p_ret);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf += 2;
|
|
||||||
/* Note this is safe as it is a bounded strcpy. */
|
|
||||||
fstrcpy(ret_name, buf);
|
|
||||||
ret_name[sizeof(fstring)-1] = '\0';
|
|
||||||
close(sock);
|
|
||||||
free_packet(p_ret);
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close(sock);
|
|
||||||
return False;
|
|
||||||
#endif /* I_HATE_WINDOWS_REPLY_CODE */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
Get the IP address list of the PDC/BDC's of a Domain.
|
Get the IP address list of the PDC/BDC's of a Domain.
|
||||||
*********************************************************/
|
*********************************************************/
|
||||||
|
|
||||||
BOOL get_dc_list(char *group, struct in_addr **ip_list, int *count)
|
BOOL get_dc_list(char *group, struct in_addr **ip_list, int *count)
|
||||||
{
|
{
|
||||||
return internal_resolve_name(group, 0x1C, ip_list, count);
|
return internal_resolve_name(group, 0x1C, ip_list, count);
|
||||||
|
@ -979,7 +979,7 @@ struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
|
|||||||
queue. The packet must be a reply packet and have the specified trn_id
|
queue. The packet must be a reply packet and have the specified trn_id
|
||||||
The timeout is in milliseconds
|
The timeout is in milliseconds
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
struct packet_struct *receive_reply_packet(int fd, int t, int trn_id)
|
struct packet_struct *receive_nmb_packet(int fd, int t, int trn_id)
|
||||||
{
|
{
|
||||||
struct packet_struct *p;
|
struct packet_struct *p;
|
||||||
|
|
||||||
@ -992,7 +992,48 @@ struct packet_struct *receive_reply_packet(int fd, int t, int trn_id)
|
|||||||
if (p) free_packet(p);
|
if (p) free_packet(p);
|
||||||
|
|
||||||
/* try the unexpected packet queue */
|
/* try the unexpected packet queue */
|
||||||
return receive_unexpected_137(trn_id);
|
return receive_unexpected(NMB_PACKET, trn_id, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
receive a UDP/138 packet either via UDP or from the unexpected packet
|
||||||
|
queue. The packet must be a reply packet and have the specified dgm_id
|
||||||
|
The timeout is in milliseconds
|
||||||
|
***************************************************************************/
|
||||||
|
struct packet_struct *receive_dgram_packet(int fd, int t, char *mailslot_name)
|
||||||
|
{
|
||||||
|
struct packet_struct *p;
|
||||||
|
|
||||||
|
p = receive_packet(fd, DGRAM_PACKET, t);
|
||||||
|
|
||||||
|
if (p && match_mailslot_name(p, mailslot_name)) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
if (p) free_packet(p);
|
||||||
|
|
||||||
|
/* try the unexpected packet queue */
|
||||||
|
return receive_unexpected(DGRAM_PACKET, 0, mailslot_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
see if a datagram has the right mailslot name
|
||||||
|
***************************************************************************/
|
||||||
|
BOOL match_mailslot_name(struct packet_struct *p, char *mailslot_name)
|
||||||
|
{
|
||||||
|
struct dgram_packet *dgram = &p->packet.dgram;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
buf = &dgram->data[0];
|
||||||
|
buf -= 4;
|
||||||
|
|
||||||
|
buf = smb_buf(buf);
|
||||||
|
|
||||||
|
if (memcmp(buf, mailslot_name, strlen(mailslot_name)+1) == 0) {
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,24 +111,28 @@ void clear_unexpected(time_t t)
|
|||||||
|
|
||||||
|
|
||||||
static struct packet_struct *matched_packet;
|
static struct packet_struct *matched_packet;
|
||||||
static int match_trn_id;
|
static int match_id;
|
||||||
|
static enum packet_type match_type;
|
||||||
|
static char *match_name;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
tdb traversal fn to find a matching 137 packet
|
tdb traversal fn to find a matching 137 packet
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
static int traverse_match_137(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf)
|
static int traverse_match(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf)
|
||||||
{
|
{
|
||||||
struct unexpected_key key;
|
struct unexpected_key key;
|
||||||
struct packet_struct *p;
|
struct packet_struct *p;
|
||||||
|
|
||||||
memcpy(&key, kbuf.dptr, sizeof(key));
|
memcpy(&key, kbuf.dptr, sizeof(key));
|
||||||
|
|
||||||
if (key.packet_type != NMB_PACKET) return 0;
|
if (key.packet_type != match_type) return 0;
|
||||||
|
|
||||||
p = parse_packet(dbuf.dptr, dbuf.dsize, NMB_PACKET);
|
p = parse_packet(dbuf.dptr, dbuf.dsize, match_type);
|
||||||
|
|
||||||
if (p->packet_type == NMB_PACKET &&
|
if ((match_type == NMB_PACKET &&
|
||||||
p->packet.nmb.header.name_trn_id == match_trn_id) {
|
p->packet.nmb.header.name_trn_id == match_id) ||
|
||||||
|
(match_type == DGRAM_PACKET &&
|
||||||
|
match_mailslot_name(p, match_name))) {
|
||||||
matched_packet = p;
|
matched_packet = p;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -142,7 +146,8 @@ static int traverse_match_137(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf)
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
check for a particular packet in the unexpected packet queue
|
check for a particular packet in the unexpected packet queue
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
struct packet_struct *receive_unexpected_137(int trn_id)
|
struct packet_struct *receive_unexpected(enum packet_type packet_type, int id,
|
||||||
|
char *mailslot_name)
|
||||||
{
|
{
|
||||||
TDB_CONTEXT *tdb2;
|
TDB_CONTEXT *tdb2;
|
||||||
|
|
||||||
@ -150,9 +155,11 @@ struct packet_struct *receive_unexpected_137(int trn_id)
|
|||||||
if (!tdb2) return NULL;
|
if (!tdb2) return NULL;
|
||||||
|
|
||||||
matched_packet = NULL;
|
matched_packet = NULL;
|
||||||
match_trn_id = trn_id;
|
match_id = id;
|
||||||
|
match_type = packet_type;
|
||||||
|
match_name = mailslot_name;
|
||||||
|
|
||||||
tdb_traverse(tdb2, traverse_match_137);
|
tdb_traverse(tdb2, traverse_match);
|
||||||
|
|
||||||
tdb_close(tdb2);
|
tdb_close(tdb2);
|
||||||
|
|
||||||
|
@ -1204,7 +1204,6 @@ static BOOL listening(struct packet_struct *p,struct nmb_name *nbname)
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Process udp 138 datagrams
|
Process udp 138 datagrams
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void process_dgram(struct packet_struct *p)
|
static void process_dgram(struct packet_struct *p)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
@ -1215,20 +1214,22 @@ static void process_dgram(struct packet_struct *p)
|
|||||||
/* If we aren't listening to the destination name then ignore the packet */
|
/* If we aren't listening to the destination name then ignore the packet */
|
||||||
if (!listening(p,&dgram->dest_name))
|
if (!listening(p,&dgram->dest_name))
|
||||||
{
|
{
|
||||||
DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from %s\n",
|
unexpected_packet(p);
|
||||||
nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip)));
|
DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from %s\n",
|
||||||
return;
|
nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip)));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dgram->header.msg_type != 0x10 &&
|
if (dgram->header.msg_type != 0x10 &&
|
||||||
dgram->header.msg_type != 0x11 &&
|
dgram->header.msg_type != 0x11 &&
|
||||||
dgram->header.msg_type != 0x12)
|
dgram->header.msg_type != 0x12)
|
||||||
{
|
{
|
||||||
/* Don't process error packets etc yet */
|
unexpected_packet(p);
|
||||||
DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from IP %s as it is \
|
/* Don't process error packets etc yet */
|
||||||
an error packet of type %x\n",
|
DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from IP %s as it is \
|
||||||
nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type));
|
an error packet of type %x\n",
|
||||||
return;
|
nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = &dgram->data[0];
|
buf = &dgram->data[0];
|
||||||
@ -1275,6 +1276,8 @@ static void process_dgram(struct packet_struct *p)
|
|||||||
process_logon_packet(p,buf2,len,NT_LOGON_MAILSLOT);
|
process_logon_packet(p,buf2,len,NT_LOGON_MAILSLOT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unexpected_packet(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -959,16 +959,18 @@ struct cli_state *server_cryptkey(void)
|
|||||||
struct cli_state *cli;
|
struct cli_state *cli;
|
||||||
fstring desthost;
|
fstring desthost;
|
||||||
struct in_addr dest_ip;
|
struct in_addr dest_ip;
|
||||||
char *p;
|
char *p, *pserver;
|
||||||
BOOL connected_ok = False;
|
BOOL connected_ok = False;
|
||||||
|
|
||||||
cli = server_client();
|
cli = server_client();
|
||||||
|
|
||||||
if (!cli_initialise(cli))
|
if (!cli_initialise(cli))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
p = lp_passwordserver();
|
pserver = strdup(lp_passwordserver());
|
||||||
while(p && next_token( &p, desthost, LIST_SEP, sizeof(desthost))) {
|
p = pserver;
|
||||||
|
|
||||||
|
while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) {
|
||||||
standard_sub_basic(desthost);
|
standard_sub_basic(desthost);
|
||||||
strupper(desthost);
|
strupper(desthost);
|
||||||
|
|
||||||
@ -989,6 +991,8 @@ struct cli_state *server_cryptkey(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(pserver);
|
||||||
|
|
||||||
if (!connected_ok) {
|
if (!connected_ok) {
|
||||||
DEBUG(0,("password server not available\n"));
|
DEBUG(0,("password server not available\n"));
|
||||||
cli_shutdown(cli);
|
cli_shutdown(cli);
|
||||||
@ -1249,15 +1253,79 @@ static BOOL attempt_connect_to_dc(struct cli_state *pcli, struct in_addr *ip, un
|
|||||||
* Ignore addresses we have already tried.
|
* Ignore addresses we have already tried.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(ip_equal(ipzero, *ip))
|
if (ip_equal(ipzero, *ip))
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
if(!lookup_pdc_name(global_myname, lp_workgroup(), ip, dc_name))
|
if (!lookup_pdc_name(global_myname, lp_workgroup(), ip, dc_name))
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
return connect_to_domain_password_server(pcli, dc_name, trust_passwd);
|
return connect_to_domain_password_server(pcli, dc_name, trust_passwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
We have been asked to dynamcially determine the IP addresses of
|
||||||
|
the PDC and BDC's for this DOMAIN, and query them in turn.
|
||||||
|
************************************************************************/
|
||||||
|
static BOOL find_connect_pdc(struct cli_state *pcli, unsigned char *trust_passwd)
|
||||||
|
{
|
||||||
|
struct in_addr *ip_list = NULL;
|
||||||
|
int count = 0;
|
||||||
|
int i;
|
||||||
|
BOOL connected_ok = False;
|
||||||
|
|
||||||
|
if (!get_dc_list(lp_workgroup(), &ip_list, &count))
|
||||||
|
return False;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Firstly try and contact a PDC/BDC who has the same
|
||||||
|
* network address as any of our interfaces.
|
||||||
|
*/
|
||||||
|
for(i = 0; i < count; i++) {
|
||||||
|
if(!is_local_net(ip_list[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if((connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
ip_list[i] = ipzero; /* Tried and failed. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Secondly try and contact a random PDC/BDC.
|
||||||
|
*/
|
||||||
|
if(!connected_ok) {
|
||||||
|
i = (sys_random() % count);
|
||||||
|
|
||||||
|
if (!(connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd)))
|
||||||
|
ip_list[i] = ipzero; /* Tried and failed. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finally go through the IP list in turn, ignoring any addresses
|
||||||
|
* we have already tried.
|
||||||
|
*/
|
||||||
|
if(!connected_ok) {
|
||||||
|
/*
|
||||||
|
* Try and connect to any of the other IP addresses in the PDC/BDC list.
|
||||||
|
* Note that from a WINS server the #1 IP address is the PDC.
|
||||||
|
*/
|
||||||
|
for(i = 0; i < count; i++) {
|
||||||
|
if((connected_ok = attempt_connect_to_dc(pcli, &ip_list[i], trust_passwd)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ip_list != NULL)
|
||||||
|
free((char *)ip_list);
|
||||||
|
|
||||||
|
|
||||||
|
return connected_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
Do the same as security=server, but using NT Domain calls and a session
|
Do the same as security=server, but using NT Domain calls and a session
|
||||||
key from the machine password.
|
key from the machine password.
|
||||||
@ -1273,7 +1341,7 @@ BOOL domain_client_validate( char *user, char *domain,
|
|||||||
unsigned char local_nt_reponse[24];
|
unsigned char local_nt_reponse[24];
|
||||||
unsigned char trust_passwd[16];
|
unsigned char trust_passwd[16];
|
||||||
fstring remote_machine;
|
fstring remote_machine;
|
||||||
char *p;
|
char *p, *pserver;
|
||||||
NET_ID_INFO_CTR ctr;
|
NET_ID_INFO_CTR ctr;
|
||||||
NET_USER_INFO_3 info3;
|
NET_USER_INFO_3 info3;
|
||||||
struct cli_state cli;
|
struct cli_state cli;
|
||||||
@ -1349,75 +1417,20 @@ BOOL domain_client_validate( char *user, char *domain,
|
|||||||
* PDC/BDC. Contact each in turn and try and authenticate.
|
* PDC/BDC. Contact each in turn and try and authenticate.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
p = lp_passwordserver();
|
pserver = strdup(lp_passwordserver());
|
||||||
while(!connected_ok && p &&
|
p = pserver;
|
||||||
next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) {
|
|
||||||
if(strequal(remote_machine, "*")) {
|
|
||||||
|
|
||||||
/*
|
while (!connected_ok &&
|
||||||
* We have been asked to dynamcially determine the IP addresses of
|
next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) {
|
||||||
* the PDC and BDC's for this DOMAIN, and query them in turn.
|
if(strequal(remote_machine, "*")) {
|
||||||
*/
|
connected_ok = find_connect_pdc(&cli, trust_passwd);
|
||||||
|
} else {
|
||||||
struct in_addr *ip_list = NULL;
|
connected_ok = connect_to_domain_password_server(&cli, remote_machine, trust_passwd);
|
||||||
int count = 0;
|
}
|
||||||
int i;
|
|
||||||
|
|
||||||
if(!get_dc_list(lp_workgroup(), &ip_list, &count))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Firstly try and contact a PDC/BDC who has the same
|
|
||||||
* network address as any of our interfaces.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for(i = 0; i < count; i++) {
|
|
||||||
if(!is_local_net(ip_list[i]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if((connected_ok = attempt_connect_to_dc(&cli, &ip_list[i], trust_passwd)))
|
|
||||||
break;
|
|
||||||
|
|
||||||
ip_list[i] = ipzero; /* Tried and failed. */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Secondly try and contact a random PDC/BDC.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(!connected_ok) {
|
|
||||||
i = (sys_random() % count);
|
|
||||||
|
|
||||||
if(!(connected_ok = attempt_connect_to_dc(&cli, &ip_list[i], trust_passwd)))
|
|
||||||
ip_list[i] = ipzero; /* Tried and failed. */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Finally go through the IP list in turn, ignoring any addresses
|
|
||||||
* we have already tried.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(!connected_ok) {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try and connect to any of the other IP addresses in the PDC/BDC list.
|
|
||||||
* Note that from a WINS server the #1 IP address is the PDC.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for(i = 0; i < count; i++) {
|
|
||||||
if((connected_ok = attempt_connect_to_dc(&cli, &ip_list[i], trust_passwd)))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ip_list != NULL)
|
|
||||||
free((char *)ip_list);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
connected_ok = connect_to_domain_password_server(&cli, remote_machine, trust_passwd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(pserver);
|
||||||
|
|
||||||
if (!connected_ok) {
|
if (!connected_ok) {
|
||||||
DEBUG(0,("domain_client_validate: Domain password server not available.\n"));
|
DEBUG(0,("domain_client_validate: Domain password server not available.\n"));
|
||||||
cli_shutdown(&cli);
|
cli_shutdown(&cli);
|
||||||
|
Loading…
Reference in New Issue
Block a user