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);
                }
-
-               
-
-               
-
        }
-
-
-
 }
-

Reply via email to