From: Chris Koeritz Date: Fri, 11 Jul 2014 17:49:03 +0000 (-0400) Subject: working on getting the run as service tool to work again. X-Git-Tag: 2.140.90~774 X-Git-Url: https://feistymeow.org/gitweb/?a=commitdiff_plain;h=4ea6c95b4bdf06e3cbe6c03edfacae6a856f647b;p=feisty_meow.git working on getting the run as service tool to work again. --- diff --git a/nucleus/library/security/dll_security.h b/nucleus/library/security/dll_security.h new file mode 100644 index 00000000..da26a14c --- /dev/null +++ b/nucleus/library/security/dll_security.h @@ -0,0 +1,39 @@ +#ifndef SECURITY_DLL_DEFINITIONS +#define SECURITY_DLL_DEFINITIONS + +/*****************************************************************************\ +* * +* Name : security DLL helper * +* Author : Chris Koeritz * +* * +* Purpose: * +* * +* Allows the security support to work within a DLL. * +* * +******************************************************************************* +* Copyright (c) 2008-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +\*****************************************************************************/ + +#include "basis/build_configuration.h" + +// windows class tags for the data structures library: +// define BUILD_SECURITY when you are creating the dll and +// define USE_HOOPLE_DLLS when you are importing a class from the dll. +#ifdef BUILD_SECURITY + #define HOOPLE_DLL_EXPORT_CLASS + #define HOOPLE_DLL_EXPORT_FUNCTION +#elif defined(USE_HOOPLE_DLLS) + #define HOOPLE_DLL_IMPORT_CLASS + #define HOOPLE_DLL_IMPORT_FUNCTION +#else + #define SECURITY_CLASS_STYLE + #define SECURITY_FUNCTION_STYLE +#endif + +#endif + diff --git a/nucleus/library/security/makefile b/nucleus/library/security/makefile new file mode 100644 index 00000000..6b963307 --- /dev/null +++ b/nucleus/library/security/makefile @@ -0,0 +1,12 @@ +CONSOLE_MODE = true + +include cpp/variables.def + +PROJECT = security +TYPE = library +ifeq "$(OP_SYSTEM)" "WIN32" + SOURCE = nt_security.cpp win32_security.cpp windows_firewall.cpp +endif +TARGETS = security.lib + +include cpp/rules.def diff --git a/nucleus/library/security/nt_security.cpp b/nucleus/library/security/nt_security.cpp new file mode 100644 index 00000000..e8f55797 --- /dev/null +++ b/nucleus/library/security/nt_security.cpp @@ -0,0 +1,380 @@ + + + +/*****************************************************************************\ +* * +* Name : nt_security * +* Author : Sue Richeson * +* Author : Chris Koeritz * +* * +******************************************************************************* +* Copyright (c) 1999-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +\*****************************************************************************/ + +#ifdef __WIN32__ + +#include "nt_security.h" +#include "win32_security.h" + +#include + +#include + +// LSA success status value. +#ifndef STATUS_SUCCESS + #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +#endif + +nt_security::nt_security() +: m_sDirServiceProvider(NIL) +{ + // Eventually, construction of nt_security should determine if WinNT:// + // or LDAP://, etc is the service provider and set a private member variable + // with the appropriate distinguished name qualifier. + m_sDirServiceProvider = new astring("WinNT://"); +} +//--------------------------------------------------------------------------- + + +nt_security::~nt_security() +{ + if (m_sDirServiceProvider) + delete m_sDirServiceProvider; +} + + +//--------------------------------------------------------------------------- + +bool nt_security::iequalsUsername(astring name1, astring name2) +{ + return normalizeUsername(name1) == normalizeUsername(name2); +} + +const astring &nt_security::normalizeUsername(astring &username) +{ + username.replace_all('/', '\\'); + username.replace_all('|', ':'); + username.to_lower(); + return username; +} + + //--------------------------------------------------------------------------- + +astring nt_security::DomainBinding(const astring &domain) +{ + astring tempstring = *m_sDirServiceProvider + domain; + return (tempstring); +} +//--------------------------------------------------------------------------- + + +astring nt_security::DomainUserBinding(const astring &domain, const astring &user_name) +{ + astring tempstring = *m_sDirServiceProvider + domain + astring("/") + user_name; + return (tempstring); +} +//--------------------------------------------------------------------------- + +// This piece of code is borrowed from the following July 1999 MSDN article +// HOWTO: Look Up Current User Name and Domain Name +// ID: Q155698 +//NOTE: It has been modified for inclusion in this class and it is NT-specific. + +bool nt_security::GetUserAndDomainName(astring &UserName, astring &DomainName) +{ + return win32_security::GetUserAndDomainName(UserName, DomainName); +} + + +//--------------------------------------------------------------------------- +// The following routines were taken from the lsapriv sample application by +// Scott Field on the MSDN January 2001. +//--------------------------------------------------------------------------- + +/*--------------------------------------------------------------------------- +This function attempts to obtain a SID representing the supplied +account on the supplied system. + +If the function succeeds, the return value is the SID. A buffer is +allocated which contains the SID representing the supplied account. +This buffer should be freed when it is no longer needed by calling +HeapFree(GetProcessHeap(), 0, buffer) + +If the function fails, the return SID is NULL. + +Scott Field (sfield) 12-Jul-95 +Sue Richeson 27-FEB-2001 Mods for use in LightLink. +Chris Koeritz 02-JAN-2008 changed some more for use within hoople. +---------------------------------------------------------------------------*/ + +PSID nt_security::GetUserSID(const astring &user_name) +{ + PSID psid = NULL; + char * ReferencedDomain = NULL; + DWORD cbSid = 128; // initial allocation attempt + DWORD cchReferencedDomain = 16; // initial allocation size + SID_NAME_USE peUse; + bool bSuccess = false; + + try + { // + // initial memory allocations + // + psid = (PSID)HeapAlloc(GetProcessHeap(), 0, cbSid); + if (psid != NULL) + { + ReferencedDomain = (char *)HeapAlloc(GetProcessHeap(), 0, cchReferencedDomain * sizeof(TCHAR)); + if (ReferencedDomain != NULL) + { + // Obtain the SID of the specified account on the specified system. + // + bSuccess = true; + while (!LookupAccountName(NULL, // machine to lookup account on + to_unicode_temp(user_name), // account to lookup + psid, // SID of interest + &cbSid, // size of SID + to_unicode_temp(ReferencedDomain), // domain where found. + &cchReferencedDomain, + &peUse)) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + // reallocate memory + // + psid = (PSID)HeapReAlloc(GetProcessHeap(), 0, psid, cbSid); + if(psid != NULL) + { + ReferencedDomain = (char *)HeapReAlloc(GetProcessHeap(), 0, + ReferencedDomain, + cchReferencedDomain * sizeof(TCHAR)); + if (ReferencedDomain == NULL) + { + break; + bSuccess = false; + } + } + else + { + break; + bSuccess = false; + } + } + else + { + break; + bSuccess = false; + } + } // end while + } // if ReferencedDomain + } // if psid + } + catch(...) + { + bSuccess = false; + } + + // Cleanup and indicate failure, if appropriate. + // + if (ReferencedDomain != NULL) + HeapFree(GetProcessHeap(), 0, ReferencedDomain); + + if (!bSuccess) + { + if (psid != NULL) + { + HeapFree(GetProcessHeap(), 0, psid); + psid = NULL; + } + } + + return psid; +} +//--------------------------------------------------------------------------- + + +DWORD nt_security::OpenPolicy(const astring &serverName, DWORD DesiredAccess, PLSA_HANDLE pPolicyHandle) +{ + LSA_OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + DWORD winerror = 0; + + // Always initialize the object attributes to all zeroes. + // + ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); + + transcode_to_utf16 temp_server(serverName); + LSA_UNICODE_STRING server; + server.Buffer = (PWSTR)(UTF16 *)temp_server; + server.Length = serverName.length() * (int)sizeof(UTF16); + server.MaximumLength = (serverName.length() +1) * (int)sizeof(UTF16); + + // Attempt to open the policy. + Status = LsaOpenPolicy(&server, &ObjectAttributes, DesiredAccess, pPolicyHandle); + if (STATUS_SUCCESS != Status) + { + winerror = LsaNtStatusToWinError(Status); + ClosePolicy(pPolicyHandle); + return winerror; + } + else + return winerror; +} +//--------------------------------------------------------------------------- + + +void nt_security::ClosePolicy(PLSA_HANDLE policyHandle) +{ + if (policyHandle != NULL) + LsaClose(policyHandle); +} +//--------------------------------------------------------------------------- + + +/* +void nt_security::InitLsaString(LPWSTR inString, PLSA_UNICODE_STRING LsaString) +{ + DWORD StringLength; + + if (inString == NULL) + { + LsaString->Buffer = NULL; + LsaString->Length = 0; + LsaString->MaximumLength = 0; + return; + } + + StringLength = wcslen(inString); + LsaString->Buffer = inString; + LsaString->Length = (USHORT) StringLength * sizeof(WCHAR); + LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR); +} +*/ +//--------------------------------------------------------------------------- + + +DWORD nt_security::SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, // open policy handle + PSID AccountSid, // SID to grant privilege to + const astring &PrivilegeName, // privilege to grant (Unicode) + bool bEnable) // enable or disable +{ + NTSTATUS Status; + DWORD winerror = 0; + + // Create a LSA_UNICODE_STRING for the privilege name. + // + transcode_to_utf16 temp_priv(PrivilegeName); + LSA_UNICODE_STRING privs; + privs.Buffer = (PWSTR)(UTF16 *)temp_priv; + privs.Length = PrivilegeName.length() * (int)sizeof(UTF16); + privs.MaximumLength = (PrivilegeName.length() +1) * (int)sizeof(UTF16); + + // grant or revoke the privilege, accordingly + // + if (bEnable) + { + Status = LsaAddAccountRights(PolicyHandle, // open policy handle + AccountSid, // target SID + &privs, // privileges + 1); // privilege count + } + else + { + Status = LsaRemoveAccountRights(PolicyHandle, // open policy handle + AccountSid, // target SID + FALSE, // do not disable all rights + &privs, // privileges + 1); // privilege count + } + + if (Status == STATUS_SUCCESS) + return winerror; + else + { + winerror = LsaNtStatusToWinError(Status); + return winerror; + } +} +//--------------------------------------------------------------------------- + + +DWORD nt_security::SetPrivilegeOnUser(const astring &domain, + const astring &user, + const astring &privilege, + bool bEnable) +{ + LSA_HANDLE policyHandle; + PSID psid = NULL; + DWORD winerror = 0; + + // Open the policy on the target machine. + // + winerror = OpenPolicy(domain, (POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES), &policyHandle); + if (winerror != 0) + return winerror; + + // Obtain the SID of the user/group. + // Note that we could target a specific machine, but we don't. + // Specifying NULL for target machine searches for the SID in the + // following order: well-known, Built-in and local, primary domain, + // trusted domains. + // + psid = GetUserSID(user); + if (psid == NULL) + { + ClosePolicy(&policyHandle); + return ERROR_NO_SUCH_USER; + } + + // Grant the SeServiceLogonRight to users represented by psid. + // + winerror = SetPrivilegeOnAccount(policyHandle, psid, privilege, bEnable); + + // Close the policy handle. + // + ClosePolicy(&policyHandle); + + // + // Free memory allocated for SID. + // + if (psid != NULL) + HeapFree(GetProcessHeap(), 0, psid); + + return winerror; +} + +DWORD nt_security::AddUserToGroup(const astring &user_name, const astring &group_name) +{ + LOCALGROUP_MEMBERS_INFO_3 lgmi3; + DWORD dwLevel = 3; + DWORD totalEntries = 1; + NET_API_STATUS nStatus; + +// fwprintf(stderr, L"Usage: %s ServerName GroupName MemberAccountName-(DomainName\\AccountName)\n", argv[0]); + + // Set up the LOCALGROUP_MEMBERS_INFO_3 structure. + // Assign the member account name in form of DomainName\AccountName + transcode_to_utf16 temp_user(user_name); + lgmi3.lgrmi3_domainandname = (LPWSTR)(UTF16 *)temp_user; + + // Call the NetLocalGroupAddMembers() function, specifying level 3. + // Level 0 can use SID + transcode_to_utf16 temp_group(group_name); + nStatus = NetLocalGroupAddMembers(L"", (LPWSTR)(UTF16 *)temp_group, dwLevel, + (LPBYTE)&lgmi3, totalEntries); + +//printf("got error code %d\n" , nStatus); + + if (nStatus == ERROR_MEMBER_IN_ALIAS) nStatus = 0; // not an error. + + return nStatus; +} + +#endif //win32 + + + diff --git a/nucleus/library/security/nt_security.h b/nucleus/library/security/nt_security.h new file mode 100644 index 00000000..6a367280 --- /dev/null +++ b/nucleus/library/security/nt_security.h @@ -0,0 +1,117 @@ +#ifndef NT_SECURITY_CLASS +#define NT_SECURITY_CLASS + +/*****************************************************************************\ +* * +* Name : nt_security * +* Author : Sue Richeson * +* Author : Chris Koeritz * +* * +* Purpose: * +* * +* Provides a Win32 oracle for security questions. * +* * +******************************************************************************* +* Copyright (c) 1999-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +\*****************************************************************************/ + +#ifdef __WIN32__ + + + +#include + + +#include + +// Forward class declarations +#include + +class nt_security +{ +public: + nt_security(); + virtual ~nt_security(); + + static bool iequalsUsername(astring name1, astring name2); + // Compares the two names for equality. Treats backslash (\) and + // forward slash (/} as equal. Ignores case. Treats the pipe (|) and + // colon (:) as equal. + + static const astring &normalizeUsername(astring &username); + // Makes the username all lowercase, converts any forward slash (/) + // characters to back slashes (\), and converts any pipe characters (|) + // to colon (:) characters. + + bool GetUserAndDomainName(astring &UserName, astring &DomainName); + // This function is NT-specific. It returns the user account name and + // domain name of the currently logged in user on the machine on which + // this class is executing. + + astring DomainBinding(const astring &domain); + // This method will constsruct a distinguished name for the domain received. + astring DomainUserBinding(const astring &domain, const astring &user_name); + // This method will construct a distinguished name based on the domain and + // user name received. + + DWORD SetPrivilegeOnUser(const astring &domain, const astring &user, + const astring &privilege, bool bEnable); + // Sets or disables the privilege for the user in the given domain. + // Can also be used to set the privilege on a group in the given domain. + // Returns 0 if successful. Returns Win32 error code if it fails. + // Domain - can be blank, in which case the local machine is assumed; can be a machine + // name or a network domain name (although, having privilege to change a + // priv in a network domain is highly unlikely and will probably result in + // failure, false, return of this method). Ex: "Legolas", "Buildotron" + // User - the account name for which to change the privilege. It can include the + // domain also. Example user names: "Fred", "Legolas/Bubba", "Buildotron/swbuld" + // Can also be a group name. Examples: "Administrators", "Legolas/Users" + // privilege - name of the privilege to be enable/disabled. + // For a list of privilges, consult winnt.h, and search for SE_ASSIGNPRIMARYTOKEN_NAME. + // For a list of logon rights consult ntsecapi.h, and search for SE_BATCH_LOGON_NAME. + // bEnable - true to enable the privilege; false to disable the privilege + + DWORD AddUserToGroup(const astring &user_name, const astring &group_name); + // adds the "user_name" to the local group "group_name". this only makes + // the change on the local machine where this is run. + +protected: + + PSID GetUserSID(const astring &user_name); + // Retrieves the security descriptor (SID) for "user_name". + // PSID is NULL if the method fails. + + DWORD OpenPolicy(const astring &serverName, DWORD DesiredAccess, + PLSA_HANDLE pPolicyHandle); + // Open the LSA policy on the given machine. + // Returns 0 if successful. Returns Win32 error code if it fails. + + void ClosePolicy(PLSA_HANDLE policyHandle); + // Close the given LSA policy handle. + + DWORD SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, // open policy handle + PSID AccountSid, // SID to grant privilege to + const astring &PrivilegeName, // privilege to grant + bool bEnable); // enable or disable + // Enable or disable the stated privilege on the given account. + // Returns 0 if successful. Returns Win32 error code if it fails. + // PolicyHandle - must already have been opened prior to calling this method. + // AccountSid - must already have been obtained prior to calling this method. + // PrivilegeName - must be a valid security privilege name (case sensitive) + // For a list of privilges, consult winnt.h, and search for SE_ASSIGNPRIMARYTOKEN_NAME. + // For a list of logon rights consult ntsecapi.h, and search for SE_BATCH_LOGON_NAME. + // bEnable - true to enable the privilege; false to disable the privilege + +private: + astring *m_sDirServiceProvider; //!< the directory service provider name. +}; + +#endif + +#endif + diff --git a/nucleus/library/security/security_library.cpp b/nucleus/library/security/security_library.cpp new file mode 100644 index 00000000..4a2d5062 --- /dev/null +++ b/nucleus/library/security/security_library.cpp @@ -0,0 +1,11 @@ + + + + +#include "nt_security.cpp" +#include "win32_security.cpp" +#include "windows_firewall.cpp" + + + + diff --git a/nucleus/library/security/win32_security.cpp b/nucleus/library/security/win32_security.cpp new file mode 100644 index 00000000..e62a65c5 --- /dev/null +++ b/nucleus/library/security/win32_security.cpp @@ -0,0 +1,141 @@ + + + +/*****************************************************************************\ +* * +* Name : win32_security * +* Author : Sue Richeson * +* Author : Chris Koeritz * +* * +******************************************************************************* +* Copyright (c) 2000-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +\*****************************************************************************/ + +#ifdef __WIN32__ + +#include "win32_security.h" + +#include +#include + +#include +#include + +// This piece of code is borrowed from the following July 1999 MSDN article +// HOWTO: Look Up Current User Name and Domain Name, ID: Q155698 +//NOTE: It has been modified for inclusion here and it is Win32-specific. + +bool win32_security::GetUserAndDomainName(astring &UserName, astring &DomainName) +{ + HANDLE hToken; + + // Initialize the return parameters. + UserName = ""; + DomainName = ""; + + #define MY_BUFSIZE 512 // highly unlikely to exceed 512 bytes + UCHAR InfoBuffer[ MY_BUFSIZE + 1 ]; + DWORD cbInfoBuffer = MY_BUFSIZE; + SID_NAME_USE snu; + + BOOL bSuccess; + + if(!OpenThreadToken( + GetCurrentThread(), + TOKEN_QUERY, + TRUE, + &hToken + )) { + + if(GetLastError() == ERROR_NO_TOKEN) { + + // + // attempt to open the process token, since no thread token + // exists + // + + if(!OpenProcessToken( + GetCurrentProcess(), + TOKEN_QUERY, + &hToken + )) return FALSE; + + } else { + + // + // error trying to get thread token + // + + return FALSE; + } + } + + bSuccess = GetTokenInformation( hToken, + TokenUser, + InfoBuffer, + cbInfoBuffer, + &cbInfoBuffer); + + if(!bSuccess) { + if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + + // + // alloc buffer and try GetTokenInformation() again + // + + CloseHandle(hToken); + return FALSE; + + } else { + + // + // error getting token info + // + + CloseHandle(hToken); + return FALSE; + } + } + + CloseHandle(hToken); + + TCHAR User[MY_BUFSIZE + 1];; + DWORD cchUserName = MY_BUFSIZE; + TCHAR Domain[MY_BUFSIZE + 1]; + DWORD cchDomainName = MY_BUFSIZE; + + bSuccess = LookupAccountSid(NULL, + ((PTOKEN_USER)InfoBuffer)->User.Sid, + User, + &cchUserName, + Domain, + &cchDomainName, + &snu); + + if (bSuccess) + { + UserName = from_unicode_temp(User); + DomainName = from_unicode_temp(Domain); + } + + return bSuccess; +} + +astring win32_security::full_user() +{ + astring user, temp_domain; + GetUserAndDomainName(user, temp_domain); + user += astring("[") + temp_domain + "]"; + return user; +} + +#endif // windows. + + + + diff --git a/nucleus/library/security/win32_security.h b/nucleus/library/security/win32_security.h new file mode 100644 index 00000000..5ccde038 --- /dev/null +++ b/nucleus/library/security/win32_security.h @@ -0,0 +1,44 @@ +#ifndef WIN32_SECURITY_CLASS +#define WIN32_SECURITY_CLASS + +/*****************************************************************************\ +* * +* Name : win32_security * +* Author : Sue Richeson * +* Author : Chris Koeritz * +* * +* Purpose: * +* * +* Some helper functions for security calls. These are lower level than * +* nt_security and only require bare OS calls. * +* * +******************************************************************************* +* Copyright (c) 2000 By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +\*****************************************************************************/ + +#ifdef __WIN32__ + + + +// forward. +#include + +class win32_security +{ +public: + static bool GetUserAndDomainName(astring &UserName, astring &DomainName); + //!< returns user account and windows domain of logged in user. + + static astring full_user(); + //!< returns user and domain combined into a parsable form: user[domain] +}; + +#endif // windows. + +#endif // outer guard. + diff --git a/nucleus/library/security/windows_firewall.cpp b/nucleus/library/security/windows_firewall.cpp new file mode 100644 index 00000000..677531df --- /dev/null +++ b/nucleus/library/security/windows_firewall.cpp @@ -0,0 +1,151 @@ +/*****************************************************************************\ +* * +* Name : windows firewall wrapper * +* Author : Chris Koeritz * +* * +******************************************************************************* +* Copyright (c) 2009-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +\*****************************************************************************/ + +#include "windows_firewall.h" + + +#include + +using namespace portable; + +// so far this is a good assumption about where to find netsh. +astring netsh_app() { return env_string("WINDIR") + "/System32/netsh.exe"; } + +int windows_firewall::poke_firewall_hole(const astring &program_name, + const astring &exception_name, const astring &hole_description) +{ + astring cmdline; +#ifdef __WIN32__ + known_operating_systems kind = determine_OS(); + if ( (kind == WIN_SRV2K8) || (kind == WIN_VISTA) ) { + // newer style firewall with advfirewall. +//::MessageBox(0, "poke app srv2k8", "yodel", MB_OK); + cmdline = a_sprintf("-c advfirewall firewall add rule name=\"%s\" dir=in " + "action=allow program=\"%s\" enable=yes profile=any " + "description=\"%s\"", exception_name.s(), program_name.s(), + hole_description.s()); + } else { + // older xp style firewall (if that). +//::MessageBox(0, "poke app xp", "yodel", MB_OK); + cmdline = a_sprintf("-c firewall add allowedprogram program=\"%s\" " + "name=\"%s\" mode=enable scope=all profile=all", program_name.s(), + exception_name.s()); + } + + basis::u_int kid_id; + basis::u_int to_return = launch_process::run(netsh_app(), cmdline, + portable::AWAIT_APP_EXIT | portable::HIDE_APP_WINDOW + | portable::SHELL_EXECUTE, kid_id); + return to_return; +#else + if (!program_name || !exception_name || !hole_description) {} // no problem. + return 1; // failure on this platform. +#endif +} + +int windows_firewall::remove_firewall_hole(const astring &program_name, + const astring &exception_name) +{ +#ifdef __WIN32__ + astring cmdline; + + known_operating_systems kind = determine_OS(); + if ( (kind == WIN_SRV2K8) || (kind == WIN_VISTA) ) { +//::MessageBox(0, "removing app srv2k8", "yodel", MB_OK); + // newer style firewall with advfirewall. + cmdline = a_sprintf("-c advfirewall firewall delete rule name=\"%s\" ", + exception_name.s()); + } else { +//::MessageBox(0, "removing app xp", "yodel", MB_OK); + // older xp style firewall (if that). + cmdline = a_sprintf("-c firewall delete allowedprogram program=\"%s\" " + "profile=all", program_name.s()); + } + + basis::u_int kid_id; + basis::u_int to_return = launch_process::run(netsh_app(), cmdline, + portable::AWAIT_APP_EXIT | portable::HIDE_APP_WINDOW + | portable::SHELL_EXECUTE, kid_id); + return to_return; +#else + if (!program_name || !exception_name) {} // no problem. + return 1; // failure on this platform. +#endif +} + +int windows_firewall::poke_firewall_hole(int port_number, + const astring &exception_name, const astring &hole_description, + const astring &protocol) +{ +#ifdef __WIN32__ + astring cmdline; + + known_operating_systems kind = determine_OS(); + if ( (kind == WIN_SRV2K8) || (kind == WIN_VISTA) ) { + // newer style firewall with advfirewall. +//::MessageBox(0, "poke port srv2k8", "yodel", MB_OK); + cmdline = a_sprintf("-c advfirewall firewall add rule name=\"%s\" dir=in " + "action=allow protocol=\"%s\" enable=yes profile=any " + "description=\"%s\" localport=%d", + exception_name.s(), protocol.s(), hole_description.s(), port_number); + } else { + // older xp style firewall (if that). +//::MessageBox(0, "poke port xp", "yodel", MB_OK); + cmdline = a_sprintf("-c firewall add portopening port=%d " + "name=\"%s\" protocol=%s mode=enable scope=all profile=all", + port_number, exception_name.s(), protocol.s()); + } + + basis::u_int kid_id; + basis::u_int to_return = launch_process::run(netsh_app(), cmdline, + portable::AWAIT_APP_EXIT | portable::HIDE_APP_WINDOW + | portable::SHELL_EXECUTE, kid_id); + return to_return; +#else + if (!port_number || !exception_name || !protocol || !hole_description) {} // no problem. + return 1; // failure on this platform. +#endif +} + +int windows_firewall::remove_firewall_hole(int port_number, + const astring &exception_name, const astring &protocol) +{ +#ifdef __WIN32__ + astring cmdline; + + known_operating_systems kind = determine_OS(); + if ( (kind == WIN_SRV2K8) || (kind == WIN_VISTA) ) { +//::MessageBox(0, "removing port srv2k8", "yodel", MB_OK); + // newer style firewall with advfirewall. + cmdline = a_sprintf("-c advfirewall firewall delete rule name=\"%s\" " + "localport=%d protocol=%s", exception_name.s(), + port_number, protocol.s()); + } else { +//::MessageBox(0, "removing port xp", "yodel", MB_OK); + // older xp style firewall (if that). + cmdline = a_sprintf("-c firewall delete portopening protocol=%s " + "port=%d profile=all", protocol.s(), port_number); + } + + basis::u_int kid_id; + basis::u_int to_return = launch_process::run(netsh_app(), cmdline, + portable::AWAIT_APP_EXIT | portable::HIDE_APP_WINDOW + | portable::SHELL_EXECUTE, kid_id); + return to_return; +#else + if (!port_number || !exception_name || !protocol) {} // no problem. + return 1; // failure on this platform. +#endif +} + diff --git a/nucleus/library/security/windows_firewall.h b/nucleus/library/security/windows_firewall.h new file mode 100644 index 00000000..37133dfd --- /dev/null +++ b/nucleus/library/security/windows_firewall.h @@ -0,0 +1,49 @@ +#ifndef WINDOWS_FIREWALL_CLASS +#define WINDOWS_FIREWALL_CLASS + +/*****************************************************************************\ +* * +* Name : windows firewall wrapper * +* Author : Chris Koeritz * +* * +******************************************************************************* +* Copyright (c) 2009-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +\*****************************************************************************/ + + + +#include + +class windows_firewall +{ +public: + // adds a firewall hole for an executable called "program_name" (which should + // be the full path) using a rule called "exception_name". the description + // for the firewall exception should be in "hole_description" (and it's only + // used on vista or server 2008 or later). + // in this and the other methods, a zero return indicates success. any other + // return indicates a failure. + static int poke_firewall_hole(const astring &program_name, + const astring &exception_name, const astring &hole_description); + + // this version will open an exception for a port rather than a program. + static int poke_firewall_hole(int port_number, + const astring &exception_name, const astring &hole_description, + const astring &protocol); + + // removes a previously poked firewall hole for an application. + static int remove_firewall_hole(const astring &program_name, + const astring &exception_name); + + // removes a previously poked exception for a port. + static int remove_firewall_hole(int port_number, + const astring &exception_name, const astring &protocol); +}; + +#endif //outer guard + diff --git a/nucleus/tools/simple_utilities/makefile b/nucleus/tools/simple_utilities/makefile index ee683578..0fe5e849 100644 --- a/nucleus/tools/simple_utilities/makefile +++ b/nucleus/tools/simple_utilities/makefile @@ -6,6 +6,7 @@ PROJECT = simplistic_utils TYPE = application TARGETS = create_guid.exe playsound.exe short_path.exe sleep_ms.exe \ zap_process.exe +#run_as_service.exe ifeq "$(OMIT_VERSIONS)" "" SOURCE += simple_utils_version.rc endif diff --git a/nucleus/tools/simple_utilities/run_as_service.cpp b/nucleus/tools/simple_utilities/run_as_service.cpp new file mode 100644 index 00000000..1f1edf4a --- /dev/null +++ b/nucleus/tools/simple_utilities/run_as_service.cpp @@ -0,0 +1,115 @@ +/*****************************************************************************\ +* * +* Name : run_as_service * +* Author : Chris Koeritz * +* * +******************************************************************************* +* Copyright (c) 2000-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +\*****************************************************************************/ + +#include +#include +#include +#include + +HOOPLE_STARTUP_CODE; + +////////////// + +bool run_as_service(char *user, log_base &out) +{ +#ifdef __WIN32__ + // ensure that the user has the "logon as a service" right. + nt_security secu; + long err = secu.SetPrivilegeOnUser("", user, "SeServiceLogonRight", true); + if (err) { + // that didn't work; probably the user name is bad? + out.log(astring(astring::SPRINTF, "There was a problem giving " + "\"%s\" the \"Logon as a Service\" right:\r\n%s", user, + critical_events::system_error_text(err).s())); + return false; + } +#else + astring junk = user; + out.eol(); + junk += ""; +#endif + return true; +} + +int main(int argc, char *argv[]) +{ + console_logger out; + if (argc < 2) { + out.log(filename(argv[0]).rootname() + " usage:\n\ +The first parameter must be a user name that will be given the\n\ +\"login as a service\" access rights.\n"); + return 1; + } + bool did_it = run_as_service(argv[1], out); + if (did_it) + out.log(astring("Success giving \"") + argv[1] + "\" the 'login as service' rights."); + else + out.log(astring("Failed in giving \"") + argv[1] + "\" the 'login as service' rights!"); + return !did_it; +} + +#ifdef __BUILD_STATIC_APPLICATION__ + // static dependencies found by buildor_gen_deps.sh: + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#endif // __BUILD_STATIC_APPLICATION__ +