[SCM] Samba Shared Repository - branch master updated

Andrew Tridgell tridge at samba.org
Fri Nov 12 01:04:05 MST 2010


The branch, master has been updated
       via  1ec8d55 s4-kdc: added proxying of kdc requests for RODCs
       via  e7fb5a6 s4-kdc Return HDB_ERR_NOT_FOUND_HERE on un-revealed accounts on an RODC
       via  aa1c32c heimdal Return HDB_ERR_NOT_FOUND_HERE to the caller
       via  2fbaa09 s4-kdc: split the kdc process return into a tri-state
       via  4f352a5 s4-kdc: we don't need the special include handling now
       via  e26609b s4-kdc: rename kdc/kdc.h to kdc/kdc-glue.h
      from  dcd346c s4-tests: Make repl_schema.py test part of Samba4 test suite

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


- Log -----------------------------------------------------------------
commit 1ec8d55e275128f2419fb481f88c7d3d87894506
Author: Andrew Tridgell <tridge at samba.org>
Date:   Fri Nov 12 17:23:34 2010 +1100

    s4-kdc: added proxying of kdc requests for RODCs
    
    when we are an RODC and we get a request for a principal that we don't
    have the right secrets for, we need to proxy the request to a
    writeable DC. This happens for both TCP and UDP requests, for both
    krb5 and kpasswd
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User: Andrew Tridgell <tridge at samba.org>
    Autobuild-Date: Fri Nov 12 08:03:20 UTC 2010 on sn-devel-104

commit e7fb5a6c9142d4dcffd4a331d3aa78ac543db34a
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Nov 12 12:32:50 2010 +1100

    s4-kdc Return HDB_ERR_NOT_FOUND_HERE on un-revealed accounts on an RODC
    
    This means that when we are an RODC, and an account does not have the
    password attributes, we can now indicate to the kdc code that it
    should forward the request to a real DC.
    
    (The proxy code itself is not in this commit).
    
    Andrew Bartlett

commit aa1c32ccb08965ff2044b82cbf624404f7fd377b
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Nov 12 12:31:33 2010 +1100

    heimdal Return HDB_ERR_NOT_FOUND_HERE to the caller
    
    This means that no reply packet should be generated, but that instead
    the user of the libkdc API should forward the packet to a real KDC,
    that has a full database.
    
    Andrew Bartlett

commit 2fbaa099192f7f3ee6ba2b996ddf2ca17baaacf5
Author: Andrew Tridgell <tridge at samba.org>
Date:   Thu Nov 11 14:22:40 2010 +1100

    s4-kdc: split the kdc process return into a tri-state
    
    this is in preparation for doing forwarding of packets for RODCs
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit 4f352a5b6a91d8990506ac33b757fd9afcc0282d
Author: Andrew Tridgell <tridge at samba.org>
Date:   Thu Nov 11 14:13:01 2010 +1100

    s4-kdc: we don't need the special include handling now
    
    the special handling was to cope with the conflict with the kdc.h
    header
    
    Pair-Programmed-With: Andrew Bartlett <abartlet at samba.org>

commit e26609b667094dde09dbe3fcabdc2d26ded7f37c
Author: Andrew Tridgell <tridge at samba.org>
Date:   Thu Nov 11 14:09:41 2010 +1100

    s4-kdc: rename kdc/kdc.h to kdc/kdc-glue.h
    
    kdc.h conflicts with a heimdal header name

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

Summary of changes:
 source4/heimdal/kdc/kerberos5.c |   12 +-
 source4/heimdal/kdc/krb5tgs.c   |   27 ++-
 source4/heimdal/kdc/misc.c      |    6 +-
 source4/kdc/db-glue.c           |    8 +-
 source4/kdc/hdb-samba4.c        |    2 +-
 source4/kdc/kdc-glue.h          |  125 ++++++++
 source4/kdc/kdc.c               |  142 +++++-----
 source4/kdc/kdc.h               |   57 ----
 source4/kdc/kpasswdd.c          |   67 ++--
 source4/kdc/pac-glue.c          |    2 +-
 source4/kdc/proxy.c             |  657 +++++++++++++++++++++++++++++++++++++++
 source4/kdc/wdc-samba4.c        |    2 +-
 source4/kdc/wscript_build       |    8 +-
 13 files changed, 930 insertions(+), 185 deletions(-)
 create mode 100644 source4/kdc/kdc-glue.h
 delete mode 100644 source4/kdc/kdc.h
 create mode 100644 source4/kdc/proxy.c


