From 632b4f806eae15e319b8f62caef5d25634cf720c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 3 Jan 2000 06:30:50 +0000 Subject: 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 32f66f4ea63038cb4b3785bdf1762abdde076f5d) --- source3/include/proto.h | 6 +- source3/libsmb/namequery.c | 402 ++++++++++++++++++-------------------------- source3/libsmb/nmblib.c | 45 ++++- source3/libsmb/unexpected.c | 25 ++- source3/nmbd/nmbd_packets.c | 21 ++- source3/smbd/password.c | 163 +++++++++--------- 6 files changed, 329 insertions(+), 333 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 2c2bcd71c1..92a57c0950 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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); BOOL send_packet(struct packet_struct *p); 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); /*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 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 */ diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 0cf89149a8..3898a721c6 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -161,7 +161,7 @@ static BOOL internal_name_status(int fd,char *name,int name_type,BOOL recurse, 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; debug_nmb_packet(p2); @@ -269,7 +269,7 @@ struct in_addr *name_query(int fd,const char *name,int name_type, 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; debug_nmb_packet(p2); @@ -712,259 +712,189 @@ BOOL find_master_ip(char *group, struct in_addr *master_ip) 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. *********************************************************/ - 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) - - fstring pdc_name; - BOOL ret; - - /* - * Due to the fact win WinNT *sucks* we must do a node status - * query here... JRA. - */ - - int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True ); - - if(sock == -1) - return False; - - *pdc_name = '\0'; - - ret = internal_name_status(sock,"*SMBSERVER",0x20,True, - *pdc_ip,NULL,pdc_name,False, - _lookup_pdc_name); - - close(sock); - - if(ret && *pdc_name) { - fstrcpy(ret_name, pdc_name); - return True; - } - - return False; - -#else /* defined(I_HATE_WINDOWS_REPLY_CODE) */ - /* - * Sigh. I *love* this code, it took me ages to get right and it's - * completely *USELESS* because NT 4.x refuses to send the mailslot - * reply back to the correct port (it always uses 138). - * I hate NT when it does these things... JRA. - */ - - 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 buffer[1024]; - 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; - } + 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; + } - buf = &dgram2->data[0]; - buf -= 4; + /* + * Create the request data. + */ - 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; - } + memset(buffer,'\0',sizeof(buffer)); + bufp = buffer; + 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); + + 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 = 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); + + 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--; + } - len = SVAL(buf,smb_vwv11); - buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); + if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) { + struct dgram_packet *dgram2 = &p_ret->packet.dgram; + char *buf; + char *buf2; - if (len <= 0) { - DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len )); - free_packet(p_ret); - continue; - } + buf = &dgram2->data[0]; + buf -= 4; - 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 (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; + } - 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; - } + 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)); - 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; - } - } + if(SVAL(buf2,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; + } - close(sock); - return False; -#endif /* I_HATE_WINDOWS_REPLY_CODE */ + buf2 += 2; + /* Note this is safe as it is a bounded strcpy. */ + fstrcpy(ret_name, buf2); + ret_name[sizeof(fstring)-1] = '\0'; + close(sock); + free_packet(p_ret); + return True; + } + } + + close(sock); + return False; } + /******************************************************** 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) { return internal_resolve_name(group, 0x1C, ip_list, count); diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c index 13f7e11123..9ddfd3a6c6 100644 --- a/source3/libsmb/nmblib.c +++ b/source3/libsmb/nmblib.c @@ -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 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; @@ -992,7 +992,48 @@ struct packet_struct *receive_reply_packet(int fd, int t, int trn_id) if (p) free_packet(p); /* 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; } diff --git a/source3/libsmb/unexpected.c b/source3/libsmb/unexpected.c index 57fad7c696..5106ef60f7 100644 --- a/source3/libsmb/unexpected.c +++ b/source3/libsmb/unexpected.c @@ -111,24 +111,28 @@ void clear_unexpected(time_t t) 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 **************************************************************************/ -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 packet_struct *p; 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 && - p->packet.nmb.header.name_trn_id == match_trn_id) { + if ((match_type == NMB_PACKET && + p->packet.nmb.header.name_trn_id == match_id) || + (match_type == DGRAM_PACKET && + match_mailslot_name(p, match_name))) { matched_packet = p; 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 **************************************************************************/ -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; @@ -150,9 +155,11 @@ struct packet_struct *receive_unexpected_137(int trn_id) if (!tdb2) return 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); diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c index 77bdb29816..3bf009f2c2 100644 --- a/source3/nmbd/nmbd_packets.c +++ b/source3/nmbd/nmbd_packets.c @@ -1204,7 +1204,6 @@ static BOOL listening(struct packet_struct *p,struct nmb_name *nbname) /**************************************************************************** Process udp 138 datagrams ****************************************************************************/ - static void process_dgram(struct packet_struct *p) { 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 (!listening(p,&dgram->dest_name)) { - DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from %s\n", - nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip))); - return; + unexpected_packet(p); + DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from %s\n", + nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip))); + return; } if (dgram->header.msg_type != 0x10 && dgram->header.msg_type != 0x11 && dgram->header.msg_type != 0x12) { - /* Don't process error packets etc yet */ - DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from IP %s as it is \ - an error packet of type %x\n", - nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type)); - return; + unexpected_packet(p); + /* Don't process error packets etc yet */ + DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from IP %s as it is \ +an error packet of type %x\n", + nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type)); + return; } 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); return; } + + unexpected_packet(p); } /**************************************************************************** diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 9792c9ebc8..ca588c6681 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -959,16 +959,18 @@ struct cli_state *server_cryptkey(void) struct cli_state *cli; fstring desthost; struct in_addr dest_ip; - char *p; - BOOL connected_ok = False; + char *p, *pserver; + BOOL connected_ok = False; cli = server_client(); if (!cli_initialise(cli)) return NULL; - p = lp_passwordserver(); - while(p && next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { + pserver = strdup(lp_passwordserver()); + p = pserver; + + while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { standard_sub_basic(desthost); strupper(desthost); @@ -989,6 +991,8 @@ struct cli_state *server_cryptkey(void) } } + free(pserver); + if (!connected_ok) { DEBUG(0,("password server not available\n")); 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. */ - if(ip_equal(ipzero, *ip)) - return False; + if (ip_equal(ipzero, *ip)) + return False; - if(!lookup_pdc_name(global_myname, lp_workgroup(), ip, dc_name)) - return False; + if (!lookup_pdc_name(global_myname, lp_workgroup(), ip, dc_name)) + return False; 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 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 trust_passwd[16]; fstring remote_machine; - char *p; + char *p, *pserver; NET_ID_INFO_CTR ctr; NET_USER_INFO_3 info3; 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. */ - p = lp_passwordserver(); - while(!connected_ok && p && - next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) { - if(strequal(remote_machine, "*")) { - - /* - * We have been asked to dynamcially determine the IP addresses of - * the PDC and BDC's for this DOMAIN, and query them in turn. - */ - - struct in_addr *ip_list = NULL; - 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); + pserver = strdup(lp_passwordserver()); + p = pserver; - 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); - } + while (!connected_ok && + next_token(&p,remote_machine,LIST_SEP,sizeof(remote_machine))) { + if(strequal(remote_machine, "*")) { + connected_ok = find_connect_pdc(&cli, trust_passwd); + } else { + connected_ok = connect_to_domain_password_server(&cli, remote_machine, trust_passwd); + } } + free(pserver); + if (!connected_ok) { DEBUG(0,("domain_client_validate: Domain password server not available.\n")); cli_shutdown(&cli); -- cgit