r4459: GENSEC refinements:
authorAndrew Bartlett <abartlet@samba.org>
Fri, 31 Dec 2004 22:45:11 +0000 (22:45 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:07:53 +0000 (13:07 -0500)
In developing a GSSAPI plugin for GENSEC, it became clear that the API
needed to change:
 - GSSAPI exposes only a wrap() and unwrap() interface, and determines
   the location of the signature itself.
 - The 'have feature' API did not correctly function in the recursive
   SPNEGO environment.

As such, NTLMSSP has been updated to support these methods.

The LDAP client and server have been updated to use the new wrap() and
unwrap() methods, and now pass the LDAP-* tests in our smbtorture.
(Unfortunely I still get valgrind warnings, in the code that was
previously unreachable).

Andrew Bartlett
(This used to be commit 9923c3bc1b5a6e93a5996aadb039bd229e888ac6)

source4/ldap_server/ldap_bind.c
source4/ldap_server/ldap_server.c
source4/libcli/auth/gensec.c
source4/libcli/auth/gensec.h
source4/libcli/auth/gensec_krb5.c
source4/libcli/auth/gensec_ntlmssp.c
source4/libcli/auth/spnego.c
source4/librpc/rpc/dcerpc_schannel.c
source4/torture/ldap/common.c

index 80d1f517485f638c9a0e266374c486cc9676981f..f4be5b524220e57402ee5f3ae4fecc3c226d0be3 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "includes.h"
 #include "ldap_server/ldap_server.h"
-
+#include "auth/auth.h"
 
 static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
 {
@@ -50,11 +50,12 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
        struct ldap_BindRequest *req = &call->request.r.BindRequest;
        struct ldapsrv_reply *reply;
        struct ldap_BindResponse *resp;
+       struct ldapsrv_connection *conn;
        int result;
        const char *errstr;
        NTSTATUS status = NT_STATUS_OK;
        NTSTATUS sasl_status;
-       /*BOOL ret;*/
+       BOOL ret;
 
        DEBUG(10, ("BindSASL dn: %s\n",req->dn));
 
@@ -69,7 +70,8 @@ static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
                
                gensec_set_target_service(call->conn->gensec, "ldap");
 
-               /*gensec_want_feature(call->conn->gensec, GENSEC_WANT_SIGN|GENSEC_WANT_SEAL);*/
+               gensec_want_feature(call->conn->gensec, GENSEC_FEATURE_SIGN);
+               gensec_want_feature(call->conn->gensec, GENSEC_FEATURE_SEAL);
 
                status = gensec_start_mech_by_sasl_name(call->conn->gensec, req->creds.SASL.mechanism);
                if (!NT_STATUS_IS_OK(status)) {
@@ -85,6 +87,8 @@ reply:
                return NT_STATUS_NO_MEMORY;
        }
        resp = &reply->msg.r.BindResponse;
+       
+       conn = call->conn;
 
        if (NT_STATUS_IS_OK(status)) {
                status = gensec_update(call->conn->gensec, reply,
@@ -118,17 +122,14 @@ reply:
                return status;
        }
 
-/*     ret = ldapsrv_append_to_buf(&call->conn->sasl_out_buffer, call->conn->out_buffer.data, call->conn->out_buffer.length);
+       ret = ldapsrv_append_to_buf(&conn->sasl_out_buffer, conn->out_buffer.data, 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;
+       ldapsrv_consumed_from_buf(&conn->out_buffer, conn->out_buffer.length);
+       if (NT_STATUS_IS_OK(status)) {
+               status = gensec_session_info(conn->gensec, &conn->session_info);
        }
-*/
 
        return status;
 }
index ea1b8cb9b4a8936976dafd31c2c092cb08728ac7..0bace4b690a35dad388b98cd44ca2785dd50a148 100644 (file)
@@ -131,7 +131,7 @@ static void ldapsrv_init(struct server_service *service,
 void ldapsrv_consumed_from_buf(struct rw_buffer *buf,
                                   size_t length)
 {
-       memcpy(buf->data, buf->data+length, buf->length-length);
+       memmove(buf->data, buf->data+length, buf->length-length);
        buf->length -= length;
 }
 
@@ -186,7 +186,8 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn)
 {
        NTSTATUS status;
        DATA_BLOB tmp_blob;
-       DATA_BLOB creds;
+       DATA_BLOB wrapped;
+       DATA_BLOB unwrapped;
        BOOL ret;
        uint8_t *buf;
        size_t buf_length, sasl_length;
@@ -194,9 +195,14 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn)
        TALLOC_CTX *mem_ctx;
        size_t nread;
 
-       if (!conn->gensec || !conn->session_info ||
-          !(gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) &&
-            gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL))) {
+       if (!conn->gensec) {
+               return read_into_buf(sock, &conn->in_buffer);
+       }
+       if (!conn->session_info) {
+               return read_into_buf(sock, &conn->in_buffer);
+       }
+       if (!(gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
+             gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL))) {
                return read_into_buf(sock, &conn->in_buffer);
        }
 
