summaryrefslogtreecommitdiff
path: root/source4/rpc_server
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-06-05 05:01:38 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:56:30 -0500
commit5341ad20e1b8953c9256cd8e04a7e55ba9ef84b5 (patch)
tree9d2c21766becd650905c32b1195d6a0203f93110 /source4/rpc_server
parent4c6f04d83f20ecfe62cd87dadf9b48a898502ea7 (diff)
downloadsamba-5341ad20e1b8953c9256cd8e04a7e55ba9ef84b5.tar.gz
samba-5341ad20e1b8953c9256cd8e04a7e55ba9ef84b5.tar.bz2
samba-5341ad20e1b8953c9256cd8e04a7e55ba9ef84b5.zip
r1030: added server side schannel support
(This used to be commit 2ac79dfba0e64056a680f21d7dd0c007f79d4a70)
Diffstat (limited to 'source4/rpc_server')
-rw-r--r--source4/rpc_server/config.mk1
-rw-r--r--source4/rpc_server/dcerpc_server.h2
-rw-r--r--source4/rpc_server/dcesrv_auth.c2
-rw-r--r--source4/rpc_server/dcesrv_crypto.c6
-rw-r--r--source4/rpc_server/dcesrv_crypto_ntlmssp.c9
-rw-r--r--source4/rpc_server/dcesrv_crypto_schannel.c170
-rw-r--r--source4/rpc_server/netlogon/schannel_state.c15
7 files changed, 194 insertions, 11 deletions
diff --git a/source4/rpc_server/config.mk b/source4/rpc_server/config.mk
index 4a7b17cffb..83bc53f1df 100644
--- a/source4/rpc_server/config.mk
+++ b/source4/rpc_server/config.mk
@@ -126,6 +126,7 @@ ADD_OBJ_FILES = \
rpc_server/dcesrv_auth.o \
rpc_server/dcesrv_crypto.o \
rpc_server/dcesrv_crypto_ntlmssp.o \
+ rpc_server/dcesrv_crypto_schannel.o \
rpc_server/handles.o
#
# End SUBSYSTEM DCERPC
diff --git a/source4/rpc_server/dcerpc_server.h b/source4/rpc_server/dcerpc_server.h
index bc5376b6ce..f73dbaf4cb 100644
--- a/source4/rpc_server/dcerpc_server.h
+++ b/source4/rpc_server/dcerpc_server.h
@@ -97,7 +97,7 @@ struct dcesrv_handle {
struct dcesrv_crypto_ops {
const char *name;
uint8 auth_type;
- NTSTATUS (*start)(struct dcesrv_auth *auth);
+ NTSTATUS (*start)(struct dcesrv_auth *auth, DATA_BLOB *auth_blob);
NTSTATUS (*update)(struct dcesrv_auth *auth, TALLOC_CTX *out_mem_ctx,
const DATA_BLOB in, DATA_BLOB *out);
NTSTATUS (*session_info)(struct dcesrv_auth *auth, struct auth_session_info **session_info);
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index df1a820039..6d08cca5fc 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -56,7 +56,7 @@ BOOL dcesrv_auth_bind(struct dcesrv_call_state *call)
return False;
}
- status = dcesrv_crypto_start(&dce_conn->auth_state);
+ status = dcesrv_crypto_start(&dce_conn->auth_state, &dce_conn->auth_state.auth_info->credentials);
if (!NT_STATUS_IS_OK(status)) {
return False;
}
diff --git a/source4/rpc_server/dcesrv_crypto.c b/source4/rpc_server/dcesrv_crypto.c
index b8dfe46835..31039510ab 100644
--- a/source4/rpc_server/dcesrv_crypto.c
+++ b/source4/rpc_server/dcesrv_crypto.c
@@ -68,9 +68,9 @@ NTSTATUS dcesrv_crypto_select_type(struct dcesrv_connection *dce_conn,
/*
start crypto state
*/
-NTSTATUS dcesrv_crypto_start(struct dcesrv_auth *auth)
+NTSTATUS dcesrv_crypto_start(struct dcesrv_auth *auth, DATA_BLOB *auth_blob)
{
- return auth->crypto_ctx.ops->start(auth);
+ return auth->crypto_ctx.ops->start(auth, auth_blob);
}
/*
@@ -138,10 +138,8 @@ void dcesrv_crypto_end(struct dcesrv_auth *auth)
const struct dcesrv_crypto_ops *dcesrv_crypto_backend_bytype(uint8_t auth_type)
{
switch (auth_type) {
-#if 0
case DCERPC_AUTH_TYPE_SCHANNEL:
return dcesrv_crypto_schannel_get_ops();
-#endif
case DCERPC_AUTH_TYPE_NTLMSSP:
return dcesrv_crypto_ntlmssp_get_ops();
}
diff --git a/source4/rpc_server/dcesrv_crypto_ntlmssp.c b/source4/rpc_server/dcesrv_crypto_ntlmssp.c
index 5fb6345599..a0bb153ef2 100644
--- a/source4/rpc_server/dcesrv_crypto_ntlmssp.c
+++ b/source4/rpc_server/dcesrv_crypto_ntlmssp.c
@@ -22,8 +22,7 @@
*/
/*
- this provides a crypto interface to the various backends (such as
- NTLMSSP and SCHANNEL) for the rpc server code
+ this provides the NTLMSSP backend for server side rpc
*/
#include "includes.h"
@@ -32,11 +31,15 @@
/*
start crypto state
*/
-static NTSTATUS dcesrv_crypto_ntlmssp_start(struct dcesrv_auth *auth)
+static NTSTATUS dcesrv_crypto_ntlmssp_start(struct dcesrv_auth *auth, DATA_BLOB *auth_blob)
{
struct auth_ntlmssp_state *ntlmssp = NULL;
NTSTATUS status;
+ /* TODO: we should parse the auth_blob and remember the client
+ hostname and target domain, then check against the auth3
+ bind packet */
+
status = auth_ntlmssp_start(&ntlmssp);
auth->crypto_ctx.private_data = ntlmssp;
diff --git a/source4/rpc_server/dcesrv_crypto_schannel.c b/source4/rpc_server/dcesrv_crypto_schannel.c
new file mode 100644
index 0000000000..a9256fb664
--- /dev/null
+++ b/source4/rpc_server/dcesrv_crypto_schannel.c
@@ -0,0 +1,170 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ server side dcerpc authentication code - schannel auth/crypto code
+
+ Copyright (C) Andrew Tridgell 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.
+*/
+
+#include "includes.h"
+
+struct srv_schannel_state {
+ TALLOC_CTX *mem_ctx;
+ struct dcerpc_bind_schannel bind_info;
+ struct schannel_state *state;
+};
+
+/*
+ start crypto state
+*/
+static NTSTATUS dcesrv_crypto_schannel_start(struct dcesrv_auth *auth, DATA_BLOB *auth_blob)
+{
+ struct srv_schannel_state *schannel = NULL;
+ NTSTATUS status;
+ TALLOC_CTX *mem_ctx;
+ uint8_t session_key[16];
+
+ mem_ctx = talloc_init("schannel_start");
+ if (!mem_ctx) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ schannel = talloc_p(mem_ctx, struct srv_schannel_state);
+ if (!schannel) {
+ talloc_destroy(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ schannel->mem_ctx = mem_ctx;
+
+ /* parse the schannel startup blob */
+ status = ndr_pull_struct_blob(auth_blob, mem_ctx, &schannel->bind_info,
+ (ndr_pull_flags_fn_t)ndr_pull_dcerpc_bind_schannel);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_destroy(mem_ctx);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* pull the session key for this client */
+ status = schannel_fetch_session_key(mem_ctx, schannel->bind_info.hostname, session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_destroy(mem_ctx);
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ /* start up the schannel server code */
+ status = schannel_start(&schannel->state, session_key, False);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_destroy(mem_ctx);
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ auth->crypto_ctx.private_data = schannel;
+
+ return status;
+}
+
+/*
+ update crypto state
+*/
+static NTSTATUS dcesrv_crypto_schannel_update(struct dcesrv_auth *auth, TALLOC_CTX *out_mem_ctx,
+ const DATA_BLOB in, DATA_BLOB *out)
+{
+ return NT_STATUS_OK;
+}
+
+/*
+ seal a packet
+*/
+static NTSTATUS dcesrv_crypto_schannel_seal(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+ uint8_t *data, size_t length, DATA_BLOB *sig)
+{
+ struct srv_schannel_state *srv_schannel_state = auth->crypto_ctx.private_data;
+
+ return schannel_seal_packet(srv_schannel_state->state, sig_mem_ctx, data, length, sig);
+}
+
+/*
+ sign a packet
+*/
+static NTSTATUS dcesrv_crypto_schannel_sign(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+ const uint8_t *data, size_t length, DATA_BLOB *sig)
+{
+ struct srv_schannel_state *srv_schannel_state = auth->crypto_ctx.private_data;
+
+ return schannel_sign_packet(srv_schannel_state->state, sig_mem_ctx, data, length, sig);
+}
+
+/*
+ check a packet signature
+*/
+static NTSTATUS dcesrv_crypto_schannel_check_sig(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+ const uint8_t *data, size_t length, const DATA_BLOB *sig)
+{
+ struct srv_schannel_state *srv_schannel_state = auth->crypto_ctx.private_data;
+
+ return schannel_check_packet(srv_schannel_state->state, data, length, sig);
+}
+
+/*
+ unseal a packet
+*/
+static NTSTATUS dcesrv_crypto_schannel_unseal(struct dcesrv_auth *auth, TALLOC_CTX *sig_mem_ctx,
+ uint8_t *data, size_t length, DATA_BLOB *sig)
+{
+ struct srv_schannel_state *srv_schannel_state = auth->crypto_ctx.private_data;
+
+ return schannel_unseal_packet(srv_schannel_state->state, sig_mem_ctx, data, length, sig);
+}
+
+/*
+ end crypto state
+*/
+static void dcesrv_crypto_schannel_end(struct dcesrv_auth *auth)
+{
+ struct srv_schannel_state *srv_schannel_state = auth->crypto_ctx.private_data;
+
+ if (srv_schannel_state == NULL) {
+ return;
+ }
+
+ schannel_end(&srv_schannel_state->state);
+
+ talloc_destroy(srv_schannel_state->mem_ctx);
+
+ auth->crypto_ctx.private_data = NULL;
+}
+
+static const struct dcesrv_crypto_ops dcesrv_crypto_schannel_ops = {
+ .name = "schannel",
+ .auth_type = DCERPC_AUTH_TYPE_SCHANNEL,
+ .start = dcesrv_crypto_schannel_start,
+ .update = dcesrv_crypto_schannel_update,
+ .seal = dcesrv_crypto_schannel_seal,
+ .sign = dcesrv_crypto_schannel_sign,
+ .check_sig = dcesrv_crypto_schannel_check_sig,
+ .unseal = dcesrv_crypto_schannel_unseal,
+ .end = dcesrv_crypto_schannel_end
+};
+
+/*
+ startup the cryptographic side of an authenticated dcerpc server
+*/
+const struct dcesrv_crypto_ops *dcesrv_crypto_schannel_get_ops(void)
+{
+ return &dcesrv_crypto_schannel_ops;
+}
diff --git a/source4/rpc_server/netlogon/schannel_state.c b/source4/rpc_server/netlogon/schannel_state.c
index f4190f21b4..eaa5013572 100644
--- a/source4/rpc_server/netlogon/schannel_state.c
+++ b/source4/rpc_server/netlogon/schannel_state.c
@@ -88,13 +88,17 @@ NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx,
ldb_msg_add_value(ldb, &msg, "sessionKey", &val);
ldb_msg_add_string(ldb, &msg, "expiry", s);
+ ldb_delete(ldb, msg.dn);
+
ret = ldb_add(ldb, &msg);
- ldb_close(ldb);
if (ret != 0) {
+ DEBUG(1,("Unable to add %s to session key db - %s\n", msg.dn, ldb_errstring(ldb)));
+ ldb_close(ldb);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
+ ldb_close(ldb);
return NT_STATUS_OK;
}
@@ -110,13 +114,20 @@ NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx,
struct ldb_message **res;
int ret;
const struct ldb_val *val;
+ char *expr=NULL;
ldb = schannel_db_connect(mem_ctx);
if (ldb == NULL) {
return NT_STATUS_NO_MEMORY;
}
- ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, "(dn=%s)", NULL, &res);
+ expr = talloc_asprintf(mem_ctx, "(dn=%s)", computer_name);
+ if (expr == NULL) {
+ ldb_close(ldb);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, expr, NULL, &res);
if (ret != 1) {
ldb_close(ldb);
return NT_STATUS_INVALID_HANDLE;