[SCM] Samba Shared Repository - branch master updated

Kai Blin kai at samba.org
Fri Aug 31 14:47:02 MDT 2012


The branch, master has been updated
       via  c256566 s4 dns: Store TKEYs in a ringbuffer
      from  e4505fc tdb: return unpack error on strdup failure

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


- Log -----------------------------------------------------------------
commit c256566aa97e040a9b3007c779b1006d20462ccb
Author: Kai Blin <kai at samba.org>
Date:   Fri Aug 31 13:41:19 2012 +0200

    s4 dns: Store TKEYs in a ringbuffer
    
    This stops us from potentially being DoSed by tons of TKEYs
    
    Autobuild-User(master): Kai Blin <kai at samba.org>
    Autobuild-Date(master): Fri Aug 31 22:46:01 CEST 2012 on sn-devel-104

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

Summary of changes:
 source4/dns_server/dns_query.c  |  125 ++++++++++++++++++++++-----------------
 source4/dns_server/dns_server.c |   27 ++++++++
 source4/dns_server/dns_server.h |   11 +++-
 3 files changed, 106 insertions(+), 57 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c
index e9c3a24..530b7b2 100644
--- a/source4/dns_server/dns_query.c
+++ b/source4/dns_server/dns_query.c
@@ -36,7 +36,6 @@
 #include "auth/auth.h"
 #include "auth/credentials/credentials.h"
 #include "auth/gensec/gensec.h"
