Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/programs/klist/main.c
4389 views
1
/*
2
* Copyright 2023 Maxim Karasev <[email protected]>
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
19
#define WIN32_LEAN_AND_MEAN
20
#include <ntstatus.h>
21
#define WIN32_NO_STATUS
22
#include <windows.h>
23
#include <ntsecapi.h>
24
25
#include "wine/debug.h"
26
27
#include "resources.h"
28
29
WINE_DEFAULT_DEBUG_CHANNEL(klist);
30
31
static WCHAR msg_buf[1024];
32
static const WCHAR *load_resource(UINT id)
33
{
34
LoadStringW(GetModuleHandleW(NULL), id, msg_buf, ARRAY_SIZE(msg_buf));
35
return msg_buf;
36
}
37
38
static const WCHAR *get_etype_text(LONG encryption_type)
39
{
40
switch (encryption_type)
41
{
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";
76
}
77
}
78
79
static BOOL get_process_logon_id(LUID *logon_id)
80
{
81
HANDLE token_handle;
82
TOKEN_STATISTICS token_statistics;
83
DWORD token_statistics_len;
84
BOOL err;
85
86
err = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token_handle);
87
if (!err)
88
{
89
ERR("OpenProcessToken failed\n");
90
return FALSE;
91
}
92
93
err = GetTokenInformation(token_handle, TokenStatistics, &token_statistics,
94
sizeof(token_statistics), &token_statistics_len);
95
if (!err)
96
{
97
ERR("GetTokenInformation failed\n");
98
return FALSE;
99
}
100
101
*logon_id = token_statistics.AuthenticationId;
102
103
return TRUE;
104
}
105
106
static void format_dates_and_times(const FILETIME *const filetimes[],
107
const WCHAR *output_strings[], ULONG count)
108
{
109
ULONG i;
110
111
for (i = 0; i < count; i++)
112
{
113
SYSTEMTIME system_time;
114
int date_len;
115
int time_len;
116
WCHAR *date;
117
118
FileTimeToSystemTime(filetimes[i], &system_time);
119
SystemTimeToTzSpecificLocalTime(NULL, &system_time, &system_time);
120
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);
123
124
date = malloc((date_len + time_len) * sizeof(date[0]));
125
126
GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_SHORTDATE, &system_time, NULL, date, date_len, NULL);
127
wcscat(date, L" ");
128
GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, &system_time, NULL, date + wcslen(date), time_len);
129
130
output_strings[i] = date;
131
}
132
}
133
134
static int tickets(void)
135
{
136
LUID logon_id;
137
BOOL status;
138
HANDLE lsa_handle;
139
NTSTATUS err;
140
ULONG i;
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),
145
};
146
ULONG kerberos_package;
147
148
KERB_QUERY_TKT_CACHE_REQUEST kerberos_cache_request = {
149
.MessageType = KerbQueryTicketCacheExMessage,
150
.LogonId = {0},
151
};
152
KERB_QUERY_TKT_CACHE_EX_RESPONSE *kerberos_cache;
153
ULONG kerberos_cache_size;
154
NTSTATUS kerberos_call_status;
155
156
status = get_process_logon_id(&logon_id);
157
if (!status)
158
{
159
wprintf(load_resource(STRING_UNKNOWN_ERROR));
160
return 1;
161
}
162
163
err = LsaConnectUntrusted(&lsa_handle);
164
if (err != STATUS_SUCCESS)
165
{
166
wprintf(load_resource(STRING_UNKNOWN_ERROR));
167
ERR("LsaConnectUntrusted NTSTATUS %lX\n", err);
168
return 1;
169
}
170
171
err = LsaLookupAuthenticationPackage(lsa_handle, &package_name, &kerberos_package);
172
if (err != STATUS_SUCCESS)
173
{
174
wprintf(load_resource(STRING_UNKNOWN_ERROR));
175
ERR("LsaLookupAuthenticationPackage NTSTATUS %lX\n", err);
176
return 1;
177
}
178
179
TRACE("Kerberos LSA package: %lu\n", kerberos_package);
180
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)
185
{
186
wprintf(load_resource(STRING_UNKNOWN_ERROR));
187
ERR("LsaCallAuthenticationPackage NTSTATUS %lX\n", err);
188
return 1;
189
}
190
191
wprintf(L"\n");
192
wprintf(L"%ls %ld:0x%lx\n", load_resource(STRING_LOGON_ID), logon_id.HighPart, logon_id.LowPart);
193
wprintf(L"\n");
194
wprintf(L"%ls: (%d)\n", load_resource(STRING_CACHED_TICKETS), kerberos_cache->CountOfTickets);
195
196
for (i = 0; i < kerberos_cache->CountOfTickets; i++)
197
{
198
KERB_TICKET_CACHE_INFO_EX 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];
202
203
format_dates_and_times(filetimes, dates, 3);
204
205
wprintf(L"\n");
206
wprintf(L"#%ld>", i);
207
208
wprintf(L" %ls: %.*ls @ %.*ls\n", load_resource(STRING_CLIENT),
209
ticket.ClientName.Length / sizeof(WCHAR), ticket.ClientName.Buffer,
210
ticket.ClientRealm.Length / sizeof(WCHAR), ticket.ClientRealm.Buffer);
211
212
wprintf(L" %ls: %.*ls @ %.*ls\n", load_resource(STRING_SERVER),
213
ticket.ServerName.Length / sizeof(WCHAR), ticket.ServerName.Buffer,
214
ticket.ServerRealm.Length / sizeof(WCHAR), ticket.ServerRealm.Buffer);
215
216
wprintf(L" %ls: ", load_resource(STRING_ENCRYPTION_TYPE));
217
wprintf(L"%s\n", get_etype_text(ticket.EncryptionType));
218
219
wprintf(L" %ls: 0x%lx ->", load_resource(STRING_TICKET_FLAGS), ticket.TicketFlags);
220
#define EXPAND_TICKET_FLAG(x) if (ticket.TicketFlags & KERB_TICKET_FLAGS_##x) wprintf(L" %ls", L ## #x)
221
EXPAND_TICKET_FLAG(forwardable);
222
EXPAND_TICKET_FLAG(forwarded);
223
EXPAND_TICKET_FLAG(proxiable);
224
EXPAND_TICKET_FLAG(proxy);
225
EXPAND_TICKET_FLAG(may_postdate);
226
EXPAND_TICKET_FLAG(postdated);
227
EXPAND_TICKET_FLAG(invalid);
228
EXPAND_TICKET_FLAG(renewable);
229
EXPAND_TICKET_FLAG(initial);
230
EXPAND_TICKET_FLAG(pre_authent);
231
EXPAND_TICKET_FLAG(hw_authent);
232
EXPAND_TICKET_FLAG(ok_as_delegate);
233
EXPAND_TICKET_FLAG(name_canonicalize);
234
EXPAND_TICKET_FLAG(cname_in_pa_data);
235
#undef EXPAND_TICKET_FLAG
236
wprintf(L"\n");
237
238
wprintf(L" %ls: %ls (local)\n", load_resource(STRING_START_TIME), dates[0]);
239
wprintf(L" %ls: %ls (local)\n", load_resource(STRING_END_TIME), dates[1]);
240
wprintf(L" %ls: %ls (local)\n", load_resource(STRING_RENEW_TIME), dates[2]);
241
}
242
LsaFreeReturnBuffer(kerberos_cache);
243
LsaDeregisterLogonProcess(lsa_handle);
244
return 0;
245
}
246
247
static int tgt(void)
248
{
249
FIXME("stub\n");
250
251
return 0;
252
}
253
254
static int purge(void)
255
{
256
FIXME("stub\n");
257
258
return 0;
259
}
260
261
static int get(const WCHAR *principal)
262
{
263
FIXME("stub\n");
264
265
return 0;
266
}
267
268
int __cdecl wmain(int argc, WCHAR *argv[])
269
{
270
if (argc < 2)
271
{
272
return tickets();
273
}
274
275
if (!wcscmp(argv[1], L"tickets"))
276
{
277
return tickets();
278
}
279
else if (!wcscmp(argv[1], L"tgt"))
280
{
281
return tgt();
282
}
283
else if (!wcscmp(argv[1], L"purge"))
284
{
285
return purge();
286
}
287
else if (!wcscmp(argv[1], L"get"))
288
{
289
if (argc < 3)
290
{
291
wprintf(load_resource(STRING_USAGE));
292
return 1;
293
}
294
295
return get(argv[2]);
296
}
297
else
298
{
299
wprintf(load_resource(STRING_USAGE));
300
return 1;
301
}
302
}
303
304