@@ -236,47 +242,25 @@ static BOOL ldapsrv_read_buf(struct ldapsrv_connection *conn)
 
        sasl_length = RIVAL(buf, 0);
 
-       if (buf_length < (4 + sasl_length)) {
+       if ((buf_length - 4) < sasl_length) {
                /* not enough yet */
                talloc_free(mem_ctx);
                return True;
        }
 
-       creds.data = buf + 4;
-       creds.length = gensec_sig_size(conn->gensec);
+       wrapped.data = buf + 4;
+       wrapped.length = sasl_length;
 
-       if (creds.length > sasl_length) {
-               /* invalid packet? */
+       status = gensec_unwrap(conn->gensec, mem_ctx,
+                              &wrapped, 
+                              &unwrapped);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("gensec_unwrap: %s\n",nt_errstr(status)));
                talloc_free(mem_ctx);
                return False;
        }
 
-       tmp_blob.data = buf + (4 + creds.length);
-       tmp_blob.length = (4 + sasl_length) - (4 + creds.length);
-
-       if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
-               status = gensec_unseal_packet(conn->gensec, mem_ctx,
-                                             tmp_blob.data, tmp_blob.length,
-                                             tmp_blob.data, tmp_blob.length,
-                                             &creds);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0,("gensec_unseal_packet: %s\n",nt_errstr(status)));
-                       talloc_free(mem_ctx);
-                       return False;
-               }
-       } else {
-               status = gensec_check_packet(conn->gensec, mem_ctx,
-                                             tmp_blob.data, tmp_blob.length,
-                                             tmp_blob.data, tmp_blob.length,
-                                             &creds);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0,("gensec_check_packet: %s\n",nt_errstr(status)));
-                       talloc_free(mem_ctx);
-                       return False;
-               }
-       }
-
-       ret = ldapsrv_append_to_buf(&conn->in_buffer, tmp_blob.data, tmp_blob.length);
+       ret = ldapsrv_append_to_buf(&conn->in_buffer, unwrapped.data, unwrapped.length);
        if (!ret) {
                talloc_free(mem_ctx);
                return False;
@@ -311,17 +295,23 @@ static BOOL write_from_buf(struct socket_context *sock, struct rw_buffer *buf)
 static BOOL ldapsrv_write_buf(struct ldapsrv_connection *conn)
 {
        NTSTATUS status;
+       DATA_BLOB wrapped;
        DATA_BLOB tmp_blob;
-       DATA_BLOB creds;
        DATA_BLOB sasl;
        size_t sendlen;
        BOOL ret;
        struct socket_context *sock = conn->connection->socket;
        TALLOC_CTX *mem_ctx;
 
-       if (!conn->gensec || !conn->session_info ||
-          !(gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) &&
-            gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL))) {
+
+       if (!conn->gensec) {
+               return write_from_buf(sock, &conn->out_buffer);
+       }
+       if (!conn->session_info) {
+               return write_from_buf(sock, &conn->out_buffer);
+       }
+       if (!(gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
+             gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL))) {
                return write_from_buf(sock, &conn->out_buffer);
        }
 
@@ -331,52 +321,37 @@ static BOOL ldapsrv_write_buf(struct ldapsrv_connection *conn)
                return False;
        }
 
