urbackup_backend/fileservplugin/main.cpp
2021-06-20 20:58:50 +02:00

392 lines
8.3 KiB
C++

/*************************************************************************
* UrBackup - Client/Server backup system
* Copyright (C) 2011-2016 Martin Raiber
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
#include "../vld.h"
#include <fstream>
#include <iostream>
#ifdef _WIN32
# include <conio.h>
# include <ws2tcpip.h>
#endif
#include "../Interface/Server.h"
#include "CTCPFileServ.h"
#include "settings.h"
#include "../stringtools.h"
#include "log.h"
std::fstream logfile;
CTCPFileServ *TCPServer=nullptr;
#ifdef LINUX
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#endif
#include <algorithm>
#ifdef DLL_EXPORT
# define EXPORT_METHOD_INT 5
#endif
#ifdef _WIN32
void RestartServer()
{
_u16 tcpport=TCPServer->getTCPPort();
_u16 udpport=TCPServer->getUDPPort();
std::string servername=TCPServer->getServername();
bool use_fqdn=TCPServer->getUseFQDN();
TCPServer->KickClients();
delete TCPServer;
Sleep(1000);
TCPServer=new CTCPFileServ;
int tries=20;
while(!TCPServer->Start(tcpport, udpport, servername, use_fqdn) )
{
Sleep(1000);
if(tries<=0)
{
_exit(32);
}
--tries;
}
}
bool EnumerateInterfaces()
{
static std::vector<std::vector<char> > ips;
char hostname[MAX_PATH];
_i32 rc=gethostname(hostname, MAX_PATH);
if(rc==SOCKET_ERROR)
return false;
bool new_ifs=false;
std::vector<std::vector<char> > new_ips;
struct addrinfo* h;
if(getaddrinfo(hostname, NULL, NULL, &h)==0)
{
for(addrinfo* ptr = h;ptr!=NULL;ptr=ptr->ai_next)
{
if(ptr->ai_family==AF_INET || ptr->ai_family==AF_INET6)
{
std::vector<char> address;
address.resize(ptr->ai_addrlen);
memcpy(&address[0], ptr->ai_addr, ptr->ai_addrlen);
if(std::find(ips.begin(), ips.end(), address)==ips.end())
{
new_ifs=true;
}
new_ips.push_back(address);
}
}
freeaddrinfo(h);
}
for(size_t i=0;i<ips.size();++i)
{
if(std::find(new_ips.begin(), new_ips.end(), ips[i])==new_ips.end())
{
new_ifs=true;
}
}
ips=new_ips;
return new_ifs;
}
void LookForInterfaceChanges()
{
static int num=-1;
if(num>=10 )
{
num=0;
if(EnumerateInterfaces()==true)
{
RestartServer();
}
}
if( num==-1 )
EnumerateInterfaces();
++num;
}
HRESULT ModifyPrivilege(
IN LPCTSTR szPrivilege,
IN BOOL fEnable)
{
HRESULT hr = S_OK;
TOKEN_PRIVILEGES NewState;
LUID luid;
HANDLE hToken = NULL;
// Open the process token for this process.
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken ))
{
Log("Failed OpenProcessToken", LL_ERROR);
return ERROR_FUNCTION_FAILED;
}
// Get the local unique ID for the privilege.
if ( !LookupPrivilegeValue( NULL,
szPrivilege,
&luid ))
{
CloseHandle( hToken );
Log("Failed LookupPrivilegeValue", LL_ERROR);
return ERROR_FUNCTION_FAILED;
}
// Assign values to the TOKEN_PRIVILEGE structure.
NewState.PrivilegeCount = 1;
NewState.Privileges[0].Luid = luid;
NewState.Privileges[0].Attributes =
(fEnable ? SE_PRIVILEGE_ENABLED : 0);
// Adjust the token privilege.
if (!AdjustTokenPrivileges(hToken,
FALSE,
&NewState,
0,
NULL,
NULL))
{
Log("Failed AdjustTokenPrivileges", LL_ERROR);
hr = ERROR_FUNCTION_FAILED;
}
// Close the handle.
CloseHandle(hToken);
return hr;
}
bool optain_backup_privs()
{
#ifdef BACKUP_SEM
bool ret = true;
HRESULT hr = ModifyPrivilege(SE_BACKUP_NAME, TRUE);
if (!SUCCEEDED(hr))
{
Log("Failed to modify backup privileges", LL_ERROR);
ret = false;
}
else
{
Log("Backup privileges set successfully", LL_DEBUG);
}
hr = ModifyPrivilege(SE_SECURITY_NAME, TRUE);
if (!SUCCEEDED(hr))
{
Log("Failed to modify backup privileges (SE_SECURITY_NAME)", LL_ERROR);
ret = false;
}
else
{
Log("Backup privileges set successfully (SE_SECURITY_NAME)", LL_DEBUG);
}
hr = ModifyPrivilege(SE_RESTORE_NAME, TRUE);
if (!SUCCEEDED(hr))
{
Log("Failed to modify backup privileges (SE_RESTORE_NAME)", LL_ERROR);
ret = false;
}
else
{
Log("Backup privileges set successfully (SE_RESTORE_NAME)", LL_DEBUG);
}
return ret;
#else
return false;
#endif
}
#endif //_WIN32
#ifdef LINUX_DAEMON
bool c_run=true;
void termination_handler(int signum)
{
c_run=false;
_exit(2);
}
#endif
#ifdef CONSOLE_ON
int main(int argc, char* argv[])
{
#elif AS_SERVICE
void my_init_fcn(void)
{
#elif EXPORT_METHOD_INT
int start_server_int(unsigned short tcpport, unsigned short udpport, const std::string &pSname, const bool *pDostop, bool use_fqdn)
{
#else
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
#endif
#ifdef _DEBUG
{
#endif
#ifdef LINUX_DAEMON
std::cout << "Starting as Daemon..." << std::endl;
if( fork()==0 )
{
setsid();
for (int i=getdtablesize();i>=0;--i) close(i);
int i=open("/dev/null",O_RDWR);
dup(i);
dup(i);
}
else
exit(0);
if (signal (SIGINT, termination_handler) == SIG_IGN)
signal (SIGINT, SIG_IGN);
if (signal (SIGHUP, termination_handler) == SIG_IGN)
signal (SIGHUP, SIG_IGN);
if (signal (SIGTERM, termination_handler) == SIG_IGN)
signal (SIGTERM, SIG_IGN);
c_run=true;
#endif
#ifndef _DEBUG
#ifndef AS_SERVICE
#ifndef EXPORT_METHOD_INT
WriteReg();
#endif
#endif
#endif
std::string servername;
#ifdef CONSOLE_ON
if(argc==2)
servername=argv[1];
#endif
#ifdef _WIN32
optain_backup_privs();
#endif
#ifdef LOG_FILE
#ifdef _WIN32
logfile.open("C:\\urinstallsrv.log", std::ios::out | std::ios::binary );
#else
logfile.open("/var/log/urinstallsrv.log", std::ios::out | std::ios::binary );
#endif
#endif
/*std::fstream out(testfilename.c_str(), std::ios::out | std::ios::binary );
if( out.is_open()==false )
Log("Can't create testfile... Could perhaps cause problems.");
char* buffer=new char[1024];
for(size_t i=0;i<1024;++i)
out.write(buffer, 1024);
out.close();
delete[] buffer;
*/
#ifdef _WIN32
SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
#endif
TCPServer=new CTCPFileServ;
#ifndef EXPORT_METHOD_INT
bool suc=TCPServer->Start(55634,55635,servername);
#else
bool suc=TCPServer->Start(tcpport, udpport, (pSname=="")?servername:pSname, use_fqdn);
#endif
if(suc==false)
{
delete TCPServer;
TCPServer=nullptr;
#ifdef _WIN32
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
#endif
return 99;
}
#ifndef AS_SERVICE
while(true)
{
#if defined(_DEBUG) && defined(_WIN32)
if( _kbhit() )
{
break;
}
#endif
bool b=TCPServer->Run();
if( b==false )
break;
#ifdef LINUX_DEAMON
if( c_run==false )
break;
#endif
#if EXPORT_METHOD_INT
if(*pDostop==true)
{
TCPServer->KickClients();
break;
}
#endif
}
delete TCPServer;
#endif //AS_SERVICE
#ifdef _WIN32
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
#endif
#ifndef AS_SERVICE
return 2;
#endif
#ifdef _DEBUG
}
#endif
}