diff options
author | Jonathan Prykop <jonathan@freeside.biz> | 2015-12-02 05:02:17 -0600 |
---|---|---|
committer | Jonathan Prykop <jonathan@freeside.biz> | 2015-12-14 20:22:09 -0600 |
commit | 8cd6e05d5d906da6b001b36bab5aa87ecdfca944 (patch) | |
tree | 4ad1a33fa011bc8a5b84bea69b9afebb6bd5d110 /fs_selfservice | |
parent | 4ff9a50fe7f35179314967d71ae66b696ab006c5 (diff) |
RT#29354: Password Security in Email [xmlhttp validation for selfservice]
Diffstat (limited to 'fs_selfservice')
8 files changed, 151 insertions, 5 deletions
diff --git a/fs_selfservice/FS-SelfService/SelfService.pm b/fs_selfservice/FS-SelfService/SelfService.pm index f4b47b2..4023aa8 100644 --- a/fs_selfservice/FS-SelfService/SelfService.pm +++ b/fs_selfservice/FS-SelfService/SelfService.pm @@ -99,6 +99,7 @@ $socket .= '.'.$tag if defined $tag && length($tag); 'reset_passwd' => 'MyAccount/reset_passwd', 'check_reset_passwd' => 'MyAccount/check_reset_passwd', 'process_reset_passwd' => 'MyAccount/process_reset_passwd', + 'validate_passwd' => 'MyAccount/validate_passwd', 'list_tickets' => 'MyAccount/list_tickets', 'create_ticket' => 'MyAccount/create_ticket', 'get_ticket' => 'MyAccount/get_ticket', diff --git a/fs_selfservice/FS-SelfService/cgi/add_password_validation.html b/fs_selfservice/FS-SelfService/cgi/add_password_validation.html new file mode 100644 index 0000000..e349fd7 --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/add_password_validation.html @@ -0,0 +1,36 @@ +<SCRIPT> +function add_password_validation (fieldid) { + var inputfield = document.getElementById(fieldid); + inputfield.onchange = function () { + var fieldid = this.id+'_result'; + var resultfield = document.getElementById(fieldid); + var svcnum = ''; + var svcfield = document.getElementById(this.id+'_svcnum'); + if (svcfield) { + svcnum = svcfield.options[svcfield.selectedIndex].value; + } + if (this.value) { + resultfield.innerHTML = '<SPAN STYLE="color: blue;">Validating password...</SPAN>'; + send_xmlhttp('selfservice.cgi', + ['action','validate_password','fieldid',fieldid,'svcnum',svcnum,'check_password',this.value], + function (result) { + result = JSON.parse(result); + var resultfield = document.getElementById(result.fieldid); + if (resultfield) { + if (result.valid) { + resultfield.innerHTML = '<SPAN STYLE="color: green;">Password valid!</SPAN>'; + } else if (result.error) { + resultfield.innerHTML = '<SPAN STYLE="color: red;">'+result.error+'</SPAN>'; + } else { + result.syserror = result.syserror || 'Server error'; + resultfield.innerHTML = '<SPAN STYLE="color: red;">'+result.syserror+'</SPAN>'; + } + } + } + ); + } else { + resultfield.innerHTML = ''; + } + }; +} +</SCRIPT> diff --git a/fs_selfservice/FS-SelfService/cgi/change_password.html b/fs_selfservice/FS-SelfService/cgi/change_password.html index 22d8973..ef66554 100644 --- a/fs_selfservice/FS-SelfService/cgi/change_password.html +++ b/fs_selfservice/FS-SelfService/cgi/change_password.html @@ -12,7 +12,7 @@ <TR> <TH ALIGN="right">Change password for account: </TH> <TD> - <SELECT NAME="svcnum"> + <SELECT ID="new_password_svcnum" NAME="svcnum"> <%= foreach my $svc ( @svcs ) { $OUT .= '<OPTION VALUE="'. $svc->{'svcnum'}. '"'. ( $svc->{'svcnum'} eq $svcnum ? ' SELECTED' : '' ). '>'. @@ -25,7 +25,15 @@ <TR> <TH ALIGN="right">New password: </TH> - <TD><INPUT TYPE="password" NAME="new_password" SIZE="18"></TD> + <TD> + <INPUT ID="new_password" TYPE="password" NAME="new_password" SIZE="18"> + <DIV ID="new_password_result"></DIV> +<%= include('send_xmlhttp') %> +<%= include('add_password_validation') %> +<SCRIPT> +add_password_validation('new_password'); +</SCRIPT> + </TD> </TR> <TR> diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index b2ebaef..5845122 100755 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -23,6 +23,7 @@ use FS::SelfService qw( mason_comp port_graph start_thirdparty finish_thirdparty reset_passwd check_reset_passwd process_reset_passwd + validate_passwd billing_history ); @@ -85,6 +86,7 @@ my @actions = ( qw( process_suspend_pkg switch_cust history + validate_password )); my @nologin_actions = (qw( @@ -109,7 +111,6 @@ if ( $cgi->param('action') =~ /^process_forgot_password_session_(\w+)$/ ) { warn "WARNING: unrecognized action '$1'\n"; } } - unless ( $nologin_actions{$action} ) { my %cookies = CGI::Cookie->fetch; @@ -1123,6 +1124,14 @@ sub do_process_forgot_password { ); } +sub validate_password { + validate_passwd( + 'session_id' => $session_id, + map { $_ => scalar($cgi->param($_)) } + qw( fieldid svcnum check_password ) + ) +} + #-- sub do_template { diff --git a/fs_selfservice/FS-SelfService/cgi/send_xmlhttp.html b/fs_selfservice/FS-SelfService/cgi/send_xmlhttp.html new file mode 100644 index 0000000..ac85cb2 --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/send_xmlhttp.html @@ -0,0 +1,45 @@ +<SCRIPT> +function rs_init_object () { + var A; + try { + A=new ActiveXObject("Msxml2.XMLHTTP"); + } catch (e) { + try { + A=new ActiveXObject("Microsoft.XMLHTTP"); + } catch (oc) { + A=null; + } + } + if(!A && typeof XMLHttpRequest != "undefined") + A = new XMLHttpRequest(); + if (!A) + alert("Can't create XMLHttpRequest object"); + return A; +} + +function send_xmlhttp (url,args,callback) { + args = args || []; + callback = callback || function (data) { return data }; + var content = ''; + for (var i = 0; i < args.length; i = i + 2) { + content = content + "&" + args[i] + "=" + escape(args[i+1]); + } + content = content.replace( /[+]/g, '%2B'); // fix unescaped plus signs + + var xmlhttp = rs_init_object(); + xmlhttp.open("POST", url, true); + + xmlhttp.onreadystatechange = function() { + if (xmlhttp.readyState != 4) + return; + if (xmlhttp.status == 200) { + var data = xmlhttp.responseText; + callback(data); + } + }; + + xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + xmlhttp.send(content); +} +</SCRIPT> + diff --git a/fs_selfservice/FS-SelfService/cgi/signup.cgi b/fs_selfservice/FS-SelfService/cgi/signup.cgi index 817fdd3..072ce96 100755 --- a/fs_selfservice/FS-SelfService/cgi/signup.cgi +++ b/fs_selfservice/FS-SelfService/cgi/signup.cgi @@ -508,3 +508,31 @@ use FS::SelfService qw( regionselector expselect popselector domainselector didselector ); +sub add_password_validation { + my $fieldid = shift; + my $out = ''; + if ((-e './send_xmlhttp.html') && (-e './add_password_validation.html')) { + my $template = new Text::Template( TYPE => 'FILE', + SOURCE => "./send_xmlhttp.html", + DELIMITERS => [ '<%=', '%>' ], + UNTAINT => 1, + ) + or die $Text::Template::ERROR; + $out .= $template->fill_in( PACKAGE => 'FS::SelfService::_signupcgi' ); + $template = new Text::Template( TYPE => 'FILE', + SOURCE => "./add_password_validation.html", + DELIMITERS => [ '<%=', '%>' ], + UNTAINT => 1, + ) + or die $Text::Template::ERROR; + $out .= $template->fill_in( PACKAGE => 'FS::SelfService::_signupcgi' ); + $out .= <<ENDOUT; +<SCRIPT> +add_password_validation('$fieldid'); +</SCRIPT> +ENDOUT + } + return $out; +} + + diff --git a/fs_selfservice/FS-SelfService/cgi/signup.html b/fs_selfservice/FS-SelfService/cgi/signup.html index 2bc59ca..5900ba6 100755 --- a/fs_selfservice/FS-SelfService/cgi/signup.html +++ b/fs_selfservice/FS-SelfService/cgi/signup.html @@ -336,7 +336,8 @@ HTML::Widgets::SelectLayers->new( <FORM name="signup_form" action="<%= $self_url %>" METHOD="POST" onsubmit="return fixup_form();"><BR><FONT SIZE="+1"><B>First package</B></FONT> <INPUT TYPE="hidden" NAME="promo_code" VALUE="<%= $promo_code %>"> <INPUT TYPE="hidden" NAME="reg_code" VALUE="<%= $reg_code %>"> -<TABLE BGCOLOR="<%= $box_bgcolor || '#c0c0c0' %>" BORDER=0 CELLSPACING=0 WIDTH="100%"> +<DIV STYLE="background: <%= $box_bgcolor %>; width: 100%"> +<TABLE BGCOLOR="<%= $box_bgcolor || '#c0c0c0' %>" BORDER=0 CELLSPACING=0> <TR> <TD COLSPAN=2><SELECT NAME="pkgpart"> @@ -383,7 +384,15 @@ ENDOUT $OUT .= <<ENDOUT; <TR> <TD ALIGN="right">Password</TD> - <TD><INPUT TYPE="password" NAME="_password" VALUE="$_password"></TD> + <TD> + <INPUT ID="new_password" TYPE="password" NAME="_password" VALUE="$_password"> + <DIV ID="new_password_result"></DIV> +ENDOUT + + $OUT .= add_password_validation('new_password'); + + $OUT .= <<ENDOUT; + </TD> </TR> <TR> <TD ALIGN="right">Re-enter Password</TD> @@ -433,6 +442,7 @@ NOMADIX %> </TABLE> +</DIV> <%= if ( @optional_packages ) { diff --git a/fs_selfservice/FS-SelfService/cgi/validate_password.html b/fs_selfservice/FS-SelfService/cgi/validate_password.html new file mode 100644 index 0000000..5cc3167 --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/validate_password.html @@ -0,0 +1,9 @@ +<%= use JSON; + encode_json({ + 'valid' => $password_valid ? 1 : 0, + 'error' => $password_invalid, + 'syserror' => $error, + 'fieldid' => $fieldid, + 'password_debug' => $password_debug, + }); %> + |