xref: /titanic_41/usr/src/uts/common/smbsrv/ndl/samrpc.ndl (revision 0f1702c5201310f0529cd5abb77652e5e9b241b6)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#ifndef _MLSVC_SAM_NDL_
27#define _MLSVC_SAM_NDL_
28
29/*
30 * Security Accounts Manager RPC (SAMR) interface definition.
31 */
32
33#include "ndrtypes.ndl"
34
35
36#define SAMR_OPNUM_ConnectAnon			0x00
37#define SAMR_OPNUM_CloseHandle			0x01
38#define SAMR_OPNUM_QuerySecObject		0x03
39#define SAMR_OPNUM_LookupDomain			0x05
40#define SAMR_OPNUM_EnumLocalDomains		0x06
41#define SAMR_OPNUM_OpenDomain			0x07
42#define SAMR_OPNUM_QueryDomainInfo		0x08
43#define SAMR_OPNUM_CreateDomainGroup		0x0a
44#define SAMR_OPNUM_QueryDomainGroups		0x0b
45#define SAMR_OPNUM_EnumDomainUsers		0x0d
46#define SAMR_OPNUM_CreateDomainAlias		0x0e
47#define SAMR_OPNUM_EnumDomainAliases		0x0f
48#define SAMR_OPNUM_LookupIds			0x10
49#define SAMR_OPNUM_LookupNames			0x11
50#define SAMR_OPNUM_LookupDomainIds		0x12
51#define SAMR_OPNUM_OpenGroup			0x13
52#define SAMR_OPNUM_QueryGroupInfo		0x14
53#define SAMR_OPNUM_StoreGroupInfo		0x15
54#define SAMR_OPNUM_AddGroupMember		0x16
55#define SAMR_OPNUM_DeleteDomainGroup		0x17
56#define SAMR_OPNUM_DeleteGroupMember		0x18
57#define SAMR_OPNUM_ListGroupMembers		0x19
58#define SAMR_OPNUM_OpenAlias			0x1b
59#define SAMR_OPNUM_QueryAliasInfo		0x1c
60#define SAMR_OPNUM_SetAliasInfo			0x1d
61#define SAMR_OPNUM_DeleteDomainAlias		0x1e
62#define SAMR_OPNUM_AddAliasMember		0x1f
63#define SAMR_OPNUM_DeleteAliasMember		0x20
64#define SAMR_OPNUM_QueryAliasMember		0x21
65#define SAMR_OPNUM_OpenUser			0x22
66#define SAMR_OPNUM_DeleteUser			0x23
67#define SAMR_OPNUM_QueryUserInfo		0x24
68#define SAMR_OPNUM_QueryUserGroups		0x27
69#define SAMR_OPNUM_QueryDispInfo		0x28	/* QueryDispInfo1 */
70#define SAMR_OPNUM_GetUserPwInfo		0x2c
71#define SAMR_OPNUM_EnumDomainGroups		0x30	/* QueryDispInfo3 */
72#define SAMR_OPNUM_CreateUser			0x32
73#define SAMR_OPNUM_QueryDispInfo4		0x33
74#define SAMR_OPNUM_AddMultiAliasMember		0x34
75#define SAMR_OPNUM_ChangeUserPasswd		0x37
76#define SAMR_OPNUM_GetDomainPwInfo		0x38
77#define SAMR_OPNUM_Connect			0x39
78#define SAMR_OPNUM_SetUserInfo			0x3a
79#define SAMR_OPNUM_Connect3			0x3e
80#define SAMR_OPNUM_Connect4			0x40
81
82
83/*
84 * UNION_INFO_ENT is intended to simplify adding new entries to a union.
85 * If the entry structures are named using the form samr_QueryUserInfoX,
86 * where X is the sitch_value, you can just add a single line. Note
87 * that you must also update the fixup function in mlsvc_sam.c.
88 */
89#define UNION_INFO_ENT(N,NAME) CASE(N) struct NAME##N info##N
90
91
92/*
93 * Sam account flags used when creating an account. These flags seem
94 * to be very similar to the USER_INFO_X flags (UF_XXX) in lmaccess.h
95 * but the values are different.
96 */
97#define SAMR_AF_ACCOUNTDISABLE			0x0001
98#define SAMR_AF_HOMEDIR_REQUIRED		0x0002
99#define SAMR_AF_PASSWD_NOTREQD			0x0004
100#define SAMR_AF_TEMP_DUPLICATE_ACCOUNT		0x0008
101#define SAMR_AF_NORMAL_ACCOUNT			0x0010
102#define SAMR_AF_MNS_LOGON_ACCOUNT		0x0020
103#define SAMR_AF_INTERDOMAIN_TRUST_ACCOUNT	0x0040
104#define SAMR_AF_WORKSTATION_TRUST_ACCOUNT	0x0080
105#define SAMR_AF_SERVER_TRUST_ACCOUNT		0x0100
106#define SAMR_AF_DONT_EXPIRE_PASSWD		0x0200
107#define SAMR_AF_ACCOUNT_AUTOLOCK		0x0400
108
109
110#define SAMR_AF_MACHINE_ACCOUNT_MASK	( \
111				SAMR_AF_INTERDOMAIN_TRUST_ACCOUNT \
112				| SAMR_AF_WORKSTATION_TRUST_ACCOUNT \
113				| SAMR_AF_SERVER_TRUST_ACCOUNT)
114
115#define SAMR_AF_ACCOUNT_TYPE_MASK	( \
116				SAMR_AF_TEMP_DUPLICATE_ACCOUNT \
117				| SAMR_AF_NORMAL_ACCOUNT \
118				| SAMR_AF_INTERDOMAIN_TRUST_ACCOUNT \
119				| SAMR_AF_WORKSTATION_TRUST_ACCOUNT \
120				| SAMR_AF_SERVER_TRUST_ACCOUNT)
121
122
123/*
124 * specific access rights which can be used in OpenAlias.
125 * extracted from Ethereal network analyzer
126 */
127#define SAMR_ALIAS_ACCESS_SET_INFO		0x00000010
128#define SAMR_ALIAS_ACCESS_GET_INFO		0x00000008
129#define SAMR_ALIAS_ACCESS_GET_MEMBERS		0x00000004
130#define SAMR_ALIAS_ACCESS_DEL_MEMBER		0x00000002
131#define SAMR_ALIAS_ACCESS_ADD_MEMBER		0x00000001
132
133/*
134 * Definition for a SID. The ndl compiler does not allow a typedef of
135 * a structure containing variable size members.
136 */
137struct samr_sid {
138	BYTE		Revision;
139	BYTE		SubAuthCount;
140	BYTE		Authority[6];
141  SIZE_IS(SubAuthCount)
142	DWORD		SubAuthority[ANY_SIZE_ARRAY];
143};
144
145
146/*
147 * SAMR definition of a security_descriptor.
148 */
149struct samr_sec_desc {
150	BYTE Revision;
151	BYTE Sbz1;
152	WORD Control;
153	struct samr_sid *owner;
154	struct samr_sid *group;
155	struct samr_sid *sacl;
156	struct samr_sid *dacl;
157};
158
159
160/*
161 * Definition for a string. The length and allosize should be set to
162 * twice the string length (i.e. strlen(str) * 2). The runtime code
163 * will perform the appropriate string to a wide-char conversions,
164 * so str should point to a regular char * string.
165 */
166struct samr_string {
167	WORD		length;
168	WORD		allosize;
169	LPTSTR		str;
170};
171typedef struct samr_string samr_string_t;
172
173
174/*
175 * Alternative varying/conformant string definition - for
176 * non-null terminated strings. This definition must match
177 * ndr_vcbuf_t.
178 */
179struct samr_vcb {
180	/*
181	 * size_is (actually a copy of length_is) will
182	 * be inserted here by the marshalling library.
183	 */
184	DWORD vc_first_is;
185	DWORD vc_length_is;
186  SIZE_IS(vc_length_is)
187	WORD buffer[ANY_SIZE_ARRAY];
188};
189
190struct samr_vcbuf {
191	WORD wclen;
192	WORD wcsize;
193	struct samr_vcb *vcb;
194};
195typedef struct samr_vcbuf samr_vcbuf_t;
196
197CONTEXT_HANDLE(samr_handle) samr_handle_t;
198
199/*
200 * A long long, i.e. 64-bit, value.
201 */
202struct samr_quad {
203	DWORD low;
204	DWORD high;
205};
206typedef struct samr_quad samr_quad_t;
207
208
209/*
210 ***********************************************************************
211 * ConnectAnon. It looks like the SAM handle is identical to an LSA
212 * handle. See Connect.
213 ***********************************************************************
214 */
215OPERATION(SAMR_OPNUM_ConnectAnon)
216struct samr_ConnectAnon {
217	IN	DWORD *servername;
218	IN	DWORD access_mask;
219	OUT	samr_handle_t handle;
220	OUT	DWORD status;
221};
222
223
224/*
225 ***********************************************************************
226 * Connect. I'm not sure what the difference is between Connect and
227 * ConnectAnon but this call seems to work better than ConnectAnon.
228 ***********************************************************************
229 */
230OPERATION(SAMR_OPNUM_Connect)
231struct samr_Connect {
232	IN	LPTSTR servername;
233	IN	DWORD access_mask;
234	OUT	samr_handle_t handle;
235	OUT	DWORD status;
236};
237
238
239/*
240 ***********************************************************************
241 * SamrConnect3. A new form of connect first seen with Windows 2000.
242 * A new field has been added to the input request. Value: 0x00000002.
243 * I haven't looked at the Win2K response yet to see if it differs
244 * from SAMR_OPNUM_Connect.
245 ***********************************************************************
246 */
247OPERATION(SAMR_OPNUM_Connect3)
248struct samr_Connect3 {
249	IN	LPTSTR servername;
250	IN	DWORD unknown_02;
251	IN	DWORD access_mask;
252	OUT	samr_handle_t handle;
253	OUT	DWORD status;
254};
255
256
257/*
258 ***********************************************************************
259 * SamrConnect4. A new form of connect first seen with Windows XP.
260 * The server name is the fully qualified domain name, i.e.
261 *	\\server.procom.com.
262 ***********************************************************************
263 */
264OPERATION(SAMR_OPNUM_Connect4)
265struct samr_Connect4 {
266	IN		LPTSTR servername;
267	IN		DWORD access_mask;
268	INOUT	DWORD unknown2_00000001;
269	INOUT	DWORD unknown3_00000001;
270	INOUT	DWORD unknown4_00000003;
271	INOUT	DWORD unknown5_00000000;
272	OUT		samr_handle_t handle;
273	OUT		DWORD status;
274};
275
276
277/*
278 ***********************************************************************
279 * CloseHandle closes an association with the SAM. Using the same
280 * structure as the LSA seems to work.
281 ***********************************************************************
282 */
283OPERATION(SAMR_OPNUM_CloseHandle)
284struct samr_CloseHandle {
285	IN	samr_handle_t handle;
286	OUT	samr_handle_t result_handle;
287	OUT	DWORD status;
288};
289
290
291/*
292 ***********************************************************************
293 * LookupDomain: lookup up the domain SID.
294 ***********************************************************************
295 */
296OPERATION(SAMR_OPNUM_LookupDomain)
297struct samr_LookupDomain {
298	IN	samr_handle_t handle;
299	IN	samr_string_t domain_name;
300	OUT struct samr_sid *sid;
301	OUT	DWORD status;
302};
303
304
305/*
306 ***********************************************************************
307 * EnumLocalDomain
308 *
309 * This looks like a request to get the local domains supported by a
310 * remote server. NT always seems to return 2 domains: the local
311 * domain (hostname) and the Builtin domain.
312 *
313 * The max_length field is set to 0x2000.
314 * Enum_context is set to 0 in the request and set to entries_read in
315 * the reply. Like most of these enums, total_entries is the same as
316 * entries_read.
317 ***********************************************************************
318 */
319struct samr_LocalDomainEntry {
320	DWORD unknown;
321	samr_string_t name;
322};
323
324struct samr_LocalDomainInfo {
325	DWORD entries_read;
326  SIZE_IS(entries_read)
327	struct samr_LocalDomainEntry *entry;
328};
329
330
331OPERATION(SAMR_OPNUM_EnumLocalDomains)
332struct samr_EnumLocalDomain {
333	IN		samr_handle_t handle;
334	INOUT	DWORD enum_context;
335	IN		DWORD max_length;
336	OUT		struct samr_LocalDomainInfo *info;
337	OUT		DWORD total_entries;
338	OUT		DWORD status;
339};
340
341
342/*
343 ***********************************************************************
344 * OpenDomain
345 *
346 * Open a specific domain within the SAM. From this I assume that each
347 * SAM can handle multiple domains so you need to identify the one with
348 * which you want to work. Working with a domain handle does appear to
349 * offer the benefit that you can then use RIDs instead of full SIDs,
350 * which simplifies things a bit. The domain handle can be used to get
351 * user and group handles.
352 ***********************************************************************
353 */
354OPERATION(SAMR_OPNUM_OpenDomain)
355struct samr_OpenDomain {
356	IN	samr_handle_t handle;
357	IN	DWORD access_mask;
358	IN REFERENCE struct samr_sid *sid;
359	OUT	samr_handle_t domain_handle;
360	OUT	DWORD status;
361};
362
363
364/*
365 ***********************************************************************
366 * QueryDomainInfo
367 *
368 * Windows 95 Server Manager sends requests for levels 6 and 7 when
369 * the services menu item is selected.
370 ***********************************************************************
371 */
372#define SAMR_QUERY_DOMAIN_INFO_2		2
373#define SAMR_QUERY_DOMAIN_INFO_6		6
374#define SAMR_QUERY_DOMAIN_INFO_7		7
375
376
377struct samr_QueryDomainInfo2 {
378	DWORD unknown1;			/* 00 00 00 00 */
379	DWORD unknown2;			/* 00 00 00 80 */
380	samr_string_t s1;
381	samr_string_t domain;
382	samr_string_t s2;
383	DWORD sequence_num;		/* 2B 00 00 00 */
384	DWORD unknown3;			/* 00 00 00 00 */
385	DWORD unknown4;			/* 01 00 00 00 */
386	DWORD unknown5;			/* 03 00 00 00 */
387	DWORD unknown6;			/* 01 */
388	DWORD num_users;
389	DWORD num_groups;
390	DWORD num_aliases;
391};
392
393
394struct samr_QueryDomainInfo6 {
395	DWORD unknown1;			/* 00 00 00 00 */
396	DWORD unknown2;			/* B0 7F 14 00 */
397	DWORD unknown3;			/* 00 00 00 00 */
398	DWORD unknown4;			/* 00 00 00 00 */
399	DWORD unknown5;			/* 00 00 00 00 */
400};
401
402
403struct samr_QueryDomainInfo7 {
404	DWORD unknown1;			/* 03 00 00 00 */
405};
406
407
408union samr_QueryDomainInfo_ru {
409	UNION_INFO_ENT(2,samr_QueryDomainInfo);
410	UNION_INFO_ENT(6,samr_QueryDomainInfo);
411	UNION_INFO_ENT(7,samr_QueryDomainInfo);
412	DEFAULT	char *nullptr;
413};
414
415struct samr_QueryDomainInfoRes {
416	WORD switch_value;
417	SWITCH(switch_value)
418		union samr_QueryDomainInfo_ru ru;
419};
420
421OPERATION(SAMR_OPNUM_QueryDomainInfo)
422struct samr_QueryDomainInfo {
423	IN	samr_handle_t domain_handle;
424	IN	WORD info_level;
425	OUT	struct samr_QueryDomainInfoRes *info;
426	OUT	DWORD status;
427};
428
429#define SAMR_QUERY_ALIAS_INFO_1			1
430#define SAMR_QUERY_ALIAS_INFO_3			3
431
432
433struct samr_QueryAliasInfo1 {
434	WORD level;
435	samr_string_t name;
436	DWORD unknown;
437	samr_string_t desc;
438};
439
440struct samr_QueryAliasInfo3 {
441	WORD level;
442	samr_string_t desc;
443};
444
445union samr_QueryAliasInfo_ru {
446	UNION_INFO_ENT(1,samr_QueryAliasInfo);
447	UNION_INFO_ENT(3,samr_QueryAliasInfo);
448	DEFAULT	char *nullptr;
449};
450
451struct samr_QueryAliasInfoRes {
452	DWORD address;
453	WORD switch_value;
454	SWITCH(switch_value)
455		union samr_QueryAliasInfo_ru ru;
456};
457
458OPERATION(SAMR_OPNUM_QueryAliasInfo)
459struct samr_QueryAliasInfo {
460	IN	samr_handle_t alias_handle;
461	IN	WORD level;
462	OUT DWORD address;
463  SWITCH (level)
464	OUT	union samr_QueryAliasInfo_ru ru;
465	OUT	DWORD status;
466};
467
468OPERATION(SAMR_OPNUM_CreateDomainAlias)
469struct samr_CreateDomainAlias {
470	IN	samr_handle_t domain_handle;
471	IN	samr_string_t alias_name;
472	IN	DWORD access_mask;
473	OUT samr_handle_t alias_handle;
474	OUT	DWORD rid;
475	OUT	DWORD status;
476};
477
478OPERATION(SAMR_OPNUM_SetAliasInfo)
479struct samr_SetAliasInfo {
480	IN	samr_handle_t alias_handle;
481	IN	WORD level;
482	/* TBD */
483	OUT	DWORD status;
484};
485
486OPERATION(SAMR_OPNUM_DeleteDomainAlias)
487struct samr_DeleteDomainAlias {
488	IN	samr_handle_t alias_handle;
489	OUT	DWORD status;
490};
491
492OPERATION(SAMR_OPNUM_OpenAlias)
493struct samr_OpenAlias {
494	IN	samr_handle_t domain_handle;
495	IN	DWORD access_mask;
496	IN	DWORD rid;
497	OUT samr_handle_t alias_handle;
498	OUT	DWORD status;
499};
500
501struct name_rid {
502	DWORD rid;
503	samr_string_t name;
504};
505
506struct aliases_info {
507	DWORD count;
508	DWORD address;
509	SIZE_IS(count)
510	struct name_rid info[ANY_SIZE_ARRAY];
511};
512
513OPERATION(SAMR_OPNUM_EnumDomainAliases)
514struct samr_EnumDomainAliases {
515	IN	samr_handle_t domain_handle;
516	IN	DWORD resume_handle;
517	IN	DWORD mask;
518	OUT	DWORD out_resume;
519	OUT struct aliases_info *aliases;
520	OUT DWORD entries;
521	OUT	DWORD status;
522};
523
524struct user_acct_info {
525	DWORD index;
526	DWORD rid;
527	DWORD ctrl;
528	samr_string_t name;
529	samr_string_t fullname;
530	samr_string_t desc;
531};
532
533struct user_disp_info {
534	OUT DWORD total_size;
535	OUT DWORD returned_size;
536	OUT WORD switch_value;
537	DWORD count;
538	SIZE_IS(count)
539	struct user_acct_info *acct;
540};
541
542OPERATION(SAMR_OPNUM_QueryDispInfo)
543struct samr_QueryDispInfo {
544	IN	samr_handle_t domain_handle;
545	IN	WORD level;
546	IN	DWORD start_idx;
547	IN	DWORD max_entries;
548	IN	DWORD pref_maxsize;
549	OUT struct user_disp_info users;
550	OUT	DWORD status;
551};
552
553struct group_acct_info {
554	DWORD index;
555	DWORD rid;
556	DWORD ctrl;
557	samr_string_t name;
558	samr_string_t desc;
559};
560
561struct group_disp_info {
562	DWORD count;
563	/* right now we just need one entry */
564	struct group_acct_info acct[1];
565};
566
567OPERATION(SAMR_OPNUM_EnumDomainGroups)
568struct samr_EnumDomainGroups {
569	IN	samr_handle_t domain_handle;
570	IN	WORD level;
571	IN	DWORD start_idx;
572	IN	DWORD max_entries;
573	IN	DWORD pref_maxsize;
574	OUT DWORD total_size;
575	OUT DWORD returned_size;
576	OUT WORD switch_value;
577	OUT DWORD count;
578	OUT struct group_disp_info *groups;
579	OUT	DWORD status;
580};
581
582/*
583 ***********************************************************************
584 * OpenUser
585 *
586 * Input must be a domain handle obtained via SAMR_OPNUM_OpenDomain,
587 * an access mask and the appropriate user rid. The output will be a
588 * handle for use with the specified user.
589 ***********************************************************************
590 */
591OPERATION(SAMR_OPNUM_OpenUser)
592struct samr_OpenUser {
593	IN	samr_handle_t handle;
594	IN	DWORD access_mask;
595	IN	DWORD rid;
596	OUT	samr_handle_t user_handle;
597	OUT	DWORD status;
598};
599
600
601/*
602 ***********************************************************************
603 * DeleteUser
604 ***********************************************************************
605 */
606OPERATION(SAMR_OPNUM_DeleteUser)
607struct samr_DeleteUser {
608	INOUT	samr_handle_t user_handle;
609	OUT	DWORD status;
610};
611
612
613/*
614 ***********************************************************************
615 * QueryUserInfo
616 *
617 * Provides various pieces of information on a specific user (see
618 * SAM_Q_QUERY_USERINFO and SAM_R_QUERY_USERINFO). The handle must
619 * be a valid SAM user handle.
620 *
621 * QueryUserInfo (
622 *	IN samr_handle_t user_handle,
623 *	IN WORD switch_value,
624 *	OUT union switch(switch_value) {
625 *		case 1: struct QueryUserInfo1 *info1;
626 *	} bufptr,
627 *	OUT DWORD status
628 * )
629 *
630 * The cases identified so far are:
631 *
632 * 1 = username, fullname, description and some other stuff.
633 * 2 = unknown
634 * 3 = large structure containing user rid, group rid, username
635 *     and fullname.
636 * 4 = unknown
637 * 5 = large structure (like 3) containing user rid, group rid,
638 *     username, fullname and description.
639 * 6 = username and fullname
640 * 7 = username
641 * 8 = fullname
642 * 9 = group rid
643 * 16 = used after creating a new account
644 *
645 * Due to an ndrgen bug, a function must be provided to to patch the
646 * offsets used by the unmarshalling code at runtime.  In order to
647 * simplify things it is useful to use a naming convention that
648 * indicates the switch value for each structure.
649 *
650 ***********************************************************************
651 */
652
653
654#define SAMR_QUERY_USER_INFO_1			1
655#define SAMR_QUERY_USER_UNAME_AND_FNAME		6
656#define SAMR_QUERY_USER_USERNAME		7
657#define SAMR_QUERY_USER_FULLNAME		8
658#define SAMR_QUERY_USER_GROUPRID		9
659#define SAMR_QUERY_USER_UNKNOWN16		16
660
661
662struct samr_QueryUserInfo1 {
663	samr_string_t username;
664	samr_string_t fullname;
665	DWORD group_rid;
666	samr_string_t description;
667	samr_string_t unknown;
668};
669
670
671struct samr_QueryUserInfo6 {
672	samr_string_t username;
673	samr_string_t fullname;
674};
675
676struct samr_QueryUserInfo7 {
677	samr_string_t username;
678};
679
680
681struct samr_QueryUserInfo8 {
682	samr_string_t fullname;
683};
684
685
686struct samr_QueryUserInfo9 {
687	DWORD group_rid;
688};
689
690
691struct samr_QueryUserInfo16 {
692	DWORD unknown;
693};
694
695
696union QueryUserInfo_result_u {
697	UNION_INFO_ENT(1,samr_QueryUserInfo);
698	UNION_INFO_ENT(6,samr_QueryUserInfo);
699	UNION_INFO_ENT(7,samr_QueryUserInfo);
700	UNION_INFO_ENT(8,samr_QueryUserInfo);
701	UNION_INFO_ENT(9,samr_QueryUserInfo);
702	UNION_INFO_ENT(16,samr_QueryUserInfo);
703	DEFAULT	char *nullptr;
704};
705
706
707/*
708 * This structure needs to be declared, even though it can't be used in
709 * samr_QueryUserInfo, in order to get the appropriate size to calculate
710 * the correct fixup offsets.  If ndrgen did the right thing,
711 * QueryUserInfo_result would be one of the out parameters.  However, if
712 * we do it that way, the switch_value isn't known early enough to do
713 * the fixup calculation.  So it all has to go in samr_QueryUserInfo.
714 */
715struct QueryUserInfo_result {
716	DWORD address;
717	WORD switch_value;
718	SWITCH(switch_value)
719		union QueryUserInfo_result_u ru;
720};
721
722
723OPERATION(SAMR_OPNUM_QueryUserInfo)
724struct samr_QueryUserInfo {
725	IN	samr_handle_t user_handle;
726	IN	WORD switch_value;
727	/*
728	 * Can't use this form because we need to include members explicitly.
729	 * OUT	struct QueryUserInfo_result result;
730	 */
731	OUT	DWORD address;
732	OUT	WORD switch_index;
733  SWITCH(switch_value)
734	OUT	union QueryUserInfo_result_u ru;
735	OUT	DWORD status;
736};
737
738
739/*
740 ***********************************************************************
741 * QueryUserGroups
742 ***********************************************************************
743 */
744struct samr_UserGroups {
745	DWORD rid;
746	DWORD attr;
747};
748
749
750struct samr_UserGroupInfo {
751	DWORD n_entry;
752  SIZE_IS(n_entry)
753	struct samr_UserGroups *groups;
754};
755
756
757OPERATION(SAMR_OPNUM_QueryUserGroups)
758struct samr_QueryUserGroups {
759	IN	samr_handle_t user_handle;
760	OUT struct samr_UserGroupInfo *info;
761	OUT	DWORD status;
762};
763
764
765/*
766 ***********************************************************************
767 * LookupName
768 ***********************************************************************
769 */
770struct samr_LookupNameTable {
771	DWORD n_entry;
772  SIZE_IS(n_entry)
773	samr_string_t names[ANY_SIZE_ARRAY];
774};
775
776
777struct samr_LookupRidTable {
778	DWORD n_entry;
779  SIZE_IS(n_entry)
780	DWORD *rid;
781};
782
783struct samr_RidType {
784	DWORD n_entry;
785  SIZE_IS(n_entry)
786	DWORD *rid_type;
787};
788
789
790OPERATION(SAMR_OPNUM_LookupNames)
791struct samr_LookupNames {
792	IN	samr_handle_t handle;
793	IN	DWORD n_entry;
794	IN	DWORD max_n_entry;
795	IN	DWORD index;
796	IN	DWORD total;
797	IN	samr_string_t name;
798	OUT	struct samr_LookupRidTable rids;
799	OUT	struct samr_RidType rid_types;
800	OUT	DWORD status;
801};
802
803
804/*
805 ***********************************************************************
806 * OpenGroup
807 *
808 * Input must be a domain handle obtained via SAMR_OPNUM_OpenDomain,
809 * an access mask and the appropriate group rid. The output will be a
810 * handle for use with the specified group.
811 ***********************************************************************
812 */
813OPERATION(SAMR_OPNUM_OpenGroup)
814struct samr_OpenGroup {
815	IN	samr_handle_t handle;
816	IN	DWORD access_mask;
817	IN	DWORD rid;
818	OUT	samr_handle_t group_handle;
819	OUT	DWORD status;
820};
821
822
823/*
824 ***********************************************************************
825 * QueryGroupInfo
826 *
827 * Input must be a group handle obtained via SAMR_OPNUM_OpenGroup,
828 * an access mask and the appropriate group rid. The output will
829 * be a handle for use with the specified group.
830 ***********************************************************************
831 */
832struct samr_QueryGroupInfo1 {
833	samr_string_t groupname;
834};
835
836
837union samr_QueryGroupInfo_result_u {
838	UNION_INFO_ENT(1,samr_QueryGroupInfo);
839	DEFAULT	char *nullptr;
840};
841
842
843struct samr_QueryGroupInfo_result {
844	DWORD address;
845	WORD switch_index;
846  SWITCH(switch_index)
847	union samr_QueryGroupInfo_result_u ru;
848};
849
850
851OPERATION(SAMR_OPNUM_QueryGroupInfo)
852struct samr_QueryGroupInfo {
853	IN	samr_handle_t group_handle;
854	IN	DWORD switch_value;
855	OUT	DWORD address;
856	OUT	WORD switch_index;
857  SWITCH(switch_index)
858	OUT	union samr_QueryGroupInfo_result_u ru;
859	OUT	DWORD status;
860};
861
862
863/*
864 ***********************************************************************
865 * StoreGroupInfo
866 *
867 * This definition is mostly just a place holder in case this is useful
868 * in the future. Note that it may not be correct. The information is
869 * from a netmon trace captured when I added a group description. I
870 * haven't implemented it because we don't have to update anything on
871 * the PDC. The description should almost certainly be in a separate
872 * structure.
873 ***********************************************************************
874 */
875OPERATION(SAMR_OPNUM_StoreGroupInfo)
876struct samr_StoreGroupInfo {
877	IN	samr_handle_t group_handle;
878	IN	DWORD switch_value;
879	IN	samr_string_t group_description;
880	OUT	DWORD status;
881};
882
883
884/*
885 ***********************************************************************
886 * Request 0x2c is a user request. The only parameter is a user handle.
887 * The response is 12 bytes of the form:
888 *		unknown: 00 00 BB 01 (443)
889 *		unknown: 00 00 00 00
890 *		status:  00 00 00 00
891 * RPC book lists this as GetUsrDomPwInfo.
892 ***********************************************************************
893 */
894struct samr_UserPwInfo {
895	WORD	unknown1;
896	WORD	unknown2;
897	DWORD	unknown3;
898};
899
900
901OPERATION(SAMR_OPNUM_GetUserPwInfo)
902struct samr_GetUserPwInfo {
903	IN	samr_handle_t user_handle;
904	OUT struct samr_UserPwInfo pw_info;
905	OUT	DWORD status;
906};
907
908
909/*
910 ***********************************************************************
911 * CreateUser
912 *
913 * Create a user in the domain specified by the domain handle. The
914 * domain handle is obtained obtained via SAMR_OPNUM_OpenDomain. There
915 * is an unknown value at the end of the request: 0xe00500b0.
916 * The output will be a handle for use with the specified user and the
917 * user's RID. I think the RID may be a pointer but the value came back
918 * as zero once so I've padded it out so that the marshalling doesn't
919 * get confused.
920 ***********************************************************************
921 */
922OPERATION(SAMR_OPNUM_CreateUser)
923struct samr_CreateUser {
924	IN	samr_handle_t handle;
925	IN	samr_vcbuf_t username;
926	IN	DWORD account_flags;
927	IN	DWORD unknown_e00500b0;
928	OUT	samr_handle_t user_handle;
929	OUT	DWORD maybe_ptr;
930	OUT	DWORD rid;
931	OUT	DWORD status;
932};
933
934
935/*
936 ***********************************************************************
937 * ChangeUserPasswd
938 ***********************************************************************
939 */
940struct samr_newpasswd {
941	BYTE data[516];
942};
943
944
945struct samr_oldpasswd {
946	BYTE data[16];
947};
948
949
950OPERATION(SAMR_OPNUM_ChangeUserPasswd)
951struct samr_ChangeUserPasswd {
952	IN	LPTSTR servername;
953	IN	LPTSTR username;
954	IN	struct samr_newpasswd *nt_newpasswd;
955	IN	struct samr_oldpasswd *nt_oldpasswd;
956	IN	struct samr_newpasswd *lm_newpasswd;
957	IN	struct samr_oldpasswd *lm_oldpasswd;
958	OUT	DWORD status;
959};
960
961
962/*
963 ***********************************************************************
964 * GetDomainPwInfo
965 ***********************************************************************
966 */
967OPERATION(SAMR_OPNUM_GetDomainPwInfo)
968struct samr_GetDomainPwInfo {
969	IN	LPTSTR servername;
970	OUT	WORD unknown0;
971	OUT	WORD unknown1;
972	OUT	WORD unknown2;
973	OUT	DWORD status;
974};
975
976
977/*
978 ***********************************************************************
979 * SetUserInfo
980 *
981 *	+++ 20 byte user handle and the union switch_value +++
982 *	00 00 00 00 77 F2 DD D5 66 48 D4 11 AD 5F D1 CD
983 *	18 43 7A DF 17 00 17 00
984 *
985 *	+++ 14 dwords (56 bytes) of zeros +++
986 *	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
987 *	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
988 *	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
989 *	00 00 00 00 00 00 00 00
990 *
991 *	+++ 9 sets of something - 72 bytes +++
992 *	00 00 02 00 D0 04 8A 77
993 *	00 00 02 00 D0 04 8A 77
994 *	00 00 02 00 D0 04 8A 77
995 *	00 00 02 00 D0 04 8A 77
996 *	00 00 02 00 D0 04 8A 77
997 *	00 00 02 00 D0 04 8A 77
998 *	00 00 02 00 D0 04 8A 77
999 *	00 00 02 00 D0 04 8A 77
1000 *	00 00 02 00 D0 04 8A 77
1001 *
1002 *	+++ 9 DWORD zeros +++
1003 *	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1004 *	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1005 *	00 00 00 00
1006 *
1007 *	+++ miscellaneous +++
1008 *	01 02 00 00
1009 *	80 00 00 00
1010 *	FA 27 F8 09
1011 *	A8 00 00 00 70 F1 14 00
1012 *	00 00 00 00 00 00 00 00 00 00 00 00
1013 *
1014 *	+++ encrypted password buffer - 512 bytes +++
1015 *	76 68 E8 AA 23 4F 62 C4 81 4E 30 B8 92 29 66 B9
1016 *	12 FF 3A 84 82 3A 55 0F C7 18 EA 56 86 50 D7 C5
1017 *	43 BA 9C F8 32 D4 E0 15 74 A1 6F E1 59 C2 F2 95
1018 *	53 A9 F2 68 9F 7F 29 B9 88 4C 65 A5 C1 DC 0B 44
1019 *	B8 3C ED 74 D1 6A F7 09 66 97 94 6B 2C 3A A5 88
1020 *	39 34 C6 FE 24 59 30 2D CF 6D 7F D5 EC B1 9A 84
1021 *	E6 57 96 29 40 32 FB 62 9D 93 E2 BE D8 A3 74 88
1022 *	8B 85 BC A0 76 D6 C9 DB 8C AF 81 BD 8A F0 08 8D
1023 *	23 B0 52 FD 69 DE EF A1 36 E5 30 19 BD DA 67 A3
1024 *	81 BD 3F D0 2A A2 8F 60 62 B0 8D 34 9E A4 4F 20
1025 *	4E 79 93 82 58 A8 E5 6F 7A DC 12 13 33 E6 74 02
1026 *	4C 32 F9 FC 1A E1 C5 0D E2 CC 36 8D FC 72 87 DD
1027 *	6C 44 E3 6F 4B FD 46 10 08 89 E5 64 B8 27 14 83
1028 *	E7 08 DE CF 69 C7 E1 40 63 DF CB 67 95 73 03 1B
1029 *	CA 99 E1 1B 53 2A 89 6B 30 39 CD 5C DF A0 8A 1C
1030 *	4E 50 74 7C 6D 3D E7 EA E9 B2 97 DD 38 7B DA EC
1031 *	1A AD DA CE C4 58 9B 29 F3 6D 30 70 4E 63 6D 84
1032 *	DB DC 5B CD 9A 4E 57 9C E4 65 5D 4F 76 E3 C7 52
1033 *	8B 3B 20 0A 3B 4C 4B B1 2E 5B 4D AB BA 2F 45 6A
1034 *	CA 17 AD 9F C0 B2 07 FB 56 7F E4 3F 9F D4 C6 8C
1035 *	A1 05 BF 53 42 1E 67 F4 57 54 E3 2C 38 CF E1 94
1036 *	75 69 F7 4E 5C 74 CC B3 FD EF 73 3F D5 28 22 EC
1037 *	9B 40 E1 1D 65 44 7C BB 69 88 57 10 05 3A C5 48
1038 *	8E 4F 77 DB 1A 5C 49 9C D5 06 00 AC 79 BC 7E 89
1039 *	B0 01 66 70 88 A2 E5 DF 96 DC 75 98 10 12 45 02
1040 *	33 35 6C DF 74 8B 14 2F 26 C6 FD 7A B4 D0 A6 7D
1041 *	DE 2B 13 44 EF 34 46 4D 9D 3E C3 75 BC 11 B4 41
1042 *	27 58 25 1E AF AA F0 BB DA 27 7A 1E AE 81 1A 78
1043 *	44 19 DE FC C4 7C 4E 32 44 F7 57 2A 41 A2 85 DC
1044 *	C0 AD 5D 6B 58 FD 2E 75 25 B9 F2 B6 19 82 E5 0E
1045 *	B6 69 0D C1 27 A9 B6 40 A6 50 49 E5 CB 17 98 65
1046 *	88 18 CA E4 1D 2E 20 F7 DE 8E 7D F2 9D A5 6B CD
1047 *
1048 *	D6 79 45 71
1049 *
1050 *	+++ table of 9 things +++
1051 *	01 00 00 00 00 00 00 00 00 00 00 00
1052 *	01 00 00 00 00 00 00 00 00 00 00 00
1053 *	01 00 00 00 00 00 00 00 00 00 00 00
1054 *	01 00 00 00 00 00 00 00 00 00 00 00
1055 *	01 00 00 00 00 00 00 00 00 00 00 00
1056 *	01 00 00 00 00 00 00 00 00 00 00 00
1057 *	01 00 00 00 00 00 00 00 00 00 00 00
1058 *	01 00 00 00 00 00 00 00 00 00 00 00
1059 *	01 00 00 00 00 00 00 00 00 00 00 00
1060 *
1061 *	+++ miscellaneous +++
1062 *	EC 04 00 00 00 00 00 00 15 00 00 00
1063 *	FF FF FF FF FF FF FF FF FF FF FF FF
1064 *	FF FF FF FF FF FF FF FF FF
1065 *
1066 ***********************************************************************
1067 */
1068
1069#define SAMR_SET_USER_INFO_23		23
1070#define SAMR_SET_USER_DATA_SZ		516
1071
1072#define SAMR_MINS_PER_WEEK		10080
1073#define SAMR_HOURS_PER_WEEK		168
1074
1075#define SAMR_HOURS_MAX_SIZE		(SAMR_MINS_PER_WEEK / 8)
1076#define SAMR_HOURS_SET_LEN(LEN)		((LEN) / 8)
1077#define SAMR_SET_USER_HOURS_SZ		21
1078
1079
1080struct samr_sd {
1081	DWORD length;
1082  SIZE_IS(length)
1083	BYTE *data;
1084};
1085
1086
1087/*
1088 * There is some sort of logon bitmap structure in here, which I
1089 * think is a varying and conformant array, i.e.
1090 *
1091 *	struct samr_logon_hours {
1092 *      DWORD size_is;		(0x04ec)
1093 *      DWORD first_is;		(zero)
1094 *      DWORD length_is;	(0xa8)
1095 *      BYTE bitmap[21];
1096 *  };
1097 *
1098 *	struct samr_logon_info {
1099 *		DWORD length;
1100 *	SIZE_IS(length / 8)
1101 *		struct samr_logon_hours *hours;
1102 *	};
1103 *
1104 * There are 10080 minutes/week => 10080/8 = 1260 (0x04EC).
1105 * So size_is is set as some sort of maximum.
1106 *
1107 * There are 168 hours/week => 168/8 = 21 (0xA8). Since there are 21
1108 * bytes (all set to 0xFF), this is is probably the default setting.
1109 *
1110 * ndrgen has a problem with complex [size_is] statements. For now,
1111 * we can try to fake it using two separate components.
1112 */
1113struct samr_logon_hours {
1114	DWORD size;
1115	DWORD first;
1116	DWORD length;
1117	BYTE bitmap[SAMR_SET_USER_HOURS_SZ];
1118};
1119
1120
1121struct samr_logon_info {
1122	DWORD units;
1123	DWORD hours;
1124};
1125
1126
1127struct samr_oem_password {
1128	BYTE password[512];
1129	DWORD length;
1130};
1131
1132
1133struct samr_SetUserInfo23 {
1134	samr_quad_t logon_time;			/* 00 00 00 00 00 00 00 00 */
1135	samr_quad_t logoff_time;		/* 00 00 00 00 00 00 00 00 */
1136	samr_quad_t kickoff_time;		/* 00 00 00 00 00 00 00 00 */
1137	samr_quad_t passwd_last_set_time;	/* 00 00 00 00 00 00 00 00 */
1138	samr_quad_t passwd_can_change_time;	/* 00 00 00 00 00 00 00 00 */
1139	samr_quad_t passwd_must_change_time;	/* 00 00 00 00 00 00 00 00 */
1140
1141	samr_vcbuf_t user_name;			/* 00 00 00 00 00 00 00 00 */
1142	samr_vcbuf_t full_name;			/* 00 00 02 00 D0 04 8A 77 */
1143	samr_vcbuf_t home_dir;			/* 00 00 02 00 D0 04 8A 77 */
1144	samr_vcbuf_t home_drive;		/* 00 00 02 00 D0 04 8A 77 */
1145	samr_vcbuf_t logon_script;		/* 00 00 02 00 D0 04 8A 77 */
1146	samr_vcbuf_t profile_path;		/* 00 00 02 00 D0 04 8A 77 */
1147	samr_vcbuf_t acct_desc;			/* 00 00 02 00 D0 04 8A 77 */
1148	samr_vcbuf_t workstations;		/* 00 00 02 00 D0 04 8A 77 */
1149	samr_vcbuf_t unknown1;			/* 00 00 02 00 D0 04 8A 77 */
1150	samr_vcbuf_t unknown2;			/* 00 00 02 00 D0 04 8A 77 */
1151	samr_vcbuf_t lm_password;		/* 00 00 00 00 00 00 00 00 */
1152	samr_vcbuf_t nt_password;		/* 00 00 00 00 00 00 00 00 */
1153	samr_vcbuf_t unknown3;			/* 00 00 00 00 00 00 00 00 */
1154
1155	struct samr_sd sd;			/* 00 00 00 00 00 00 00 00 */
1156	DWORD user_rid;				/* 00 00 00 00 */
1157	DWORD group_rid;			/* 01 02 00 00 */
1158	DWORD acct_info;			/* 80 00 00 00 */
1159	DWORD flags;				/* FA 27 F8 09 */
1160	struct samr_logon_info logon_info;  /* A8 00 00 00 70 F1 14 00->0xFF */
1161	/*
1162	 * The following 12 bytes are encoded in Ethereal as:
1163	 *
1164	 *	WORD bad_pwd_count;
1165	 *	WORD logon_count;
1166	 *
1167	 *	WORD country;			(default 0)
1168	 *	WORD codepage;
1169	 *
1170	 *	BYTE nt_pwd_set;
1171	 *	BYTE lm_pwd_set;
1172	 *	BYTE expired_flag;
1173	 *	BYTE unknown_char;
1174	 */
1175	DWORD unknown4_zero;			/* 00 00 00 00 */
1176	DWORD unknown5_zero;			/* 00 00 00 00 */
1177	DWORD unknown6_zero;			/* 00 00 00 00 */
1178	BYTE password[SAMR_SET_USER_DATA_SZ];
1179};
1180
1181
1182union samr_SetUserInfo_u {
1183	UNION_INFO_ENT(23,samr_SetUserInfo);
1184	DEFAULT	char *nullptr;
1185};
1186
1187
1188struct samr_SetUserInfo_s {
1189	WORD index;
1190	WORD switch_value;
1191  SWITCH(switch_value)
1192	union samr_SetUserInfo_u ru;
1193};
1194
1195
1196/*
1197	IN	DWORD unknown_04EC;
1198	IN	DWORD unknown_zero;
1199	IN	DWORD logon_bitmap_size;
1200	IN	BYTE logon_bitmap[SAMR_SET_USER_HOURS_SZ];
1201*/
1202OPERATION(SAMR_OPNUM_SetUserInfo)
1203struct samr_SetUserInfo {
1204	IN	samr_handle_t user_handle;
1205	IN	struct samr_SetUserInfo_s info;
1206	IN	struct samr_logon_hours logon_hours;
1207	OUT	DWORD status;
1208};
1209
1210
1211/*
1212 ***********************************************************************
1213 * The SAMR interface definition.
1214 ***********************************************************************
1215 */
1216INTERFACE(0)
1217union samr_interface {
1218	CASE(SAMR_OPNUM_ConnectAnon)
1219		struct samr_ConnectAnon		ConnectAnon;
1220	CASE(SAMR_OPNUM_CloseHandle)
1221		struct samr_CloseHandle		CloseHandle;
1222	CASE(SAMR_OPNUM_LookupDomain)
1223		struct samr_LookupDomain	LookupDomain;
1224	CASE(SAMR_OPNUM_EnumLocalDomains)
1225		struct samr_EnumLocalDomain	EnumLocalDomain;
1226	CASE(SAMR_OPNUM_OpenDomain)
1227		struct samr_OpenDomain		OpenDomain;
1228	CASE(SAMR_OPNUM_QueryDomainInfo)
1229		struct samr_QueryDomainInfo	QueryDomainInfo;
1230	CASE(SAMR_OPNUM_LookupNames)
1231		struct samr_LookupNames		LookupNames;
1232	CASE(SAMR_OPNUM_OpenUser)
1233		struct samr_OpenUser		OpenUser;
1234	CASE(SAMR_OPNUM_DeleteUser)
1235		struct samr_DeleteUser		DeleteUser;
1236	CASE(SAMR_OPNUM_QueryUserInfo)
1237		struct samr_QueryUserInfo	QueryUserInfo;
1238	CASE(SAMR_OPNUM_QueryUserGroups)
1239		struct samr_QueryUserGroups	QueryUserGroups;
1240	CASE(SAMR_OPNUM_OpenGroup)
1241		struct samr_OpenGroup		OpenGroup;
1242	CASE(SAMR_OPNUM_GetUserPwInfo)
1243		struct samr_GetUserPwInfo	GetUserPwInfo;
1244	CASE(SAMR_OPNUM_CreateUser)
1245		struct samr_CreateUser		CreateUser;
1246	CASE(SAMR_OPNUM_ChangeUserPasswd)
1247		struct samr_ChangeUserPasswd	ChangeUserPasswd;
1248	CASE(SAMR_OPNUM_GetDomainPwInfo)
1249		struct samr_GetDomainPwInfo	GetDomainPwInfo;
1250	CASE(SAMR_OPNUM_Connect)
1251		struct samr_Connect		Connect;
1252	CASE(SAMR_OPNUM_SetUserInfo)
1253		struct samr_SetUserInfo		SetUserInfo;
1254	CASE(SAMR_OPNUM_Connect3)
1255		struct samr_Connect3		Connect3;
1256	CASE(SAMR_OPNUM_Connect4)
1257		struct samr_Connect4		Connect4;
1258	CASE(SAMR_OPNUM_QueryDispInfo)
1259		struct samr_QueryDispInfo	QueryDispInfo;
1260	CASE(SAMR_OPNUM_OpenAlias)
1261		struct samr_OpenAlias		OpenAlias;
1262	CASE(SAMR_OPNUM_CreateDomainAlias)
1263		struct samr_CreateDomainAlias	CreateDomainAlias;
1264	CASE(SAMR_OPNUM_SetAliasInfo)
1265		struct samr_SetAliasInfo	SetAliasInfo;
1266	CASE(SAMR_OPNUM_QueryAliasInfo)
1267		struct samr_QueryAliasInfo	QueryAliasInfo;
1268	CASE(SAMR_OPNUM_DeleteDomainAlias)
1269		struct samr_DeleteDomainAlias	DeleteDomainAlias;
1270	CASE(SAMR_OPNUM_EnumDomainAliases)
1271		struct samr_EnumDomainAliases	EnumDomainAliases;
1272	CASE(SAMR_OPNUM_EnumDomainGroups)
1273		struct samr_EnumDomainGroups	EnumDomainGroups;
1274};
1275typedef union samr_interface	samr_interface_t;
1276EXTERNTYPEINFO(samr_interface)
1277
1278#endif /* _MLSVC_SAM_NDL_ */
1279