source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/Authentication.java@ 37517

Last change on this file since 37517 was 37517, checked in by kjdon, 14 months ago

check for null user result

File size: 47.0 KB
Line 
1package org.greenstone.gsdl3.service;
2
3import java.io.File;
4import java.io.Serializable;
5import java.math.BigInteger;
6import java.sql.SQLException;
7import java.util.ArrayList;
8import java.util.HashMap;
9import java.util.UUID;
10import java.util.Vector;
11import java.util.regex.Pattern;
12
13// for verifying recaptcha
14import java.io.BufferedReader;
15import java.io.DataOutputStream;
16import java.io.IOException;
17import java.io.InputStreamReader;
18import java.io.StringReader;
19import java.net.URL;
20import javax.net.ssl.HttpsURLConnection;
21// https://developer.android.com/reference/org/json/JSONObject.html
22// https://developer.android.com/reference/org/json/JSONArray.html
23import org.json.JSONArray;
24import org.json.JSONException;
25import org.json.JSONObject;
26
27import org.apache.commons.codec.digest.DigestUtils;
28import org.greenstone.gsdl3.util.DerbyWrapper;
29import org.greenstone.gsdl3.util.GSXML;
30import org.greenstone.gsdl3.util.UserQueryResult;
31import org.greenstone.gsdl3.util.UserTermInfo;
32import org.greenstone.gsdl3.util.XMLConverter;
33import org.greenstone.util.GlobalProperties;
34
35import org.w3c.dom.Document;
36import org.w3c.dom.Element;
37import org.w3c.dom.NodeList;
38
39public class Authentication extends ServiceRack
40{
41 //Some useful constants
42 protected static final int USERNAME_MIN_LENGTH = 2;
43 protected static final int USERNAME_MAX_LENGTH = 30;
44 protected static final int PASSWORD_MIN_LENGTH = 3;
45 protected static final int PASSWORD_MAX_LENGTH = 64;
46
47 //Error codes
48 public static final int NO_ERROR = 0;
49 protected static final int ERROR_NOT_LOGGED_IN = -1;
50 protected static final int ERROR_ADMIN_NOT_LOGGED_IN = -2;
51 protected static final int ERROR_COULD_NOT_GET_USER_INFO = -3;
52 protected static final int ERROR_USERNAME_NOT_SPECIFIED = -4;
53 protected static final int ERROR_USER_NOT_FOUND = -5;
54 protected static final int ERROR_USER_NOT_AUTHORISED = -6;
55 protected static final int ERROR_INVALID_USERNAME = -7;
56 protected static final int ERROR_USER_ALREADY_EXISTS = -8;
57 protected static final int ERROR_PASSWORD_NOT_ENTERED = -9;
58 protected static final int ERROR_PASSWORD_TOO_SHORT = -10;
59 protected static final int ERROR_PASSWORD_TOO_LONG = -11;
60 protected static final int ERROR_PASSWORD_USES_ILLEGAL_CHARACTERS = -12;
61 protected static final int ERROR_INCORRECT_PASSWORD = -13;
62 protected static final int ERROR_ADDING_USER = -14;
63 protected static final int ERROR_REMOVING_USER = -15;
64 protected static final int ERROR_CAPTCHA_FAILED = -16;
65 protected static final int ERROR_CAPTCHA_MISSING = -17;
66 protected static final int ERROR_CONNECTION_FAILED = -18;
67 protected static final int ERROR_MISSING_PARAMS = -19;
68 protected static final int ERROR_SOMETHING_WRONG = -20;
69
70 // recaptcha
71 protected static final HashMap<Integer, String> _errorKeyMap;
72 static
73 {
74 //Corresponding error message keys for looking up in ServiceRack dictionary
75 HashMap<Integer, String> errorKeyMap = new HashMap<Integer, String>();
76 errorKeyMap.put(ERROR_NOT_LOGGED_IN, "auth.error.not_logged_in");
77 errorKeyMap.put(ERROR_ADMIN_NOT_LOGGED_IN, "auth.error.admin_not_logged_in");
78 errorKeyMap.put(ERROR_COULD_NOT_GET_USER_INFO, "auth.error.could_not_get_user_info");
79 errorKeyMap.put(ERROR_USERNAME_NOT_SPECIFIED, "auth.error.username_not_specified");
80 errorKeyMap.put(ERROR_USER_NOT_FOUND, "auth.error.user_not_found");
81 errorKeyMap.put(ERROR_USER_NOT_AUTHORISED, "auth.error.not_authorised");
82 errorKeyMap.put(ERROR_INVALID_USERNAME, "auth.error.invalid_username");
83 errorKeyMap.put(ERROR_USER_ALREADY_EXISTS, "auth.error.user_already_exists");
84 errorKeyMap.put(ERROR_PASSWORD_NOT_ENTERED, "auth.error.no_password");
85 errorKeyMap.put(ERROR_PASSWORD_TOO_SHORT, "auth.error.password_too_short");
86 errorKeyMap.put(ERROR_PASSWORD_TOO_LONG, "auth.error.password_too_long");
87 errorKeyMap.put(ERROR_PASSWORD_USES_ILLEGAL_CHARACTERS, "auth.error.password_illegal_chars");
88 errorKeyMap.put(ERROR_INCORRECT_PASSWORD, "auth.error.incorrect_password");
89 errorKeyMap.put(ERROR_ADDING_USER, "auth.error.add_user_error");
90 errorKeyMap.put(ERROR_REMOVING_USER, "auth.error.remove_user_error");
91 errorKeyMap.put(ERROR_CAPTCHA_FAILED, "auth.error.captcha_failed");
92 errorKeyMap.put(ERROR_CAPTCHA_MISSING, "auth.error.captcha_missing");
93 errorKeyMap.put(ERROR_CONNECTION_FAILED, "auth.error.connection_failed");
94
95 errorKeyMap.put(ERROR_MISSING_PARAMS, "auth.error.missing_params"); // ???
96 errorKeyMap.put(ERROR_SOMETHING_WRONG, "auth.error.something_wrong");
97 _errorKeyMap = errorKeyMap;
98 }
99
100 //Admin-required operations
101 protected static final String LIST_USERS = "ListUsers";
102 protected static final String PERFORM_ADD = "PerformAdd";
103 protected static final String PERFORM_EDIT = "PerformEdit";
104 protected static final String ADD_USER = "AddUser";
105 protected static final String EDIT_USER = "EditUser";
106 protected static final String PERFORM_DELETE_USER = "PerformDeleteUser";
107
108 protected static final ArrayList<String> _adminOpList;
109 static
110 {
111 ArrayList<String> opList = new ArrayList<String>();
112 opList.add(LIST_USERS);
113 opList.add(PERFORM_ADD);
114 opList.add(PERFORM_EDIT);
115 opList.add(ADD_USER);
116 opList.add(EDIT_USER);
117 opList.add(PERFORM_DELETE_USER);
118
119 _adminOpList = opList;
120 }
121
122 //User-required operations
123 protected static final String ACCOUNT_SETTINGS = "AccountSettings";
124 protected static final String PERFORM_ACCOUNT_EDIT = "PerformAccEdit";
125 protected static final String PERFORM_RESET_PASSWORD = "PerformResetPassword";
126 protected static final String PERFORM_CHANGE_PASSWORD = "PerformChangePassword";
127 protected static final String PERFORM_RETRIEVE_PASSWORD = "PerformRetrievePassword";
128 protected static final ArrayList<String> _userOpList;
129 static
130 {
131 ArrayList<String> opList = new ArrayList<String>();
132 opList.add(ACCOUNT_SETTINGS);
133 opList.add(PERFORM_ACCOUNT_EDIT);
134 opList.add(PERFORM_RESET_PASSWORD);
135 opList.add(PERFORM_CHANGE_PASSWORD);
136 opList.add(PERFORM_RETRIEVE_PASSWORD);
137 opList.addAll(_adminOpList);
138 _userOpList = opList;
139 }
140
141 //Other operations
142 protected static final String REGISTER = "Register"; // displays the register page
143 protected static final String PERFORM_REGISTER = "PerformRegister"; // performs the registration action
144 protected static final String LOGIN = "Login";
145 protected static final String BLANK = "Info"; // a dummy page just for showing an error message
146
147 //the services on offer
148 public static final String AUTHENTICATION_SERVICE = "Authentication";
149 protected static final String GET_USER_INFORMATION_SERVICE = "GetUserInformation";
150 protected static final String CHANGE_USER_EDIT_MODE_SERVICE = "ChangeUserEditMode";
151 protected static final String REMOTE_AUTHENTICATION_SERVICE = "RemoteAuthentication";
152
153 protected static boolean _derbyWrapperDoneForcedShutdown = false;
154
155 // some XML strings
156 protected static final String RECAPTCHA_ELEM = "recaptcha";
157 protected static final String SITE_KEY = "site_key";
158 protected static final String SECRET_KEY = "secret_key";
159 protected static final String OPERATIONS = "operations";
160 protected static final String OPERATION = "operation";
161 protected static final String USERNAME = "username";
162 protected static final String PASSWORD = "password";
163 protected static final String COLLECTION = "collection";
164 protected static final String GROUPS = "groups";
165 protected static final String COMPACTED_GROUPS = "compacted_groups";
166 protected static final String EXPANDED_GROUPS = "expanded_groups";
167 protected static final String STATUS = "status";
168 protected static final String RECAPTCHA_KEY = "recaptcha_key";
169 protected static final String COMMENT = "comment";
170 protected static final String EMAIL = "email";
171
172 // cgi params
173 protected static final String USERNAME_PARAM = "username";
174 protected static final String PREV_USERNAME_PARAM = "prevUsername";
175 protected static final String NEW_USERNAME_PARAM = "newUsername";
176 protected static final String PASSWORD_PARAM = "password";
177 protected static final String OLD_PASSWORD_PARAM = "oldPassword";
178 protected static final String NEW_PASSWORD_PARAM = "newPassword";
179 protected static final String GROUPS_PARAM = "groups";
180 protected static final String ENABLED_PARAM = "enabled";
181 protected static final String COMMENT_PARAM = "comment";
182 protected static final String STATUS_PARAM = "status";
183 protected static final String EMAIL_PARAM = "email";
184 protected static final String NEW_EMAIL_PARAM = "newEmail";
185 protected static final String ACCOUNT_STATUS_PARAM = "accountstatus";
186 protected static final String EDIT_ENABLED_PARAM = "editEnabled";
187 protected static final String AUTHPAGE_PARAM = "authpage";
188 public static final String RECAPTCHA_RESPONSE_PARAM = "g-recaptcha-response";
189
190 protected String _recaptchaSiteKey = null;
191 protected String _recaptchaSecretKey = null;
192 protected static ArrayList<String> _recaptchaOpList = null;
193 /** constructor */
194 public Authentication()
195 {
196 }
197
198 public void cleanUp()
199 {
200 super.cleanUp();
201
202 if (!_derbyWrapperDoneForcedShutdown)
203 {
204
205 // This boolean is used to ensure we always shutdown the derby server, even if it is never
206 // used by the Authentication server. This is because the Tomcat greenstone3.xml
207 // config file also specifies a connection to the database, which can result in the
208 // server being initialized when the servlet is first accessed. Note also,
209 // Authentication is a ServiceRack, meaning cleanUp() is called for each service
210 // supported, however we only need to shutdown the Derby server once. Again
211 // this boolean variable helps achieve this.
212
213 logger.info("Authentication Service performing forced shutdown of Derby Server ...");
214
215 DerbyWrapper.shutdownDatabaseServer();
216 _derbyWrapperDoneForcedShutdown = true;
217 }
218 }
219
220 public boolean configure(Element info, Element extra_info)
221 {
222 logger.info("Configuring Authentication...");
223 this.config_info = info;
224
225 // set up Authentication service info - for now just has name and type
226 Element authentication_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
227 authentication_service.setAttribute(GSXML.TYPE_ATT, "authen");
228 authentication_service.setAttribute(GSXML.NAME_ATT, AUTHENTICATION_SERVICE);
229 this.short_service_info.appendChild(authentication_service);
230
231 Element getUserInformation_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
232 getUserInformation_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
233 getUserInformation_service.setAttribute(GSXML.NAME_ATT, GET_USER_INFORMATION_SERVICE);
234 this.short_service_info.appendChild(getUserInformation_service);
235
236 Element changeEditMode_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
237 changeEditMode_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
238 changeEditMode_service.setAttribute(GSXML.NAME_ATT, CHANGE_USER_EDIT_MODE_SERVICE);
239 this.short_service_info.appendChild(changeEditMode_service);
240
241 Element remoteAuthentication_service = this.desc_doc.createElement(GSXML.SERVICE_ELEM);
242 remoteAuthentication_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
243 remoteAuthentication_service.setAttribute(GSXML.NAME_ATT, REMOTE_AUTHENTICATION_SERVICE);
244 this.short_service_info.appendChild(remoteAuthentication_service);
245
246 DerbyWrapper.createDatabaseIfNeeded();
247
248 NodeList recaptchaElems = info.getElementsByTagName(RECAPTCHA_ELEM);
249 for (int i = 0; i < recaptchaElems.getLength(); i++)
250 {
251 Element currentElem = (Element) recaptchaElems.item(i);
252 if (currentElem.getAttribute(GSXML.NAME_ATT).equals(SITE_KEY))
253 {
254 if (!currentElem.getAttribute(GSXML.VALUE_ATT).equals(""))
255 {
256 _recaptchaSiteKey = currentElem.getAttribute(GSXML.VALUE_ATT);
257 }
258 }
259 else if (currentElem.getAttribute(GSXML.NAME_ATT).equals(SECRET_KEY))
260 {
261 if (!currentElem.getAttribute(GSXML.VALUE_ATT).equals(""))
262 {
263 _recaptchaSecretKey = currentElem.getAttribute(GSXML.VALUE_ATT);
264 }
265 }
266 else if (currentElem.getAttribute(GSXML.NAME_ATT).equals(OPERATIONS))
267 {
268 _recaptchaOpList = new ArrayList<String>();
269 String value = currentElem.getAttribute(GSXML.VALUE_ATT);
270 String[] ops = value.split(",");
271 for (int j=0; j<ops.length; j++) {
272 if (!ops[j].equals("")) {
273 _recaptchaOpList.add(ops[j]); /// value checking?
274 }
275 }
276 }
277
278 }
279 // check recaptcha
280 if (_recaptchaSecretKey == null || _recaptchaSecretKey.length() == 0 || _recaptchaSiteKey == null || _recaptchaSiteKey.length() == 0) {
281 _recaptchaSecretKey = null;
282 _recaptchaSiteKey = null;
283 _recaptchaOpList = null;
284 }
285
286 // while all of our params are "not saved" for the session, a few of them are also sensitive, so should not be listed in the page response XML
287 this.sensitive_params.add(PASSWORD_PARAM);
288 this.sensitive_params.add(NEW_PASSWORD_PARAM);
289 this.sensitive_params.add(OLD_PASSWORD_PARAM);
290 this.sensitive_params.add(RECAPTCHA_RESPONSE_PARAM);
291
292
293
294 return true;
295 }
296
297 public String getRecaptchaSiteKey() {
298 return _recaptchaSiteKey;
299 }
300
301 public String getRecaptchaSecretKey() {
302
303 return _recaptchaSecretKey;
304 }
305 protected Element getServiceDescription(Document doc, String service_id, String lang, String subset)
306 {
307
308 Element authen_service = doc.createElement(GSXML.SERVICE_ELEM);
309
310 if (service_id.equals(AUTHENTICATION_SERVICE))
311 {
312 authen_service.setAttribute(GSXML.TYPE_ATT, "authen");
313 authen_service.setAttribute(GSXML.NAME_ATT, AUTHENTICATION_SERVICE);
314 }
315 else if (service_id.equals(GET_USER_INFORMATION_SERVICE))
316 {
317 authen_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
318 authen_service.setAttribute(GSXML.NAME_ATT, GET_USER_INFORMATION_SERVICE);
319 }
320 else if (service_id.equals(CHANGE_USER_EDIT_MODE_SERVICE))
321 {
322 authen_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
323 authen_service.setAttribute(GSXML.NAME_ATT, CHANGE_USER_EDIT_MODE_SERVICE);
324 }
325 else if (service_id.equals(REMOTE_AUTHENTICATION_SERVICE))
326 {
327 authen_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
328 authen_service.setAttribute(GSXML.NAME_ATT, REMOTE_AUTHENTICATION_SERVICE);
329 }
330 else
331 {
332 return null;
333 }
334
335 if (service_id.equals(AUTHENTICATION_SERVICE) && (subset == null || subset.equals(GSXML.DISPLAY_TEXT_ELEM + GSXML.LIST_MODIFIER)))
336 {
337 authen_service.appendChild(GSXML.createDisplayTextElement(doc, GSXML.DISPLAY_TEXT_NAME, getServiceName(service_id, lang)));
338 authen_service.appendChild(GSXML.createDisplayTextElement(doc, GSXML.DISPLAY_TEXT_DESCRIPTION, getServiceDescription(service_id, lang)));
339 }
340 return authen_service;
341 }
342
343 protected String getServiceName(String service_id, String lang)
344 {
345 return getTextString(service_id + ".name", lang);
346 }
347
348 protected String getServiceSubmit(String service_id, String lang)
349 {
350 return getTextString(service_id + ".submit", lang);
351 }
352
353 protected String getServiceDescription(String service_id, String lang)
354 {
355 return getTextString(service_id + ".description", lang);
356 }
357 protected String getErrorTextString(int error_code, String lang) {
358 return getTextString(_errorKeyMap.get(error_code), lang);
359
360 }
361 public static String getErrorKey(int error_code) {
362
363 return _errorKeyMap.get(error_code);
364 }
365 protected Element processChangeUserEditMode(Element request)
366 {
367 // Create a new (empty) result message
368 Document result_doc = XMLConverter.newDOM();
369 Element result = result_doc.createElement(GSXML.RESPONSE_ELEM);
370
371 result.setAttribute(GSXML.FROM_ATT, CHANGE_USER_EDIT_MODE_SERVICE);
372 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
373
374 Element paramList = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
375 if (paramList == null)
376 {
377 logger.error("ChangeUserEditMode request has no param list!!");
378 return result;
379 }
380
381 HashMap<String, Serializable> params = GSXML.extractParams(paramList, true);
382
383 String username = (String) params.get(USERNAME_PARAM);
384 String editMode = (String) params.get(ENABLED_PARAM);
385
386 if (!editMode.toLowerCase().equals("true") && !editMode.toLowerCase().equals("false"))
387 {
388 editMode = "false";
389 }
390
391 DerbyWrapper dw = openDatabase();
392 dw.addUserData(username, "USER_EDIT_ENABLED", editMode);
393 dw.closeDatabase();
394
395 return result;
396 }
397
398 /**
399 * This method replaces the gliserver.pl code for authenticating a user against the derby database
400 * gliserver.pl needed to instantiate its own JVM to access the derby DB, but the GS3 already has
401 * the Derby DB open and 2 JVMs are not allowed concurrent access to an open embedded Derby DB.
402 * Gliserver.pl now goes through this method (via ServletRealmCheck.java), thereby using the same
403 * connection to the DerbyDB. This method reproduces the same behaviour as gliserver.pl used to,
404 * by returning the user_groups on successful authentication, else returns the specific
405 * "Authentication failed" messages that gliserver.pl would produce.
406 * http://remote-host-name:8383/greenstone3/library?a=s&sa=authenticated-ping&excerptid=gs_content&un=admin&pw=<PW>&col=demo
407 */
408 protected Element processRemoteAuthentication(Element request) {
409 //logger.info("*** Authentication::processRemoteAuthentication");
410
411 String message = "";
412
413 Element system = (Element) GSXML.getChildByTagName(request, GSXML.REQUEST_TYPE_SYSTEM);
414 String username = system.hasAttribute(USERNAME) ? system.getAttribute(USERNAME) : "";
415 String password = system.hasAttribute(PASSWORD) ? system.getAttribute(PASSWORD) : "";
416
417
418 // If we're not editing a collection then the user doesn't need to be in a particular group
419 String collection = system.hasAttribute(COLLECTION) ? system.getAttribute(COLLECTION) : "";
420
421
422 if(username.equals("") || password.equals("")) {
423 message = "Authentication failed: no (username or) password specified.";
424 //logger.error("*** Remote login failed. No username or pwd provided");
425 }
426 else {
427 String storedPassword = retrieveDataForUser(username, PASSWORD);
428 if(storedPassword != null && (password.equals(storedPassword) || hashPassword(password).equals(storedPassword))) {
429
430 // gliserver.pl used to return the groups when authentication succeeded
431 String groups = retrieveDataForUser(username, EXPANDED_GROUPS); //comma-separated list
432
433 if(collection.equals("")) {
434 message = groups;
435 } else {
436
437 if(groups.indexOf("all-collections-editor") != -1) { // Does this user have access to all collections?
438 message = groups;
439 } else if(groups.indexOf("personal-collections-editor") != -1 && collection.startsWith(username+"-")) { // Does this user have access to personal collections, and is this one?
440 message = groups;
441 } else if(groups.indexOf(collection+"-collection-editor") != -1) { // Does this user have access to this collection?
442 message = groups;
443 }
444 else {
445 message = "Authentication failed: user is not in the required group.";
446 //logger.error("*** Remote login failed. Groups did not match for the collection specified");
447 }
448 }
449
450 } else {
451
452 if(storedPassword == null) {
453 message = "Authentication failed: no account for user '" + username + "'";
454 //logger.error("*** Remote login failed. User not found or password not set for user.");
455 } else {
456 message = "Authentication failed: incorrect password.";
457 //logger.error("*** Remote login failed. Password did not match for user");
458 }
459 }
460 }
461 Document result_doc = XMLConverter.newDOM();
462 Element result = result_doc.createElement(GSXML.RESPONSE_ELEM);
463 result.setAttribute(GSXML.FROM_ATT, REMOTE_AUTHENTICATION_SERVICE);
464 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
465 Element s = GSXML.createTextElement(result_doc, GSXML.STATUS_ELEM, message);
466 result.appendChild(s);
467 return result;
468 }
469
470 protected Element processGetUserInformation(Element request)
471 {
472 // Create a new (empty) result message
473 Document result_doc = XMLConverter.newDOM();
474 Element result = result_doc.createElement(GSXML.RESPONSE_ELEM);
475
476 result.setAttribute(GSXML.FROM_ATT, GET_USER_INFORMATION_SERVICE);
477 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
478
479 String lang = request.getAttribute(GSXML.LANG_ATT);
480 Element paramList = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
481 if (paramList == null)
482 {
483 logger.error("GetUserInformation request has no param list");
484 return result;
485 }
486
487 HashMap<String, Serializable> params = GSXML.extractParams(paramList, true);
488
489 String username = (String) params.get(USERNAME_PARAM);
490
491 if (username == null)
492 {
493 GSXML.addError(result, getErrorTextString(ERROR_USERNAME_NOT_SPECIFIED, lang));
494 return result;
495 }
496
497 DerbyWrapper derbyWrapper = openDatabase();
498
499 UserQueryResult userQueryResult = derbyWrapper.findUser(username);
500 String editEnabled = derbyWrapper.getUserData(username, "USER_EDIT_ENABLED");
501
502 Vector<UserTermInfo> terms = userQueryResult.getUserTerms();
503
504 if (terms.size() == 0)
505 {
506 GSXML.addError(result, getErrorTextString(ERROR_USER_NOT_FOUND, lang));
507 return result;
508 }
509
510 UserTermInfo userInfo = terms.get(0);
511 Element userInfoList = result_doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
512 result.appendChild(userInfoList);
513
514 Element usernameField = GSXML.createParameter(result_doc, USERNAME_PARAM, userInfo.getUsername());
515 Element passwordField = GSXML.createParameter(result_doc, PASSWORD_PARAM, userInfo.getPassword());
516 Element groupsField = GSXML.createParameter(result_doc, GROUPS_PARAM, userInfo.getExpandedGroups()); // used by LibraryServlet that calls the containing method
517 Element accountStatusField = GSXML.createParameter(result_doc, ACCOUNT_STATUS_PARAM, userInfo.getAccountStatus());
518 Element commentField = GSXML.createParameter(result_doc, COMMENT_PARAM, userInfo.getComment());
519
520 if (editEnabled != null)
521 {
522 Element editEnabledElem = GSXML.createParameter(result_doc, EDIT_ENABLED_PARAM, editEnabled);
523 userInfoList.appendChild(editEnabledElem);
524 }
525
526 userInfoList.appendChild(usernameField);
527 userInfoList.appendChild(passwordField);
528 userInfoList.appendChild(groupsField);
529 userInfoList.appendChild(accountStatusField);
530 userInfoList.appendChild(commentField);
531
532 derbyWrapper.closeDatabase();
533
534 return result;
535 }
536
537 protected Element processAuthentication(Element request)
538 {
539 checkAdminUserExists();
540
541 // Create a new (empty) result message
542 Document result_doc = XMLConverter.newDOM();
543 Element result = result_doc.createElement(GSXML.RESPONSE_ELEM);
544 result.setAttribute(GSXML.FROM_ATT, AUTHENTICATION_SERVICE);
545 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
546
547 // Create an Authentication node put into the result
548 Element authenNode = result_doc.createElement(GSXML.AUTHEN_NODE_ELEM);
549 result.appendChild(authenNode);
550 result.appendChild(getCollectList(result_doc, this.site_home + File.separatorChar + "collect"));
551
552 // Create a service node added into the Authentication node
553 Element serviceNode = result_doc.createElement(GSXML.SERVICE_ELEM);
554 authenNode.appendChild(serviceNode);
555
556 // Get the parameters of the request
557 String lang = request.getAttribute(GSXML.LANG_ATT);
558 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
559 if (param_list == null)
560 {
561 serviceNode.setAttribute(OPERATION, BLANK);
562 logger.error("Authentication request has no param list");
563 return result; // Return the empty result
564 }
565 HashMap<String, Serializable> paramMap = GSXML.extractParams(param_list, false);
566 String op = (String) paramMap.get(AUTHPAGE_PARAM);
567 serviceNode.setAttribute(OPERATION, op);
568
569 String username = null;
570 String groups = null;
571
572 Element userInformation = (Element) GSXML.getChildByTagName(request, GSXML.USER_INFORMATION_ELEM);
573 if (userInformation != null)
574 {
575 username = userInformation.getAttribute(GSXML.USERNAME_ATT);
576 groups = userInformation.getAttribute(GSXML.GROUPS_ATT);
577 }
578 logger.debug("username="+username+", groups = "+groups);
579 logger.debug("expandedGroups would be: "+UserTermInfo.expandGroups(groups));
580 logger.debug("compactedGroups would be: "+UserTermInfo.compactGroups(groups));
581
582 if ((userInformation == null || username == null) && _userOpList.contains(op))
583 {
584 // its an operation that requires the user to be logged on - direct them to login page
585 serviceNode.setAttribute(OPERATION, LOGIN);
586 if (_recaptchaOpList != null && _recaptchaOpList.contains(LOGIN)) {
587 serviceNode.setAttribute(RECAPTCHA_KEY, _recaptchaSiteKey);
588 }
589 GSXML.addError(result, getErrorTextString(ERROR_NOT_LOGGED_IN, lang));
590 return result;
591 }
592
593 if (_adminOpList.contains(op) && (groups == null || !groups.matches(".*\\badministrator\\b.*")))
594 {
595 // actually, the user needs to be an admin user and they are not
596 serviceNode.setAttribute(OPERATION, LOGIN);
597 if (_recaptchaOpList != null && _recaptchaOpList.contains(LOGIN)) {
598 serviceNode.setAttribute(RECAPTCHA_KEY, _recaptchaSiteKey);
599 }
600 GSXML.addError(result, getErrorTextString(ERROR_ADMIN_NOT_LOGGED_IN, lang));
601 return result;
602 }
603
604 if (_recaptchaOpList != null && _recaptchaOpList.contains(op)) {
605 serviceNode.setAttribute(RECAPTCHA_KEY, _recaptchaSiteKey);
606 }
607
608 if (op.equals(LIST_USERS))
609 {
610 int error = addUserInformationToNode(null, serviceNode);
611 if (error != NO_ERROR)
612 {
613 serviceNode.setAttribute(OPERATION, BLANK);
614 GSXML.addError(result, getErrorTextString(error, lang));
615 }
616 return result;
617
618 }
619
620 if (op.equals(PERFORM_ADD))
621 {
622 String newUsername = (String) paramMap.get(USERNAME_PARAM);
623 String newPassword = (String) paramMap.get(PASSWORD_PARAM);
624 String newGroups = (String) paramMap.get(GROUPS_PARAM);
625 String newStatus = (String) paramMap.get(STATUS_PARAM);
626 String newComment = (String) paramMap.get(COMMENT_PARAM);
627 String newEmail = (String) paramMap.get(EMAIL_PARAM);
628
629 if (_recaptchaOpList != null && _recaptchaOpList.contains(ADD_USER)) {
630 serviceNode.setAttribute(RECAPTCHA_KEY, _recaptchaSiteKey);
631 }
632 //Check the given user name
633 int error;
634 if (checkUserExists(newUsername)) {
635 error = ERROR_USER_ALREADY_EXISTS;
636 } else {
637 error = checkUsername(newUsername);
638 }
639 if (error != NO_ERROR)
640 {
641 serviceNode.setAttribute(OPERATION, ADD_USER);
642 GSXML.addError(result, getErrorTextString(error, lang));
643 return result;
644 }
645
646 //Check the given password
647 if ((error = checkPassword(newPassword)) != NO_ERROR)
648 {
649 serviceNode.setAttribute(OPERATION, ADD_USER);
650 GSXML.addError(result, getErrorTextString(error, lang));
651 return result;
652 }
653
654 newPassword = hashPassword(newPassword);
655
656 error = addUser(newUsername, newPassword, newGroups, newStatus, newComment, newEmail);
657 if (error != NO_ERROR)
658 {
659 serviceNode.setAttribute(OPERATION, ADD_USER);
660 GSXML.addError(result, getErrorTextString(error, lang));
661 }
662 else
663 {
664 addUserInformationToNode(null, serviceNode);
665 serviceNode.setAttribute(OPERATION, LIST_USERS);
666 }
667 return result;
668 }
669
670 if (op.equals(REGISTER)) {
671 // don't need any additional info
672 return result;
673 }
674 if (op.equals(PERFORM_REGISTER))
675 {
676 String newUsername = (String) paramMap.get(USERNAME_PARAM);
677 String newPassword = (String) paramMap.get(PASSWORD_PARAM);
678 String newEmail = (String) paramMap.get(EMAIL_PARAM);
679
680 //Check the given details
681 int error;
682 if (checkUserExists(newUsername)) {
683 error = ERROR_USER_ALREADY_EXISTS;
684 } else {
685 error = checkUsername(newUsername);
686 }
687 if (error == NO_ERROR) {
688 if ((error = checkPassword(newPassword)) == NO_ERROR) {
689 newPassword = hashPassword(newPassword);
690 if (_recaptchaOpList != null && _recaptchaOpList.contains(REGISTER)) {
691 String user_response = (String) paramMap.get(RECAPTCHA_RESPONSE_PARAM);
692 if ((error= verifyRecaptcha(_recaptchaSecretKey, user_response)) == NO_ERROR) {
693 error = addUser(newUsername, newPassword, "", "true", "", newEmail);
694 }
695 }
696 }
697 }
698
699 if (error != NO_ERROR)
700 {
701 serviceNode.setAttribute(OPERATION, REGISTER);
702 if (_recaptchaOpList != null && _recaptchaOpList.contains(REGISTER)) {
703 serviceNode.setAttribute(RECAPTCHA_KEY, _recaptchaSiteKey);
704 }
705 GSXML.addError(result, getErrorTextString(error, lang));
706 }
707 // otherwise everything hunky dory and we return result
708 return result;
709 }
710
711 // PERFORM_EDIT is caled when admin is running EditUser, and PERFORM_ACCOUNT_EDIT is called when a user is running AccountSettings to change their own details
712 if (op.equals(PERFORM_EDIT) || op.equals(PERFORM_ACCOUNT_EDIT)) {
713
714 String parent_op = EDIT_USER;
715 if (op.equals(PERFORM_ACCOUNT_EDIT)) {
716 parent_op = ACCOUNT_SETTINGS;
717 }
718 String previousUsername = (String) paramMap.get(PREV_USERNAME_PARAM);
719 String newUsername = (String) paramMap.get(NEW_USERNAME_PARAM);
720 int error;
721 // Has the user name been changed? Make sure it doesn't already exist and is a valid username
722 if (previousUsername == null) {
723 // we have ended up here by mistake (via s1.authpage which is no longer valid)
724 serviceNode.setAttribute(OPERATION, BLANK);
725 GSXML.addError(result, getErrorTextString(ERROR_SOMETHING_WRONG, lang));
726 return result;
727 }
728
729 if (!previousUsername.equals(newUsername)) {
730
731 error = NO_ERROR;
732 if (checkUserExists(newUsername)) {
733 error = ERROR_USER_ALREADY_EXISTS;
734 } else {
735 error = checkUsername(newUsername);
736 }
737 if (error != NO_ERROR) {
738 addUserInformationToNode(previousUsername, serviceNode);
739 serviceNode.setAttribute(OPERATION, parent_op);
740 GSXML.addError(result, getErrorTextString(error, lang));
741 return result;
742 }
743 }
744
745 // password checking
746 String newPassword;
747 if (op.equals(PERFORM_EDIT)) {
748 newPassword = (String) paramMap.get(PASSWORD_PARAM);
749 } else {
750 newPassword = (String) paramMap.get(NEW_PASSWORD_PARAM);
751 }
752 if (newPassword == null) {
753 // we are not changing the password
754 newPassword = retrieveDataForUser(previousUsername, PASSWORD);
755 } else {
756 // we need to check the old one
757 if (op.equals(PERFORM_ACCOUNT_EDIT)) {
758 // check that they entered their old password correctly
759 String prevPassword = retrieveDataForUser(previousUsername, PASSWORD);
760 String oldPassword = (String) paramMap.get(OLD_PASSWORD_PARAM);
761 oldPassword = hashPassword(oldPassword);
762 if (oldPassword == null || !oldPassword.equals(prevPassword)) {
763
764 addUserInformationToNode(previousUsername, serviceNode);
765 serviceNode.setAttribute(OPERATION, ACCOUNT_SETTINGS);
766 GSXML.addError(result, getErrorTextString(ERROR_INCORRECT_PASSWORD, lang), "INCORRECT_PASSWORD");
767 return result;
768 }
769 }
770 // need to make sure the new password is a valid password
771 if ((error = checkPassword(newPassword)) != NO_ERROR) {
772
773 addUserInformationToNode(previousUsername, serviceNode);
774 serviceNode.setAttribute(OPERATION, parent_op);
775 GSXML.addError(result, getErrorTextString(error, lang));
776 return result;
777 }
778 newPassword = hashPassword(newPassword);
779
780 }
781
782 // are we using recaptcha for AccountSettings or EditUser?
783 if (_recaptchaOpList != null && _recaptchaOpList.contains(parent_op)) {
784 String user_response = (String) paramMap.get(RECAPTCHA_RESPONSE_PARAM);
785 if ((error= verifyRecaptcha(_recaptchaSecretKey, user_response)) != NO_ERROR) {
786 addUserInformationToNode(previousUsername, serviceNode);
787 serviceNode.setAttribute(OPERATION, parent_op);
788 serviceNode.setAttribute(RECAPTCHA_KEY, _recaptchaSiteKey);
789 GSXML.addError(result, getErrorTextString(error, lang));
790 return result;
791 }
792 }
793
794 groups = null; // doesn't matter if local groups var keeps value in compactedGroups or expandedGroups form,
795 // as addUser() and addUserInformationToNode() will ensure use of expanded and compacted forms respectively
796 String status = null;
797 String comment = null;
798 String email = (String) paramMap.get(NEW_EMAIL_PARAM);
799 if (op.equals(PERFORM_EDIT)) {
800 groups = (String) paramMap.get(GROUPS_PARAM);
801 status = (String) paramMap.get(STATUS_PARAM);
802 comment = (String) paramMap.get(COMMENT_PARAM);
803
804 } else {
805 groups = retrieveDataForUser(previousUsername, EXPANDED_GROUPS);
806 status = retrieveDataForUser(previousUsername, STATUS);
807 comment = retrieveDataForUser(previousUsername, COMMENT);
808 }
809
810
811 error = removeUser(previousUsername);
812 if (error != NO_ERROR) {
813 addUserInformationToNode(previousUsername, serviceNode);
814 serviceNode.setAttribute(OPERATION, parent_op);
815 GSXML.addError(result, getErrorTextString(error, lang));
816 return result;
817 }
818
819 error = addUser(newUsername, newPassword, groups, status, comment, email);
820 if (error != NO_ERROR) {
821
822 // oh dear. we have removed previous data, but were unable to add new data. The user is now gone :-(
823 serviceNode.setAttribute(OPERATION, BLANK);
824 GSXML.addError(result, getErrorTextString(error, lang));
825 }
826 else {
827 if (op.equals(PERFORM_ACCOUNT_EDIT)) {
828 addUserInformationToNode(newUsername, serviceNode);
829 serviceNode.setAttribute(OPERATION, parent_op);
830 if (_recaptchaOpList != null && _recaptchaOpList.contains(parent_op)) {
831 serviceNode.setAttribute(RECAPTCHA_KEY, _recaptchaSiteKey);
832 }
833 GSXML.addError(result, getTextString("auth.success.account_settings", lang));
834
835 } else {
836
837 addUserInformationToNode(null, serviceNode);
838 serviceNode.setAttribute(OPERATION, LIST_USERS);
839 String [] args = {newUsername};
840 GSXML.addError(result, getTextString("auth.success.edit_user", lang, args));
841 }
842
843 }
844 return result;
845 }
846 if (op.equals(PERFORM_RETRIEVE_PASSWORD))
847 {
848 return result;
849 }
850 if (op.equals(PERFORM_CHANGE_PASSWORD))
851 {
852 serviceNode.setAttribute(OPERATION, PERFORM_CHANGE_PASSWORD);
853 String user_name = (String) paramMap.get(USERNAME_PARAM);
854 String oldPassword = (String) paramMap.get(OLD_PASSWORD_PARAM);
855 String newPassword = (String) paramMap.get(NEW_PASSWORD_PARAM);
856 if (user_name == null || oldPassword == null || newPassword == null)
857 {
858 GSXML.addError(result, getErrorTextString(ERROR_MISSING_PARAMS, lang));
859 return result;
860 }
861
862 String prevPassword = retrieveDataForUser(user_name, PASSWORD);
863 if (!hashPassword(oldPassword).equals(prevPassword))
864 {
865 addUserInformationToNode(user_name, serviceNode);
866 GSXML.addError(result, getErrorTextString(ERROR_INCORRECT_PASSWORD, lang), "INCORRECT_PASSWORD");
867 return result;
868 }
869
870 //Check the given password
871 int error;
872 if ((error = checkPassword(newPassword)) != NO_ERROR)
873 {
874 GSXML.addError(result, getErrorTextString(error, lang));
875 return result;
876 }
877
878 DerbyWrapper derbyWrapper = openDatabase();
879 String chpa_groups = retrieveDataForUser(user_name, EXPANDED_GROUPS); // userDB now stores expandedGroups, not compactedGroups
880 String chpa_comment = "password_changed_by_user";
881 String info = derbyWrapper.modifyUserInfo(user_name, hashPassword(newPassword), chpa_groups, null, chpa_comment, null);
882 derbyWrapper.closeDatabase();
883 if (info != "succeed")
884 {//see DerbyWrapper.modifyUserInfo
885 GSXML.addError(result, info);
886 return result;
887 }
888 return result;
889 }
890 if (op.equals(EDIT_USER))
891 {
892 String editUsername = (String) paramMap.get(USERNAME_PARAM);
893 int error = addUserInformationToNode(editUsername, serviceNode);
894 if (error != NO_ERROR)
895 {
896 GSXML.addError(result, getErrorTextString(error, lang));
897 }
898 return result;
899 }
900 if (op.equals(ACCOUNT_SETTINGS))
901 {
902 String editUsername = (String) paramMap.get(USERNAME_PARAM);
903
904 if (editUsername == null)
905 {
906 serviceNode.setAttribute(OPERATION, "");
907 GSXML.addError(result, getErrorTextString(ERROR_USERNAME_NOT_SPECIFIED, lang));
908 return result;
909 }
910
911 if (!editUsername.equals(username))
912 {
913 serviceNode.setAttribute(OPERATION, LOGIN);
914 GSXML.addError(result, getErrorTextString(ERROR_USER_NOT_AUTHORISED, lang));
915 return result;
916 }
917 int error = addUserInformationToNode(editUsername, serviceNode);
918 if (error != NO_ERROR)
919 {
920 GSXML.addError(result, getErrorTextString(error, lang));
921 }
922 return result;
923 }
924 if (op.equals(PERFORM_RESET_PASSWORD))
925 {
926 String passwordResetUser = (String) paramMap.get(USERNAME_PARAM);
927
928 String newPassword = UUID.randomUUID().toString();
929 newPassword = newPassword.substring(0, newPassword.indexOf("-"));
930
931 String email = retrieveDataForUser(passwordResetUser, EMAIL);
932 String from = "[email protected]";
933 String host = request.getAttribute("remoteAddress");
934
935 //TODO: FINISH THIS
936 return result;
937 }
938 if (op.equals(PERFORM_DELETE_USER))
939 {
940 String usernameToDelete = (String) paramMap.get(USERNAME_PARAM);
941 int error = removeUser(usernameToDelete);
942 if (error != NO_ERROR)
943 {
944 GSXML.addError(result, getErrorTextString(error, lang));
945 }
946 addUserInformationToNode(null, serviceNode);
947 serviceNode.setAttribute(OPERATION, LIST_USERS);
948 String[] args = {usernameToDelete};
949 GSXML.addError(result, getTextString("auth.success.delete_user", lang, args));
950 return result;
951 }
952
953 return result; // or should we return null, as we haven't recognised the operation??
954 }
955
956 public int checkUsernameAndPassword(String username, String password)
957 {
958 int uResult = checkUsername(username);
959 int pResult = checkPassword(password);
960
961 return (uResult != NO_ERROR ? uResult : (pResult != NO_ERROR ? pResult : NO_ERROR));
962 }
963
964 public int checkUsername(String username)
965 {
966 //Check the given user name
967 if ((username == null) || (username.length() < USERNAME_MIN_LENGTH) || (username.length() > USERNAME_MAX_LENGTH) || (!(Pattern.matches("[a-zA-Z0-9//_//.]+", username))))
968 {
969 return ERROR_INVALID_USERNAME;
970 }
971 return NO_ERROR;
972 }
973
974 public int checkPassword(String password)
975 {
976 //Check the given password
977 if (password == null)
978 {
979 return ERROR_PASSWORD_NOT_ENTERED;
980 }
981 else if (password.length() < PASSWORD_MIN_LENGTH)
982 {
983 return ERROR_PASSWORD_TOO_SHORT;
984 }
985 else if (password.length() > PASSWORD_MAX_LENGTH)
986 {
987 return ERROR_PASSWORD_TOO_LONG;
988 }
989 else if (!(Pattern.matches("[\\p{ASCII}]+", password)))
990 {
991 return ERROR_PASSWORD_USES_ILLEGAL_CHARACTERS;
992 }
993 return NO_ERROR;
994 }
995
996 public static String hashPassword(String password)
997 {
998 return DigestUtils.sha1Hex(password);
999 }
1000
1001 public static int verifyRecaptcha(String secret_key, String user_response) {
1002
1003 if (user_response == null || user_response.length() == 0) {
1004 return ERROR_CAPTCHA_MISSING;
1005 }
1006
1007 try{
1008
1009 URL obj = new URL("https://www.google.com/recaptcha/api/siteverify");
1010 HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
1011
1012 // add reuqest header
1013 con.setRequestMethod("POST");
1014 con.setRequestProperty("User-Agent", "Mozilla/5.0");
1015 con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
1016
1017 String postParams = "secret=" + secret_key + "&response="
1018 + user_response;
1019
1020 // Send post request
1021 con.setDoOutput(true);
1022 DataOutputStream wr = new DataOutputStream(con.getOutputStream());
1023 wr.writeBytes(postParams);
1024 wr.flush();
1025 wr.close();
1026
1027 int responseCode = con.getResponseCode();
1028 //System.out.println("\nSending 'POST' request to URL : https://www.google.com/recaptcha/api/siteverify");// + url);
1029 //System.out.println("Post parameters : " + postParams);
1030 //System.out.println("Response Code : " + responseCode);
1031
1032 BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
1033 String inputLine;
1034 StringBuffer response = new StringBuffer();
1035
1036 while ((inputLine = in.readLine()) != null) {
1037 response.append(inputLine);
1038 }
1039 in.close();
1040
1041 // print result
1042 //System.out.println(response.toString());
1043
1044 JSONObject json_obj = new JSONObject(response.toString());
1045 boolean res = json_obj.getBoolean("success");
1046 if (res) {
1047 return NO_ERROR;
1048 } else {
1049 return ERROR_CAPTCHA_FAILED;
1050 }
1051 }catch(Exception e){
1052 e.printStackTrace();
1053 return ERROR_CONNECTION_FAILED;
1054 }
1055
1056 }
1057 // This method can also be used for printing out the password in hex (in case
1058 // the password used the UTF-8 Charset), or the hex values in any unicode string.
1059 // From http://stackoverflow.com/questions/923863/converting-a-string-to-hexadecimal-in-java
1060 public static String toHex(String arg)
1061 {
1062 try
1063 {
1064 return String.format("%x", new BigInteger(arg.getBytes("US-ASCII"))); // set to same charset as used by hashPassword
1065 }
1066 catch (Exception e)
1067 { // UnsupportedEncodingException
1068 e.printStackTrace();
1069 }
1070 return "Unable to print";
1071 }
1072
1073 private void checkAdminUserExists()
1074 {
1075 DerbyWrapper derbyWrapper = openDatabase();
1076 UserQueryResult userQueryResult = derbyWrapper.findUser(null, null);
1077 derbyWrapper.closeDatabase();
1078
1079 if (userQueryResult != null)
1080 {
1081 Vector userInfo = userQueryResult.getUserTerms();
1082
1083 boolean adminFound = false;
1084 for (int i = 0; i < userQueryResult.getSize(); i++)
1085 {
1086 // can call either getExpandedGroups() or getCompactedGroups() to check admin group is in there:
1087 if (((UserTermInfo) userInfo.get(i)).getCompactedGroups() != null && ((UserTermInfo) userInfo.get(i)).getCompactedGroups().matches(".*\\badministrator\\b.*"))
1088 {
1089 adminFound = true;
1090 }
1091 }
1092
1093 if (!adminFound)
1094 {
1095 addUser("admin", "admin", "administrator", "true", "Change the password for this account as soon as possible", "");
1096 }
1097 }
1098 }
1099
1100 private DerbyWrapper openDatabase()
1101 {
1102 // check the usersDb database, if it isn't existing, check the etc dir, create the etc dir if it isn't existing, then create the user database and add a "admin" user
1103 String usersDB_dir = GlobalProperties.getGSDL3Home() + File.separatorChar + "etc" + File.separatorChar + "usersDB";
1104 DerbyWrapper derbyWrapper = new DerbyWrapper(usersDB_dir);
1105 return derbyWrapper;
1106 }
1107
1108 private int addUserInformationToNode(String username, Element serviceNode)
1109 {
1110 DerbyWrapper derbyWrapper = openDatabase();
1111 UserQueryResult userQueryResult = derbyWrapper.findUser(username, null);
1112 derbyWrapper.closeDatabase();
1113
1114 if (userQueryResult != null)
1115 {
1116 Element user_node = getUserNodeList(serviceNode.getOwnerDocument(), userQueryResult);
1117 serviceNode.appendChild(user_node);
1118 return NO_ERROR;
1119 }
1120
1121 return ERROR_COULD_NOT_GET_USER_INFO;
1122 }
1123
1124 private int removeUser(String username)
1125 {
1126 if (username == null)
1127 {
1128 return ERROR_USERNAME_NOT_SPECIFIED;
1129 }
1130
1131 DerbyWrapper derbyWrapper = openDatabase();
1132 boolean success = derbyWrapper.deleteUser(username);
1133 derbyWrapper.closeDatabase();
1134
1135 if (success)
1136 {
1137 return NO_ERROR;
1138 }
1139
1140 return ERROR_REMOVING_USER;
1141 }
1142
1143 private int addUser(String newUsername, String newPassword, String newGroups, String newStatus, String newComment, String newEmail)
1144 {
1145 newGroups = newGroups.replaceAll(" ", "");
1146 // store only expandedGroups in DB now
1147 newGroups = UserTermInfo.expandGroups(newGroups);
1148
1149 //Check if the user already exists
1150 DerbyWrapper derbyWrapper = openDatabase();
1151 UserQueryResult userQueryResult = derbyWrapper.findUser(newUsername, null);
1152
1153 if (userQueryResult != null)
1154 {
1155 derbyWrapper.closeDatabase();
1156 return ERROR_USER_ALREADY_EXISTS;
1157 }
1158 else
1159 {
1160 boolean success = derbyWrapper.addUser(newUsername, newPassword, newGroups, newStatus, newComment, newEmail);
1161 derbyWrapper.closeDatabase();
1162
1163 if (!success)
1164 {
1165 return ERROR_ADDING_USER;
1166 }
1167 }
1168
1169 return NO_ERROR;
1170 }
1171
1172 private boolean checkUserExists(String username)
1173 {
1174 boolean check_status = false;
1175
1176 DerbyWrapper derbyWrapper = openDatabase();
1177 try
1178 {
1179 UserQueryResult result = derbyWrapper.findUser(username);
1180
1181 if (result != null)
1182 {
1183 check_status = true;
1184 }
1185
1186 }
1187 catch (Exception ex)
1188 {
1189 // some error occurred accessing the database
1190 ex.printStackTrace();
1191 }
1192 derbyWrapper.closeDatabase();
1193
1194 return check_status;
1195 }
1196
1197 private String retrieveDataForUser(String username, String dataType)
1198 {
1199 openDatabase();
1200
1201 String data = null;
1202
1203 try
1204 {
1205 DerbyWrapper derbyWrapper = openDatabase();
1206 UserQueryResult result = derbyWrapper.findUser(username);
1207 derbyWrapper.closeDatabase();
1208 if (result == null) {
1209 return null;
1210 }
1211 Vector userInfo = result.getUserTerms();
1212
1213 for (int i = 0; i < result.getSize(); i++)
1214 {
1215 if (dataType.equals(PASSWORD))
1216 {
1217 data = ((UserTermInfo) userInfo.get(i)).getPassword();
1218 break;
1219 }
1220 else if (dataType.equals(COMPACTED_GROUPS))
1221 {
1222 data = ((UserTermInfo) userInfo.get(i)).getCompactedGroups();
1223 break;
1224 }
1225 else if (dataType.equals(EXPANDED_GROUPS))
1226 {
1227 data = ((UserTermInfo) userInfo.get(i)).getExpandedGroups();
1228 break;
1229 }
1230 else if (dataType.equals(STATUS))
1231 {
1232 data = ((UserTermInfo) userInfo.get(i)).getAccountStatus();
1233 break;
1234 }
1235 else if (dataType.equals(COMMENT))
1236 {
1237 data = ((UserTermInfo) userInfo.get(i)).getComment();
1238 break;
1239 }
1240 else if (dataType.equals(EMAIL))
1241 {
1242 data = ((UserTermInfo) userInfo.get(i)).getEmail();
1243 break;
1244 }
1245 }
1246 }
1247 catch (Exception ex)
1248 {
1249 ex.printStackTrace();
1250 }
1251
1252 return data;
1253 }
1254
1255 private Element getUserNodeList(Document doc, UserQueryResult userQueryResult)
1256 {
1257 Element user_list_node = doc.createElement(GSXML.USER_NODE_ELEM + GSXML.LIST_MODIFIER);
1258
1259 Vector userInfo = userQueryResult.getUserTerms();
1260
1261 for (int i = 0; i < userQueryResult.getSize(); i++)
1262 {
1263 Element user_node = doc.createElement(GSXML.USER_NODE_ELEM);
1264 String username = ((UserTermInfo) userInfo.get(i)).getUsername();
1265 String compactedGroups = ((UserTermInfo) userInfo.get(i)).getCompactedGroups();
1266 // Since this is used for display in admin pages, get compacted (more similar to user-entered) groups
1267 // and not expanded groups, as getUserNodeList only used in addUserInformationToNode() which
1268 // allows displaying and modifying user info pages and authenticating admin user,
1269 // none of which requires expanded groups.
1270 String accountstatus = ((UserTermInfo) userInfo.get(i)).getAccountStatus();
1271 String comment = ((UserTermInfo) userInfo.get(i)).getComment();
1272 String email = ((UserTermInfo) userInfo.get(i)).getEmail();
1273 user_node.setAttribute(USERNAME, username);
1274 user_node.setAttribute(GROUPS, compactedGroups);
1275 user_node.setAttribute(STATUS, accountstatus);
1276 user_node.setAttribute(COMMENT, comment);
1277 user_node.setAttribute(EMAIL, email);
1278
1279 user_list_node.appendChild(user_node);
1280 }
1281 return user_list_node;
1282 }
1283
1284 private Element getCollectList(Document doc, String collect)
1285 {
1286 Element collect_list_node = doc.createElement(GSXML.COLLECTION_ELEM + GSXML.LIST_MODIFIER);
1287 File[] collect_dir = (new File(collect)).listFiles();
1288 if (collect_dir != null && collect_dir.length > 0)
1289 {
1290 for (int i = 0; i < collect_dir.length; i++)
1291 {
1292 if (collect_dir[i].isDirectory() && (!collect_dir[i].getName().startsWith(".svn")))
1293 {
1294 Element collect_node = doc.createElement(GSXML.COLLECTION_ELEM);
1295 collect_node.setAttribute(GSXML.NAME_ATT, collect_dir[i].getName());
1296 collect_list_node.appendChild(collect_node);
1297 }
1298 }
1299 }
1300 return collect_list_node;
1301 }
1302
1303
1304 // main() method - calls hashPassword() on any String argument, printing this to stdout
1305 // This main() is invoked by gliserver.pl perl code to encrypt passwords identically to Java code.
1306 public static void main(String[] args)
1307 {
1308 if (args.length < 1)
1309 {
1310 System.err.println("Usage: Authentication <string to encrypt>");
1311 System.exit(-1);
1312 }
1313 // just hash the first argument
1314 String hash = Authentication.hashPassword(args[0]);
1315 System.out.println(hash);
1316 }
1317}
Note: See TracBrowser for help on using the repository browser.