mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-18 02:40:13 +00:00
Windows compile fixes, check if running as administrator on startup for Windows.
This commit is contained in:
parent
4935fdf6e4
commit
2498ecbc84
216
main.cpp
216
main.cpp
@ -41,6 +41,7 @@
|
||||
#include <Windows.h>
|
||||
#include <tchar.h>
|
||||
#include <wchar.h>
|
||||
#include <lmcons.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
@ -317,8 +318,8 @@ static int main(int argc,char **argv)
|
||||
fprintf(stderr,"%s is not readable"ZT_EOL_S,argv[3]);
|
||||
return -1;
|
||||
}
|
||||
C25519::Signature signature = id.sign(inf.data(),inf.length());
|
||||
printf("%s",Utils::hex(signature.data,signature.size()).c_str());
|
||||
C25519::Signature signature = id.sign(inf.data(),(unsigned int)inf.length());
|
||||
printf("%s",Utils::hex(signature.data,(unsigned int)signature.size()).c_str());
|
||||
} else if (!strcmp(argv[1],"verify")) {
|
||||
if (argc < 4) {
|
||||
printHelp(stderr,argv[0]);
|
||||
@ -338,7 +339,7 @@ static int main(int argc,char **argv)
|
||||
}
|
||||
|
||||
std::string signature(Utils::unhex(argv[4]));
|
||||
if ((signature.length() > ZT_ADDRESS_LENGTH)&&(id.verify(inf.data(),inf.length(),signature.data(),signature.length()))) {
|
||||
if ((signature.length() > ZT_ADDRESS_LENGTH)&&(id.verify(inf.data(),(unsigned int)inf.length(),signature.data(),(unsigned int)signature.length()))) {
|
||||
printf("%s signature valid"ZT_EOL_S,argv[3]);
|
||||
} else {
|
||||
fprintf(stderr,"%s signature check FAILED"ZT_EOL_S,argv[3]);
|
||||
@ -380,7 +381,186 @@ static BOOL WINAPI _handlerRoutine(DWORD dwCtrlType)
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static BOOL IsCurrentUserLocalAdministrator(void)
|
||||
{
|
||||
BOOL fReturn = FALSE;
|
||||
DWORD dwStatus;
|
||||
DWORD dwAccessMask;
|
||||
DWORD dwAccessDesired;
|
||||
DWORD dwACLSize;
|
||||
DWORD dwStructureSize = sizeof(PRIVILEGE_SET);
|
||||
PACL pACL = NULL;
|
||||
PSID psidAdmin = NULL;
|
||||
|
||||
HANDLE hToken = NULL;
|
||||
HANDLE hImpersonationToken = NULL;
|
||||
|
||||
PRIVILEGE_SET ps;
|
||||
GENERIC_MAPPING GenericMapping;
|
||||
|
||||
PSECURITY_DESCRIPTOR psdAdmin = NULL;
|
||||
SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
|
||||
|
||||
|
||||
/*
|
||||
Determine if the current thread is running as a user that is a member
|
||||
|
||||
of
|
||||
the local admins group. To do this, create a security descriptor
|
||||
|
||||
that
|
||||
has a DACL which has an ACE that allows only local aministrators
|
||||
|
||||
access.
|
||||
Then, call AccessCheck with the current thread's token and the
|
||||
|
||||
security
|
||||
descriptor. It will say whether the user could access an object if
|
||||
|
||||
it
|
||||
had that security descriptor. Note: you do not need to actually
|
||||
|
||||
create
|
||||
the object. Just checking access against the security descriptor
|
||||
|
||||
alone
|
||||
will be sufficient.
|
||||
*/
|
||||
const DWORD ACCESS_READ = 1;
|
||||
const DWORD ACCESS_WRITE = 2;
|
||||
|
||||
|
||||
__try
|
||||
{
|
||||
|
||||
/*
|
||||
AccessCheck() requires an impersonation token. We first get a
|
||||
|
||||
primary
|
||||
token and then create a duplicate impersonation token. The
|
||||
impersonation token is not actually assigned to the thread, but is
|
||||
used in the call to AccessCheck. Thus, this function itself never
|
||||
impersonates, but does use the identity of the thread. If the
|
||||
|
||||
thread
|
||||
was impersonating already, this function uses that impersonation
|
||||
|
||||
context.
|
||||
*/
|
||||
if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY,
|
||||
|
||||
TRUE, &hToken))
|
||||
{
|
||||
if (GetLastError() != ERROR_NO_TOKEN)
|
||||
__leave;
|
||||
|
||||
if (!OpenProcessToken(GetCurrentProcess(),
|
||||
|
||||
TOKEN_DUPLICATE|TOKEN_QUERY, &hToken))
|
||||
__leave;
|
||||
}
|
||||
|
||||
if (!DuplicateToken (hToken, SecurityImpersonation,
|
||||
|
||||
&hImpersonationToken))
|
||||
__leave;
|
||||
|
||||
|
||||
/*
|
||||
Create the binary representation of the well-known SID that
|
||||
represents the local administrators group. Then create the
|
||||
|
||||
security
|
||||
descriptor and DACL with an ACE that allows only local admins
|
||||
|
||||
access.
|
||||
After that, perform the access check. This will determine whether
|
||||
the current user is a local admin.
|
||||
*/
|
||||
if (!AllocateAndInitializeSid(&SystemSidAuthority, 2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID,
|
||||
DOMAIN_ALIAS_RID_ADMINS,
|
||||
0, 0, 0, 0, 0, 0, &psidAdmin))
|
||||
__leave;
|
||||
|
||||
psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||||
if (psdAdmin == NULL)
|
||||
__leave;
|
||||
|
||||
if (!InitializeSecurityDescriptor(psdAdmin,
|
||||
|
||||
SECURITY_DESCRIPTOR_REVISION))
|
||||
__leave;
|
||||
|
||||
// Compute size needed for the ACL.
|
||||
dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) +
|
||||
GetLengthSid(psidAdmin) - sizeof(DWORD);
|
||||
|
||||
pACL = (PACL)LocalAlloc(LPTR, dwACLSize);
|
||||
if (pACL == NULL)
|
||||
__leave;
|
||||
|
||||
if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2))
|
||||
__leave;
|
||||
|
||||
dwAccessMask= ACCESS_READ | ACCESS_WRITE;
|
||||
|
||||
if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask,
|
||||
|
||||
psidAdmin))
|
||||
__leave;
|
||||
|
||||
if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE))
|
||||
__leave;
|
||||
|
||||
/*
|
||||
AccessCheck validates a security descriptor somewhat; set the
|
||||
|
||||
group
|
||||
and owner so that enough of the security descriptor is filled out
|
||||
|
||||
to
|
||||
make AccessCheck happy.
|
||||
*/
|
||||
SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE);
|
||||
SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE);
|
||||
|
||||
if (!IsValidSecurityDescriptor(psdAdmin))
|
||||
__leave;
|
||||
|
||||
dwAccessDesired = ACCESS_READ;
|
||||
|
||||
/*
|
||||
Initialize GenericMapping structure even though you
|
||||
do not use generic rights.
|
||||
*/
|
||||
GenericMapping.GenericRead = ACCESS_READ;
|
||||
GenericMapping.GenericWrite = ACCESS_WRITE;
|
||||
GenericMapping.GenericExecute = 0;
|
||||
GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE;
|
||||
|
||||
if (!AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired,
|
||||
&GenericMapping, &ps, &dwStructureSize, &dwStatus,
|
||||
&fReturn))
|
||||
{
|
||||
fReturn = FALSE;
|
||||
__leave;
|
||||
}
|
||||
}
|
||||
__finally
|
||||
{
|
||||
// Clean up.
|
||||
if (pACL) LocalFree(pACL);
|
||||
if (psdAdmin) LocalFree(psdAdmin);
|
||||
if (psidAdmin) FreeSid(psidAdmin);
|
||||
if (hImpersonationToken) CloseHandle (hImpersonationToken);
|
||||
if (hToken) CloseHandle (hToken);
|
||||
}
|
||||
|
||||
return fReturn;
|
||||
}
|
||||
#endif // __WINDOWS__
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
@ -477,6 +657,13 @@ int main(int argc,char **argv)
|
||||
fclose(pf);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifdef __WINDOWS__
|
||||
if (IsCurrentUserLocalAdministrator() != TRUE) {
|
||||
fprintf(stderr,"%s: must be run as a local administrator."ZT_EOL_S,argv[0]);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int exitCode = 0;
|
||||
@ -485,15 +672,30 @@ int main(int argc,char **argv)
|
||||
node = new Node(homeDir,port,controlPort);
|
||||
switch(node->run()) {
|
||||
case Node::NODE_RESTART_FOR_UPGRADE: {
|
||||
#ifdef __UNIX_LIKE__
|
||||
const char *upgPath = node->reasonForTermination();
|
||||
#ifdef __UNIX_LIKE__
|
||||
// On Unix-type OSes we exec() right into the upgrade. This in turn will
|
||||
// end with us being re-launched either via the upgrade itself or something
|
||||
// like OSX's launchd.
|
||||
if (upgPath) {
|
||||
Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
|
||||
execl(upgPath,upgPath,(char *)0);
|
||||
::execl(upgPath,upgPath,(char *)0);
|
||||
}
|
||||
exitCode = 2;
|
||||
fprintf(stderr,"%s: abnormal termination: unable to execute update at %s\n",argv[0],(upgPath) ? upgPath : "(unknown path)");
|
||||
#endif
|
||||
#else // not __UNIX_LIKE
|
||||
#ifdef __WINDOWS__
|
||||
// On Windows the service checks updates.d and invokes updates if they are
|
||||
// found there. This only happens after exit code 4. The Windows service
|
||||
// will listen to stdout as well to catch the filename.
|
||||
if (upgPath) {
|
||||
printf("[[[ UPDATE AVAILABLE: \"%s\" ]]]\r\n",upgPath);
|
||||
exitCode = 4;
|
||||
} else {
|
||||
exitCode = 2;
|
||||
}
|
||||
#endif // __WINDOWS__
|
||||
#endif // not __UNIX_LIKE__
|
||||
} break;
|
||||
case Node::NODE_UNRECOVERABLE_ERROR: {
|
||||
exitCode = 3;
|
||||
|
@ -151,22 +151,22 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<TargetExt>.exe</TargetExt>
|
||||
<OutDir>$(SolutionDir)\Build\$(Platform)\$(Configuration)\</OutDir>
|
||||
<TargetName>zerotier-one-x86</TargetName>
|
||||
<TargetName>zerotier-one_x86</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<TargetExt>.exe</TargetExt>
|
||||
<OutDir>$(SolutionDir)\Build\$(Platform)\$(Configuration)\</OutDir>
|
||||
<TargetName>zerotier-one-x86</TargetName>
|
||||
<TargetName>zerotier-one_x86</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<TargetExt>.exe</TargetExt>
|
||||
<OutDir>$(SolutionDir)\Build\$(Platform)\$(Configuration)\</OutDir>
|
||||
<TargetName>zerotier-one-x64</TargetName>
|
||||
<TargetName>zerotier-one_x64</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetExt>.exe</TargetExt>
|
||||
<OutDir>$(SolutionDir)\Build\$(Platform)\$(Configuration)\</OutDir>
|
||||
<TargetName>zerotier-one-x64</TargetName>
|
||||
<TargetName>zerotier-one_x64</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
|
@ -45,6 +45,7 @@ namespace ZeroTierOneService
|
||||
|
||||
private void ztService_Exited(object sender, System.EventArgs e)
|
||||
{
|
||||
ztService = null;
|
||||
}
|
||||
|
||||
private string ztHome;
|
||||
|
Loading…
Reference in New Issue
Block a user