Changeset truncated at 500 lines:

diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c
index 40e597b..394f4de 100644
--- a/source4/heimdal/kdc/kerberos5.c
+++ b/source4/heimdal/kdc/kerberos5.c
@@ -990,7 +990,10 @@ _kdc_as_rep(krb5_context context,
     ret = _kdc_db_fetch(context, config, client_princ,
 			HDB_F_GET_CLIENT | flags, NULL,
 			&clientdb, &client);
-    if(ret){
+    if(ret == HDB_ERR_NOT_FOUND_HERE) {
+	kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy", client_name);
+	goto out;
+    } else if(ret){
 	const char *msg = krb5_get_error_message(context, ret);
 	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, msg);
 	krb5_free_error_message(context, msg);
@@ -1001,7 +1004,10 @@ _kdc_as_rep(krb5_context context,
     ret = _kdc_db_fetch(context, config, server_princ,
 			HDB_F_GET_SERVER|HDB_F_GET_KRBTGT,
 			NULL, NULL, &server);
-    if(ret){
+    if(ret == HDB_ERR_NOT_FOUND_HERE) {
+	kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", server_name);
+	goto out;
+    } else if(ret){
 	const char *msg = krb5_get_error_message(context, ret);
 	kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name, msg);
 	krb5_free_error_message(context, msg);
@@ -1778,7 +1784,7 @@ _kdc_as_rep(krb5_context context,
 
 out:
     free_AS_REP(&rep);
-    if(ret){
+    if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE){
 	krb5_mk_error(context,
 		      ret,
 		      e_text,
diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c
index 71d99e2..60fb4dc 100644
--- a/source4/heimdal/kdc/krb5tgs.c
+++ b/source4/heimdal/kdc/krb5tgs.c
@@ -1170,7 +1170,17 @@ tgs_parse_request(krb5_context context,
 
     ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, ap_req.ticket.enc_part.kvno, NULL, krbtgt);
 
-    if(ret) {
+    if(ret == HDB_ERR_NOT_FOUND_HERE) {
+	char *p;
+	ret = krb5_unparse_name(context, princ, &p);
+	if (ret != 0)
+	    p = "<unparse_name failed>";
+	krb5_free_principal(context, princ);
+	kdc_log(context, config, 5, "Ticket-granting ticket account %s does not have secrets at this KDC, need to proxy", p);
+	if (ret == 0)
+	    free(p);
+	goto out;
+    } else if(ret){
 	const char *msg = krb5_get_error_message(context, ret);
 	char *p;
 	ret = krb5_unparse_name(context, princ, &p);
@@ -1565,7 +1575,10 @@ server_lookup:
     ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | HDB_F_CANON,
 			NULL, NULL, &server);
 
-    if(ret){
+    if(ret == HDB_ERR_NOT_FOUND_HERE) {
+	kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp);
+	goto out;
+    } else if(ret){
 	const char *new_rlm, *msg;
 	Realm req_rlm;
 	krb5_realm *realms;
@@ -1625,7 +1638,10 @@ server_lookup:
 
     ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON,
 			NULL, &clientdb, &client);
-    if(ret) {
+    if(ret == HDB_ERR_NOT_FOUND_HERE) {
+	kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy", cp);
+	goto out;
+    } else if(ret){
 	const char *krbtgt_realm, *msg;
 
 	/*
@@ -2230,7 +2246,7 @@ _kdc_tgs_rep(krb5_context context,
 out:
     if (replykey)
 	krb5_free_keyblock(context, replykey);
-    if(ret && data->data == NULL){
+    if(ret && ret != HDB_ERR_NOT_FOUND_HERE && data->data == NULL){
 	krb5_mk_error(context,
 		      ret,
 		      NULL,
@@ -2240,6 +2256,7 @@ out:
 		      csec,
 		      cusec,
 		      data);
+	ret = 0;
     }
     free(csec);
     free(cusec);
@@ -2253,5 +2270,5 @@ out:
 	free(auth_data);
     }
 
-    return 0;
+    return ret;
 }
diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c
index 9feb99c..2e95ad2 100644
--- a/source4/heimdal/kdc/misc.c
+++ b/source4/heimdal/kdc/misc.c
@@ -45,7 +45,7 @@ _kdc_db_fetch(krb5_context context,
 	      hdb_entry_ex **h)
 {
     hdb_entry_ex *ent;
-    krb5_error_code ret;
+    krb5_error_code ret = HDB_ERR_NOENTRY;
     int i;
     unsigned kvno = 0;
 
@@ -118,9 +118,9 @@ _kdc_db_fetch(krb5_context context,
 	}
     }
     free(ent);
-    krb5_set_error_message(context, HDB_ERR_NOENTRY,
+    krb5_set_error_message(context, ret,
 			   "no such entry found in hdb");
-    return HDB_ERR_NOENTRY;
+    return ret;
 }
 
 void
diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c
index e9ae5b3..eaa97e3 100644
--- a/source4/kdc/db-glue.c
+++ b/source4/kdc/db-glue.c
@@ -192,6 +192,7 @@ static void samba_kdc_free_entry(krb5_context context, hdb_entry_ex *entry_ex)
 }
 
 static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
+						    struct samba_kdc_db_context *kdc_db_ctx,
 						    TALLOC_CTX *mem_ctx,
 						    struct ldb_message *msg,
 						    uint32_t rid,
@@ -376,6 +377,11 @@ static krb5_error_code samba_kdc_message2entry_keys(krb5_context context,
 	}
 
 	if (allocated_keys == 0) {
+		if (kdc_db_ctx->rodc) {
+			/* We are on an RODC, but don't have keys for this account.  Signal this to the caller */
+			return HDB_ERR_NOT_FOUND_HERE;
+		}
+
 		/* oh, no password.  Apparently (comment in
 		 * hdb-ldap.c) this violates the ASN.1, but this
 		 * allows an entry with no keys (yet). */
@@ -768,7 +774,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
 	entry_ex->entry.generation = NULL;
 
 	/* Get keys from the db */
-	ret = samba_kdc_message2entry_keys(context, p, msg, 
+	ret = samba_kdc_message2entry_keys(context, kdc_db_ctx, p, msg,
 					   rid, is_rodc, userAccountControl,
 					   ent_type, entry_ex);
 	if (ret) {
diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c
index 3956ce2..596e73e 100644
--- a/source4/kdc/hdb-samba4.c
+++ b/source4/kdc/hdb-samba4.c
@@ -37,7 +37,7 @@
 #include "auth/credentials/credentials.h"
 #include "dsdb/samdb/samdb.h"
 #include "param/param.h"
-#include "kdc/kdc.h"
+#include "kdc/kdc-glue.h"
 #include "kdc/db-glue.h"
 
 static krb5_error_code hdb_samba4_open(krb5_context context, HDB *db, int flags, mode_t mode)
diff --git a/source4/kdc/kdc-glue.h b/source4/kdc/kdc-glue.h
new file mode 100644
index 0000000..75b6b98
--- /dev/null
+++ b/source4/kdc/kdc-glue.h
@@ -0,0 +1,125 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   KDC structures
+
+   Copyright (C) Andrew Tridgell	2005
+   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2005
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _KDC_KDC_H
+#define _KDC_KDC_H
+
+#include "system/kerberos.h"
+#include "auth/kerberos/kerberos.h"
+#include <hdb.h>
+#include <kdc.h>
+#include <krb5/windc_plugin.h>
+#include "kdc/samba_kdc.h"
+
+struct tsocket_address;
+
+/*
+  top level context structure for the kdc server
+*/
+struct kdc_server {
+	struct task_server *task;
+	krb5_kdc_configuration *config;
+	struct smb_krb5_context *smb_krb5_context;
+	struct samba_kdc_base_context *base_ctx;
+	struct ldb_context *samdb;
+	bool am_rodc;
+	uint32_t proxy_timeout;
+};
+
+enum kdc_process_ret {
+	KDC_PROCESS_OK=0,
+	KDC_PROCESS_FAILED,
+	KDC_PROCESS_PROXY};
+
+struct kdc_udp_call {
+	struct tsocket_address *src;
+	DATA_BLOB in;
+	DATA_BLOB out;
+};
+
+/* hold information about one kdc/kpasswd udp socket */
+struct kdc_udp_socket {
+	struct kdc_socket *kdc_socket;
+	struct tdgram_context *dgram;
+	struct tevent_queue *send_queue;
+};
+
+struct kdc_tcp_call {
+	struct kdc_tcp_connection *kdc_conn;
+	DATA_BLOB in;
+	DATA_BLOB out;
+	uint8_t out_hdr[4];
+	struct iovec out_iov[2];
+};
+
+typedef enum kdc_process_ret (*kdc_process_fn_t)(struct kdc_server *kdc,
+						 TALLOC_CTX *mem_ctx,
+						 DATA_BLOB *input,
+						 DATA_BLOB *reply,
+						 struct tsocket_address *peer_addr,
+						 struct tsocket_address *my_addr,
+						 int datagram);
+
+
+/* hold information about one kdc socket */
+struct kdc_socket {
+	struct kdc_server *kdc;
+	struct tsocket_address *local_address;
+	kdc_process_fn_t process;
+};
+
+/*
+  state of an open tcp connection
+*/
+struct kdc_tcp_connection {
+	/* stream connection we belong to */
+	struct stream_connection *conn;
+
+	/* the kdc_server the connection belongs to */
+	struct kdc_socket *kdc_socket;
+
+	struct tstream_context *tstream;
+
+	struct tevent_queue *send_queue;
+};
+
+
+enum kdc_process_ret kpasswdd_process(struct kdc_server *kdc,
+				      TALLOC_CTX *mem_ctx,
+				      DATA_BLOB *input,
+				      DATA_BLOB *reply,
+				      struct tsocket_address *peer_addr,
+				      struct tsocket_address *my_addr,
+				      int datagram_reply);
+
+/* from hdb-samba4.c */
+NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx,
+			       krb5_context context, struct HDB **db);
+
+/* from proxy.c */
+void kdc_udp_proxy(struct kdc_server *kdc, struct kdc_udp_socket *sock,
+		   struct kdc_udp_call *call, uint16_t port);
+
+void kdc_tcp_proxy(struct kdc_server *kdc, struct kdc_tcp_connection *kdc_conn,
+		   struct kdc_tcp_call *call, uint16_t port);
+
+#endif
diff --git a/source4/kdc/kdc.c b/source4/kdc/kdc.c
index a4bab42..2a90ea5 100644
--- a/source4/kdc/kdc.c
+++ b/source4/kdc/kdc.c
@@ -39,43 +39,14 @@
 #include "librpc/gen_ndr/ndr_krb5pac.h"
 #include "lib/socket/netif.h"
 #include "param/param.h"
-#include "kdc/kdc.h"
+#include "kdc/kdc-glue.h"
 #include "librpc/gen_ndr/ndr_misc.h"
-
+#include "dsdb/samdb/samdb.h"
+#include "auth/session.h"
 
 extern struct krb5plugin_windc_ftable windc_plugin_table;
 extern struct hdb_method hdb_samba4;
 
-typedef bool (*kdc_process_fn_t)(struct kdc_server *kdc,
-				 TALLOC_CTX *mem_ctx,
-				 DATA_BLOB *input,
-				 DATA_BLOB *reply,
-				 struct tsocket_address *peer_addr,
-				 struct tsocket_address *my_addr,
-				 int datagram);
-
-/* hold information about one kdc socket */
-struct kdc_socket {
-	struct kdc_server *kdc;
-	struct tsocket_address *local_address;
-	kdc_process_fn_t process;
-};
-
-/*
-  state of an open tcp connection
-*/
-struct kdc_tcp_connection {
-	/* stream connection we belong to */
-	struct stream_connection *conn;
-
-	/* the kdc_server the connection belongs to */
-	struct kdc_socket *kdc_socket;
-
-	struct tstream_context *tstream;
-
-	struct tevent_queue *send_queue;
-};
-
 static void kdc_tcp_terminate_connection(struct kdc_tcp_connection *kdcconn, const char *reason)
 {
 	stream_terminate_connection(kdcconn->conn, reason);
@@ -102,13 +73,13 @@ static void kdc_tcp_send(struct stream_connection *conn, uint16_t flags)
    calling conventions
 */
 
-static bool kdc_process(struct kdc_server *kdc,
-			TALLOC_CTX *mem_ctx,
-			DATA_BLOB *input,
-			DATA_BLOB *reply,
-			struct tsocket_address *peer_addr,
-			struct tsocket_address *my_addr,
-			int datagram_reply)
+static enum kdc_process_ret kdc_process(struct kdc_server *kdc,
+					TALLOC_CTX *mem_ctx,
+					DATA_BLOB *input,
+					DATA_BLOB *reply,
+					struct tsocket_address *peer_addr,
+					struct tsocket_address *my_addr,
+					int datagram_reply)
 {
 	int ret;
 	char *pa;
@@ -121,11 +92,11 @@ static bool kdc_process(struct kdc_server *kdc,
 	ret = tsocket_address_bsd_sockaddr(peer_addr, (struct sockaddr *) &ss,
 				sizeof(struct sockaddr_storage));
 	if (ret < 0) {
-		return false;
+		return KDC_PROCESS_FAILED;
 	}
 	pa = tsocket_address_string(peer_addr, mem_ctx);
 	if (pa == NULL) {
-		return false;
+		return KDC_PROCESS_FAILED;
 	}
 
 	DEBUG(10,("Received KDC packet of length %lu from %s\n",
@@ -140,25 +111,23 @@ static bool kdc_process(struct kdc_server *kdc,
 					    datagram_reply);
 	if (ret == -1) {
 		*reply = data_blob(NULL, 0);
-		return false;
+		return KDC_PROCESS_FAILED;
+	}
+
+	if (ret == HDB_ERR_NOT_FOUND_HERE) {
+		*reply = data_blob(NULL, 0);
+		return KDC_PROCESS_PROXY;
 	}
+
 	if (k5_reply.length) {
 		*reply = data_blob_talloc(mem_ctx, k5_reply.data, k5_reply.length);
 		krb5_data_free(&k5_reply);
 	} else {
 		*reply = data_blob(NULL, 0);
 	}
-	return true;
+	return KDC_PROCESS_OK;
 }
 
-struct kdc_tcp_call {
-	struct kdc_tcp_connection *kdc_conn;
-	DATA_BLOB in;
-	DATA_BLOB out;
-	uint8_t out_hdr[4];
-	struct iovec out_iov[2];
-};
-
 static void kdc_tcp_call_writev_done(struct tevent_req *subreq);
 
 static void kdc_tcp_call_loop(struct tevent_req *subreq)
@@ -167,7 +136,7 @@ static void kdc_tcp_call_loop(struct tevent_req *subreq)
 				      struct kdc_tcp_connection);
 	struct kdc_tcp_call *call;
 	NTSTATUS status;
-	bool ok;
+	enum kdc_process_ret ret;
 
 	call = talloc(kdc_conn, struct kdc_tcp_call);
 	if (call == NULL) {
@@ -204,19 +173,30 @@ static void kdc_tcp_call_loop(struct tevent_req *subreq)
 	call->in.length -= 4;
 
 	/* Call krb5 */
-	ok = kdc_conn->kdc_socket->process(kdc_conn->kdc_socket->kdc,
+	ret = kdc_conn->kdc_socket->process(kdc_conn->kdc_socket->kdc,
 					   call,
 					   &call->in,
 					   &call->out,
 					   kdc_conn->conn->remote_address,
 					   kdc_conn->conn->local_address,
 					   0 /* Stream */);
-	if (!ok) {
+	if (ret == KDC_PROCESS_FAILED) {
 		kdc_tcp_terminate_connection(kdc_conn,
 				"kdc_tcp_call_loop: process function failed");
 		return;
 	}
 
+	if (ret == KDC_PROCESS_PROXY) {
+		if (!kdc_conn->kdc_socket->kdc->am_rodc) {
+			kdc_tcp_terminate_connection(kdc_conn,
+						     "kdc_tcp_call_loop: proxying requested when not RODC");
+			return;
+		}
+		kdc_tcp_proxy(kdc_conn->kdc_socket->kdc, kdc_conn, call,
+			      tsocket_address_inet_port(kdc_conn->conn->local_address));
+		goto done;
+	}
+
 	/* First add the length of the out buffer */
 	RSIVAL(call->out_hdr, 0, call->out.length);
 	call->out_iov[0].iov_base = (char *) call->out_hdr;
@@ -237,6 +217,7 @@ static void kdc_tcp_call_loop(struct tevent_req *subreq)
 	}
 	tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call);
 
+done:
 	/*
 	 * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
 	 * packet_full_request_u32 provides the pdu length then.
@@ -349,19 +330,6 @@ static const struct stream_server_ops kdc_tcp_stream_ops = {
 	.send_handler		= kdc_tcp_send
 };
 
-/* hold information about one kdc/kpasswd udp socket */
-struct kdc_udp_socket {
-	struct kdc_socket *kdc_socket;
-	struct tdgram_context *dgram;
-	struct tevent_queue *send_queue;
-};
-
-struct kdc_udp_call {
-	struct tsocket_address *src;
-	DATA_BLOB in;
-	DATA_BLOB out;
-};
-
 static void kdc_udp_call_sendto_done(struct tevent_req *subreq);
 
 static void kdc_udp_call_loop(struct tevent_req *subreq)


-- 
Samba Shared Repository


More information about the samba-cvs mailing list