summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/libcli/auth/credentials.c68
-rw-r--r--source4/libcli/util/smbdes.c82
-rw-r--r--source4/librpc/idl/netlogon.idl10
-rw-r--r--source4/torture/rpc/netlogon.c18
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");
}