diff options
author | Keith Vetter <keithv@fusion.com> | 1995-03-22 20:17:41 +0000 |
---|---|---|
committer | Keith Vetter <keithv@fusion.com> | 1995-03-22 20:17:41 +0000 |
commit | c3f88158d5a194b7e3fe1c655d45799521895847 (patch) | |
tree | b17a500398c28db0436e7962c1e1c23685d4bac6 /src/windows/cns/cns.c | |
parent | 43e4214cf96717848a5b68b970eaab83f80591da (diff) | |
download | krb5-c3f88158d5a194b7e3fe1c655d45799521895847.tar.gz krb5-c3f88158d5a194b7e3fe1c655d45799521895847.tar.xz krb5-c3f88158d5a194b7e3fe1c655d45799521895847.zip |
Added files to the windows/cns directory
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5189 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/windows/cns/cns.c')
-rw-r--r-- | src/windows/cns/cns.c | 2878 |
1 files changed, 2878 insertions, 0 deletions
diff --git a/src/windows/cns/cns.c b/src/windows/cns/cns.c new file mode 100644 index 0000000000..3fc8913dc4 --- /dev/null +++ b/src/windows/cns/cns.c @@ -0,0 +1,2878 @@ +/* + * cns.c + * + * Tabs 4 + * + * Main routine of the Kerberos user interface. Also handles + * all dialog level management functions. + * + * Copyright 1994 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * <mit-copyright.h>. + */ + +#if !defined(KRB5) && !defined(KRB4) + #define KRB5 1 +#endif + +#include <windows.h> +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <malloc.h> +#include <ctype.h> +#include <time.h> + +#ifdef KRB4 + #define DEFINE_SOCKADDR + #include "mit-copyright.h" + #include "krb.h" + #include "kadm.h" + #include "org.h" +#endif + +#ifdef KRB5 + #define NEED_SOCKETS + #include "krb5.h" + #include "krbini.h" + #include "com_err.h" + + #define DEFAULT_TKT_LIFE 120 + #define ANAME_SZ 40 + #define REALM_SZ 40 + #define SNAME_SZ 40 + #define INST_SZ 40 + #define MAX_KPW_LEN 128 + /* include space for '.' and '@' */ + #define MAX_K_NAME_SZ (ANAME_SZ + INST_SZ + REALM_SZ + 2) + #define ORGANIZATION "Cygnus Support" + + #define CREDENTIALS char +#endif + +#include "cns.h" +#include "tktlist.h" + +/* + * Constants + */ +#define BLOCK_MAX_SEC 30 /* Blocking timeout duration */ +#define KWIN_UPDATE_PERIOD 30000 /* Every 30 seconds update the screen */ +#define TIME_BUFFER 300 /* Pop-up time buffer in seconds */ +#define WM_KWIN_SETNAME (WM_USER+100) /* Sets the name fields in the dialog */ + +enum { /* Actions after login */ + LOGIN_AND_EXIT, + LOGIN_AND_MINIMIZE, + LOGIN_AND_RUN, +}; + +/* + * Globals + */ +static HICON kwin_icons[MAX_ICONS]; /* Icons depicting time */ +static HFONT hfontdialog = NULL; /* Font in which the dialog is drawn. */ +static HFONT hfonticon = NULL; /* Font for icon label */ +static HINSTANCE hinstance; +static int dlgncmdshow; /* ncmdshow from WinMain */ +static char confname[FILENAME_MAX]; /* current krb.conf location */ +static char realmsname[FILENAME_MAX]; /* current krb.realms location */ +static UINT wm_kerberos_changed; /* Registered message for cache changing */ +static int action; /* After login actions */ +static UINT kwin_timer_id; /* Timer being used for update */ +static BOOL alert; /* Actions on ticket expiration */ +static BOOL beep; +static BOOL alerted; /* TRUE when user already alerted */ +static BOOL isblocking = FALSE; /* TRUE when blocked in WinSock */ +static DWORD blocking_end_time; /* Ending tick count for blocking timeout */ +static FARPROC hook_instance; /* Intance handle for blocking hook function */ + +#ifdef KRB5 + krb5_context k5_context; + krb5_ccache k5_ccache; +#endif + +/*+ + * Function: Called during blocking operations. Implement a timeout + * if nothing occurs within the specified time, cancel the blocking + * operation. Also permit the user to press escape in order to + * cancel the blocking operation. + * + * Returns: TRUE if we got and dispatched a message, FALSE otherwise. + */ +BOOL __export CALLBACK +blocking_hook_proc (void) +{ + MSG msg; + BOOL rc; + + if (GetTickCount() > blocking_end_time) { + WSACancelBlockingCall(); + return FALSE; + } + + rc = (BOOL) PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); + if (!rc) + return FALSE; + + if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) { + WSACancelBlockingCall(); + blocking_end_time = msg.time - 1; + return FALSE; + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + + return TRUE; + +} /* blocking_hook_proc */ + + +/*+ + * Function: Set up a blocking hook function. + * + * Parameters: + * timeout - # of seconds to block for before cancelling. + */ +static void +start_blocking_hook ( + int timeout) +{ + FARPROC proc; + + if (isblocking) + return; + + isblocking = TRUE; + blocking_end_time = GetTickCount() + (1000 * timeout); + hook_instance = MakeProcInstance(blocking_hook_proc, hinstance); + proc = WSASetBlockingHook(hook_instance); + assert(proc != NULL); + +} /* start_blocking_hook */ + + +/*+ + * Function: End the blocking hook fuction set up above. + */ +static void +end_blocking_hook (void) +{ + + FreeProcInstance(hook_instance); + WSAUnhookBlockingHook(); + isblocking = FALSE; + +} /* end_blocking_hook */ + + +/*+ + * Function: Centers the specified window on the screen. + * + * Parameters: + * hwnd - the window to center on the screen. + */ +static void +center_dialog ( + HWND hwnd) +{ + int scrwidth, scrheight; + int dlgwidth, dlgheight; + RECT r; + HDC hdc; + + if (hwnd == NULL) + return; + + GetWindowRect(hwnd, &r); + dlgwidth = r.right - r.left; + dlgheight = r.bottom - r.top ; + hdc = GetDC(NULL); + scrwidth = GetDeviceCaps(hdc, HORZRES); + scrheight = GetDeviceCaps(hdc, VERTRES); + ReleaseDC(NULL, hdc); + r.left = (scrwidth - dlgwidth) / 2; + r.top = (scrheight - dlgheight) / 2; + MoveWindow(hwnd, r.left, r.top, dlgwidth, dlgheight, TRUE); + +} /* center_dialog */ + + +/*+ + * Function: Positions the kwin dialog either to the saved location + * or the center of the screen if no saved location. + * + * Parameters: + * hwnd - the window to center on the screen. + */ +static void +position_dialog ( + HWND hwnd) +{ + int n; + int scrwidth, scrheight; + HDC hdc; + char position[256]; + int x, y, cx, cy; + + if (hwnd == NULL) + return; + + hdc = GetDC(NULL); + scrwidth = GetDeviceCaps(hdc, HORZRES); + scrheight = GetDeviceCaps(hdc, VERTRES); + ReleaseDC(NULL, hdc); + GetPrivateProfileString(INI_DEFAULTS, INI_POSITION, "", + position, sizeof(position), KERBEROS_INI); + + n = sscanf(position, " [%d , %d , %d , %d", &x, &y, &cx, &cy); + if (n != 4 || + x > scrwidth || + y > scrheight || + x + cx < 0 || + y + cy < 0) + center_dialog(hwnd); + else + MoveWindow(hwnd, x, y, cx, cy, TRUE); + +} /* position_dialog */ + + +/*+ + * Function: Set font of all dialog items. + * + * Parameters: + * hwnd - the dialog to set the font of + */ +static void +set_dialog_font ( + HWND hwnd, + HFONT hfont) +{ + hwnd = GetWindow(hwnd, GW_CHILD); + + while (hwnd != NULL) { + SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, 0); + hwnd = GetWindow(hwnd, GW_HWNDNEXT); + } + +} /* set_dialog_font */ + + +/*+ + * Function: Trim leading and trailing white space from a string. + * + * Parameters: + * s - the string to trim. + */ +void +trim ( + char *s) +{ + int l; + int i; + + for (i = 0; s[i]; i++) + if (s[i] != ' ' && s[i] != '\t') + break; + + l = strlen(&s[i]); + memmove(s, &s[i], l + 1); + + for (l--; l >= 0; l--) { + if (s[l] != ' ' && s[l] != '\t') + break; + } + s[l + 1] = 0; + +} /* trim */ + + +/*+ + * Function: This routine figures out the current time epoch and + * returns the conversion factor. It exists because Microloss + * screwed the pooch on the time() and _ftime() calls in its release + * 7.0 libraries. They changed the epoch to Dec 31, 1899! + */ +time_t +kwin_get_epoch (void) +{ + static struct tm jan_1_70 = {0, 0, 0, 1, 0, 70}; + time_t epoch = 0; + + epoch = -mktime(&jan_1_70); /* Seconds til 1970 localtime */ + epoch += _timezone; /* Seconds til 1970 GMT */ + + return epoch; + +} /* kwin_get_epoch */ + + +/*+ + * Function: Save the credentials for later restoration. + * + * Parameters: + * c - Returned pointer to saved credential cache. + * + * pname - Returned as principal name of session. + * + * pinstance - Returned as principal instance of session. + * + * ncred - Returned number of credentials saved. + */ +static void +push_credentials ( + CREDENTIALS **cp, + char *pname, + char *pinstance, + int *ncred) +{ +#ifdef KRB4 + int i; + char service[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + CREDENTIALS *c; + + if (krb_get_tf_fullname ((char *) 0, pname, pinstance, (char *) 0) != KSUCCESS) { + pname[0] = 0; + + pinstance[0] = 0; + } + + *ncred = krb_get_num_cred(); + if (*ncred <= 0) + return; + + c= malloc(*ncred * sizeof(CREDENTIALS)); + assert(c != NULL); + if (c == NULL) { + *ncred = 0; + + return; + } + + for (i = 0; i < *ncred; i++) { + krb_get_nth_cred(service, instance, realm, i + 1); + krb_get_cred(service, instance, realm, &c[i]); + } + + *cp = c; +#endif + +#ifdef KRB5 /* FIXME */ + return; +#endif + +} /* push_credentials */ + + +/*+ + * Function: Restore the saved credentials. + * + * c - Pointer to saved credential cache. + * + * pname - Principal name of session. + * + * pinstance - Principal instance of session. + * + * ncred - Number of credentials saved. + */ +static void +pop_credentials ( + CREDENTIALS *c, + char *pname, + char *pinstance, + int ncred) +{ +#ifdef KRB4 + int i; + + if (pname[0]) + in_tkt(pname, pinstance); + else + dest_tkt(); + + if (ncred <= 0) + return; + + for (i = 0; i < ncred; i++) { + krb_save_credentials(c[i].service, c[i].instance, c[i].realm, + c[i].session, c[i].lifetime, c[i].kvno, &(c[i].ticket_st), + c[i].issue_date); + } + + free(c); +#endif +#ifdef KRB5 /* FIXME */ + return; +#endif + +} /* pop_credentials */ + + +/*+ + * Function: Changes the password. + * + * Parameters: + * hwnd - the current window from which command was invoked. + * + * name - name of user to change password for + * + * instance - instance of user to change password for + * + * realm - realm in which to change password + * + * oldpw - the old password + * + * newpw - the new password to change to + * + * Returns: TRUE if change took place, FALSE otherwise. + */ +static BOOL +change_password ( + HWND hwnd, + char *name, + char *instance, + char *realm, + char *oldpw, + char *newpw) +{ +#ifdef KRB4 + des_cblock new_key; + char *ret_st; + int krc; + char *p; + CREDENTIALS *c; + int ncred; + char pname[ANAME_SZ]; + char pinstance[INST_SZ]; + + push_credentials(&c, pname, pinstance, &ncred); + krc = krb_get_pw_in_tkt( + name, instance, realm, PWSERV_NAME, KADM_SINST, 1, oldpw); + + if (krc != KSUCCESS) { + if (krc == INTK_BADPW) + p = "Old password is incorrect"; + else + p = krb_get_err_text(krc); + pop_credentials(c, pname, pinstance, ncred); + MessageBox(hwnd, p, "", MB_OK | MB_ICONEXCLAMATION); + + return FALSE; + } + + krc = kadm_init_link(PWSERV_NAME, KRB_MASTER, realm); + + if (krc != KSUCCESS) { + pop_credentials(c, pname, pinstance, ncred); + MessageBox(hwnd, kadm_get_err_text(krc), "", MB_OK | MB_ICONEXCLAMATION); + + return FALSE; + } + + des_string_to_key(newpw, new_key); + krc = kadm_change_pw2(new_key, newpw, &ret_st); + pop_credentials(c, pname, pinstance, ncred); + + if (ret_st != NULL) + free(ret_st); + + if (krc != KSUCCESS) { + MessageBox(hwnd, kadm_get_err_text(krc), "", MB_OK | MB_ICONEXCLAMATION); + + return FALSE; + } + + return TRUE; +#endif + +#ifdef KRB5 /* FIXME */ + MessageBox (NULL, "Changing passwords is not yet implemented", "", MB_ICONEXCLAMATION); + return TRUE; +#endif + +} /* change_password */ + +/*+ + * Function: Process WM_COMMAND messages for the password dialog. + * + * Parameters: + * hwnd - the window recieving the message. + * + * wparam - id of the command item + * + * lparam - LOWORD=hwnd of control, HIWORD=notification message. + * + * Returns: TRUE if initialized sucessfully, false otherwise. + */ +static LONG +password_command ( + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + char name[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + char oldpw[MAX_KPW_LEN]; + char newpw1[MAX_KPW_LEN]; + char newpw2[MAX_KPW_LEN]; + HCURSOR hcursor; + BOOL b; + int id; + + if (HIWORD(lparam) != BN_CLICKED) { + GetDlgItemText(hwnd, IDD_PASSWORD_NAME, name, sizeof(name)); + trim(name); + GetDlgItemText(hwnd, IDD_PASSWORD_REALM, realm, sizeof(realm)); + trim(realm); + GetDlgItemText(hwnd, IDD_OLD_PASSWORD, oldpw, sizeof(oldpw)); + GetDlgItemText(hwnd, IDD_NEW_PASSWORD1, newpw1, sizeof(newpw1)); + GetDlgItemText(hwnd, IDD_NEW_PASSWORD2, newpw2, sizeof(newpw2)); + b = strlen(name) && strlen(realm) && strlen(oldpw) && + strlen(newpw1) && strlen(newpw2); + EnableWindow(GetDlgItem(hwnd, IDOK), b); + id = (b) ? IDOK : IDD_PASSWORD_CR; + SendMessage(hwnd, DM_SETDEFID, id, 0); + + return FALSE; + } + + switch (wparam) { + case IDOK: + if (isblocking) + return TRUE; + + GetDlgItemText(hwnd, IDD_PASSWORD_NAME, name, sizeof(name)); + trim(name); + GetDlgItemText(hwnd, IDD_PASSWORD_INSTANCE, instance, sizeof(instance)); + trim(instance); + GetDlgItemText(hwnd, IDD_PASSWORD_REALM, realm, sizeof(realm)); + trim(realm); + GetDlgItemText(hwnd, IDD_OLD_PASSWORD, oldpw, sizeof(oldpw)); + GetDlgItemText(hwnd, IDD_NEW_PASSWORD1, newpw1, sizeof(newpw1)); + GetDlgItemText(hwnd, IDD_NEW_PASSWORD2, newpw2, sizeof(newpw2)); + + if (strcmp(newpw1, newpw2) != 0) { + MessageBox(hwnd, "The two passwords you entered don't match!", "", + MB_OK | MB_ICONEXCLAMATION); + SetDlgItemText(hwnd, IDD_NEW_PASSWORD1, ""); + SetDlgItemText(hwnd, IDD_NEW_PASSWORD2, ""); + PostMessage(hwnd, WM_NEXTDLGCTL, + GetDlgItem(hwnd, IDD_NEW_PASSWORD1), MAKELONG(1, 0)); + + return TRUE; + } + + hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + start_blocking_hook(BLOCK_MAX_SEC); + + if (change_password(hwnd, name, instance, realm, oldpw, newpw1)) + EndDialog(hwnd, IDOK); + else + PostMessage(hwnd, WM_NEXTDLGCTL, + GetDlgItem(hwnd, IDD_OLD_PASSWORD), MAKELONG(1, 0)); + + end_blocking_hook(); + SetCursor(hcursor); + + return TRUE; + + case IDCANCEL: + if (isblocking) + WSACancelBlockingCall(); + EndDialog(hwnd, IDCANCEL); + + return TRUE; + + case IDD_PASSWORD_CR: + id = GetDlgCtrlID(GetFocus()); + assert(id != 0); + + if (id == IDD_NEW_PASSWORD2) + PostMessage(hwnd, WM_NEXTDLGCTL, + GetDlgItem(hwnd, IDD_PASSWORD_NAME), MAKELONG(1, 0)); + else + PostMessage(hwnd, WM_NEXTDLGCTL, 0, 0); + + return TRUE; + + } + + return FALSE; + +} /* password_command */ + + +/*+ + * Function: Process WM_INITDIALOG messages for the password dialog. + * Set up all initial dialog values from the parent dialog. + * + * Parameters: + * hwnd - the window recieving the message. + * + * wparam - handle of the control for focus. + * + * lparam - lparam from dialog box call. + * + * Returns: TRUE if we didn't set the focus here, + * FALSE if we did. + */ +static BOOL +password_initdialog ( + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + char name[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + HWND hwndparent; + int id; + + center_dialog(hwnd); + set_dialog_font(hwnd, hfontdialog); + + hwndparent = GetParent(hwnd); + assert(hwndparent != NULL); + + GetDlgItemText(hwndparent, IDD_LOGIN_NAME, name, sizeof(name)); + trim(name); + SetDlgItemText(hwnd, IDD_PASSWORD_NAME, name); + + GetDlgItemText(hwndparent, IDD_LOGIN_INSTANCE, instance, sizeof(instance)); + trim(instance); + SetDlgItemText(hwnd, IDD_PASSWORD_INSTANCE, instance); + + GetDlgItemText(hwndparent, IDD_LOGIN_REALM, realm, sizeof(realm)); + trim(realm); + SetDlgItemText(hwnd, IDD_PASSWORD_REALM, realm); + + if (strlen(name) == 0) + id = IDD_PASSWORD_NAME; + else if (strlen(realm) == 0) + id = IDD_PASSWORD_REALM; + else + id = IDD_OLD_PASSWORD; + + SetFocus(GetDlgItem(hwnd, id)); + + return FALSE; + +} /* password_initdialog */ + + +/*+ + * Function: Process dialog specific messages for the password dialog. + * + * Parameters: + * hwnd - the dialog receiving the message. + * + * message - the message to process. + * + * wparam - wparam of the message. + * + * lparam - lparam of the message. + * + * Returns: TRUE if message handled locally, FALSE otherwise. + */ +static BOOL CALLBACK +password_dlg_proc ( + HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) +{ + LRESULT rc; + + switch (message) { + + case WM_INITDIALOG: + return password_initdialog(hwnd, wparam, lparam); + + case WM_COMMAND: + password_command(hwnd, wparam, lparam); + return (BOOL) rc; + + case WM_SETCURSOR: + if (isblocking) { + SetCursor(LoadCursor(NULL, IDC_WAIT)); + SetWindowLong(hwnd, DWL_MSGRESULT, TRUE); + + return TRUE; + } + break; + } + + return FALSE; + +} /* password_dlg_proc */ + + +/*+ + * Function: Display and process the password dialog. + * + * Parameters: + * hwnd - the parent window for the dialog + * + * Returns: TRUE if the dialog completed successfully, FALSE otherwise. + */ +static BOOL +password_dialog ( + HWND hwnd) +{ + DLGPROC dlgproc; + int rc; + + dlgproc = (FARPROC) MakeProcInstance(password_dlg_proc, hinstance); + assert(dlgproc != NULL); + + if (dlgproc == NULL) + return FALSE; + + rc = DialogBox(hinstance, MAKEINTRESOURCE(ID_PASSWORD), hwnd, dlgproc); + assert(rc != -1); + + FreeProcInstance((FARPROC) dlgproc); + + return rc == IDOK; + +} /* password_dialog */ + + +/*+ + * Function: Process WM_INITDIALOG messages for the options dialog. + * Set up all initial dialog values from the KERBEROS_INI file. + * + * Parameters: + * hwnd - the window recieving the message. + * + * wparam - handle of the control for focus. + * + * lparam - lparam from dialog box call. + * + * Returns: TRUE if we didn't set the focus here, + * FALSE if we did. + */ +static LONG +opts_initdialog ( + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + char defname[FILENAME_MAX]; + UINT rc; + int lifetime; + + center_dialog(hwnd); + set_dialog_font(hwnd, hfontdialog); + + /* krb.conf file */ + rc = GetWindowsDirectory(defname, sizeof(defname)); + assert(rc > 0); + + strcat(defname, "\\"); + strcat(defname, DEF_KRB_CONF); + GetPrivateProfileString(INI_FILES, INI_KRB_CONF, defname, + confname, sizeof(confname), KERBEROS_INI); + _strupr(confname); + SetDlgItemText(hwnd, IDD_CONF, confname); + + /* krb.realms file */ + rc = GetWindowsDirectory(defname, sizeof(defname)); + assert(rc > 0); + + strcat(defname, "\\"); + strcat(defname, DEF_KRB_REALMS); + GetPrivateProfileString(INI_FILES, INI_KRB_REALMS, defname, + realmsname, sizeof(realmsname), KERBEROS_INI); + _strupr(realmsname); + SetDlgItemText(hwnd, IDD_REALMS, realmsname); + + /* Ticket duration */ + lifetime = GetPrivateProfileInt(INI_OPTIONS, INI_DURATION, + DEFAULT_TKT_LIFE * 5, KERBEROS_INI); + SetDlgItemInt(hwnd, IDD_LIFETIME, lifetime, FALSE); + + /* Expiration action */ + GetPrivateProfileString(INI_EXPIRATION, INI_ALERT, "No", + defname, sizeof(defname), KERBEROS_INI); + alert = _stricmp(defname, "Yes") == 0; + SendDlgItemMessage(hwnd, IDD_ALERT, BM_SETCHECK, alert, 0); + GetPrivateProfileString(INI_EXPIRATION, INI_BEEP, "No", + defname, sizeof(defname), KERBEROS_INI); + beep = _stricmp(defname, "Yes") == 0; + SendDlgItemMessage(hwnd, IDD_BEEP, BM_SETCHECK, beep, 0); + + return TRUE; + +} /* opts_initdialog */ + + +/*+ + * Function: Process WM_COMMAND messages for the options dialog. + * + * Parameters: + * hwnd - the window recieving the message. + * + * wparam - id of the command item + * + * lparam - LOWORD=hwnd of control, HIWORD=notification message. + * + * Returns: TRUE if initialized sucessfully, false otherwise. + */ +static LONG +opts_command ( + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + char defname[FILENAME_MAX]; + char *p; + BOOL b; + int lifetime; + int rc; + + switch (wparam) { + + case IDOK: + /* Ticket duration */ + lifetime = GetDlgItemInt(hwnd, IDD_LIFETIME, &b, FALSE); + + if (!b) { + MessageBox(hwnd, "Lifetime must be a number!", "", MB_OK | MB_ICONEXCLAMATION); + + return TRUE; + } + + _itoa(lifetime, defname, 10); + b = WritePrivateProfileString(INI_OPTIONS, INI_DURATION, defname, KERBEROS_INI); + assert(b); + + /* krb.conf file */ + GetDlgItemText(hwnd, IDD_CONF, confname, sizeof(confname)); + trim(confname); + rc = GetWindowsDirectory(defname, sizeof(defname)); + assert(rc > 0); + + strcat(defname, "\\"); + strcat(defname, DEF_KRB_CONF); + if (_stricmp(confname, defname) == 0 || !defname[0]) + p = NULL; + else + p = confname; + b = WritePrivateProfileString(INI_FILES, INI_KRB_CONF, p, KERBEROS_INI); + assert(b); + + /* krb.realms file */ + GetDlgItemText(hwnd, IDD_REALMS, realmsname, sizeof(realmsname)); + trim(realmsname); + rc = GetWindowsDirectory(defname, sizeof(defname)); + assert(rc > 0); + + strcat(defname, "\\"); + strcat(defname, DEF_KRB_REALMS); + if (_stricmp(realmsname, defname) == 0 || !defname[0]) + p = NULL; + else + p = defname; + b = WritePrivateProfileString(INI_FILES, INI_KRB_REALMS, p, KERBEROS_INI); + assert(b); + + /* Expiration action */ + alert = (BOOL) SendDlgItemMessage(hwnd, IDD_ALERT, BM_GETCHECK, 0, 0); + p = (alert) ? "Yes" : "No"; + b = WritePrivateProfileString(INI_EXPIRATION, INI_ALERT, p, KERBEROS_INI); + assert(b); + + beep = (BOOL) SendDlgItemMessage(hwnd, IDD_BEEP, BM_GETCHECK, 0, 0); + p = (beep) ? "Yes" : "No"; + b = WritePrivateProfileString(INI_EXPIRATION, INI_BEEP, p, KERBEROS_INI); + assert(b); + + EndDialog(hwnd, IDOK); + + return TRUE; + + case IDCANCEL: + EndDialog(hwnd, IDCANCEL); + + return TRUE; + } + + return FALSE; + +} /* opts_command */ + + +/*+ + * Function: Process dialog specific messages for the opts dialog. + * + * Parameters: + * hwnd - the dialog receiving the message. + * + * message - the message to process. + * + * wparam - wparam of the message. + * + * lparam - lparam of the message. + * + * Returns: TRUE if message handled locally, FALSE otherwise. + */ +static BOOL CALLBACK +opts_dlg_proc ( + HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) +{ + LRESULT rc; + + switch (message) { + + case WM_INITDIALOG: + rc = opts_initdialog(hwnd, wparam, lparam); + + return (BOOL) rc; + + case WM_COMMAND: + rc = opts_command(hwnd, wparam, lparam); + + return (BOOL) rc; + } + + return FALSE; + +} /* opts_dlg_proc */ + + +/*+ + * Function: Display and process the options dialog. + * + * Parameters: + * hwnd - the parent window for the dialog + * + * Returns: TRUE if the dialog completed successfully, FALSE otherwise. + */ +static BOOL +opts_dialog ( + HWND hwnd) +{ + DLGPROC dlgproc; + int rc; + + dlgproc = (FARPROC) MakeProcInstance(opts_dlg_proc, hinstance); + assert(dlgproc != NULL); + + if (dlgproc == NULL) + return FALSE; + + rc = DialogBox(hinstance, MAKEINTRESOURCE(ID_OPTS), hwnd, dlgproc); + assert(rc != -1); + + FreeProcInstance((FARPROC) dlgproc); + + return rc == IDOK; + +} /* opts_dialog */ + + +/*+ + * Function: Save most recent login triplets for placement on the + * bottom of the file menu. + * + * Parameters: + * hwnd - the handle of the window containing the menu to edit. + * + * name - A login name to save in the recent login list + * + * instance - An instance to save in the recent login list + * + * realm - A realm to save in the recent login list + */ +static void +kwin_push_login ( + HWND hwnd, + char *name, + char *instance, + char *realm) +{ + HMENU hmenu; + int i; + int id; + int ctitems; + char fullname[MAX_K_NAME_SZ + 3]; + char menuitem[MAX_K_NAME_SZ + 3]; + BOOL rc; + + strcpy(fullname, "&x "); + strcat(fullname, name); + strcat(fullname, "."); + strcat(fullname, instance); + strcat(fullname, "@"); + strcat(fullname, realm); + + hmenu = GetMenu(hwnd); + assert(hmenu != NULL); + + hmenu = GetSubMenu(hmenu, 0); + assert(hmenu != NULL); + + ctitems = GetMenuItemCount(hmenu); + assert(ctitems >= FILE_MENU_ITEMS); + + if (ctitems == FILE_MENU_ITEMS) { + rc = AppendMenu(hmenu, MF_SEPARATOR, 0, NULL); + assert(rc); + + ctitems++; + } + + for (i = FILE_MENU_ITEMS + 1; i < ctitems; i++) { + GetMenuString(hmenu, i, menuitem, sizeof(menuitem), MF_BYPOSITION); + + if (strcmp(&fullname[3], &menuitem[3]) == 0) { + rc = RemoveMenu(hmenu, i, MF_BYPOSITION); + assert(rc); + + ctitems--; + + break; + } + } + + rc = InsertMenu(hmenu, FILE_MENU_ITEMS + 1, MF_BYPOSITION, 1, fullname); + assert(rc); + + ctitems++; + if (ctitems - FILE_MENU_ITEMS - 1 > FILE_MENU_MAX_LOGINS) { + RemoveMenu(hmenu, ctitems - 1, MF_BYPOSITION); + + ctitems--; + } + + id = 0; + for (i = FILE_MENU_ITEMS + 1; i < ctitems; i++) { + GetMenuString(hmenu, i, menuitem, sizeof(menuitem), MF_BYPOSITION); + + rc = RemoveMenu(hmenu, i, MF_BYPOSITION); + assert(rc); + + menuitem[1] = '1' + id; + rc = InsertMenu(hmenu, i, MF_BYPOSITION, IDM_FIRST_LOGIN + id, menuitem); + assert(rc); + + id++; + } + +} /* kwin_push_login */ + + +/*+ + * Function: Initialize the logins on the file menu form the KERBEROS.INI + * file. + * + * Parameters: + * hwnd - handle of the dialog containing the file menu. + */ +static void +kwin_init_file_menu ( + HWND hwnd) +{ + HMENU hmenu; + int i; + char login[sizeof(INI_LOGIN)+1]; + char menuitem[MAX_K_NAME_SZ + 3]; + int id; + BOOL rc; + + hmenu = GetMenu(hwnd); + assert(hmenu != NULL); + + hmenu = GetSubMenu(hmenu, 0); + assert(hmenu != NULL); + + strcpy(login, INI_LOGIN); + id = 0; + for (i = 0; i < FILE_MENU_MAX_LOGINS; i++) { + login[sizeof(INI_LOGIN) - 1] = '1' + i; + login[sizeof(INI_LOGIN)] = 0; + GetPrivateProfileString(INI_RECENT_LOGINS, login, "", + &menuitem[3], sizeof(menuitem) - 3, KERBEROS_INI); + if (!menuitem[3]) + continue; + + menuitem[0] = '&'; + menuitem[1] = '1' + id; + menuitem[2] = ' '; + + if (id == 0) { + rc = AppendMenu(hmenu, MF_SEPARATOR, 0, NULL); + assert(rc); + } + AppendMenu(hmenu, MF_STRING, IDM_FIRST_LOGIN + id, menuitem); + + id++; + } + +} /* kwin_init_file_menu */ + + +/*+ + * Function: Save the items on the file menu in the KERBEROS.INI file. + * + * Parameters: + * hwnd - handle of the dialog containing the file menu. + */ +static void +kwin_save_file_menu ( + HWND hwnd) +{ + HMENU hmenu; + int i; + int id; + int ctitems; + char menuitem[MAX_K_NAME_SZ + 3]; + char login[sizeof(INI_LOGIN)+1]; + BOOL rc; + + hmenu = GetMenu(hwnd); + assert(hmenu != NULL); + + hmenu = GetSubMenu(hmenu, 0); + assert(hmenu != NULL); + + strcpy(login, INI_LOGIN); + ctitems = GetMenuItemCount(hmenu); + assert(ctitems >= FILE_MENU_ITEMS); + + id = 0; + for (i = FILE_MENU_ITEMS + 1; i < ctitems; i++) { + GetMenuString(hmenu, i, menuitem, sizeof(menuitem), MF_BYPOSITION); + login[sizeof(INI_LOGIN) - 1] = '1' + id; + login[sizeof(INI_LOGIN)] = 0; + + rc = WritePrivateProfileString(INI_RECENT_LOGINS, login, &menuitem[3], KERBEROS_INI); + assert(rc); + + id++; + } + +} /* kwin_save_file_menu */ + + + +/*+ + * Function: Given an expiration time, choose an appropriate + * icon to display. + * + * Parameters: + * expiration time of expiration in time() compatible units + * + * Returns: Handle of icon to display + */ +HICON +kwin_get_icon ( + time_t expiration) +{ + int ixicon; + time_t dt; + + dt = expiration - time(NULL); + dt = dt / 60; /* convert to minutes */ + if (dt <= 0) + ixicon = IDI_EXPIRED - IDI_FIRST_CLOCK; + else if (dt > 60) + ixicon = IDI_TICKET - IDI_FIRST_CLOCK; + else + ixicon = (int) (dt / 5); + + return kwin_icons[ixicon]; + +} /* kwin_get_icon */ + + +/*+ + * Function: Intialize name fields in the Kerberos dialog. + * + * Parameters: + * hwnd - the window recieving the message. + * + * fullname - the full kerberos name to initialize with + */ +static void +kwin_init_name ( + HWND hwnd, + char *fullname) +{ + char name[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + int krc; + + if (fullname == NULL || fullname[0] == 0) { + #ifdef KRB4 + strcpy(name, krb_get_default_user()); + GetPrivateProfileString(INI_DEFAULTS, INI_INSTANCE, "", + instance, sizeof(instance), KERBEROS_INI); + krc = krb_get_lrealm(realm, 1); + if (krc != KSUCCESS) + realm[0] = 0; + #endif + + + #ifdef KRB5 + { + krb5_error_code code; + char *ptr; + + GetPrivateProfileString (INI_DEFAULTS, INI_USER, "", + name, sizeof(name), KERBEROS_INI); + //GetPrivateProfileString(INI_DEFAULTS, INI_INSTANCE, "", + // instance, sizeof(instance), KERBEROS_INI); + *instance = '\0'; + + *realm = '\0'; + code = krb5_get_default_realm (k5_context, &ptr); + if (! code) { + strcpy (realm, ptr); + free (ptr); + } + } + #endif + + GetPrivateProfileString(INI_DEFAULTS, INI_REALM, realm, + realm, sizeof(realm), KERBEROS_INI); + } else { + #ifdef KRB4 + kname_parse(name, instance, realm, fullname); + #endif + + #ifdef KRB5 + krc = k5_kname_parse(name, realm, fullname); + *instance = '\0'; + #endif + } + + SetDlgItemText(hwnd, IDD_LOGIN_NAME, name); + name[0] = 0; + GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); + SetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance); + SetDlgItemText(hwnd, IDD_LOGIN_REALM, realm); + +} /* kwin_init_name */ + + +/*+ + * Function: Set the focus to the name control if no name + * exists, the realm control if no realm exists or the + * password control. Uses PostMessage not SetFocus. + * + * Parameters: + * hwnd - the Window handle of the parent. + */ +void +kwin_set_default_focus ( + HWND hwnd) +{ + char name[ANAME_SZ]; + char realm[REALM_SZ]; + HWND hwnditem; + + GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); + + trim(name); + if (strlen(name) <= 0) + hwnditem = GetDlgItem(hwnd, IDD_LOGIN_NAME); + else { + GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm)); + trim(realm); + + if (strlen(realm) <= 0) + hwnditem = GetDlgItem(hwnd, IDD_LOGIN_REALM); + else + hwnditem = GetDlgItem(hwnd, IDD_LOGIN_PASSWORD); + } + + PostMessage(hwnd, WM_NEXTDLGCTL, hwnditem, MAKELONG(1, 0)); + +} /* kwin_set_default_focus */ + + +/*+ + * Function: Save the values which live in the KERBEROS.INI file. + * + * Parameters: + * hwnd - the window handle of the dialog containing fields to + * be saved + */ +static void +kwin_save_name ( + HWND hwnd) +{ + char name[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + + GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); + trim(name); + + #ifdef KRB4 + krb_set_default_user(name); + GetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance, sizeof(instance)); + trim(instance); + WritePrivateProfileString(INI_DEFAULTS, INI_INSTANCE, instance, KERBEROS_INI); + #endif + + #ifdef KRB5 + WritePrivateProfileString(INI_DEFAULTS, INI_USER, name, KERBEROS_INI); + *instance = '\0'; + #endif + + GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm)); + trim(realm); + WritePrivateProfileString(INI_DEFAULTS, INI_REALM, realm, KERBEROS_INI); + + kwin_push_login(hwnd, name, instance, realm); + +} /* kwin_save_name */ + + +/*+ + * Function: Process WM_INITDIALOG messages. Set the fonts + * for all items on the dialog and populate the ticket list. + * Also set the default values for user, instance and realm. + * + * Parameters: + * hwnd - the window recieving the message. + * + * wparam - handle of the control for focus. + * + * lparam - lparam from dialog box call. + * + * Returns: TRUE if we didn't set the focus here, + * FALSE if we did. + */ +static BOOL +kwin_initdialog ( + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + LOGFONT lf; + HDC hdc; + char name[ANAME_SZ]; + + position_dialog(hwnd); + ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST)); + kwin_init_file_menu(hwnd); + kwin_init_name(hwnd, (char *) lparam); + hdc = GetDC(NULL); + assert(hdc != NULL); + + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = -MulDiv(9, GetDeviceCaps(hdc, LOGPIXELSY), 72); + strcpy(lf.lfFaceName, "Arial"); + hfontdialog = CreateFontIndirect(&lf); + assert(hfontdialog != NULL); + + if (hfontdialog == NULL) { + ReleaseDC(NULL, hdc); + + return TRUE; + } + + lf.lfHeight = -MulDiv(8, GetDeviceCaps(hdc, LOGPIXELSY), 72); + hfonticon = CreateFontIndirect(&lf); + assert(hfonticon != NULL); + + if (hfonticon == NULL) { + ReleaseDC(NULL, hdc); + + return TRUE; + } + + ReleaseDC(NULL, hdc); + + set_dialog_font(hwnd, hfontdialog); + GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); + trim(name); + + if (strlen(name) > 0) + SetFocus(GetDlgItem(hwnd, IDD_LOGIN_PASSWORD)); + else + SetFocus(GetDlgItem(hwnd, IDD_LOGIN_NAME)); + + ShowWindow(hwnd, dlgncmdshow); + kwin_timer_id = SetTimer(hwnd, 1, KWIN_UPDATE_PERIOD, NULL); + assert(kwin_timer_id != 0); + + return FALSE; + +} /* kwin_initdialog */ + + +/*+ + * Function: Process WM_DESTROY messages. Delete the font + * created for use by the controls. + * + * Parameters: + * hwnd - the window recieving the message. + * + * wparam - none + * + * lparam - none + * + * Returns: 0 + */ +static LONG +kwin_destroy ( + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + char position[256]; + RECT r; + BOOL b; + + ticket_destroy(GetDlgItem(hwnd, IDD_TICKET_LIST)); + + if (hfontdialog != NULL) + DeleteObject(hfontdialog); + + if (hfonticon != NULL) + DeleteObject(hfonticon); + + kwin_save_file_menu(hwnd); + GetWindowRect(hwnd, &r); + sprintf(position, "[%d,%d,%d,%d]", r.left, r.top, + r.right - r.left, r.bottom - r.top); + b = WritePrivateProfileString(INI_DEFAULTS, INI_POSITION, position, KERBEROS_INI); + assert(b); + + KillTimer(hwnd, kwin_timer_id); + + return 0; + +} /* kwin_destroy */ + + +/*+ + * Function: Retrievs item WindowRect in hwnd client + * coordiate system. + * + * Parameters: + * hwnditem - the item to retrieve + * + * item - dialog in which into which to translate + * + * r - rectangle returned + */ +static void +windowrect ( + HWND hwnditem, + HWND hwnd, + RECT *r) +{ + GetWindowRect(hwnditem, r); + ScreenToClient(hwnd, (LPPOINT) &(r->left)); + ScreenToClient(hwnd, (LPPOINT) &(r->right)); + +} /* windowrect */ + + +/*+ + * Function: Process WM_SIZE messages. Resize the + * list and position the buttons attractively. + * + * Parameters: + * hwnd - the window receiving the message. + * + * wparam - type of resize occuring + * + * lparam - LOWORD=width of client area, + * HIWORD=height of client area. + * + * Returns: 0 + */ +static LONG +kwin_size ( + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + #define listgap 8 + RECT r; + RECT rdlg; + int hmargin, vmargin; + HWND hwnditem; + int cx, cy; + int cxdlg, cydlg; + int i; + int titlebottom; + int editbottom; + int listbottom; + int gap; + int left; + int titleleft[IDD_MAX_TITLE - IDD_MIN_TITLE + 1]; + + if (wparam == SIZE_MINIMIZED) + return 0; + + GetClientRect(hwnd, &rdlg); + cxdlg = LOWORD(lparam); + cydlg = HIWORD(lparam); + + /* + * The ticket list title + */ + hwnditem = GetDlgItem(hwnd, IDD_TICKET_LIST_TITLE); + + if (hwnditem == NULL) + return 0; + + windowrect(hwnditem, hwnd, &r); + hmargin = r.left; + vmargin = r.top; + cx = cxdlg - 2 * hmargin; + cy = r.bottom - r.top; + MoveWindow(hwnditem, r.left, r.top, cx, cy, TRUE); + + /* + * The buttons + */ + cx = 0; + + for (i = IDD_MIN_BUTTON; i <= IDD_MAX_BUTTON; i++) { + hwnditem = GetDlgItem(hwnd, i); + windowrect(hwnditem, hwnd, &r); + if (i == IDD_MIN_BUTTON) + hmargin = r.left; + + cx += r.right - r.left; + } + + gap = (cxdlg - 2 * hmargin - cx) / (IDD_MAX_BUTTON - IDD_MIN_BUTTON); + left = hmargin; + for (i = IDD_MIN_BUTTON; i <= IDD_MAX_BUTTON; i++) { + hwnditem = GetDlgItem(hwnd, i); + windowrect(hwnditem, hwnd, &r); + editbottom = -r.top; + cx = r.right - r.left; + cy = r.bottom - r.top; + r.top = rdlg.bottom - vmargin - cy; + MoveWindow(hwnditem, left, r.top, cx, cy, TRUE); + + left += cx + gap; + } + + /* + * Edit fields + */ + editbottom += r.top; + + cx = 0; + for (i = IDD_MIN_EDIT; i <= IDD_MAX_EDIT; i++) { + hwnditem = GetDlgItem(hwnd, i); + windowrect(hwnditem, hwnd, &r); + + if (i == IDD_MIN_EDIT) { + gap = r.right; + hmargin = r.left; + editbottom += r.bottom; + titlebottom = -r.top; + } + if (i == IDD_MIN_EDIT + 1) + gap = r.left - gap; + + cx += r.right - r.left; + } + + cx = cxdlg - 2 * hmargin - (IDD_MAX_EDIT - IDD_MIN_EDIT) * gap; + cx = cx / (IDD_MAX_EDIT - IDD_MIN_EDIT + 1); + left = hmargin; + + for (i = IDD_MIN_EDIT; i <= IDD_MAX_EDIT; i++) { + hwnditem = GetDlgItem(hwnd, i); + windowrect(hwnditem, hwnd, &r); + cy = r.bottom - r.top; + r.top = editbottom - cy; + MoveWindow(hwnditem, left, r.top, cx, cy, TRUE); + titleleft[i-IDD_MIN_EDIT] = left; + + left += cx + gap; + } + + /* + * Edit field titles + */ + titlebottom += r.top; + windowrect(GetDlgItem(hwnd, IDD_MIN_TITLE), hwnd, &r); + titlebottom += r.bottom; + listbottom = -r.top; + + for (i = IDD_MIN_TITLE; i <= IDD_MAX_TITLE; i++) { + hwnditem = GetDlgItem(hwnd, i); + windowrect(hwnditem, hwnd, &r); + cx = r.right - r.left; + cy = r.bottom - r.top; + r.top = titlebottom - cy; + MoveWindow(hwnditem, titleleft[i-IDD_MIN_TITLE], r.top, cx, cy, TRUE); + } + + /* + * The list + */ + listbottom = r.top - listgap; + hwnditem = GetDlgItem(hwnd, IDD_TICKET_LIST); + windowrect(hwnditem, hwnd, &r); + hmargin = r.left; + cx = cxdlg - 2 * hmargin; + cy = listbottom - r.top; + MoveWindow(hwnditem, r.left, r.top, cx, cy, TRUE); + + return 0; + +} /* kwin_size */ + + +/*+ + * Function: Process WM_GETMINMAXINFO messages + * + * Parameters: + * hwnd - the window recieving the message. + * + * wparam - none. + * + * lparam - LPMINMAXINFO + * + * Returns: 0 + */ +static LONG +kwin_getminmaxinfo ( + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + MINMAXINFO *lpmmi; + + lpmmi = (MINMAXINFO *) lparam; + lpmmi->ptMinTrackSize.x = (KWIN_MIN_WIDTH * LOWORD(GetDialogBaseUnits())) / 4; + lpmmi->ptMinTrackSize.y = (KWIN_MIN_HEIGHT * HIWORD(GetDialogBaseUnits())) / 8; + + return 0; + +} /* kwin_getminmaxinfo */ + + +/*+ + * Function: Process WM_TIMER messages + * + * Parameters: + * hwnd - the window recieving the message. + * + * wparam - the timer id. + * + * lparam - timer callback proceedure + * + * Returns: 0 + */ +static LONG +kwin_timer ( + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + HWND hwndfocus; + time_t t; + time_t expiration; + BOOL expired; + #ifdef KRB4 + CREDENTIALS c; + int ncred; + int i; + char service[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + #endif + #ifdef KRB5 + krb5_error_code code; + krb5_cc_cursor cursor; + krb5_creds cred; + int n; + char *s; + #endif + + if (wparam != 1) + return DefDlgProc(hwnd, WM_TIMER, wparam, lparam); + + expired = FALSE; + ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST)); + + if (alerted) { + if (IsIconic(hwnd)) + InvalidateRect(hwnd, NULL, TRUE); + + return 0; + } + + #ifdef KRB4 + ncred = krb_get_num_cred(); + for (i = 1; i <= ncred; i++) { + krb_get_nth_cred(service, instance, realm, i); + + if (_stricmp(service, "krbtgt") == 0) { + /* Warn if ticket will expire w/i TIME_BUFFER seconds */ + krb_get_cred(service, instance, realm, &c); + expiration = c.issue_date + (long) c.lifetime * 5L * 60L; + t = TIME_BUFFER + time(NULL); + + if (t >= expiration) { + expired = TRUE; + /* Don't alert because of stale tickets */ + if (t >= expiration + KWIN_UPDATE_PERIOD / 1000) { + alerted = TRUE; + + if (IsIconic(hwnd)) + InvalidateRect(hwnd, NULL, TRUE); + return 0; + } + break; + } + } + } + #endif + + #ifdef KRB5 + code = krb5_cc_start_seq_get (k5_context, k5_ccache, &cursor); + + while (code == 0) { + code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &cred); + if (code) + break; + n = krb5_princ_component(k5_context, cred.server, 0)->length; + s = krb5_princ_component(k5_context, cred.server, 0)->data; + if (n != KRB5_TGS_NAME_SIZE) + continue; + if (memcmp (KRB5_TGS_NAME, s, KRB5_TGS_NAME_SIZE)) + continue; + + /* Warn if ticket will expire w/i TIME_BUFFER seconds */ + expiration = cred.times.endtime; + t = TIME_BUFFER + time(NULL); + + if (t >= expiration) { + expired = TRUE; + /* Don't alert because of stale tickets */ + if (t >= expiration + KWIN_UPDATE_PERIOD / 1000) { + alerted = TRUE; + + if (IsIconic(hwnd)) + InvalidateRect(hwnd, NULL, TRUE); + return 0; + } + break; + } + } + krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor); + + #endif + + if (!expired) { + if (IsIconic(hwnd)) + InvalidateRect(hwnd, NULL, TRUE); + + return 0; + } + + alerted = TRUE; + + if (beep) + MessageBeep(MB_ICONEXCLAMATION); + + if (alert) { + if (IsIconic(hwnd)) { + hwndfocus = GetFocus(); + ShowWindow(hwnd, SW_RESTORE); + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); + SetFocus(hwndfocus); + } + + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); + + return 0; + } + + if (IsIconic(hwnd)) + InvalidateRect(hwnd, NULL, TRUE); + + return 0; + +} /* kwin_timer */ + + +/*+ + * Function: Process WM_COMMAND messages + * + * Parameters: + * hwnd - the window recieving the message. + * + * wparam - id of the command item + * + * lparam - LOWORD=hwnd of control, HIWORD=notification message. + * + * Returns: TRUE if initialized sucessfully, false otherwise. + */ +static LONG +kwin_command ( + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + char name[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + char password[MAX_KPW_LEN]; + HCURSOR hcursor; + BOOL blogin; + HMENU hmenu; + char menuitem[MAX_K_NAME_SZ + 3]; + char copyright[128]; + #ifdef KRB4 + int lifetime; + int krc; + #endif + #ifdef KRB5 + long lifetime; + krb5_error_code code; + krb5_principal principal; + krb5_creds creds; + krb5_principal server; + krb5_timestamp now; + #endif + + #ifdef KRB4 + EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), krb_get_num_cred() > 0); + #endif + + #ifdef KRB5 + EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), k5_get_num_cred() > 0); + #endif + + GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); + trim(name); + blogin = strlen(name) > 0; + + if (blogin) { + GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm)); + trim(realm); + blogin = strlen(realm) > 0; + } + + if (blogin) { + GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password)); + blogin = strlen(password) > 0; + } + + EnableWindow(GetDlgItem(hwnd, IDD_LOGIN), blogin); + + if (HIWORD(lparam) != BN_CLICKED && HIWORD(lparam) != 0 && HIWORD(lparam) != 1) + return FALSE; + + if (wparam >= IDM_FIRST_LOGIN && wparam < IDM_FIRST_LOGIN + FILE_MENU_MAX_LOGINS) { + hmenu = GetMenu(hwnd); + assert(hmenu != NULL); + + hmenu = GetSubMenu(hmenu, 0); + assert(hmenu != NULL); + + if (!GetMenuString(hmenu, wparam, menuitem, sizeof(menuitem), MF_BYCOMMAND)) + return TRUE; + + if (menuitem[0]) + kwin_init_name(hwnd, &menuitem[3]); + + return TRUE; + } + + switch (wparam) { + case IDM_EXIT: + if (isblocking) + WSACancelBlockingCall(); + WinHelp(hwnd, KERBEROS_HLP, HELP_QUIT, 0); + PostQuitMessage(0); + + return TRUE; + + case IDD_LOGIN: + if (isblocking) + return TRUE; + + GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name)); + trim(name); + GetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance, sizeof(instance)); + trim(instance); + GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm)); + trim(realm); + GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password)); + trim(password); + + hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); + lifetime = GetPrivateProfileInt(INI_OPTIONS, INI_DURATION, + DEFAULT_TKT_LIFE * 5, KERBEROS_INI); + start_blocking_hook(BLOCK_MAX_SEC); + + #ifdef KRB4 + lifetime = (lifetime + 4) / 5; + krc = krb_get_pw_in_tkt(name, instance, realm, "krbtgt", realm, + lifetime, password); + #endif + + #ifdef KRB5 + code = krb5_parse_name(k5_context, name, &principal); + code = krb5_cc_initialize(k5_context, k5_ccache, principal); + memset(&creds, 0, sizeof(creds)); + creds.client = principal; + + code = krb5_build_principal_ext(k5_context, &server, + krb5_princ_realm(k5_context, principal)->length, + krb5_princ_realm(k5_context, principal)->data, + KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, + krb5_princ_realm(k5_context, principal)->length, + krb5_princ_realm(k5_context, principal)->data, 0); + + creds.server = server; + + //code = krb5_os_localaddr(&address); + code = krb5_timeofday(k5_context, &now); + + creds.times.starttime = 0; + creds.times.endtime = now + 60L * lifetime; + creds.times.renew_till = 0; + + code = krb5_get_in_tkt_with_password(k5_context, 0, NULL, NULL, + NULL, password, k5_ccache, &creds, 0); + + krb5_free_principal(k5_context, server); + //krb5_free_addresses(k5_context, address); + + #endif + + end_blocking_hook(); + SetCursor(hcursor); + kwin_set_default_focus(hwnd); + + #ifdef KRB4 + if (krc != KSUCCESS) { + MessageBox(hwnd, krb_get_err_text(krc), "", + MB_OK | MB_ICONEXCLAMATION); + + return TRUE; + } + #endif + + #ifdef KRB5 + if (code) { + com_err (NULL, code, "while logging in"); + return TRUE; + } + // ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST)); + + #endif + + SetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, ""); + kwin_save_name(hwnd); + alerted = FALSE; + + switch (action) { + case LOGIN_AND_EXIT: + SendMessage(hwnd, WM_COMMAND, IDM_EXIT, 0); + break; + + case LOGIN_AND_MINIMIZE: + ShowWindow(hwnd, SW_MINIMIZE); + break; + } + + return TRUE; + + case IDD_TICKET_DELETE: + if (isblocking) + return TRUE; + + #ifdef KRB4 + krc = dest_tkt(); + if (krc != KSUCCESS) + MessageBox(hwnd, krb_get_err_text(krc), "", + MB_OK | MB_ICONEXCLAMATION); + #endif + + #ifdef KRB5 + code = k5_dest_tkt (); + // ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST)); + #endif + + kwin_set_default_focus(hwnd); + alerted = FALSE; + + return TRUE; + + case IDD_CHANGE_PASSWORD: + if (isblocking) + return TRUE; + password_dialog(hwnd); + kwin_set_default_focus(hwnd); + + return TRUE; + + case IDM_OPTIONS: + if (isblocking) + return TRUE; + opts_dialog(hwnd); + + return TRUE; + + case IDM_HELP_INDEX: + WinHelp(hwnd, KERBEROS_HLP, HELP_INDEX, 0); + + return TRUE; + + case 1234: + ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST)); + + return TRUE; + + case IDM_ABOUT: + if (isblocking) + return TRUE; + + strcpy(copyright, " Kerberos for Windows\n"); + strcat(copyright, "\n Version 1.00\n\n"); + strcat(copyright, " For support, contact:\n"); + strcat(copyright, ORGANIZATION); + strcat(copyright, " - (415) 903-1400"); + MessageBox(hwnd, copyright, "Kerberos", MB_OK); + + return TRUE; + } + + return FALSE; + +} /* kwin_command */ + + +/*+ + * Function: Process WM_SYSCOMMAND messages by setting + * the focus to the password or name on restore. + * + * Parameters: + * hwnd - the window recieving the message. + * + * wparam - the syscommand option. + * + * lparam - + * + * Returns: 0 + */ +static LONG +kwin_syscommand ( + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + if ((wparam & 0xFFF0) == SC_RESTORE) + kwin_set_default_focus(hwnd); + + if ((wparam & 0xFFF0) == SC_CLOSE) { + SendMessage(hwnd, WM_COMMAND, IDM_EXIT, 0); + + return 0; + } + + return DefDlgProc(hwnd, WM_SYSCOMMAND, wparam, lparam); + +} /* kwin_syscommand */ + + +/*+ + * Function: Process WM_PAINT messages by displaying an + * informative icon when we are iconic. + * + * Parameters: + * hwnd - the window recieving the message. + * + * wparam - none + * + * lparam - none + * + * Returns: 0 + */ +static LONG +kwin_paint ( + HWND hwnd, + WPARAM wparam, + LPARAM lparam) +{ + HDC hdc; + PAINTSTRUCT ps; + HICON hicon; + time_t expiration = 0; + time_t dt; + char buf[20]; + RECT r; + #ifdef KRB4 + int i; + int ncred; + char service[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + CREDENTIALS c; + #endif + #ifdef KRB5 + krb5_error_code code; + krb5_cc_cursor cursor; + krb5_creds c; + int n; + char *service; + #endif + + if (!IsIconic(hwnd)) + return DefDlgProc(hwnd, WM_PAINT, wparam, lparam); + + #ifdef KRB4 + ncred = krb_get_num_cred(); + + for (i = 1; i <= ncred; i++) { + krb_get_nth_cred(service, instance, realm, i); + krb_get_cred(service, instance, realm, &c); + if (_stricmp(c.service, "krbtgt") == 0) { + expiration = c.issue_date - kwin_get_epoch() + (long) c.lifetime * 5L * 60L; + break; + } + } + #endif + + #ifdef KRB5 + code = krb5_cc_start_seq_get (k5_context, k5_ccache, &cursor); + + while (code == 0) { + code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c); + if (code) + break; + n = krb5_princ_component(k5_context, c.server, 0)->length; + service = krb5_princ_component(k5_context, c.server, 0)->data; + if (n != KRB5_TGS_NAME_SIZE) + continue; + if (memcmp (KRB5_TGS_NAME, service, KRB5_TGS_NAME_SIZE)) + continue; + expiration = c.times.endtime; + break; + + } + krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor); + #endif + + hdc = BeginPaint(hwnd, &ps); + GetClientRect(hwnd, &r); + DefWindowProc(hwnd, WM_ICONERASEBKGND, hdc, 0); + + if (expiration == 0) { + strcpy(buf, KWIN_DIALOG_NAME); + hicon = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_KWIN)); + } + else { + hicon = kwin_get_icon(expiration); + dt = (expiration - time(NULL)) / 60; + + if (dt <= 0) + sprintf(buf, "%s - %s", KWIN_DIALOG_NAME, "Expired"); + else if (dt < 60) { + dt %= 60; + sprintf(buf, "%s - %ld min", KWIN_DIALOG_NAME, dt); + } + else { + dt /= 60; + sprintf(buf, "%s - %ld hr", KWIN_DIALOG_NAME, dt); + } + + if (dt > 1) + strcat(buf, "s"); + } + + DrawIcon(hdc, r.left, r.top, hicon); + EndPaint(hwnd, &ps); + SetWindowText(hwnd, buf); + + return 0; + +} /* kwin_paint */ + + +/*+ + * Function: Window proceedure for the Kerberos control panel dialog. + * + * Parameters: + * hwnd - the window receiving the message. + * + * message - the message to process. + * + * wparam - wparam of the message. + * + * lparam - lparam of the message. + * + * Returns: message dependent value. + */ +LRESULT __export CALLBACK +kwin_wnd_proc ( + HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) +{ + LRESULT rc; + int n; + + if (message == wm_kerberos_changed) { /* Message from the ccache */ + n = ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST)); + EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), n > 0); + + return 0; + } + + switch (message) { + case WM_GETMINMAXINFO: + rc = kwin_getminmaxinfo(hwnd, wparam, lparam); + return rc; + + case WM_DESTROY: + rc = kwin_destroy(hwnd, wparam, lparam); + return rc; + + case WM_MEASUREITEM: + if (wparam == IDD_TICKET_LIST) { + rc = ticket_measureitem(hwnd, wparam, lparam); + return rc; + } + break; + + case WM_DRAWITEM: + if (wparam == IDD_TICKET_LIST) { + rc = ticket_drawitem(hwnd, wparam, lparam); + return rc; + } + break; + + case WM_SETCURSOR: + if (isblocking) { + SetCursor(LoadCursor(NULL, IDC_WAIT)); + return TRUE; + } + break; + + case WM_SIZE: + rc = kwin_size(hwnd, wparam, lparam); + return rc; + + case WM_SYSCOMMAND: + rc = kwin_syscommand(hwnd, wparam, lparam); + return rc; + + case WM_TIMER: + rc = kwin_timer(hwnd, wparam, lparam); + return 0; + + case WM_PAINT: + rc = kwin_paint(hwnd, wparam, lparam); + return rc; + + case WM_ERASEBKGND: + if (!IsIconic(hwnd)) + break; + return 0; + + case WM_KWIN_SETNAME: + kwin_init_name(hwnd, (char *) lparam); + } + + return DefDlgProc(hwnd, message, wparam, lparam); + +} /* kwin_wnd_proc */ + + +/*+ + * Function: Dialog procedure called by the dialog manager + * to process dialog specific messages. + * + * Parameters: + * hwnd - the dialog receiving the message. + * + * message - the message to process. + * + * wparam - wparam of the message. + * + * lparam - lparam of the message. + * + * Returns: TRUE if message handled locally, FALSE otherwise. + */ +static BOOL CALLBACK +kwin_dlg_proc ( + HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) +{ + LRESULT rc; + + switch (message) { + case WM_INITDIALOG: + return kwin_initdialog(hwnd, wparam, lparam); + + case WM_COMMAND: + rc = kwin_command(hwnd, wparam, lparam); + return TRUE; + } + + return FALSE; + +} /* kwin_dlg_proc */ + + +/*+ + * Function: Initialize the kwin dialog class. + * + * Parameters: + * hinstance - the instance to initialize + * + * Returns: TRUE if dialog class registration is sucessfully, false otherwise. + */ +static BOOL +kwin_init ( + HINSTANCE hinstance) +{ + WNDCLASS class; + ATOM rc; + + class.style = CS_HREDRAW | CS_VREDRAW; + class.lpfnWndProc = (WNDPROC) kwin_wnd_proc; + class.cbClsExtra = 0; + class.cbWndExtra = DLGWINDOWEXTRA; + class.hInstance = hinstance; + class.hIcon = NULL; +// LoadIcon(hinstance, MAKEINTRESOURCE(IDI_KWIN)); + class.hCursor = NULL; + class.hbrBackground = NULL; + class.lpszMenuName = NULL; + class.lpszClassName = KWIN_DIALOG_CLASS; + + rc = RegisterClass (&class); + assert(rc); + + return rc; + +} /* kwin_init */ + + +/*+ + * Function: Initialize the KWIN application. This routine should + * only be called if no previous instance of the application + * exists. Currently it only registers a class for the kwin + * dialog type. + * + * Parameters: + * hinstance - the instance to initialize + * + * Returns: TRUE if initialized sucessfully, false otherwise. + */ +static BOOL +init_application ( + HINSTANCE hinstance) +{ + BOOL rc; + + #ifdef KRB4 + wm_kerberos_changed = krb_get_notification_message(); + #endif + + #ifdef KRB5 + wm_kerberos_changed = krb5_get_notification_message(); + #endif + + rc = kwin_init(hinstance); + + return rc; + +} /* init_application */ + + +/*+ + * Function: Quits the KWIN application. This routine should + * be called when the last application instance exits. + * + * Parameters: + * hinstance - the instance which is quitting. + * + * Returns: TRUE if initialized sucessfully, false otherwise. + */ +static BOOL +quit_application ( + HINSTANCE hinstance) +{ + return TRUE; +} /* quit_application */ + + +/*+ + * Function: Initialize the current instance of the KWIN application. + * + * Parameters: + * hinstance - the instance to initialize + * + * ncmdshow - show flag to indicate wheather to come up minimized + * or not. + * + * Returns: TRUE if initialized sucessfully, false otherwise. + */ +static BOOL +init_instance ( + HINSTANCE hinstance, + int ncmdshow) +{ + WORD versionrequested; + WSADATA wsadata; + int rc; + char buf[20]; + int i; + + versionrequested = 0x0101; /* We need version 1.1 */ + rc = WSAStartup(versionrequested, &wsadata); + if (rc != 0) { + MessageBox(NULL, "Couldn't initialize Winsock library", "", MB_OK | MB_ICONSTOP); + + return FALSE; + } + + if (versionrequested != wsadata.wVersion) { + WSACleanup(); + MessageBox(NULL, "Winsock version 1.1 not available", "", MB_OK | MB_ICONSTOP); + + return FALSE; + } + + /* + * Set up expiration action + */ + GetPrivateProfileString(INI_EXPIRATION, INI_ALERT, "No", + buf, sizeof(buf), KERBEROS_INI); + alert = _stricmp(buf, "Yes") == 0; + GetPrivateProfileString(INI_EXPIRATION, INI_BEEP, "No", + buf, sizeof(buf), KERBEROS_INI); + beep = _stricmp(buf, "Yes") == 0; + + /* + * Load clock icons + */ + for (i = IDI_FIRST_CLOCK; i <= IDI_LAST_CLOCK; i++) + kwin_icons[i - IDI_FIRST_CLOCK] = LoadIcon(hinstance, MAKEINTRESOURCE(i)); + + #ifdef KRB4 + krb_start_session(NULL); + #endif + + #ifdef KRB5 + krb5_init_context(&k5_context); + krb5_init_ets(k5_context); + krb5_cc_default(k5_context, &k5_ccache); + #endif + + return TRUE; + +} /* init_instance */ + + +/*+ + * Function: Quits the current instance of the KWIN application. + * + * Parameters: + * hinstance - the instance to quit. + * + * Returns: TRUE if termination was sucessfully, false otherwise. + */ +static BOOL +quit_instance ( + HINSTANCE hinstance) +{ + int i; + + #ifdef KRB4 + krb_end_session((char *) NULL); + #endif + + #ifdef KRB5 /* FIXME */ + krb5_cc_close (k5_context, k5_ccache); + #endif + + WSACleanup(); + + /* + * Unload clock icons + */ + for (i = IDI_FIRST_CLOCK; i <= IDI_LAST_CLOCK; i++) + DestroyIcon(kwin_icons[i - IDI_FIRST_CLOCK]); + + return TRUE; + +} /* quit_instance */ + + +/*+ + * Function: Main routine called on program invocation. + * + * Parameters: + * hinstance - the current instance + * + * hprevinstance - previous instance if one exists or NULL. + * + * cmdline - the command line string passed by Windows. + * + * ncmdshow - show flag to indicate wheather to come up minimized + * or not. + * + * Returns: TRUE if initialized sucessfully, false otherwise. + */ +int PASCAL +WinMain ( + HINSTANCE hinst, + HINSTANCE hprevinstance, + LPSTR cmdline, + int ncmdshow) +{ + DLGPROC dlgproc; + HWND hwnd; + HACCEL haccel; + MSG msg; + char *p; + char buf[MAX_K_NAME_SZ + 9]; + char name[MAX_K_NAME_SZ]; + + strcpy(buf, cmdline); + action = LOGIN_AND_RUN; + name[0] = 0; + p = strtok(buf, " ,"); + + while (p != NULL) { + if (_stricmp(p, "/exit") == 0) + action = LOGIN_AND_EXIT; + else if (_stricmp(p, "/minimize") == 0) + action = LOGIN_AND_MINIMIZE; + else + strcpy(name, p); + + p = strtok(NULL, " ,"); + } + + dlgncmdshow = ncmdshow; + hinstance = hinst; + + /* + * If a previous instance of this application exits, bring it + * to the front and exit. + */ + if (hprevinstance != NULL) { + hwnd = FindWindow(KWIN_DIALOG_CLASS, NULL); + + if (IsWindow(hwnd) && IsWindowVisible(hwnd)) { + if (GetWindowWord(hwnd, GWW_HINSTANCE) == hprevinstance) { + if (name[0]) + SendMessage(hwnd, WM_KWIN_SETNAME, 0, (LONG) name); + + ShowWindow(hwnd, ncmdshow); + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, + SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); + + return FALSE; + } + } + } + + if (hprevinstance == NULL) + if (!init_application(hinstance)) + return FALSE; + + if (!init_instance(hinstance, ncmdshow)) + return FALSE; + + dlgproc = (FARPROC) MakeProcInstance(kwin_dlg_proc, hinstance); + assert(dlgproc != NULL); + + if (dlgproc == NULL) + return 1; + + hwnd = CreateDialogParam(hinstance, MAKEINTRESOURCE (ID_KWIN), + HWND_DESKTOP, dlgproc, (LONG) name); + assert(hwnd != NULL); + + if (hwnd == NULL) + return 1; + haccel = LoadAccelerators(hinstance, MAKEINTRESOURCE(IDA_KWIN)); + assert(hwnd != NULL); + + while (GetMessage(&msg, NULL, 0, 0)) { + if (!TranslateAccelerator(hwnd, haccel, &msg) && + !IsDialogMessage(hwnd, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + DestroyWindow(hwnd); + FreeProcInstance((FARPROC) dlgproc); + + return 0; + +} /* WinMain */ + + +#if 0 + + #define WM_ASYNC_COMPLETED (WM_USER + 1) + #define GETHOSTBYNAME_CLASS "krb_gethostbyname" + static HTASK htaskasync; /* Asynchronos call in progress */ + static BOOL iscompleted; /* True when async call is completed */ + + /* + * This routine is called to cancel a blocking hook call within + * the Kerberos library. The need for this routine arises due + * to bugs which exist in existing WINSOCK implementations. We + * blocking gethostbyname with WSAASyncGetHostByName. In order + * to cancel such an operation, this routine must be called. + * Applications may call this routine in addition to calls to + * WSACancelBlockingCall to get any sucy Async calls canceled. + * Return values are as they would be for WSACancelAsyncRequest. + */ + int + krb_cancel_blocking_call(void) + { + if (htaskasync == NULL) + return 0; + iscompleted = TRUE; + + return WSACancelAsyncRequest(htask); + + } /* krb_cancel_blocking_call */ + + + /* + * Window proceedure for temporary Windows created in + * krb_gethostbyname. Fields completion messages. + */ + LRESULT __export CALLBACK krb_gethostbyname_wnd_proc( + HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) + { + if (message == WM_ASYNC_COMPLETED) { + iscompleted = TRUE; + return 0; + } + + return DefWindowProc(hwnd, message, wparam, lparam); + + } /* krb_gethostbyname_wnd_proc */ + + + /* + * The WINSOCK routine gethostbyname has a bug in both FTP and NetManage + * implementations which causes the blocking hook, if any, not to be + * called. This routine attempts to work around the problem by using + * the async routines to emulate the functionality of the synchronous + * routines + */ + struct hostent FAR *PASCAL FAR + krb_gethostbyname( + const char FAR *name) + { + HWND hwnd; + char buf[MAXGETHOSTSTRUCT]; + BOOL FARPROC blockinghook; + WNDCLASS wc; + static BOOL isregistered; + + blockinghook = WSASetBlockingHook(NULL); + WSASetBlockingHook(blockinghook); + + if (blockinghook == NULL) + return gethostbyname(name); + + if (RegisterWndClass() == NULL) + return gethostbyname(name); + + if (!isregistered) { + wc.style = 0; + wc.lpfnWndProc = gethostbyname_wnd_proc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hlibinstance; + wc.hIcon = NULL; + wc.hCursor = NULL; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = GETHOSTBYNAME_CLASS; + + if (!RegisterClass(&wc)) + return gethostbyname(name); + + isregistered = TRUE; + } + + hwnd = CreateWindow(GETHOSTBYNAME_CLASS, "", WS_OVERLAPPED, + -100, -100, 0, 0, HWND_DESKTOP, NULL, hlibinstance, NULL); + if (hwnd == NULL) + return gethostbyname(name); + + htaskasync = + WSAAsyncGetHostByName(hwnd, WM_ASYNC_COMPLETED, name, buf, sizeof(buf)); + b = blockinghook(NULL); + + } /* krb_gethostbyname */ + +#endif + +#ifdef KRB5 + +void +debugbox () { + MessageBox (NULL, "foobar", "FOOBAR", IDOK | MB_ICONINFORMATION); +} + +/*+ + * Function: destroys all tickets in a k5 ccache + * + * Parameters: + * none + * + * Returns: K5 error code (0 == success) + */ +static krb5_error_code +k5_dest_tkt (void) { + krb5_error_code code; + krb5_principal princ; + char *defname; /* Name of cache */ + + if (code = krb5_cc_get_principal(k5_context, k5_ccache, &princ)) { + com_err (NULL, code, "while retrieving principal name"); + return code; + } + if (code = krb5_unparse_name(k5_context, princ, &defname)) { + com_err (NULL, code, "while unparsing principal name"); + return code; + } + + code = krb5_cc_initialize (k5_context, k5_ccache, princ); + if (code != 0) { + com_err (NULL, code, "when re-initializing cache"); + return code; + } + + return code; +} + +/*+ + * + * k5_get_num_cred + * + * Returns: number of creds in the credential cache + * + */ +static int +k5_get_num_cred () { + krb5_error_code code; + krb5_cc_cursor cursor; + krb5_creds c; + int ncreds = 0; + + if (code = krb5_cc_start_seq_get(k5_context, k5_ccache, &cursor)) { + if (code != KRB5_FCC_NOFILE) + com_err (NULL, code, "while starting to retrieve tickets"); + return 0; + } + + while (1) { + code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c); + if (code) + break; + ++ncreds; + } + + if (code == KRB5_CC_END) { /* End of ccache */ + if (code = krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor)) + com_err (NULL, code, "while finishing ticket retrieval"); + } else { + com_err (NULL, code, "while retrieving a ticket"); + return 0; + } + + return ncreds; +} + +static int +k5_get_num_cred2 () { + krb5_error_code code; + krb5_cc_cursor cursor; + krb5_creds c; + int ncreds = 0; + + code = krb5_cc_start_seq_get (k5_context, k5_ccache, &cursor); + if (code == KRB5_FCC_NOFILE) + return 0; + + while (1) { + code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c); + if (code) + break; + ++ncreds; + } + krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor); + + return ncreds; +} + +/*+ + * Function: Parses fullname into name, instance and realm + * + * Parameters: + * name - buffer filled with name of user + * + * realm - buffer filled with realm of user + * + * fullname - string in form name.instance@realm + * + * Returns: 0 + */ +static int +k5_kname_parse (char *name, char *realm, char *fullname) { + char *ptr; /* For parsing */ + + ptr = strchr (fullname, '@'); /* Name, realm separator */ + + if (ptr != NULL) { /* Get the name */ + strncpy (name, fullname, ptr - fullname); + name[ptr - fullname] = '\0'; + } else + strcpy (name, fullname); + + if (ptr != NULL) /* Get realm */ + strcpy (realm, ptr + 1); + else + *realm = '\0'; + + return 0; +} +#endif /* KRB5 */ |