s3:winbindd: change getpwsid() to return a passwd struct for a group sid id-mapped...
[Samba/gebeck_regimport.git] / testprogs / win32 / prepare_dcpromo / prepare_dcpromo.c
blob91b819b54e684ae6f2e53f106eb88a906352cbd0
1 /*
2 Copyright (C) Stefan Metzmacher <metze@samba.org> 2010
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 Published to the public domain
20 * This tool can set the DOMAIN-SID and nextRid counter in
21 * the local SAM on windows servers (tested with w2k8r2)
23 * dcpromo will use this values for the ad domain it creates.
25 * This might be useful for upgrades from a Samba3 domain.
28 #include <windows.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
33 /* Convert a binary SID to a character string */
34 static DWORD SidToString(const SID *sid,
35 char **string)
37 DWORD id_auth;
38 int i, ofs, maxlen;
39 char *result;
41 if (!sid) {
42 return ERROR_INVALID_SID;
45 maxlen = sid->SubAuthorityCount * 11 + 25;
47 result = (char *)malloc(maxlen);
48 if (result == NULL) {
49 return ERROR_NOT_ENOUGH_MEMORY;
53 * BIG NOTE: this function only does SIDS where the identauth is not
54 * >= ^32 in a range of 2^48.
57 id_auth = sid->IdentifierAuthority.Value[5] +
58 (sid->IdentifierAuthority.Value[4] << 8) +
59 (sid->IdentifierAuthority.Value[3] << 16) +
60 (sid->IdentifierAuthority.Value[2] << 24);
62 ofs = snprintf(result, maxlen, "S-%u-%lu",
63 (unsigned int)sid->Revision, (unsigned long)id_auth);
65 for (i = 0; i < sid->SubAuthorityCount; i++) {
66 ofs += snprintf(result + ofs, maxlen - ofs, "-%lu",
67 (unsigned long)sid->SubAuthority[i]);
70 *string = result;
71 return ERROR_SUCCESS;
74 static DWORD StringToSid(const char *str,
75 SID *sid)
77 const char *p;
78 char *q;
79 DWORD x;
81 if (!sid) {
82 return ERROR_INVALID_PARAMETER;
85 /* Sanity check for either "S-" or "s-" */
87 if (!str
88 || (str[0]!='S' && str[0]!='s')
89 || (str[1]!='-'))
91 return ERROR_INVALID_PARAMETER;
94 /* Get the SID revision number */
96 p = str+2;
97 x = (DWORD)strtol(p, &q, 10);
98 if (x==0 || !q || *q!='-') {
99 return ERROR_INVALID_SID;
101 sid->Revision = (BYTE)x;
103 /* Next the Identifier Authority. This is stored in big-endian
104 in a 6 byte array. */
106 p = q+1;
107 x = (DWORD)strtol(p, &q, 10);
108 if (!q || *q!='-') {
109 return ERROR_INVALID_SID;
111 sid->IdentifierAuthority.Value[5] = (x & 0x000000ff);
112 sid->IdentifierAuthority.Value[4] = (x & 0x0000ff00) >> 8;
113 sid->IdentifierAuthority.Value[3] = (x & 0x00ff0000) >> 16;
114 sid->IdentifierAuthority.Value[2] = (x & 0xff000000) >> 24;
115 sid->IdentifierAuthority.Value[1] = 0;
116 sid->IdentifierAuthority.Value[0] = 0;
118 /* now read the the subauthorities */
120 p = q +1;
121 sid->SubAuthorityCount = 0;
122 while (sid->SubAuthorityCount < 6) {
123 x=(DWORD)strtoul(p, &q, 10);
124 if (p == q)
125 break;
126 if (q == NULL) {
127 return ERROR_INVALID_SID;
129 sid->SubAuthority[sid->SubAuthorityCount++] = x;
131 if ((*q!='-') || (*q=='\0'))
132 break;
133 p = q + 1;
136 /* IF we ended early, then the SID could not be converted */
138 if (q && *q!='\0') {
139 return ERROR_INVALID_SID;
142 return ERROR_SUCCESS;
145 #define MIN(a,b) ((a)<(b)?(a):(b))
146 static void print_asc(const unsigned char *buf,int len)
148 int i;
149 for (i=0;i<len;i++)
150 printf("%c", isprint(buf[i])?buf[i]:'.');
153 static void dump_data(const unsigned char *buf1,int len)
155 const unsigned char *buf = (const unsigned char *)buf1;
156 int i=0;
157 if (len<=0) return;
159 printf("[%03X] ",i);
160 for (i=0;i<len;) {
161 printf("%02X ",(int)buf[i]);
162 i++;
163 if (i%8 == 0) printf(" ");
164 if (i%16 == 0) {
165 print_asc(&buf[i-16],8); printf(" ");
166 print_asc(&buf[i-8],8); printf("\n");
167 if (i<len) printf("[%03X] ",i);
170 if (i%16) {
171 int n;
172 n = 16 - (i%16);
173 printf(" ");
174 if (n>8) printf(" ");
175 while (n--) printf(" ");
176 n = MIN(8,i%16);
177 print_asc(&buf[i-(i%16)],n); printf( " " );
178 n = (i%16) - n;
179 if (n>0) print_asc(&buf[i-n],n);
180 printf("\n");
184 static DWORD calc_tmp_HKLM_SECURITY_SD(SECURITY_DESCRIPTOR *old_sd,
185 SID *current_user_sid,
186 SECURITY_DESCRIPTOR **_old_parent_sd,
187 SECURITY_DESCRIPTOR **_old_child_sd,
188 SECURITY_DESCRIPTOR **_new_parent_sd,
189 SECURITY_DESCRIPTOR **_new_child_sd)
191 LONG status;
192 DWORD cbSecurityDescriptor = 0;
193 SECURITY_DESCRIPTOR *old_parent_sd = NULL;
194 SECURITY_DESCRIPTOR *old_child_sd = NULL;
195 SECURITY_DESCRIPTOR *new_parent_sd = NULL;
196 SECURITY_DESCRIPTOR *new_child_sd = NULL;
197 BOOL ok;
198 ACL *old_Dacl = NULL;
199 ACL *new_Dacl = NULL;
200 ACL_SIZE_INFORMATION dacl_info;
201 DWORD i = 0;
202 SECURITY_DESCRIPTOR *AbsoluteSD = NULL;
203 DWORD dwAbsoluteSDSize = 0;
204 DWORD dwRelativeSDSize = 0;
205 DWORD dwDaclSize = 0;
206 ACL *Sacl = NULL;
207 DWORD dwSaclSize = 0;
208 SID *Owner = NULL;
209 DWORD dwOwnerSize = 0;
210 SID *PrimaryGroup = NULL;
211 DWORD dwPrimaryGroupSize = 0;
212 ACCESS_ALLOWED_ACE *ace = NULL;
214 ok = MakeAbsoluteSD(old_sd,
215 NULL,
216 &dwAbsoluteSDSize,
217 NULL,
218 &dwDaclSize,
219 NULL,
220 &dwSaclSize,
221 NULL,
222 &dwOwnerSize,
223 NULL,
224 &dwPrimaryGroupSize);
225 if (!ok) {
226 status = GetLastError();
228 if (status != ERROR_INSUFFICIENT_BUFFER) {
229 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
230 return status;
233 AbsoluteSD = (SECURITY_DESCRIPTOR *)malloc(dwAbsoluteSDSize+1024);
234 if (AbsoluteSD == NULL) {
235 printf("LINE:%u: Error: no memory\n", __LINE__);
236 return ERROR_NOT_ENOUGH_MEMORY;
238 old_Dacl = (ACL *)malloc(dwDaclSize + 1024);
239 if (old_Dacl == NULL) {
240 printf("LINE:%u: Error: no memory\n", __LINE__);
241 return ERROR_NOT_ENOUGH_MEMORY;
243 Sacl = (ACL *)malloc(dwSaclSize);
244 if (Sacl == NULL) {
245 printf("LINE:%u: Error: no memory\n", __LINE__);
246 return ERROR_NOT_ENOUGH_MEMORY;
248 Owner = (SID *)malloc(dwOwnerSize);
249 if (Owner == NULL) {
250 printf("LINE:%u: Error: no memory\n", __LINE__);
251 return ERROR_NOT_ENOUGH_MEMORY;
253 PrimaryGroup = (SID *)malloc(dwPrimaryGroupSize);
254 if (PrimaryGroup == NULL) {
255 printf("LINE:%u: Error: no memory\n", __LINE__);
256 return ERROR_NOT_ENOUGH_MEMORY;
259 ok = MakeAbsoluteSD(old_sd,
260 AbsoluteSD,
261 &dwAbsoluteSDSize,
262 old_Dacl,
263 &dwDaclSize,
264 Sacl,
265 &dwSaclSize,
266 Owner,
267 &dwOwnerSize,
268 PrimaryGroup,
269 &dwPrimaryGroupSize);
270 if (!ok) {
271 status = GetLastError();
272 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
273 return status;
276 AbsoluteSD->Control |= SE_DACL_AUTO_INHERITED | SE_DACL_AUTO_INHERIT_REQ | SE_DACL_PROTECTED;
277 dwRelativeSDSize = 0;
278 ok = MakeSelfRelativeSD(AbsoluteSD,
279 NULL,
280 &dwRelativeSDSize);
281 if (!ok) {
282 status = GetLastError();
284 if (status != ERROR_INSUFFICIENT_BUFFER) {
285 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
286 return ERROR_NOT_ENOUGH_MEMORY;
289 old_parent_sd = (SECURITY_DESCRIPTOR *)malloc(dwRelativeSDSize);
290 if (old_parent_sd == NULL) {
291 printf("LINE:%u: Error: no memory\n", __LINE__);
292 return ERROR_NOT_ENOUGH_MEMORY;
295 ok = MakeSelfRelativeSD(AbsoluteSD,
296 old_parent_sd,
297 &dwRelativeSDSize);
298 if (!ok) {
299 status = GetLastError();
300 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
301 return status;
304 ok = GetAclInformation(old_Dacl,
305 &dacl_info,
306 sizeof(dacl_info),
307 AclSizeInformation);
308 if (!ok) {
309 status = GetLastError();
310 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
311 return status;
314 new_Dacl = (ACL *)calloc(dacl_info.AclBytesInUse + 1024, 1);
315 if (new_Dacl == NULL) {
316 printf("LINE:%u: Error: no memory\n", __LINE__);
317 return ERROR_NOT_ENOUGH_MEMORY;
320 InitializeAcl(new_Dacl, dacl_info.AclBytesInUse + 1024, ACL_REVISION);
322 ok = AddAccessAllowedAce(new_Dacl, ACL_REVISION,
323 KEY_ALL_ACCESS, current_user_sid);
324 if (!ok) {
325 status = GetLastError();
326 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
327 return status;
330 ok = GetAce(new_Dacl, 0, (LPVOID *)&ace);
331 if (!ok) {
332 status = GetLastError();
333 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
334 return status;
337 ace->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
339 for (i=0; i < dacl_info.AceCount; i++) {
340 ok = GetAce(old_Dacl, i, (LPVOID *)&ace);
341 if (!ok) {
342 status = GetLastError();
343 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
344 return status;
347 ok = AddAce(new_Dacl, ACL_REVISION, MAXDWORD,
348 ace, ace->Header.AceSize);
349 if (!ok) {
350 status = GetLastError();
351 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
352 return status;
356 AbsoluteSD->Dacl = new_Dacl;
357 dwRelativeSDSize = 0;
358 ok = MakeSelfRelativeSD(AbsoluteSD,
359 NULL,
360 &dwRelativeSDSize);
361 if (!ok) {
362 status = GetLastError();
364 if (status != ERROR_INSUFFICIENT_BUFFER) {
365 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
366 return ERROR_NOT_ENOUGH_MEMORY;
369 new_parent_sd = (SECURITY_DESCRIPTOR *)malloc(dwRelativeSDSize);
370 if (new_parent_sd == NULL) {
371 printf("LINE:%u: Error: no memory\n", __LINE__);
372 return ERROR_NOT_ENOUGH_MEMORY;
375 ok = MakeSelfRelativeSD(AbsoluteSD,
376 new_parent_sd,
377 &dwRelativeSDSize);
378 if (!ok) {
379 status = GetLastError();
380 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
381 return status;
384 for (i=0; i < dacl_info.AceCount; i++) {
385 ok = GetAce(old_Dacl, i, (LPVOID *)&ace);
386 if (!ok) {
387 status = GetLastError();
388 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
389 return status;
392 ace->Header.AceFlags |= INHERITED_ACE;
395 AbsoluteSD->Control &= ~SE_DACL_PROTECTED;
396 AbsoluteSD->Dacl = old_Dacl;
397 dwRelativeSDSize = 0;
398 ok = MakeSelfRelativeSD(AbsoluteSD,
399 NULL,
400 &dwRelativeSDSize);
401 if (!ok) {
402 status = GetLastError();
404 if (status != ERROR_INSUFFICIENT_BUFFER) {
405 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
406 return ERROR_NOT_ENOUGH_MEMORY;
409 old_child_sd = (SECURITY_DESCRIPTOR *)malloc(dwRelativeSDSize);
410 if (old_child_sd == NULL) {
411 printf("LINE:%u: Error: no memory\n", __LINE__);
412 return ERROR_NOT_ENOUGH_MEMORY;
415 ok = MakeSelfRelativeSD(AbsoluteSD,
416 old_child_sd,
417 &dwRelativeSDSize);
418 if (!ok) {
419 status = GetLastError();
420 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
421 return status;
424 for (i=0; i < dacl_info.AceCount + 1; i++) {
425 ok = GetAce(new_Dacl, i, (LPVOID *)&ace);
426 if (!ok) {
427 status = GetLastError();
428 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
429 return status;
432 ace->Header.AceFlags |= INHERITED_ACE;
435 AbsoluteSD->Dacl = new_Dacl;
436 dwRelativeSDSize = 0;
437 ok = MakeSelfRelativeSD(AbsoluteSD,
438 NULL,
439 &dwRelativeSDSize);
440 if (!ok) {
441 status = GetLastError();
443 if (status != ERROR_INSUFFICIENT_BUFFER) {
444 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
445 return ERROR_NOT_ENOUGH_MEMORY;
448 new_child_sd = (SECURITY_DESCRIPTOR *)malloc(dwRelativeSDSize);
449 if (new_child_sd == NULL) {
450 printf("LINE:%u: Error: no memory\n", __LINE__);
451 return ERROR_NOT_ENOUGH_MEMORY;
454 ok = MakeSelfRelativeSD(AbsoluteSD,
455 new_child_sd,
456 &dwRelativeSDSize);
457 if (!ok) {
458 status = GetLastError();
459 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
460 return status;
463 *_old_parent_sd = old_parent_sd;
464 *_old_child_sd = old_child_sd;
465 *_new_parent_sd = new_parent_sd;
466 *_new_child_sd = new_child_sd;
467 return ERROR_SUCCESS;
470 static DWORD inherit_SD(HKEY parent_hk,
471 char *current_key,
472 BOOL reset,
473 SECURITY_DESCRIPTOR *current_sd,
474 SECURITY_DESCRIPTOR *child_sd)
476 DWORD status;
477 DWORD i = 0;
478 HKEY current_hk;
480 if (!reset) {
481 status = RegOpenKeyEx(parent_hk,
482 current_key,
483 0, /* options */
484 WRITE_DAC, /* samDesired */
485 &current_hk);
486 if (status != ERROR_SUCCESS) {
487 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
488 return status;
491 status = RegSetKeySecurity(current_hk,
492 DACL_SECURITY_INFORMATION |
493 PROTECTED_DACL_SECURITY_INFORMATION |
494 UNPROTECTED_DACL_SECURITY_INFORMATION |
495 UNPROTECTED_SACL_SECURITY_INFORMATION,
496 current_sd /* pSecurityDescriptor */
498 if (status != ERROR_SUCCESS) {
499 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
500 return status;
503 RegCloseKey(current_hk);
506 status = RegOpenKeyEx(parent_hk,
507 current_key,
508 0, /* options */
509 KEY_ENUMERATE_SUB_KEYS, /* samDesired */
510 &current_hk);
511 if (status != ERROR_SUCCESS) {
512 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
513 return status;
516 for (i=0; ; i++) {
517 char subkey[10240];
518 HKEY hk_child;
520 memset(subkey, 0, sizeof(subkey));
521 status = RegEnumKey(current_hk, i, subkey, sizeof(subkey));
522 if (status == ERROR_NO_MORE_ITEMS) {
523 break;
525 if (status != ERROR_SUCCESS) {
526 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
527 return status;
530 #if 0
531 printf("subkey: %s\n", subkey);
532 #endif
534 status = inherit_SD(current_hk, subkey, reset,
535 child_sd, child_sd);
536 if (status != ERROR_SUCCESS) {
537 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
538 return status;
542 RegCloseKey(current_hk);
544 if (reset) {
545 status = RegOpenKeyEx(parent_hk,
546 current_key,
547 0, /* options */
548 WRITE_DAC, /* samDesired */
549 &current_hk);
550 if (status != ERROR_SUCCESS) {
551 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
552 return status;
555 status = RegSetKeySecurity(current_hk,
556 DACL_SECURITY_INFORMATION |
557 PROTECTED_DACL_SECURITY_INFORMATION |
558 UNPROTECTED_DACL_SECURITY_INFORMATION |
559 UNPROTECTED_SACL_SECURITY_INFORMATION,
560 current_sd /* pSecurityDescriptor */
562 if (status != ERROR_SUCCESS) {
563 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
564 return status;
567 RegCloseKey(current_hk);
570 return ERROR_SUCCESS;
573 static DWORD replaceSIDBuffer(BYTE *buf, DWORD len,
574 SID *oldDomainSid,
575 SID *newDomainSid)
577 DWORD ret = 0;
578 BYTE *oldb = ((BYTE *)oldDomainSid)+2;
579 BYTE *newb = ((BYTE *)newDomainSid)+2;
580 int cmp;
582 #if 0
583 printf("replaceSIDBuffer: %u\n", len);
584 dump_data(buf, len);
585 #endif
587 if (len < 24) {
588 return 0;
591 if (buf[0] != SID_REVISION) {
592 return 0;
595 switch (buf[1]) {
596 case 4:
597 ret = 24;
598 break;
599 case 5:
600 if (len < 28) {
601 return 0;
603 ret = 28;
604 break;
605 default:
606 return 0;
609 #if 0
610 printf("oldb:\n");
611 dump_data(oldb, 22);
612 #endif
613 cmp = memcmp(&buf[2], oldb, 22);
614 if (cmp != 0) {
615 return 0;
618 memcpy(&buf[2], newb, 22);
620 return ret;
623 static DWORD replaceSID(HKEY parent_hk,
624 const char *parent_path,
625 const char *current_key,
626 SID *oldDomainSid,
627 SID *newDomainSid)
629 DWORD status;
630 DWORD i = 0;
631 HKEY current_hk;
632 char current_path[10240];
634 snprintf(current_path, sizeof(current_path), "%s\\%s",
635 parent_path, current_key);
637 status = RegOpenKeyEx(parent_hk,
638 current_key,
639 0, /* options */
640 KEY_ALL_ACCESS, /* samDesired */
641 &current_hk);
642 if (status != ERROR_SUCCESS) {
643 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
644 return status;
647 for (i=0; ; i++) {
648 char subkey[10240];
649 HKEY hk_child;
651 memset(subkey, 0, sizeof(subkey));
652 status = RegEnumKey(current_hk, i, subkey, sizeof(subkey));
653 if (status == ERROR_NO_MORE_ITEMS) {
654 break;
656 if (status != ERROR_SUCCESS) {
657 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
658 return status;
661 #if 0
662 printf("subkey: %s\n", subkey);
663 #endif
665 status = replaceSID(current_hk, current_path, subkey,
666 oldDomainSid, newDomainSid);
667 if (status != ERROR_SUCCESS) {
668 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
669 return status;
673 for (i=0; ; i++) {
674 char valueName[10240];
675 DWORD cbValueName;
676 DWORD valueType = 0;
677 BYTE *valueData = NULL;
678 DWORD cbValueData = 0;
679 DWORD ofs = 0;
680 BOOL modified = FALSE;
682 memset(valueName, 0, sizeof(valueName));
683 cbValueName = sizeof(valueName)-1;
684 status = RegEnumValue(current_hk, i,
685 valueName, &cbValueName,
686 NULL, NULL,
687 NULL, &cbValueData);
688 if (status == ERROR_NO_MORE_ITEMS) {
689 break;
691 if (status != ERROR_SUCCESS) {
692 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
693 return status;
696 valueData = (BYTE *)malloc(cbValueData);
697 if (valueData == NULL) {
698 printf("LINE:%u: Error: no memory\n", __LINE__);
699 return ERROR_NOT_ENOUGH_MEMORY;
702 cbValueName = sizeof(valueName)-1;
703 status = RegEnumValue(current_hk, i,
704 valueName, &cbValueName,
705 NULL, &valueType,
706 valueData, &cbValueData);
707 if (status != ERROR_SUCCESS) {
708 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
709 return status;
712 if (valueType != REG_BINARY) {
713 free(valueData);
714 continue;
717 for (ofs=0; ofs < cbValueData;) {
718 DWORD len;
720 len = replaceSIDBuffer(valueData + ofs,
721 cbValueData - ofs,
722 oldDomainSid,
723 newDomainSid);
724 if (len == 0) {
725 ofs += 4;
726 continue;
729 #if 0
730 printf("%s value[%u]:%s modified ofs:%u (0x%X) len:%u\n",
731 current_path, i, valueName, ofs, ofs, len);
732 #endif
734 ofs += len;
735 modified = TRUE;
738 if (!modified) {
739 free(valueData);
740 continue;
743 printf("%s value[%u]:%s replacing data\n",
744 current_path, i, valueName);
745 status = RegSetValueEx(current_hk,
746 valueName,
748 valueType,
749 valueData,
750 cbValueData);
751 if (status != ERROR_SUCCESS) {
752 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
753 return status;
756 free(valueData);
759 RegCloseKey(current_hk);
761 return ERROR_SUCCESS;
764 int main(int argc, char *argv[])
766 LONG status;
767 HANDLE tokenHandle = NULL;
768 TOKEN_USER *tokenUser = NULL;
769 DWORD cbTokenUser = 0;
770 HKEY hklm;
771 HKEY hk_security;
772 HKEY hk_account_domain;
773 DWORD cbSecurityDescriptor = 0;
774 SECURITY_DESCRIPTOR *security_old_sd = NULL;
775 SECURITY_DESCRIPTOR *security_parent_old_sd = NULL;
776 SECURITY_DESCRIPTOR *security_child_old_sd = NULL;
777 SECURITY_DESCRIPTOR *security_parent_new_sd = NULL;
778 SECURITY_DESCRIPTOR *security_child_new_sd = NULL;
779 SID *currentUserSid = NULL;
780 char *currentUserSidString = NULL;
781 BOOL ok;
782 DWORD cbTmp = 0;
783 BYTE *AccountDomainF = NULL;
784 DWORD cbAccountDomainF = 0;
785 DWORD AccountDomainFType = 0;
786 DWORD *nextRid = NULL;
787 DWORD oldNextRid = 0;
788 DWORD newNextRid = 0;
789 BYTE *AccountDomainV = NULL;
790 DWORD cbAccountDomainV = 0;
791 SID *oldDomainSid = NULL;
792 char *oldDomainSidString = NULL;
793 SID *newDomainSid = NULL;
794 const char *newDomainSidString = NULL;
796 if (argc < 2 || argc > 3) {
797 printf("Usage: %s <DOMAINSID> [<NEXTRID>]\n", argv[0]);
798 return -1;
801 newDomainSidString = argv[1];
803 newDomainSid = (SID *)malloc(24);
804 if (newDomainSid == NULL) {
805 printf("LINE:%u: Error: no memory\n", __LINE__);
806 return -1;
809 status = StringToSid(newDomainSidString, newDomainSid);
810 if (status != ERROR_SUCCESS) {
811 printf("Failed to parse DOMAINSID[%s]: Error: %d (0x%X)\n",
812 newDomainSidString, status, status);
813 return -1;
815 if (newDomainSid->SubAuthorityCount != 4) {
816 printf("DOMAINSID[%s]: Invalid SubAuthorityCount[%u] should be 4\n",
817 newDomainSidString, newDomainSid->SubAuthorityCount);
818 return -1;
821 if (argc == 3) {
822 char *q = NULL;
823 newNextRid = (DWORD)strtoul(argv[2], &q, 10);
824 if (newNextRid == 0 || newNextRid == 0xFFFFFFFF || !q || *q!='\0') {
825 printf("Invalid newNextRid[%s]\n", argv[2]);
826 return -1;
828 if (newNextRid < 1000) {
829 printf("newNextRid[%u] < 1000\n", newNextRid);
830 return -1;
834 ok = OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &tokenHandle);
835 if (!ok) {
836 status = GetLastError();
837 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
838 return status;
841 ok = GetTokenInformation(tokenHandle, TokenUser,
842 NULL, 0, &cbTokenUser);
843 if (!ok) {
844 status = GetLastError();
846 if (status != ERROR_INSUFFICIENT_BUFFER) {
847 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
848 return status;
851 tokenUser = (TOKEN_USER *)malloc(cbTokenUser);
852 if (tokenUser == NULL) {
853 printf("LINE:%u: Error: no memory\n", __LINE__);
854 return -1;
857 ok = GetTokenInformation(tokenHandle, TokenUser,
858 tokenUser, cbTokenUser, &cbTokenUser);
859 if (!ok) {
860 status = GetLastError();
861 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
862 return status;
865 currentUserSid = tokenUser->User.Sid;
867 status = SidToString(currentUserSid, &currentUserSidString);
868 if (status != ERROR_SUCCESS) {
869 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
870 return -1;
873 status = RegConnectRegistry(NULL, HKEY_LOCAL_MACHINE, &hklm);
874 if (status != ERROR_SUCCESS) {
875 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
876 return -1;
879 status = RegOpenKeyEx(hklm, "SECURITY",
880 0, /* options */
881 READ_CONTROL, /* samDesired */
882 &hk_security);
883 if (status != ERROR_SUCCESS) {
884 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
885 return -1;
888 status = RegGetKeySecurity(hk_security,
889 OWNER_SECURITY_INFORMATION |
890 GROUP_SECURITY_INFORMATION |
891 DACL_SECURITY_INFORMATION |
892 PROTECTED_DACL_SECURITY_INFORMATION |
893 UNPROTECTED_DACL_SECURITY_INFORMATION |
894 UNPROTECTED_SACL_SECURITY_INFORMATION,
895 NULL, /* pSecurityDescriptor */
896 &cbSecurityDescriptor /* lpcbSecurityDescriptor */
898 if (status != ERROR_INSUFFICIENT_BUFFER) {
899 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
900 return -1;
903 security_old_sd = (SECURITY_DESCRIPTOR *)malloc(cbSecurityDescriptor);
904 if (security_old_sd == NULL) {
905 printf("LINE:%u: Error: no memory\n", __LINE__);
906 return -1;
909 status = RegGetKeySecurity(hk_security,
910 OWNER_SECURITY_INFORMATION |
911 GROUP_SECURITY_INFORMATION |
912 DACL_SECURITY_INFORMATION |
913 PROTECTED_DACL_SECURITY_INFORMATION |
914 UNPROTECTED_DACL_SECURITY_INFORMATION |
915 UNPROTECTED_SACL_SECURITY_INFORMATION,
916 security_old_sd, /* pSecurityDescriptor */
917 &cbSecurityDescriptor /* lpcbSecurityDescriptor */
919 if (status != ERROR_SUCCESS) {
920 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
921 return -1;
924 RegCloseKey(hk_security);
926 printf("currentUserSid: %s\n", currentUserSidString);
928 status = calc_tmp_HKLM_SECURITY_SD(security_old_sd,
929 currentUserSid,
930 &security_parent_old_sd,
931 &security_child_old_sd,
932 &security_parent_new_sd,
933 &security_child_new_sd);
934 if (status != ERROR_SUCCESS) {
935 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
936 return -1;
939 printf("Grant full access to HKLM\\SECURITY\n");
940 status = inherit_SD(hklm, "SECURITY", FALSE,
941 security_parent_new_sd, security_child_new_sd);
942 if (status != ERROR_SUCCESS) {
943 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
944 return -1;
947 status = RegOpenKeyEx(hklm, "SECURITY\\SAM\\Domains\\Account",
948 0, /* options */
949 KEY_ALL_ACCESS, /* samDesired */
950 &hk_account_domain);
951 if (status != ERROR_SUCCESS) {
952 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
953 return -1;
956 status = RegQueryValueEx(hk_account_domain,
957 "F", NULL, NULL,
958 NULL,
959 &cbAccountDomainF);
960 if (status != ERROR_SUCCESS) {
961 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
962 return -1;
965 AccountDomainF = (BYTE *)malloc(cbAccountDomainF);
966 if (AccountDomainF == NULL) {
967 printf("LINE:%u: Error: no memory\n", __LINE__);
968 return -1;
971 status = RegQueryValueEx(hk_account_domain,
972 "F", NULL, NULL,
973 AccountDomainF,
974 &cbAccountDomainF);
975 if (status != ERROR_SUCCESS) {
976 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
977 return -1;
980 nextRid = (DWORD *)((BYTE *)AccountDomainF + 0x48);
981 oldNextRid = *nextRid;
982 if (newNextRid == 0) {
983 newNextRid = oldNextRid;
985 printf("AccountDomainF: %u bytes\n", cbAccountDomainF);
987 status = RegQueryValueEx(hk_account_domain,
988 "V", NULL, NULL,
989 NULL,
990 &cbAccountDomainV);
991 if (status != ERROR_SUCCESS) {
992 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
993 return -1;
996 AccountDomainV = (BYTE *)malloc(cbAccountDomainV);
997 if (AccountDomainV == NULL) {
998 printf("LINE:%u: Error: no memory\n", __LINE__);
999 return -1;
1002 status = RegQueryValueEx(hk_account_domain,
1003 "V", NULL, NULL,
1004 AccountDomainV,
1005 &cbAccountDomainV);
1006 if (status != ERROR_SUCCESS) {
1007 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
1008 return -1;
1011 printf("AccountDomainV: %u bytes\n", cbAccountDomainV);
1012 oldDomainSid = (SID *)((BYTE *)AccountDomainV + (cbAccountDomainV - 24));
1014 status = SidToString(oldDomainSid, &oldDomainSidString);
1015 if (status != ERROR_SUCCESS) {
1016 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
1017 return -1;
1020 printf("Old Domain:%s, NextRid: %u (0x%08X)\n",
1021 oldDomainSidString, oldNextRid, oldNextRid);
1022 printf("New Domain:%s, NextRid: %u (0x%08X)\n",
1023 newDomainSidString, newNextRid, newNextRid);
1025 status = replaceSID(hklm, "HKLM", "SECURITY\\SAM\\Domains",
1026 oldDomainSid, newDomainSid);
1027 if (status != ERROR_SUCCESS) {
1028 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
1029 goto failed;
1032 status = RegQueryValueEx(hk_account_domain,
1033 "F", NULL, &AccountDomainFType,
1034 AccountDomainF,
1035 &cbAccountDomainF);
1036 if (status != ERROR_SUCCESS) {
1037 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
1038 return -1;
1040 nextRid = (DWORD *)((BYTE *)AccountDomainF + 0x48);
1041 *nextRid = newNextRid;
1043 printf("AccountDomainF replacing data (nextRid)\n");
1044 status = RegSetValueEx(hk_account_domain,
1045 "F",
1047 AccountDomainFType,
1048 AccountDomainF,
1049 cbAccountDomainF);
1050 if (status != ERROR_SUCCESS) {
1051 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
1052 return status;
1055 printf("Withdraw full access to HKLM\\SECURITY\n");
1056 status = inherit_SD(hklm, "SECURITY", TRUE,
1057 security_parent_old_sd, security_child_old_sd);
1058 if (status != ERROR_SUCCESS) {
1059 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
1060 return -1;
1062 printf("DONE!\n");
1063 return 0;
1064 failed:
1065 printf("Withdraw full access to HKLM\\SECURITY\n");
1066 status = inherit_SD(hklm, "SECURITY", TRUE,
1067 security_parent_old_sd, security_child_old_sd);
1068 if (status != ERROR_SUCCESS) {
1069 printf("LINE:%u: Error: %d (0x%X)\n", __LINE__, status, status);
1070 return -1;
1072 printf("FAILED!\n");
1073 return 0;