diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/libcli/auth/credentials.c | 68 | ||||
-rw-r--r-- | source4/libcli/util/smbdes.c | 82 | ||||
-rw-r--r-- | source4/librpc/idl/netlogon.idl | 10 | ||||
-rw-r--r-- | source4/torture/rpc/netlogon.c | 18 |
4 files changed, 102 insertions, 76 deletions
diff --git a/source4/libcli/auth/credentials.c b/source4/libcli/auth/credentials.c index 06ca416592..80ea2e9583 100644 --- a/source4/libcli/auth/credentials.c +++ b/source4/libcli/auth/credentials.c @@ -23,12 +23,16 @@ #include "includes.h" /* - initialise the credentials state + 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 */ void creds_init(struct netr_CredentialState *creds, const struct netr_Credential *client_challenge, const struct netr_Credential *server_challenge, - const uint8 machine_password[16]) + const uint8 machine_password[16], + struct netr_Credential *initial_creds) { struct netr_Credential time_cred; uint32 sum[2]; @@ -44,40 +48,64 @@ void creds_init(struct netr_CredentialState *creds, creds->sequence = 0; - SIVAL(time_cred.data, 0, IVAL(client_challenge->data, 0) + creds->sequence); + SIVAL(time_cred.data, 0, IVAL(client_challenge->data, 0)); SIVAL(time_cred.data, 4, IVAL(client_challenge->data, 4)); - cred_hash2(creds->client_cred.data, time_cred.data, creds->session_key); + cred_hash2(creds->cred2.data, time_cred.data, creds->session_key); + + creds->cred1 = *server_challenge; - creds->server_cred = *server_challenge; + *initial_creds = creds->cred2; } + /* - check that the credentials reply is correct then generate the next - set of credentials + check that a credentials reply is correct */ -BOOL creds_next(struct netr_CredentialState *creds, - const struct netr_Credential *next) +BOOL creds_check(struct netr_CredentialState *creds, + const struct netr_Credential *received_credentials) { - struct netr_Credential cred2; - struct netr_Credential time_cred; + struct netr_Credential cred2, time_cred; + uint32 sequence = creds->sequence?creds->sequence+1:0; - SIVAL(time_cred.data, 0, IVAL(creds->server_cred.data, 0) + creds->sequence); - SIVAL(time_cred.data, 4, IVAL(creds->server_cred.data, 4)); + SIVAL(time_cred.data, 0, IVAL(creds->cred1.data, 0) + sequence); + SIVAL(time_cred.data, 4, IVAL(creds->cred1.data, 4)); cred_hash2(cred2.data, time_cred.data, creds->session_key); - if (memcmp(next->data, cred2.data, 8) != 0) { + if (memcmp(received_credentials->data, cred2.data, 8) != 0) { DEBUG(2,("credentials check failed\n")); return False; } - creds->server_cred = creds->client_cred; + return True; +} - SIVAL(time_cred.data, 0, IVAL(creds->client_cred.data, 0) + creds->sequence); - SIVAL(time_cred.data, 4, IVAL(creds->client_cred.data, 4)); +/* + 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)); cred_hash2(cred2.data, time_cred.data, creds->session_key); - creds->client_cred = cred2; - creds->sequence++; - return True; + creds->cred2 = cred2; + + next->cred = creds->cred2; + next->timestamp = creds->sequence; } diff --git a/source4/libcli/util/smbdes.c b/source4/libcli/util/smbdes.c index cde77f94a3..e5c4c6f3f1 100644 --- a/source4/libcli/util/smbdes.c +++ b/source4/libcli/util/smbdes.c @@ -306,7 +306,7 @@ static void smbhash(unsigned char *out, const unsigned char *in, const unsigned void E_P16(const unsigned char *p14,unsigned char *p16) { - unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; + unsigned const char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; smbhash(p16, sp8, p14, 1); smbhash(p16+8, sp8, p14+7, 1); } @@ -341,8 +341,8 @@ void cred_hash1(unsigned char *out, const unsigned char *in, const unsigned char void cred_hash2(unsigned char *out, const unsigned char *in, const unsigned char *key) { unsigned char buf[8]; - static unsigned char key2[8]; - + unsigned char key2[8]; + ZERO_STRUCT(key2); smbhash(buf, in, key, 1); key2[0] = key[7]; smbhash(out, buf, key2, 1); @@ -350,8 +350,8 @@ void cred_hash2(unsigned char *out, const unsigned char *in, const unsigned char void cred_hash3(unsigned char *out, unsigned char *in, const unsigned char *key, int forw) { - static unsigned char key2[8]; - + unsigned char key2[8]; + ZERO_STRUCT(key2); smbhash(out, in, key, forw); key2[0] = key[7]; smbhash(out + 8, in + 8, key2, forw); @@ -359,48 +359,46 @@ void cred_hash3(unsigned char *out, unsigned char *in, const unsigned char *key, void SamOEMhash( unsigned char *data, const unsigned char *key, int val) { - unsigned char s_box[256]; - unsigned char index_i = 0; - unsigned char index_j = 0; - unsigned char j = 0; - int ind; - - for (ind = 0; ind < 256; ind++) - { - s_box[ind] = (unsigned char)ind; - } - - for( ind = 0; ind < 256; ind++) - { - unsigned char tc; - - j += (s_box[ind] + key[ind%16]); - - tc = s_box[ind]; - s_box[ind] = s_box[j]; - s_box[j] = tc; - } - for( ind = 0; ind < val; ind++) - { - unsigned char tc; - unsigned char t; - - index_i++; - index_j += s_box[index_i]; - - tc = s_box[index_i]; - s_box[index_i] = s_box[index_j]; - s_box[index_j] = tc; - - t = s_box[index_i] + s_box[index_j]; - data[ind] = data[ind] ^ s_box[t]; - } + unsigned char s_box[256]; + unsigned char index_i = 0; + unsigned char index_j = 0; + unsigned char j = 0; + int ind; + + for (ind = 0; ind < 256; ind++) { + s_box[ind] = (unsigned char)ind; + } + + for( ind = 0; ind < 256; ind++) { + unsigned char tc; + + j += (s_box[ind] + key[ind%16]); + + tc = s_box[ind]; + s_box[ind] = s_box[j]; + s_box[j] = tc; + } + + for (ind = 0; ind < val; ind++){ + unsigned char tc; + unsigned char t; + + index_i++; + index_j += s_box[index_i]; + + tc = s_box[index_i]; + s_box[index_i] = s_box[index_j]; + s_box[index_j] = tc; + + t = s_box[index_i] + s_box[index_j]; + data[ind] = data[ind] ^ s_box[t]; + } } + /* Decode a sam password hash into a password. The password hash is the same method used to store passwords in the NT registry. The DES key used is based on the RID of the user. */ - void sam_pwd_hash(unsigned int rid, const uchar *in, uchar *out, int forw) { uchar s[14]; diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl index 38df1c48da..efdbed34be 100644 --- a/source4/librpc/idl/netlogon.idl +++ b/source4/librpc/idl/netlogon.idl @@ -71,8 +71,8 @@ interface netlogon typedef [flag(NDR_PAHEX)] struct { uint8 session_key[8]; uint32 sequence; - netr_Credential client_cred; - netr_Credential server_cred; + netr_Credential cred1; + netr_Credential cred2; } netr_CredentialState; typedef struct { @@ -229,11 +229,11 @@ interface netlogon [out] uint32 authoritative ); - WERROR netr_LogonSamLogoff( + NTSTATUS netr_LogonSamLogoff( [in] unistr *server_name, [in] unistr *computer_name, - [in] netr_Authenticator credential, - [in] netr_Authenticator return_authenticator, + [in] netr_Authenticator *credential, + [in][out] netr_Authenticator *return_authenticator, [in] uint16 logon_level, [in] [switch_is(logon_level)] netr_LogonLevel logon ); diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index d0bffcc0e9..50b72dfec1 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -71,6 +71,7 @@ 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_LogonSamLogoff lo; const char *plain_pass; uint8 mach_pwd[16]; struct netr_Authenticator auth, auth2; @@ -83,8 +84,7 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) r.in.server_name = NULL; r.in.computer_name = lp_netbios_name(); - r.in.credentials.low = 1; - r.in.credentials.high = 2; + generate_random_buffer(r.in.credentials.data, sizeof(r.in.credentials.data), False); status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { @@ -100,13 +100,13 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) E_md4hash(plain_pass, mach_pwd); - creds_init(&creds, &r.in.credentials, &r.out.credentials, mach_pwd); + creds_init(&creds, &r.in.credentials, &r.out.credentials, mach_pwd, + &a.in.credentials); 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.credentials = creds.client_cred; printf("Testing ServerAuthenticate\n"); @@ -116,13 +116,11 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) return False; } - if (!creds_next(&creds, &a.out.credentials)) { + if (!creds_check(&creds, &a.out.credentials)) { printf("Credential chaining failed\n"); + return False; } - auth.timestamp = 0; - auth.cred = creds.client_cred; - ninfo.logon_info.domain_name.string = lp_workgroup(); ninfo.logon_info.parameter_control = 0; ninfo.logon_info.logon_id_low = 0; @@ -140,6 +138,8 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) ZERO_STRUCT(auth2); + creds_authenticator(&creds, &auth); + l.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p)); l.in.workstation = lp_netbios_name(); l.in.credential = &auth; @@ -156,7 +156,7 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) return False; } - if (!creds_next(&creds, &l.out.authenticator->cred)) { + if (!creds_check(&creds, &l.out.authenticator->cred)) { printf("Credential chaining failed\n"); } |