Browse Source

Implement Password Reveal Feature

- Only "hot" user input -- i.e, freshly typed password starting
  from an empty string, with keyboard focus still in the edit
  box -- can be revealed.
  In particular, prefilled passwod (from cached value) cannot be
  revealed.
- Once keyboard focus moves out of the password edit box, the inpit has
  to be deleted for the reveal feature to get re-enabled.

Signed-off-by: Selva Nair <selva.nair@gmail.com>
pull/622/head
Selva Nair 2 years ago committed by Lev Stipakov
parent
commit
9186648285
  1. 2
      Makefile.am
  2. 25
      as.c
  3. 61
      misc.c
  4. 3
      misc.h
  5. 3
      openvpn-gui-res.h
  6. 34
      openvpn.c
  7. 2
      plap/Makefile.am
  8. 2
      plap/openvpn-plap-res.rc
  9. BIN
      res/eye-stroke.ico
  10. BIN
      res/eye.ico
  11. 16
      res/openvpn-gui-res-en.rc
  12. 2
      res/openvpn-gui-res.rc

2
Makefile.am

@ -75,6 +75,8 @@ openvpn_gui_RESOURCES = \
res/disconnected.ico \
res/openvpn-gui.ico \
res/reconnecting.ico \
res/eye.ico \
res/eye-stroke.ico \
res/openvpn-gui.manifest \
res/tileimage.bmp

25
as.c