-       tmp_blob.data = conn->out_buffer.data;
-       tmp_blob.length = conn->out_buffer.length;
-
-       if (tmp_blob.length == 0) {
+       if (conn->out_buffer.length == 0) {
                goto nodata;
        }
 
-       if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
-               status = gensec_seal_packet(conn->gensec, mem_ctx,
-                                           tmp_blob.data, tmp_blob.length,
-                                           tmp_blob.data, tmp_blob.length,
-                                           &creds);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0,("gensec_seal_packet: %s\n",nt_errstr(status)));
-                       talloc_free(mem_ctx);
-                       return False;
-               }
-       } else {
-               status = gensec_sign_packet(conn->gensec, mem_ctx,
-                                           tmp_blob.data, tmp_blob.length,
-                                           tmp_blob.data, tmp_blob.length,
-                                           &creds);
-               if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(0,("gensec_sign_packet: %s\n",nt_errstr(status)));
-                       talloc_free(mem_ctx);
-                       return False;
-               }               
+       tmp_blob.data = conn->out_buffer.data;
+       tmp_blob.length = conn->out_buffer.length;
+       status = gensec_wrap(conn->gensec, mem_ctx,
+                            &tmp_blob,
+                            &wrapped);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("gensec_wrap: %s\n",nt_errstr(status)));
+               talloc_free(mem_ctx);
+               return False;
        }
 
-       sasl = data_blob_talloc(mem_ctx, NULL, 4 + creds.length + tmp_blob.length);
+       sasl = data_blob_talloc(mem_ctx, NULL, 4 + wrapped.length);
        if (!sasl.data) {
                DEBUG(0,("no memory\n"));
                talloc_free(mem_ctx);
                return False;
        }
 
-       RSIVAL(sasl.data, 0, creds.length + tmp_blob.length);
-       memcpy(sasl.data + 4, creds.data, creds.length);
-       memcpy(sasl.data + 4 + creds.length, tmp_blob.data, tmp_blob.length);
+       RSIVAL(sasl.data, 0, wrapped.length);
+       memcpy(sasl.data + 4, wrapped.data, wrapped.length);
 
        ret = ldapsrv_append_to_buf(&conn->sasl_out_buffer, sasl.data, sasl.length);
        if (!ret) {
                talloc_free(mem_ctx);
                return False;
        }
-       ldapsrv_consumed_from_buf(&conn->out_buffer, tmp_blob.length);
+       ldapsrv_consumed_from_buf(&conn->out_buffer, conn->out_buffer.length);
 nodata:
        tmp_blob.data = conn->sasl_out_buffer.data;
        tmp_blob.length = conn->sasl_out_buffer.length;
index 75086f928112b891c273fba22bd86a2837865fd7..79cd98a076a7b0770dfa029c44ca030816327d13 100644 (file)
@@ -137,7 +137,6 @@ static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx, struct gensec_security **gense
 
        (*gensec_security)->subcontext = False;
        (*gensec_security)->want_features = 0;
-       (*gensec_security)->have_features = 0;
        return NT_STATUS_OK;
 }
 
@@ -395,6 +394,28 @@ size_t gensec_sig_size(struct gensec_security *gensec_security)
        return gensec_security->ops->sig_size(gensec_security);
 }
 
