[SCM] Samba Shared Repository - branch master updated

Amitay Isaacs amitay at samba.org
Tue Dec 6 18:21:02 MST 2011


The branch, master has been updated
       via  dbbb626 s4-dns Use match-by-key in GSSAPI server if principal is not specified
       via  0344e72 auth: Allow a NULL principal to be obtained from the credentials
       via  b9f4feb dlz_bind9: Add command line options for URL and debug
       via  de9a4ca dlz_bind9: Set debugging output to stderr
       via  ce19bfc dlz_bind9: Use client supplied credentials for DNS record update
       via  d3d365d dlz_bind9: For creating a child entry, use only SEC_ADS_CREATE_CHILD
      from  817f752 tevent: Install python tevent modules.

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


- Log -----------------------------------------------------------------
commit dbbb626dc0ad7b0100aec3ee3a787e1ac18f528a
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Dec 6 14:18:41 2011 +1100

    s4-dns Use match-by-key in GSSAPI server if principal is not specified
    
    This allows dlz_bind9 to match on exactly the same key as bind9 itself
    
    Andrew Bartlett
    
    Autobuild-User: Amitay Isaacs <amitay at samba.org>
    Autobuild-Date: Wed Dec  7 02:20:10 CET 2011 on sn-devel-104

commit 0344e7278b5ddaba0efd7b31a894e901bd9ef6fb
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Dec 6 15:56:44 2011 +1100

    auth: Allow a NULL principal to be obtained from the credentials
    
    This is important when trying to let GSSAPI search the keytab.
    
    Andrew Bartlett

commit b9f4febd405c9ed8c5386cedeb3190aa395b41c4
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Tue Dec 6 12:01:42 2011 +1100

    dlz_bind9: Add command line options for URL and debug
    
    To specify debug level, use -d <level> in named.conf.
    To specify sam db, use -H <path/to/sam.ldb> in named.conf.
    
    The default log level is set to 0. The log level specified in smb.conf
    is not used. To set log level, use -d option.

commit de9a4ca831a0928044d7a2bc6d9801d92e23e5d9
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Tue Dec 6 10:51:01 2011 +1100

    dlz_bind9: Set debugging output to stderr

commit ce19bfcc6bcbd266c8696b97128d9dd89a2d3bf6
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Wed Nov 30 16:06:08 2011 +1100

    dlz_bind9: Use client supplied credentials for DNS record update
    
    This creates the DNS records with correct owner and group settings.

commit d3d365daab18245ee5f6c2a2de54b9ba00c47f6e
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Wed Nov 30 10:37:14 2011 +1100

    dlz_bind9: For creating a child entry, use only SEC_ADS_CREATE_CHILD
    
    The member servers in AD do not have access to modify the parent, but
    do have access to create child DNS records.

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

Summary of changes:
 auth/credentials/credentials_krb5.c   |   12 ++-
 source4/auth/gensec/gensec_krb5.c     |    5 +-
 source4/auth/kerberos/kerberos_util.c |   12 ++-
 source4/dns_server/dlz_bind9.c        |  146 ++++++++++++++++++++++++++-------
 source4/dns_server/wscript_build      |    2 +-
 5 files changed, 139 insertions(+), 38 deletions(-)


Changeset truncated at 500 lines:

diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c
index 1b7be3f..1e5600c 100644
--- a/auth/credentials/credentials_krb5.c
+++ b/auth/credentials/credentials_krb5.c
@@ -794,9 +794,15 @@ _PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred,
 		return ENOMEM;
 	}
 
