⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vncimportacl.cpp

📁 远程控制软件UltraVNC
💻 CPP
字号:
/////////////////////////////////////////////////////////////////////////////
//  Copyright (C) 2004 Martin Scharpf. All Rights Reserved.
//
//  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 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 General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
//  USA.
//
// If the source code for the program is not available from the place from
// which you received this file, check 
// http://ultravnc.sourceforge.net/
#include "vncImportACL.h"

vncImportACL::vncImportACL(){
	lastAllowACE = NULL;
	lastDenyACE = NULL;
}

vncImportACL::~vncImportACL(){
	fprintf(stderr, "deleting ACE_DATA linked lists\n");
	ACE_DATA *tmp = NULL;
	for (ACE_DATA *i = lastDenyACE; i != NULL; i = tmp){
		if (i->pSID)
			delete i->pSID;
		tmp = i->next;
		delete i;
	}
	for (ACE_DATA *j = lastAllowACE; j != NULL; j = tmp){
		if (j->pSID)
			delete j->pSID;
		tmp = j->next;
		delete j;
	}

}

void vncImportACL::GetOldACL(){
	PACL pOldACL = NULL;
	ACL_SIZE_INFORMATION asi;
	HKEY hk = NULL; 
	DWORD dwValueLength = SECURITY_DESCRIPTOR_MIN_LENGTH;
	
	__try{
		
		if (ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE,
			"Software\\ORL\\WinVNC3",
			0, KEY_QUERY_VALUE, &hk )){
			__leave;
		}
		// Read the ACL value from the VNC registry key
		// First call to RegQueryValueEx just gets the buffer length.
		if (ERROR_SUCCESS != RegQueryValueEx(hk,	// subkey handle 
            "ACL",					// value name 
            0,                      // must be zero 
            0,						// value type , not needed here
			NULL,					// 
            &dwValueLength)){       // length of value data 
			__leave;
		}
		pOldACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwValueLength);
		
		if (ERROR_SUCCESS != RegQueryValueEx(hk,	// subkey handle 
            "ACL",					// value name 
            0,										// must be zero 
            0,										// value type 
			(LPBYTE) pOldACL,
            &dwValueLength)){						// length of value data 
			__leave;
		}

	} __finally {
		if (hk)
			RegCloseKey(hk); 
	}

	if ( pOldACL == NULL )
		return;

	if (!GetAclInformation( pOldACL, &asi, sizeof asi, AclSizeInformation))	{
		fprintf(stderr, "GAI(): gle == %lu\n", GetLastError());
		return;
	}

	for (DWORD i = 0; i < asi.AceCount; ++ i)
		ReadAce(i, pOldACL);

	HeapFree(GetProcessHeap(), 0, pOldACL);
}

void vncImportACL::ReadAce(int index, PACL pACL){
	ACE_HEADER *ace;
	//char *type;
	//PSID psid;
	ACE_DATA * pACEdata;

	if (!GetAce( pACL, index, (void **) &ace)) {
		fprintf(stderr, "DACL, entry %d: GetAce() failed, gle == %lu\n",
			index, GetLastError());
		return;
	}

	pACEdata = new ACE_DATA;
	switch ( ace->AceType ) {
		case ACCESS_ALLOWED_ACE_TYPE:
			pACEdata->type = ACCESS_ALLOWED;
			pACEdata->pSID = CopySID(&((ACCESS_ALLOWED_ACE *) ace)->SidStart);
			pACEdata->mask = ((ACCESS_ALLOWED_ACE *) ace)->Mask;
			pACEdata->next = lastAllowACE;
			lastAllowACE   = pACEdata;
			break;
		case ACCESS_DENIED_ACE_TYPE:
			pACEdata->type = ACCESS_DENIED;
			pACEdata->pSID = CopySID(&((ACCESS_DENIED_ACE *) ace)->SidStart);
			pACEdata->mask = ((ACCESS_DENIED_ACE *) ace)->Mask;
			pACEdata->next = lastDenyACE;
			lastDenyACE   = pACEdata;
			break;
		default:
			fprintf(stderr, "Error: Unknown ACE type\n");
			delete pACEdata;
			break;
	}
}

