From ad8b47a2ba4e81420bc2272e8438a727cc2223ee Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 9 Feb 2006 07:03:23 +0000 Subject: [PATCH] r13407: Change the credentials code to be more like the Samba4 structure, makes fixes much easier to port. Fix the size of dc->sess_key to be 16 bytes, not 8 bytes - only store 8 bytes in the inter-smbd store in secrets.tdb though. Should fix some uses of the dc->sess_key where we where assuming we could read 16 bytes. Jeremy. (This used to be commit 5b3c2e63c73fee8949108abe19ac7a448a033a7f) --- source3/include/ntdomain.h | 2 +- source3/include/rpc_dce.h | 11 +++- source3/libsmb/credentials.c | 97 ++++++++++++------------------ source3/libsmb/smbdes.c | 36 +++++++++-- source3/passdb/secrets.c | 1 + source3/rpc_parse/parse_rpc.c | 1 - source3/rpc_server/srv_netlog_nt.c | 8 +-- 7 files changed, 84 insertions(+), 72 deletions(-) diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index a30b7243727..82e212c0ca0 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -140,7 +140,7 @@ struct dcinfo { DOM_CHAL clnt_chal; /* Client credential */ DOM_CHAL srv_chal; /* Server credential */ - uchar sess_key[8]; /* Session key */ + uchar sess_key[16]; /* Session key - 8 bytes followed by 8 zero bytes */ uchar mach_pw[16]; /* md4(machine password) */ fstring mach_acct; /* Machine name we've authenticated. */ diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index e718d92271c..218cad336de 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -90,12 +90,19 @@ enum RPC_PKT_TYPE { #define RPC_AUTH_SCHANNEL_SIGN_ONLY_CHK_LEN 0x18 +#define NETLOGON_EXTRA_SIDS 0x0020 +#define NETLOGON_RESOURCE_GROUPS 0x0200 +#define NETLOGON_NEG_ARCFOUR 0x00000004 +#define NETLOGON_NEG_128BIT 0x00004000 +#define NETLOGON_NEG_SCHANNEL 0x40000000 + /* The 7 here seems to be required to get Win2k not to downgrade us to NT4. Actually, anything other than 1ff would seem to do... */ #define NETLOGON_NEG_AUTH2_FLAGS 0x000701ff - -#define NETLOGON_NEG_SCHANNEL 0x40000000 #define NETLOGON_NEG_DOMAIN_TRUST_ACCOUNT 0x2010b000 + +/* these are the flags that ADS clients use */ +#define NETLOGON_NEG_AUTH2_ADS_FLAGS (0x200fbffb | NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT | NETLOGON_NEG_SCHANNEL) enum schannel_direction { SENDER_IS_INITIATOR, diff --git a/source3/libsmb/credentials.c b/source3/libsmb/credentials.c index ad06cd9015f..795c30d12d6 100644 --- a/source3/libsmb/credentials.c +++ b/source3/libsmb/credentials.c @@ -36,38 +36,52 @@ char *credstr(const uchar *cred) /**************************************************************************** - Setup the session key. - Input: 8 byte challenge block - 8 byte server challenge block - 16 byte md4 encrypted password - Output: - 16 byte session key (last 8 bytes zero). + Setup the session key and the client and server creds in dc. + Used by both client and server creds setup. ****************************************************************************/ -static void cred_create_session_key(const DOM_CHAL *clnt_chal_in, +static void creds_init_64(struct dcinfo *dc, + const DOM_CHAL *clnt_chal_in, const DOM_CHAL *srv_chal_in, - const uchar *pass_in, - uchar session_key_out[16]) + const char mach_pw[16]) { uint32 sum[2]; unsigned char sum2[8]; + /* Just in case this isn't already there */ + memcpy(dc->mach_pw, mach_pw, 16); + 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); SIVAL(sum2,0,sum[0]); SIVAL(sum2,4,sum[1]); - cred_hash1(session_key_out, sum2, pass_in); - memset(&session_key_out[8], '\0', 8); + ZERO_STRUCT(dc->sess_key); + + des_crypt128(dc->sess_key, sum2, dc->mach_pw); /* debug output */ - DEBUG(4,("cred_create_session_key\n")); - + DEBUG(5,("creds_init_64\n")); DEBUG(5,(" clnt_chal_in: %s\n", credstr(clnt_chal_in->data))); DEBUG(5,(" srv_chal_in : %s\n", credstr(srv_chal_in->data))); DEBUG(5,(" clnt+srv : %s\n", credstr(sum2))); - DEBUG(5,(" sess_key_out : %s\n", credstr(session_key_out))); + 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); } /**************************************************************************** @@ -88,7 +102,7 @@ static void creds_step(struct dcinfo *dc) DEBUG(5,("\tseed+seq %s\n", credstr(time_chal.data) )); - cred_hash2(dc->clnt_chal.data, time_chal.data, dc->sess_key); + des_crypt112(dc->clnt_chal.data, time_chal.data, dc->sess_key, 1); DEBUG(5,("\tCLIENT %s\n", credstr(dc->clnt_chal.data) )); @@ -97,12 +111,11 @@ static void creds_step(struct dcinfo *dc) DEBUG(5,("\tseed+seq+1 %s\n", credstr(time_chal.data) )); - cred_hash2(dc->srv_chal.data, time_chal.data, dc->sess_key); + des_crypt112(dc->srv_chal.data, time_chal.data, dc->sess_key, 1); DEBUG(5,("\tSERVER %s\n", credstr(dc->srv_chal.data) )); } - /**************************************************************************** Create a server credential struct. ****************************************************************************/ @@ -117,29 +130,14 @@ void creds_server_init(struct dcinfo *dc, DEBUG(10,("creds_server_init: server chal : %s\n", credstr(srv_chal->data) )); dump_data_pw("creds_server_init: machine pass", (const unsigned char *)mach_pw, 16); - /* Just in case this isn't already there */ - memcpy(dc->mach_pw, mach_pw, 16); - - /* Generate the session key. */ - cred_create_session_key(clnt_chal, /* Stored client challenge. */ - srv_chal, /* Stored server challenge. */ - dc->mach_pw, /* input machine password. */ - dc->sess_key); /* output session key. */ + /* Generate the session key and the next client and server creds. */ + creds_init_64(dc, + clnt_chal, + srv_chal, + mach_pw); dump_data_pw("creds_server_init: session key", dc->sess_key, 16); - /* Generate the next client and server creds. */ - cred_hash2(dc->clnt_chal.data, /* output */ - clnt_chal->data, /* input */ - dc->sess_key); /* input */ - - cred_hash2(dc->srv_chal.data, /* output */ - srv_chal->data, /* input */ - dc->sess_key); /* input */ - - /* Seed is the client chal. */ - memcpy(dc->seed_chal.data, dc->clnt_chal.data, 8); - 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) )); @@ -214,29 +212,14 @@ void creds_client_init(struct dcinfo *dc, DEBUG(10,("creds_client_init: server chal : %s\n", credstr(srv_chal->data) )); dump_data_pw("creds_client_init: machine pass", (const unsigned char *)mach_pw, 16); - /* Just in case this isn't already there */ - memcpy(dc->mach_pw, mach_pw, 16); - - /* Generate the session key. */ - cred_create_session_key(clnt_chal, /* Stored client challenge. */ - srv_chal, /* Stored server challenge. */ - dc->mach_pw, /* input machine password. */ - dc->sess_key); /* output session key. */ + /* Generate the session key and the next client and server creds. */ + creds_init_64(dc, + clnt_chal, + srv_chal, + mach_pw); dump_data_pw("creds_client_init: session key", dc->sess_key, 16); - /* Generate the next client and server creds. */ - cred_hash2(dc->clnt_chal.data, /* output */ - clnt_chal->data, /* input */ - dc->sess_key); /* input */ - - cred_hash2(dc->srv_chal.data, /* output */ - srv_chal->data, /* input */ - dc->sess_key); /* input */ - - /* Seed is the client cred. */ - memcpy(dc->seed_chal.data, dc->clnt_chal.data, 8); - 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) )); diff --git a/source3/libsmb/smbdes.c b/source3/libsmb/smbdes.c index 4378385f3fd..ee43f4beee5 100644 --- a/source3/libsmb/smbdes.c +++ b/source3/libsmb/smbdes.c @@ -258,7 +258,8 @@ static void dohash(char *out, char *in, char *key, int forw) permute(out, rl, perm6, 64); } -static void str_to_key(const unsigned char *str,unsigned char *key) +/* Convert a 7 byte string to an 8 byte key. */ +static void str_to_key(const unsigned char str[7], unsigned char key[8]) { int i; @@ -330,7 +331,8 @@ void E_old_pw_hash( unsigned char *p14, const unsigned char *in, unsigned char * des_crypt56(out+8, in+8, p14+7, 1); } -void cred_hash1(unsigned char *out, const unsigned char *in, const unsigned char *key) +/* forward des encryption with a 128 bit key */ +void des_crypt128(unsigned char out[8], const unsigned char in[8], const unsigned char key[16]) { unsigned char buf[8]; @@ -338,25 +340,49 @@ void cred_hash1(unsigned char *out, const unsigned char *in, const unsigned char des_crypt56(out, buf, key+9, 1); } -void cred_hash2(unsigned char *out, const unsigned char *in, const unsigned char *key) +/* forward des encryption with a 64 bit key */ +void des_crypt64(unsigned char out[8], const unsigned char in[8], const unsigned char key[8]) { unsigned char buf[8]; - static unsigned char key2[8]; + unsigned char key2[8]; + memset(key2,'\0',8); des_crypt56(buf, in, key, 1); key2[0] = key[7]; des_crypt56(out, buf, key2, 1); } +/* des encryption with a 112 bit (14 byte) key */ +/* Note that if the forw is 1, and key is actually 8 bytes of key, followed by 6 bytes of zeros, + this is identical to des_crypt64(). JRA. */ + +void des_crypt112(unsigned char out[8], const unsigned char in[8], const unsigned char key[14], int forw) +{ + unsigned char buf[8]; + des_crypt56(buf, in, key, forw); + des_crypt56(out, buf, key+7, forw); +} + void cred_hash3(unsigned char *out, const unsigned char *in, const unsigned char *key, int forw) { - static unsigned char key2[8]; + unsigned char key2[8]; + memset(key2,'\0',8); des_crypt56(out, in, key, forw); key2[0] = key[7]; des_crypt56(out + 8, in + 8, key2, forw); } +/* des encryption of a 16 byte lump of data with a 112 bit key */ +/* Note that if the key is actually 8 bytes of key, followed by 6 bytes of zeros, + this is identical to cred_hash3(). JRA. */ + +void des_crypt112_16(unsigned char out[16], unsigned char in[16], const unsigned char key[14], int forw) +{ + des_crypt56(out, in, key, forw); + des_crypt56(out + 8, in + 8, key+7, forw); +} + /***************************************************************** arc4 crypt/decrypt with a 16 byte key. *****************************************************************/ diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 69bafc7ce57..8f93bec9bc7 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -1063,6 +1063,7 @@ BOOL secrets_restore_schannel_session_info(TALLOC_CTX *mem_ctx, memcpy(pdc->clnt_chal.data, pclnt_chal, 8); memcpy(pdc->srv_chal.data, psrv_chal, 8); memcpy(pdc->sess_key, psess_key, 8); + memset(&pdc->sess_key[8], '\0', 8); /* key followed by 8 bytes of zero. */ memcpy(pdc->mach_pw, pmach_pw, 16); /* We know these are true so didn't bother to store them. */ diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index 544d139acb3..79dfc05e43c 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/rpc_parse/parse_rpc.c @@ -848,4 +848,3 @@ BOOL smb_io_rpc_auth_schannel_chk(const char *desc, int auth_len, return True; } - diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index d6ec31a9857..784f7336172 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -817,7 +817,6 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * fstring group_sid_string; uchar user_session_key[16]; uchar lm_session_key[16]; - uchar netlogon_sess_key[16]; sampw = server_info->sam_account; @@ -859,23 +858,20 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * return status; } - ZERO_STRUCT(netlogon_sess_key); - memcpy(netlogon_sess_key, p->dc->sess_key, 8); if (server_info->user_session_key.length) { memcpy(user_session_key, server_info->user_session_key.data, MIN(sizeof(user_session_key), server_info->user_session_key.length)); - SamOEMhash(user_session_key, netlogon_sess_key, 16); + SamOEMhash(user_session_key, p->dc->sess_key, 16); } if (server_info->lm_session_key.length) { memcpy(lm_session_key, server_info->lm_session_key.data, MIN(sizeof(lm_session_key), server_info->lm_session_key.length)); - SamOEMhash(lm_session_key, netlogon_sess_key, 16); + SamOEMhash(lm_session_key, p->dc->sess_key, 16); } - ZERO_STRUCT(netlogon_sess_key); init_net_user_info3(p->mem_ctx, usr_info, user_rid,