From f9e2a8af391f8ecb7cf6aa2d017898503d16985f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 1 Dec 2003 12:41:54 +0000 Subject: neater credentials handling in netlogon client code (This used to be commit b7d748f499f79415b444e7cebe7d8de7186fbc94) --- source4/libcli/auth/credentials.c | 191 +++++++------------------------------- source4/librpc/idl/netlogon.idl | 35 ++++--- source4/torture/rpc/netlogon.c | 40 ++++---- 3 files changed, 69 insertions(+), 197 deletions(-) (limited to 'source4') diff --git a/source4/libcli/auth/credentials.c b/source4/libcli/auth/credentials.c index 72572d8f91..06ca416592 100644 --- a/source4/libcli/auth/credentials.c +++ b/source4/libcli/auth/credentials.c @@ -22,32 +22,15 @@ #include "includes.h" -/**************************************************************************** -represent a credential as a string -****************************************************************************/ -char *credstr(const uchar *cred) -{ - static fstring buf; - slprintf(buf, sizeof(buf) - 1, "%02X%02X%02X%02X%02X%02X%02X%02X", - cred[0], cred[1], cred[2], cred[3], - cred[4], cred[5], cred[6], cred[7]); - return buf; -} - - -/**************************************************************************** - setup the session key. -Input: 8 byte challenge block - 8 byte server challenge block - 16 byte md4 encrypted password -Output: - 8 byte session key -****************************************************************************/ -void cred_session_key(const struct netr_Credential *client_challenge, - const struct netr_Credential *server_challenge, - const uint8 md4_pass[16], - uint8 session_key[8]) +/* + initialise the credentials state +*/ +void creds_init(struct netr_CredentialState *creds, + const struct netr_Credential *client_challenge, + const struct netr_Credential *server_challenge, + const uint8 machine_password[16]) { + struct netr_Credential time_cred; uint32 sum[2]; uint8 sum2[8]; @@ -57,154 +40,44 @@ void cred_session_key(const struct netr_Credential *client_challenge, SIVAL(sum2,0,sum[0]); SIVAL(sum2,4,sum[1]); - cred_hash1(session_key, sum2, md4_pass); -} - - -/**************************************************************************** -create a credential + cred_hash1(creds->session_key, sum2, machine_password); -Input: - 8 byte sesssion key - 8 byte stored credential - 4 byte timestamp - -Output: - 8 byte credential -****************************************************************************/ -void cred_create(uchar session_key[8], struct netr_Credential *stor_cred, time_t timestamp, - struct netr_Credential *cred) -{ - struct netr_Credential time_cred; + creds->sequence = 0; - SIVAL(time_cred.data, 0, IVAL(stor_cred->data, 0) + timestamp); - SIVAL(time_cred.data, 4, IVAL(stor_cred->data, 4)); + SIVAL(time_cred.data, 0, IVAL(client_challenge->data, 0) + creds->sequence); + SIVAL(time_cred.data, 4, IVAL(client_challenge->data, 4)); - cred_hash2(cred->data, time_cred.data, session_key); + cred_hash2(creds->client_cred.data, time_cred.data, creds->session_key); - /* debug output*/ - DEBUG(4,("cred_create\n")); - - DEBUG(5,(" sess_key : %s\n", credstr(session_key))); - DEBUG(5,(" stor_cred: %s\n", credstr(stor_cred->data))); - DEBUG(5,(" timestamp: %x\n", (unsigned)timestamp)); - DEBUG(5,(" timecred : %s\n", credstr(time_cred.data))); - DEBUG(5,(" calc_cred: %s\n", credstr(cred->data))); + creds->server_cred = *server_challenge; } - -/**************************************************************************** - 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 -****************************************************************************/ -int cred_assert(struct netr_Credential *cred, uchar session_key[8], - struct netr_Credential *stored_cred, - time_t timestamp) +/* + check that the credentials reply is correct then generate the next + set of credentials +*/ +BOOL creds_next(struct netr_CredentialState *creds, + const struct netr_Credential *next) { struct netr_Credential cred2; + struct netr_Credential time_cred; - cred_create(session_key, stored_cred, timestamp, &cred2); - - /* debug output*/ - DEBUG(4,("cred_assert\n")); - - DEBUG(5,(" challenge : %s\n", credstr(cred->data))); - DEBUG(5,(" calculated: %s\n", credstr(cred2.data))); - - 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; - } -} - - -/**************************************************************************** - checks credentials; generates next step in the credential chain -****************************************************************************/ -BOOL clnt_deal_with_creds(uchar sess_key[8], - struct netr_Authenticator *sto_clnt_cred, - struct netr_Authenticator *rcv_srv_cred) -{ - time_t new_clnt_time; - uint32 new_cred; - - /* increment client time by one second !?! */ - new_clnt_time = sto_clnt_cred->timestamp + 1; - - /* check that the received server credentials are valid */ - if (!cred_assert(&rcv_srv_cred->cred, sess_key, - &sto_clnt_cred->cred, new_clnt_time)) { - return False; - } - - /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */ - new_cred = IVAL(sto_clnt_cred->cred.data, 0); - new_cred += new_clnt_time; - - /* store new seed in client credentials */ - SIVAL(sto_clnt_cred->cred.data, 0, new_cred); - - return True; -} - - -/**************************************************************************** - checks credentials; generates next step in the credential chain -****************************************************************************/ -BOOL deal_with_creds(uchar sess_key[8], - struct netr_Authenticator *sto_clnt_cred, - struct netr_Authenticator *rcv_clnt_cred, - struct netr_Authenticator *rtn_srv_cred) -{ - time_t new_clnt_time; - uint32 new_cred; - - DEBUG(5,("deal_with_creds: %d\n", __LINE__)); - - /* check that the received client credentials are valid */ - if (!cred_assert(&rcv_clnt_cred->cred, sess_key, - &sto_clnt_cred->cred, rcv_clnt_cred->timestamp)) - { + SIVAL(time_cred.data, 0, IVAL(creds->server_cred.data, 0) + creds->sequence); + SIVAL(time_cred.data, 4, IVAL(creds->server_cred.data, 4)); + cred_hash2(cred2.data, time_cred.data, creds->session_key); + if (memcmp(next->data, cred2.data, 8) != 0) { + DEBUG(2,("credentials check failed\n")); return False; } - /* increment client time by one second */ - new_clnt_time = rcv_clnt_cred->timestamp + 1; - - /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */ - new_cred = IVAL(sto_clnt_cred->cred.data, 0); - new_cred += new_clnt_time; - - DEBUG(5,("deal_with_creds: new_cred[0]=%x\n", new_cred)); - - /* doesn't matter that server time is 0 */ - rtn_srv_cred->timestamp = 0; - - DEBUG(5,("deal_with_creds: new_clnt_time=%x\n", (unsigned)new_clnt_time)); + creds->server_cred = creds->client_cred; - /* create return credentials for inclusion in the reply */ - cred_create(sess_key, &sto_clnt_cred->cred, new_clnt_time, - &rtn_srv_cred->cred); - - DEBUG(5,("deal_with_creds: clnt_cred=%s\n", credstr(sto_clnt_cred->cred.data))); + SIVAL(time_cred.data, 0, IVAL(creds->client_cred.data, 0) + creds->sequence); + SIVAL(time_cred.data, 4, IVAL(creds->client_cred.data, 4)); - /* store new seed in client credentials */ - SIVAL(sto_clnt_cred->cred.data, 0, new_cred); + cred_hash2(cred2.data, time_cred.data, creds->session_key); + creds->client_cred = cred2; + creds->sequence++; return True; } diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl index f6749b4e57..38df1c48da 100644 --- a/source4/librpc/idl/netlogon.idl +++ b/source4/librpc/idl/netlogon.idl @@ -64,6 +64,17 @@ interface netlogon /*****************/ /* Function 0x02 */ + typedef [flag(NDR_PAHEX)] struct { + uint8 data[8]; + } netr_Credential; + + typedef [flag(NDR_PAHEX)] struct { + uint8 session_key[8]; + uint32 sequence; + netr_Credential client_cred; + netr_Credential server_cred; + } netr_CredentialState; + typedef struct { [value(strlen_m(r->string)*2)] uint16 size; [value(r->size)] uint16 length; @@ -89,19 +100,15 @@ interface netlogon netr_Password ntpassword; } netr_PasswordInfo; - typedef [flag(NDR_PAHEX)] struct { - uint8 data[8]; - } netr_Credential; - typedef [flag(NDR_PAHEX)] struct { uint16 length; [value(r->length)] uint16 size; [size_is(size),length_is(length)] uint8 *data; } netr_ChallengeResponse; - typedef struct { + typedef [flag(NDR_PAHEX)] struct { netr_IdentityInfo logon_info; - netr_Credential challenge; + uint8 challenge[8]; netr_ChallengeResponse nt; netr_ChallengeResponse lm; } netr_NetworkInfo; @@ -232,17 +239,17 @@ interface netlogon ); WERROR netr_ServerReqChallenge( - [in] unistr *server_name, - [in] unistr computer_name, - [in][out][ref] netr_Credential *credential + [in] unistr *server_name, + [in] unistr computer_name, + [in][out] netr_Credential credentials ); WERROR netr_ServerAuthenticate( - [in] unistr *server_name, - [in] unistr username, - [in] uint16 secure_challenge_type, - [in] unistr computer_name, - [in,out,ref] netr_Credential *client_challenge + [in] unistr *server_name, + [in] unistr username, + [in] uint16 secure_challenge_type, + [in] unistr computer_name, + [in,out] netr_Credential credentials ); #if 0 diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index 4ed62bc543..d0bffcc0e9 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -71,25 +71,20 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) struct netr_ServerReqChallenge r; struct netr_ServerAuthenticate a; struct netr_LogonSamLogon l; - struct netr_Credential client_chal, server_chal, cred2, cred3; - uint8 session_key[8]; const char *plain_pass; uint8 mach_pwd[16]; struct netr_Authenticator auth, auth2; struct netr_NetworkInfo ninfo; const char *username = lp_parm_string(-1, "torture", "username"); const char *password = lp_parm_string(-1, "torture", "password"); + struct netr_CredentialState creds; printf("Testing ServerReqChallenge\n"); - ZERO_STRUCT(client_chal); - - generate_random_buffer(client_chal.data, sizeof(client_chal.data), False); - r.in.server_name = NULL; r.in.computer_name = lp_netbios_name(); - r.in.credential = &client_chal; - r.out.credential = &server_chal; + r.in.credentials.low = 1; + r.in.credentials.high = 2; status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -104,16 +99,14 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) } E_md4hash(plain_pass, mach_pwd); - cred_session_key(&client_chal, &server_chal, mach_pwd, session_key); - cred_create(session_key, &client_chal, 0, &cred2); + creds_init(&creds, &r.in.credentials, &r.out.credentials, mach_pwd); a.in.server_name = NULL; a.in.username = talloc_asprintf(mem_ctx, "%s$", lp_netbios_name()); a.in.secure_challenge_type = 2; a.in.computer_name = lp_netbios_name(); - a.in.client_challenge = &cred2; - a.out.client_challenge = &cred3; + a.in.credentials = creds.client_cred; printf("Testing ServerAuthenticate\n"); @@ -123,17 +116,12 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) return False; } - - if (!cred_assert(&cred3, session_key, &server_chal, 0)) { - printf("cred_assert failed!\n"); + if (!creds_next(&creds, &a.out.credentials)) { + printf("Credential chaining failed\n"); } auth.timestamp = 0; - auth.cred = cred3; - auth2.timestamp = 0; - auth2.cred = server_chal; - - cred_create(session_key, &cred2, 0, &auth.cred); + auth.cred = creds.client_cred; ninfo.logon_info.domain_name.string = lp_workgroup(); ninfo.logon_info.parameter_control = 0; @@ -141,14 +129,14 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) ninfo.logon_info.logon_id_high = 0; ninfo.logon_info.username.string = username; ninfo.logon_info.workstation.string = lp_netbios_name(); - generate_random_buffer(ninfo.challenge.data, - sizeof(ninfo.challenge.data), False); + generate_random_buffer(ninfo.challenge, + sizeof(ninfo.challenge), False); ninfo.nt.length = 24; ninfo.nt.data = talloc(mem_ctx, 24); - SMBNTencrypt(password, ninfo.challenge.data, ninfo.nt.data); + SMBNTencrypt(password, ninfo.challenge, ninfo.nt.data); ninfo.lm.length = 24; ninfo.lm.data = talloc(mem_ctx, 24); - SMBencrypt(password, ninfo.challenge.data, ninfo.lm.data); + SMBencrypt(password, ninfo.challenge, ninfo.lm.data); ZERO_STRUCT(auth2); @@ -168,6 +156,10 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) return False; } + if (!creds_next(&creds, &l.out.authenticator->cred)) { + printf("Credential chaining failed\n"); + } + return True; } -- cgit