From 73e9f435f5e797b7c3b9874b57d081c2714a8bca Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 9 Oct 2004 22:00:00 +0000 Subject: 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 34fe29c04a76f2f53f27adcaf9be2dce8d177516) --- source4/ldap_server/ldap_bind.c | 120 +++++++++++++++++++++++++++++++++++++- source4/ldap_server/ldap_server.c | 48 +++++++++------ source4/ldap_server/ldap_server.h | 4 +- 3 files changed, 147 insertions(+), 25 deletions(-) (limited to 'source4') diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c index d0e24bde29..3d9cd4b984 100644 --- a/source4/ldap_server/ldap_bind.c +++ b/source4/ldap_server/ldap_bind.c @@ -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; } diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index 2ce6b03762..5336cc04f1 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -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)) { diff --git a/source4/ldap_server/ldap_server.h b/source4/ldap_server/ldap_server.h index e88b266b0a..6d4824bc9d 100644 --- a/source4/ldap_server/ldap_server.h +++ b/source4/ldap_server/ldap_server.h @@ -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; -- cgit