summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/auth/gensec/gensec.c77
-rw-r--r--source4/auth/gensec/gensec_gssapi.c1
-rw-r--r--source4/auth/gensec/gensec_krb5.c1
-rw-r--r--source4/libcli/ldap/ldap_bind.c57
4 files changed, 129 insertions, 7 deletions
diff --git a/source4/auth/gensec/gensec.c b/source4/auth/gensec/gensec.c
index 375c55e3ba..3818965a6f 100644
--- a/source4/auth/gensec/gensec.c
+++ b/source4/auth/gensec/gensec.c
@@ -98,6 +98,71 @@ const struct gensec_security_ops **gensec_security_all(int *num_backends_out)
* The list is in the exact order of the OIDs asked for, where available.
*/
+const struct gensec_security_ops **gensec_security_by_sasl(TALLOC_CTX *mem_ctx,
+ const char **sasl_names)
+{
+ const struct gensec_security_ops **backends_out;
+ const struct gensec_security_ops **backends;
+ int i, k, sasl_idx;
+ int num_backends_out = 0;
+ int num_backends;
+
+ if (!sasl_names) {
+ return NULL;
+ }
+
+ backends = gensec_security_all(&num_backends);
+
+ backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
+ if (!backends_out) {
+ return NULL;
+ }
+ backends_out[0] = NULL;
+
+ /* Find backends in our preferred order, by walking our list,
+ * then looking in the supplied list */
+ for (i=0; i < num_backends; i++) {
+ for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
+ if (!backends[i]->sasl_name ||
+ !(strcmp(backends[i]->sasl_name,
+ sasl_names[sasl_idx]) == 0)) {
+ continue;
+ }
+
+ for (k=0; backends_out[k]; k++) {
+ if (backends_out[k] == backends[i]) {
+ break;
+ }
+ }
+
+ if (k < num_backends_out) {
+ /* already in there */
+ continue;
+ }
+
+ backends_out = talloc_realloc(mem_ctx, backends_out,
+ const struct gensec_security_ops *,
+ num_backends_out + 2);
+ if (!backends_out) {
+ return NULL;
+ }
+
+ backends_out[num_backends_out] = backends[i];
+ num_backends_out++;
+ backends_out[num_backends_out] = NULL;
+ }
+ }
+ return backends_out;
+}
+
+/**
+ * Return a unique list of security subsystems from those specified in
+ * the OID list. That is, where two OIDs refer to the same module,
+ * return that module only once
+ *
+ * The list is in the exact order of the OIDs asked for, where available.
+ */
+
const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(TALLOC_CTX *mem_ctx,
const char **oid_strings,
const char *skip)
@@ -121,15 +186,17 @@ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(TALLOC_CTX
backends_out[0].op = NULL;
backends_out[0].oid = NULL;
- for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
- if (strcmp(oid_strings[oid_idx], skip) == 0) {
+ /* Find backends in our preferred order, by walking our list,
+ * then looking in the supplied list */
+ for (i=0; i < num_backends; i++) {
+ if (!backends[i]->oid) {
continue;
}
-
- for (i=0; i < num_backends; i++) {
- if (!backends[i]->oid) {
+ for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
+ if (strcmp(oid_strings[oid_idx], skip) == 0) {
continue;
}
+
for (j=0; backends[i]->oid[j]; j++) {
if (!backends[i]->oid[j] ||
!(strcmp(backends[i]->oid[j],
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index 745191e693..08e2298c1a 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -965,6 +965,7 @@ static const char *gensec_gssapi_krb5_oids[] = {
/* As a server, this could in theory accept any GSSAPI mech */
static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
.name = "gssapi_krb5",
+ .sasl_name = "GSSAPI",
.auth_type = DCERPC_AUTH_TYPE_KRB5,
.oid = gensec_gssapi_krb5_oids,
.client_start = gensec_gssapi_client_start,
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index 43187939bb..d5a2fd9a8f 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -667,6 +667,7 @@ static const char *gensec_krb5_oids[] = {
static const struct gensec_security_ops gensec_fake_gssapi_krb5_security_ops = {
.name = "fake_gssapi_krb5",
+ .sasl_name = "GSSAPI",
.auth_type = DCERPC_AUTH_TYPE_KRB5,
.oid = gensec_krb5_oids,
.client_start = gensec_fake_gssapi_krb5_client_start,
diff --git a/source4/libcli/ldap/ldap_bind.c b/source4/libcli/ldap/ldap_bind.c
index c08ffabc22..81e0c8b4e6 100644
--- a/source4/libcli/ldap/ldap_bind.c
+++ b/source4/libcli/ldap/ldap_bind.c
@@ -145,6 +145,18 @@ NTSTATUS ldap_bind_sasl(struct ldap_connection *conn, struct cli_credentials *cr
DATA_BLOB input = data_blob(NULL, 0);
DATA_BLOB output = data_blob(NULL, 0);
+ struct ldap_message **sasl_mechs_msgs;
+ struct ldap_SearchResEntry *search;
+ int count, i;
+
+ const char **sasl_names;
+ const struct gensec_security_ops **mechs;
+
+ static const char *supported_sasl_mech_attrs[] = {
+ "supportedSASLMechanisms",
+ NULL
+ };
+
status = gensec_client_start(conn, &conn->gensec, NULL);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
@@ -174,16 +186,57 @@ NTSTATUS ldap_bind_sasl(struct ldap_connection *conn, struct cli_credentials *cr
goto failed;
}
- status = gensec_start_mech_by_sasl_name(conn->gensec, "NTLM");
+ status = ildap_search(conn, "", LDAP_SEARCH_SCOPE_BASE, "", supported_sasl_mech_attrs,
+ False, &sasl_mechs_msgs);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to set GENSEC client SPNEGO mechanism: %s\n",
+ DEBUG(1, ("Failed to inquire of target's available sasl mechs in rootdse search: %s\n",
nt_errstr(status)));
goto failed;
}
+
+ count = ildap_count_entries(conn, sasl_mechs_msgs);
+ if (count != 1) {
+ DEBUG(1, ("Failed to inquire of target's available sasl mechs in rootdse search: wrong number of replies: %d\n",
+ count));
+ goto failed;
+ }
tmp_ctx = talloc_new(conn);
if (tmp_ctx == NULL) goto failed;
+ search = &sasl_mechs_msgs[0]->r.SearchResultEntry;
+ if (search->num_attributes != 1) {
+ DEBUG(1, ("Failed to inquire of target's available sasl mechs in rootdse search: wrong number of attributes: %d\n",
+ search->num_attributes));
+ goto failed;
+ }
+
+ sasl_names = talloc_array(tmp_ctx, const char *, search->attributes[0].num_values + 1);
+ if (!sasl_names) {
+ DEBUG(1, ("talloc_arry(char *, %d) failed\n",
+ count));
+ goto failed;
+ }
+
+ for (i=0; i<search->attributes[0].num_values; i++) {
+ sasl_names[i] = (const char *)search->attributes[0].values[i].data;
+ }
+ sasl_names[i] = NULL;
+
+ mechs = gensec_security_by_sasl(tmp_ctx, sasl_names);
+ if (!mechs || !mechs[0]) {
+ DEBUG(1, ("None of the %d proposed SASL mechs were acceptable\n",
+ count));
+ goto failed;
+ }
+
+ status = gensec_start_mech_by_ops(conn->gensec, mechs[0]);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to set GENSEC client mechanism: %s/%s %s\n",
+ mechs[0]->name, mechs[0]->sasl_name, nt_errstr(status)));
+ goto failed;
+ }
+
while (1) {
NTSTATUS gensec_status;
struct ldap_message *response;