• sspi for NTLM or Kerberos


    代码
      1 /*
      2 You can get a locally valid logon session (a network logon session) by using SSPI.
      3 Simply specify alternate credentials when you call AcquireCredentialsHandle,
      4 and then after you follow the normal InitializeSecurityContext/AcceptSecurityContext
      5 handshake, you'll end up with a logon session for the user,
      6 without having to have the TCB privilege.
      7 
      8 See the attached example...
      9 
     10 Keith
     11   */
     12 
     13 // this version requires Windows 2000
     14 #define _WIN32_WINNT 0x500
     15 #define UNICODE
     16 #include <windows.h>
     17 #include <stdio.h>
     18 #define SECURITY_WIN32
     19 #include <security.h>
     20 #pragma comment(lib, "secur32.lib")
     21 
     22 // brain-dead error routine that dumps the last error and exits
     23 void _err(const wchar_t* pszFcn, DWORD nErr = GetLastError())
     24 {
     25  
     26     wchar_t szErr[256];
     27     if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, nErr, 0,
     28                       szErr, sizeof szErr / sizeof *szErr, 0))
     29          wprintf(L"%s failed: %s", pszFcn, szErr);
     30     else wprintf(L"%s failed: 0x%08X", nErr);
     31     exit(1);
     32 }
     33 
     34 // Upon success, returns a handle to a NETWORK logon session
     35 // for the specified principal (it will *not* have network
     36 // credentials). Call CloseHandle to dispose of it when
     37 // you are finished.
     38 HANDLE _logonUserWithSSPI(wchar_t* pszSSP,
     39                           DWORD grfDesiredAccessToToken,
     40                           wchar_t* pszAuthority,
     41                           wchar_t* pszPrincipal,
     42                           wchar_t* pszPassword) {
     43 
     44     // the following code loads the SSPI interface DLL
     45     // and initializes it, getting a table of function ptrs
     46     HINSTANCE hdll = LoadLibrary(L"security.dll");
     47     if (!hdll)
     48         _err(L"LoadLibrary");
     49     INIT_SECURITY_INTERFACE_W initSecurityInterface =
     50             (INIT_SECURITY_INTERFACE_W)GetProcAddress(hdll,
     51                 SECURITY_ENTRYPOINT_ANSIW);
     52     if (!initSecurityInterface)
     53         _err(L"GetProcAddress");
     54     PSecurityFunctionTable pSSPI = initSecurityInterface();
     55 
     56     // here's where we specify the credentials to verify
     57     SEC_WINNT_AUTH_IDENTITY_EX authIdent = {
     58         SEC_WINNT_AUTH_IDENTITY_VERSION,
     59         sizeof authIdent,
     60         pszPrincipal, lstrlenW(pszPrincipal),
     61         pszAuthority, lstrlenW(pszAuthority),
     62         pszPassword,  lstrlenW(pszPassword),
     63         SEC_WINNT_AUTH_IDENTITY_UNICODE,
     64         00
     65     };
     66 
     67     // get an SSPI handle for these credentials
     68     CredHandle hcredClient;
     69     TimeStamp expiryClient;
     70     SECURITY_STATUS err =
     71         pSSPI->AcquireCredentialsHandle(0, pszSSP,
     72                                         SECPKG_CRED_OUTBOUND,
     73                                         0&authIdent,
     74                                         00,
     75                                         &hcredClient,
     76                                         &expiryClient);
     77     if (err)
     78         _err(L"AcquireCredentialsHandle for client", err);
     79 
     80     // use the caller's credentials for the server
     81     CredHandle hcredServer;
     82     TimeStamp expiryServer;
     83     err = pSSPI->AcquireCredentialsHandle(0, pszSSP,
     84                                           SECPKG_CRED_INBOUND,
     85                                           0000,
     86                                           &hcredServer,
     87                                           &expiryServer);
     88     if (err)
     89         _err(L"AcquireCredentialsHandle for server", err);
     90 
     91     CtxtHandle hctxClient;
     92     CtxtHandle hctxServer;
     93 
     94     // create two buffers:
     95     //    one for the client sending tokens to the server,
     96     //    one for the server sending tokens to the client
     97     // (buffer size chosen based on current Kerb SSP setting
     98     //  for cbMaxToken - you may need to adjust this)
     99     BYTE bufC2S[8000];
    100     BYTE bufS2C[8000];
    101     SecBuffer sbufC2S = { sizeof bufC2S, SECBUFFER_TOKEN, bufC2S };
    102     SecBuffer sbufS2C = { sizeof bufS2C, SECBUFFER_TOKEN, bufS2C };
    103     SecBufferDesc bdC2S = { SECBUFFER_VERSION, 1&sbufC2S };
    104     SecBufferDesc bdS2C = { SECBUFFER_VERSION, 1&sbufS2C };
    105 
    106     // don't really need any special context attributes
    107     DWORD grfRequiredCtxAttrsClient = ISC_REQ_DATAGRAM;//ISC_REQ_DELEGATE
    108     DWORD grfRequiredCtxAttrsServer = ASC_REQ_DATAGRAM;
    109 
    110     // set up some aliases to make it obvious what's happening
    111     PCtxtHandle    pClientCtxHandleIn  = 0;
    112     PCtxtHandle    pClientCtxHandleOut = &hctxClient;
    113     PCtxtHandle    pServerCtxHandleIn  = 0;
    114     PCtxtHandle    pServerCtxHandleOut = &hctxServer;
    115     SecBufferDesc* pClientInput  = 0;
    116     SecBufferDesc* pClientOutput = &bdC2S;
    117     SecBufferDesc* pServerInput  = &bdC2S;
    118     SecBufferDesc* pServerOutput = &bdS2C;
    119     DWORD          grfCtxAttrsClient = 0;
    120     DWORD          grfCtxAttrsServer = 0;
    121     TimeStamp      expiryClientCtx;
    122     TimeStamp      expiryServerCtx;
    123 
    124     // since the caller is acting as the server, we need
    125     // a server principal name so that the client will
    126     // be able to get a Kerb ticket (if Kerb is used)
    127     wchar_t szSPN[256]={0};
    128     ULONG cchSPN = sizeof szSPN / sizeof *szSPN;
    129     GetUserNameEx(NameSamCompatible, szSPN, &cchSPN);
    130  
    131  //sevice class / host: port / service instance
    132  
    133 // wcscpy (szSPN, TEXT("192.168.1.11"));
    134 // wcscpy (szSPN, TEXT("testwork-AD11.testwork.com"));
    135 // wcscpy (szSPN, TEXT("192.168.1.11"));
    136 // wcscpy (szSPN, TEXT("TESTWORK\\administrator"));
    137 // wcscpy (szSPN, TEXT("..."));
    138  printf("%ws\n",szSPN);
    139     // perform the authentication handshake, playing the
    140     // role of both client *and* server.
    141     bool bClientContinue = true;
    142     bool bServerContinue = true;
    143  int count=1;
    144     while (bClientContinue || bServerContinue) {
    145   
    146         if (bClientContinue) {
    147    
    148             sbufC2S.cbBuffer = sizeof bufC2S;
    149             err = pSSPI->InitializeSecurityContext(
    150                 &hcredClient, pClientCtxHandleIn,
    151                 szSPN,
    152                 grfRequiredCtxAttrsClient,
    153                 0, SECURITY_NETWORK_DREP,
    154                 pClientInput, 0,
    155                 pClientCtxHandleOut,
    156                 pClientOutput,
    157                 &grfCtxAttrsClient,
    158                 &expiryClientCtx);
    159             switch (err) {
    160                 case 0:
    161                     bClientContinue = false;
    162                     break;
    163                 case SEC_I_CONTINUE_NEEDED:
    164                     pClientCtxHandleIn = pClientCtxHandleOut;
    165                     pClientInput       = pServerOutput;
    166                     break;
    167                 default:
    168      printf("err=%x\n",err);
    169                     _err(L"InitializeSecurityContext", err);
    170             }
    171         }
    172 
    173         if (bServerContinue) {
    174             sbufS2C.cbBuffer = sizeof bufS2C;
    175             err = pSSPI->AcceptSecurityContext(
    176                 &hcredServer, pServerCtxHandleIn,
    177                 pServerInput,
    178                 grfRequiredCtxAttrsServer,
    179                 SECURITY_NETWORK_DREP,
    180                 pServerCtxHandleOut,
    181                 pServerOutput,
    182                 &grfCtxAttrsServer,
    183                 &expiryServerCtx);
    184             switch (err) {
    185                 case 0:
    186                     bServerContinue = false;
    187                     break;
    188                 case SEC_I_CONTINUE_NEEDED:
    189                     pServerCtxHandleIn = pServerCtxHandleOut;
    190                     break;
    191                 default:
    192                     _err(L"AcceptSecurityContext", err);
    193             }
    194         }
    195   printf("%d bClientContinue %d bServerContinue %d\n",count++,bClientContinue,bServerContinue);
    196     }
    197     // if everything has gone smoothly, we've now got a logon
    198     // session for the client - let's grab the token now
    199     pSSPI->ImpersonateSecurityContext(pServerCtxHandleOut);
    200     HANDLE htok;
    201     if (!OpenThreadToken(GetCurrentThread(),
    202                          grfDesiredAccessToToken,
    203                          TRUE, &htok))
    204         _err(L"OpenThreadToken");
    205     pSSPI->RevertSecurityContext(pServerCtxHandleOut);
    206 
    207     // clean up
    208     pSSPI->FreeCredentialsHandle(&hcredClient);
    209     pSSPI->FreeCredentialsHandle(&hcredServer);
    210     pSSPI->DeleteSecurityContext(pServerCtxHandleOut);
    211     pSSPI->DeleteSecurityContext(pClientCtxHandleOut);
    212     
    213     return htok;
    214 }
    215 
    216 // here's an example of usage
    217 void main() {
    218     // use "NTLM" or "Kerberos"
    219 
    220 //Kerbero需要在加入域或者有域环境下才能正确运行
    221     HANDLE htok = _logonUserWithSSPI(L"Kerberos",
    222                                      TOKEN_QUERY,
    223                                      NULL,
    224                                      L"administrator",
    225                                      L"!QAZsx");
    226     if (htok) {
    227         // password is valid!
    228         CloseHandle(htok);
    229     }
    230 }
    231 
    232 
  • 相关阅读:
    第39周星期日中秋节杂记
    php array_multisort
    php统计近一周和近30天的用户数据
    什么是CGI、FastCGI、PHPCGI、PHPFPM、SpawnFCGI?
    PHP array_multisort()函数超详细理解
    微博第三方登陆请求授权出现错误码:21322(重定向地址不匹配)的解决方法
    艾伟_转载:C# 反射技术应用 狼人:
    艾伟_转载:HttpApplication的认识与加深理解 狼人:
    艾伟_转载:C# .NET学习经验总结 狼人:
    艾伟_转载:C# 委托的同步调用和异步调用 狼人:
  • 原文地址:https://www.cnblogs.com/ahuo/p/1767293.html
Copyright © 2020-2023  润新知