Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

236 lines (191 sloc) 5.584 kB
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* Cherokee
*
* Authors:
* Alvaro Lopez Ortega <alvaro@alobbs.com>
*
* Copyright (C) 2001-2011 Alvaro Lopez Ortega
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "common-internal.h"
#include "http.h"
#include "validator_pam.h"
#include "connection-protected.h"
#include "plugin_loader.h"
#include <security/pam_appl.h>
/* PAM service name
*/
#define CHEROKEE_AUTH_SERVICE "cherokee"
/* Plug-in initialization
*/
PLUGIN_INFO_VALIDATOR_EASIEST_INIT (pam, http_auth_basic);
ret_t
cherokee_validator_pam_configure (cherokee_config_node_t *conf,
cherokee_server_t *srv,
cherokee_module_props_t **props)
{
UNUSED(conf);
UNUSED(srv);
UNUSED(props);
return ret_ok;
}
ret_t
cherokee_validator_pam_new (cherokee_validator_pam_t **pam,
cherokee_module_props_t *props)
{
CHEROKEE_NEW_STRUCT(n,validator_pam);
/* Init
*/
cherokee_validator_init_base (VALIDATOR(n), VALIDATOR_PROPS(props), PLUGIN_INFO_VALIDATOR_PTR(pam));
VALIDATOR(n)->support = http_auth_basic;
MODULE(n)->free = (module_func_free_t) cherokee_validator_pam_free;
VALIDATOR(n)->check = (validator_func_check_t) cherokee_validator_pam_check;
VALIDATOR(n)->add_headers = (validator_func_add_headers_t) cherokee_validator_pam_add_headers;
*pam = n;
return ret_ok;
}
ret_t
cherokee_validator_pam_free (cherokee_validator_pam_t *pam)
{
cherokee_validator_free_base (VALIDATOR(pam));
return ret_ok;
}
/*
* auth_pam_talker: supply authentication information to PAM when asked
*
* Assumptions:
* A password is asked for by requesting input without echoing
* A username is asked for by requesting input _with_ echoing
*
*/
static int
auth_pam_talker (int num_msg,
const struct pam_message **msg,
struct pam_response **resp,
void *appdata_ptr)
{
unsigned short i = 0;
struct pam_response *response = NULL;
cherokee_connection_t *conn = CONN(appdata_ptr);
/* parameter sanity checking
*/
if (!resp || !msg || !conn) {
return PAM_CONV_ERR;
}
/* allocate memory to store response
*/
response = malloc (num_msg * sizeof(struct pam_response));
if (!response) {
return PAM_CONV_ERR;
}
/* copy values
*/
for (i = 0; i < num_msg; i++) {
/* initialize to safe values
*/
response[i].resp_retcode = 0;
response[i].resp = 0;
/* select response based on requested output style
*/
switch (msg[i]->msg_style) {
case PAM_PROMPT_ECHO_ON:
response[i].resp = strdup(conn->validator->user.buf);
break;
case PAM_PROMPT_ECHO_OFF:
response[i].resp = strdup(conn->validator->passwd.buf);
break;
default:
if (response)
free(response);
return PAM_CONV_ERR;
}
}
/* everything okay, set PAM response values
*/
*resp = response;
return PAM_SUCCESS;
}
ret_t
cherokee_validator_pam_check (cherokee_validator_pam_t *pam,
cherokee_connection_t *conn)
{
int ret;
pam_handle_t *pamhandle = NULL;
struct pam_conv pamconv = {&auth_pam_talker, conn};
extern int _pam_dispatch (pam_handle_t *, int, int);
UNUSED(pam);
/* Start the PAM query
*/
ret = pam_start (CHEROKEE_AUTH_SERVICE, conn->validator->user.buf, &pamconv, &pamhandle);
if (ret != PAM_SUCCESS) {
conn->error_code = http_internal_error;
return ret_error;
}
/* Try to authenticate user:
*/
#ifdef HAVE_PAM_FAIL_DELAY
ret = pam_fail_delay (pamhandle, 0);
if (ret != PAM_SUCCESS) {
LOG_ERROR_S (CHEROKEE_ERROR_VALIDATOR_PAM_DELAY);
conn->error_code = http_internal_error;
return ret_error;
}
ret = pam_authenticate (pamhandle, 0);
#elif defined(HAVE_PAM_DISPATCH)
/* If you can't set the delay to zero, you try to call one of
* the PAM internal functions. It is nasty, but reached this
* point it's the only thing you can do.
*
* Parameters: The second one, 0, are the flags. The third
* means PAM_AUTHENTICATE
*/
ret = _pam_dispatch (pamhandle, 0, 1);
#else
/* If it fails, it will probably block
*/
ret = pam_authenticate (pamhandle, 0);
#endif
if (ret != PAM_SUCCESS) {
LOG_ERROR (CHEROKEE_ERROR_VALIDATOR_PAM_AUTH,
conn->validator->user.buf,
pam_strerror(pamhandle, ret));
goto unauthorized;
}
/* Check that the account is healthy
*/
ret = pam_acct_mgmt (pamhandle, PAM_DISALLOW_NULL_AUTHTOK);
if (ret != PAM_SUCCESS) {
LOG_ERROR (CHEROKEE_ERROR_VALIDATOR_PAM_ACCOUNT,
conn->validator->user.buf,
pam_strerror(pamhandle, ret));
goto unauthorized;
}
pam_end (pamhandle, PAM_SUCCESS);
return ret_ok;
unauthorized:
pam_end (pamhandle, PAM_SUCCESS);
return ret_error;
}
ret_t
cherokee_validator_pam_add_headers (cherokee_validator_pam_t *pam,
cherokee_connection_t *conn,
cherokee_buffer_t *buf)
{
UNUSED(pam);
UNUSED(conn);
UNUSED(buf);
return ret_ok;
}
Jump to Line
Something went wrong with that request. Please try again.