1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

another big improvement in the credentials API. I think it now

actually makes sense, and as a nice side effect it matches the debug
output of the w2k3 netlogon.log
(This used to be commit 3c7287c24e)
This commit is contained in:
Andrew Tridgell 2003-12-02 02:15:33 +00:00
parent 06ae424835
commit 2e70035f87
3 changed files with 286 additions and 144 deletions

View File

@ -28,11 +28,10 @@
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],
struct netr_Credential *initial_creds)
static 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];
@ -46,36 +45,82 @@ void creds_init(struct netr_CredentialState *creds,
cred_hash1(creds->session_key, sum2, machine_password);
creds->sequence = 0;
creds->sequence = time(NULL);
SIVAL(time_cred.data, 0, IVAL(client_challenge->data, 0));
SIVAL(time_cred.data, 4, IVAL(client_challenge->data, 4));
cred_hash2(creds->client.data, time_cred.data, creds->session_key);
cred_hash2(creds->cred2.data, time_cred.data, creds->session_key);
SIVAL(time_cred.data, 0, IVAL(server_challenge->data, 0));
SIVAL(time_cred.data, 4, IVAL(server_challenge->data, 4));
cred_hash2(creds->server.data, time_cred.data, creds->session_key);
creds->cred1 = *server_challenge;
*initial_creds = creds->cred2;
creds->seed = creds->client;
}
/*
check that a credentials reply is correct
step the credentials to the next element in the chain
*/
BOOL creds_check(struct netr_CredentialState *creds,
const struct netr_Credential *received_credentials)
static void creds_step(struct netr_CredentialState *creds)
{
struct netr_Credential cred2, time_cred;
uint32 sequence = creds->sequence?creds->sequence+1:0;
struct netr_Credential time_cred;
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(received_credentials->data, cred2.data, 8) != 0) {
creds->sequence += 2;
DEBUG(5,("\tseed %08x:%08x\n",
IVAL(creds->seed.data, 0), IVAL(creds->seed.data, 4)));
SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence);
SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
DEBUG(5,("\tseed+time %08x:%08x\n", IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
cred_hash2(creds->client.data, time_cred.data, creds->session_key);
DEBUG(5,("\tCLIENT %08x:%08x\n",
IVAL(creds->client.data, 0), IVAL(creds->client.data, 4)));
SIVAL(time_cred.data, 0, IVAL(creds->seed.data, 0) + creds->sequence + 1);
SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4));
DEBUG(5,("\tseed+time+1 %08x:%08x\n",
IVAL(time_cred.data, 0), IVAL(time_cred.data, 4)));
cred_hash2(creds->server.data, time_cred.data, creds->session_key);
DEBUG(5,("\tSERVER %08x:%08x\n",
IVAL(creds->server.data, 0), IVAL(creds->server.data, 4)));
creds->seed = time_cred;
}
/*
initialise the credentials chain and return the first client
credentials
*/
void creds_client_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 *initial_credential)
{
creds_init(creds, client_challenge, server_challenge, machine_password);
*initial_credential = creds->client;
}
/*
check that a credentials reply from a server is correct
*/
BOOL creds_client_check(struct netr_CredentialState *creds,
const struct netr_Credential *received_credentials)
{
if (memcmp(received_credentials->data, creds->server.data, 8) != 0) {
DEBUG(2,("credentials check failed\n"));
return False;
}
return True;
}
@ -83,30 +128,12 @@ BOOL creds_check(struct netr_CredentialState *creds,
produce the next authenticator in the sequence ready to send to
the server
*/
void creds_authenticator(struct netr_CredentialState *creds,
struct netr_Authenticator *next)
void creds_client_authenticator(struct netr_CredentialState *creds,
struct netr_Authenticator *next)
{
struct netr_Credential cred2;
struct netr_Credential time_cred;
creds_step(creds);
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->cred2 = cred2;
next->cred = creds->cred2;
next->cred = creds->client;
next->timestamp = creds->sequence;
}
@ -114,7 +141,7 @@ void creds_authenticator(struct netr_CredentialState *creds,
/*
encrypt a 16 byte password buffer using the session key
*/
void creds_encrypt(struct netr_CredentialState *creds, struct netr_Password *pass)
void creds_client_encrypt(struct netr_CredentialState *creds, struct netr_Password *pass)
{
struct netr_Password tmp;
cred_hash3(tmp.data, pass->data, creds->session_key, 1);

View File

@ -71,8 +71,9 @@ interface netlogon
typedef [flag(NDR_PAHEX)] struct {
uint8 session_key[8];
uint32 sequence;
netr_Credential cred1;
netr_Credential cred2;
netr_Credential seed;
netr_Credential client;
netr_Credential server;
} netr_CredentialState;
typedef struct {
@ -229,6 +230,10 @@ interface netlogon
[out] uint32 authoritative
);
/*****************/
/* Function 0x03 */
NTSTATUS netr_LogonSamLogoff(
[in] unistr *server_name,
[in] unistr *computer_name,
@ -238,13 +243,22 @@ interface netlogon
[in] [switch_is(logon_level)] netr_LogonLevel logon
);
WERROR netr_ServerReqChallenge(
/*****************/
/* Function 0x04 */
NTSTATUS netr_ServerReqChallenge(
[in] unistr *server_name,
[in] unistr computer_name,
[in][out] netr_Credential credentials
);
WERROR netr_ServerAuthenticate(
/*****************/
/* Function 0x05 */
NTSTATUS netr_ServerAuthenticate(
[in] unistr *server_name,
[in] unistr username,
[in] uint16 secure_challenge_type,
@ -253,6 +267,9 @@ interface netlogon
);
/*****************/
/* Function 0x06 */
NTSTATUS netr_ServerPasswordSet(
[in] unistr *server_name,
[in] unistr username,
@ -264,22 +281,28 @@ interface netlogon
);
#if 0
/*****************/
/* Function 0x07 */
typedef struct {
unistr *username;
netr_String dummy1;
netr_String dummy2;
netr_String dummy3;
netr_String dummy4;
uint32 dummy5;
uint32 dummy6;
uint32 dummy7;
uint32 dummy8;
netr_String unknown1;
netr_String unknown2;
netr_String unknown3;
netr_String unknown4;
uint32 unknown5;
uint32 unknown6;
uint32 unknown7;
uint32 unknown8;
} DELTA_DELETE_USER;
typedef struct {
bool SensitiveDataFlag;
uint32 DataLength;
[size_is(DataLength)] uint8 *SensitiveData;
} USER_PRIVATE_INFO;
typedef struct {
netr_String username;
netr_String FullName;
@ -310,15 +333,16 @@ interface netlogon
USER_PRIVATE_INFO user_private_info;
uint32 SecurityInformation;
LSA_SECURITY_DESCRIPTOR sec_desc;
netr_String dummy1;
netr_String dummy2;
netr_String dummy3;
netr_String dummy4;
uint32 dummy5;
uint32 dummy6;
uint32 dummy7;
uint32 dummy8;
netr_String unknown1;
netr_String unknown2;
netr_String unknown3;
netr_String unknown4;
uint32 unknown5;
uint32 unknown6;
uint32 unknown7;
uint32 unknown8;
} DELTA_USER;
typedef struct {
netr_String DomainName;
netr_String OEMInfo;
@ -331,72 +355,78 @@ interface netlogon
NTTIME domain_create_time;
uint32 SecurityInformation;
LSA_SECURITY_DESCRIPTOR sec_desc;
netr_String dummy1;
netr_String dummy2;
netr_String dummy3;
netr_String dummy4;
uint32 dummy5;
uint32 dummy6;
uint32 dummy7;
uint32 dummy8;
netr_String unknown1;
netr_String unknown2;
netr_String unknown3;
netr_String unknown4;
uint32 unknown5;
uint32 unknown6;
uint32 unknown7;
uint32 unknown8;
} DELTA_DOMAIN;
typedef struct {
netr_String groupname;
GROUP_MEMBERSHIP group_membership;
netr_String comment;
uint32 SecurityInformation;
LSA_SECURITY_DESCRIPTOR sec_desc;
netr_String dummy1;
netr_String dummy2;
netr_String dummy3;
netr_String dummy4;
uint32 dummy5;
uint32 dummy6;
uint32 dummy7;
uint32 dummy8;
netr_String unknown1;
netr_String unknown2;
netr_String unknown3;
netr_String unknown4;
uint32 unknown5;
uint32 unknown6;
uint32 unknown7;
uint32 unknown8;
} DELTA_GROUP;
typedef struct {
netr_String OldName;
netr_String NewName;
netr_String dummy1;
netr_String dummy2;
netr_String dummy3;
netr_String dummy4;
uint32 dummy5;
uint32 dummy6;
uint32 dummy7;
uint32 dummy8;
netr_String unknown1;
netr_String unknown2;
netr_String unknown3;
netr_String unknown4;
uint32 unknown5;
uint32 unknown6;
uint32 unknown7;
uint32 unknown8;
} DELTA_RENAME;
typedef struct {
[size_is(num_rids)] uint32 *rids;
[size_is(num_rids)] uint32 *attribs;
uint32 num_rids;
uint32 dummy1;
uint32 dummy2;
uint32 dummy3;
uint32 dummy4;
uint32 unknown1;
uint32 unknown2;
uint32 unknown3;
uint32 unknown4;
} DELTA_GROUP_MEMBER;
typedef struct {
netr_String alias_name;
uint32 rid;
uint32 SecurityInformation;
LSA_SECURITY_DESCRIPTOR sec_desc;
netr_String dummy1;
netr_String dummy2;
netr_String dummy3;
netr_String dummy4;
uint32 dummy5;
uint32 dummy6;
uint32 dummy7;
uint32 dummy8;
netr_String unknown1;
netr_String unknown2;
netr_String unknown3;
netr_String unknown4;
uint32 unknown5;
uint32 unknown6;
uint32 unknown7;
uint32 unknown8;
} DELTA_ALIAS;
typedef struct {
SID_ARRAY sids;
uint32 dummy1;
uint32 dummy2;
uint32 dummy3;
uint32 dummy4;
uint32 unknown1;
uint32 unknown2;
uint32 unknown3;
uint32 unknown4;
} DELTA_ALIAS_MEMBER;
typedef struct {
uint32 pagedpoollimit;
uint32 nonpagedpoollimit;
@ -405,6 +435,7 @@ interface netlogon
uint32 pagefilelimit;
NTTIME timelimit;
} QUOTA_LIMITS;
typedef struct {
uint32 maxlogsize;
NTTIME auditretentionperiod;
@ -418,30 +449,32 @@ interface netlogon
NTTIME db_create_time;
uint32 SecurityInformation;
LSA_SECURITY_DESCRIPTOR sec_desc;
netr_String dummy1;
netr_String dummy2;
netr_String dummy3;
netr_String dummy4;
uint32 dummy5;
uint32 dummy6;
uint32 dummy7;
uint32 dummy8;
netr_String unknown1;
netr_String unknown2;
netr_String unknown3;
netr_String unknown4;
uint32 unknown5;
uint32 unknown6;
uint32 unknown7;
uint32 unknown8;
} DELTA_POLICY;
typedef struct {
netr_String DomainName;
uint32 num_controllers;
[size_is(num_controllers)] netr_String *controller_names;
uint32 SecurityInformation;
LSA_SECURITY_DESCRIPTOR sec_desc;
netr_String dummy1;
netr_String dummy2;
netr_String dummy3;
netr_String dummy4;
uint32 dummy5;
uint32 dummy6;
uint32 dummy7;
uint32 dummy8;
netr_String unknown1;
netr_String unknown2;
netr_String unknown3;
netr_String unknown4;
uint32 unknown5;
uint32 unknown6;
uint32 unknown7;
uint32 unknown8;
} DELTA_TRUSTED_DOMAINS;
typedef struct {
uint32 privilegeentries;
uint32 provolegecontrol;
@ -450,20 +483,22 @@ interface netlogon
QUOTALIMITS quotalimits;
uint32 SecurityInformation;
LSA_SECURITY_DESCRIPTOR sec_desc;
netr_String dummy1;
netr_String dummy2;
netr_String dummy3;
netr_String dummy4;
uint32 dummy5;
uint32 dummy6;
uint32 dummy7;
uint32 dummy8;
netr_String unknown1;
netr_String unknown2;
netr_String unknown3;
netr_String unknown4;
uint32 unknown5;
uint32 unknown6;
uint32 unknown7;
uint32 unknown8;
} DELTA_ACCOUNTS;
typedef struct {
uint32 len;
uint32 maxlen;
[size_is(maxlen)][length_is(len)] uint8 *cipher_data;
} CIPHER_VALUE;
typedef struct {
CIPHER_VALUE current_cipher;
NTTIME current_cipher_set_time;
@ -471,15 +506,16 @@ interface netlogon
NTTIME old_cipher_set_time;
uint32 SecurityInformation;
LSA_SECURITY_DESCRIPTOR sec_desc;
netr_String dummy1;
netr_String dummy2;
netr_String dummy3;
netr_String dummy4;
uint32 dummy5;
uint32 dummy6;
uint32 dummy7;
uint32 dummy8;
netr_String unknown1;
netr_String unknown2;
netr_String unknown3;
netr_String unknown4;
uint32 unknown5;
uint32 unknown6;
uint32 unknown7;
uint32 unknown8;
} DELTA_SECRET;
typedef struct {
uint32 low_value;
uint32 high_value;
@ -527,15 +563,19 @@ interface netlogon
[case(20)] uint32 rid;
[case(21)] uint32 rid;
} DELTA_ID_UNION;
typedef struct {
uint16 delta_type;
DELTA_ID_UNION delta_id_union;
DELTA_UNION delta_union;
} DELTA_ENUM;
typedef struct {
uint32 num_deltas;
[size_is(num_deltas)] DELTA_ENUM *delta_enum;
} DELTA_ENUM_ARRAY;
WERROR netr_DatabaseDeltas(
[in][string][ref] wchar_t *logonserver, # REF!!!
[in][string][ref] wchar_t *computername,
@ -546,6 +586,11 @@ interface netlogon
[in] uint32 preferredmaximumlength,
[out] DELTA_ENUM_ARRAY *delta_enum_array
);
/*****************/
/* Function 0x08 */
WERROR netr_DatabaseSync(
[in][string][ref] wchar_t *logonserver, # REF!!!
[in][string][ref] wchar_t *computername,
@ -556,11 +601,17 @@ interface netlogon
[in] uint32 preferredmaximumlength,
[out] DELTA_ENUM_ARRAY *delta_enum_array
);
/*****************/
/* Function 0x09 */
typedef struct {
uint8 computer_name[16];
uint32 timecreated;
uint32 serial_number;
} UAS_INFO_0;
WERROR netr_AccountDeltas(
[in][string] wchar_t *logonserver,
[in][string][ref] wchar_t *computername,
@ -574,6 +625,11 @@ interface netlogon
[in][long] level,
[in][long] buffersize,
);
/*****************/
/* Function 0x0A */
WERROR netr_AccountSync(
[in][string] wchar_t *logonserver,
[in][string][ref] wchar_t *computername,
@ -588,21 +644,29 @@ interface netlogon
[in][long] buffersize,
[in][out][ref] UAS_INFO_0 recordid,
);
/*****************/
/* Function 0x0B */
WERROR netr_GetDcName(
[in] unistr logon_server,
[in] unistr *domainname,
[out]unistr *dcname,
};
typedef struct {
uint32 flags;
uint32 pdc_connection_status;
} NETLOGON_INFO_1;
typedef struct {
uint32 flags;
uint32 pdc_connection_status;
unistrtrusted_dc_name;
uint32 tc_connection_status;
} NETLOGON_INFO_2;
typedef struct {
uint32 flags;
uint32 logon_attempts;
@ -612,28 +676,45 @@ interface netlogon
uint32 reserved;
uint32 reserved;
} NETLOGON_INFO_3;
typedef [switch_type(long)] union {
[case(1)] NETLOGON_INFO_1 *i1;
[case(2)] NETLOGON_INFO_2 *i2;
[case(3)] NETLOGON_INFO_3 *i3;
} CONTROL_QUERY_INFORMATION;
/*****************/
/* Function 0x0C */
WERROR netr_LogonControl(
[in][string] wchar_t *logonserver,
[in] uint32 function_code,
[in] uint32 level,
[out][ref] CONTROL_QUERY_INFORMATION
);
/*****************/
/* Function 0x0D */
WERROR netr_GetAnyDCName(
[in] unistr *logon_server,
[in] unistr *domainname,
[out]unistr *dcname,
};
typedef [switch_type(long)] union {
[case(5)] unistr *unknown;
[case(6)] unistr *unknown;
[case(0xfffe)] uint32 unknown;
[case(7)] unistry*unknown;
} CONTROL_DATA_INFORMATION;
/*****************/
/* Function 0x0E */
WERROR netr_LogonControl2(
[in][string] wchar_t *logonserver,
[in] uint32 function_code,
@ -641,6 +722,11 @@ interface netlogon
[in][ref] CONTROL_DATA_INFORMATION *data,
[out][ref] CONTROL_QUERY_INFORMATION *query
);
/*****************/
/* Function 0x0F */
WERROR netr_ServerAuthenticate2(
[in][string] wchar_t *logonserver,
[in] unistr username,
@ -650,6 +736,11 @@ interface netlogon
[out][ref] CREDENTIAL *server_chal,
[in][out][ref] uint32 *negotiate_flags,
);
/*****************/
/* Function 0x10 */
WERROR netr_DatabaseSync2(
[in][string][ref] wchar_t *logonserver, # REF!!!
[in][string][ref] wchar_t *computername,
@ -661,6 +752,11 @@ interface netlogon
[in] uint32 preferredmaximumlength,
[out] DELTA_ENUM_ARRAY *delta_enum_array
);
/*****************/
/* Function 0x11 */
WERROR netr_DatabaseRedo(
[in][string][ref] wchar_t *logonserver, # REF!!!
[in][string][ref] wchar_t *computername,
@ -670,6 +766,11 @@ interface netlogon
[in] uint32 change_log_entry_size,
[out] DELTA_ENUM_ARRAY *delta_enum_array
);
/*****************/
/* Function 0x12 */
WERROR netr_LogonControl2Ex(
[in][string] wchar_t *logonserver,
[in] uint32 function_code,

View File

@ -94,8 +94,8 @@ static BOOL test_SetupCredentials(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,
&a.in.credentials);
creds_client_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());
@ -110,7 +110,7 @@ static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return False;
}
if (!creds_check(creds, &a.out.credentials)) {
if (!creds_client_check(creds, &a.out.credentials)) {
printf("Credential chaining failed\n");
return False;
}
@ -152,7 +152,7 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
ZERO_STRUCT(auth2);
creds_authenticator(&creds, &auth);
creds_client_authenticator(&creds, &auth);
r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
r.in.workstation = lp_netbios_name();
@ -170,7 +170,7 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
return False;
}
if (!creds_check(&creds, &r.out.authenticator->cred)) {
if (!creds_client_check(&creds, &r.out.authenticator->cred)) {
printf("Credential chaining failed\n");
}
@ -192,8 +192,6 @@ static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
return False;
}
creds_authenticator(&creds, &r.in.credential);
r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
r.in.username = talloc_asprintf(mem_ctx, "%s$", lp_netbios_name());
r.in.secure_challenge_type = 2;
@ -202,10 +200,12 @@ static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
password = generate_random_str(8);
E_md4hash(password, r.in.new_password.data);
creds_encrypt(&creds, &r.in.new_password);
creds_client_encrypt(&creds, &r.in.new_password);
printf("Testing ServerPasswordSet on machine account\n");
creds_client_authenticator(&creds, &r.in.credential);
status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("ServerPasswordSet - %s\n", nt_errstr(status));
@ -216,7 +216,21 @@ static BOOL test_SetPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
printf("Failed to save machine password\n");
}
if (!creds_check(&creds, &r.out.return_authenticator.cred)) {
if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
printf("Credential chaining failed\n");
}
printf("Testing a second ServerPasswordSet on machine account\n");
creds_client_authenticator(&creds, &r.in.credential);
status = dcerpc_netr_ServerPasswordSet(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
printf("ServerPasswordSet - %s\n", nt_errstr(status));
return False;
}
if (!creds_client_check(&creds, &r.out.return_authenticator.cred)) {
printf("Credential chaining failed\n");
}