示例#1
0
  public void setPassword(String username, String password) throws UserNotFoundException {
    // Determine if the password should be stored as plain text or encrypted.
    boolean usePlainPassword = JiveGlobals.getBooleanProperty("user.usePlainPassword");
    boolean scramOnly = JiveGlobals.getBooleanProperty("user.scramHashedPasswordOnly");
    String encryptedPassword = null;
    if (username.contains("@")) {
      // Check that the specified domain matches the server's domain
      int index = username.indexOf("@");
      String domain = username.substring(index + 1);
      if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) {
        username = username.substring(0, index);
      } else {
        // Unknown domain.
        throw new UserNotFoundException();
      }
    }

    // Store the salt and salted password so SCRAM-SHA-1 SASL auth can be used later.
    byte[] saltShaker = new byte[32];
    random.nextBytes(saltShaker);
    String salt = DatatypeConverter.printBase64Binary(saltShaker);

    int iterations =
        JiveGlobals.getIntProperty(
            "sasl.scram-sha-1.iteration-count", ScramUtils.DEFAULT_ITERATION_COUNT);
    byte[] saltedPassword = null, clientKey = null, storedKey = null, serverKey = null;
    try {
      saltedPassword = ScramUtils.createSaltedPassword(saltShaker, password, iterations);
      clientKey = ScramUtils.computeHmac(saltedPassword, "Client Key");
      storedKey = MessageDigest.getInstance("SHA-1").digest(clientKey);
      serverKey = ScramUtils.computeHmac(saltedPassword, "Server Key");
    } catch (SaslException | NoSuchAlgorithmException | UnsupportedEncodingException e) {
      Log.warn("Unable to persist values for SCRAM authentication.");
    }

    if (!scramOnly && !usePlainPassword) {
      try {
        encryptedPassword = AuthFactory.encryptPassword(password);
        // Set password to null so that it's inserted that way.
        password = null;
      } catch (UnsupportedOperationException uoe) {
        // Encryption may fail. In that case, ignore the error and
        // the plain password will be stored.
      }
    }
    if (scramOnly) {
      encryptedPassword = null;
      password = null;
    }

    Connection con = null;
    PreparedStatement pstmt = null;
    try {
      con = DbConnectionManager.getConnection();
      pstmt = con.prepareStatement(UPDATE_PASSWORD);
      if (password == null) {
        pstmt.setNull(1, Types.VARCHAR);
      } else {
        pstmt.setString(1, password);
      }
      if (encryptedPassword == null) {
        pstmt.setNull(2, Types.VARCHAR);
      } else {
        pstmt.setString(2, encryptedPassword);
      }
      if (storedKey == null) {
        pstmt.setNull(3, Types.VARCHAR);
      } else {
        pstmt.setString(3, DatatypeConverter.printBase64Binary(storedKey));
      }
      if (serverKey == null) {
        pstmt.setNull(4, Types.VARCHAR);
      } else {
        pstmt.setString(4, DatatypeConverter.printBase64Binary(serverKey));
      }
      pstmt.setString(5, salt);
      pstmt.setInt(6, iterations);
      pstmt.setString(7, username);
      pstmt.executeUpdate();
    } catch (SQLException sqle) {
      throw new UserNotFoundException(sqle);
    } finally {
      DbConnectionManager.closeConnection(pstmt, con);
    }
  }
示例#2
0
 public boolean checkPassword(String username, String testPassword) throws UserNotFoundException {
   Connection con = null;
   PreparedStatement pstmt = null;
   ResultSet rs = null;
   if (username.contains("@")) {
     // Check that the specified domain matches the server's domain
     int index = username.indexOf("@");
     String domain = username.substring(index + 1);
     if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) {
       username = username.substring(0, index);
     } else {
       // Unknown domain.
       throw new UserNotFoundException();
     }
   }
   try {
     con = DbConnectionManager.getConnection();
     pstmt = con.prepareStatement(TEST_PASSWORD);
     pstmt.setString(1, username);
     rs = pstmt.executeQuery();
     if (!rs.next()) {
       throw new UserNotFoundException(username);
     }
     String plainText = rs.getString(1);
     String encrypted = rs.getString(2);
     int iterations = rs.getInt(3);
     String salt = rs.getString(4);
     String storedKey = rs.getString(5);
     if (encrypted != null) {
       try {
         plainText = AuthFactory.decryptPassword(encrypted);
       } catch (UnsupportedOperationException uoe) {
         // Ignore and return plain password instead.
       }
     }
     if (plainText != null) {
       boolean scramOnly = JiveGlobals.getBooleanProperty("user.scramHashedPasswordOnly");
       if (scramOnly) {
         // If we have a password here, but we're meant to be scramOnly, we should reset it.
         setPassword(username, plainText);
       }
       return testPassword.equals(plainText);
     }
     // Don't have either plain or encrypted, so test SCRAM hash.
     if (salt == null || iterations == 0 || storedKey == null) {
       Log.warn("No available credentials for checkPassword.");
       return false;
     }
     byte[] saltShaker = DatatypeConverter.parseBase64Binary(salt);
     byte[] saltedPassword = null, clientKey = null, testStoredKey = null;
     try {
       saltedPassword = ScramUtils.createSaltedPassword(saltShaker, testPassword, iterations);
       clientKey = ScramUtils.computeHmac(saltedPassword, "Client Key");
       testStoredKey = MessageDigest.getInstance("SHA-1").digest(clientKey);
     } catch (SaslException | NoSuchAlgorithmException | UnsupportedEncodingException e) {
       Log.warn("Unable to check SCRAM values for PLAIN authentication.");
       return false;
     }
     return DatatypeConverter.printBase64Binary(testStoredKey).equals(storedKey);
   } catch (SQLException sqle) {
     Log.error("User SQL failure:", sqle);
     throw new UserNotFoundException(sqle);
   } finally {
     DbConnectionManager.closeConnection(rs, pstmt, con);
   }
 }