org.bimserver.webservices.authorization.Authorization.java Source code

Java tutorial

Introduction

Here is the source code for org.bimserver.webservices.authorization.Authorization.java

Source

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<http://www.gnu.org/licenses/>}.
 *****************************************************************************/

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;
                case SingleProjectAuthorization.ID:
                    authorization = SingleProjectAuthorization.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;
    }
}