You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AuthenticationManagerTest.java 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. /*
  2. * Copyright 2013 gitblit.com.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.gitblit.tests;
  17. import java.io.BufferedReader;
  18. import java.io.IOException;
  19. import java.io.UnsupportedEncodingException;
  20. import java.security.Principal;
  21. import java.util.*;
  22. import javax.servlet.AsyncContext;
  23. import javax.servlet.DispatcherType;
  24. import javax.servlet.RequestDispatcher;
  25. import javax.servlet.ServletContext;
  26. import javax.servlet.ServletException;
  27. import javax.servlet.ServletInputStream;
  28. import javax.servlet.ServletRequest;
  29. import javax.servlet.ServletResponse;
  30. import javax.servlet.http.Cookie;
  31. import javax.servlet.http.HttpServletRequest;
  32. import javax.servlet.http.HttpServletResponse;
  33. import javax.servlet.http.HttpSession;
  34. import javax.servlet.http.HttpSessionContext;
  35. import javax.servlet.http.HttpUpgradeHandler;
  36. import javax.servlet.http.Part;
  37. import com.gitblit.utils.PasswordHash;
  38. import org.junit.Test;
  39. import com.gitblit.IUserService;
  40. import com.gitblit.Keys;
  41. import com.gitblit.manager.AuthenticationManager;
  42. import com.gitblit.manager.IAuthenticationManager;
  43. import com.gitblit.manager.IRuntimeManager;
  44. import com.gitblit.manager.RuntimeManager;
  45. import com.gitblit.manager.UserManager;
  46. import com.gitblit.models.TeamModel;
  47. import com.gitblit.models.UserModel;
  48. import com.gitblit.tests.mock.MemorySettings;
  49. import com.gitblit.utils.XssFilter;
  50. import com.gitblit.utils.XssFilter.AllowXssFilter;
  51. /**
  52. * Class for testing local authentication.
  53. *
  54. * @author James Moger
  55. *
  56. */
  57. @SuppressWarnings("deprecation")
  58. public class AuthenticationManagerTest extends GitblitUnitTest {
  59. UserManager users;
  60. private static final class DummyHttpServletRequest implements HttpServletRequest {
  61. @Override
  62. public Object getAttribute(String name) {
  63. return null;
  64. }
  65. @Override
  66. public Enumeration<String> getAttributeNames() {
  67. return null;
  68. }
  69. @Override
  70. public String getCharacterEncoding() {
  71. return null;
  72. }
  73. @Override
  74. public void setCharacterEncoding(String env)
  75. throws UnsupportedEncodingException {
  76. }
  77. @Override
  78. public int getContentLength() {
  79. return 0;
  80. }
  81. @Override
  82. public long getContentLengthLong() {
  83. return 0;
  84. }
  85. @Override
  86. public String getContentType() {
  87. return null;
  88. }
  89. @Override
  90. public ServletInputStream getInputStream() throws IOException {
  91. return null;
  92. }
  93. @Override
  94. public String getParameter(String name) {
  95. return null;
  96. }
  97. @Override
  98. public Enumeration<String> getParameterNames() {
  99. return null;
  100. }
  101. @Override
  102. public String[] getParameterValues(String name) {
  103. return null;
  104. }
  105. @Override
  106. public Map<String, String[]> getParameterMap() {
  107. return null;
  108. }
  109. @Override
  110. public String getProtocol() {
  111. return null;
  112. }
  113. @Override
  114. public String getScheme() {
  115. return null;
  116. }
  117. @Override
  118. public String getServerName() {
  119. return null;
  120. }
  121. @Override
  122. public int getServerPort() {
  123. return 0;
  124. }
  125. @Override
  126. public BufferedReader getReader() throws IOException {
  127. return null;
  128. }
  129. @Override
  130. public String getRemoteAddr() {
  131. return null;
  132. }
  133. @Override
  134. public String getRemoteHost() {
  135. return null;
  136. }
  137. @Override
  138. public void setAttribute(String name, Object o) {
  139. }
  140. @Override
  141. public void removeAttribute(String name) {
  142. }
  143. @Override
  144. public Locale getLocale() {
  145. return null;
  146. }
  147. @Override
  148. public Enumeration<Locale> getLocales() {
  149. return null;
  150. }
  151. @Override
  152. public boolean isSecure() {
  153. return false;
  154. }
  155. @Override
  156. public RequestDispatcher getRequestDispatcher(String path) {
  157. return null;
  158. }
  159. @Override
  160. public String getRealPath(String path) {
  161. return null;
  162. }
  163. @Override
  164. public int getRemotePort() {
  165. return 0;
  166. }
  167. @Override
  168. public String getLocalName() {
  169. return null;
  170. }
  171. @Override
  172. public String getLocalAddr() {
  173. return null;
  174. }
  175. @Override
  176. public int getLocalPort() {
  177. return 0;
  178. }
  179. @Override
  180. public ServletContext getServletContext() {
  181. return null;
  182. }
  183. @Override
  184. public AsyncContext startAsync() throws IllegalStateException {
  185. return null;
  186. }
  187. @Override
  188. public AsyncContext startAsync(ServletRequest servletRequest,
  189. ServletResponse servletResponse)
  190. throws IllegalStateException {
  191. return null;
  192. }
  193. @Override
  194. public boolean isAsyncStarted() {
  195. return false;
  196. }
  197. @Override
  198. public boolean isAsyncSupported() {
  199. return false;
  200. }
  201. @Override
  202. public AsyncContext getAsyncContext() {
  203. return null;
  204. }
  205. @Override
  206. public DispatcherType getDispatcherType() {
  207. return null;
  208. }
  209. @Override
  210. public String getAuthType() {
  211. return null;
  212. }
  213. @Override
  214. public Cookie[] getCookies() {
  215. return null;
  216. }
  217. @Override
  218. public long getDateHeader(String name) {
  219. return 0;
  220. }
  221. @Override
  222. public String getHeader(String name) {
  223. return null;
  224. }
  225. @Override
  226. public Enumeration<String> getHeaders(String name) {
  227. return null;
  228. }
  229. @Override
  230. public Enumeration<String> getHeaderNames() {
  231. return null;
  232. }
  233. @Override
  234. public int getIntHeader(String name) {
  235. return 0;
  236. }
  237. @Override
  238. public String getMethod() {
  239. return null;
  240. }
  241. @Override
  242. public String getPathInfo() {
  243. return null;
  244. }
  245. @Override
  246. public String getPathTranslated() {
  247. return null;
  248. }
  249. @Override
  250. public String getContextPath() {
  251. return null;
  252. }
  253. @Override
  254. public String getQueryString() {
  255. return null;
  256. }
  257. @Override
  258. public String getRemoteUser() {
  259. return null;
  260. }
  261. @Override
  262. public boolean isUserInRole(String role) {
  263. if(role != null && "admin".equals(role)) {
  264. return true;
  265. }
  266. return false;
  267. }
  268. @Override
  269. public Principal getUserPrincipal() {
  270. return new Principal(){
  271. @Override
  272. public String getName() {
  273. return "sunnyjim";
  274. }
  275. };
  276. }
  277. @Override
  278. public String getRequestedSessionId() {
  279. return null;
  280. }
  281. @Override
  282. public String getRequestURI() {
  283. return null;
  284. }
  285. @Override
  286. public StringBuffer getRequestURL() {
  287. return null;
  288. }
  289. @Override
  290. public String getServletPath() {
  291. return null;
  292. }
  293. @Override
  294. public HttpSession getSession(boolean create) {
  295. return null;
  296. }
  297. final Map<String, Object> sessionAttributes = new HashMap<String, Object>();
  298. @Override
  299. public HttpSession getSession() {
  300. return new HttpSession() {
  301. @Override
  302. public long getCreationTime() {
  303. return 0;
  304. }
  305. @Override
  306. public String getId() {
  307. return null;
  308. }
  309. @Override
  310. public long getLastAccessedTime() {
  311. return 0;
  312. }
  313. @Override
  314. public ServletContext getServletContext() {
  315. return null;
  316. }
  317. @Override
  318. public void setMaxInactiveInterval(int interval) {
  319. }
  320. @Override
  321. public int getMaxInactiveInterval() {
  322. return 0;
  323. }
  324. @Override
  325. public HttpSessionContext getSessionContext() {
  326. return null;
  327. }
  328. @Override
  329. public Object getAttribute(String name) {
  330. return sessionAttributes.get(name);
  331. }
  332. @Override
  333. public Object getValue(String name) {
  334. return null;
  335. }
  336. @Override
  337. public Enumeration<String> getAttributeNames() {
  338. return Collections.enumeration(sessionAttributes.keySet());
  339. }
  340. @Override
  341. public String[] getValueNames() {
  342. return null;
  343. }
  344. @Override
  345. public void setAttribute(String name,
  346. Object value) {
  347. }
  348. @Override
  349. public void putValue(String name, Object value) {
  350. }
  351. @Override
  352. public void removeAttribute(String name) {
  353. }
  354. @Override
  355. public void removeValue(String name) {
  356. }
  357. @Override
  358. public void invalidate() {
  359. }
  360. @Override
  361. public boolean isNew() {
  362. return false;
  363. }
  364. };
  365. }
  366. @Override
  367. public String changeSessionId() {
  368. return null;
  369. }
  370. @Override
  371. public boolean isRequestedSessionIdValid() {
  372. return false;
  373. }
  374. @Override
  375. public boolean isRequestedSessionIdFromCookie() {
  376. return false;
  377. }
  378. @Override
  379. public boolean isRequestedSessionIdFromURL() {
  380. return false;
  381. }
  382. @Override
  383. public boolean isRequestedSessionIdFromUrl() {
  384. return false;
  385. }
  386. @Override
  387. public boolean authenticate(HttpServletResponse response)
  388. throws IOException, ServletException {
  389. return false;
  390. }
  391. @Override
  392. public void login(String username, String password)
  393. throws ServletException {
  394. }
  395. @Override
  396. public void logout() throws ServletException {
  397. }
  398. @Override
  399. public Collection<Part> getParts() throws IOException,
  400. ServletException {
  401. return null;
  402. }
  403. @Override
  404. public Part getPart(String name) throws IOException,
  405. ServletException {
  406. return null;
  407. }
  408. @Override
  409. public <T extends HttpUpgradeHandler> T upgrade(
  410. Class<T> handlerClass) throws IOException,
  411. ServletException {
  412. return null;
  413. }
  414. }
  415. HashMap<String, Object> settings = new HashMap<String, Object>();
  416. MemorySettings getSettings() {
  417. return new MemorySettings(settings);
  418. }
  419. IAuthenticationManager newAuthenticationManager() {
  420. XssFilter xssFilter = new AllowXssFilter();
  421. RuntimeManager runtime = new RuntimeManager(getSettings(), xssFilter, GitBlitSuite.BASEFOLDER).start();
  422. users = new UserManager(runtime, null).start();
  423. final Map<String, UserModel> virtualUsers = new HashMap<String, UserModel>();
  424. users.setUserService(new IUserService() {
  425. @Override
  426. public void setup(IRuntimeManager runtimeManager) {
  427. }
  428. @Override
  429. public String getCookie(UserModel model) {
  430. return null;
  431. }
  432. @Override
  433. public UserModel getUserModel(char[] cookie) {
  434. return null;
  435. }
  436. @Override
  437. public UserModel getUserModel(String username) {
  438. return virtualUsers.get(username);
  439. }
  440. @Override
  441. public boolean updateUserModel(UserModel model) {
  442. virtualUsers.put(model.username, model);
  443. return true;
  444. }
  445. @Override
  446. public boolean updateUserModels(Collection<UserModel> models) {
  447. return false;
  448. }
  449. @Override
  450. public boolean updateUserModel(String username, UserModel model) {
  451. virtualUsers.put(username, model);
  452. return true;
  453. }
  454. @Override
  455. public boolean deleteUserModel(UserModel model) {
  456. return false;
  457. }
  458. @Override
  459. public boolean deleteUser(String username) {
  460. return false;
  461. }
  462. @Override
  463. public List<String> getAllUsernames() {
  464. return null;
  465. }
  466. @Override
  467. public List<UserModel> getAllUsers() {
  468. return null;
  469. }
  470. @Override
  471. public List<String> getAllTeamNames() {
  472. return null;
  473. }
  474. @Override
  475. public List<TeamModel> getAllTeams() {
  476. return null;
  477. }
  478. @Override
  479. public List<String> getTeamNamesForRepositoryRole(String role) {
  480. return null;
  481. }
  482. @Override
  483. public TeamModel getTeamModel(String teamname) {
  484. return null;
  485. }
  486. @Override
  487. public boolean updateTeamModel(TeamModel model) {
  488. return false;
  489. }
  490. @Override
  491. public boolean updateTeamModels(Collection<TeamModel> models) {
  492. return false;
  493. }
  494. @Override
  495. public boolean updateTeamModel(String teamname, TeamModel model) {
  496. return false;
  497. }
  498. @Override
  499. public boolean deleteTeamModel(TeamModel model) {
  500. return false;
  501. }
  502. @Override
  503. public boolean deleteTeam(String teamname) {
  504. return false;
  505. }
  506. @Override
  507. public List<String> getUsernamesForRepositoryRole(String role) {
  508. return null;
  509. }
  510. @Override
  511. public boolean renameRepositoryRole(String oldRole,
  512. String newRole) {
  513. return false;
  514. }
  515. @Override
  516. public boolean deleteRepositoryRole(String role) {
  517. return false;
  518. }
  519. });
  520. AuthenticationManager auth = new AuthenticationManager(runtime, users).start();
  521. return auth;
  522. }
  523. @Test
  524. public void testAuthenticate() throws Exception {
  525. IAuthenticationManager auth = newAuthenticationManager();
  526. String password = "pass word";
  527. UserModel user = new UserModel("sunnyjim");
  528. user.password = password;
  529. users.updateUserModel(user);
  530. char[] pwd = password.toCharArray();
  531. assertNotNull(auth.authenticate(user.username, pwd, null));
  532. // validate that the passed in password has been zeroed out in memory
  533. char[] zeroes = new char[pwd.length];
  534. Arrays.fill(zeroes, Character.MIN_VALUE);
  535. assertArrayEquals(zeroes, pwd);
  536. }
  537. @Test
  538. public void testAuthenticateDisabledUser() throws Exception {
  539. IAuthenticationManager auth = newAuthenticationManager();
  540. String password = "password";
  541. UserModel user = new UserModel("sunnyjim");
  542. user.password = password;
  543. user.disabled = true;
  544. users.updateUserModel(user);
  545. assertNull(auth.authenticate(user.username, password.toCharArray(), null));
  546. user.disabled = false;
  547. users.updateUserModel(user);
  548. assertNotNull(auth.authenticate(user.username, password.toCharArray(), null));
  549. }
  550. @Test
  551. public void testAuthenticateEmptyPassword() throws Exception {
  552. IAuthenticationManager auth = newAuthenticationManager();
  553. String password = "password";
  554. UserModel user = new UserModel("sunnyjim");
  555. user.password = password;
  556. users.updateUserModel(user);
  557. assertNull(auth.authenticate(user.username, "".toCharArray(), null));
  558. assertNull(auth.authenticate(user.username, " ".toCharArray(), null));
  559. assertNull(auth.authenticate(user.username, new char[]{' ', '\u0010', '\u0015'}, null));
  560. }
  561. @Test
  562. public void testAuthenticateWrongPassword() throws Exception {
  563. IAuthenticationManager auth = newAuthenticationManager();
  564. String password = "password";
  565. UserModel user = new UserModel("sunnyjim");
  566. user.password = password;
  567. users.updateUserModel(user);
  568. assertNull(auth.authenticate(user.username, "helloworld".toCharArray(), null));
  569. }
  570. @Test
  571. public void testAuthenticateNoSuchUser() throws Exception {
  572. IAuthenticationManager auth = newAuthenticationManager();
  573. String password = "password";
  574. UserModel user = new UserModel("sunnyjim");
  575. user.password = password;
  576. users.updateUserModel(user);
  577. assertNull(auth.authenticate("rainyjoe", password.toCharArray(), null));
  578. }
  579. @Test
  580. public void testAuthenticateUpgradePlaintext() throws Exception {
  581. IAuthenticationManager auth = newAuthenticationManager();
  582. String password = "topsecret";
  583. UserModel user = new UserModel("sunnyjim");
  584. user.password = password;
  585. users.updateUserModel(user);
  586. assertNotNull(auth.authenticate(user.username, password.toCharArray(), null));
  587. // validate that plaintext password was automatically updated to hashed one
  588. assertTrue(user.password.startsWith(PasswordHash.getDefaultType().name() + ":"));
  589. // validate that the password is still valid and the user can log in
  590. assertNotNull(auth.authenticate(user.username, password.toCharArray(), null));
  591. }
  592. @Test
  593. public void testAuthenticateUpgradeMD5() throws Exception {
  594. IAuthenticationManager auth = newAuthenticationManager();
  595. String password = "secretAndHashed";
  596. UserModel user = new UserModel("sunnyjim");
  597. user.password = "MD5:BD95A1CFD00868B59B3564112D1E5847";
  598. users.updateUserModel(user);
  599. assertNotNull(auth.authenticate(user.username, password.toCharArray(), null));
  600. // validate that MD5 password was automatically updated to hashed one
  601. assertTrue(user.password.startsWith(PasswordHash.getDefaultType().name() + ":"));
  602. // validate that the password is still valid and the user can log in
  603. assertNotNull(auth.authenticate(user.username, password.toCharArray(), null));
  604. }
  605. @Test
  606. public void testContenairAuthenticate() throws Exception {
  607. settings.put(Keys.realm.container.autoCreateAccounts, "true");
  608. settings.put(Keys.realm.container.autoAccounts.displayName, "displayName");
  609. settings.put(Keys.realm.container.autoAccounts.emailAddress, "emailAddress");
  610. settings.put(Keys.realm.container.autoAccounts.adminRole, "admin");
  611. settings.put(Keys.realm.container.autoAccounts.locale, "locale");
  612. DummyHttpServletRequest request = new DummyHttpServletRequest();
  613. request.sessionAttributes.put("displayName", "Sunny Jim");
  614. request.sessionAttributes.put("emailAddress", "Jim.Sunny@gitblit.com");
  615. request.sessionAttributes.put("locale", "it");
  616. IAuthenticationManager auth = newAuthenticationManager();
  617. UserModel user = auth.authenticate(request);
  618. assertTrue(user.canAdmin);
  619. assertEquals("Sunny Jim", user.displayName);
  620. assertEquals("Jim.Sunny@gitblit.com", user.emailAddress);
  621. assertEquals(Locale.ITALIAN, user.getPreferences().getLocale());
  622. }
  623. @Test
  624. public void testContenairAuthenticateEmpty() throws Exception {
  625. settings.put(Keys.realm.container.autoCreateAccounts, "true");
  626. settings.put(Keys.realm.container.autoAccounts.displayName, "displayName");
  627. settings.put(Keys.realm.container.autoAccounts.emailAddress, "emailAddress");
  628. settings.put(Keys.realm.container.autoAccounts.adminRole, "notAdmin");
  629. DummyHttpServletRequest request = new DummyHttpServletRequest();
  630. IAuthenticationManager auth = newAuthenticationManager();
  631. UserModel user = auth.authenticate(request);
  632. assertFalse(user.canAdmin);
  633. assertEquals("sunnyjim", user.displayName);
  634. assertNull(user.emailAddress);
  635. assertNull(user.getPreferences().getLocale());
  636. }
  637. }