/*
** mod_absec.c -- Apache sample absec module
** [Autogenerated via ``apxs -n absec -g'']
**
** To play with this sample module first compile it into a
** DSO file and install it into Apache's modules directory
** by running:
**
** $ apxs -c -i mod_absec.c
**
** Then activate it in Apache's httpd.conf file for instance
** for the URL /absec in as follows:
**
** # httpd.conf
** LoadModule absec_module modules/mod_absec.so
**
** SetHandler absec
**
**
** Then after restarting Apache via
**
** $ apachectl restart
**
** you immediately can request the URL /absec and watch for the
** output of this module. This can be achieved for instance via:
**
** $ lynx -mime_header http://localhost/absec
**
** The output should be similar to the following one:
**
** HTTP/1.1 200 OK
** Date: Tue, 31 Mar 1998 14:42:22 GMT
** Server: Apache/1.3.4 (Unix)
** Connection: close
** Content-Type: text/html
**
** The sample page from mod_absec.c
*/
/*
TEST URL
http://10.211.55.15/absec?joe=blow
INFORMATION SOURCES
https://apr.apache.org/docs/apr/1.5/group__apr__strings.html
https://apr.apache.org/docs/apr-util/1.6/files.html
https://httpd.apache.org/docs/2.4/developer/modguide.html
http://www.ziviani.net/2011/how-to-create-an-apache-module
https://en.wikipedia.org/wiki/Basic_access_authentication
*/
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_protocol.h"
#include "ap_config.h"
#include "apr_base64.h"
#include "apr_strings.h"
#include "apr_portable.h"
#include "apr_user.h"
#include
#include
#include
#include "apr_want.h"
#include
#include
////////////////////////////////////////////////////////////////
/* The sample content handler */
static int absec_handler(request_rec *r)
{
if (strcmp(r->handler, "absec")) {
return DECLINED;
}
const char* auth64p;
r->content_type = "text/html";
if (!r->header_only)
// Check if we have an auth header
auth64p = apr_table_get(r->headers_in,"Authorization");
if (auth64p==NULL) {
apr_table_setn(r->err_headers_out,
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
: "WWW-Authenticate",
apr_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r),
"\"", NULL));
return HTTP_UNAUTHORIZED;
}
////////
/* Retrieve user/pass from http basic auth header */
// Get the basic auth base64 string and decode it
// Start at char 6 to skip 'Basic '
char *auth64;
//apr_strtok((char*)auth64p, " ", &auth64);
//ap_rprintf(r, "Test: %s \n
", auth64);
auth64 = apr_pstrdup(r->pool, auth64p+6);
//ap_rprintf(r, "Test: %s \n
", auth64);
char *auth;
auth = apr_pcalloc(r->pool, 64);
apr_base64_decode(auth, auth64);
// Validate user/pass against unix cred
char *user;
char *pass;
user = apr_strtok(auth, ":", &pass);
// Get UID, GIDs for the user
ap_rprintf(r, "The sample page from mod_absec.c %s \n
", r->args);
ap_rprintf(r, "Url: %s from %s \n
", r->filename, r->uri);
ap_rprintf(r, "Headers Authorization: %s \n
", auth64);
ap_rprintf(r, "User/Pass: %s/%s \n
", user, pass);
////////
/* Working example, but just UID not PW */
apr_status_t ret;
apr_uid_t i;
apr_gid_t g;
ret = apr_uid_get ( &i, &g, user, r->pool );
ap_rprintf(r, "Result2: G:%d, I:%d \n
", g,i);
////////
/* Retrieve PW from /etc/passwd */
/* Should include */
struct passwd *pw;
if((pw = getpwnam(user)) == NULL)
{
ap_rprintf(r, "NULL \n
");
apr_table_setn(r->err_headers_out,
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
: "WWW-Authenticate",
apr_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r),
"\"", NULL));
return HTTP_UNAUTHORIZED;
}
else
{
ap_rprintf(r, "Unix PW : %s \n
", pw->pw_passwd);
}
////////
/* Retrieve PW from /etc/shadow */
/* Should include */
struct spwd *spw;
errno = 0;
if((spw = getspnam(user)) == NULL)
{
ap_rprintf(r, "NULL %d\n
", errno);
apr_table_setn(r->err_headers_out,
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
: "WWW-Authenticate",
apr_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r),
"\"", NULL));
return HTTP_UNAUTHORIZED;
}
else
{
ap_rprintf(r, "Shadow PW : %s \n
", spw->sp_pwdp);
}
if (spw->sp_pwdp[0] == 'x' || spw->sp_pwdp[0] == '*' || spw->sp_pwdp[0] == '!') {
apr_table_setn(r->err_headers_out,
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
: "WWW-Authenticate",
apr_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r),
"\"", NULL));
return HTTP_UNAUTHORIZED;
}
////////
/* Encrypt and compare shadow password */
// TODO : Valider qu'on a un user
// TODO : Valider qu'il y a un password (pas * ! rien)
char *encrypted;
const char *correct;
int rrr;
encrypted = crypt(pass, spw->sp_pwdp);
rrr = strcmp(encrypted, spw->sp_pwdp);
ap_rprintf(r, "compare pw : %s \n
", encrypted);;
ap_rprintf(r, "compare : %d \n
", rrr);
if (rrr!=0) {
apr_table_setn(r->err_headers_out,
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
: "WWW-Authenticate",
apr_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r),
"\"", NULL));
return HTTP_UNAUTHORIZED;
}
////////
/* check file permission on filesystem */
/* should include */
struct stat fperm;
int status;
status = stat(r->filename, &fperm);
ap_rprintf(r, "File perms %o, owner %d, group %d (status %d)", fperm.st_mode, fperm.st_uid, fperm.st_gid, status);
return OK;
}
////////////////////////////////////////////////////////////////
static void absec_register_hooks(apr_pool_t *p)
{
ap_hook_handler(absec_handler, NULL, NULL, APR_HOOK_MIDDLE);
}
////////////////////////////////////////////////////////////////
/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA absec_module = {
STANDARD20_MODULE_STUFF,
NULL, /* create per-dir config structures */
NULL, /* merge per-dir config structures */
NULL, /* create per-server config structures */
NULL, /* merge per-server config structures */
NULL, /* table of config file commands */
absec_register_hooks /* register hooks */
};