windows-nt/Source/XPSP1/NT/inetsrv/iis/setup/osrc/setuser.cpp

1553 lines
58 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include "stdafx.h"
#include "svc.h"
#include "setuser.h"
#include "dcomperm.h"
#ifndef _CHICAGO_
int GetGuestUserName_SlowWay(LPWSTR lpGuestUsrName)
{
LPWSTR ServerName = NULL; // default to local machine
DWORD Level = 1; // to retrieve info of all local and global normal user accounts
DWORD Index = 0;
DWORD EntriesRequested = 5;
DWORD PreferredMaxLength = 1024;
DWORD ReturnedEntryCount = 0;
PVOID SortedBuffer = NULL;
NET_DISPLAY_USER *p = NULL;
DWORD i=0;
int err = 0;
BOOL fStatus = TRUE;
while (fStatus)
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetQueryDisplayInformation().Start.")));
err = NetQueryDisplayInformation(ServerName, Level, Index, EntriesRequested, PreferredMaxLength, &ReturnedEntryCount, &SortedBuffer);
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetQueryDisplayInformation().End.")));
if (err == NERR_Success)
fStatus = FALSE;
if (err == NERR_Success || err == ERROR_MORE_DATA)
{
p = (NET_DISPLAY_USER *)SortedBuffer;
i = 0;
while (i < ReturnedEntryCount && (p[i].usri1_user_id != DOMAIN_USER_RID_GUEST))
i++;
if (i == ReturnedEntryCount)
{
if (err == ERROR_MORE_DATA)
{ // need to get more entries
Index = p[i-1].usri1_next_index;
}
}
else
{
wcscpy(lpGuestUsrName, p[i].usri1_name);
fStatus = FALSE;
}
}
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().Start.")));
NetApiBufferFree(SortedBuffer);
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().End.")));
}
return 0;
}
int GetGuestGrpName(LPTSTR lpGuestGrpName)
{
LPCTSTR ServerName = NULL; // local machine
DWORD cbName = UNLEN+1;
TCHAR ReferencedDomainName[200];
DWORD cbReferencedDomainName = sizeof(ReferencedDomainName);
SID_NAME_USE sidNameUse = SidTypeUser;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
PSID GuestsSid = NULL;
AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS,0,0,0,0,0,0, &GuestsSid);
LookupAccountSid(ServerName, GuestsSid, lpGuestGrpName, &cbName, ReferencedDomainName, &cbReferencedDomainName, &sidNameUse);
if (GuestsSid)
FreeSid(GuestsSid);
return 0;
}
void InitLsaString(PLSA_UNICODE_STRING LsaString,LPWSTR String)
{
DWORD StringLength;
if (String == NULL)
{
LsaString->Buffer = NULL;
LsaString->Length = 0;
LsaString->MaximumLength = 0;
return;
}
StringLength = wcslen(String);
LsaString->Buffer = String;
LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR);
}
DWORD OpenPolicy(LPTSTR ServerName,DWORD DesiredAccess,PLSA_HANDLE PolicyHandle)
{
DWORD Error;
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
LSA_UNICODE_STRING ServerString;
PLSA_UNICODE_STRING Server = NULL;
SECURITY_QUALITY_OF_SERVICE QualityOfService;
QualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
QualityOfService.ImpersonationLevel = SecurityImpersonation;
QualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
QualityOfService.EffectiveOnly = FALSE;
//
// The two fields that must be set are length and the quality of service.
//
ObjectAttributes.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
ObjectAttributes.RootDirectory = NULL;
ObjectAttributes.ObjectName = NULL;
ObjectAttributes.Attributes = 0;
ObjectAttributes.SecurityDescriptor = NULL;
ObjectAttributes.SecurityQualityOfService = &QualityOfService;
if (ServerName != NULL)
{
//
// Make a LSA_UNICODE_STRING out of the LPWSTR passed in
//
InitLsaString(&ServerString,ServerName);
Server = &ServerString;
}
//
// Attempt to open the policy for all access
//
Error = LsaOpenPolicy(Server,&ObjectAttributes,DesiredAccess,PolicyHandle);
return(Error);
}
INT RegisterAccountToLocalGroup(LPCTSTR szAccountName, LPCTSTR szLocalGroupName, BOOL fAction)
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("RegisterAccountToLocalGroup:Action=%d,Account=%s\n"), fAction, szAccountName));
int err;
// get the sid of szAccountName
PSID pSID = NULL;
BOOL bWellKnownSID = FALSE;
err = GetPrincipalSID ((LPTSTR)szAccountName, &pSID, &bWellKnownSID);
if (err != ERROR_SUCCESS)
{
iisDebugOut((LOG_TYPE_ERROR, _T("RegisterAccountToLocalGroup:GetPrincipalSID:fAction=%d, Account=%s, Group=%s, err=%d.\n"), fAction, szAccountName, szLocalGroupName, err));
return (err);
}
// Get the localized LocalGroupName
TCHAR szLocalizedLocalGroupName[GNLEN + 1];
if (_tcsicmp(szLocalGroupName, _T("Guests")) == 0)
{
GetGuestGrpName(szLocalizedLocalGroupName);
}
else
{
_tcscpy(szLocalizedLocalGroupName, szLocalGroupName);
}
// transfer szLocalGroupName to WCHAR
WCHAR wszLocalGroupName[_MAX_PATH];
#if defined(UNICODE) || defined(_UNICODE)
_tcscpy(wszLocalGroupName, szLocalizedLocalGroupName);
#else
MultiByteToWideChar( CP_ACP, 0, szLocalizedLocalGroupName, -1, wszLocalGroupName, _MAX_PATH);
#endif
LOCALGROUP_MEMBERS_INFO_0 buf;
buf.lgrmi0_sid = pSID;
if (fAction)
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetLocalGroupAddMembers().Start.")));
err = NetLocalGroupAddMembers(NULL, wszLocalGroupName, 0, (LPBYTE)&buf, 1);
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetLocalGroupAddMembers().End.")));
}
else
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetLocalGroupDelMembers().Start.")));
err = NetLocalGroupDelMembers(NULL, wszLocalGroupName, 0, (LPBYTE)&buf, 1);
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetLocalGroupDelMembers().End.")));
}
iisDebugOut((LOG_TYPE_TRACE, _T("RegisterAccountToLocalGroup:fAction=%d, Account=%s, Group=%s, err=%d.\n"), fAction, szAccountName, szLocalGroupName, err));
if (pSID)
{
if (bWellKnownSID)
FreeSid (pSID);
else
free (pSID);
}
return (err);
}
INT RegisterAccountUserRights(LPCTSTR szAccountName, BOOL fAction, BOOL fSpecicaliwamaccount)
{
iisDebugOut((LOG_TYPE_TRACE, _T("RegisterAccountUserRights:Action=%d,Account=%s,iwam=%d\n"), fAction, szAccountName,fSpecicaliwamaccount));
int err;
// get the sid of szAccountName
PSID pSID = NULL;
BOOL bWellKnownSID = FALSE;
err = GetPrincipalSID ((LPTSTR)szAccountName, &pSID, &bWellKnownSID);
if (err != ERROR_SUCCESS)
{
iisDebugOut((LOG_TYPE_ERROR, _T("RegisterAccountUserRights:GetPrincipalSID:fAction=%d, Account=%s, err=%d.\n"), fAction, szAccountName, err));
return (err);
}
LSA_UNICODE_STRING UserRightString;
LSA_HANDLE PolicyHandle = NULL;
err = OpenPolicy(NULL, POLICY_ALL_ACCESS,&PolicyHandle);
if ( err == NERR_Success )
{
if (fAction)
{
// defined in ntsecapi.h and ntlsa.h
//#define SE_INTERACTIVE_LOGON_NAME TEXT("SeInteractiveLogonRight")
//#define SE_NETWORK_LOGON_NAME TEXT("SeNetworkLogonRight")
//#define SE_BATCH_LOGON_NAME TEXT("SeBatchLogonRight")
//#define SE_SERVICE_LOGON_NAME TEXT("SeServiceLogonRight")
// Defined in winnt.h
//#define SE_CREATE_TOKEN_NAME TEXT("SeCreateTokenPrivilege")
//#define SE_ASSIGNPRIMARYTOKEN_NAME TEXT("SeAssignPrimaryTokenPrivilege")
//#define SE_LOCK_MEMORY_NAME TEXT("SeLockMemoryPrivilege")
//#define SE_INCREASE_QUOTA_NAME TEXT("SeIncreaseQuotaPrivilege")
//#define SE_UNSOLICITED_INPUT_NAME TEXT("SeUnsolicitedInputPrivilege")
//#define SE_MACHINE_ACCOUNT_NAME TEXT("SeMachineAccountPrivilege")
//#define SE_TCB_NAME TEXT("SeTcbPrivilege")
//#define SE_SECURITY_NAME TEXT("SeSecurityPrivilege")
//#define SE_TAKE_OWNERSHIP_NAME TEXT("SeTakeOwnershipPrivilege")
//#define SE_LOAD_DRIVER_NAME TEXT("SeLoadDriverPrivilege")
//#define SE_SYSTEM_PROFILE_NAME TEXT("SeSystemProfilePrivilege")
//#define SE_SYSTEMTIME_NAME TEXT("SeSystemtimePrivilege")
//#define SE_PROF_SINGLE_PROCESS_NAME TEXT("SeProfileSingleProcessPrivilege")
//#define SE_INC_BASE_PRIORITY_NAME TEXT("SeIncreaseBasePriorityPrivilege")
//#define SE_CREATE_PAGEFILE_NAME TEXT("SeCreatePagefilePrivilege")
//#define SE_CREATE_PERMANENT_NAME TEXT("SeCreatePermanentPrivilege")
//#define SE_BACKUP_NAME TEXT("SeBackupPrivilege")
//#define SE_RESTORE_NAME TEXT("SeRestorePrivilege")
//#define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege")
//#define SE_DEBUG_NAME TEXT("SeDebugPrivilege")
//#define SE_AUDIT_NAME TEXT("SeAuditPrivilege")
//#define SE_SYSTEM_ENVIRONMENT_NAME TEXT("SeSystemEnvironmentPrivilege")
//#define SE_CHANGE_NOTIFY_NAME TEXT("SeChangeNotifyPrivilege")
//#define SE_REMOTE_SHUTDOWN_NAME TEXT("SeRemoteShutdownPrivilege")
//#define SE_UNDOCK_NAME TEXT("SeUndockPrivilege")
//#define SE_SYNC_AGENT_NAME TEXT("SeSyncAgentPrivilege")
//#define SE_ENABLE_DELEGATION_NAME TEXT("SeEnableDelegationPrivilege")
if (fSpecicaliwamaccount)
{
InitLsaString(&UserRightString, SE_NETWORK_LOGON_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
// For NT5 -- the Iwam account will not have a ton of priveleges like was first decided.
// for security reasons it was trimmed.
InitLsaString(&UserRightString, SE_BATCH_LOGON_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
// For NT51 (Whistler)
// iwam should have additional rights, per bug277113 "SeAssignPrimaryTokenPrivilege","SeIncreaseQuotaPrivilege"
InitLsaString(&UserRightString, SE_ASSIGNPRIMARYTOKEN_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_INCREASE_QUOTA_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
/* Old stuff that was taken out post NT5 Beta3
// Per Bug 291206 - IWAM account should not have the "log on locally" right, as it currently does
// So make sure it is not there -- since this is a potential security hole!
InitLsaString(&UserRightString, SE_INTERACTIVE_LOGON_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
// stuff for nt5 Beta3
InitLsaString(&UserRightString, SE_TCB_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_CREATE_PAGEFILE_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_CREATE_TOKEN_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_CREATE_PERMANENT_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_DEBUG_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_AUDIT_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_INCREASE_QUOTA_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_INC_BASE_PRIORITY_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_LOAD_DRIVER_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_LOCK_MEMORY_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_SYSTEM_ENVIRONMENT_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_PROF_SINGLE_PROCESS_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_ASSIGNPRIMARYTOKEN_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
*/
}
else
{
InitLsaString(&UserRightString, SE_INTERACTIVE_LOGON_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_NETWORK_LOGON_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
InitLsaString(&UserRightString, SE_BATCH_LOGON_NAME);
err = LsaAddAccountRights(PolicyHandle, pSID, &UserRightString, 1);
if (err != STATUS_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("RegisterAccountUserRights:LsaAddAccountRights FAILED. err=0x%x\n"), err));}
}
}
else
{
InitLsaString(&UserRightString, SE_INTERACTIVE_LOGON_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_NETWORK_LOGON_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_BATCH_LOGON_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_ASSIGNPRIMARYTOKEN_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_INCREASE_QUOTA_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
/* Old stuff that was taken out post NT5 Beta3
// if special iwam account or not, let's remove these rights from the iusr or iwam user
InitLsaString(&UserRightString, SE_TCB_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_CREATE_PAGEFILE_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_CREATE_TOKEN_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_CREATE_PERMANENT_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_DEBUG_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_AUDIT_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_INCREASE_QUOTA_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_INC_BASE_PRIORITY_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_LOAD_DRIVER_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_LOCK_MEMORY_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_SYSTEM_ENVIRONMENT_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_PROF_SINGLE_PROCESS_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
InitLsaString(&UserRightString, SE_ASSIGNPRIMARYTOKEN_NAME);
err = LsaRemoveAccountRights(PolicyHandle, pSID, FALSE, &UserRightString,1);
*/
}
LsaClose(PolicyHandle);
}
else
{
iisDebugOut((LOG_TYPE_TRACE, _T("RegisterAccountUserRights:Action=%d,Account=%s,iwam=%d,err=0x%x\n"), fAction, szAccountName,fSpecicaliwamaccount,err));
}
if (pSID)
{
if (bWellKnownSID)
FreeSid (pSID);
else
free (pSID);
}
if (err)
{
iisDebugOut((LOG_TYPE_TRACE, _T("RegisterAccountUserRights:Action=%d,Account=%s,iwam=%d,err=0x%x\n"), fAction, szAccountName,fSpecicaliwamaccount,err));
}
return (err);
}
BOOL IsUserExist( LPWSTR strUsername )
{
BYTE *pBuffer;
INT err = NERR_Success;
do
{
WCHAR *pMachineName = NULL;
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetServerGetInfo().Start.")));
err = NetServerGetInfo( NULL, 101, &pBuffer );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetServerGetInfo().End.")));
// make sure we are not backup docmain first
if (err != NERR_Success )
{
// if this call returns that the service is not running, then let's just assume that the user does exist!!!!
if (err == NERR_ServerNotStarted)
{
// Try to start the server service.
err = InetStartService(_T("LanmanServer"));
if (err == 0 || err == ERROR_SERVICE_ALREADY_RUNNING)
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetServerGetInfo().Start.")));
err = NetServerGetInfo( NULL, 101, &pBuffer );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetServerGetInfo().End.")));
if (err != NERR_Success )
{
if (err == NERR_ServerNotStarted)
{
iisDebugOut((LOG_TYPE_WARN, _T("NetServerGetInfo:failed.The Server service is not started. assume that %s exists.err=0x%x.\n"),strUsername,err));
err = NERR_Success;
}
}
}
else
{
iisDebugOut((LOG_TYPE_ERROR, _T("NetServerGetInfo:failed.The Server service is not started. assume that %s exists.err=0x%x.\n"),strUsername,err));
err = NERR_Success;
}
}
else
{
iisDebugOut((LOG_TYPE_ERROR, _T("NetServerGetInfo:failed.Do not call this on PDC or BDC takes too long.This must be a PDC or BDC.err=0x%x.\n"),err));
}
break;
}
LPSERVER_INFO_101 pInfo = (LPSERVER_INFO_101)pBuffer;
if (( pInfo->sv101_type & SV_TYPE_DOMAIN_BAKCTRL ) != 0 )
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetGetDCName().Start.")));
NetGetDCName( NULL, NULL, (LPBYTE*)&pMachineName );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetGetDCName().End.")));
}
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().Start.")));
NetApiBufferFree( pBuffer );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().End.")));
if (pMachineName){iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NetUserGetInfo:[%s\\%s].Start.\n"),pMachineName,strUsername));}
else{iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NetUserGetInfo:[(null)\\%s].Start.\n"),strUsername));}
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetUserGetInfo().Start.")));
err = NetUserGetInfo( pMachineName, strUsername, 3, &pBuffer );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetUserGetInfo().End.")));
if (pMachineName){iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NetUserGetInfo:[%s\\%s].End.Ret=0x%x.\n"),pMachineName,strUsername,err));}
else{iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NetUserGetInfo:[(null)\\%s].End.\n"),strUsername));}
if ( err == NERR_Success )
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().Start.")));
NetApiBufferFree( pBuffer );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().End.")));
}
if ( pMachineName != NULL )
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().Start.")));
NetApiBufferFree( pMachineName );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().End.")));
}
} while (FALSE);
return(err == NERR_Success );
}
//
// Create InternetGuest Account
//
INT CreateUser( LPCTSTR szUsername, LPCTSTR szPassword, LPCTSTR szComment, LPCTSTR szFullName, BOOL fiWamUser,INT *NewlyCreated)
{
iisDebugOut((LOG_TYPE_TRACE, _T("CreateUser: %s\n"), szUsername));
INT iTheUserAlreadyExists = FALSE;
INT err = NERR_Success;
INT iTheUserIsMissingARight = FALSE;
BYTE *pBuffer;
WCHAR defGuest[UNLEN+1];
TCHAR defGuestGroup[GNLEN+1];
WCHAR wchGuestGroup[GNLEN+1];
WCHAR wchUsername[UNLEN+1];
WCHAR wchPassword[LM20_PWLEN+1];
WCHAR *pMachineName = NULL;
*NewlyCreated = 0;
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetGuestUserName:Start.\n")));
GetGuestUserName(defGuest);
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetGuestUserName:End.\n")));
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetGuestGrpName:Start.\n")));
GetGuestGrpName(defGuestGroup);
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetGuestGrpName:End.\n")));
iisDebugOut((LOG_TYPE_TRACE, _T("defGuest=%s, defGuestGroup=%s\n"), defGuest, defGuestGroup));
memset((PVOID)wchUsername, 0, sizeof(wchUsername));
memset((PVOID)wchPassword, 0, sizeof(wchPassword));
#if defined(UNICODE) || defined(_UNICODE)
wcsncpy(wchGuestGroup, defGuestGroup, GNLEN);
wcsncpy(wchUsername, szUsername, UNLEN);
wcsncpy(wchPassword, szPassword, LM20_PWLEN);
#else
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)defGuestGroup, -1, (LPWSTR)wchGuestGroup, GNLEN);
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szUsername, -1, (LPWSTR)wchUsername, UNLEN);
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szPassword, -1, (LPWSTR)wchPassword, LM20_PWLEN);
#endif
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetUserGetInfo:(%s) Start.\n"),defGuest));
err = NetUserGetInfo( NULL, defGuest, 3, &pBuffer );
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetUserGetInfo:(%s) End.Ret=0x%x.\n"),defGuest,err));
if ( err == NERR_Success )
{
do
{
WCHAR wchComment[MAXCOMMENTSZ+1];
WCHAR wchFullName[UNLEN+1];
memset((PVOID)wchComment, 0, sizeof(wchComment));
memset((PVOID)wchFullName, 0, sizeof(wchFullName));
#if defined(UNICODE) || defined(_UNICODE)
wcsncpy(wchComment, szComment, MAXCOMMENTSZ);
wcsncpy(wchFullName, szFullName, UNLEN);
#else
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szComment, -1, (LPWSTR)wchComment, MAXCOMMENTSZ);
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szFullName, -1, (LPWSTR)wchFullName, UNLEN);
#endif
USER_INFO_3 *lpui3 = (USER_INFO_3 *)pBuffer;
lpui3->usri3_name = wchUsername;
lpui3->usri3_password = wchPassword;
lpui3->usri3_flags &= ~ UF_ACCOUNTDISABLE;
lpui3->usri3_flags |= UF_DONT_EXPIRE_PASSWD;
lpui3->usri3_acct_expires = TIMEQ_FOREVER;
lpui3->usri3_comment = wchComment;
lpui3->usri3_usr_comment = wchComment;
lpui3->usri3_full_name = wchFullName;
lpui3->usri3_primary_group_id = DOMAIN_GROUP_RID_USERS;
DWORD parm_err;
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetUserAdd():Start.\n")));
err = NetUserAdd( NULL, 3, pBuffer, &parm_err );
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetUserAdd():End.Ret=0x%x.\n"),err));
if ( err == NERR_NotPrimary )
{
// it is a backup dc
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetGetDCName():Start.\n")));
err = NetGetDCName( NULL, NULL, (LPBYTE *)&pMachineName );
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetGetDCName():End.Ret=0x%x\n"),err));
if (err != NERR_Success)
{
MyMessageBox(NULL, _T("CreateUser:NetGetDCName"), err, MB_OK | MB_SETFOREGROUND);
break;
}
else
{
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetUserAdd().Start.")));
err = NetUserAdd( pMachineName, 3, pBuffer, &parm_err );
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetUserAdd().End.")));
}
}
else if ( err == NERR_UserExists )
{
iTheUserAlreadyExists = TRUE;
iisDebugOut((LOG_TYPE_TRACE, _T("CreateUser:User Already exists. reusing.")));
// see if we can just change the password.
if (TRUE == ChangeUserPassword((LPTSTR) szUsername, (LPTSTR) szPassword))
{
err = NERR_Success;
}
}
if ( err != NERR_Success )
{
MyMessageBox(NULL, _T("CreateUser:NetUserAdd"), err, MB_OK | MB_SETFOREGROUND);
break;
}
} while (FALSE);
if ( pMachineName != NULL )
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().Start.")));
NetApiBufferFree( pMachineName );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().End.")));
}
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().Start.")));
NetApiBufferFree( pBuffer );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().End.")));
}
if ( err == NERR_Success )
{
if (iTheUserAlreadyExists)
{
// if the user already exists, then
// don't change any rights or the group that its in leave it alone.
TCHAR PrivilegeName[256];
iTheUserIsMissingARight = FALSE;
//#define SE_INTERACTIVE_LOGON_NAME TEXT("SeInteractiveLogonRight")
//#define SE_NETWORK_LOGON_NAME TEXT("SeNetworkLogonRight")
//#define SE_BATCH_LOGON_NAME TEXT("SeBatchLogonRight")
_tcscpy(PrivilegeName, _T("SeNetworkLogonRight"));
if (FALSE == DoesUserHaveThisRight(szUsername, PrivilegeName))
{
iTheUserIsMissingARight = TRUE;
}
else
{
_tcscpy(PrivilegeName, _T("SeBatchLogonRight"));
if (FALSE == DoesUserHaveThisRight(szUsername, PrivilegeName))
{
iTheUserIsMissingARight = TRUE;
}
else
{
if (fiWamUser)
{
// make sure the iwam user has these additional rights
// AssignPrimaryToken and IncreaseQuota privileges
_tcscpy(PrivilegeName, _T("SeAssignPrimaryTokenPrivilege"));
if (FALSE == DoesUserHaveThisRight(szUsername, PrivilegeName))
{
iTheUserIsMissingARight = TRUE;
}
else
{
_tcscpy(PrivilegeName, _T("SeIncreaseQuotaPrivilege"));
if (FALSE == DoesUserHaveThisRight(szUsername, PrivilegeName))
{
iTheUserIsMissingARight = TRUE;
}
}
}
else
{
// make sure the iusr user has these additional rights
_tcscpy(PrivilegeName, _T("SeInteractiveLogonRight"));
if (FALSE == DoesUserHaveThisRight(szUsername, PrivilegeName))
{
iTheUserIsMissingARight = TRUE;
}
}
}
}
// nope, we have to make sure that our iusr\iwam user has at least these
// rights, because otherwise it won't work bug#361833
if (iTheUserIsMissingARight == TRUE)
{
iisDebugOut((LOG_TYPE_TRACE, _T("Missing user right[%s]:resetting it."),PrivilegeName));
RegisterAccountUserRights(szUsername, TRUE, fiWamUser);
}
// if its the the iwam user, then make sure they are not part of the Guests Group by removing them
if (fiWamUser)
{
RegisterAccountToLocalGroup(szUsername, _T("Guests"), FALSE);
}
}
else
{
// User was successfully newly created
*NewlyCreated = 1;
// add it to the guests group
// (but don't do it for the iwam user)
if (!fiWamUser)
{
RegisterAccountToLocalGroup(szUsername, _T("Guests"), TRUE);
}
// add certain user rights to this account
RegisterAccountUserRights(szUsername, TRUE, fiWamUser);
}
}
if (TRUE == iTheUserAlreadyExists)
{*NewlyCreated = 2;}
return err;
}
INT DeleteGuestUser(LPCTSTR szUsername, INT *UserWasDeleted)
{
iisDebugOut((LOG_TYPE_TRACE, _T("DeleteGuestUser:%s\n"), szUsername));
INT err = NERR_Success;
BYTE *pBuffer;
*UserWasDeleted = 0;
WCHAR wchUsername[UNLEN+1];
#if defined(UNICODE) || defined(_UNICODE)
wcsncpy(wchUsername, szUsername, UNLEN);
#else
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)szUsername, -1, (LPWSTR)wchUsername, UNLEN);
#endif
if (FALSE == IsUserExist(wchUsername))
{
*UserWasDeleted = 1;
iisDebugOut((LOG_TYPE_TRACE, _T("DeleteGuestUser return. %s doesn't exist.\n"), szUsername));
return err;
}
// remove it from the guests group
RegisterAccountToLocalGroup(szUsername, _T("Guests"), FALSE);
// remove certain user rights of this account
RegisterAccountUserRights(szUsername, FALSE, TRUE);
do
{
WCHAR *pMachine = NULL;
// make sure we are not backup docmain first
iisDebugOut((LOG_TYPE_TRACE, _T("NetServerGetInfo:Start.\n")));
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetServerGetInfo().Start.")));
err = NetServerGetInfo( NULL, 101, &pBuffer );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetServerGetInfo().End.")));
if (err != NERR_Success )
{
iisDebugOut((LOG_TYPE_ERROR, _T("NetServerGetInfo:failed.err=0x%x.\n"),err));
break;
}
iisDebugOut((LOG_TYPE_TRACE, _T("NetServerGetInfo:End.\n")));
LPSERVER_INFO_101 pInfo = (LPSERVER_INFO_101)pBuffer;
if (( pInfo->sv101_type & SV_TYPE_DOMAIN_BAKCTRL ) != 0 )
{
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetGetDCName():Start.\n")));
NetGetDCName( NULL, NULL, (LPBYTE *)&pMachine);
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetGetDCName():End.\n")));
}
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().Start.")));
NetApiBufferFree( pBuffer );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().End.")));
iisDebugOut((LOG_TYPE_TRACE, _T("NetUserDel:Start.\n")));
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetUserDel().Start.")));
INT err = ::NetUserDel( pMachine, wchUsername );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetUserDel().End.")));
iisDebugOut((LOG_TYPE_TRACE, _T("NetUserDel:End.Ret=0x%x.\n"),err));
if (err == NERR_Success)
{
*UserWasDeleted = 1;
}
if ( pMachine != NULL )
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().Start.")));
NetApiBufferFree( pMachine );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("NETAPI32.dll:NetApiBufferFree().End.")));
}
} while(FALSE);
iisDebugOut((LOG_TYPE_TRACE, _T("DeleteGuestUser:%s. End. Return 0x%x\n"), szUsername, err));
return err;
}
BOOL GuestAccEnabled()
{
BOOL fEnabled = FALSE;
INT err = NERR_Success;
BYTE *pBuffer;
WCHAR defGuest[UNLEN+1];
GetGuestUserName(defGuest);
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetUserGetInfo:Start.\n")));
err = NetUserGetInfo( NULL, defGuest, 3, &pBuffer );
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetUserGetInfo:End.Ret=0x%x.\n"),err));
if ( err == NERR_Success )
{
USER_INFO_3 *lpui3 = (USER_INFO_3 *)pBuffer;
fEnabled = ( lpui3->usri3_flags & UF_ACCOUNTDISABLE ) == 0;
}
return fEnabled;
}
NET_API_STATUS
NetpNtStatusToApiStatus (
IN NTSTATUS NtStatus
)
/*++
Routine Description:
This function takes an NT status code and maps it to the appropriate
LAN Man error code.
Arguments:
NtStatus - Supplies the NT status.
Return Value:
Returns the appropriate LAN Man error code for the NT status.
--*/
{
NET_API_STATUS error;
//
// A small optimization for the most common case.
//
if ( NtStatus == STATUS_SUCCESS ) {
return NERR_Success;
}
switch ( NtStatus ) {
case STATUS_BUFFER_TOO_SMALL :
return NERR_BufTooSmall;
case STATUS_FILES_OPEN :
return NERR_OpenFiles;
case STATUS_CONNECTION_IN_USE :
return NERR_DevInUse;
case STATUS_INVALID_LOGON_HOURS :
return NERR_InvalidLogonHours;
case STATUS_INVALID_WORKSTATION :
return NERR_InvalidWorkstation;
case STATUS_PASSWORD_EXPIRED :
return NERR_PasswordExpired;
case STATUS_ACCOUNT_EXPIRED :
return NERR_AccountExpired;
case STATUS_REDIRECTOR_NOT_STARTED :
return NERR_NetNotStarted;
case STATUS_GROUP_EXISTS:
return NERR_GroupExists;
case STATUS_INTERNAL_DB_CORRUPTION:
return NERR_InvalidDatabase;
case STATUS_INVALID_ACCOUNT_NAME:
return NERR_BadUsername;
case STATUS_INVALID_DOMAIN_ROLE:
case STATUS_INVALID_SERVER_STATE:
case STATUS_BACKUP_CONTROLLER:
return NERR_NotPrimary;
case STATUS_INVALID_DOMAIN_STATE:
return NERR_ACFNotLoaded;
case STATUS_MEMBER_IN_GROUP:
return NERR_UserInGroup;
case STATUS_MEMBER_NOT_IN_GROUP:
return NERR_UserNotInGroup;
case STATUS_NONE_MAPPED:
case STATUS_NO_SUCH_GROUP:
return NERR_GroupNotFound;
case STATUS_SPECIAL_GROUP:
case STATUS_MEMBERS_PRIMARY_GROUP:
return NERR_SpeGroupOp;
case STATUS_USER_EXISTS:
return NERR_UserExists;
case STATUS_NO_SUCH_USER:
return NERR_UserNotFound;
case STATUS_PRIVILEGE_NOT_HELD:
return ERROR_ACCESS_DENIED;
case STATUS_LOGON_SERVER_CONFLICT:
return NERR_LogonServerConflict;
case STATUS_TIME_DIFFERENCE_AT_DC:
return NERR_TimeDiffAtDC;
case STATUS_SYNCHRONIZATION_REQUIRED:
return NERR_SyncRequired;
case STATUS_WRONG_PASSWORD_CORE:
return NERR_BadPasswordCore;
case STATUS_DOMAIN_CONTROLLER_NOT_FOUND:
return NERR_DCNotFound;
case STATUS_PASSWORD_RESTRICTION:
return NERR_PasswordTooShort;
case STATUS_ALREADY_DISCONNECTED:
return NERR_Success;
default:
//
// Use the system routine to do the mapping to ERROR_ codes.
//
#ifndef WIN32_CHICAGO
error = RtlNtStatusToDosError( NtStatus );
if ( error != (NET_API_STATUS)NtStatus ) {
return error;
}
#endif // WIN32_CHICAGO
//
// Could not map the NT status to anything appropriate.
// Write this to the eventlog file
//
return NERR_InternalError;
}
} // NetpNtStatusToApiStatus
NET_API_STATUS
UaspGetDomainId(
IN LPCWSTR ServerName OPTIONAL,
OUT PSAM_HANDLE SamServerHandle OPTIONAL,
OUT PPOLICY_ACCOUNT_DOMAIN_INFO * AccountDomainInfo
)
/*++
Routine Description:
Return a domain ID of the account domain of a server.
Arguments:
ServerName - A pointer to a string containing the name of the
Domain Controller (DC) to query. A NULL pointer
or string specifies the local machine.
SamServerHandle - Returns the SAM connection handle if the caller wants it.
DomainId - Receives a pointer to the domain ID.
Caller must deallocate buffer using NetpMemoryFree.
Return Value:
Error code for the operation.
--*/
{
NET_API_STATUS NetStatus;
NTSTATUS Status;
SAM_HANDLE LocalSamHandle = NULL;
ACCESS_MASK LSADesiredAccess;
LSA_HANDLE LSAPolicyHandle = NULL;
OBJECT_ATTRIBUTES LSAObjectAttributes;
UNICODE_STRING ServerNameString;
//
// Connect to the SAM server
//
RtlInitUnicodeString( &ServerNameString, ServerName );
Status = SamConnect(
&ServerNameString,
&LocalSamHandle,
SAM_SERVER_LOOKUP_DOMAIN,
NULL);
if ( !NT_SUCCESS(Status))
{
LocalSamHandle = NULL;
NetStatus = NetpNtStatusToApiStatus( Status );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("UaspGetDomainId: Cannot connect to Sam. err=0x%x\n"),NetStatus));
goto Cleanup;
}
//
// Open LSA to read account domain info.
//
if ( AccountDomainInfo != NULL) {
//
// set desired access mask.
//
LSADesiredAccess = POLICY_VIEW_LOCAL_INFORMATION;
InitializeObjectAttributes( &LSAObjectAttributes,
NULL, // Name
0, // Attributes
NULL, // Root
NULL ); // Security Descriptor
Status = LsaOpenPolicy( &ServerNameString,
&LSAObjectAttributes,
LSADesiredAccess,
&LSAPolicyHandle );
if( !NT_SUCCESS(Status) ) {
NetStatus = NetpNtStatusToApiStatus( Status );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("UaspGetDomainId: Cannot open LSA Policy %lX\n"),NetStatus));
goto Cleanup;
}
//
// now read account domain info from LSA.
//
Status = LsaQueryInformationPolicy(
LSAPolicyHandle,
PolicyAccountDomainInformation,
(PVOID *) AccountDomainInfo );
if( !NT_SUCCESS(Status) ) {
NetStatus = NetpNtStatusToApiStatus( Status );
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("UaspGetDomainId: Cannot read LSA.Err=0x%x.\n"),NetStatus));
goto Cleanup;
}
}
//
// Return the SAM connection handle to the caller if he wants it.
// Otherwise, disconnect from SAM.
//
if ( ARGUMENT_PRESENT( SamServerHandle ) ) {
*SamServerHandle = LocalSamHandle;
LocalSamHandle = NULL;
}
NetStatus = NERR_Success;
//
// Cleanup locally used resources
//
Cleanup:
if ( LocalSamHandle != NULL ) {
(VOID) SamCloseHandle( LocalSamHandle );
}
if( LSAPolicyHandle != NULL ) {
LsaClose( LSAPolicyHandle );
}
return NetStatus;
} // UaspGetDomainId
NET_API_STATUS
SampCreateFullSid(
IN PSID DomainSid,
IN ULONG Rid,
OUT PSID *AccountSid
)
/*++
Routine Description:
This function creates a domain account sid given a domain sid and
the relative id of the account within the domain.
The returned Sid may be freed with LocalFree.
--*/
{
NET_API_STATUS NetStatus;
NTSTATUS IgnoreStatus;
UCHAR AccountSubAuthorityCount;
ULONG AccountSidLength;
PULONG RidLocation;
//
// Calculate the size of the new sid
//
AccountSubAuthorityCount = *RtlSubAuthorityCountSid(DomainSid) + (UCHAR)1;
AccountSidLength = RtlLengthRequiredSid(AccountSubAuthorityCount);
//
// Allocate space for the account sid
//
*AccountSid = LocalAlloc(LMEM_ZEROINIT,AccountSidLength);
if (*AccountSid == NULL)
{
NetStatus = ERROR_NOT_ENOUGH_MEMORY;
}
else
{
//
// Copy the domain sid into the first part of the account sid
//
IgnoreStatus = RtlCopySid(AccountSidLength, *AccountSid, DomainSid);
ASSERT(NT_SUCCESS(IgnoreStatus));
//
// Increment the account sid sub-authority count
//
*RtlSubAuthorityCountSid(*AccountSid) = AccountSubAuthorityCount;
//
// Add the rid as the final sub-authority
//
RidLocation = RtlSubAuthoritySid(*AccountSid, AccountSubAuthorityCount-1);
*RidLocation = Rid;
//iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("AccountSid=0x%x"),*AccountSid));
NetStatus = NERR_Success;
}
return(NetStatus);
}
int GetGuestUserNameForDomain_FastWay(LPTSTR szDomainToLookUp,LPTSTR lpGuestUsrName)
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetGuestUserNameForDomain_FastWay.start.domain=%s\n"),szDomainToLookUp));
int iReturn = FALSE;
NET_API_STATUS NetStatus;
// for UaspGetDomainId()
SAM_HANDLE SamServerHandle = NULL;
PPOLICY_ACCOUNT_DOMAIN_INFO pAccountDomainInfo;
PSID pAccountSid = NULL;
PSID pDomainSid = NULL;
// for LookupAccountSid()
SID_NAME_USE sidNameUse = SidTypeUser;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
TCHAR szUserName[UNLEN+1];
DWORD cbName = UNLEN+1;
// must be big enough to hold something bigger than DNLen since LookupAccountSid may returnn something really big.
TCHAR szReferencedDomainName[200];
DWORD cbReferencedDomainName = sizeof(szReferencedDomainName);
ASSERT(lpGuestUsrName);
// make sure not to return back gobble-d-gook
_tcscpy(lpGuestUsrName, _T(""));
//
// Get the Sid for the specified Domain
//
// szDomainToLookUp=NULL for local machine
NetStatus = UaspGetDomainId( szDomainToLookUp,&SamServerHandle,&pAccountDomainInfo );
if ( NetStatus != NERR_Success )
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetGuestUserNameForDomain:UaspGetDomainId failed.ret=0x%x."),NetStatus));
goto GetGuestUserNameForDomain_FastWay_Exit;
}
pDomainSid = pAccountDomainInfo->DomainSid;
//
// Use the Domain Sid and the well known Guest RID to create the Real Guest Sid
//
// Well-known users ...
// DOMAIN_USER_RID_ADMIN (0x000001F4L)
// DOMAIN_USER_RID_GUEST (0x000001F5L)
NetStatus = NERR_InternalError;
NetStatus = SampCreateFullSid(pDomainSid, DOMAIN_USER_RID_GUEST, &pAccountSid);
if ( NetStatus != NERR_Success )
{
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetGuestUserNameForDomain:SampCreateFullSid failed.ret=0x%x."),NetStatus));
goto GetGuestUserNameForDomain_FastWay_Exit;
}
//
// Check if the SID is valid
//
if (0 == IsValidSid(pAccountSid))
{
DWORD dwErr = GetLastError();
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetGuestUserNameForDomain:IsValidSid FAILED. GetLastError()= 0x%x\n"), dwErr));
goto GetGuestUserNameForDomain_FastWay_Exit;
}
//
// Retrieve the UserName for the specified SID
//
_tcscpy(szUserName, _T(""));
_tcscpy(szReferencedDomainName, _T(""));
// szDomainToLookUp=NULL for local machine
if (!LookupAccountSid(szDomainToLookUp, pAccountSid, szUserName, &cbName, szReferencedDomainName, &cbReferencedDomainName, &sidNameUse))
{
DWORD dwErr = GetLastError();
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GetGuestUserNameForDomain:LookupAccountSid FAILED. GetLastError()= 0x%x\n"), dwErr));
goto GetGuestUserNameForDomain_FastWay_Exit;
}
//iisDebugOut((LOG_TYPE_TRACE, _T("GetGuestUserNameForDomain:szDomainToLookUp=%s\n"),szDomainToLookUp));
//iisDebugOut((LOG_TYPE_TRACE, _T("GetGuestUserNameForDomain:pAccountSid=0x%x\n"),pAccountSid));
//iisDebugOut((LOG_TYPE_TRACE, _T("GetGuestUserNameForDomain:szUserName=%s\n"),szUserName));
//iisDebugOut((LOG_TYPE_TRACE, _T("GetGuestUserNameForDomain:szReferencedDomainName=%s\n"),szReferencedDomainName));
// Return the guest user name that we got.
_tcscpy(lpGuestUsrName, szUserName);
// Wow, after all that, we must have succeeded
iReturn = TRUE;
GetGuestUserNameForDomain_FastWay_Exit:
// Free the Domain info if we got some
if (pAccountDomainInfo) {NetpMemoryFree(pAccountDomainInfo);}
// Free the sid if we had allocated one
if (pAccountSid) {LocalFree(pAccountSid);}
iisDebugOut((LOG_TYPE_TRACE, _T("GetGuestUserNameForDomain_FastWay.end.domain=%s.ret=%d.\n"),szDomainToLookUp,iReturn));
return iReturn;
}
void GetGuestUserName(LPTSTR lpOutGuestUsrName)
{
// try to retrieve the guest username the fast way
// meaning = lookup the domain sid, and the well known guest rid, to get the guest sid.
// then look it up. The reason for this function is that on large domains with mega users
// the account can be quickly looked up.
TCHAR szGuestUsrName[UNLEN+1];
LPTSTR pszComputerName = NULL;
if (!GetGuestUserNameForDomain_FastWay(pszComputerName,szGuestUsrName))
{
iisDebugOut((LOG_TYPE_WARN, _T("GetGuestUserNameForDomain_FastWay:Did not succeed use slow way. WARNING.")));
// if the fast way failed for some reason, then let's do it
// the slow way, since this way always used to work, only on large domains (1 mil users)
// it could take 24hrs (since this function actually enumerates thru the domain)
GetGuestUserName_SlowWay(szGuestUsrName);
}
// Return back the username
_tcscpy(lpOutGuestUsrName,szGuestUsrName);
return;
}
int ChangeUserPassword(IN LPTSTR szUserName, IN LPTSTR szNewPassword)
{
int iReturn = TRUE;
USER_INFO_1003 pi1003;
NET_API_STATUS nas;
TCHAR szRawComputerName[CNLEN + 10];
DWORD dwLen = CNLEN + 10;
TCHAR szComputerName[CNLEN + 10];
TCHAR szCopyOfUserName[UNLEN+10];
TCHAR szTempFullUserName[(CNLEN + 10) + (DNLEN+1)];
LPTSTR pch = NULL;
_tcscpy(szCopyOfUserName, szUserName);
//iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ChangeUserPassword().Start.name=%s,pass=%s"),szCopyOfUserName,szNewPassword));
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ChangeUserPassword().Start.name=%s"),szCopyOfUserName));
if ( !GetComputerName( szRawComputerName, &dwLen ))
{goto ChangeUserPassword_Exit;}
// Make a copy to be sure not to move the pointer around.
_tcscpy(szTempFullUserName, szCopyOfUserName);
// Check if there is a "\" in there.
pch = _tcschr(szTempFullUserName, _T('\\'));
if (pch)
{
// szCopyOfUserName should now go from something like this:
// mycomputer\myuser
// to this myuser
_tcscpy(szCopyOfUserName,pch+1);
// trim off the '\' character to leave just the domain\computername so we can check against it.
*pch = _T('\0');
// compare the szTempFullUserName with the local computername.
if (0 == _tcsicmp(szRawComputerName, szTempFullUserName))
{
// the computername\username has a hardcoded computername in it.
// lets try to get only the username
// look szCopyOfusername is already set
}
else
{
// the local computer machine name
// and the specified username are different, so get out
// and don't even try to change this user\password since
// it's probably a domain\username
// return true -- saying that we did in fact change the passoword.
// we really didn't but we can't
iReturn = TRUE;
goto ChangeUserPassword_Exit;
}
}
// Make sure the computername has a \\ in front of it
if ( szRawComputerName[0] != _T('\\') )
{_tcscpy(szComputerName,_T("\\\\"));}
_tcscat(szComputerName,szRawComputerName);
//
// administrative over-ride of existing password
//
// by this time szCopyOfUserName
// should not look like mycomputername\username but it should look like username.
pi1003.usri1003_password = szNewPassword;
nas = NetUserSetInfo(
szComputerName, // computer name
szCopyOfUserName, // username
1003, // info level
(LPBYTE)&pi1003, // new info
NULL
);
if(nas != NERR_Success)
{
iReturn = FALSE;
goto ChangeUserPassword_Exit;
}
ChangeUserPassword_Exit:
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("ChangeUserPassword().End.Ret=%d"),iReturn));
return iReturn;
}
BOOL DoesUserHaveThisRight(LPCTSTR szAccountName, LPTSTR PrivilegeName)
{
iisDebugOut((LOG_TYPE_TRACE, _T("DoesUserHaveBasicRights:Account=%s\n"), szAccountName));
int err;
BOOL fEnabled = FALSE;
NTSTATUS status;
LSA_UNICODE_STRING UserRightString;
// Create a LSA_UNICODE_STRING for the privilege name.
InitLsaString(&UserRightString, PrivilegeName);
// get the sid of szAccountName
PSID pSID = NULL;
BOOL bWellKnownSID = FALSE;
err = GetPrincipalSID ((LPTSTR)szAccountName, &pSID, &bWellKnownSID);
if (err != ERROR_SUCCESS)
{
iisDebugOut((LOG_TYPE_ERROR, _T("DoesUserHaveBasicRights:GetPrincipalSID:Account=%s, err=%d.\n"), szAccountName, err));
return (err);
}
LSA_HANDLE PolicyHandle = NULL;
err = OpenPolicy(NULL, POLICY_ALL_ACCESS,&PolicyHandle);
if ( err == NERR_Success )
{
UINT i;
LSA_UNICODE_STRING *rgUserRights = NULL;
ULONG cRights;
status = LsaEnumerateAccountRights(
PolicyHandle,
pSID,
&rgUserRights,
&cRights);
if (status==STATUS_OBJECT_NAME_NOT_FOUND)
{
// no rights/privileges for this account
fEnabled = FALSE;
}
else if (!NT_SUCCESS(status))
{
iisDebugOut((LOG_TYPE_ERROR, _T("DoesUserHaveBasicRights:GetPrincipalSID:Failed to enumerate rights: status 0x%08lx\n"), status));
goto DoesUserHaveBasicRights_Exit;
}
for(i=0; i < cRights; i++)
{
if ( RtlEqualUnicodeString(&rgUserRights[i],&UserRightString,FALSE) )
{
fEnabled = TRUE;
break;
}
}
if (rgUserRights) {LsaFreeMemory(rgUserRights);}
}
DoesUserHaveBasicRights_Exit:
if (PolicyHandle){LsaClose(PolicyHandle);}
if (pSID)
{
if (bWellKnownSID){FreeSid (pSID);}
else{free (pSID);}
}
return (fEnabled);
}
HRESULT CreateGroup(LPTSTR szGroupName, LPCTSTR szGroupComment, int iAction)
{
HRESULT hr = S_OK;
NET_API_STATUS dwRes;
LOCALGROUP_INFO_1 MyLocalGroup;
WCHAR wszLocalGroupName[_MAX_PATH];
WCHAR wszLocalGroupComment[_MAX_PATH];
memset(&MyLocalGroup, 0, sizeof(MyLocalGroup));
#if defined(UNICODE) || defined(_UNICODE)
_tcscpy(wszLocalGroupName, szGroupName);
_tcscpy(wszLocalGroupComment, szGroupComment);
#else
MultiByteToWideChar( CP_ACP, 0, szGroupName, -1, wszLocalGroupName, _MAX_PATH);
MultiByteToWideChar( CP_ACP, 0, szGroupComment, -1, wszLocalGroupComment, _MAX_PATH);
#endif
MyLocalGroup.lgrpi1_name = (LPWSTR)szGroupName;
MyLocalGroup.lgrpi1_comment = (LPWSTR)szGroupComment;
if (iAction)
{
dwRes = ::NetLocalGroupAdd( NULL, 1, (LPBYTE)&MyLocalGroup, NULL );
if(dwRes != NERR_Success &&
dwRes != NERR_GroupExists &&
dwRes != ERROR_ALIAS_EXISTS )
{
hr = HRESULT_FROM_WIN32(dwRes);
}
}
else
{
dwRes = ::NetLocalGroupDel( NULL, wszLocalGroupName);
if(dwRes != NERR_Success &&
dwRes != NERR_GroupNotFound &&
dwRes != ERROR_NO_SUCH_ALIAS )
{
hr = HRESULT_FROM_WIN32(dwRes);
}
}
return hr;
}
int CreateGroupDC(LPTSTR szGroupName, LPCTSTR szGroupComment)
{
int iReturn = FALSE;
GROUP_INFO_1 GI1;
ULONG BadParm;
WCHAR * pMachineName = NULL;
ULONG ulErr = ERROR_SUCCESS;
WCHAR wszLocalGroupName[_MAX_PATH];
WCHAR wszLocalGroupComment[_MAX_PATH];
memset(&GI1, 0, sizeof(GROUP_INFO_1));
#if defined(UNICODE) || defined(_UNICODE)
_tcscpy(wszLocalGroupName, szGroupName);
_tcscpy(wszLocalGroupComment, szGroupComment);
#else
MultiByteToWideChar( CP_ACP, 0, szGroupName, -1, wszLocalGroupName, _MAX_PATH);
MultiByteToWideChar( CP_ACP, 0, szGroupComment, -1, wszLocalGroupComment, _MAX_PATH);
#endif
GI1.grpi1_name = wszLocalGroupName;
GI1.grpi1_comment = wszLocalGroupComment;
iisDebugOut((LOG_TYPE_TRACE, _T("CreateGroup:NetGroupAdd\n")));
ulErr = NetGroupAdd(NULL,1,(PBYTE)&GI1,&BadParm);
iisDebugOut((LOG_TYPE_TRACE, _T("CreateGroup:NetGroupAdd,ret=0x%x\n"),ulErr));
switch (ulErr)
{
case NERR_Success:
iisDebugOut((LOG_TYPE_TRACE, _T("CreateGroup:NetGroupAdd,success\n"),ulErr));
iReturn = TRUE;
break;
case NERR_GroupExists:
iReturn = TRUE;
break;
case NERR_InvalidComputer:
iReturn = FALSE;
break;
case NERR_NotPrimary:
{
// it is a backup dc
int err;
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetGetDCName():Start.\n")));
err = NetGetDCName( NULL, NULL, (LPBYTE *)&pMachineName );
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetGetDCName():End.Ret=0x%x\n"),err));
if (err != NERR_Success)
{
MyMessageBox(NULL, _T("CreateUser:NetGetDCName"), err, MB_OK | MB_SETFOREGROUND);
}
else
{
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetGroupAdd().Start.")));
ulErr = NetGroupAdd(pMachineName,1,(PBYTE)&GI1,&BadParm);
iisDebugOut((LOG_TYPE_TRACE, _T("NETAPI32.dll:NetGroupAdd().End.")));
if (NERR_Success == ulErr || NERR_GroupExists == ulErr)
{
iReturn = TRUE;
}
}
}
break;
case ERROR_ACCESS_DENIED:
iReturn = FALSE;
break;
default:
iReturn = FALSE;
break;
}
return iReturn;
}
#endif //_CHICAGO_