Windows global stuff:
[krb5.git] / src / windows / cns / tktlist.c
1 /*
2  * tktlist.c
3  *
4  * Handle all actions of the Kerberos ticket list.
5  *
6  * Copyright 1994 by the Massachusetts Institute of Technology.
7  *
8  * For copying and distribution information, please see the file
9  * <mit-copyright.h>.
10  */
11
12 #if !defined(KRB5) && !defined(KRB4)
13         #define KRB5 1
14 #endif
15
16 #include <windows.h>
17 #include <stdio.h>
18 #include <assert.h>
19 #include <malloc.h>
20 #include <string.h>
21 #include <time.h>
22
23 #ifdef KRB4
24         #include "mit-copyright.h"
25         #include "kerberos.h"
26 #endif
27
28 #ifdef KRB5
29         #define NEED_SOCKETS
30         #include "krb5.h"
31         #include "krbini.h"
32     #include "com_err.h"
33
34         #define DEFAULT_TKT_LIFE 120
35         #define         ANAME_SZ        40
36         #define         REALM_SZ        40
37         #define         SNAME_SZ        40
38         #define         INST_SZ         40
39         #define         MAX_KPW_LEN     128
40         /* include space for '.' and '@' */
41         #define         MAX_K_NAME_SZ   (ANAME_SZ + INST_SZ + REALM_SZ + 2)
42         #define ORGANIZATION "Cygnus Support"
43 #endif
44
45 #include "cns.h"
46 #include "tktlist.h"
47
48 /*
49  * Ticket information for a list line
50  */
51 typedef struct {
52         BOOL ticket;            /* TRUE if this is a real ticket */
53     time_t issue_time;  /* time_t of issue */
54         long lifetime;          /* Lifetime for ticket in 5 minute intervals */
55         char buf[0];            /* String to display */
56 } TICKETINFO, *LPTICKETINFO;
57
58 /*+
59  * Function: Returns a standard ctime date with day of week and year
60  *      removed.
61  *
62  * Parameters:
63  *      t - time_t date to convert
64  *
65  * Returns: A pointer to the adjusted time value.
66  */
67 static char *
68 short_date (long t) {
69         static char buf[26 - 4];
70         char *p;
71
72         p = ctime(&t);
73         assert(p != NULL);
74
75         strcpy (buf, p + 4);
76         buf[12] = '\0';
77
78         return buf;
79
80 } /* short_date */
81
82
83 /*++
84  * Function: Initializes and populates the ticket list with all existing
85  *      Kerberos tickets.
86  *
87  * Parameters:
88  *      hwnd - the window handle of the ticket window.
89  *
90  * Returns: Number of elements in the list or -1 on error
91  */
92 int
93 ticket_init_list (
94         HWND hwnd)
95 {
96         int ncred;
97         LRESULT rc;
98         int l;
99         LPTICKETINFO lpinfo;
100     char buf[26+2 + 26+2 + ANAME_SZ+1 + INST_SZ+1 + REALM_SZ + 22];
101         #ifdef KRB4
102                 int i;
103                 time_t expiration;
104                 char service[ANAME_SZ];
105                 char instance[INST_SZ];
106                 char realm[REALM_SZ];
107                 CREDENTIALS c;
108         #endif
109         #ifdef KRB5
110                 krb5_cc_cursor cursor;
111                 krb5_error_code code;
112                 krb5_creds c;
113         krb5_flags flags;
114         char *sname;                            /* Name of the service */
115         char *flags_string(krb5_creds *cred);
116         #endif
117
118         SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
119
120         rc = SendMessage(hwnd, LB_GETCOUNT, 0, 0);
121         assert(rc != LB_ERR);
122
123         if (rc > 0)
124                 ticket_destroy(hwnd);
125
126         while (--rc >= 0)
127                 SendMessage(hwnd, LB_DELETESTRING, (WPARAM) rc, 0);
128
129         #ifdef KRB4
130
131                 ncred = krb_get_num_cred();
132                 for (i = 1; i <= ncred; i++) {
133                         krb_get_nth_cred(service, instance, realm, i);
134                         krb_get_cred(service, instance, realm, &c);
135                         strcpy(buf, " ");
136                         strcat(buf, short_date(c.issue_date - kwin_get_epoch()));
137                         expiration = c.issue_date - kwin_get_epoch() + (long) c.lifetime * 5L * 60L;
138                         strcat(buf, "  ");
139                         strcat(buf, short_date(expiration));
140                         l = strlen(buf);
141                         sprintf(&buf[l], "  %s%s%s%s%s (%d)",
142                                 c.service, (c.instance[0] ? "." : ""), c.instance,
143                                 (c.realm[0] ? "@" : ""), c.realm, c.kvno);
144                         l = strlen(buf);
145
146                         lpinfo = (LPTICKETINFO) malloc(sizeof(TICKETINFO) + l + 1);
147                         assert(lpinfo != NULL);
148
149                         if (lpinfo == NULL)
150                                 return -1;
151
152                         lpinfo->ticket = TRUE;
153                         lpinfo->issue_time = c.issue_date - kwin_get_epoch(); /* back to system time */
154                         lpinfo->lifetime = (long) c.lifetime * 5L * 60L;
155                         strcpy(lpinfo->buf, buf);
156
157                         rc = SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM) lpinfo);
158                         assert(rc >= 0);
159
160                         if (rc < 0)
161                                 return -1;
162                 }
163
164         #endif
165
166         #ifdef KRB5
167
168                 ncred = 0;
169         flags = 0;
170         if (code = krb5_cc_set_flags(k5_context, k5_ccache, flags)) {
171             if (code != KRB5_FCC_NOFILE) {
172                 //com_err (NULL, code,
173                 //    "while setting cache flags (ticket cache %s)",
174                 //    krb5_cc_get_name(k5_context, k5_ccache));
175                 return -1;
176             }
177         } else {
178             if (code = krb5_cc_start_seq_get(k5_context, k5_ccache, &cursor)) {
179                 //com_err (NULL, code, "while starting to retrieve tickets");
180                 return -1;
181             }
182
183                     while (1) {
184                         code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c);
185                         if (code != 0)
186                                 break;
187
188                         ncred++;
189                 strcpy (buf, "  ");
190                 strcat (buf, short_date (c.times.starttime - kwin_get_epoch()));
191                 strcat (buf, "  ");
192                 strcat (buf, short_date (c.times.endtime - kwin_get_epoch()));
193                 strcat (buf, "  ");
194
195                 /* Add ticket service name and realm */
196                 code = krb5_unparse_name (k5_context, c.server, &sname);
197                 if (code) {
198                     com_err (NULL, code, "while unparsing server name");
199                     break;
200                 }
201                 strcat (buf, sname);
202                 free (sname);
203                 strcat (buf, flags_string (&c)); /* Add flag info */
204
205                         l = strlen(buf);
206                             lpinfo = (LPTICKETINFO) malloc(sizeof(TICKETINFO) + l + 1);
207                         assert(lpinfo != NULL);
208         
209                         if (lpinfo == NULL)
210                                 return -1;
211
212                         lpinfo->ticket = TRUE;
213                         lpinfo->issue_time = c.times.starttime - kwin_get_epoch();
214                         lpinfo->lifetime = c.times.endtime - c.times.starttime;
215                         strcpy(lpinfo->buf, buf);
216
217                         rc = SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM) lpinfo);
218                         assert(rc >= 0);
219
220                         if (rc < 0)
221                                 return -1;
222                 }
223
224             if (code == KRB5_CC_END) {               /* End of ccache */
225                 if (code = krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor)) {
226                     //com_err(NULL, code, "while finishing ticket retrieval");
227                     return -1;
228                 }
229                 flags = KRB5_TC_OPENCLOSE;          /* turns on OPENCLOSE mode */
230                 if (code = krb5_cc_set_flags(k5_context, k5_ccache, flags)) {
231                     //com_err(NULL, code, "while closing ccache");
232                     return -1;
233                 }
234             } else {
235                 //com_err(NULL, code, "while retrieving a ticket");
236                 return -1;
237             }
238         }
239         #endif
240
241         if (ncred <= 0) {
242                 strcpy(buf, " No Tickets");
243                 lpinfo = (LPTICKETINFO) malloc(sizeof(TICKETINFO) + strlen(buf) + 1);
244                 assert(lpinfo != NULL);
245
246                 if (lpinfo == NULL)
247                         return -1;
248
249                 lpinfo->ticket = FALSE;
250                 strcpy (lpinfo->buf, buf);
251                 rc = SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM) lpinfo);
252                 assert(rc >= 0);
253         }
254
255         SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
256
257         return ncred;
258
259 } /* ticket_init_list */
260
261
262 /*+
263  * Function: Destroy the ticket list.  Make sure to delete all
264  *      ticket entries created during ticket initialization.
265  *
266  * Parameters:
267  *      hwnd - the window handle of the ticket window.
268  */
269 void
270 ticket_destroy (
271         HWND hwnd)
272 {
273         int i;
274         int n;
275         LRESULT rc;
276
277         n = (int) SendMessage(hwnd, LB_GETCOUNT, 0, 0);
278
279         for (i = 0; i < n; i++) {
280                 rc = SendMessage(hwnd, LB_GETITEMDATA, i, 0);
281                 assert(rc != LB_ERR);
282
283                 if (rc != LB_ERR)
284                         free ((void *) rc);
285         }
286
287 } /* ticket_destroy */
288
289
290 /*+
291  * Function: Respond to the WM_MEASUREITEM message for the ticket list
292  *      by setting each list item up at 1/4" hight.
293  *
294  * Parameters:
295  *      hwnd - the window handle of the ticket window.
296  *
297  *      wparam - control id of the ticket list.
298  *
299  *      lparam - pointer to the MEASUREITEMSTRUCT.
300  *
301  * Returns: TRUE if message process, FALSE otherwise.
302  */
303 LONG
304 ticket_measureitem (
305         HWND hwnd,
306         WPARAM wparam,
307         LPARAM lparam)
308 {
309         int logpixelsy;
310         LPMEASUREITEMSTRUCT lpmi;
311         HDC hdc;
312
313         lpmi = (LPMEASUREITEMSTRUCT) lparam;
314         hdc = GetDC(HWND_DESKTOP);
315         logpixelsy = GetDeviceCaps(hdc, LOGPIXELSY);
316         ReleaseDC(HWND_DESKTOP, hdc);
317         lpmi->itemHeight = logpixelsy / 4;      /* 1/4 inch */
318
319         return TRUE;
320
321 } /* ticket_measureitem */
322
323
324 /*+
325  * Function: Respond to the WM_DRAWITEM message for the ticket list
326  *      by displaying a single list item.
327  *
328  * Parameters:
329  *      hwnd - the window handle of the ticket window.
330  *
331  *      wparam - control id of the ticket list.
332  *
333  *      lparam - pointer to the DRAWITEMSTRUCT.
334  *
335  * Returns: TRUE if message process, FALSE otherwise.
336  */
337 LONG ticket_drawitem(
338         HWND hwnd,
339         WPARAM wparam,
340         LPARAM lparam)
341 {
342         LPDRAWITEMSTRUCT lpdi;
343         BOOL rc;
344         COLORREF bkcolor;
345         HBRUSH hbrush;
346         UINT textheight;
347         UINT alignment;
348         int left, top;
349         BOOL b;
350         LPTICKETINFO lpinfo;
351         HICON hicon;
352         #if 0
353                 COLORREF textcolor;
354                 COLORREF orgbkcolor;
355                 COLORREF orgtextcolor;
356         #endif
357
358         lpdi = (LPDRAWITEMSTRUCT) lparam;
359         lpinfo = (LPTICKETINFO) lpdi->itemData;
360
361         if (lpdi->itemAction == ODA_FOCUS)
362                 return TRUE;
363
364         #if 0
365                 if (lpdi->itemState & ODS_SELECTED) {
366                         textcolor = GetSysColor(COLOR_HIGHLIGHTTEXT);
367                         bkcolor = GetSysColor(COLOR_HIGHLIGHT);
368
369                         orgtextcolor = SetTextColor(lpdi->hDC, textcolor);
370                 assert(textcolor != 0x80000000);
371
372                         orgbkcolor = SetBkColor(lpdi->hDC, bkcolor);
373                 assert(bkcolor != 0x80000000);
374                 }
375                 else
376         #endif
377
378         bkcolor = GetBkColor(lpdi->hDC);
379         hbrush = CreateSolidBrush(bkcolor);
380         assert(hbrush != NULL);
381
382         FillRect(lpdi->hDC, &(lpdi->rcItem), hbrush);
383         DeleteObject(hbrush);
384
385         /*
386          * Display the appropriate icon
387          */
388         if (lpinfo->ticket) {
389                 hicon = kwin_get_icon(lpinfo->issue_time + lpinfo->lifetime);
390                 left = lpdi->rcItem.left - (32 - ICON_WIDTH) / 2;
391                 top = lpdi->rcItem.top;
392                 top += (lpdi->rcItem.bottom - lpdi->rcItem.top - 32) / 2;
393
394                 b = DrawIcon(lpdi->hDC, left, top, hicon);
395                 assert(b);
396         }
397
398         /*
399          * Display centered string
400          */
401         textheight = HIWORD(GetTextExtent(lpdi->hDC, "X", 1));
402         alignment = SetTextAlign(lpdi->hDC, TA_TOP | TA_LEFT);
403
404         if (lpinfo->ticket)
405                 left = lpdi->rcItem.left + ICON_WIDTH;
406         else
407                 left = lpdi->rcItem.left;
408
409         top = lpdi->rcItem.top;
410         top += (lpdi->rcItem.bottom - lpdi->rcItem.top - textheight) / 2;
411         rc = TextOut(lpdi->hDC, left, top, (LPSTR) lpinfo->buf,
412                         strlen((LPSTR) lpinfo->buf));
413         assert(rc);
414
415         alignment = SetTextAlign(lpdi->hDC, alignment);
416
417         #if 0
418                 if (lpdi->itemState & ODS_SELECTED) {
419                         textcolor = SetTextColor(lpdi->hDC, orgtextcolor);
420                 assert(textcolor != 0x80000000);
421
422                         bkcolor = SetBkColor(lpdi->hDC, orgbkcolor);
423                 assert(bkcolor != 0x80000000);
424                 }
425
426         #endif
427
428         return TRUE;
429
430 } /* ticket_drawitem */
431
432
433 #ifdef KRB5
434
435 /*+
436  * 
437  * Flags_string
438  * 
439  * Return buffer with the current flags for the credential
440  * 
441  */
442 char *
443 flags_string(krb5_creds *cred) {
444     static char buf[32];
445     int i = 0;
446
447     buf[i++] = ' ';    
448     buf[i++] = '(';    
449     if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
450         buf[i++] = 'F';
451     if (cred->ticket_flags & TKT_FLG_FORWARDED)
452         buf[i++] = 'f';
453     if (cred->ticket_flags & TKT_FLG_PROXIABLE)
454         buf[i++] = 'P';
455     if (cred->ticket_flags & TKT_FLG_PROXY)
456         buf[i++] = 'p';
457     if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
458         buf[i++] = 'D';
459     if (cred->ticket_flags & TKT_FLG_POSTDATED)
460         buf[i++] = 'd';
461     if (cred->ticket_flags & TKT_FLG_INVALID)
462         buf[i++] = 'i';
463     if (cred->ticket_flags & TKT_FLG_RENEWABLE)
464         buf[i++] = 'R';
465     if (cred->ticket_flags & TKT_FLG_INITIAL)
466         buf[i++] = 'I';
467     if (cred->ticket_flags & TKT_FLG_HW_AUTH)
468         buf[i++] = 'H';
469     if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
470         buf[i++] = 'A';
471
472     buf[i++] = ')';    
473     buf[i] = '\0';
474     if (i <= 3)
475         buf[0] = '\0';
476     return(buf);
477 }
478
479 #endif /* KRB5 */