diff options
Diffstat (limited to 'testprogs/win32/prepare_dcpromo')
-rwxr-xr-x | testprogs/win32/prepare_dcpromo/GNUmakefile | 21 | ||||
-rwxr-xr-x | testprogs/win32/prepare_dcpromo/NMakefile | 16 | ||||
-rwxr-xr-x | testprogs/win32/prepare_dcpromo/prepare_dcpromo.c | 1074 |
3 files changed, 1111 insertions, 0 deletions
diff --git a/testprogs/win32/prepare_dcpromo/GNUmakefile b/testprogs/win32/prepare_dcpromo/GNUmakefile new file mode 100755 index 0000000..1c95613 --- /dev/null +++ b/testprogs/win32/prepare_dcpromo/GNUmakefile @@ -0,0 +1,21 @@ +INCLUDES=-I. +CFLAGS=$(INCLUDES) +LIBS=-ladvapi32 + +PREPARE_DCPROMO = prepare_dcpromo.exe + +all: $(PREPARE_DCPROMO) + +MINGW_CC = i586-mingw32msvc-cc +CC = $(MINGW_CC) + +.SUFFIXES: .c .obj .exe + +.c.obj: + $(CC) $(CFLAGS) -c $< -o $@ + +.obj.exe: + $(CC) $(CFLAGS) -o $@ $< $(LIBS) + +clean: + rm -f *~ *.obj *.exe diff --git a/testprogs/win32/prepare_dcpromo/NMakefile b/testprogs/win32/prepare_dcpromo/NMakefile new file mode 100755 index 0000000..6f810ee --- /dev/null +++ b/testprogs/win32/prepare_dcpromo/NMakefile @@ -0,0 +1,16 @@ +# +# use nmake /f NMakefile [<target>] +# +INCLUDES=-I +CFLAGS=$(INCLUDES) -Zi -nologo -Dsnprintf=sprintf_s +LIBS=advapi32.lib + +PREPARE_DCPROMO = prepare_dcpromo.exe + +all: $(PREPARE_DCPROMO) + +clean: + del *~ *.obj *.exe + +prepare_dcpromo.exe: prepare_dcpromo.obj + $(CC) $(CFLAGS) -o prepare_dcpromo.exe prepare_dcpromo.obj $(LIBS) diff --git a/testprogs/win32/prepare_dcpromo/prepare_dcpromo.c b/testprogs/win32/prepare_dcpromo/prepare_dcpromo.c new file mode 100755 index 0000000..91b819b --- /dev/null +++ b/testprogs/win32/prepare_dcpromo/prepare_dcpromo.c @@ -0,0 +1,1074 @@ +/* + Copyright (C) Stefan Metzmacher <metze@samba.org> 2010 + + 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 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + Published to the public domain + */ + +/* + * This tool can set the DOMAIN-SID and nextRid counter in + * the local SAM on windows servers (tested with w2k8r2) + * + * dcpromo will use this values for the ad domain it creates. + * + * This might be useful for upgrades from a Samba3 domain. + */ + +#include <windows.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +/* Convert a binary SID to a character string */ +static DWORD SidToString(const SID *sid, + char **string) +{ + DWORD id_auth; + int i, ofs, maxlen; + char *result; + + if (!sid) { + return ERROR_INVALID_SID; + } + + maxlen = sid->SubAuthorityCount * 11 + 25; + + result = (char *)malloc(maxlen); + if (result == NULL) { + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* + * BIG NOTE: this function only does SIDS where the identauth is not + * >= ^32 in a range of 2^48. + */ + + id_auth = sid->IdentifierAuthority.Value[5] + + (sid->IdentifierAuthority.Value[4] << 8) + + (sid->IdentifierAuthority.Value[3] << 16) + + (sid->IdentifierAuthority.Value[2] << 24); + + ofs = snprintf(result, maxlen, "S-%u-%lu", + (unsigned int)sid->Revision, (unsigned long)id_auth); + + for (i = 0; i < sid->SubAuthorityCount; i++) { + ofs += snprintf(result + ofs, maxlen - ofs, "-%lu", + (unsigned long)sid->SubAuthority[i]); + } + + *string = result; + return ERROR_SUCCESS; +} + +static DWORD StringToSid(const char *str, + SID *sid) +{ + const char *p; + char *q; + DWORD x; + + if (!sid) { + return ERROR_INVALID_PARAMETER; + } + + /* Sanity check for either "S-" or "s-" */ + + if (!str + || (str[0]!='S' && str[0]!='s') + || (str[1]!='-')) + { + return ERROR_INVALID_PARAMETER; + } + + /* Get the SID revision number */ + + p = str+2; + x = (DWORD)strtol(p, &q, 10); + if (x==0 || !q || *q!='-') { + return ERROR_INVALID_SID; + } + sid->Revision = (BYTE)x; + + /* Next the Identifier Authority. This is stored in big-endian + in a 6 byte array. */ + + p = q+1; + x = (DWORD)strtol(p, &q, 10); + if (!q || *q!='-') { + return ERROR_INVALID_SID; + } + sid->IdentifierAuthority.Value[5] = (x & 0x000000ff); + sid->IdentifierAuthority.Value[4] = (x & 0x0000ff00) >> 8; + sid->IdentifierAuthority.Value[3] = (x & 0x00ff0000) >> 16; + sid->IdentifierAuthority.Value[2] = (x & 0xff000000) >> 24; + sid->IdentifierAuthority.Value[1] = 0; + sid->IdentifierAuthority.Value[0] = 0; + + /* now read the the subauthorities */ + + p = q +1; + sid->SubAuthorityCount = 0; + while (sid->SubAuthorityCount < 6) { + x=(DWORD)strtoul(p, &q, 10); + if (p == q) + break; + if (q == NULL) { + return ERROR_INVALID_SID; + } + sid->SubAuthority[sid->SubAuthorityCount++] = x; + + if ((*q!='-') || (*q=='\0')) + break; + p = q + 1; + } + + /* IF we ended early, then the SID could not be converted */ + + if (q && *q!='\0') { + return ERROR_INVALID_SID; + } + + return ERROR_SUCCESS; +} + +#define MIN(a,b) ((a)<(b)?(a):(b)) +static void print_asc(const unsigned char *buf,int len) +{ + int i; + for (i=0;i<len;i++) + printf("%c", isprint(buf[i])?buf[i]:'.'); +} + +static void dump_data(const unsigned char *buf1,int len) +{ + const unsigned char *buf = (const unsigned char *)buf1; + int i=0; + if (len<=0) return; + + printf("[%03X] ",i); + for (i=0;i<len;) { + printf("%02X ",(int)buf[i]); + i++; + if (i%8 == 0) printf(" "); + if (i%16 == 0) { + print_asc(&buf[i-16],8); printf(" "); + print_asc(&buf[i-8],8); printf("\n"); + if (i<len) printf("[%03X] ",i); + } + } + if (i%16) { + int n; + n = 16 - (i%16); + printf(" "); + if (n>8) printf(" "); + while (n--) printf(" "); + n = MIN(8,i%16); + print_asc(&buf[i-(i%16)],n); printf( " " ); + n = (i%16) - n; + if (n>0) print_asc(&buf[i-n],n); + printf("\n"); + } +} + +static DWORD calc_tmp_HKLM_SECURITY_SD(SECURITY_DESCRIPTOR *old_sd, + SID *current_user_sid, + SECURITY_DESCRIPTOR **_old_parent_sd, + SECURITY_DESCRIPTOR **_old_child_sd, + SECURITY_DESCRIPTOR **_new_parent_sd, + SECURITY_DESCRIPTOR **_new_child_sd) +{ + LONG status; + DWORD cbSecurityDescriptor = 0; + SECURITY_DESCRIPTOR *old_parent_sd = NULL; + SECURITY_DESCRIPTOR *old_child_sd = NULL; + SECURITY_DESCRIPTOR *new_parent_sd = NULL; + SECURITY_DESCRIPTOR *new_child_sd = NULL; + BOOL ok; + ACL *old_Dacl = NULL; + ACL *new_Dacl = NULL; + ACL_SIZE_INFORMATION dacl_info; + DWORD i = 0; + SECURITY_DESCRIPTOR *AbsoluteSD = NULL; + DWORD dwAbsoluteSDSize = 0; + DWORD dwRelativeSDSize = 0; + DWORD dwDaclSize = 0; + ACL *Sacl = NULL; + DWORD dwSaclSize = 0; + SID *Owner = NULL; + DWORD dwOwnerSize = 0; + SID *PrimaryGroup = NULL; + DWORD dwPrimaryGroupSize = 0; + ACCESS_ALLOWED_ACE *ace = NULL; + + ok = MakeAbsoluteSD(old_sd, + NULL, + &dwAbsoluteSDSize, + NULL, + &dwDaclSize, + NULL, + &dwSaclSize, + NULL, + &dwOwnerSize, + NULL, + &dwPrimaryGroupSize); + if (!ok) { + status = GetLastError(); + } + if (status != ERROR_INSUFFICIENT_BUFFER) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + AbsoluteSD = (SECURITY_DESCRIPTOR *)malloc(dwAbsoluteSDSize+1024); + if (AbsoluteSD == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return ERROR_NOT_ENOUGH_MEMORY; + } + old_Dacl = (ACL *)malloc(dwDaclSize + 1024); + if (old_Dacl == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return ERROR_NOT_ENOUGH_MEMORY; + } + Sacl = (ACL *)malloc(dwSaclSize); + if (Sacl == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return ERROR_NOT_ENOUGH_MEMORY; + } + Owner = (SID *)malloc(dwOwnerSize); + if (Owner == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return ERROR_NOT_ENOUGH_MEMORY; + } + PrimaryGroup = (SID *)malloc(dwPrimaryGroupSize); + if (PrimaryGroup == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return ERROR_NOT_ENOUGH_MEMORY; + } + + ok = MakeAbsoluteSD(old_sd, + AbsoluteSD, + &dwAbsoluteSDSize, + old_Dacl, + &dwDaclSize, + Sacl, + &dwSaclSize, + Owner, + &dwOwnerSize, + PrimaryGroup, + &dwPrimaryGroupSize); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + AbsoluteSD->Control |= SE_DACL_AUTO_INHERITED | SE_DACL_AUTO_INHERIT_REQ | SE_DACL_PROTECTED; + dwRelativeSDSize = 0; + ok = MakeSelfRelativeSD(AbsoluteSD, + NULL, + &dwRelativeSDSize); + if (!ok) { + status = GetLastError(); + } + if (status != ERROR_INSUFFICIENT_BUFFER) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return ERROR_NOT_ENOUGH_MEMORY; + } + + old_parent_sd = (SECURITY_DESCRIPTOR *)malloc(dwRelativeSDSize); + if (old_parent_sd == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return ERROR_NOT_ENOUGH_MEMORY; + } + + ok = MakeSelfRelativeSD(AbsoluteSD, + old_parent_sd, + &dwRelativeSDSize); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + ok = GetAclInformation(old_Dacl, + &dacl_info, + sizeof(dacl_info), + AclSizeInformation); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + new_Dacl = (ACL *)calloc(dacl_info.AclBytesInUse + 1024, 1); + if (new_Dacl == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return ERROR_NOT_ENOUGH_MEMORY; + } + + InitializeAcl(new_Dacl, dacl_info.AclBytesInUse + 1024, ACL_REVISION); + + ok = AddAccessAllowedAce(new_Dacl, ACL_REVISION, + KEY_ALL_ACCESS, current_user_sid); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + ok = GetAce(new_Dacl, 0, (LPVOID *)&ace); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + ace->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE; + + for (i=0; i < dacl_info.AceCount; i++) { + ok = GetAce(old_Dacl, i, (LPVOID *)&ace); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + ok = AddAce(new_Dacl, ACL_REVISION, MAXDWORD, + ace, ace->Header.AceSize); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + } + + AbsoluteSD->Dacl = new_Dacl; + dwRelativeSDSize = 0; + ok = MakeSelfRelativeSD(AbsoluteSD, + NULL, + &dwRelativeSDSize); + if (!ok) { + status = GetLastError(); + } + if (status != ERROR_INSUFFICIENT_BUFFER) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return ERROR_NOT_ENOUGH_MEMORY; + } + + new_parent_sd = (SECURITY_DESCRIPTOR *)malloc(dwRelativeSDSize); + if (new_parent_sd == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return ERROR_NOT_ENOUGH_MEMORY; + } + + ok = MakeSelfRelativeSD(AbsoluteSD, + new_parent_sd, + &dwRelativeSDSize); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + for (i=0; i < dacl_info.AceCount; i++) { + ok = GetAce(old_Dacl, i, (LPVOID *)&ace); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + ace->Header.AceFlags |= INHERITED_ACE; + } + + AbsoluteSD->Control &= ~SE_DACL_PROTECTED; + AbsoluteSD->Dacl = old_Dacl; + dwRelativeSDSize = 0; + ok = MakeSelfRelativeSD(AbsoluteSD, + NULL, + &dwRelativeSDSize); + if (!ok) { + status = GetLastError(); + } + if (status != ERROR_INSUFFICIENT_BUFFER) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return ERROR_NOT_ENOUGH_MEMORY; + } + + old_child_sd = (SECURITY_DESCRIPTOR *)malloc(dwRelativeSDSize); + if (old_child_sd == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return ERROR_NOT_ENOUGH_MEMORY; + } + + ok = MakeSelfRelativeSD(AbsoluteSD, + old_child_sd, + &dwRelativeSDSize); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + for (i=0; i < dacl_info.AceCount + 1; i++) { + ok = GetAce(new_Dacl, i, (LPVOID *)&ace); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + ace->Header.AceFlags |= INHERITED_ACE; + } + + AbsoluteSD->Dacl = new_Dacl; + dwRelativeSDSize = 0; + ok = MakeSelfRelativeSD(AbsoluteSD, + NULL, + &dwRelativeSDSize); + if (!ok) { + status = GetLastError(); + } + if (status != ERROR_INSUFFICIENT_BUFFER) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return ERROR_NOT_ENOUGH_MEMORY; + } + + new_child_sd = (SECURITY_DESCRIPTOR *)malloc(dwRelativeSDSize); + if (new_child_sd == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return ERROR_NOT_ENOUGH_MEMORY; + } + + ok = MakeSelfRelativeSD(AbsoluteSD, + new_child_sd, + &dwRelativeSDSize); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + *_old_parent_sd = old_parent_sd; + *_old_child_sd = old_child_sd; + *_new_parent_sd = new_parent_sd; + *_new_child_sd = new_child_sd; + return ERROR_SUCCESS; +} + +static DWORD inherit_SD(HKEY parent_hk, + char *current_key, + BOOL reset, + SECURITY_DESCRIPTOR *current_sd, + SECURITY_DESCRIPTOR *child_sd) +{ + DWORD status; + DWORD i = 0; + HKEY current_hk; + + if (!reset) { + status = RegOpenKeyEx(parent_hk, + current_key, + 0, /* options */ + WRITE_DAC, /* samDesired */ + ¤t_hk); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + status = RegSetKeySecurity(current_hk, + DACL_SECURITY_INFORMATION | + PROTECTED_DACL_SECURITY_INFORMATION | + UNPROTECTED_DACL_SECURITY_INFORMATION | + UNPROTECTED_SACL_SECURITY_INFORMATION, + current_sd /* pSecurityDescriptor */ + ); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + RegCloseKey(current_hk); + } + + status = RegOpenKeyEx(parent_hk, + current_key, + 0, /* options */ + KEY_ENUMERATE_SUB_KEYS, /* samDesired */ + ¤t_hk); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + for (i=0; ; i++) { + char subkey[10240]; + HKEY hk_child; + + memset(subkey, 0, sizeof(subkey)); + status = RegEnumKey(current_hk, i, subkey, sizeof(subkey)); + if (status == ERROR_NO_MORE_ITEMS) { + break; + } + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + +#if 0 + printf("subkey: %s\n", subkey); +#endif + + status = inherit_SD(current_hk, subkey, reset, + child_sd, child_sd); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + } + + RegCloseKey(current_hk); + + if (reset) { + status = RegOpenKeyEx(parent_hk, + current_key, + 0, /* options */ + WRITE_DAC, /* samDesired */ + ¤t_hk); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + status = RegSetKeySecurity(current_hk, + DACL_SECURITY_INFORMATION | + PROTECTED_DACL_SECURITY_INFORMATION | + UNPROTECTED_DACL_SECURITY_INFORMATION | + UNPROTECTED_SACL_SECURITY_INFORMATION, + current_sd /* pSecurityDescriptor */ + ); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + RegCloseKey(current_hk); + } + + return ERROR_SUCCESS; +} + +static DWORD replaceSIDBuffer(BYTE *buf, DWORD len, + SID *oldDomainSid, + SID *newDomainSid) +{ + DWORD ret = 0; + BYTE *oldb = ((BYTE *)oldDomainSid)+2; + BYTE *newb = ((BYTE *)newDomainSid)+2; + int cmp; + +#if 0 + printf("replaceSIDBuffer: %u\n", len); + dump_data(buf, len); +#endif + + if (len < 24) { + return 0; + } + + if (buf[0] != SID_REVISION) { + return 0; + } + + switch (buf[1]) { + case 4: + ret = 24; + break; + case 5: + if (len < 28) { + return 0; + } + ret = 28; + break; + default: + return 0; + } + +#if 0 + printf("oldb:\n"); + dump_data(oldb, 22); +#endif + cmp = memcmp(&buf[2], oldb, 22); + if (cmp != 0) { + return 0; + } + + memcpy(&buf[2], newb, 22); + + return ret; +} + +static DWORD replaceSID(HKEY parent_hk, + const char *parent_path, + const char *current_key, + SID *oldDomainSid, + SID *newDomainSid) +{ + DWORD status; + DWORD i = 0; + HKEY current_hk; + char current_path[10240]; + + snprintf(current_path, sizeof(current_path), "%s\\%s", + parent_path, current_key); + + status = RegOpenKeyEx(parent_hk, + current_key, + 0, /* options */ + KEY_ALL_ACCESS, /* samDesired */ + ¤t_hk); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + for (i=0; ; i++) { + char subkey[10240]; + HKEY hk_child; + + memset(subkey, 0, sizeof(subkey)); + status = RegEnumKey(current_hk, i, subkey, sizeof(subkey)); + if (status == ERROR_NO_MORE_ITEMS) { + break; + } + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + +#if 0 + printf("subkey: %s\n", subkey); +#endif + + status = replaceSID(current_hk, current_path, subkey, + oldDomainSid, newDomainSid); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + } + + for (i=0; ; i++) { + char valueName[10240]; + DWORD cbValueName; + DWORD valueType = 0; + BYTE *valueData = NULL; + DWORD cbValueData = 0; + DWORD ofs = 0; + BOOL modified = FALSE; + + memset(valueName, 0, sizeof(valueName)); + cbValueName = sizeof(valueName)-1; + status = RegEnumValue(current_hk, i, + valueName, &cbValueName, + NULL, NULL, + NULL, &cbValueData); + if (status == ERROR_NO_MORE_ITEMS) { + break; + } + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + valueData = (BYTE *)malloc(cbValueData); + if (valueData == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return ERROR_NOT_ENOUGH_MEMORY; + } + + cbValueName = sizeof(valueName)-1; + status = RegEnumValue(current_hk, i, + valueName, &cbValueName, + NULL, &valueType, + valueData, &cbValueData); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + if (valueType != REG_BINARY) { + free(valueData); + continue; + } + + for (ofs=0; ofs < cbValueData;) { + DWORD len; + + len = replaceSIDBuffer(valueData + ofs, + cbValueData - ofs, + oldDomainSid, + newDomainSid); + if (len == 0) { + ofs += 4; + continue; + } + +#if 0 + printf("%s value[%u]:%s modified ofs:%u (0x%X) len:%u\n", + current_path, i, valueName, ofs, ofs, len); +#endif + + ofs += len; + modified = TRUE; + } + + if (!modified) { + free(valueData); + continue; + } + + printf("%s value[%u]:%s replacing data\n", + current_path, i, valueName); + status = RegSetValueEx(current_hk, + valueName, + 0, + valueType, + valueData, + cbValueData); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + free(valueData); + } + + RegCloseKey(current_hk); + + return ERROR_SUCCESS; +} + +int main(int argc, char *argv[]) +{ + LONG status; + HANDLE tokenHandle = NULL; + TOKEN_USER *tokenUser = NULL; + DWORD cbTokenUser = 0; + HKEY hklm; + HKEY hk_security; + HKEY hk_account_domain; + DWORD cbSecurityDescriptor = 0; + SECURITY_DESCRIPTOR *security_old_sd = NULL; + SECURITY_DESCRIPTOR *security_parent_old_sd = NULL; + SECURITY_DESCRIPTOR *security_child_old_sd = NULL; + SECURITY_DESCRIPTOR *security_parent_new_sd = NULL; + SECURITY_DESCRIPTOR *security_child_new_sd = NULL; + SID *currentUserSid = NULL; + char *currentUserSidString = NULL; + BOOL ok; + DWORD cbTmp = 0; + BYTE *AccountDomainF = NULL; + DWORD cbAccountDomainF = 0; + DWORD AccountDomainFType = 0; + DWORD *nextRid = NULL; + DWORD oldNextRid = 0; + DWORD newNextRid = 0; + BYTE *AccountDomainV = NULL; + DWORD cbAccountDomainV = 0; + SID *oldDomainSid = NULL; + char *oldDomainSidString = NULL; + SID *newDomainSid = NULL; + const char *newDomainSidString = NULL; + + if (argc < 2 || argc > 3) { + printf("Usage: %s <DOMAINSID> [<NEXTRID>]\n", argv[0]); + return -1; + } + + newDomainSidString = argv[1]; + + newDomainSid = (SID *)malloc(24); + if (newDomainSid == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return -1; + } + + status = StringToSid(newDomainSidString, newDomainSid); + if (status != ERROR_SUCCESS) { + printf("Failed to parse DOMAINSID[%s]: Error: %d (0x%X)\n", + newDomainSidString, status, status); + return -1; + } + if (newDomainSid->SubAuthorityCount != 4) { + printf("DOMAINSID[%s]: Invalid SubAuthorityCount[%u] should be 4\n", + newDomainSidString, newDomainSid->SubAuthorityCount); + return -1; + } + + if (argc == 3) { + char *q = NULL; + newNextRid = (DWORD)strtoul(argv[2], &q, 10); + if (newNextRid == 0 || newNextRid == 0xFFFFFFFF || !q || *q!='\0') { + printf("Invalid newNextRid[%s]\n", argv[2]); + return -1; + } + if (newNextRid < 1000) { + printf("newNextRid[%u] < 1000\n", newNextRid); + return -1; + } + } + + ok = OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &tokenHandle); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + ok = GetTokenInformation(tokenHandle, TokenUser, + NULL, 0, &cbTokenUser); + if (!ok) { + status = GetLastError(); + } + if (status != ERROR_INSUFFICIENT_BUFFER) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + tokenUser = (TOKEN_USER *)malloc(cbTokenUser); + if (tokenUser == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return -1; + } + + ok = GetTokenInformation(tokenHandle, TokenUser, + tokenUser, cbTokenUser, &cbTokenUser); + if (!ok) { + status = GetLastError(); + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + currentUserSid = tokenUser->User.Sid; + + status = SidToString(currentUserSid, ¤tUserSidString); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + status = RegConnectRegistry(NULL, HKEY_LOCAL_MACHINE, &hklm); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + status = RegOpenKeyEx(hklm, "SECURITY", + 0, /* options */ + READ_CONTROL, /* samDesired */ + &hk_security); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + status = RegGetKeySecurity(hk_security, + OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION | + PROTECTED_DACL_SECURITY_INFORMATION | + UNPROTECTED_DACL_SECURITY_INFORMATION | + UNPROTECTED_SACL_SECURITY_INFORMATION, + NULL, /* pSecurityDescriptor */ + &cbSecurityDescriptor /* lpcbSecurityDescriptor */ + ); + if (status != ERROR_INSUFFICIENT_BUFFER) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + security_old_sd = (SECURITY_DESCRIPTOR *)malloc(cbSecurityDescriptor); + if (security_old_sd == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return -1; + } + + status = RegGetKeySecurity(hk_security, + OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION | + PROTECTED_DACL_SECURITY_INFORMATION | + UNPROTECTED_DACL_SECURITY_INFORMATION | + UNPROTECTED_SACL_SECURITY_INFORMATION, + security_old_sd, /* pSecurityDescriptor */ + &cbSecurityDescriptor /* lpcbSecurityDescriptor */ + ); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + RegCloseKey(hk_security); + + printf("currentUserSid: %s\n", currentUserSidString); + + status = calc_tmp_HKLM_SECURITY_SD(security_old_sd, + currentUserSid, + &security_parent_old_sd, + &security_child_old_sd, + &security_parent_new_sd, + &security_child_new_sd); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + printf("Grant full access to HKLM\\SECURITY\n"); + status = inherit_SD(hklm, "SECURITY", FALSE, + security_parent_new_sd, security_child_new_sd); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + status = RegOpenKeyEx(hklm, "SECURITY\\SAM\\Domains\\Account", + 0, /* options */ + KEY_ALL_ACCESS, /* samDesired */ + &hk_account_domain); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + status = RegQueryValueEx(hk_account_domain, + "F", NULL, NULL, + NULL, + &cbAccountDomainF); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + AccountDomainF = (BYTE *)malloc(cbAccountDomainF); + if (AccountDomainF == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return -1; + } + + status = RegQueryValueEx(hk_account_domain, + "F", NULL, NULL, + AccountDomainF, + &cbAccountDomainF); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + nextRid = (DWORD *)((BYTE *)AccountDomainF + 0x48); + oldNextRid = *nextRid; + if (newNextRid == 0) { + newNextRid = oldNextRid; + } + printf("AccountDomainF: %u bytes\n", cbAccountDomainF); + + status = RegQueryValueEx(hk_account_domain, + "V", NULL, NULL, + NULL, + &cbAccountDomainV); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + AccountDomainV = (BYTE *)malloc(cbAccountDomainV); + if (AccountDomainV == NULL) { + printf("LINE:%u: Error: no memory\n", __LINE__); + return -1; + } + + status = RegQueryValueEx(hk_account_domain, + "V", NULL, NULL, + AccountDomainV, + &cbAccountDomainV); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + printf("AccountDomainV: %u bytes\n", cbAccountDomainV); + oldDomainSid = (SID *)((BYTE *)AccountDomainV + (cbAccountDomainV - 24)); + + status = SidToString(oldDomainSid, &oldDomainSidString); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + + printf("Old Domain:%s, NextRid: %u (0x%08X)\n", + oldDomainSidString, oldNextRid, oldNextRid); + printf("New Domain:%s, NextRid: %u (0x%08X)\n", + newDomainSidString, newNextRid, newNextRid); + + status = replaceSID(hklm, "HKLM", "SECURITY\\SAM\\Domains", + oldDomainSid, newDomainSid); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + goto failed; + } + + status = RegQueryValueEx(hk_account_domain, + "F", NULL, &AccountDomainFType, + AccountDomainF, + &cbAccountDomainF); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + nextRid = (DWORD *)((BYTE *)AccountDomainF + 0x48); + *nextRid = newNextRid; + + printf("AccountDomainF replacing data (nextRid)\n"); + status = RegSetValueEx(hk_account_domain, + "F", + 0, + AccountDomainFType, + AccountDomainF, + cbAccountDomainF); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return status; + } + + printf("Withdraw full access to HKLM\\SECURITY\n"); + status = inherit_SD(hklm, "SECURITY", TRUE, + security_parent_old_sd, security_child_old_sd); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + printf("DONE!\n"); + return 0; +failed: + printf("Withdraw full access to HKLM\\SECURITY\n"); + status = inherit_SD(hklm, "SECURITY", TRUE, + security_parent_old_sd, security_child_old_sd); + if (status != ERROR_SUCCESS) { + printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status); + return -1; + } + printf("FAILED!\n"); + return 0; +} |