6 * Main routine of the Kerberos user interface. Also handles
7 * all dialog level management functions.
9 * Copyright 1994 by the Massachusetts Institute of Technology.
11 * For copying and distribution information, please see the file
15 #if !defined(KRB5) && !defined(KRB4)
29 #define DEFINE_SOCKADDR
30 #include "mit-copyright.h"
42 #define DEFAULT_TKT_LIFE 120 // In 5 minute units
47 #define MAX_KPW_LEN 128
48 /* include space for '.' and '@' */
49 #define MAX_K_NAME_SZ (ANAME_SZ + INST_SZ + REALM_SZ + 2)
50 #define ORGANIZATION "Cygnus Support"
52 #define CREDENTIALS char
61 #define BLOCK_MAX_SEC 30 /* Blocking timeout duration */
62 #define KWIN_UPDATE_PERIOD 30000 /* Every 30 seconds update the screen */
63 #define TIME_BUFFER 300 /* Pop-up time buffer in seconds */
64 #define WM_KWIN_SETNAME (WM_USER+100) /* Sets the name fields in the dialog */
66 enum { /* Actions after login */
75 static HICON kwin_icons[MAX_ICONS]; /* Icons depicting time */
76 static HFONT hfontdialog = NULL; /* Font in which the dialog is drawn. */
77 static HFONT hfonticon = NULL; /* Font for icon label */
78 static HINSTANCE hinstance;
79 static int dlgncmdshow; /* ncmdshow from WinMain */
80 static UINT wm_kerberos_changed; /* Registered message for cache changing */
81 static int action; /* After login actions */
82 static UINT kwin_timer_id; /* Timer being used for update */
83 static BOOL alert; /* Actions on ticket expiration */
85 static BOOL alerted; /* TRUE when user already alerted */
86 static BOOL isblocking = FALSE; /* TRUE when blocked in WinSock */
87 static DWORD blocking_end_time; /* Ending tick count for blocking timeout */
88 static FARPROC hook_instance; /* Intance handle for blocking hook function */
91 krb5_context k5_context;
92 krb5_ccache k5_ccache;
93 static char ccname[FILENAME_MAX]; /* ccache file location */
97 * Function: Called during blocking operations. Implement a timeout
98 * if nothing occurs within the specified time, cancel the blocking
99 * operation. Also permit the user to press escape in order to
100 * cancel the blocking operation.
102 * Returns: TRUE if we got and dispatched a message, FALSE otherwise.
104 BOOL __export CALLBACK
105 blocking_hook_proc (void)
110 if (GetTickCount() > blocking_end_time) {
111 WSACancelBlockingCall();
115 rc = (BOOL) PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
119 if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) {
120 WSACancelBlockingCall();
121 blocking_end_time = msg.time - 1;
125 TranslateMessage(&msg);
126 DispatchMessage(&msg);
130 } /* blocking_hook_proc */
134 * Function: Set up a blocking hook function.
137 * timeout - # of seconds to block for before cancelling.
140 start_blocking_hook (
149 blocking_end_time = GetTickCount() + (1000 * timeout);
150 hook_instance = MakeProcInstance(blocking_hook_proc, hinstance);
151 proc = WSASetBlockingHook(hook_instance);
152 assert(proc != NULL);
154 } /* start_blocking_hook */
158 * Function: End the blocking hook fuction set up above.
161 end_blocking_hook (void)
164 FreeProcInstance(hook_instance);
165 WSAUnhookBlockingHook();
168 } /* end_blocking_hook */
172 * Function: Centers the specified window on the screen.
175 * hwnd - the window to center on the screen.
181 int scrwidth, scrheight;
182 int dlgwidth, dlgheight;
189 GetWindowRect(hwnd, &r);
190 dlgwidth = r.right - r.left;
191 dlgheight = r.bottom - r.top ;
193 scrwidth = GetDeviceCaps(hdc, HORZRES);
194 scrheight = GetDeviceCaps(hdc, VERTRES);
195 ReleaseDC(NULL, hdc);
196 r.left = (scrwidth - dlgwidth) / 2;
197 r.top = (scrheight - dlgheight) / 2;
198 MoveWindow(hwnd, r.left, r.top, dlgwidth, dlgheight, TRUE);
200 } /* center_dialog */
204 * Function: Positions the kwin dialog either to the saved location
205 * or the center of the screen if no saved location.
208 * hwnd - the window to center on the screen.
215 int scrwidth, scrheight;
224 scrwidth = GetDeviceCaps(hdc, HORZRES);
225 scrheight = GetDeviceCaps(hdc, VERTRES);
226 ReleaseDC(NULL, hdc);
227 GetPrivateProfileString(INI_DEFAULTS, INI_POSITION, "",
228 position, sizeof(position), KERBEROS_INI);
230 n = sscanf(position, " [%d , %d , %d , %d", &x, &y, &cx, &cy);
238 MoveWindow(hwnd, x, y, cx, cy, TRUE);
240 } /* position_dialog */
244 * Function: Set font of all dialog items.
247 * hwnd - the dialog to set the font of
254 hwnd = GetWindow(hwnd, GW_CHILD);
256 while (hwnd != NULL) {
257 SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, 0);
258 hwnd = GetWindow(hwnd, GW_HWNDNEXT);
261 } /* set_dialog_font */
265 * Function: Trim leading and trailing white space from a string.
268 * s - the string to trim.
277 for (i = 0; s[i]; i++)
278 if (s[i] != ' ' && s[i] != '\t')
282 memmove(s, &s[i], l + 1);
284 for (l--; l >= 0; l--) {
285 if (s[l] != ' ' && s[l] != '\t')
294 * Function: This routine figures out the current time epoch and
295 * returns the conversion factor. It exists because Microloss
296 * screwed the pooch on the time() and _ftime() calls in its release
297 * 7.0 libraries. They changed the epoch to Dec 31, 1899!
300 kwin_get_epoch (void)
302 static struct tm jan_1_70 = {0, 0, 0, 1, 0, 70};
305 epoch = -mktime(&jan_1_70); /* Seconds til 1970 localtime */
306 epoch += _timezone; /* Seconds til 1970 GMT */
310 } /* kwin_get_epoch */
314 * Function: Save the credentials for later restoration.
317 * c - Returned pointer to saved credential cache.
319 * pname - Returned as principal name of session.
321 * pinstance - Returned as principal instance of session.
323 * ncred - Returned number of credentials saved.
334 char service[ANAME_SZ];
335 char instance[INST_SZ];
336 char realm[REALM_SZ];
339 if (krb_get_tf_fullname ((char *) 0, pname, pinstance, (char *) 0) != KSUCCESS) {
345 *ncred = krb_get_num_cred();
349 c= malloc(*ncred * sizeof(CREDENTIALS));
357 for (i = 0; i < *ncred; i++) {
358 krb_get_nth_cred(service, instance, realm, i + 1);
359 krb_get_cred(service, instance, realm, &c[i]);
365 #ifdef KRB5 /* FIXME */
369 } /* push_credentials */
373 * Function: Restore the saved credentials.
375 * c - Pointer to saved credential cache.
377 * pname - Principal name of session.
379 * pinstance - Principal instance of session.
381 * ncred - Number of credentials saved.
394 in_tkt(pname, pinstance);
401 for (i = 0; i < ncred; i++) {
402 krb_save_credentials(c[i].service, c[i].instance, c[i].realm,
403 c[i].session, c[i].lifetime, c[i].kvno, &(c[i].ticket_st),
409 #ifdef KRB5 /* FIXME */
413 } /* pop_credentials */
417 * Function: Changes the password.
420 * hwnd - the current window from which command was invoked.
422 * name - name of user to change password for
424 * instance - instance of user to change password for
426 * realm - realm in which to change password
428 * oldpw - the old password
430 * newpw - the new password to change to
432 * Returns: TRUE if change took place, FALSE otherwise.
450 char pname[ANAME_SZ];
451 char pinstance[INST_SZ];
453 push_credentials(&c, pname, pinstance, &ncred);
454 krc = krb_get_pw_in_tkt(
455 name, instance, realm, PWSERV_NAME, KADM_SINST, 1, oldpw);
457 if (krc != KSUCCESS) {
458 if (krc == INTK_BADPW)
459 p = "Old password is incorrect";
461 p = krb_get_err_text(krc);
462 pop_credentials(c, pname, pinstance, ncred);
463 MessageBox(hwnd, p, "", MB_OK | MB_ICONEXCLAMATION);
468 krc = kadm_init_link(PWSERV_NAME, KRB_MASTER, realm);
470 if (krc != KSUCCESS) {
471 pop_credentials(c, pname, pinstance, ncred);
472 MessageBox(hwnd, kadm_get_err_text(krc), "", MB_OK | MB_ICONEXCLAMATION);
477 des_string_to_key(newpw, new_key);
478 krc = kadm_change_pw2(new_key, newpw, &ret_st);
479 pop_credentials(c, pname, pinstance, ncred);
484 if (krc != KSUCCESS) {
485 MessageBox(hwnd, kadm_get_err_text(krc), "", MB_OK | MB_ICONEXCLAMATION);
493 #ifdef KRB5 /* FIXME */
494 char *msg; // Message string
495 krb5_error_code code; // Return value
497 krb5_error_code //FIXME INTERFACE
498 krb5_change_password(
499 krb5_context context,
506 code = krb5_change_password (k5_context, name, realm, oldpw, newpw, &msg);
509 MessageBox (NULL, msg, NULL, MB_ICONEXCLAMATION);
510 //WHO FREES THIS SPACE??? free (msg);
512 com_err (NULL, code, "while changing password.");
517 } /* change_password */
520 krb5_error_code //FIXME INTERFACE
521 krb5_change_password(
522 krb5_context context,
529 *text = "Changing passwords is not yet implemented";
534 * Function: Process WM_COMMAND messages for the password dialog.
537 * hwnd - the window recieving the message.
539 * wparam - id of the command item
541 * lparam - LOWORD=hwnd of control, HIWORD=notification message.
543 * Returns: TRUE if initialized sucessfully, false otherwise.
552 char instance[INST_SZ];
553 char realm[REALM_SZ];
554 char oldpw[MAX_KPW_LEN];
555 char newpw1[MAX_KPW_LEN];
556 char newpw2[MAX_KPW_LEN];
561 if (HIWORD(lparam) != BN_CLICKED) {
562 GetDlgItemText(hwnd, IDD_PASSWORD_NAME, name, sizeof(name));
564 GetDlgItemText(hwnd, IDD_PASSWORD_REALM, realm, sizeof(realm));
566 GetDlgItemText(hwnd, IDD_OLD_PASSWORD, oldpw, sizeof(oldpw));
567 GetDlgItemText(hwnd, IDD_NEW_PASSWORD1, newpw1, sizeof(newpw1));
568 GetDlgItemText(hwnd, IDD_NEW_PASSWORD2, newpw2, sizeof(newpw2));
569 b = strlen(name) && strlen(realm) && strlen(oldpw) &&
570 strlen(newpw1) && strlen(newpw2);
571 EnableWindow(GetDlgItem(hwnd, IDOK), b);
572 id = (b) ? IDOK : IDD_PASSWORD_CR;
573 SendMessage(hwnd, DM_SETDEFID, id, 0);
583 GetDlgItemText(hwnd, IDD_PASSWORD_NAME, name, sizeof(name));
585 GetDlgItemText(hwnd, IDD_PASSWORD_INSTANCE, instance, sizeof(instance));
587 GetDlgItemText(hwnd, IDD_PASSWORD_REALM, realm, sizeof(realm));
589 GetDlgItemText(hwnd, IDD_OLD_PASSWORD, oldpw, sizeof(oldpw));
590 GetDlgItemText(hwnd, IDD_NEW_PASSWORD1, newpw1, sizeof(newpw1));
591 GetDlgItemText(hwnd, IDD_NEW_PASSWORD2, newpw2, sizeof(newpw2));
593 if (strcmp(newpw1, newpw2) != 0) {
594 MessageBox(hwnd, "The two passwords you entered don't match!", "",
595 MB_OK | MB_ICONEXCLAMATION);
596 SetDlgItemText(hwnd, IDD_NEW_PASSWORD1, "");
597 SetDlgItemText(hwnd, IDD_NEW_PASSWORD2, "");
598 PostMessage(hwnd, WM_NEXTDLGCTL,
599 GetDlgItem(hwnd, IDD_NEW_PASSWORD1), MAKELONG(1, 0));
604 hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
605 start_blocking_hook(BLOCK_MAX_SEC);
607 if (change_password(hwnd, name, instance, realm, oldpw, newpw1))
608 EndDialog(hwnd, IDOK);
610 PostMessage(hwnd, WM_NEXTDLGCTL,
611 GetDlgItem(hwnd, IDD_OLD_PASSWORD), MAKELONG(1, 0));
620 WSACancelBlockingCall();
621 EndDialog(hwnd, IDCANCEL);
625 case IDD_PASSWORD_CR:
626 id = GetDlgCtrlID(GetFocus());
629 if (id == IDD_NEW_PASSWORD2)
630 PostMessage(hwnd, WM_NEXTDLGCTL,
631 GetDlgItem(hwnd, IDD_PASSWORD_NAME), MAKELONG(1, 0));
633 PostMessage(hwnd, WM_NEXTDLGCTL, 0, 0);
641 } /* password_command */
645 * Function: Process WM_INITDIALOG messages for the password dialog.
646 * Set up all initial dialog values from the parent dialog.
649 * hwnd - the window recieving the message.
651 * wparam - handle of the control for focus.
653 * lparam - lparam from dialog box call.
655 * Returns: TRUE if we didn't set the focus here,
659 password_initdialog (
665 char realm[REALM_SZ];
669 char instance[INST_SZ];
673 set_dialog_font(hwnd, hfontdialog);
675 hwndparent = GetParent(hwnd);
676 assert(hwndparent != NULL);
678 GetDlgItemText(hwndparent, IDD_LOGIN_NAME, name, sizeof(name));
680 SetDlgItemText(hwnd, IDD_PASSWORD_NAME, name);
683 GetDlgItemText(hwndparent, IDD_LOGIN_INSTANCE, instance, sizeof(instance));
685 SetDlgItemText(hwnd, IDD_PASSWORD_INSTANCE, instance);
688 GetDlgItemText(hwndparent, IDD_LOGIN_REALM, realm, sizeof(realm));
690 SetDlgItemText(hwnd, IDD_PASSWORD_REALM, realm);
692 if (strlen(name) == 0)
693 id = IDD_PASSWORD_NAME;
694 else if (strlen(realm) == 0)
695 id = IDD_PASSWORD_REALM;
697 id = IDD_OLD_PASSWORD;
699 SetFocus(GetDlgItem(hwnd, id));
703 } /* password_initdialog */
707 * Function: Process dialog specific messages for the password dialog.
710 * hwnd - the dialog receiving the message.
712 * message - the message to process.
714 * wparam - wparam of the message.
716 * lparam - lparam of the message.
718 * Returns: TRUE if message handled locally, FALSE otherwise.
732 return password_initdialog(hwnd, wparam, lparam);
735 password_command(hwnd, wparam, lparam);
740 SetCursor(LoadCursor(NULL, IDC_WAIT));
741 SetWindowLong(hwnd, DWL_MSGRESULT, TRUE);
750 } /* password_dlg_proc */
754 * Function: Display and process the password dialog.
757 * hwnd - the parent window for the dialog
759 * Returns: TRUE if the dialog completed successfully, FALSE otherwise.
768 dlgproc = (FARPROC) MakeProcInstance(password_dlg_proc, hinstance);
769 assert(dlgproc != NULL);
774 rc = DialogBox(hinstance, MAKEINTRESOURCE(ID_PASSWORD), hwnd, dlgproc);
777 FreeProcInstance((FARPROC) dlgproc);
781 } /* password_dialog */
785 * Function: Process WM_INITDIALOG messages for the options dialog.
786 * Set up all initial dialog values from the KERBEROS_INI file.
789 * hwnd - the window recieving the message.
791 * wparam - handle of the control for focus.
793 * lparam - lparam from dialog box call.
795 * Returns: TRUE if we didn't set the focus here,
804 char defname[FILENAME_MAX];
805 char newname[FILENAME_MAX];
810 set_dialog_font(hwnd, hfontdialog);
813 rc = GetWindowsDirectory(defname, sizeof(defname));
816 strcat(defname, "\\");
817 strcat(defname, DEF_KRB_CONF);
818 GetPrivateProfileString(INI_FILES, INI_KRB_CONF, defname,
819 newname, sizeof(newname), KERBEROS_INI);
821 SetDlgItemText(hwnd, IDD_CONF, newname);
823 /* krb.realms file */
824 rc = GetWindowsDirectory(defname, sizeof(defname));
827 strcat(defname, "\\");
828 strcat(defname, DEF_KRB_REALMS);
829 GetPrivateProfileString(INI_FILES, INI_KRB_REALMS, defname,
830 newname, sizeof(newname), KERBEROS_INI);
832 SetDlgItemText(hwnd, IDD_REALMS, newname);
834 /* Credential cache file */
836 rc = GetWindowsDirectory(defname, sizeof(defname));
839 strcat(defname, "\\");
840 strcat(defname, "krb5cc");
841 GetPrivateProfileString(INI_FILES, INI_KRB_CCACHE, defname,
842 ccname, sizeof(ccname), KERBEROS_INI);
844 SetDlgItemText(hwnd, IDD_CCACHE, ccname);
847 /* Ticket duration */
848 lifetime = GetPrivateProfileInt(INI_OPTIONS, INI_DURATION,
849 DEFAULT_TKT_LIFE * 5, KERBEROS_INI);
850 SetDlgItemInt(hwnd, IDD_LIFETIME, lifetime, FALSE);
852 /* Expiration action */
853 GetPrivateProfileString(INI_EXPIRATION, INI_ALERT, "No",
854 defname, sizeof(defname), KERBEROS_INI);
855 alert = _stricmp(defname, "Yes") == 0;
856 SendDlgItemMessage(hwnd, IDD_ALERT, BM_SETCHECK, alert, 0);
857 GetPrivateProfileString(INI_EXPIRATION, INI_BEEP, "No",
858 defname, sizeof(defname), KERBEROS_INI);
859 beep = _stricmp(defname, "Yes") == 0;
860 SendDlgItemMessage(hwnd, IDD_BEEP, BM_SETCHECK, beep, 0);
864 } /* opts_initdialog */
868 * Function: Process WM_COMMAND messages for the options dialog.
871 * hwnd - the window recieving the message.
873 * wparam - id of the command item
875 * lparam - LOWORD=hwnd of control, HIWORD=notification message.
877 * Returns: TRUE if initialized sucessfully, false otherwise.
885 char defname[FILENAME_MAX];
886 char newname[FILENAME_MAX];
894 /* Ticket duration */
895 lifetime = GetDlgItemInt(hwnd, IDD_LIFETIME, &b, FALSE);
898 MessageBox(hwnd, "Lifetime must be a number!", "", MB_OK | MB_ICONEXCLAMATION);
902 _itoa(lifetime, defname, 10);
903 b = WritePrivateProfileString(INI_OPTIONS, INI_DURATION, defname, KERBEROS_INI);
907 GetDlgItemText(hwnd, IDD_CONF, newname, sizeof(newname));
909 rc = GetWindowsDirectory(defname, sizeof(defname));
912 strcat(defname, "\\");
913 strcat(defname, DEF_KRB_CONF);
914 if (_stricmp(newname, defname) == 0 || !newname[0])
918 b = WritePrivateProfileString(INI_FILES, INI_KRB_CONF, p, KERBEROS_INI);
921 /* krb.realms file */
922 GetDlgItemText(hwnd, IDD_REALMS, newname, sizeof(newname));
924 rc = GetWindowsDirectory(defname, sizeof(defname));
927 strcat(defname, "\\");
928 strcat(defname, DEF_KRB_REALMS);
929 if (_stricmp(newname, defname) == 0 || !newname[0])
933 b = WritePrivateProfileString(INI_FILES, INI_KRB_REALMS, p, KERBEROS_INI);
936 /* Credential cache file */
938 GetDlgItemText(hwnd, IDD_CCACHE, newname, sizeof(newname));
940 rc = GetWindowsDirectory(defname, sizeof(defname));
943 strcat(defname, "\\");
944 strcat(defname, "krb5cc");
945 if (*newname == '\0')
946 strcpy (newname, defname);
947 if (_stricmp(newname, defname) == 0 || *newname == '\0')
951 b = WritePrivateProfileString(INI_FILES, INI_KRB_CCACHE, p, KERBEROS_INI);
954 if (strcmp (ccname, newname)) { // Did we change ccache file?
955 krb5_error_code code;
958 code = k5_init_ccache (&cctemp);
959 if (code) { // Problem opening new one?
961 "while changing ccache.\r\nRestoring old ccache.");
962 b = WritePrivateProfileString(INI_FILES, INI_KRB_CCACHE,
963 ccname, KERBEROS_INI);
965 code = krb5_cc_close (k5_context, k5_ccache);
966 k5_ccache = cctemp; // Copy new into old
967 if (k5_name_from_ccache (k5_ccache)) {
968 kwin_init_name (GetParent(hwnd), "");
969 kwin_set_default_focus(GetParent(hwnd));
971 ticket_init_list (GetDlgItem (GetParent(hwnd),
978 /* Expiration action */
979 alert = (BOOL) SendDlgItemMessage(hwnd, IDD_ALERT, BM_GETCHECK, 0, 0);
980 p = (alert) ? "Yes" : "No";
981 b = WritePrivateProfileString(INI_EXPIRATION, INI_ALERT, p, KERBEROS_INI);
984 beep = (BOOL) SendDlgItemMessage(hwnd, IDD_BEEP, BM_GETCHECK, 0, 0);
985 p = (beep) ? "Yes" : "No";
986 b = WritePrivateProfileString(INI_EXPIRATION, INI_BEEP, p, KERBEROS_INI);
989 EndDialog(hwnd, IDOK);
994 EndDialog(hwnd, IDCANCEL);
1001 } /* opts_command */
1005 * Function: Process dialog specific messages for the opts dialog.
1008 * hwnd - the dialog receiving the message.
1010 * message - the message to process.
1012 * wparam - wparam of the message.
1014 * lparam - lparam of the message.
1016 * Returns: TRUE if message handled locally, FALSE otherwise.
1018 static BOOL CALLBACK
1030 rc = opts_initdialog(hwnd, wparam, lparam);
1035 rc = opts_command(hwnd, wparam, lparam);
1042 } /* opts_dlg_proc */
1046 * Function: Display and process the options dialog.
1049 * hwnd - the parent window for the dialog
1051 * Returns: TRUE if the dialog completed successfully, FALSE otherwise.
1060 dlgproc = (FARPROC) MakeProcInstance(opts_dlg_proc, hinstance);
1061 assert(dlgproc != NULL);
1063 if (dlgproc == NULL)
1066 rc = DialogBox(hinstance, MAKEINTRESOURCE(ID_OPTS), hwnd, dlgproc);
1069 FreeProcInstance((FARPROC) dlgproc);
1077 * Function: Save most recent login triplets for placement on the
1078 * bottom of the file menu.
1081 * hwnd - the handle of the window containing the menu to edit.
1083 * name - A login name to save in the recent login list
1085 * instance - An instance to save in the recent login list
1087 * realm - A realm to save in the recent login list
1100 char fullname[MAX_K_NAME_SZ + 3];
1101 char menuitem[MAX_K_NAME_SZ + 3];
1104 strcpy(fullname, "&x ");
1105 strcat(fullname, name);
1106 strcat(fullname, ".");
1107 strcat(fullname, instance);
1108 strcat(fullname, "@");
1109 strcat(fullname, realm);
1111 hmenu = GetMenu(hwnd);
1112 assert(hmenu != NULL);
1114 hmenu = GetSubMenu(hmenu, 0);
1115 assert(hmenu != NULL);
1117 ctitems = GetMenuItemCount(hmenu);
1118 assert(ctitems >= FILE_MENU_ITEMS);
1120 if (ctitems == FILE_MENU_ITEMS) {
1121 rc = AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);
1127 for (i = FILE_MENU_ITEMS + 1; i < ctitems; i++) {
1128 GetMenuString(hmenu, i, menuitem, sizeof(menuitem), MF_BYPOSITION);
1130 if (strcmp(&fullname[3], &menuitem[3]) == 0) {
1131 rc = RemoveMenu(hmenu, i, MF_BYPOSITION);
1140 rc = InsertMenu(hmenu, FILE_MENU_ITEMS + 1, MF_BYPOSITION, 1, fullname);
1144 if (ctitems - FILE_MENU_ITEMS - 1 > FILE_MENU_MAX_LOGINS) {
1145 RemoveMenu(hmenu, ctitems - 1, MF_BYPOSITION);
1151 for (i = FILE_MENU_ITEMS + 1; i < ctitems; i++) {
1152 GetMenuString(hmenu, i, menuitem, sizeof(menuitem), MF_BYPOSITION);
1154 rc = RemoveMenu(hmenu, i, MF_BYPOSITION);
1157 menuitem[1] = '1' + id;
1158 rc = InsertMenu(hmenu, i, MF_BYPOSITION, IDM_FIRST_LOGIN + id, menuitem);
1164 } /* kwin_push_login */
1168 * Function: Initialize the logins on the file menu form the KERBEROS.INI
1172 * hwnd - handle of the dialog containing the file menu.
1175 kwin_init_file_menu (
1180 char login[sizeof(INI_LOGIN)+1];
1181 char menuitem[MAX_K_NAME_SZ + 3];
1185 hmenu = GetMenu(hwnd);
1186 assert(hmenu != NULL);
1188 hmenu = GetSubMenu(hmenu, 0);
1189 assert(hmenu != NULL);
1191 strcpy(login, INI_LOGIN);
1193 for (i = 0; i < FILE_MENU_MAX_LOGINS; i++) {
1194 login[sizeof(INI_LOGIN) - 1] = '1' + i;
1195 login[sizeof(INI_LOGIN)] = 0;
1196 GetPrivateProfileString(INI_RECENT_LOGINS, login, "",
1197 &menuitem[3], sizeof(menuitem) - 3, KERBEROS_INI);
1202 menuitem[1] = '1' + id;
1206 rc = AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);
1209 AppendMenu(hmenu, MF_STRING, IDM_FIRST_LOGIN + id, menuitem);
1214 } /* kwin_init_file_menu */
1218 * Function: Save the items on the file menu in the KERBEROS.INI file.
1221 * hwnd - handle of the dialog containing the file menu.
1224 kwin_save_file_menu (
1231 char menuitem[MAX_K_NAME_SZ + 3];
1232 char login[sizeof(INI_LOGIN)+1];
1235 hmenu = GetMenu(hwnd);
1236 assert(hmenu != NULL);
1238 hmenu = GetSubMenu(hmenu, 0);
1239 assert(hmenu != NULL);
1241 strcpy(login, INI_LOGIN);
1242 ctitems = GetMenuItemCount(hmenu);
1243 assert(ctitems >= FILE_MENU_ITEMS);
1246 for (i = FILE_MENU_ITEMS + 1; i < ctitems; i++) {
1247 GetMenuString(hmenu, i, menuitem, sizeof(menuitem), MF_BYPOSITION);
1248 login[sizeof(INI_LOGIN) - 1] = '1' + id;
1249 login[sizeof(INI_LOGIN)] = 0;
1251 rc = WritePrivateProfileString(INI_RECENT_LOGINS, login, &menuitem[3], KERBEROS_INI);
1257 } /* kwin_save_file_menu */
1262 * Function: Given an expiration time, choose an appropriate
1266 * expiration time of expiration in time() compatible units
1268 * Returns: Handle of icon to display
1277 dt = expiration - time(NULL);
1278 dt = dt / 60; /* convert to minutes */
1280 ixicon = IDI_EXPIRED - IDI_FIRST_CLOCK;
1282 ixicon = IDI_TICKET - IDI_FIRST_CLOCK;
1284 ixicon = (int) (dt / 5);
1286 return kwin_icons[ixicon];
1288 } /* kwin_get_icon */
1292 * Function: Intialize name fields in the Kerberos dialog.
1295 * hwnd - the window recieving the message.
1297 * fullname - the full kerberos name to initialize with
1304 char name[ANAME_SZ];
1305 char instance[INST_SZ];
1306 char realm[REALM_SZ];
1309 if (fullname == NULL || fullname[0] == 0) {
1311 strcpy(name, krb_get_default_user());
1312 GetPrivateProfileString(INI_DEFAULTS, INI_INSTANCE, "",
1313 instance, sizeof(instance), KERBEROS_INI);
1314 krc = krb_get_lrealm(realm, 1);
1315 if (krc != KSUCCESS)
1317 GetPrivateProfileString(INI_DEFAULTS, INI_REALM, realm,
1318 realm, sizeof(realm), KERBEROS_INI);
1324 krb5_error_code code;
1327 GetPrivateProfileString (INI_DEFAULTS, INI_USER, "",
1328 name, sizeof(name), KERBEROS_INI);
1331 code = krb5_get_default_realm (k5_context, &ptr);
1333 strcpy (realm, ptr);
1336 GetPrivateProfileString(INI_DEFAULTS, INI_REALM, realm,
1337 realm, sizeof(realm), KERBEROS_INI);
1343 kname_parse(name, instance, realm, fullname);
1344 SetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance);
1348 krc = k5_kname_parse(name, realm, fullname);
1353 SetDlgItemText(hwnd, IDD_LOGIN_NAME, name);
1354 SetDlgItemText(hwnd, IDD_LOGIN_REALM, realm);
1356 } /* kwin_init_name */
1360 * Function: Set the focus to the name control if no name
1361 * exists, the realm control if no realm exists or the
1362 * password control. Uses PostMessage not SetFocus.
1365 * hwnd - the Window handle of the parent.
1368 kwin_set_default_focus (
1371 char name[ANAME_SZ];
1372 char realm[REALM_SZ];
1375 GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
1378 if (strlen(name) <= 0)
1379 hwnditem = GetDlgItem(hwnd, IDD_LOGIN_NAME);
1381 GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm));
1384 if (strlen(realm) <= 0)
1385 hwnditem = GetDlgItem(hwnd, IDD_LOGIN_REALM);
1387 hwnditem = GetDlgItem(hwnd, IDD_LOGIN_PASSWORD);
1390 PostMessage(hwnd, WM_NEXTDLGCTL, hwnditem, MAKELONG(1, 0));
1392 } /* kwin_set_default_focus */
1396 * Function: Save the values which live in the KERBEROS.INI file.
1399 * hwnd - the window handle of the dialog containing fields to
1406 char name[ANAME_SZ];
1407 char instance[INST_SZ];
1408 char realm[REALM_SZ];
1410 GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
1414 krb_set_default_user(name);
1415 GetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance, sizeof(instance));
1417 WritePrivateProfileString(INI_DEFAULTS, INI_INSTANCE, instance, KERBEROS_INI);
1421 WritePrivateProfileString(INI_DEFAULTS, INI_USER, name, KERBEROS_INI);
1425 GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm));
1427 WritePrivateProfileString(INI_DEFAULTS, INI_REALM, realm, KERBEROS_INI);
1429 kwin_push_login(hwnd, name, instance, realm);
1431 } /* kwin_save_name */
1435 * Function: Process WM_INITDIALOG messages. Set the fonts
1436 * for all items on the dialog and populate the ticket list.
1437 * Also set the default values for user, instance and realm.
1440 * hwnd - the window recieving the message.
1442 * wparam - handle of the control for focus.
1444 * lparam - lparam from dialog box call.
1446 * Returns: TRUE if we didn't set the focus here,
1457 char name[ANAME_SZ];
1459 position_dialog(hwnd);
1460 ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST));
1461 kwin_init_file_menu(hwnd);
1462 kwin_init_name(hwnd, (char *) lparam);
1464 assert(hdc != NULL);
1466 memset(&lf, 0, sizeof(lf));
1467 lf.lfHeight = -MulDiv(9, GetDeviceCaps(hdc, LOGPIXELSY), 72);
1468 strcpy(lf.lfFaceName, "Arial");
1469 hfontdialog = CreateFontIndirect(&lf);
1470 assert(hfontdialog != NULL);
1472 if (hfontdialog == NULL) {
1473 ReleaseDC(NULL, hdc);
1478 lf.lfHeight = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72);
1479 hfonticon = CreateFontIndirect(&lf);
1480 assert(hfonticon != NULL);
1482 if (hfonticon == NULL) {
1483 ReleaseDC(NULL, hdc);
1488 ReleaseDC(NULL, hdc);
1490 set_dialog_font(hwnd, hfontdialog);
1491 GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
1494 if (strlen(name) > 0)
1495 SetFocus(GetDlgItem(hwnd, IDD_LOGIN_PASSWORD));
1497 SetFocus(GetDlgItem(hwnd, IDD_LOGIN_NAME));
1499 ShowWindow(hwnd, dlgncmdshow);
1500 kwin_timer_id = SetTimer(hwnd, 1, KWIN_UPDATE_PERIOD, NULL);
1501 assert(kwin_timer_id != 0);
1505 } /* kwin_initdialog */
1509 * Function: Process WM_DESTROY messages. Delete the font
1510 * created for use by the controls.
1513 * hwnd - the window recieving the message.
1531 ticket_destroy(GetDlgItem(hwnd, IDD_TICKET_LIST));
1533 if (hfontdialog != NULL)
1534 DeleteObject(hfontdialog);
1536 if (hfonticon != NULL)
1537 DeleteObject(hfonticon);
1539 kwin_save_file_menu(hwnd);
1540 GetWindowRect(hwnd, &r);
1541 sprintf(position, "[%d,%d,%d,%d]", r.left, r.top,
1542 r.right - r.left, r.bottom - r.top);
1543 b = WritePrivateProfileString(INI_DEFAULTS, INI_POSITION, position, KERBEROS_INI);
1546 KillTimer(hwnd, kwin_timer_id);
1550 } /* kwin_destroy */
1554 * Function: Retrievs item WindowRect in hwnd client
1558 * hwnditem - the item to retrieve
1560 * item - dialog in which into which to translate
1562 * r - rectangle returned
1570 GetWindowRect(hwnditem, r);
1571 ScreenToClient(hwnd, (LPPOINT) &(r->left));
1572 ScreenToClient(hwnd, (LPPOINT) &(r->right));
1578 * Function: Process WM_SIZE messages. Resize the
1579 * list and position the buttons attractively.
1582 * hwnd - the window receiving the message.
1584 * wparam - type of resize occuring
1586 * lparam - LOWORD=width of client area,
1587 * HIWORD=height of client area.
1600 int hmargin, vmargin;
1610 int titleleft[IDD_MAX_TITLE - IDD_MIN_TITLE + 1];
1612 if (wparam == SIZE_MINIMIZED)
1615 GetClientRect(hwnd, &rdlg);
1616 cxdlg = LOWORD(lparam);
1617 cydlg = HIWORD(lparam);
1620 * The ticket list title
1622 hwnditem = GetDlgItem(hwnd, IDD_TICKET_LIST_TITLE);
1624 if (hwnditem == NULL)
1627 windowrect(hwnditem, hwnd, &r);
1630 cx = cxdlg - 2 * hmargin;
1631 cy = r.bottom - r.top;
1632 MoveWindow(hwnditem, r.left, r.top, cx, cy, TRUE);
1639 for (i = IDD_MIN_BUTTON; i <= IDD_MAX_BUTTON; i++) {
1640 hwnditem = GetDlgItem(hwnd, i);
1641 windowrect(hwnditem, hwnd, &r);
1642 if (i == IDD_MIN_BUTTON)
1645 cx += r.right - r.left;
1648 gap = (cxdlg - 2 * hmargin - cx) / (IDD_MAX_BUTTON - IDD_MIN_BUTTON);
1650 for (i = IDD_MIN_BUTTON; i <= IDD_MAX_BUTTON; i++) {
1651 hwnditem = GetDlgItem(hwnd, i);
1652 windowrect(hwnditem, hwnd, &r);
1653 editbottom = -r.top;
1654 cx = r.right - r.left;
1655 cy = r.bottom - r.top;
1656 r.top = rdlg.bottom - vmargin - cy;
1657 MoveWindow(hwnditem, left, r.top, cx, cy, TRUE);
1663 * Edit fields: stretch boxes, keeping the gap between boxes equal to
1664 * what it was on entry.
1666 editbottom += r.top;
1668 hwnditem = GetDlgItem(hwnd, IDD_MIN_EDIT);
1669 windowrect(hwnditem, hwnd, &r);
1672 editbottom += r.bottom;
1673 titlebottom = -r.top;
1675 hwnditem = GetDlgItem(hwnd, IDD_MIN_EDIT + 1);
1676 windowrect(hwnditem, hwnd, &r);
1679 cx = cxdlg - 2 * hmargin - (IDD_MAX_EDIT - IDD_MIN_EDIT) * gap;
1680 cx = cx / (IDD_MAX_EDIT - IDD_MIN_EDIT + 1);
1683 for (i = IDD_MIN_EDIT; i <= IDD_MAX_EDIT; i++) {
1684 hwnditem = GetDlgItem(hwnd, i);
1685 windowrect(hwnditem, hwnd, &r);
1686 cy = r.bottom - r.top;
1687 r.top = editbottom - cy;
1688 MoveWindow(hwnditem, left, r.top, cx, cy, TRUE);
1689 titleleft[i-IDD_MIN_EDIT] = left;
1697 titlebottom += r.top;
1698 windowrect(GetDlgItem(hwnd, IDD_MIN_TITLE), hwnd, &r);
1699 titlebottom += r.bottom;
1700 listbottom = -r.top;
1702 for (i = IDD_MIN_TITLE; i <= IDD_MAX_TITLE; i++) {
1703 hwnditem = GetDlgItem(hwnd, i);
1704 windowrect(hwnditem, hwnd, &r);
1705 cx = r.right - r.left;
1706 cy = r.bottom - r.top;
1707 r.top = titlebottom - cy;
1708 MoveWindow(hwnditem, titleleft[i-IDD_MIN_TITLE], r.top, cx, cy, TRUE);
1714 listbottom = r.top - listgap;
1715 hwnditem = GetDlgItem(hwnd, IDD_TICKET_LIST);
1716 windowrect(hwnditem, hwnd, &r);
1718 cx = cxdlg - 2 * hmargin;
1719 cy = listbottom - r.top;
1720 MoveWindow(hwnditem, r.left, r.top, cx, cy, TRUE);
1728 * Function: Process WM_GETMINMAXINFO messages
1731 * hwnd - the window recieving the message.
1735 * lparam - LPMINMAXINFO
1740 kwin_getminmaxinfo (
1747 lpmmi = (MINMAXINFO *) lparam;
1748 lpmmi->ptMinTrackSize.x = (KWIN_MIN_WIDTH * LOWORD(GetDialogBaseUnits())) / 4;
1749 lpmmi->ptMinTrackSize.y = (KWIN_MIN_HEIGHT * HIWORD(GetDialogBaseUnits())) / 8;
1753 } /* kwin_getminmaxinfo */
1757 * Function: Process WM_TIMER messages
1760 * hwnd - the window recieving the message.
1762 * wparam - the timer id.
1764 * lparam - timer callback proceedure
1782 char service[ANAME_SZ];
1783 char instance[INST_SZ];
1784 char realm[REALM_SZ];
1787 krb5_error_code code;
1788 krb5_cc_cursor cursor;
1795 return DefDlgProc(hwnd, WM_TIMER, wparam, lparam);
1798 ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST));
1802 InvalidateRect(hwnd, NULL, TRUE);
1808 ncred = krb_get_num_cred();
1809 for (i = 1; i <= ncred; i++) {
1810 krb_get_nth_cred(service, instance, realm, i);
1812 if (_stricmp(service, "krbtgt") == 0) {
1813 /* Warn if ticket will expire w/i TIME_BUFFER seconds */
1814 krb_get_cred(service, instance, realm, &c);
1815 expiration = c.issue_date + (long) c.lifetime * 5L * 60L;
1816 t = TIME_BUFFER + time(NULL);
1818 if (t >= expiration) {
1820 /* Don't alert because of stale tickets */
1821 if (t >= expiration + KWIN_UPDATE_PERIOD / 1000) {
1825 InvalidateRect(hwnd, NULL, TRUE);
1835 code = krb5_cc_start_seq_get (k5_context, k5_ccache, &cursor);
1838 code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &cred);
1841 n = krb5_princ_component(k5_context, cred.server, 0)->length;
1842 s = krb5_princ_component(k5_context, cred.server, 0)->data;
1843 if (n != KRB5_TGS_NAME_SIZE)
1845 if (memcmp (KRB5_TGS_NAME, s, KRB5_TGS_NAME_SIZE))
1848 /* Warn if ticket will expire w/i TIME_BUFFER seconds */
1849 expiration = cred.times.endtime;
1850 t = TIME_BUFFER + time(NULL);
1852 if (t >= expiration) {
1854 /* Don't alert because of stale tickets */
1855 if (t >= expiration + KWIN_UPDATE_PERIOD / 1000) {
1859 InvalidateRect(hwnd, NULL, TRUE);
1865 if (code == 0 || code == KRB5_CC_END)
1866 krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor);
1872 InvalidateRect(hwnd, NULL, TRUE);
1880 MessageBeep(MB_ICONEXCLAMATION);
1883 if (IsIconic(hwnd)) {
1884 hwndfocus = GetFocus();
1885 ShowWindow(hwnd, SW_RESTORE);
1886 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
1887 SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
1888 SetFocus(hwndfocus);
1891 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
1892 SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
1898 InvalidateRect(hwnd, NULL, TRUE);
1906 * Function: Process WM_COMMAND messages
1909 * hwnd - the window recieving the message.
1911 * wparam - id of the command item
1913 * lparam - LOWORD=hwnd of control, HIWORD=notification message.
1915 * Returns: TRUE if initialized sucessfully, false otherwise.
1923 char name[ANAME_SZ];
1924 char realm[REALM_SZ];
1925 char password[MAX_KPW_LEN];
1929 char menuitem[MAX_K_NAME_SZ + 3];
1930 char copyright[128];
1933 char instance[INST_SZ];
1939 krb5_error_code code;
1940 krb5_principal principal;
1942 krb5_principal server;
1944 krb5_int32 sec, usec;
1948 EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), krb_get_num_cred() > 0);
1952 EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), k5_get_num_cred(0) > 0);
1955 GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
1957 blogin = strlen(name) > 0;
1960 GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm));
1962 blogin = strlen(realm) > 0;
1966 GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password));
1967 blogin = strlen(password) > 0;
1970 EnableWindow(GetDlgItem(hwnd, IDD_LOGIN), blogin);
1971 id = (blogin) ? IDD_LOGIN : IDD_PASSWORD_CR2;
1972 SendMessage(hwnd, DM_SETDEFID, id, 0);
1974 if (HIWORD(lparam) != BN_CLICKED && HIWORD(lparam) != 0 && HIWORD(lparam) != 1)
1977 if (wparam >= IDM_FIRST_LOGIN && wparam < IDM_FIRST_LOGIN + FILE_MENU_MAX_LOGINS) {
1978 hmenu = GetMenu(hwnd);
1979 assert(hmenu != NULL);
1981 hmenu = GetSubMenu(hmenu, 0);
1982 assert(hmenu != NULL);
1984 if (!GetMenuString(hmenu, wparam, menuitem, sizeof(menuitem), MF_BYCOMMAND))
1988 kwin_init_name(hwnd, &menuitem[3]);
1996 WSACancelBlockingCall();
1997 WinHelp(hwnd, KERBEROS_HLP, HELP_QUIT, 0);
2002 case IDD_PASSWORD_CR2: // Make CR == TAB
2003 id = GetDlgCtrlID(GetFocus());
2006 if (id == IDD_MAX_EDIT)
2007 PostMessage(hwnd, WM_NEXTDLGCTL,
2008 GetDlgItem(hwnd, IDD_MIN_EDIT), MAKELONG(1, 0));
2010 PostMessage(hwnd, WM_NEXTDLGCTL, 0, 0);
2018 GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
2020 GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm));
2022 GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password));
2026 GetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance, sizeof(instance));
2030 hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
2031 lifetime = GetPrivateProfileInt(INI_OPTIONS, INI_DURATION,
2032 DEFAULT_TKT_LIFE * 5, KERBEROS_INI);
2033 start_blocking_hook(BLOCK_MAX_SEC);
2036 lifetime = (lifetime + 4) / 5;
2037 krc = krb_get_pw_in_tkt(name, instance, realm, "krbtgt", realm,
2038 lifetime, password);
2043 principal = server = NULL;
2044 memset(&creds, 0, sizeof(creds));
2046 sprintf (menuitem, "%s@%s", name, realm);
2047 code = krb5_parse_name(k5_context, menuitem, &principal);
2050 code = krb5_cc_initialize(k5_context, k5_ccache, principal);
2053 code = krb5_build_principal_ext(k5_context, &server,
2054 krb5_princ_realm(k5_context, principal)->length,
2055 krb5_princ_realm(k5_context, principal)->data,
2056 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
2057 krb5_princ_realm(k5_context, principal)->length,
2058 krb5_princ_realm(k5_context, principal)->data, 0);
2061 creds.client = principal;
2062 creds.server = server;
2064 code = krb5_us_timeofday(k5_context, &sec, &usec);
2066 code = krb5_timeofday(k5_context, &now);
2068 if (labs(now-sec) > 60*60) { // Off by more than an hour
2069 MessageBox (NULL, "DEBUG: timeofday != us_timeofday", NULL, 0);
2072 creds.times.starttime = 0;
2073 creds.times.endtime = sec + 60L * lifetime;
2074 creds.times.renew_till = 0;
2076 code = krb5_get_in_tkt_with_password(k5_context, 0, NULL,
2077 NULL, NULL, password, k5_ccache, &creds, 0);
2081 krb5_free_principal(k5_context, principal);
2083 krb5_free_principal(k5_context, server);
2087 end_blocking_hook();
2089 kwin_set_default_focus(hwnd);
2092 if (krc != KSUCCESS) {
2093 MessageBox(hwnd, krb_get_err_text(krc), "",
2094 MB_OK | MB_ICONEXCLAMATION);
2102 com_err (NULL, code, "while logging in");
2107 SetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, "");
2108 kwin_save_name(hwnd);
2112 case LOGIN_AND_EXIT:
2113 SendMessage(hwnd, WM_COMMAND, IDM_EXIT, 0);
2116 case LOGIN_AND_MINIMIZE:
2117 ShowWindow(hwnd, SW_MINIMIZE);
2123 case IDD_TICKET_DELETE:
2129 if (krc != KSUCCESS)
2130 MessageBox(hwnd, krb_get_err_text(krc), "",
2131 MB_OK | MB_ICONEXCLAMATION);
2135 code = k5_dest_tkt ();
2138 kwin_set_default_focus(hwnd);
2143 case IDD_CHANGE_PASSWORD:
2146 password_dialog(hwnd);
2147 kwin_set_default_focus(hwnd);
2158 case IDM_HELP_INDEX:
2159 WinHelp(hwnd, KERBEROS_HLP, HELP_INDEX, 0);
2164 ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST));
2169 strcpy(copyright, " Kerberos 4 for Windows\n");
2172 strcpy(copyright, " Kerberos 5 for Windows\n");
2174 strcat(copyright, "\n Version 1.00\n\n");
2175 strcat(copyright, " For support, contact:\n");
2176 strcat(copyright, ORGANIZATION);
2177 strcat(copyright, " - (415) 903-1400");
2178 MessageBox(hwnd, copyright, "Kerberos", MB_OK);
2185 } /* kwin_command */
2189 * Function: Process WM_SYSCOMMAND messages by setting
2190 * the focus to the password or name on restore.
2193 * hwnd - the window recieving the message.
2195 * wparam - the syscommand option.
2207 if ((wparam & 0xFFF0) == SC_RESTORE)
2208 kwin_set_default_focus(hwnd);
2210 if ((wparam & 0xFFF0) == SC_CLOSE) {
2211 SendMessage(hwnd, WM_COMMAND, IDM_EXIT, 0);
2216 return DefDlgProc(hwnd, WM_SYSCOMMAND, wparam, lparam);
2218 } /* kwin_syscommand */
2222 * Function: Process WM_PAINT messages by displaying an
2223 * informative icon when we are iconic.
2226 * hwnd - the window recieving the message.
2243 time_t expiration = 0;
2250 char service[ANAME_SZ];
2251 char instance[INST_SZ];
2252 char realm[REALM_SZ];
2256 krb5_error_code code;
2257 krb5_cc_cursor cursor;
2263 if (!IsIconic(hwnd))
2264 return DefDlgProc(hwnd, WM_PAINT, wparam, lparam);
2267 ncred = krb_get_num_cred();
2269 for (i = 1; i <= ncred; i++) {
2270 krb_get_nth_cred(service, instance, realm, i);
2271 krb_get_cred(service, instance, realm, &c);
2272 if (_stricmp(c.service, "krbtgt") == 0) {
2273 expiration = c.issue_date - kwin_get_epoch() + (long) c.lifetime * 5L * 60L;
2280 code = krb5_cc_start_seq_get (k5_context, k5_ccache, &cursor);
2283 code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c);
2286 n = krb5_princ_component(k5_context, c.server, 0)->length;
2287 service = krb5_princ_component(k5_context, c.server, 0)->data;
2288 if (n != KRB5_TGS_NAME_SIZE)
2290 if (memcmp (KRB5_TGS_NAME, service, KRB5_TGS_NAME_SIZE))
2292 expiration = c.times.endtime;
2296 if (code == 0 || code == KRB5_CC_END)
2297 krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor);
2300 hdc = BeginPaint(hwnd, &ps);
2301 GetClientRect(hwnd, &r);
2302 DefWindowProc(hwnd, WM_ICONERASEBKGND, hdc, 0);
2304 if (expiration == 0) {
2305 strcpy(buf, KWIN_DIALOG_NAME);
2306 hicon = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_KWIN));
2309 hicon = kwin_get_icon(expiration);
2310 dt = (expiration - time(NULL)) / 60;
2313 sprintf(buf, "%s - %s", KWIN_DIALOG_NAME, "Expired");
2316 sprintf(buf, "%s - %ld min", KWIN_DIALOG_NAME, dt);
2320 sprintf(buf, "%s - %ld hr", KWIN_DIALOG_NAME, dt);
2327 DrawIcon(hdc, r.left, r.top, hicon);
2328 EndPaint(hwnd, &ps);
2329 SetWindowText(hwnd, buf);
2337 * Function: Window proceedure for the Kerberos control panel dialog.
2340 * hwnd - the window receiving the message.
2342 * message - the message to process.
2344 * wparam - wparam of the message.
2346 * lparam - lparam of the message.
2348 * Returns: message dependent value.
2350 LRESULT __export CALLBACK
2360 if (message == wm_kerberos_changed) { /* Message from the ccache */
2361 n = ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST));
2362 EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), n > 0);
2368 case WM_GETMINMAXINFO:
2369 rc = kwin_getminmaxinfo(hwnd, wparam, lparam);
2373 rc = kwin_destroy(hwnd, wparam, lparam);
2376 case WM_MEASUREITEM:
2377 if (wparam == IDD_TICKET_LIST) {
2378 rc = ticket_measureitem(hwnd, wparam, lparam);
2384 if (wparam == IDD_TICKET_LIST) {
2385 rc = ticket_drawitem(hwnd, wparam, lparam);
2392 SetCursor(LoadCursor(NULL, IDC_WAIT));
2398 rc = kwin_size(hwnd, wparam, lparam);
2402 rc = kwin_syscommand(hwnd, wparam, lparam);
2406 rc = kwin_timer(hwnd, wparam, lparam);
2410 rc = kwin_paint(hwnd, wparam, lparam);
2414 if (!IsIconic(hwnd))
2418 case WM_KWIN_SETNAME:
2419 kwin_init_name(hwnd, (char *) lparam);
2422 return DefDlgProc(hwnd, message, wparam, lparam);
2424 } /* kwin_wnd_proc */
2428 * Function: Dialog procedure called by the dialog manager
2429 * to process dialog specific messages.
2432 * hwnd - the dialog receiving the message.
2434 * message - the message to process.
2436 * wparam - wparam of the message.
2438 * lparam - lparam of the message.
2440 * Returns: TRUE if message handled locally, FALSE otherwise.
2442 static BOOL CALLBACK
2453 return kwin_initdialog(hwnd, wparam, lparam);
2456 rc = kwin_command(hwnd, wparam, lparam);
2462 } /* kwin_dlg_proc */
2466 * Function: Initialize the kwin dialog class.
2469 * hinstance - the instance to initialize
2471 * Returns: TRUE if dialog class registration is sucessfully, false otherwise.
2475 HINSTANCE hinstance)
2480 class.style = CS_HREDRAW | CS_VREDRAW;
2481 class.lpfnWndProc = (WNDPROC) kwin_wnd_proc;
2482 class.cbClsExtra = 0;
2483 class.cbWndExtra = DLGWINDOWEXTRA;
2484 class.hInstance = hinstance;
2486 // LoadIcon(hinstance, MAKEINTRESOURCE(IDI_KWIN));
2487 class.hCursor = NULL;
2488 class.hbrBackground = NULL;
2489 class.lpszMenuName = NULL;
2490 class.lpszClassName = KWIN_DIALOG_CLASS;
2492 rc = RegisterClass (&class);
2501 * Function: Initialize the KWIN application. This routine should
2502 * only be called if no previous instance of the application
2503 * exists. Currently it only registers a class for the kwin
2507 * hinstance - the instance to initialize
2509 * Returns: TRUE if initialized sucessfully, false otherwise.
2513 HINSTANCE hinstance)
2518 wm_kerberos_changed = krb_get_notification_message();
2522 wm_kerberos_changed = krb5_get_notification_message();
2525 rc = kwin_init(hinstance);
2529 } /* init_application */
2533 * Function: Quits the KWIN application. This routine should
2534 * be called when the last application instance exits.
2537 * hinstance - the instance which is quitting.
2539 * Returns: TRUE if initialized sucessfully, false otherwise.
2543 HINSTANCE hinstance)
2546 } /* quit_application */
2550 * Function: Initialize the current instance of the KWIN application.
2553 * hinstance - the instance to initialize
2555 * ncmdshow - show flag to indicate wheather to come up minimized
2558 * Returns: TRUE if initialized sucessfully, false otherwise.
2562 HINSTANCE hinstance,
2565 WORD versionrequested;
2571 versionrequested = 0x0101; /* We need version 1.1 */
2572 rc = WSAStartup(versionrequested, &wsadata);
2574 MessageBox(NULL, "Couldn't initialize Winsock library", "", MB_OK | MB_ICONSTOP);
2579 if (versionrequested != wsadata.wVersion) {
2581 MessageBox(NULL, "Winsock version 1.1 not available", "", MB_OK | MB_ICONSTOP);
2587 * Set up expiration action
2589 GetPrivateProfileString(INI_EXPIRATION, INI_ALERT, "No",
2590 buf, sizeof(buf), KERBEROS_INI);
2591 alert = _stricmp(buf, "Yes") == 0;
2592 GetPrivateProfileString(INI_EXPIRATION, INI_BEEP, "No",
2593 buf, sizeof(buf), KERBEROS_INI);
2594 beep = _stricmp(buf, "Yes") == 0;
2599 for (i = IDI_FIRST_CLOCK; i <= IDI_LAST_CLOCK; i++)
2600 kwin_icons[i - IDI_FIRST_CLOCK] = LoadIcon(hinstance, MAKEINTRESOURCE(i));
2603 krb_start_session(NULL);
2608 krb5_error_code code;
2610 code = krb5_init_context(&k5_context);
2612 krb5_init_ets(k5_context);
2613 code = k5_init_ccache (&k5_ccache);
2616 com_err (NULL, code, "while initializing program");
2619 k5_name_from_ccache (k5_ccache);
2625 } /* init_instance */
2629 * Function: Quits the current instance of the KWIN application.
2632 * hinstance - the instance to quit.
2634 * Returns: TRUE if termination was sucessfully, false otherwise.
2638 HINSTANCE hinstance)
2643 krb_end_session((char *) NULL);
2646 #ifdef KRB5 /* FIXME */
2647 krb5_cc_close (k5_context, k5_ccache);
2653 * Unload clock icons
2655 for (i = IDI_FIRST_CLOCK; i <= IDI_LAST_CLOCK; i++)
2656 DestroyIcon(kwin_icons[i - IDI_FIRST_CLOCK]);
2660 } /* quit_instance */
2664 * Function: Main routine called on program invocation.
2667 * hinstance - the current instance
2669 * hprevinstance - previous instance if one exists or NULL.
2671 * cmdline - the command line string passed by Windows.
2673 * ncmdshow - show flag to indicate wheather to come up minimized
2676 * Returns: TRUE if initialized sucessfully, false otherwise.
2681 HINSTANCE hprevinstance,
2690 char buf[MAX_K_NAME_SZ + 9];
2691 char name[MAX_K_NAME_SZ];
2693 strcpy(buf, cmdline);
2694 action = LOGIN_AND_RUN;
2696 p = strtok(buf, " ,");
2699 if (_stricmp(p, "/exit") == 0)
2700 action = LOGIN_AND_EXIT;
2701 else if (_stricmp(p, "/minimize") == 0)
2702 action = LOGIN_AND_MINIMIZE;
2706 p = strtok(NULL, " ,");
2709 dlgncmdshow = ncmdshow;
2713 * If a previous instance of this application exits, bring it
2714 * to the front and exit.
2716 if (hprevinstance != NULL) {
2717 hwnd = FindWindow(KWIN_DIALOG_CLASS, NULL);
2719 if (IsWindow(hwnd) && IsWindowVisible(hwnd)) {
2720 if (GetWindowWord(hwnd, GWW_HINSTANCE) == hprevinstance) {
2722 SendMessage(hwnd, WM_KWIN_SETNAME, 0, (LONG) name);
2724 ShowWindow(hwnd, ncmdshow);
2725 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
2726 SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
2733 if (hprevinstance == NULL)
2734 if (!init_application(hinstance))
2737 if (!init_instance(hinstance, ncmdshow))
2740 dlgproc = (FARPROC) MakeProcInstance(kwin_dlg_proc, hinstance);
2741 assert(dlgproc != NULL);
2743 if (dlgproc == NULL)
2746 hwnd = CreateDialogParam(hinstance, MAKEINTRESOURCE (ID_KWIN),
2747 HWND_DESKTOP, dlgproc, (LONG) name);
2748 assert(hwnd != NULL);
2752 haccel = LoadAccelerators(hinstance, MAKEINTRESOURCE(IDA_KWIN));
2753 assert(hwnd != NULL);
2755 while (GetMessage(&msg, NULL, 0, 0)) {
2756 if (!TranslateAccelerator(hwnd, haccel, &msg) &&
2757 !IsDialogMessage(hwnd, &msg)) {
2758 TranslateMessage(&msg);
2759 DispatchMessage(&msg);
2763 DestroyWindow(hwnd);
2764 FreeProcInstance((FARPROC) dlgproc);
2773 #define WM_ASYNC_COMPLETED (WM_USER + 1)
2774 #define GETHOSTBYNAME_CLASS "krb_gethostbyname"
2775 static HTASK htaskasync; /* Asynchronos call in progress */
2776 static BOOL iscompleted; /* True when async call is completed */
2779 * This routine is called to cancel a blocking hook call within
2780 * the Kerberos library. The need for this routine arises due
2781 * to bugs which exist in existing WINSOCK implementations. We
2782 * blocking gethostbyname with WSAASyncGetHostByName. In order
2783 * to cancel such an operation, this routine must be called.
2784 * Applications may call this routine in addition to calls to
2785 * WSACancelBlockingCall to get any sucy Async calls canceled.
2786 * Return values are as they would be for WSACancelAsyncRequest.
2789 krb_cancel_blocking_call(void)
2791 if (htaskasync == NULL)
2795 return WSACancelAsyncRequest(htask);
2797 } /* krb_cancel_blocking_call */
2801 * Window proceedure for temporary Windows created in
2802 * krb_gethostbyname. Fields completion messages.
2804 LRESULT __export CALLBACK krb_gethostbyname_wnd_proc(
2810 if (message == WM_ASYNC_COMPLETED) {
2815 return DefWindowProc(hwnd, message, wparam, lparam);
2817 } /* krb_gethostbyname_wnd_proc */
2821 * The WINSOCK routine gethostbyname has a bug in both FTP and NetManage
2822 * implementations which causes the blocking hook, if any, not to be
2823 * called. This routine attempts to work around the problem by using
2824 * the async routines to emulate the functionality of the synchronous
2827 struct hostent FAR *PASCAL FAR
2829 const char FAR *name)
2832 char buf[MAXGETHOSTSTRUCT];
2833 BOOL FARPROC blockinghook;
2835 static BOOL isregistered;
2837 blockinghook = WSASetBlockingHook(NULL);
2838 WSASetBlockingHook(blockinghook);
2840 if (blockinghook == NULL)
2841 return gethostbyname(name);
2843 if (RegisterWndClass() == NULL)
2844 return gethostbyname(name);
2846 if (!isregistered) {
2848 wc.lpfnWndProc = gethostbyname_wnd_proc;
2851 wc.hInstance = hlibinstance;
2854 wc.hbrBackground = NULL;
2855 wc.lpszMenuName = NULL;
2856 wc.lpszClassName = GETHOSTBYNAME_CLASS;
2858 if (!RegisterClass(&wc))
2859 return gethostbyname(name);
2861 isregistered = TRUE;
2864 hwnd = CreateWindow(GETHOSTBYNAME_CLASS, "", WS_OVERLAPPED,
2865 -100, -100, 0, 0, HWND_DESKTOP, NULL, hlibinstance, NULL);
2867 return gethostbyname(name);
2870 WSAAsyncGetHostByName(hwnd, WM_ASYNC_COMPLETED, name, buf, sizeof(buf));
2871 b = blockinghook(NULL);
2873 } /* krb_gethostbyname */
2880 * Function: destroys all tickets in a k5 ccache
2885 * Returns: K5 error code (0 == success)
2887 static krb5_error_code
2888 k5_dest_tkt (void) {
2889 krb5_error_code code;
2890 krb5_principal princ;
2892 if (code = krb5_cc_get_principal(k5_context, k5_ccache, &princ)) {
2893 com_err (NULL, code, "while retrieving principal name");
2897 code = krb5_cc_initialize (k5_context, k5_ccache, princ);
2899 com_err (NULL, code, "when re-initializing cache");
2900 krb5_free_principal (k5_context, princ);
2904 krb5_free_principal (k5_context, princ);
2912 * Returns: number of creds in the credential cache, -1 on error
2916 k5_get_num_cred (int verbose) {
2917 krb5_error_code code;
2918 krb5_cc_cursor cursor;
2922 /* Turn off OPENCLOSE and leave open while we use ccache */
2923 if (code = krb5_cc_set_flags(k5_context, k5_ccache, 0)) {
2924 if (code == KRB5_FCC_NOFILE)
2927 com_err (NULL, code,
2928 "while setting cache flags (ticket cache %s)",
2929 krb5_cc_get_name(k5_context, k5_ccache));
2933 if (code = krb5_cc_start_seq_get(k5_context, k5_ccache, &cursor)) {
2935 com_err (NULL, code, "while starting to retrieve tickets.");
2939 while (1) { /* Loop and get creds */
2940 code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c);
2946 if (code != KRB5_CC_END) { /* Error while looping??? */
2948 com_err (NULL, code, "while retrieving a ticket.");
2952 if (code = krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor)) {
2954 com_err (NULL, code, "while closing ccache.");
2955 } else if (code = krb5_cc_set_flags(k5_context, k5_ccache, KRB5_TC_OPENCLOSE)) {
2957 com_err(NULL, code, "while closing ccache.");
2964 k5_get_num_cred2 () {
2965 krb5_error_code code;
2966 krb5_cc_cursor cursor;
2970 code = krb5_cc_start_seq_get (k5_context, k5_ccache, &cursor);
2971 if (code == KRB5_FCC_NOFILE)
2975 code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c);
2980 if (code == KRB5_CC_END)
2981 krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor);
2987 * Function: Parses fullname into name, instance and realm
2990 * name - buffer filled with name of user
2992 * realm - buffer filled with realm of user
2994 * fullname - string in form name.instance@realm
2999 k5_kname_parse (char *name, char *realm, char *fullname) {
3000 char *ptr; /* For parsing */
3002 ptr = strchr (fullname, '@'); /* Name, realm separator */
3004 if (ptr != NULL) /* Get realm */
3005 strcpy (realm, ptr + 1);
3009 if (ptr != NULL) { /* Get the name */
3010 strncpy (name, fullname, ptr - fullname);
3011 name[ptr - fullname] = '\0';
3013 strcpy (name, fullname);
3015 ptr = strchr (name, '.'); /* K4 compatability */
3022 * Function: Initializes ccache and catches illegal caches such as
3023 * bad format or no permissions.
3026 * ccache - credential cache structure to use
3028 * Returns: krb5_error_code
3030 static krb5_error_code
3031 k5_init_ccache (krb5_ccache *ccache) {
3032 krb5_error_code code;
3033 krb5_principal princ;
3036 code = krb5_cc_default (k5_context, ccache); // Initialize the ccache
3040 code = krb5_cc_get_principal (k5_context, *ccache, &princ);
3041 if (code == KRB5_FCC_NOFILE) { // Doesn't exist yet
3042 fp = fopen (krb5_cc_get_name(k5_context, *ccache), "w");
3043 if (fp == NULL) // Can't open it
3044 return KRB5_FCC_PERM;
3048 if (code) { // Bad, delete and try again
3049 remove (krb5_cc_get_name(k5_context, *ccache));
3050 code = krb5_cc_get_principal (k5_context, *ccache, &princ);
3051 if (code == KRB5_FCC_NOFILE) // Doesn't exist yet
3057 krb5_free_principal (k5_context, princ);
3062 * Function: Reads the name and realm out of the ccache.
3065 * ccache - credentials cache to get info from
3067 * name - buffer to hold user name
3069 * realm - buffer to hold the realm
3072 * Returns: TRUE if read names, FALSE if not
3076 k5_name_from_ccache (krb5_ccache k5_ccache) {
3077 krb5_error_code code;
3078 krb5_principal princ;
3079 char name[ANAME_SZ];
3080 char realm[REALM_SZ];
3083 if (code = krb5_cc_get_principal(k5_context, k5_ccache, &princ))
3086 code = krb5_unparse_name(k5_context, princ, &defname);
3088 krb5_free_principal (k5_context, princ);
3092 k5_kname_parse(name, realm, defname); // Extract the components
3093 WritePrivateProfileString(INI_DEFAULTS, INI_USER, name, KERBEROS_INI);
3094 WritePrivateProfileString(INI_DEFAULTS, INI_REALM, realm, KERBEROS_INI);
3096 krb5_free_principal(k5_context, princ);