Remove unused marshalling for SAMR_SET_ALIASINFO.
[kai/samba.git] / source3 / rpc_client / cli_samr.c
1 /* 
2    Unix SMB/CIFS implementation.
3    RPC pipe client
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.
8    
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.
13    
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.
18    
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/>.
21 */
22
23 #include "includes.h"
24
25 static void init_lsa_String(struct lsa_String *name, const char *s)
26 {
27         name->string = s;
28 }
29
30 /* Query user info */
31
32 NTSTATUS rpccli_samr_query_userinfo(struct rpc_pipe_client *cli,
33                                     TALLOC_CTX *mem_ctx,
34                                     const POLICY_HND *user_pol,
35                                     uint16 switch_value, 
36                                     SAM_USERINFO_CTR **ctr)
37 {
38         prs_struct qbuf, rbuf;
39         SAMR_Q_QUERY_USERINFO q;
40         SAMR_R_QUERY_USERINFO r;
41         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
42
43         DEBUG(10,("cli_samr_query_userinfo\n"));
44
45         ZERO_STRUCT(q);
46         ZERO_STRUCT(r);
47
48         /* Marshall data and send request */
49
50         init_samr_q_query_userinfo(&q, user_pol, switch_value);
51
52         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_USERINFO,
53                 q, r,
54                 qbuf, rbuf,
55                 samr_io_q_query_userinfo,
56                 samr_io_r_query_userinfo,
57                 NT_STATUS_UNSUCCESSFUL); 
58
59         /* Return output parameters */
60
61         result = r.status;
62         *ctr = r.ctr;
63
64         return result;
65 }
66
67 /* Set group info */
68
69 NTSTATUS rpccli_samr_set_groupinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
70                                 POLICY_HND *group_pol, GROUP_INFO_CTR *ctr)
71 {
72         prs_struct qbuf, rbuf;
73         SAMR_Q_SET_GROUPINFO q;
74         SAMR_R_SET_GROUPINFO r;
75         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
76
77         DEBUG(10,("cli_samr_set_groupinfo\n"));
78
79         ZERO_STRUCT(q);
80         ZERO_STRUCT(r);
81
82         /* Marshall data and send request */
83
84         init_samr_q_set_groupinfo(&q, group_pol, ctr);
85
86         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_GROUPINFO,
87                 q, r,
88                 qbuf, rbuf,
89                 samr_io_q_set_groupinfo,
90                 samr_io_r_set_groupinfo,
91                 NT_STATUS_UNSUCCESSFUL); 
92
93         /* Return output parameters */
94
95         result = r.status;
96
97         return result;
98 }
99
100 /* Query group info */
101
102 NTSTATUS rpccli_samr_query_groupinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
103                                   POLICY_HND *group_pol, uint32 info_level, 
104                                   GROUP_INFO_CTR **ctr)
105 {
106         prs_struct qbuf, rbuf;
107         SAMR_Q_QUERY_GROUPINFO q;
108         SAMR_R_QUERY_GROUPINFO r;
109         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
110
111         DEBUG(10,("cli_samr_query_groupinfo\n"));
112
113         ZERO_STRUCT(q);
114         ZERO_STRUCT(r);
115
116         /* Marshall data and send request */
117
118         init_samr_q_query_groupinfo(&q, group_pol, info_level);
119
120         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_GROUPINFO,
121                 q, r,
122                 qbuf, rbuf,
123                 samr_io_q_query_groupinfo,
124                 samr_io_r_query_groupinfo,
125                 NT_STATUS_UNSUCCESSFUL); 
126
127         *ctr = r.ctr;
128
129         /* Return output parameters */
130
131         result = r.status;
132
133         return result;
134 }
135
136 /* Query user groups */
137
138 NTSTATUS rpccli_samr_query_usergroups(struct rpc_pipe_client *cli,
139                                       TALLOC_CTX *mem_ctx, 
140                                       POLICY_HND *user_pol,
141                                       uint32 *num_groups, 
142                                       DOM_GID **gid)
143 {
144         prs_struct qbuf, rbuf;
145         SAMR_Q_QUERY_USERGROUPS q;
146         SAMR_R_QUERY_USERGROUPS r;
147         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
148
149         DEBUG(10,("cli_samr_query_usergroups\n"));
150
151         ZERO_STRUCT(q);
152         ZERO_STRUCT(r);
153
154         /* Marshall data and send request */
155
156         init_samr_q_query_usergroups(&q, user_pol);
157
158         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_USERGROUPS,
159                 q, r,
160                 qbuf, rbuf,
161                 samr_io_q_query_usergroups,
162                 samr_io_r_query_usergroups,
163                 NT_STATUS_UNSUCCESSFUL); 
164
165         /* Return output parameters */
166
167         if (NT_STATUS_IS_OK(result = r.status)) {
168                 *num_groups = r.num_entries;
169                 *gid = r.gid;
170         }
171
172         return result;
173 }
174
175 /**
176  * Enumerate domain users
177  *
178  * @param cli client state structure
179  * @param mem_ctx talloc context
180  * @param pol opened domain policy handle
181  * @param start_idx starting index of enumeration, returns context for
182                     next enumeration
183  * @param acb_mask account control bit mask (to enumerate some particular
184  *                 kind of accounts)
185  * @param size max acceptable size of response
186  * @param dom_users returned array of domain user names
187  * @param rids returned array of domain user RIDs
188  * @param num_dom_users numer returned entries
189  * 
190  * @return NTSTATUS returned in rpc response
191  **/
192
193 NTSTATUS rpccli_samr_enum_dom_users(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
194                                  POLICY_HND *pol, uint32 *start_idx, uint32 acb_mask,
195                                  uint32 size, char ***dom_users, uint32 **rids,
196                                  uint32 *num_dom_users)
197 {
198         prs_struct qbuf;
199         prs_struct rbuf;
200         SAMR_Q_ENUM_DOM_USERS q;
201         SAMR_R_ENUM_DOM_USERS r;
202         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
203         int i;
204         
205         DEBUG(10,("cli_samr_enum_dom_users starting at index %u\n", (unsigned int)*start_idx));
206
207         ZERO_STRUCT(q);
208         ZERO_STRUCT(r);
209         
210         /* always init this */
211         *num_dom_users = 0;
212         
213         /* Fill query structure with parameters */
214
215         init_samr_q_enum_dom_users(&q, pol, *start_idx, acb_mask, size);
216         
217         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ENUM_DOM_USERS,
218                 q, r,
219                 qbuf, rbuf,
220                 samr_io_q_enum_dom_users,
221                 samr_io_r_enum_dom_users,
222                 NT_STATUS_UNSUCCESSFUL); 
223
224         result = r.status;
225
226         if (!NT_STATUS_IS_OK(result) &&
227             NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES))
228                 goto done;
229         
230         *start_idx = r.next_idx;
231         *num_dom_users = r.num_entries2;
232
233         if (r.num_entries2) {
234                 /* allocate memory needed to return received data */    
235                 *rids = TALLOC_ARRAY(mem_ctx, uint32, r.num_entries2);
236                 if (!*rids) {
237                         DEBUG(0, ("Error in cli_samr_enum_dom_users(): out of memory\n"));
238                         return NT_STATUS_NO_MEMORY;
239                 }
240                 
241                 *dom_users = TALLOC_ARRAY(mem_ctx, char*, r.num_entries2);
242                 if (!*dom_users) {
243                         DEBUG(0, ("Error in cli_samr_enum_dom_users(): out of memory\n"));
244                         return NT_STATUS_NO_MEMORY;
245                 }
246                 
247                 /* fill output buffers with rpc response */
248                 for (i = 0; i < r.num_entries2; i++) {
249                         fstring conv_buf;
250                         
251                         (*rids)[i] = r.sam[i].rid;
252                         unistr2_to_ascii(conv_buf, &(r.uni_acct_name[i]), sizeof(conv_buf));
253                         (*dom_users)[i] = talloc_strdup(mem_ctx, conv_buf);
254                 }
255         }
256         
257 done:
258         return result;
259 }
260
261 /* Enumerate domain groups */
262
263 NTSTATUS rpccli_samr_enum_dom_groups(struct rpc_pipe_client *cli,
264                                      TALLOC_CTX *mem_ctx, 
265                                      POLICY_HND *pol, uint32 *start_idx, 
266                                      uint32 size, struct acct_info **dom_groups,
267                                      uint32 *num_dom_groups)
268 {
269         prs_struct qbuf, rbuf;
270         SAMR_Q_ENUM_DOM_GROUPS q;
271         SAMR_R_ENUM_DOM_GROUPS r;
272         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
273         uint32 name_idx, i;
274
275         DEBUG(10,("cli_samr_enum_dom_groups starting at index %u\n", (unsigned int)*start_idx));
276
277         ZERO_STRUCT(q);
278         ZERO_STRUCT(r);
279
280         /* Marshall data and send request */
281
282         init_samr_q_enum_dom_groups(&q, pol, *start_idx, size);
283
284         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ENUM_DOM_GROUPS,
285                 q, r,
286                 qbuf, rbuf,
287                 samr_io_q_enum_dom_groups,
288                 samr_io_r_enum_dom_groups,
289                 NT_STATUS_UNSUCCESSFUL); 
290
291         /* Return output parameters */
292
293         result = r.status;
294
295         if (!NT_STATUS_IS_OK(result) &&
296             NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES))
297                 goto done;
298
299         *num_dom_groups = r.num_entries2;
300
301         if (*num_dom_groups == 0)
302                 goto done;
303
304         if (!((*dom_groups) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_dom_groups))) {
305                 result = NT_STATUS_NO_MEMORY;
306                 goto done;
307         }
308
309         memset(*dom_groups, 0, sizeof(struct acct_info) * (*num_dom_groups));
310
311         name_idx = 0;
312
313         for (i = 0; i < *num_dom_groups; i++) {
314
315                 (*dom_groups)[i].rid = r.sam[i].rid;
316
317                 if (r.sam[i].hdr_name.buffer) {
318                         unistr2_to_ascii((*dom_groups)[i].acct_name,
319                                          &r.uni_grp_name[name_idx],
320                                          sizeof((*dom_groups)[i].acct_name));
321                         name_idx++;
322                 }
323
324                 *start_idx = r.next_idx;
325         }
326
327  done:
328         return result;
329 }
330
331 /* Enumerate domain groups */
332
333 NTSTATUS rpccli_samr_enum_als_groups(struct rpc_pipe_client *cli,
334                                      TALLOC_CTX *mem_ctx, 
335                                      POLICY_HND *pol, uint32 *start_idx, 
336                                      uint32 size, struct acct_info **dom_aliases,
337                                      uint32 *num_dom_aliases)
338 {
339         prs_struct qbuf, rbuf;
340         SAMR_Q_ENUM_DOM_ALIASES q;
341         SAMR_R_ENUM_DOM_ALIASES r;
342         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
343         uint32 name_idx, i;
344
345         DEBUG(10,("cli_samr_enum_als_groups starting at index %u\n", (unsigned int)*start_idx));
346
347         ZERO_STRUCT(q);
348         ZERO_STRUCT(r);
349
350         /* Marshall data and send request */
351
352         init_samr_q_enum_dom_aliases(&q, pol, *start_idx, size);
353
354         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ENUM_DOM_ALIASES,
355                 q, r,
356                 qbuf, rbuf,
357                 samr_io_q_enum_dom_aliases,
358                 samr_io_r_enum_dom_aliases,
359                 NT_STATUS_UNSUCCESSFUL); 
360
361         /* Return output parameters */
362
363         result = r.status;
364
365         if (!NT_STATUS_IS_OK(result) &&
366             NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES)) {
367                 goto done;
368         }
369
370         *num_dom_aliases = r.num_entries2;
371
372         if (*num_dom_aliases == 0)
373                 goto done;
374
375         if (!((*dom_aliases) = TALLOC_ARRAY(mem_ctx, struct acct_info, *num_dom_aliases))) {
376                 result = NT_STATUS_NO_MEMORY;
377                 goto done;
378         }
379
380         memset(*dom_aliases, 0, sizeof(struct acct_info) * *num_dom_aliases);
381
382         name_idx = 0;
383
384         for (i = 0; i < *num_dom_aliases; i++) {
385
386                 (*dom_aliases)[i].rid = r.sam[i].rid;
387
388                 if (r.sam[i].hdr_name.buffer) {
389                         unistr2_to_ascii((*dom_aliases)[i].acct_name,
390                                          &r.uni_grp_name[name_idx],
391                                          sizeof((*dom_aliases)[i].acct_name));
392                         name_idx++;
393                 }
394
395                 *start_idx = r.next_idx;
396         }
397
398  done:
399         return result;
400 }
401
402 /* Query alias info */
403
404 NTSTATUS rpccli_samr_query_alias_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
405                                    POLICY_HND *alias_pol, uint16 switch_value,
406                                    ALIAS_INFO_CTR *ctr)
407 {
408         prs_struct qbuf, rbuf;
409         SAMR_Q_QUERY_ALIASINFO q;
410         SAMR_R_QUERY_ALIASINFO r;
411         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
412
413         DEBUG(10,("cli_samr_query_alias_info\n"));
414
415         ZERO_STRUCT(q);
416         ZERO_STRUCT(r);
417
418         /* Marshall data and send request */
419
420         init_samr_q_query_aliasinfo(&q, alias_pol, switch_value);
421
422         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_ALIASINFO,
423                 q, r,
424                 qbuf, rbuf,
425                 samr_io_q_query_aliasinfo,
426                 samr_io_r_query_aliasinfo,
427                 NT_STATUS_UNSUCCESSFUL); 
428
429         /* Return output parameters */
430
431         if (!NT_STATUS_IS_OK(result = r.status)) {
432                 goto done;
433         }
434
435         *ctr = *r.ctr;
436
437   done:
438
439         return result;
440 }
441
442 /* User change password */
443
444 NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
445                                     TALLOC_CTX *mem_ctx,
446                                     const char *username,
447                                     const char *newpassword,
448                                     const char *oldpassword)
449 {
450         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
451         struct samr_CryptPassword new_nt_password;
452         struct samr_CryptPassword new_lm_password;
453         struct samr_Password old_nt_hash_enc;
454         struct samr_Password old_lanman_hash_enc;
455
456         uchar old_nt_hash[16];
457         uchar old_lanman_hash[16];
458         uchar new_nt_hash[16];
459         uchar new_lanman_hash[16];
460         struct lsa_String server, account;
461         char *srv_name_slash = NULL;
462
463         DEBUG(10,("rpccli_samr_chgpasswd_user\n"));
464
465         init_lsa_String(&server, srv_name_slash);
466         init_lsa_String(&account, username);
467
468         srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
469         if (!srv_name_slash) {
470                 return NT_STATUS_NO_MEMORY;
471         }
472
473         /* Calculate the MD4 hash (NT compatible) of the password */
474         E_md4hash(oldpassword, old_nt_hash);
475         E_md4hash(newpassword, new_nt_hash);
476
477         if (lp_client_lanman_auth() &&
478             E_deshash(newpassword, new_lanman_hash) &&
479             E_deshash(oldpassword, old_lanman_hash)) {
480                 /* E_deshash returns false for 'long' passwords (> 14
481                    DOS chars).  This allows us to match Win2k, which
482                    does not store a LM hash for these passwords (which
483                    would reduce the effective password length to 14) */
484
485                 encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE);
486
487                 SamOEMhash(new_lm_password.data, old_nt_hash, 516);
488                 E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
489         } else {
490                 ZERO_STRUCT(new_lm_password);
491                 ZERO_STRUCT(old_lanman_hash_enc);
492         }
493
494         encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE);
495
496         SamOEMhash(new_nt_password.data, old_nt_hash, 516);
497         E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
498
499         result = rpccli_samr_ChangePasswordUser2(cli, mem_ctx,
500                                                  &server,
501                                                  &account,
502                                                  &new_nt_password,
503                                                  &old_nt_hash_enc,
504                                                  true,
505                                                  &new_lm_password,
506                                                  &old_lanman_hash_enc);
507
508         return result;
509 }
510
511 /* User change password given blobs */
512
513 NTSTATUS rpccli_samr_chng_pswd_auth_crap(struct rpc_pipe_client *cli,
514                                          TALLOC_CTX *mem_ctx,
515                                          const char *username,
516                                          DATA_BLOB new_nt_password_blob,
517                                          DATA_BLOB old_nt_hash_enc_blob,
518                                          DATA_BLOB new_lm_password_blob,
519                                          DATA_BLOB old_lm_hash_enc_blob)
520 {
521         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
522         struct samr_CryptPassword new_nt_password;
523         struct samr_CryptPassword new_lm_password;
524         struct samr_Password old_nt_hash_enc;
525         struct samr_Password old_lm_hash_enc;
526         struct lsa_String server, account;
527         char *srv_name_slash = NULL;
528
529         DEBUG(10,("rpccli_samr_chng_pswd_auth_crap\n"));
530
531         srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
532         if (!srv_name_slash) {
533                 return NT_STATUS_NO_MEMORY;
534         }
535
536         init_lsa_String(&server, srv_name_slash);
537         init_lsa_String(&account, username);
538
539         memcpy(&new_nt_password.data, new_nt_password_blob.data, 516);
540         memcpy(&new_lm_password.data, new_lm_password_blob.data, 516);
541         memcpy(&old_nt_hash_enc.hash, old_nt_hash_enc_blob.data, 16);
542         memcpy(&old_lm_hash_enc.hash, old_lm_hash_enc_blob.data, 16);
543
544         result = rpccli_samr_ChangePasswordUser2(cli, mem_ctx,
545                                                  &server,
546                                                  &account,
547                                                  &new_nt_password,
548                                                  &old_nt_hash_enc,
549                                                  true,
550                                                  &new_lm_password,
551                                                  &old_lm_hash_enc);
552         return result;
553 }
554
555
556 /* change password 3 */
557
558 NTSTATUS rpccli_samr_chgpasswd3(struct rpc_pipe_client *cli,
559                                 TALLOC_CTX *mem_ctx,
560                                 const char *username,
561                                 const char *newpassword,
562                                 const char *oldpassword,
563                                 struct samr_DomInfo1 **dominfo1,
564                                 struct samr_ChangeReject **reject)
565 {
566         NTSTATUS status;
567
568         struct samr_CryptPassword new_nt_password;
569         struct samr_CryptPassword new_lm_password;
570         struct samr_Password old_nt_hash_enc;
571         struct samr_Password old_lanman_hash_enc;
572
573         uchar old_nt_hash[16];
574         uchar old_lanman_hash[16];
575         uchar new_nt_hash[16];
576         uchar new_lanman_hash[16];
577
578         struct lsa_String server, account;
579         char *srv_name_slash = NULL;
580
581         DEBUG(10,("rpccli_samr_chgpasswd_user3\n"));
582
583         srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
584         if (!srv_name_slash) {
585                 return NT_STATUS_NO_MEMORY;
586         }
587
588         init_lsa_String(&server, srv_name_slash);
589         init_lsa_String(&account, username);
590
591         /* Calculate the MD4 hash (NT compatible) of the password */
592         E_md4hash(oldpassword, old_nt_hash);
593         E_md4hash(newpassword, new_nt_hash);
594
595         if (lp_client_lanman_auth() &&
596             E_deshash(newpassword, new_lanman_hash) &&
597             E_deshash(oldpassword, old_lanman_hash)) {
598                 /* E_deshash returns false for 'long' passwords (> 14
599                    DOS chars).  This allows us to match Win2k, which
600                    does not store a LM hash for these passwords (which
601                    would reduce the effective password length to 14) */
602
603                 encode_pw_buffer(new_lm_password.data, newpassword, STR_UNICODE);
604
605                 SamOEMhash(new_lm_password.data, old_nt_hash, 516);
606                 E_old_pw_hash(new_nt_hash, old_lanman_hash, old_lanman_hash_enc.hash);
607         } else {
608                 ZERO_STRUCT(new_lm_password);
609                 ZERO_STRUCT(old_lanman_hash_enc);
610         }
611
612         encode_pw_buffer(new_nt_password.data, newpassword, STR_UNICODE);
613
614         SamOEMhash(new_nt_password.data, old_nt_hash, 516);
615         E_old_pw_hash(new_nt_hash, old_nt_hash, old_nt_hash_enc.hash);
616
617         status = rpccli_samr_ChangePasswordUser3(cli, mem_ctx,
618                                                  &server,
619                                                  &account,
620                                                  &new_nt_password,
621                                                  &old_nt_hash_enc,
622                                                  true,
623                                                  &new_lm_password,
624                                                  &old_lanman_hash_enc,
625                                                  NULL,
626                                                  dominfo1,
627                                                  reject);
628         return status;
629 }
630
631 /* This function returns the bizzare set of (max_entries, max_size) required
632    for the QueryDisplayInfo RPC to actually work against a domain controller
633    with large (10k and higher) numbers of users.  These values were 
634    obtained by inspection using ethereal and NT4 running User Manager. */
635
636 void get_query_dispinfo_params(int loop_count, uint32 *max_entries,
637                                uint32 *max_size)
638 {
639         switch(loop_count) {
640         case 0:
641                 *max_entries = 512;
642                 *max_size = 16383;
643                 break;
644         case 1:
645                 *max_entries = 1024;
646                 *max_size = 32766;
647                 break;
648         case 2:
649                 *max_entries = 2048;
650                 *max_size = 65532;
651                 break;
652         case 3:
653                 *max_entries = 4096;
654                 *max_size = 131064;
655                 break;
656         default:              /* loop_count >= 4 */
657                 *max_entries = 4096;
658                 *max_size = 131071;
659                 break;
660         }
661 }                    
662
663 /* Query display info */
664
665 NTSTATUS rpccli_samr_query_dispinfo(struct rpc_pipe_client *cli,
666                                     TALLOC_CTX *mem_ctx, 
667                                     POLICY_HND *domain_pol, uint32 *start_idx,
668                                     uint16 switch_value, uint32 *num_entries,
669                                     uint32 max_entries, uint32 max_size,
670                                     SAM_DISPINFO_CTR *ctr)
671 {
672         prs_struct qbuf, rbuf;
673         SAMR_Q_QUERY_DISPINFO q;
674         SAMR_R_QUERY_DISPINFO r;
675         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
676
677         DEBUG(10,("cli_samr_query_dispinfo for start_idx = %u\n", *start_idx));
678
679         ZERO_STRUCT(q);
680         ZERO_STRUCT(r);
681
682         *num_entries = 0;
683
684         /* Marshall data and send request */
685
686         init_samr_q_query_dispinfo(&q, domain_pol, switch_value,
687                                    *start_idx, max_entries, max_size);
688
689         r.ctr = ctr;
690
691         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_DISPINFO,
692                 q, r,
693                 qbuf, rbuf,
694                 samr_io_q_query_dispinfo,
695                 samr_io_r_query_dispinfo,
696                 NT_STATUS_UNSUCCESSFUL); 
697
698         /* Return output parameters */
699
700         result = r.status;
701
702         if (!NT_STATUS_IS_OK(result) &&
703             NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES)) {
704                 goto done;
705         }
706
707         *num_entries = r.num_entries;
708         *start_idx += r.num_entries;  /* No next_idx in this structure! */
709
710  done:
711         return result;
712 }
713
714 /* Lookup rids.  Note that NT4 seems to crash if more than ~1000 rids are
715    looked up in one packet. */
716
717 NTSTATUS rpccli_samr_lookup_rids(struct rpc_pipe_client *cli,
718                                  TALLOC_CTX *mem_ctx, 
719                                  POLICY_HND *domain_pol,
720                                  uint32 num_rids, uint32 *rids, 
721                                  uint32 *num_names, char ***names,
722                                  uint32 **name_types)
723 {
724         prs_struct qbuf, rbuf;
725         SAMR_Q_LOOKUP_RIDS q;
726         SAMR_R_LOOKUP_RIDS r;
727         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
728         uint32 i;
729
730         DEBUG(10,("cli_samr_lookup_rids\n"));
731
732         if (num_rids > 1000) {
733                 DEBUG(2, ("cli_samr_lookup_rids: warning: NT4 can crash if "
734                           "more than ~1000 rids are looked up at once.\n"));
735         }
736
737         ZERO_STRUCT(q);
738         ZERO_STRUCT(r);
739
740         /* Marshall data and send request */
741
742         init_samr_q_lookup_rids(mem_ctx, &q, domain_pol, 1000, num_rids, rids);
743
744         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_LOOKUP_RIDS,
745                 q, r,
746                 qbuf, rbuf,
747                 samr_io_q_lookup_rids,
748                 samr_io_r_lookup_rids,
749                 NT_STATUS_UNSUCCESSFUL); 
750
751         /* Return output parameters */
752
753         result = r.status;
754
755         if (!NT_STATUS_IS_OK(result) &&
756             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
757                 goto done;
758
759         if (r.num_names1 == 0) {
760                 *num_names = 0;
761                 *names = NULL;
762                 goto done;
763         }
764
765         *num_names = r.num_names1;
766         *names = TALLOC_ARRAY(mem_ctx, char *, r.num_names1);
767         *name_types = TALLOC_ARRAY(mem_ctx, uint32, r.num_names1);
768
769         if ((*names == NULL) || (*name_types == NULL)) {
770                 TALLOC_FREE(*names);
771                 TALLOC_FREE(*name_types);
772                 return NT_STATUS_NO_MEMORY;
773         }
774
775         for (i = 0; i < r.num_names1; i++) {
776                 fstring tmp;
777
778                 unistr2_to_ascii(tmp, &r.uni_name[i], sizeof(tmp));
779                 (*names)[i] = talloc_strdup(mem_ctx, tmp);
780                 (*name_types)[i] = r.type[i];
781         }
782
783  done:
784
785         return result;
786 }
787
788 /* Lookup names */
789
790 NTSTATUS rpccli_samr_lookup_names(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
791                                POLICY_HND *domain_pol, uint32 flags,
792                                uint32 num_names, const char **names,
793                                uint32 *num_rids, uint32 **rids,
794                                uint32 **rid_types)
795 {
796         prs_struct qbuf, rbuf;
797         SAMR_Q_LOOKUP_NAMES q;
798         SAMR_R_LOOKUP_NAMES r;
799         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
800         uint32 i;
801
802         DEBUG(10,("cli_samr_lookup_names\n"));
803
804         ZERO_STRUCT(q);
805         ZERO_STRUCT(r);
806
807         /* Marshall data and send request */
808
809         init_samr_q_lookup_names(mem_ctx, &q, domain_pol, flags,
810                                  num_names, names);
811
812         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_LOOKUP_NAMES,
813                 q, r,
814                 qbuf, rbuf,
815                 samr_io_q_lookup_names,
816                 samr_io_r_lookup_names,
817                 NT_STATUS_UNSUCCESSFUL); 
818
819         /* Return output parameters */
820
821         if (!NT_STATUS_IS_OK(result = r.status)) {
822                 goto done;
823         }
824
825         if (r.num_rids1 == 0) {
826                 *num_rids = 0;
827                 goto done;
828         }
829
830         *num_rids = r.num_rids1;
831         *rids = TALLOC_ARRAY(mem_ctx, uint32, r.num_rids1);
832         *rid_types = TALLOC_ARRAY(mem_ctx, uint32, r.num_rids1);
833
834         if ((*rids == NULL) || (*rid_types == NULL)) {
835                 TALLOC_FREE(*rids);
836                 TALLOC_FREE(*rid_types);
837                 return NT_STATUS_NO_MEMORY;
838         }
839
840         for (i = 0; i < r.num_rids1; i++) {
841                 (*rids)[i] = r.rids[i];
842                 (*rid_types)[i] = r.types[i];
843         }
844
845  done:
846
847         return result;
848 }
849
850 /* Set userinfo */
851
852 NTSTATUS rpccli_samr_set_userinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
853                                const POLICY_HND *user_pol, uint16 switch_value,
854                                DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
855 {
856         prs_struct qbuf, rbuf;
857         SAMR_Q_SET_USERINFO q;
858         SAMR_R_SET_USERINFO r;
859         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
860
861         DEBUG(10,("cli_samr_set_userinfo\n"));
862
863         ZERO_STRUCT(q);
864         ZERO_STRUCT(r);
865
866         if (!sess_key->length) {
867                 DEBUG(1, ("No user session key\n"));
868                 return NT_STATUS_NO_USER_SESSION_KEY;
869         }
870
871         /* Initialise parse structures */
872
873         prs_init(&qbuf, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
874         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
875
876         /* Marshall data and send request */
877
878         q.ctr = ctr;
879
880         init_samr_q_set_userinfo(&q, user_pol, sess_key, switch_value, 
881                                  ctr->info.id);
882
883         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_USERINFO,
884                 q, r,
885                 qbuf, rbuf,
886                 samr_io_q_set_userinfo,
887                 samr_io_r_set_userinfo,
888                 NT_STATUS_UNSUCCESSFUL); 
889
890         /* Return output parameters */
891
892         if (!NT_STATUS_IS_OK(result = r.status)) {
893                 goto done;
894         }
895
896  done:
897
898         return result;
899 }
900
901 /* Set userinfo2 */
902
903 NTSTATUS rpccli_samr_set_userinfo2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
904                                    const POLICY_HND *user_pol, uint16 switch_value,
905                                 DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
906 {
907         prs_struct qbuf, rbuf;
908         SAMR_Q_SET_USERINFO2 q;
909         SAMR_R_SET_USERINFO2 r;
910         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
911
912         DEBUG(10,("cli_samr_set_userinfo2\n"));
913
914         if (!sess_key->length) {
915                 DEBUG(1, ("No user session key\n"));
916                 return NT_STATUS_NO_USER_SESSION_KEY;
917         }
918
919         ZERO_STRUCT(q);
920         ZERO_STRUCT(r);
921
922         /* Marshall data and send request */
923
924         init_samr_q_set_userinfo2(&q, user_pol, sess_key, switch_value, ctr);
925
926         CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_USERINFO2,
927                 q, r,
928                 qbuf, rbuf,
929                 samr_io_q_set_userinfo2,
930                 samr_io_r_set_userinfo2,
931                 NT_STATUS_UNSUCCESSFUL); 
932
933         /* Return output parameters */
934
935         if (!NT_STATUS_IS_OK(result = r.status)) {
936                 goto done;
937         }
938
939  done:
940
941         return result;
942 }