2 Unix SMB/CIFS implementation.
4 Copyright (C) Tim Potter 2000-2001,
5 Copyright (C) Andrew Tridgell 1992-1997,2000,
6 Copyright (C) Rafal Szczesniak 2002.
7 Copyright (C) Jeremy Allison 2005.
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 static void init_lsa_String(struct lsa_String *name, const char *s)
32 NTSTATUS rpccli_samr_query_userinfo(struct rpc_pipe_client *cli,
34 const POLICY_HND *user_pol,
36 SAM_USERINFO_CTR **ctr)
38 prs_struct qbuf, rbuf;
39 SAMR_Q_QUERY_USERINFO q;
40 SAMR_R_QUERY_USERINFO r;
41 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
43 DEBUG(10,("cli_samr_query_userinfo\n"));
48 /* Marshall data and send request */
50 init_samr_q_query_userinfo(&q, user_pol, switch_value);
52 CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_USERINFO,
55 samr_io_q_query_userinfo,
56 samr_io_r_query_userinfo,
57 NT_STATUS_UNSUCCESSFUL);
59 /* Return output parameters */
67 /* Enumerate domain groups */
69 NTSTATUS rpccli_samr_enum_dom_groups(struct rpc_pipe_client *cli,
71 POLICY_HND *pol, uint32 *start_idx,
72 uint32 size, struct acct_info **dom_groups,
73 uint32 *num_dom_groups)
75 prs_struct qbuf, rbuf;
76 SAMR_Q_ENUM_DOM_GROUPS q;
77 SAMR_R_ENUM_DOM_GROUPS r;
78 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
81 DEBUG(10,("cli_samr_enum_dom_groups starting at index %u\n", (unsigned int)*start_idx));
86 /* Marshall data and send request */
88 init_samr_q_enum_dom_groups(&q, pol, *start_idx, size);
90 CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ENUM_DOM_GROUPS,
93 samr_io_q_enum_dom_groups,
94 samr_io_r_enum_dom_groups,
95 NT_STATUS_UNSUCCESSFUL);
97 /* Return output parameters */
101 if (!NT_STATUS_IS_OK(result) &&
102 NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES))
105 *num_dom_groups = r.num_entries2;
107 if (*num_dom_groups == 0)
110 if (!((*dom_groups) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_dom_groups))) {
111 result = NT_STATUS_NO_MEMORY;
115 memset(*dom_groups, 0, sizeof(struct acct_info) * (*num_dom_groups));
119 for (i = 0; i < *num_dom_groups; i++) {
121 (*dom_groups)[i].rid = r.sam[i].rid;
123 if (r.sam[i].hdr_name.buffer) {
124 unistr2_to_ascii((*dom_groups)[i].acct_name,
125 &r.uni_grp_name[name_idx],
126 sizeof((*dom_groups)[i].acct_name));
130 *start_idx = r.next_idx;
137 /* Enumerate domain groups */
139 NTSTATUS rpccli_samr_enum_als_groups(struct rpc_pipe_client *cli,
141 POLICY_HND *pol, uint32 *start_idx,
142 uint32 size, struct acct_info **dom_aliases,
143 uint32 *num_dom_aliases)
145 prs_struct qbuf, rbuf;
146 SAMR_Q_ENUM_DOM_ALIASES q;
147 SAMR_R_ENUM_DOM_ALIASES r;
148 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
151 DEBUG(10,("cli_samr_enum_als_groups starting at index %u\n", (unsigned int)*start_idx));
156 /* Marshall data and send request */
158 init_samr_q_enum_dom_aliases(&q, pol, *start_idx, size);
160 CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ENUM_DOM_ALIASES,
163 samr_io_q_enum_dom_aliases,
164 samr_io_r_enum_dom_aliases,
165 NT_STATUS_UNSUCCESSFUL);
167 /* Return output parameters */
171 if (!NT_STATUS_IS_OK(result) &&
172 NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES)) {
176 *num_dom_aliases = r.num_entries2;
178 if (*num_dom_aliases == 0)
181 if (!((*dom_aliases) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_dom_aliases))) {
182 result = NT_STATUS_NO_MEMORY;
186 memset(*dom_aliases, 0, sizeof(struct acct_info) * *num_dom_aliases);
190 for (i = 0; i < *num_dom_aliases; i++) {
192 (*dom_aliases)[i].rid = r.sam[i].rid;
194 if (r.sam[i].hdr_name.buffer) {
195 unistr2_to_ascii((*dom_aliases)[i].acct_name,
196 &r.uni_grp_name[name_idx],
197 sizeof((*dom_aliases)[i].acct_name));
201 *start_idx = r.next_idx;
208 /* User change password */
210 NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
212 const char *username,
213 const char *newpassword,
214 const char *oldpassword)
216 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
217 struct samr_CryptPassword new_nt_password;
218 struct samr_CryptPassword new_lm_password;
219 struct samr_Password old_nt_hash_enc;
220 struct samr_Password old_lanman_hash_enc;
222 uchar old_nt_hash[16];
223 uchar old_lanman_hash[16];
224 uchar new_nt_hash[16];
225 uchar new_lanman_hash[16];
226 struct lsa_String server, account;
227 char *srv_name_slash = NULL;
229 DEBUG(10,("rpccli_samr_chgpasswd_user\n"));
231 init_lsa_String(&server, srv_name_slash);
232 init_lsa_String(&account, username);
234 srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
235 if (!srv_name_slash) {
236 return NT_STATUS_NO_MEMORY;
239 /* Calculate the MD4 hash (NT compatible) of the password */
240 E_md4hash(oldpassword, old_nt_hash);
241 E_md4hash(newpassword, new_nt_hash);
243 if (lp_client_lanman_auth() &&
244 E_deshash(newpassword, new_lanman_hash) &&
245 E_deshash(oldpassword, old_lanman_hash)) {
246 /* E_deshash returns false for 'long' passwords (> 14
247 DOS chars). This allows us to match Win2k, which
248 does not store a LM hash for these passwords (which
249 would reduce the effective password length to 14) */
251 encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE);
253 SamOEMhash(new_lm_password.data, old_nt_hash, 516);
254 E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
256 ZERO_STRUCT(new_lm_password);
257 ZERO_STRUCT(old_lanman_hash_enc);
260 encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE);
262 SamOEMhash(new_nt_password.data, old_nt_hash, 516);
263 E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
265 result = rpccli_samr_ChangePasswordUser2(cli, mem_ctx,
272 &old_lanman_hash_enc);
277 /* User change password given blobs */
279 NTSTATUS rpccli_samr_chng_pswd_auth_crap(struct rpc_pipe_client *cli,
281 const char *username,
282 DATA_BLOB new_nt_password_blob,
283 DATA_BLOB old_nt_hash_enc_blob,
284 DATA_BLOB new_lm_password_blob,
285 DATA_BLOB old_lm_hash_enc_blob)
287 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
288 struct samr_CryptPassword new_nt_password;
289 struct samr_CryptPassword new_lm_password;
290 struct samr_Password old_nt_hash_enc;
291 struct samr_Password old_lm_hash_enc;
292 struct lsa_String server, account;
293 char *srv_name_slash = NULL;
295 DEBUG(10,("rpccli_samr_chng_pswd_auth_crap\n"));
297 srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
298 if (!srv_name_slash) {
299 return NT_STATUS_NO_MEMORY;
302 init_lsa_String(&server, srv_name_slash);
303 init_lsa_String(&account, username);
305 memcpy(&new_nt_password.data, new_nt_password_blob.data, 516);
306 memcpy(&new_lm_password.data, new_lm_password_blob.data, 516);
307 memcpy(&old_nt_hash_enc.hash, old_nt_hash_enc_blob.data, 16);
308 memcpy(&old_lm_hash_enc.hash, old_lm_hash_enc_blob.data, 16);
310 result = rpccli_samr_ChangePasswordUser2(cli, mem_ctx,
322 /* change password 3 */
324 NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
326 const char *username,
327 const char *newpassword,
328 const char *oldpassword,
329 struct samr_DomInfo1 **dominfo1,
330 struct samr_ChangeReject **reject)
334 struct samr_CryptPassword new_nt_password;
335 struct samr_CryptPassword new_lm_password;
336 struct samr_Password old_nt_hash_enc;
337 struct samr_Password old_lanman_hash_enc;
339 uchar old_nt_hash[16];
340 uchar old_lanman_hash[16];
341 uchar new_nt_hash[16];
342 uchar new_lanman_hash[16];
344 struct lsa_String server, account;
345 char *srv_name_slash = NULL;
347 DEBUG(10,("rpccli_samr_chgpasswd_user3\n"));
349 srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
350 if (!srv_name_slash) {
351 return NT_STATUS_NO_MEMORY;
354 init_lsa_String(&server, srv_name_slash);
355 init_lsa_String(&account, username);
357 /* Calculate the MD4 hash (NT compatible) of the password */
358 E_md4hash(oldpassword, old_nt_hash);
359 E_md4hash(newpassword, new_nt_hash);
361 if (lp_client_lanman_auth() &&
362 E_deshash(newpassword, new_lanman_hash) &&
363 E_deshash(oldpassword, old_lanman_hash)) {
364 /* E_deshash returns false for 'long' passwords (> 14
365 DOS chars). This allows us to match Win2k, which
366 does not store a LM hash for these passwords (which
367 would reduce the effective password length to 14) */
369 encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE);
371 SamOEMhash(new_lm_password.data, old_nt_hash, 516);
372 E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
374 ZERO_STRUCT(new_lm_password);
375 ZERO_STRUCT(old_lanman_hash_enc);
378 encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE);
380 SamOEMhash(new_nt_password.data, old_nt_hash, 516);
381 E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
383 status = rpccli_samr_ChangePasswordUser3(cli, mem_ctx,
390 &old_lanman_hash_enc,
397 /* This function returns the bizzare set of (max_entries, max_size) required
398 for the QueryDisplayInfo RPC to actually work against a domain controller
399 with large (10k and higher) numbers of users. These values were
400 obtained by inspection using ethereal and NT4 running User Manager. */
402 void get_query_dispinfo_params(int loop_count, uint32 *max_entries,
422 default: /* loop_count >= 4 */
429 /* Lookup rids. Note that NT4 seems to crash if more than ~1000 rids are
430 looked up in one packet. */
432 NTSTATUS rpccli_samr_lookup_rids(struct rpc_pipe_client *cli,
434 POLICY_HND *domain_pol,
435 uint32 num_rids, uint32 *rids,
436 uint32 *num_names, char ***names,
439 prs_struct qbuf, rbuf;
440 SAMR_Q_LOOKUP_RIDS q;
441 SAMR_R_LOOKUP_RIDS r;
442 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
445 DEBUG(10,("cli_samr_lookup_rids\n"));
447 if (num_rids > 1000) {
448 DEBUG(2, ("cli_samr_lookup_rids: warning: NT4 can crash if "
449 "more than ~1000 rids are looked up at once.\n"));
455 /* Marshall data and send request */
457 init_samr_q_lookup_rids(mem_ctx, &q, domain_pol, 1000, num_rids, rids);
459 CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_LOOKUP_RIDS,
462 samr_io_q_lookup_rids,
463 samr_io_r_lookup_rids,
464 NT_STATUS_UNSUCCESSFUL);
466 /* Return output parameters */
470 if (!NT_STATUS_IS_OK(result) &&
471 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
474 if (r.num_names1 == 0) {
480 *num_names = r.num_names1;
481 *names = TALLOC_ARRAY(mem_ctx, char *, r.num_names1);
482 *name_types = TALLOC_ARRAY(mem_ctx, uint32, r.num_names1);
484 if ((*names == NULL) || (*name_types == NULL)) {
486 TALLOC_FREE(*name_types);
487 return NT_STATUS_NO_MEMORY;
490 for (i = 0; i < r.num_names1; i++) {
493 unistr2_to_ascii(tmp, &r.uni_name[i], sizeof(tmp));
494 (*names)[i] = talloc_strdup(mem_ctx, tmp);
495 (*name_types)[i] = r.type[i];
505 NTSTATUS rpccli_samr_set_userinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
506 const POLICY_HND *user_pol, uint16 switch_value,
507 DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
509 prs_struct qbuf, rbuf;
510 SAMR_Q_SET_USERINFO q;
511 SAMR_R_SET_USERINFO r;
512 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
514 DEBUG(10,("cli_samr_set_userinfo\n"));
519 if (!sess_key->length) {
520 DEBUG(1, ("No user session key\n"));
521 return NT_STATUS_NO_USER_SESSION_KEY;
524 /* Initialise parse structures */
526 prs_init(&qbuf, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
527 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
529 /* Marshall data and send request */
533 init_samr_q_set_userinfo(&q, user_pol, sess_key, switch_value,
536 CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_USERINFO,
539 samr_io_q_set_userinfo,
540 samr_io_r_set_userinfo,
541 NT_STATUS_UNSUCCESSFUL);
543 /* Return output parameters */
545 if (!NT_STATUS_IS_OK(result = r.status)) {
556 NTSTATUS rpccli_samr_set_userinfo2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
557 const POLICY_HND *user_pol, uint16 switch_value,
558 DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
560 prs_struct qbuf, rbuf;
561 SAMR_Q_SET_USERINFO2 q;
562 SAMR_R_SET_USERINFO2 r;
563 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
565 DEBUG(10,("cli_samr_set_userinfo2\n"));
567 if (!sess_key->length) {
568 DEBUG(1, ("No user session key\n"));
569 return NT_STATUS_NO_USER_SESSION_KEY;
575 /* Marshall data and send request */
577 init_samr_q_set_userinfo2(&q, user_pol, sess_key, switch_value, ctr);
579 CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_USERINFO2,
582 samr_io_q_set_userinfo2,
583 samr_io_r_set_userinfo2,
584 NT_STATUS_UNSUCCESSFUL);
586 /* Return output parameters */
588 if (!NT_STATUS_IS_OK(result = r.status)) {