PSID vncImportACL::CopySID(PSID pSID){
	PSID pNewSID = NULL;
	DWORD sidLength = 0;

	if (IsValidSid(pSID)){
		sidLength = GetLengthSid(pSID);
		pNewSID = (PSID) new char[sidLength];
		CopySid(sidLength, pNewSID, pSID);
	}
	return pNewSID;
}

int vncImportACL::ScanInput(){
	int rc = 0;
	vncScanInput scanInput;

	do {
		char linebuf[MAXLEN];
		char *line = linebuf;
		char *token[3];
		char accesstype[MAXLEN];
		char accessmaskstring[MAXLEN];
		char domainaccount[MAXLEN];
		DWORD accessmask = 0;
		token[0] = accesstype;
		token[1] = accessmaskstring;
		token[2] = domainaccount;

		if (!scanInput.GetLine(line)) {
			rc |= 1;
			break;
		}
		scanInput.RemoveNewline(line);
		scanInput.RemoveComment(line);
		if (scanInput.isEmptyLine(line))
			continue;
		if (scanInput.Tokenize(line, token)
			&& sscanf(accessmaskstring, "%x", &accessmask) == 1) {
			FillAceData(accesstype, accessmask, domainaccount);
		} else {
			printf("Error tokenizing line\n");
			rc |= 2;
		}
	} while(!feof(stdin));
	return rc;
}

PACL vncImportACL::BuildACL(){
	PACL pACL = NULL;
	// Need canonical order and normalization??
	// Solution canonical order: aceAllowStart and aceDenyStart?
	// Solution normalization: Check for multiple occurrance of SID
	// in allow list and deny list and merge them.
	long aclSize = 8; // For ACL header

	for (ACE_DATA *i = lastDenyACE; i != NULL; i = i->next){
		aclSize += GetLengthSid(i->pSID) + sizeof(ACCESS_DENIED_ACE) - sizeof(DWORD);
	}
	for (ACE_DATA *j = lastAllowACE; j != NULL; j = j->next){
		aclSize += GetLengthSid(j->pSID) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD);
	}

	pACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,	aclSize);
	
	// Initialize the new ACL.
	if (InitializeAcl(pACL, aclSize, ACL_REVISION)) {
		// Add the access-denied ACEs to the ACL.
		for (ACE_DATA *i = lastDenyACE; i != NULL; i = i->next){
			//Todo: add error handling.
			AddAccessDeniedAce(pACL, ACL_REVISION, i->mask, i->pSID);
		}
		for (ACE_DATA *j = lastAllowACE; j != NULL; j = j->next){
			//Todo: add error handling.
			AddAccessAllowedAce(pACL, ACL_REVISION, j->mask, j->pSID);
		}
	}
	return pACL;
}

bool vncImportACL::SetACL(PACL pACL){
   HKEY hk = NULL; 
	bool isSaveOK = false;

	
	ACL_SIZE_INFORMATION AclInformation;
	DWORD nAclInformationLength = sizeof(AclInformation);

	// Todo: Better error handling
	if (pACL)
		GetAclInformation(pACL, &AclInformation, nAclInformationLength, AclSizeInformation);

	__try{
		if (ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE,
			"Software\\ORL\\WinVNC3",
			0, KEY_SET_VALUE, &hk )){
			fprintf(stderr, "Error %d: RegOpenKeyEx\n", GetLastError());
			__leave;
		}
		
		// Add the ACL value to the VNC registry key
		if (ERROR_SUCCESS != RegSetValueEx(hk,
            "ACL",
            0,
            REG_BINARY,
			(LPBYTE) pACL,
            AclInformation.AclBytesInUse)){
			fprintf(stderr, "Error %d: RegSetValueEx\n", GetLastError());
			__leave;
		}
		isSaveOK = true;
		fprintf(stderr, "RegSetValueEx passed\n");
	} __finally {
		if (hk)
			RegCloseKey(hk); 
	}
	return isSaveOK;
}

