/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/* $Rev$ $Date$ */

/**
 * HTTPD module for Tuscany Open authentication.
 *
 * This module allows multiple authentication mechanisms to co-exist in a
 * single Web site:
 * - OAuth1 using Tuscany's mod-tuscany-oauth1
 * - OAuth2 using Tuscany's mod-tuscany-oauth2
 * - OpenID using mod_auth_openid
 * - Form-based using HTTPD's mod_auth_form
 * - SSL certificate using SSLFakeBasicAuth and mod_auth_basic
 */

#include <sys/stat.h>

#define WANT_HTTPD_LOG 1
#include "string.hpp"
#include "stream.hpp"
#include "list.hpp"
#include "tree.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "httpd.hpp"
#include "http.hpp"
#include "openauth.hpp"


extern "C" {
extern module AP_MODULE_DECLARE_DATA mod_tuscany_openauth;
}

namespace tuscany {
namespace openauth {

/**
 * Server configuration.
 */
class ServerConf {
public:
    ServerConf(apr_pool_t* const p, server_rec* const s) : p(p), server(s) {
    }

    const gc_pool p;
    server_rec* const server;
};

/**
 * Authentication provider configuration.
 */
class AuthnProviderConf {
public:
    AuthnProviderConf() : name(), provider(NULL) {
    }
    AuthnProviderConf(const string name, const authn_provider* const provider) : name(name), provider(provider) {
    }

    const string name;
    const authn_provider* const provider;
};

/**
 * Directory configuration.
 */
class DirConf {
public:
    DirConf(apr_pool_t* const p, const char* d) : p(p), dir(d), enabled(false), login(emptyString) {
    }

    const gc_pool p;
    const char* const dir;
    bool enabled;
    gc_mutable_ref<string> login;
    gc_mutable_ref<list<AuthnProviderConf> > apcs;
};

#ifdef WANT_MAINTAINER_LOG

/**
 * Log session entries.
 */
int debugSessionEntry(unused void* r, const char* const key, const char* const value) {
    cdebug << "  session key: " << key << ", value: " << value << endl;
    return 1;
}

const bool debugSession(request_rec* const r, const session_rec* const z) {
    apr_table_do(debugSessionEntry, r, z->entries, NULL);
    return true;
}

#define debug_authSession(r, z) if(debug_islogging()) openauth::debugSession(r, z)

#else

#define debug_authSession(r, z)

#endif

/**
 * Session hook functions.
 */
static int (*ap_session_load_fn) (request_rec * r, session_rec ** z) = NULL;
static apr_status_t (*ap_session_get_fn) (request_rec * r, session_rec * z, const char *key, const char **value) = NULL;
static apr_status_t (*ap_session_set_fn)(request_rec * r, session_rec * z, const char *key, const char *value) = NULL;

/**
 * Run the authnz hooks to authenticate a request.
 */
const failable<int> checkAuthnzProviders(const string& user, const string& pw, request_rec* const r, const list<AuthnProviderConf>& apcs) {
    if(isNil(apcs))
        return mkfailure<int>("Authentication failure for: " + user, HTTP_UNAUTHORIZED);
    const AuthnProviderConf apc = car<AuthnProviderConf>(apcs);
    if(apc.provider == NULL || !apc.provider->check_password)
        return checkAuthnzProviders(user, pw, r, cdr(apcs));

    apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, c_str(apc.name));
    const authn_status auth_result = apc.provider->check_password(r, c_str(user), c_str(pw));
    apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE);
    if(auth_result != AUTH_GRANTED)
        return checkAuthnzProviders(user, pw, r, cdr(apcs));
    return OK;
}

const failable<int> checkAuthnz(const string& user, const string& pw, request_rec* const r, const DirConf& dc) {
    if(substr(user, 0, 1) == "/" && pw == "password")
        return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED);

    if(isNil((const list<AuthnProviderConf>)dc.apcs)) {
        const authn_provider* provider = (const authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION);
        return checkAuthnzProviders(user, pw, r, mklist<AuthnProviderConf>(AuthnProviderConf(AUTHN_DEFAULT_PROVIDER, provider)));
    }
    return checkAuthnzProviders(user, pw, r, dc.apcs);
}

/**
 * Return the user info from a form auth encrypted session cookie.
 */