+NTSTATUS gensec_wrap(struct gensec_security *gensec_security, 
+                    TALLOC_CTX *mem_ctx, 
+                    const DATA_BLOB *in, 
+                    DATA_BLOB *out) 
+{
+       if (!gensec_security->ops->wrap) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+       return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
+}
+
+NTSTATUS gensec_unwrap(struct gensec_security *gensec_security, 
+                      TALLOC_CTX *mem_ctx, 
+                      const DATA_BLOB *in, 
+                      DATA_BLOB *out) 
+{
+       if (!gensec_security->ops->unwrap) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+       return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
+}
+
 NTSTATUS gensec_session_key(struct gensec_security *gensec_security, 
                            DATA_BLOB *session_key)
 {
@@ -459,11 +480,10 @@ void gensec_want_feature(struct gensec_security *gensec_security,
 BOOL gensec_have_feature(struct gensec_security *gensec_security,
                         uint32 feature) 
 {
-       if (gensec_security->have_features & feature) {
-               return True;
+       if (!gensec_security->ops->have_feature) {
+               return False;
        }
-
-       return False;
+       return gensec_security->ops->have_feature(gensec_security, feature);
 }
 
 /** 
index 2b44f0d902ce44a74aae82fde9ff202d28dc19f4..7c462414ff30e7272bd08693fa904cbb542e1cc8 100644 (file)
@@ -81,9 +81,19 @@ struct gensec_security_ops {
                                  uint8_t *data, size_t length, 
                                  const uint8_t *whole_pdu, size_t pdu_length, 
                                  DATA_BLOB *sig);
+       NTSTATUS (*wrap)(struct gensec_security *gensec_security, 
+                                 TALLOC_CTX *mem_ctx, 
+                                 const DATA_BLOB *in, 
+                                 DATA_BLOB *out); 
+       NTSTATUS (*unwrap)(struct gensec_security *gensec_security, 
+                                 TALLOC_CTX *mem_ctx, 
+                                 const DATA_BLOB *in, 
+                                 DATA_BLOB *out); 
        NTSTATUS (*session_key)(struct gensec_security *gensec_security, DATA_BLOB *session_key);
        NTSTATUS (*session_info)(struct gensec_security *gensec_security, 
                                 struct auth_session_info **session_info); 
+       BOOL (*have_feature)(struct gensec_security *gensec_security,
+                                   uint32 feature); 
 };
        
 #define GENSEC_INTERFACE_VERSION 0
@@ -99,7 +109,6 @@ struct gensec_security {
        enum gensec_role gensec_role;
        BOOL subcontext;
        uint32 want_features;
-       uint32 have_features;
 };
 
 /* this structure is used by backends to determine the size of some critical types */
index 86e76c55862bce32a6c46e5716a903ec677f9192..f55006c6446ef1b3d884617dbd7ae72323b0c267 100644 (file)
@@ -691,6 +691,16 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
        return nt_status;
 }
 
+static BOOL gensec_krb5_have_feature(struct gensec_security *gensec_security,
+                                    uint32 feature)
+{
+       if (feature & GENSEC_FEATURE_SESSION_KEY) {
+               return True;
+       } 
+       
+       return False;
+}
+
 
 static const struct gensec_security_ops gensec_krb5_security_ops = {
        .name           = "krb5",
@@ -701,6 +711,7 @@ static const struct gensec_security_ops gensec_krb5_security_ops = {
        .update         = gensec_krb5_update,
        .session_key    = gensec_krb5_session_key,
        .session_info   = gensec_krb5_session_info,
+       .have_feature   = gensec_krb5_have_feature,
 };
 
 static const struct gensec_security_ops gensec_ms_krb5_security_ops = {
@@ -712,6 +723,7 @@ static const struct gensec_security_ops gensec_ms_krb5_security_ops = {
        .update         = gensec_krb5_update,
        .session_key    = gensec_krb5_session_key,
        .session_info   = gensec_krb5_session_info,
+       .have_feature   = gensec_krb5_have_feature,
 };
 
 
index cf8019402c0dffc19778d95c2a1ac4b40b6499da..10b71ca8b0036a08d5b60b97a017c5c8027a9ea2 100644 (file)
@@ -28,6 +28,7 @@ struct gensec_ntlmssp_state {
        struct auth_context *auth_context;
        struct auth_serversupplied_info *server_info;
        struct ntlmssp_state *ntlmssp_state;
+       uint32 have_features;
 };
 
 
@@ -171,6 +172,7 @@ static NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security)
        gensec_ntlmssp_state->ntlmssp_state = NULL;
        gensec_ntlmssp_state->auth_context = NULL;
        gensec_ntlmssp_state->server_info = NULL;
+       gensec_ntlmssp_state->have_features = 0;
 
        talloc_set_destructor(gensec_ntlmssp_state, gensec_ntlmssp_destroy); 
 
@@ -341,6 +343,99 @@ static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security)
        return NTLMSSP_SIG_SIZE;
 }
 
+static NTSTATUS gensec_ntlmssp_wrap(struct gensec_security *gensec_security, 
+                                   TALLOC_CTX *mem_ctx, 
+                                   const DATA_BLOB *in, 
+                                   DATA_BLOB *out)
+{
+       struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
+       DATA_BLOB sig;
+       NTSTATUS nt_status;
+
+       if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
+
+               *out = data_blob_talloc(mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE);
+               memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length);
+
+               nt_status = ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, 
+                                               out->data + NTLMSSP_SIG_SIZE, 
+                                               out->length - NTLMSSP_SIG_SIZE, 
+                                               out->data + NTLMSSP_SIG_SIZE, 
+                                               out->length - NTLMSSP_SIG_SIZE, 
+                                               &sig);
+
+               if (NT_STATUS_IS_OK(nt_status)) {
+                       memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE);
+               }
+               return nt_status;
+
+       } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) 
+                  || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
+
+               *out = data_blob_talloc(mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE);
+               memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length);
+
+               nt_status = ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, 
+                                               out->data + NTLMSSP_SIG_SIZE, 
+                                               out->length - NTLMSSP_SIG_SIZE, 
+                                               out->data + NTLMSSP_SIG_SIZE, 
+                                               out->length - NTLMSSP_SIG_SIZE, 
+                                               &sig);
+
+               if (NT_STATUS_IS_OK(nt_status)) {
+                       memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE);
+               }
+               return nt_status;
+
+       } else {
+               *out = *in;
+               return NT_STATUS_OK;
+       }
+}
+
+
+static NTSTATUS gensec_ntlmssp_unwrap(struct gensec_security *gensec_security, 
+                                     TALLOC_CTX *mem_ctx, 
+                                     const DATA_BLOB *in, 
+                                     DATA_BLOB *out)
+{
+       struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
+       DATA_BLOB sig;
+
+       if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
+               if (in->length < NTLMSSP_SIG_SIZE) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               sig.data = in->data;
+               sig.length = NTLMSSP_SIG_SIZE;
+
+               *out = data_blob_talloc(mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE);
+               
+               return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, 
+                                            out->data, out->length, 
+                                            out->data, out->length, 
+                                            &sig);
+                                                 
+       } else if ((gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) 
+                  || (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
+               if (in->length < NTLMSSP_SIG_SIZE) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               sig.data = in->data;
+               sig.length = NTLMSSP_SIG_SIZE;
+
+               *out = data_blob_talloc(mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE);
+               
+               return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, 
+                                           out->data, out->length, 
+                                           out->data, out->length, 
+                                           &sig);
+       } else {
+               *out = *in;
+               return NT_STATUS_OK;
+       }
+}
+
 static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, 
                                           DATA_BLOB *session_key)
 {
@@ -371,17 +466,19 @@ static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, T
        if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
                return status;
        }
