mod_authn_socache.c revision 5b0a925d0d2cfe3defeb45cd0d29126ef3603bb4
/* 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
*
*
* 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.
*/
#include "apr_strings.h"
#include "apr_md5.h" /* for apr_password_validate */
#include "ap_config.h"
#include "ap_provider.h"
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
#include "http_request.h"
#include "mod_auth.h"
#include "ap_socache.h"
#include "util_mutex.h"
#include "apr_optional.h"
typedef struct authn_cache_dircfg {
const char *context;
/* FIXME: figure out usage of socache create vs init
* I think the cache and mutex should be global
*/
static const char *const authn_cache_id = "authn-socache";
static int configured;
{
if (authn_cache_mutex) {
}
return APR_SUCCESS;
}
{
if (socache_instance) {
}
return APR_SUCCESS;
}
{
NULL, APR_LOCK_DEFAULT, 0);
if (rv != APR_SUCCESS) {
"failed to register %s mutex", authn_cache_id);
return 500; /* An HTTP status would be a misnomer! */
}
configured = 0;
return OK;
}
{
const char *errmsg;
if (!configured) {
return OK; /* don't waste the overhead of creating mutex & cache */
}
if (socache_provider == NULL) {
"Please select a socache provider with AuthnCacheSOCache "
"(no default found on this platform)");
return 500; /* An HTTP status would be a misnomer! */
}
if (rv != APR_SUCCESS) {
"failed to create %s mutex", authn_cache_id);
return 500; /* An HTTP status would be a misnomer! */
}
if (errmsg) {
return 500; /* An HTTP status would be a misnomer! */
}
&authn_cache_hints, s, pconf);
if (rv != APR_SUCCESS) {
"failed to initialise %s cache", authn_cache_id);
return 500; /* An HTTP status would be a misnomer! */
}
return OK;
}
{
const char *lock;
if (!configured) {
return; /* don't waste the overhead of creating mutex & cache */
}
if (rv != APR_SUCCESS) {
"failed to initialise mutex in child_init");
}
}
const char *arg)
{
if (socache_provider == NULL) {
errmsg = "Unknown socache provider";
}
return errmsg;
}
{
configured = 1;
return errmsg;
}
static const char *const directory = "directory";
{
return ret;
}
/* not sure we want this. Might be safer to document use-all-or-none */
{
/* preserve context and timeout if not defaults */
}
}
}
return ret;
}
const char *arg)
{
}
configured = 1;
return NULL;
}
const char *arg)
{
return NULL;
}
static const command_rec authn_cache_cmds[] =
{
/* global stuff: cache and mutex */
"socache provider for authn cache"),
"enable socache configuration in htaccess even if not enabled anywhere else"),
/* per-dir stuff */
OR_AUTHCFG, "Determine what authn providers to cache for"),
OR_AUTHCFG, "Timeout (secs) for cached credentials"),
ACCESS_CONF, "Context for authn cache"),
{NULL}
};
{
/* handle "special" context values */
/* FIXME: are we at risk of this blowing up? */
}
}
/* any other context value is literal */
}
else { /* digest auth */
}
}
const char* data)
{
const char *key;
int i;
int use_cache = 0;
/* first check whether we're cacheing for this module */
return;
}
use_cache = 1;
break;
}
}
if (!use_cache) {
return;
}
/* OK, we're on. Grab mutex to do our business */
if (APR_STATUS_IS_EBUSY(rv)) {
/* don't wait around; just abandon it */
"authn credentials for %s not cached (mutex busy)", user);
return;
}
else if (rv != APR_SUCCESS) {
"Failed to cache authn credentials for %s in %s",
return;
}
/* We have the mutex, so go ahead */
/* first build our key and determine expiry time */
/* store it */
if (rv == APR_SUCCESS) {
"Cached authn credentials for %s in %s",
}
else {
"Failed to cache authn credentials for %s in %s",
}
/* We're done with the mutex */
if (rv != APR_SUCCESS) {
}
return;
}
#define MAX_VAL_LEN 100
const char *password)
{
/* construct key
* look it up
* if found, test password
*
* mutexing here would be a big performance drag.
* It's definitely unnecessary with some backends (like ndbm or gdbm)
* Is there a risk in the general case? I guess the only risk we
* care about is a race condition that gets us a dangling pointer
* to no-longer-defined memory. Hmmm ...
*/
const char *key;
unsigned char val[MAX_VAL_LEN];
return AUTH_USER_NOT_FOUND;
}
if (APR_STATUS_IS_NOTFOUND(rv)) {
/* not found - just return */
"Authn cache: no credentials found for %s", user);
return AUTH_USER_NOT_FOUND;
}
else if (rv == APR_SUCCESS) {
/* OK, we got a value */
"Authn cache: found credentials for %s", user);
}
else {
/* error: give up and pass the buck */
/* FIXME: getting this for NOTFOUND - prolly a bug in mod_socache */
"Error accessing authentication cache");
return AUTH_USER_NOT_FOUND;
}
if (rv != APR_SUCCESS) {
return AUTH_DENIED;
}
return AUTH_GRANTED;
}
{
const char *key;
unsigned char val[MAX_VAL_LEN];
return AUTH_USER_NOT_FOUND;
}
if (APR_STATUS_IS_NOTFOUND(rv)) {
/* not found - just return */
"Authn cache: no credentials found for %s", user);
return AUTH_USER_NOT_FOUND;
}
else if (rv == APR_SUCCESS) {
/* OK, we got a value */
"Authn cache: found credentials for %s", user);
}
else {
/* error: give up and pass the buck */
/* FIXME: getting this for NOTFOUND - prolly a bug in mod_socache */
"Error accessing authentication cache");
return AUTH_USER_NOT_FOUND;
}
return AUTH_USER_FOUND;
}
static const authn_provider authn_cache_provider =
{
};
static void register_hooks(apr_pool_t *p)
{
}
{
NULL,
NULL,
};