aboutsummaryrefslogtreecommitdiffstats
path: root/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFAuthenticationInfo.java
blob: 4e5d59bd4ae883536318257a49d5e6c93cd0285e (plain)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/**
 * ============LICENSE_START====================================================
 * org.onap.aaf
 * ===========================================================================
 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
 * ===========================================================================
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============LICENSE_END====================================================
 *
 */
package org.onap.aaf.cadi.shiro;

import java.nio.ByteBuffer;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import org.apache.log4j.Logger;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.PrincipalCollection;
import org.onap.aaf.cadi.Access;
import org.onap.aaf.cadi.Hash;

public class AAFAuthenticationInfo implements AuthenticationInfo {
	private static final long serialVersionUID = -1502704556864321020L;
	
	final static Logger logger = Logger.getLogger(AAFAuthenticationInfo.class);
	
	// We assume that Shiro is doing Memory Only, and this salt is not needed cross process
	private final static int salt = new SecureRandom().nextInt(); 

	private final AAFPrincipalCollection apc;
	private final byte[] hash;
	private Access access;

	public AAFAuthenticationInfo(Access access, String username, String password) {
		this.access = access;
		apc = new AAFPrincipalCollection(username);
		hash = getSaltedCred(password);
	}
	@Override
	public byte[] getCredentials() {
		logger.debug("AAFAuthenticationInfo.getCredentials");
		return hash;
	}

	@Override
	public PrincipalCollection getPrincipals() {
		logger.debug( "AAFAuthenticationInfo.getPrincipals");
		return apc;
	}

	public boolean matches(AuthenticationToken atoken) {
		if(atoken instanceof UsernamePasswordToken) {
			UsernamePasswordToken upt = (UsernamePasswordToken)atoken;
			if(apc.getPrimaryPrincipal().getName().equals(upt.getPrincipal())) {
				byte[] newhash = getSaltedCred(new String(upt.getPassword()));
				if(newhash.length==hash.length) {
					for(int i=0;i<hash.length;++i) {
						if(hash[i]!=newhash[i]) {
							return false;
						}
					}
					return true;
				}
			}
		}
		return false;
	}
	
	private byte[] getSaltedCred(String password) {
		byte[] pbytes = password.getBytes();
		ByteBuffer bb = ByteBuffer.allocate(pbytes.length+Integer.SIZE/8);
		bb.asIntBuffer().put(salt);
		bb.put(password.getBytes());
		try {
			return Hash.hashSHA256(bb.array());
		} catch (NoSuchAlgorithmException e) {
			return new byte[0]; // should never get here
		}
	}
}