1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-28 07:21:54 +03:00

r1802: start to support SASL in our ldap libraries

does not work yet but we are close currently we send the right data
on wire and fail to decode the answer
This commit is contained in:
Simo Sorce 2004-08-13 05:26:38 +00:00 committed by Gerald (Jerry) Carter
parent afe5715200
commit 10baf58582
4 changed files with 230 additions and 33 deletions

View File

@ -790,8 +790,8 @@ BOOL ldap_encode(struct ldap_message *msg, DATA_BLOB *result)
asn1_push_tag(&data, r->mechanism | 0xa0);
asn1_write_OctetString(&data, r->creds.SASL.mechanism,
strlen(r->creds.SASL.mechanism));
asn1_write_OctetString(&data, r->creds.SASL.creds.data,
r->creds.SASL.creds.length);
asn1_write_OctetString(&data, r->creds.SASL.secblob.data,
r->creds.SASL.secblob.length);
asn1_pop_tag(&data);
break;
default:
@ -1537,6 +1537,7 @@ struct ldap_connection *new_ldap_connection(void)
result->search_entries = NULL;
result->auth_dn = NULL;
result->simple_pw = NULL;
result->gensec = NULL;
return result;
}
@ -1740,14 +1741,15 @@ struct ldap_message *ldap_transaction(struct ldap_connection *conn,
return ldap_receive(conn, request->messageid, NULL);
}
struct ldap_message *ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
int ldap_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
{
struct ldap_message *response;
struct ldap_message *msg;
const char *dn, *pw;
int result = LDAP_OTHER;
if (conn == NULL || msg == NULL)
return False;
if (conn == NULL)
return result;
if (userdn) {
dn = userdn;
@ -1771,33 +1773,152 @@ struct ldap_message *ldap_bind_simple(struct ldap_connection *conn, const char *
msg = new_ldap_simple_bind_msg(dn, pw);
if (!msg)
return False;
return result;
response = ldap_transaction(conn, msg);
if (!response) {
destroy_ldap_message(msg);
return result;
}
result = response->r.BindResponse.response.resultcode;
destroy_ldap_message(msg);
return response;
destroy_ldap_message(response);
return result;
}
int ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
{
NTSTATUS status;
TALLOC_CTX *mem_ctx = NULL;
struct ldap_message *response;
struct ldap_message *msg;
DATA_BLOB input = data_blob(NULL, 0);
DATA_BLOB output = data_blob(NULL, 0);
int result = LDAP_OTHER;
if (conn == NULL)
return result;
status = gensec_client_start(&conn->gensec);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
return result;
}
status = gensec_set_domain(conn->gensec, domain);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n",
domain, nt_errstr(status)));
goto done;
}
status = gensec_set_username(conn->gensec, username);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n",
username, nt_errstr(status)));
goto done;
}
status = gensec_set_password(conn->gensec, password);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start set GENSEC client password: %s\n",
nt_errstr(status)));
goto done;
}
status = gensec_set_target_hostname(conn->gensec, conn->host);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n",
nt_errstr(status)));
goto done;
}
status = gensec_start_mech_by_sasl_name(conn->gensec, "GSS-SPNEGO");
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism: %s\n",
nt_errstr(status)));
goto done;
}
mem_ctx = talloc_init("ldap_bind_sasl");
if (!mem_ctx)
goto done;
status = gensec_update(conn->gensec, mem_ctx,
input,
&output);
while(1) {
if (NT_STATUS_IS_OK(status) && output.length == 0) {
break;
}
if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
break;
}
msg = new_ldap_sasl_bind_msg("GSS-SPNEGO", &output);
if (!msg)
goto done;
response = ldap_transaction(conn, msg);
destroy_ldap_message(msg);
result = response->r.BindResponse.response.resultcode;
if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
break;
}
status = gensec_update(conn->gensec, mem_ctx,
response->r.BindResponse.SASL.creds,
&output);
destroy_ldap_message(response);
}
done:
if (conn->gensec)
gensec_end(&conn->gensec);
if (mem_ctx)
talloc_destroy(mem_ctx);
return result;
}
BOOL ldap_setup_connection(struct ldap_connection *conn,
const char *url, const char *userdn, const char *password)
{
struct ldap_message *response;
BOOL result;
int result;
if (!ldap_connect(conn, url)) {
return False;
}
response = ldap_bind_simple(conn, userdn, password);
if (response == NULL) {
result = False;
} else {
result = (response->r.BindResponse.response.resultcode == 0);
result = ldap_bind_simple(conn, userdn, password);
if (result == LDAP_SUCCESS) {
return True;
}
destroy_ldap_message(response);
return result;
return False;
}
BOOL ldap_setup_connection_with_sasl(struct ldap_connection *conn, const char *url, const char *username, const char *domain, const char *password)
{
int result;
if (!ldap_connect(conn, url)) {
return False;
}
result = ldap_bind_sasl(conn, username, domain, password);
if (result == LDAP_SUCCESS) {
return True;
}
return False;
}
static BOOL ldap_abandon_message(struct ldap_connection *conn, int msgid,
@ -1856,6 +1977,22 @@ struct ldap_message *new_ldap_simple_bind_msg(const char *dn, const char *pw)
return res;
}
struct ldap_message *new_ldap_sasl_bind_msg(const char *sasl_mechanism, DATA_BLOB *secblob)
{
struct ldap_message *res = new_ldap_message();
if (res == NULL)
return NULL;
res->type = LDAP_TAG_BindRequest;
res->r.BindRequest.version = 3;
res->r.BindRequest.dn = "";
res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res->mem_ctx, sasl_mechanism);
res->r.BindRequest.creds.SASL.secblob = *secblob;
return res;
}
BOOL ldap_setsearchent(struct ldap_connection *conn, struct ldap_message *msg,
const struct timeval *endtime)
{

View File

@ -50,6 +50,12 @@ enum ldap_auth_mechanism {
LDAP_AUTH_MECH_SASL = 3
};
enum ldap_result_code {
LDAP_SUCCESS = 0,
LDAP_SASL_BIND_IN_PROGRESS = 0x0e,
LDAP_OTHER = 0x50
};
struct ldap_Result {
int resultcode;
const char *dn;
@ -71,7 +77,7 @@ struct ldap_BindRequest {
const char *password;
struct {
const char *mechanism;
DATA_BLOB creds;
DATA_BLOB secblob;
} SASL;
} creds;
};
@ -79,8 +85,8 @@ struct ldap_BindRequest {
struct ldap_BindResponse {
struct ldap_Result response;
union {
DATA_BLOB credentials;
} SASL_Credentials;
DATA_BLOB creds;
} SASL;
};
struct ldap_UnbindRequest {
@ -241,6 +247,9 @@ struct ldap_connection {
/* Outstanding LDAP requests that have not yet been replied to */
struct ldap_queue_entry *outstanding;
/* Let's support SASL */
struct gensec_security *gensec;
};
#endif

View File

@ -1,23 +1,47 @@
#include "includes.h"
BOOL test_multibind(struct ldap_connection *conn, TALLOC_CTX *mem_ctx, const char *userdn, const char *password)
BOOL test_bind_simple(struct ldap_connection *conn, const char *userdn, const char *password)
{
NTSTATUS status;
BOOL ret = True;
printf("\nTesting multiple binds on a single connnection as anonymous and user\n");
status = torture_ldap_bind(conn, userdn, password);
if (!NT_STATUS_IS_OK(status)) {
printf("1st bind as user over an anonymous bind failed\n");
return False;
ret = False;
}
status = torture_ldap_bind(conn, NULL, NULL);
return ret;
}
BOOL test_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
{
NTSTATUS status;
BOOL ret = True;
status = torture_ldap_bind_sasl(conn, username, domain, password);
if (!NT_STATUS_IS_OK(status)) {
printf("2nd bind as anonymous over an authenticated bind failed\n");
return False;
ret = False;
}
return ret;
}
BOOL test_multibind(struct ldap_connection *conn, const char *userdn, const char *password)
{
BOOL ret = True;
printf("\nTesting multiple binds on a single connnection as anonymous and user\n");
ret = test_bind_simple(conn, NULL, NULL);
if (!ret) {
printf("1st bind as anonymous failed\n");
return ret;
}
ret = test_bind_simple(conn, userdn, password);
if (!ret) {
printf("2nd bind as authenticated user failed\n");
}
return ret;
@ -30,6 +54,9 @@ BOOL torture_ldap_basic(int dummy)
TALLOC_CTX *mem_ctx;
BOOL ret = True;
const char *host = lp_parm_string(-1, "torture", "host");
const char *username = lp_parm_string(-1, "torture", "username");
const char *domain = lp_workgroup();
const char *password = lp_parm_string(-1, "torture", "password");
const char *userdn = lp_parm_string(-1, "torture", "ldap_userdn");
const char *basedn = lp_parm_string(-1, "torture", "ldap_basedn");
const char *secret = lp_parm_string(-1, "torture", "ldap_secret");
@ -39,14 +66,18 @@ BOOL torture_ldap_basic(int dummy)
url = talloc_asprintf(mem_ctx, "ldap://%s/", host);
status = torture_ldap_connection(&conn, url, NULL, NULL);
status = torture_ldap_connection(&conn, url, userdn, secret);
if (!NT_STATUS_IS_OK(status)) {
return False;
}
/* other basic tests here */
if (!test_multibind(conn, mem_ctx, userdn, secret)) {
if (!test_multibind(conn, userdn, secret)) {
ret = False;
}
if (!test_bind_sasl(conn, username, domain, password)) {
ret = False;
}

View File

@ -3,19 +3,39 @@
NTSTATUS torture_ldap_bind(struct ldap_connection *conn, const char *userdn, const char *password)
{
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
struct ldap_message *response;
int result;
if (!conn) {
printf("We need a valid ldap_connection structure and be connected\n");
return status;
}
response = ldap_bind_simple(conn, userdn, password);
if (!response || (response->r.BindResponse.response.resultcode != 0)) {
result = ldap_bind_simple(conn, userdn, password);
if (result != LDAP_SUCCESS) {
printf("Failed to bind with provided credentials\n");
/* FIXME: what abut actually implementing an ldap_connection_free() function ?
:-) sss */
destroy_ldap_message(response);
return status;
}
return NT_STATUS_OK;
}
NTSTATUS torture_ldap_bind_sasl(struct ldap_connection *conn, const char *username, const char *domain, const char *password)
{
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
int result;
if (!conn) {
printf("We need a valid ldap_connection structure and be connected\n");
return status;
}
result = ldap_bind_sasl(conn, username, domain, password);
if (result != LDAP_SUCCESS) {
printf("Failed to bind with provided credentialsi and SASL mechanism\n");
/* FIXME: what abut actually implementing an ldap_connection_free() function ?
:-) sss */
return status;
}