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.

1273 lines
30 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: ticktest.cxx
  7. //
  8. // Contents: KDC Ticket granting service test code.
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 19-Aug-93 WadeR Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <secpch2.hxx>
  18. #pragma hdrstop
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <kerbcomm.h>
  22. #include <kerbcred.h>
  23. extern "C"
  24. {
  25. #include <dsgetdc.h>
  26. #include <kdcdbg.h>
  27. }
  28. UNICODE_STRING ClientName;
  29. UNICODE_STRING ServiceName;
  30. UNICODE_STRING ClientRealm;
  31. UNICODE_STRING ServiceRealm;
  32. UNICODE_STRING ClientPassword;
  33. UNICODE_STRING ServicePassword;
  34. UNICODE_STRING KdcName;
  35. WCHAR KdcNameString[100];
  36. ULONG AddressType = DS_NETBIOS_ADDRESS;
  37. ULONG CryptType = KERB_ETYPE_RC4_MD4;
  38. PVOID KdcBinding;
  39. BOOLEAN
  40. BindToKdc()
  41. {
  42. ULONG NetStatus;
  43. PDOMAIN_CONTROLLER_INFO DcInfo = NULL;
  44. if (KdcName.Buffer == NULL)
  45. {
  46. //
  47. // No kdc specified, use DSGetDCName
  48. //
  49. NetStatus = DsGetDcName(
  50. NULL,
  51. ClientRealm.Buffer,
  52. NULL,
  53. NULL,
  54. DS_KDC_REQUIRED,
  55. &DcInfo
  56. );
  57. if (NetStatus != NO_ERROR)
  58. {
  59. printf("DsGetDcName returned %d\n",NetStatus);
  60. return(FALSE);
  61. }
  62. RtlInitUnicodeString(
  63. &KdcName,
  64. DcInfo->DomainControllerAddress+2
  65. );
  66. AddressType = DcInfo->DomainControllerAddressType;
  67. }
  68. return(TRUE);
  69. }
  70. BOOLEAN
  71. GetAnAsTicket(
  72. IN PUNICODE_STRING ServerName,
  73. OUT PKERB_TICKET Ticket,
  74. OUT PKERB_ENCRYPTED_KDC_REPLY * ReplyBody,
  75. OUT PKERB_KDC_REPLY * Reply
  76. )
  77. {
  78. KERBERR KerbErr = KDC_ERR_NONE;
  79. NTSTATUS Status = STATUS_SUCCESS;
  80. KERB_ENCRYPTION_KEY UserKey;
  81. KERB_MESSAGE_BUFFER InputMessage;
  82. KERB_MESSAGE_BUFFER OutputMessage;
  83. KERB_KDC_REQUEST Request;
  84. PKERB_KDC_REQUEST_BODY RequestBody;
  85. ULONG CryptArray[KERB_MAX_CRYPTO_SYSTEMS];
  86. ULONG CryptArraySize;
  87. UNICODE_STRING FullServiceName;
  88. UNICODE_STRING FullClientName;
  89. PKERB_ERROR ErrorMessage = NULL;
  90. LARGE_INTEGER TempTime;
  91. ULONG KdcFlagOptions = 0;
  92. ULONG KdcOptions = 0;
  93. BOOLEAN DoingSomething = FALSE;
  94. RtlZeroMemory(
  95. &OutputMessage,
  96. sizeof(KERB_MESSAGE_BUFFER)
  97. );
  98. RtlZeroMemory(
  99. &InputMessage,
  100. sizeof(KERB_MESSAGE_BUFFER)
  101. );
  102. //
  103. // Build the request
  104. //
  105. RtlZeroMemory(
  106. &Request,
  107. sizeof( KERB_KDC_REQUEST )
  108. );
  109. RequestBody = &Request.request_body;
  110. KdcOptions =
  111. KERB_KDC_OPTIONS_forwardable |
  112. KERB_KDC_OPTIONS_proxiable |
  113. KERB_KDC_OPTIONS_renewable |
  114. KERB_KDC_OPTIONS_renewable_ok;
  115. KdcFlagOptions = KerbConvertUlongToFlagUlong(KdcOptions);
  116. RequestBody->kdc_options.value = (PUCHAR) &KdcFlagOptions ;
  117. RequestBody->kdc_options.length = sizeof(ULONG) * 8;
  118. RequestBody->nonce = 3;
  119. TempTime.QuadPart = 0;
  120. KerbConvertLargeIntToGeneralizedTime(
  121. &RequestBody->KERB_KDC_REQUEST_BODY_starttime,
  122. NULL,
  123. &TempTime
  124. );
  125. TempTime.LowPart = 0xffffffff;
  126. TempTime.HighPart = 0x7fffffff;
  127. KerbConvertLargeIntToGeneralizedTime(
  128. &RequestBody->KERB_KDC_REQUEST_BODY_renew_until,
  129. NULL,
  130. &TempTime
  131. );
  132. RequestBody->bit_mask |= KERB_KDC_REQUEST_BODY_renew_until_present;
  133. TempTime.QuadPart = 0;
  134. KerbConvertLargeIntToGeneralizedTime(
  135. &RequestBody->endtime,
  136. NULL,
  137. &TempTime
  138. );
  139. //
  140. // Build crypt vector.
  141. //
  142. CryptArraySize = KERB_MAX_CRYPTO_SYSTEMS;
  143. CDBuildVect( &CryptArraySize, CryptArray );
  144. KerbErr = KerbConvertArrayToCryptList(
  145. &RequestBody->encryption_type,
  146. CryptArray,
  147. CryptArraySize
  148. );
  149. if (!KERB_SUCCESS(KerbErr))
  150. {
  151. printf("Failed to convert array to crypt list: 0x%x\n",KerbErr);
  152. goto Cleanup;
  153. }
  154. //
  155. // BUGBUG: don't build pre-auth data
  156. //
  157. KerbBuildFullServiceName(
  158. &ClientRealm,
  159. ServerName,
  160. &FullServiceName
  161. );
  162. KerbErr = KerbConvertStringToPrincipalName(
  163. &RequestBody->KERB_KDC_REQUEST_BODY_server_name,
  164. &FullServiceName,
  165. KRB_NT_MS_PRINCIPAL
  166. );
  167. if (!KERB_SUCCESS(KerbErr))
  168. {
  169. printf("Failed to convert string to principal name: 0x%x\n",KerbErr);
  170. goto Cleanup;
  171. }
  172. RequestBody->bit_mask |= KERB_KDC_REQUEST_BODY_server_name_present;
  173. KerbBuildFullServiceName(
  174. &ClientRealm,
  175. &ClientName,
  176. &FullClientName
  177. );
  178. KerbErr = KerbConvertStringToPrincipalName(
  179. &RequestBody->KERB_KDC_REQUEST_BODY_client_name,
  180. &FullClientName,
  181. KRB_NT_MS_PRINCIPAL
  182. );
  183. if (!KERB_SUCCESS(KerbErr))
  184. {
  185. printf("Failed to convert string to principal name: 0x%x\n",KerbErr);
  186. goto Cleanup;
  187. }
  188. RequestBody->bit_mask |= KERB_KDC_REQUEST_BODY_client_name_present;
  189. KerbErr = KerbConvertUnicodeStringToRealm(
  190. &RequestBody->realm,
  191. &ClientRealm
  192. );
  193. if (!KERB_SUCCESS(KerbErr))
  194. {
  195. printf("Failed to convert unicde string to realm: 0x%x\n",KerbErr);
  196. goto Cleanup;
  197. }
  198. Request.version = KERBEROS_VERSION;
  199. Request.message_type = KRB_AS_REQ;
  200. KerbErr = KerbPackAsRequest(
  201. &Request,
  202. &InputMessage.BufferSize,
  203. &InputMessage.Buffer
  204. );
  205. if (!KERB_SUCCESS(KerbErr))
  206. {
  207. printf("Failed to pack KDC request: 0x%x\n",KerbErr);
  208. goto Cleanup;
  209. }
  210. Status = KerbCallKdc(
  211. &KdcName,
  212. AddressType,
  213. 10,
  214. TRUE,
  215. &InputMessage,
  216. &OutputMessage
  217. );
  218. if (!NT_SUCCESS(Status))
  219. {
  220. printf("KerbCallKdc failed: 0x%x\n",Status);
  221. KerbErr = KRB_ERR_GENERIC;
  222. goto Cleanup;
  223. }
  224. KerbErr = KerbUnpackAsReply(
  225. OutputMessage.Buffer,
  226. OutputMessage.BufferSize,
  227. Reply
  228. );
  229. if (!KERB_SUCCESS(KerbErr))
  230. {
  231. printf("Failed to unpack KDC reply: 0x%x\n",KerbErr);
  232. KerbErr = KerbUnpackKerbError(
  233. OutputMessage.Buffer,
  234. OutputMessage.BufferSize,
  235. &ErrorMessage
  236. );
  237. if (KERB_SUCCESS(KerbErr))
  238. {
  239. printf("Failed to get AS ticket: 0x%x\n",ErrorMessage->error_code);
  240. KerbErr = (KERBERR) ErrorMessage->error_code;
  241. }
  242. goto Cleanup;
  243. }
  244. KerbErr = KerbHashPassword(
  245. &ClientPassword,
  246. (*Reply)->encrypted_part.encryption_type,
  247. &UserKey
  248. );
  249. if (!KERB_SUCCESS(KerbErr))
  250. {
  251. printf("Failed to hash password with 0x%x alg\n",(*Reply)->encrypted_part.encryption_type);
  252. goto Cleanup;
  253. }
  254. KerbErr = KerbUnpackKdcReplyBody(
  255. &(*Reply)->encrypted_part,
  256. &UserKey,
  257. KERB_ENCRYPTED_AS_REPLY_PDU,
  258. ReplyBody
  259. );
  260. if (!KERB_SUCCESS(KerbErr))
  261. {
  262. printf("Failed to unpack KDC reply body: 0x%x\n",KerbErr);
  263. goto Cleanup;
  264. }
  265. *Ticket = (*Reply)->ticket;
  266. Cleanup:
  267. //
  268. // BUGBUG: memory leak here
  269. //
  270. if (KERB_SUCCESS(KerbErr))
  271. {
  272. return(TRUE);
  273. }
  274. else
  275. {
  276. return(FALSE);
  277. }
  278. }
  279. BOOLEAN
  280. GetATgsTicket(
  281. IN PKERB_TICKET TicketGrantingTicket,
  282. IN PKERB_ENCRYPTED_KDC_REPLY TgtReplyBody,
  283. IN PKERB_KDC_REPLY TgtReply,
  284. IN BOOLEAN Renew,
  285. OUT PKERB_TICKET Ticket,
  286. OUT PKERB_ENCRYPTED_KDC_REPLY * ReplyBody,
  287. OUT PKERB_KDC_REPLY * Reply
  288. )
  289. {
  290. KERB_KDC_REQUEST Request;
  291. PKERB_KDC_REQUEST_BODY RequestBody = &Request.request_body;
  292. UNICODE_STRING FullServiceName;
  293. PKERB_INTERNAL_NAME FullClientName;
  294. KERBERR KerbErr;
  295. KERB_PA_DATA_LIST PaData;
  296. ULONG CryptArray[KERB_MAX_CRYPTO_SYSTEMS];
  297. ULONG CryptArraySize = 0;
  298. LARGE_INTEGER TempTime;
  299. KERB_MESSAGE_BUFFER InputMessage;
  300. KERB_MESSAGE_BUFFER OutputMessage;
  301. PKERB_ERROR ErrorMessage = NULL;
  302. ULONG NameType;
  303. ULONG KdcFlagOptions = 0;
  304. ULONG KdcOptions = 0;
  305. //
  306. // Build the request
  307. //
  308. RtlZeroMemory( &Request, sizeof( KERB_KDC_REQUEST ) );
  309. KdcOptions = KERB_KDC_OPTIONS_forwardable |
  310. KERB_KDC_OPTIONS_proxiable |
  311. KERB_KDC_OPTIONS_renewable |
  312. KERB_KDC_OPTIONS_renewable_ok;
  313. if (Renew)
  314. {
  315. KdcOptions |= KERB_KDC_OPTIONS_renew;
  316. }
  317. KdcFlagOptions = KerbConvertUlongToFlagUlong(KdcOptions);
  318. RequestBody->kdc_options.value = (PUCHAR) &KdcFlagOptions ;
  319. RequestBody->kdc_options.length = sizeof(ULONG) * 8;
  320. RequestBody->nonce = 4;
  321. //
  322. // Build an AP request inside an encrypted data structure.
  323. //
  324. KerbConvertPrincipalNameToKdcName(
  325. &FullClientName,
  326. &TgtReply->client_name
  327. );
  328. PaData.next = NULL;
  329. PaData.value.preauth_data_type = KRB5_PADATA_TGS_REQ;
  330. KerbErr = KerbCreateApRequest(
  331. FullClientName,
  332. &ClientRealm,
  333. &TgtReplyBody->session_key,
  334. NULL, // no sub session key
  335. 5, // nonce
  336. TicketGrantingTicket,
  337. 0, // AP options
  338. NULL, // gss checksum
  339. NULL, // server time
  340. TRUE, // KDC request
  341. (PULONG) &PaData.value.preauth_data.length,
  342. &PaData.value.preauth_data.value
  343. );
  344. if (!KERB_SUCCESS(KerbErr))
  345. {
  346. printf("Failed to create AP request: 0x%x\n",KerbErr);
  347. goto Cleanup;
  348. }
  349. Request.KERB_KDC_REQUEST_preauth_data = &PaData;
  350. Request.bit_mask |= KERB_KDC_REQUEST_preauth_data_present;
  351. //
  352. // Build crypt vector.
  353. //
  354. CDBuildVect( &CryptArraySize, CryptArray );
  355. KerbErr = KerbConvertArrayToCryptList(
  356. &RequestBody->encryption_type,
  357. CryptArray,
  358. CryptArraySize
  359. );
  360. if (!KERB_SUCCESS(KerbErr))
  361. {
  362. printf("Failed to convert array to crypt list: 0x%x\n",KerbErr);
  363. goto Cleanup;
  364. }
  365. KerbErr = KerbDuplicatePrincipalName(
  366. &RequestBody->KERB_KDC_REQUEST_BODY_client_name,
  367. &TgtReply->client_name
  368. );
  369. if (!KERB_SUCCESS(KerbErr))
  370. {
  371. goto Cleanup;
  372. }
  373. RequestBody->bit_mask |= KERB_KDC_REQUEST_BODY_client_name_present;
  374. KerbErr = KerbConvertUnicodeStringToRealm(
  375. &RequestBody->realm,
  376. &ClientRealm
  377. );
  378. if (!KERB_SUCCESS(KerbErr))
  379. {
  380. goto Cleanup;
  381. }
  382. KerbErr = KerbConvertStringToPrincipalName(
  383. &RequestBody->KERB_KDC_REQUEST_BODY_server_name,
  384. &ServiceName,
  385. KRB_NT_MS_PRINCIPAL
  386. );
  387. if (!KERB_SUCCESS(KerbErr))
  388. {
  389. goto Cleanup;
  390. }
  391. RequestBody->bit_mask |= KERB_KDC_REQUEST_BODY_server_name_present;
  392. TempTime.QuadPart = 0;
  393. KerbConvertLargeIntToGeneralizedTime(
  394. &RequestBody->KERB_KDC_REQUEST_BODY_starttime,
  395. NULL,
  396. &TempTime
  397. );
  398. TempTime.LowPart = 0xffffffff;
  399. TempTime.HighPart = 0x7fffffff;
  400. KerbConvertLargeIntToGeneralizedTime(
  401. &RequestBody->KERB_KDC_REQUEST_BODY_renew_until,
  402. NULL,
  403. &TempTime
  404. );
  405. RequestBody->bit_mask |= KERB_KDC_REQUEST_BODY_renew_until_present;
  406. TempTime.LowPart = 0xffffffff;
  407. TempTime.HighPart = 0x7fffffff;
  408. KerbConvertLargeIntToGeneralizedTime(
  409. &RequestBody->endtime,
  410. NULL,
  411. &TempTime
  412. );
  413. Request.version = KERBEROS_VERSION;
  414. Request.message_type = KRB_TGS_REQ;
  415. KerbErr = KerbPackTgsRequest(
  416. &Request,
  417. &InputMessage.BufferSize,
  418. &InputMessage.Buffer
  419. );
  420. if (!KERB_SUCCESS(KerbErr))
  421. {
  422. printf("Failed to pack KDC request: 0x%x\n",KerbErr);
  423. goto Cleanup;
  424. }
  425. //
  426. // Get the ticket.
  427. //
  428. OutputMessage.Buffer = NULL;
  429. OutputMessage.BufferSize = 0;
  430. KerbErr = (KERBERR) KerbCallKdc(
  431. &KdcName,
  432. AddressType,
  433. 10,
  434. TRUE,
  435. &InputMessage,
  436. &OutputMessage
  437. );
  438. if (!KERB_SUCCESS(KerbErr))
  439. {
  440. printf("KerbCallKdc failed: 0x%x\n",KerbErr);
  441. goto Cleanup;
  442. }
  443. KerbErr = KerbUnpackTgsReply(
  444. OutputMessage.Buffer,
  445. OutputMessage.BufferSize,
  446. Reply
  447. );
  448. if (!KERB_SUCCESS(KerbErr))
  449. {
  450. printf("Failed to unpack KDC reply: 0x%x\n",KerbErr);
  451. KerbErr = KerbUnpackKerbError(
  452. OutputMessage.Buffer,
  453. OutputMessage.BufferSize,
  454. &ErrorMessage
  455. );
  456. if (KERB_SUCCESS(KerbErr))
  457. {
  458. printf("Failed to get TGS ticket: 0x%x\n",ErrorMessage->error_code);
  459. KerbErr = (KERBERR) ErrorMessage->error_code;
  460. }
  461. goto Cleanup;
  462. }
  463. KerbErr = KerbUnpackKdcReplyBody(
  464. &(*Reply)->encrypted_part,
  465. &TgtReplyBody->session_key,
  466. KERB_ENCRYPTED_TGS_REPLY_PDU,
  467. ReplyBody
  468. );
  469. if (!KERB_SUCCESS(KerbErr))
  470. {
  471. printf("Failed to unpack KDC reply body: 0x%x\n",KerbErr);
  472. goto Cleanup;
  473. }
  474. *Ticket = (*Reply)->ticket;
  475. Cleanup:
  476. //
  477. // BUGBUG: memory leak here
  478. //
  479. if (KERB_SUCCESS(KerbErr))
  480. {
  481. return(TRUE);
  482. }
  483. else
  484. {
  485. return(FALSE);
  486. }
  487. }
  488. BOOLEAN
  489. UStringFromAnsi(
  490. OUT PUNICODE_STRING UnicodeString,
  491. IN LPSTR String
  492. )
  493. {
  494. STRING AnsiString;
  495. RtlInitString(
  496. &AnsiString,
  497. String
  498. );
  499. if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(
  500. UnicodeString,
  501. &AnsiString,
  502. TRUE
  503. )))
  504. {
  505. return(FALSE);
  506. }
  507. else
  508. {
  509. return(TRUE);
  510. }
  511. }
  512. void
  513. SetDefaultOpts()
  514. {
  515. UNICODE_STRING TempString;
  516. STRING AnsiString;
  517. LPSTR String;
  518. KerbInitializeSockets(0x0101,5);
  519. //
  520. // Username
  521. //
  522. String = getenv( "USERNAME" );
  523. if (String == NULL)
  524. {
  525. String = "mikesw";
  526. }
  527. UStringFromAnsi(
  528. &ClientName,
  529. String
  530. );
  531. String = getenv( "USERDOMAIN" );
  532. if (String == NULL)
  533. {
  534. String = "NTDS";
  535. }
  536. UStringFromAnsi(
  537. &ClientRealm,
  538. String
  539. );
  540. UStringFromAnsi(
  541. &ServiceRealm,
  542. String
  543. );
  544. }
  545. VOID
  546. SetPassword(
  547. IN PUNICODE_STRING UserName,
  548. IN PUNICODE_STRING PrincipalName,
  549. IN PUNICODE_STRING Password,
  550. IN BOOLEAN UnixOnly
  551. )
  552. {
  553. NTSTATUS Status;
  554. DWORD sc;
  555. LPTSTR pszBinding;
  556. RPC_IF_HANDLE ifh = KdcDebug_ClientIfHandle;
  557. handle_t hBinding;
  558. sc = RpcStringBindingCompose(0, L"ncalrpc",L"",NULL,
  559. 0, &pszBinding);
  560. if (sc) {
  561. printf("error:rpcstringbindingcompose\n" );
  562. return;
  563. }
  564. sc = RpcBindingFromStringBinding(pszBinding, &hBinding);
  565. (void) RpcStringFree(&pszBinding);
  566. if (sc) {
  567. printf("error:rpcbindingfromstringbinding\n" );
  568. return;
  569. }
  570. sc = RpcEpResolveBinding(hBinding, ifh);
  571. if (sc) {
  572. printf("error:rpcepresolvebinding\n" );
  573. return;
  574. }
  575. Status = KDC_SetPassword(
  576. hBinding,
  577. UserName,
  578. PrincipalName,
  579. Password,
  580. UnixOnly ? KERB_PRIMARY_CRED_RFC1510_ONLY : 0
  581. );
  582. RpcBindingFree(&hBinding);
  583. printf("SetPassword returned 0x%x\n",Status);
  584. }
  585. BOOLEAN
  586. BindToKdcRpc(
  587. handle_t * hBinding
  588. )
  589. {
  590. DWORD sc;
  591. LPTSTR pszBinding;
  592. RPC_IF_HANDLE ifh = KdcDebug_ClientIfHandle;
  593. if (KdcName.Buffer == NULL)
  594. {
  595. sc = RpcStringBindingCompose(0, L"ncalrpc",L"",NULL,
  596. 0, &pszBinding);
  597. }
  598. else
  599. {
  600. sc = RpcStringBindingCompose(0, L"ncacn_ip_tcp",KdcNameString,NULL,
  601. 0, &pszBinding);
  602. }
  603. if (sc) {
  604. printf("error:rpcstringbindingcompose\n" );
  605. return FALSE;
  606. }
  607. sc = RpcBindingFromStringBinding(pszBinding, hBinding);
  608. (void) RpcStringFree(&pszBinding);
  609. if (sc) {
  610. printf("error:rpcbindingfromstringbinding\n" );
  611. return FALSE;
  612. }
  613. sc = RpcEpResolveBinding(*hBinding, ifh);
  614. if (sc) {
  615. printf("error:rpcepresolvebinding\n" );
  616. return FALSE;
  617. }
  618. return TRUE;
  619. }
  620. VOID
  621. DumpKdc(
  622. VOID
  623. )
  624. {
  625. NTSTATUS Status;
  626. DWORD sc;
  627. LPTSTR pszBinding;
  628. RPC_IF_HANDLE ifh = KdcDebug_ClientIfHandle;
  629. handle_t hBinding;
  630. sc = RpcStringBindingCompose(0, L"ncalrpc",L"",NULL,
  631. 0, &pszBinding);
  632. if (sc) {
  633. printf("error:rpcstringbindingcompose\n" );
  634. return;
  635. }
  636. sc = RpcBindingFromStringBinding(pszBinding, &hBinding);
  637. (void) RpcStringFree(&pszBinding);
  638. if (sc) {
  639. printf("error:rpcbindingfromstringbinding\n" );
  640. return;
  641. }
  642. sc = RpcEpResolveBinding(hBinding, ifh);
  643. if (sc) {
  644. printf("error:rpcepresolvebinding\n" );
  645. return;
  646. }
  647. Status = KDC_Dump(
  648. hBinding
  649. );
  650. RpcBindingFree(&hBinding);
  651. }
  652. VOID
  653. DumpKdcDomains( VOID )
  654. {
  655. NTSTATUS Status;
  656. PKDC_DBG_DOMAIN_LIST DomainList = NULL;
  657. ULONG Index;
  658. handle_t hBinding = NULL;
  659. if (!BindToKdcRpc(&hBinding))
  660. {
  661. printf("Failed to bind to kdc\n");
  662. return;
  663. }
  664. Status = KDC_GetDomainList(
  665. hBinding,
  666. &DomainList
  667. );
  668. if (!NT_SUCCESS(Status))
  669. {
  670. printf("Failed toget domain list: 0x%x\n",Status);
  671. }
  672. else
  673. {
  674. for (Index = 0; Index < DomainList->Count ; Index++ )
  675. {
  676. printf("Domain %d:\n",Index);
  677. printf("\tDnsName = %wZ\n",&DomainList->Domains[Index].DnsName);
  678. printf("\tNetbiosName = %wZ\n",&DomainList->Domains[Index].NetbiosName);
  679. printf("\tClosestRoute = %wZ\n",&DomainList->Domains[Index].ClosestRoute);
  680. printf("\tType = 0x%x, Attributes = 0x%x\n",DomainList->Domains[Index].Type, DomainList->Domains[Index].Attributes);
  681. }
  682. }
  683. }
  684. VOID
  685. KdcNormalize(
  686. ULONG Flags,
  687. PKERB_DBG_INTERNAL_NAME Name
  688. )
  689. {
  690. NTSTATUS Status;
  691. PKDC_DBG_DOMAIN_LIST DomainList = NULL;
  692. ULONG Index;
  693. handle_t hBinding = NULL;
  694. if (!BindToKdcRpc(&hBinding))
  695. {
  696. printf("Failed to bind to kdc\n");
  697. return;
  698. }
  699. Status = KDC_Normalize(
  700. hBinding,
  701. Name,
  702. Flags
  703. );
  704. if (!NT_SUCCESS(Status))
  705. {
  706. printf("Failed toget domain list: 0x%x\n",Status);
  707. }
  708. else
  709. {
  710. printf("Success\n");
  711. }
  712. }
  713. VOID
  714. KdcSetState(
  715. ULONG Lifetime,
  716. ULONG RenewTime
  717. )
  718. {
  719. NTSTATUS Status;
  720. LARGE_INTEGER FudgeFactor = {0};
  721. handle_t hBinding = NULL;
  722. if (!BindToKdcRpc(&hBinding))
  723. {
  724. printf("Failed to bind to kdc\n");
  725. return;
  726. }
  727. Status = KDC_SetState(
  728. hBinding,
  729. 0, // no flags
  730. Lifetime,
  731. RenewTime,
  732. FudgeFactor
  733. );
  734. if (!NT_SUCCESS(Status))
  735. {
  736. printf("Failed to set kdc options: 0x%x\n",Status);
  737. }
  738. else
  739. {
  740. printf("Success\n");
  741. }
  742. }
  743. void
  744. Usage(char * Name)
  745. {
  746. printf("%s\n",Name);
  747. printf("-cname, -sname : set client & service names\n");
  748. printf("-crealm, -srealm : set client & service realms\n");
  749. printf("-cpass, -spass : set client & service passwords\n");
  750. printf("-crypt : set encryption type\n");
  751. printf("-gettgt : get a TGT in client's realm, incompat. with -getas\n");
  752. printf("-getas : get an AS ticket to a service, incompat. with -gettgt\n");
  753. printf("-gettgs : get a TGS ticket to a service, requires a TGT\n");
  754. printf("-renew : renew last ticket acquired\n");
  755. printf("-dump : dump kdc heap trace\n");
  756. printf("-kdc : set kdc name\n");
  757. printf("-norm 0xFlags type name1 name2 name3 ... : normalize a name\n");
  758. printf("-domains : dump domain list\n");
  759. printf("-setstate lifespan renewspan : set ticket lifetime\n");
  760. printf("\n");
  761. printf("-setpass username principalname password : sets KRB5 password\n");
  762. }
  763. void
  764. __cdecl main(int argc, char *argv[])
  765. {
  766. int Index;
  767. BOOLEAN GetAsTicket = FALSE;
  768. BOOLEAN GetTgsTicket = FALSE;
  769. BOOLEAN GetTgt = FALSE;
  770. BOOLEAN RenewTicket = FALSE;
  771. BOOLEAN SetPass = FALSE;
  772. BOOLEAN Dump = FALSE;
  773. BOOLEAN Normalize= FALSE;
  774. BOOLEAN DumpDomains = FALSE;
  775. BOOLEAN SetState = FALSE;
  776. ULONG Lifespan = 0;
  777. ULONG RenewSpan = 0;
  778. UNICODE_STRING UserName;
  779. UNICODE_STRING PrincipalName;
  780. UNICODE_STRING Password;
  781. STRING AnsiString;
  782. UNICODE_STRING AsServerName;
  783. PKERB_ENCRYPTED_KDC_REPLY AsReplyBody = NULL;
  784. PKERB_KDC_REPLY AsReply = NULL;
  785. KERB_TICKET AsTicket;
  786. PKERB_ENCRYPTED_KDC_REPLY TgsReplyBody = NULL;
  787. PKERB_KDC_REPLY TgsReply = NULL;
  788. KERB_TICKET TgsTicket;
  789. BOOLEAN UnixOnly = FALSE;
  790. KERB_DBG_INTERNAL_NAME Name = {0};
  791. ULONG Flags;
  792. UNICODE_STRING NameParts[20];
  793. WCHAR NameBuffers[20][100];
  794. ULONG Index2;
  795. SetDefaultOpts();
  796. for (Index = 1; Index < argc ; Index++ )
  797. {
  798. //
  799. // First the principal name features
  800. //
  801. if (!_stricmp(argv[Index],"-crealm"))
  802. {
  803. if (Index+1 == argc)
  804. {
  805. goto Usage;
  806. }
  807. UStringFromAnsi(
  808. &ClientRealm,
  809. argv[++Index]
  810. );
  811. } else
  812. if (!_stricmp(argv[Index],"-srealm"))
  813. {
  814. if (Index+1 == argc)
  815. {
  816. goto Usage;
  817. }
  818. UStringFromAnsi(
  819. &ServiceRealm,
  820. argv[++Index]
  821. );
  822. } else
  823. if (!_stricmp(argv[Index],"-cname"))
  824. {
  825. if (Index+1 == argc)
  826. {
  827. goto Usage;
  828. }
  829. UStringFromAnsi(
  830. &ClientName,
  831. argv[++Index]
  832. );
  833. } else
  834. if (!_stricmp(argv[Index],"-sname"))
  835. {
  836. if (Index+1 == argc)
  837. {
  838. goto Usage;
  839. }
  840. UStringFromAnsi(
  841. &ServiceName,
  842. argv[++Index]
  843. );
  844. } else
  845. if (!_stricmp(argv[Index],"-cpass"))
  846. {
  847. if (Index+1 == argc)
  848. {
  849. goto Usage;
  850. }
  851. UStringFromAnsi(
  852. &ClientPassword,
  853. argv[++Index]
  854. );
  855. } else
  856. if (!_stricmp(argv[Index],"-spass"))
  857. {
  858. if (Index+1 == argc)
  859. {
  860. goto Usage;
  861. }
  862. UStringFromAnsi(
  863. &ServicePassword,
  864. argv[++Index]
  865. );
  866. } else
  867. if (!_stricmp(argv[Index],"-crypt"))
  868. {
  869. if (Index+1 == argc)
  870. {
  871. goto Usage;
  872. }
  873. sscanf(argv[++Index],"%d",&CryptType);
  874. } else
  875. if (!_stricmp(argv[Index],"-gettgt"))
  876. {
  877. GetTgt = TRUE;
  878. } else
  879. if (!_stricmp(argv[Index],"-getas"))
  880. {
  881. GetAsTicket = TRUE;
  882. } else
  883. if (!_stricmp(argv[Index],"-gettgs"))
  884. {
  885. GetTgsTicket = TRUE;
  886. } else
  887. if (!_stricmp(argv[Index],"-renew"))
  888. {
  889. RenewTicket = TRUE;
  890. }
  891. else if (!_stricmp(argv[Index],"-setpass"))
  892. {
  893. if (Index+4 > argc)
  894. {
  895. printf("Not enough args: %d instead of %d\n", argc, Index+3);
  896. goto Usage;
  897. }
  898. SetPass = TRUE;
  899. UStringFromAnsi(
  900. &UserName,
  901. argv[++Index]
  902. );
  903. UStringFromAnsi(
  904. &PrincipalName,
  905. argv[++Index]
  906. );
  907. UStringFromAnsi(
  908. &Password,
  909. argv[++Index]
  910. );
  911. }
  912. else if (!_stricmp(argv[Index],"-dump"))
  913. {
  914. Dump = TRUE;
  915. }
  916. else if (!_stricmp(argv[Index],"-unix"))
  917. {
  918. UnixOnly = TRUE;
  919. }
  920. else if (!_stricmp(argv[Index],"-kdc"))
  921. {
  922. if (Index+2 > argc)
  923. {
  924. goto Usage;
  925. }
  926. mbstowcs(KdcNameString,argv[++Index],100);
  927. RtlInitUnicodeString(
  928. &KdcName,
  929. KdcNameString
  930. );
  931. }
  932. else if (!_stricmp(argv[Index],"-norm"))
  933. {
  934. Normalize = TRUE;
  935. if (Index+4 > argc)
  936. {
  937. goto Usage;
  938. }
  939. sscanf(argv[++Index],"0x%x",&Flags);
  940. sscanf(argv[++Index],"%d",&Name.NameType);
  941. Name.NameCount = 0;
  942. Name.References = 0;
  943. Name.Names = NameParts;
  944. Index2 = 0;
  945. while (Index < argc-1)
  946. {
  947. mbstowcs(NameBuffers[Index2],argv[++Index],100);
  948. RtlInitUnicodeString(
  949. &NameParts[Index2],
  950. NameBuffers[Index2]
  951. );
  952. Index2++;
  953. Name.NameCount++;
  954. }
  955. }
  956. else if (!_stricmp(argv[Index],"-domains"))
  957. {
  958. DumpDomains = TRUE;
  959. }
  960. else if (!_stricmp(argv[Index],"-setstate"))
  961. {
  962. if (Index+3 > argc)
  963. {
  964. goto Usage;
  965. }
  966. sscanf(argv[++Index],"%d",&Lifespan);
  967. sscanf(argv[++Index],"%d",&RenewSpan);
  968. SetState = TRUE;
  969. }
  970. else {
  971. goto Usage;
  972. }
  973. }
  974. if (GetTgsTicket && !GetTgt)
  975. {
  976. printf("ERROR: Can't get a TGS ticket without a TGT\n");
  977. goto Usage;
  978. }
  979. if (GetAsTicket && GetTgt)
  980. {
  981. printf("ERROR: Can't get both an AS ticket and a TGT\n");
  982. goto Usage;
  983. }
  984. if (SetPass)
  985. {
  986. SetPassword( &UserName, &PrincipalName, &Password, UnixOnly );
  987. goto Cleanup;
  988. }
  989. if (Dump)
  990. {
  991. DumpKdc();
  992. goto Cleanup;
  993. }
  994. if (DumpDomains)
  995. {
  996. DumpKdcDomains();
  997. goto Cleanup;
  998. }
  999. if (SetState)
  1000. {
  1001. KdcSetState(
  1002. Lifespan,
  1003. RenewSpan
  1004. );
  1005. goto Cleanup;
  1006. }
  1007. if (Normalize)
  1008. {
  1009. KdcNormalize(
  1010. Flags,
  1011. &Name
  1012. );
  1013. goto Cleanup;
  1014. }
  1015. //
  1016. // Bind to the KDC
  1017. //
  1018. if (!BindToKdc())
  1019. {
  1020. printf("ERROR: Failed to bind to KDC\n");
  1021. goto Cleanup;
  1022. }
  1023. //
  1024. // Now try to get the AS ticket
  1025. //
  1026. if (GetAsTicket)
  1027. {
  1028. AsServerName = ServiceName;
  1029. }
  1030. else if (GetTgt)
  1031. {
  1032. RtlInitUnicodeString(
  1033. &AsServerName,
  1034. KDC_PRINCIPAL_NAME
  1035. );
  1036. }
  1037. if (!GetAnAsTicket(
  1038. &AsServerName,
  1039. &AsTicket,
  1040. &AsReplyBody,
  1041. &AsReply
  1042. ))
  1043. {
  1044. printf("ERROR: Failed to get AS ticket\n");
  1045. goto Cleanup;
  1046. }
  1047. else
  1048. {
  1049. printf("SUCCESS: got an AS ticket\n");
  1050. }
  1051. if (GetTgsTicket)
  1052. {
  1053. if (!GetATgsTicket(
  1054. &AsTicket,
  1055. AsReplyBody,
  1056. AsReply,
  1057. FALSE, // don't renew
  1058. &TgsTicket,
  1059. &TgsReplyBody,
  1060. &TgsReply))
  1061. {
  1062. printf("ERROR: Failed to get TGS ticket\n");
  1063. goto Cleanup;
  1064. }
  1065. else
  1066. {
  1067. printf("SUCCESS: got a TGS ticket\n");
  1068. }
  1069. }
  1070. if (Dump)
  1071. {
  1072. DumpKdc();
  1073. }
  1074. goto Cleanup;
  1075. Usage:
  1076. Usage(argv[0]);
  1077. Cleanup:
  1078. KerbCleanupTickets();
  1079. return;
  1080. }
  1081. void *
  1082. MIDL_user_allocate( size_t cb )
  1083. {
  1084. return LocalAlloc( 0, ROUND_UP_COUNT(cb,8) );
  1085. }
  1086. void
  1087. MIDL_user_free( void * pv )
  1088. {
  1089. LocalFree( pv );
  1090. }