1997-10-09 10:01:12 +00:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
1997-10-09 10:01:12 +00:00
code to manipulate domain credentials
1998-01-22 13:27:43 +00:00
Copyright ( C ) Andrew Tridgell 1997 - 1998
2005-09-30 17:13:37 +00:00
Largely rewritten by Jeremy Allison 2005.
1997-10-09 10:01:12 +00:00
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 0213 9 , USA .
*/
# include "includes.h"
1997-11-02 04:01:57 +00:00
/****************************************************************************
2005-09-30 17:13:37 +00:00
Represent a credential as a string .
1997-11-02 04:01:57 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 17:13:37 +00:00
2002-03-02 04:41:55 +00:00
char * credstr ( const uchar * cred )
1997-11-02 04:01:57 +00:00
{
static fstring buf ;
1998-05-12 00:55:32 +00:00
slprintf ( buf , sizeof ( buf ) - 1 , " %02X%02X%02X%02X%02X%02X%02X%02X " ,
1997-11-02 04:01:57 +00:00
cred [ 0 ] , cred [ 1 ] , cred [ 2 ] , cred [ 3 ] ,
cred [ 4 ] , cred [ 5 ] , cred [ 6 ] , cred [ 7 ] ) ;
return buf ;
}
1997-10-09 10:01:12 +00:00
/****************************************************************************
2006-02-09 07:03:23 +00:00
Setup the session key and the client and server creds in dc .
Used by both client and server creds setup .
1997-10-09 10:01:12 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 17:13:37 +00:00
2006-02-09 07:03:23 +00:00
static void creds_init_64 ( struct dcinfo * dc ,
const DOM_CHAL * clnt_chal_in ,
2005-09-30 17:13:37 +00:00
const DOM_CHAL * srv_chal_in ,
2006-02-09 07:03:23 +00:00
const char mach_pw [ 16 ] )
1997-10-09 10:01:12 +00:00
{
uint32 sum [ 2 ] ;
1997-10-20 02:50:12 +00:00
unsigned char sum2 [ 8 ] ;
1997-10-09 10:01:12 +00:00
2006-02-09 07:03:23 +00:00
/* Just in case this isn't already there */
memcpy ( dc - > mach_pw , mach_pw , 16 ) ;
2005-09-30 17:13:37 +00:00
sum [ 0 ] = IVAL ( clnt_chal_in - > data , 0 ) + IVAL ( srv_chal_in - > data , 0 ) ;
sum [ 1 ] = IVAL ( clnt_chal_in - > data , 4 ) + IVAL ( srv_chal_in - > data , 4 ) ;
1997-10-09 10:01:12 +00:00
SIVAL ( sum2 , 0 , sum [ 0 ] ) ;
SIVAL ( sum2 , 4 , sum [ 1 ] ) ;
2006-02-09 07:03:23 +00:00
ZERO_STRUCT ( dc - > sess_key ) ;
1997-10-13 13:35:37 +00:00
2006-02-09 07:03:23 +00:00
des_crypt128 ( dc - > sess_key , sum2 , dc - > mach_pw ) ;
1997-10-13 13:35:37 +00:00
2006-02-09 07:03:23 +00:00
/* debug output */
DEBUG ( 5 , ( " creds_init_64 \n " ) ) ;
2005-09-30 17:13:37 +00:00
DEBUG ( 5 , ( " clnt_chal_in: %s \n " , credstr ( clnt_chal_in - > data ) ) ) ;
DEBUG ( 5 , ( " srv_chal_in : %s \n " , credstr ( srv_chal_in - > data ) ) ) ;
1997-11-02 04:01:57 +00:00
DEBUG ( 5 , ( " clnt+srv : %s \n " , credstr ( sum2 ) ) ) ;
2006-02-09 07:03:23 +00:00
DEBUG ( 5 , ( " sess_key_out : %s \n " , credstr ( dc - > sess_key ) ) ) ;
/* Generate the next client and server creds. */
des_crypt112 ( dc - > clnt_chal . data , /* output */
clnt_chal_in - > data , /* input */
dc - > sess_key , /* input */
1 ) ;
des_crypt112 ( dc - > srv_chal . data , /* output */
srv_chal_in - > data , /* input */
dc - > sess_key , /* input */
1 ) ;
/* Seed is the client chal. */
memcpy ( dc - > seed_chal . data , dc - > clnt_chal . data , 8 ) ;
1997-10-09 10:01:12 +00:00
}
/****************************************************************************
2005-09-30 17:13:37 +00:00
Utility function to step credential chain one forward .
Deliberately doesn ' t update the seed . See reseed comment below .
1997-10-09 10:01:12 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 17:13:37 +00:00
static void creds_step ( struct dcinfo * dc )
1997-10-09 10:01:12 +00:00
{
2005-09-30 17:13:37 +00:00
DOM_CHAL time_chal ;
1997-10-14 17:01:43 +00:00
2005-09-30 17:13:37 +00:00
DEBUG ( 5 , ( " \t sequence = 0x%x \n " , ( unsigned int ) dc - > sequence ) ) ;
1997-10-13 13:35:37 +00:00
2005-09-30 17:13:37 +00:00
DEBUG ( 5 , ( " \t seed: %s \n " , credstr ( dc - > seed_chal . data ) ) ) ;
1997-10-26 18:42:47 +00:00
2005-09-30 17:13:37 +00:00
SIVAL ( time_chal . data , 0 , IVAL ( dc - > seed_chal . data , 0 ) + dc - > sequence ) ;
SIVAL ( time_chal . data , 4 , IVAL ( dc - > seed_chal . data , 4 ) ) ;
DEBUG ( 5 , ( " \t seed+seq %s \n " , credstr ( time_chal . data ) ) ) ;
1997-10-13 13:35:37 +00:00
2006-02-09 07:03:23 +00:00
des_crypt112 ( dc - > clnt_chal . data , time_chal . data , dc - > sess_key , 1 ) ;
1997-10-09 10:01:12 +00:00
2005-09-30 17:13:37 +00:00
DEBUG ( 5 , ( " \t CLIENT %s \n " , credstr ( dc - > clnt_chal . data ) ) ) ;
1997-10-09 10:01:12 +00:00
2005-09-30 17:13:37 +00:00
SIVAL ( time_chal . data , 0 , IVAL ( dc - > seed_chal . data , 0 ) + dc - > sequence + 1 ) ;
SIVAL ( time_chal . data , 4 , IVAL ( dc - > seed_chal . data , 4 ) ) ;
DEBUG ( 5 , ( " \t seed+seq+1 %s \n " , credstr ( time_chal . data ) ) ) ;
1997-10-09 10:01:12 +00:00
2006-02-09 07:03:23 +00:00
des_crypt112 ( dc - > srv_chal . data , time_chal . data , dc - > sess_key , 1 ) ;
2005-09-30 17:13:37 +00:00
DEBUG ( 5 , ( " \t SERVER %s \n " , credstr ( dc - > srv_chal . data ) ) ) ;
}
1997-10-09 10:01:12 +00:00
2005-09-30 17:13:37 +00:00
/****************************************************************************
Create a server credential struct .
1997-10-09 10:01:12 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 17:13:37 +00:00
void creds_server_init ( struct dcinfo * dc ,
DOM_CHAL * clnt_chal ,
DOM_CHAL * srv_chal ,
const char mach_pw [ 16 ] ,
DOM_CHAL * init_chal_out )
1997-10-09 10:01:12 +00:00
{
2005-09-30 17:13:37 +00:00
DEBUG ( 10 , ( " creds_server_init: client chal : %s \n " , credstr ( clnt_chal - > data ) ) ) ;
DEBUG ( 10 , ( " creds_server_init: server chal : %s \n " , credstr ( srv_chal - > data ) ) ) ;
2005-10-18 03:24:00 +00:00
dump_data_pw ( " creds_server_init: machine pass " , ( const unsigned char * ) mach_pw , 16 ) ;
1997-10-09 10:01:12 +00:00
2006-02-09 07:03:23 +00:00
/* Generate the session key and the next client and server creds. */
creds_init_64 ( dc ,
clnt_chal ,
srv_chal ,
mach_pw ) ;
1997-10-13 13:35:37 +00:00
2005-09-30 17:13:37 +00:00
dump_data_pw ( " creds_server_init: session key " , dc - > sess_key , 16 ) ;
1997-10-13 13:35:37 +00:00
2005-09-30 17:13:37 +00:00
DEBUG ( 10 , ( " creds_server_init: clnt : %s \n " , credstr ( dc - > clnt_chal . data ) ) ) ;
DEBUG ( 10 , ( " creds_server_init: server : %s \n " , credstr ( dc - > srv_chal . data ) ) ) ;
DEBUG ( 10 , ( " creds_server_init: seed : %s \n " , credstr ( dc - > seed_chal . data ) ) ) ;
memcpy ( init_chal_out - > data , dc - > srv_chal . data , 8 ) ;
}
/****************************************************************************
Check a credential sent by the client .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL creds_server_check ( const struct dcinfo * dc , const DOM_CHAL * rcv_cli_chal_in )
{
if ( memcmp ( dc - > clnt_chal . data , rcv_cli_chal_in - > data , 8 ) ) {
DEBUG ( 5 , ( " creds_server_check: challenge : %s \n " , credstr ( rcv_cli_chal_in - > data ) ) ) ;
DEBUG ( 5 , ( " calculated: %s \n " , credstr ( dc - > clnt_chal . data ) ) ) ;
2006-01-25 23:00:07 +00:00
DEBUG ( 2 , ( " creds_server_check: credentials check failed. \n " ) ) ;
1997-10-17 16:46:56 +00:00
return False ;
}
2005-09-30 17:13:37 +00:00
DEBUG ( 10 , ( " creds_server_check: credentials check OK. \n " ) ) ;
return True ;
1997-10-09 10:01:12 +00:00
}
1997-10-25 10:58:18 +00:00
/****************************************************************************
2005-09-30 17:13:37 +00:00
Replace current seed chal . Internal function - due to split server step below .
1997-10-25 10:58:18 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 17:13:37 +00:00
static void creds_reseed ( struct dcinfo * dc )
1997-10-25 10:58:18 +00:00
{
2005-09-30 17:13:37 +00:00
DOM_CHAL time_chal ;
1997-10-25 10:58:18 +00:00
2005-09-30 17:13:37 +00:00
SIVAL ( time_chal . data , 0 , IVAL ( dc - > seed_chal . data , 0 ) + dc - > sequence + 1 ) ;
SIVAL ( time_chal . data , 4 , IVAL ( dc - > seed_chal . data , 4 ) ) ;
1997-10-26 18:42:47 +00:00
2005-09-30 17:13:37 +00:00
dc - > seed_chal = time_chal ;
1997-10-25 10:58:18 +00:00
2005-09-30 17:13:37 +00:00
DEBUG ( 5 , ( " cred_reseed: seed %s \n " , credstr ( dc - > seed_chal . data ) ) ) ;
}
1997-10-25 10:58:18 +00:00
2005-09-30 17:13:37 +00:00
/****************************************************************************
Step the server credential chain one forward .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-10-25 10:58:18 +00:00
2005-09-30 17:13:37 +00:00
BOOL creds_server_step ( struct dcinfo * dc , const DOM_CRED * received_cred , DOM_CRED * cred_out )
{
2006-02-15 23:15:55 +00:00
BOOL ret ;
struct dcinfo tmp_dc = * dc ;
1997-10-25 10:58:18 +00:00
2006-02-15 23:15:55 +00:00
/* Do all operations on a temporary copy of the dc,
which we throw away if the checks fail . */
tmp_dc . sequence = received_cred - > timestamp . time ;
creds_step ( & tmp_dc ) ;
2005-09-30 17:13:37 +00:00
/* Create the outgoing credentials */
2006-02-15 23:15:55 +00:00
cred_out - > timestamp . time = tmp_dc . sequence + 1 ;
cred_out - > challenge = tmp_dc . srv_chal ;
creds_reseed ( & tmp_dc ) ;
1997-10-25 10:58:18 +00:00
2006-02-15 23:15:55 +00:00
ret = creds_server_check ( & tmp_dc , & received_cred - > challenge ) ;
if ( ! ret ) {
return False ;
}
2005-09-30 17:13:37 +00:00
2006-02-15 23:15:55 +00:00
/* creds step succeeded - replace the current creds. */
* dc = tmp_dc ;
return True ;
2005-09-30 17:13:37 +00:00
}
1997-10-25 10:58:18 +00:00
/****************************************************************************
2005-09-30 17:13:37 +00:00
Create a client credential struct .
1997-10-25 10:58:18 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 17:13:37 +00:00
void creds_client_init ( struct dcinfo * dc ,
DOM_CHAL * clnt_chal ,
DOM_CHAL * srv_chal ,
2005-10-18 03:24:00 +00:00
const unsigned char mach_pw [ 16 ] ,
2005-09-30 17:13:37 +00:00
DOM_CHAL * init_chal_out )
1997-10-25 10:58:18 +00:00
{
2005-09-30 17:13:37 +00:00
dc - > sequence = time ( NULL ) ;
1997-10-25 10:58:18 +00:00
2005-09-30 17:13:37 +00:00
DEBUG ( 10 , ( " creds_client_init: client chal : %s \n " , credstr ( clnt_chal - > data ) ) ) ;
DEBUG ( 10 , ( " creds_client_init: server chal : %s \n " , credstr ( srv_chal - > data ) ) ) ;
2005-10-18 03:24:00 +00:00
dump_data_pw ( " creds_client_init: machine pass " , ( const unsigned char * ) mach_pw , 16 ) ;
1997-10-25 10:58:18 +00:00
2006-02-09 07:03:23 +00:00
/* Generate the session key and the next client and server creds. */
creds_init_64 ( dc ,
clnt_chal ,
srv_chal ,
mach_pw ) ;
1997-10-25 10:58:18 +00:00
2005-09-30 17:13:37 +00:00
dump_data_pw ( " creds_client_init: session key " , dc - > sess_key , 16 ) ;
1997-10-25 10:58:18 +00:00
2005-09-30 17:13:37 +00:00
DEBUG ( 10 , ( " creds_client_init: clnt : %s \n " , credstr ( dc - > clnt_chal . data ) ) ) ;
DEBUG ( 10 , ( " creds_client_init: server : %s \n " , credstr ( dc - > srv_chal . data ) ) ) ;
DEBUG ( 10 , ( " creds_client_init: seed : %s \n " , credstr ( dc - > seed_chal . data ) ) ) ;
1997-10-25 10:58:18 +00:00
2005-09-30 17:13:37 +00:00
memcpy ( init_chal_out - > data , dc - > clnt_chal . data , 8 ) ;
}
/****************************************************************************
Check a credential returned by the server .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-10-25 10:58:18 +00:00
2005-09-30 17:13:37 +00:00
BOOL creds_client_check ( const struct dcinfo * dc , const DOM_CHAL * rcv_srv_chal_in )
{
if ( memcmp ( dc - > srv_chal . data , rcv_srv_chal_in - > data , 8 ) ) {
DEBUG ( 5 , ( " creds_client_check: challenge : %s \n " , credstr ( rcv_srv_chal_in - > data ) ) ) ;
DEBUG ( 5 , ( " calculated: %s \n " , credstr ( dc - > srv_chal . data ) ) ) ;
DEBUG ( 0 , ( " creds_client_check: credentials check failed. \n " ) ) ;
return False ;
}
DEBUG ( 10 , ( " creds_client_check: credentials check OK. \n " ) ) ;
1997-10-25 10:58:18 +00:00
return True ;
}
2005-09-30 17:13:37 +00:00
/****************************************************************************
Step the client credentials to the next element in the chain , updating the
current client and server credentials and the seed
produce the next authenticator in the sequence ready to send to
the server
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void creds_client_step ( struct dcinfo * dc , DOM_CRED * next_cred_out )
{
dc - > sequence + = 2 ;
creds_step ( dc ) ;
creds_reseed ( dc ) ;
next_cred_out - > challenge = dc - > clnt_chal ;
next_cred_out - > timestamp . time = dc - > sequence ;
}