mirror of
https://github.com/samba-team/samba.git
synced 2025-01-22 22:04:08 +03:00
s3:schannel streamline interface
Make calling schannel much easier by removing the need to explicitly open the database. Let the abstraction do it instead.
This commit is contained in:
parent
e5ab64a799
commit
3b12c38ac0
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
status = schannel_fetch_session_key_tdb(tdb, mem_ctx,
|
||||
computer_name, creds);
|
||||
|
||||
tdb_close(tdb);
|
||||
|
||||
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.
|
||||
|
||||
Validate an incoming authenticator against the credentials for the remote
|
||||
machine.
|
||||
|
||||
The credentials are (re)read and from the schannel database, and
|
||||
written back after the caclulations are performed.
|
||||
|
||||
The creds_out parameter (if not NULL) returns the credentials, if
|
||||
the caller needs some of that information.
|
||||
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);
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
status = netlogon_creds_server_step_check(creds,
|
||||
received_authenticator,
|
||||
return_authenticator);
|
||||
}
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
status = schannel_store_session_key_tdb(tdb, mem_ctx, creds);
|
||||
}
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
tdb_transaction_commit(tdb);
|
||||
if (creds_out) {
|
||||
*creds_out = creds;
|
||||
talloc_steal(mem_ctx, creds);
|
||||
}
|
||||
} else {
|
||||
status = schannel_fetch_session_key_tdb(tdb, tmpctx,
|
||||
computer_name, &creds);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
tdb_transaction_cancel(tdb);
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = netlogon_creds_server_step_check(creds,
|
||||
received_authenticator,
|
||||
return_authenticator);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
tdb_transaction_cancel(tdb);
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = schannel_store_session_key_tdb(tdb, tmpctx, creds);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
tdb_transaction_cancel(tdb);
|
||||
goto done;
|
||||
}
|
||||
|
||||
tdb_transaction_commit(tdb);
|
||||
|
||||
if (creds_out) {
|
||||
*creds_out = talloc_steal(mem_ctx, creds);
|
||||
if (!*creds_out) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
status = NT_STATUS_OK;
|
||||
|
||||
done:
|
||||
talloc_free(tmpctx);
|
||||
if (tdb) tdb_close(tdb);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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);
|
||||
|
@ -87,6 +87,4 @@ struct afs_keyfile {
|
||||
|
||||
#define SECRETS_AFS_KEYFILE "SECRETS/AFS_KEYFILE"
|
||||
|
||||
#define SECRETS_SCHANNEL_STATE "SECRETS/SCHANNEL"
|
||||
|
||||
#endif /* _SECRETS_H */
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
@ -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;
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user