r2878: add server sasl support
authorStefan Metzmacher <metze@samba.org>
Sat, 9 Oct 2004 22:00:00 +0000 (22:00 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:59:41 +0000 (12:59 -0500)
(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
source4/ldap_server/ldap_server.c
source4/ldap_server/ldap_server.h

index d0e24bde291c9f813fd2b1d902f1ba6d92f5eb8a..3d9cd4b984c2c17f63f9283f2cdd56062cb40429 100644 (file)
 #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;
 }
index 2ce6b037621eee6364fb246619f3f4f1bb89bd11..5336cc04f10c448d74f8d5dbd8a91f31279f8dea 100644 (file)
@@ -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)) {
index e88b266b0afdc0c3b09c9db8d6858ebd46bd06d9..6d4824bc9d86ffd75b66f28a5dcb8134f027a2a0 100644 (file)
@@ -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;