const failable<value> userInfoFromSession(const string& realm, request_rec* const r) {
    debug("modopenauth::userInfoFromSession");
    session_rec *z = NULL;
    ap_session_load_fn(r, &z);
    if(z == NULL)
        return mkfailure<value>("Couldn't retrieve user session", HTTP_UNAUTHORIZED);
    debug_authSession(r, z);

    const char* user = NULL;
    ap_session_get_fn(r, z, c_str(realm + "-user"), &user);
    if(user == NULL)
        return mkfailure<value>("Couldn't retrieve user id", HTTP_UNAUTHORIZED);
    const char* pw = NULL;
    ap_session_get_fn(r, z, c_str(realm + "-pw"), &pw);
    if(pw == NULL)
        return mkfailure<value>("Couldn't retrieve password", HTTP_UNAUTHORIZED);
    return value(mklist<value>(mklist<value>("realm", realm), mklist<value>("id", string(user)), mklist<value>("password", string(pw))));
}

/**
 * Return the user info from a form auth session cookie.
 */
const failable<value> userInfoFromCookie(const value& sid, const string& realm, request_rec* const r) {
    const list<value> info = httpd::queryArgs(sid);
    debug(info, "modopenauth::userInfoFromCookie::info");
    const list<value> user = assoc<value>(realm + "-user", info);
    if(isNil(user))
        return userInfoFromSession(realm, r);
    const list<value> pw = assoc<value>(realm + "-pw", info);
    if(isNil(pw))
        return mkfailure<value>("Couldn't retrieve password", HTTP_UNAUTHORIZED);
    return value(mklist<value>(mklist<value>("realm", realm), mklist<value>("id", cadr(user)), mklist<value>("password", cadr(pw))));
}

/**
 * Return the user info from a basic auth header.
 */
const failable<value> userInfoFromHeader(const char* header, const string& realm, request_rec* const r) {
    debug(header, "modopenauth::userInfoFromHeader::header");
    if(strcasecmp(ap_getword(r->pool, &header, ' '), "Basic"))
        return mkfailure<value>("Wrong authentication scheme", HTTP_UNAUTHORIZED);

    while (apr_isspace(*header))
        header++;
    char *decoded_line = (char*)apr_palloc(r->pool, apr_base64_decode_len(header) + 1);
    int length = apr_base64_decode(decoded_line, header);
    decoded_line[length] = '\0';

    const string user(ap_getword_nulls(r->pool, const_cast<const char**>(&decoded_line), ':'));
    const string pw(decoded_line);

    return value(mklist<value>(mklist<value>("realm", realm), mklist<value>("id", user), mklist<value>("password", pw)));
}

/**
 * Handle an authenticated request.
 */
const failable<int> authenticated(const list<value>& info, request_rec* const r) {
    debug(info, "modopenauth::authenticated::info");

    // Store user info in the request
    const list<value> realm = assoc<value>("realm", info);
    if(isNil(realm) || isNil(cdr(realm)))
        return mkfailure<int>("Couldn't retrieve realm", HTTP_UNAUTHORIZED);
    apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "REALM"), apr_pstrdup(r->pool, c_str(cadr(realm))));

    const list<value> id = assoc<value>("id", info);
    if(isNil(id) || isNil(cdr(id)))
        return mkfailure<int>("Couldn't retrieve user id", HTTP_UNAUTHORIZED);
    r->user = apr_pstrdup(r->pool, c_str(cadr(id)));

    apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "NICKNAME"), apr_pstrdup(r->pool, c_str(cadr(id))));
    return OK;
}

/**
 * Check user authentication.
 */
