diff --git a/ChangeLog b/ChangeLog index 4d9a92c04..2bab950d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-03-14 Ludovic Marcotte + + * Improved the password policy code. All corner + cases should now be handled correctly. + 2010-03-12 Wolfgang Sourdeau * SoObjects/Appointments/SOGoAppointmentObject.m diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m index a1da79fcb..11dcf1a11 100644 --- a/UI/MainUI/SOGoRootPage.m +++ b/UI/MainUI/SOGoRootPage.m @@ -1,20 +1,22 @@ /* + + Copyright (C) 2006-2010 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG - This file is part of OpenGroupware.org. + This file is part of SOGo. - OGo is free software; you can redistribute it and/or modify it under + SOGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - OGo is distributed in the hope that it will be useful, but WITHOUT ANY + SOGo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with OGo; see the file COPYING. If not, write to the + License along with SOGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -137,7 +139,7 @@ BOOL b; err = PolicyNoError; - expire = grace = 0; + expire = grace = -1; auth = [[WOApplication application] authenticatorInContext: context]; @@ -148,17 +150,23 @@ if ((b = [auth checkLogin: username password: password perr: &err expire: &expire grace: &grace]) - && (err == PolicyNoError)) + && (err == PolicyNoError) + // no password policy + && ((expire < 0 && grace < 0) // no password policy or everything is alright + || (expire < 0 && grace > 0) // password expired, grace still permits login + || (expire > 0 && grace == -1))) // password about to expire { - [self logWithFormat: @"successful login for user '%@'", username]; - response = [self responseWith204]; - - // We must warn the user that he has to change his password - if (err == PolicyChangeAfterReset) - { - - } + NSDictionary *json; + [self logWithFormat: @"successful login for user '%@' - expire = %d grace = %d", username, expire, grace]; + + + json = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: expire], @"expire", + [NSNumber numberWithInt: grace], @"grace", nil]; + + response = [self responseWithStatus: 200 + andJSONRepresentation: json]; + authCookie = [self _cookieWithUsername: username andPassword: password forAuthenticator: auth]; [response addCookie: authCookie]; @@ -174,20 +182,7 @@ } else { - [self logWithFormat: @"Login for user '%@' might not have worked - password policy: %d bound: ", username, err, b]; - - if (err == PolicyNoError) - { - [self logWithFormat: @"failed login for user '%@' due to wrong password", username]; - } - else if (err == PolicyAccountLocked) - { - // Account has been locked due to too many failures - } - else if (err == PolicyPasswordExpired) - { - // The password MUST be changed - we need to ask for the old password and the new one here - } + [self logWithFormat: @"Login for user '%@' might not have worked - password policy: %d grace: %d expire: %d bound: %d", username, err, grace, expire, b]; response = [self _responseWithLDAPPolicyError: err]; } diff --git a/UI/WebServerResources/SOGoRootPage.js b/UI/WebServerResources/SOGoRootPage.js index 06c6bb64d..bf2679ea7 100644 --- a/UI/WebServerResources/SOGoRootPage.js +++ b/UI/WebServerResources/SOGoRootPage.js @@ -79,7 +79,7 @@ function onLoginClick(event) { : ("&language=" + language.value)); /// Discarded as it seems to create a cookie for nothing. To discard // a cookie in JS, have a look here: http://www.quirksmode.org/js/cookies.html - //document.cookie = ""; + //document.cookie = "";\ triggerAjaxRequest(url, onLoginCallback, null, (parameters), { "Content-type": "application/x-www-form-urlencoded", "Content-length": parameters.length, @@ -95,7 +95,7 @@ function onLoginCallback(http) { if (http.readyState == 4) { var submitBtn = $("submit"); - if (isHttpStatus204(http.status)) { + if (http.status == 200) { // Make sure browser's cookies are enabled var loginCookie = readLoginCookie(); if (!loginCookie) { @@ -104,7 +104,21 @@ function onLoginCallback(http) { return; } - redirectToUserPage(); + var jsonResponse = http.responseText.evalJSON(false); + if (jsonResponse + && typeof(jsonResponse["expire"]) != "undefined" + && typeof(jsonResponse["grace"]) != "undefined") { + + if (jsonResponse["expire"] < 0 && jsonResponse["grace"] > 0) + showPasswordDialog("grace", createPasswordGraceDialog, jsonResponse["grace"]); + else if (jsonResponse["expire"] > 0 && jsonResponse["grace"] == -1) + showPasswordDialog("expiration", createPasswordExpirationDialog, jsonResponse["expire"]); + else { + redirectToUserPage(); + } + } + else + redirectToUserPage(); } else { if (http.status == 403 @@ -159,10 +173,14 @@ function handlePasswordError(jsonResponse) { SetLogMessage("errorMessage", _("Your account was locked due to too many" + " failed attempts.")); - } else if (perr == PolicyChangeAfterReset - || perr == PolicyPasswordExpired) { + } else if (perr == PolicyChangeAfterReset) { showPasswordDialog("change", createPasswordChangeDialog, 5); - } else + } else if (perr == PolicyPasswordExpired) { + SetLogMessage("errorMessage", + _("Your account was locked due to an" + + " expired password.")); + } + else SetLogMessage("errorMessage", _("Login failed due to unhandled error case: " + perr)); } @@ -268,9 +286,8 @@ function createPasswordGraceDialog(tries) { return createDialog("passwordGraceDialog", _("Password Grace Period"), _("You have %{0} logins remaining before your" - + " password expires. Please change your" - + " password in the preference dialog.") - .formatted(tries), + + " account is locked. Please change your" + + " password in the preference dialog.").formatted(tries), button, "right"); } @@ -279,6 +296,26 @@ function passwordGraceDialogOK(event) { var dialog = $("passwordGraceDialog"); dialog.hide(); event.stop(); + redirectToUserPage(); +} + +function createPasswordExpirationDialog(expire) { + var button = createButton("expirationOKButton", _("OK")); + button.observe("click", passwordExpirationDialogOK); + button.addClassName("actionButton"); + + return createDialog("passwordExpirationDialog", + _("Password about to expire"), + _("Your password is going to expire in %{0} seconds.").formatted(expire), + button, + "right"); +} + +function passwordExpirationDialogOK(event) { + var dialog = $("passwordExpirationDialog"); + dialog.hide(); + event.stop(); + redirectToUserPage(); } document.observe("dom:loaded", initLogin);