diff options
author | Stefan Metzmacher <metze@samba.org> | 2010-05-31 10:02:38 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2010-06-22 10:47:39 +0200 |
commit | df96f18e8ff3400d1bb7e9743498936ad32ee005 (patch) | |
tree | 4d42d45e44bb3b38a6f723a93be9441cbc78aa7f /testprogs | |
parent | efe65cd7b707c3ba5b321016829da431d6905415 (diff) | |
download | samba-df96f18e8ff3400d1bb7e9743498936ad32ee005.tar.gz samba-df96f18e8ff3400d1bb7e9743498936ad32ee005.tar.bz2 samba-df96f18e8ff3400d1bb7e9743498936ad32ee005.zip |
testprogs/win32: add prepare_dcpromo tool
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.
metze
Diffstat (limited to 'testprogs')
-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 0000000000..1c9561398e --- /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 0000000000..6f810ee3b4 --- /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 0000000000..91b819b54e --- /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; +} |