static int checkAuthn(request_rec* const r) {
    const gc_scoped_pool sp(r->pool);

    // Decline if we're not enabled or AuthType is not set to Open
    const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
    if(!dc.enabled)
        return DECLINED;
    const char* atype = ap_auth_type(r);
    debug_httpdRequest(r, "modopenauth::checkAuthn::input");
    debug(atype, "modopenauth::checkAuthn::auth_type");
    if(atype == NULL || strcasecmp(atype, "Open"))
        return DECLINED;
    debug(atype, "modopenauth::checkAuthn::auth_type");

    // Get the request args
    const list<value> args = httpd::queryArgs(r);

    // Get session id from the request
    const maybe<string> sid = sessionID(r, "TuscanyOpenAuth");
    if(hasContent(sid)) {
        // Decline if the session id was not created by this module
        const string stype = substr(content(sid), 0, 7);
        if(stype == "OAuth2_" || stype == "OAuth1_" || stype == "OpenID_")
            return DECLINED;

        // Retrieve the auth realm
        const char* aname = ap_auth_name(r);
        if(aname == NULL)
            return reportStatus(mkfailure<int>("Missing AuthName", HTTP_UNAUTHORIZED), dc.login, nilValue, r);

        // Extract user info from the session id
        const failable<value> userinfo = userInfoFromCookie(content(sid), aname, r);
        if(hasContent(userinfo)) {

            // Try to authenticate the request
            const value uinfo = content(userinfo);
            const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", uinfo)), cadr(assoc<value>("password", uinfo)), r, dc);
            if(!hasContent(authz)) {

                // Authentication failed, redirect to login page
                r->ap_auth_type = const_cast<char*>(atype);
                return reportStatus(authz, dc.login, 1, r);
            }

            // Successfully authenticated, store the user info in the request
            r->ap_auth_type = const_cast<char*>(atype);
            return reportStatus(authenticated(uinfo, r), dc.login, nilValue, r);
        }
    }

    // Get basic auth header from the request
    const char* const header = apr_table_get(r->headers_in, (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization" : "Authorization");
    if(header != NULL) {

        // Retrieve the auth realm
        const char* const aname = ap_auth_name(r);
        if(aname == NULL)
            return reportStatus(mkfailure<int>("Missing AuthName", HTTP_UNAUTHORIZED), dc.login, nilValue, r);

        // Extract user info from the session id
        const failable<value> info = userInfoFromHeader(header, aname, r);
        if(hasContent(info)) {

            // Try to authenticate the request
            const value uinfo = content(info);
            const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", uinfo)), cadr(assoc<value>("password", uinfo)), r, dc);
            if(!hasContent(authz)) {

                // Authentication failed, redirect to login page
                r->ap_auth_type = const_cast<char*>(atype);
                return reportStatus(authz, dc.login, 1, r);
            }

            // Successfully authenticated, store the user info in the request
            r->ap_auth_type = const_cast<char*>(atype);
            return reportStatus(authenticated(uinfo, r), dc.login, nilValue, r);
        }
    }

    // Decline if the request is for another authentication provider
    if(!isNil(assoc<value>("openid_identifier", args)))
        return DECLINED;

    // Redirect to the login page, unless we have a session id from another module
    if(hasContent(sessionID(r, "TuscanyOpenIDAuth")) ||
        hasContent(sessionID(r, "TuscanyOAuth1")) ||
        hasContent(sessionID(r, "TuscanyOAuth2")))
        return DECLINED;

    r->ap_auth_type = const_cast<char*>(atype);
    return httpd::reportStatus(login(dc.login, nilValue, nilValue, r));
}

/**
 * Load the auth session cookie from the request.
 */
static int sessionCookieLoad(request_rec* const r, session_rec** const z) {
    const gc_scoped_pool sp(r->pool);

    const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
    if(!dc.enabled)
        return DECLINED;

    // First look in the notes
    const char* const note = apr_pstrcat(r->pool, "mod_openauth", "TuscanyOpenAuth", NULL);
    session_rec* zz = (session_rec*)(void*)apr_table_get(r->notes, note);
    if(zz != NULL) {
        *z = zz;
        return OK;
    }

    // Parse the cookie
    const maybe<string> sid = openauth::sessionID(r, "TuscanyOpenAuth");

    // Create a new session
    zz = (session_rec*)apr_pcalloc(r->pool, sizeof(session_rec));
    zz->pool = r->pool;
    zz->entries = apr_table_make(r->pool, 10);
    zz->encoded = hasContent(sid)? c_str(content(sid)) : NULL;
    zz->uuid = (apr_uuid_t *) apr_pcalloc(r->pool, sizeof(apr_uuid_t));
    *z = zz;

    // Store it in the notes
    apr_table_setn(r->notes, note, (char*)zz);

    return OK;
}

/**
 * Save the auth session cookie in the response.
 */
static int sessionCookieSave(request_rec* const r, session_rec* const z) {
    const gc_scoped_pool sp(r->pool);

    const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
    if(!dc.enabled)
        return DECLINED;
    if(z->encoded == NULL || *(z->encoded) == '\0') {
        const maybe<string> sid = sessionID(r, "TuscanyOpenAuth");
        if(!hasContent(sid))
            return OK;
    }

    debug(c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))), "modopenauth::sessioncookiesave::setcookie");
    apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))));
    return OK;
}

/**
 * Logout request handler.
 */
int logoutHandler(request_rec* const r) {
    if(r->handler == NULL || strcmp(r->handler, "mod_tuscany_openauth_logout"))
        return DECLINED;

    const gc_scoped_pool sp(r->pool);
    debug_httpdRequest(r, "modopenauth::handler::input");
    const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth);
    if(!dc.enabled)
        return DECLINED;

    // Clear the current session
    if(hasContent(sessionID(r, "TuscanyOpenAuth"))) {
        const char* const authname = ap_auth_name(r);
        session_rec* z = NULL;
        ap_session_load_fn(r, &z);
        if(z != NULL && authname != NULL) {
            ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-user", NULL), NULL);
            ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-pw", NULL), NULL);
            ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-site", NULL), NULL);
        } else
            apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", emptyString, httpd::hostName(r))));
    }
    if(hasContent(sessionID(r, "TuscanyOpenIDAuth")))
        apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenIDAuth", emptyString, httpd::hostName(r))));
    if(hasContent(sessionID(r, "TuscanyOAuth1")))
        apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOAuth1", emptyString, httpd::hostName(r))));
    if(hasContent(sessionID(r, "TuscanyOAuth2")))
        apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOAuth2", emptyString, httpd::hostName(r))));

    // Redirect to the login page
    return httpd::reportStatus(login(dc.login, "/", nilValue, r));
}