-#include "lib/util/dlinklist.h"
 
 static WERROR create_response_rr(const struct dns_name_question *question,
 				 const struct dnsp_DnssrvRpcRecord *rec,
@@ -321,19 +320,73 @@ static WERROR handle_question(struct dns_server *dns,
 	return WERR_OK;
 }
 
-static NTSTATUS create_new_tkey(TALLOC_CTX *mem_ctx,
-				struct dns_server *dns,
-				struct dns_server_tkey **tkey,
-				const char* name)
+static NTSTATUS accept_gss_ticket(TALLOC_CTX *mem_ctx,
+				  struct dns_server *dns,
+				  struct dns_server_tkey *tkey,
+				  const DATA_BLOB *key,
+				  DATA_BLOB *reply,
+				  uint16_t *dns_auth_error)
+{
+	NTSTATUS status;
+
+	status = gensec_update(tkey->gensec, mem_ctx, dns->task->event_ctx,
+			       *key, reply);
+
+	if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
+		*dns_auth_error = DNS_RCODE_OK;
+		return status;
+	}
+
+	if (NT_STATUS_IS_OK(status)) {
+
+		status = gensec_session_info(tkey->gensec, tkey, &tkey->session_info);
+		if (!NT_STATUS_IS_OK(status)) {
+			*dns_auth_error = DNS_RCODE_BADKEY;
+			return status;
+		}
+		*dns_auth_error = DNS_RCODE_OK;
+	}
+
+	return status;
+}
+
+static struct dns_server_tkey *find_tkey(struct dns_server_tkey_store *store,
+					 const char *name)
+{
+	struct dns_server_tkey *tkey = NULL;
+	uint16_t i = 0;
+
+	do {
+		struct dns_server_tkey *tmp_key = store->tkeys[i];
+
+		i++;
+		i %= TKEY_BUFFER_SIZE;
+
+		if (tmp_key == NULL) {
+			continue;
+		}
+		if (dns_name_equal(name, tmp_key->name)) {
+			tkey = tmp_key;
+			break;
+		}
+	} while (i != 0);
+
+	return tkey;
+}
+
+static NTSTATUS create_tkey(struct dns_server *dns,
+			    const char* name,
+			    struct dns_server_tkey **tkey)
 {
 	NTSTATUS status;
-	struct dns_server_tkey *k = talloc_zero(mem_ctx, struct dns_server_tkey);
+	struct dns_server_tkey_store *store = dns->tkeys;
+	struct dns_server_tkey *k = talloc_zero(store, struct dns_server_tkey);
 
 	if (k == NULL) {
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	k->name = talloc_strdup(mem_ctx, name);
+	k->name = talloc_strdup(k, name);
 
 	if (k->name  == NULL) {
 		return NT_STATUS_NO_MEMORY;
@@ -363,52 +416,16 @@ static NTSTATUS create_new_tkey(TALLOC_CTX *mem_ctx,
 		return status;
 	}
 
-	*tkey = k;
-	return NT_STATUS_OK;
-}
-
-static NTSTATUS accept_gss_ticket(TALLOC_CTX *mem_ctx,
-				  struct dns_server *dns,
-				  struct dns_server_tkey *tkey,
-				  const DATA_BLOB *key,
-				  DATA_BLOB *reply,
-				  uint16_t *dns_auth_error)
-{
-	NTSTATUS status;
-
-	status = gensec_update(tkey->gensec, mem_ctx, dns->task->event_ctx,
-			       *key, reply);
-
-	if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
-		*dns_auth_error = DNS_RCODE_OK;
-		return status;
+	if (store->tkeys[store->next_idx] != NULL) {
+		TALLOC_FREE(store->tkeys[store->next_idx]);
 	}
 
-	if (NT_STATUS_IS_OK(status)) {
+	store->tkeys[store->next_idx] = k;
+	(store->next_idx)++;
+	store->next_idx %= store->size;
 
-		status = gensec_session_info(tkey->gensec, tkey, &tkey->session_info);
-		if (!NT_STATUS_IS_OK(status)) {
-			*dns_auth_error = DNS_RCODE_BADKEY;
-			return status;
-		}
-		*dns_auth_error = DNS_RCODE_OK;
-	}
-
-	return status;
-}
-
-static struct dns_server_tkey *find_tkey(struct dns_server *dns,
-					 const char *name)
-{
-	struct dns_server_tkey *tkey = NULL;
-
-	for (tkey = dns->tkeys; tkey != NULL; tkey = tkey->next) {
-		if (dns_name_equal(name, tkey->name)) {
-			break;
-		}
-	}
-
-	return tkey;
+	*tkey = k;
+	return NT_STATUS_OK;
 }
 
 static WERROR handle_tkey(struct dns_server *dns,
@@ -470,7 +487,7 @@ static WERROR handle_tkey(struct dns_server *dns,
 		DATA_BLOB key;
 		DATA_BLOB reply;
 
-		tkey = find_tkey(dns, in->questions[0].name);
+		tkey = find_tkey(dns->tkeys, in->questions[0].name);
 		if (tkey != NULL && tkey->complete) {
 			/* TODO: check if the key is still valid */
 			DEBUG(1, ("Rejecting tkey negotiation for already established key\n"));
@@ -479,14 +496,12 @@ static WERROR handle_tkey(struct dns_server *dns,
 		}
 
 		if (tkey == NULL) {
-			status  = create_new_tkey(dns, dns, &tkey,
-						  in->questions[0].name);
+			status  = create_tkey(dns, in->questions[0].name,
+					      &tkey);
 			if (!NT_STATUS_IS_OK(status)) {
 				ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
 				return ntstatus_to_werror(status);
 			}
-
-			DLIST_ADD_END(dns->tkeys, tkey, NULL);
 		}
 
 		key.data = in_tkey->rdata.tkey_record.key_data;
diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c
index 70fb6a2..887fc8e 100644
--- a/source4/dns_server/dns_server.c
+++ b/source4/dns_server/dns_server.c
@@ -683,6 +683,27 @@ static int dns_server_sort_zones(struct ldb_message **m1, struct ldb_message **m
 	return 0;
 }
 
+static struct dns_server_tkey_store *tkey_store_init(TALLOC_CTX *mem_ctx,
+						     uint16_t size)
+{
+	struct dns_server_tkey_store *buffer = talloc_zero(mem_ctx,
+						struct dns_server_tkey_store);
+
+	if (buffer == NULL) {
+		return NULL;
+	}
+
+	buffer->size = size;
+	buffer->next_idx = 0;
+
+	buffer->tkeys = talloc_zero_array(buffer, struct dns_server_tkey *, size);
+	if (buffer->tkeys == NULL) {
+		TALLOC_FREE(buffer);
+	}
+
+	return buffer;
+}
+
 static void dns_task_init(struct task_server *task)
 {
 	struct dns_server *dns;
@@ -738,6 +759,12 @@ static void dns_task_init(struct task_server *task)
 		return;
 	}
 
+	dns->tkeys = tkey_store_init(dns, TKEY_BUFFER_SIZE);
+	if (!dns->tkeys) {
+		task_server_terminate(task, "Failed to allocate tkey storage\n", true);
+		return;
+	}
+
 	dns->samdb = samdb_connect(dns, dns->task->event_ctx, dns->task->lp_ctx,
 			      system_session(dns->task->lp_ctx), 0);
 	if (!dns->samdb) {
diff --git a/source4/dns_server/dns_server.h b/source4/dns_server/dns_server.h
index c2fe6cf..42ae0ba 100644
--- a/source4/dns_server/dns_server.h
+++ b/source4/dns_server/dns_server.h
@@ -34,7 +34,6 @@ struct dns_server_zone {
 };
 
 struct dns_server_tkey {
-	struct dns_server_tkey *prev, *next;
 	const char *name;
 	enum dns_tkey_mode mode;
 	struct auth_session_info *session_info;
@@ -42,11 +41,19 @@ struct dns_server_tkey {
 	bool complete;
 };
 
+#define TKEY_BUFFER_SIZE 128
+
+struct dns_server_tkey_store {
+	struct dns_server_tkey **tkeys;
+	uint16_t next_idx;
+	uint16_t size;
+};
+
 struct dns_server {
 	struct task_server *task;
 	struct ldb_context *samdb;
 	struct dns_server_zone *zones;
-	struct dns_server_tkey *tkeys;
+	struct dns_server_tkey_store *tkeys;
 	struct cli_credentials *server_credentials;
 };
 


-- 
Samba Shared Repository


More information about the samba-cvs mailing list