@ -248,6 +248,8 @@ CRDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
/* disable OK button by default - not disabled in resources */
EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_RESPONSE),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), 0);
break;
case WM_COMMAND:
@ -255,6 +257,11 @@ CRDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
switch (LOWORD(wParam)) {
case ID_EDT_RESPONSE:
if (!(param->flags & FLAG_CR_ECHO))
{
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_RESPONSE),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
}
if (HIWORD(wParam) == EN_UPDATE) {
/* enable OK if response is non-empty */
BOOL enableOK = GetWindowTextLength((HWND)lParam);
@ -272,6 +279,11 @@ CRDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
case IDCANCEL:
EndDialog(hwndDlg, LOWORD(wParam));
return TRUE;
case ID_PASSWORD_REVEAL: /* password reveal symbol clicked */
ChangePasswordVisibility(GetDlgItem(hwndDlg, ID_EDT_RESPONSE),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
return TRUE;
}
break;
@ -624,15 +636,19 @@ ImportProfileFromURLDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa
}
/* disable OK button until required data is filled in */
EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), 0);
break;
case WM_COMMAND:
type = (server_type_t) GetProp(hwndDlg, cfgProp);
switch (LOWORD(wParam))
{
case ID_EDT_AUTH_USER:
case ID_EDT_AUTH_PASS:
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
/* fall through */
case ID_EDT_AUTH_USER:
case ID_EDT_URL:
if (HIWORD(wParam) == EN_UPDATE) {
/* enable OK button only if url and username are filled */
@ -690,6 +706,11 @@ ImportProfileFromURLDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lPa
case IDCANCEL:
EndDialog(hwndDlg, LOWORD(wParam));
return TRUE;
case ID_PASSWORD_REVEAL: /* password reveal symbol clicked */
ChangePasswordVisibility(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
return TRUE;
}
break;

61
misc.c

@ -1083,3 +1083,64 @@ out:
CryptReleaseContext(cp, 0);
return retval;
}
/* Setup Password reveal
* Inputs: edit handle to password edit control
* btn handle to the control that toggles the reveal
* wParam action being handled, or 0 for init
*/
void
ResetPasswordReveal(HWND edit, HWND btn, WPARAM wParam)
{
if (!edit || !btn)
{
return;
}
/* set the password field to be masked as a sane default */
SendMessage(edit, EM_SETPASSWORDCHAR, (WPARAM)'*', 0);
SendMessage(btn, STM_SETIMAGE, (WPARAM) IMAGE_ICON, (LPARAM)LoadLocalizedSmallIcon(ID_ICO_EYE));
/* if password is not masked on init, disable reveal "button" */
if (wParam == 0 && SendMessage(edit, EM_GETPASSWORDCHAR, 0, 0) == 0)
{
ShowWindow(btn, SW_HIDE);
}
/* on losing focus disable password reveal button */
else if (HIWORD(wParam) == EN_KILLFOCUS)
{
ShowWindow(btn, SW_HIDE);
}
/* if/when password is cleared enable/re-enable reveal button */
else if (GetWindowTextLength(edit) == 0)
{
ShowWindow(btn, SW_SHOW);
}
}
/* Toggle masking of text in password field
* Inputs: edit handle to password edit control
* btn handle to the control that toggles the reveal
* wParam action being handled
*/
void
ChangePasswordVisibility(HWND edit, HWND btn, WPARAM wParam)
{
if (!edit || !btn)
{
return;
}
if (HIWORD(wParam) == STN_CLICKED)
{
if (SendMessage(edit, EM_GETPASSWORDCHAR, 0, 0) == 0) /* currently visible */
{
SendMessage(edit, EM_SETPASSWORDCHAR, (WPARAM)'*', 0);
SendMessage(btn, STM_SETIMAGE, (WPARAM) IMAGE_ICON, (LPARAM)LoadLocalizedSmallIcon(ID_ICO_EYE));
}
else
{
SendMessage(edit, EM_SETPASSWORDCHAR, 0, 0);
SendMessage(btn, STM_SETIMAGE, (WPARAM) IMAGE_ICON, (LPARAM)LoadLocalizedSmallIcon(ID_ICO_EYESTROKE));
}
InvalidateRect(edit, NULL, TRUE); /* without this the control doesn't seem to get redrawn promptly */
}
}

3
misc.h

@ -156,4 +156,7 @@ bool OVPNMsgWait(DWORD timeout, HWND hdlg);
bool GetRandomPassword(char *buf, size_t len);
void ResetPasswordReveal(HWND edit, HWND btn, WPARAM wParam);
void ChangePasswordVisibility(HWND edit, HWND btn, WPARAM wParam);
#endif

3
openvpn-gui-res.h

@ -27,6 +27,8 @@
#define ID_ICO_CONNECTED 91
#define ID_ICO_CONNECTING 92
#define ID_ICO_DISCONNECTED 93
#define ID_ICO_EYE 94
#define ID_ICO_EYESTROKE 95
/* About Dialog */
#define ID_DLG_ABOUT 100
@ -39,6 +41,7 @@
#define ID_DLG_PASSPHRASE 150
#define ID_EDT_PASSPHRASE 151
#define ID_LTEXT_PASSWORD 152
#define ID_PASSWORD_REVEAL 153
/* Status Dialog */
#define ID_DLG_STATUS 160

34
openvpn.c

@ -575,7 +575,8 @@ UserAuthDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
ForceForegroundWindow(hwndDlg);
else
SetForegroundWindow(hwndDlg);
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), 0);
break;
case WM_LBUTTONDOWN:
@ -590,8 +591,11 @@ UserAuthDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
param = (auth_param_t *) GetProp(hwndDlg, cfgProp);
switch (LOWORD(wParam))
{
case ID_EDT_AUTH_USER:
case ID_EDT_AUTH_PASS:
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
/* fall through */
case ID_EDT_AUTH_USER:
case ID_EDT_AUTH_CHALLENGE:
if (HIWORD(wParam) == EN_UPDATE)
{
@ -654,6 +658,11 @@ UserAuthDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
EndDialog(hwndDlg, LOWORD(wParam));
StopOpenVPN(param->c);
return TRUE;
case ID_PASSWORD_REVEAL: /* password reveal symbol clicked */
ChangePasswordVisibility(GetDlgItem(hwndDlg, ID_EDT_AUTH_PASS),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
return TRUE;
}
break;
@ -771,6 +780,8 @@ GenericPassDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
/* disable OK button until response is filled-in */
EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
}
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_RESPONSE),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), 0);
break;
@ -781,6 +792,11 @@ GenericPassDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
switch (LOWORD(wParam))
{
case ID_EDT_RESPONSE:
if (!(param->flags & FLAG_CR_ECHO))
{
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_RESPONSE),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
}
if (HIWORD(wParam) == EN_UPDATE)
{
/* enable OK if response is non-empty */
@ -854,6 +870,11 @@ GenericPassDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
EndDialog(hwndDlg, LOWORD(wParam));
StopOpenVPN(param->c);
return TRUE;
case ID_PASSWORD_REVEAL: /* password reveal symbol clicked */
ChangePasswordVisibility(GetDlgItem(hwndDlg, ID_EDT_RESPONSE),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
return TRUE;
}
break;
@ -926,6 +947,8 @@ PrivKeyPassDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
/* disable OK button by default - not disabled in resources */
EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_PASSPHRASE),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), 0);
break;
case WM_COMMAND:
@ -944,6 +967,8 @@ PrivKeyPassDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
break;
case ID_EDT_PASSPHRASE:
ResetPasswordReveal(GetDlgItem(hwndDlg, ID_EDT_PASSPHRASE),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
if (HIWORD(wParam) == EN_UPDATE)
{
/* enable OK if response is non-empty */
@ -975,6 +1000,11 @@ PrivKeyPassDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
EndDialog(hwndDlg, LOWORD(wParam));
StopOpenVPN (c);
return TRUE;
case ID_PASSWORD_REVEAL: /* password reveal symbol clicked */
ChangePasswordVisibility(GetDlgItem(hwndDlg, ID_EDT_PASSPHRASE),
GetDlgItem(hwndDlg, ID_PASSWORD_REVEAL), wParam);
return TRUE;
}
break;

2
plap/Makefile.am

@ -67,6 +67,8 @@ libopenvpn_plap_la_RESOURCES = \
$(top_srcdir)/res/disconnected.ico \
$(top_srcdir)/res/openvpn-gui.ico \
$(top_srcdir)/res/reconnecting.ico \
$(top_srcdir)/res/eye.ico \
$(top_srcdir)/res/eye-stroke.ico \
openvpn-plap-res.rc \
openvpn-plap.manifest

2
plap/openvpn-plap-res.rc

@ -39,6 +39,8 @@ ID_ICO_APP ICON DISCARDABLE "../res/openvpn-gui.ico"
ID_ICO_CONNECTED ICON DISCARDABLE "../res/connected.ico"
ID_ICO_CONNECTING ICON DISCARDABLE "../res/connecting.ico"
ID_ICO_DISCONNECTED ICON DISCARDABLE "../res/disconnected.ico"
ID_ICO_EYE ICON DISCARDABLE "../res/eye.ico"
ID_ICO_EYESTROKE ICON DISCARDABLE "../res/eye-stroke.ico"
IDB_TILE_IMAGE BITMAP DISCARDABLE "../res/tileimage.bmp"

BIN
res/eye-stroke.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
res/eye.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

16
res/openvpn-gui-res-en.rc

@ -30,6 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
BEGIN
LTEXT "Enter &Password:", 201, 6, 6, 100, 10
EDITTEXT ID_EDT_PASSPHRASE, 6, 17, 107, 12, ES_PASSWORD | ES_AUTOHSCROLL
ICON ID_ICO_EYE, ID_PASSWORD_REVEAL, 126, 18, 14, 14, SS_ICON|SS_NOTIFY|SS_REALSIZEIMAGE
CHECKBOX "&Save password", ID_CHK_SAVE_PASS, 6, 33, 100, 10
PUSHBUTTON "&OK", IDOK, 20, 49, 50, 14
PUSHBUTTON "&Cancel", IDCANCEL, 90, 49, 50, 14
@ -37,7 +38,7 @@ BEGIN
END
/* Auth Username/Password Dialog */
ID_DLG_AUTH DIALOGEX 6, 18, 160, 95
ID_DLG_AUTH DIALOGEX 6, 18, 180, 95
STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_CENTER | DS_SETFOREGROUND
EXSTYLE WS_EX_TOPMOST
FONT 8, "Microsoft Sans Serif"
@ -47,6 +48,7 @@ BEGIN
EDITTEXT ID_EDT_AUTH_USER, 60, 6, 94, 12, ES_AUTOHSCROLL
LTEXT "&Password:", ID_LTEXT_PASSWORD, 6, 26, 50, 10
EDITTEXT ID_EDT_AUTH_PASS, 60, 23, 94, 12, ES_PASSWORD | ES_AUTOHSCROLL
ICON ID_ICO_EYE, ID_PASSWORD_REVEAL, 156, 24, 14, 14, SS_ICON|SS_NOTIFY|SS_REALSIZEIMAGE
CHECKBOX "&Save password", ID_CHK_SAVE_PASS, 6, 42, 100, 10
PUSHBUTTON "&OK", IDOK, 20, 58, 50, 14, BS_DEFPUSHBUTTON | WS_TABSTOP | WS_DISABLED
PUSHBUTTON "&Cancel", IDCANCEL, 90, 58, 52, 14
@ -54,7 +56,7 @@ BEGIN
END
/* Auth Username/Password/Challenge Dialog */
ID_DLG_AUTH_CHALLENGE DIALOG 6, 18, 160, 129
ID_DLG_AUTH_CHALLENGE DIALOGEX 6, 18, 180, 129
STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | DS_CENTER | DS_SETFOREGROUND
EXSTYLE WS_EX_TOPMOST
CAPTION "OpenVPN – User Authentication"
@ -65,6 +67,7 @@ BEGIN
EDITTEXT ID_EDT_AUTH_USER, 60, 6, 94, 12, ES_AUTOHSCROLL
LTEXT "&Password:", ID_LTEXT_PASSWORD, 6, 26, 50, 10
EDITTEXT ID_EDT_AUTH_PASS, 60, 23, 94, 12, ES_PASSWORD | ES_AUTOHSCROLL
ICON ID_ICO_EYE, ID_PASSWORD_REVEAL, 156, 24, 14, 14, SS_ICON|SS_NOTIFY|SS_REALSIZEIMAGE
LTEXT "&Response:", ID_LTEXT_RESPONSE, 6, 60, 50, 10
LTEXT "", ID_TXT_AUTH_CHALLENGE, 6, 43, 148, 10
EDITTEXT ID_EDT_AUTH_CHALLENGE, 60, 57, 94, 12, ES_PASSWORD | ES_AUTOHSCROLL
@ -75,7 +78,7 @@ BEGIN
END
/* Challenge Response Dialog */
ID_DLG_CHALLENGE_RESPONSE DIALOG 6, 18, 212, 72
ID_DLG_CHALLENGE_RESPONSE DIALOGEX 6, 18, 212, 72
STYLE WS_SIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | DS_CENTER | DS_SETFOREGROUND
EXSTYLE WS_EX_TOPMOST
CAPTION "OpenVPN – Challenge Response"
@ -85,6 +88,7 @@ BEGIN
LTEXT "", ID_TXT_DESCRIPTION, 6, 9, 400, 20
LTEXT "&Response:", ID_LTEXT_RESPONSE, 6, 30, 50, 10
EDITTEXT ID_EDT_RESPONSE, 60, 27, 94, 12, ES_PASSWORD | ES_AUTOHSCROLL
ICON ID_ICO_EYE, ID_PASSWORD_REVEAL, 156, 28, 14, 14, SS_ICON|SS_NOTIFY|SS_REALSIZEIMAGE
PUSHBUTTON "&OK", IDOK, 20, 51, 50, 14, BS_PUSHBUTTON | WS_TABSTOP
PUSHBUTTON "&Cancel", IDCANCEL, 90, 51, 52, 14
END
@ -265,7 +269,7 @@ https://openvpn.net/", ID_LTEXT_ABOUT4, 8, 106, 240, 64
END
/* Proxy Authentication Dialog */
ID_DLG_PROXY_AUTH DIALOG 29, 23, 154, 65
ID_DLG_PROXY_AUTH DIALOGEX 29, 23, 170, 65
STYLE DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | DS_CENTER
EXSTYLE WS_EX_TOPMOST
CAPTION "OpenVPN – Proxy Authentication"
@ -276,11 +280,12 @@ BEGIN
EDITTEXT ID_EDT_PROXY_USER, 49, 5, 94, 12, ES_AUTOHSCROLL
LTEXT "&Password:", 202, 9, 26, 38, 10
EDITTEXT ID_EDT_PROXY_PASS, 49, 23, 94, 12, ES_PASSWORD | ES_AUTOHSCROLL
ICON ID_ICO_EYE, ID_PASSWORD_REVEAL, 145, 24, 14, 14, SS_ICON|SS_NOTIFY|SS_REALSIZEIMAGE
PUSHBUTTON "&OK", IDOK, 58, 43, 40, 14, BS_PUSHBUTTON | WS_TABSTOP | WS_DISABLED
END
/* URL Profile Import Dialog */
ID_DLG_URL_PROFILE_IMPORT DIALOG 6, 18, 249, 95
ID_DLG_URL_PROFILE_IMPORT DIALOGEX 6, 18, 249, 95
STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_CENTER | DS_SETFOREGROUND
CAPTION "Import Profile from Access Server"
FONT 8, "Microsoft Sans Serif"
@ -292,6 +297,7 @@ BEGIN
EDITTEXT ID_EDT_AUTH_USER, 60, 23, 94, 12, ES_AUTOHSCROLL
LTEXT "&Password:", ID_LTEXT_PASSWORD, 6, 42, 50, 10
EDITTEXT ID_EDT_AUTH_PASS, 60, 40, 94, 12, ES_PASSWORD | ES_AUTOHSCROLL
ICON ID_ICO_EYE, ID_PASSWORD_REVEAL, 156, 41, 14, 14, SS_ICON|SS_NOTIFY|SS_REALSIZEIMAGE
AUTOCHECKBOX "&Autologin", ID_CHK_AUTOLOGIN, 6, 59, 100, 10
PUSHBUTTON "&OK", IDOK, 20, 76, 50, 14, BS_PUSHBUTTON | WS_TABSTOP | WS_DISABLED
PUSHBUTTON "&Cancel", IDCANCEL, 90, 76, 52, 14

2
res/openvpn-gui-res.rc

@ -38,6 +38,8 @@ ID_ICO_APP ICON DISCARDABLE "openvpn-gui.ico"
ID_ICO_CONNECTED ICON DISCARDABLE "connected.ico"
ID_ICO_CONNECTING ICON DISCARDABLE "connecting.ico"
ID_ICO_DISCONNECTED ICON DISCARDABLE "disconnected.ico"
ID_ICO_EYE ICON DISCARDABLE "eye.ico"
ID_ICO_EYESTROKE ICON DISCARDABLE "eye-stroke.ico"
#ifdef ENABLE_OVPN3
#define ADVANCED_DIALOG_HEIGHT 320

Loading…
Cancel
Save