Apache module development by extending existing mod_basic_auth
This below mentioned step by step procedure help you to create apache module to protected your digital good.
Step 1: Prerequisite
1.1 Install apache2 webserversudo apt-get install apache21.2 Install apache compiler using the below mentioned command.sudo apt-get install apache2-threaded-dev1.3 Install latest libcurl package using the below mentioned command.sudo apt-get install libcurl4-openssl-dev
Step 2: Create a simple apache module c file and compile it using the below mentioned command.
apxs2 -c mod_paypal_ec.c (for debian OS)apxs -c mod_paypal_ec.c (for mac OS)
Step 3: Apache load config file
Create test_ec.load config file under /etc/apache2/mods-availableLoadFile /usr/lib/x86_64-linux-gnu/libcurl.so LoadModule mod_test_ec /Users/csivakolundu/mod_test_ec/src/.libs/mod_test_ec.so <Location /books> AuthType EC AuthName "Test EC" Require valid-user </Location>
Step 4: Apache config file
Create test_ec.conf config file under /etc/apache2/mods-available with all your application properties which are going to referred in your c file.ApiUserName aaaaaa_1350334651_biz_api1.paypal.com ApiPassword 1350334729
Step 5: Enabling mod_test_ec module
Create symbolic link for test_ec.load and test_ec.conf files under /etc/apache2/mods-enable/ folder.Step 6: Apache virtual host
Update apache virtual host file from /etc/apache2/sites-enabled/ with the following changes.<IfModule mod_paypal_ec> <Location /books> AuthType ExpressCheckout AuthName "PayPal ExpressCheckout" Require valid-user </Location> </IfModule>
Step 7: Simple mod_test_ec.c file.
Simple apache c file to protected your digital good available under /var/www/books folder. Auth check is not done in the below example.
#include "httpd.h" #include "http_config.h" #include "http_core.h" #include "http_log.h" #include "http_main.h" #include "http_protocol.h" #include "http_request.h" #include "util_script.h" #include "mod_auth.h" #include <stdio.h> #include <string.h> #include <stdlib.h> #include <curl/curl.h> #include <curl/easy.h> typedef struct { const char* endPoint; const char* userName; const char* password; const char* ecType; }app_config; static app_config config; int ec_handler(request_rec *r); void register_hooks(apr_pool_t *p); int sendFile(request_rec *r, apr_table_t *data); static int authenticate_user(request_rec *r); const char *api_endpoint_handler(cmd_parms *cmd, void *cfg, const char *arg) { config.endPoint= arg; return NULL; } const char *api_username_handler(cmd_parms *cmd, void *cfg, const char *arg) { config.userName= arg; return NULL; } const char *apr_password_handler(cmd_parms *cmd, void *cfg, const char *arg) { config.password= arg; return NULL; } const char *ec_type_handler(cmd_parms *cmd, void *cfg, const char *arg) { config.ecType = arg; return NULL; } static const command_rec ec_directives[] = { AP_INIT_TAKE1("ApiEndPoint", api_endpoint_handler, NULL, RSRC_CONF, "The mod_paypal_ec application configuration file"), AP_INIT_TAKE1("ApiUserName", api_username_handler, NULL, RSRC_CONF, "The mod_paypal_ec application configuration file"), AP_INIT_TAKE1("ApiPassword", apr_password_handler, NULL, RSRC_CONF, "The mod_paypal_ec application configuration file"), AP_INIT_TAKE1("ECType", ec_type_handler, NULL, RSRC_CONF, "The mod_paypal_ec application configuration file"), {NULL} }; module AP_MODULE_DECLARE_DATA mod_test_ec = { STANDARD20_MODULE_STUFF, NULL, NULL, NULL, NULL, ec_directives, register_hooks }; void register_hooks(apr_pool_t *p) { ap_hook_check_user_id(authenticate_user,NULL,NULL,APR_HOOK_MIDDLE); } static int authenticate_user(request_rec *r) { const char *sent_user, *sent_pw, *current_auth; int res; authn_status auth_result; ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Authenticate_user starting...."); current_auth = ap_auth_type(r); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Current auth %s", current_auth); if (!current_auth || strcasecmp(current_auth, "EC")) { return DECLINED; } ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "After auth check"); /* We need an authentication realm. */ if (!ap_auth_name(r)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "need AuthName: %s", r->uri); return HTTP_INTERNAL_SERVER_ERROR; } ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "After auth name check"); r->ap_auth_type = "EC"; ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Calling ec handler"); return ec_handler(r); } int ec_handler(request_rec *r) { char *next = r->uri; char *uri = r->unparsed_uri; if ( r->method_number != M_GET ) { return HTTP_METHOD_NOT_ALLOWED ; } status = sendFile(r, data); if(status > 0) { return HTTP_INTERNAL_SERVER_ERROR; } return OK; } int sendFile(request_rec *r, apr_table_t *data) { int status = 0; apr_file_t *fd; apr_size_t sz; apr_status_t rv; if (r->filename == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,"Incomplete request_rec!"); status = 1; return status; } char* ext = strrchr(r->filename, '.') ; if(strcmp(ext, ".pdf") ==0) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Downloading pdf file"); ap_set_content_type(r, "application/pdf"); } else { ap_set_content_type(r, "application/pdf"); } ap_set_content_length(r, r->finfo.size); //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "File size : %zu", r-> finfo.size); if (r->finfo.mtime) { char *datestring = apr_palloc(r->pool, APR_RFC822_DATE_LEN); apr_rfc822_date(datestring, r->finfo.mtime); apr_table_setn(r->headers_out, "Last-Modified", datestring); } rv = apr_file_open(&fd, r->filename, APR_READ|APR_SHARELOCK|APR_SENDFILE_ENABLED, APR_OS_DEFAULT, r->pool); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,"can't open %s", r->filename); return HTTP_NOT_FOUND ; } ap_send_fd(fd, r, 0, r->finfo.size, &sz); apr_file_close(fd); return status; }
Step 8: For Mac only.
4.1 Update the libcurl.so path from paypal_ec.load to "LoadFile /usr/lib/libcurl.4.dylib"
4.2 Create Simbolic link like below.
$> cd /Applications/Xcode.app/Contents/Developer/Toolchains/
$> sudo ln -s XcodeDefault.xctoolchain/ OSX10.8.xctoolchain