+       
+       gensec_ntlmssp_state->have_features = 0;
 
        if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
-               gensec_security->have_features |= GENSEC_FEATURE_SIGN;
+               gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SIGN;
        }
 
        if (gensec_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
-               gensec_security->have_features |= GENSEC_FEATURE_SEAL;
+               gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SEAL;
        }
 
        if (gensec_ntlmssp_state->ntlmssp_state->session_key.data) {
-               gensec_security->have_features |= GENSEC_FEATURE_SESSION_KEY;
+               gensec_ntlmssp_state->have_features |= GENSEC_FEATURE_SESSION_KEY;
        }
 
        return status;
@@ -418,6 +515,17 @@ static NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_secur
        return NT_STATUS_OK;
 }
 
+static BOOL gensec_ntlmssp_have_feature(struct gensec_security *gensec_security,
+                                       uint32 feature)
+{
+       struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
+       if (gensec_ntlmssp_state->have_features & feature) {
+               return True;
+       }
+
+       return False;
+}
+
 static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
        .name           = "ntlmssp",
        .sasl_name      = "NTLM",
@@ -431,8 +539,11 @@ static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
        .sign_packet    = gensec_ntlmssp_sign_packet,
        .check_packet   = gensec_ntlmssp_check_packet,
        .unseal_packet  = gensec_ntlmssp_unseal_packet,
+       .wrap           = gensec_ntlmssp_wrap,
+       .unwrap         = gensec_ntlmssp_unwrap,
        .session_key    = gensec_ntlmssp_session_key,
        .session_info   = gensec_ntlmssp_session_info,
+       .have_feature   = gensec_ntlmssp_have_feature
 };
 
 
index 4f1dc57e9ddf7041e63622f77297daf74883546a..f13bbc11b47df4e063f987758ba93cdeb383a70f 100644 (file)
@@ -162,6 +162,40 @@ static NTSTATUS gensec_spnego_sign_packet(struct gensec_security *gensec_securit
                                  sig);
 }
 
