2
Unix SMB/CIFS implementation.
3
NT Domain Authentication SMB / MSRPC client
4
Copyright (C) Andrew Tridgell 1992-2000
5
Copyright (C) Jeremy Allison 1998.
6
Largely re-written by Jeremy Allison (C) 2005.
7
Copyright (C) Guenther Deschner 2008.
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 3 of the License, or
12
(at your option) any later version.
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
GNU General Public License for more details.
19
You should have received a copy of the GNU General Public License
20
along with this program. If not, see <http://www.gnu.org/licenses/>.
25
/****************************************************************************
26
Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
27
credentials chain. Stores the credentials in the struct dcinfo in the
29
****************************************************************************/
31
NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
32
const char *server_name,
34
const char *clnt_name,
35
const char *machine_account,
36
const unsigned char machine_pwd[16],
37
enum netr_SchannelType sec_chan_type,
38
uint32_t *neg_flags_inout)
40
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
41
struct netr_Credential clnt_chal_send;
42
struct netr_Credential srv_chal_recv;
46
SMB_ASSERT(ndr_syntax_id_equal(&cli->abstract_syntax,
47
&ndr_table_netlogon.syntax_id));
50
cli->dc = talloc_zero(cli, struct dcinfo);
51
if (cli->dc == NULL) {
52
return NT_STATUS_NO_MEMORY;
56
/* Store the machine account password we're going to use. */
57
memcpy(dc->mach_pw, machine_pwd, 16);
59
fstrcpy(dc->remote_machine, "\\\\");
60
fstrcat(dc->remote_machine, server_name);
62
fstrcpy(dc->domain, domain);
64
fstr_sprintf( dc->mach_acct, "%s$", machine_account);
67
/* Create the client challenge. */
68
generate_random_buffer(clnt_chal_send.data, 8);
70
/* Get the server challenge. */
71
result = rpccli_netr_ServerReqChallenge(cli, talloc_tos(),
76
if (!NT_STATUS_IS_OK(result)) {
80
/* Calculate the session key and client credentials */
81
creds_client_init(*neg_flags_inout,
89
* Send client auth-2 challenge and receive server repy.
92
result = rpccli_netr_ServerAuthenticate2(cli, talloc_tos(),
97
&clnt_chal_send, /* input. */
98
&srv_chal_recv, /* output. */
101
/* we might be talking to NT4, so let's downgrade in that case and retry
102
* with the returned neg_flags - gd */
104
if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) {
109
if (!NT_STATUS_IS_OK(result)) {
114
* Check the returned value using the initial
115
* server received challenge.
118
if (!netlogon_creds_client_check(dc, &srv_chal_recv)) {
120
* Server replied with bad credential. Fail.
122
DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
123
"replied with bad credential\n",
125
return NT_STATUS_ACCESS_DENIED;
128
DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
129
"chain established.\n",
135
/* Logon domain user */
137
NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
139
uint32 logon_parameters,
141
const char *username,
142
const char *password,
143
const char *workstation,
146
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
147
struct netr_Authenticator clnt_creds;
148
struct netr_Authenticator ret_creds;
149
union netr_LogonLevel *logon;
150
union netr_Validation validation;
151
uint8_t authoritative;
152
int validation_level = 3;
153
fstring clnt_name_slash;
156
ZERO_STRUCT(ret_creds);
159
logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
161
return NT_STATUS_NO_MEMORY;
165
fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
167
fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
170
/* Initialise input parameters */
172
netlogon_creds_client_step(cli->dc, &clnt_creds);
174
switch (logon_type) {
175
case NetlogonInteractiveInformation: {
177
struct netr_PasswordInfo *password_info;
179
struct samr_Password lmpassword;
180
struct samr_Password ntpassword;
182
unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
184
unsigned char lm_owf[16];
185
unsigned char nt_owf[16];
186
unsigned char key[16];
188
password_info = TALLOC_ZERO_P(mem_ctx, struct netr_PasswordInfo);
189
if (!password_info) {
190
return NT_STATUS_NO_MEMORY;
193
nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
195
#ifdef DEBUG_PASSWORD
196
DEBUG(100,("lm cypher:"));
197
dump_data(100, lm_owf_user_pwd, 16);
199
DEBUG(100,("nt cypher:"));
200
dump_data(100, nt_owf_user_pwd, 16);
203
memcpy(key, cli->dc->sess_key, 8);
205
memcpy(lm_owf, lm_owf_user_pwd, 16);
206
SamOEMhash(lm_owf, key, 16);
207
memcpy(nt_owf, nt_owf_user_pwd, 16);
208
SamOEMhash(nt_owf, key, 16);
210
#ifdef DEBUG_PASSWORD
211
DEBUG(100,("encrypt of lm owf password:"));
212
dump_data(100, lm_owf, 16);
214
DEBUG(100,("encrypt of nt owf password:"));
215
dump_data(100, nt_owf, 16);
217
memcpy(lmpassword.hash, lm_owf, 16);
218
memcpy(ntpassword.hash, nt_owf, 16);
220
init_netr_PasswordInfo(password_info,
230
logon->password = password_info;
234
case NetlogonNetworkInformation: {
235
struct netr_NetworkInfo *network_info;
237
unsigned char local_lm_response[24];
238
unsigned char local_nt_response[24];
239
struct netr_ChallengeResponse lm;
240
struct netr_ChallengeResponse nt;
245
network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
247
return NT_STATUS_NO_MEMORY;
250
generate_random_buffer(chal, 8);
252
SMBencrypt(password, chal, local_lm_response);
253
SMBNTencrypt(password, chal, local_nt_response);
256
lm.data = local_lm_response;
259
nt.data = local_nt_response;
261
init_netr_NetworkInfo(network_info,
272
logon->network = network_info;
277
DEBUG(0, ("switch value %d not supported\n",
279
return NT_STATUS_INVALID_INFO_CLASS;
282
result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
283
cli->dc->remote_machine,
293
if (memcmp(zeros, &ret_creds.cred.data, sizeof(ret_creds.cred.data)) != 0) {
294
/* Check returned credentials if present. */
295
if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
296
DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
297
return NT_STATUS_ACCESS_DENIED;
306
* Logon domain user with an 'network' SAM logon
308
* @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
311
NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
313
uint32 logon_parameters,
315
const char *username,
317
const char *workstation,
319
DATA_BLOB lm_response,
320
DATA_BLOB nt_response,
321
struct netr_SamInfo3 **info3)
323
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
324
int validation_level = 3;
325
const char *workstation_name_slash;
326
const char *server_name_slash;
328
struct netr_Authenticator clnt_creds;
329
struct netr_Authenticator ret_creds;
330
union netr_LogonLevel *logon = NULL;
331
struct netr_NetworkInfo *network_info;
332
uint8_t authoritative;
333
union netr_Validation validation;
334
struct netr_ChallengeResponse lm;
335
struct netr_ChallengeResponse nt;
340
ZERO_STRUCT(ret_creds);
345
logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
347
return NT_STATUS_NO_MEMORY;
350
network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
352
return NT_STATUS_NO_MEMORY;
355
netlogon_creds_client_step(cli->dc, &clnt_creds);
357
if (server[0] != '\\' && server[1] != '\\') {
358
server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
360
server_name_slash = server;
363
if (workstation[0] != '\\' && workstation[1] != '\\') {
364
workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
366
workstation_name_slash = workstation;
369
if (!workstation_name_slash || !server_name_slash) {
370
DEBUG(0, ("talloc_asprintf failed!\n"));
371
return NT_STATUS_NO_MEMORY;
374
/* Initialise input parameters */
376
lm.data = lm_response.data;
377
lm.length = lm_response.length;
378
nt.data = nt_response.data;
379
nt.length = nt_response.length;
381
init_netr_NetworkInfo(network_info,
387
workstation_name_slash,
392
logon->network = network_info;
394
/* Marshall data and send request */
396
result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
401
NetlogonNetworkInformation,
406
if (!NT_STATUS_IS_OK(result)) {
410
if (memcmp(zeros, validation.sam3->base.key.key, 16) != 0) {
411
SamOEMhash(validation.sam3->base.key.key,
412
cli->dc->sess_key, 16);
415
if (memcmp(zeros, validation.sam3->base.LMSessKey.key, 8) != 0) {
416
SamOEMhash(validation.sam3->base.LMSessKey.key,
417
cli->dc->sess_key, 8);
420
if (memcmp(zeros, ret_creds.cred.data, sizeof(ret_creds.cred.data)) != 0) {
421
/* Check returned credentials if present. */
422
if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
423
DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
424
return NT_STATUS_ACCESS_DENIED;
428
*info3 = validation.sam3;
433
NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
435
uint32 logon_parameters,
437
const char *username,
439
const char *workstation,
441
DATA_BLOB lm_response,
442
DATA_BLOB nt_response,
443
struct netr_SamInfo3 **info3)
445
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
446
int validation_level = 3;
447
const char *workstation_name_slash;
448
const char *server_name_slash;
450
union netr_LogonLevel *logon = NULL;
451
struct netr_NetworkInfo *network_info;
452
uint8_t authoritative;
453
union netr_Validation validation;
454
struct netr_ChallengeResponse lm;
455
struct netr_ChallengeResponse nt;
465
logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
467
return NT_STATUS_NO_MEMORY;
470
network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
472
return NT_STATUS_NO_MEMORY;
475
if (server[0] != '\\' && server[1] != '\\') {
476
server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
478
server_name_slash = server;
481
if (workstation[0] != '\\' && workstation[1] != '\\') {
482
workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
484
workstation_name_slash = workstation;
487
if (!workstation_name_slash || !server_name_slash) {
488
DEBUG(0, ("talloc_asprintf failed!\n"));
489
return NT_STATUS_NO_MEMORY;
492
/* Initialise input parameters */
494
lm.data = lm_response.data;
495
lm.length = lm_response.length;
496
nt.data = nt_response.data;
497
nt.length = nt_response.length;
499
init_netr_NetworkInfo(network_info,
505
workstation_name_slash,
510
logon->network = network_info;
512
/* Marshall data and send request */
514
result = rpccli_netr_LogonSamLogonEx(cli, mem_ctx,
517
NetlogonNetworkInformation,
523
if (!NT_STATUS_IS_OK(result)) {
527
if (memcmp(zeros, validation.sam3->base.key.key, 16) != 0) {
528
SamOEMhash(validation.sam3->base.key.key,
529
cli->dc->sess_key, 16);
532
if (memcmp(zeros, validation.sam3->base.LMSessKey.key, 8) != 0) {
533
SamOEMhash(validation.sam3->base.LMSessKey.key,
534
cli->dc->sess_key, 8);
537
*info3 = validation.sam3;
542
/*********************************************************
543
Change the domain password on the PDC.
545
Just changes the password betwen the two values specified.
547
Caller must have the cli connected to the netlogon pipe
549
**********************************************************/
551
NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
553
const unsigned char orig_trust_passwd_hash[16],
554
const char *new_trust_pwd_cleartext,
555
const unsigned char new_trust_passwd_hash[16],
556
uint32_t sec_channel_type)
559
uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
560
struct netr_Authenticator clnt_creds, srv_cred;
562
result = rpccli_netlogon_setup_creds(cli,
563
cli->desthost, /* server name */
564
lp_workgroup(), /* domain */
565
global_myname(), /* client name */
566
global_myname(), /* machine account name */
567
orig_trust_passwd_hash,
571
if (!NT_STATUS_IS_OK(result)) {
572
DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
577
netlogon_creds_client_step(cli->dc, &clnt_creds);
579
if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) {
581
struct netr_CryptPassword new_password;
583
init_netr_CryptPassword(new_trust_pwd_cleartext,
587
result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx,
588
cli->dc->remote_machine,
595
if (!NT_STATUS_IS_OK(result)) {
596
DEBUG(0,("rpccli_netr_ServerPasswordSet2 failed: %s\n",
602
struct samr_Password new_password;
604
des_crypt112_16(new_password.hash,
605
(unsigned char *)new_trust_passwd_hash,
606
cli->dc->sess_key, 1);
608
result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
609
cli->dc->remote_machine,
616
if (!NT_STATUS_IS_OK(result)) {
617
DEBUG(0,("rpccli_netr_ServerPasswordSet failed: %s\n",
623
/* Always check returned credentials. */
624
if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
625
DEBUG(0,("credentials chain check failed\n"));
626
return NT_STATUS_ACCESS_DENIED;