Compare commits
12 Commits
154d770cf3
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 605dbdc46f | |||
| 74b7534151 | |||
| 0a8e97a54a | |||
| ea59731e1f | |||
| 2fb12410ea | |||
| 823bd9094d | |||
| 5baaf67c0e | |||
| fc4095fca4 | |||
| d18504ce2a | |||
| 950e76d6e8 | |||
| eb4fd57eb9 | |||
| 0c909d5a93 |
Binary file not shown.
+1
-1
@@ -15,6 +15,6 @@
|
||||
#define PAM_ERROR_STOP -3
|
||||
|
||||
#define HTTP_UNAUTHORIZED 401
|
||||
#define OK 200
|
||||
#define OK 0
|
||||
|
||||
int check_user(char* user, char* pass);
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
////////
|
||||
//
|
||||
// header file for autorisation
|
||||
// used either for absec_fs or absec_mysql
|
||||
//
|
||||
// author: Jean-Luc Cyr
|
||||
// date: 2018-10
|
||||
//
|
||||
// usage: include this file as header definition
|
||||
// then link the program with either -labsec_fs or -labsec_mysql
|
||||
//
|
||||
|
||||
#include "httpd.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
int perms_lookup(request_rec *r, struct stat *fperm);
|
||||
@@ -0,0 +1,63 @@
|
||||
/////
|
||||
//
|
||||
// File : absec_chown.c
|
||||
// Author : Jean-Luc Cyr
|
||||
// Date : 2018-10
|
||||
//
|
||||
// Description: tool to change ownership from mysql database
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <mysql.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// mysql call
|
||||
int mysql_update(char *url, int gid)
|
||||
{
|
||||
MYSQL *conn;
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
char *server = "localhost";
|
||||
char *user = "jlcyr";
|
||||
char *password = "password"; /* set me first */
|
||||
char *database = "absec";
|
||||
|
||||
conn = mysql_init(NULL);
|
||||
|
||||
/* Connect to database */
|
||||
if (!mysql_real_connect(conn, server,
|
||||
user, password, database, 0, NULL, 0)) {
|
||||
printf("%s\n", mysql_error(conn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
char query[256];
|
||||
sprintf(query, "update urls set gid=%d where url='%s'", gid, url); // where url='%s'", r->uri);
|
||||
//printf("update urls set gid=%d where url='%s'\r\n", gid, url); // where url='%s'", r->uri);
|
||||
/* send SQL query */
|
||||
//if (mysql_query(conn, "show tables")) {
|
||||
if (mysql_query(conn, query)) {
|
||||
printf("%s\n", mysql_error(conn));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
mysql_close(conn);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void main(int argc, char** argv)
|
||||
{
|
||||
int perms = 0;
|
||||
switch (argc) {
|
||||
default:
|
||||
printf("Usage: abchgrp <uid> <url>\r\n\r\n");
|
||||
exit(1);
|
||||
break;
|
||||
case 3:
|
||||
printf("Updating group ownership on %s to %d\r\n", argv[2], atoi(argv[1]));
|
||||
mysql_update(argv[2], atoi(argv[1]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/////
|
||||
//
|
||||
// File : absec_ls.c
|
||||
// Author : Jean-Luc Cyr
|
||||
// Date : 2018-10
|
||||
//
|
||||
// Description: tool to query permissions from mysql database
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <mysql.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// define PAM callback function
|
||||
int mysql_update(char *url, int uid, int gid, int perms)
|
||||
{
|
||||
MYSQL *conn;
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
char *server = "localhost";
|
||||
char *user = "jlcyr";
|
||||
char *password = "password"; /* set me first */
|
||||
char *database = "absec";
|
||||
|
||||
conn = mysql_init(NULL);
|
||||
|
||||
/* Connect to database */
|
||||
if (!mysql_real_connect(conn, server,
|
||||
user, password, database, 0, NULL, 0)) {
|
||||
printf("%s\n", mysql_error(conn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
char query[256];
|
||||
sprintf(query, "update urls set uid=%d, gid=%d, perms=%d where url='%s'", uid, gid, perms, url); // where url='%s'", r->uri);
|
||||
//printf("update urls set uid=%d, gid=%d, perms=%d where url='%s'\r\n", uid, gid, perms, url); // where url='%s'", r->uri);
|
||||
/* send SQL query */
|
||||
//if (mysql_query(conn, "show tables")) {
|
||||
if (mysql_query(conn, query)) {
|
||||
printf("%s\n", mysql_error(conn));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* close connection */
|
||||
mysql_free_result(res);
|
||||
mysql_close(conn);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void main(int argc, char** argv)
|
||||
{
|
||||
int perms = 0;
|
||||
switch (argc) {
|
||||
default:
|
||||
printf("Usage: abchmod <perms> <url>\r\n\r\n");
|
||||
exit(1);
|
||||
break;
|
||||
case 2:
|
||||
printf("Updating perms on %s\r\n", argv[0]);
|
||||
mysql_update(argv[1], 1000, 100, 501);
|
||||
break;
|
||||
case 3:
|
||||
perms = strtol(argv[1], NULL, 8);
|
||||
printf("Updating perms on %s to %o (%d)\r\n", argv[2], perms, perms);
|
||||
mysql_update(argv[2], 1000, 100, perms);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/////
|
||||
//
|
||||
// File : absec_chown.c
|
||||
// Author : Jean-Luc Cyr
|
||||
// Date : 2018-10
|
||||
//
|
||||
// Description: tool to change ownership from mysql database
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <mysql.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// mysql call
|
||||
int mysql_update(char *url, int uid)
|
||||
{
|
||||
MYSQL *conn;
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
char *server = "localhost";
|
||||
char *user = "jlcyr";
|
||||
char *password = "password"; /* set me first */
|
||||
char *database = "absec";
|
||||
|
||||
conn = mysql_init(NULL);
|
||||
|
||||
/* Connect to database */
|
||||
if (!mysql_real_connect(conn, server,
|
||||
user, password, database, 0, NULL, 0)) {
|
||||
printf("%s\n", mysql_error(conn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
char query[256];
|
||||
sprintf(query, "update urls set uid=%d where url='%s'", uid, url); // where url='%s'", r->uri);
|
||||
//printf("update urls set uid=%d where url='%s'\r\n", uid, url); // where url='%s'", r->uri);
|
||||
/* send SQL query */
|
||||
//if (mysql_query(conn, "show tables")) {
|
||||
if (mysql_query(conn, query)) {
|
||||
printf("%s\n", mysql_error(conn));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
mysql_close(conn);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void main(int argc, char** argv)
|
||||
{
|
||||
int perms = 0;
|
||||
switch (argc) {
|
||||
default:
|
||||
printf("Usage: abchown <uid> <url>\r\n\r\n");
|
||||
exit(1);
|
||||
break;
|
||||
case 3:
|
||||
printf("Updating ownership on %s to %d\r\n", argv[2], atoi(argv[1]));
|
||||
mysql_update(argv[2], atoi(argv[1]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
|
||||
#define PAM_OK 0
|
||||
#define PAM_ERROR_START -1
|
||||
#define PAM_ERROR_INVALID_CRED -2
|
||||
#define PAM_ERROR_STOP -3
|
||||
|
||||
#define HTTP_UNAUTHORIZED 401
|
||||
#define OK 200
|
||||
|
||||
int check_user(char* user, char* pass);
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/////
|
||||
//
|
||||
// File : absec_fs.c
|
||||
// Author : Jean-Luc Cyr
|
||||
// Date : 2018-10
|
||||
//
|
||||
// Description: Using filesystem as autorisation method
|
||||
//
|
||||
|
||||
|
||||
#include "absec_auto.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include "httpd.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// file system based permission lookup
|
||||
int perms_lookup(request_rec *r, struct stat *fperm)
|
||||
{
|
||||
int status;
|
||||
status = stat(r->filename, fperm);
|
||||
|
||||
return status;
|
||||
}
|
||||
+18
-20
@@ -1,3 +1,11 @@
|
||||
/////
|
||||
//
|
||||
// File : absec_ls.c
|
||||
// Author : Jean-Luc Cyr
|
||||
// Date : 2018-10
|
||||
//
|
||||
// Description: tool to query permissions from mysql database
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -28,7 +36,7 @@ char* perms_to_string(int perms)
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// define PAM callback function
|
||||
int mysql_lookup()//request_rec *r, struct stat *fperm)
|
||||
int mysql_lookup(char* pattern)//request_rec *r, struct stat *fperm)
|
||||
{
|
||||
MYSQL *conn;
|
||||
MYSQL_RES *res;
|
||||
@@ -49,37 +57,23 @@ int mysql_lookup()//request_rec *r, struct stat *fperm)
|
||||
}
|
||||
|
||||
char query[256];
|
||||
sprintf(query, "select * from urls"); // where url='%s'", r->uri);
|
||||
sprintf(query, "select * from urls where url like '%s'", pattern); // where url='%s'", r->uri);
|
||||
/* send SQL query */
|
||||
//if (mysql_query(conn, "show tables")) {
|
||||
if (mysql_query(conn, query)) {
|
||||
printf("%s\n", mysql_error(conn));
|
||||
printf("%s\r\n", mysql_error(conn));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
res = mysql_use_result(conn);
|
||||
|
||||
/* output table name */
|
||||
printf("ABSEC permissions\n");
|
||||
printf("ABSEC permissions\r\n");
|
||||
int cnt = 0;
|
||||
while ((row = mysql_fetch_row(res)) != NULL) {
|
||||
printf("%s\t%d\t%d\t%s \n", perms_to_string(atoi(row[3])), atoi(row[1]), atoi(row[2]), row[0] );
|
||||
|
||||
/*fperm->st_uid = atoi(row[1]);
|
||||
fperm->st_gid = atoi(row[2]);
|
||||
fperm->st_mode = atoi(row[3]);*/
|
||||
cnt = cnt + 1;
|
||||
printf("%s\t%d\t%d\t%s \r\n", perms_to_string(atoi(row[3])), atoi(row[1]), atoi(row[2]), row[0] );
|
||||
}
|
||||
|
||||
/*if (cnt==0) {
|
||||
sprintf(query, "insert into urls (url, uid, gid, perms) values ('%s', 0, 0, 0)", r->uri);
|
||||
if (mysql_query(conn, query)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(0);
|
||||
}
|
||||
ap_rprintf(r, "Aucune donnee\n<br/>");
|
||||
}*/
|
||||
|
||||
/* close connection */
|
||||
mysql_free_result(res);
|
||||
mysql_close(conn);
|
||||
@@ -88,5 +82,9 @@ int mysql_lookup()//request_rec *r, struct stat *fperm)
|
||||
|
||||
void main(int argc, char** argv)
|
||||
{
|
||||
mysql_lookup();
|
||||
if (argc>1) {
|
||||
mysql_lookup(argv[1]);
|
||||
} else {
|
||||
mysql_lookup("%");
|
||||
}
|
||||
}
|
||||
+13
-3
@@ -1,12 +1,22 @@
|
||||
/////
|
||||
//
|
||||
// File : absec_mysql.c
|
||||
// Author : Jean-Luc Cyr
|
||||
// Date : 2018-10
|
||||
//
|
||||
// Description: Using mysql database as autorisation method
|
||||
//
|
||||
|
||||
|
||||
#include "absec_auto.h"
|
||||
|
||||
#include <mysql.h>
|
||||
#include <sys/stat.h>
|
||||
#include "httpd.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
int mysql_lookup(request_rec *r, struct stat *fperm)
|
||||
// mysql based permission lookup
|
||||
int perms_lookup(request_rec *r, struct stat *fperm)
|
||||
{
|
||||
MYSQL *conn;
|
||||
MYSQL_RES *res;
|
||||
@@ -49,7 +59,7 @@ int mysql_lookup(request_rec *r, struct stat *fperm)
|
||||
}
|
||||
|
||||
if (cnt==0) {
|
||||
sprintf(query, "insert into urls (url, uid, gid, perms) values ('%s', 0, 0, 0)", r->uri);
|
||||
sprintf(query, "insert into urls (url, uid, gid, perms) values ('%s', %d, %d, %d)", r->uri, fperm->st_uid, fperm->st_gid, fperm->st_mode);
|
||||
if (mysql_query(conn, query)) {
|
||||
printf("%s\n", mysql_error(conn));
|
||||
return(0);
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
|
||||
int mysql_lookup(request_rec *r, struct stat *fperm);
|
||||
+8
-19
@@ -1,23 +1,17 @@
|
||||
|
||||
/////
|
||||
//
|
||||
// File : absec_pam.c
|
||||
// Author : Jean-Luc Cyr
|
||||
// Date : 2018-10
|
||||
//
|
||||
// Description: Using PAM as authentification method
|
||||
//
|
||||
|
||||
#include "absec_authen.h"
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_misc.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Check user autentication against unix user/pass */
|
||||
/*static int check_autentication(request_rec *r)
|
||||
{
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Check check file perms */
|
||||
/*static int check_autorization(request_rec *r)
|
||||
{
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
// Global var for passing fake response to PAM callback
|
||||
struct pam_response *reply;
|
||||
@@ -59,8 +53,3 @@ int check_user(char* user, char* pass) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/*void main(int argc, char** argv) {
|
||||
printf("absec_pam OK\n");
|
||||
exit(0);
|
||||
}*/
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
#define PAM_OK 0
|
||||
#define PAM_ERROR_START -1
|
||||
#define PAM_ERROR_INVALID_CRED -2
|
||||
#define PAM_ERROR_STOP -3
|
||||
|
||||
int check_user(char* user, char* pass);
|
||||
+62
-46
@@ -1,84 +1,100 @@
|
||||
#!/bin/bash
|
||||
ABSEC_AUTHEN_DEP="-lpam -lpam_misc "
|
||||
ABSEC_AUTHEN_FILE="absec_pam.o"
|
||||
#could be absec_pam or absec_etc
|
||||
ABSEC_AUTO_DEP="`mysql_config --cflags --libs` "
|
||||
ABSEC_AUTO_FILE="absec_mysql.o"
|
||||
#could be absec_fs or absec_mysql
|
||||
|
||||
echo "----------------"
|
||||
echo "Cleaning projets"
|
||||
rm -fv *.o *.lo *.la *.slo
|
||||
|
||||
echo "----------------"
|
||||
echo "================"
|
||||
echo "Compiling pam module (absec_pam)"
|
||||
#/home/jlcyr/apache2/bin/apxs -lpam -lpam_misc `mysql_config --cflags --libs` -c -i mod_absec.c
|
||||
#gcc -fPIC -c -lpam -lpam_misc -o absec_pam.o absec_pam.c
|
||||
#gcc absec_pam.c -lpam -lpam_misc -o absec_pam
|
||||
gcc absec_pam.c -lpam -lpam_misc -c
|
||||
|
||||
#ld -lpam -lpam_misc --shared -o absec_pam absec_pam.o
|
||||
#./absec_pam
|
||||
#exit
|
||||
gcc absec_pam.c -lpam -lpam_misc -fPIC -c
|
||||
|
||||
echo "----------------"
|
||||
echo "Compiling authen test with pam (test_authen -labsec_pam)"
|
||||
#/home/jlcyr/apache2/bin/apxs -lpam -lpam_misc `mysql_config --cflags --libs` -c -i mod_absec.c
|
||||
gcc test_authen.c absec_pam.o -lpam -lpam_misc -o test_authen
|
||||
#gcc -o test_pam -lpam -lpam_misc absec_pam.o test_pam.c
|
||||
#ld -o test_pam -lc --entry main test_pam.o
|
||||
#ld -lpam -lpam_misc --shared -o test_pam absec_pam.o test_pam.o
|
||||
echo "Running test"
|
||||
./test_authen
|
||||
|
||||
echo "----------------"
|
||||
echo "================"
|
||||
echo "Compiling etc module (absec_etc)"
|
||||
#/home/jlcyr/apache2/bin/apxs -lpam -lpam_misc `mysql_config --cflags --libs` -c -i mod_absec.c
|
||||
#gcc -fPIC -c -lpam -lpam_misc -o absec_pam.o absec_pam.c
|
||||
#gcc absec_pam.c -lpam -lpam_misc -o absec_pam
|
||||
gcc -I /usr/local/apache2/include -I /usr/include/apr-1.0 absec_etc.c -c
|
||||
gcc -I /usr/local/apache2/include -I /usr/include/apr-1.0 -fPIC absec_etc.c -c
|
||||
|
||||
|
||||
echo "----------------"
|
||||
echo "Compiling authen test with etc (test_authen -labsec_etc)"
|
||||
#/home/jlcyr/apache2/bin/apxs -lpam -lpam_misc `mysql_config --cflags --libs` -c -i mod_absec.c
|
||||
gcc test_authen.c absec_etc.o -L/usr/lib/x86_64-linux-gnu -lapr-1 -lcrypt -o test_authen
|
||||
#gcc -o test_pam -lpam -lpam_misc absec_pam.o test_pam.c
|
||||
#ld -o test_pam -lc --entry main test_pam.o
|
||||
#ld -lpam -lpam_misc --shared -o test_pam absec_pam.o test_pam.o
|
||||
echo "Running test"
|
||||
./test_authen
|
||||
|
||||
|
||||
echo "----------------"
|
||||
echo "================"
|
||||
echo "Compiling mysql module"
|
||||
#/home/jlcyr/apache2/bin/apxs -lpam -lpam_misc `mysql_config --cflags --libs` -c -i mod_absec.c
|
||||
#gcc -fPIC -c -lpam -lpam_misc -o absec_pam.o absec_pam.c
|
||||
#gcc absec_pam.c -lpam -lpam_misc -o absec_pam
|
||||
gcc absec_mysql.c `mysql_config --cflags --libs` -I/usr/include/apache2 -I/usr/include/apr-1.0 -c
|
||||
|
||||
#ld -lpam -lpam_misc --shared -o absec_pam absec_pam.o
|
||||
#./absec_pam
|
||||
#exit
|
||||
gcc absec_mysql.c `mysql_config --cflags --libs` -I/usr/include/apache2 -I/usr/include/apr-1.0 -fPIC -c
|
||||
|
||||
echo "----------------"
|
||||
echo "Compiling autho test with mysql"
|
||||
#/home/jlcyr/apache2/bin/apxs -lpam -lpam_misc `mysql_config --cflags --libs` -c -i mod_absec.c
|
||||
gcc test_mysql.c absec_mysql.o -lpam -lpam_misc `mysql_config --cflags --libs` -o test_mysql
|
||||
#gcc -o test_pam -lpam -lpam_misc absec_pam.o test_pam.c
|
||||
#ld -o test_pam -lc --entry main test_pam.o
|
||||
#ld -lpam -lpam_misc --shared -o test_pam absec_pam.o test_pam.o
|
||||
echo "Compiling auto test with mysql (test_auto -labsec_mysql)"
|
||||
gcc test_auto.c absec_mysql.o `mysql_config --cflags --libs` -I/usr/include/apache2 -I/usr/include/apr-1.0 -o test_auto
|
||||
echo "Running test"
|
||||
./test_mysql
|
||||
./test_auto
|
||||
|
||||
echo "================"
|
||||
echo "Compiling filesystem module"
|
||||
gcc absec_fs.c -I/usr/include/apache2 -I/usr/include/apr-1.0 -fPIC -c
|
||||
|
||||
echo "----------------"
|
||||
echo "Compiling auto test with filesystem (test_auto -labsec_fs)"
|
||||
gcc test_auto.c absec_fs.o -I/usr/include/apache2 -I/usr/include/apr-1.0 -o test_auto
|
||||
echo "Running test"
|
||||
./test_auto
|
||||
|
||||
echo "================"
|
||||
echo "Compiling absec tools"
|
||||
echo "- absec_ls"
|
||||
#/home/jlcyr/apache2/bin/apxs -lpam -lpam_misc `mysql_config --cflags --libs` -c -i mod_absec.c
|
||||
gcc absec_ls.c `mysql_config --cflags --libs` -o abls
|
||||
#gcc -o test_pam -lpam -lpam_misc absec_pam.o test_pam.c
|
||||
#ld -o test_pam -lc --entry main test_pam.o
|
||||
#ld -lpam -lpam_misc --shared -o test_pam absec_pam.o test_pam.o
|
||||
echo "Running test"
|
||||
./abls
|
||||
exit
|
||||
./abls /
|
||||
|
||||
echo "----------------"
|
||||
echo "Compiling absec module"
|
||||
sudo apxs -lpam -lpam_misc `mysql_config --cflags --libs` -c -i absec_pam.o absec_mysql.o mod_absec.c
|
||||
echo "================"
|
||||
echo "Compiling absec tools"
|
||||
echo "- absec_chmod"
|
||||
gcc absec_chmod.c `mysql_config --cflags --libs` -o abchmod
|
||||
echo "Running test"
|
||||
./abchmod 0 /
|
||||
./abls /
|
||||
./abchmod 666 /
|
||||
./abls /
|
||||
|
||||
echo "================"
|
||||
echo "Compiling absec tools"
|
||||
echo "- absec_chown"
|
||||
gcc absec_chown.c `mysql_config --cflags --libs` -o abchown
|
||||
echo "Running test"
|
||||
./abchown 100 /
|
||||
./abls /
|
||||
./abchown 200 /
|
||||
./abls /
|
||||
|
||||
echo "================"
|
||||
echo "Compiling absec tools"
|
||||
echo "- absec_chgrp"
|
||||
gcc absec_chgrp.c `mysql_config --cflags --libs` -o abchgrp
|
||||
echo "Running test"
|
||||
./abchgrp 100 /
|
||||
./abls /
|
||||
./abchgrp 200 /
|
||||
./abls /
|
||||
|
||||
echo "================"
|
||||
echo "Compiling apache absec module"
|
||||
echo "selected authen :" $ABSEC_AUTHEN_DEP $ABSEC_AUTHEN_FILE
|
||||
echo "selected auto :" $ABSEC_AUTO_DEP $ABSEC_AUTO_FILE
|
||||
sudo apxs $ABSEC_AUTHEN_DEP $ABSEC_AUTO_DEP -c -i $ABSEC_AUTHEN_FILE $ABSEC_AUTO_FILE mod_absec.c
|
||||
#/home/jlcyr/apache2/bin/apachectl restart
|
||||
echo "Restarting apache"
|
||||
sudo /etc/init.d/apache2 restart
|
||||
|
||||
+179
-129
@@ -1,3 +1,12 @@
|
||||
/////
|
||||
//
|
||||
// File : mod_absec.c
|
||||
// Author : Jean-Luc Cyr
|
||||
// Date : 2018-10
|
||||
//
|
||||
// Description: apache module for authentification and autorisation management
|
||||
//
|
||||
|
||||
/*
|
||||
** mod_absec.c -- Apache absec module
|
||||
** [base Autogenerated via ``apxs -n absec -g'']
|
||||
@@ -43,11 +52,17 @@
|
||||
#include "http_config.h"
|
||||
#include "http_core.h"
|
||||
#include "http_protocol.h"
|
||||
#include "http_request.h"
|
||||
#include "http_log.h"
|
||||
#include "ap_config.h"
|
||||
#include "apr_base64.h"
|
||||
#include "apr_strings.h"
|
||||
#include "apr_portable.h"
|
||||
#include "apr_user.h"
|
||||
#include "ap_provider.h"
|
||||
#include "mod_auth.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
@@ -58,50 +73,123 @@
|
||||
#include <shadow.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "absec_pam.h"
|
||||
#include "absec_mysql.h"
|
||||
#include "absec_authen.h"
|
||||
#include "absec_auto.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Main routine - called after request processing */
|
||||
static int absec_handler_last(request_rec *r)
|
||||
// Macro declaration du module
|
||||
module AP_MODULE_DECLARE_DATA absec_module;
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// structure de configuration du module
|
||||
typedef struct {
|
||||
int default_uid;
|
||||
int default_gid;
|
||||
int default_perms;
|
||||
} authnz_config_rec;
|
||||
|
||||
static void *authnz_absec_config(apr_pool_t *pool, char *x)
|
||||
{
|
||||
// Is this module really called?
|
||||
if (strcmp(r->handler, "absec")) {
|
||||
return DECLINED;
|
||||
}
|
||||
return apr_pcalloc(pool, sizeof(authnz_config_rec));
|
||||
}
|
||||
|
||||
////////
|
||||
/* http method validate the perm asked (r/w vs get/post,put) */
|
||||
ap_rprintf(r, "After Method: %s<br/>\r\n", r->method);
|
||||
int permmask = 0;
|
||||
if (strcmp(r->method,"GET")!=0)
|
||||
static const char* set_default_perms(cmd_parms* cmd, void* cfg, const char* val) {
|
||||
int octal, decimal;
|
||||
octal = atoi(val);
|
||||
decimal = 0;
|
||||
int i=0;
|
||||
while (octal != 0)
|
||||
{
|
||||
// Not a GET, it's too late to do anything
|
||||
ap_rprintf(r, "Not a GET post treatement is too late!\n<br/>");
|
||||
return (DECLINED);
|
||||
decimal = decimal +(octal % 10)* pow(8, i++);
|
||||
octal = octal / 10;
|
||||
}
|
||||
|
||||
r->content_type = "text/html";
|
||||
//ap_rprintf(r, "The sample page from mod_absec.c %s \n<br/>", r->args);
|
||||
ap_rprintf(r, "After GET Url: %s from %s \n<br/>", r->filename, r->uri);
|
||||
return (DECLINED);
|
||||
((authnz_config_rec*)cfg)->default_perms = decimal;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* set_default_uid(cmd_parms* cmd, void* cfg, const char* val) {
|
||||
((authnz_config_rec*)cfg)->default_uid = atoi(val);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* set_default_gid(cmd_parms* cmd, void* cfg, const char* val) {
|
||||
((authnz_config_rec*)cfg)->default_gid = atoi(val);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Main routine - called before request processing */
|
||||
static int absec_handler_first(request_rec *r)
|
||||
static const command_rec absec_auth_basic_cmds[] =
|
||||
{
|
||||
ap_rprintf(r, "Before Method: %s<br/>\r\n", r->method);
|
||||
// Is this module really called?
|
||||
/*if (strcmp(r->handler, "absec")) {
|
||||
ap_rprintf(r, "DECLINED<br/>\r\n");
|
||||
return DECLINED;
|
||||
}*/
|
||||
/* AP_INIT_ITERATE("AuthBasicProvider", add_authn_provider, NULL, OR_AUTHCFG,
|
||||
"specify the auth providers for a directory or location"),*/
|
||||
AP_INIT_TAKE1("ABSECDefaultPerms", set_default_perms, NULL, OR_AUTHCFG,
|
||||
"Set to default octal value of perms "),
|
||||
AP_INIT_TAKE1("ABSECDefaultUID", set_default_uid, NULL, OR_AUTHCFG,
|
||||
"Set to default octal value of perms "),
|
||||
AP_INIT_TAKE1("ABSECDefaultGID", set_default_gid, NULL, OR_AUTHCFG,
|
||||
"Set to default octal value of perms "),
|
||||
/* AP_INIT_TAKE12("AuthBasicFake", add_basic_fake, NULL, OR_AUTHCFG,
|
||||
"Fake basic authentication using the given expressions for "
|
||||
"username and password, 'off' to disable. Password defaults "
|
||||
"to 'password' if missing."),
|
||||
AP_INIT_TAKE1("AuthBasicUseDigestAlgorithm", set_use_digest_algorithm,
|
||||
NULL, OR_AUTHCFG,
|
||||
"Set to 'MD5' to use the auth provider's authentication "
|
||||
"check for digest auth, using a hash of 'user:realm:pass'"),*/
|
||||
{NULL}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Validate authentification (user/pass)
|
||||
static authn_status authn_check_absec(request_rec *r, const char* user, const char* password)
|
||||
{
|
||||
ap_log_rerror("mod_absec.c", 269, 1, APLOG_ERR, APR_SUCCESS, r, "authn_check_absec : user : %s, pass : %s", user, password);
|
||||
|
||||
int pam_result = check_user(user, password);
|
||||
if ( (pam_result==PAM_ERROR_START) || (pam_result==PAM_ERROR_STOP) ) {
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
if (pam_result==PAM_ERROR_INVALID_CRED) {
|
||||
ap_log_rerror("mod_absec.c", 269, 1, APLOG_ERR, APR_SUCCESS, r, "authn_check_absec : DENIED");
|
||||
return AUTH_DENIED;
|
||||
}
|
||||
ap_log_rerror("mod_absec.c", 269, 1, APLOG_ERR, APR_SUCCESS, r, "authn_check_absec : GRANTED");
|
||||
return AUTH_GRANTED;
|
||||
|
||||
// Example code
|
||||
/*
|
||||
if (strcmp(user, "joe")) {
|
||||
return AUTH_USER_NOT_FOUND;
|
||||
} else {
|
||||
if (strcmp(password, "poi")) {
|
||||
return AUTH_DENIED;
|
||||
} else {
|
||||
return AUTH_GRANTED;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Possible return status
|
||||
// AUTH_GENERAL_ERROR
|
||||
// AUTH_USER_NOT_FOUND
|
||||
// AUTH_USER_FOUND
|
||||
// AUTH_DENIED
|
||||
// AUTH_GRANTED
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Validate autorisation (ressource access)
|
||||
// request_rec contain user/pass if basic auth
|
||||
// it could also contain cookies if cookies based auth
|
||||
static authz_status authz_check_absec(request_rec *r, const char *require_args, const void *parsed_require_args)
|
||||
{
|
||||
char *user = r->user;
|
||||
ap_log_rerror("mod_absec.c", 342, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : user : %s", user);
|
||||
|
||||
////////
|
||||
/* http method validate the perm asked (r/w vs get/post,put) */
|
||||
ap_rprintf(r, "Before Method: %s<br/>\r\n", r->method);
|
||||
//ap_rprintf(r, "Before Method: %s<br/>\r\n", r->method);
|
||||
|
||||
int permmask = 0;
|
||||
if (strcmp(r->method,"GET")==0) permmask=0444; // r
|
||||
@@ -109,167 +197,129 @@ static int absec_handler_first(request_rec *r)
|
||||
if (strcmp(r->method,"POST")==0) permmask=0222; // w
|
||||
if (strcmp(r->method,"DELETE")==0) permmask=0111; // x
|
||||
|
||||
authnz_config_rec *cfg = ap_get_module_config(r->per_dir_config, &absec_module);
|
||||
struct stat fperm;
|
||||
fperm.st_mode = cfg->default_perms;
|
||||
ap_log_rerror("mod_absec.c", 329, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : default perms : %o", cfg->default_perms);
|
||||
fperm.st_uid = cfg->default_uid;
|
||||
ap_log_rerror("mod_absec.c", 329, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : default uid : %o", cfg->default_uid);
|
||||
fperm.st_gid = cfg->default_gid;
|
||||
ap_log_rerror("mod_absec.c", 329, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : default gid : %o", cfg->default_gid);
|
||||
|
||||
////////
|
||||
/* check file permission on filesystem */
|
||||
/* should include <sys/stat.h> */
|
||||
struct stat fperm;
|
||||
int status;
|
||||
status = stat(r->filename, &fperm);
|
||||
//status = mysql_lookup(r, &fperm);
|
||||
//status = stat(r->filename, &fperm);
|
||||
status = perms_lookup(r, &fperm);
|
||||
//ap_rprintf(r, "Result mysql: %d<br/>\r\n", );
|
||||
if (status==-1) {
|
||||
ap_rprintf(r, "stat erreur %d", errno);
|
||||
ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : stat erreur %d", errno);
|
||||
return (OK);
|
||||
}
|
||||
|
||||
//ap_rprintf(r, "File perms %o, owner %d, group %d (status %d)<br/>\r\n", fperm.st_mode, fperm.st_uid, fperm.st_gid, status);
|
||||
|
||||
/* check if any permission (ogw) match method (get r, put/post w, delete x) */
|
||||
if ((fperm.st_mode & permmask)==0) {
|
||||
/* no permission match, return don't even have to check user perms */
|
||||
ap_rprintf(r, "Aucune permission pour la methode %s (%o, %o)", r->method, fperm.st_mode, permmask);
|
||||
return (OK);
|
||||
ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : Aucune permission pour la methode %s (%o, %o)", r->method, fperm.st_mode, permmask);
|
||||
return AUTHZ_DENIED;
|
||||
}
|
||||
|
||||
// If file is world accessible for asked method return content
|
||||
if (fperm.st_mode & 0x7 & permmask) {
|
||||
/* if so, return, no need to check user perms */
|
||||
//ap_rprintf(r, "Fichier public<br/>\r\n");
|
||||
return (DECLINED);
|
||||
ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : Fichier accessible a tous");
|
||||
return AUTHZ_GRANTED;
|
||||
}
|
||||
|
||||
////////
|
||||
/* Check if we have a basic auth user */
|
||||
const char* auth64p;
|
||||
// Check if we have an auth header
|
||||
auth64p = apr_table_get(r->headers_in,"Authorization");
|
||||
|
||||
// If no basic auth, ask for one
|
||||
if (auth64p==NULL) {
|
||||
r->content_type = "text/html";
|
||||
apr_table_setn(r->err_headers_out,
|
||||
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
|
||||
: "WWW-Authenticate",
|
||||
apr_pstrcat(r->pool, "Basic realm=\"PAS DE USER ", ap_auth_name(r),
|
||||
"\"", NULL));
|
||||
return HTTP_UNAUTHORIZED;
|
||||
if (!user) {
|
||||
ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : No user");
|
||||
return AUTHZ_DENIED_NO_USER;
|
||||
}
|
||||
|
||||
////////
|
||||
/* 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;
|
||||
auth64 = apr_pstrdup(r->pool, auth64p+6);
|
||||
char *auth;
|
||||
auth = apr_pcalloc(r->pool, 64);
|
||||
apr_base64_decode(auth, auth64);
|
||||
char *user;
|
||||
char *pass;
|
||||
user = apr_strtok(auth, ":", &pass);
|
||||
|
||||
r->content_type = "text/html";
|
||||
ap_rprintf(r, "Url: %s from %s \n<br/>", r->filename, r->uri);
|
||||
//ap_rprintf(r, "Headers Authorization: %s \n<br/>", auth64);
|
||||
//ap_rprintf(r, "User/Pass: %s/%s \n<br/>", user, pass);
|
||||
|
||||
int pam_result = pam_check_user(user, pass);
|
||||
if ( (pam_result==PAM_ERROR_START) || (pam_result==PAM_ERROR_STOP) ) {
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
if (pam_result==PAM_ERROR_INVALID_CRED) {
|
||||
r->content_type = "text/html";
|
||||
apr_table_setn(r->err_headers_out,
|
||||
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
|
||||
: "WWW-Authenticate",
|
||||
apr_pstrcat(r->pool, "Basic realm=\"USER/PASS INVALIDE ", ap_auth_name(r),
|
||||
"\"", NULL));
|
||||
return HTTP_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
////////
|
||||
// Continue checking permission
|
||||
|
||||
////////
|
||||
/* Retrieve user details from /etc/passwd to get uid and primary group */
|
||||
/* Should include <pwd.h> */
|
||||
struct passwd *pw;
|
||||
if((pw = getpwnam(user)) == NULL)
|
||||
{
|
||||
// Should never happend as already verified with PAM
|
||||
ap_rprintf(r, "NULL \n<br/>");
|
||||
apr_table_setn(r->err_headers_out,
|
||||
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
|
||||
: "WWW-Authenticate",
|
||||
apr_pstrcat(r->pool, "Basic realm=\"USER INCONNU ", ap_auth_name(r),
|
||||
"\"", NULL));
|
||||
// User cannot be found, unauthorized
|
||||
return HTTP_UNAUTHORIZED;
|
||||
}
|
||||
pw = getpwnam(user);
|
||||
|
||||
// If file is user readable and user match return content
|
||||
if ((fperm.st_uid==pw->pw_uid) && (fperm.st_mode & 0700 & permmask)) {
|
||||
ap_rprintf(r, "Fichier propriétaire<br/>\r\n");
|
||||
return (DECLINED);
|
||||
//ap_rprintf(r, "Fichier propriétaire<br/>\r\n");
|
||||
ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : Fichier propriétaire<br/>\r\n");
|
||||
return AUTHZ_GRANTED;
|
||||
} else {
|
||||
ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : No user access %d", pw->pw_uid);
|
||||
}
|
||||
|
||||
// If file is group readable and primary group match return content
|
||||
if ((fperm.st_gid==pw->pw_gid) && (fperm.st_mode & 0070 & permmask)) {
|
||||
ap_rprintf(r, "Fichier groupe<br/>\r\n");
|
||||
return (DECLINED);
|
||||
//ap_rprintf(r, "Fichier groupe<br/>\r\n");
|
||||
ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : Fichier groupe<br/>\r\n");
|
||||
return AUTHZ_GRANTED;
|
||||
} else {
|
||||
ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : No group access %d", pw->pw_gid);
|
||||
}
|
||||
|
||||
////////
|
||||
/* Check supplemental groups */
|
||||
/* Should include <grp.h> */
|
||||
//ap_rprintf(r, "Fichier propriétaire %d %d %o %o<br/>\r\n", fperm.st_uid, i, fperm.st_mode, 0400);
|
||||
// check supplemental groups
|
||||
gid_t grouplist[16];
|
||||
int grouplistsize = 16;
|
||||
int groupreturn;
|
||||
groupreturn = getgrouplist(user, pw->pw_gid, grouplist, &grouplistsize);
|
||||
if (groupreturn >= 0) {
|
||||
ap_rprintf(r, "OK liste des groupes (%d)<br/>\r\n", grouplistsize);
|
||||
ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : liste groups (%d)", grouplistsize);
|
||||
for (int i=0; i<grouplistsize; i++) {
|
||||
ap_rprintf(r, "group: %d\r\n", grouplist[i]);
|
||||
ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : group %d", grouplist[i]);
|
||||
// If file is group readable and match a supplemental group return content
|
||||
if ((fperm.st_gid==grouplist[i]) && (fperm.st_mode & 0070 & permmask)) {
|
||||
ap_rprintf(r, "Fichier groupe supplementaire<br/>\r\n");
|
||||
return (DECLINED);
|
||||
ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : Fichier group supp");
|
||||
return AUTHZ_GRANTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// else decline request
|
||||
ap_rprintf(r, "Aucuns droits de voir le fichier<br/>\r\n");
|
||||
apr_table_setn(r->err_headers_out,
|
||||
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
|
||||
: "WWW-Authenticate",
|
||||
apr_pstrcat(r->pool, "Basic realm=\"NON AUTHORISE", ap_auth_name(r),
|
||||
"\"", NULL));
|
||||
return HTTP_UNAUTHORIZED;
|
||||
ap_log_rerror("mod_absec.c", 282, 1, APLOG_ERR, APR_SUCCESS, r, "authz_check_absec : DENIED<br/>\r\n");
|
||||
return AUTHZ_DENIED;
|
||||
|
||||
if (r->user==NULL) {
|
||||
return AUTHZ_DENIED;
|
||||
}
|
||||
|
||||
return AUTHZ_GRANTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
static const authn_provider authn_absec_provider =
|
||||
{
|
||||
&authn_check_absec,
|
||||
NULL
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
static const authz_provider authz_absec_provider =
|
||||
{
|
||||
&authz_check_absec,
|
||||
NULL
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
static void absec_register_hooks(apr_pool_t *p)
|
||||
{
|
||||
//ap_hook_handler(absec_handler, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_handler(absec_handler_last, NULL, NULL, APR_HOOK_LAST);
|
||||
ap_hook_handler(absec_handler_first, NULL, NULL, APR_HOOK_FIRST);
|
||||
|
||||
// should use HOOK FIXUP
|
||||
|
||||
// should use FILTER
|
||||
ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "absec", "0", &authn_absec_provider, AP_AUTH_INTERNAL_PER_CONF);
|
||||
ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "absec", "0", &authz_absec_provider, AP_AUTH_INTERNAL_PER_CONF);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Dispatch list for API hooks */
|
||||
module AP_MODULE_DECLARE_DATA absec_module = {
|
||||
AP_DECLARE_MODULE(absec) = {
|
||||
STANDARD20_MODULE_STUFF,
|
||||
NULL, /* create per-dir config structures */
|
||||
authnz_absec_config, /* 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_auth_basic_cmds, /* table of config file commands */
|
||||
absec_register_hooks /* register hooks */
|
||||
};
|
||||
|
||||
|
||||
-378
@@ -1,378 +0,0 @@
|
||||
/*
|
||||
** 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
|
||||
** <Location /absec>
|
||||
** SetHandler absec
|
||||
** </Location>
|
||||
**
|
||||
** Then after restarting Apache via
|
||||
**
|
||||
** $ apachectl restart
|
||||
**
|
||||
*/
|
||||
|
||||
/*
|
||||
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 <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "apr_want.h"
|
||||
|
||||
#include <shadow.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Check user autentication against unix user/pass */
|
||||
static int check_autentication(request_rec *r)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Check check file perms */
|
||||
static int check_autorization(request_rec *r)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// define PAM callback function
|
||||
int mysql_lookup(request_rec *r, struct stat *fperm)
|
||||
{
|
||||
MYSQL *conn;
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
char *server = "localhost";
|
||||
char *user = "jlcyr";
|
||||
char *password = "password"; /* set me first */
|
||||
char *database = "absec";
|
||||
|
||||
conn = mysql_init(NULL);
|
||||
|
||||
/* Connect to database */
|
||||
if (!mysql_real_connect(conn, server,
|
||||
user, password, database, 0, NULL, 0)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
char query[256];
|
||||
sprintf(query, "select * from urls where url='%s'", r->uri);
|
||||
/* send SQL query */
|
||||
//if (mysql_query(conn, "show tables")) {
|
||||
if (mysql_query(conn, query)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
res = mysql_use_result(conn);
|
||||
|
||||
/* output table name */
|
||||
ap_rprintf(r, "MySQL data:\n<br/>");
|
||||
int cnt = 0;
|
||||
while ((row = mysql_fetch_row(res)) != NULL) {
|
||||
ap_rprintf(r, "%s %d %d %o \n<br/>", row[0], atoi(row[1]), atoi(row[2]), atoi(row[3]));
|
||||
fperm->st_uid = atoi(row[1]);
|
||||
fperm->st_gid = atoi(row[2]);
|
||||
fperm->st_mode = atoi(row[3]);
|
||||
cnt = cnt + 1;
|
||||
}
|
||||
|
||||
if (cnt==0) {
|
||||
sprintf(query, "insert into urls (url, uid, gid, perms) values ('%s', 0, 0, 0)", r->uri);
|
||||
if (mysql_query(conn, query)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(0);
|
||||
}
|
||||
ap_rprintf(r, "Aucune donnee\n<br/>");
|
||||
}
|
||||
|
||||
/* close connection */
|
||||
mysql_free_result(res);
|
||||
mysql_close(conn);
|
||||
return(0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Main routine */
|
||||
static int absec_handler_last(request_rec *r)
|
||||
{
|
||||
// Is this module really called?
|
||||
if (strcmp(r->handler, "absec")) {
|
||||
return DECLINED;
|
||||
}
|
||||
r->content_type = "text/html";
|
||||
//ap_rprintf(r, "The sample page from mod_absec.c %s \n<br/>", r->args);
|
||||
ap_rprintf(r, "After Url: %s from %s \n<br/>", r->filename, r->uri);
|
||||
return (OK);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Main routine */
|
||||
static int absec_handler_first(request_rec *r)
|
||||
{
|
||||
// Is this module really called?
|
||||
if (strcmp(r->handler, "absec")) {
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
////////
|
||||
/* http method validate the perm asked (r/w vs get/post,put) */
|
||||
ap_rprintf(r, "Method: %s<br/>\r\n", r->method);
|
||||
int permmask = 0;
|
||||
if (strcmp(r->method,"GET")==0) permmask=0444; // r
|
||||
if (strcmp(r->method,"PUT")==0) permmask=0222; // w
|
||||
if (strcmp(r->method,"POST")==0) permmask=0222; // w
|
||||
if (strcmp(r->method,"DELETE")==0) permmask=0111; // x
|
||||
|
||||
////////
|
||||
/* check file permission on filesystem */
|
||||
/* should include <sys/stat.h> */
|
||||
struct stat fperm;
|
||||
int status;
|
||||
//status = stat(r->filename, &fperm);
|
||||
status = mysql_lookup(r, &fperm);
|
||||
//ap_rprintf(r, "Result mysql: %d<br/>\r\n", );
|
||||
if (status==-1) {
|
||||
ap_rprintf(r, "stat erreur %d", errno);
|
||||
return (OK);
|
||||
}
|
||||
//ap_rprintf(r, "File perms %o, owner %d, group %d (status %d)<br/>\r\n", fperm.st_mode, fperm.st_uid, fperm.st_gid, status);
|
||||
|
||||
/* check if any permission (ogw) match method (get r, put/post w, delete x) */
|
||||
if ((fperm.st_mode & permmask)==0) {
|
||||
/* no permission match, return don't even have to check user perms */
|
||||
//ap_rprintf(r, "Aucune permission pour la methode %s (%o, %o)", r->method, fperm.st_mode, permmask);
|
||||
return (OK);
|
||||
}
|
||||
|
||||
// If file is world accessible for asked method return content
|
||||
// TODO : if put/post/delete, must check BEFORE ACTION not AFTER!!!
|
||||
if (fperm.st_mode & 0x7 & permmask) {
|
||||
/* if so, return, no need to check user perms */
|
||||
//ap_rprintf(r, "Fichier public<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
////////
|
||||
/* Check if we have a basic auth user */
|
||||
const char* auth64p;
|
||||
// Check if we have an auth header
|
||||
auth64p = apr_table_get(r->headers_in,"Authorization");
|
||||
|
||||
// If no basic auth, ask for one
|
||||
if (auth64p==NULL) {
|
||||
r->content_type = "text/html";
|
||||
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;
|
||||
auth64 = apr_pstrdup(r->pool, auth64p+6);
|
||||
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);
|
||||
|
||||
r->content_type = "text/html";
|
||||
//ap_rprintf(r, "The sample page from mod_absec.c %s \n<br/>", r->args);
|
||||
ap_rprintf(r, "Url: %s from %s \n<br/>", r->filename, r->uri);
|
||||
//ap_rprintf(r, "Headers Authorization: %s \n<br/>", auth64);
|
||||
//ap_rprintf(r, "User/Pass: %s/%s \n<br/>", user, pass);
|
||||
|
||||
////////
|
||||
// Get UID, GIDs for the user
|
||||
/* 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<br/>", g,i);
|
||||
|
||||
////////
|
||||
/* Retrieve PW from /etc/passwd */
|
||||
/* Should include <pwd.h> */
|
||||
struct passwd *pw;
|
||||
if((pw = getpwnam(user)) == NULL)
|
||||
{
|
||||
ap_rprintf(r, "NULL \n<br/>");
|
||||
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<br/>", pw->pw_passwd);
|
||||
}
|
||||
|
||||
////////
|
||||
/* Retrieve PW from /etc/shadow */
|
||||
/* Should include <shadow.h> */
|
||||
struct spwd *spw;
|
||||
errno = 0;
|
||||
if((spw = getspnam(user)) == NULL)
|
||||
{
|
||||
ap_rprintf(r, "NULL %d\n<br/>", 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<br/>", 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<br/>", encrypted);;
|
||||
ap_rprintf(r, "compare : %d \n<br/>", 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;
|
||||
}
|
||||
|
||||
|
||||
// If file is user readable and user match return content
|
||||
if ((fperm.st_uid==i) && (fperm.st_mode & 0700 & permmask)) {
|
||||
ap_rprintf(r, "Fichier propriétaire<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
// If file is group readable and primary group match return content
|
||||
if ((fperm.st_gid==g) && (fperm.st_mode & 0070 & permmask)) {
|
||||
ap_rprintf(r, "Fichier groupe<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
// now check supplemental groups
|
||||
//ap_rprintf(r, "Fichier propriétaire %d %d %o %o<br/>\r\n", fperm.st_uid, i, fperm.st_mode, 0400);
|
||||
gid_t grouplist[16];
|
||||
int grouplistsize = 16;
|
||||
int *groupreturn;
|
||||
groupreturn = getgrouplist("jlcyr", g, grouplist, &grouplistsize);
|
||||
if (groupreturn != -1) {
|
||||
ap_rprintf(r, "OK liste des groupes (%d)<br/>\r\n", grouplistsize);
|
||||
for (i=0; i<grouplistsize; i++) {
|
||||
ap_rprintf(r, "group: %d\r\n", grouplist[i]);
|
||||
// If file is group readable and match a supplemental group return content
|
||||
if ((fperm.st_gid==grouplist[i]) && (fperm.st_mode & 0070 & permmask)) {
|
||||
ap_rprintf(r, "Fichier groupe supplementaire<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ap_rprintf(r, "Erreur<br/>\r\n");
|
||||
return OK;
|
||||
}
|
||||
|
||||
// else decline
|
||||
ap_rprintf(r, "Aucuns droits de voir le fichier<br/>\r\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;
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
static void absec_register_hooks(apr_pool_t *p)
|
||||
{
|
||||
//ap_hook_handler(absec_handler, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_handler(absec_handler_last, NULL, NULL, APR_HOOK_LAST);
|
||||
ap_hook_handler(absec_handler_first, NULL, NULL, APR_HOOK_FIRST);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
-378
@@ -1,378 +0,0 @@
|
||||
/*
|
||||
** 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
|
||||
** <Location /absec>
|
||||
** SetHandler absec
|
||||
** </Location>
|
||||
**
|
||||
** Then after restarting Apache via
|
||||
**
|
||||
** $ apachectl restart
|
||||
**
|
||||
*/
|
||||
|
||||
/*
|
||||
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 <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "apr_want.h"
|
||||
|
||||
#include <shadow.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Check user autentication against unix user/pass */
|
||||
static int check_autentication(request_rec *r)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Check check file perms */
|
||||
static int check_autorization(request_rec *r)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// define PAM callback function
|
||||
int mysql_lookup(request_rec *r, struct stat *fperm)
|
||||
{
|
||||
MYSQL *conn;
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
char *server = "localhost";
|
||||
char *user = "jlcyr";
|
||||
char *password = "password"; /* set me first */
|
||||
char *database = "absec";
|
||||
|
||||
conn = mysql_init(NULL);
|
||||
|
||||
/* Connect to database */
|
||||
if (!mysql_real_connect(conn, server,
|
||||
user, password, database, 0, NULL, 0)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
char query[256];
|
||||
sprintf(query, "select * from urls where url='%s'", r->uri);
|
||||
/* send SQL query */
|
||||
//if (mysql_query(conn, "show tables")) {
|
||||
if (mysql_query(conn, query)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
res = mysql_use_result(conn);
|
||||
|
||||
/* output table name */
|
||||
ap_rprintf(r, "MySQL data:\n<br/>");
|
||||
int cnt = 0;
|
||||
while ((row = mysql_fetch_row(res)) != NULL) {
|
||||
ap_rprintf(r, "%s %d %d %o \n<br/>", row[0], atoi(row[1]), atoi(row[2]), atoi(row[3]));
|
||||
fperm->st_uid = atoi(row[1]);
|
||||
fperm->st_gid = atoi(row[2]);
|
||||
fperm->st_mode = atoi(row[3]);
|
||||
cnt = cnt + 1;
|
||||
}
|
||||
|
||||
if (cnt==0) {
|
||||
sprintf(query, "insert into urls (url, uid, gid, perms) values ('%s', 0, 0, 0)", r->uri);
|
||||
if (mysql_query(conn, query)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(0);
|
||||
}
|
||||
ap_rprintf(r, "Aucune donnee\n<br/>");
|
||||
}
|
||||
|
||||
/* close connection */
|
||||
mysql_free_result(res);
|
||||
mysql_close(conn);
|
||||
return(0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Main routine */
|
||||
static int absec_handler_last(request_rec *r)
|
||||
{
|
||||
// Is this module really called?
|
||||
if (strcmp(r->handler, "absec")) {
|
||||
return DECLINED;
|
||||
}
|
||||
r->content_type = "text/html";
|
||||
//ap_rprintf(r, "The sample page from mod_absec.c %s \n<br/>", r->args);
|
||||
ap_rprintf(r, "After Url: %s from %s \n<br/>", r->filename, r->uri);
|
||||
return (OK);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Main routine */
|
||||
static int absec_handler_first(request_rec *r)
|
||||
{
|
||||
// Is this module really called?
|
||||
if (strcmp(r->handler, "absec")) {
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
////////
|
||||
/* http method validate the perm asked (r/w vs get/post,put) */
|
||||
ap_rprintf(r, "Method: %s<br/>\r\n", r->method);
|
||||
int permmask = 0;
|
||||
if (strcmp(r->method,"GET")==0) permmask=0444; // r
|
||||
if (strcmp(r->method,"PUT")==0) permmask=0222; // w
|
||||
if (strcmp(r->method,"POST")==0) permmask=0222; // w
|
||||
if (strcmp(r->method,"DELETE")==0) permmask=0111; // x
|
||||
|
||||
////////
|
||||
/* check file permission on filesystem */
|
||||
/* should include <sys/stat.h> */
|
||||
struct stat fperm;
|
||||
int status;
|
||||
//status = stat(r->filename, &fperm);
|
||||
status = mysql_lookup(r, &fperm);
|
||||
//ap_rprintf(r, "Result mysql: %d<br/>\r\n", );
|
||||
if (status==-1) {
|
||||
ap_rprintf(r, "stat erreur %d", errno);
|
||||
return (OK);
|
||||
}
|
||||
//ap_rprintf(r, "File perms %o, owner %d, group %d (status %d)<br/>\r\n", fperm.st_mode, fperm.st_uid, fperm.st_gid, status);
|
||||
|
||||
/* check if any permission (ogw) match method (get r, put/post w, delete x) */
|
||||
if ((fperm.st_mode & permmask)==0) {
|
||||
/* no permission match, return don't even have to check user perms */
|
||||
//ap_rprintf(r, "Aucune permission pour la methode %s (%o, %o)", r->method, fperm.st_mode, permmask);
|
||||
return (OK);
|
||||
}
|
||||
|
||||
// If file is world accessible for asked method return content
|
||||
// TODO : if put/post/delete, must check BEFORE ACTION not AFTER!!!
|
||||
if (fperm.st_mode & 0x7 & permmask) {
|
||||
/* if so, return, no need to check user perms */
|
||||
//ap_rprintf(r, "Fichier public<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
////////
|
||||
/* Check if we have a basic auth user */
|
||||
const char* auth64p;
|
||||
// Check if we have an auth header
|
||||
auth64p = apr_table_get(r->headers_in,"Authorization");
|
||||
|
||||
// If no basic auth, ask for one
|
||||
if (auth64p==NULL) {
|
||||
r->content_type = "text/html";
|
||||
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;
|
||||
auth64 = apr_pstrdup(r->pool, auth64p+6);
|
||||
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);
|
||||
|
||||
r->content_type = "text/html";
|
||||
//ap_rprintf(r, "The sample page from mod_absec.c %s \n<br/>", r->args);
|
||||
ap_rprintf(r, "Url: %s from %s \n<br/>", r->filename, r->uri);
|
||||
//ap_rprintf(r, "Headers Authorization: %s \n<br/>", auth64);
|
||||
//ap_rprintf(r, "User/Pass: %s/%s \n<br/>", user, pass);
|
||||
|
||||
////////
|
||||
// Get UID, GIDs for the user
|
||||
/* 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<br/>", g,i);
|
||||
|
||||
////////
|
||||
/* Retrieve PW from /etc/passwd */
|
||||
/* Should include <pwd.h> */
|
||||
struct passwd *pw;
|
||||
if((pw = getpwnam(user)) == NULL)
|
||||
{
|
||||
ap_rprintf(r, "NULL \n<br/>");
|
||||
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<br/>", pw->pw_passwd);
|
||||
}
|
||||
|
||||
////////
|
||||
/* Retrieve PW from /etc/shadow */
|
||||
/* Should include <shadow.h> */
|
||||
struct spwd *spw;
|
||||
errno = 0;
|
||||
if((spw = getspnam(user)) == NULL)
|
||||
{
|
||||
ap_rprintf(r, "NULL %d\n<br/>", 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<br/>", 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<br/>", encrypted);;
|
||||
ap_rprintf(r, "compare : %d \n<br/>", 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;
|
||||
}
|
||||
|
||||
|
||||
// If file is user readable and user match return content
|
||||
if ((fperm.st_uid==i) && (fperm.st_mode & 0700 & permmask)) {
|
||||
ap_rprintf(r, "Fichier propriétaire<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
// If file is group readable and primary group match return content
|
||||
if ((fperm.st_gid==g) && (fperm.st_mode & 0070 & permmask)) {
|
||||
ap_rprintf(r, "Fichier groupe<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
// now check supplemental groups
|
||||
//ap_rprintf(r, "Fichier propriétaire %d %d %o %o<br/>\r\n", fperm.st_uid, i, fperm.st_mode, 0400);
|
||||
gid_t grouplist[16];
|
||||
int grouplistsize = 16;
|
||||
int *groupreturn;
|
||||
groupreturn = getgrouplist("jlcyr", g, grouplist, &grouplistsize);
|
||||
if (groupreturn != -1) {
|
||||
ap_rprintf(r, "OK liste des groupes (%d)<br/>\r\n", grouplistsize);
|
||||
for (i=0; i<grouplistsize; i++) {
|
||||
ap_rprintf(r, "group: %d\r\n", grouplist[i]);
|
||||
// If file is group readable and match a supplemental group return content
|
||||
if ((fperm.st_gid==grouplist[i]) && (fperm.st_mode & 0070 & permmask)) {
|
||||
ap_rprintf(r, "Fichier groupe supplementaire<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ap_rprintf(r, "Erreur<br/>\r\n");
|
||||
return OK;
|
||||
}
|
||||
|
||||
// else decline
|
||||
ap_rprintf(r, "Aucuns droits de voir le fichier<br/>\r\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;
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
static void absec_register_hooks(apr_pool_t *p)
|
||||
{
|
||||
//ap_hook_handler(absec_handler, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_handler(absec_handler_last, NULL, NULL, APR_HOOK_LAST);
|
||||
ap_hook_handler(absec_handler_first, NULL, NULL, APR_HOOK_FIRST);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
-388
@@ -1,388 +0,0 @@
|
||||
/*
|
||||
** mod_absec.c -- Apache absec module
|
||||
** [base 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 -lpam -lpam_misc -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
|
||||
** <Location /absec>
|
||||
** SetHandler absec
|
||||
** </Location>
|
||||
**
|
||||
** Then after restarting Apache via
|
||||
**
|
||||
** $ apachectl restart
|
||||
**
|
||||
*/
|
||||
|
||||
/*
|
||||
TEST URL
|
||||
http://10.211.55.15/absec/<fichier>
|
||||
|
||||
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 <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "apr_want.h"
|
||||
|
||||
#include <shadow.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_misc.h>
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Check user autentication against unix user/pass */
|
||||
static int check_autentication(request_rec *r)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Check check file perms */
|
||||
static int check_autorization(request_rec *r)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Global var for passing fake response to PAM callback
|
||||
struct pam_response *reply;
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// PAM response callback function
|
||||
int converse(int n, const struct pam_message **msg,
|
||||
struct pam_response **resp, void *data)
|
||||
{
|
||||
// Return globally set response
|
||||
*resp = reply;
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// define PAM callback function
|
||||
struct pam_conv conv = { converse, 0 };
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// define PAM callback function
|
||||
int mysql_lookup(request_rec *r, struct stat *fperm)
|
||||
{
|
||||
MYSQL *conn;
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
char *server = "localhost";
|
||||
char *user = "jlcyr";
|
||||
char *password = "password"; /* set me first */
|
||||
char *database = "absec";
|
||||
|
||||
conn = mysql_init(NULL);
|
||||
|
||||
/* Connect to database */
|
||||
if (!mysql_real_connect(conn, server,
|
||||
user, password, database, 0, NULL, 0)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
char query[256];
|
||||
sprintf(query, "select * from urls where url='%s'", r->uri);
|
||||
/* send SQL query */
|
||||
//if (mysql_query(conn, "show tables")) {
|
||||
if (mysql_query(conn, query)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
res = mysql_use_result(conn);
|
||||
|
||||
/* output table name */
|
||||
ap_rprintf(r, "MySQL data:\n<br/>");
|
||||
int cnt = 0;
|
||||
while ((row = mysql_fetch_row(res)) != NULL) {
|
||||
ap_rprintf(r, "%s %d %d %o \n<br/>", row[0], atoi(row[1]), atoi(row[2]), atoi(row[3]));
|
||||
fperm->st_uid = atoi(row[1]);
|
||||
fperm->st_gid = atoi(row[2]);
|
||||
fperm->st_mode = atoi(row[3]);
|
||||
cnt = cnt + 1;
|
||||
}
|
||||
|
||||
if (cnt==0) {
|
||||
sprintf(query, "insert into urls (url, uid, gid, perms) values ('%s', 0, 0, 0)", r->uri);
|
||||
if (mysql_query(conn, query)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(0);
|
||||
}
|
||||
ap_rprintf(r, "Aucune donnee\n<br/>");
|
||||
}
|
||||
|
||||
/* close connection */
|
||||
mysql_free_result(res);
|
||||
mysql_close(conn);
|
||||
return(0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Main routine - called after request processing */
|
||||
static int absec_handler_last(request_rec *r)
|
||||
{
|
||||
// Is this module really called?
|
||||
if (strcmp(r->handler, "absec")) {
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
////////
|
||||
/* http method validate the perm asked (r/w vs get/post,put) */
|
||||
ap_rprintf(r, "After Method: %s<br/>\r\n", r->method);
|
||||
int permmask = 0;
|
||||
if (strcmp(r->method,"GET")!=0)
|
||||
{
|
||||
// Not a GET, it's too late to do anything
|
||||
ap_rprintf(r, "Not a GET post treatement is too late!\n<br/>");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
r->content_type = "text/html";
|
||||
//ap_rprintf(r, "The sample page from mod_absec.c %s \n<br/>", r->args);
|
||||
ap_rprintf(r, "After GET Url: %s from %s \n<br/>", r->filename, r->uri);
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Main routine - called before request processing */
|
||||
static int absec_handler_first(request_rec *r)
|
||||
{
|
||||
ap_rprintf(r, "Before Method: %s<br/>\r\n", r->method);
|
||||
// Is this module really called?
|
||||
/*if (strcmp(r->handler, "absec")) {
|
||||
ap_rprintf(r, "DECLINED<br/>\r\n");
|
||||
return DECLINED;
|
||||
}*/
|
||||
|
||||
|
||||
////////
|
||||
/* http method validate the perm asked (r/w vs get/post,put) */
|
||||
ap_rprintf(r, "Before Method: %s<br/>\r\n", r->method);
|
||||
|
||||
int permmask = 0;
|
||||
if (strcmp(r->method,"GET")==0) permmask=0444; // r
|
||||
if (strcmp(r->method,"PUT")==0) permmask=0222; // w
|
||||
if (strcmp(r->method,"POST")==0) permmask=0222; // w
|
||||
if (strcmp(r->method,"DELETE")==0) permmask=0111; // x
|
||||
|
||||
////////
|
||||
/* check file permission on filesystem */
|
||||
/* should include <sys/stat.h> */
|
||||
struct stat fperm;
|
||||
int status;
|
||||
//status = stat(r->filename, &fperm);
|
||||
status = mysql_lookup(r, &fperm);
|
||||
//ap_rprintf(r, "Result mysql: %d<br/>\r\n", );
|
||||
if (status==-1) {
|
||||
ap_rprintf(r, "stat erreur %d", errno);
|
||||
return (OK);
|
||||
}
|
||||
//ap_rprintf(r, "File perms %o, owner %d, group %d (status %d)<br/>\r\n", fperm.st_mode, fperm.st_uid, fperm.st_gid, status);
|
||||
|
||||
/* check if any permission (ogw) match method (get r, put/post w, delete x) */
|
||||
if ((fperm.st_mode & permmask)==0) {
|
||||
/* no permission match, return don't even have to check user perms */
|
||||
ap_rprintf(r, "Aucune permission pour la methode %s (%o, %o)", r->method, fperm.st_mode, permmask);
|
||||
return (OK);
|
||||
}
|
||||
|
||||
// If file is world accessible for asked method return content
|
||||
if (fperm.st_mode & 0x7 & permmask) {
|
||||
/* if so, return, no need to check user perms */
|
||||
//ap_rprintf(r, "Fichier public<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
////////
|
||||
/* Check if we have a basic auth user */
|
||||
const char* auth64p;
|
||||
// Check if we have an auth header
|
||||
auth64p = apr_table_get(r->headers_in,"Authorization");
|
||||
|
||||
// If no basic auth, ask for one
|
||||
if (auth64p==NULL) {
|
||||
r->content_type = "text/html";
|
||||
apr_table_setn(r->err_headers_out,
|
||||
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
|
||||
: "WWW-Authenticate",
|
||||
apr_pstrcat(r->pool, "Basic realm=\"PAS DE USER ", 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;
|
||||
auth64 = apr_pstrdup(r->pool, auth64p+6);
|
||||
char *auth;
|
||||
auth = apr_pcalloc(r->pool, 64);
|
||||
apr_base64_decode(auth, auth64);
|
||||
char *user;
|
||||
char *pass;
|
||||
user = apr_strtok(auth, ":", &pass);
|
||||
|
||||
r->content_type = "text/html";
|
||||
ap_rprintf(r, "Url: %s from %s \n<br/>", r->filename, r->uri);
|
||||
//ap_rprintf(r, "Headers Authorization: %s \n<br/>", auth64);
|
||||
//ap_rprintf(r, "User/Pass: %s/%s \n<br/>", user, pass);
|
||||
|
||||
////////
|
||||
// Connect to PAM to auth user
|
||||
pam_handle_t * pamh = NULL;
|
||||
int rret;
|
||||
|
||||
if((rret = pam_start("httpd", user/*pw->pw_name*/, &conv, &pamh)) != PAM_SUCCESS) {
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
printf("Pam start failed\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Set the PAM callback function response (would call for password)
|
||||
reply = (struct pam_response *)malloc(sizeof(struct pam_response));
|
||||
reply[0].resp = strdup(pass); // password received in basic auth
|
||||
reply[0].resp_retcode = 0;
|
||||
|
||||
if((rret = pam_authenticate(pamh, 0)) != PAM_SUCCESS) {
|
||||
r->content_type = "text/html";
|
||||
apr_table_setn(r->err_headers_out,
|
||||
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
|
||||
: "WWW-Authenticate",
|
||||
apr_pstrcat(r->pool, "Basic realm=\"USER/PASS INVALIDE ", ap_auth_name(r),
|
||||
"\"", NULL));
|
||||
return HTTP_UNAUTHORIZED;
|
||||
printf("User auth failed\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if(pam_end(pamh, rret) != PAM_SUCCESS) {
|
||||
//perror("pam_end");
|
||||
pamh = NULL;
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
////////
|
||||
// Continue checking permission
|
||||
|
||||
////////
|
||||
/* Retrieve user details from /etc/passwd to get uid and primary group */
|
||||
/* Should include <pwd.h> */
|
||||
struct passwd *pw;
|
||||
if((pw = getpwnam(user)) == NULL)
|
||||
{
|
||||
// Should never happend as already verified with PAM
|
||||
ap_rprintf(r, "NULL \n<br/>");
|
||||
apr_table_setn(r->err_headers_out,
|
||||
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
|
||||
: "WWW-Authenticate",
|
||||
apr_pstrcat(r->pool, "Basic realm=\"USER INCONNU ", ap_auth_name(r),
|
||||
"\"", NULL));
|
||||
// User cannot be found, unauthorized
|
||||
return HTTP_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
// If file is user readable and user match return content
|
||||
if ((fperm.st_uid==pw->pw_uid) && (fperm.st_mode & 0700 & permmask)) {
|
||||
ap_rprintf(r, "Fichier propriétaire<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
// If file is group readable and primary group match return content
|
||||
if ((fperm.st_gid==pw->pw_gid) && (fperm.st_mode & 0070 & permmask)) {
|
||||
ap_rprintf(r, "Fichier groupe<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
////////
|
||||
/* Check supplemental groups */
|
||||
/* Should include <grp.h> */
|
||||
//ap_rprintf(r, "Fichier propriétaire %d %d %o %o<br/>\r\n", fperm.st_uid, i, fperm.st_mode, 0400);
|
||||
gid_t grouplist[16];
|
||||
int grouplistsize = 16;
|
||||
int groupreturn;
|
||||
groupreturn = getgrouplist(user, pw->pw_gid, grouplist, &grouplistsize);
|
||||
if (groupreturn >= 0) {
|
||||
ap_rprintf(r, "OK liste des groupes (%d)<br/>\r\n", grouplistsize);
|
||||
for (int i=0; i<grouplistsize; i++) {
|
||||
ap_rprintf(r, "group: %d\r\n", grouplist[i]);
|
||||
// If file is group readable and match a supplemental group return content
|
||||
if ((fperm.st_gid==grouplist[i]) && (fperm.st_mode & 0070 & permmask)) {
|
||||
ap_rprintf(r, "Fichier groupe supplementaire<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// else decline request
|
||||
ap_rprintf(r, "Aucuns droits de voir le fichier<br/>\r\n");
|
||||
apr_table_setn(r->err_headers_out,
|
||||
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
|
||||
: "WWW-Authenticate",
|
||||
apr_pstrcat(r->pool, "Basic realm=\"NON AUTHORISE", ap_auth_name(r),
|
||||
"\"", NULL));
|
||||
return HTTP_UNAUTHORIZED;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
static void absec_register_hooks(apr_pool_t *p)
|
||||
{
|
||||
//ap_hook_handler(absec_handler, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_handler(absec_handler_last, NULL, NULL, APR_HOOK_LAST);
|
||||
ap_hook_handler(absec_handler_first, NULL, NULL, APR_HOOK_FIRST);
|
||||
|
||||
// should use HOOK FIXUP
|
||||
|
||||
// should use FILTER
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
-388
@@ -1,388 +0,0 @@
|
||||
/*
|
||||
** mod_absec.c -- Apache absec module
|
||||
** [base 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 -lpam -lpam_misc -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
|
||||
** <Location /absec>
|
||||
** SetHandler absec
|
||||
** </Location>
|
||||
**
|
||||
** Then after restarting Apache via
|
||||
**
|
||||
** $ apachectl restart
|
||||
**
|
||||
*/
|
||||
|
||||
/*
|
||||
TEST URL
|
||||
http://10.211.55.15/absec/<fichier>
|
||||
|
||||
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 <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "apr_want.h"
|
||||
|
||||
#include <shadow.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_misc.h>
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Check user autentication against unix user/pass */
|
||||
static int check_autentication(request_rec *r)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Check check file perms */
|
||||
static int check_autorization(request_rec *r)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Global var for passing fake response to PAM callback
|
||||
struct pam_response *reply;
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// PAM response callback function
|
||||
int converse(int n, const struct pam_message **msg,
|
||||
struct pam_response **resp, void *data)
|
||||
{
|
||||
// Return globally set response
|
||||
*resp = reply;
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// define PAM callback function
|
||||
struct pam_conv conv = { converse, 0 };
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// define PAM callback function
|
||||
int mysql_lookup(request_rec *r, struct stat *fperm)
|
||||
{
|
||||
MYSQL *conn;
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
char *server = "localhost";
|
||||
char *user = "jlcyr";
|
||||
char *password = "password"; /* set me first */
|
||||
char *database = "absec";
|
||||
|
||||
conn = mysql_init(NULL);
|
||||
|
||||
/* Connect to database */
|
||||
if (!mysql_real_connect(conn, server,
|
||||
user, password, database, 0, NULL, 0)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
char query[256];
|
||||
sprintf(query, "select * from urls where url='%s'", r->uri);
|
||||
/* send SQL query */
|
||||
//if (mysql_query(conn, "show tables")) {
|
||||
if (mysql_query(conn, query)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
res = mysql_use_result(conn);
|
||||
|
||||
/* output table name */
|
||||
ap_rprintf(r, "MySQL data:\n<br/>");
|
||||
int cnt = 0;
|
||||
while ((row = mysql_fetch_row(res)) != NULL) {
|
||||
ap_rprintf(r, "%s %d %d %o \n<br/>", row[0], atoi(row[1]), atoi(row[2]), atoi(row[3]));
|
||||
fperm->st_uid = atoi(row[1]);
|
||||
fperm->st_gid = atoi(row[2]);
|
||||
fperm->st_mode = atoi(row[3]);
|
||||
cnt = cnt + 1;
|
||||
}
|
||||
|
||||
if (cnt==0) {
|
||||
sprintf(query, "insert into urls (url, uid, gid, perms) values ('%s', 0, 0, 0)", r->uri);
|
||||
if (mysql_query(conn, query)) {
|
||||
ap_rprintf(r, "%s\n<br/>", mysql_error(conn));
|
||||
return(0);
|
||||
}
|
||||
ap_rprintf(r, "Aucune donnee\n<br/>");
|
||||
}
|
||||
|
||||
/* close connection */
|
||||
mysql_free_result(res);
|
||||
mysql_close(conn);
|
||||
return(0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Main routine - called after request processing */
|
||||
static int absec_handler_last(request_rec *r)
|
||||
{
|
||||
// Is this module really called?
|
||||
if (strcmp(r->handler, "absec")) {
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
////////
|
||||
/* http method validate the perm asked (r/w vs get/post,put) */
|
||||
ap_rprintf(r, "After Method: %s<br/>\r\n", r->method);
|
||||
int permmask = 0;
|
||||
if (strcmp(r->method,"GET")!=0)
|
||||
{
|
||||
// Not a GET, it's too late to do anything
|
||||
ap_rprintf(r, "Not a GET post treatement is too late!\n<br/>");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
r->content_type = "text/html";
|
||||
//ap_rprintf(r, "The sample page from mod_absec.c %s \n<br/>", r->args);
|
||||
ap_rprintf(r, "After GET Url: %s from %s \n<br/>", r->filename, r->uri);
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* Main routine - called before request processing */
|
||||
static int absec_handler_first(request_rec *r)
|
||||
{
|
||||
ap_rprintf(r, "Before Method: %s<br/>\r\n", r->method);
|
||||
// Is this module really called?
|
||||
/*if (strcmp(r->handler, "absec")) {
|
||||
ap_rprintf(r, "DECLINED<br/>\r\n");
|
||||
return DECLINED;
|
||||
}*/
|
||||
|
||||
|
||||
////////
|
||||
/* http method validate the perm asked (r/w vs get/post,put) */
|
||||
ap_rprintf(r, "Before Method: %s<br/>\r\n", r->method);
|
||||
|
||||
int permmask = 0;
|
||||
if (strcmp(r->method,"GET")==0) permmask=0444; // r
|
||||
if (strcmp(r->method,"PUT")==0) permmask=0222; // w
|
||||
if (strcmp(r->method,"POST")==0) permmask=0222; // w
|
||||
if (strcmp(r->method,"DELETE")==0) permmask=0111; // x
|
||||
|
||||
////////
|
||||
/* check file permission on filesystem */
|
||||
/* should include <sys/stat.h> */
|
||||
struct stat fperm;
|
||||
int status;
|
||||
//status = stat(r->filename, &fperm);
|
||||
status = mysql_lookup(r, &fperm);
|
||||
//ap_rprintf(r, "Result mysql: %d<br/>\r\n", );
|
||||
if (status==-1) {
|
||||
ap_rprintf(r, "stat erreur %d", errno);
|
||||
return (OK);
|
||||
}
|
||||
//ap_rprintf(r, "File perms %o, owner %d, group %d (status %d)<br/>\r\n", fperm.st_mode, fperm.st_uid, fperm.st_gid, status);
|
||||
|
||||
/* check if any permission (ogw) match method (get r, put/post w, delete x) */
|
||||
if ((fperm.st_mode & permmask)==0) {
|
||||
/* no permission match, return don't even have to check user perms */
|
||||
ap_rprintf(r, "Aucune permission pour la methode %s (%o, %o)", r->method, fperm.st_mode, permmask);
|
||||
return (OK);
|
||||
}
|
||||
|
||||
// If file is world accessible for asked method return content
|
||||
if (fperm.st_mode & 0x7 & permmask) {
|
||||
/* if so, return, no need to check user perms */
|
||||
//ap_rprintf(r, "Fichier public<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
////////
|
||||
/* Check if we have a basic auth user */
|
||||
const char* auth64p;
|
||||
// Check if we have an auth header
|
||||
auth64p = apr_table_get(r->headers_in,"Authorization");
|
||||
|
||||
// If no basic auth, ask for one
|
||||
if (auth64p==NULL) {
|
||||
r->content_type = "text/html";
|
||||
apr_table_setn(r->err_headers_out,
|
||||
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
|
||||
: "WWW-Authenticate",
|
||||
apr_pstrcat(r->pool, "Basic realm=\"PAS DE USER ", 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;
|
||||
auth64 = apr_pstrdup(r->pool, auth64p+6);
|
||||
char *auth;
|
||||
auth = apr_pcalloc(r->pool, 64);
|
||||
apr_base64_decode(auth, auth64);
|
||||
char *user;
|
||||
char *pass;
|
||||
user = apr_strtok(auth, ":", &pass);
|
||||
|
||||
r->content_type = "text/html";
|
||||
ap_rprintf(r, "Url: %s from %s \n<br/>", r->filename, r->uri);
|
||||
//ap_rprintf(r, "Headers Authorization: %s \n<br/>", auth64);
|
||||
//ap_rprintf(r, "User/Pass: %s/%s \n<br/>", user, pass);
|
||||
|
||||
////////
|
||||
// Connect to PAM to auth user
|
||||
pam_handle_t * pamh = NULL;
|
||||
int rret;
|
||||
|
||||
if((rret = pam_start("httpd", user/*pw->pw_name*/, &conv, &pamh)) != PAM_SUCCESS) {
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
printf("Pam start failed\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Set the PAM callback function response (would call for password)
|
||||
reply = (struct pam_response *)malloc(sizeof(struct pam_response));
|
||||
reply[0].resp = strdup(pass); // password received in basic auth
|
||||
reply[0].resp_retcode = 0;
|
||||
|
||||
if((rret = pam_authenticate(pamh, 0)) != PAM_SUCCESS) {
|
||||
r->content_type = "text/html";
|
||||
apr_table_setn(r->err_headers_out,
|
||||
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
|
||||
: "WWW-Authenticate",
|
||||
apr_pstrcat(r->pool, "Basic realm=\"USER/PASS INVALIDE ", ap_auth_name(r),
|
||||
"\"", NULL));
|
||||
return HTTP_UNAUTHORIZED;
|
||||
printf("User auth failed\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if(pam_end(pamh, rret) != PAM_SUCCESS) {
|
||||
//perror("pam_end");
|
||||
pamh = NULL;
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
////////
|
||||
// Continue checking permission
|
||||
|
||||
////////
|
||||
/* Retrieve user details from /etc/passwd to get uid and primary group */
|
||||
/* Should include <pwd.h> */
|
||||
struct passwd *pw;
|
||||
if((pw = getpwnam(user)) == NULL)
|
||||
{
|
||||
// Should never happend as already verified with PAM
|
||||
ap_rprintf(r, "NULL \n<br/>");
|
||||
apr_table_setn(r->err_headers_out,
|
||||
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
|
||||
: "WWW-Authenticate",
|
||||
apr_pstrcat(r->pool, "Basic realm=\"USER INCONNU ", ap_auth_name(r),
|
||||
"\"", NULL));
|
||||
// User cannot be found, unauthorized
|
||||
return HTTP_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
// If file is user readable and user match return content
|
||||
if ((fperm.st_uid==pw->pw_uid) && (fperm.st_mode & 0700 & permmask)) {
|
||||
ap_rprintf(r, "Fichier propriétaire<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
// If file is group readable and primary group match return content
|
||||
if ((fperm.st_gid==pw->pw_gid) && (fperm.st_mode & 0070 & permmask)) {
|
||||
ap_rprintf(r, "Fichier groupe<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
////////
|
||||
/* Check supplemental groups */
|
||||
/* Should include <grp.h> */
|
||||
//ap_rprintf(r, "Fichier propriétaire %d %d %o %o<br/>\r\n", fperm.st_uid, i, fperm.st_mode, 0400);
|
||||
gid_t grouplist[16];
|
||||
int grouplistsize = 16;
|
||||
int groupreturn;
|
||||
groupreturn = getgrouplist(user, pw->pw_gid, grouplist, &grouplistsize);
|
||||
if (groupreturn >= 0) {
|
||||
ap_rprintf(r, "OK liste des groupes (%d)<br/>\r\n", grouplistsize);
|
||||
for (int i=0; i<grouplistsize; i++) {
|
||||
ap_rprintf(r, "group: %d\r\n", grouplist[i]);
|
||||
// If file is group readable and match a supplemental group return content
|
||||
if ((fperm.st_gid==grouplist[i]) && (fperm.st_mode & 0070 & permmask)) {
|
||||
ap_rprintf(r, "Fichier groupe supplementaire<br/>\r\n");
|
||||
return (DECLINED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// else decline request
|
||||
ap_rprintf(r, "Aucuns droits de voir le fichier<br/>\r\n");
|
||||
apr_table_setn(r->err_headers_out,
|
||||
(PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate"
|
||||
: "WWW-Authenticate",
|
||||
apr_pstrcat(r->pool, "Basic realm=\"NON AUTHORISE", ap_auth_name(r),
|
||||
"\"", NULL));
|
||||
return HTTP_UNAUTHORIZED;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
static void absec_register_hooks(apr_pool_t *p)
|
||||
{
|
||||
//ap_hook_handler(absec_handler, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_handler(absec_handler_last, NULL, NULL, APR_HOOK_LAST);
|
||||
ap_hook_handler(absec_handler_first, NULL, NULL, APR_HOOK_FIRST);
|
||||
|
||||
// should use HOOK FIXUP
|
||||
|
||||
// should use FILTER
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# projet absec |
|
||||
|
||||
## Jean-Luc Cyr
|
||||
## 2019
|
||||
|
||||
module d'abstraction de l'authentification et de l'autorisation du code applicatif d'un site web
|
||||
|
||||
[Site Web du Projet](http://absec.adninformatique.com/)
|
||||
|
||||
Le projet dépend pour être compilé de
|
||||
|
||||
* libpam_dev
|
||||
* libapr1-dev
|
||||
* libaprutil-dev
|
||||
* apache2-dev
|
||||
* libmysqlclient-dev
|
||||
|
||||
Un script de compilation est disponible
|
||||
|
||||
```bash
|
||||
compile.sh
|
||||
```
|
||||
|
||||
Le projet consiste principalement en un module pour Apache 2.x ce module peut être compilé pour utiliser
|
||||
|
||||
l'authentification:
|
||||
* via les fichiers systèmes /etc/passwd, /etc/shadow, /etc/group
|
||||
* via l'utilisation de PAM
|
||||
|
||||
les autorisations:
|
||||
* via le système de fichier (permissions unix) map url-fichier
|
||||
* via une base de donnée MySQL map url-entrée dans la bd
|
||||
|
||||
l'authentification a une entête commune soit absec_authen.h
|
||||
et à l'étape de liaison (link) l'on utilise soit absec_etc ou absec_pam
|
||||
|
||||
un outil de test pour l'un ou l'autre selon la liaison est disponible
|
||||
sous test_authen
|
||||
|
||||
l'autorisation a une entête commune soit absec_auto.h
|
||||
et à l'étape de liaison (link) l'on utilise soit absec_fs ou absec_mysql
|
||||
|
||||
un outil de test pour l'un ou l'autre selon la liaison est disponible
|
||||
sous test_auto
|
||||
|
||||
[Mémoire de maîtrise](https://constellation.uqac.ca/id/eprint/5228/1/Cyr_uqac_0862N_10581.pdf)
|
||||
https://constellation.uqac.ca/id/eprint/5228/1/Cyr_uqac_0862N_10581.pdf
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
| projet absec |
|
||||
| module d'abstraction de l'authentification et de |
|
||||
| l'autorisation du code applicatif d'un site web |
|
||||
| |
|
||||
| Projet : http://absec.adninformatique.com/ |
|
||||
| Jean-Luc Cyr - 2019 |
|
||||
+-------------------------------------------------------+
|
||||
|
||||
Le projet dépend pour être compilé de
|
||||
@@ -9,6 +12,7 @@ Le projet dépend pour être compilé de
|
||||
* libapr1-dev
|
||||
* libaprutil-dev
|
||||
* apache2-dev
|
||||
* libmysqlclient-dev
|
||||
|
||||
Un script de compilation est disponible
|
||||
compile.sh
|
||||
@@ -34,3 +38,4 @@ et à l'étape de liaison (link) l'on utilise soit absec_fs ou absec_mysql
|
||||
un outil de test pour l'un ou l'autre selon la liaison est disponible
|
||||
sous test_auto
|
||||
|
||||
Ref : https://constellation.uqac.ca/id/eprint/5228/1/Cyr_uqac_0862N_10581.pdf
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
/////
|
||||
//
|
||||
// File : test_authen.c
|
||||
// Author : Jean-Luc Cyr
|
||||
// Date : 2018-10
|
||||
//
|
||||
// Description: authentification method test file
|
||||
//
|
||||
|
||||
//#include "absec_pam.h"
|
||||
//#include "absec_etc.h"
|
||||
#include "absec_authen.h"
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/////
|
||||
//
|
||||
// File : test_auto.c
|
||||
// Author : Jean-Luc Cyr
|
||||
// Date : 2018-10
|
||||
//
|
||||
// Description: autorisation method test file
|
||||
//
|
||||
|
||||
#include "absec_auto.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include "httpd.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
int main() {
|
||||
|
||||
struct request_rec r;
|
||||
struct stat fperm;
|
||||
|
||||
char* filename = "/var/www/html/absec/test.php";
|
||||
r.filename=malloc(strlen(filename));
|
||||
strcpy(r.filename, filename);
|
||||
char* uri = "/absec/test.php";
|
||||
r.uri=malloc(strlen(uri));
|
||||
strcpy(r.uri, uri);
|
||||
|
||||
printf("ABSEC auto perms for file %s or uri %s\r\n", r.filename, r.uri);
|
||||
|
||||
perms_lookup(&r, &fperm);
|
||||
|
||||
printf("Perms: %o\r\n", fperm.st_mode);
|
||||
|
||||
printf("Test completed\r\n");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
/*
|
||||
printf("Retval: %d\r\n", retval);
|
||||
if (retval == PAM_ERROR_START) printf("Error at start\r\n");
|
||||
if (retval == PAM_ERROR_INVALID_CRED) printf("Invalid user/pass\r\n");
|
||||
if (retval == PAM_OK) printf("OK\r\n");
|
||||
*/
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
#include "absec_pam.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void main(int argc, char** argv){
|
||||
char *user = "jlcyr";
|
||||
char *pass = "jlcyrpass01!";
|
||||
printf("ABSEC auth etc for %s identified by %s\r\n", user, pass);
|
||||
int retval;
|
||||
retval = check_user(user, pass);
|
||||
printf("Retval: %d\r\n", retval);
|
||||
if (retval == PAM_ERROR_START) printf("Error at start\r\n");
|
||||
if (retval == PAM_ERROR_INVALID_CRED) printf("Invalid user/pass\r\n");
|
||||
if (retval == PAM_OK) printf("OK\r\n");
|
||||
printf("Test completed\r\n");
|
||||
return;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
|
||||
|
||||
|
||||
#include <mysql.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
MYSQL *conn;
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
|
||||
char *server = "localhost";
|
||||
char *user = "jlcyr";
|
||||
char *password = "password"; /* set me first */
|
||||
char *database = "absec";
|
||||
|
||||
conn = mysql_init(NULL);
|
||||
|
||||
/* Connect to database */
|
||||
if (!mysql_real_connect(conn, server,
|
||||
user, password, database, 0, NULL, 0)) {
|
||||
fprintf(stderr, "%s\n", mysql_error(conn));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* send SQL query */
|
||||
if (mysql_query(conn, "show tables")) {
|
||||
fprintf(stderr, "%s\n", mysql_error(conn));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
res = mysql_use_result(conn);
|
||||
|
||||
/* output table name */
|
||||
printf("MySQL Tables in mysql database:\n");
|
||||
while ((row = mysql_fetch_row(res)) != NULL)
|
||||
printf("%s \n", row[0]);
|
||||
|
||||
/* close connection */
|
||||
mysql_free_result(res);
|
||||
mysql_close(conn);
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
#include "absec_pam.h"
|
||||
#include "absec_etc.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void main(int argc, char** argv){
|
||||
char *user = "jlcyr";
|
||||
char *pass = "jlcyrpass01!";
|
||||
printf("ABSEC auth pam for %s identified by %s\r\n", user, pass);
|
||||
int retval = check_user(user, pass);
|
||||
printf("Retval: %d\r\n", retval);
|
||||
if (retval == PAM_ERROR_START) printf("Error at start\r\n");
|
||||
if (retval == PAM_ERROR_INVALID_CRED) printf("Invalid user/pass\r\n");
|
||||
if (retval == PAM_OK) printf("OK\r\n");
|
||||
printf("Test completed\r\n");
|
||||
return;
|
||||
}
|
||||
Reference in New Issue
Block a user