1997-10-09 14:01:12 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
code to manipulate domain credentials
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1997 - 1998
1997-10-09 14:01:12 +04: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 07:01:57 +03:00
/****************************************************************************
represent a credential as a string
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char * credstr ( uchar * cred )
{
static fstring buf ;
1998-05-12 04:55:32 +04:00
slprintf ( buf , sizeof ( buf ) - 1 , " %02X%02X%02X%02X%02X%02X%02X%02X " ,
1997-11-02 07:01:57 +03:00
cred [ 0 ] , cred [ 1 ] , cred [ 2 ] , cred [ 3 ] ,
cred [ 4 ] , cred [ 5 ] , cred [ 6 ] , cred [ 7 ] ) ;
return buf ;
}
1997-10-09 14:01:12 +04:00
/****************************************************************************
setup the session key .
Input : 8 byte challenge block
8 byte server challenge block
16 byte md4 encrypted password
Output :
8 byte session key
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-10-10 18:48:05 +04:00
void cred_session_key ( DOM_CHAL * clnt_chal , DOM_CHAL * srv_chal , char * pass ,
1997-11-02 07:01:57 +03:00
uchar session_key [ 8 ] )
1997-10-09 14:01:12 +04:00
{
uint32 sum [ 2 ] ;
1997-10-20 06:50:12 +04:00
unsigned char sum2 [ 8 ] ;
1997-10-09 14:01:12 +04:00
1997-10-10 18:48:05 +04:00
sum [ 0 ] = IVAL ( clnt_chal - > data , 0 ) + IVAL ( srv_chal - > data , 0 ) ;
sum [ 1 ] = IVAL ( clnt_chal - > data , 4 ) + IVAL ( srv_chal - > data , 4 ) ;
1997-10-09 14:01:12 +04:00
SIVAL ( sum2 , 0 , sum [ 0 ] ) ;
SIVAL ( sum2 , 4 , sum [ 1 ] ) ;
1997-11-02 07:01:57 +03:00
cred_hash1 ( session_key , sum2 , ( unsigned char * ) pass ) ;
1997-10-13 17:35:37 +04:00
1997-10-14 21:01:43 +04:00
/* debug output */
DEBUG ( 4 , ( " cred_session_key \n " ) ) ;
1997-10-13 17:35:37 +04:00
1997-11-02 07:01:57 +03:00
DEBUG ( 5 , ( " clnt_chal: %s \n " , credstr ( clnt_chal - > data ) ) ) ;
DEBUG ( 5 , ( " srv_chal : %s \n " , credstr ( srv_chal - > data ) ) ) ;
DEBUG ( 5 , ( " clnt+srv : %s \n " , credstr ( sum2 ) ) ) ;
DEBUG ( 5 , ( " sess_key : %s \n " , credstr ( session_key ) ) ) ;
1997-10-09 14:01:12 +04:00
}
/****************************************************************************
create a credential
Input :
8 byte sesssion key
8 byte stored credential
4 byte timestamp
Output :
8 byte credential
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-11-02 07:01:57 +03:00
void cred_create ( uchar session_key [ 8 ] , DOM_CHAL * stor_cred , UTIME timestamp ,
1997-10-10 18:48:05 +04:00
DOM_CHAL * cred )
1997-10-09 14:01:12 +04:00
{
1997-10-26 21:42:47 +03:00
DOM_CHAL time_cred ;
1997-10-14 21:01:43 +04:00
1997-11-02 07:01:57 +03:00
SIVAL ( time_cred . data , 0 , IVAL ( stor_cred - > data , 0 ) + timestamp . time ) ;
SIVAL ( time_cred . data , 4 , IVAL ( stor_cred - > data , 4 ) ) ;
1997-10-13 17:35:37 +04:00
1997-11-02 07:01:57 +03:00
cred_hash2 ( cred - > data , time_cred . data , session_key ) ;
1997-10-26 21:42:47 +03:00
1997-10-13 17:35:37 +04:00
/* debug output*/
DEBUG ( 4 , ( " cred_create \n " ) ) ;
1997-11-02 07:01:57 +03:00
DEBUG ( 5 , ( " sess_key : %s \n " , credstr ( session_key ) ) ) ;
DEBUG ( 5 , ( " stor_cred: %s \n " , credstr ( stor_cred - > data ) ) ) ;
1998-08-14 21:38:29 +04:00
DEBUG ( 5 , ( " timestamp: %x \n " , timestamp . time ) ) ;
1997-11-02 07:01:57 +03:00
DEBUG ( 5 , ( " timecred : %s \n " , credstr ( time_cred . data ) ) ) ;
DEBUG ( 5 , ( " calc_cred: %s \n " , credstr ( cred - > data ) ) ) ;
1997-10-09 14:01:12 +04:00
}
/****************************************************************************
check a supplied credential
Input :
8 byte received credential
8 byte sesssion key
8 byte stored credential
4 byte timestamp
Output :
returns 1 if computed credential matches received credential
returns 0 otherwise
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-11-02 07:11:05 +03:00
int cred_assert ( DOM_CHAL * cred , uchar session_key [ 8 ] , DOM_CHAL * stored_cred ,
1997-10-10 18:48:05 +04:00
UTIME timestamp )
1997-10-09 14:01:12 +04:00
{
1997-10-10 18:48:05 +04:00
DOM_CHAL cred2 ;
1997-10-09 14:01:12 +04:00
1997-10-10 18:48:05 +04:00
cred_create ( session_key , stored_cred , timestamp , & cred2 ) ;
1997-10-09 14:01:12 +04:00
1997-10-13 17:35:37 +04:00
/* debug output*/
DEBUG ( 4 , ( " cred_assert \n " ) ) ;
1997-11-02 07:01:57 +03:00
DEBUG ( 5 , ( " challenge : %s \n " , credstr ( cred - > data ) ) ) ;
DEBUG ( 5 , ( " calculated: %s \n " , credstr ( cred2 . data ) ) ) ;
1997-10-13 17:35:37 +04:00
1997-10-17 20:46:56 +04:00
if ( memcmp ( cred - > data , cred2 . data , 8 ) = = 0 )
{
DEBUG ( 5 , ( " credentials check ok \n " ) ) ;
return True ;
}
else
{
DEBUG ( 5 , ( " credentials check wrong \n " ) ) ;
return False ;
}
1997-10-09 14:01:12 +04:00
}
1997-10-25 14:58:18 +04:00
/****************************************************************************
checks credentials ; generates next step in the credential chain
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-11-02 07:11:05 +03:00
BOOL clnt_deal_with_creds ( uchar sess_key [ 8 ] ,
1997-11-02 07:01:57 +03:00
DOM_CRED * sto_clnt_cred , DOM_CRED * rcv_srv_cred )
1997-10-25 14:58:18 +04:00
{
UTIME new_clnt_time ;
uint32 new_cred ;
1997-10-26 21:42:47 +03:00
DEBUG ( 5 , ( " clnt_deal_with_creds: %d \n " , __LINE__ ) ) ;
/* increment client time by one second */
new_clnt_time . time = sto_clnt_cred - > timestamp . time + 1 ;
1997-10-25 14:58:18 +04:00
1997-10-26 21:42:47 +03:00
/* check that the received server credentials are valid */
2001-09-25 01:53:34 +04:00
if ( ! cred_assert ( & rcv_srv_cred - > challenge , sess_key ,
& sto_clnt_cred - > challenge , new_clnt_time ) )
1997-10-25 14:58:18 +04:00
{
return False ;
}
/* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */
1997-10-26 21:42:47 +03:00
new_cred = IVAL ( sto_clnt_cred - > challenge . data , 0 ) ;
1997-10-25 14:58:18 +04:00
new_cred + = new_clnt_time . time ;
1997-10-26 21:42:47 +03:00
/* store new seed in client credentials */
SIVAL ( sto_clnt_cred - > challenge . data , 0 , new_cred ) ;
1997-10-25 14:58:18 +04:00
1997-11-02 07:01:57 +03:00
DEBUG ( 5 , ( " new clnt cred: %s \n " , credstr ( sto_clnt_cred - > challenge . data ) ) ) ;
1997-10-25 14:58:18 +04:00
return True ;
}
/****************************************************************************
checks credentials ; generates next step in the credential chain
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-11-02 07:01:57 +03:00
BOOL deal_with_creds ( uchar sess_key [ 8 ] ,
DOM_CRED * sto_clnt_cred ,
DOM_CRED * rcv_clnt_cred , DOM_CRED * rtn_srv_cred )
1997-10-25 14:58:18 +04:00
{
UTIME new_clnt_time ;
uint32 new_cred ;
DEBUG ( 5 , ( " deal_with_creds: %d \n " , __LINE__ ) ) ;
1997-10-26 21:42:47 +03:00
/* check that the received client credentials are valid */
2001-09-25 01:53:34 +04:00
if ( ! cred_assert ( & rcv_clnt_cred - > challenge , sess_key ,
& sto_clnt_cred - > challenge , rcv_clnt_cred - > timestamp ) )
1997-10-25 14:58:18 +04:00
{
return False ;
}
1997-10-26 21:42:47 +03:00
1997-10-25 14:58:18 +04:00
/* increment client time by one second */
1997-10-26 21:42:47 +03:00
new_clnt_time . time = rcv_clnt_cred - > timestamp . time + 1 ;
1997-10-25 14:58:18 +04:00
/* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */
1997-10-26 21:42:47 +03:00
new_cred = IVAL ( sto_clnt_cred - > challenge . data , 0 ) ;
1997-10-25 14:58:18 +04:00
new_cred + = new_clnt_time . time ;
1998-08-14 21:38:29 +04:00
DEBUG ( 5 , ( " deal_with_creds: new_cred[0]=%x \n " , new_cred ) ) ;
1997-10-25 14:58:18 +04:00
1997-10-26 21:42:47 +03:00
/* doesn't matter that server time is 0 */
rtn_srv_cred - > timestamp . time = 0 ;
1997-10-25 14:58:18 +04:00
1998-08-14 21:38:29 +04:00
DEBUG ( 5 , ( " deal_with_creds: new_clnt_time=%x \n " , new_clnt_time . time ) ) ;
1997-10-25 14:58:18 +04:00
1997-10-26 21:42:47 +03:00
/* create return credentials for inclusion in the reply */
2001-09-25 01:53:34 +04:00
cred_create ( sess_key , & sto_clnt_cred - > challenge , new_clnt_time ,
& rtn_srv_cred - > challenge ) ;
1997-10-26 21:42:47 +03:00
1997-11-02 07:01:57 +03:00
DEBUG ( 5 , ( " deal_with_creds: clnt_cred=%s \n " , credstr ( sto_clnt_cred - > challenge . data ) ) ) ;
1997-10-25 14:58:18 +04:00
1997-10-26 21:42:47 +03:00
/* store new seed in client credentials */
SIVAL ( sto_clnt_cred - > challenge . data , 0 , new_cred ) ;
1997-10-25 14:58:18 +04:00
return True ;
}