netscape-revival
security/lib/nav/pwdlgs.c
/*
* Dialogs for password management
*
* Copyright © 1995 Netscape Communications Corporation, all rights reserved.
*
* $Id: pwdlgs.c,v 1.35.2.4 1997/05/24 00:23:41 jwz Exp $
*/
#include "xp.h"
#include "key.h"
#include "secitem.h"
#include "net.h"
#include "secnav.h"
#include "htmldlgs.h"
#include "secprefs.h"
#include "fe_proto.h"
#include "pk11func.h"
#include "xpgetstr.h"
#include "prefapi.h"
extern int XP_PW_SETUP_STRINGS;
extern int XP_SETUPNSPW_TITLE_STRING;
extern int XP_CHANGENSPW_TITLE_STRING;
extern int XP_PWERROR_TITLE_STRING;
extern int XP_PW_SETUP_SSO_FAIL_STRINGS;
extern int XP_SSO_GET_PW_STRINGS;
extern int XP_PW_RETRY_SSO_STRINGS;
extern int SEC_ERROR_RETRY_PASSWORD;
extern int SEC_ERROR_INVALID_PASSWORD;
extern int XP_KEY_GEN_MOREINFO_STRINGS;
extern int XP_KEY_GEN_MOREINFO_TITLE_STRING;
extern int XP_PW_MOREINFO_STRINGS;
extern int XP_PW_CHANGE_STRINGS;
extern int XP_PW_CHANGE_FAILURE_STRINGS;
extern int XP_PW_SETUP_REFUSED_STRINGS;
extern int SEC_ERROR_RETRY_OLD_PASSWORD;
extern void secmoz_SetPWEnabled(void *, PRBool enable);
static PRBool pwSetupHandler(XPDialogState *state, char **argv, int argc,
unsigned int button);
static PRBool pwSetupSSOHandler(XPDialogState *state, char **argv, int argc,
unsigned int button);
static PRBool pwChangeHandler(XPDialogState *state, char **argv, int argc,
unsigned int button);
static XPDialogInfo failureDialog = {
XP_DIALOG_OK_BUTTON,
0,
550,
300
};
typedef struct {
void *proto_win;
char *sso;
PK11SlotInfo *slot;
SECNAVPWSetupCallback cb1;
SECNAVPWSetupCallback cb2;
void *cbarg;
int error;
int button;
} PWSetupPanelState;
static XPDialogInfo pwSetupDialog = {
XP_DIALOG_OK_BUTTON | XP_DIALOG_CANCEL_BUTTON | XP_DIALOG_MOREINFO_BUTTON,
pwSetupHandler,
600,
400
};
static void
pw_setup_retry_cb(void *closure)
{
PWSetupPanelState *mystate = (PWSetupPanelState *)closure;
XPDialogStrings *strings;
#ifndef AKBAR
XPDialogState *state = NULL;
#endif /* !AKBAR */
strings = XP_GetDialogStrings(XP_PW_SETUP_STRINGS);
if (strings) {
#ifndef AKBAR
state =
#endif /* !AKBAR */
XP_MakeHTMLDialog(mystate->proto_win, &pwSetupDialog,
XP_SETUPNSPW_TITLE_STRING,
strings, (void *)mystate);
XP_FreeDialogStrings(strings);
}
if ((mystate->error != 0)
#ifndef AKBAR
&& (state != NULL) && (state->window != NULL)
#endif /* !AKBAR */
) {
FE_Alert(
#ifndef AKBAR
state->window,
#else /* AKBAR */
mystate->proto_win,
#endif /* AKBAR */
XP_GetString(mystate->error));
}
}
static XPDialogInfo infoDialog = {
XP_DIALOG_OK_BUTTON,
0,
500,
300
};
static PRBool
pwSetupNoPWHandler(XPDialogState *state, char **argv, int argc,
unsigned int button)
{
PWSetupPanelState *mystate = (PWSetupPanelState *)(state->arg);
if ( mystate->cb2 ) {
(* mystate->cb2)(mystate->cbarg, PR_FALSE);
}
if (mystate->sso != NULL) {
/* clear and free the password */
SECNAV_ZeroPassword(mystate->sso);
PORT_Free(mystate->sso);
}
if (mystate->slot != NULL) {
PK11_FreeSlot(mystate->slot);
}
PORT_Free(mystate);
return PR_FALSE;
}
static XPDialogInfo setupNoPWDialog = {
XP_DIALOG_OK_BUTTON,
pwSetupNoPWHandler,
500,
300
};
static void
pw_setup_nopw_cb(void *closure)
{
PWSetupPanelState *mystate = (PWSetupPanelState *)closure;
XPDialogStrings *strings;
strings = XP_GetDialogStrings(XP_PW_SETUP_REFUSED_STRINGS);
if (strings) {
XP_MakeHTMLDialog(mystate->proto_win, &setupNoPWDialog,
XP_SETUPNSPW_TITLE_STRING,
strings, (void *)mystate);
XP_FreeDialogStrings(strings);
}
}
static void
pw_setup_done_cb(void *closure)
{
PWSetupPanelState *mystate = (PWSetupPanelState *)closure;
if (mystate->cb2) {
if (mystate->button == XP_DIALOG_CANCEL_BUTTON) {
(* mystate->cb2)(mystate->cbarg, PR_TRUE);
} else {
(* mystate->cb2)(mystate->cbarg, PR_FALSE);
}
}
if (mystate->sso != NULL) {
/* clear and free the password */
SECNAV_ZeroPassword(mystate->sso);
PORT_Free(mystate->sso);
}
if (mystate->slot != NULL) {
PK11_FreeSlot(mystate->slot);
}
PORT_Free(mystate);
}
static PRBool
pwSetupHandler(XPDialogState *state, char **argv, int argc, unsigned int button)
{
PWSetupPanelState *mystate = (PWSetupPanelState *)(state->arg);
char *pw1 = NULL, *pw2 = NULL;
SECStatus rv;
/* save button so we can use it in pw_setup_done_cb */
mystate->button = button;
if (button == XP_DIALOG_CANCEL_BUTTON) {
if (mystate->cb1) {
(* mystate->cb1)(mystate->cbarg, PR_TRUE);
}
goto done;
}
if (button == XP_DIALOG_MOREINFO_BUTTON) {
XPDialogStrings *strings;
strings = XP_GetDialogStrings(XP_PW_MOREINFO_STRINGS);
if ( strings ) {
XP_MakeHTMLDialog(state->window, &infoDialog,
XP_KEY_GEN_MOREINFO_TITLE_STRING,
strings, 0);
XP_FreeDialogStrings(strings);
}
return PR_TRUE;
}
pw1 = XP_FindValueInArgs("password1", argv, argc);
pw2 = XP_FindValueInArgs("password2", argv, argc);
if ((pw1 != NULL) && (pw2 != NULL)) {
if (PORT_Strcmp(pw1, pw2) != 0) {
/* passwords are different; force retry */
mystate->error = SEC_ERROR_RETRY_PASSWORD;
goto retry;
}
/* check for good password here */
if (PK11_VerifyPW(mystate->slot, pw1) != SECSuccess) {
mystate->error = SEC_ERROR_INVALID_PASSWORD;
goto retry;
}
} else {
PORT_Assert(0);
return PR_FALSE;
}
if (PK11_NeedUserInit(mystate->slot)) {
rv = PK11_InitPin(mystate->slot, mystate->sso, pw1);
} else {
rv = PK11_ChangePW(mystate->slot, NULL, pw1);
}
if (mystate->cb1) {
(* mystate->cb1)(mystate->cbarg, PR_FALSE);
}
if (*pw1 == '\0') {
/* no password, pop up the no password dialog. It will do cleanup. */
state->deleteCallback = pw_setup_nopw_cb;
state->cbarg = (void *)mystate;
goto finally;
}
done:
state->deleteCallback = pw_setup_done_cb;
state->cbarg = (void *)mystate;
finally:
if (pw1 != NULL)
SECNAV_ZeroPassword(pw1);
if (pw2 != NULL)
SECNAV_ZeroPassword(pw2);
return PR_FALSE;
retry:
state->deleteCallback = pw_setup_retry_cb;
state->cbarg = (void *)mystate;
goto finally;
}
static XPDialogInfo pwSetupSSODialog = {
XP_DIALOG_OK_BUTTON | XP_DIALOG_CANCEL_BUTTON,
pwSetupSSOHandler,
600,
400
};
static void
pw_setup_sso_retry_cb(void *closure)
{
PWSetupPanelState *mystate = (PWSetupPanelState *)closure;
XPDialogStrings *strings;
char *tokenName;
strings = XP_GetDialogStrings(XP_PW_RETRY_SSO_STRINGS);
if (strings) {
tokenName = PK11_GetTokenName(mystate->slot);
XP_CopyDialogString(strings, 0, tokenName);
XP_CopyDialogString(strings, 1, tokenName);
XP_MakeHTMLDialog(mystate->proto_win, &pwSetupSSODialog,
XP_SETUPNSPW_TITLE_STRING,
strings, (void *)mystate);
XP_FreeDialogStrings(strings);
}
}
static XPDialogInfo pwSSOFailDialog = {
XP_DIALOG_OK_BUTTON,
NULL,
400,
200
};
static void
pw_setup_sso_fail_cb(void *closure)
{
PWSetupPanelState *mystate = (PWSetupPanelState *)closure;
XPDialogStrings *strings;
char *tokenName;
strings = XP_GetDialogStrings(XP_PW_SETUP_SSO_FAIL_STRINGS);
if (strings) {
tokenName = PK11_GetTokenName(mystate->slot);
XP_CopyDialogString(strings, 0, tokenName);
XP_CopyDialogString(strings, 1, XP_GetString(mystate->error));
XP_MakeHTMLDialog(mystate->proto_win, &pwSetupSSODialog,
XP_SETUPNSPW_TITLE_STRING,
strings, NULL);
XP_FreeDialogStrings(strings);
}
if (mystate->sso != NULL) {
/* clear and free the password */
SECNAV_ZeroPassword(mystate->sso);
PORT_Free(mystate->sso);
}
if (mystate->slot != NULL) {
PK11_FreeSlot(mystate->slot);
}
PORT_Free(mystate);
}
static PRBool
pwSetupSSOHandler(XPDialogState *state, char **argv, int argc,
unsigned int button)
{
PWSetupPanelState *mystate;
char *ssopw;
SECStatus rv;
mystate = (PWSetupPanelState *)(state->arg);
ssopw = XP_FindValueInArgs("ssopassword", argv, argc);
if (ssopw == NULL) {
return PR_TRUE;
} else {
/* check to make sure it's valid */
rv = PK11_CheckSSOPassword(mystate->slot,ssopw);
switch (rv) {
case SECSuccess:
/* checked out, not logout */
mystate->sso = PORT_Strdup(ssopw);
state->deleteCallback = pw_setup_retry_cb;
mystate->error = 0;
break;
case SECFailure:
state->deleteCallback = pw_setup_sso_fail_cb;
mystate->error = PORT_GetError();
break;
default:
/* everything is functioning, the Pin was just entered wrong */
state->deleteCallback = pw_setup_sso_retry_cb;
break;
}
SECNAV_ZeroPassword(ssopw);
}
state->cbarg = (void *)mystate;
return PR_FALSE;
}
void
SECNAV_MakePWSetupDialog(void *proto_win, SECNAVPWSetupCallback cb1,
SECNAVPWSetupCallback cb2, PK11SlotInfo *slot,
void *cbarg)
{
PWSetupPanelState *mystate;
XPDialogStrings *strings = NULL;
char *tokenName;
mystate = (PWSetupPanelState *)PORT_ZAlloc(sizeof(PWSetupPanelState));
if ( mystate == NULL ) {
return;
}
mystate->proto_win = proto_win;
mystate->sso = NULL;
mystate->cb1 = cb1;
mystate->cb2 = cb2;
mystate->slot = PK11_ReferenceSlot(slot);
mystate->cbarg = cbarg;
mystate->error = 0;
if (PK11_IsInternal(slot) || !PK11_NeedUserInit(slot)) {
strings = XP_GetDialogStrings(XP_PW_SETUP_STRINGS);
if (strings) {
XP_MakeHTMLDialog(proto_win, &pwSetupDialog,
XP_SETUPNSPW_TITLE_STRING,
strings, (void *)mystate);
}
} else {
strings = XP_GetDialogStrings(XP_SSO_GET_PW_STRINGS);
tokenName = PK11_GetTokenName(mystate->slot);
XP_CopyDialogString(strings, 0, tokenName);
XP_CopyDialogString(strings, 1, tokenName);
if (strings) {
XP_MakeHTMLDialog(proto_win, &pwSetupSSODialog,
XP_SETUPNSPW_TITLE_STRING,
strings, (void *)mystate);
}
}
if (strings) {
XP_FreeDialogStrings(strings);
}
}
typedef struct {
void *proto_win;
char *oldpw;
PK11SlotInfo *slot;
int error;
} PWChangePanelState;
static XPDialogInfo pwChangeDialog = {
XP_DIALOG_OK_BUTTON | XP_DIALOG_CANCEL_BUTTON | XP_DIALOG_MOREINFO_BUTTON,
pwChangeHandler,
600,
400
};
static void
pw_change_retry_cb(void *closure)
{
PWChangePanelState *mystate = (PWChangePanelState *)closure;
XPDialogStrings *strings;
#ifndef AKBAR
XPDialogState *state = NULL;
#endif /* !AKBAR */
char *tokenName;
strings = XP_GetDialogStrings(XP_PW_CHANGE_STRINGS);
if (strings) {
tokenName = PK11_GetTokenName(mystate->slot);
if (tokenName != NULL) {
XP_CopyDialogString(strings, 0, tokenName);
}
if (mystate->oldpw != NULL)
XP_CopyDialogString(strings, 1, mystate->oldpw);
#ifndef AKBAR
state =
#endif /* !AKBAR */
XP_MakeHTMLDialog(mystate->proto_win, &pwChangeDialog,
XP_CHANGENSPW_TITLE_STRING,
strings, (void *)mystate);
XP_FreeDialogStrings(strings);
}
if ((mystate->error != 0)
#ifndef AKBAR
&& (state != NULL) &&
(state->window != NULL)
#endif /* !AKBAR */
) {
FE_Alert(
#ifndef AKBAR
state->window,
#else /* AKBAR */
mystate->proto_win,
#endif /* AKBAR */
XP_GetString(mystate->error));
}
}
static void
pw_change_fail_cb(void *closure)
{
XPDialogStrings *strings;
strings = XP_GetDialogStrings(XP_PW_CHANGE_FAILURE_STRINGS);
if (strings != NULL) {
XP_MakeHTMLDialog((MWContext *)closure, &failureDialog,
XP_PWERROR_TITLE_STRING, strings, NULL);
XP_FreeDialogStrings(strings);
}
}
static XPDialogInfo changeNoPWDialog = {
XP_DIALOG_OK_BUTTON,
NULL,
500,
300
};
static void
pw_change_nopw_cb(void *closure)
{
PWChangePanelState *mystate = (PWChangePanelState *)closure;
XPDialogStrings *strings;
strings = XP_GetDialogStrings(XP_PW_SETUP_REFUSED_STRINGS);
if (strings) {
XP_MakeHTMLDialog(mystate->proto_win, &changeNoPWDialog,
XP_CHANGENSPW_TITLE_STRING,
strings, (void *)mystate);
XP_FreeDialogStrings(strings);
}
if (mystate->oldpw != NULL) {
SECNAV_ZeroPassword(mystate->oldpw);
PORT_Free(mystate->oldpw);
}
if (mystate->slot != NULL) {
PK11_FreeSlot(mystate->slot);
}
PORT_Free(mystate);
}
static PRBool
pwChangeHandler(XPDialogState *state, char **argv, int argc,
unsigned int button)
{
PWChangePanelState *mystate;
SECStatus rv;
char *pw1 = NULL, *pw2 = NULL, *oldpw = NULL;
mystate = (PWChangePanelState *)(state->arg);
if (button == XP_DIALOG_CANCEL_BUTTON) {
goto done;
}
if (button == XP_DIALOG_MOREINFO_BUTTON) {
XPDialogStrings *strings;
strings = XP_GetDialogStrings(XP_PW_MOREINFO_STRINGS);
if ( strings ) {
XP_MakeHTMLDialog(state->window, &infoDialog,
XP_CHANGENSPW_TITLE_STRING,
strings, 0);
XP_FreeDialogStrings(strings);
}
return PR_TRUE;
}
oldpw = XP_FindValueInArgs("password", argv, argc);
pw1 = XP_FindValueInArgs("password1", argv, argc);
pw2 = XP_FindValueInArgs("password2", argv, argc);
if (oldpw == NULL) {
PORT_Assert(0);
return PR_FALSE;
} else if (PORT_Strlen(oldpw) != 0) {
/* Maybe this should pop up a special error dialog. It gets the
* normal bad password one anyway. */
}
rv = PK11_CheckUserPassword(mystate->slot, oldpw);
if (rv != SECSuccess) {
mystate->error = SEC_ERROR_RETRY_OLD_PASSWORD;
SECNAV_ZeroPassword(oldpw);
oldpw = NULL;
goto retry;
}
if ((pw1 != NULL) && (pw2 != NULL)) {
if (PORT_Strcmp(pw1, pw2) != 0) {
/* passwords are different; force retry */
mystate->error = SEC_ERROR_RETRY_PASSWORD;
goto retry;
}
/* check for good password here */
if (PK11_VerifyPW(mystate->slot, pw1) != SECSuccess) {
mystate->error = SEC_ERROR_INVALID_PASSWORD;
goto retry;
}
} else {
PORT_Assert(0);
return PR_FALSE;
}
rv = PK11_ChangePW(mystate->slot, oldpw, pw1);
if (rv != SECSuccess) {
state->deleteCallback = pw_change_fail_cb;
state->cbarg = (void *)mystate->proto_win;
goto done;
}
if (*pw1 == '\0') {
/* no password, pop up the no password dialog. It will do cleanup. */
state->deleteCallback = pw_change_nopw_cb;
state->cbarg = (void *)mystate;
goto finally;
}
done:
if (mystate->oldpw != NULL) {
SECNAV_ZeroPassword(mystate->oldpw);
PORT_Free(mystate->oldpw);
}
if (mystate->slot != NULL) {
PK11_FreeSlot(mystate->slot);
}
PORT_Free(mystate);
finally:
if (oldpw != NULL)
SECNAV_ZeroPassword(oldpw);
if (pw1 != NULL)
SECNAV_ZeroPassword(pw1);
if (pw2 != NULL)
SECNAV_ZeroPassword(pw2);
return PR_FALSE;
retry:
if (mystate->oldpw != NULL) {
SECNAV_ZeroPassword(mystate->oldpw);
PORT_Free(mystate->oldpw);
mystate->oldpw = NULL;
}
if (oldpw != NULL) {
mystate->oldpw = PORT_Strdup(oldpw);
}
state->deleteCallback = pw_change_retry_cb;
state->cbarg = (void *)mystate;
goto finally;
}
void
SECNAV_MakePWChangeDialog(void *proto_win, PK11SlotInfo *slot)
{
PWChangePanelState *mystate;
XPDialogStrings *strings;
char *tokenName;
mystate = (PWChangePanelState *)PORT_ZAlloc(sizeof(PWChangePanelState));
if ( mystate == NULL ) {
return;
}
mystate->proto_win = proto_win;
mystate->oldpw = NULL;
mystate->slot = PK11_ReferenceSlot(slot);
strings = XP_GetDialogStrings(XP_PW_CHANGE_STRINGS);
if (strings) {
tokenName = PK11_GetTokenName(mystate->slot);
if (tokenName != NULL) {
XP_CopyDialogString(strings, 0, tokenName);
}
XP_MakeHTMLDialog(proto_win, &pwChangeDialog,
XP_CHANGENSPW_TITLE_STRING,
strings, (void *)mystate);
XP_FreeDialogStrings(strings);
}
}