bool vncImportACL::FillAceData(const char *type, 
				 DWORD mask, 
				 const char *user){
	ACE_TYPE acetype;
	char *domainaccount = NULL;
	PSID pSID = NULL;

	//type
	if (_stricmp(type, "allow") == 0)
		acetype = ACCESS_ALLOWED;
	else if (_stricmp(type, "deny") == 0)
		acetype = ACCESS_DENIED;
	else {
		fprintf(stderr, "error with ACE type, neither 'allow' nor 'deny'\n");
		return false;
	}

	//mask
	mask &= ALL_RIGHTS;

	// if name starts with ".\", replace the dot with the computername.
	// if name starts with "..\", replace the dots with the domainname.
	if (strncmp(user, ".\\", 2) == 0)
		domainaccount = AddComputername(user);
	else if  (strncmp(user, "..\\", 2) == 0)
		domainaccount = AddDomainname(user);
	else {
		domainaccount = new char[strlen(user)+1];
		strcpy(domainaccount,user);
	}
	pSID = GetSID(domainaccount);
	if (!pSID)
		return false;
	printf("account: %s, mask: %x, type: %s\n", 
		domainaccount, mask, acetype == ACCESS_ALLOWED ? "allow" : "deny");
	ACE_DATA *ace = new ACE_DATA;
	ace->type = acetype;
	ace->mask = mask;
	ace->pSID = pSID;
	switch (acetype){
	case ACCESS_ALLOWED:
		ace->next = lastAllowACE;
		lastAllowACE = ace;
		break;
	case ACCESS_DENIED:
		ace->next = lastDenyACE;
		lastDenyACE = ace;
		break;
	default:
		break;
	}

	delete [] domainaccount;
	domainaccount = NULL;

	return true; // Needs better error signalling.
}

PSID vncImportACL::GetSID(const char *domainaccount){
	PSID pSid = NULL;
	unsigned long ulDomLen = 0;
	unsigned long ulSidLen = 0;
	SID_NAME_USE peUse;
	char *domain = NULL;

	// Get accounts's SID
	// First call to LookupAccountName is expected to fail.
	// Sets pSid and domain size
	LookupAccountName(NULL, domainaccount, pSid, &ulSidLen,
		domain, &ulDomLen, &peUse);
	pSid = (PSID)new char[ulSidLen];
	domain = new char[ulDomLen];
	LookupAccountName(NULL, domainaccount,
		pSid, &ulSidLen, domain, &ulDomLen, &peUse);
	if (!IsValidSid(pSid)){
		fprintf(stderr, "%s: SID not valid.\n", domainaccount);
		delete [] pSid;
				pSid = NULL;
	}
	delete [] domain;

	return pSid;
}

// SplitString splits a string 'input' on the first occurence of char 'separator'
// into string 'head' and 'tail' (removing the separator).
// If separator is not found, head = "" and tail = input.
const char * vncImportACL::SplitString(const char *input, char separator, char *head){
	const char * tail;
	int l;

	tail = strchr(input, separator);
	if (tail){
		l = tail - input;
		// get rid of separator
		tail = tail + 1; 
		strncpy(head, input, l);
		head[l] = '\0';
	} else {
		tail   = input;
		head[0] = '\0';
	}
	return tail;
}

char *vncImportACL::AddComputername(const char *user){
	unsigned long buflen = MAXLEN;
	char computername[MAXLEN];
	if (!GetComputerName(computername, &buflen)){
		fprintf(stderr, "GetComputerName error %i\n", GetLastError());
		return NULL;
	}
	fprintf(stderr, "Detected computername = %s\n", computername);
	// Length of computername and user minus beginning dot plus terminating '\0'.
	char *domainaccount = new char[strlen(computername) + strlen(user)];
	strcpy(domainaccount, computername);
	strcat(domainaccount, user + 1);

	return domainaccount;
}

