/*++ Copyright (c) 1992 Microsoft Corporation Module Name: ctlklsa.c Abstract: Local Security Authority Subsystem - Short CT for Lsa LookupAccountName/Sid This is a small test that simply calls the LsaLookupName/Sid API once. Usage: ctlklsa \\ServerName [-p] -a AccountName ... AccountName -p - pause before name and sid lookup operation -a - start of list of account names Building Instructions: nmake UMTEST=ctlklsa UMTYPE=console Author: Environment: Revision History: --*/ #include "lsaclip.h" VOID DumpSID( IN PSID s ); VOID CtPause( ); #define LSA_WIN_STANDARD_BUFFER_SIZE 0x000000200L VOID __cdecl main(argc, argv) int argc; char **argv; { NTSTATUS Status = STATUS_SUCCESS, SidStatus; ULONG Index, ArgCount = (ULONG) argc, DomainIndex, NameIndex, NameCount, DomainSidLength; ANSI_STRING NamesAnsi[ LSA_WIN_STANDARD_BUFFER_SIZE], SystemNameAnsi; UNICODE_STRING Names[ LSA_WIN_STANDARD_BUFFER_SIZE], SystemName; PUNICODE_STRING DomainName; PSID Sid = NULL, *Sids = NULL; SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService; OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE PolicyHandle; PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = NULL, ReferencedSidsDomains = NULL; PLSA_TRANSLATED_SID TranslatedSids = NULL; PLSA_TRANSLATED_NAME TranslatedNames = NULL; UCHAR SubAuthorityCount; BOOLEAN Pause = FALSE, DoLookupSids = TRUE; if (argc < 4) { printf("usage: ctlkacct [-p] -a [ ...]\n\n"); printf(" -p - pause before name and sid lookup operations\n"); printf(" -a - start of list of account names\n\n"); printf("example:\n"); printf(" ctlklsa \\\\jimk -p -a interactive \"domain guests\" administrators\n\n"); return; } NameIndex = 0; // // Capture argument 1, the Server Name // RtlInitString( &SystemNameAnsi, (PUCHAR) argv[1] ); Status = RtlAnsiStringToUnicodeString( &SystemName, &SystemNameAnsi, TRUE ); if (!NT_SUCCESS(Status)) { goto MainError; } for (Index = 2; Index < ArgCount; Index++) { if (strncmp(argv[Index], "-p", 2) == 0) { // // The caller wants a pause before each lookup call. // Pause = TRUE; } else if (strncmp(argv[Index], "-a", 2) == 0) { Index++; while (Index < ArgCount) { if (strncmp(argv[Index], "-", 1) == 0) { Index--; break; } // // Capture the Account Name as a Unicode String. // RtlInitString( &NamesAnsi[ NameIndex ], argv[Index] ); Status = RtlAnsiStringToUnicodeString( &Names[ NameIndex ], &NamesAnsi[ NameIndex ], TRUE ); if (!NT_SUCCESS(Status)) { break; } NameIndex++; Index++; } if (Index == ArgCount) { break; } } } if (!NT_SUCCESS(Status)) { goto MainError; } NameCount = NameIndex; SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation; SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; SecurityQualityOfService.EffectiveOnly = FALSE; // // Set up the object attributes prior to opening the LSA. // InitializeObjectAttributes( &ObjectAttributes, NULL, 0L, NULL, NULL ); // // The InitializeObjectAttributes macro presently stores NULL for // the SecurityQualityOfService field, so we must manually copy that // structure for now. // ObjectAttributes.SecurityQualityOfService = &SecurityQualityOfService; // // Open the LSA Policy Database for the target system. This is the // starting point for the Name Lookup operation. // Status = LsaOpenPolicy( &SystemName, &ObjectAttributes, POLICY_LOOKUP_NAMES, &PolicyHandle ); if (!NT_SUCCESS(Status)) { goto MainError; } if (Pause) { printf( "\n\n..... Pausing before name lookup \n "); CtPause( ); } // // Attempt to translate the Names to Sids. // Status = LsaLookupNames( PolicyHandle, NameCount, Names, &ReferencedDomains, &TranslatedSids ); if (!NT_SUCCESS(Status)) { goto MainError; } // // Build the Sids from the output. // Sids = (PSID *) LocalAlloc( 0, NameCount * sizeof (PSID) ); if (Sids == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto MainError; } for (NameIndex = 0; NameIndex < NameCount; NameIndex++) { if (TranslatedSids[NameIndex].Use == SidTypeUnknown) { Sids[NameIndex] = NULL; DoLookupSids = FALSE; } else { DomainIndex = TranslatedSids[NameIndex].DomainIndex; DomainSidLength = RtlLengthSid( ReferencedDomains->Domains[DomainIndex].Sid ); Sid = (PSID) LocalAlloc( (UINT) 0, (UINT) (DomainSidLength + sizeof(ULONG)) ); if (Sid == NULL) { printf(" ** ERROR - couldn't allocate heap !!\n"); return; } RtlMoveMemory( Sid, ReferencedDomains->Domains[DomainIndex].Sid, DomainSidLength ); if (TranslatedSids[NameIndex].Use != SidTypeDomain) { (*RtlSubAuthorityCountSid( Sid ))++; SubAuthorityCount = *RtlSubAuthorityCountSid( Sid ); *RtlSubAuthoritySid(Sid,SubAuthorityCount - (UCHAR) 1) = TranslatedSids[NameIndex].RelativeId; } Sids[NameIndex] = Sid; } } // // Pause before SID lookup... // if (!DoLookupSids) { printf("\n\n Unknown Name causing sid lookup to be skipped\n"); } else { if (Pause) { printf( "\n\n..... Pausing before SID lookup \n "); CtPause(); } // // Now translate the Sids back to Names // SidStatus = LsaLookupSids( PolicyHandle, NameCount, (PSID *) Sids, &ReferencedSidsDomains, &TranslatedNames ); } /* * Print information returned by LookupAccountName */ printf( "*********************************************\n" "Information returned by LookupAccountName\n" "*********************************************\n\n" ); for (NameIndex = 0; NameIndex < NameCount; NameIndex++) { printf(" Name looked up: *%wZ*\n", &Names[NameIndex]); printf(" Use = "); switch (TranslatedSids[NameIndex].Use) { case SidTypeUser: printf("SidTypeUser\n"); break; case SidTypeGroup: printf("SidTypeGroup\n"); break; case SidTypeDomain: printf("SidTypeDomain\n"); break; case SidTypeAlias: printf("SidTypeAlias\n"); break; case SidTypeWellKnownGroup: printf("SidTypeWellKnownGroup\n"); break; case SidTypeDeletedAccount: printf("SidTypeDeletedAccount\n"); break; case SidTypeInvalid: printf("SidTypeInvalid\n"); break; case SidTypeUnknown: printf("SidTypeUnknown\n\n"); break; default: printf("Hmmm - something unusual came back !!!! \n\n"); break; } if (TranslatedSids[NameIndex].Use != SidTypeUnknown) { printf(" Sid = " ); DumpSID((PSID) Sids[NameIndex]); DomainIndex = TranslatedSids[NameIndex].DomainIndex; DomainName = &ReferencedDomains->Domains[ DomainIndex ].Name; printf(" Referenced Domain Name = *%wZ*\n\n", DomainName ); } } if (DoLookupSids) { printf( "*********************************************\n" "Information returned by LookupAccountSid\n" "*********************************************\n\n" ); if (!NT_SUCCESS(SidStatus)) { printf(" Sid lookup failed. Status 0x%lx\n" " Dumping sids that were being looked up...\n", SidStatus); } for (NameIndex = 0; NameIndex < NameCount; NameIndex++) { printf(" Sid = " ); DumpSID((PSID) Sids[NameIndex]); if (NT_SUCCESS(SidStatus)) { printf(" Sid Use = "); switch (TranslatedNames[NameIndex].Use) { case SidTypeUser: printf("SidTypeUser\n"); break; case SidTypeGroup: printf("SidTypeGroup\n"); break; case SidTypeDomain: printf("SidTypeDomain\n"); break; case SidTypeAlias: printf("SidTypeAlias\n"); break; case SidTypeWellKnownGroup: printf("SidTypeWellKnownGroup\n"); break; case SidTypeDeletedAccount: printf("SidTypeDeletedAccount\n"); break; case SidTypeInvalid: printf("SidTypeInvalid\n"); break; case SidTypeUnknown: printf("SidTypeUnknown\n"); break; default: printf("Hmmm - unexpected value !!!\n"); break; } DomainIndex = TranslatedNames[NameIndex].DomainIndex; DomainName = &ReferencedSidsDomains->Domains[ DomainIndex ].Name; if (TranslatedNames[NameIndex].Use == SidTypeDomain) { printf( " Domain Name = *%wZ*\n\n", DomainName ); } else { printf( " Account Name = *%wZ*\n" " Referenced Domain Name = *%wZ*\n\n", &TranslatedNames[NameIndex].Name, DomainName ); } } } } MainFinish: return; MainError: printf("Error: status = 0x%lx\n", Status); goto MainFinish; } VOID DumpSID( IN PSID s ) { SID_IDENTIFIER_AUTHORITY *a; ULONG id = 0, i; BOOLEAN PrintValue = FALSE; try { a = GetSidIdentifierAuthority(s); printf("s-1-"); for (i=0; i<5; i++) { if ((a->Value[i] != 0) || PrintValue) { printf("%02x", a->Value[i]); PrintValue = TRUE; } } printf("%02x", a->Value[5]); for (i = 0; i < (ULONG) *GetSidSubAuthorityCount(s); i++) { printf("-0x%lx", *GetSidSubAuthority(s, i)); } } except (EXCEPTION_EXECUTE_HANDLER) { printf("\n", s); } printf("\n"); } VOID CtPause( ) { CHAR IgnoreInput[300]; printf("Press to continue . . ."); gets( &IgnoreInput[0] ); return; }