#!/usr/local/bin/php
<?php
/**
 *    Copyright (C) 2015 Deciso B.V.
 *
 *    All rights reserved.
 *
 *    Redistribution and use in source and binary forms, with or without
 *    modification, are permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 *    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 *    AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *    AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 *    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *    POSSIBILITY OF SUCH DAMAGE.
 *
 */

require_once("config.inc");
require_once("auth.inc");

openlog("squid", LOG_ODELAY, LOG_AUTH);

$authFactory = new \OPNsense\Auth\AuthenticationFactory();

$f = fopen("php://stdin", "r");
while (!(feof($f))) {
    $line = fgets($f);
    if ($line) {
        $fields = explode(' ', trim($line));
        $username = rawurldecode($fields[0]);
        $password = rawurldecode($fields[1]);

        $isAuthenticated = false;
        if (isset($config['OPNsense']['proxy']['forward']['authentication']['method'])) {
            foreach (explode(',', $config['OPNsense']['proxy']['forward']['authentication']['method']) as $authServerName) {
                $authServer = $authFactory->get(trim($authServerName));
                if ($authServer == null) {
                    // authenticator not found, use local
                    $authServer = $authFactory->get('Local Database');
                }
                $isAuthenticated = $authServer->authenticate($username, $password);
                if ($isAuthenticated) {
                    if (get_class($authServer) == "OPNsense\Auth\Local") {
                        // todo: user priv check needs a reload of squid, maybe it's better to move the token check to
                        //       the auth object.
                        //
                        // when using local authentication, check if user has role user-proxy-auth
                        $user = getUserEntry($username);
                        if (is_array($user) && userHasPrivilege($user, "user-proxy-auth")) {
                            break;
                        } else {
                            // log user auth failure
                            syslog(LOG_WARNING, "user '{$username}' cannot authenticate for squid because of missing user-proxy-auth role");
                            fwrite(STDOUT, "ERR\n");
                            $isAuthenticated = false;
                        }
                    } else {
                        break;
                    }
                }
            }
        }

        if ($isAuthenticated) {
            syslog(LOG_NOTICE, "user '{$username}' authenticated\n");
            fwrite(STDOUT, "OK\n");
        } else {
            syslog(LOG_WARNING, "user '{$username}' could not authenticate.\n");
            fwrite(STDOUT, "ERR\n");
        }
    }
}

closelog();