/**
 * Process the module configuration.
 */
int postConfigMerge(const ServerConf& mainsc, server_rec* const s) {
    if(s == NULL)
        return OK;
    debug(httpd::serverName(s), "modopenauth::postConfigMerge::serverName");

    return postConfigMerge(mainsc, s->next);
}

int postConfig(apr_pool_t* const p, unused apr_pool_t* const plog, unused apr_pool_t* const ptemp, server_rec* const s) {
    const gc_scoped_pool sp(p);

    const ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_openauth);
    debug(httpd::serverName(s), "modopenauth::postConfig::serverName");

    // Retrieve session hook functions
    if(ap_session_load_fn == NULL)
        ap_session_load_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_load);
    if(ap_session_get_fn == NULL)
        ap_session_get_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_get);
    if(ap_session_set_fn == NULL)
        ap_session_set_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_set);

    // Merge server configurations
    return postConfigMerge(sc, s);
}

/**
 * Child process initialization.
 */
void childInit(apr_pool_t* const p, server_rec* const s) {
    const gc_scoped_pool sp(p);

    const ServerConf* const psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_openauth);
    if(psc == NULL) {
        cfailure << "[Tuscany] Due to one or more errors mod_tuscany_openauth loading failed. Causing apache to stop loading." << endl;
        exit(APEXIT_CHILDFATAL);
    }
    const ServerConf& sc = *psc;

    // Merge the updated configuration into the virtual hosts
    postConfigMerge(sc, s->next);
}

/**
 * Configuration commands.
 */
char* confEnabled(cmd_parms* cmd, void *c, const int arg) {
    const gc_scoped_pool sp(cmd->pool);
    DirConf& dc = httpd::dirConf<DirConf>(c);
    dc.enabled = (bool)arg;
    return NULL;
}
char* confLogin(cmd_parms *cmd, void *c, const char* arg) {
    const gc_scoped_pool sp(cmd->pool);
    DirConf& dc = httpd::dirConf<DirConf>(c);
    dc.login = arg;
    return NULL;
}
char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) {
    const gc_scoped_pool sp(cmd->pool);
    DirConf& dc = httpd::dirConf<DirConf>(c);

    // Lookup and cache the Authn provider
    const authn_provider* provider = (authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, arg, AUTHN_PROVIDER_VERSION);
    if(provider == NULL)
        return apr_psprintf(cmd->pool, "Unknown Authn provider: %s", arg);
    if(!provider->check_password)
        return apr_psprintf(cmd->pool, "The '%s' Authn provider doesn't support password authentication", arg);
    dc.apcs = append<AuthnProviderConf>(dc.apcs, mklist<AuthnProviderConf>(AuthnProviderConf(arg, provider)));
    return NULL;
}

/**
 * HTTP server module declaration.
 */
const command_rec commands[] = {
    AP_INIT_ITERATE("AuthOpenAuthProvider", (const char*(*)())confAuthnProvider, NULL, OR_AUTHCFG, "Auth providers for a directory or location"),
    AP_INIT_FLAG("AuthOpenAuth", (const char*(*)())confEnabled, NULL, OR_AUTHCFG, "Tuscany Open Auth authentication On | Off"),
    AP_INIT_TAKE1("AuthOpenAuthLoginPage", (const char*(*)())confLogin, NULL, OR_AUTHCFG, "Tuscany Open Auth login page"),
    {NULL, NULL, NULL, 0, NO_ARGS, NULL}
};

void registerHooks(unused apr_pool_t *p) {
    ap_hook_post_config(postConfig, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_child_init(childInit, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_check_authn(checkAuthn, NULL, NULL, APR_HOOK_MIDDLE, AP_AUTH_INTERNAL_PER_CONF);
    ap_hook_session_load(sessionCookieLoad, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_session_save(sessionCookieSave, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_handler(logoutHandler, NULL, NULL, APR_HOOK_MIDDLE);
}

}
}

extern "C" {

module AP_MODULE_DECLARE_DATA mod_tuscany_openauth = {
    STANDARD20_MODULE_STUFF,
    // dir config and merger
    tuscany::httpd::makeDirConf<tuscany::openauth::DirConf>, NULL,
    // server config and merger
    tuscany::httpd::makeServerConf<tuscany::openauth::ServerConf>, NULL,
    // commands and hooks
    tuscany::openauth::commands, tuscany::openauth::registerHooks
};

}
