📄 vncimportacl.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 + -