0
点赞
收藏
分享

微信扫一扫

sspi for NTLM or Kerberos

九月的栩 2022-05-20 阅读 102


sspi for NTLM or Kerberos_idesspi for NTLM or Kerberos_#include_02代码

  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 sspi for NTLM or Kerberos_#include_03

sspi for NTLM or Kerberos_#define_04sspi for NTLM or Kerberos_ide_05





举报

相关推荐

0 条评论