Guest User

Untitled

a guest
Apr 22nd, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.83 KB | None | 0 0
  1. /**
  2. * $Revision: 1116 $
  3. * $Date: 2005-03-10 20:18:08 -0300 (Thu, 10 Mar 2005) $
  4. *
  5. * Copyright (C) 2006 Jive Software. All rights reserved.
  6. *
  7. * This software is published under the terms of the GNU Public License (GPL),
  8. * a copy of which is included in this distribution.
  9. */
  10.  
  11. package org.jivesoftware.openfire.auth;
  12.  
  13. import org.jivesoftware.database.DbConnectionManager;
  14. import org.jivesoftware.openfire.XMPPServer;
  15. import org.jivesoftware.openfire.user.UserAlreadyExistsException;
  16. import org.jivesoftware.openfire.user.UserManager;
  17. import org.jivesoftware.openfire.user.UserNotFoundException;
  18. import org.jivesoftware.util.JiveGlobals;
  19. import org.jivesoftware.util.Log;
  20. import org.jivesoftware.util.StringUtils;
  21.  
  22. import java.sql.*;
  23.  
  24. /**
  25. * The JDBC auth provider allows you to authenticate users against any database
  26. * that you can connect to with JDBC. It can be used along with the
  27. * {@link HybridAuthProvider hybrid} auth provider, so that you can also have
  28. * XMPP-only users that won't pollute your external data.<p>
  29. *
  30. * To enable this provider, set the following in the XML configuration file:
  31. *
  32. * <pre>
  33. * <provider>
  34. * <auth>
  35. * <className>org.jivesoftware.openfire.auth.JDBCAuthProvider</className>
  36. * </auth>
  37. * </provider>
  38. * </pre>
  39. *
  40. * You'll also need to set your JDBC driver, connection string, and SQL statements:
  41. *
  42. * <pre>
  43. * <jdbcProvider>
  44. * <driver>com.mysql.jdbc.Driver</driver>
  45. * <connectionString>jdbc:mysql://localhost/dbname?user=username&password=secret</connectionString>
  46. * </jdbcProvider>
  47. *
  48. * <jdbcAuthProvider>
  49. * <passwordSQL>SELECT password FROM user_account WHERE username=?</passwordSQL>
  50. * <passwordType>plain</passwordType>
  51. * </jdbcAuthProvider></pre>
  52. *
  53. * The passwordType setting tells Openfire how the password is stored. Setting the value
  54. * is optional (when not set, it defaults to "plain"). The valid values are:<ul>
  55. * <li>{@link PasswordType#plain plain}
  56. * <li>{@link PasswordType#md5 md5}
  57. * <li>{@link PasswordType#sha1 sha1}
  58. * </ul>
  59. *
  60. * @author David Snopek
  61. */
  62. public class JDBCAuthProvider implements AuthProvider {
  63.  
  64. private String connectionString;
  65.  
  66. private String passwordSQL;
  67. private PasswordType passwordType;
  68.  
  69. /**
  70. * Constructs a new JDBC authentication provider.
  71. */
  72. public JDBCAuthProvider() {
  73. // Load the JDBC driver and connection string.
  74. String jdbcDriver = JiveGlobals.getXMLProperty("jdbcProvider.driver");
  75. try {
  76. Class.forName(jdbcDriver).newInstance();
  77. }
  78. catch (Exception e) {
  79. Log.error("Unable to load JDBC driver: " + jdbcDriver, e);
  80. return;
  81. }
  82. connectionString = JiveGlobals.getXMLProperty("jdbcProvider.connectionString");
  83.  
  84. // Load SQL statements.
  85. passwordSQL = JiveGlobals.getXMLProperty("jdbcAuthProvider.passwordSQL");
  86. passwordType = PasswordType.plain;
  87. try {
  88. passwordType = PasswordType.valueOf(
  89. JiveGlobals.getXMLProperty("jdbcAuthProvider.passwordType", "plain"));
  90. }
  91. catch (IllegalArgumentException iae) {
  92. Log.error(iae);
  93. }
  94. }
  95.  
  96. public void authenticate(String username, String password) throws UnauthorizedException {
  97. if (username == null || password == null) {
  98. throw new UnauthorizedException();
  99. }
  100. username = username.trim().toLowerCase();
  101. if (username.contains("@")) {
  102. // Check that the specified domain matches the server's domain
  103. int index = username.indexOf("@");
  104. String domain = username.substring(index + 1);
  105. if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) {
  106. username = username.substring(0, index);
  107. } else {
  108. // Unknown domain. Return authentication failed.
  109. throw new UnauthorizedException();
  110. }
  111. }
  112. String userPassword;
  113. try {
  114. userPassword = getPasswordValue(username);
  115. }
  116. catch (UserNotFoundException unfe) {
  117. throw new UnauthorizedException();
  118. }
  119. // If the user's password doesn't match the password passed in, authentication
  120. // should fail.
  121. if (passwordType == PasswordType.md5) {
  122. password = StringUtils.hash(password, "MD5");
  123. }
  124. else if (passwordType == PasswordType.sha1) {
  125. password = StringUtils.hash(password, "SHA-1");
  126. }
  127. if (!password.equals(userPassword)) {
  128. throw new UnauthorizedException();
  129. }
  130.  
  131. // Got this far, so the user must be authorized.
  132. createUser(username);
  133. }
  134.  
  135. public void authenticate(String username, String token, String digest)
  136. throws UnauthorizedException
  137. {
  138. if (passwordType != PasswordType.plain) {
  139. throw new UnsupportedOperationException("Digest authentication not supported for "
  140. + "password type " + passwordType);
  141. }
  142. if (username == null || token == null || digest == null) {
  143. throw new UnauthorizedException();
  144. }
  145. username = username.trim().toLowerCase();
  146. if (username.contains("@")) {
  147. // Check that the specified domain matches the server's domain
  148. int index = username.indexOf("@");
  149. String domain = username.substring(index + 1);
  150. if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) {
  151. username = username.substring(0, index);
  152. } else {
  153. // Unknown domain. Return authentication failed.
  154. throw new UnauthorizedException();
  155. }
  156. }
  157. String password;
  158. try {
  159. password = getPasswordValue(username);
  160. }
  161. catch (UserNotFoundException unfe) {
  162. throw new UnauthorizedException();
  163. }
  164. String anticipatedDigest = AuthFactory.createDigest(token, password);
  165. if (!digest.equalsIgnoreCase(anticipatedDigest)) {
  166. throw new UnauthorizedException();
  167. }
  168.  
  169. // Got this far, so the user must be authorized.
  170. createUser(username);
  171. }
  172.  
  173. public boolean isPlainSupported() {
  174. // If the auth SQL is defined, plain text authentication is supported.
  175. return (passwordSQL != null);
  176. }
  177.  
  178. public boolean isDigestSupported() {
  179. // The auth SQL must be defined and the password type is supported.
  180. return (passwordSQL != null && passwordType == PasswordType.plain);
  181. }
  182.  
  183. public String getPassword(String username) throws UserNotFoundException,
  184. UnsupportedOperationException
  185. {
  186.  
  187. if (!supportsPasswordRetrieval()) {
  188. throw new UnsupportedOperationException();
  189. }
  190. if (username.contains("@")) {
  191. // Check that the specified domain matches the server's domain
  192. int index = username.indexOf("@");
  193. String domain = username.substring(index + 1);
  194. if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) {
  195. username = username.substring(0, index);
  196. } else {
  197. // Unknown domain.
  198. throw new UserNotFoundException();
  199. }
  200. }
  201. return getPasswordValue(username);
  202. }
  203.  
  204. public void setPassword(String username, String password)
  205. throws UserNotFoundException, UnsupportedOperationException
  206. {
  207. throw new UnsupportedOperationException();
  208. }
  209.  
  210. public boolean supportsPasswordRetrieval() {
  211. return (passwordSQL != null && passwordType == PasswordType.plain);
  212. }
  213.  
  214. /**
  215. * Returns the value of the password field. It will be in plain text or hashed
  216. * format, depending on the password type.
  217. *
  218. * @return the password value.
  219. * @throws UserNotFoundException if the given user could not be loaded.
  220. */
  221. private String getPasswordValue(String username) throws UserNotFoundException {
  222. String password = null;
  223. Connection con = null;
  224. PreparedStatement pstmt = null;
  225. ResultSet rs = null;
  226. if (username.contains("@")) {
  227. // Check that the specified domain matches the server's domain
  228. int index = username.indexOf("@");
  229. String domain = username.substring(index + 1);
  230. if (domain.equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) {
  231. username = username.substring(0, index);
  232. } else {
  233. // Unknown domain.
  234. throw new UserNotFoundException();
  235. }
  236. }
  237. try {
  238. con = DriverManager.getConnection(connectionString);
  239. pstmt = con.prepareStatement(passwordSQL);
  240. pstmt.setString(1, username);
  241.  
  242. rs = pstmt.executeQuery();
  243.  
  244. // If the query had no results, the username and password
  245. // did not match a user record. Therefore, throw an exception.
  246. if (!rs.next()) {
  247. throw new UserNotFoundException();
  248. }
  249. password = rs.getString(1);
  250. }
  251. catch (SQLException e) {
  252. Log.error("Exception in JDBCAuthProvider", e);
  253. throw new UserNotFoundException();
  254. }
  255. finally {
  256. DbConnectionManager.closeConnection(rs, pstmt, con);
  257. }
  258. return password;
  259. }
  260.  
  261. /**
  262. * Indicates how the password is stored.
  263. */
  264. @SuppressWarnings({"UnnecessarySemicolon"}) // Support for QDox Parser
  265. public enum PasswordType {
  266.  
  267. /**
  268. * The password is stored as plain text.
  269. */
  270. plain,
  271.  
  272. /**
  273. * The password is stored as a hex-encoded MD5 hash.
  274. */
  275. md5,
  276.  
  277. /**
  278. * The password is stored as a hex-encoded SHA-1 hash.
  279. */
  280. sha1;
  281. }
  282.  
  283. /**
  284. * Checks to see if the user exists; if not, a new user is created.
  285. *
  286. * @param username the username.
  287. */
  288. private static void createUser(String username) {
  289. // See if the user exists in the database. If not, automatically create them.
  290. UserManager userManager = UserManager.getInstance();
  291. try {
  292. userManager.getUser(username);
  293. }
  294. catch (UserNotFoundException unfe) {
  295. try {
  296. Log.debug("JDBCAuthProvider: Automatically creating new user account for " + username);
  297. UserManager.getUserProvider().createUser(username, StringUtils.randomString(8),
  298. null, null);
  299. }
  300. catch (UserAlreadyExistsException uaee) {
  301. // Ignore.
  302. }
  303. }
  304. }
  305. }
Add Comment
Please, Sign In to add comment