char *vncImportACL::AddDomainname(const char *user){
	unsigned long buflen = MAXLEN;
	char domain[MAXLEN * sizeof(wchar_t)];
	LPWKSTA_INFO_100 wkstainfo = NULL;
	NET_API_STATUS nStatus;

	nStatus = NetWkstaGetInfo( 0 , 100 , (LPBYTE *) &wkstainfo);
	if (nStatus == NERR_Success)
		wcstombs( domain, wkstainfo->wki100_langroup, MAXLEN );
	else
		fprintf(stderr, "NetWkstaGetInfo() returned %lu \n", wkstainfo);
	domain[MAXLEN - 1] = '\0';
	fprintf(stderr, "Detected domain = %s\n",domain);
	NetApiBufferFree(wkstainfo);
	wkstainfo = NULL;

	// Length of domainname and user minus beginning dots plus terminating '\0'.
	char *domainaccount = new char[strlen(domain) + strlen(user) - 1];
	strcpy(domainaccount, domain);
	strcat(domainaccount, user + 2);

	return domainaccount;
}

// vncScanInput struct

bool vncScanInput::GetLine(char *line){
	line[0] = '\0';
	fgets(line, MAXLEN, stdin);
	return ferror(stdin) ? false : true;
}

bool vncScanInput::isEmptyLine(char *line){
	for (unsigned int i = 0; i < strlen(line); i++)
		if (line[i] != ' ' && line[i] != '\t')
			return false;
	return true;
}

void vncScanInput::RemoveComment(char *line){
	if (char *comment = strchr(line, ';'))
		*comment = '\0';
}

void vncScanInput::RemoveNewline(char *line){
	if (line[strlen(line)-1] == '\n')
		line[strlen(line)-1] = '\0';
}

bool vncScanInput::Tokenize(const char *line, char **token){
	int tokenCount = 0;

	// Loop until the end of line or until 4th token found
	for (; strlen(line) > 0 && tokenCount < 4;) {
		int len = 0;
		switch (*line) {
		case ' ' :
		case '\t': 
			line++; // Eat whitespace
			break;
		case '"' : 
			line++; // Eat opening quote
			len = GetQuoteLength(line);
			tokenCount = AddToken(token, tokenCount, &line, len);
			line++; // Eat closing quote
			break;
		default:
			len = GetWordLength(line);
			tokenCount = AddToken(token, tokenCount, &line, len);
			break;
		}
	}
	return (tokenCount == 3 && strlen(line) == 0) ? true : false;
}

int vncScanInput::GetWordLength(const char *line){
	int length = 0;
	int blength = 0;
	int tlength = 0;
	
	char *nextblank = strchr(line, ' ');
	char *nexttab   = strchr(line, '\t');
	if (nextblank) 
		blength = nextblank - line;
	if (nexttab)
		tlength = nexttab - line;
	if (nextblank && nexttab) // Found blank and tab
		length = __min(blength, tlength);
	else if (nextblank) // Found only a blank
		length = blength;
	else if (nexttab) // Found only a tab
		length = tlength;
	if (!length) // Found neither blank nor tab
		length = strlen(line);
	return length;
}

int vncScanInput::GetQuoteLength(const char *line){
	char *eoq = strchr(line, '"');
	int len = 0;
	if (eoq)
		len = eoq - line;
	return len;
}

int vncScanInput::AddToken(char **token, int tokenCount, const char **line, int len){
	if (len) {
		if (tokenCount < 3) {
			strncpy(token[tokenCount], *line, len);
			token[tokenCount][len] = '\0';
		}
		*line += len; // Eat token
		tokenCount++;
	}
	return tokenCount;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -