static bool has_valid_session(request_rec *r, modauthopenid_config *s_cfg) { // test for valid session - if so, return DECLINED std::string session_id = ""; modauthopenid::get_session_id(r, std::string(s_cfg->cookie_name), session_id); if(session_id != "" && s_cfg->use_cookie) { modauthopenid::debug("found session_id in cookie: " + session_id); modauthopenid::session_t session; modauthopenid::SessionManager sm(std::string(s_cfg->db_location)); sm.get_session(session_id, session); sm.close(); // if session found if(std::string(session.identity) != "") { std::string uri_path; modauthopenid::base_dir(std::string(r->uri), uri_path); std::string valid_path(session.path); // if found session has a valid path if(valid_path == uri_path.substr(0, valid_path.size()) && apr_strnatcmp(session.hostname.c_str(), r->hostname)==0) { const char* idchar = std::string(session.identity).c_str(); APDEBUG(r, "setting REMOTE_USER to \"%s\"", idchar); r->user = apr_pstrdup(r->pool, idchar); return true; } else { APDEBUG(r, "session found for different path or hostname (cooke was for %s)", session.hostname.c_str()); } } } return false; };
static int set_session_cookie(request_rec *r, modauthopenid_config *s_cfg, opkele::params_t& params, std::string identity) { // now set auth cookie, if we're doing session based auth std::string session_id, hostname, path, cookie_value, redirect_location, args; if(s_cfg->cookie_path != NULL) path = std::string(s_cfg->cookie_path); else modauthopenid::base_dir(std::string(r->uri), path); modauthopenid::make_rstring(32, session_id); modauthopenid::make_cookie_value(cookie_value, std::string(s_cfg->cookie_name), session_id, path, s_cfg->cookie_lifespan); APDEBUG(r, "Setting cookie after authentication of user %s", identity.c_str()); apr_table_set(r->err_headers_out, "Set-Cookie", cookie_value.c_str()); hostname = std::string(r->hostname); // save session values modauthopenid::SessionManager sm(std::string(s_cfg->db_location)); sm.store_session(session_id, hostname, path, identity, s_cfg->cookie_lifespan); sm.close(); opkele::params_t ext_params; modauthopenid::get_extension_params(ext_params, params); modauthopenid::remove_openid_vars(params); modauthopenid::merge_params(ext_params, params); args = params.append_query("", "").substr(1); if(args.length() == 0) r->args = NULL; else apr_cpystrn(r->args, args.c_str(), 1024); full_uri(r, redirect_location, s_cfg); return modauthopenid::http_redirect(r, redirect_location); };
static int start_authentication_session(request_rec *r, modauthopenid_config *s_cfg, opkele::params_t& params, std::string& return_to, std::string& trust_root) { // remove all openid GET query params (openid.*) - we don't want that maintained through // the redirection process. We do, however, want to keep all other GET params. // also, add a nonce for security std::string identity = s_cfg->use_single_idp ? s_cfg->single_idp_url : params.get_param("openid_identifier"); APDEBUG(r, "identity = %s, use_single_idp = %s", identity.c_str(), s_cfg->use_single_idp ? "true" : "false"); // pull out the extension parameters before we get rid of openid.* opkele::params_t ext_params; modauthopenid::get_extension_params(ext_params, params); modauthopenid::remove_openid_vars(params); // if attribute directives are set, add AX stuff to extension params if(s_cfg->use_ax) { ext_params["openid.ns." DEFAULT_AX_NAMESPACE_ALIAS] = AX_NAMESPACE; ext_params["openid." DEFAULT_AX_NAMESPACE_ALIAS ".mode"] = "fetch_request"; std::string required = ""; bool first_alias = true; for(int i = 0; i < s_cfg->ax_attrs->nelts; ++i) { std::string alias = APR_ARRAY_IDX(s_cfg->ax_attrs, i, const char *); std::string uri = apr_table_get(s_cfg->ax_attr_uris, alias.c_str()); ext_params["openid." DEFAULT_AX_NAMESPACE_ALIAS ".type." + alias] = uri; if(first_alias) { first_alias = false; } else { required += ','; } required += alias; } ext_params["openid." DEFAULT_AX_NAMESPACE_ALIAS ".required"] = required; }
static bool is_distrusted_provider(modauthopenid_config *s_cfg, std::string url, request_rec *r) { if(apr_is_empty_array(s_cfg->distrusted)) return false; char **distrusted_sites = (char **) s_cfg->distrusted->elts; std::string base_url = modauthopenid::get_queryless_url(url); for (int i = 0; i < s_cfg->distrusted->nelts; i++) { pcre * re = modauthopenid::make_regex(distrusted_sites[i]); if(re == NULL) { APERR(r, "regex compilation failed for regex: %s", distrusted_sites[i]); } else if(modauthopenid::regex_match(base_url, re)) { APWARN(r, "%s is a distrusted (on black list) identity provider", base_url.c_str()); return true; } } APDEBUG(r, "%s is NOT a distrusted identity provider (not blacklisted)", base_url.c_str()); return false; };
static int mod_authopenid_method_handler(request_rec *r) { modauthopenid_config *s_cfg; s_cfg = (modauthopenid_config *) ap_get_module_config(r->per_dir_config, &authopenid_module); // if we're not enabled for this location/dir, decline doing anything const char *current_auth = ap_auth_type(r); if (!current_auth || strcasecmp(current_auth, "openid")) return DECLINED; // make a record of our being called APDEBUG(r, "*** %s module has been called ***", PACKAGE_STRING); // if user has a valid session, they are authorized (OK) if(has_valid_session(r, s_cfg)) return OK; // parse the get/post params opkele::params_t params; modauthopenid::get_request_params(r, params); // get our current url and trust root std::string return_to, trust_root; full_uri(r, return_to, s_cfg); if(s_cfg->trust_root == NULL) modauthopenid::base_dir(return_to, trust_root); else trust_root = std::string(s_cfg->trust_root); // if we're in SSO mode, force the openid_identifier to a specific value if(s_cfg->sso_url && !params.has_param("openid.assoc_handle")) params.set_field("openid_identifier", s_cfg->sso_url); // if user is posting id (only openid_identifier will contain a value) if(params.has_param("openid_identifier") && !params.has_param("openid.assoc_handle")) { return start_authentication_session(r, s_cfg, params, return_to, trust_root); } else if(params.has_param("openid.assoc_handle")) { // user has been redirected, authenticate them and set cookie return validate_authentication_session(r, s_cfg, params, return_to); } else { //display an input form if(params.has_param("openid.mode") && params.get_param("openid.mode") == "cancel") return show_input(r, s_cfg, modauthopenid::canceled); return show_input(r, s_cfg); } }
static int validate_authentication_session(request_rec *r, modauthopenid_config *s_cfg, opkele::params_t& params, std::string& return_to) { // make sure nonce is present if(!params.has_param("modauthopenid.nonce")) return show_input(r, s_cfg, modauthopenid::invalid_nonce); modauthopenid::MoidConsumer consumer(std::string(s_cfg->db_location), params.get_param("modauthopenid.nonce"), return_to); try { consumer.id_res(modauthopenid::modauthopenid_message_t(params)); // if no exception raised, check nonce if(!consumer.session_exists()) { consumer.close(); return show_input(r, s_cfg, modauthopenid::invalid_nonce); } // if we should be using a user specified auth program, run it to see if user is authorized if(s_cfg->use_auth_program) { std::string username = consumer.get_claimed_id(); std::string progname = std::string(s_cfg->auth_program); modauthopenid::exec_result_t eresult = modauthopenid::exec_auth(progname, username); if(eresult != modauthopenid::id_accepted) { std::string error = modauthopenid::exec_error_to_string(eresult, progname, username); APERR(r, "Error in authentication: %s", error.c_str()); consumer.close(); return show_input(r, s_cfg, modauthopenid::unauthorized); } else { APDEBUG(r, "Authenticated %s using %s", username.c_str(), progname.c_str()); } } // Make sure that identity is set to the original one given by the user (in case of delegation // this will be different than openid_identifier GET param std::string identity; if (s_cfg->sso_url && s_cfg->sso_user_base) { std::string c_identity = consumer.get_claimed_id(); if (strstr(c_identity.c_str(), s_cfg->sso_user_base) == c_identity.c_str()) { identity = strdup(c_identity.c_str() + strlen(s_cfg->sso_user_base)); } else { std::string error = "SSOUserBase didn't match in the identity"; APERR(r, "Error in authentication: %s", error.c_str()); consumer.close(); return show_input(r, s_cfg, modauthopenid::unauthorized); } } else identity = consumer.get_claimed_id(); consumer.kill_session(); consumer.close(); if(s_cfg->use_cookie) return set_session_cookie(r, s_cfg, params, identity); // if we're not setting cookie - don't redirect, just show page APERR(r, "Setting REMOTE_USER to %s", identity.c_str()); r->user = apr_pstrdup(r->pool, identity.c_str()); return DECLINED; } catch(opkele::exception &e) { APERR(r, "Error in authentication: %s", e.what()); consumer.close(); return show_input(r, s_cfg, modauthopenid::unspecified); } };