hd3gtv.mydmam.auth.AuthenticationBackend.java Source code

Java tutorial

Introduction

Here is the source code for hd3gtv.mydmam.auth.AuthenticationBackend.java

Source

/*
 * This file is part of MyDMAM.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * 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 Lesser General Public License for more details.
 * 
 * Copyright (C) hdsdi3g for hd3g.tv 2014
 * 
*/

package hd3gtv.mydmam.auth;

import hd3gtv.configuration.Configuration;
import hd3gtv.log2.Log2;
import hd3gtv.log2.Log2Dump;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Random;

import models.ACLUser;

import org.apache.commons.net.util.Base64;

public class AuthenticationBackend {

    static {
        try {
            refreshConfiguration();
        } catch (Exception e) {
            Log2.log.error("Error with loading authentication configuration", e);
        }
    }

    private static List<Authenticator> authenticators;
    private static List<String> authenticators_domains;
    private static boolean force_select_domain;

    public static void refreshConfiguration() throws Exception {
        if (Configuration.global.isElementExists("auth") == false) {
            throw new NullPointerException("Can't found \"auth\" element in configuration");
        }
        if (Configuration.global.isElementKeyExists("auth", "backend") == false) {
            throw new NullPointerException("Can't found \"auth/backend\" element in configuration");
        }

        List<LinkedHashMap<String, ?>> elements = Configuration.global.getListMapValues("auth", "backend");

        if (elements == null) {
            throw new NullPointerException("No items for \"auth/backend\" element in configuration");
        }

        force_select_domain = Configuration.global.getValueBoolean("auth", "force_select_domain");

        authenticators = new ArrayList<Authenticator>(elements.size());
        authenticators_domains = new ArrayList<String>(elements.size());

        LinkedHashMap<String, ?> configuration_element;
        File auth_file;
        for (int pos = 0; pos < elements.size(); pos++) {
            configuration_element = elements.get(pos);
            String element_source = (String) configuration_element.get("source");
            if (element_source.equals("local")) {
                String path = (String) configuration_element.get("path");

                auth_file = new File(path);
                if (auth_file.exists() == false) {
                    if (auth_file.isAbsolute() == false) {
                        if (auth_file.getParentFile().getName().equals("conf") & Configuration
                                .getGlobalConfigurationDirectory().getParentFile().getName().equals("conf")) {
                            /**
                             * SQLite file is located in Play conf directory, and Play /app.d/ is also located in conf directory.
                             * We consider that conf directory is the same.
                             */
                            auth_file = new File(Configuration.getGlobalConfigurationDirectory().getParent()
                                    + File.separator + auth_file.getName());
                        }
                    }
                }
                if (auth_file.exists() == false) {
                    throw new FileNotFoundException(path);
                }

                String masterkey = (String) configuration_element.get("masterkey");
                authenticators.add(new AuthenticatorLocalsqlite(auth_file, masterkey));

                String label = (String) configuration_element.get("label");
                authenticators_domains.add(label);
            } else if (element_source.equals("ad")) {
                String domain = (String) configuration_element.get("domain");
                String server = (String) configuration_element.get("server");
                int port = (Integer) configuration_element.get("port");
                authenticators.add(new AuthenticatorActivedirectory(domain, server, port));

                authenticators_domains.add(domain);
            } else {
                Log2.log.error("Can't import \"auth/backend\" " + (pos + 1) + " configuration item", null,
                        new Log2Dump("item", configuration_element.toString()));
            }
        }

        if (authenticators.isEmpty()) {
            throw new NullPointerException("No authentication backend is correctly set");
        }
    }

    public static boolean isForce_select_domain() {
        return force_select_domain;
    }

    public static List<String> getAuthenticators_domains() {
        return authenticators_domains;
    }

    public static List<Authenticator> getAuthenticators() {
        return authenticators;
    }

