Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

758 lines
19 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. tktlogon.cxx
  5. Abstract:
  6. ticket logon
  7. Author:
  8. Larry Zhu (LZhu) January 1, 2002 Created
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. #pragma hdrstop
  15. #include "tktlogon.hxx"
  16. VOID
  17. Usage(
  18. IN PCSTR pszApp
  19. )
  20. {
  21. DebugPrintf(SSPI_ERROR, "\n\nUsage: %s <LogonId.HighPart> <LogonId.LowPart> "
  22. "<serviceprincipal(host/machine@domain)>\n",
  23. pszApp);
  24. exit(-1);
  25. }
  26. NTSTATUS
  27. GetTGT(
  28. IN HANDLE hLsa,
  29. IN ULONG PackageId,
  30. IN LUID* pLogonId,
  31. OUT KERB_EXTERNAL_TICKET** ppCacheEntry
  32. )
  33. {
  34. TNtStatus Status;
  35. NTSTATUS SubStatus;
  36. KERB_QUERY_TKT_CACHE_REQUEST CacheRequest;
  37. ULONG ResponseSize;
  38. CacheRequest.MessageType = KerbRetrieveTicketMessage;
  39. CacheRequest.LogonId = *pLogonId;
  40. DebugPrintf(SSPI_LOG, "GetTgt PackageId %#x, LogonId %#x:%#x\n", PackageId, pLogonId->HighPart, pLogonId->LowPart);
  41. Status DBGCHK = LsaCallAuthenticationPackage(
  42. hLsa,
  43. PackageId,
  44. &CacheRequest,
  45. sizeof(CacheRequest),
  46. (VOID **) ppCacheEntry,
  47. &ResponseSize,
  48. &SubStatus
  49. );
  50. if (NT_SUCCESS(Status))
  51. {
  52. Status DBGCHK = SubStatus;
  53. }
  54. return Status;
  55. }
  56. NTSTATUS
  57. GetServiceTicket(
  58. IN HANDLE hLsa,
  59. IN ULONG ulPackageId,
  60. IN UNICODE_STRING* pServicePrincipal,
  61. IN LUID* pLogonId,
  62. IN BOOLEAN useCache,
  63. OUT KERB_RETRIEVE_TKT_RESPONSE** ppCacheResponse
  64. )
  65. {
  66. TNtStatus Status;
  67. NTSTATUS SubStatus;
  68. VOID* pResponse;
  69. ULONG ResponseSize;
  70. KERB_RETRIEVE_TKT_REQUEST* pCacheRequest = NULL;
  71. ULONG cbCacheRequest = 0;
  72. UNICODE_STRING Target = {0};
  73. HANDLE hLogon = hLsa;
  74. ULONG PackageId = ulPackageId;
  75. cbCacheRequest = pServicePrincipal->Length
  76. + ROUND_UP_COUNT(sizeof(KERB_RETRIEVE_TKT_REQUEST), sizeof(ULONG_PTR));
  77. pCacheRequest = (KERB_RETRIEVE_TKT_REQUEST*) new CHAR[cbCacheRequest];
  78. Status DBGCHK = pCacheRequest ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  79. if (NT_SUCCESS(Status))
  80. {
  81. RtlZeroMemory(pCacheRequest, cbCacheRequest);
  82. pCacheRequest->MessageType = KerbRetrieveEncodedTicketMessage;
  83. Target.Buffer = (PWSTR) (pCacheRequest + 1);
  84. Target.Length = pServicePrincipal->Length;
  85. Target.MaximumLength = pServicePrincipal->MaximumLength;
  86. pCacheRequest->LogonId = *pLogonId;
  87. RtlCopyMemory(
  88. Target.Buffer,
  89. pServicePrincipal->Buffer,
  90. pServicePrincipal->Length
  91. );
  92. pCacheRequest->TargetName = Target;
  93. if (!useCache)
  94. {
  95. pCacheRequest->CacheOptions = KERB_RETRIEVE_TICKET_DONT_USE_CACHE;
  96. }
  97. else
  98. {
  99. pCacheRequest->CacheOptions = 0;
  100. }
  101. DebugPrintf(SSPI_LOG, "ServicePrincipal: %wZ\n", &Target);
  102. Status DBGCHK = LsaCallAuthenticationPackage(
  103. hLsa,
  104. ulPackageId,
  105. pCacheRequest,
  106. pServicePrincipal->Length + sizeof(KERB_RETRIEVE_TKT_REQUEST),
  107. &pResponse,
  108. &ResponseSize,
  109. &SubStatus
  110. );
  111. }
  112. if (NT_SUCCESS(Status))
  113. {
  114. Status DBGCHK = SubStatus;
  115. }
  116. if (NT_SUCCESS(Status))
  117. {
  118. *ppCacheResponse = (KERB_RETRIEVE_TKT_RESPONSE*) pResponse;
  119. pResponse = NULL;
  120. }
  121. if (pCacheRequest)
  122. {
  123. delete [] pCacheRequest;
  124. }
  125. if (pResponse)
  126. {
  127. LsaFreeReturnBuffer(pResponse);
  128. }
  129. return NT_SUCCESS(Status) ? SubStatus : Status;
  130. }
  131. NTSTATUS
  132. BuildAllocTicketLogonInfo(
  133. IN UCHAR* pTGTData,
  134. IN ULONG cbTGTDataLength,
  135. IN UCHAR* pTicketData,
  136. IN ULONG cbTicketDataLength,
  137. IN ULONG DataOffset,
  138. IN OUT ULONG *pLogonInfoSize,
  139. OUT KERB_TICKET_LOGON** ppLogonInfo
  140. )
  141. {
  142. TNtStatus Status = STATUS_SUCCESS;
  143. UCHAR* pWhere = NULL;
  144. KERB_TICKET_LOGON* pLogonInfo = NULL;
  145. ULONG cbLogonInfoSize = *pLogonInfoSize;
  146. //assemble LogonInfo
  147. cbLogonInfoSize += cbTicketDataLength;
  148. if (cbTGTDataLength && pTGTData)
  149. {
  150. cbLogonInfoSize += cbTGTDataLength;
  151. }
  152. pLogonInfo = (KERB_TICKET_LOGON*) new CHAR[cbLogonInfoSize];
  153. Status DBGCHK = pLogonInfo ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  154. if (NT_SUCCESS(Status))
  155. {
  156. RtlZeroMemory(pLogonInfo, cbLogonInfoSize);
  157. pWhere = ((UCHAR*) pLogonInfo) + DataOffset;
  158. pLogonInfo->ServiceTicket = (UCHAR*) pWhere;
  159. pLogonInfo->ServiceTicketLength = cbTicketDataLength;
  160. RtlCopyMemory(pLogonInfo->ServiceTicket, pTicketData, cbTicketDataLength);
  161. pWhere += pLogonInfo->ServiceTicketLength;
  162. pLogonInfo->TicketGrantingTicketLength = cbTGTDataLength;
  163. if (pLogonInfo->TicketGrantingTicketLength)
  164. {
  165. pLogonInfo->TicketGrantingTicket = (UCHAR*) pWhere;
  166. RtlCopyMemory(pLogonInfo->TicketGrantingTicket, pTGTData, cbTGTDataLength);
  167. }
  168. *ppLogonInfo = pLogonInfo;
  169. pLogonInfo = NULL;
  170. *pLogonInfoSize = cbLogonInfoSize;
  171. }
  172. if (pLogonInfo)
  173. {
  174. delete [] pLogonInfo;
  175. }
  176. return Status;
  177. }
  178. NTSTATUS
  179. LsaTicketLogon(
  180. IN HANDLE hLsa,
  181. IN ULONG ulPackageId,
  182. IN UCHAR* pTGTData,
  183. IN ULONG cbTGTDataLength,
  184. IN UCHAR* pTicketData,
  185. IN ULONG cbTicketDataLength,
  186. OUT LUID* pLogonId,
  187. OUT HANDLE* phUserToken
  188. )
  189. {
  190. TNtStatus Status;
  191. SECURITY_LOGON_TYPE LogonType = Interactive;
  192. KERB_TICKET_LOGON* pLogonInfo = NULL;
  193. ULONG cbLogonInfoSize = sizeof(KERB_TICKET_LOGON);
  194. TOKEN_SOURCE SourceContext = {0};
  195. KERB_TICKET_PROFILE* pKerbTicketProfile = NULL;
  196. ULONG ProfileSize;
  197. STRING Name = {0};
  198. QUOTA_LIMITS Quotas = {0};
  199. NTSTATUS SubStatus;
  200. Status DBGCHK = BuildAllocTicketLogonInfo(
  201. pTGTData,
  202. cbTGTDataLength,
  203. pTicketData,
  204. cbTicketDataLength,
  205. sizeof(KERB_TICKET_LOGON), //offset for data copy
  206. &cbLogonInfoSize, //initialized to struct size
  207. &pLogonInfo
  208. );
  209. if (NT_SUCCESS(Status))
  210. {
  211. pLogonInfo->MessageType = KerbTicketLogon;
  212. pLogonInfo->Flags = 0;
  213. strncpy(
  214. SourceContext.SourceName,
  215. "krlogind",
  216. sizeof(SourceContext.SourceName)
  217. );
  218. RtlInitString(&Name, "lzhu");
  219. Status DBGCHK = NtAllocateLocallyUniqueId(&SourceContext.SourceIdentifier);
  220. }
  221. if (NT_SUCCESS(Status))
  222. {
  223. Status DBGCHK = LsaLogonUser(
  224. hLsa,
  225. &Name,
  226. LogonType,
  227. ulPackageId,
  228. pLogonInfo,
  229. cbLogonInfoSize,
  230. NULL, // no token groups
  231. &SourceContext,
  232. (PVOID *) &pKerbTicketProfile,
  233. &ProfileSize,
  234. pLogonId,
  235. phUserToken,
  236. &Quotas,
  237. &SubStatus
  238. );
  239. }
  240. if (NT_SUCCESS(Status))
  241. {
  242. Status DBGCHK = SubStatus;
  243. }
  244. if (NT_SUCCESS(Status))
  245. {
  246. DebugPrintf(SSPI_LOG, "LogonId %#x:%#x\n", pLogonId->HighPart, pLogonId->LowPart);
  247. DebugPrintf(SSPI_LOG, "TokenHandle %p\n", *phUserToken);
  248. DebugPrintf(SSPI_LOG, "Quotas PagedPoolLimit %p, NonPagedPoolLimit %p, "
  249. "MinimumWorkingSetSize %p, MaximumWorkingSetSize %p, PagedPoolLimit %p\n",
  250. Quotas.PagedPoolLimit, Quotas.NonPagedPoolLimit,
  251. Quotas.MinimumWorkingSetSize, Quotas.MaximumWorkingSetSize,
  252. Quotas.PagedPoolLimit);
  253. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "TimeLimit", &Quotas.TimeLimit);
  254. KERB_INTERACTIVE_PROFILE* pKrbInteractiveProfile = &pKerbTicketProfile->Profile;
  255. DebugPrintf(SSPI_LOG, "interactive logon profile: "
  256. "LogCount %#x, BaddPasswordCount %#x, LogonScript %wZ, "
  257. "HomeDirectory %wZ, FullName %wZ, ProfilePath %wZ, "
  258. "HomeDriectoryDrive %wZ, LogonServer %wZ, UserFlags %#x\n",
  259. pKrbInteractiveProfile->LogonCount,
  260. pKrbInteractiveProfile->BadPasswordCount,
  261. &pKrbInteractiveProfile->LogonScript,
  262. &pKrbInteractiveProfile->HomeDirectory,
  263. &pKrbInteractiveProfile->FullName,
  264. &pKrbInteractiveProfile->ProfilePath,
  265. &pKrbInteractiveProfile->HomeDirectoryDrive,
  266. &pKrbInteractiveProfile->LogonServer,
  267. pKrbInteractiveProfile->UserFlags);
  268. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "LogonTime ", &pKrbInteractiveProfile->LogonTime);
  269. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "KickOffTime ", &pKrbInteractiveProfile->KickOffTime);
  270. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "PasswordLastSet ", &pKrbInteractiveProfile->PasswordLastSet);
  271. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "PasswordCanChange ", &pKrbInteractiveProfile->PasswordCanChange);
  272. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "PasswordMustChange ", &pKrbInteractiveProfile->PasswordMustChange);
  273. DebugPrintHex(SSPI_LOG, "SessionKey:", sizeof(pKerbTicketProfile->SessionKey), &pKerbTicketProfile->SessionKey);
  274. }
  275. if (pKerbTicketProfile)
  276. {
  277. LsaFreeReturnBuffer(pKerbTicketProfile);
  278. }
  279. if (pLogonInfo)
  280. {
  281. delete [] pLogonInfo;
  282. }
  283. return Status;
  284. }
  285. NTSTATUS
  286. KerbBuildKerbCredFromExternalTickets(
  287. IN PKERB_EXTERNAL_TICKET pTicket,
  288. IN PKERB_EXTERNAL_TICKET pDelegationTicket,
  289. OUT PUCHAR* pMarshalledKerbCred,
  290. OUT PULONG pcbKerbCredSize
  291. )
  292. {
  293. TKerbErr KerbErr;
  294. KERB_CRED KerbCred;
  295. KERB_CRED_INFO_LIST CredInfo;
  296. KERB_ENCRYPTED_CRED EncryptedCred;
  297. KERB_CRED_TICKET_LIST TicketList;
  298. ULONG EncryptionOverhead;
  299. ULONG BlockSize;
  300. PUCHAR pMarshalledEncryptPart = NULL;
  301. ULONG MarshalledEncryptSize;
  302. ULONG ConvertedFlags;
  303. PKERB_TICKET pDecodedTicket = NULL;
  304. //
  305. // Initialize the structures so they can be freed later.
  306. //
  307. *pMarshalledKerbCred = NULL;
  308. *pcbKerbCredSize = 0;
  309. RtlZeroMemory(
  310. &KerbCred,
  311. sizeof(KERB_CRED)
  312. );
  313. RtlZeroMemory(
  314. &EncryptedCred,
  315. sizeof(KERB_ENCRYPTED_CRED)
  316. );
  317. RtlZeroMemory(
  318. &CredInfo,
  319. sizeof(KERB_CRED_INFO_LIST)
  320. );
  321. RtlZeroMemory(
  322. &TicketList,
  323. sizeof(KERB_CRED_TICKET_LIST)
  324. );
  325. KerbCred.version = KERBEROS_VERSION;
  326. KerbCred.message_type = KRB_CRED;
  327. //
  328. // Decode the ticket so we can put it in the structure (to re-encode it)
  329. //
  330. KerbErr DBGCHK = KerbUnpackData(
  331. pDelegationTicket->EncodedTicket,
  332. pDelegationTicket->EncodedTicketSize,
  333. KERB_TICKET_PDU,
  334. (PVOID *) &pDecodedTicket
  335. );
  336. //
  337. // First stick the ticket into the ticket list.
  338. //
  339. if (KERB_SUCCESS(KerbErr))
  340. {
  341. TicketList.next= NULL;
  342. TicketList.value = *pDecodedTicket;
  343. KerbCred.tickets = &TicketList;
  344. //
  345. // Now build the KERB_CRED_INFO for this ticket
  346. //
  347. CredInfo.value.key = * (PKERB_ENCRYPTION_KEY) &pDelegationTicket->SessionKey;
  348. KerbConvertLargeIntToGeneralizedTime(
  349. &CredInfo.value.endtime,
  350. NULL,
  351. &pDelegationTicket->EndTime
  352. );
  353. CredInfo.value.bit_mask |= endtime_present;
  354. KerbConvertLargeIntToGeneralizedTime(
  355. &CredInfo.value.starttime,
  356. NULL,
  357. &pDelegationTicket->StartTime
  358. );
  359. CredInfo.value.bit_mask |= KERB_CRED_INFO_starttime_present;
  360. KerbConvertLargeIntToGeneralizedTime(
  361. &CredInfo.value.KERB_CRED_INFO_renew_until,
  362. NULL,
  363. &pDelegationTicket->RenewUntil
  364. );
  365. CredInfo.value.bit_mask |= KERB_CRED_INFO_renew_until_present;
  366. ConvertedFlags = KerbConvertUlongToFlagUlong(pDelegationTicket->TicketFlags);
  367. CredInfo.value.flags.value = (PUCHAR) &ConvertedFlags;
  368. CredInfo.value.flags.length = 8 * sizeof(ULONG);
  369. CredInfo.value.bit_mask |= flags_present;
  370. KerbErr DBGCHK = KerbConvertKdcNameToPrincipalName(
  371. &CredInfo.value.principal_name,
  372. (PKERB_INTERNAL_NAME) pDelegationTicket->ClientName
  373. );
  374. }
  375. if (KERB_SUCCESS(KerbErr))
  376. {
  377. CredInfo.value.bit_mask |= principal_name_present;
  378. KerbErr DBGCHK = KerbConvertKdcNameToPrincipalName(
  379. &CredInfo.value.principal_name,
  380. (PKERB_INTERNAL_NAME) pDelegationTicket->ServiceName
  381. );
  382. }
  383. if (KERB_SUCCESS(KerbErr))
  384. {
  385. CredInfo.value.bit_mask |= principal_name_present;
  386. KerbErr DBGCHK = KerbConvertUnicodeStringToRealm(
  387. &CredInfo.value.principal_realm,
  388. &pDelegationTicket->DomainName
  389. );
  390. }
  391. //
  392. // The realms are the same, so don't allocate both
  393. //
  394. if (KERB_SUCCESS(KerbErr))
  395. {
  396. CredInfo.value.service_realm = CredInfo.value.service_realm;
  397. CredInfo.value.bit_mask |= principal_realm_present | service_realm_present;
  398. EncryptedCred.ticket_info = &CredInfo;
  399. //
  400. // Now encrypted the encrypted cred into the cred
  401. //
  402. KerbErr DBGCHK = KerbPackEncryptedCred(
  403. &EncryptedCred,
  404. &MarshalledEncryptSize,
  405. &pMarshalledEncryptPart
  406. );
  407. }
  408. //
  409. // If we are doing DES encryption, then we are talking with an non-NT
  410. // server. Hence, don't encrypt the kerb-cred.
  411. //
  412. if (KERB_SUCCESS(KerbErr))
  413. {
  414. if ((pTicket->SessionKey.KeyType == KERB_ETYPE_DES_CBC_CRC) ||
  415. (pTicket->SessionKey.KeyType == KERB_ETYPE_DES_CBC_MD5))
  416. {
  417. KerbCred.encrypted_part.cipher_text.length = MarshalledEncryptSize;
  418. KerbCred.encrypted_part.cipher_text.value = pMarshalledEncryptPart;
  419. KerbCred.encrypted_part.encryption_type = 0;
  420. pMarshalledEncryptPart = NULL;
  421. }
  422. else
  423. {
  424. //
  425. // Now get the encryption overhead
  426. //
  427. KerbErr DBGCHK = KerbAllocateEncryptionBufferWrapper(
  428. pTicket->SessionKey.KeyType,
  429. MarshalledEncryptSize,
  430. &KerbCred.encrypted_part.cipher_text.length,
  431. &KerbCred.encrypted_part.cipher_text.value
  432. );
  433. //
  434. // Encrypt the data.
  435. //
  436. if (KERB_SUCCESS(KerbErr))
  437. {
  438. KerbErr DBGCHK = KerbEncryptDataEx(
  439. &KerbCred.encrypted_part,
  440. MarshalledEncryptSize,
  441. pMarshalledEncryptPart,
  442. pTicket->SessionKey.KeyType,
  443. KERB_CRED_SALT,
  444. (PKERB_ENCRYPTION_KEY) &pTicket->SessionKey
  445. );
  446. }
  447. }
  448. }
  449. //
  450. // Now we have to marshall the whole KERB_CRED
  451. //
  452. if (KERB_SUCCESS(KerbErr))
  453. {
  454. KerbErr DBGCHK = KerbPackKerbCred(
  455. &KerbCred,
  456. pcbKerbCredSize,
  457. pMarshalledKerbCred
  458. );
  459. }
  460. if (pDecodedTicket != NULL)
  461. {
  462. KerbFreeData(
  463. KERB_TICKET_PDU,
  464. pDecodedTicket
  465. );
  466. }
  467. KerbFreePrincipalName(&CredInfo.value.service_name);
  468. KerbFreePrincipalName(&CredInfo.value.principal_name);
  469. KerbFreeRealm(&CredInfo.value.principal_realm);
  470. if (pMarshalledEncryptPart != NULL)
  471. {
  472. MIDL_user_free(pMarshalledEncryptPart);
  473. }
  474. if (KerbCred.encrypted_part.cipher_text.value != NULL)
  475. {
  476. MIDL_user_free(KerbCred.encrypted_part.cipher_text.value);
  477. }
  478. return KerbMapKerbError(KerbErr);
  479. }
  480. NTSTATUS
  481. TicketLogon(
  482. IN LUID* pLogonId,
  483. IN PCSTR pszServicePrincipal,
  484. OUT HANDLE* phToken
  485. )
  486. {
  487. TNtStatus Status;
  488. HANDLE hLogon = NULL;
  489. ULONG PackageId = -1;
  490. KERB_EXTERNAL_TICKET* pTGTExternal = NULL;
  491. KERB_RETRIEVE_TKT_RESPONSE* pTicketCacheResponse = NULL;
  492. UNICODE_STRING ServicePrincipal = {0};
  493. UCHAR* pMarshalledTGT = NULL;
  494. ULONG ulTGTSize = 0;
  495. LUID UserId;
  496. Status DBGCHK = CreateUnicodeStringFromAsciiz(pszServicePrincipal, &ServicePrincipal);
  497. if (NT_SUCCESS(Status))
  498. {
  499. Status DBGCHK = GetLsaHandleAndPackageId(
  500. MICROSOFT_KERBEROS_NAME_A,
  501. &hLogon,
  502. &PackageId
  503. );
  504. }
  505. if (NT_SUCCESS(Status))
  506. {
  507. Status DBGCHK = GetTGT(
  508. hLogon,
  509. PackageId,
  510. pLogonId,
  511. &pTGTExternal
  512. );
  513. }
  514. //
  515. // get service pTicket
  516. //
  517. if (NT_SUCCESS(Status))
  518. {
  519. Status DBGCHK = GetServiceTicket(
  520. hLogon,
  521. PackageId,
  522. &ServicePrincipal,
  523. pLogonId,
  524. FALSE,
  525. &pTicketCacheResponse
  526. );
  527. }
  528. if (NT_SUCCESS(Status))
  529. {
  530. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "StartTime: ", &pTGTExternal->StartTime);
  531. Status DBGCHK = KerbBuildKerbCredFromExternalTickets(
  532. &pTicketCacheResponse->Ticket,
  533. pTGTExternal,
  534. &pMarshalledTGT,
  535. &ulTGTSize
  536. );
  537. }
  538. if (NT_SUCCESS(Status))
  539. {
  540. Status DBGCHK = LsaTicketLogon(
  541. hLogon,
  542. PackageId,
  543. pMarshalledTGT,
  544. ulTGTSize,
  545. pTicketCacheResponse->Ticket.EncodedTicket,
  546. pTicketCacheResponse->Ticket.EncodedTicketSize,
  547. &UserId,
  548. phToken
  549. );
  550. }
  551. if (hLogon)
  552. {
  553. LsaDeregisterLogonProcess(hLogon);
  554. }
  555. if (pTGTExternal)
  556. {
  557. LsaFreeReturnBuffer(pTGTExternal);
  558. }
  559. if (pTicketCacheResponse)
  560. {
  561. LsaFreeReturnBuffer(pTicketCacheResponse);
  562. }
  563. if (pMarshalledTGT)
  564. {
  565. MIDL_user_free(pMarshalledTGT);
  566. }
  567. RtlFreeUnicodeString(&ServicePrincipal);
  568. return Status;
  569. }
  570. VOID
  571. __cdecl
  572. main(
  573. IN INT argc,
  574. IN PSTR argv[]
  575. )
  576. {
  577. TNtStatus Status = STATUS_SUCCESS;
  578. HANDLE hToken = NULL;
  579. LUID LogonId = {0};
  580. if (argc != 4)
  581. {
  582. Usage(argv[0]);
  583. }
  584. LogonId.HighPart = strtol(argv[1], NULL, 0);
  585. LogonId.LowPart = strtol(argv[2], NULL, 0);
  586. DebugPrintf(SSPI_LOG, "LogonId %#x:%#x\n", LogonId.HighPart, LogonId.LowPart);
  587. DebugPrintf(SSPI_LOG, "service principal is %s\n", argv[3]);
  588. Status DBGCHK = TicketLogon(&LogonId, argv[3], &hToken);
  589. if (NT_SUCCESS(Status))
  590. {
  591. UNICODE_STRING Application = {0};
  592. Status DBGCHK = CreateUnicodeStringFromAsciiz("cmd.exe", &Application);
  593. if (NT_SUCCESS(Status))
  594. {
  595. Status DBGCHK = StartInteractiveClientProcessAsUser(hToken, Application.Buffer);
  596. }
  597. RtlFreeUnicodeString(&Application);
  598. }
  599. if (NT_SUCCESS(Status))
  600. {
  601. DebugPrintf(SSPI_LOG, "tktlogon succeeded\n");
  602. }
  603. else
  604. {
  605. DebugPrintf(SSPI_ERROR, "tktlogon failed\n");
  606. }
  607. if (hToken)
  608. {
  609. CloseHandle(hToken);
  610. }
  611. }