1 /* 2 * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <jni.h> 27 #include "jni_util.h" 28 #include "com_sun_security_auth_module_NTSystem.h" 29 30 #include <windows.h> 31 #include <stdio.h> 32 #include <wchar.h> 33 #include <ntsecapi.h> 34 #include <lmerr.h> 35 36 static BOOL debug = FALSE; 37 38 BOOL getToken(PHANDLE); 39 BOOL getUser(HANDLE tokenHandle, LPTSTR *userName, 40 LPTSTR *domainName, LPTSTR *userSid, LPTSTR *domainSid); 41 BOOL getPrimaryGroup(HANDLE tokenHandle, LPTSTR *primaryGroup); 42 BOOL getGroups(HANDLE tokenHandle, PDWORD numGroups, LPTSTR **groups); 43 BOOL getImpersonationToken(PHANDLE impersonationToken); 44 BOOL getTextualSid(PSID pSid, LPTSTR TextualSid, LPDWORD lpdwBufferLen); 45 void DisplayErrorText(DWORD dwLastError); 46 47 static void throwIllegalArgumentException(JNIEnv *env, const char *msg) { 48 jclass clazz = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); 49 if (clazz != NULL) 50 (*env)->ThrowNew(env, clazz, msg); 51 } 52 53 /* 54 * Declare library specific JNI_Onload entry if static build 55 */ 56 DEF_STATIC_JNI_OnLoad 57 58 JNIEXPORT jlong JNICALL 59 Java_com_sun_security_auth_module_NTSystem_getImpersonationToken0 60 (JNIEnv *env, jobject obj) { 61 HANDLE impersonationToken = 0; // impersonation token 62 if (debug) { 63 printf("getting impersonation token\n"); 64 } 65 if (getImpersonationToken(&impersonationToken) == FALSE) { 66 return 0; 67 } 68 return (jlong)impersonationToken; 69 } 70 71 JNIEXPORT void JNICALL 72 Java_com_sun_security_auth_module_NTSystem_getCurrent 73 (JNIEnv *env, jobject obj, jboolean debugNative) { 74 75 long i, j = 0; 76 HANDLE tokenHandle = INVALID_HANDLE_VALUE; 77 78 LPTSTR userName = NULL; // user name 79 LPTSTR userSid = NULL; // user sid 80 LPTSTR domainName = NULL; // domain name 81 LPTSTR domainSid = NULL; // domain sid 82 LPTSTR primaryGroup = NULL; // primary group sid 83 DWORD numGroups = 0; // num groups 84 LPTSTR *groups = NULL; // groups array 85 long pIndex = -1; // index of primaryGroup in groups array 86 87 jfieldID fid; 88 jstring jstr; 89 jobjectArray jgroups; 90 jclass stringClass = 0; 91 jclass cls = (*env)->GetObjectClass(env, obj); 92 93 debug = debugNative; 94 95 // get NT information first 96 97 if (debug) { 98 printf("getting access token\n"); 99 } 100 if (getToken(&tokenHandle) == FALSE) { 101 return; 102 } 103 104 if (debug) { 105 printf("getting user info\n"); 106 } 107 if (getUser 108 (tokenHandle, &userName, &domainName, &userSid, &domainSid) == FALSE) { 109 return; 110 } 111 112 if (debug) { 113 printf("getting primary group\n"); 114 } 115 if (getPrimaryGroup(tokenHandle, &primaryGroup) == FALSE) { 116 return; 117 } 118 119 if (debug) { 120 printf("getting supplementary groups\n"); 121 } 122 if (getGroups(tokenHandle, &numGroups, &groups) == FALSE) { 123 return; 124 } 125 126 // then set values into NTSystem 127 128 fid = (*env)->GetFieldID(env, cls, "userName", "Ljava/lang/String;"); 129 if (fid == 0) { 130 (*env)->ExceptionClear(env); 131 throwIllegalArgumentException(env, "invalid field: userName"); 132 goto cleanup; 133 } 134 jstr = (*env)->NewStringUTF(env, userName); 135 if (jstr == NULL) 136 goto cleanup; 137 (*env)->SetObjectField(env, obj, fid, jstr); 138 139 fid = (*env)->GetFieldID(env, cls, "userSID", "Ljava/lang/String;"); 140 if (fid == 0) { 141 (*env)->ExceptionClear(env); 142 throwIllegalArgumentException(env, "invalid field: userSID"); 143 goto cleanup; 144 } 145 jstr = (*env)->NewStringUTF(env, userSid); 146 if (jstr == NULL) 147 goto cleanup; 148 (*env)->SetObjectField(env, obj, fid, jstr); 149 150 fid = (*env)->GetFieldID(env, cls, "domain", "Ljava/lang/String;"); 151 if (fid == 0) { 152 (*env)->ExceptionClear(env); 153 throwIllegalArgumentException(env, "invalid field: domain"); 154 goto cleanup; 155 } 156 jstr = (*env)->NewStringUTF(env, domainName); 157 if (jstr == NULL) 158 goto cleanup; 159 (*env)->SetObjectField(env, obj, fid, jstr); 160 161 if (domainSid != NULL) { 162 fid = (*env)->GetFieldID(env, cls, "domainSID", "Ljava/lang/String;"); 163 if (fid == 0) { 164 (*env)->ExceptionClear(env); 165 throwIllegalArgumentException(env, "invalid field: domainSID"); 166 goto cleanup; 167 } 168 jstr = (*env)->NewStringUTF(env, domainSid); 169 if (jstr == NULL) 170 goto cleanup; 171 (*env)->SetObjectField(env, obj, fid, jstr); 172 } 173 174 fid = (*env)->GetFieldID(env, cls, "primaryGroupID", "Ljava/lang/String;"); 175 if (fid == 0) { 176 (*env)->ExceptionClear(env); 177 throwIllegalArgumentException(env, "invalid field: PrimaryGroupID"); 178 goto cleanup; 179 } 180 jstr = (*env)->NewStringUTF(env, primaryGroup); 181 if (jstr == NULL) 182 goto cleanup; 183 (*env)->SetObjectField(env, obj, fid, jstr); 184 185 // primary group may or may not be part of supplementary groups 186 for (i = 0; i < (long)numGroups; i++) { 187 if (strcmp(primaryGroup, groups[i]) == 0) { 188 // found primary group in groups array 189 pIndex = i; 190 break; 191 } 192 } 193 194 if (numGroups == 0 || (pIndex == 0 && numGroups == 1)) { 195 // primary group is only group in groups array 196 197 if (debug) { 198 printf("no secondary groups\n"); 199 } 200 } else { 201 202 // the groups array is non-empty, 203 // and may or may not contain the primary group 204 205 fid = (*env)->GetFieldID(env, cls, "groupIDs", "[Ljava/lang/String;"); 206 if (fid == 0) { 207 (*env)->ExceptionClear(env); 208 throwIllegalArgumentException(env, "groupIDs"); 209 goto cleanup; 210 } 211 212 stringClass = (*env)->FindClass(env, "java/lang/String"); 213 if (stringClass == NULL) 214 goto cleanup; 215 216 if (pIndex == -1) { 217 // primary group not in groups array 218 jgroups = (*env)->NewObjectArray(env, numGroups, stringClass, 0); 219 } else { 220 // primary group in groups array - 221 // allocate one less array entry and do not add into new array 222 jgroups = (*env)->NewObjectArray(env, numGroups-1, stringClass, 0); 223 } 224 if (jgroups == NULL) 225 goto cleanup; 226 227 for (i = 0, j = 0; i < (long)numGroups; i++) { 228 if (pIndex == i) { 229 // continue if equal to primary group 230 continue; 231 } 232 jstr = (*env)->NewStringUTF(env, groups[i]); 233 if (jstr == NULL) 234 goto cleanup; 235 (*env)->SetObjectArrayElement(env, jgroups, j++, jstr); 236 } 237 (*env)->SetObjectField(env, obj, fid, jgroups); 238 } 239 240 cleanup: 241 if (userName != NULL) { 242 HeapFree(GetProcessHeap(), 0, userName); 243 } 244 if (domainName != NULL) { 245 HeapFree(GetProcessHeap(), 0, domainName); 246 } 247 if (userSid != NULL) { 248 HeapFree(GetProcessHeap(), 0, userSid); 249 } 250 if (domainSid != NULL) { 251 HeapFree(GetProcessHeap(), 0, domainSid); 252 } 253 if (primaryGroup != NULL) { 254 HeapFree(GetProcessHeap(), 0, primaryGroup); 255 } 256 if (groups != NULL) { 257 for (i = 0; i < (long)numGroups; i++) { 258 if (groups[i] != NULL) { 259 HeapFree(GetProcessHeap(), 0, groups[i]); 260 } 261 } 262 HeapFree(GetProcessHeap(), 0, groups); 263 } 264 CloseHandle(tokenHandle); 265 266 return; 267 } 268 269 BOOL getToken(PHANDLE tokenHandle) { 270 271 // first try the thread token 272 if (OpenThreadToken(GetCurrentThread(), 273 TOKEN_READ, 274 FALSE, 275 tokenHandle) == 0) { 276 if (debug) { 277 printf(" [getToken] OpenThreadToken error [%d]: ", GetLastError()); 278 DisplayErrorText(GetLastError()); 279 } 280 281 // next try the process token 282 if (OpenProcessToken(GetCurrentProcess(), 283 TOKEN_READ, 284 tokenHandle) == 0) { 285 if (debug) { 286 printf(" [getToken] OpenProcessToken error [%d]: ", 287 GetLastError()); 288 DisplayErrorText(GetLastError()); 289 } 290 return FALSE; 291 } 292 } 293 294 if (debug) { 295 printf(" [getToken] got user access token\n"); 296 } 297 298 return TRUE; 299 } 300 301 BOOL getUser(HANDLE tokenHandle, LPTSTR *userName, 302 LPTSTR *domainName, LPTSTR *userSid, LPTSTR *domainSid) { 303 304 BOOL error = FALSE; 305 DWORD bufSize = 0; 306 DWORD buf2Size = 0; 307 DWORD retBufSize = 0; 308 PTOKEN_USER tokenUserInfo = NULL; // getTokenInformation 309 SID_NAME_USE nameUse; // LookupAccountSid 310 311 PSID dSid = NULL; 312 LPTSTR domainSidName = NULL; 313 314 // get token information 315 GetTokenInformation(tokenHandle, 316 TokenUser, 317 NULL, // TokenInformation - if NULL get buffer size 318 0, // since TokenInformation is NULL 319 &bufSize); 320 321 tokenUserInfo = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, bufSize); 322 if (GetTokenInformation(tokenHandle, 323 TokenUser, 324 tokenUserInfo, 325 bufSize, 326 &retBufSize) == 0) { 327 if (debug) { 328 printf(" [getUser] GetTokenInformation error [%d]: ", 329 GetLastError()); 330 DisplayErrorText(GetLastError()); 331 } 332 error = TRUE; 333 goto cleanup; 334 } 335 336 if (debug) { 337 printf(" [getUser] Got TokenUser info\n"); 338 } 339 340 // get userName 341 bufSize = 0; 342 buf2Size = 0; 343 LookupAccountSid(NULL, // local host 344 tokenUserInfo->User.Sid, 345 NULL, 346 &bufSize, 347 NULL, 348 &buf2Size, 349 &nameUse); 350 351 *userName = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, bufSize); 352 *domainName = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, buf2Size); 353 if (LookupAccountSid(NULL, // local host 354 tokenUserInfo->User.Sid, 355 *userName, 356 &bufSize, 357 *domainName, 358 &buf2Size, 359 &nameUse) == 0) { 360 if (debug) { 361 printf(" [getUser] LookupAccountSid error [%d]: ", 362 GetLastError()); 363 DisplayErrorText(GetLastError()); 364 } 365 error = TRUE; 366 goto cleanup; 367 } 368 369 if (debug) { 370 printf(" [getUser] userName: %s, domainName = %s\n", 371 *userName, *domainName); 372 } 373 374 bufSize = 0; 375 getTextualSid(tokenUserInfo->User.Sid, NULL, &bufSize); 376 *userSid = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, bufSize); 377 getTextualSid(tokenUserInfo->User.Sid, *userSid, &bufSize); 378 if (debug) { 379 printf(" [getUser] userSid: %s\n", *userSid); 380 } 381 382 // get domainSid 383 bufSize = 0; 384 buf2Size = 0; 385 LookupAccountName(NULL, // local host 386 *domainName, 387 NULL, 388 &bufSize, 389 NULL, 390 &buf2Size, 391 &nameUse); 392 393 dSid = (PSID)HeapAlloc(GetProcessHeap(), 0, bufSize); 394 domainSidName = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, buf2Size); 395 if (LookupAccountName(NULL, // local host 396 *domainName, 397 dSid, 398 &bufSize, 399 domainSidName, 400 &buf2Size, 401 &nameUse) == 0) { 402 if (debug) { 403 printf(" [getUser] LookupAccountName error [%d]: ", 404 GetLastError()); 405 DisplayErrorText(GetLastError()); 406 } 407 // ok not to have a domain SID (no error) 408 goto cleanup; 409 } 410 411 bufSize = 0; 412 getTextualSid(dSid, NULL, &bufSize); 413 *domainSid = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, bufSize); 414 getTextualSid(dSid, *domainSid, &bufSize); 415 if (debug) { 416 printf(" [getUser] domainSid: %s\n", *domainSid); 417 } 418 419 cleanup: 420 if (tokenUserInfo != NULL) { 421 HeapFree(GetProcessHeap(), 0, tokenUserInfo); 422 } 423 if (dSid != NULL) { 424 HeapFree(GetProcessHeap(), 0, dSid); 425 } 426 if (domainSidName != NULL) { 427 HeapFree(GetProcessHeap(), 0, domainSidName); 428 } 429 if (error) { 430 return FALSE; 431 } 432 return TRUE; 433 } 434 435 BOOL getPrimaryGroup(HANDLE tokenHandle, LPTSTR *primaryGroup) { 436 437 BOOL error = FALSE; 438 DWORD bufSize = 0; 439 DWORD retBufSize = 0; 440 441 PTOKEN_PRIMARY_GROUP tokenGroupInfo = NULL; 442 443 // get token information 444 GetTokenInformation(tokenHandle, 445 TokenPrimaryGroup, 446 NULL, // TokenInformation - if NULL get buffer size 447 0, // since TokenInformation is NULL 448 &bufSize); 449 450 tokenGroupInfo = (PTOKEN_PRIMARY_GROUP)HeapAlloc 451 (GetProcessHeap(), 0, bufSize); 452 if (GetTokenInformation(tokenHandle, 453 TokenPrimaryGroup, 454 tokenGroupInfo, 455 bufSize, 456 &retBufSize) == 0) { 457 if (debug) { 458 printf(" [getPrimaryGroup] GetTokenInformation error [%d]: ", 459 GetLastError()); 460 DisplayErrorText(GetLastError()); 461 } 462 error = TRUE; 463 goto cleanup; 464 } 465 466 if (debug) { 467 printf(" [getPrimaryGroup] Got TokenPrimaryGroup info\n"); 468 } 469 470 bufSize = 0; 471 getTextualSid(tokenGroupInfo->PrimaryGroup, NULL, &bufSize); 472 *primaryGroup = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, bufSize); 473 getTextualSid(tokenGroupInfo->PrimaryGroup, *primaryGroup, &bufSize); 474 if (debug) { 475 printf(" [getPrimaryGroup] primaryGroup: %s\n", *primaryGroup); 476 } 477 478 cleanup: 479 if (tokenGroupInfo != NULL) { 480 HeapFree(GetProcessHeap(), 0, tokenGroupInfo); 481 } 482 if (error) { 483 return FALSE; 484 } 485 return TRUE; 486 } 487 488 BOOL getGroups(HANDLE tokenHandle, PDWORD numGroups, LPTSTR **groups) { 489 490 BOOL error = FALSE; 491 DWORD bufSize = 0; 492 DWORD retBufSize = 0; 493 long i = 0; 494 495 PTOKEN_GROUPS tokenGroupInfo = NULL; 496 497 // get token information 498 GetTokenInformation(tokenHandle, 499 TokenGroups, 500 NULL, // TokenInformation - if NULL get buffer size 501 0, // since TokenInformation is NULL 502 &bufSize); 503 504 tokenGroupInfo = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), 0, bufSize); 505 if (GetTokenInformation(tokenHandle, 506 TokenGroups, 507 tokenGroupInfo, 508 bufSize, 509 &retBufSize) == 0) { 510 if (debug) { 511 printf(" [getGroups] GetTokenInformation error [%d]: ", 512 GetLastError()); 513 DisplayErrorText(GetLastError()); 514 } 515 error = TRUE; 516 goto cleanup; 517 } 518 519 if (debug) { 520 printf(" [getGroups] Got TokenGroups info\n"); 521 } 522 523 if (tokenGroupInfo->GroupCount == 0) { 524 // no groups 525 goto cleanup; 526 } 527 528 // return group info 529 *numGroups = tokenGroupInfo->GroupCount; 530 *groups = (LPTSTR *)HeapAlloc 531 (GetProcessHeap(), 0, (*numGroups) * sizeof(LPTSTR)); 532 for (i = 0; i < (long)*numGroups; i++) { 533 bufSize = 0; 534 getTextualSid(tokenGroupInfo->Groups[i].Sid, NULL, &bufSize); 535 (*groups)[i] = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, bufSize); 536 getTextualSid(tokenGroupInfo->Groups[i].Sid, (*groups)[i], &bufSize); 537 if (debug) { 538 printf(" [getGroups] group %d: %s\n", i, (*groups)[i]); 539 } 540 } 541 542 cleanup: 543 if (tokenGroupInfo != NULL) { 544 HeapFree(GetProcessHeap(), 0, tokenGroupInfo); 545 } 546 if (error) { 547 return FALSE; 548 } 549 return TRUE; 550 } 551 552 BOOL getImpersonationToken(PHANDLE impersonationToken) { 553 554 HANDLE dupToken; 555 556 if (OpenThreadToken(GetCurrentThread(), 557 TOKEN_DUPLICATE, 558 FALSE, 559 &dupToken) == 0) { 560 if (OpenProcessToken(GetCurrentProcess(), 561 TOKEN_DUPLICATE, 562 &dupToken) == 0) { 563 if (debug) { 564 printf 565 (" [getImpersonationToken] OpenProcessToken error [%d]: ", 566 GetLastError()); 567 DisplayErrorText(GetLastError()); 568 } 569 return FALSE; 570 } 571 } 572 573 if (DuplicateToken(dupToken, 574 SecurityImpersonation, 575 impersonationToken) == 0) { 576 if (debug) { 577 printf(" [getImpersonationToken] DuplicateToken error [%d]: ", 578 GetLastError()); 579 DisplayErrorText(GetLastError()); 580 } 581 return FALSE; 582 } 583 CloseHandle(dupToken); 584 585 if (debug) { 586 printf(" [getImpersonationToken] token = %p\n", 587 (void *)*impersonationToken); 588 } 589 return TRUE; 590 } 591 592 BOOL getTextualSid 593 (PSID pSid, // binary SID 594 LPTSTR TextualSid, // buffer for Textual representation of SID 595 LPDWORD lpdwBufferLen) { // required/provided TextualSid buffersize 596 597 PSID_IDENTIFIER_AUTHORITY psia; 598 DWORD dwSubAuthorities; 599 DWORD dwSidRev=SID_REVISION; 600 DWORD dwCounter; 601 DWORD dwSidSize; 602 603 // Validate the binary SID. 604 if(!IsValidSid(pSid)) return FALSE; 605 606 // Get the identifier authority value from the SID. 607 psia = GetSidIdentifierAuthority(pSid); 608 609 // Get the number of subauthorities in the SID. 610 dwSubAuthorities = *GetSidSubAuthorityCount(pSid); 611 612 // Compute the buffer length. 613 // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL 614 dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR); 615 616 // Check input buffer length. 617 // If too small, indicate the proper size and set last error. 618 if (*lpdwBufferLen < dwSidSize) { 619 *lpdwBufferLen = dwSidSize; 620 SetLastError(ERROR_INSUFFICIENT_BUFFER); 621 return FALSE; 622 } 623 624 // Add 'S' prefix and revision number to the string. 625 dwSidSize=wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev ); 626 627 // Add SID identifier authority to the string. 628 if ((psia->Value[0] != 0) || (psia->Value[1] != 0)) { 629 dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid), 630 TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), 631 (USHORT)psia->Value[0], 632 (USHORT)psia->Value[1], 633 (USHORT)psia->Value[2], 634 (USHORT)psia->Value[3], 635 (USHORT)psia->Value[4], 636 (USHORT)psia->Value[5]); 637 } else { 638 dwSidSize+=wsprintf(TextualSid + lstrlen(TextualSid), 639 TEXT("%lu"), 640 (ULONG)(psia->Value[5] ) + 641 (ULONG)(psia->Value[4] << 8) + 642 (ULONG)(psia->Value[3] << 16) + 643 (ULONG)(psia->Value[2] << 24) ); 644 } 645 646 // Add SID subauthorities to the string. 647 for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++) { 648 dwSidSize+=wsprintf(TextualSid + dwSidSize, TEXT("-%lu"), 649 *GetSidSubAuthority(pSid, dwCounter) ); 650 } 651 652 return TRUE; 653 } 654 655 void DisplayErrorText(DWORD dwLastError) { 656 HMODULE hModule = NULL; // default to system source 657 LPSTR MessageBuffer; 658 DWORD dwBufferLength; 659 660 DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | 661 FORMAT_MESSAGE_IGNORE_INSERTS | 662 FORMAT_MESSAGE_FROM_SYSTEM ; 663 664 // 665 // If dwLastError is in the network range, 666 // load the message source. 667 // 668 669 if(dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) { 670 hModule = LoadLibraryEx(TEXT("netmsg.dll"), 671 NULL, 672 LOAD_LIBRARY_AS_DATAFILE); 673 674 if(hModule != NULL) 675 dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE; 676 } 677 678 // 679 // Call FormatMessage() to allow for message 680 // text to be acquired from the system 681 // or from the supplied module handle. 682 // 683 684 if(dwBufferLength = FormatMessageA(dwFormatFlags, 685 hModule, // module to get message from (NULL == system) 686 dwLastError, 687 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language 688 (LPSTR) &MessageBuffer, 689 0, 690 NULL)) { 691 DWORD dwBytesWritten; 692 693 // 694 // Output message string on stderr. 695 // 696 WriteFile(GetStdHandle(STD_ERROR_HANDLE), 697 MessageBuffer, 698 dwBufferLength, 699 &dwBytesWritten, 700 NULL); 701 702 // 703 // Free the buffer allocated by the system. 704 // 705 LocalFree(MessageBuffer); 706 } 707 708 // 709 // If we loaded a message source, unload it. 710 // 711 if(hModule != NULL) 712 FreeLibrary(hModule); 713 } 714 715 /** 716 * 1. comment out first two #includes 717 * 2. set 'debug' to TRUE 718 * 3. comment out 'getCurrent' 719 * 4. uncomment 'main' 720 * 5. cc -c nt.c 721 * 6. link nt.obj user32.lib advapi32.lib /out:nt.exe 722 */ 723 /* 724 void main(int argc, char *argv[]) { 725 726 long i = 0; 727 HANDLE tokenHandle = INVALID_HANDLE_VALUE; 728 729 LPTSTR userName = NULL; 730 LPTSTR userSid = NULL; 731 LPTSTR domainName = NULL; 732 LPTSTR domainSid = NULL; 733 LPTSTR primaryGroup = NULL; 734 DWORD numGroups = 0; 735 LPTSTR *groups = NULL; 736 HANDLE impersonationToken = 0; 737 738 printf("getting access token\n"); 739 if (getToken(&tokenHandle) == FALSE) { 740 exit(1); 741 } 742 743 printf("getting user info\n"); 744 if (getUser 745 (tokenHandle, &userName, &domainName, &userSid, &domainSid) == FALSE) { 746 exit(1); 747 } 748 749 printf("getting primary group\n"); 750 if (getPrimaryGroup(tokenHandle, &primaryGroup) == FALSE) { 751 exit(1); 752 } 753 754 printf("getting supplementary groups\n"); 755 if (getGroups(tokenHandle, &numGroups, &groups) == FALSE) { 756 exit(1); 757 } 758 759 printf("getting impersonation token\n"); 760 if (getImpersonationToken(&impersonationToken) == FALSE) { 761 exit(1); 762 } 763 764 printf("userName = %s, userSid = %s, domainName = %s, domainSid = %s\n", 765 userName, userSid, domainName, domainSid); 766 printf("primaryGroup = %s\n", primaryGroup); 767 for (i = 0; i < numGroups; i++) { 768 printf("Group[%d] = %s\n", i, groups[i]); 769 } 770 printf("impersonationToken = %ld\n", impersonationToken); 771 772 if (userName != NULL) { 773 HeapFree(GetProcessHeap(), 0, userName); 774 } 775 if (userSid != NULL) { 776 HeapFree(GetProcessHeap(), 0, userSid); 777 } 778 if (domainName != NULL) { 779 HeapFree(GetProcessHeap(), 0, domainName); 780 } 781 if (domainSid != NULL) { 782 HeapFree(GetProcessHeap(), 0, domainSid); 783 } 784 if (primaryGroup != NULL) { 785 HeapFree(GetProcessHeap(), 0, primaryGroup); 786 } 787 if (groups != NULL) { 788 for (i = 0; i < numGroups; i++) { 789 if (groups[i] != NULL) { 790 HeapFree(GetProcessHeap(), 0, groups[i]); 791 } 792 } 793 HeapFree(GetProcessHeap(), 0, groups); 794 } 795 CloseHandle(impersonationToken); 796 CloseHandle(tokenHandle); 797 } 798 */ 799 800 /** 801 * extra main method for testing debug printing 802 */ 803 /* 804 void main(int argc, char *argv[]) { 805 if(argc != 2) { 806 fprintf(stderr,"Usage: %s <error number>\n", argv[0]); 807 } 808 809 DisplayErrorText(atoi(argv[1])); 810 } 811 */