All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bimserver.webservices.authorization.Authorization Maven / Gradle / Ivy

There is a newer version: 1.5.9
Show newest version
package org.bimserver.webservices.authorization;

/******************************************************************************
 * Copyright (C) 2009-2016  BIMserver.org
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see {@literal}.
 *****************************************************************************/

import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.TimeUnit;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bimserver.models.store.Project;
import org.bimserver.models.store.User;
import org.bimserver.models.store.UserType;
import org.bimserver.shared.exceptions.UserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class Authorization {
	private static final Logger LOGGER = LoggerFactory.getLogger(Authorization.class);
	private final GregorianCalendar expires = new GregorianCalendar();
	private long uoid = -1;

	public Authorization(int expires, TimeUnit expiresUnit) {
		this.expires.add(Calendar.SECOND, (int) TimeUnit.SECONDS.convert(expires, expiresUnit));
	}
	
	public Authorization() {
	}

	public GregorianCalendar getExpires() {
		return expires;
	}

	public void canDownload(long roid) throws UserException {
	}

	public void canCheckin(long poid) throws UserException {
	}

	public void canReadExtendedData(long roid) throws UserException {
	}

	public void canWriteExtendedData(long roid) throws UserException {
	}

	protected abstract int getBufferSize();

	protected abstract byte getId();

	public boolean hasRightsOnProjectOrSuperProjectsOrSubProjects(User user, Project project) {
		if (user == null) {
			return false;
		}
		if (user.getUserType() == UserType.ADMIN || user.getUserType() == UserType.SYSTEM) {
			return true;
		}
		while (project != null) {
			if (hasRightsOnProjectOrSubProjects(user, project)) {
				return true;
			}
			project = project.getParent();
		}
		return false;
	}

	public boolean hasRightsOnProjectOrSuperProjects(User user, Project project) {
		if (user.getUserType() == UserType.ADMIN || user.getUserType() == UserType.SYSTEM) {
			return true;
		}
		if (hasRightsOnProject(user, project)) {
			return true;
		}
		if (project.getParent() != null) {
			if (hasRightsOnProjectOrSuperProjects(user, project.getParent())) {
				return true;
			}
		}
		return false;
	}

	public boolean hasRightsOnProjectOrSubProjects(User user, Project project) {
		if (user.getUserType() == UserType.ADMIN || user.getUserType() == UserType.SYSTEM) {
			return true;
		}
		if (hasRightsOnProject(user, project)) {
			return true;
		}
		for (Project subProject : project.getSubProjects()) {
			if (hasRightsOnProjectOrSubProjects(user, subProject)) {
				return true;
			}
		}
		return false;
	}

	public boolean hasRightsOnProject(User user, Project project) {
		if (user.getUserType() == UserType.ADMIN || user.getUserType() == UserType.SYSTEM) {
			return true;
		}
		for (User authorizedUser : project.getHasAuthorizedUsers()) {
			if (authorizedUser == user) {
				return true;
			}
		}
		return false;
	}

	protected abstract void getBytes(ByteBuffer buffer);

	public String asHexToken(Key key) {
		try {
			Cipher encodingCipher = Cipher.getInstance("AES");
			encodingCipher.init(Cipher.ENCRYPT_MODE, key);

			ByteBuffer buffer = ByteBuffer.allocate(16 + 1 + 8 + 8 + getBufferSize());
			buffer.position(16);
			buffer.put(getId());
			buffer.putLong(getExpires().getTimeInMillis());
			buffer.putLong(getUoid());
			getBytes(buffer);
			if (buffer.position() != buffer.capacity()) {
				throw new RuntimeException("Buffer's position should be at the end " + buffer.position() + "/" + buffer.capacity());
			}
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			buffer.position(16);
			messageDigest.update(buffer);
			buffer.position(0);
			buffer.put(messageDigest.digest());

			byte[] encodedBytes = encodingCipher.doFinal(buffer.array());
			String encodedHexString = new String(Hex.encodeHex(encodedBytes));
			return encodedHexString;
		} catch (Exception e) {
			LOGGER.error("", e);
		}
		return null;
	}
	
	public static Authorization fromToken(SecretKeySpec key, String token) throws AuthenticationException {
		if (token == null) {
			throw new IllegalArgumentException("Token required");
		}
		try {
			int hashSizeBytes = 16;
			Cipher decodingCipher = Cipher.getInstance("AES");
			decodingCipher.init(Cipher.DECRYPT_MODE, key);
			ByteBuffer buffer = ByteBuffer.wrap(decodingCipher.doFinal(Hex.decodeHex(token.toCharArray())));
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			byte[] foundHash = new byte[hashSizeBytes];
			buffer.get(foundHash, 0, hashSizeBytes);
			byte[] hashInput = new byte[buffer.capacity() - hashSizeBytes];
			buffer.get(hashInput);
			buffer.position(hashSizeBytes);
			byte[] calculatedHash = messageDigest.digest(hashInput);
			if (Arrays.equals(foundHash, calculatedHash)) {
				byte type = buffer.get();
				Authorization authorization = null;
				long expires = buffer.getLong();
				long uoid = buffer.getLong();
				switch (type) {
				case ExplicitRightsAuthorization.ID:
					authorization = ExplicitRightsAuthorization.fromBuffer(buffer);
					break;
				case UserAuthorization.ID:
					authorization = UserAuthorization.fromBuffer(buffer);
					break;
				case SystemAuthorization.ID:
					authorization = SystemAuthorization.fromBuffer(buffer);
					break;
				case AnonymousAuthorization.ID:
					authorization = AnonymousAuthorization.fromBuffer(buffer);
					break;
				case AdminAuthorization.ID:
					authorization = AdminAuthorization.fromBuffer(buffer);
					break;
				default:
					throw new AuthenticationException("Unknown authorization type: " + type);
				}
				authorization.setUoid(uoid);
				authorization.setExpires(expires);
				if (authorization.getExpires().getTimeInMillis() < new GregorianCalendar().getTimeInMillis()) {
					throw new AuthenticationException("This token has expired");
				}
				return authorization;
			} else {
				throw new AuthenticationException("Given token is corrupt");
			}
		} catch (GeneralSecurityException e) {
			throw new AuthenticationException("Invalid token", e);
		} catch (DecoderException e) {
			throw new AuthenticationException(e);
		}
	}

	private void setExpires(long expires) {
		this.expires.setTimeInMillis(expires);
	}

	public long getUoid() {
		return uoid;
	}

	public void setUoid(long uoid) {
		this.uoid = uoid;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy