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