[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Sat Nov 13 22:23:01 MST 2010


The branch, master has been updated
       via  52f2520 Fix the unexpected.tdb database problem. Change nmbd to store the transaction id of packets it was requested to send via a client, and only store replies that match these ids. On the client side change clients to always attempt to ask nmbd first for name_query and node_status calls, and then fall back to doing socket calls if we can't talk to nmbd (either nmbd is not running, or we're not root and cannot open the messaging tdb's). Fix readers of unexpected.tdb to delete packets they've successfully read.
       via  781c4aa Move error reporting of messaging context creation fail into the daemons themselves. Allows client utilities to silently fail to create a messaging context due to access denied on the messaging tdb (which I need for the following patch).
      from  7cb0f95 s4-auth: fixed infinite loop in krb5 auth

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 52f252064817b4be4d45d9fdbb0ad07748a0f317
Author: Jeremy Allison <jra at samba.org>
Date:   Sat Nov 13 20:32:36 2010 -0800

    Fix the unexpected.tdb database problem. Change nmbd to store the
    transaction id of packets it was requested to send via a client, and
    only store replies that match these ids. On the client side change
    clients to always attempt to ask nmbd first for name_query and
    node_status calls, and then fall back to doing socket calls if
    we can't talk to nmbd (either nmbd is not running, or we're not
    root and cannot open the messaging tdb's). Fix readers of unexpected.tdb
    to delete packets they've successfully read.
    
    This should fix a long standing problem of unexpected.tdb
    growing out of control in noisy NetBIOS envioronments with
    lots of bradcasts, yet still allow unprivileged client apps
    to work mostly as well as they already did (nmblookup for
    example) in an environment when nmbd isn't running.
    
    Jeremy.
    
    Autobuild-User: Jeremy Allison <jra at samba.org>
    Autobuild-Date: Sun Nov 14 05:22:45 UTC 2010 on sn-devel-104

commit 781c4aabb87e63df77c76a360b6ed5f6a20e6d58
Author: Jeremy Allison <jra at samba.org>
Date:   Sat Nov 13 20:28:41 2010 -0800

    Move error reporting of messaging context creation fail into
    the daemons themselves. Allows client utilities to silently
    fail to create a messaging context due to access denied on the
    messaging tdb (which I need for the following patch).
    
    Jeremy.

-----------------------------------------------------------------------

Summary of changes:
 source3/include/proto.h        |    2 +
 source3/lib/messages.c         |    4 +-
 source3/lib/messages_local.c   |    2 +-
 source3/lib/server_contexts.c  |    3 -
 source3/libsmb/clidgram.c      |   14 +++--
 source3/libsmb/clidgram.h      |    4 +-
 source3/libsmb/dsgetdcname.c   |    8 ++-
 source3/libsmb/namequery.c     |   35 +++++++++--
 source3/libsmb/unexpected.c    |  133 +++++++++++++++++++++++++++++++++++++++-
 source3/nmbd/nmbd.c            |   25 +++-----
 source3/nmbd/nmbd_packets.c    |    7 ++-
 source3/smbd/globals.c         |    6 ++-
 source3/winbindd/winbindd.c    |   10 +++
 source3/winbindd/winbindd.h    |    1 -
 source3/winbindd/winbindd_cm.c |    7 ++-
 15 files changed, 219 insertions(+), 42 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/proto.h b/source3/include/proto.h
index 10409a4..e31d30d 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -2907,6 +2907,8 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m
 
 /* The following definitions come from libsmb/unexpected.c  */
 
+bool is_requested_send_packet(struct packet_struct *p);
+bool store_outstanding_send_packet(struct packet_struct *p);
 void unexpected_packet(struct packet_struct *p);
 void clear_unexpected(time_t t);
 struct packet_struct *receive_unexpected(enum packet_type packet_type, int id,
diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index 11dc931..41f67d0 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -194,7 +194,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
 	status = messaging_tdb_init(ctx, ctx, &ctx->local);
 
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(0, ("messaging_tdb_init failed: %s\n",
+		DEBUG(2, ("messaging_tdb_init failed: %s\n",
 			  nt_errstr(status)));
 		TALLOC_FREE(ctx);
 		return NULL;
@@ -205,7 +205,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
 		status = messaging_ctdbd_init(ctx, ctx, &ctx->remote);
 
 		if (!NT_STATUS_IS_OK(status)) {
-			DEBUG(1, ("messaging_ctdb_init failed: %s\n",
+			DEBUG(2, ("messaging_ctdb_init failed: %s\n",
 				  nt_errstr(status)));
 			TALLOC_FREE(ctx);
 			return NULL;
diff --git a/source3/lib/messages_local.c b/source3/lib/messages_local.c
index bad577c..8cc060b 100644
--- a/source3/lib/messages_local.c
+++ b/source3/lib/messages_local.c
@@ -108,7 +108,7 @@ NTSTATUS messaging_tdb_init(struct messaging_context *msg_ctx,
 
 	if (!ctx->tdb) {
 		NTSTATUS status = map_nt_error_from_unix(errno);
-		DEBUG(0, ("ERROR: Failed to initialise messages database: "
+		DEBUG(2, ("ERROR: Failed to initialise messages database: "
 			  "%s\n", strerror(errno)));
 		TALLOC_FREE(result);
 		return status;
diff --git a/source3/lib/server_contexts.c b/source3/lib/server_contexts.c
index 5e48b79..f8fe9dc 100644
--- a/source3/lib/server_contexts.c
+++ b/source3/lib/server_contexts.c
@@ -57,9 +57,6 @@ struct messaging_context *server_messaging_context(void)
 					        procid_self(),
 					        server_event_context());
 	}
-	if (server_msg_ctx == NULL) {
-		DEBUG(0, ("Could not init server's messaging context.\n"));
-	}
 	return server_msg_ctx;
 }
 
diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c
index 919ea93..6a7c1b9 100644
--- a/source3/libsmb/clidgram.c
+++ b/source3/libsmb/clidgram.c
@@ -33,7 +33,8 @@ static bool cli_send_mailslot(struct messaging_context *msg_ctx,
 		       char *buf, int len,
 		       const char *srcname, int src_type,
 		       const char *dstname, int dest_type,
-		       const struct sockaddr_storage *dest_ss)
+		       const struct sockaddr_storage *dest_ss,
+		       int dgm_id)
 {
 	struct packet_struct p;
 	struct dgram_packet *dgram = &p.packet.dgram;
@@ -63,8 +64,7 @@ static bool cli_send_mailslot(struct messaging_context *msg_ctx,
 	dgram->header.flags.node_type = M_NODE;
 	dgram->header.flags.first = True;
 	dgram->header.flags.more = False;
-	dgram->header.dgm_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) +
-		((unsigned)sys_getpid()%(unsigned)100);
+	dgram->header.dgm_id = dgm_id;
 	/* source ip is filled by nmbd */
 	dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
 	dgram->header.packet_offset = 0;
@@ -133,7 +133,8 @@ bool send_getdc_request(TALLOC_CTX *mem_ctx,
 			struct sockaddr_storage *dc_ss,
 			const char *domain_name,
 			const struct dom_sid *sid,
-			uint32_t nt_version)
+			uint32_t nt_version,
+			int dgm_id)
 {
 	struct in_addr dc_ip;
 	const char *my_acct_name = NULL;
@@ -193,12 +194,13 @@ bool send_getdc_request(TALLOC_CTX *mem_ctx,
 				 false, NBT_MAILSLOT_NTLOGON, 0,
 				 (char *)blob.data, blob.length,
 				 global_myname(), 0, domain_name, 0x1c,
-				 dc_ss);
+				 dc_ss, dgm_id);
 }
 
 bool receive_getdc_response(TALLOC_CTX *mem_ctx,
 			    struct sockaddr_storage *dc_ss,
 			    const char *domain_name,
+			    int dgm_id,
 			    uint32_t *nt_version,
 			    const char **dc_name,
 			    struct netlogon_samlogon_response **samlogon_response)
@@ -226,7 +228,7 @@ bool receive_getdc_response(TALLOC_CTX *mem_ctx,
 		return false;
 	}
 
-	packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
+	packet = receive_unexpected(DGRAM_PACKET, dgm_id, my_mailslot);
 
 	if (packet == NULL) {
 		DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
diff --git a/source3/libsmb/clidgram.h b/source3/libsmb/clidgram.h
index ff98f3b..b61c0b0 100644
--- a/source3/libsmb/clidgram.h
+++ b/source3/libsmb/clidgram.h
@@ -7,10 +7,12 @@ bool send_getdc_request(TALLOC_CTX *mem_ctx,
 			struct sockaddr_storage *dc_ss,
 			const char *domain_name,
 			const struct dom_sid *sid,
-			uint32_t nt_version);
+			uint32_t nt_version,
+			int dgm_id);
 bool receive_getdc_response(TALLOC_CTX *mem_ctx,
 			    struct sockaddr_storage *dc_ss,
 			    const char *domain_name,
+			    int dgm_id,
 			    uint32_t *nt_version,
 			    const char **dc_name,
 			    struct netlogon_samlogon_response **reply);
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index 4d0310f..1b57c04 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -937,6 +937,11 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
 	DEBUG(10,("process_dc_netbios\n"));
 
 	for (i=0; i<num_dcs; i++) {
+		uint16_t val;
+		int dgm_id;
+
+		generate_random_buffer((uint8_t *)&val, 2);
+		dgm_id = val;
 
 		ip_list.ss = dclist[i].ss;
 		ip_list.port = 0;
@@ -947,7 +952,7 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
 
 		if (send_getdc_request(mem_ctx, msg_ctx,
 				       &dclist[i].ss, domain_name,
-				       NULL, nt_version))
+				       NULL, nt_version, dgm_id))
 		{
 			int k;
 			smb_msleep(300);
@@ -955,6 +960,7 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
 				if (receive_getdc_response(mem_ctx,
 							   &dclist[i].ss,
 							   domain_name,
+							   dgm_id,
 							   &nt_version,
 							   &dc_name,
 							   &r)) {
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index d1fb5ab..6ff5f71 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -22,6 +22,7 @@
 #include "libads/sitename_cache.h"
 #include "libads/dns.h"
 #include "../libcli/netlogon.h"
+#include "librpc/gen_ndr/messaging.h"
 
 /* nmbd.c sets this to True. */
 bool global_in_nmbd = False;
@@ -246,6 +247,31 @@ static NODE_STATUS_STRUCT *parse_node_status(char *p,
 	return ret;
 }
 
+/****************************************************************************
+ Try and send a request to nmbd to send a packet_struct packet first.
+ If this fails, use send_packet().
+**************************************************************************/
+
+static bool send_packet_request(struct packet_struct *p)
+{
+	struct messaging_context *msg_ctx = server_messaging_context();
+	if (msg_ctx) {
+		pid_t nmbd_pid = pidfile_pid("nmbd");
+
+		if (nmbd_pid) {
+			/* Try nmbd. */
+			if (NT_STATUS_IS_OK(messaging_send_buf(msg_ctx,
+					pid_to_procid(nmbd_pid),
+					MSG_SEND_PACKET,
+					(uint8_t *)p,
+					sizeof(struct packet_struct)))) {
+				return true;
+			}
+		}
+	}
+
+	return send_packet(p);
+}
 
 /****************************************************************************
  Do a NBT node status query on an open socket and return an array of
@@ -299,7 +325,7 @@ NODE_STATUS_STRUCT *node_status_query(int fd,
 
 	clock_gettime_mono(&tp);
 
-	if (!send_packet(&p))
+	if (!send_packet_request(&p))
 		return NULL;
 
 	retries--;
@@ -310,7 +336,7 @@ NODE_STATUS_STRUCT *node_status_query(int fd,
 		if (nsec_time_diff(&tp2,&tp)/1000000 > retry_time) {
 			if (!retries)
 				break;
-			if (!found && !send_packet(&p))
+			if (!found && !send_packet_request(&p))
 				return NULL;
 			clock_gettime_mono(&tp);
 			retries--;
@@ -707,7 +733,7 @@ struct sockaddr_storage *name_query(int fd,
 
 	clock_gettime_mono(&tp);
 
-	if (!send_packet(&p))
+	if (!send_packet_request(&p))
 		return NULL;
 
 	retries--;
@@ -719,12 +745,11 @@ struct sockaddr_storage *name_query(int fd,
 		if (nsec_time_diff(&tp2,&tp)/1000000 > retry_time) {
 			if (!retries)
 				break;
-			if (!found && !send_packet(&p))
+			if (!found && !send_packet_request(&p))
 				return NULL;
 			clock_gettime_mono(&tp);
 			retries--;
 		}
-
 		if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
 			struct nmb_packet *nmb2 = &p2->packet.nmb;
 			debug_nmb_packet(p2);
diff --git a/source3/libsmb/unexpected.c b/source3/libsmb/unexpected.c
index 7f86495..0f4227d 100644
--- a/source3/libsmb/unexpected.c
+++ b/source3/libsmb/unexpected.c
@@ -29,6 +29,117 @@ struct unexpected_key {
 	int count;
 };
 
+struct pending_unexpected {
+	struct pending_unexpected *prev, *next;
+	enum packet_type packet_type;
+	int id;
+	time_t timeout;
+};
+
+static struct pending_unexpected *pu_list;
+
+/****************************************************************************
+ This function is called when nmbd has received an unexpected packet.
+ It checks against the list of outstanding packet transaction id's
+ to see if it should be stored in the unexpected.tdb.
+**************************************************************************/
+
+static struct pending_unexpected *find_unexpected_packet(struct packet_struct *p)
+{
+	struct pending_unexpected *pu;
+
+	if (!p) {
+		return NULL;
+	}
+
+	for (pu = pu_list; pu; pu = pu->next) {
+		if (pu->packet_type == p->packet_type) {
+			int id = (p->packet_type == DGRAM_PACKET) ?
+				p->packet.dgram.header.dgm_id :
+				p->packet.nmb.header.name_trn_id;
+			if (id == pu->id) {
+				DEBUG(10,("find_unexpected_packet: found packet "
+					"with id = %d\n", pu->id ));
+				return pu;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+
+/****************************************************************************
+ This function is called when nmbd has been given a packet to send out.
+ It stores a list of outstanding packet transaction id's and the timeout
+ when they should be removed.
+**************************************************************************/
+
+bool store_outstanding_send_packet(struct packet_struct *p)
+{
+	struct pending_unexpected *pu = NULL;
+
+	if (!p) {
+		return false;
+	}
+
+	pu = find_unexpected_packet(p);
+	if (pu) {
+		/* This is a resend, and we haven't received a
+		   reply yet ! Ignore it. */
+		return false;
+	}
+
+	pu = SMB_MALLOC_P(struct pending_unexpected);
+	if (!pu || !p) {
+		return false;
+	}
+
+	ZERO_STRUCTP(pu);
+	pu->packet_type = p->packet_type;
+	pu->id = (p->packet_type == DGRAM_PACKET) ?
+			p->packet.dgram.header.dgm_id :
+			p->packet.nmb.header.name_trn_id;
+	pu->timeout = time(NULL) + 15;
+
+	DLIST_ADD_END(pu_list, pu, struct pending_unexpected *);
+
+	DEBUG(10,("store_outstanding_unexpected_packet: storing packet "
+		"with id = %d\n", pu->id ));
+
+	return true;
+}
+
+/****************************************************************************
+ Return true if this is a reply to a packet we were requested to send.
+**************************************************************************/
+
+bool is_requested_send_packet(struct packet_struct *p)
+{
+	return (find_unexpected_packet(p) != NULL);
+}
+
+/****************************************************************************
+ This function is called when nmbd has received an unexpected packet.
+ It checks against the list of outstanding packet transaction id's
+ to see if it should be stored in the unexpected.tdb. Don't store if
+ not found.
+**************************************************************************/
+
+static bool should_store_unexpected_packet(struct packet_struct *p)
+{
+	struct pending_unexpected *pu = find_unexpected_packet(p);
+
+	if (!pu) {
+		return false;
+	}
+
+	/* Remove the outstanding entry. */
+	DLIST_REMOVE(pu_list, pu);
+	SAFE_FREE(pu);
+	return true;
+}
+
 /****************************************************************************
  All unexpected packets are passed in here, to be stored in a unexpected
  packet database. This allows nmblookup and other tools to receive packets
@@ -44,6 +155,13 @@ void unexpected_packet(struct packet_struct *p)
 	int len=0;
 	uint32_t enc_ip;
 
+	if (!should_store_unexpected_packet(p)) {
+		DEBUG(10,("Not storing unexpected packet\n"));
+		return;
+	}
+
+	DEBUG(10,("unexpected_packet: storing packet\n"));
+
 	if (!tdbd) {
 		tdbd = tdb_wrap_open(NULL, lock_path("unexpected.tdb"), 0,
 				     TDB_CLEAR_IF_FIRST|TDB_DEFAULT|TDB_INCOMPATIBLE_HASH,
@@ -108,6 +226,15 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
 
 void clear_unexpected(time_t t)
 {
+	struct pending_unexpected *pu, *pu_next;
+
+	for (pu = pu_list; pu; pu = pu_next) {
+		pu_next = pu->next;
+		if (pu->timeout < t) {
+			DLIST_REMOVE(pu_list, pu);
+		}
+	}
+
 	if (!tdbd) return;
 
 	if ((lastt != 0) && (t < lastt + NMBD_UNEXPECTED_TIMEOUT))
@@ -168,8 +295,10 @@ static int traverse_match(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf,
 	if ((state->match_type == NMB_PACKET &&
 	     p->packet.nmb.header.name_trn_id == state->match_id) ||
 	    (state->match_type == DGRAM_PACKET &&
-	     match_mailslot_name(p, state->match_name))) {
+	     match_mailslot_name(p, state->match_name) &&
+	     p->packet.dgram.header.dgm_id == state->match_id)) {
 		state->matched_packet = p;
+		tdb_delete(ttdb, kbuf);
 		return -1;
 	}
 
@@ -189,7 +318,7 @@ struct packet_struct *receive_unexpected(enum packet_type packet_type, int id,
 	struct receive_unexpected_state state;
 
 	tdb2 = tdb_wrap_open(talloc_tos(), lock_path("unexpected.tdb"), 0, 0,
-			     O_RDONLY, 0);
+			     O_RDWR, 0);
 	if (!tdb2) return NULL;
 
 	state.matched_packet = NULL;
diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c
index 2bae5f7..30bbeaa 100644
--- a/source3/nmbd/nmbd.c
+++ b/source3/nmbd/nmbd.c
@@ -43,26 +43,17 @@ time_t StartupTime = 0;
 
 struct event_context *nmbd_event_context(void)
 {
-	static struct event_context *ctx;
-
-	if (!ctx && !(ctx = event_context_init(NULL))) {
-		smb_panic("Could not init nmbd event context");
-	}
-	return ctx;
+	return server_event_context();
 }
 
 struct messaging_context *nmbd_messaging_context(void)
 {
-	static struct messaging_context *ctx;
-
-	if (ctx == NULL) {
-		ctx = messaging_init(NULL, procid_self(),
-				     nmbd_event_context());
+	struct messaging_context *msg_ctx = server_messaging_context();
+	if (likely(msg_ctx != NULL)) {
+		return msg_ctx;
 	}
-	if (ctx == NULL) {
-		DEBUG(0, ("Could not init nmbd messaging context.\n"));
-	}
-	return ctx;
+	smb_panic("Could not init nmbd's messaging context.\n");
+	return NULL;
 }
 
 /**************************************************************************** **
@@ -469,7 +460,9 @@ static void msg_nmbd_send_packet(struct messaging_context *msg,
 		p->packet.dgram.header.source_port = 138;
 	}
 
-	send_packet(p);
+	if (store_outstanding_send_packet(p)) {
+		send_packet(p);
+	}
 }
 
 /**************************************************************************** **
diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c
index c80bac4..401eb25 100644
--- a/source3/nmbd/nmbd_packets.c
+++ b/source3/nmbd/nmbd_packets.c
@@ -1909,6 +1909,7 @@ bool listen_for_packets(bool run_election)
 		const char *packet_name;
 		int client_fd;
 		int client_port;
+		bool is_requested_send_reply = false;
 
 		if (sock_array[i] == -1) {
 			continue;
@@ -1937,6 +1938,8 @@ bool listen_for_packets(bool run_election)
 			continue;
 		}
 
+		is_requested_send_reply = is_requested_send_packet(packet);
+
 		/*
 		 * If we got a packet on the broadcast socket and interfaces
 		 * only is set then check it came from one of our local nets.
@@ -1950,7 +1953,8 @@ bool listen_for_packets(bool run_election)
 			continue;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list