[prev in list] [next in list] [prev in thread] [next in thread]
List: pam-list
Subject: pam & apache 1.3.2
From: Ingo Luetkebohle ingo () devconsult ! de
Date: 1998-09-30 20:13:11
[Download RAW message or body]
On Wed, 30 Sep 1998, Leo Wierzbowski wrote:
> Anyone able to get the PAM module to make with Apache 1.3.2 on RedHat 5.1?
I am, which is not very surprising, since I'm the author :-)
I currently have sent a copy of a 1.3.x compatible mod_auth_pam to everyone
who asked for it. The reason its not "officially" available is because
there's no configure support and no real testing yet.
I attached a version for everyone who's interested.
--
Ingo Luetkebohle / netdancer@irc / ingo@blank.pages.de
dev/consulting Gesellschaft fuer Netzwerkentwicklung und -beratung mbH
url: http://www.devconsult.de/ - fon: 0521-1365800 - fax: 0521-1365803
["mod_auth_pam.c" (TEXT/PLAIN)]
/*
* Copyright (c) 1997,1998 Ingo Lütkebohle <ingo@blank.pages.de>
* All rights reserved.
*
*/
/*
* v 0.6 from 25-Sep-98
*
* mod_auth_pam:
* basic authentication against pluggable authentication module lib
*
* For information about PAM, please refer to
* http://parc.power.net/morgan/Linux-PAM/
*
* For recent versions of this file and other information refer to
* http://blank.pages.de/pam/
*
* Author: Ingo Lütkebohle <ingo@blank.pages.de>
* based upon mod_auth.c
*
* Changes:
* 25-Sep-98: replaced pwdb groups routine with standard C
* 19-Oct-97: made module fall through (if configured to do so),
* even when a user of the given name is found in the PAM
* databases
* 17-Apr-97: fixed segfault that occured when Apache couldn't look
* up the remote host name
* removed annoying compiler warnings
*
* 05-Apr-97: made fall-through configurable with AuthPAM_Authorative
*
* 25-Mar-97: added support for transparent fall-through to other auth
* modules with configurable fail delays
* added acct_mgmt hook
* added group support (through libpwdb)
*
* usage information:
*
* 1. Configuration:
* Module pam_auth_module mod_auth_pam.o
* EXTRA_LIBS+= -lpam -ldl
*
* 2. Add an auth and an account entry for service type "httpd"
* to your PAM configuration
*
*
* configuration directives:
* AuthFailDelay <msecs>
* number of mili-seconds to wait after a
* failed authentication attempt. this is
* a minimum value and may have been
* increased by other pam apps.
* defaults to 0
*
* AuthPAM_Authorative on|off
* If off, mod_auth_pam will DECLINE if it
* can't authenticate the user. this will
* enable other authentication modules to
* have a try.
* defaults to on. Only change this if
* you know what you are doing!
*
*/
#include <unistd.h>
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
#include <security/pam_appl.h>
#define PAM_STRE_NEEDS_PAMH 1
module pam_auth_module;
static const char
*pam_servicename = "httpd",
*valid_user = "valid-user";
typedef struct {
char *name, *pw;
} auth_pam_userinfo;
/*
* configuration directive handling
*/
typedef struct {
int fail_delay, is_authorative;
} auth_pam_dir_config;
void* create_auth_pam_dir_config(pool *p, char *dummy)
{
auth_pam_dir_config *new =
(auth_pam_dir_config*) ap_palloc (p, sizeof(auth_pam_dir_config));
new->fail_delay = 0; /* 0 ms */
new->is_authorative = 1; /* on */
return new;
}
char* auth_fail_delay(cmd_parms *cmd, auth_pam_dir_config *config, char *secs)
{
if(secs)
config->fail_delay = atoi(secs);
return NULL;
}
char* auth_fall_through(cmd_parms *cmd, auth_pam_dir_config *config, int arg)
{
config->is_authorative = arg;
return NULL;
}
command_rec auth_pam_cmds[] = {
{ "AuthFailDelay", (const char*(*)())auth_fail_delay, 0, OR_AUTHCFG, TAKE1,
"number of micro seconds to wait after failed authentication attempt. defau
lt is 0" },
{ "AuthPAM_Authorative", (const char*(*)())auth_fall_through, 0, OR_AUTHCFG, FLAG,
"on|off - determines if other authentication methods are attempted if this
one fails" },
{ 0 }
};
/*
* get a list of groups the given user belongs to
*
* adapted from the version in mod_auth to use a new means of
* group information.
*
* note: someone should really have a hard look at all the auth
* modules and compile a more generic version of the
* functions. currently there's lots of code overlap
*/
table *get_groups (pool *p, char *user)
{
table *grps = ap_make_table (p, 15);
pool *sp = 0;
char *group_name = 0;
int ngrps = 0;
gid_t *gid_list = 0;
struct passwd *pw_ent = 0;
struct group *gr_ent = 0;
int i = 0;
sp = ap_make_sub_pool(p);
if(!sp)
return 0;
/* enter principal group */
if(pw_ent = getpwnam(user)) {
gr_ent = getgrgid(pw_ent->pw_gid);
if(gr_ent)
ap_table_set(grps, gr_ent->gr_name, "in");
} else
return 0; /* no such user */
/* get list of supplemental groups */
ngrps = getgroups(0, 0);
gid_list = ap_palloc(sp, ngrps * sizeof(gid_t));
if(gid_list)
getgroups(ngrps, gid_list);
/* enter supplemental groups */
for(i = 0; i < ngrps; i++) {
gr_ent = getgrgid(gid_list[i]);
ap_table_set(grps, gr_ent->gr_name, "in");
}
ap_destroy_pool (sp);
return grps;
}
/*
* 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
*
*/
int auth_pam_talker(int num_msg,
const struct pam_message **msg,
struct pam_response **resp,
void *appdata_ptr)
{
unsigned short i = 0;
auth_pam_userinfo *userinfo = (auth_pam_userinfo*)appdata_ptr;
struct pam_response *response = 0;
/* parameter sanity checking */
if(!resp || !msg || !userinfo)
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:
/* on memory allocation failure, auth fails */
response[i].resp = strdup(userinfo->name);
break;
case PAM_PROMPT_ECHO_OFF:
response[i].resp = strdup(userinfo->pw);
break;
default:
if(response)
free(response);
return PAM_CONV_ERR;
}
}
/* everything okay, set PAM response values */
*resp = response;
return PAM_SUCCESS;
}
/*
* These functions return 0 if client is OK, and proper error status
* if not... either AUTH_REQUIRED, if we made a check, and it failed, or
* SERVER_ERROR, if things are so totally confused that we couldn't
* figure out how to tell if the client is authorized or not.
*
* If they return DECLINED, and all other modules also decline, that's
* treated by the server core as a configuration error, logged and
* reported as such.
*/
/*
* Determine user ID, and check if it really is that user
*/
int pam_auth_basic_user (request_rec *r)
{
int res = 0;
/* mod_auth_pam specific */
auth_pam_userinfo userinfo = { NULL, NULL };
auth_pam_dir_config *conf = (auth_pam_dir_config*)
ap_get_module_config(r->per_dir_config, &pam_auth_module);
/* PAM specific */
struct pam_conv conv_info = { &auth_pam_talker, &userinfo};
pam_handle_t *pamh = NULL;
/* read sent pw */
if ((res = ap_get_basic_auth_pw (r, (const char**)&(userinfo.pw))))
return res;
/* this is only set after get_basic_auth_pw was called */
userinfo.name = r->connection->user;
/* initialize pam */
if((res = pam_start(pam_servicename,
userinfo.name,
&conv_info,
&pamh)) != PAM_SUCCESS) {
#ifdef PAM_STRE_NEEDS_PAMH
ap_log_reason((char*)pam_strerror(pamh, res), r->uri, r);
#else
ap_log_reason((char*)pam_strerror(res), r->uri, r);
#endif
return DECLINED;
}
/* set fail delay */
#ifdef PAM_FAIL_DELAY
pam_fail_delay(pamh, conf->fail_delay);
#endif
/* set remote user information */
/* this seems to cause segfaults in lots of cases -- disabled for now
pam_set_item(pamh, PAM_USER, userinfo.name);
pam_set_item(pamh, PAM_RHOST, get_remote_host(r->connection,
conf,
REMOTE_NAME));
*/
/* try to authenticate user, log error on failure */
if((res = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS
) {
if(!conf->is_authorative) {
/* we don't know about the user, but other auth modules might do */
pam_end(pamh, PAM_SUCCESS);
return DECLINED;
}
else {
#ifdef PAM_STRE_NEEDS_PAMH
ap_log_reason((char*)pam_strerror(pamh, res), r->uri, r);
#else
ap_log_reason((char*)pam_strerror(res), r->uri, r);
#endif
pam_end(pamh, PAM_SUCCESS);
ap_note_basic_auth_failure(r);
return AUTH_REQUIRED;
}
}
/* check that the account is healthy */
if((res = pam_acct_mgmt(pamh, PAM_DISALLOW_NULL_AUTHTOK)) != PAM_SUCCESS) {
#ifdef PAM_STRE_NEEDS_PAMH
ap_log_reason((char*)pam_strerror(pamh, res), r->uri, r);
#else
ap_log_reason((char*)pam_strerror(res), r->uri, r);
#endif
pam_end(pamh, PAM_SUCCESS);
return AUTH_REQUIRED;
}
pam_end(pamh, PAM_SUCCESS);
return OK;
}
/*
* Look if that user (as authenticated above) is allowed here
*/
int pam_check_auth (request_rec *r)
{
register int i = 0;
char method_restricted = 0, *line = 0, *word = 0;
table *groups = 0;
/* check for allowed users/group */
const array_header *reqs_arr = ap_requires (r);
require_line *reqs = 0;
/* if any valid user suffices return success */
if (!reqs_arr)
return (OK);
/* otherwise */
reqs = (require_line*)reqs_arr->elts;
groups = get_groups(r->pool, r->connection->user);
/* loop over requirement lines */
for( i = 0; i < reqs_arr->nelts; i++) {
/* if method of this requirement matches current method */
if (reqs[i].method_mask & (1 << r->method_number)) {
method_restricted = 1;
line = reqs[i].requirement;
word = ap_getword(r->pool, (const char**)&line, ' ');
/* if any user is ok */
if(!strcmp(word, valid_user))
return OK;
/* loop over line */
if(!strcmp(word, "user")) {
while(*line) {
word = ap_getword_conf(r->pool, (const char**)&line);
/* if username matches remote username */
if(!strcmp(r->connection->user, word))
/* return success */
return OK;
}
} /* end if user */
else if(!strcmp(word, "group")) {
if(!groups) {
ap_log_printf(r->server, "couldn't get group list");
return DECLINED;
}
while(*line) {
word = ap_getword_conf(r->pool, (const char**)&line);
if(ap_table_get(groups, word))
return OK;
}
} /* end if group */
}
}
if (!method_restricted)
return OK;
ap_note_basic_auth_failure (r);
return AUTH_REQUIRED;
}
module pam_auth_module = {
STANDARD_MODULE_STUFF,
NULL, /* initializer */
create_auth_pam_dir_config, /* dir config creater */
NULL, /* dir merger --- default is to override */
NULL, /* server config */
NULL, /* merge server config */
auth_pam_cmds, /* command table */
NULL, /* handlers */
NULL, /* filename translation */
pam_auth_basic_user, /* check_user_id */
pam_check_auth, /* check auth */
NULL, /* check access */
NULL, /* type_checker */
NULL, /* fixups */
NULL /* logger */
};
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic