2003-12-01 07:13:43 +03:00
/*
Unix SMB / CIFS implementation .
code to manipulate domain credentials
Copyright ( C ) Andrew Tridgell 1997 - 2003
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"
2003-12-01 15:41:54 +03:00
/*
2003-12-02 01:13:11 +03:00
initialise the credentials state and return the initial credentials
to be sent as part of a netr_ServerAuthenticate * ( ) call .
this call is made after the netr_ServerReqChallenge call
2003-12-01 15:41:54 +03:00
*/
void creds_init ( struct netr_CredentialState * creds ,
const struct netr_Credential * client_challenge ,
const struct netr_Credential * server_challenge ,
2003-12-02 01:13:11 +03:00
const uint8 machine_password [ 16 ] ,
struct netr_Credential * initial_creds )
2003-12-01 07:13:43 +03:00
{
2003-12-01 15:41:54 +03:00
struct netr_Credential time_cred ;
2003-12-01 07:13:43 +03:00
uint32 sum [ 2 ] ;
uint8 sum2 [ 8 ] ;
sum [ 0 ] = IVAL ( client_challenge - > data , 0 ) + IVAL ( server_challenge - > data , 0 ) ;
sum [ 1 ] = IVAL ( client_challenge - > data , 4 ) + IVAL ( server_challenge - > data , 4 ) ;
SIVAL ( sum2 , 0 , sum [ 0 ] ) ;
SIVAL ( sum2 , 4 , sum [ 1 ] ) ;
2003-12-01 15:41:54 +03:00
cred_hash1 ( creds - > session_key , sum2 , machine_password ) ;
2003-12-01 07:13:43 +03:00
2003-12-01 15:41:54 +03:00
creds - > sequence = 0 ;
2003-12-01 07:13:43 +03:00
2003-12-02 01:13:11 +03:00
SIVAL ( time_cred . data , 0 , IVAL ( client_challenge - > data , 0 ) ) ;
2003-12-01 15:41:54 +03:00
SIVAL ( time_cred . data , 4 , IVAL ( client_challenge - > data , 4 ) ) ;
2003-12-01 07:13:43 +03:00
2003-12-02 01:13:11 +03:00
cred_hash2 ( creds - > cred2 . data , time_cred . data , creds - > session_key ) ;
creds - > cred1 = * server_challenge ;
2003-12-01 07:13:43 +03:00
2003-12-02 01:13:11 +03:00
* initial_creds = creds - > cred2 ;
2003-12-01 07:13:43 +03:00
}
2003-12-02 01:13:11 +03:00
2003-12-01 15:41:54 +03:00
/*
2003-12-02 01:13:11 +03:00
check that a credentials reply is correct
2003-12-01 15:41:54 +03:00
*/
2003-12-02 01:13:11 +03:00
BOOL creds_check ( struct netr_CredentialState * creds ,
const struct netr_Credential * received_credentials )
2003-12-01 07:13:43 +03:00
{
2003-12-02 01:13:11 +03:00
struct netr_Credential cred2 , time_cred ;
uint32 sequence = creds - > sequence ? creds - > sequence + 1 : 0 ;
2003-12-01 07:13:43 +03:00
2003-12-02 01:13:11 +03:00
SIVAL ( time_cred . data , 0 , IVAL ( creds - > cred1 . data , 0 ) + sequence ) ;
SIVAL ( time_cred . data , 4 , IVAL ( creds - > cred1 . data , 4 ) ) ;
2003-12-01 15:41:54 +03:00
cred_hash2 ( cred2 . data , time_cred . data , creds - > session_key ) ;
2003-12-02 01:13:11 +03:00
if ( memcmp ( received_credentials - > data , cred2 . data , 8 ) ! = 0 ) {
2003-12-01 15:41:54 +03:00
DEBUG ( 2 , ( " credentials check failed \n " ) ) ;
2003-12-01 07:13:43 +03:00
return False ;
}
2003-12-02 01:13:11 +03:00
return True ;
}
2003-12-01 07:13:43 +03:00
2003-12-02 01:13:11 +03:00
/*
produce the next authenticator in the sequence ready to send to
the server
*/
void creds_authenticator ( struct netr_CredentialState * creds ,
struct netr_Authenticator * next )
{
struct netr_Credential cred2 ;
struct netr_Credential time_cred ;
if ( creds - > sequence = = 0 ) {
creds - > sequence = time ( NULL ) ;
}
/* this step size is quite arbitrary - the client can choose
any sequence number it likes */
creds - > sequence + = 2 ;
creds - > cred1 = creds - > cred2 ;
SIVAL ( time_cred . data , 0 , IVAL ( creds - > cred2 . data , 0 ) + creds - > sequence ) ;
SIVAL ( time_cred . data , 4 , IVAL ( creds - > cred2 . data , 4 ) ) ;
2003-12-01 07:13:43 +03:00
2003-12-01 15:41:54 +03:00
cred_hash2 ( cred2 . data , time_cred . data , creds - > session_key ) ;
2003-12-01 07:13:43 +03:00
2003-12-02 01:13:11 +03:00
creds - > cred2 = cred2 ;
next - > cred = creds - > cred2 ;
next - > timestamp = creds - > sequence ;
2003-12-01 07:13:43 +03:00
}
2003-12-02 03:31:54 +03:00
/*
encrypt a 16 byte password buffer using the session key
*/
void creds_encrypt ( struct netr_CredentialState * creds , struct netr_Password * pass )
{
struct netr_Password tmp ;
cred_hash3 ( tmp . data , pass - > data , creds - > session_key , 1 ) ;
* pass = tmp ;
}