com.sshtools.daemon.authentication.AuthorizationFileVerification.java Source code

Java tutorial

Introduction

Here is the source code for com.sshtools.daemon.authentication.AuthorizationFileVerification.java

Source

/*
 *  SSHTools - Java SSH2 API
 *
 *  Copyright (C) 2002 Lee David Painter.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  You may also distribute it and/or modify it under the terms of the
 *  Apache style J2SSH Software License. A copy of which should have
 *  been provided with the distribution.
 *
 *  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
 *  License document supplied with your distribution for more details.
 *
 */

package com.sshtools.daemon.authentication;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.sshtools.common.configuration.Authorization;
import com.sshtools.daemon.configuration.ServerConfiguration;
import com.sshtools.daemon.platform.NativeAuthenticationProvider;
import com.sshtools.j2ssh.authentication.AuthenticationProtocolException;
import com.sshtools.j2ssh.authentication.SshMsgUserAuthRequest;
import com.sshtools.j2ssh.configuration.ConfigurationLoader;
import com.sshtools.j2ssh.io.ByteArrayWriter;
import com.sshtools.j2ssh.transport.publickey.SshKeyPair;
import com.sshtools.j2ssh.transport.publickey.SshKeyPairFactory;
import com.sshtools.j2ssh.transport.publickey.SshPublicKey;
import com.sshtools.j2ssh.transport.publickey.SshPublicKeyFile;

/**
 *
 *
 * @author $author$
 * @version $Revision: 1.1.1.1 $
 */
public class AuthorizationFileVerification implements PublicKeyVerification {
    private static Log log = LogFactory.getLog(AuthorizationFileVerification.class);

    /**
     *
     *
     * @param username
     * @param algorithm
     * @param encoded
     * @param service
     * @param sessionId
     * @param signature
     *
     * @return
     *
     * @throws IOException
     */
    public boolean verifyKeySignature(String username, String algorithm, byte[] encoded, String service,
            byte[] sessionId, byte[] signature) throws IOException {
        try {
            SshPublicKey key = getAuthorizedKey(username, algorithm, encoded);

            ByteArrayWriter data = new ByteArrayWriter();
            data.writeBinaryString(sessionId);
            data.write(SshMsgUserAuthRequest.SSH_MSG_USERAUTH_REQUEST);
            data.writeString(username);
            data.writeString(service);
            data.writeString("publickey");
            data.write(1);
            data.writeString(key.getAlgorithmName());
            data.writeBinaryString(key.getEncoded());

            if (key.verifySignature(signature, data.toByteArray())) {
                return true;
            }
        } catch (IOException ex) {
        }

        return false;
    }

    private SshPublicKey getAuthorizedKey(String username, String algorithm, byte[] encoded) throws IOException {
        NativeAuthenticationProvider provider = NativeAuthenticationProvider.getInstance();

        String userHome = provider.getHomeDirectory(username); //, nativeSettings);

        if (userHome == null) {
            log.warn("There is no home directory for " + username + " is available");
        }

        // Replace '\' with '/' because when we use it in String.replaceAll
        // for some reason it removes them?
        if (userHome != null) {
            userHome = userHome.replace('\\', '/');
        }

        ServerConfiguration config = (ServerConfiguration) ConfigurationLoader
                .getConfiguration(ServerConfiguration.class);
        String authorizationFile;
        String userConfigDir = config.getUserConfigDirectory();

        // First replace any '\' with '/' (Becasue replaceAll removes them!)
        userConfigDir = userConfigDir.replace('\\', '/');

        // Replace any home directory tokens
        if ((userConfigDir.indexOf("%D") > -1) && (userHome == null)) {
            throw new IOException(
                    "<UserConfigDirectory> requires home directory, but none available for " + username);
        }

        int idx = 0;

        while ((idx = userConfigDir.indexOf("%D", idx + 1)) > -1) {
            StringBuffer buf = new StringBuffer(userConfigDir);
            buf = buf.replace(idx, idx + 1, userHome);
            userConfigDir = buf.toString();
        }

        idx = 0;

        while ((idx = userConfigDir.indexOf("%U", idx + 1)) > -1) {
            StringBuffer buf = new StringBuffer(userConfigDir);
            buf = buf.replace(idx, idx + 1, username);
            userConfigDir = buf.toString();
        }

        // Replace the '/' with File.seperator and trim
        userConfigDir = userConfigDir.replace('/', File.separatorChar).trim();

        if (!userConfigDir.endsWith(File.separator)) {
            userConfigDir += File.separator;
        }

        authorizationFile = userConfigDir + config.getAuthorizationFile();

        // Load the authorization file
        File file = new File(authorizationFile);

        if (!file.exists()) {
            log.info("authorizationFile: " + authorizationFile + " does not exist.");
            throw new IOException("authorizationFile: " + authorizationFile + " does not exist.");
        }

        FileInputStream in = new FileInputStream(file);
        Authorization keys;

        try {
            keys = new Authorization(in);
        } catch (Exception e) {
            throw new AuthenticationProtocolException("Failed to load authorized keys file " + authorizationFile);
        }

        //      SshPublicKey key = SshPublicKeyFile.parse(encoded);
        Iterator it = keys.getAuthorizedKeys().iterator();

        SshKeyPair pair = SshKeyPairFactory.newInstance(algorithm);
        SshPublicKey authorizedKey = null;
        SshPublicKey key = pair.decodePublicKey(encoded);
        boolean valid = false;
        String keyfile;

        while (it.hasNext()) {
            keyfile = (String) it.next();

            // Look for the file in the user config dir first
            file = new File(userConfigDir + keyfile);

            // If it does not exist then look absolute
            if (!file.exists()) {
                file = new File(keyfile);
            }

            if (file.exists()) {
                // Try to open the public key in the default file format
                // otherwise attempt the supported key formats
                SshPublicKeyFile pkf = SshPublicKeyFile.parse(file);
                authorizedKey = pkf.toPublicKey();

                if (authorizedKey.equals(key)) {
                    return authorizedKey;
                }
            } else {
                log.info("Failed attempt to load key file " + keyfile);
            }
        }

        throw new IOException("");
    }

    /**
     *
     *
     * @param username
     * @param algorithm
     * @param encoded
     *
     * @return
     *
     * @throws IOException
     */
    public boolean acceptKey(String username, String algorithm, byte[] encoded) throws IOException {
        try {
            getAuthorizedKey(username, algorithm, encoded);

            return true;
        } catch (Exception ex) {
            return false;
        }
    }
}