+static NTSTATUS gensec_spnego_wrap(struct gensec_security *gensec_security, 
+                                  TALLOC_CTX *mem_ctx, 
+                                  const DATA_BLOB *in, 
+                                  DATA_BLOB *out)
+{
+       struct spnego_state *spnego_state = gensec_security->private_data;
+
+       if (spnego_state->state_position != SPNEGO_DONE 
+           && spnego_state->state_position != SPNEGO_FALLBACK) {
+               DEBUG(1, ("gensec_spnego_wrap: wrong state for wrap\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       
+       return gensec_wrap(spnego_state->sub_sec_security, 
+                          mem_ctx, in, out);
+}
+
+static NTSTATUS gensec_spnego_unwrap(struct gensec_security *gensec_security, 
+                                    TALLOC_CTX *mem_ctx, 
+                                    const DATA_BLOB *in, 
+                                    DATA_BLOB *out)
+{
+       struct spnego_state *spnego_state = gensec_security->private_data;
+
+       if (spnego_state->state_position != SPNEGO_DONE 
+           && spnego_state->state_position != SPNEGO_FALLBACK) {
+               DEBUG(1, ("gensec_spnego_unwrap: wrong state for unwrap\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       
+       return gensec_unwrap(spnego_state->sub_sec_security, 
+                            mem_ctx, in, out);
+}
+
 static size_t gensec_spnego_sig_size(struct gensec_security *gensec_security) 
 {
        struct spnego_state *spnego_state = gensec_security->private_data;
@@ -357,11 +391,11 @@ static NTSTATUS gensec_spnego_client_negTokenInit(struct gensec_security *gensec
                spnego_state->expected_packet = SPNEGO_NEG_TOKEN_TARG;
                spnego_state->state_position = SPNEGO_CLIENT_TARG;
                return nt_status;
-       }
+       } 
        talloc_free(spnego_state->sub_sec_security);
        spnego_state->sub_sec_security = NULL;
 
-       DEBUG(1, ("Failed to setup SPNEGO netTokenInit request\n"));
+       DEBUG(1, ("Failed to setup SPNEGO negTokenInit request: %s\n", nt_errstr(nt_status)));
        return NT_STATUS_INVALID_PARAMETER;
 }
 
@@ -698,6 +732,18 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
        return NT_STATUS_INVALID_PARAMETER;
 }
 
+static BOOL gensec_spnego_have_feature(struct gensec_security *gensec_security,
+                                      uint32 feature) 
+{
+       struct spnego_state *spnego_state = gensec_security->private_data;
+       if (!spnego_state->sub_sec_security) {
+               return False;
+       }
+       
+       return gensec_have_feature(spnego_state->sub_sec_security, 
+                                  feature);
+}
+
 static const struct gensec_security_ops gensec_spnego_security_ops = {
        .name           = "spnego",
        .sasl_name      = "GSS-SPNEGO",
@@ -711,8 +757,11 @@ static const struct gensec_security_ops gensec_spnego_security_ops = {
        .sig_size       = gensec_spnego_sig_size,
        .check_packet   = gensec_spnego_check_packet,
        .unseal_packet  = gensec_spnego_unseal_packet,
+       .wrap           = gensec_spnego_wrap,
+       .unwrap         = gensec_spnego_unwrap,
        .session_key    = gensec_spnego_session_key,
        .session_info   = gensec_spnego_session_info,
+       .have_feature   = gensec_spnego_have_feature
 };
 
 NTSTATUS gensec_spnego_init(void)
index 6df48b7dd34d976b450d510a3261b89c1179ca7d..d58f58625e8878afb8bbe6b63e1af9b8110d9594 100644 (file)
@@ -289,10 +289,6 @@ static NTSTATUS dcerpc_schannel_start(struct gensec_security *gensec_security)
 
        dce_schan_state->state = DCERPC_SCHANNEL_STATE_START;
        gensec_security->private_data = dce_schan_state;
-       gensec_security->have_features = 
-               GENSEC_FEATURE_SESSION_KEY | 
-               GENSEC_FEATURE_SIGN | 
-               GENSEC_FEATURE_SEAL;
 
        talloc_set_destructor(dce_schan_state, dcerpc_schannel_destroy);
        
@@ -513,6 +509,18 @@ NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p,
                                                 creds);
 }
 
+static BOOL dcerpc_schannel_have_feature(struct gensec_security *gensec_security,
+                                         uint32 feature)
+{
+       if (feature & (GENSEC_FEATURE_SESSION_KEY | 
+                      GENSEC_FEATURE_SIGN | 
+                      GENSEC_FEATURE_SEAL)) {
+               return True;
+       }
+       return False;
+}
+
+
 static const struct gensec_security_ops gensec_dcerpc_schannel_security_ops = {
        .name           = "dcerpc_schannel",
        .auth_type      = DCERPC_AUTH_TYPE_SCHANNEL,
@@ -526,6 +534,7 @@ static const struct gensec_security_ops gensec_dcerpc_schannel_security_ops = {
        .session_key    = dcerpc_schannel_session_key,
        .session_info   = dcerpc_schannel_session_info,
        .sig_size       = dcerpc_schannel_sig_size,
+       .have_feature  = dcerpc_schannel_have_feature
 };
 
 NTSTATUS gensec_dcerpc_schannel_init(void)
index eea3b12073520403d8ba87cfa6be8ae7e3b32c59..162934a38dc5be9bf298673a0fa6e8b436818d16 100644 (file)
@@ -57,7 +57,7 @@ NTSTATUS torture_ldap_bind_sasl(struct ldap_connection *conn, const char *userna
 
        result = ldap_bind_sasl(conn, username, domain, password);
        if (result != LDAP_SUCCESS) {
-               printf("Failed to bind with provided credentialsi and SASL mechanism\n");
+               printf("Failed to bind with provided credentials and SASL mechanism\n");
                /* FIXME: what abut actually implementing an ldap_connection_free() function ?
                          :-) sss */
                return status;
@@ -109,9 +109,9 @@ BOOL ldap_sasl_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
        NTSTATUS status;
        DATA_BLOB request;
        BOOL result;
-       DATA_BLOB creds;
-       DATA_BLOB pdu;
+       DATA_BLOB wrapped;
        int len;
+       char length[4];
        struct asn1_data asn1;
        TALLOC_CTX *mem_ctx;
 
@@ -120,53 +120,48 @@ BOOL ldap_sasl_send_msg(struct ldap_connection *conn, struct ldap_message *msg,
        if (!ldap_encode(msg, &request))
                return False;
 
-       status = gensec_seal_packet(conn->gensec, 
-                                   msg->mem_ctx, 
-                                   request.data, request.length,
-                                   request.data, request.length,
-                                   &creds);
+       status = gensec_wrap(conn->gensec, 
+                            msg->mem_ctx, 
+                            &request,
+                            &wrapped);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("gensec_seal_packet: %s\n",nt_errstr(status)));
+               DEBUG(0,("gensec_wrap: %s\n",nt_errstr(status)));
                return False;
        }
 
-       len = 4 + creds.length + request.length;
-       pdu = data_blob_talloc(msg->mem_ctx, NULL, len);
-       RSIVAL(pdu.data, 0, len-4);
-       memcpy(pdu.data + 4, creds.data, creds.length);
-       memcpy(pdu.data + 4 + creds.length, request.data, request.length);
+       RSIVAL(length, 0, wrapped.length);
 
-       result = (write_data_until(conn->sock, pdu.data, pdu.length,
-                                  endtime) == pdu.length);
+       result = (write_data_until(conn->sock, length, 4,
+                                  endtime) == 4);
        if (!result)
                return result;
 
-       pdu = data_blob(NULL, 0x4000);
-       data_blob_clear(&pdu);
-
-       result = (read_data_until(conn->sock, pdu.data, 4, NULL) == 4);
+       result = (write_data_until(conn->sock, wrapped.data, wrapped.length,
+                                  endtime) == wrapped.length);
        if (!result)
                return result;
 
-       len = RIVAL(pdu.data,0);
+       wrapped = data_blob(NULL, 0x4000);
+       data_blob_clear(&wrapped);
 
-       result = (read_data_until(conn->sock, pdu.data + 4, MIN(0x4000,len), NULL) == len);
+       result = (read_data_until(conn->sock, length, 4, NULL) == 4);
        if (!result)
                return result;
 
-       pdu.length = 4+len;
+       len = RIVAL(length,0);
 
-       creds = data_blob(pdu.data + 4 , gensec_sig_size(conn->gensec));
+       result = (read_data_until(conn->sock, wrapped.data, MIN(wrapped.length,len), NULL) == len);
+       if (!result)
+               return result;
 
-       request = data_blob(pdu.data + (4 + creds.length), pdu.length - (4 + creds.length));
+       wrapped.length = len;
 
-       status = gensec_unseal_packet(conn->gensec,
-                            msg->mem_ctx,
-                            request.data, request.length,
-                            request.data, request.length,
-                            &creds);
+       status = gensec_unwrap(conn->gensec,
+                              msg->mem_ctx,
+                              &wrapped,
+                              &request);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0,("gensec_unseal_packet: %s\n",nt_errstr(status)));
+               DEBUG(0,("gensec_unwrap: %s\n",nt_errstr(status)));
                return False;
        }