1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.astrogrid.community.server.security.service ;
29
30 import org.apache.commons.logging.Log ;
31 import org.apache.commons.logging.LogFactory ;
32
33 import java.util.Vector ;
34
35 import java.rmi.server.UID ;
36
37 import org.exolab.castor.jdo.Database;
38 import org.exolab.castor.jdo.ObjectNotFoundException ;
39
40 import org.astrogrid.store.Ivorn ;
41
42 import org.astrogrid.community.server.security.data.PasswordData ;
43 import org.astrogrid.community.common.security.data.SecurityToken ;
44 import org.astrogrid.community.common.security.service.SecurityService ;
45
46 import org.astrogrid.community.common.ivorn.CommunityIvornParser ;
47 import org.astrogrid.community.common.ivorn.CommunityAccountIvornFactory ;
48
49 import org.astrogrid.community.server.service.CommunityServiceImpl ;
50 import org.astrogrid.community.server.database.configuration.DatabaseConfiguration ;
51
52 import org.astrogrid.community.common.exception.CommunityServiceException ;
53 import org.astrogrid.community.common.exception.CommunitySecurityException ;
54 import org.astrogrid.community.common.exception.CommunityIdentifierException ;
55
56 /***
57 * Implementation of our SecurityService service.
58 *
59 */
60 public class SecurityServiceImpl
61 extends CommunityServiceImpl
62 implements SecurityService
63 {
64 /***
65 * Our debug logger.
66 *
67 */
68 private static Log log = LogFactory.getLog(SecurityServiceImpl.class);
69
70 /***
71 * Public constructor, using default database configuration.
72 *
73 */
74 public SecurityServiceImpl()
75 {
76 super() ;
77 }
78
79 /***
80 * Public constructor, using specific database configuration.
81 *
82 */
83 public SecurityServiceImpl(DatabaseConfiguration config)
84 {
85 super(config) ;
86 }
87
88 /***
89 * Public constructor, using a parent service.
90 *
91 */
92 public SecurityServiceImpl(CommunityServiceImpl parent)
93 {
94 super(parent) ;
95 }
96
97 /***
98 * Generate a new token for an account.
99 * @param account The Account ident.
100 * @throws CommunityIdentifierException If the identifiers are not valid.
101 * @throws CommunityServiceException If the local Community identifier is not set.
102 *
103 */
104 protected SecurityToken createToken(CommunityIvornParser account)
105 throws CommunityServiceException, CommunityIdentifierException
106 {
107 log.debug("") ;
108 log.debug("----\"----") ;
109 log.debug("SecurityServiceImpl.createToken()") ;
110
111
112 UID uid = new UID() ;
113
114
115 Ivorn ivorn = CommunityAccountIvornFactory.createLocal(
116 uid.toString()
117 ) ;
118
119
120 SecurityToken token = new SecurityToken(
121 account.getAccountIdent(),
122 ivorn.toString()
123 ) ;
124
125
126 token.setStatus(SecurityToken.VALID_TOKEN) ;
127
128
129 log.debug(" Token : " + token) ;
130 return token ;
131 }
132
133 /***
134 * Check an Account password.
135 * @param account The account ident.
136 * @param password The account password.
137 * @return A valid SecurityToken if the ident and password are valid.
138 * @throws CommunitySecurityException If the security check fails.
139 * @throws CommunityServiceException If there is an internal error in service.
140 * @throws CommunityIdentifierException If the account identifier is invalid.
141 * @todo Check Account is local.
142 *
143 */
144 public SecurityToken checkPassword(String account, String password)
145 throws CommunityServiceException, CommunitySecurityException, CommunityIdentifierException
146 {
147 log.debug("") ;
148 log.debug("----\"----") ;
149 log.debug("SecurityServiceImpl.checkPassword()") ;
150 log.debug(" Ident : " + account) ;
151 log.debug(" Pass : " + password) ;
152
153
154 if (null == account)
155 {
156 throw new CommunityIdentifierException(
157 "Null account"
158 ) ;
159 }
160
161
162 if (null == password)
163 {
164 throw new CommunityIdentifierException(
165 "Null password"
166 ) ;
167 }
168
169
170 CommunityIvornParser ident = new CommunityIvornParser(
171 account
172 ) ;
173
174
175 SecurityToken token = null ;
176 Database database = null ;
177 try {
178
179
180 database = this.getDatabase() ;
181
182
183 database.begin();
184
185
186 PasswordData match = (PasswordData) database.load(PasswordData.class, ident.getAccountIdent()) ;
187 log.debug(" PASS : Got password data") ;
188 log.debug(" Account : " + match.getAccount()) ;
189 log.debug(" Password : " + match.getPassword()) ;
190
191
192 if (password.equals(match.getPassword()))
193 {
194 log.debug(" PASS : Password matches") ;
195
196
197 token = this.createToken(ident) ;
198 database.create(token);
199 log.debug(" PASS : Got new token") ;
200
201
202 database.commit() ;
203 }
204
205
206 else {
207
208
209 throw new CommunitySecurityException(
210 "Password invalid",
211 ident.getAccountIdent()
212 ) ;
213 }
214 }
215
216
217 catch (CommunitySecurityException ouch)
218 {
219
220
221 rollbackTransaction(database) ;
222
223
224 throw ouch ;
225 }
226
227
228 catch (ObjectNotFoundException ouch)
229 {
230
231
232 rollbackTransaction(database) ;
233
234
235 throw new CommunitySecurityException(
236 "Account password not found",
237 ident.toString()
238 ) ;
239 }
240
241
242 catch (Exception ouch)
243 {
244
245
246 logException(
247 ouch,
248 "SecurityServiceImpl.checkPassword()"
249 ) ;
250
251
252 rollbackTransaction(database) ;
253
254
255 throw new CommunityServiceException(
256 "Database transaction failed",
257 ident.toString(),
258 ouch
259 ) ;
260 }
261
262
263 finally
264 {
265 closeConnection(database) ;
266 }
267
268
269 return token ;
270 }
271
272 /***
273 * Validate a SecurityToken.
274 * Validates a token, and creates a new tokens issued to the same account.
275 * @param token The token to validate.
276 * @return A new SecurityToken if the original was valid.
277 * @throws CommunitySecurityException If the security check fails.
278 * @throws CommunityServiceException If there is an internal error in service.
279 * @throws CommunityIdentifierException If the token is invalid.
280 * @todo Refactor to call split and unpack ?
281 * @todo Check Token is local.
282 *
283 */
284 public SecurityToken checkToken(SecurityToken original)
285 throws CommunityServiceException, CommunitySecurityException, CommunityIdentifierException
286 {
287 log.debug("") ;
288 log.debug("----\"----") ;
289 log.debug("SecurityServiceImpl.checkToken()") ;
290 log.debug(" Token : " + original) ;
291
292
293 if (null == original)
294 {
295 throw new CommunityIdentifierException(
296 "Null token"
297 ) ;
298 }
299
300
301 original.setStatus(SecurityToken.INVALID_TOKEN) ;
302
303
304 CommunityIvornParser token = new CommunityIvornParser(
305 original.getToken()
306 ) ;
307 log.debug(" Token : " + token) ;
308
309
310 CommunityIvornParser account = new CommunityIvornParser(
311 original.getAccount()
312 ) ;
313 log.debug(" Account : " + account) ;
314
315 SecurityToken result = null ;
316 Database database = null ;
317 try {
318
319
320 database = this.getDatabase() ;
321
322
323 database.begin();
324
325
326 SecurityToken match = (SecurityToken) database.load(SecurityToken.class, original.getToken()) ;
327 log.debug(" PASS : Got matching token") ;
328 log.debug(" Token : " + match) ;
329
330
331 if (match.isValid())
332 {
333 log.debug(" PASS : Original is valid") ;
334
335
336
337 match.setStatus(SecurityToken.INVALID_TOKEN) ;
338
339
340 result = this.createToken(account) ;
341 database.create(result) ;
342
343
344 database.commit() ;
345
346
347 return result ;
348 }
349
350
351 else {
352 log.debug(" FAIL : Original is not valid") ;
353
354
355 throw new CommunitySecurityException(
356 "Token invalid",
357 original.getToken()
358 ) ;
359 }
360 }
361
362
363 catch (CommunitySecurityException ouch)
364 {
365
366
367 rollbackTransaction(database) ;
368
369
370 throw ouch ;
371 }
372
373
374 catch (ObjectNotFoundException ouch)
375 {
376
377
378 rollbackTransaction(database) ;
379
380
381 throw new CommunitySecurityException(
382 "Token not found",
383 original.getToken()
384 ) ;
385 }
386
387
388 catch (Exception ouch)
389 {
390
391
392 logException(
393 ouch,
394 "SecurityServiceImpl.checkToken()"
395 ) ;
396
397
398 rollbackTransaction(database) ;
399
400
401 throw new CommunityServiceException(
402 "Database transaction failed",
403 original.getToken(),
404 ouch
405 ) ;
406 }
407
408
409 finally
410 {
411 closeConnection(database) ;
412 }
413 }
414
415 /***
416 * Split a SecurityToken.
417 * Validates a token, and then creates a new set of tokens issued to the same account.
418 * @throws CommunitySecurityException If the security check fails.
419 * @throws CommunityServiceException If there is an internal error in service.
420 * @throws CommunityIdentifierException If the token is invalid.
421 * @todo Check Token is local.
422 *
423 */
424 public Object[] splitToken(SecurityToken original, int count)
425 throws CommunityServiceException, CommunitySecurityException, CommunityIdentifierException
426 {
427 log.debug("") ;
428 log.debug("----\"----") ;
429 log.debug("SecurityServiceImpl.checkToken()") ;
430 log.debug(" Token : " + original) ;
431
432
433 if (null == original)
434 {
435 throw new CommunityIdentifierException(
436 "Null token"
437 ) ;
438 }
439
440
441 original.setStatus(SecurityToken.INVALID_TOKEN) ;
442
443
444 CommunityIvornParser token = new CommunityIvornParser(
445 original.getToken()
446 ) ;
447 log.debug(" Token : " + token) ;
448
449
450 CommunityIvornParser account = new CommunityIvornParser(
451 original.getAccount()
452 ) ;
453 log.debug(" Account : " + account) ;
454
455 Vector vector = new Vector() ;
456 Database database = null ;
457 try {
458
459
460 database = this.getDatabase() ;
461
462
463 database.begin();
464
465
466 SecurityToken match = (SecurityToken) database.load(SecurityToken.class, original.getToken()) ;
467 log.debug(" PASS : Got matching token") ;
468 log.debug(" Token : " + match) ;
469
470
471 if (match.isValid())
472 {
473 log.debug(" PASS : Original is valid") ;
474
475
476
477 match.setStatus(SecurityToken.INVALID_TOKEN) ;
478
479
480 for (int i = 0 ; i < count ; i++)
481 {
482 SecurityToken result = this.createToken(account) ;
483 database.create(result) ;
484 vector.add(result) ;
485 }
486
487
488 database.commit() ;
489 }
490
491
492 else {
493 log.debug(" FAIL : Original is not valid") ;
494
495
496 throw new CommunitySecurityException(
497 "Token invalid",
498 original.getToken()
499 ) ;
500 }
501 }
502
503
504 catch (CommunitySecurityException ouch)
505 {
506
507
508 rollbackTransaction(database) ;
509
510
511 throw ouch ;
512 }
513
514
515 catch (ObjectNotFoundException ouch)
516 {
517
518
519 rollbackTransaction(database) ;
520
521
522 throw new CommunitySecurityException(
523 "Token not found",
524 original.getToken()
525 ) ;
526 }
527
528
529 catch (Exception ouch)
530 {
531
532
533 logException(
534 ouch,
535 "SecurityServiceImpl.checkToken()"
536 ) ;
537
538
539 rollbackTransaction(database) ;
540
541
542 throw new CommunityServiceException(
543 "Database transaction failed",
544 original.getToken(),
545 ouch
546 ) ;
547 }
548
549
550 finally
551 {
552 closeConnection(database) ;
553 }
554
555
556 return vector.toArray() ;
557 }
558 }