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/>.
24 #include "rpc_client/rpc_client.h"
25 #include "../libcli/auth/libcli_auth.h"
26 #include "../libcli/auth/netlogon_creds_cli.h"
27 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
28 #include "rpc_client/cli_netlogon.h"
29 #include "rpc_client/init_netlogon.h"
30 #include "rpc_client/util_netlogon.h"
31 #include "../libcli/security/security.h"
32 #include "lib/param/param.h"
34 /****************************************************************************
35 Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
36 credentials chain. Stores the credentials in the struct dcinfo in the
38 ****************************************************************************/
40 NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
41 const char *server_name,
43 const char *clnt_name,
44 const char *machine_account,
45 const unsigned char machine_pwd[16],
46 enum netr_SchannelType sec_chan_type,
47 uint32_t *neg_flags_inout)
49 TALLOC_CTX *frame = talloc_stackframe();
50 struct loadparm_context *lp_ctx;
52 struct samr_Password password;
54 struct dcerpc_binding_handle *b = cli->binding_handle;
55 struct netlogon_creds_CredentialState *creds = NULL;
57 if (!ndr_syntax_id_equal(&cli->abstract_syntax,
58 &ndr_table_netlogon.syntax_id)) {
60 return NT_STATUS_INVALID_PARAMETER;
63 if (!strequal(lp_netbios_name(), clnt_name)) {
65 return NT_STATUS_INVALID_PARAMETER;
68 TALLOC_FREE(cli->netlogon_creds);
70 fstr_sprintf( mach_acct, "%s$", machine_account);
72 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
75 return NT_STATUS_NO_MEMORY;
77 status = netlogon_creds_cli_context_global(lp_ctx,
83 cli, &cli->netlogon_creds);
84 talloc_unlink(frame, lp_ctx);
85 if (!NT_STATUS_IS_OK(status)) {
90 status = netlogon_creds_cli_get(cli->netlogon_creds,
92 if (NT_STATUS_IS_OK(status)) {
93 DEBUG(5,("rpccli_netlogon_setup_creds: server %s using "
94 "cached credential\n",
96 *neg_flags_inout = creds->negotiate_flags;
101 /* Store the machine account password we're going to use. */
102 memcpy(password.hash, machine_pwd, 16);
104 DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
105 "chain established.\n",
108 status = netlogon_creds_cli_auth(cli->netlogon_creds, b,
110 if (!NT_STATUS_IS_OK(status)) {
115 status = netlogon_creds_cli_get(cli->netlogon_creds,
117 if (!NT_STATUS_IS_OK(status)) {
119 return NT_STATUS_INTERNAL_ERROR;
122 *neg_flags_inout = creds->negotiate_flags;
127 /* Logon domain user */
129 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
131 uint32 logon_parameters,
133 const char *username,
134 const char *password,
135 const char *workstation,
136 uint16_t _ignored_validation_level,
140 union netr_LogonLevel *logon;
141 uint16_t validation_level = 0;
142 union netr_Validation *validation = NULL;
143 uint8_t authoritative = 0;
145 fstring clnt_name_slash;
147 logon = talloc_zero(mem_ctx, union netr_LogonLevel);
149 return NT_STATUS_NO_MEMORY;
153 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
155 fstr_sprintf( clnt_name_slash, "\\\\%s", lp_netbios_name() );
158 /* Initialise input parameters */
160 switch (logon_type) {
161 case NetlogonInteractiveInformation: {
163 struct netr_PasswordInfo *password_info;
165 struct samr_Password lmpassword;
166 struct samr_Password ntpassword;
168 password_info = talloc_zero(mem_ctx, struct netr_PasswordInfo);
169 if (!password_info) {
170 return NT_STATUS_NO_MEMORY;
173 nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
175 password_info->identity_info.domain_name.string = domain;
176 password_info->identity_info.parameter_control = logon_parameters;
177 password_info->identity_info.logon_id_low = 0xdead;
178 password_info->identity_info.logon_id_high = 0xbeef;
179 password_info->identity_info.account_name.string = username;
180 password_info->identity_info.workstation.string = clnt_name_slash;
182 password_info->lmpassword = lmpassword;
183 password_info->ntpassword = ntpassword;
185 logon->password = password_info;
189 case NetlogonNetworkInformation: {
190 struct netr_NetworkInfo *network_info;
192 unsigned char local_lm_response[24];
193 unsigned char local_nt_response[24];
194 struct netr_ChallengeResponse lm;
195 struct netr_ChallengeResponse nt;
200 network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
202 return NT_STATUS_NO_MEMORY;
205 generate_random_buffer(chal, 8);
207 SMBencrypt(password, chal, local_lm_response);
208 SMBNTencrypt(password, chal, local_nt_response);
211 lm.data = local_lm_response;
214 nt.data = local_nt_response;
216 network_info->identity_info.domain_name.string = domain;
217 network_info->identity_info.parameter_control = logon_parameters;
218 network_info->identity_info.logon_id_low = 0xdead;
219 network_info->identity_info.logon_id_high = 0xbeef;
220 network_info->identity_info.account_name.string = username;
221 network_info->identity_info.workstation.string = clnt_name_slash;
223 memcpy(network_info->challenge, chal, 8);
224 network_info->nt = nt;
225 network_info->lm = lm;
227 logon->network = network_info;
232 DEBUG(0, ("switch value %d not supported\n",
234 return NT_STATUS_INVALID_INFO_CLASS;
237 status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds,
246 if (!NT_STATUS_IS_OK(status)) {
253 static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx,
254 uint16_t validation_level,
255 union netr_Validation *validation,
256 struct netr_SamInfo3 **info3_p)
258 struct netr_SamInfo3 *info3;
261 if (validation == NULL) {
262 return NT_STATUS_INVALID_PARAMETER;
265 switch (validation_level) {
267 if (validation->sam3 == NULL) {
268 return NT_STATUS_INVALID_PARAMETER;
271 info3 = talloc_move(mem_ctx, &validation->sam3);
274 if (validation->sam6 == NULL) {
275 return NT_STATUS_INVALID_PARAMETER;
278 info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
280 return NT_STATUS_NO_MEMORY;
282 status = copy_netr_SamBaseInfo(info3, &validation->sam6->base, &info3->base);
283 if (!NT_STATUS_IS_OK(status)) {
288 info3->sidcount = validation->sam6->sidcount;
289 info3->sids = talloc_move(info3, &validation->sam6->sids);
292 return NT_STATUS_BAD_VALIDATION_CLASS;
301 * Logon domain user with an 'network' SAM logon
303 * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
306 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
308 uint32 logon_parameters,
310 const char *username,
312 const char *workstation,
314 uint16_t _ignored_validation_level,
315 DATA_BLOB lm_response,
316 DATA_BLOB nt_response,
317 struct netr_SamInfo3 **info3)
320 const char *workstation_name_slash;
321 union netr_LogonLevel *logon = NULL;
322 struct netr_NetworkInfo *network_info;
323 uint16_t validation_level = 0;
324 union netr_Validation *validation = NULL;
325 uint8_t authoritative = 0;
327 struct netr_ChallengeResponse lm;
328 struct netr_ChallengeResponse nt;
335 logon = talloc_zero(mem_ctx, union netr_LogonLevel);
337 return NT_STATUS_NO_MEMORY;
340 network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
342 return NT_STATUS_NO_MEMORY;
345 if (workstation[0] != '\\' && workstation[1] != '\\') {
346 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
348 workstation_name_slash = workstation;
351 if (!workstation_name_slash) {
352 DEBUG(0, ("talloc_asprintf failed!\n"));
353 return NT_STATUS_NO_MEMORY;
356 /* Initialise input parameters */
358 lm.data = lm_response.data;
359 lm.length = lm_response.length;
360 nt.data = nt_response.data;
361 nt.length = nt_response.length;
363 network_info->identity_info.domain_name.string = domain;
364 network_info->identity_info.parameter_control = logon_parameters;
365 network_info->identity_info.logon_id_low = 0xdead;
366 network_info->identity_info.logon_id_high = 0xbeef;
367 network_info->identity_info.account_name.string = username;
368 network_info->identity_info.workstation.string = workstation_name_slash;
370 memcpy(network_info->challenge, chal, 8);
371 network_info->nt = nt;
372 network_info->lm = lm;
374 logon->network = network_info;
376 /* Marshall data and send request */
378 status = netlogon_creds_cli_LogonSamLogon(cli->netlogon_creds,
380 NetlogonNetworkInformation,
387 if (!NT_STATUS_IS_OK(status)) {
391 status = map_validation_to_info3(mem_ctx,
392 validation_level, validation,
394 if (!NT_STATUS_IS_OK(status)) {
401 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
403 uint32 logon_parameters,
405 const char *username,
407 const char *workstation,
409 uint16_t validation_level,
410 DATA_BLOB lm_response,
411 DATA_BLOB nt_response,
412 struct netr_SamInfo3 **info3)
414 return rpccli_netlogon_sam_network_logon(cli,
428 /*********************************************************
429 Change the domain password on the PDC.
431 Just changes the password betwen the two values specified.
433 Caller must have the cli connected to the netlogon pipe
435 **********************************************************/
437 NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
439 const char *account_name,
440 const unsigned char orig_trust_passwd_hash[16],
441 const char *new_trust_pwd_cleartext,
442 const unsigned char new_trust_passwd_hash[16],
443 enum netr_SchannelType sec_channel_type)
447 if (cli->netlogon_creds == NULL) {
448 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS |
449 NETLOGON_NEG_SUPPORTS_AES;
450 result = rpccli_netlogon_setup_creds(cli,
451 cli->desthost, /* server name */
452 lp_workgroup(), /* domain */
453 lp_netbios_name(), /* client name */
454 account_name, /* machine account name */
455 orig_trust_passwd_hash,
458 if (!NT_STATUS_IS_OK(result)) {
459 DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
465 result = netlogon_creds_cli_ServerPasswordSet(cli->netlogon_creds,
467 new_trust_pwd_cleartext,
468 NULL); /* new_version */
469 if (!NT_STATUS_IS_OK(result)) {
470 DEBUG(0,("netlogon_creds_cli_ServerPasswordSet failed: %s\n",