sspi for NTLM or Kerberos

 

ExpandedBlockStart.gif 代码
  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           0 0
 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                                           0 0 ,
 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                                             0 0 0 0 ,
 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 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值