From 765832748b4ef6141802ff72e3dea99453bf23d8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 6 Mar 2005 06:37:38 +0000 Subject: r5667: Move schannel state into libcli/auth (as it belongs with schannel, which will move in with the rest of GENSEC shortly). Add the RID as another element in the schannel state. Andrew Bartlett (This used to be commit 69114b4a8e1c937ab5ff12ca91dd22bd83fd9a3b) --- source4/libcli/auth/credentials.h | 1 + source4/libcli/auth/gensec.mk | 10 ++ source4/libcli/auth/schannel_state.c | 225 ++++++++++++++++++++++++++ source4/librpc/rpc/dcerpc_schannel.c | 7 - source4/rpc_server/config.mk | 9 -- source4/rpc_server/netlogon/dcerpc_netlogon.c | 11 +- source4/rpc_server/netlogon/schannel_state.c | 214 ------------------------ 7 files changed, 239 insertions(+), 238 deletions(-) create mode 100644 source4/libcli/auth/schannel_state.c delete mode 100644 source4/rpc_server/netlogon/schannel_state.c (limited to 'source4') diff --git a/source4/libcli/auth/credentials.h b/source4/libcli/auth/credentials.h index 7c3c4379d1..d1417bf83e 100644 --- a/source4/libcli/auth/credentials.h +++ b/source4/libcli/auth/credentials.h @@ -32,6 +32,7 @@ struct creds_CredentialState { uint16_t secure_channel_type; const char *computer_name; const char *account_name; + uint32_t rid; }; /* for the timebeing, use the same neg flags as Samba3. */ diff --git a/source4/libcli/auth/gensec.mk b/source4/libcli/auth/gensec.mk index e4559bb972..7e2e34081d 100644 --- a/source4/libcli/auth/gensec.mk +++ b/source4/libcli/auth/gensec.mk @@ -67,3 +67,13 @@ ADD_OBJ_FILES = \ REQUIRED_SUBSYSTEMS = AUTH # End MODULE gensec_ntlmssp ################################################ + +################################################ +# Start SUBSYSTEM SCHANNELDB +[SUBSYSTEM::SCHANNELDB] +INIT_OBJ_FILES = \ + libcli/auth/schannel_state.o +# +# End SUBSYSTEM SCHANNELDB +################################################ + diff --git a/source4/libcli/auth/schannel_state.c b/source4/libcli/auth/schannel_state.c new file mode 100644 index 0000000000..2a9e0a3ec3 --- /dev/null +++ b/source4/libcli/auth/schannel_state.c @@ -0,0 +1,225 @@ +/* + Unix SMB/CIFS implementation. + + module to store/fetch session keys for the schannel server + + 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" +#include "system/time.h" +#include "auth/auth.h" +#include "lib/ldb/include/ldb.h" +#include "db_wrap.h" + +/* a reasonable amount of time to keep credentials live */ +#define SCHANNEL_CREDENTIALS_EXPIRY 600 + +/* + connect to the schannel ldb +*/ +static struct ldb_context *schannel_db_connect(TALLOC_CTX *mem_ctx) +{ + char *path; + struct ldb_context *ldb; + + path = smbd_tmp_path(mem_ctx, "schannel.ldb"); + if (!path) { + return NULL; + } + + ldb = ldb_wrap_connect(mem_ctx, path, 0, NULL); + talloc_free(path); + if (!ldb) { + return NULL; + } + + return ldb; +} + +/* + remember an established session key for a netr server authentication + use a simple ldb structure +*/ +NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx, + struct creds_CredentialState *creds) +{ + struct ldb_context *ldb; + struct ldb_message *msg; + struct ldb_val val, seed; + char *s; + char *f; + char *sct; + char *rid; + time_t expiry = time(NULL) + SCHANNEL_CREDENTIALS_EXPIRY; + int ret; + + ldb = schannel_db_connect(mem_ctx); + if (ldb == NULL) { + return NT_STATUS_NO_MEMORY; + } + + s = talloc_asprintf(mem_ctx, "%u", (unsigned int)expiry); + + if (s == NULL) { + talloc_free(ldb); + return NT_STATUS_NO_MEMORY; + } + + f = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->negotiate_flags); + + if (f == NULL) { + talloc_free(ldb); + return NT_STATUS_NO_MEMORY; + } + + sct = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->secure_channel_type); + + if (sct == NULL) { + talloc_free(ldb); + return NT_STATUS_NO_MEMORY; + } + + rid = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->rid); + + if (rid == NULL) { + talloc_free(ldb); + return NT_STATUS_NO_MEMORY; + } + + msg = ldb_msg_new(mem_ctx); + if (msg == NULL) { + talloc_free(ldb); + return NT_STATUS_NO_MEMORY; + } + + msg->dn = talloc_asprintf(msg, "computerName=%s", creds->computer_name); + if (msg->dn == NULL) { + talloc_free(ldb); + talloc_free(msg); + return NT_STATUS_NO_MEMORY; + } + + val.data = creds->session_key; + val.length = sizeof(creds->session_key); + + seed.data = creds->seed.data; + seed.length = sizeof(creds->seed.data); + + ldb_msg_add_value(ldb, msg, "sessionKey", &val); + ldb_msg_add_value(ldb, msg, "seed", &seed); + ldb_msg_add_string(ldb, msg, "expiry", s); + ldb_msg_add_string(ldb, msg, "negotiateFlags", f); + ldb_msg_add_string(ldb, msg, "secureChannelType", sct); + ldb_msg_add_string(ldb, msg, "accountName", creds->account_name); + ldb_msg_add_string(ldb, msg, "computerName", creds->computer_name); + ldb_msg_add_string(ldb, msg, "rid", rid); + + ldb_delete(ldb, msg->dn); + + ret = ldb_add(ldb, msg); + + talloc_free(s); + + if (ret != 0) { + DEBUG(0,("Unable to add %s to session key db - %s\n", + msg->dn, ldb_errstring(ldb))); + talloc_free(ldb); + talloc_free(msg); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + talloc_free(msg); + talloc_free(ldb); + + return NT_STATUS_OK; +} + + +/* + read back a credentials back for a computer +*/ +NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx, + const char *computer_name, + struct creds_CredentialState **creds) +{ + struct ldb_context *ldb; + time_t expiry; + struct ldb_message **res; + int ret; + const struct ldb_val *val; + char *expr=NULL; + + *creds = talloc_zero(mem_ctx, struct creds_CredentialState); + if (!*creds) { + return NT_STATUS_NO_MEMORY; + } + + ldb = schannel_db_connect(mem_ctx); + if (ldb == NULL) { + return NT_STATUS_NO_MEMORY; + } + + expr = talloc_asprintf(mem_ctx, "(dn=computerName=%s)", computer_name); + if (expr == NULL) { + talloc_free(ldb); + return NT_STATUS_NO_MEMORY; + } + + ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, expr, NULL, &res); + if (ret != 1) { + talloc_free(ldb); + return NT_STATUS_INVALID_HANDLE; + } + + expiry = ldb_msg_find_uint(res[0], "expiry", 0); + if (expiry < time(NULL)) { + DEBUG(1,("schannel: attempt to use expired session key for %s\n", computer_name)); + talloc_free(ldb); + return NT_STATUS_INVALID_HANDLE; + } + + val = ldb_msg_find_ldb_val(res[0], "sessionKey"); + if (val == NULL || val->length != 16) { + talloc_free(ldb); + return NT_STATUS_INVALID_HANDLE; + } + + memcpy((*creds)->session_key, val->data, 16); + + val = ldb_msg_find_ldb_val(res[0], "seed"); + if (val == NULL || val->length != 8) { + talloc_free(ldb); + return NT_STATUS_INVALID_HANDLE; + } + + memcpy((*creds)->seed.data, val->data, 8); + + (*creds)->negotiate_flags = ldb_msg_find_int(res[0], "negotiateFlags", 0); + + (*creds)->secure_channel_type = ldb_msg_find_int(res[0], "secureChannelType", 0); + + (*creds)->account_name = talloc_reference(*creds, ldb_msg_find_string(res[0], "accountName", NULL)); + + (*creds)->computer_name = talloc_reference(*creds, ldb_msg_find_string(res[0], "computerName", NULL)); + + (*creds)->rid = ldb_msg_find_uint(res[0], "rid", 0); + + talloc_free(ldb); + + return NT_STATUS_OK; +} diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c index a6262d85f0..d99d43ad58 100644 --- a/source4/librpc/rpc/dcerpc_schannel.c +++ b/source4/librpc/rpc/dcerpc_schannel.c @@ -36,13 +36,6 @@ struct dcerpc_schannel_state { char *account_name; }; -static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p, - const char *domain, - const char *username, - const char *password, - int chan_type, - struct creds_CredentialState *creds); - /* wrappers for the schannel_*() functions diff --git a/source4/rpc_server/config.mk b/source4/rpc_server/config.mk index e50aa58c35..765f2237bc 100644 --- a/source4/rpc_server/config.mk +++ b/source4/rpc_server/config.mk @@ -31,15 +31,6 @@ REQUIRED_SUBSYSTEMS = \ # End MODULE dcerpc_dcom ################################################ -################################################ -# Start SUBSYSTEM SCHANNELDB -[SUBSYSTEM::SCHANNELDB] -INIT_OBJ_FILES = \ - rpc_server/netlogon/schannel_state.o -# -# End SUBSYSTEM SCHANNELDB -################################################ - ################################################ # Start MODULE dcerpc_rpcecho [MODULE::dcerpc_rpcecho] diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index bb16ed54c6..fd93d495e2 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -45,17 +45,11 @@ static NTSTATUS netlogon_schannel_setup(struct dcesrv_call_state *dce_call) struct server_pipe_state *state; NTSTATUS status; - state = talloc(dce_call->conn, struct server_pipe_state); + /* We want the client and server challenge zero */ + state = talloc_zero(dce_call->conn, struct server_pipe_state); if (state == NULL) { return NT_STATUS_NO_MEMORY; } - ZERO_STRUCTP(state); - - if (dce_call->conn->auth_state.session_info == NULL) { - talloc_free(state); - smb_panic("No session info provided by schannel level setup!"); - return NT_STATUS_NO_USER_SESSION_KEY; - } status = dcerpc_schannel_creds(dce_call->conn->auth_state.gensec_security, state, @@ -235,6 +229,7 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL pipe_state->creds->secure_channel_type = r->in.secure_channel_type; + pipe_state->creds->rid = *r->out.rid; /* remember this session key state */ nt_status = schannel_store_session_key(mem_ctx, pipe_state->creds); diff --git a/source4/rpc_server/netlogon/schannel_state.c b/source4/rpc_server/netlogon/schannel_state.c deleted file mode 100644 index e7c9c13314..0000000000 --- a/source4/rpc_server/netlogon/schannel_state.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - module to store/fetch session keys for the schannel server - - 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" -#include "system/time.h" -#include "auth/auth.h" -#include "lib/ldb/include/ldb.h" -#include "db_wrap.h" - -/* a reasonable amount of time to keep credentials live */ -#define SCHANNEL_CREDENTIALS_EXPIRY 600 - -/* - connect to the schannel ldb -*/ -static struct ldb_context *schannel_db_connect(TALLOC_CTX *mem_ctx) -{ - char *path; - struct ldb_context *ldb; - - path = smbd_tmp_path(mem_ctx, "schannel.ldb"); - if (!path) { - return NULL; - } - - ldb = ldb_wrap_connect(mem_ctx, path, 0, NULL); - talloc_free(path); - if (!ldb) { - return NULL; - } - - return ldb; -} - -/* - remember an established session key for a netr server authentication - use a simple ldb structure -*/ -NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx, - struct creds_CredentialState *creds) -{ - struct ldb_context *ldb; - struct ldb_message *msg; - struct ldb_val val, seed; - char *s; - char *f; - char *sct; - time_t expiry = time(NULL) + SCHANNEL_CREDENTIALS_EXPIRY; - int ret; - - ldb = schannel_db_connect(mem_ctx); - if (ldb == NULL) { - return NT_STATUS_NO_MEMORY; - } - - s = talloc_asprintf(mem_ctx, "%u", (unsigned int)expiry); - - if (s == NULL) { - talloc_free(ldb); - return NT_STATUS_NO_MEMORY; - } - - f = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->negotiate_flags); - - if (f == NULL) { - talloc_free(ldb); - return NT_STATUS_NO_MEMORY; - } - - sct = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->secure_channel_type); - - if (sct == NULL) { - talloc_free(ldb); - return NT_STATUS_NO_MEMORY; - } - - msg = ldb_msg_new(mem_ctx); - if (msg == NULL) { - talloc_free(ldb); - return NT_STATUS_NO_MEMORY; - } - - msg->dn = talloc_asprintf(msg, "computerName=%s", creds->computer_name); - if (msg->dn == NULL) { - talloc_free(ldb); - talloc_free(msg); - return NT_STATUS_NO_MEMORY; - } - - val.data = creds->session_key; - val.length = sizeof(creds->session_key); - - seed.data = creds->seed.data; - seed.length = sizeof(creds->seed.data); - - ldb_msg_add_value(ldb, msg, "sessionKey", &val); - ldb_msg_add_value(ldb, msg, "seed", &seed); - ldb_msg_add_string(ldb, msg, "expiry", s); - ldb_msg_add_string(ldb, msg, "negotiateFlags", f); - ldb_msg_add_string(ldb, msg, "secureChannelType", sct); - ldb_msg_add_string(ldb, msg, "accountName", creds->account_name); - ldb_msg_add_string(ldb, msg, "computerName", creds->computer_name); - - ldb_delete(ldb, msg->dn); - - ret = ldb_add(ldb, msg); - - talloc_free(s); - - if (ret != 0) { - DEBUG(0,("Unable to add %s to session key db - %s\n", - msg->dn, ldb_errstring(ldb))); - talloc_free(ldb); - talloc_free(msg); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - talloc_free(msg); - talloc_free(ldb); - - return NT_STATUS_OK; -} - - -/* - read back a credentials back for a computer -*/ -NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx, - const char *computer_name, - struct creds_CredentialState **creds) -{ - struct ldb_context *ldb; - time_t expiry; - struct ldb_message **res; - int ret; - const struct ldb_val *val; - char *expr=NULL; - - *creds = talloc_zero(mem_ctx, struct creds_CredentialState); - if (!*creds) { - return NT_STATUS_NO_MEMORY; - } - - ldb = schannel_db_connect(mem_ctx); - if (ldb == NULL) { - return NT_STATUS_NO_MEMORY; - } - - expr = talloc_asprintf(mem_ctx, "(dn=computerName=%s)", computer_name); - if (expr == NULL) { - talloc_free(ldb); - return NT_STATUS_NO_MEMORY; - } - - ret = ldb_search(ldb, NULL, LDB_SCOPE_SUBTREE, expr, NULL, &res); - if (ret != 1) { - talloc_free(ldb); - return NT_STATUS_INVALID_HANDLE; - } - - expiry = ldb_msg_find_uint(res[0], "expiry", 0); - if (expiry < time(NULL)) { - DEBUG(1,("schannel: attempt to use expired session key for %s\n", computer_name)); - talloc_free(ldb); - return NT_STATUS_INVALID_HANDLE; - } - - val = ldb_msg_find_ldb_val(res[0], "sessionKey"); - if (val == NULL || val->length != 16) { - talloc_free(ldb); - return NT_STATUS_INVALID_HANDLE; - } - - memcpy((*creds)->session_key, val->data, 16); - - val = ldb_msg_find_ldb_val(res[0], "seed"); - if (val == NULL || val->length != 8) { - talloc_free(ldb); - return NT_STATUS_INVALID_HANDLE; - } - - memcpy((*creds)->seed.data, val->data, 8); - - (*creds)->negotiate_flags = ldb_msg_find_int(res[0], "negotiateFlags", 0); - - (*creds)->secure_channel_type = ldb_msg_find_int(res[0], "secureChannelType", 0); - - (*creds)->account_name = talloc_reference(*creds, ldb_msg_find_string(res[0], "accountName", NULL)); - - (*creds)->computer_name = talloc_reference(*creds, ldb_msg_find_string(res[0], "computerName", NULL)); - - talloc_free(ldb); - - return NT_STATUS_OK; -} -- cgit