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