mirror of
https://github.com/samba-team/samba.git
synced 2025-08-03 04:22:09 +03:00
r2878: add server sasl support
(there are a lot of clean ups following later, but the LDAP-BASIC test
works :-)
metze
(This used to be commit 34fe29c04a
)
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
85e18e252d
commit
73e9f435f5
@ -21,13 +21,13 @@
|
||||
#include "includes.h"
|
||||
|
||||
|
||||
NTSTATUS ldapsrv_BindRequest(struct ldapsrv_call *call)
|
||||
static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
|
||||
{
|
||||
struct ldap_BindRequest *req = &call->request.r.BindRequest;
|
||||
struct ldapsrv_reply *reply;
|
||||
struct ldap_BindResponse *resp;
|
||||
|
||||
DEBUG(10, ("BindRequest dn: %s\n",req->dn));
|
||||
DEBUG(10, ("BindSimple dn: %s\n",req->dn));
|
||||
|
||||
reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
|
||||
if (!reply) {
|
||||
@ -44,9 +44,123 @@ NTSTATUS ldapsrv_BindRequest(struct ldapsrv_call *call)
|
||||
return ldapsrv_queue_reply(call, reply);
|
||||
}
|
||||
|
||||
static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
|
||||
{
|
||||
struct ldap_BindRequest *req = &call->request.r.BindRequest;
|
||||
struct ldapsrv_reply *reply;
|
||||
struct ldap_BindResponse *resp;
|
||||
int result;
|
||||
const char *errstr;
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
NTSTATUS sasl_status;
|
||||
BOOL ret;
|
||||
|
||||
DEBUG(10, ("BindSASL dn: %s\n",req->dn));
|
||||
|
||||
if (!call->conn->gensec) {
|
||||
call->conn->session_info = NULL;
|
||||
|
||||
status = gensec_server_start(call->conn, &call->conn->gensec);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
|
||||
return status;
|
||||
}
|
||||
|
||||
gensec_want_feature(call->conn->gensec, GENSEC_WANT_SIGN|GENSEC_WANT_SEAL);
|
||||
|
||||
status = gensec_start_mech_by_sasl_name(call->conn->gensec, req->creds.SASL.mechanism);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(1, ("Failed to start GENSEC SASL[%s] server code: %s\n",
|
||||
req->creds.SASL.mechanism, nt_errstr(status)));
|
||||
goto reply;
|
||||
}
|
||||
}
|
||||
|
||||
reply:
|
||||
reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
|
||||
if (!reply) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
resp = &reply->msg.r.BindResponse;
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
status = gensec_update(call->conn->gensec, reply,
|
||||
req->creds.SASL.secblob, &resp->SASL.secblob);
|
||||
}
|
||||
|
||||
if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
|
||||
result = LDAP_SASL_BIND_IN_PROGRESS;
|
||||
errstr = NULL;
|
||||
} else if (NT_STATUS_IS_OK(status)) {
|
||||
result = LDAP_SUCCESS;
|
||||
errstr = NULL;
|
||||
} else {
|
||||
result = 49;
|
||||
errstr = talloc_asprintf(reply, "SASL:[%s]: %s", req->creds.SASL.mechanism, nt_errstr(status));
|
||||
}
|
||||
|
||||
resp->response.resultcode = result;
|
||||
resp->response.dn = NULL;
|
||||
resp->response.errormessage = errstr;
|
||||
resp->response.referral = NULL;
|
||||
|
||||
sasl_status = status;
|
||||
status = ldapsrv_queue_reply(call, reply);
|
||||
if (!NT_STATUS_IS_OK(sasl_status) || !NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = ldapsrv_do_responses(call->conn);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
ret = ldapsrv_append_to_buf(&call->conn->sasl_out_buffer, call->conn->out_buffer.data, call->conn->out_buffer.length);
|
||||
if (!ret) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
ldapsrv_consumed_from_buf(&call->conn->out_buffer, call->conn->out_buffer.length);
|
||||
|
||||
status = gensec_session_info(call->conn->gensec, &call->conn->session_info);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//debug_session_info(0, 0, call->conn->session_info);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS ldapsrv_BindRequest(struct ldapsrv_call *call)
|
||||
{
|
||||
struct ldap_BindRequest *req = &call->request.r.BindRequest;
|
||||
struct ldapsrv_reply *reply;
|
||||
struct ldap_BindResponse *resp;
|
||||
|
||||
switch (req->mechanism) {
|
||||
case LDAP_AUTH_MECH_SIMPLE:
|
||||
return ldapsrv_BindSimple(call);
|
||||
case LDAP_AUTH_MECH_SASL:
|
||||
return ldapsrv_BindSASL(call);
|
||||
}
|
||||
|
||||
reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
|
||||
if (!reply) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
resp = &reply->msg.r.BindResponse;
|
||||
resp->response.resultcode = 7;
|
||||
resp->response.dn = NULL;
|
||||
resp->response.errormessage = talloc_asprintf(reply, "Bad AuthenticationChoice [%d]", req->mechanism);
|
||||
resp->response.referral = NULL;
|
||||
resp->SASL.secblob = data_blob(NULL, 0);
|
||||
|
||||
return ldapsrv_queue_reply(call, reply);
|
||||
}
|
||||
|
||||
NTSTATUS ldapsrv_UnbindRequest(struct ldapsrv_call *call)
|
||||
{
|
||||
/* struct ldap_UnbindRequest *req = &call->request->r.UnbindRequest;*/
|
||||
DEBUG(10, ("UnbindRequest\n"));
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ static void ldapsrv_init(struct server_service *service,
|
||||
that a read(2) holds a complete request that is then thrown away
|
||||
completely. */
|
||||
|
||||
static void consumed_from_buf(struct rw_buffer *buf,
|
||||
void ldapsrv_consumed_from_buf(struct rw_buffer *buf,
|
||||
size_t length)
|
||||
{
|
||||
memcpy(buf->data, buf->data+length, buf->length-length);
|
||||
@ -136,7 +136,7 @@ static void peek_into_read_buf(struct rw_buffer *buf, uint8_t **out,
|
||||
*out_length = buf->length;
|
||||
}
|
||||
|
||||
static BOOL append_to_buf(struct rw_buffer *buf, uint8_t *data, size_t length)
|
||||
BOOL ldapsrv_append_to_buf(struct rw_buffer *buf, uint8_t *data, size_t length)
|
||||
{
|
||||
buf->data = realloc(buf->data, buf->length+length);
|
||||
|
||||
@ -161,7 +161,7 @@ static BOOL read_into_buf(struct socket_context *sock, struct rw_buffer *buf)
|
||||
return False;
|
||||
}
|
||||
|
||||
ret = append_to_buf(buf, tmp_blob.data, tmp_blob.length);
|
||||
ret = ldapsrv_append_to_buf(buf, tmp_blob.data, tmp_blob.length);
|
||||
|
||||
talloc_free(tmp_blob.data);
|
||||
|
||||
@ -179,7 +179,7 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn)
|
||||
struct socket_context *sock = conn->connection->socket;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
|
||||
if (!conn->gensec ||
|
||||
if (!conn->gensec || !conn->session_info ||
|
||||
!(gensec_have_feature(conn->gensec, GENSEC_WANT_SIGN) &&
|
||||
gensec_have_feature(conn->gensec, GENSEC_WANT_SEAL))) {
|
||||
return read_into_buf(sock, &conn->in_buffer);
|
||||
@ -198,7 +198,7 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn)
|
||||
return False;
|
||||
}
|
||||
|
||||
ret = append_to_buf(&conn->sasl_in_buffer, tmp_blob.data, tmp_blob.length);
|
||||
ret = ldapsrv_append_to_buf(&conn->sasl_in_buffer, tmp_blob.data, tmp_blob.length);
|
||||
if (!ret) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
@ -254,13 +254,13 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn)
|
||||
}
|
||||
}
|
||||
|
||||
ret = append_to_buf(&conn->in_buffer, tmp_blob.data, tmp_blob.length);
|
||||
ret = ldapsrv_append_to_buf(&conn->in_buffer, tmp_blob.data, tmp_blob.length);
|
||||
if (!ret) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
consumed_from_buf(&conn->sasl_in_buffer, 4 + sasl_length);
|
||||
ldapsrv_consumed_from_buf(&conn->sasl_in_buffer, 4 + sasl_length);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
return ret;
|
||||
@ -281,7 +281,7 @@ static BOOL write_from_buf(struct socket_context *sock, struct rw_buffer *buf)
|
||||
return False;
|
||||
}
|
||||
|
||||
consumed_from_buf(buf, sendlen);
|
||||
ldapsrv_consumed_from_buf(buf, sendlen);
|
||||
|
||||
return True;
|
||||
}
|
||||
@ -297,7 +297,7 @@ static BOOL ldapsrv_write_buf(struct ldapsrv_connection *conn)
|
||||
struct socket_context *sock = conn->connection->socket;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
|
||||
if (!conn->gensec ||
|
||||
if (!conn->gensec || !conn->session_info ||
|
||||
!(gensec_have_feature(conn->gensec, GENSEC_WANT_SIGN) &&
|
||||
gensec_have_feature(conn->gensec, GENSEC_WANT_SEAL))) {
|
||||
return write_from_buf(sock, &conn->out_buffer);
|
||||
@ -312,6 +312,10 @@ static BOOL ldapsrv_write_buf(struct ldapsrv_connection *conn)
|
||||
tmp_blob.data = conn->out_buffer.data;
|
||||
tmp_blob.length = conn->out_buffer.length;
|
||||
|
||||
if (tmp_blob.length == 0) {
|
||||
goto nodata;
|
||||
}
|
||||
|
||||
if (gensec_have_feature(conn->gensec, GENSEC_WANT_SEAL)) {
|
||||
status = gensec_seal_packet(conn->gensec, mem_ctx,
|
||||
tmp_blob.data, tmp_blob.length,
|
||||
@ -345,12 +349,15 @@ static BOOL ldapsrv_write_buf(struct ldapsrv_connection *conn)
|
||||
memcpy(sasl.data + 4, creds.data, creds.length);
|
||||
memcpy(sasl.data + 4 + creds.length, tmp_blob.data, tmp_blob.length);
|
||||
|
||||
ret = append_to_buf(&conn->sasl_out_buffer, sasl.data, sasl.length);
|
||||
ret = ldapsrv_append_to_buf(&conn->sasl_out_buffer, sasl.data, sasl.length);
|
||||
if (!ret) {
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
consumed_from_buf(&conn->out_buffer, tmp_blob.length);
|
||||
ldapsrv_consumed_from_buf(&conn->out_buffer, tmp_blob.length);
|
||||
nodata:
|
||||
tmp_blob.data = conn->sasl_out_buffer.data;
|
||||
tmp_blob.length = conn->sasl_out_buffer.length;
|
||||
|
||||
status = socket_send(sock, mem_ctx, &tmp_blob, &sendlen, 0);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
@ -359,14 +366,14 @@ static BOOL ldapsrv_write_buf(struct ldapsrv_connection *conn)
|
||||
return False;
|
||||
}
|
||||
|
||||
consumed_from_buf(&conn->sasl_out_buffer, sendlen);
|
||||
ldapsrv_consumed_from_buf(&conn->sasl_out_buffer, sendlen);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL ldap_append_to_buf(struct ldap_message *msg, struct rw_buffer *buf)
|
||||
static BOOL ldap_encode_to_buf(struct ldap_message *msg, struct rw_buffer *buf)
|
||||
{
|
||||
DATA_BLOB blob;
|
||||
BOOL res;
|
||||
@ -374,20 +381,20 @@ static BOOL ldap_append_to_buf(struct ldap_message *msg, struct rw_buffer *buf)
|
||||
if (!ldap_encode(msg, &blob))
|
||||
return False;
|
||||
|
||||
res = append_to_buf(buf, blob.data, blob.length);
|
||||
res = ldapsrv_append_to_buf(buf, blob.data, blob.length);
|
||||
|
||||
data_blob_free(&blob);
|
||||
return res;
|
||||
}
|
||||
|
||||
static NTSTATUS ldapsrv_do_responses(struct ldapsrv_connection *conn)
|
||||
NTSTATUS ldapsrv_do_responses(struct ldapsrv_connection *conn)
|
||||
{
|
||||
struct ldapsrv_call *call, *next_call = NULL;
|
||||
struct ldapsrv_reply *reply, *next_reply = NULL;
|
||||
|
||||
for (call=conn->calls; call; call=next_call) {
|
||||
for (reply=call->replies; reply; reply=next_reply) {
|
||||
if (!ldap_append_to_buf(&reply->msg, &conn->out_buffer)) {
|
||||
if (!ldap_encode_to_buf(&reply->msg, &conn->out_buffer)) {
|
||||
return NT_STATUS_FOOBAR;
|
||||
}
|
||||
next_reply = reply->next;
|
||||
@ -404,6 +411,11 @@ static NTSTATUS ldapsrv_do_responses(struct ldapsrv_connection *conn)
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS ldapsrv_flush_responses(struct ldapsrv_connection *conn)
|
||||
{
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
called when a LDAP socket becomes readable
|
||||
*/
|
||||
@ -462,8 +474,6 @@ static void ldapsrv_recv(struct server_connection *conn, time_t t,
|
||||
ZERO_STRUCTP(call);
|
||||
call->state = LDAPSRV_CALL_STATE_NEW;
|
||||
call->conn = ldap_conn;
|
||||
/* TODO: we should use talloc_reference() here */
|
||||
call->session_info = ldap_conn->session_info;
|
||||
call->request.mem_ctx = call;
|
||||
|
||||
if (!ldap_decode(&data, &call->request)) {
|
||||
@ -478,7 +488,7 @@ static void ldapsrv_recv(struct server_connection *conn, time_t t,
|
||||
DLIST_ADD_END(ldap_conn->calls, call,
|
||||
struct ldapsrv_call *);
|
||||
|
||||
consumed_from_buf(&ldap_conn->in_buffer, msg_length);
|
||||
ldapsrv_consumed_from_buf(&ldap_conn->in_buffer, msg_length);
|
||||
|
||||
status = ldapsrv_do_call(call);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
|
@ -45,8 +45,6 @@ struct ldapsrv_call {
|
||||
|
||||
struct ldapsrv_connection *conn;
|
||||
|
||||
const struct auth_session_info *session_info;
|
||||
|
||||
struct ldap_message request;
|
||||
|
||||
struct ldapsrv_reply {
|
||||
@ -62,7 +60,7 @@ struct ldapsrv_connection {
|
||||
struct server_connection *connection;
|
||||
|
||||
struct gensec_security *gensec;
|
||||
const struct auth_session_info *session_info;
|
||||
struct auth_session_info *session_info;
|
||||
|
||||
struct rw_buffer sasl_in_buffer;
|
||||
struct rw_buffer sasl_out_buffer;
|
||||
|
Reference in New Issue
Block a user