r1004: continue tridge's work on dcerpc server auth/crypto code
authorStefan Metzmacher <metze@samba.org>
Fri, 4 Jun 2004 09:46:46 +0000 (09:46 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:56:25 +0000 (12:56 -0500)
I made it much more generic, and we should be able to add a
module interface to this code, so that other DCERPC_AUTH types can be added
via modules...

metze

source/rpc_server/config.mk
source/rpc_server/dcerpc_server.c
source/rpc_server/dcerpc_server.h
source/rpc_server/dcesrv_auth.c
source/rpc_server/dcesrv_crypto.c
source/rpc_server/dcesrv_crypto_ntlmssp.c [new file with mode: 0644]

index 4f8b4796fddfa8409dd29705bee51e78a2c7092d..d532256c109044ee17963b580e7fe70f09965229 100644 (file)
@@ -123,6 +123,7 @@ ADD_OBJ_FILES = \
                rpc_server/dcerpc_tcp.o \
                rpc_server/dcesrv_auth.o \
                rpc_server/dcesrv_crypto.o \
+               rpc_server/dcesrv_crypto_ntlmssp.o \
                rpc_server/handles.o
 #
 # End SUBSYSTEM DCERPC
index fd806c52891e32e9ee257ac1a5f1c15f8ceb5509..2c0db1508140a1abe66edfa8ec5204333d13b0a5 100644 (file)
@@ -268,8 +268,9 @@ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
        (*p)->cli_max_recv_frag = 0;
        (*p)->handles = NULL;
        (*p)->partial_input = data_blob(NULL, 0);
-       (*p)->auth_state.crypto_state = NULL;
        (*p)->auth_state.auth_info = NULL;
+       (*p)->auth_state.crypto_ctx.private_data = NULL;
+       (*p)->auth_state.crypto_ctx.ops = NULL;
        (*p)->session_key = data_blob(NULL, 0);
 
        return NT_STATUS_OK;
@@ -326,7 +327,11 @@ void dcesrv_endpoint_disconnect(struct dcesrv_connection *p)
        while (p->handles) {
                dcesrv_handle_destroy(p, p->handles);
        }
-       
+
+       if (p->auth_state.crypto_ctx.ops) {
+               p->auth_state.crypto_ctx.ops->end(&p->auth_state);
+       }
+
        talloc_destroy(p->mem_ctx);
 }
 
index bdda8f252fc9f72b1550d852ed4ef398ff02ad80..44726b582851b6dea3c69fcad9318665a957f0fa 100644 (file)
@@ -45,6 +45,7 @@ struct dcesrv_ep_description {
 
 struct dcesrv_connection;
 struct dcesrv_call_state;
+struct dcesrv_auth;
 
 /* the dispatch functions for an interface take this form */
 typedef NTSTATUS (*dcesrv_dispatch_fn_t)(struct dcesrv_call_state *, TALLOC_CTX *, void *);
@@ -93,10 +94,30 @@ struct dcesrv_handle {
        void (*destroy)(struct dcesrv_connection *, struct dcesrv_handle *);
 };
 
+struct dcesrv_cyrpto_ops {
+       const char *name;
+       uint8 auth_type;
+       NTSTATUS (*start)(struct dcesrv_auth *auth);
+       NTSTATUS (*update)(struct dcesrv_auth *auth, TALLOC_CTX *out_mem_ctx,
+                               const DATA_BLOB in, DATA_BLOB *out);
+       NTSTATUS (*seal)(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+                               uint8_t *data, size_t length, DATA_BLOB *sig);
+       NTSTATUS (*sign)(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+                               const uint8_t *data, size_t length, DATA_BLOB *sig);
+       NTSTATUS (*check_sig)(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx, 
+                               const uint8_t *data, size_t length, const DATA_BLOB *sig);
+       NTSTATUS (*unseal)(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+                               uint8_t *data, size_t length, DATA_BLOB *sig);
+       void (*end)(struct dcesrv_auth *auth);
+};
+
 /* hold the authentication state information */
 struct dcesrv_auth {
-       void *crypto_state;
        struct dcerpc_auth *auth_info;
+       struct {
+               void *private_data;
+               const struct dcesrv_cyrpto_ops *ops;
+       } crypto_ctx;
 };
 
 
index 7aa296c24572fa84cf9dfdb88640d050de6f9faf..df1a8200397407a6030110db2f4517a1e584da1e 100644 (file)
@@ -51,11 +51,16 @@ BOOL dcesrv_auth_bind(struct dcesrv_call_state *call)
                return False;
        }
 
