1 19 20 package com.sslexplorer.jdbc; 21 22 import java.io.File ; 23 import java.sql.ResultSet ; 24 import java.sql.SQLException ; 25 import java.util.ArrayList ; 26 import java.util.Arrays ; 27 import java.util.Calendar ; 28 import java.util.Collection ; 29 import java.util.Collections ; 30 import java.util.HashSet ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Vector ; 34 import java.util.regex.Pattern ; 35 36 import org.apache.commons.logging.Log; 37 import org.apache.commons.logging.LogFactory; 38 39 import com.sslexplorer.boot.ContextHolder; 40 import com.sslexplorer.boot.Util; 41 import com.sslexplorer.core.CoreEvent; 42 import com.sslexplorer.core.CoreEventConstants; 43 import com.sslexplorer.core.CoreListener; 44 import com.sslexplorer.core.CoreServlet; 45 import com.sslexplorer.navigation.DefaultFavorite; 46 import com.sslexplorer.navigation.Favorite; 47 import com.sslexplorer.security.AuthenticationModuleManager; 48 import com.sslexplorer.security.AuthenticationScheme; 49 import com.sslexplorer.security.DefaultAuthenticationScheme; 50 import com.sslexplorer.security.IpRestriction; 51 import com.sslexplorer.security.SystemDatabase; 52 import com.sslexplorer.security.User; 53 import com.sslexplorer.util.CIDRNetwork; 54 55 65 public class JDBCSystemDatabase implements SystemDatabase, CoreListener { 66 private static final Log log = LogFactory.getLog(JDBCSystemDatabase.class); 67 private static final String LOCAL_HOST = "localhost"; 68 private static final String LOCAL_LOOP_BACK = "127.0.0.1"; 69 70 private final Collection <String > authorizedIPAddresses = new HashSet <String >(); 71 private final Collection <String > excludedIPAddresses = new HashSet <String >(); 72 private JDBCDatabaseEngine db; 73 74 77 public JDBCSystemDatabase() { 78 initialiseIpRestrictionCache(); 79 } 80 81 84 public void open(CoreServlet controllingServlet) throws Exception { 85 String dbName = System.getProperty("sslexplorer.systemDatabase.jdbc.dbName", "explorer_configuration"); 86 controllingServlet.addDatabase(dbName, ContextHolder.getContext().getDBDirectory()); 87 String jdbcUser = System.getProperty("sslexplorer.jdbc.username", "sa"); 88 String jdbcPassword = System.getProperty("sslexplorer.jdbc.password", ""); 89 String vendorDB = System.getProperty("sslexplorer.jdbc.vendorClass", "com.sslexplorer.jdbc.hsqldb.HSQLDBDatabaseEngine"); 90 91 if (log.isInfoEnabled()) { 92 log.info("System database is being opened..."); 93 log.info("JDBC vendor class implementation is " + vendorDB); 94 } 95 96 db = (JDBCDatabaseEngine) Class.forName(vendorDB).newInstance(); 97 db.init("systemDatabase", dbName, jdbcUser, jdbcPassword, null); 98 99 File upgradeDir = new File ("install/upgrade"); 100 DBUpgrader upgrader = new DBUpgrader(ContextHolder.getContext() 101 .getVersion(), db, ContextHolder.getContext().getDBDirectory(), upgradeDir); 102 upgrader.upgrade(); 103 104 CoreServlet.getServlet().addCoreListener(this); 105 } 106 107 111 public void close() throws Exception { 112 } 113 114 118 public void cleanup() throws Exception { 119 } 120 121 125 public void coreEvent(CoreEvent evt) { 126 if (evt.getId() == CoreEventConstants.USER_REMOVED) { 127 User user = (User) evt.getParameter(); 128 129 if(user==null) 131 return; 132 133 try { 134 removeUser(user.getPrincipalName()); 135 } catch (Exception e) { 136 log.error("Failed to remove user from system database.", e); 137 } 138 } 139 } 140 141 private void initialiseIpRestrictionCache() { 142 synchronized (authorizedIPAddresses) { 143 authorizedIPAddresses.clear(); 144 authorizedIPAddresses.addAll(getAlwaysAuthorizedIpAddresses()); 145 excludedIPAddresses.clear(); 146 } 147 } 148 149 private static Collection <String > getAlwaysAuthorizedIpAddresses() { 150 String property = System.getProperty("sslexplorer.iprestrictions.allow", ""); 151 Collection <String > propertyAsCollection = property.length() == 0 ? Collections.<String >emptyList() : Arrays.asList(property.split(",")); 152 153 156 Collection <String > alwaysAuthorized = new HashSet <String >(); 157 alwaysAuthorized.add(LOCAL_HOST); 158 alwaysAuthorized.add(LOCAL_LOOP_BACK); 159 alwaysAuthorized.addAll(propertyAsCollection); 160 return alwaysAuthorized; 161 } 162 163 166 public boolean verifyIPAddress(String ipAddress) throws Exception { 167 if (authorizedIPAddresses.contains(ipAddress)) { 169 return true; 170 } else if (excludedIPAddresses.contains(ipAddress)) { 171 return false; 172 } 173 174 IpRestriction[] ipRestrictions = getIpRestrictions(); 175 return verifyIPAddress(ipAddress, ipRestrictions); 176 } 177 178 181 public boolean verifyIPAddress(String ipAddress, IpRestriction[] ipRestrictions) throws Exception { 182 synchronized (authorizedIPAddresses) { 183 boolean isValid = isAddressValid(ipAddress, ipRestrictions); 184 if (isValid) { authorizedIPAddresses.add(ipAddress); 186 } else { 187 excludedIPAddresses.add(ipAddress); 188 } 189 return isValid; 190 } 191 } 192 193 199 private boolean isAddressValid(String ipAddress, IpRestriction[] ipRestrictions) throws Exception { 200 203 204 if (LOCAL_LOOP_BACK.equals(ipAddress) || LOCAL_HOST.equalsIgnoreCase(ipAddress)) { 205 return true; 206 } 207 208 if (ipAddress.length() == 0) { 209 return true; 210 } 211 212 if(ipRestrictions.length == 0) { 214 return true; 215 } 216 217 220 int state = -1; 221 for(int i = 0 ; i < ipRestrictions.length; i++) { 222 if(matchesAddress(ipRestrictions[i], ipAddress)) { 223 state = ipRestrictions[i].getAllowed() ? IpRestriction.ALLOWED : IpRestriction.DENIED; 224 } 225 } 226 return state == IpRestriction.ALLOWED; 227 } 228 229 234 private boolean matchesAddress(IpRestriction restriction, String ipAddress) { 235 String ipRestrictionAddress = restriction.getAddress(); 236 237 if (isIpAddressMatch(ipAddress, ipRestrictionAddress)) { 238 return true; 239 } else if (restriction.isWildcardMatch() && isIpAddressWildcardMatch(ipAddress, ipRestrictionAddress)) { 240 return true; 241 } else if (isCIDRMatch(ipAddress, ipRestrictionAddress)) { 242 return true; 243 } 244 245 return false; 246 } 247 248 253 private static boolean isIpAddressMatch(String toCheck, String ipRestrictionAddress) { 254 return toCheck.equals(ipRestrictionAddress); 255 } 256 257 262 private static boolean isIpAddressWildcardMatch(String toCheck, String ipRestrictionAddress) { 263 String regex = Util.parseSimplePatternToRegExp(ipRestrictionAddress); 264 return Pattern.matches(regex, toCheck); 265 } 266 267 272 private static boolean isCIDRMatch(String toCheck, String ipRestrictionAddress) { 273 try { 274 CIDRNetwork network = new CIDRNetwork(ipRestrictionAddress); 275 return network.isValidAddressForNetwork(toCheck); 276 } catch (Exception e) { 277 return false; 278 } 279 } 280 281 public void addIpRestriction(String addressPattern, int type) throws Exception { 282 IpRestriction[] r = getIpRestrictions(); 283 int priority = ( r == null || r.length == 0 ? 10 : r[r.length - 1].getPriority() ) + 10; 284 JDBCPreparedStatement ps = db.getStatement("addIpRestriction.insert"); 285 try { 286 ps.setString(1, addressPattern); 287 ps.setInt(2, type); 288 ps.setInt(3, priority); 289 ps.execute(); 290 } finally { 291 ps.releasePreparedStatement(); 292 initialiseIpRestrictionCache(); 293 } 294 } 295 296 299 public void updateIpRestriction(IpRestriction restriction) throws Exception { 300 JDBCPreparedStatement ps = db.getStatement("updateIpRestriction.update"); 301 try { 302 ps.setString(1, restriction.getAddress()); 303 ps.setInt(2, restriction.getType()); 304 ps.setInt(3, restriction.getPriority()); 305 ps.setInt(4, restriction.getID()); 306 ps.execute(); 307 } finally { 308 ps.releasePreparedStatement(); 309 initialiseIpRestrictionCache(); 310 } 311 } 312 313 316 public void swapIpRestrictions(IpRestriction restriction1, IpRestriction restriction2) throws Exception { 317 if(restriction1.isDefault() || restriction2.isDefault()) { 318 throw new IllegalArgumentException ("You may not move the default Ip restriction."); 319 } 320 int priority2 = restriction2.getPriority(); 321 restriction2.setPriority(restriction1.getPriority()); 322 restriction1.setPriority(priority2); 323 updateIpRestriction(restriction1); 324 updateIpRestriction(restriction2); 325 } 326 327 330 public IpRestriction[] getIpRestrictions() throws Exception { 331 JDBCPreparedStatement statement = db.getStatement("getIpRestrictions.select"); 332 Collection <IpRestriction> restrictions = new ArrayList <IpRestriction>(); 333 ResultSet resultSet = null; 334 335 try { 336 resultSet = statement.executeQuery(); 337 while (resultSet.next()) { 338 restrictions.add(buildIpRestriction(resultSet)); 339 } 340 } finally { 341 JDBCUtil.cleanup(resultSet); 342 statement.releasePreparedStatement(); 343 } 344 345 return restrictions.toArray(new IpRestriction[restrictions.size()]); 346 } 347 348 351 public IpRestriction getIpRestriction(int id) throws Exception { 352 JDBCPreparedStatement ps = db.getStatement("getIpRestriction.select"); 353 ps.setInt(1, id); 354 try { 355 ResultSet rs = ps.executeQuery(); 356 try { 357 if (rs.next()) { 358 return buildIpRestriction(rs); 359 } 360 } finally { 361 rs.close(); 362 } 363 } finally { 364 ps.releasePreparedStatement(); 365 } 366 return null; 367 } 368 369 374 private static IpRestriction buildIpRestriction(ResultSet resultSet) throws SQLException { 375 return new IpRestriction(resultSet.getInt("restriction_id"), resultSet.getString("address"), resultSet.getInt("type"), 376 resultSet.getInt("priority")); 377 } 378 379 383 public void removeIpRestriction(int id) throws Exception { 384 JDBCPreparedStatement ps = db.getStatement("removeIpRestriction.delete"); 385 try { 386 ps.setInt(1, id); 387 ps.execute(); 388 } finally { 389 ps.releasePreparedStatement(); 390 initialiseIpRestrictionCache(); 391 } 392 } 393 394 398 public void addFavorite(int type, int favoriteKey, String username) throws Exception { 399 JDBCPreparedStatement ps = db.getStatement("addFavorite.insert"); 400 try { 401 ps.setInt(1, type); 402 ps.setString(2, username == null ? "" : username); 403 ps.setInt(3, favoriteKey); 404 ps.execute(); 405 ps.reset(); 406 } finally { 407 ps.releasePreparedStatement(); 408 } 409 } 410 411 415 public void removeFavorite(int type, int favoriteKey, String username) throws Exception { 416 JDBCPreparedStatement ps = db.getStatement("removeFavorite.delete"); 417 try { 418 ps.setInt(1, type); 419 ps.setString(2, username == null ? "" : username); 420 ps.setInt(3, favoriteKey); 421 ps.execute(); 422 } finally { 423 ps.releasePreparedStatement(); 424 } 425 426 } 427 428 431 public List <Favorite> getFavorites(int type, User user) throws Exception { 432 JDBCPreparedStatement ps = null; 433 if (type == -1) { 434 ps = db.getStatement("getFavorites.selectAllForUser"); 435 ps.setString(1, user == null ? "" : user.getPrincipalName()); 436 } else { 437 ps = db.getStatement("getFavorites.selectTypeForUser"); 438 ps.setString(1, user == null ? "" : user.getPrincipalName()); 439 ps.setInt(2, type); 440 } 441 try { 442 Vector <Favorite> v = new Vector <Favorite>(); 443 ResultSet rs = ps.executeQuery(); 444 try { 445 while (rs.next()) { 446 447 v.add(new DefaultFavorite(rs.getInt("favorite_id"), type, user == null ? null : user.getPrincipalName(), rs.getInt("favorite_key"))); 448 } 449 } finally { 450 rs.close(); 451 } 452 return v; 453 } finally { 454 ps.releasePreparedStatement(); 455 } 456 457 } 458 459 463 public Favorite getFavorite(int type, User user, int resourceId) throws Exception { 464 JDBCPreparedStatement ps = db.getStatement("getFavorite.select"); 465 ps.setString(1, user == null ? "" : user.getPrincipalName()); 466 ps.setInt(2, type); 467 ps.setInt(3, resourceId); 468 try { 469 ResultSet rs = ps.executeQuery(); 470 try { 471 if (rs.next()) { 472 return new DefaultFavorite(rs.getInt("favorite_id"), type, user == null ? null : user.getPrincipalName(), rs.getInt("favorite_key")); 473 } 474 } finally { 475 rs.close(); 476 } 477 } finally { 478 ps.releasePreparedStatement(); 479 } 480 return null; 481 } 482 483 485 489 public List <AuthenticationScheme> getAuthenticationSchemeSequences() throws Exception { 490 JDBCPreparedStatement ps = db.getStatement("getAuthenticationSchemeSequences.select"); 491 try { 492 ResultSet rs = ps.executeQuery(); 493 try { 494 List <AuthenticationScheme> sequences = new ArrayList <AuthenticationScheme>(); 495 while (rs.next()) { 496 AuthenticationScheme sequence = buildAuthenticationSchemeSequence(rs); 497 if (sequence != null) { 498 sequences.add(sequence); 499 } 500 } 501 return sequences; 502 } finally { 503 rs.close(); 504 } 505 } finally { 506 ps.releasePreparedStatement(); 507 } 508 } 509 510 514 public AuthenticationScheme getAuthenticationSchemeSequence(int id) throws Exception { 515 JDBCPreparedStatement ps = db.getStatement("getAuthenticationSchemeSequence.select"); 516 ResultSet rs = null; 517 try { 518 ps.setInt(1, id); 519 rs = ps.executeQuery(); 520 if (rs.next()) { 521 return buildAuthenticationSchemeSequence(rs); 522 } 523 } finally { 524 JDBCUtil.cleanup(rs); 525 ps.releasePreparedStatement(); 526 } 527 return null; 528 } 529 530 533 public AuthenticationScheme getAuthenticationSchemeSequence(String name, int realmID) throws Exception { 534 JDBCPreparedStatement ps = db.getStatement("getAuthenticationSchemeSequence.select.byName"); 535 ResultSet rs = null; 536 try { 537 ps.setInt(1, realmID); 538 ps.setString(2, name); 539 rs = ps.executeQuery(); 540 if (rs.next()) { 541 return buildAuthenticationSchemeSequence(rs); 542 } 543 } finally { 544 JDBCUtil.cleanup(rs); 545 ps.releasePreparedStatement(); 546 } 547 return null; 548 } 549 550 553 public AuthenticationScheme createAuthenticationSchemeSequence(int realmID, String name, String description, String [] modules, boolean enabled, int priority) throws Exception { 554 Calendar calendar = Calendar.getInstance(); 555 String timestamp = db.formatTimestamp(calendar); 556 JDBCPreparedStatement ps = db.getStatement("createAuthenticationSchemeSequence.insert"); 557 try { 558 ps.setString(1, name); 559 ps.setString(2, description); 560 ps.setString(3, timestamp); 561 ps.setString(4, timestamp); 562 ps.setInt(5, enabled ? 1 : 0); 563 ps.setInt(6, priority); 564 ps.setInt(7, realmID); 565 ps.execute(); 566 int id = db.getLastInsertId(ps, "createAuthenticationSchemeSequence.lastInsertId"); 567 AuthenticationScheme sequence = getAuthenticationSchemeSequence(id); 568 updateAuthenticationSequence(sequence, modules); 569 return sequence; 570 } finally { 571 ps.releasePreparedStatement(); 572 } 573 } 574 575 private void updateAuthenticationSequence(AuthenticationScheme sequence, String [] modules) throws Exception { 576 for (int index = 0; index < modules.length; index++) { 577 sequence.addModule(modules[index]); 578 } 579 updateSequence(sequence); 580 } 581 582 586 public void updateAuthenticationSchemeSequence(AuthenticationScheme sequence) throws Exception { 587 JDBCPreparedStatement ps = db.getStatement("updateAuthenticationSchemeSequence.update"); 588 try { 589 ps.setString(1, sequence.getResourceName()); 590 ps.setString(2, sequence.getResourceDescription()); 591 Calendar now = Calendar.getInstance(); 592 ps.setString(3, db.formatTimestamp(now)); 593 ps.setInt(4, sequence.getEnabled() ? 1 : 0); 594 ps.setInt(5, sequence.getResourceId()); 595 ps.execute(); 596 updateSequence(sequence); 597 } finally { 598 ps.releasePreparedStatement(); 599 } 600 } 601 602 606 private void updateSequence(AuthenticationScheme sequence) throws Exception { 607 deleteAuthenticationSequence(sequence.getResourceId()); 608 updateAuthentictionSequence(sequence); 609 } 610 611 private void updateAuthentictionSequence(AuthenticationScheme sequence) throws Exception { 612 JDBCPreparedStatement statement = db.getStatement("updateSequence.insert"); 613 try { 614 int seq = 0; 615 for (Iterator itr = sequence.modules(); itr.hasNext();) { 616 String module = (String ) itr.next(); 617 statement.setInt(1, sequence.getResourceId()); 618 statement.setString(2, module); 619 statement.setInt(3, seq); 620 statement.execute(); 621 seq += 10; 622 statement.reset(); 623 } 624 } finally { 625 statement.releasePreparedStatement(); 626 } 627 } 628 629 632 public void moveAuthenticationSchemeUp(AuthenticationScheme scheme, List <AuthenticationScheme> schemes) throws Exception { 633 int indexOf = schemes.indexOf(scheme); 634 if (indexOf == 0) 635 throw new IllegalStateException ("Scheme is already set to highest priority"); 636 637 int schemeAboveIndex = indexOf - 1; 638 AuthenticationScheme schemeAbove = schemes.get(schemeAboveIndex); 639 updateAuthenticationSchemePriority(scheme, schemeAbove.getPriorityInt()); 640 updateAuthenticationSchemePriority(schemeAbove, scheme.getPriorityInt()); 641 } 642 643 646 public void moveAuthenticationSchemeDown(AuthenticationScheme scheme, List <AuthenticationScheme> schemes) throws Exception { 647 int indexOf = schemes.indexOf(scheme); 648 if (indexOf == schemes.size() - 1) 649 throw new IllegalStateException ("Scheme is already set to lowest priority"); 650 651 int schemeBelowIndex = indexOf + 1; 652 AuthenticationScheme schemeBelow = schemes.get(schemeBelowIndex); 653 updateAuthenticationSchemePriority(scheme, schemeBelow.getPriorityInt()); 654 updateAuthenticationSchemePriority(schemeBelow, scheme.getPriorityInt()); 655 } 656 657 private void updateAuthenticationSchemePriority(AuthenticationScheme scheme, int priority) throws Exception { 658 JDBCPreparedStatement ps = db.getStatement("updateAuthenticationSchemeSequence.update.priority"); 659 try { 660 ps.setInt(1, priority); 661 ps.setInt(2, scheme.getResourceId()); 662 ps.execute(); 663 } finally { 664 ps.releasePreparedStatement(); 665 } 666 } 667 668 672 public void deleteAuthenticationSchemeSequence(int id) throws Exception { 673 AuthenticationScheme scheme = getAuthenticationSchemeSequence(id); 674 if (scheme == null) { 675 throw new Exception ("No authentication scheme with " + id + "."); 676 } 677 deleteAuthenticationScheme(id); 678 deleteAuthenticationSequence(id); 679 } 680 681 private void deleteAuthenticationScheme(int id) throws SQLException , ClassNotFoundException { 682 JDBCPreparedStatement ps = db.getStatement("deleteAuthenticationSchemeSequence.delete.authSchemes"); 683 try { 684 ps.setInt(1, id); 685 ps.execute(); 686 } finally { 687 ps.releasePreparedStatement(); 688 } 689 } 690 691 private void deleteAuthenticationSequence(int id) throws SQLException , ClassNotFoundException { 692 JDBCPreparedStatement ps; 693 ps = db.getStatement("deleteAuthenticationSchemeSequence.delete.authSequence"); 694 try { 695 ps.setInt(1, id); 696 ps.execute(); 697 } finally { 698 ps.releasePreparedStatement(); 699 } 700 } 701 702 707 private AuthenticationScheme buildAuthenticationSchemeSequence(ResultSet resultSet) throws Exception { 708 Calendar created = JDBCUtil.getCalendar(resultSet, "date_created"); 709 Calendar amended = JDBCUtil.getCalendar(resultSet, "date_amended"); 710 boolean enabled = resultSet.getInt("enabled") == 1; 711 AuthenticationScheme seq = new DefaultAuthenticationScheme(resultSet.getInt("realm_id"), resultSet.getInt("resource_id"), 712 resultSet.getString("resource_name"), resultSet.getString("resource_description"), created, amended, 713 enabled, resultSet.getInt("priority")); 714 return isSchemeAvailable(seq) ? seq : null; 715 } 716 717 private boolean isSchemeAvailable(AuthenticationScheme scheme) throws Exception { 718 JDBCPreparedStatement statement = db.getStatement("buildAuthenticationSchemeSequences.select.scheme"); 719 ResultSet resultSet = null; 720 boolean available = true; 721 try { 722 statement.setInt(1, scheme.getResourceId()); 723 resultSet = statement.executeQuery(); 724 while (resultSet.next()) { 725 String moduleId = resultSet.getString("module_id"); 726 if (!AuthenticationModuleManager.getInstance().isRegistered(moduleId)) { 727 available = false; 728 } 729 scheme.addModule(moduleId); 730 } 731 } finally { 732 JDBCUtil.cleanup(resultSet); 733 statement.releasePreparedStatement(); 734 } 735 return available; 736 } 737 738 742 protected void removeUser(String username) throws Exception { 743 String [] statements = { "removeUser.delete.explorerProperties", 744 "removeUser.delete.propertyProfiles"}; 745 for (int i = 0; i < statements.length; i++) { 746 JDBCPreparedStatement ps = db.getStatement(statements[i]); 747 try { 748 ps.setString(1, username); 749 ps.execute(); 750 } finally { 751 ps.releasePreparedStatement(); 752 } 753 } 754 } 755 756 public List <AuthenticationScheme> getAuthenticationSchemeSequences(int realmID) throws Exception { 757 JDBCPreparedStatement ps = db.getStatement("getAuthenticationSchemeSequences.realm.select"); 758 try { 759 ps.setInt(1, realmID); 760 ResultSet rs = ps.executeQuery(); 761 try { 762 List <AuthenticationScheme> sequences = new ArrayList <AuthenticationScheme>(); 763 while (rs.next()) { 764 AuthenticationScheme sequence = buildAuthenticationSchemeSequence(rs); 765 if (sequence != null) { 766 sequences.add(sequence); 767 } 768 } 769 return sequences; 770 } finally { 771 rs.close(); 772 } 773 } finally { 774 ps.releasePreparedStatement(); 775 } 776 } 777 } | Popular Tags |