2009-08-25 23:16:27 +04:00
/*
Unix SMB / CIFS implementation .
module to store / fetch session keys for the schannel server
Copyright ( C ) Andrew Tridgell 2004
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2006 - 2009
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"
2010-02-19 00:17:06 +03:00
# include "system/filesys.h"
2012-06-19 07:13:10 +04:00
# include "../lib/tdb/include/tdb.h"
2010-02-19 00:17:06 +03:00
# include "../lib/util/util_tdb.h"
2011-10-12 15:55:34 +04:00
# include "../lib/param/param.h"
2010-09-11 14:53:21 +04:00
# include "../libcli/auth/schannel.h"
2009-08-25 23:16:27 +04:00
# include "../librpc/gen_ndr/ndr_schannel.h"
2013-04-11 11:42:12 +04:00
# include "lib/dbwrap/dbwrap.h"
2009-08-25 23:16:27 +04:00
2010-02-18 22:44:09 +03:00
# define SECRETS_SCHANNEL_STATE "SECRETS / SCHANNEL"
/******************************************************************************
2010-06-23 04:31:50 +04:00
Open or create the schannel session store tdb . Non - static so it can
be called from parent processes to corectly handle TDB_CLEAR_IF_FIRST
2010-02-18 22:44:09 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-11 11:42:12 +04:00
struct db_context * open_schannel_session_store ( TALLOC_CTX * mem_ctx ,
struct loadparm_context * lp_ctx )
2010-02-18 22:44:09 +03:00
{
2013-04-11 11:42:12 +04:00
struct db_context * db_sc = NULL ;
2013-04-11 11:42:13 +04:00
char * fname = lpcfg_private_db_path ( mem_ctx , lp_ctx , " schannel_store " ) ;
2018-04-17 17:20:02 +03:00
int hash_size , tdb_flags ;
2010-02-18 22:44:09 +03:00
if ( ! fname ) {
return NULL ;
}
2018-04-17 17:18:50 +03:00
hash_size = lpcfg_tdb_hash_size ( lp_ctx , fname ) ;
2018-04-17 17:20:02 +03:00
tdb_flags = lpcfg_tdb_flags ( lp_ctx , TDB_CLEAR_IF_FIRST | TDB_NOSYNC ) ;
2018-04-17 17:18:50 +03:00
db_sc = dbwrap_local_open (
mem_ctx ,
fname ,
hash_size ,
2018-04-17 17:20:02 +03:00
tdb_flags ,
2018-04-17 17:18:50 +03:00
O_RDWR | O_CREAT ,
0600 ,
DBWRAP_LOCK_ORDER_NONE ,
DBWRAP_FLAG_NONE ) ;
2010-02-18 22:44:09 +03:00
2013-04-11 11:42:12 +04:00
if ( ! db_sc ) {
2010-02-26 12:09:36 +03:00
DEBUG ( 0 , ( " open_schannel_session_store: Failed to open %s - %s \n " ,
fname , strerror ( errno ) ) ) ;
2010-02-18 22:44:09 +03:00
TALLOC_FREE ( fname ) ;
return NULL ;
}
TALLOC_FREE ( fname ) ;
2013-04-11 11:42:12 +04:00
return db_sc ;
2010-02-18 22:44:09 +03:00
}
2009-08-25 23:16:27 +04:00
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-02-18 22:44:09 +03:00
static
2013-04-11 11:42:12 +04:00
NTSTATUS schannel_store_session_key_tdb ( struct db_context * db_sc ,
2009-08-25 23:16:27 +04:00
TALLOC_CTX * mem_ctx ,
struct netlogon_creds_CredentialState * creds )
{
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
TDB_DATA value ;
char * keystr ;
2010-02-19 00:17:06 +03:00
char * name_upper ;
2013-04-11 11:42:12 +04:00
NTSTATUS status ;
2009-08-25 23:16:27 +04:00
2014-01-10 16:13:40 +04:00
if ( strlen ( creds - > computer_name ) > 15 ) {
/*
* We may want to check for a completely
* valid netbios name .
*/
return STATUS_BUFFER_OVERFLOW ;
}
2010-02-19 00:17:06 +03:00
name_upper = strupper_talloc ( mem_ctx , creds - > computer_name ) ;
if ( ! name_upper ) {
return NT_STATUS_NO_MEMORY ;
}
keystr = talloc_asprintf ( mem_ctx , " %s/%s " ,
SECRETS_SCHANNEL_STATE , name_upper ) ;
TALLOC_FREE ( name_upper ) ;
2009-08-25 23:16:27 +04:00
if ( ! keystr ) {
return NT_STATUS_NO_MEMORY ;
}
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & blob , mem_ctx , creds ,
2009-08-25 23:16:27 +04:00
( ndr_push_flags_fn_t ) ndr_push_netlogon_creds_CredentialState ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
talloc_free ( keystr ) ;
return ndr_map_error2ntstatus ( ndr_err ) ;
}
value . dptr = blob . data ;
value . dsize = blob . length ;
2013-04-11 11:42:12 +04:00
status = dbwrap_store_bystring ( db_sc , keystr , value , TDB_REPLACE ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-08-25 23:16:27 +04:00
DEBUG ( 0 , ( " Unable to add %s to session key db - %s \n " ,
2013-04-11 11:42:12 +04:00
keystr , nt_errstr ( status ) ) ) ;
2009-08-25 23:16:27 +04:00
talloc_free ( keystr ) ;
2013-04-11 11:42:12 +04:00
return status ;
2009-08-25 23:16:27 +04:00
}
DEBUG ( 3 , ( " schannel_store_session_key_tdb: stored schannel info with key %s \n " ,
keystr ) ) ;
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( netlogon_creds_CredentialState , creds ) ;
}
talloc_free ( keystr ) ;
return NT_STATUS_OK ;
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-02-18 22:44:09 +03:00
static
2013-04-11 11:42:12 +04:00
NTSTATUS schannel_fetch_session_key_tdb ( struct db_context * db_sc ,
2009-08-25 23:16:27 +04:00
TALLOC_CTX * mem_ctx ,
const char * computer_name ,
struct netlogon_creds_CredentialState * * pcreds )
{
NTSTATUS status ;
TDB_DATA value ;
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
struct netlogon_creds_CredentialState * creds = NULL ;
char * keystr = NULL ;
2010-02-19 00:17:06 +03:00
char * name_upper ;
2009-08-25 23:16:27 +04:00
* pcreds = NULL ;
2010-02-19 00:17:06 +03:00
name_upper = strupper_talloc ( mem_ctx , computer_name ) ;
if ( ! name_upper ) {
return NT_STATUS_NO_MEMORY ;
}
keystr = talloc_asprintf ( mem_ctx , " %s/%s " ,
SECRETS_SCHANNEL_STATE , name_upper ) ;
TALLOC_FREE ( name_upper ) ;
2009-08-25 23:16:27 +04:00
if ( ! keystr ) {
2010-04-12 00:56:09 +04:00
return NT_STATUS_NO_MEMORY ;
2009-08-25 23:16:27 +04:00
}
2013-04-11 11:42:12 +04:00
status = dbwrap_fetch_bystring ( db_sc , keystr , keystr , & value ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-09-04 01:01:38 +04:00
DEBUG ( 10 , ( " schannel_fetch_session_key_tdb: Failed to find entry with key %s \n " ,
2009-08-25 23:16:27 +04:00
keystr ) ) ;
goto done ;
}
creds = talloc_zero ( mem_ctx , struct netlogon_creds_CredentialState ) ;
if ( ! creds ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
blob = data_blob_const ( value . dptr , value . dsize ) ;
2010-05-09 19:20:01 +04:00
ndr_err = ndr_pull_struct_blob ( & blob , creds , creds ,
2009-08-25 23:16:27 +04:00
( ndr_pull_flags_fn_t ) ndr_pull_netlogon_creds_CredentialState ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
goto done ;
}
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( netlogon_creds_CredentialState , creds ) ;
}
DEBUG ( 3 , ( " schannel_fetch_session_key_tdb: restored schannel info key %s \n " ,
keystr ) ) ;
status = NT_STATUS_OK ;
done :
talloc_free ( keystr ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( creds ) ;
return status ;
}
* pcreds = creds ;
return NT_STATUS_OK ;
}
2010-02-18 22:44:09 +03:00
/******************************************************************************
Wrapper around schannel_fetch_session_key_tdb ( )
Note we must be root here .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS schannel_get_creds_state ( TALLOC_CTX * mem_ctx ,
2011-10-12 15:55:34 +04:00
struct loadparm_context * lp_ctx ,
2010-02-18 22:44:09 +03:00
const char * computer_name ,
2010-02-19 00:17:06 +03:00
struct netlogon_creds_CredentialState * * _creds )
2010-02-18 22:44:09 +03:00
{
2010-02-19 00:17:06 +03:00
TALLOC_CTX * tmpctx ;
2013-04-11 11:42:12 +04:00
struct db_context * db_sc ;
2010-02-19 00:17:06 +03:00
struct netlogon_creds_CredentialState * creds ;
2010-02-18 22:44:09 +03:00
NTSTATUS status ;
2010-02-19 00:17:06 +03:00
tmpctx = talloc_named ( mem_ctx , 0 , " schannel_get_creds_state " ) ;
if ( ! tmpctx ) {
return NT_STATUS_NO_MEMORY ;
2010-02-18 22:44:09 +03:00
}
2009-08-25 23:16:27 +04:00
2013-04-11 11:42:12 +04:00
db_sc = open_schannel_session_store ( tmpctx , lp_ctx ) ;
if ( ! db_sc ) {
2010-02-19 00:17:06 +03:00
return NT_STATUS_ACCESS_DENIED ;
}
2009-08-25 23:16:27 +04:00
2013-04-11 11:42:12 +04:00
status = schannel_fetch_session_key_tdb ( db_sc , tmpctx ,
2010-02-19 00:17:06 +03:00
computer_name , & creds ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
* _creds = talloc_steal ( mem_ctx , creds ) ;
if ( ! * _creds ) {
status = NT_STATUS_NO_MEMORY ;
}
}
2009-08-25 23:16:27 +04:00
2010-02-19 00:17:06 +03:00
talloc_free ( tmpctx ) ;
2010-02-18 22:44:09 +03:00
return status ;
}
/******************************************************************************
Wrapper around schannel_store_session_key_tdb ( )
Note we must be root here .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS schannel_save_creds_state ( TALLOC_CTX * mem_ctx ,
2011-10-12 15:55:34 +04:00
struct loadparm_context * lp_ctx ,
2010-02-18 22:44:09 +03:00
struct netlogon_creds_CredentialState * creds )
{
2010-02-19 00:17:06 +03:00
TALLOC_CTX * tmpctx ;
2013-04-11 11:42:12 +04:00
struct db_context * db_sc ;
2010-02-18 22:44:09 +03:00
NTSTATUS status ;
2010-02-19 00:17:06 +03:00
tmpctx = talloc_named ( mem_ctx , 0 , " schannel_save_creds_state " ) ;
if ( ! tmpctx ) {
return NT_STATUS_NO_MEMORY ;
2010-02-18 22:44:09 +03:00
}
2009-08-25 23:16:27 +04:00
2013-04-11 11:42:12 +04:00
db_sc = open_schannel_session_store ( tmpctx , lp_ctx ) ;
if ( ! db_sc ) {
2017-07-26 18:24:51 +03:00
status = NT_STATUS_ACCESS_DENIED ;
goto fail ;
2010-02-19 00:17:06 +03:00
}
2010-02-18 22:44:09 +03:00
2013-04-11 11:42:12 +04:00
status = schannel_store_session_key_tdb ( db_sc , tmpctx , creds ) ;
2010-02-18 22:44:09 +03:00
2017-07-26 18:24:51 +03:00
fail :
2010-02-19 00:17:06 +03:00
talloc_free ( tmpctx ) ;
2010-02-18 22:44:09 +03:00
return status ;
}
2016-11-09 05:17:00 +03:00
/*
* Create a very lossy hash of the computer name .
*
* The idea here is to compress the computer name into small space so
* that malicious clients cannot fill the database with junk , as only a
* maximum of 16 k of entries are possible .
*
* Collisions are certainly possible , and the design behaves in the
* same way as when the hostname is reused , but clients that use the
* same connection do not go via the cache , and the cache only needs
* to function between the ReqChallenge and ServerAuthenticate
* packets .
*/
static void hash_computer_name ( const char * computer_name ,
char keystr [ 16 ] )
{
unsigned int hash ;
TDB_DATA computer_tdb_data = {
. dptr = ( uint8_t * ) discard_const_p ( char , computer_name ) ,
. dsize = strlen ( computer_name )
} ;
hash = tdb_jenkins_hash ( & computer_tdb_data ) ;
/* we are using 14 bits of the digest to index our connections, so
that we use at most 16 , 384 buckets . */
snprintf ( keystr , 15 , " CHALLENGE/%x%x " , hash & 0xFF ,
( hash & 0xFF00 > > 8 ) & 0x3f ) ;
return ;
}
static
NTSTATUS schannel_store_challenge_tdb ( struct db_context * db_sc ,
TALLOC_CTX * mem_ctx ,
const struct netr_Credential * client_challenge ,
const struct netr_Credential * server_challenge ,
const char * computer_name )
{
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
TDB_DATA value ;
char * name_upper = NULL ;
NTSTATUS status ;
char keystr [ 16 ] = { 0 , } ;
struct netlogon_cache_entry cache_entry ;
if ( strlen ( computer_name ) > 255 ) {
/*
* We don ' t make this a limit at 15 chars as Samba has
* a test showing this can be longer : - (
*/
return STATUS_BUFFER_OVERFLOW ;
}
name_upper = strupper_talloc ( mem_ctx , computer_name ) ;
if ( name_upper = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
hash_computer_name ( name_upper , keystr ) ;
cache_entry . computer_name = name_upper ;
cache_entry . client_challenge = * client_challenge ;
cache_entry . server_challenge = * server_challenge ;
ndr_err = ndr_push_struct_blob ( & blob , mem_ctx , & cache_entry ,
( ndr_push_flags_fn_t ) ndr_push_netlogon_cache_entry ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return NT_STATUS_UNSUCCESSFUL ;
}
value . dptr = blob . data ;
value . dsize = blob . length ;
status = dbwrap_store_bystring ( db_sc , keystr , value , TDB_REPLACE ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " %s: failed to stored challenge info for '%s' "
" with key %s - %s \n " ,
__func__ , cache_entry . computer_name , keystr ,
nt_errstr ( status ) ) ) ;
return status ;
}
DEBUG ( 3 , ( " %s: stored challenge info for '%s' with key %s \n " ,
__func__ , cache_entry . computer_name , keystr ) ) ;
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( netlogon_cache_entry , & cache_entry ) ;
}
return NT_STATUS_OK ;
}
/********************************************************************
Fetch a single challenge from the TDB .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
NTSTATUS schannel_fetch_challenge_tdb ( struct db_context * db_sc ,
TALLOC_CTX * mem_ctx ,
struct netr_Credential * client_challenge ,
struct netr_Credential * server_challenge ,
const char * computer_name )
{
NTSTATUS status ;
TDB_DATA value ;
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
char keystr [ 16 ] = { 0 , } ;
struct netlogon_cache_entry cache_entry ;
char * name_upper = NULL ;
name_upper = strupper_talloc ( mem_ctx , computer_name ) ;
if ( name_upper = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
hash_computer_name ( name_upper , keystr ) ;
status = dbwrap_fetch_bystring ( db_sc , mem_ctx , keystr , & value ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 3 , ( " %s: Failed to find entry for %s with key %s - %s \n " ,
__func__ , name_upper , keystr , nt_errstr ( status ) ) ) ;
goto done ;
}
blob = data_blob_const ( value . dptr , value . dsize ) ;
ndr_err = ndr_pull_struct_blob_all ( & blob , mem_ctx , & cache_entry ,
( ndr_pull_flags_fn_t ) ndr_pull_netlogon_cache_entry ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
status = ndr_map_error2ntstatus ( ndr_err ) ;
DEBUG ( 3 , ( " %s: Failed to parse entry for %s with key %s - %s \n " ,
__func__ , name_upper , keystr , nt_errstr ( status ) ) ) ;
goto done ;
}
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( netlogon_cache_entry , & cache_entry ) ;
}
if ( strcmp ( cache_entry . computer_name , name_upper ) ! = 0 ) {
status = NT_STATUS_NOT_FOUND ;
DEBUG ( 1 , ( " %s: HASH COLLISION with key %s ! "
" Wanted to fetch record for %s but got %s. " ,
__func__ , keystr , name_upper ,
cache_entry . computer_name ) ) ;
} else {
DEBUG ( 3 , ( " %s: restored key %s for %s \n " ,
__func__ , keystr , cache_entry . computer_name ) ) ;
* client_challenge = cache_entry . client_challenge ;
* server_challenge = cache_entry . server_challenge ;
}
done :
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return NT_STATUS_OK ;
}
/******************************************************************************
2017-07-26 18:22:42 +03:00
Wrapper around schannel_fetch_challenge_tdb ( )
2016-11-09 05:17:00 +03:00
Note we must be root here .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS schannel_get_challenge ( struct loadparm_context * lp_ctx ,
struct netr_Credential * client_challenge ,
struct netr_Credential * server_challenge ,
const char * computer_name )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct db_context * db_sc ;
NTSTATUS status ;
db_sc = open_schannel_session_store ( frame , lp_ctx ) ;
if ( ! db_sc ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_ACCESS_DENIED ;
}
status = schannel_fetch_challenge_tdb ( db_sc , frame ,
client_challenge ,
server_challenge ,
computer_name ) ;
TALLOC_FREE ( frame ) ;
return status ;
}
/******************************************************************************
Wrapper around dbwrap_delete_bystring ( )
Note we must be root here .
This allows the challenge to be removed from the TDB , which should be
as soon as the TDB or in - memory copy it is used , to avoid reuse .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS schannel_delete_challenge ( struct loadparm_context * lp_ctx ,
const char * computer_name )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct db_context * db_sc ;
char * name_upper ;
char keystr [ 16 ] = { 0 , } ;
db_sc = open_schannel_session_store ( frame , lp_ctx ) ;
if ( ! db_sc ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_ACCESS_DENIED ;
}
name_upper = strupper_talloc ( frame , computer_name ) ;
if ( ! name_upper ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
hash_computer_name ( name_upper , keystr ) ;
/* Now delete it, we do not want to permit fetch of this twice */
dbwrap_delete_bystring ( db_sc , keystr ) ;
TALLOC_FREE ( frame ) ;
return NT_STATUS_OK ;
}
/******************************************************************************
Wrapper around schannel_store_session_key_tdb ( )
Note we must be root here .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS schannel_save_challenge ( struct loadparm_context * lp_ctx ,
const struct netr_Credential * client_challenge ,
const struct netr_Credential * server_challenge ,
const char * computer_name )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct db_context * db_sc ;
NTSTATUS status ;
db_sc = open_schannel_session_store ( frame , lp_ctx ) ;
if ( ! db_sc ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_ACCESS_DENIED ;
}
status = schannel_store_challenge_tdb ( db_sc , frame ,
client_challenge ,
server_challenge ,
computer_name ) ;
TALLOC_FREE ( frame ) ;
return status ;
}
2010-02-18 22:44:09 +03:00
/********************************************************************
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 .
2009-08-25 23:16:27 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-02-18 22:44:09 +03:00
NTSTATUS schannel_check_creds_state ( TALLOC_CTX * mem_ctx ,
2011-10-12 15:55:34 +04:00
struct loadparm_context * lp_ctx ,
2010-02-18 22:44:09 +03:00
const char * computer_name ,
struct netr_Authenticator * received_authenticator ,
struct netr_Authenticator * return_authenticator ,
struct netlogon_creds_CredentialState * * creds_out )
2009-08-25 23:16:27 +04:00
{
2010-02-18 22:44:09 +03:00
TALLOC_CTX * tmpctx ;
2013-04-11 11:42:12 +04:00
struct db_context * db_sc ;
2009-08-25 23:16:27 +04:00
struct netlogon_creds_CredentialState * creds ;
NTSTATUS status ;
2013-03-27 11:43:18 +04:00
char * name_upper = NULL ;
char * keystr = NULL ;
2013-04-11 11:42:12 +04:00
struct db_record * record ;
2013-03-27 11:43:18 +04:00
TDB_DATA key ;
if ( creds_out ! = NULL ) {
* creds_out = NULL ;
}
2009-08-25 23:16:27 +04:00
2010-02-18 22:44:09 +03:00
tmpctx = talloc_named ( mem_ctx , 0 , " schannel_check_creds_state " ) ;
if ( ! tmpctx ) {
return NT_STATUS_NO_MEMORY ;
}
2013-03-27 11:43:18 +04:00
name_upper = strupper_talloc ( tmpctx , computer_name ) ;
if ( ! name_upper ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
keystr = talloc_asprintf ( tmpctx , " %s/%s " ,
SECRETS_SCHANNEL_STATE , name_upper ) ;
if ( ! keystr ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
key = string_term_tdb_data ( keystr ) ;
2013-04-11 11:42:12 +04:00
db_sc = open_schannel_session_store ( tmpctx , lp_ctx ) ;
if ( ! db_sc ) {
2010-02-18 22:44:09 +03:00
status = NT_STATUS_ACCESS_DENIED ;
goto done ;
}
2013-04-11 11:42:12 +04:00
record = dbwrap_fetch_locked ( db_sc , tmpctx , key ) ;
if ( ! record ) {
2010-02-18 22:44:09 +03:00
status = NT_STATUS_INTERNAL_DB_CORRUPTION ;
goto done ;
2009-08-25 23:16:27 +04:00
}
/* Because this is a shared structure (even across
* disconnects ) we must update the database every time we
* update the structure */
2013-04-11 11:42:12 +04:00
status = schannel_fetch_session_key_tdb ( db_sc , tmpctx ,
2010-02-18 22:44:09 +03:00
computer_name , & creds ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2009-08-25 23:16:27 +04:00
2010-02-18 22:44:09 +03:00
status = netlogon_creds_server_step_check ( creds ,
received_authenticator ,
return_authenticator ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
2009-08-25 23:16:27 +04:00
}
2013-04-11 11:42:12 +04:00
status = schannel_store_session_key_tdb ( db_sc , tmpctx , creds ) ;
2010-02-18 22:44:09 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-12-14 21:21:26 +04:00
goto done ;
}
2010-02-18 22:44:09 +03:00
if ( creds_out ) {
* creds_out = talloc_steal ( mem_ctx , creds ) ;
if ( ! * creds_out ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
2009-08-25 23:16:27 +04:00
}
}
2010-02-18 22:44:09 +03:00
status = NT_STATUS_OK ;
done :
talloc_free ( tmpctx ) ;
2009-08-25 23:16:27 +04:00
return status ;
}
2010-02-18 22:44:09 +03:00