103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.security;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slack
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.security.PropertyUserStore.UserListener;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.UserIdentity;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.Scanner;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.resource.Resource;
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.security.Credential;
3003928aee4356845252ac6b662d5c72c29903813eJake Slack
3103928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
3203928aee4356845252ac6b662d5c72c29903813eJake Slack/**
3303928aee4356845252ac6b662d5c72c29903813eJake Slack * Properties User Realm.
3403928aee4356845252ac6b662d5c72c29903813eJake Slack *
3503928aee4356845252ac6b662d5c72c29903813eJake Slack * An implementation of UserRealm that stores users and roles in-memory in HashMaps.
3603928aee4356845252ac6b662d5c72c29903813eJake Slack * <P>
3703928aee4356845252ac6b662d5c72c29903813eJake Slack * Typically these maps are populated by calling the load() method or passing a properties resource to the constructor. The format of the properties file is:
3803928aee4356845252ac6b662d5c72c29903813eJake Slack *
3903928aee4356845252ac6b662d5c72c29903813eJake Slack * <PRE>
4003928aee4356845252ac6b662d5c72c29903813eJake Slack *  username: password [,rolename ...]
4103928aee4356845252ac6b662d5c72c29903813eJake Slack * </PRE>
4203928aee4356845252ac6b662d5c72c29903813eJake Slack *
4303928aee4356845252ac6b662d5c72c29903813eJake Slack * Passwords may be clear text, obfuscated or checksummed. The class com.eclipse.Util.Password should be used to generate obfuscated passwords or password
4403928aee4356845252ac6b662d5c72c29903813eJake Slack * checksums.
4503928aee4356845252ac6b662d5c72c29903813eJake Slack *
4603928aee4356845252ac6b662d5c72c29903813eJake Slack * If DIGEST Authentication is used, the password must be in a recoverable format, either plain text or OBF:.
4703928aee4356845252ac6b662d5c72c29903813eJake Slack */
4803928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class HashLoginService extends MappedLoginService implements UserListener
4903928aee4356845252ac6b662d5c72c29903813eJake Slack{
5003928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(HashLoginService.class);
5103928aee4356845252ac6b662d5c72c29903813eJake Slack
5203928aee4356845252ac6b662d5c72c29903813eJake Slack    private PropertyUserStore _propertyUserStore;
5303928aee4356845252ac6b662d5c72c29903813eJake Slack    private String _config;
5403928aee4356845252ac6b662d5c72c29903813eJake Slack    private Resource _configResource;
5503928aee4356845252ac6b662d5c72c29903813eJake Slack    private Scanner _scanner;
5603928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _refreshInterval = 0;// default is not to reload
5703928aee4356845252ac6b662d5c72c29903813eJake Slack
5803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
5903928aee4356845252ac6b662d5c72c29903813eJake Slack    public HashLoginService()
6003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
6103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
6203928aee4356845252ac6b662d5c72c29903813eJake Slack
6303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
6403928aee4356845252ac6b662d5c72c29903813eJake Slack    public HashLoginService(String name)
6503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
6603928aee4356845252ac6b662d5c72c29903813eJake Slack        setName(name);
6703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
6803928aee4356845252ac6b662d5c72c29903813eJake Slack
6903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
7003928aee4356845252ac6b662d5c72c29903813eJake Slack    public HashLoginService(String name, String config)
7103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7203928aee4356845252ac6b662d5c72c29903813eJake Slack        setName(name);
7303928aee4356845252ac6b662d5c72c29903813eJake Slack        setConfig(config);
7403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
7503928aee4356845252ac6b662d5c72c29903813eJake Slack
7603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
7703928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getConfig()
7803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7903928aee4356845252ac6b662d5c72c29903813eJake Slack        return _config;
8003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
8103928aee4356845252ac6b662d5c72c29903813eJake Slack
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
8303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void getConfig(String config)
8403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
8503928aee4356845252ac6b662d5c72c29903813eJake Slack        _config = config;
8603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
8703928aee4356845252ac6b662d5c72c29903813eJake Slack
8803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
8903928aee4356845252ac6b662d5c72c29903813eJake Slack    public Resource getConfigResource()
9003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9103928aee4356845252ac6b662d5c72c29903813eJake Slack        return _configResource;
9203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
9303928aee4356845252ac6b662d5c72c29903813eJake Slack
9403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
9503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
9603928aee4356845252ac6b662d5c72c29903813eJake Slack     * Load realm users from properties file. The property file maps usernames to password specs followed by an optional comma separated list of role names.
9703928aee4356845252ac6b662d5c72c29903813eJake Slack     *
9803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param config
9903928aee4356845252ac6b662d5c72c29903813eJake Slack     *            Filename or url of user properties file.
10003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
10103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setConfig(String config)
10203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
10303928aee4356845252ac6b662d5c72c29903813eJake Slack        _config = config;
10403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
10503928aee4356845252ac6b662d5c72c29903813eJake Slack
10603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
10703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setRefreshInterval(int msec)
10803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
10903928aee4356845252ac6b662d5c72c29903813eJake Slack        _refreshInterval = msec;
11003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11103928aee4356845252ac6b662d5c72c29903813eJake Slack
11203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11303928aee4356845252ac6b662d5c72c29903813eJake Slack    public int getRefreshInterval()
11403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11503928aee4356845252ac6b662d5c72c29903813eJake Slack        return _refreshInterval;
11603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11703928aee4356845252ac6b662d5c72c29903813eJake Slack
11803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11903928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
12003928aee4356845252ac6b662d5c72c29903813eJake Slack    protected UserIdentity loadUser(String username)
12103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12203928aee4356845252ac6b662d5c72c29903813eJake Slack        return null;
12303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
12403928aee4356845252ac6b662d5c72c29903813eJake Slack
12503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
12603928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
12703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void loadUsers() throws IOException
12803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12903928aee4356845252ac6b662d5c72c29903813eJake Slack        // TODO: Consider refactoring MappedLoginService to not have to override with unused methods
13003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
13103928aee4356845252ac6b662d5c72c29903813eJake Slack
13203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
13303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
13403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
13503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
13603928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void doStart() throws Exception
13703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13803928aee4356845252ac6b662d5c72c29903813eJake Slack        super.doStart();
13903928aee4356845252ac6b662d5c72c29903813eJake Slack
14003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_propertyUserStore == null)
14103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
14203928aee4356845252ac6b662d5c72c29903813eJake Slack            if(LOG.isDebugEnabled())
14303928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("doStart: Starting new PropertyUserStore. PropertiesFile: " + _config + " refreshInterval: " + _refreshInterval);
14403928aee4356845252ac6b662d5c72c29903813eJake Slack
14503928aee4356845252ac6b662d5c72c29903813eJake Slack            _propertyUserStore = new PropertyUserStore();
14603928aee4356845252ac6b662d5c72c29903813eJake Slack            _propertyUserStore.setRefreshInterval(_refreshInterval);
14703928aee4356845252ac6b662d5c72c29903813eJake Slack            _propertyUserStore.setConfig(_config);
14803928aee4356845252ac6b662d5c72c29903813eJake Slack            _propertyUserStore.registerUserListener(this);
14903928aee4356845252ac6b662d5c72c29903813eJake Slack            _propertyUserStore.start();
15003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
15103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
15203928aee4356845252ac6b662d5c72c29903813eJake Slack
15303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
15403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
15503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
15603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
15703928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void doStop() throws Exception
15803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
15903928aee4356845252ac6b662d5c72c29903813eJake Slack        super.doStop();
16003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_scanner != null)
16103928aee4356845252ac6b662d5c72c29903813eJake Slack            _scanner.stop();
16203928aee4356845252ac6b662d5c72c29903813eJake Slack        _scanner = null;
16303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
16403928aee4356845252ac6b662d5c72c29903813eJake Slack
16503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
16603928aee4356845252ac6b662d5c72c29903813eJake Slack    public void update(String userName, Credential credential, String[] roleArray)
16703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
16803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (LOG.isDebugEnabled())
16903928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("update: " + userName + " Roles: " + roleArray.length);
17003928aee4356845252ac6b662d5c72c29903813eJake Slack        putUser(userName,credential,roleArray);
17103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
17203928aee4356845252ac6b662d5c72c29903813eJake Slack
17303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
17403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void remove(String userName)
17503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
17603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (LOG.isDebugEnabled())
17703928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("remove: " + userName);
17803928aee4356845252ac6b662d5c72c29903813eJake Slack        removeUser(userName);
17903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
18003928aee4356845252ac6b662d5c72c29903813eJake Slack}
181