-	/* This creates a GSSAPI cred_id_t with the principal and keytab set */
-	maj_stat = gss_krb5_import_cred(&min_stat, NULL, princ, ktc->keytab, 
-					&gcc->creds);
+	if (obtained < CRED_SPECIFIED) {
+		/* This creates a GSSAPI cred_id_t with the principal and keytab set */
+		maj_stat = gss_krb5_import_cred(&min_stat, NULL, NULL, ktc->keytab,
+						&gcc->creds);
+	} else {
+		/* This creates a GSSAPI cred_id_t with the principal and keytab set */
+		maj_stat = gss_krb5_import_cred(&min_stat, NULL, princ, ktc->keytab,
+						&gcc->creds);
+	}
 	if (maj_stat) {
 		if (min_stat) {
 			ret = min_stat;
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index 2a3bd22..0c86177 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -521,7 +521,10 @@ static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security,
 			return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 		}
 		
-		/* This ensures we lookup the correct entry in that keytab */
+		/* This ensures we lookup the correct entry in that
+		 * keytab.  A NULL principal is acceptable, and means
+		 * that the krb5 libs should search the keytab at
+		 * accept time for any matching key */
 		ret = principal_from_credentials(out_mem_ctx, gensec_get_credentials(gensec_security), 
 						 gensec_krb5_state->smb_krb5_context, 
 						 &server_in_keytab, &obtained, &error_string);
diff --git a/source4/auth/kerberos/kerberos_util.c b/source4/auth/kerberos/kerberos_util.c
index c255e66..0a42c30 100644
--- a/source4/auth/kerberos/kerberos_util.c
+++ b/source4/auth/kerberos/kerberos_util.c
@@ -293,14 +293,16 @@ krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
 	krb5_error_code ret;
 	const char *princ_string;
 	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
+	*obtained = CRED_UNINITIALISED;
+
 	if (!mem_ctx) {
 		(*error_string) = error_message(ENOMEM);
 		return ENOMEM;
 	}
 	princ_string = cli_credentials_get_principal_and_obtained(credentials, mem_ctx, obtained);
 	if (!princ_string) {
-		(*error_string) = error_message(ENOMEM);
-		return ENOMEM;
+		*princ = NULL;
+		return 0;
 	}
 
 	ret = parse_principal(parent_ctx, princ_string,
@@ -359,6 +361,12 @@ krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
 		return ret;
 	}
 
+	if (princ == NULL) {
+		(*error_string) = talloc_asprintf(credentials, "principal, username or realm was not specified in the credentials");
+		talloc_free(mem_ctx);
+		return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+	}
+
 	ret = impersonate_principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &impersonate_principal, error_string);
 	if (ret) {
 		talloc_free(mem_ctx);
diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c
index 87476d3..97eaac8 100644
--- a/source4/dns_server/dlz_bind9.c
+++ b/source4/dns_server/dlz_bind9.c
@@ -35,11 +35,13 @@
 #include "gen_ndr/ndr_dnsp.h"
 #include "gen_ndr/server_id.h"
 #include "messaging/messaging.h"
+#include "lib/cmdline/popt_common.h"
 #include "dlz_minimal.h"
 
 
 struct b9_options {
 	const char *url;
+	const char *debug;
 };
 
 struct dlz_bind9_data {
@@ -52,6 +54,8 @@ struct dlz_bind9_data {
 
 	/* Used for dynamic update */
 	struct smb_krb5_context *smb_krb5_ctx;
+	struct auth_session_info *session_info;
+	char *update_name;
 
 	/* helper functions from the dlz_dlopen driver */
 	void (*log)(int level, const char *fmt, ...);
@@ -435,12 +439,23 @@ static isc_result_t parse_options(struct dlz_bind9_data *state,
 				  unsigned int argc, char *argv[],
 				  struct b9_options *options)
 {
-	if (argc == 2) {
-		options->url = talloc_strdup(state, argv[1]);
-		if (options->url == NULL) {
-			return ISC_R_NOMEMORY;
+	int opt;
+	poptContext pc;
+	struct poptOption long_options[] = {
+		{ "url", 'H', POPT_ARG_STRING, &options->url, 0, "database URL", "URL" },
+		{ "debug", 'd', POPT_ARG_STRING, &options->debug, 0, "debug level", "DEBUG" },
+		{ NULL }
+	};
+
+	pc = poptGetContext("dlz_bind9", argc, (const char **)argv, long_options,
+			POPT_CONTEXT_KEEP_FIRST);
+	while ((opt = poptGetNextOpt(pc)) != -1) {
+		switch (opt) {
+		default:
+			state->log(ISC_LOG_ERROR, "dlz_bind9: Invalid option %s: %s",
+				   poptBadOption(pc, 0), poptStrerror(opt));
+			return ISC_R_FAILURE;
 		}
-		state->log(ISC_LOG_INFO, "samba_dlz: Using samdb URL %s", options->url);
 	}
 
 	return ISC_R_SUCCESS;
@@ -476,6 +491,12 @@ _PUBLIC_ isc_result_t dlz_create(const char *dlzname,
 	}
 	va_end(ap);
 
+	/* Do not install samba signal handlers */
+	fault_setup_disable();
+
+	/* Start logging */
+	setup_logging("samba_dlz", DEBUG_DEFAULT_STDERR);
+
 	state->ev_ctx = s4_event_context_init(state);
 	if (state->ev_ctx == NULL) {
 		result = ISC_R_NOMEMORY;
@@ -493,6 +514,12 @@ _PUBLIC_ isc_result_t dlz_create(const char *dlzname,
 		goto failed;
 	}
 
+	if (state->options.debug) {
+		lpcfg_do_global_parameter(state->lp, "log level", state->options.debug);
+	} else {
+		lpcfg_do_global_parameter(state->lp, "log level", "0");
+	}
+
 	if (smb_krb5_init_context(state, state->ev_ctx, state->lp, &state->smb_krb5_ctx) != 0) {
 		result = ISC_R_NOMEMORY;
 		goto failed;
@@ -512,9 +539,6 @@ _PUBLIC_ isc_result_t dlz_create(const char *dlzname,
 		}
 	}
 
-	/* Do not install samba signal handlers */
-	fault_setup_disable();
-
 	state->samdb = samdb_connect_url(state, state->ev_ctx, state->lp,
 					system_session(state->lp), 0, state->options.url);
 	if (state->samdb == NULL) {
@@ -1019,17 +1043,6 @@ _PUBLIC_ isc_result_t dlz_configure(dns_view_t *view, void *dbdata)
 	return ISC_R_SUCCESS;
 }
 
-static char *strlower(char *str)
-{
-	int i;
-
-	for (i=0; i<strlen(str); i++) {
-		str[i] = (char) tolower(str[i]);
-	}
-
-	return str;
-}
-
 /*
   authorize a zone update
  */
@@ -1041,8 +1054,8 @@ _PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const
 	TALLOC_CTX *tmp_ctx;
 	DATA_BLOB ap_req;
 	struct cli_credentials *server_credentials;
-	char *keytab_name, *username;
-	bool ret;
+	char *keytab_name;
+	int ret;
 	int ldb_ret;
 	NTSTATUS nt_status;
 	struct gensec_security *gensec_ctx;
@@ -1053,6 +1066,16 @@ _PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const
 	const char * attrs[] = { NULL };
 	uint32_t access_mask;
 
+	/* Remove cached credentials, if any */
+	if (state->session_info) {
+		talloc_free(state->session_info);
+		state->session_info = NULL;
+	}
+	if (state->update_name) {
+		talloc_free(state->update_name);
+		state->update_name = NULL;
+	}
+
 	tmp_ctx = talloc_new(NULL);
 	if (tmp_ctx == NULL) {
 		state->log(ISC_LOG_ERROR, "samba_dlz: no memory");
@@ -1070,22 +1093,17 @@ _PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const
 	cli_credentials_set_krb5_context(server_credentials, state->smb_krb5_ctx);
 	cli_credentials_set_conf(server_credentials, state->lp);
 
-	username = talloc_asprintf(tmp_ctx, "dns-%s", lpcfg_netbios_name(state->lp));
-	username = strlower(username);
-	cli_credentials_set_username(server_credentials, username, CRED_SPECIFIED);
-	talloc_free(username);
-
 	keytab_name = talloc_asprintf(tmp_ctx, "file:%s/dns.keytab",
 					lpcfg_private_dir(state->lp));
 	ret = cli_credentials_set_keytab_name(server_credentials, state->lp, keytab_name,
 						CRED_SPECIFIED);
-	talloc_free(keytab_name);
 	if (ret != 0) {
-		state->log(ISC_LOG_ERROR, "samba_dlz: failed to obtain server credentials for %s",
-				username);
+		state->log(ISC_LOG_ERROR, "samba_dlz: failed to obtain server credentials from %s",
+			   keytab_name);
 		talloc_free(tmp_ctx);
 		return false;
 	}
+	talloc_free(keytab_name);
 
 	nt_status = gensec_server_start(tmp_ctx,
 					lpcfg_gensec_settings(tmp_ctx, state->lp),
@@ -1097,7 +1115,6 @@ _PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const
 	}
 
 	gensec_set_credentials(gensec_ctx, server_credentials);
-	gensec_set_target_service(gensec_ctx, "dns");
 
 	nt_status = gensec_start_mech_by_name(gensec_ctx, "spnego");
 	if (!NT_STATUS_IS_OK(nt_status)) {
@@ -1133,7 +1150,7 @@ _PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const
 				attrs, "objectClass=dnsNode");
 	if (ldb_ret == LDB_ERR_NO_SUCH_OBJECT) {
 		ldb_dn_remove_child_components(dn, 1);
-		access_mask = SEC_STD_REQUIRED | SEC_ADS_CREATE_CHILD;
+		access_mask = SEC_ADS_CREATE_CHILD;
 		talloc_free(res);
 	} else if (ldb_ret == LDB_SUCCESS) {
 		access_mask = SEC_STD_REQUIRED | SEC_ADS_SELF_WRITE;
@@ -1155,6 +1172,15 @@ _PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const
 		return false;
 	}
 
+	/* Cache session_info, so it can be used in the actual add/delete operation */
+	state->update_name = talloc_strdup(state, name);
+	if (state->update_name == NULL) {
+		state->log(ISC_LOG_ERROR, "samba_dlz: memory allocation error");
+		talloc_free(tmp_ctx);
+		return false;
+	}
+	state->session_info = talloc_steal(state, session_info);
+
 	state->log(ISC_LOG_INFO, "samba_dlz: allowing update of signer=%s name=%s tcpaddr=%s type=%s key=%s",
 		   signer, name, tcpaddr, type, key);
 
@@ -1278,6 +1304,39 @@ static bool b9_record_match(struct dlz_bind9_data *state,
 	return false;
 }
 
+/*
+ * Update session_info on samdb using the cached credentials
+ */
+static bool b9_set_session_info(struct dlz_bind9_data *state, const char *name)
+{
+	int ret;
+
+	if (state->update_name == NULL || state->session_info == NULL) {
+		state->log(ISC_LOG_ERROR, "samba_dlz: invalid credentials");
+		return false;
+	}
+
+	/* Do not use client credentials, if we not updating the client specified name */
+	if (strcmp(state->update_name, name) != 0) {
+		return true;
+	}
+
+	ret = ldb_set_opaque(state->samdb, "sessionInfo", state->session_info);
+	if (ret != LDB_SUCCESS) {
+		state->log(ISC_LOG_ERROR, "samba_dlz: unable to set session info");
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * Reset session_info on samdb as system session
+ */
+static void b9_reset_session_info(struct dlz_bind9_data *state)
+{
+	ldb_set_opaque(state->samdb, "sessionInfo", system_session(state->lp));
+}
 
 /*
   add or modify a rdataset
@@ -1329,7 +1388,12 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo
 	/* get any existing records */
 	ret = ldb_search(state->samdb, rec, &res, dn, LDB_SCOPE_BASE, attrs, "objectClass=dnsNode");
 	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+		if (!b9_set_session_info(state, name)) {
+			talloc_free(rec);
+			return ISC_R_FAILURE;
+		}
 		result = b9_add_record(state, name, dn, rec);
+		b9_reset_session_info(state);
 		talloc_free(rec);
 		if (result == ISC_R_SUCCESS) {
 			state->log(ISC_LOG_ERROR, "samba_dlz: added %s %s", name, rdatastr);
@@ -1383,9 +1447,16 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo
 		return ISC_R_FAILURE;
 	}
 
+
+	if (!b9_set_session_info(state, name)) {
+		talloc_free(rec);
+		return ISC_R_FAILURE;
+	}
+
 	/* modify the record */
 	el->flags = LDB_FLAG_MOD_REPLACE;
 	ret = ldb_modify(state->samdb, res->msgs[0]);
+	b9_reset_session_info(state);
 	if (ret != LDB_SUCCESS) {
 		state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s",
 			   ldb_dn_get_linearized(dn), ldb_errstring(state->samdb));
@@ -1480,14 +1551,21 @@ _PUBLIC_ isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, vo
 	}
 	el->num_values--;
 
+	if (!b9_set_session_info(state, name)) {
+		talloc_free(rec);
+		return ISC_R_FAILURE;
+	}
+
 	if (el->num_values == 0) {
 		/* delete the record */
 		ret = ldb_delete(state->samdb, dn);
+		b9_reset_session_info(state);
 	} else {
 		/* modify the record */
 		el->flags = LDB_FLAG_MOD_REPLACE;
 		ret = ldb_modify(state->samdb, res->msgs[0]);
 	}
+	b9_reset_session_info(state);
 	if (ret != LDB_SUCCESS) {
 		state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s",
 			   ldb_dn_get_linearized(dn), ldb_errstring(state->samdb));
@@ -1581,6 +1659,11 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void *
 		return ISC_R_FAILURE;
 	}
 
+	if (!b9_set_session_info(state, name)) {
+		talloc_free(tmp_ctx);
+		return ISC_R_FAILURE;
+	}
+
 	if (el->num_values == 0) {
 		/* delete the record */
 		ret = ldb_delete(state->samdb, dn);
@@ -1589,6 +1672,7 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, const char *type, void *
 		el->flags = LDB_FLAG_MOD_REPLACE;
 		ret = ldb_modify(state->samdb, res->msgs[0]);
 	}
+	b9_reset_session_info(state);
 	if (ret != LDB_SUCCESS) {
 		state->log(ISC_LOG_ERROR, "samba_dlz: failed to delete type %s in %s - %s",
 			   type, ldb_dn_get_linearized(dn), ldb_errstring(state->samdb));
diff --git a/source4/dns_server/wscript_build b/source4/dns_server/wscript_build
index 8c5bb9c..04c8188 100644
--- a/source4/dns_server/wscript_build
+++ b/source4/dns_server/wscript_build
@@ -16,4 +16,4 @@ bld.SAMBA_LIBRARY('dlz_bind9',
                   link_name='modules/bind9/dlz_bind9.so',
                   realname='dlz_bind9.so',
                   install_path='${MODULESDIR}/bind9',
-                  deps='samba-hostconfig samdb gensec')
+                  deps='samba-hostconfig samdb gensec popt')


-- 
Samba Shared Repository


More information about the samba-cvs mailing list