Tuesday, May 7, 2013

Apache module development to protect digital good.

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 webserver 
               sudo apt-get install apache2 
    1.2 Install apache compiler using the below mentioned command.
               sudo apt-get install apache2-threaded-dev 
    1.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-available



LoadFile /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








No comments:

Post a Comment