From 3b12c38ac09ad253cf56099c243659a3a362ea67 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 18 Feb 2010 14:44:09 -0500 Subject: [PATCH] s3:schannel streamline interface Make calling schannel much easier by removing the need to explicitly open the database. Let the abstraction do it instead. --- libcli/auth/schannel_state.h | 27 ++-- libcli/auth/schannel_state_tdb.c | 196 ++++++++++++++++++++++++----- source3/Makefile.in | 3 +- source3/include/proto.h | 9 -- source3/include/secrets.h | 2 - source3/passdb/secrets_schannel.c | 131 ------------------- source3/rpc_server/srv_netlog_nt.c | 22 ++-- source3/rpc_server/srv_pipe.c | 2 +- 8 files changed, 191 insertions(+), 201 deletions(-) delete mode 100644 source3/passdb/secrets_schannel.c diff --git a/libcli/auth/schannel_state.h b/libcli/auth/schannel_state.h index efa8d20b086..c1fa1245cf5 100644 --- a/libcli/auth/schannel_state.h +++ b/libcli/auth/schannel_state.h @@ -23,8 +23,20 @@ #ifndef _LIBCLI_AUTH_SCHANNEL_STATE_H__ #define _LIBCLI_AUTH_SCHANNEL_STATE_H__ +NTSTATUS schannel_get_creds_state(TALLOC_CTX *mem_ctx, + const char *computer_name, + struct netlogon_creds_CredentialState **creds); + +NTSTATUS schannel_save_creds_state(TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState *creds); + +NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx, + const char *computer_name, + struct netr_Authenticator *received_authenticator, + struct netr_Authenticator *return_authenticator, + struct netlogon_creds_CredentialState **creds_out); + struct ldb_context; -struct tdb_context; NTSTATUS schannel_store_session_key_ldb(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, @@ -39,17 +51,4 @@ NTSTATUS schannel_creds_server_step_check_ldb(struct ldb_context *ldb, struct netr_Authenticator *received_authenticator, struct netr_Authenticator *return_authenticator, struct netlogon_creds_CredentialState **creds_out); -NTSTATUS schannel_store_session_key_tdb(struct tdb_context *tdb, - TALLOC_CTX *mem_ctx, - struct netlogon_creds_CredentialState *creds); -NTSTATUS schannel_fetch_session_key_tdb(struct tdb_context *tdb, - TALLOC_CTX *mem_ctx, - const char *computer_name, - struct netlogon_creds_CredentialState **creds); -NTSTATUS schannel_creds_server_step_check_tdb(struct tdb_context *tdb, - TALLOC_CTX *mem_ctx, - const char *computer_name, - struct netr_Authenticator *received_authenticator, - struct netr_Authenticator *return_authenticator, - struct netlogon_creds_CredentialState **creds_out); #endif diff --git a/libcli/auth/schannel_state_tdb.c b/libcli/auth/schannel_state_tdb.c index 49c89085be2..434d7d7f8cf 100644 --- a/libcli/auth/schannel_state_tdb.c +++ b/libcli/auth/schannel_state_tdb.c @@ -26,9 +26,75 @@ #include "../libcli/auth/schannel_state.h" #include "../librpc/gen_ndr/ndr_schannel.h" +#define SECRETS_SCHANNEL_STATE "SECRETS/SCHANNEL" + +/****************************************************************************** + Open or create the schannel session store tdb. +*******************************************************************************/ + +#define SCHANNEL_STORE_VERSION_1 1 +#define SCHANNEL_STORE_VERSION_2 2 /* should not be used */ +#define SCHANNEL_STORE_VERSION_CURRENT SCHANNEL_STORE_VERSION_1 + +static TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx) +{ + TDB_DATA vers; + uint32 ver; + TDB_CONTEXT *tdb_sc = NULL; + char *fname = talloc_asprintf(mem_ctx, "%s/schannel_store.tdb", lp_private_dir()); + + if (!fname) { + return NULL; + } + + tdb_sc = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); + + if (!tdb_sc) { + DEBUG(0,("open_schannel_session_store: Failed to open %s\n", fname)); + TALLOC_FREE(fname); + return NULL; + } + + again: + vers = tdb_fetch_bystring(tdb_sc, "SCHANNEL_STORE_VERSION"); + if (vers.dptr == NULL) { + /* First opener, no version. */ + SIVAL(&ver,0,SCHANNEL_STORE_VERSION_CURRENT); + vers.dptr = (uint8 *)&ver; + vers.dsize = 4; + tdb_store_bystring(tdb_sc, "SCHANNEL_STORE_VERSION", vers, TDB_REPLACE); + vers.dptr = NULL; + } else if (vers.dsize == 4) { + ver = IVAL(vers.dptr,0); + if (ver == SCHANNEL_STORE_VERSION_2) { + DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n", + (int)ver, fname )); + tdb_wipe_all(tdb_sc); + goto again; + } + if (ver != SCHANNEL_STORE_VERSION_CURRENT) { + DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n", + (int)ver, fname )); + tdb_close(tdb_sc); + tdb_sc = NULL; + } + } else { + tdb_close(tdb_sc); + tdb_sc = NULL; + DEBUG(0,("open_schannel_session_store: wrong version number size %d in %s\n", + (int)vers.dsize, fname )); + } + + SAFE_FREE(vers.dptr); + TALLOC_FREE(fname); + + return tdb_sc; +} + /******************************************************************** ********************************************************************/ +static NTSTATUS schannel_store_session_key_tdb(struct tdb_context *tdb, TALLOC_CTX *mem_ctx, struct netlogon_creds_CredentialState *creds) @@ -79,6 +145,7 @@ NTSTATUS schannel_store_session_key_tdb(struct tdb_context *tdb, /******************************************************************** ********************************************************************/ +static NTSTATUS schannel_fetch_session_key_tdb(struct tdb_context *tdb, TALLOC_CTX *mem_ctx, const char *computer_name, @@ -147,61 +214,134 @@ NTSTATUS schannel_fetch_session_key_tdb(struct tdb_context *tdb, return NT_STATUS_OK; } -/******************************************************************** +/****************************************************************************** + Wrapper around schannel_fetch_session_key_tdb() + Note we must be root here. +*******************************************************************************/ + +NTSTATUS schannel_get_creds_state(TALLOC_CTX *mem_ctx, + const char *computer_name, + struct netlogon_creds_CredentialState **creds) +{ + struct tdb_context *tdb; + NTSTATUS status; + + tdb = open_schannel_session_store(mem_ctx); + if (!tdb) { + return NT_STATUS_ACCESS_DENIED; + } - Validate an incoming authenticator against the credentials for the remote - machine. + status = schannel_fetch_session_key_tdb(tdb, mem_ctx, + computer_name, creds); - The credentials are (re)read and from the schannel database, and - written back after the caclulations are performed. + tdb_close(tdb); - The creds_out parameter (if not NULL) returns the credentials, if - the caller needs some of that information. + return status; +} + +/****************************************************************************** + Wrapper around schannel_store_session_key_tdb() + Note we must be root here. +*******************************************************************************/ + +NTSTATUS schannel_save_creds_state(TALLOC_CTX *mem_ctx, + struct netlogon_creds_CredentialState *creds) +{ + struct tdb_context *tdb; + NTSTATUS status; + + tdb = open_schannel_session_store(mem_ctx); + if (!tdb) { + return NT_STATUS_ACCESS_DENIED; + } + status = schannel_store_session_key_tdb(tdb, mem_ctx, creds); + + tdb_close(tdb); + + return status; +} + +/******************************************************************** + Validate an incoming authenticator against the credentials for the + remote machine stored in the schannel database. + + The credentials are (re)read and from the schannel database, and + written back after the caclulations are performed. + + If the creds_out parameter is not NULL returns the credentials. ********************************************************************/ -NTSTATUS schannel_creds_server_step_check_tdb(struct tdb_context *tdb, - TALLOC_CTX *mem_ctx, - const char *computer_name, - struct netr_Authenticator *received_authenticator, - struct netr_Authenticator *return_authenticator, - struct netlogon_creds_CredentialState **creds_out) +NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx, + const char *computer_name, + struct netr_Authenticator *received_authenticator, + struct netr_Authenticator *return_authenticator, + struct netlogon_creds_CredentialState **creds_out) { + TALLOC_CTX *tmpctx; + struct tdb_context *tdb; struct netlogon_creds_CredentialState *creds; NTSTATUS status; int ret; + tmpctx = talloc_named(mem_ctx, 0, "schannel_check_creds_state"); + if (!tmpctx) { + return NT_STATUS_NO_MEMORY; + } + + tdb = open_schannel_session_store(tmpctx); + if (!tdb) { + status = NT_STATUS_ACCESS_DENIED; + goto done; + } + ret = tdb_transaction_start(tdb); if (ret != 0) { return NT_STATUS_INTERNAL_DB_CORRUPTION; + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto done; } /* Because this is a shared structure (even across * disconnects) we must update the database every time we * update the structure */ - status = schannel_fetch_session_key_tdb(tdb, mem_ctx, computer_name, - &creds); + status = schannel_fetch_session_key_tdb(tdb, tmpctx, + computer_name, &creds); + if (!NT_STATUS_IS_OK(status)) { + tdb_transaction_cancel(tdb); + goto done; + } - if (NT_STATUS_IS_OK(status)) { - status = netlogon_creds_server_step_check(creds, - received_authenticator, - return_authenticator); + status = netlogon_creds_server_step_check(creds, + received_authenticator, + return_authenticator); + if (!NT_STATUS_IS_OK(status)) { + tdb_transaction_cancel(tdb); + goto done; } - if (NT_STATUS_IS_OK(status)) { - status = schannel_store_session_key_tdb(tdb, mem_ctx, creds); + status = schannel_store_session_key_tdb(tdb, tmpctx, creds); + if (!NT_STATUS_IS_OK(status)) { + tdb_transaction_cancel(tdb); + goto done; } - if (NT_STATUS_IS_OK(status)) { - tdb_transaction_commit(tdb); - if (creds_out) { - *creds_out = creds; - talloc_steal(mem_ctx, creds); + tdb_transaction_commit(tdb); + + if (creds_out) { + *creds_out = talloc_steal(mem_ctx, creds); + if (!*creds_out) { + status = NT_STATUS_NO_MEMORY; + goto done; } - } else { - tdb_transaction_cancel(tdb); } + status = NT_STATUS_OK; + +done: + talloc_free(tmpctx); + if (tdb) tdb_close(tdb); return status; } + diff --git a/source3/Makefile.in b/source3/Makefile.in index e966023a1ab..6e40f8362f6 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -508,8 +508,7 @@ SCHANNEL_OBJ = ../libcli/auth/credentials.o \ ../libcli/auth/schannel_sign.o \ ../libcli/auth/schannel_state_tdb.o \ ../librpc/gen_ndr/ndr_schannel.o \ - ../librpc/ndr/ndr_schannel.o \ - passdb/secrets_schannel.o + ../librpc/ndr/ndr_schannel.o LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \ libsmb/clikrb5.o libsmb/clispnego.o \ diff --git a/source3/include/proto.h b/source3/include/proto.h index f8c3032ff13..be932a960db 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4746,15 +4746,6 @@ bool secrets_delete_generic(const char *owner, const char *key); bool secrets_store_local_schannel_key(uint8_t schannel_key[16]); bool secrets_fetch_local_schannel_key(uint8_t schannel_key[16]); -/* The following definitions come from passdb/secrets_schannel.c */ - -TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx); -NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx, - const char *computer_name, - struct netlogon_creds_CredentialState **pcreds); -NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx, - struct netlogon_creds_CredentialState *creds); - /* The following definitions come from passdb/util_builtin.c */ bool lookup_builtin_rid(TALLOC_CTX *mem_ctx, uint32 rid, const char **name); diff --git a/source3/include/secrets.h b/source3/include/secrets.h index f369379c701..d0848bdfa4a 100644 --- a/source3/include/secrets.h +++ b/source3/include/secrets.h @@ -87,6 +87,4 @@ struct afs_keyfile { #define SECRETS_AFS_KEYFILE "SECRETS/AFS_KEYFILE" -#define SECRETS_SCHANNEL_STATE "SECRETS/SCHANNEL" - #endif /* _SECRETS_H */ diff --git a/source3/passdb/secrets_schannel.c b/source3/passdb/secrets_schannel.c deleted file mode 100644 index f4da625fc60..00000000000 --- a/source3/passdb/secrets_schannel.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Copyright (C) Guenther Deschner 2009 - - 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 3 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, see . -*/ - -#include "includes.h" -#include "../libcli/auth/libcli_auth.h" -#include "../libcli/auth/schannel_state.h" - -/****************************************************************************** - Open or create the schannel session store tdb. -*******************************************************************************/ - -#define SCHANNEL_STORE_VERSION_1 1 -#define SCHANNEL_STORE_VERSION_2 2 /* should not be used */ -#define SCHANNEL_STORE_VERSION_CURRENT SCHANNEL_STORE_VERSION_1 - -TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx) -{ - TDB_DATA vers; - uint32 ver; - TDB_CONTEXT *tdb_sc = NULL; - char *fname = talloc_asprintf(mem_ctx, "%s/schannel_store.tdb", lp_private_dir()); - - if (!fname) { - return NULL; - } - - tdb_sc = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - - if (!tdb_sc) { - DEBUG(0,("open_schannel_session_store: Failed to open %s\n", fname)); - TALLOC_FREE(fname); - return NULL; - } - - again: - vers = tdb_fetch_bystring(tdb_sc, "SCHANNEL_STORE_VERSION"); - if (vers.dptr == NULL) { - /* First opener, no version. */ - SIVAL(&ver,0,SCHANNEL_STORE_VERSION_CURRENT); - vers.dptr = (uint8 *)&ver; - vers.dsize = 4; - tdb_store_bystring(tdb_sc, "SCHANNEL_STORE_VERSION", vers, TDB_REPLACE); - vers.dptr = NULL; - } else if (vers.dsize == 4) { - ver = IVAL(vers.dptr,0); - if (ver == SCHANNEL_STORE_VERSION_2) { - DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n", - (int)ver, fname )); - tdb_wipe_all(tdb_sc); - goto again; - } - if (ver != SCHANNEL_STORE_VERSION_CURRENT) { - DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n", - (int)ver, fname )); - tdb_close(tdb_sc); - tdb_sc = NULL; - } - } else { - tdb_close(tdb_sc); - tdb_sc = NULL; - DEBUG(0,("open_schannel_session_store: wrong version number size %d in %s\n", - (int)vers.dsize, fname )); - } - - SAFE_FREE(vers.dptr); - TALLOC_FREE(fname); - - return tdb_sc; -} - -/****************************************************************************** - Wrapper around schannel_fetch_session_key_tdb() - Note we must be root here. -*******************************************************************************/ - -NTSTATUS schannel_fetch_session_key(TALLOC_CTX *mem_ctx, - const char *computer_name, - struct netlogon_creds_CredentialState **pcreds) -{ - struct tdb_context *tdb; - NTSTATUS status; - - tdb = open_schannel_session_store(mem_ctx); - if (!tdb) { - return NT_STATUS_ACCESS_DENIED; - } - - status = schannel_fetch_session_key_tdb(tdb, mem_ctx, computer_name, pcreds); - - tdb_close(tdb); - - return status; -} - -/****************************************************************************** - Wrapper around schannel_store_session_key_tdb() - Note we must be root here. -*******************************************************************************/ - -NTSTATUS schannel_store_session_key(TALLOC_CTX *mem_ctx, - struct netlogon_creds_CredentialState *creds) -{ - struct tdb_context *tdb; - NTSTATUS status; - - tdb = open_schannel_session_store(mem_ctx); - if (!tdb) { - return NT_STATUS_ACCESS_DENIED; - } - - status = schannel_store_session_key_tdb(tdb, mem_ctx, creds); - - tdb_close(tdb); - - return status; -} diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 769936ca200..15f19b52074 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -724,7 +724,7 @@ NTSTATUS _netr_ServerAuthenticate3(pipes_struct *p, /* Store off the state so we can continue after client disconnect. */ become_root(); - status = schannel_store_session_key(p->mem_ctx, creds); + status = schannel_save_creds_state(p->mem_ctx, creds); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { @@ -806,7 +806,6 @@ static NTSTATUS netr_creds_server_step_check(pipes_struct *p, struct netlogon_creds_CredentialState **creds_out) { NTSTATUS status; - struct tdb_context *tdb; bool schannel_global_required = (lp_server_schannel() == true) ? true:false; if (schannel_global_required) { @@ -818,17 +817,11 @@ static NTSTATUS netr_creds_server_step_check(pipes_struct *p, } } - tdb = open_schannel_session_store(mem_ctx); - if (!tdb) { - return NT_STATUS_ACCESS_DENIED; - } - - status = schannel_creds_server_step_check_tdb(tdb, mem_ctx, - computer_name, - received_authenticator, - return_authenticator, - creds_out); - tdb_close(tdb); + status = schannel_check_creds_state(mem_ctx, + computer_name, + received_authenticator, + return_authenticator, + creds_out); return status; } @@ -1393,7 +1386,8 @@ NTSTATUS _netr_LogonSamLogonEx(pipes_struct *p, struct netlogon_creds_CredentialState *creds = NULL; become_root(); - status = schannel_fetch_session_key(p->mem_ctx, r->in.computer_name, &creds); + status = schannel_get_creds_state(p->mem_ctx, + r->in.computer_name, &creds); unbecome_root(); if (!NT_STATUS_IS_OK(status)) { return status; diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 23f947f95bf..5cde423dafc 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -1477,7 +1477,7 @@ static bool pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, */ become_root(); - status = schannel_fetch_session_key(p, + status = schannel_get_creds_state(p, neg.oem_netbios_computer.a, &creds); unbecome_root(); -- 2.34.1