2 * Copyright 2023 Maxim Karasev <mxkrsv@etersoft.ru>
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.
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.
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
19 #define WIN32_LEAN_AND_MEAN
21 #define WIN32_NO_STATUS
25 #include "wine/debug.h"
27 #include "resources.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(klist
);
31 static WCHAR msg_buf
[1024];
32 static const WCHAR
*load_resource(UINT id
)
34 LoadStringW(GetModuleHandleW(NULL
), id
, msg_buf
, ARRAY_SIZE(msg_buf
));
38 static const WCHAR
*get_etype_text(LONG encryption_type
)
40 switch (encryption_type
)
42 case KERB_ETYPE_NULL
: return L
"NULL";
43 case KERB_ETYPE_DES_CBC_CRC
: return L
"DES-CBC-CRC";
44 case KERB_ETYPE_DES_CBC_MD4
: return L
"DES-CBC-MD4";
45 case KERB_ETYPE_DES_CBC_MD5
: return L
"DES-CBC-MD5";
46 case KERB_ETYPE_AES128_CTS_HMAC_SHA1_96
: return L
"AES-128-CTS-HMAC-SHA1-96";
47 case KERB_ETYPE_AES256_CTS_HMAC_SHA1_96
: return L
"AES-256-CTS-HMAC-SHA1-96";
48 case KERB_ETYPE_RC4_MD4
: return L
"RC4-MD4";
49 case KERB_ETYPE_RC4_PLAIN2
: return L
"RC4-PLAIN2";
50 case KERB_ETYPE_RC4_LM
: return L
"RC4-LM";
51 case KERB_ETYPE_RC4_SHA
: return L
"RC4-SHA";
52 case KERB_ETYPE_DES_PLAIN
: return L
"DES-PLAIN";
53 case KERB_ETYPE_RC4_HMAC_OLD
: return L
"RC4-HMAC-OLD";
54 case KERB_ETYPE_RC4_PLAIN_OLD
: return L
"RC4-PLAIN-OLD";
55 case KERB_ETYPE_RC4_HMAC_OLD_EXP
: return L
"RC4-HMAC-OLD-EXP";
56 case KERB_ETYPE_RC4_PLAIN_OLD_EXP
: return L
"RC4-PLAIN-OLD-EXP";
57 case KERB_ETYPE_RC4_PLAIN
: return L
"RC4-PLAIN";
58 case KERB_ETYPE_RC4_PLAIN_EXP
: return L
"RC4-PLAIN-EXP";
59 case KERB_ETYPE_AES128_CTS_HMAC_SHA1_96_PLAIN
: return L
"AES-128-CTS-HMAC-SHA1-96-PLAIN";
60 case KERB_ETYPE_AES256_CTS_HMAC_SHA1_96_PLAIN
: return L
"AES-256-CTS-HMAC-SHA1-96-PLAIN";
61 case KERB_ETYPE_DSA_SHA1_CMS
: return L
"DSA-SHA1-CMS";
62 case KERB_ETYPE_RSA_MD5_CMS
: return L
"RSA-MD5-CMS";
63 case KERB_ETYPE_RSA_SHA1_CMS
: return L
"RSA-SHA1-CMS";
64 case KERB_ETYPE_RC2_CBC_ENV
: return L
"RC2-CBC-ENV";
65 case KERB_ETYPE_RSA_ENV
: return L
"RSA-ENV";
66 case KERB_ETYPE_RSA_ES_OEAP_ENV
: return L
"RSA-ES-OEAP-ENV";
67 case KERB_ETYPE_DES_EDE3_CBC_ENV
: return L
"DES-EDE3-CBC-ENV";
68 case KERB_ETYPE_DSA_SIGN
: return L
"DSA-SIGN";
69 case KERB_ETYPE_DES3_CBC_MD5
: return L
"DES3-CBC-MD5";
70 case KERB_ETYPE_DES3_CBC_SHA1
: return L
"DES3-CBC-SHA1";
71 case KERB_ETYPE_DES3_CBC_SHA1_KD
: return L
"DES3-CBC-SHA1-KD";
72 case KERB_ETYPE_DES_CBC_MD5_NT
: return L
"DES-CBC-MD5-NT";
73 case KERB_ETYPE_RC4_HMAC_NT
: return L
"RC4-HMAC-NT";
74 case KERB_ETYPE_RC4_HMAC_NT_EXP
: return L
"RC4-HMAC-NT-EXP";
75 default: return L
"unknown";
79 static BOOL
get_process_logon_id(LUID
*logon_id
)
82 TOKEN_STATISTICS token_statistics
;
83 DWORD token_statistics_len
;
86 err
= OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &token_handle
);
89 ERR("OpenProcessToken failed\n");
93 err
= GetTokenInformation(token_handle
, TokenStatistics
, &token_statistics
,
94 sizeof(token_statistics
), &token_statistics_len
);
97 ERR("GetTokenInformation failed\n");
101 *logon_id
= token_statistics
.AuthenticationId
;
106 static void format_dates_and_times(const FILETIME
*const filetimes
[],
107 const WCHAR
*output_strings
[], ULONG count
)
111 for (i
= 0; i
< count
; i
++)
113 SYSTEMTIME system_time
;
118 FileTimeToSystemTime(filetimes
[i
], &system_time
);
119 SystemTimeToTzSpecificLocalTime(NULL
, &system_time
, &system_time
);
121 date_len
= GetDateFormatEx(LOCALE_NAME_USER_DEFAULT
, DATE_SHORTDATE
, &system_time
, NULL
, NULL
, 0, NULL
);
122 time_len
= GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT
, 0, &system_time
, NULL
, NULL
, 0);
124 date
= malloc((date_len
+ time_len
) * sizeof(date
[0]));
126 GetDateFormatEx(LOCALE_NAME_USER_DEFAULT
, DATE_SHORTDATE
, &system_time
, NULL
, date
, date_len
, NULL
);
128 GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT
, 0, &system_time
, NULL
, date
+ wcslen(date
), time_len
);
130 output_strings
[i
] = date
;
134 static int tickets(void)
141 LSA_STRING package_name
= {
142 .Buffer
= (char*)MICROSOFT_KERBEROS_NAME_A
,
143 .Length
= strlen(MICROSOFT_KERBEROS_NAME_A
),
144 .MaximumLength
= strlen(MICROSOFT_KERBEROS_NAME_A
),
146 ULONG kerberos_package
;
148 KERB_QUERY_TKT_CACHE_REQUEST kerberos_cache_request
= {
149 .MessageType
= KerbQueryTicketCacheMessage
,
152 KERB_QUERY_TKT_CACHE_RESPONSE
*kerberos_cache
;
153 ULONG kerberos_cache_size
;
154 NTSTATUS kerberos_call_status
;
156 status
= get_process_logon_id(&logon_id
);
159 wprintf(load_resource(STRING_UNKNOWN_ERROR
));
163 err
= LsaConnectUntrusted(&lsa_handle
);
164 if (err
!= STATUS_SUCCESS
)
166 wprintf(load_resource(STRING_UNKNOWN_ERROR
));
167 ERR("LsaConnectUntrusted NTSTATUS %lX\n", err
);
171 err
= LsaLookupAuthenticationPackage(lsa_handle
, &package_name
, &kerberos_package
);
172 if (err
!= STATUS_SUCCESS
)
174 wprintf(load_resource(STRING_UNKNOWN_ERROR
));
175 ERR("LsaLookupAuthenticationPackage NTSTATUS %lX\n", err
);
179 TRACE("Kerberos LSA package: %lu\n", kerberos_package
);
181 err
= LsaCallAuthenticationPackage(lsa_handle
, kerberos_package
, &kerberos_cache_request
,
182 sizeof(kerberos_cache_request
), (PVOID
*)&kerberos_cache
, &kerberos_cache_size
,
183 &kerberos_call_status
);
184 if (err
!= STATUS_SUCCESS
)
186 wprintf(load_resource(STRING_UNKNOWN_ERROR
));
187 ERR("LsaCallAuthenticationPackage NTSTATUS %lX\n", err
);
192 wprintf(L
"%ls %ld:0x%lx\n", load_resource(STRING_LOGON_ID
), logon_id
.HighPart
, logon_id
.LowPart
);
194 wprintf(L
"%ls: (%d)\n", load_resource(STRING_CACHED_TICKETS
), kerberos_cache
->CountOfTickets
);
196 for (i
= 0; i
< kerberos_cache
->CountOfTickets
; i
++)
198 KERB_TICKET_CACHE_INFO ticket
= kerberos_cache
->Tickets
[i
];
199 const FILETIME
*const filetimes
[] = { (FILETIME
*)&ticket
.StartTime
,
200 (FILETIME
*)&ticket
.EndTime
, (FILETIME
*)&ticket
.RenewTime
};
201 const WCHAR
*dates
[3];
203 format_dates_and_times(filetimes
, dates
, 3);
206 wprintf(L
"#%ld>", i
);
208 wprintf(L
" %ls: %.*ls @ %.*ls\n", load_resource(STRING_SERVER
),
209 ticket
.ServerName
.Length
/ sizeof(WCHAR
), ticket
.ServerName
.Buffer
,
210 ticket
.RealmName
.Length
/ sizeof(WCHAR
), ticket
.RealmName
.Buffer
);
212 wprintf(L
" %ls: ", load_resource(STRING_ENCRYPTION_TYPE
));
213 wprintf(L
"%s\n", get_etype_text(ticket
.EncryptionType
));
215 wprintf(L
" %ls: 0x%lx ->", load_resource(STRING_TICKET_FLAGS
), ticket
.TicketFlags
);
216 #define EXPAND_TICKET_FLAG(x) if (ticket.TicketFlags & KERB_TICKET_FLAGS_##x) wprintf(L" %ls", L ## #x)
217 EXPAND_TICKET_FLAG(forwardable
);
218 EXPAND_TICKET_FLAG(forwarded
);
219 EXPAND_TICKET_FLAG(proxiable
);
220 EXPAND_TICKET_FLAG(proxy
);
221 EXPAND_TICKET_FLAG(may_postdate
);
222 EXPAND_TICKET_FLAG(postdated
);
223 EXPAND_TICKET_FLAG(invalid
);
224 EXPAND_TICKET_FLAG(renewable
);
225 EXPAND_TICKET_FLAG(initial
);
226 EXPAND_TICKET_FLAG(pre_authent
);
227 EXPAND_TICKET_FLAG(hw_authent
);
228 EXPAND_TICKET_FLAG(ok_as_delegate
);
229 EXPAND_TICKET_FLAG(name_canonicalize
);
230 EXPAND_TICKET_FLAG(cname_in_pa_data
);
231 #undef EXPAND_TICKET_FLAG
234 wprintf(L
" %ls: %ls (local)\n", load_resource(STRING_START_TIME
), dates
[0]);
235 wprintf(L
" %ls: %ls (local)\n", load_resource(STRING_END_TIME
), dates
[1]);
236 wprintf(L
" %ls: %ls (local)\n", load_resource(STRING_RENEW_TIME
), dates
[2]);
238 LsaFreeReturnBuffer(kerberos_cache
);
239 LsaDeregisterLogonProcess(lsa_handle
);
250 static int purge(void)
257 static int get(const WCHAR
*principal
)
264 int __cdecl
wmain(int argc
, WCHAR
*argv
[])
271 if (!wcscmp(argv
[1], L
"tickets"))
275 else if (!wcscmp(argv
[1], L
"tgt"))
279 else if (!wcscmp(argv
[1], L
"purge"))
283 else if (!wcscmp(argv
[1], L
"get"))
287 wprintf(load_resource(STRING_USAGE
));
295 wprintf(load_resource(STRING_USAGE
));