-       status = dcesrv_crypto_startup(dce_conn, &dce_conn->auth_state);
+       status = dcesrv_crypto_select_type(dce_conn, &dce_conn->auth_state);
        if (!NT_STATUS_IS_OK(status)) {
                return False;
        }
-       
+
+       status = dcesrv_crypto_start(&dce_conn->auth_state);
+       if (!NT_STATUS_IS_OK(status)) {
+               return False;
+       }
+
        return True;
 }
 
@@ -67,7 +72,7 @@ BOOL dcesrv_auth_bind_ack(struct dcesrv_call_state *call, struct dcerpc_packet *
        struct dcesrv_connection *dce_conn = call->conn;
        NTSTATUS status;
 
-       if (!call->conn->auth_state.crypto_state) {
+       if (!call->conn->auth_state.crypto_ctx.ops) {
                return True;
        }
 
@@ -98,7 +103,7 @@ BOOL dcesrv_auth_auth3(struct dcesrv_call_state *call)
        NTSTATUS status;
 
        if (!dce_conn->auth_state.auth_info ||
-           !dce_conn->auth_state.crypto_state ||
+           !dce_conn->auth_state.crypto_ctx.ops ||
            pkt->u.auth.auth_info.length == 0) {
                return False;
        }
@@ -138,7 +143,7 @@ BOOL dcesrv_auth_request(struct dcesrv_call_state *call)
        NTSTATUS status;
 
        if (!dce_conn->auth_state.auth_info ||
-           !dce_conn->auth_state.crypto_state) {
+           !dce_conn->auth_state.crypto_ctx.ops) {
                return True;
        }
 
@@ -213,7 +218,7 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
        struct ndr_push *ndr;
 
        /* non-signed packets are simple */
-       if (!dce_conn->auth_state.auth_info || !dce_conn->auth_state.crypto_state) {
+       if (!dce_conn->auth_state.auth_info || !dce_conn->auth_state.crypto_ctx.ops) {
                status = dcerpc_push_auth(blob, call->mem_ctx, pkt, NULL);
                return NT_STATUS_IS_OK(status);
        }
index f9e109abd2d09e6ca988f8be511f8917ce707eef..11956fe3be0e8188da7cd2688b4ddf4f0744b762 100644 (file)
@@ -4,6 +4,7 @@
    server side dcerpc authentication code - crypto support
 
    Copyright (C) Andrew Tridgell 2004
+   Copyright (C) Stefan (metze) Metzmacher 2004
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 /*
   startup the cryptographic side of an authenticated dcerpc server
 */
-NTSTATUS dcesrv_crypto_startup(struct dcesrv_connection *dce_conn,
+NTSTATUS dcesrv_crypto_select_type(struct dcesrv_connection *dce_conn,
                               struct dcesrv_auth *auth)
 {
-       struct auth_ntlmssp_state *ntlmssp = NULL;
        NTSTATUS status;
 
        if (auth->auth_info->auth_level != DCERPC_AUTH_LEVEL_INTEGRITY &&
@@ -43,20 +43,34 @@ NTSTATUS dcesrv_crypto_startup(struct dcesrv_connection *dce_conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       if (auth->crypto_ctx.ops != NULL) {
+               /* TODO:
+                * this this function should not be called
+                * twice per dcesrv_connection!
+                * 
+                * so we need to find out the right
+                * dcerpc error to return
+                */
+       }
+
+       /*
+        * TODO:
+        * maybe a dcesrv_crypto_find_backend_by_type() whould be better here
+        * to make thinks more generic
+        */
        switch (auth->auth_info->auth_type) {
-/*
-       case DCERPC_AUTH_TYPE_SCHANNEL:
-               return auth_schannel_start();
-*/
 
+/*     case DCERPC_AUTH_TYPE_SCHANNEL:
+               status = dcesrv_crypto_schannel_get_ops(dce_conn, auth);
+               break;
+*/
        case DCERPC_AUTH_TYPE_NTLMSSP:
-               status = auth_ntlmssp_start(&ntlmssp);
-               auth->crypto_state = ntlmssp;
+               status = dcesrv_crypto_ntlmssp_get_ops(dce_conn, auth);
                break;
 
        default:
                DEBUG(2,("dcesrv auth_type %d not supported\n", auth->auth_info->auth_type));
-               status = NT_STATUS_INVALID_PARAMETER;
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
        DEBUG(4,("dcesrv_crypto_startup: %s\n", nt_errstr(status)));
@@ -64,6 +78,14 @@ NTSTATUS dcesrv_crypto_startup(struct dcesrv_connection *dce_conn,
        return status;
 }
 
+/*
+  start crypto state
+*/
+NTSTATUS dcesrv_crypto_start(struct dcesrv_auth *auth) 
+{
+       return auth->crypto_ctx.ops->start(auth);
+}
+
 /*
   update crypto state
 */
@@ -71,52 +93,49 @@ NTSTATUS dcesrv_crypto_update(struct dcesrv_auth *auth,
                              TALLOC_CTX *out_mem_ctx, 
                              const DATA_BLOB in, DATA_BLOB *out) 
 {
-       struct auth_ntlmssp_state *ntlmssp = auth->crypto_state;
-
-       return ntlmssp_update(ntlmssp->ntlmssp_state, out_mem_ctx, in, out);
+       return auth->crypto_ctx.ops->update(auth, out_mem_ctx, in, out);
 }
 
-
 /*
   seal a packet
 */
-NTSTATUS dcesrv_crypto_seal(struct dcesrv_auth *auth, 
-                           TALLOC_CTX *sig_mem_ctx, uint8_t *data, size_t length, DATA_BLOB *sig)
+NTSTATUS dcesrv_crypto_seal(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+                               uint8_t *data, size_t length, DATA_BLOB *sig)
 {
-       struct auth_ntlmssp_state *ntlmssp = auth->crypto_state;
-
-       return ntlmssp_seal_packet(ntlmssp->ntlmssp_state, sig_mem_ctx, data, length, sig);
+       return auth->crypto_ctx.ops->seal(auth, sig_mem_ctx, data, length, sig);
 }
 
 /*
   sign a packet
 */
-NTSTATUS dcesrv_crypto_sign(struct dcesrv_auth *auth, 
-                           TALLOC_CTX *sig_mem_ctx, const uint8_t *data, size_t length, DATA_BLOB *sig) 
+NTSTATUS dcesrv_crypto_sign(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+                               const uint8_t *data, size_t length, DATA_BLOB *sig) 
 {
-       struct auth_ntlmssp_state *ntlmssp = auth->crypto_state;
-
-       return ntlmssp_sign_packet(ntlmssp->ntlmssp_state, sig_mem_ctx, data, length, sig);
+       return auth->crypto_ctx.ops->sign(auth, sig_mem_ctx, data, length, sig);
 }
 
 /*
   check a packet signature
 */
-NTSTATUS dcesrv_crypto_check_sig(struct dcesrv_auth *auth, 
-                                TALLOC_CTX *sig_mem_ctx, const uint8_t *data, size_t length, const DATA_BLOB *sig)
+NTSTATUS dcesrv_crypto_check_sig(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+                               const uint8_t *data, size_t length, const DATA_BLOB *sig)
 {
-       struct auth_ntlmssp_state *ntlmssp = auth->crypto_state;
-
-       return ntlmssp_check_packet(ntlmssp->ntlmssp_state, sig_mem_ctx, data, length, sig);
+       return auth->crypto_ctx.ops->check_sig(auth, sig_mem_ctx, data, length, sig);
 }
 
 /*
   unseal a packet
 */
-NTSTATUS dcesrv_crypto_unseal(struct dcesrv_auth *auth, 
-                              TALLOC_CTX *sig_mem_ctx, uint8_t *data, size_t length, DATA_BLOB *sig)
+NTSTATUS dcesrv_crypto_unseal(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+                               uint8_t *data, size_t length, DATA_BLOB *sig)
 {
-       struct auth_ntlmssp_state *ntlmssp = auth->crypto_state;
+       return auth->crypto_ctx.ops->unseal(auth, sig_mem_ctx, data, length, sig);
+}
 
-       return ntlmssp_unseal_packet(ntlmssp->ntlmssp_state, sig_mem_ctx, data, length, sig);
+/*
+  end crypto state
+*/
+void dcesrv_crypto_end(struct dcesrv_auth *auth) 
+{
+       auth->crypto_ctx.ops->end(auth);
 }
diff --git a/source/rpc_server/dcesrv_crypto_ntlmssp.c b/source/rpc_server/dcesrv_crypto_ntlmssp.c
new file mode 100644 (file)
index 0000000..b894f0f
--- /dev/null
@@ -0,0 +1,139 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   server side dcerpc authentication code - NTLMSSP auth/crypto code
+
+   Copyright (C) Andrew Tridgell 2004
+   Copyright (C) Stefan (metze) Metzmacher 2004
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+  this provides a crypto interface to the various backends (such as
+  NTLMSSP and SCHANNEL) for the rpc server code
+*/
+
+#include "includes.h"
+
+
+/*
+  start crypto state
+*/
+static NTSTATUS dcesrv_crypto_ntlmssp_start(struct dcesrv_auth *auth)
+{
+       struct auth_ntlmssp_state *ntlmssp = NULL;
+       NTSTATUS status;
+
+       status = auth_ntlmssp_start(&ntlmssp);
+
+       auth->crypto_ctx.private_data = ntlmssp;
+
+       return status;
+}
+
+/*
+  update crypto state
+*/
+static NTSTATUS dcesrv_crypto_ntlmssp_update(struct dcesrv_auth *auth, TALLOC_CTX *out_mem_ctx, 
+                                               const DATA_BLOB in, DATA_BLOB *out) 
+{
+       struct auth_ntlmssp_state *auth_ntlmssp_state = auth->crypto_ctx.private_data;
+
+       return ntlmssp_update(auth_ntlmssp_state->ntlmssp_state, out_mem_ctx, in, out);
+}
+
+/*
+  seal a packet
+*/
+static NTSTATUS dcesrv_crypto_ntlmssp_seal(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+                                               uint8_t *data, size_t length, DATA_BLOB *sig)
+{
+       struct auth_ntlmssp_state *auth_ntlmssp_state = auth->crypto_ctx.private_data;
+
+       return ntlmssp_seal_packet(auth_ntlmssp_state->ntlmssp_state, sig_mem_ctx, data, length, sig);
+}
+
+/*
+  sign a packet
+*/
+static NTSTATUS dcesrv_crypto_ntlmssp_sign(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+                                               const uint8_t *data, size_t length, DATA_BLOB *sig) 
+{
+       struct auth_ntlmssp_state *auth_ntlmssp_state = auth->crypto_ctx.private_data;
+
+       return ntlmssp_sign_packet(auth_ntlmssp_state->ntlmssp_state, sig_mem_ctx, data, length, sig);
+}
+
+/*
+  check a packet signature
+*/
+static NTSTATUS dcesrv_crypto_ntlmssp_check_sig(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+                                               const uint8_t *data, size_t length, const DATA_BLOB *sig)
+{
+       struct auth_ntlmssp_state *auth_ntlmssp_state = auth->crypto_ctx.private_data;
+
+       return ntlmssp_check_packet(auth_ntlmssp_state->ntlmssp_state, sig_mem_ctx, data, length, sig);
+}
+
+/*
+  unseal a packet
+*/
+static NTSTATUS dcesrv_crypto_ntlmssp_unseal(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+                                               uint8_t *data, size_t length, DATA_BLOB *sig)
+{
+       struct auth_ntlmssp_state *auth_ntlmssp_state = auth->crypto_ctx.private_data;
+
+       return ntlmssp_unseal_packet(auth_ntlmssp_state->ntlmssp_state, sig_mem_ctx, data, length, sig);
+}
+
+/*
+  end crypto state
+*/
+static void dcesrv_crypto_ntlmssp_end(struct dcesrv_auth *auth)
+{
+       struct auth_ntlmssp_state *auth_ntlmssp_state = auth->crypto_ctx.private_data;
+
+       auth->crypto_ctx.private_data = NULL;
+
+       auth_ntlmssp_end(&auth_ntlmssp_state);
+
+       return;
+}
+
+static const struct dcesrv_cyrpto_ops dcesrv_crypto_ntlmssp_ops = {
+       .name           = "ntlmssp",
+       .auth_type      = DCERPC_AUTH_TYPE_NTLMSSP,
+       .start          = dcesrv_crypto_ntlmssp_start,
+       .update         = dcesrv_crypto_ntlmssp_update,
+       .seal           = dcesrv_crypto_ntlmssp_seal,
+       .sign           = dcesrv_crypto_ntlmssp_sign,
+       .check_sig      = dcesrv_crypto_ntlmssp_check_sig,
+       .unseal         = dcesrv_crypto_ntlmssp_unseal,
+       .end            = dcesrv_crypto_ntlmssp_end
+};
+
+/*
+  startup the cryptographic side of an authenticated dcerpc server
+*/
+NTSTATUS dcesrv_crypto_ntlmssp_get_ops(struct dcesrv_connection *dce_conn,
+                              struct dcesrv_auth *auth)
+{
+       NTSTATUS status = NT_STATUS_OK;
+
+       auth->crypto_ctx.ops = &dcesrv_crypto_ntlmssp_ops;
+
+       return status;
+}