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 OUT DWORD total_size; 551 OUT DWORD returned_size; 552 OUT WORD switch_value; 553 DWORD count; 554 SIZE_IS(count) 555 struct user_acct_info *acct; 556}; 557 558OPERATION(SAMR_OPNUM_QueryDispInfo) 559struct samr_QueryDispInfo { 560 IN samr_handle_t domain_handle; 561 IN WORD level; 562 IN DWORD start_idx; 563 IN DWORD max_entries; 564 IN DWORD pref_maxsize; 565 OUT struct user_disp_info users; 566 OUT DWORD status; 567}; 568 569struct group_acct_info { 570 DWORD index; 571 DWORD rid; 572 DWORD ctrl; 573 samr_string_t name; 574 samr_string_t desc; 575}; 576 577struct group_disp_info { 578 DWORD count; 579 /* right now we just need one entry */ 580 struct group_acct_info acct[1]; 581}; 582 583OPERATION(SAMR_OPNUM_EnumDomainGroups) 584struct samr_EnumDomainGroups { 585 IN samr_handle_t domain_handle; 586 IN WORD level; 587 IN DWORD start_idx; 588 IN DWORD max_entries; 589 IN DWORD pref_maxsize; 590 OUT DWORD total_size; 591 OUT DWORD returned_size; 592 OUT WORD switch_value; 593 OUT DWORD count; 594 OUT struct group_disp_info *groups; 595 OUT DWORD status; 596}; 597 598/* 599 *********************************************************************** 600 * OpenUser 601 * 602 * Input must be a domain handle obtained via SAMR_OPNUM_OpenDomain, 603 * an access mask and the appropriate user rid. The output will be a 604 * handle for use with the specified user. 605 *********************************************************************** 606 */ 607OPERATION(SAMR_OPNUM_OpenUser) 608struct samr_OpenUser { 609 IN samr_handle_t handle; 610 IN DWORD access_mask; 611 IN DWORD rid; 612 OUT samr_handle_t user_handle; 613 OUT DWORD status; 614}; 615 616 617/* 618 *********************************************************************** 619 * DeleteUser 620 *********************************************************************** 621 */ 622OPERATION(SAMR_OPNUM_DeleteUser) 623struct samr_DeleteUser { 624 INOUT samr_handle_t user_handle; 625 OUT DWORD status; 626}; 627 628 629/* 630 *********************************************************************** 631 * QueryUserInfo 632 * 633 * Provides various pieces of information on a specific user (see 634 * SAM_Q_QUERY_USERINFO and SAM_R_QUERY_USERINFO). The handle must 635 * be a valid SAM user handle. 636 * 637 * QueryUserInfo ( 638 * IN samr_handle_t user_handle, 639 * IN WORD switch_value, 640 * OUT union switch(switch_value) { 641 * case 1: struct QueryUserInfo1 *info1; 642 * } bufptr, 643 * OUT DWORD status 644 * ) 645 * 646 * The cases identified so far are: 647 * 648 * 1 = username, fullname, description and some other stuff. 649 * 2 = unknown 650 * 3 = large structure containing user rid, group rid, username 651 * and fullname. 652 * 4 = unknown 653 * 5 = large structure (like 3) containing user rid, group rid, 654 * username, fullname and description. 655 * 6 = username and fullname 656 * 7 = username 657 * 8 = fullname 658 * 9 = group rid 659 * 16 = used after creating a new account 660 * 661 * Due to an ndrgen bug, a function must be provided to to patch the 662 * offsets used by the unmarshalling code at runtime. In order to 663 * simplify things it is useful to use a naming convention that 664 * indicates the switch value for each structure. 665 * 666 *********************************************************************** 667 */ 668 669 670#define SAMR_QUERY_USER_INFO_1 1 671#define SAMR_QUERY_USER_UNAME_AND_FNAME 6 672#define SAMR_QUERY_USER_USERNAME 7 673#define SAMR_QUERY_USER_FULLNAME 8 674#define SAMR_QUERY_USER_GROUPRID 9 675#define SAMR_QUERY_USER_UNKNOWN16 16 676 677 678struct samr_QueryUserInfo1 { 679 samr_string_t username; 680 samr_string_t fullname; 681 DWORD group_rid; 682 samr_string_t description; 683 samr_string_t unknown; 684}; 685 686 687struct samr_QueryUserInfo6 { 688 samr_string_t username; 689 samr_string_t fullname; 690}; 691 692struct samr_QueryUserInfo7 { 693 samr_string_t username; 694}; 695 696 697struct samr_QueryUserInfo8 { 698 samr_string_t fullname; 699}; 700 701 702struct samr_QueryUserInfo9 { 703 DWORD group_rid; 704}; 705 706 707struct samr_QueryUserInfo16 { 708 DWORD unknown; 709}; 710 711 712union QueryUserInfo_result_u { 713 UNION_INFO_ENT(1,samr_QueryUserInfo); 714 UNION_INFO_ENT(6,samr_QueryUserInfo); 715 UNION_INFO_ENT(7,samr_QueryUserInfo); 716 UNION_INFO_ENT(8,samr_QueryUserInfo); 717 UNION_INFO_ENT(9,samr_QueryUserInfo); 718 UNION_INFO_ENT(16,samr_QueryUserInfo); 719 DEFAULT char *nullptr; 720}; 721 722 723/* 724 * This structure needs to be declared, even though it can't be used in 725 * samr_QueryUserInfo, in order to get the appropriate size to calculate 726 * the correct fixup offsets. If ndrgen did the right thing, 727 * QueryUserInfo_result would be one of the out parameters. However, if 728 * we do it that way, the switch_value isn't known early enough to do 729 * the fixup calculation. So it all has to go in samr_QueryUserInfo. 730 */ 731struct QueryUserInfo_result { 732 DWORD address; 733 WORD switch_value; 734 SWITCH(switch_value) 735 union QueryUserInfo_result_u ru; 736}; 737 738 739OPERATION(SAMR_OPNUM_QueryUserInfo) 740struct samr_QueryUserInfo { 741 IN samr_handle_t user_handle; 742 IN WORD switch_value; 743 /* 744 * Can't use this form because we need to include members explicitly. 745 * OUT struct QueryUserInfo_result result; 746 */ 747 OUT DWORD address; 748 OUT WORD switch_index; 749 SWITCH(switch_value) 750 OUT union QueryUserInfo_result_u ru; 751 OUT DWORD status; 752}; 753 754 755/* 756 *********************************************************************** 757 * QueryUserGroups 758 *********************************************************************** 759 */ 760struct samr_UserGroups { 761 DWORD rid; 762 DWORD attr; 763}; 764 765 766struct samr_UserGroupInfo { 767 DWORD n_entry; 768 SIZE_IS(n_entry) 769 struct samr_UserGroups *groups; 770}; 771 772 773OPERATION(SAMR_OPNUM_QueryUserGroups) 774struct samr_QueryUserGroups { 775 IN samr_handle_t user_handle; 776 OUT struct samr_UserGroupInfo *info; 777 OUT DWORD status; 778}; 779 780 781/* 782 *********************************************************************** 783 * LookupName 784 *********************************************************************** 785 */ 786struct samr_LookupNameTable { 787 DWORD n_entry; 788 SIZE_IS(n_entry) 789 samr_string_t names[ANY_SIZE_ARRAY]; 790}; 791 792 793struct samr_LookupRidTable { 794 DWORD n_entry; 795 SIZE_IS(n_entry) 796 DWORD *rid; 797}; 798 799struct samr_RidType { 800 DWORD n_entry; 801 SIZE_IS(n_entry) 802 DWORD *rid_type; 803}; 804 805 806OPERATION(SAMR_OPNUM_LookupNames) 807struct samr_LookupNames { 808 IN samr_handle_t handle; 809 IN DWORD n_entry; 810 IN DWORD max_n_entry; 811 IN DWORD index; 812 IN DWORD total; 813 IN samr_string_t name; 814 OUT struct samr_LookupRidTable rids; 815 OUT struct samr_RidType rid_types; 816 OUT DWORD status; 817}; 818 819 820/* 821 *********************************************************************** 822 * OpenGroup 823 * 824 * Input must be a domain handle obtained via SAMR_OPNUM_OpenDomain, 825 * an access mask and the appropriate group rid. The output will be a 826 * handle for use with the specified group. 827 *********************************************************************** 828 */ 829OPERATION(SAMR_OPNUM_OpenGroup) 830struct samr_OpenGroup { 831 IN samr_handle_t handle; 832 IN DWORD access_mask; 833 IN DWORD rid; 834 OUT samr_handle_t group_handle; 835 OUT DWORD status; 836}; 837 838 839/* 840 *********************************************************************** 841 * QueryGroupInfo 842 * 843 * Input must be a group handle obtained via SAMR_OPNUM_OpenGroup, 844 * an access mask and the appropriate group rid. The output will 845 * be a handle for use with the specified group. 846 *********************************************************************** 847 */ 848struct samr_QueryGroupInfo1 { 849 samr_string_t groupname; 850}; 851 852 853union samr_QueryGroupInfo_result_u { 854 UNION_INFO_ENT(1,samr_QueryGroupInfo); 855 DEFAULT char *nullptr; 856}; 857 858 859struct samr_QueryGroupInfo_result { 860 DWORD address; 861 WORD switch_index; 862 SWITCH(switch_index) 863 union samr_QueryGroupInfo_result_u ru; 864}; 865 866 867OPERATION(SAMR_OPNUM_QueryGroupInfo) 868struct samr_QueryGroupInfo { 869 IN samr_handle_t group_handle; 870 IN DWORD switch_value; 871 OUT DWORD address; 872 OUT WORD switch_index; 873 SWITCH(switch_index) 874 OUT union samr_QueryGroupInfo_result_u ru; 875 OUT DWORD status; 876}; 877 878 879/* 880 *********************************************************************** 881 * StoreGroupInfo 882 * 883 * This definition is mostly just a place holder in case this is useful 884 * in the future. Note that it may not be correct. The information is 885 * from a netmon trace captured when I added a group description. I 886 * haven't implemented it because we don't have to update anything on 887 * the PDC. The description should almost certainly be in a separate 888 * structure. 889 *********************************************************************** 890 */ 891OPERATION(SAMR_OPNUM_StoreGroupInfo) 892struct samr_StoreGroupInfo { 893 IN samr_handle_t group_handle; 894 IN DWORD switch_value; 895 IN samr_string_t group_description; 896 OUT DWORD status; 897}; 898 899 900/* 901 *********************************************************************** 902 * Request 0x2c is a user request. The only parameter is a user handle. 903 * The response is 12 bytes of the form: 904 * unknown: 00 00 BB 01 (443) 905 * unknown: 00 00 00 00 906 * status: 00 00 00 00 907 * RPC book lists this as GetUsrDomPwInfo. 908 *********************************************************************** 909 */ 910struct samr_UserPwInfo { 911 WORD unknown1; 912 WORD unknown2; 913 DWORD unknown3; 914}; 915 916 917OPERATION(SAMR_OPNUM_GetUserPwInfo) 918struct samr_GetUserPwInfo { 919 IN samr_handle_t user_handle; 920 OUT struct samr_UserPwInfo pw_info; 921 OUT DWORD status; 922}; 923 924 925/* 926 *********************************************************************** 927 * CreateUser 928 * 929 * Create a user in the domain specified by the domain handle. The 930 * domain handle is obtained obtained via SAMR_OPNUM_OpenDomain. There 931 * is an unknown value at the end of the request: 0xe00500b0. 932 * The output will be a handle for use with the specified user and the 933 * user's RID. I think the RID may be a pointer but the value came back 934 * as zero once so I've padded it out so that the marshalling doesn't 935 * get confused. 936 *********************************************************************** 937 */ 938OPERATION(SAMR_OPNUM_CreateUser) 939struct samr_CreateUser { 940 IN samr_handle_t handle; 941 IN samr_vcbuf_t username; 942 IN DWORD account_flags; 943 IN DWORD unknown_e00500b0; 944 OUT samr_handle_t user_handle; 945 OUT DWORD maybe_ptr; 946 OUT DWORD rid; 947 OUT DWORD status; 948}; 949 950 951/* 952 *********************************************************************** 953 * ChangeUserPasswd 954 *********************************************************************** 955 */ 956struct samr_newpasswd { 957 BYTE data[516]; 958}; 959 960 961struct samr_oldpasswd { 962 BYTE data[16]; 963}; 964 965 966OPERATION(SAMR_OPNUM_ChangeUserPasswd) 967struct samr_ChangeUserPasswd { 968 IN LPTSTR servername; 969 IN LPTSTR username; 970 IN struct samr_newpasswd *nt_newpasswd; 971 IN struct samr_oldpasswd *nt_oldpasswd; 972 IN struct samr_newpasswd *lm_newpasswd; 973 IN struct samr_oldpasswd *lm_oldpasswd; 974 OUT DWORD status; 975}; 976 977 978/* 979 *********************************************************************** 980 * GetDomainPwInfo 981 *********************************************************************** 982 */ 983OPERATION(SAMR_OPNUM_GetDomainPwInfo) 984struct samr_GetDomainPwInfo { 985 IN LPTSTR servername; 986 OUT WORD unknown0; 987 OUT WORD unknown1; 988 OUT WORD unknown2; 989 OUT DWORD status; 990}; 991 992 993/* 994 *********************************************************************** 995 * SetUserInfo 996 * 997 * +++ 20 byte user handle and the union switch_value +++ 998 * 00 00 00 00 77 F2 DD D5 66 48 D4 11 AD 5F D1 CD 999 * 18 43 7A DF 17 00 17 00 1000 * 1001 * +++ 14 dwords (56 bytes) of zeros +++ 1002 * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 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 1006 * 1007 * +++ 9 sets of something - 72 bytes +++ 1008 * 00 00 02 00 D0 04 8A 77 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 * 1018 * +++ 9 DWORD zeros +++ 1019 * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1020 * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1021 * 00 00 00 00 1022 * 1023 * +++ miscellaneous +++ 1024 * 01 02 00 00 1025 * 80 00 00 00 1026 * FA 27 F8 09 1027 * A8 00 00 00 70 F1 14 00 1028 * 00 00 00 00 00 00 00 00 00 00 00 00 1029 * 1030 * +++ encrypted password buffer - 512 bytes +++ 1031 * 76 68 E8 AA 23 4F 62 C4 81 4E 30 B8 92 29 66 B9 1032 * 12 FF 3A 84 82 3A 55 0F C7 18 EA 56 86 50 D7 C5 1033 * 43 BA 9C F8 32 D4 E0 15 74 A1 6F E1 59 C2 F2 95 1034 * 53 A9 F2 68 9F 7F 29 B9 88 4C 65 A5 C1 DC 0B 44 1035 * B8 3C ED 74 D1 6A F7 09 66 97 94 6B 2C 3A A5 88 1036 * 39 34 C6 FE 24 59 30 2D CF 6D 7F D5 EC B1 9A 84 1037 * E6 57 96 29 40 32 FB 62 9D 93 E2 BE D8 A3 74 88 1038 * 8B 85 BC A0 76 D6 C9 DB 8C AF 81 BD 8A F0 08 8D 1039 * 23 B0 52 FD 69 DE EF A1 36 E5 30 19 BD DA 67 A3 1040 * 81 BD 3F D0 2A A2 8F 60 62 B0 8D 34 9E A4 4F 20 1041 * 4E 79 93 82 58 A8 E5 6F 7A DC 12 13 33 E6 74 02 1042 * 4C 32 F9 FC 1A E1 C5 0D E2 CC 36 8D FC 72 87 DD 1043 * 6C 44 E3 6F 4B FD 46 10 08 89 E5 64 B8 27 14 83 1044 * E7 08 DE CF 69 C7 E1 40 63 DF CB 67 95 73 03 1B 1045 * CA 99 E1 1B 53 2A 89 6B 30 39 CD 5C DF A0 8A 1C 1046 * 4E 50 74 7C 6D 3D E7 EA E9 B2 97 DD 38 7B DA EC 1047 * 1A AD DA CE C4 58 9B 29 F3 6D 30 70 4E 63 6D 84 1048 * DB DC 5B CD 9A 4E 57 9C E4 65 5D 4F 76 E3 C7 52 1049 * 8B 3B 20 0A 3B 4C 4B B1 2E 5B 4D AB BA 2F 45 6A 1050 * CA 17 AD 9F C0 B2 07 FB 56 7F E4 3F 9F D4 C6 8C 1051 * A1 05 BF 53 42 1E 67 F4 57 54 E3 2C 38 CF E1 94 1052 * 75 69 F7 4E 5C 74 CC B3 FD EF 73 3F D5 28 22 EC 1053 * 9B 40 E1 1D 65 44 7C BB 69 88 57 10 05 3A C5 48 1054 * 8E 4F 77 DB 1A 5C 49 9C D5 06 00 AC 79 BC 7E 89 1055 * B0 01 66 70 88 A2 E5 DF 96 DC 75 98 10 12 45 02 1056 * 33 35 6C DF 74 8B 14 2F 26 C6 FD 7A B4 D0 A6 7D 1057 * DE 2B 13 44 EF 34 46 4D 9D 3E C3 75 BC 11 B4 41 1058 * 27 58 25 1E AF AA F0 BB DA 27 7A 1E AE 81 1A 78 1059 * 44 19 DE FC C4 7C 4E 32 44 F7 57 2A 41 A2 85 DC 1060 * C0 AD 5D 6B 58 FD 2E 75 25 B9 F2 B6 19 82 E5 0E 1061 * B6 69 0D C1 27 A9 B6 40 A6 50 49 E5 CB 17 98 65 1062 * 88 18 CA E4 1D 2E 20 F7 DE 8E 7D F2 9D A5 6B CD 1063 * 1064 * D6 79 45 71 1065 * 1066 * +++ table of 9 things +++ 1067 * 01 00 00 00 00 00 00 00 00 00 00 00 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 * 1077 * +++ miscellaneous +++ 1078 * EC 04 00 00 00 00 00 00 15 00 00 00 1079 * FF FF FF FF FF FF FF FF FF FF FF FF 1080 * FF FF FF FF FF FF FF FF FF 1081 * 1082 *********************************************************************** 1083 */ 1084 1085#define SAMR_SET_USER_INFO_23 23 1086#define SAMR_SET_USER_DATA_SZ 516 1087 1088#define SAMR_MINS_PER_WEEK 10080 1089#define SAMR_HOURS_PER_WEEK 168 1090 1091#define SAMR_HOURS_MAX_SIZE (SAMR_MINS_PER_WEEK / 8) 1092#define SAMR_HOURS_SET_LEN(LEN) ((LEN) / 8) 1093#define SAMR_SET_USER_HOURS_SZ 21 1094 1095 1096struct samr_sd { 1097 DWORD length; 1098 SIZE_IS(length) 1099 BYTE *data; 1100}; 1101 1102 1103/* 1104 * There is some sort of logon bitmap structure in here, which I 1105 * think is a varying and conformant array, i.e. 1106 * 1107 * struct samr_logon_hours { 1108 * DWORD size_is; (0x04ec) 1109 * DWORD first_is; (zero) 1110 * DWORD length_is; (0xa8) 1111 * BYTE bitmap[21]; 1112 * }; 1113 * 1114 * struct samr_logon_info { 1115 * DWORD length; 1116 * SIZE_IS(length / 8) 1117 * struct samr_logon_hours *hours; 1118 * }; 1119 * 1120 * There are 10080 minutes/week => 10080/8 = 1260 (0x04EC). 1121 * So size_is is set as some sort of maximum. 1122 * 1123 * There are 168 hours/week => 168/8 = 21 (0xA8). Since there are 21 1124 * bytes (all set to 0xFF), this is is probably the default setting. 1125 * 1126 * ndrgen has a problem with complex [size_is] statements. For now, 1127 * we can try to fake it using two separate components. 1128 */ 1129struct samr_logon_hours { 1130 DWORD size; 1131 DWORD first; 1132 DWORD length; 1133 BYTE bitmap[SAMR_SET_USER_HOURS_SZ]; 1134}; 1135 1136 1137struct samr_logon_info { 1138 DWORD units; 1139 DWORD hours; 1140}; 1141 1142 1143struct samr_oem_password { 1144 BYTE password[512]; 1145 DWORD length; 1146}; 1147 1148 1149struct samr_SetUserInfo23 { 1150 samr_quad_t logon_time; /* 00 00 00 00 00 00 00 00 */ 1151 samr_quad_t logoff_time; /* 00 00 00 00 00 00 00 00 */ 1152 samr_quad_t kickoff_time; /* 00 00 00 00 00 00 00 00 */ 1153 samr_quad_t passwd_last_set_time; /* 00 00 00 00 00 00 00 00 */ 1154 samr_quad_t passwd_can_change_time; /* 00 00 00 00 00 00 00 00 */ 1155 samr_quad_t passwd_must_change_time; /* 00 00 00 00 00 00 00 00 */ 1156 1157 samr_vcbuf_t user_name; /* 00 00 00 00 00 00 00 00 */ 1158 samr_vcbuf_t full_name; /* 00 00 02 00 D0 04 8A 77 */ 1159 samr_vcbuf_t home_dir; /* 00 00 02 00 D0 04 8A 77 */ 1160 samr_vcbuf_t home_drive; /* 00 00 02 00 D0 04 8A 77 */ 1161 samr_vcbuf_t logon_script; /* 00 00 02 00 D0 04 8A 77 */ 1162 samr_vcbuf_t profile_path; /* 00 00 02 00 D0 04 8A 77 */ 1163 samr_vcbuf_t acct_desc; /* 00 00 02 00 D0 04 8A 77 */ 1164 samr_vcbuf_t workstations; /* 00 00 02 00 D0 04 8A 77 */ 1165 samr_vcbuf_t unknown1; /* 00 00 02 00 D0 04 8A 77 */ 1166 samr_vcbuf_t unknown2; /* 00 00 02 00 D0 04 8A 77 */ 1167 samr_vcbuf_t lm_password; /* 00 00 00 00 00 00 00 00 */ 1168 samr_vcbuf_t nt_password; /* 00 00 00 00 00 00 00 00 */ 1169 samr_vcbuf_t unknown3; /* 00 00 00 00 00 00 00 00 */ 1170 1171 struct samr_sd sd; /* 00 00 00 00 00 00 00 00 */ 1172 DWORD user_rid; /* 00 00 00 00 */ 1173 DWORD group_rid; /* 01 02 00 00 */ 1174 DWORD acct_info; /* 80 00 00 00 */ 1175 DWORD flags; /* FA 27 F8 09 */ 1176 struct samr_logon_info logon_info; /* A8 00 00 00 70 F1 14 00->0xFF */ 1177 /* 1178 * The following 12 bytes are encoded in Ethereal as: 1179 * 1180 * WORD bad_pwd_count; 1181 * WORD logon_count; 1182 * 1183 * WORD country; (default 0) 1184 * WORD codepage; 1185 * 1186 * BYTE nt_pwd_set; 1187 * BYTE lm_pwd_set; 1188 * BYTE expired_flag; 1189 * BYTE unknown_char; 1190 */ 1191 DWORD unknown4_zero; /* 00 00 00 00 */ 1192 DWORD unknown5_zero; /* 00 00 00 00 */ 1193 DWORD unknown6_zero; /* 00 00 00 00 */ 1194 BYTE password[SAMR_SET_USER_DATA_SZ]; 1195}; 1196 1197 1198union samr_SetUserInfo_u { 1199 UNION_INFO_ENT(23,samr_SetUserInfo); 1200 DEFAULT char *nullptr; 1201}; 1202 1203 1204struct samr_SetUserInfo_s { 1205 WORD index; 1206 WORD switch_value; 1207 SWITCH(switch_value) 1208 union samr_SetUserInfo_u ru; 1209}; 1210 1211 1212/* 1213 IN DWORD unknown_04EC; 1214 IN DWORD unknown_zero; 1215 IN DWORD logon_bitmap_size; 1216 IN BYTE logon_bitmap[SAMR_SET_USER_HOURS_SZ]; 1217*/ 1218OPERATION(SAMR_OPNUM_SetUserInfo) 1219struct samr_SetUserInfo { 1220 IN samr_handle_t user_handle; 1221 IN struct samr_SetUserInfo_s info; 1222 IN struct samr_logon_hours logon_hours; 1223 OUT DWORD status; 1224}; 1225 1226 1227/* 1228 *********************************************************************** 1229 * The SAMR interface definition. 1230 *********************************************************************** 1231 */ 1232INTERFACE(0) 1233union samr_interface { 1234 CASE(SAMR_OPNUM_ConnectAnon) 1235 struct samr_ConnectAnon ConnectAnon; 1236 CASE(SAMR_OPNUM_CloseHandle) 1237 struct samr_CloseHandle CloseHandle; 1238 CASE(SAMR_OPNUM_LookupDomain) 1239 struct samr_LookupDomain LookupDomain; 1240 CASE(SAMR_OPNUM_EnumLocalDomains) 1241 struct samr_EnumLocalDomain EnumLocalDomain; 1242 CASE(SAMR_OPNUM_OpenDomain) 1243 struct samr_OpenDomain OpenDomain; 1244 CASE(SAMR_OPNUM_QueryDomainInfo) 1245 struct samr_QueryDomainInfo QueryDomainInfo; 1246 CASE(SAMR_OPNUM_LookupNames) 1247 struct samr_LookupNames LookupNames; 1248 CASE(SAMR_OPNUM_OpenUser) 1249 struct samr_OpenUser OpenUser; 1250 CASE(SAMR_OPNUM_DeleteUser) 1251 struct samr_DeleteUser DeleteUser; 1252 CASE(SAMR_OPNUM_QueryUserInfo) 1253 struct samr_QueryUserInfo QueryUserInfo; 1254 CASE(SAMR_OPNUM_QueryUserGroups) 1255 struct samr_QueryUserGroups QueryUserGroups; 1256 CASE(SAMR_OPNUM_OpenGroup) 1257 struct samr_OpenGroup OpenGroup; 1258 CASE(SAMR_OPNUM_GetUserPwInfo) 1259 struct samr_GetUserPwInfo GetUserPwInfo; 1260 CASE(SAMR_OPNUM_CreateUser) 1261 struct samr_CreateUser CreateUser; 1262 CASE(SAMR_OPNUM_ChangeUserPasswd) 1263 struct samr_ChangeUserPasswd ChangeUserPasswd; 1264 CASE(SAMR_OPNUM_GetDomainPwInfo) 1265 struct samr_GetDomainPwInfo GetDomainPwInfo; 1266 CASE(SAMR_OPNUM_Connect) 1267 struct samr_Connect Connect; 1268 CASE(SAMR_OPNUM_SetUserInfo) 1269 struct samr_SetUserInfo SetUserInfo; 1270 CASE(SAMR_OPNUM_Connect3) 1271 struct samr_Connect3 Connect3; 1272 CASE(SAMR_OPNUM_Connect4) 1273 struct samr_Connect4 Connect4; 1274 CASE(SAMR_OPNUM_QueryDispInfo) 1275 struct samr_QueryDispInfo QueryDispInfo; 1276 CASE(SAMR_OPNUM_OpenAlias) 1277 struct samr_OpenAlias OpenAlias; 1278 CASE(SAMR_OPNUM_CreateDomainAlias) 1279 struct samr_CreateDomainAlias CreateDomainAlias; 1280 CASE(SAMR_OPNUM_SetAliasInfo) 1281 struct samr_SetAliasInfo SetAliasInfo; 1282 CASE(SAMR_OPNUM_QueryAliasInfo) 1283 struct samr_QueryAliasInfo QueryAliasInfo; 1284 CASE(SAMR_OPNUM_DeleteDomainAlias) 1285 struct samr_DeleteDomainAlias DeleteDomainAlias; 1286 CASE(SAMR_OPNUM_EnumDomainAliases) 1287 struct samr_EnumDomainAliases EnumDomainAliases; 1288 CASE(SAMR_OPNUM_EnumDomainGroups) 1289 struct samr_EnumDomainGroups EnumDomainGroups; 1290}; 1291typedef union samr_interface samr_interface_t; 1292EXTERNTYPEINFO(samr_interface) 1293 1294#endif /* _MLSVC_SAM_NDL_ */ 1295