580 lines
13 KiB
C
580 lines
13 KiB
C
/*++
|
|
|
|
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 <ServerName> [-p] -a <AccountName> [<AccountName> ...]\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("<invalid pointer (0x%lx)>\n", s);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
VOID
|
|
CtPause(
|
|
)
|
|
{
|
|
CHAR
|
|
IgnoreInput[300];
|
|
|
|
printf("Press <ENTER> to continue . . .");
|
|
gets( &IgnoreInput[0] );
|
|
return;
|
|
}
|