Repository: openmeetings Updated Branches: refs/heads/3.3.x ae930bedc -> 156bcc792
no jira: fallback mechanism for ICrypt is implemented Project: http://git-wip-us.apache.org/repos/asf/openmeetings/repo Commit: http://git-wip-us.apache.org/repos/asf/openmeetings/commit/156bcc79 Tree: http://git-wip-us.apache.org/repos/asf/openmeetings/tree/156bcc79 Diff: http://git-wip-us.apache.org/repos/asf/openmeetings/diff/156bcc79 Branch: refs/heads/3.3.x Commit: 156bcc792e7eabea6c8425e5df2de7009dcf15cf Parents: ae930be Author: Maxim Solodovnik <[email protected]> Authored: Sat Jun 17 13:12:25 2017 +0700 Committer: Maxim Solodovnik <[email protected]> Committed: Sat Jun 17 13:12:25 2017 +0700 ---------------------------------------------------------------------- .../db/dao/basic/MailMessageDao.java | 2 +- .../openmeetings/db/dao/user/UserDao.java | 32 ++++++++-- .../apache/openmeetings/util/crypt/ICrypt.java | 17 ++++- .../util/crypt/MD5Implementation.java | 48 +++++++++++++++ .../util/crypt/SCryptImplementation.java | 11 ++++ .../util/crypt/SHA256Implementation.java | 63 +++++++++++++++++++ .../openmeetings/util/crypt/TestSCrypt.java | 16 +++++ .../TestDatabaseStructureAppointment.java | 65 ++++++++------------ 8 files changed, 205 insertions(+), 49 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/openmeetings/blob/156bcc79/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/MailMessageDao.java ---------------------------------------------------------------------- diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/MailMessageDao.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/MailMessageDao.java index aed66db..8fa1aa5 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/MailMessageDao.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/MailMessageDao.java @@ -111,7 +111,7 @@ public class MailMessageDao implements IDataProviderDao<MailMessage> { em.persist(m); } else { m.setUpdated(Calendar.getInstance()); - m = em.merge(m); + m = em.merge(m); } return m; } http://git-wip-us.apache.org/repos/asf/openmeetings/blob/156bcc79/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/user/UserDao.java ---------------------------------------------------------------------- diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/user/UserDao.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/user/UserDao.java index 2998497..2b6d2c3 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/user/UserDao.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/user/UserDao.java @@ -59,6 +59,7 @@ import org.apache.openmeetings.db.util.UserHelper; import org.apache.openmeetings.util.DaoHelper; import org.apache.openmeetings.util.OmException; import org.apache.openmeetings.util.crypt.CryptProvider; +import org.apache.openmeetings.util.crypt.ICrypt; import org.apache.wicket.util.string.Strings; import org.red5.logging.Red5LoggerFactory; import org.slf4j.Logger; @@ -236,7 +237,7 @@ public class UserDao implements IGroupAdminDataProviderDao<User> { em.persist(u); } else { u.setUpdated(new Date()); - u = em.merge(u); + u = em.merge(u); } return u; } @@ -250,6 +251,13 @@ public class UserDao implements IGroupAdminDataProviderDao<User> { return u; } + private User updatePassword(Long id, String pwd, Long updatedBy) throws NoSuchAlgorithmException { + //OpenJPA is not allowing to set fields not being fetched before + User u = get(id, true); + u.updatePassword(cfgDao, pwd); + return update(u, updatedBy); + } + // TODO: Why the password field is not set via the Model is because its // FetchType is Lazy, this extra hook here might be not needed with a // different mechanism to protect the password from being read @@ -257,10 +265,7 @@ public class UserDao implements IGroupAdminDataProviderDao<User> { public User update(User user, String password, Long updatedBy) throws NoSuchAlgorithmException { User u = update(user, updatedBy); if (u != null && !Strings.isEmpty(password)) { - //OpenJPA is not allowing to set fields not being fetched before - User u1 = get(u.getId(), true); - u1.updatePassword(cfgDao, password); - u = update(u1, updatedBy); + u = updatePassword(u.getId(), password, updatedBy); } return u; } @@ -464,7 +469,22 @@ public class UserDao implements IGroupAdminDataProviderDao<User> { if (l == null || l.size() != 1) { return false; } - return CryptProvider.get().verify(password, l.get(0)); + String hash = l.get(0); + ICrypt crypt = CryptProvider.get(); + if (crypt.verify(password, hash)) { + return true; + } + if (crypt.fallback(password, hash)) { + log.warn("Password for user with ID {} crypted with outdated Crypt, updating ...", userId); + try { + User u = updatePassword(userId, password, userId); + log.warn("Password for user {} updated successfully", u); + return true; + } catch (NoSuchAlgorithmException e) { + log.error("Unexpected exception while updating password"); + } + } + return false; } public User getContact(String email, Long ownerId) { http://git-wip-us.apache.org/repos/asf/openmeetings/blob/156bcc79/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/ICrypt.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/ICrypt.java b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/ICrypt.java index 6837f64..88b8c7f 100644 --- a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/ICrypt.java +++ b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/ICrypt.java @@ -22,7 +22,7 @@ package org.apache.openmeetings.util.crypt; * Interface for Encryption-Class see: * http://openmeetings.apache.org/CustomCryptMechanism.html see: * https://crackstation.net/hashing-security.htm - * + * * @author sebastianwagner, solomax * */ @@ -30,7 +30,7 @@ package org.apache.openmeetings.util.crypt; public interface ICrypt { /** * Creates hash of given string - * + * * @param str * - string to calculate hash for * @return hash of passed string @@ -39,7 +39,7 @@ public interface ICrypt { /** * Verify string passed is matches given hash - * + * * @param str * - string to check hash for * @param hash @@ -47,4 +47,15 @@ public interface ICrypt { * @return <code>true</code> in case string matches hash, <code>false</code> otherwise */ boolean verify(String str, String hash); + + /** + * Verify string passed is matches given hash (using fallback crypt mechanism) + * + * @param str + * - string to check hash for + * @param hash + * - hash to compare + * @return <code>true</code> in case string matches hash, <code>false</code> otherwise + */ + boolean fallback(String str, String hash); } http://git-wip-us.apache.org/repos/asf/openmeetings/blob/156bcc79/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Implementation.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Implementation.java b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Implementation.java new file mode 100644 index 0000000..1ed2db7 --- /dev/null +++ b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Implementation.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License") + you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openmeetings.util.crypt; + +import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey; + +import java.security.NoSuchAlgorithmException; + +import org.red5.logging.Red5LoggerFactory; +import org.slf4j.Logger; + +/** + * Package private SHA256 implementation to be able to authenticate against + * passwords created using OM earlier than 3.1.0 + */ +class MD5Implementation { + private static final Logger log = Red5LoggerFactory.getLogger(MD5Implementation.class, webAppRootKey); + + private static String hash(String str) { + String passPhrase = null; + try { + passPhrase = MD5.checksum(str); + } catch (NoSuchAlgorithmException e) { + log.error("Error", e); + } + return passPhrase; + } + + static boolean verify(String str, String hash) { + return hash != null && hash.equals(hash(str)); + } +} http://git-wip-us.apache.org/repos/asf/openmeetings/blob/156bcc79/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SCryptImplementation.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SCryptImplementation.java b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SCryptImplementation.java index f356bd0..1c4a012 100644 --- a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SCryptImplementation.java +++ b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SCryptImplementation.java @@ -84,4 +84,15 @@ public class SCryptImplementation implements ICrypt { return false; } } + + @Override + public boolean fallback(String str, String hash) { + if (SHA256Implementation.verify(str, hash)) { + return true; + } + if (MD5Implementation.verify(str, hash)) { + return true; + } + return false; + } } http://git-wip-us.apache.org/repos/asf/openmeetings/blob/156bcc79/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256Implementation.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256Implementation.java b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256Implementation.java new file mode 100644 index 0000000..1fd8dcd --- /dev/null +++ b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256Implementation.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License") + you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openmeetings.util.crypt; + +import java.nio.charset.StandardCharsets; + +import org.apache.commons.codec.binary.Base64; +import org.bouncycastle.crypto.digests.SHA256Digest; +import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; +import org.bouncycastle.crypto.params.KeyParameter; + +/** + * Package private SHA256 implementation to be able to authenticate against + * passwords created using OM 3.1.x-3.2.x + */ +class SHA256Implementation { + private static final int KEY_LENGTH = 128 * 8; + + private static String hash(String str, byte[] salt, int iter) { + PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest()); + gen.init(str.getBytes(StandardCharsets.UTF_8), salt, iter); + byte[] dk = ((KeyParameter) gen.generateDerivedParameters(KEY_LENGTH)).getKey(); + return Base64.encodeBase64String(dk); + } + + static boolean verify(String str, String hash) { + if (str == null) { + return hash == null; + } + if (hash == null) { + return false; + } + String[] ss = hash.split(":"); + if (ss.length != 3) { + return false; + } + try { + int iter = Integer.parseInt(ss[0]); + String h1 = ss[1]; + byte[] salt = Base64.decodeBase64(ss[2]); + String h2 = hash(str, salt, iter); + return h2.equals(h1); + } catch (Exception e) { + return false; + } + } +} http://git-wip-us.apache.org/repos/asf/openmeetings/blob/156bcc79/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSCrypt.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSCrypt.java b/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSCrypt.java index 41d1e7c..094d0b5 100644 --- a/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSCrypt.java +++ b/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSCrypt.java @@ -18,11 +18,27 @@ */ package org.apache.openmeetings.util.crypt; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import org.junit.BeforeClass; +import org.junit.Test; public class TestSCrypt extends AbstractCryptTest { + private static final String TEST_PASS = "12345"; + private static final String MD5_HASH = "827ccb0eea8a706c4c34a16891f84e7b"; + private static final String SHA_HASH = "1000:3C2Sm1yw8NoyEBg8KaJfJMye9GaM8uKDNfUNyPWSbwNI2amKAK10KIrPOQeOV7uLkGCT1Fl5gabBRGjLRSBzi7S8LgaVetiEuCL0d8oVPYT1xtgrmEzx/dIyd7hVaGbol388FVW2Ei7ZxIce8DIOtKmMfrxqoNEZa+ERRAzBGLE=:lbveBdEopW7QuU2jcgv4UeuA1m0eDwfIz+KjWgciF/8TWdLi7utCiy+wm3X2pp0WRffqKEs+wwBh6iJbF2WNPIH06YaB68Q1h34wpxjBdziqAbUiGt2nZiPdKghNNX5j4L0Jp1gGRWpXOrg7V1NqYV6pLmwa+SipQs7MJGCCf+HAcwYW3HNIcp2Rbu9IzH7/t7oJo+FCgL4i1rYVHxrbHhAZCA9hr+dKM6u3S/Ef+EsZfSxCOX2BIRkoqHF4ZlLpwCIf6gmq3m7jenAjz0h2AuO/pM3Mf5d8Oy0LAqgiznU9/S7eEP6QYifF3V/P2ZL6/nX9RprVTTiSf0+GsAygOg=="; + @BeforeClass public static void setup() { crypt = new SCryptImplementation(); } + + @Test + public void fallbackTest() { + assertFalse("MD5 is not valid hash", crypt.verify(TEST_PASS, MD5_HASH)); + assertFalse("SHA256 is not valid hash", crypt.verify(TEST_PASS, SHA_HASH)); + assertTrue("MD5 is valid fallback", crypt.fallback(TEST_PASS, MD5_HASH)); + assertTrue("SHA256 is valid fallback", crypt.fallback(TEST_PASS, SHA_HASH)); + } } http://git-wip-us.apache.org/repos/asf/openmeetings/blob/156bcc79/openmeetings-web/src/test/java/org/apache/openmeetings/test/calendar/TestDatabaseStructureAppointment.java ---------------------------------------------------------------------- diff --git a/openmeetings-web/src/test/java/org/apache/openmeetings/test/calendar/TestDatabaseStructureAppointment.java b/openmeetings-web/src/test/java/org/apache/openmeetings/test/calendar/TestDatabaseStructureAppointment.java index f32fc14..6d75f0a 100644 --- a/openmeetings-web/src/test/java/org/apache/openmeetings/test/calendar/TestDatabaseStructureAppointment.java +++ b/openmeetings-web/src/test/java/org/apache/openmeetings/test/calendar/TestDatabaseStructureAppointment.java @@ -36,54 +36,41 @@ import org.springframework.beans.factory.annotation.Autowired; public class TestDatabaseStructureAppointment extends AbstractJUnitDefaults { private static final Logger log = Red5LoggerFactory.getLogger(TestDatabaseStructureAppointment.class, webAppRootKey); + @Autowired private AppointmentDao appointmentDao; @Test - public void testAddingGroup(){ - + public void testAddingGroup() { try { - - Calendar cal = Calendar.getInstance(); - cal.set(2008, 9, 2); - cal.get(Calendar.DAY_OF_MONTH); - cal.getTime(); - - SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd" ); - Date date = format.parse( "2008-17-08" ); - Date date2 = format.parse( "2008-18-08" ); - - List<Appointment> listAppoints = appointmentDao.getInRange(1L, date, date2); - //List<Appointment> listAppoints = AppointmentDaoImpl.getInstance().searchAppointmentsByName("%"); - //AppointmentDaoImpl.getInstance().getNextAppointmentById(1L); - //AppointmentDaoImpl.getInstance().addAppointment("mezo",1L, "Pforzheim", "zweiter", Calendar.getInstance().getTime() , - //date, null, true, null, null, 1L,1L); - //AppointmentDaoImpl.getInstance().addAppointment("testap", "erster Test",Calendar.getInstance().getTime() , - ///Calendar.getInstance().getTime(), true, false, false, false, new Long(1), 1L); - log.debug("Anzahl: "+listAppoints.size()); - - + Calendar cal = Calendar.getInstance(); + cal.set(2008, 9, 2); + cal.get(Calendar.DAY_OF_MONTH); + cal.getTime(); + + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + Date date = format.parse("2008-17-08"); + Date date2 = format.parse("2008-18-08"); + + List<Appointment> listAppoints = appointmentDao.getInRange(1L, date, date2); + // List<Appointment> listAppoints = appointmentDao.searchAppointmentsByName("%"); + // appointmentDao.getNextAppointmentById(1L); + // appointmentDao.addAppointment("mezo", 1L, "Pforzheim", "zweiter", Calendar.getInstance().getTime(), + // date, null, true, null, null, 1L,1L); + // appointmentDao.addAppointment("testap", "erster Test",Calendar.getInstance().getTime(), + // Calendar.getInstance().getTime(), true, false, false, false, new Long(1), 1L); + log.debug("Anzahl: " + listAppoints.size()); + for (Appointment appoints : listAppoints) { - log.debug("Termin: "+appoints.getTitle()+" startDate: "+appoints.getStart()+ " endDate: "+appoints.getEnd()); - log.debug("MeetingMembers: "+appoints.getMeetingMembers().size()); + log.debug("Termin: " + appoints.getTitle() + " startDate: " + appoints.getStart() + " endDate: " + appoints.getEnd()); + log.debug("MeetingMembers: " + appoints.getMeetingMembers().size()); } - - for (Iterator<Appointment> iter = listAppoints.iterator();iter.hasNext();) { - log.debug(""+iter.next()); + + for (Iterator<Appointment> iter = listAppoints.iterator(); iter.hasNext();) { + log.debug("" + iter.next()); } } catch (Exception err) { - - log.error("[testAddingGroup]",err); - + log.error("[testAddingGroup]", err); } - - - - - } - - - } -
