diff options
Diffstat (limited to 'source4/rpc_server')
-rw-r--r-- | source4/rpc_server/netlogon/schannel_state.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/source4/rpc_server/netlogon/schannel_state.c b/source4/rpc_server/netlogon/schannel_state.c new file mode 100644 index 0000000000..f4190f21b4 --- /dev/null +++ b/source4/rpc_server/netlogon/schannel_state.c @@ -0,0 +1,143 @@ +/* + 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" + +/* 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 = lock_path(mem_ctx, "schannel.ldb"); + if (!path) { + return NULL; + } + + ldb = ldb_connect(path, 0, NULL); + if (!ldb) { + return NULL; + } + + ldb_set_alloc(ldb, talloc_ldb_alloc, mem_ctx); + + 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, + const char *computer_name, struct creds_CredentialState *creds) +{ + struct ldb_context *ldb; + struct ldb_message msg; + struct ldb_val val; + char *s = NULL; + time_t expiry = time(NULL) + SCHANNEL_CREDENTIALS_EXPIRY; + int ret; + + ldb = schannel_db_connect(mem_ctx); + if (ldb == NULL) { + return NT_STATUS_NO_MEMORY; + } + + asprintf(&s, "%u", (unsigned int)expiry); + + if (s == NULL) { + ldb_close(ldb); + return NT_STATUS_NO_MEMORY; + } + + + ZERO_STRUCT(msg); + msg.dn = talloc_strdup(mem_ctx, computer_name); + if (msg.dn == NULL) { + ldb_close(ldb); + return NT_STATUS_NO_MEMORY; + } + + val.data = creds->session_key; + val.length = sizeof(creds->session_key); + + ldb_msg_add_value(ldb, &msg, "sessionKey", &val); + ldb_msg_add_string(ldb, &msg, "expiry", s); + + ret = ldb_add(ldb, &msg); + ldb_close(ldb); + + if (ret != 0) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + return NT_STATUS_OK; +} + + +/* + read back a session key for a computer +*/ +NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx, + const char *computer_name, uint8_t session_key[16]) +{ + struct ldb_context *ldb; + time_t expiry; + struct ldb_message **res; + int ret; + const struct ldb_val *val; + + 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); + if (ret != 1) { + ldb_close(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)); + ldb_close(ldb); + return NT_STATUS_INVALID_HANDLE; + } + + val = ldb_msg_find_ldb_val(res[0], "sessionKey"); + if (val == NULL || val->length != 16) { + ldb_close(ldb); + return NT_STATUS_INVALID_HANDLE; + } + + memcpy(session_key, val->data, 16); + + ldb_close(ldb); + + return NT_STATUS_OK; +} |