src/jdk.security.auth/windows/native/libjaas/nt.c
changeset 47216 71c04702a3d5
parent 33653 c1ee09fe3274
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     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 */