    /**
     * Try to get User with authenticator or throws exception
     */
    public static AuthenticationUser authenticate(Authenticator authenticator, String username, String password)
            throws InvalidAuthenticatorUserException {
        if (authenticator == null) {
            throw new NullPointerException("\"authenticator\" can't to be null");
        }
        if (username == null) {
            throw new NullPointerException("\"username\" can't to be null");
        }
        if (password == null) {
            throw new NullPointerException("\"password\" can't to be null");
        }

        AuthenticationUser authenticationUser;
        Log2Dump dump;
        dump = new Log2Dump();
        dump.add("username", username);
        dump.addAll(authenticator);
        try {
            authenticationUser = authenticator.getUser(username, password);
            if (authenticationUser != null) {
                Log2.log.debug("Valid user found for this authentication method", dump);
                return authenticationUser;
            }
        } catch (IOException e) {
            Log2.log.error("Invalid authentication method", e, dump);
        }
        return null;
    }

    /**
     * Try to get User, authenticator after authenticator, until it found a correct user or throws exception
     */
    public static AuthenticationUser authenticate(String username, String password)
            throws InvalidAuthenticatorUserException {
        AuthenticationUser authenticationUser;
        Log2Dump dump = new Log2Dump();
        for (int pos = 0; pos < authenticators.size(); pos++) {
            try {
                dump = new Log2Dump();
                dump.add("authenticator", authenticators.get(pos));

                authenticationUser = authenticate(authenticators.get(pos), username, password);
                if (authenticationUser != null) {
                    return authenticationUser;
                }
            } catch (InvalidAuthenticatorUserException e) {
                dump.add("cause", e.getMessage());
                if (e.getCause() != null) {
                    dump.add("from", e.getCause().getMessage());
                }
                Log2.log.debug("Invalid user for this authentication method", dump);
            }
        }
        throw new InvalidAuthenticatorUserException("Can't authenticate with " + username);
    }

    public static void checkFirstPlayBoot() throws Exception {
        if (authenticators == null) {
            throw new NullPointerException("No backend");
        }
        if (authenticators.size() == 0) {
            throw new NullPointerException("No backend");
        }
        if ((authenticators.get(0) instanceof AuthenticatorLocalsqlite) == false) {
            /**
             * Admin has set a configuration : no need to setup a first boot
             */
            return;
        }
        AuthenticatorLocalsqlite authenticatorlocalsqlite = (AuthenticatorLocalsqlite) authenticators.get(0);
        if (authenticatorlocalsqlite.isUserExists(ACLUser.ADMIN_NAME) == false) {
            String newpassword = passwordGenerator();
            authenticatorlocalsqlite.createUser(ACLUser.ADMIN_NAME, newpassword, "Local Admin", true);

            File textfile = new File("play-new-password.txt");
            FileWriter fw = new FileWriter(textfile, false);
            fw.write("Admin login: " + ACLUser.ADMIN_NAME + "\r\n");
            fw.write("Admin password: " + newpassword + "\r\n");
            fw.write("\r\n");
            fw.write("You should remove this file after keeping this password..\r\n");
            fw.write("\r\n");
            fw.write("You can change this password with mydmam-cli:\r\n");
            fw.write("$ mydmam-cli localauth -f " + authenticatorlocalsqlite.getDbfile().getAbsolutePath()
                    + " -key " + authenticatorlocalsqlite.getMaster_password_key() + " -passwd -u "
                    + ACLUser.ADMIN_NAME + "\r\n");
            fw.write("\r\n");
            fw.write(
                    "Note: you haven't need a local authenticator if you set another backend and if you grant some new administrators\r\n");
            fw.close();

            Log2Dump dump = new Log2Dump();
            dump.add("login", ACLUser.ADMIN_NAME);
            dump.add("password file", textfile.getAbsoluteFile());
            dump.add("local database", authenticatorlocalsqlite.getDbfile());
            Log2.log.security("Create Play administrator account", dump);

        } else if (authenticatorlocalsqlite.isEnabledUser(ACLUser.ADMIN_NAME) == false) {
            throw new Exception("User " + ACLUser.ADMIN_NAME + " is disabled in sqlite file !");
        }

    }

    /**
     * @return 12 first chars of Base64(SHA-264(random(1024b)))
     */
    public static String passwordGenerator() throws NoSuchAlgorithmException, NoSuchProviderException {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        Random r = new Random();
        byte[] fill = new byte[1024];
        r.nextBytes(fill);
        byte[] key = md.digest(fill);
        return new String(Base64.encodeBase64String(key)).substring(0, 12);
    }

}