main.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * Copyright 2023 Maxim Karasev <mxkrsv@etersoft.ru>
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  17. */
  18. #define WIN32_LEAN_AND_MEAN
  19. #include <ntstatus.h>
  20. #define WIN32_NO_STATUS
  21. #include <windows.h>
  22. #include <ntsecapi.h>
  23. #include "wine/debug.h"
  24. #include "resources.h"
  25. WINE_DEFAULT_DEBUG_CHANNEL(klist);
  26. static WCHAR msg_buf[1024];
  27. static const WCHAR *load_resource(UINT id)
  28. {
  29. LoadStringW(GetModuleHandleW(NULL), id, msg_buf, ARRAY_SIZE(msg_buf));
  30. return msg_buf;
  31. }
  32. static const WCHAR *get_etype_text(LONG encryption_type)
  33. {
  34. switch (encryption_type)
  35. {
  36. case KERB_ETYPE_NULL: return L"NULL";
  37. case KERB_ETYPE_DES_CBC_CRC: return L"DES-CBC-CRC";
  38. case KERB_ETYPE_DES_CBC_MD4: return L"DES-CBC-MD4";
  39. case KERB_ETYPE_DES_CBC_MD5: return L"DES-CBC-MD5";
  40. case KERB_ETYPE_AES128_CTS_HMAC_SHA1_96: return L"AES-128-CTS-HMAC-SHA1-96";
  41. case KERB_ETYPE_AES256_CTS_HMAC_SHA1_96: return L"AES-256-CTS-HMAC-SHA1-96";
  42. case KERB_ETYPE_RC4_MD4: return L"RC4-MD4";
  43. case KERB_ETYPE_RC4_PLAIN2: return L"RC4-PLAIN2";
  44. case KERB_ETYPE_RC4_LM: return L"RC4-LM";
  45. case KERB_ETYPE_RC4_SHA: return L"RC4-SHA";
  46. case KERB_ETYPE_DES_PLAIN: return L"DES-PLAIN";
  47. case KERB_ETYPE_RC4_HMAC_OLD: return L"RC4-HMAC-OLD";
  48. case KERB_ETYPE_RC4_PLAIN_OLD: return L"RC4-PLAIN-OLD";
  49. case KERB_ETYPE_RC4_HMAC_OLD_EXP: return L"RC4-HMAC-OLD-EXP";
  50. case KERB_ETYPE_RC4_PLAIN_OLD_EXP: return L"RC4-PLAIN-OLD-EXP";
  51. case KERB_ETYPE_RC4_PLAIN: return L"RC4-PLAIN";
  52. case KERB_ETYPE_RC4_PLAIN_EXP: return L"RC4-PLAIN-EXP";
  53. case KERB_ETYPE_AES128_CTS_HMAC_SHA1_96_PLAIN: return L"AES-128-CTS-HMAC-SHA1-96-PLAIN";
  54. case KERB_ETYPE_AES256_CTS_HMAC_SHA1_96_PLAIN: return L"AES-256-CTS-HMAC-SHA1-96-PLAIN";
  55. case KERB_ETYPE_DSA_SHA1_CMS: return L"DSA-SHA1-CMS";
  56. case KERB_ETYPE_RSA_MD5_CMS: return L"RSA-MD5-CMS";
  57. case KERB_ETYPE_RSA_SHA1_CMS: return L"RSA-SHA1-CMS";
  58. case KERB_ETYPE_RC2_CBC_ENV: return L"RC2-CBC-ENV";
  59. case KERB_ETYPE_RSA_ENV: return L"RSA-ENV";
  60. case KERB_ETYPE_RSA_ES_OEAP_ENV: return L"RSA-ES-OEAP-ENV";
  61. case KERB_ETYPE_DES_EDE3_CBC_ENV: return L"DES-EDE3-CBC-ENV";
  62. case KERB_ETYPE_DSA_SIGN: return L"DSA-SIGN";
  63. case KERB_ETYPE_DES3_CBC_MD5: return L"DES3-CBC-MD5";
  64. case KERB_ETYPE_DES3_CBC_SHA1: return L"DES3-CBC-SHA1";
  65. case KERB_ETYPE_DES3_CBC_SHA1_KD: return L"DES3-CBC-SHA1-KD";
  66. case KERB_ETYPE_DES_CBC_MD5_NT: return L"DES-CBC-MD5-NT";
  67. case KERB_ETYPE_RC4_HMAC_NT: return L"RC4-HMAC-NT";
  68. case KERB_ETYPE_RC4_HMAC_NT_EXP: return L"RC4-HMAC-NT-EXP";
  69. default: return L"unknown";
  70. }
  71. }
  72. static BOOL get_process_logon_id(LUID *logon_id)
  73. {
  74. HANDLE token_handle;
  75. TOKEN_STATISTICS token_statistics;
  76. DWORD token_statistics_len;
  77. BOOL err;
  78. err = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token_handle);
  79. if (!err)
  80. {
  81. ERR("OpenProcessToken failed\n");
  82. return FALSE;
  83. }
  84. err = GetTokenInformation(token_handle, TokenStatistics, &token_statistics,
  85. sizeof(token_statistics), &token_statistics_len);
  86. if (!err)
  87. {
  88. ERR("GetTokenInformation failed\n");
  89. return FALSE;
  90. }
  91. *logon_id = token_statistics.AuthenticationId;
  92. return TRUE;
  93. }
  94. static void format_dates_and_times(const FILETIME *const filetimes[],
  95. const WCHAR *output_strings[], ULONG count)
  96. {
  97. ULONG i;
  98. for (i = 0; i < count; i++)
  99. {
  100. SYSTEMTIME system_time;
  101. int date_len;
  102. int time_len;
  103. WCHAR *date;
  104. FileTimeToSystemTime(filetimes[i], &system_time);
  105. SystemTimeToTzSpecificLocalTime(NULL, &system_time, &system_time);
  106. date_len = GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_SHORTDATE, &system_time, NULL, NULL, 0, NULL);
  107. time_len = GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &system_time, NULL, NULL, 0);
  108. date = malloc((date_len + time_len) * sizeof(date[0]));
  109. GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_SHORTDATE, &system_time, NULL, date, date_len, NULL);
  110. wcscat(date, L" ");
  111. GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &system_time, NULL, date + wcslen(date), time_len);
  112. output_strings[i] = date;
  113. }
  114. }
  115. static int tickets(void)
  116. {
  117. LUID logon_id;
  118. BOOL status;
  119. HANDLE lsa_handle;
  120. NTSTATUS err;
  121. ULONG i;
  122. LSA_STRING package_name = {
  123. .Buffer = (char*)MICROSOFT_KERBEROS_NAME_A,
  124. .Length = strlen(MICROSOFT_KERBEROS_NAME_A),
  125. .MaximumLength = strlen(MICROSOFT_KERBEROS_NAME_A),
  126. };
  127. ULONG kerberos_package;
  128. KERB_QUERY_TKT_CACHE_REQUEST kerberos_cache_request = {
  129. .MessageType = KerbQueryTicketCacheExMessage,
  130. .LogonId = {0},
  131. };
  132. KERB_QUERY_TKT_CACHE_EX_RESPONSE *kerberos_cache;
  133. ULONG kerberos_cache_size;
  134. NTSTATUS kerberos_call_status;
  135. status = get_process_logon_id(&logon_id);
  136. if (!status)
  137. {
  138. wprintf(load_resource(STRING_UNKNOWN_ERROR));
  139. return 1;
  140. }
  141. err = LsaConnectUntrusted(&lsa_handle);
  142. if (err != STATUS_SUCCESS)
  143. {
  144. wprintf(load_resource(STRING_UNKNOWN_ERROR));
  145. ERR("LsaConnectUntrusted NTSTATUS %lX\n", err);
  146. return 1;
  147. }
  148. err = LsaLookupAuthenticationPackage(lsa_handle, &package_name, &kerberos_package);
  149. if (err != STATUS_SUCCESS)
  150. {
  151. wprintf(load_resource(STRING_UNKNOWN_ERROR));
  152. ERR("LsaLookupAuthenticationPackage NTSTATUS %lX\n", err);
  153. return 1;
  154. }
  155. TRACE("Kerberos LSA package: %lu\n", kerberos_package);
  156. err = LsaCallAuthenticationPackage(lsa_handle, kerberos_package, &kerberos_cache_request,
  157. sizeof(kerberos_cache_request), (PVOID*)&kerberos_cache, &kerberos_cache_size,
  158. &kerberos_call_status);
  159. if (err != STATUS_SUCCESS)
  160. {
  161. wprintf(load_resource(STRING_UNKNOWN_ERROR));
  162. ERR("LsaCallAuthenticationPackage NTSTATUS %lX\n", err);
  163. return 1;
  164. }
  165. wprintf(L"\n");
  166. wprintf(L"%ls %ld:0x%lx\n", load_resource(STRING_LOGON_ID), logon_id.HighPart, logon_id.LowPart);
  167. wprintf(L"\n");
  168. wprintf(L"%ls: (%d)\n", load_resource(STRING_CACHED_TICKETS), kerberos_cache->CountOfTickets);
  169. for (i = 0; i < kerberos_cache->CountOfTickets; i++)
  170. {
  171. KERB_TICKET_CACHE_INFO_EX ticket = kerberos_cache->Tickets[i];
  172. const FILETIME *const filetimes[] = { (FILETIME*)&ticket.StartTime,
  173. (FILETIME*)&ticket.EndTime, (FILETIME*)&ticket.RenewTime };
  174. const WCHAR *dates[3];
  175. format_dates_and_times(filetimes, dates, 3);
  176. wprintf(L"\n");
  177. wprintf(L"#%ld>", i);
  178. wprintf(L" %ls: %.*ls @ %.*ls\n", load_resource(STRING_CLIENT),
  179. ticket.ClientName.Length / sizeof(WCHAR), ticket.ClientName.Buffer,
  180. ticket.ClientRealm.Length / sizeof(WCHAR), ticket.ClientRealm.Buffer);
  181. wprintf(L" %ls: %.*ls @ %.*ls\n", load_resource(STRING_SERVER),
  182. ticket.ServerName.Length / sizeof(WCHAR), ticket.ServerName.Buffer,
  183. ticket.ServerRealm.Length / sizeof(WCHAR), ticket.ServerRealm.Buffer);
  184. wprintf(L" %ls: ", load_resource(STRING_ENCRYPTION_TYPE));
  185. wprintf(L"%s\n", get_etype_text(ticket.EncryptionType));
  186. wprintf(L" %ls: 0x%lx ->", load_resource(STRING_TICKET_FLAGS), ticket.TicketFlags);
  187. #define EXPAND_TICKET_FLAG(x) if (ticket.TicketFlags & KERB_TICKET_FLAGS_##x) wprintf(L" %ls", L ## #x)
  188. EXPAND_TICKET_FLAG(forwardable);
  189. EXPAND_TICKET_FLAG(forwarded);
  190. EXPAND_TICKET_FLAG(proxiable);
  191. EXPAND_TICKET_FLAG(proxy);
  192. EXPAND_TICKET_FLAG(may_postdate);
  193. EXPAND_TICKET_FLAG(postdated);
  194. EXPAND_TICKET_FLAG(invalid);
  195. EXPAND_TICKET_FLAG(renewable);
  196. EXPAND_TICKET_FLAG(initial);
  197. EXPAND_TICKET_FLAG(pre_authent);
  198. EXPAND_TICKET_FLAG(hw_authent);
  199. EXPAND_TICKET_FLAG(ok_as_delegate);
  200. EXPAND_TICKET_FLAG(name_canonicalize);
  201. EXPAND_TICKET_FLAG(cname_in_pa_data);
  202. #undef EXPAND_TICKET_FLAG
  203. wprintf(L"\n");
  204. wprintf(L" %ls: %ls (local)\n", load_resource(STRING_START_TIME), dates[0]);
  205. wprintf(L" %ls: %ls (local)\n", load_resource(STRING_END_TIME), dates[1]);
  206. wprintf(L" %ls: %ls (local)\n", load_resource(STRING_RENEW_TIME), dates[2]);
  207. }
  208. LsaFreeReturnBuffer(kerberos_cache);
  209. LsaDeregisterLogonProcess(lsa_handle);
  210. return 0;
  211. }
  212. static int tgt(void)
  213. {
  214. FIXME("stub\n");
  215. return 0;
  216. }
  217. static int purge(void)
  218. {
  219. FIXME("stub\n");
  220. return 0;
  221. }
  222. static int get(const WCHAR *principal)
  223. {
  224. FIXME("stub\n");
  225. return 0;
  226. }
  227. int __cdecl wmain(int argc, WCHAR *argv[])
  228. {
  229. if (argc < 2)
  230. {
  231. return tickets();
  232. }
  233. if (!wcscmp(argv[1], L"tickets"))
  234. {
  235. return tickets();
  236. }
  237. else if (!wcscmp(argv[1], L"tgt"))
  238. {
  239. return tgt();
  240. }
  241. else if (!wcscmp(argv[1], L"purge"))
  242. {
  243. return purge();
  244. }
  245. else if (!wcscmp(argv[1], L"get"))
  246. {
  247. if (argc < 3)
  248. {
  249. wprintf(load_resource(STRING_USAGE));
  250. return 1;
  251. }
  252. return get(argv[2]);
  253. }
  254. else
  255. {
  256. wprintf(load_resource(STRING_USAGE));
  257. return 1;
  258. }
  259. }