/**************************************************************************** PROGRAM: LSA.C PURPOSE: Utility routines that access the LSA. ****************************************************************************/ #include "SECEDIT.h" #include // Module global that holds handle to LSA once it has been opened. static LSA_HANDLE LsaHandle = NULL; LSA_HANDLE OpenLsa(VOID); VOID CloseLsa(LSA_HANDLE); /**************************************************************************** FUNCTION: LsaInit PURPOSE: Does any initialization required for this module RETURNS: TRUE on success, FALSE on failure ****************************************************************************/ BOOL LsaInit(VOID) { #ifdef LSA_AVAILABLE LsaHandle = OpenLsa(); return (LsaHandle != NULL); #endif return (TRUE); } /**************************************************************************** FUNCTION: LsaTerminate PURPOSE: Does any cleanup required for this module RETURNS: TRUE on success, FALSE on failure ****************************************************************************/ BOOL LsaTerminate(VOID) { #ifdef LSA_AVAILABLE if (LsaHandle != NULL) { CloseLsa(LsaHandle); } #endif LsaHandle = NULL; return(TRUE); } #ifdef LSA_AVAILABLE /**************************************************************************** FUNCTION: OpenLsa PURPOSE: Opens the Lsa Returns handle to Lsa or NULL on failure ****************************************************************************/ LSA_HANDLE OpenLsa(VOID) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE ConnectHandle = NULL; SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService; // // Set up the Security Quality Of Service // 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, (HANDLE)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 a handle to the LSA. Specifying NULL for the Server means that the // server is the same as the client. // Status = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_LOOKUP_NAMES, &ConnectHandle ); if (!NT_SUCCESS(Status)) { DbgPrint("LSM - Lsa Open failed 0x%lx\n", Status); return NULL; } return(ConnectHandle); } /**************************************************************************** FUNCTION: CloseLsa PURPOSE: Closes the Lsa ****************************************************************************/ VOID CloseLsa( LSA_HANDLE LsaHandle) { NTSTATUS Status; Status = LsaClose(LsaHandle); if (!NT_SUCCESS(Status)) { DbgPrint("LSM - Lsa Close failed 0x%lx\n", Status); } return; } #endif #ifdef LSA_AVAILABLE /**************************************************************************** FUNCTION: SID2Name PURPOSE: Converts a SID into a readable string. RETURNS : TRUE on success otherwise FALSE. ****************************************************************************/ BOOL SID2Name( PSID Sid, LPSTR String, UINT MaxStringBytes) { NTSTATUS Status; ANSI_STRING AnsiName; PLSA_REFERENCED_DOMAIN_LIST DomainList; PLSA_TRANSLATED_NAME NameList; if (LsaHandle == NULL) { DbgPrint("SECEDIT : Lsa not open yet\n"); return(FALSE); } Status = LsaLookupSids(LsaHandle, 1, &Sid, &DomainList, &NameList); if (NT_SUCCESS(Status)) { // Convert to ansi string RtlUnicodeStringToAnsiString(&AnsiName, &NameList->Name, TRUE); // Free up the returned data LsaFreeMemory((PVOID)DomainList); LsaFreeMemory((PVOID)NameList); // Copy the ansi string into our local variable strncpy(String, AnsiName.Buffer, MaxStringBytes); // Free up the ansi string RtlFreeAnsiString(&AnsiName); return(TRUE); } return(FALSE); } #else #include "..\..\..\inc\seopaque.h" /**************************************************************************** FUNCTION: SID2Name PURPOSE: Converts a SID into a readable string. RETURNS : TRUE on success otherwise FALSE. ****************************************************************************/ BOOL SID2Name( PSID Sid, LPSTR String, UINT MaxStringBytes) { UCHAR Buffer[128]; UCHAR i; ULONG Tmp; PISID iSid = (PISID)Sid; // pointer to opaque structure PSID NextSid = (PSID)Alloc(RtlLengthRequiredSid(1)); NTSTATUS Status; ANSI_STRING AnsiName; if (NextSid == NULL) { DbgPrint("SECEDIT: SID2Name failed to allocate space for SID\n"); return(FALSE); } { SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_WORLD_SID_AUTHORITY; RtlInitializeSid(NextSid, &SidAuthority, 1 ); *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_WORLD_RID; if (RtlEqualSid(Sid, NextSid)) { strcpy(String, "World"); Free((PVOID)NextSid); return(TRUE); } } { SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_LOCAL_SID_AUTHORITY; RtlInitializeSid(NextSid, &SidAuthority, 1 ); *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_LOCAL_RID; if (RtlEqualSid(Sid, NextSid)) { strcpy(String, "Local"); Free((PVOID)NextSid); return(TRUE); } } { SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_CREATOR_SID_AUTHORITY; RtlInitializeSid(NextSid, &SidAuthority, 1 ); *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_CREATOR_OWNER_RID; if (RtlEqualSid(Sid, NextSid)) { strcpy(String, "Creator"); Free((PVOID)NextSid); return(TRUE); } } { SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY; RtlInitializeSid(NextSid, &SidAuthority, 1 ); *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_DIALUP_RID; if (RtlEqualSid(Sid, NextSid)) { strcpy(String, "Dialup"); Free((PVOID)NextSid); return(TRUE); } } { SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY; RtlInitializeSid(NextSid, &SidAuthority, 1 ); *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_NETWORK_RID; if (RtlEqualSid(Sid, NextSid)) { strcpy(String, "Network"); Free((PVOID)NextSid); return(TRUE); } } { SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY; RtlInitializeSid(NextSid, &SidAuthority, 1 ); *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_BATCH_RID; if (RtlEqualSid(Sid, NextSid)) { strcpy(String, "Batch"); Free((PVOID)NextSid); return(TRUE); } } { SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY; RtlInitializeSid(NextSid, &SidAuthority, 1 ); *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_INTERACTIVE_RID; if (RtlEqualSid(Sid, NextSid)) { strcpy(String, "Interactive"); Free((PVOID)NextSid); return(TRUE); } } { SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY; RtlInitializeSid(NextSid, &SidAuthority, 1 ); *(RtlSubAuthoritySid(NextSid, 0)) = SECURITY_LOCAL_SYSTEM_RID; if (RtlEqualSid(Sid, NextSid)) { strcpy(String, "Local System"); Free((PVOID)NextSid); return(TRUE); } } Free((PVOID)NextSid); wsprintf(Buffer, "S-%u-", (USHORT)iSid->Revision ); lstrcpy(String, Buffer); if ( (iSid->IdentifierAuthority.Value[0] != 0) || (iSid->IdentifierAuthority.Value[1] != 0) ){ wsprintf(Buffer, "0x%02hx%02hx%02hx%02hx%02hx%02hx", (USHORT)iSid->IdentifierAuthority.Value[0], (USHORT)iSid->IdentifierAuthority.Value[1], (USHORT)iSid->IdentifierAuthority.Value[2], (USHORT)iSid->IdentifierAuthority.Value[3], (USHORT)iSid->IdentifierAuthority.Value[4], (USHORT)iSid->IdentifierAuthority.Value[5] ); lstrcat(String, Buffer); } else { Tmp = (ULONG)iSid->IdentifierAuthority.Value[5] + (ULONG)(iSid->IdentifierAuthority.Value[4] << 8) + (ULONG)(iSid->IdentifierAuthority.Value[3] << 16) + (ULONG)(iSid->IdentifierAuthority.Value[2] << 24); wsprintf(Buffer, "%lu", Tmp); lstrcat(String, Buffer); } for (i=0;iSubAuthorityCount ;i++ ) { wsprintf(Buffer, "-%lu", iSid->SubAuthority[i]); lstrcat(String, Buffer); } return(TRUE); } #endif /**************************************************************************** FUNCTION: PRIV2Name PURPOSE: Converts a PRIVILEGE into a readable string. RETURNS : TRUE on success otherwise FALSE. ****************************************************************************/ BOOL PRIV2Name( LUID Privilege, LPSTR lpstr, UINT MaxStringBytes) { NTSTATUS Status; STRING String; PUNICODE_STRING UString; LSA_HANDLE PolicyHandle; OBJECT_ATTRIBUTES ObjectAttributes; InitializeObjectAttributes( &ObjectAttributes, NULL, 0, 0, NULL); Status = LsaOpenPolicy( NULL, &ObjectAttributes, POLICY_LOOKUP_NAMES, &PolicyHandle); Status = LsaLookupPrivilegeName(PolicyHandle, &Privilege, &UString); if (!NT_SUCCESS(Status)) { DbgPrint("SECEDIT: LsaLookupPrivilegeName failed, status = 0x%lx\n", Status); strcpy(lpstr, ""); } else { // // Convert it to ANSI - because that's what the rest of the app is. // if (UString->Length > (USHORT)MaxStringBytes) { DbgPrint("SECEDIT: Truncating returned privilege name: *%Z*\n", UString); UString->Length = (USHORT)MaxStringBytes; DbgPrint(" To: *%Z*\n", UString); } String.Length = 0; String.MaximumLength = (USHORT)MaxStringBytes; String.Buffer = lpstr; Status = RtlUnicodeStringToAnsiString( &String, UString, FALSE ); ASSERT(NT_SUCCESS(Status)); LsaFreeMemory( UString ); } return(TRUE); }