Advertisement
Guest User

mod_authnz_external.c

a guest
Aug 30th, 2018
484
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 30.29 KB | None | 0 0
  1. /* ====================================================================
  2.  * Copyright (c) 1995 The Apache Group.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  *
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in
  13.  *    the documentation and/or other materials provided with the
  14.  *    distribution.
  15.  *
  16.  * 3. All advertising materials mentioning features or use of this
  17.  *    software must display the following acknowledgment:
  18.  *    "This product includes software developed by the Apache Group
  19.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  20.  *
  21.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  22.  *    endorse or promote products derived from this software without
  23.  *    prior written permission.
  24.  *
  25.  * 5. Redistributions of any form whatsoever must retain the following
  26.  *    acknowledgment:
  27.  *    "This product includes software developed by the Apache Group
  28.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  29.  *
  30.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  31.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  33.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  34.  * IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  41.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  42.  * ====================================================================
  43.  *
  44.  * This software consists of voluntary contributions made by many
  45.  * individuals on behalf of the Apache Group and was originally based
  46.  * on public domain software written at the National Center for
  47.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  48.  * For more information on the Apache Group and the Apache HTTP server
  49.  * project, please see <http://www.apache.org/>.
  50.  *
  51.  */
  52.  
  53. /* Uncomment if you want to use a HARDCODE'd check (default off) */
  54. #define _HARDCODE_
  55.  
  56. #ifdef _HARDCODE_
  57.   #include <stdlib.h>
  58.   #include <string.h>
  59.   int my_authentication(char *user_name, const char *user_passwd, char *config_path){
  60.     char command[100] = "perl C:\\Apache24\\htdocs\\authenticator.pl ";
  61.     strcat(command, user_name);
  62.     char space[4] = " ";
  63.     strcat(command, space);
  64.     strcat(command, user_passwd);
  65.  
  66.     return system(command);
  67.   }
  68. #endif
  69.  
  70.  
  71. #include "apr_lib.h"
  72.  
  73. #include "ap_config.h"
  74. #include "ap_provider.h"
  75. #include "mod_auth.h"
  76. #include "apr_signal.h"
  77.  
  78. #define APR_WANT_STRFUNC
  79. #include "apr_want.h"
  80. #include "apr_strings.h"
  81. #include "apr_sha1.h"
  82.  
  83. #include "httpd.h"
  84. #include "http_config.h"
  85. #include "http_core.h"
  86. #include "http_log.h"
  87. #include "http_protocol.h"
  88. #include "http_request.h"   /* for ap_hook_(check_user_id | auth_checker)*/
  89. #if APR_HAVE_UNISTD_H
  90. #include <unistd.h>
  91. #endif
  92.  
  93. #ifndef STANDARD20_MODULE_STUFF
  94. #error This module requires Apache 2.2.0 or later.
  95. #endif
  96.  
  97. /* Names of environment variables used to pass data to authenticator */
  98. #define ENV_USER    "USER"
  99. #define ENV_PASS    "PASS"
  100. #define ENV_GROUP   "GROUP"
  101. #define ENV_URI     "URI"
  102. #define ENV_IP      "IP"
  103. #define ENV_HOST    "HOST"      /* Remote Host */
  104. #define ENV_HTTP_HOST   "HTTP_HOST" /* Local Host */
  105. #define ENV_CONTEXT "CONTEXT"   /* Arbitrary Data from Config */
  106. /* Undefine this if you do not want cookies passed to the script */
  107. #define ENV_COOKIE  "COOKIE"
  108.  
  109. /* Maximum number of arguments passed to an authenticator */
  110. #define MAX_ARG 32
  111.  
  112. /* Default authentication method - "pipe", "environment" or "checkpass" */
  113. #define DEFAULT_METHOD "pipe"
  114.  
  115. /*
  116.  * Structure for the module itself.  The actual definition of this structure
  117.  * is at the end of the file.
  118.  */
  119. module AP_MODULE_DECLARE_DATA authnz_external_module;
  120.  
  121. /*
  122.  *  Data types for per-directory and per-server configuration
  123.  */
  124.  
  125. typedef struct
  126. {
  127.     apr_array_header_t *auth_name; /* Auth keyword for current dir */
  128.     char *group_name;        /* Group keyword for current dir */
  129.     char *context;       /* Context string from AuthExternalContext */
  130.     int  groupsatonce;       /* Check all groups in one call? */
  131.     int  providecache;       /* Provide auth data to mod_authn_socache? */
  132.  
  133. } authnz_external_dir_config_rec;
  134.  
  135.  
  136. typedef struct
  137. {
  138.     apr_table_t *auth_path;  /* Hash mapping auth keywords to paths */
  139.     apr_table_t *auth_method;    /* Hash mapping auth keywords to methods */
  140.  
  141.     apr_table_t *group_path;     /* Hash mapping group keywords to paths */
  142.     apr_table_t *group_method;   /* Hash mapping group keywords to methods */
  143.  
  144. } authnz_external_svr_config_rec;
  145.  
  146.  
  147. /* mod_authz_owner's function for retrieving the requested file's group */
  148. APR_DECLARE_OPTIONAL_FN(char*, authz_owner_get_file_group, (request_rec *r));
  149. APR_OPTIONAL_FN_TYPE(authz_owner_get_file_group) *authz_owner_get_file_group;
  150.  
  151. /* mod_authn_socache's function for adding credentials to its cache */
  152. static APR_OPTIONAL_FN_TYPE(ap_authn_cache_store) *authn_cache_store = NULL;
  153.  
  154.  
  155. /* Creators for per-dir and server configurations.  These are called
  156.  * via the hooks in the module declaration to allocate and initialize
  157.  * the per-directory and per-server configuration data structures declared
  158.  * above. */
  159.  
  160. static void *create_authnz_external_dir_config(apr_pool_t *p, char *d)
  161. {
  162.     authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
  163.     apr_palloc(p, sizeof(authnz_external_dir_config_rec));
  164.  
  165.     dir->auth_name= apr_array_make(p,2,sizeof(const char *)); /* no default */
  166.     dir->group_name= NULL;  /* no default */
  167.     dir->context= NULL;     /* no default */
  168.     dir->groupsatonce= 1;   /* default to on */
  169.     dir->providecache= 0;   /* default to off */
  170.     return dir;
  171. }
  172.  
  173. static void *create_authnz_external_svr_config( apr_pool_t *p, server_rec *s)
  174. {
  175.     authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
  176.     apr_palloc(p, sizeof(authnz_external_svr_config_rec));
  177.  
  178.     svr->auth_method=  apr_table_make(p, 4);
  179.     svr->auth_path=    apr_table_make(p, 4);
  180.     svr->group_method= apr_table_make(p, 4);
  181.     svr->group_path=   apr_table_make(p, 4);
  182.     /* Note: 4 is only initial hash size - they can grow bigger) */
  183.  
  184.     return (void *)svr;
  185. }
  186.  
  187. /* Handler for a DefineExternalAuth server config line */
  188. static const char *def_extauth(cmd_parms *cmd, void *dummy, const char *keyword,
  189.                 const char *method, const char *path)
  190. {
  191.     authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
  192.     ap_get_module_config( cmd->server->module_config,
  193.         &authnz_external_module);
  194.  
  195.     apr_table_set( svr->auth_path,   keyword, path );
  196.     apr_table_set( svr->auth_method, keyword, method );
  197.  
  198.     return NULL;
  199. }
  200.  
  201.  
  202. /* Handler for a DefineExternalGroup server config line */
  203. static const char *def_extgroup(cmd_parms *cmd, void *dummy,
  204.     const char *keyword, const char *method, const char *path)
  205. {
  206.     authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
  207.     ap_get_module_config( cmd->server->module_config,
  208.         &authnz_external_module);
  209.  
  210.     apr_table_set( svr->group_path,   keyword, path );
  211.     apr_table_set( svr->group_method, keyword, method );
  212.  
  213.     return NULL;
  214. }
  215.  
  216.  
  217.  
  218. /* Handler for a AddExternalAuth server config line - add a external auth
  219.  * type to the server configuration */
  220. static const char *add_extauth(cmd_parms *cmd, void *dummy, const char *keyword,
  221.                 const char *path)
  222. {
  223.     authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
  224.     ap_get_module_config( cmd->server->module_config,
  225.         &authnz_external_module);
  226.  
  227.     apr_table_set( svr->auth_path,   keyword, path );
  228.     apr_table_set( svr->auth_method, keyword, DEFAULT_METHOD );
  229.  
  230.     return NULL;
  231. }
  232.  
  233.  
  234. /* Handler for a AddExternalGroup server config line - add a external group
  235.  * type to the server configuration */
  236. static const char *add_extgroup(cmd_parms *cmd, void *dummy,
  237.                 const char *keyword, const char *path)
  238. {
  239.     authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
  240.     ap_get_module_config( cmd->server->module_config,
  241.         &authnz_external_module);
  242.  
  243.     apr_table_set( svr->group_path,   keyword, path );
  244.     apr_table_set( svr->group_method, keyword, DEFAULT_METHOD );
  245.  
  246.     return NULL;
  247. }
  248.  
  249. /* Handler for a SetExternalAuthMethod server config line - change an external
  250.  * auth method in the server configuration */
  251. static const char *set_authnz_external_method(cmd_parms *cmd, void *dummy,
  252.                     const char *keyword, const char *method)
  253. {
  254.     authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
  255.     ap_get_module_config( cmd->server->module_config,
  256.         &authnz_external_module);
  257.  
  258.     apr_table_set( svr->auth_method, keyword, method );
  259.  
  260.     return NULL;
  261. }
  262.  
  263.  
  264. /* Handler for a SetExternalGroupMethod server config line - change an external
  265.  * group method in the server configuration */
  266. static const char *set_extgroup_method(cmd_parms *cmd, void *dummy,
  267.                     const char *keyword, const char *method)
  268. {
  269.     authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
  270.     ap_get_module_config( cmd->server->module_config,
  271.         &authnz_external_module);
  272.  
  273.     apr_table_set( svr->group_method, keyword, method );
  274.  
  275.     return NULL;
  276. }
  277.  
  278. /* Append an argument to an array defined by the offset */
  279. static const char *append_array_slot(cmd_parms *cmd, void *struct_ptr,
  280.                 const char *arg)
  281. {
  282.     int offset = (int)(long)cmd->info;
  283.     apr_array_header_t *array=
  284.         *(apr_array_header_t **)((char *)struct_ptr + offset);
  285.  
  286.     *(const char **)apr_array_push(array)= apr_pstrdup(array->pool, arg);
  287.  
  288.     return NULL;
  289. }
  290.  
  291.  
  292. /* Config file directives for this module */
  293. static const command_rec authnz_external_cmds[] =
  294. {
  295.     AP_INIT_ITERATE("AuthExternal",
  296.     append_array_slot,
  297.     (void *)APR_OFFSETOF(authnz_external_dir_config_rec,auth_name),
  298.     OR_AUTHCFG,
  299.     "one (or more) keywords indicating which authenticators to use"),
  300.  
  301.     AP_INIT_TAKE3("DefineExternalAuth",
  302.     def_extauth,
  303.     NULL,
  304.     RSRC_CONF,
  305.     "a keyword followed by auth method and path to authentictor"),
  306.  
  307.     AP_INIT_TAKE2("AddExternalAuth",
  308.     add_extauth,
  309.     NULL,
  310.     RSRC_CONF,
  311.     "a keyword followed by a path to the authenticator program"),
  312.  
  313.     AP_INIT_TAKE2("SetExternalAuthMethod",
  314.     set_authnz_external_method,
  315.     NULL,
  316.     RSRC_CONF,
  317.     "a keyword followed by the method by which the data is passed"),
  318.  
  319.     AP_INIT_TAKE1("GroupExternal",
  320.     ap_set_string_slot,
  321.     (void *)APR_OFFSETOF(authnz_external_dir_config_rec, group_name),
  322.     OR_AUTHCFG,
  323.     "a keyword indicating which group checker to use"),
  324.  
  325.     AP_INIT_TAKE3("DefineExternalGroup",
  326.     def_extgroup,
  327.     NULL,
  328.     RSRC_CONF,
  329.     "a keyword followed by auth method type and path to group checker"),
  330.  
  331.     AP_INIT_TAKE2("AddExternalGroup",
  332.     add_extgroup,
  333.     NULL,
  334.     RSRC_CONF,
  335.     "a keyword followed by a path to the group check program"),
  336.  
  337.     AP_INIT_TAKE2("SetExternalGroupMethod",
  338.     set_extgroup_method,
  339.     NULL,
  340.     RSRC_CONF,
  341.     "a keyword followed by the method by which the data is passed"),
  342.  
  343.     AP_INIT_TAKE1("AuthExternalContext",
  344.     ap_set_string_slot,
  345.     (void *)APR_OFFSETOF(authnz_external_dir_config_rec, context),
  346.     OR_AUTHCFG,
  347.     "An arbitrary context string to pass to the authenticator in the "
  348.     ENV_CONTEXT " environment variable"),
  349.  
  350.     AP_INIT_FLAG("AuthExternalProvideCache",
  351.     ap_set_flag_slot,
  352.     (void *)APR_OFFSETOF(authnz_external_dir_config_rec, providecache),
  353.     OR_AUTHCFG,
  354.     "Should we forge authentication credentials for mod_authn_socache?"),
  355.  
  356.     AP_INIT_FLAG("GroupExternalManyAtOnce",
  357.     ap_set_flag_slot,
  358.     (void *)APR_OFFSETOF(authnz_external_dir_config_rec, groupsatonce),
  359.     OR_AUTHCFG,
  360.     "Set to 'off' if group authenticator cannot handle multiple group "
  361.         "names in one invocation" ),
  362.  
  363.     AP_INIT_FLAG("AuthExternalGroupsAtOnce",
  364.     ap_set_flag_slot,
  365.     (void *)APR_OFFSETOF(authnz_external_dir_config_rec, groupsatonce),
  366.     OR_AUTHCFG,
  367.     "Old version of 'GroupExternalManyAtOnce'" ),
  368.  
  369.     { NULL }
  370. };
  371.  
  372.  
  373. /* Called from apr_proc_create() if there are errors during launch of child
  374.  * process.  Mostly just lifted from mod_cgi. */
  375. static void extchilderr(apr_pool_t *p, apr_status_t err, const char *desc)
  376. {
  377.     apr_file_t *stderr_log;
  378.     char errbuf[200];
  379.     apr_file_open_stderr(&stderr_log, p);
  380.     apr_file_printf(stderr_log,"%s: (%d) %s\n", ap_escape_logitem(p,desc),
  381.     err, apr_strerror(err,errbuf,sizeof(errbuf)));
  382. }
  383.  
  384.  
  385. /* Run an external authentication program using the given method for passing
  386.  * in the data.  The login name is always passed in.   Dataname is "GROUP" or
  387.  * "PASS" and data is the group list or password being checked.  To launch
  388.  * a detached daemon, run this with extmethod=NULL.
  389.  *
  390.  * If the authenticator was run, we return the numeric code from the
  391.  * authenticator, normally 0 if the login was valid, some small positive
  392.  * number if not.  If we were not able to run the authenticator, we log
  393.  * an error message and return a numeric error code:
  394.  *
  395.  *   -1   Could not execute authenticator, usually a path or permission problem
  396.  *   -2   The external authenticator crashed or was killed.
  397.  *   -3   Could not create process attribute structure
  398.  *   -4   apr_proc_wait() did not return a status code.  Should never happen.
  399.  *   -5   apr_proc_wait() returned before child finished.  Should never happen.
  400.  */
  401. static int exec_external(const char *extpath, const char *extmethod,
  402.         const request_rec *r, const char *dataname, const char *data)
  403. {
  404.     conn_rec *c= r->connection;
  405.     apr_pool_t *p= r->pool;
  406.     int isdaemon, usecheck= 0, usepipeout= 0, usepipein= 0;
  407.     apr_procattr_t *procattr;
  408.     apr_proc_t proc;
  409.     apr_status_t rc= APR_SUCCESS;
  410.     char *child_env[12];
  411.     char *child_arg[MAX_ARG+2];
  412.     const char *t;
  413.     int i, status= -4;
  414.     apr_exit_why_e why= APR_PROC_EXIT;
  415.  
  416.     /* Set various flags based on the execution method */
  417.  
  418.     isdaemon= (extmethod == NULL);
  419.     if (!isdaemon)
  420.     {
  421.     usecheck= extmethod && !strcasecmp(extmethod, "checkpassword");
  422.     usepipeout= usecheck || (extmethod && !strcasecmp(extmethod, "pipes"));
  423.     usepipein= usepipeout || (extmethod && !strcasecmp(extmethod, "pipe"));
  424.     }
  425.  
  426.     /* Create the environment for the child.  Daemons don't get these, they
  427.      * just inherit apache's environment variables.
  428.      */
  429.  
  430.     if (!isdaemon)
  431.     {
  432.     const char *cookie, *host, *remote_host;
  433.     authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
  434.         ap_get_module_config(r->per_dir_config, &authnz_external_module);
  435.     i= 0;
  436.  
  437.     if (!usepipein)
  438.     {
  439.         /* Put user name and password/group into environment */
  440.         child_env[i++]= apr_pstrcat(p, ENV_USER"=", r->user, NULL);
  441.         child_env[i++]= apr_pstrcat(p, dataname, "=", data, NULL);
  442.     }
  443.  
  444.     child_env[i++]= apr_pstrcat(p, "PATH=", getenv("PATH"), NULL);
  445.  
  446.     child_env[i++]= apr_pstrcat(p, "AUTHTYPE=", dataname, NULL);
  447.  
  448.     remote_host= ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST,NULL);
  449.     if (remote_host != NULL)
  450.         child_env[i++]= apr_pstrcat(p, ENV_HOST"=", remote_host,NULL);
  451.  
  452.     if (r->useragent_ip)
  453.         child_env[i++]= apr_pstrcat(p, ENV_IP"=", r->useragent_ip, NULL);
  454.  
  455.     if (r->uri)
  456.         child_env[i++]= apr_pstrcat(p, ENV_URI"=", r->uri, NULL);
  457.  
  458.     if ((host= apr_table_get(r->headers_in, "Host")) != NULL)
  459.         child_env[i++]= apr_pstrcat(p, ENV_HTTP_HOST"=", host, NULL);
  460.  
  461.     if (dir->context)
  462.         child_env[i++]= apr_pstrcat(r->pool, ENV_CONTEXT"=",
  463.             dir->context, NULL);
  464.  
  465. #ifdef ENV_COOKIE
  466.     if ((cookie= apr_table_get(r->headers_in, "Cookie")) != NULL)
  467.         child_env[i++]= apr_pstrcat(p, ENV_COOKIE"=", cookie, NULL);
  468. #endif
  469.     /* NOTE:  If you add environment variables,
  470.      *   remember to increase the size of the child_env[] array */
  471.  
  472.     /* End of environment */
  473.     child_env[i]= NULL;
  474.     }
  475.  
  476.     /* Construct argument array */
  477.     for (t= extpath, i=0; *t != '\0' && (i <= MAX_ARG + 1);
  478.      child_arg[i++]= ap_getword_white(p, &t)) {}
  479.     child_arg[i]= NULL;
  480.  
  481.     /* Create the process attribute structure describing the script we
  482.      * want to run using the Thread/Process functions from the Apache
  483.      * portable runtime library. */
  484.  
  485.     if (((rc= apr_procattr_create(&procattr, p)) != APR_SUCCESS) ||
  486.  
  487.     /* should we create pipes to stdin, stdout and stderr? */
  488.         ((rc= apr_procattr_io_set(procattr,
  489.         (usepipein && !usecheck) ? APR_FULL_BLOCK : APR_NO_PIPE,
  490.         usepipeout ? APR_FULL_BLOCK : APR_NO_PIPE,
  491.         (usepipein && usecheck) ? APR_FULL_BLOCK : APR_NO_PIPE))
  492.            != APR_SUCCESS ) ||
  493.  
  494.     /* will give full path of program and make a new environment */
  495.     ((rc= apr_procattr_cmdtype_set(procattr,
  496.         isdaemon ? APR_PROGRAM_ENV : APR_PROGRAM)) != APR_SUCCESS) ||
  497.  
  498.     /* detach the child only if it is a daemon */
  499.     ((rc= apr_procattr_detach_set(procattr, isdaemon)) != APR_SUCCESS) ||
  500.  
  501.     /* function to call if child has error after fork, before exec */
  502.     ((rc= apr_procattr_child_errfn_set(procattr, extchilderr)
  503.           != APR_SUCCESS)))
  504.     {
  505.     /* Failed.  Probably never happens. */
  506.         ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
  507.         "could not set child process attributes");
  508.     return -3;
  509.     }
  510.  
  511.     /* Start the child process */
  512.     rc= apr_proc_create(&proc, child_arg[0],
  513.         (const char * const *)child_arg,
  514.     (const char * const *)child_env, procattr, p);
  515.     if (rc != APR_SUCCESS)
  516.     {
  517.     ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
  518.         "Could not run external authenticator: %d: %s", rc,
  519.         child_arg[0]);
  520.     return -1;
  521.     }
  522.  
  523.     if (isdaemon) return 0;
  524.  
  525.     apr_pool_note_subprocess(p, &proc, APR_KILL_AFTER_TIMEOUT);
  526.  
  527.     if (usepipein)
  528.     {
  529.     /* Select appropriate pipe to write to */
  530.     apr_file_t *pipe= (usecheck ? proc.err : proc.in);
  531.  
  532.     /* Send the user */
  533.     apr_file_write_full(pipe, r->user, strlen(r->user), NULL);
  534.     apr_file_putc(usecheck ? '\0' : '\n', pipe);
  535.  
  536.     /* Send the password */
  537.     apr_file_write_full(pipe, data, strlen(data), NULL);
  538.     apr_file_putc(usecheck ? '\0' : '\n', pipe);
  539.  
  540.     /* Send the uri/path */
  541.     apr_file_write_full(pipe, r->uri, strlen(r->uri), NULL);
  542.     apr_file_putc(usecheck ? '\0' : '\n', pipe);
  543.  
  544.     /* Send dummy timestamp for checkpassword */
  545.     if (usecheck) apr_file_write_full(pipe, "0", 2, NULL);
  546.  
  547.     /* Close the file */
  548.     apr_file_close(pipe);
  549.     }
  550.  
  551.     /* Wait for the child process to terminate, and get status */
  552.     rc= apr_proc_wait(&proc,&status,&why,APR_WAIT);
  553.  
  554.     if (!APR_STATUS_IS_CHILD_DONE(rc))
  555.     {
  556.         ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
  557.         "Could not get status from child process");
  558.     return -5;
  559.     }
  560.     if (!APR_PROC_CHECK_EXIT(why))
  561.     {
  562.     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  563.         "External authenticator died on signal %d",status);
  564.     return -2;
  565.     }
  566.  
  567.     return status;
  568. }
  569.  
  570.  
  571. /* Call the hardcoded function specified by the external path.  Of course,
  572.  * you'll have to write the hardcoded functions yourself and insert them
  573.  * into this source file, as well as inserting a call to them into this
  574.  * routine.
  575.  */
  576. static int exec_hardcode(const request_rec *r, const char *extpath,
  577.     const char *password)
  578. {
  579. #ifdef _HARDCODE_
  580.     char *check_type;       /* Pointer to HARDCODE type check  */
  581.     char *config_file;      /* Pointer to HARDCODE config file */
  582.     int standard_auth= 0;
  583.     int code;
  584.  
  585.     /* Parse a copy of extpath into type and filename */
  586.     check_type= apr_pstrdup(r->pool, extpath);
  587.     config_file= strchr(check_type, ':');
  588.     if (config_file != NULL)
  589.     {
  590.     *config_file= '\0';        /* Mark end of type */
  591.     config_file++;                     /* Start of filename */
  592.     }
  593.  
  594.  
  595.  
  596.     /* This is where you make your function call.  Here is an example of
  597.      * what one looks like:
  598.      *
  599.      *   if (strcmp(check_type,"RADIUS")==0)
  600.      *      code= radcheck(r->user,password,config_file);
  601.      *
  602.      * Replace 'radcheck' with whatever the name of your function is.
  603.      * Replace 'RADIUS' with whatever you are using as the <type> in:
  604.      *     AddExternalAuth <keyword> <type>:<config file>
  605.      */
  606.  
  607.     if (strcmp(check_type,"MIS_AUTH")==0)       /* change this! */
  608.         code= my_authentication(r->user,password,config_file);  /* change this! */
  609.     else
  610.     code= -5;
  611.     return code;
  612. #else
  613.     return -4;      /* If _HARDCODE_ is not defined, always fail */
  614. #endif /* _HARDCODE_ */
  615. }
  616.  
  617.  
  618. /* Handle a group check triggered by a 'Require external-group foo bar baz'
  619.  * directive. */
  620. static authz_status externalgroup_check_authorization(request_rec *r,
  621.     const char *require_args, const void *parsed_require_args)
  622. {
  623.     authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
  624.     ap_get_module_config(r->per_dir_config, &authnz_external_module);
  625.  
  626.     authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
  627.     ap_get_module_config(r->server->module_config, &authnz_external_module);
  628.  
  629.     char *user= r->user;
  630.     char *extname= dir->group_name;
  631.     const char *extpath, *extmethod;
  632.     const char *t, *w;
  633.     int code;
  634.  
  635.     /* If no authenticated user, pass */
  636.     if ( !user ) return AUTHZ_DENIED_NO_USER;
  637.  
  638.     /* If no external authenticator has been configured, pass */
  639.     if ( !extname ) return AUTHZ_DENIED;
  640.  
  641.     /* Get the path and method associated with that external */
  642.     if (!(extpath= apr_table_get(svr->group_path, extname)) ||
  643.     !(extmethod= apr_table_get(svr->group_method,extname)))
  644.     {
  645.     errno= 0;
  646.     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  647.         "invalid GroupExternal keyword (%s)", extname);
  648.     return AUTHZ_DENIED;
  649.     }
  650.  
  651.     if (dir->groupsatonce)
  652.     {
  653.     /* Pass rest of require line to authenticator */
  654.     code= exec_external(extpath, extmethod, r, ENV_GROUP, require_args);
  655.     if (code == 0) return AUTHZ_GRANTED;
  656.     }
  657.     else
  658.     {
  659.     /* Call authenticator once for each group name on line */
  660.     t= require_args;
  661.     while ((w= ap_getword_conf(r->pool, &t)) && w[0])
  662.     {
  663.         code= exec_external(extpath, extmethod, r, ENV_GROUP, w);
  664.         if (code == 0) return AUTHZ_GRANTED;
  665.     }
  666.     }
  667.  
  668.     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  669.     "Authorization of user %s to access %s failed. "
  670.     "User not in Required group.",
  671.         r->user, r->uri);
  672.  
  673.     return AUTHZ_DENIED;
  674. }
  675.  
  676.  
  677. /* Handle a group check triggered by a 'Require external-file-group'
  678.  * directive. */
  679. static authz_status externalfilegroup_check_authorization(request_rec *r,
  680.     const char *require_args, const void *parsed_require_args)
  681. {
  682.     authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
  683.     ap_get_module_config(r->per_dir_config, &authnz_external_module);
  684.  
  685.     authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
  686.     ap_get_module_config(r->server->module_config, &authnz_external_module);
  687.  
  688.     char *user= r->user;
  689.     char *extname= dir->group_name;
  690.     const char *extpath, *extmethod;
  691.     const char *filegroup= NULL;
  692.     const char *t, *w;
  693.     int code;
  694.  
  695.     /* If no authenticated user, pass */
  696.     if ( !user ) return AUTHZ_DENIED_NO_USER;
  697.  
  698.     /* If no external authenticator has been configured, pass */
  699.     if ( !extname ) return AUTHZ_DENIED;
  700.  
  701.     /* Get the path and method associated with that external */
  702.     if (!(extpath= apr_table_get(svr->group_path, extname)) ||
  703.     !(extmethod= apr_table_get(svr->group_method,extname)))
  704.     {
  705.     errno= 0;
  706.     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  707.         "invalid GroupExternal keyword (%s)", extname);
  708.     return AUTHZ_DENIED;
  709.     }
  710.  
  711.     /* Get group name for requested file from mod_authz_owner */
  712.     filegroup= authz_owner_get_file_group(r);
  713.  
  714.     if (!filegroup)
  715.     /* No errog log entry, because mod_authz_owner already made one */
  716.     return AUTHZ_DENIED;
  717.  
  718.     /* Pass the group to the external authenticator */
  719.     code= exec_external(extpath, extmethod, r, ENV_GROUP, filegroup);
  720.     if (code == 0) return AUTHZ_GRANTED;
  721.  
  722.     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  723.     "Authorization of user %s to access %s failed. "
  724.     "User not in Required file group (%s).",
  725.         r->user, r->uri, filegroup);
  726.  
  727.     return AUTHZ_DENIED;
  728. }
  729.  
  730.  
  731. /* Mod_authn_socache wants us to pass it the username and the encrypted
  732.  * password from the user database to cache. But we have no access to the
  733.  * actual user database - only the external authenticator can see that -
  734.  * and chances are, the passwords there aren't encrypted in any way that
  735.  * mod_authn_socache would understand anyway. So instead, after successful
  736.  * authentications only, we take the user's plain text password, encrypt
  737.  * that using an algorithm mod_authn_socache will understand, and cache that
  738.  * as if we'd actually gotten it from a password database.
  739.  */
  740. void mock_turtle_cache(request_rec *r, const char *plainpw)
  741. {
  742.     char cryptpw[120];
  743.  
  744.     /* Authn_cache_store will be null if mod_authn_socache does not exist.
  745.      * If it does exist, but is not set up to cache us, then
  746.      * authn_cache_store() will do nothing, which is why we turn this off
  747.      * with "AuthExternalProvideCache Off" to avoid doing the encryption
  748.      * for no reason. */
  749.     if (authn_cache_store != NULL)
  750.     {
  751.     apr_sha1_base64(plainpw,strlen(plainpw),cryptpw);
  752.         authn_cache_store(r, "external", r->user, NULL, cryptpw);
  753.     }
  754. }
  755.  
  756.  
  757. /* Password checker for basic authentication - given a login/password,
  758.  * check if it is valid.  Returns one of AUTH_DENIED, AUTH_GRANTED,
  759.  * or AUTH_GENERAL_ERROR. */
  760.  
  761. static authn_status authn_external_check_password(request_rec *r,
  762.     const char *user, const char *password)
  763. {
  764.     const char *extname, *extpath, *extmethod;
  765.     int i;
  766.     authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *)
  767.         ap_get_module_config(r->per_dir_config, &authnz_external_module);
  768.  
  769.     authnz_external_svr_config_rec *svr= (authnz_external_svr_config_rec *)
  770.         ap_get_module_config(r->server->module_config,
  771.         &authnz_external_module);
  772.     int code= 1;
  773.  
  774.     /* Check if we are supposed to handle this authentication */
  775.     if (dir->auth_name->nelts == 0)
  776.     {
  777.     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  778.         "No AuthExternal name has been set");
  779.     return AUTH_GENERAL_ERROR;
  780.     }
  781.  
  782.     for (i= 0; i < dir->auth_name->nelts; i++)
  783.     {
  784.     extname= ((const char **)dir->auth_name->elts)[i];
  785.  
  786.     /* Get the path associated with that external */
  787.     if (!(extpath= apr_table_get(svr->auth_path, extname)))
  788.     {
  789.         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  790.         "Invalid AuthExternal keyword (%s)", extname);
  791.         return AUTH_GENERAL_ERROR;
  792.     }
  793.  
  794.     /* Do the authentication, by the requested method */
  795.     extmethod= apr_table_get(svr->auth_method, extname);
  796.     if ( extmethod && !strcasecmp(extmethod, "function") )
  797.         code= exec_hardcode(r, extpath, password);
  798.     else
  799.         code= exec_external(extpath, extmethod, r, ENV_PASS, password);
  800.  
  801.     /* If return code was zero, authentication succeeded */
  802.     if (code == 0)
  803.     {
  804.         if (dir->providecache) mock_turtle_cache(r, password);
  805.         return AUTH_GRANTED;
  806.     }
  807.  
  808.     /* Log a failed authentication */
  809.     errno= 0;
  810.     ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  811.         "AuthExtern %s [%s]: Failed (%d) for user %s",
  812.         extname, extpath, code, r->user);
  813.     }
  814.     /* If no authenticators succeed, refuse authentication */
  815.     return AUTH_DENIED;
  816. }
  817.  
  818.  
  819. #if 0
  820. /* Password checker for digest authentication - given a login/password,
  821.  * check if it is valid.  Returns one of AUTH_USER_FOUND, AUTH_USER_NOT_FOUND,
  822.  * or AUTH_GENERAL_ERROR.   Not implemented at this time and probably not ever.
  823.  */
  824.  
  825. auth_status *authn_external_get_realm_hash(request_rec *r, const char *user,
  826.     const char *realm, char **rethash);
  827. {
  828. }
  829. #endif
  830.  
  831. /* This is called after all modules have been initialized to acquire pointers
  832.  * to some functions from other modules that we would like to use if they are
  833.  * available. */
  834. static void opt_retr(void)
  835. {
  836.     /* Get authn_cache_store from mod_authn_socache */
  837.     authn_cache_store=
  838.     APR_RETRIEVE_OPTIONAL_FN(ap_authn_cache_store);
  839.  
  840.     /* Get authz_owner_get_file_group from mod_authz_owner */
  841.     authz_owner_get_file_group=
  842.     APR_RETRIEVE_OPTIONAL_FN(authz_owner_get_file_group);
  843. }
  844.  
  845. /* This tells mod_auth_basic and mod_auth_digest what to call for
  846.  * authentication. */
  847. static const authn_provider authn_external_provider =
  848. {
  849.     &authn_external_check_password,
  850. #if 0
  851.     &authn_external_get_realm_hash
  852. #else
  853.     NULL    /* No support for digest authentication */
  854. #endif
  855. };
  856.  
  857. /* This tells mod_auth_basic and mod_auth_digest what to call for
  858.  * access control with 'Require external-group' directives. */
  859. static const authz_provider authz_externalgroup_provider =
  860. {
  861.     &externalgroup_check_authorization,
  862.     NULL,
  863. };
  864.  
  865. /* This tells mod_auth_basic and mod_auth_digest what to call for
  866.  * access control with 'Require external-file-group' directives. */
  867. static const authz_provider authz_externalfilegroup_provider =
  868. {
  869.     &externalfilegroup_check_authorization,
  870.     NULL,
  871. };
  872.  
  873. /* Register this module with Apache */
  874. static void register_hooks(apr_pool_t *p)
  875. {
  876.     /* Register authn provider */
  877.     ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "external",
  878.         AUTHN_PROVIDER_VERSION,
  879.         &authn_external_provider, AP_AUTH_INTERNAL_PER_CONF);
  880.  
  881.     /* Register authz providers */
  882.     ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "external-group",
  883.         AUTHZ_PROVIDER_VERSION,
  884.         &authz_externalgroup_provider, AP_AUTH_INTERNAL_PER_CONF);
  885.  
  886.     ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "external-file-group",
  887.         AUTHZ_PROVIDER_VERSION,
  888.         &authz_externalfilegroup_provider, AP_AUTH_INTERNAL_PER_CONF);
  889.  
  890.     /* Ask for opt_retr() to be called after all modules have registered */
  891.     ap_hook_optional_fn_retrieve(opt_retr, NULL, NULL, APR_HOOK_MIDDLE);
  892. }
  893.  
  894.  
  895. AP_DECLARE_MODULE(authnz_external) = {
  896.     STANDARD20_MODULE_STUFF,
  897.     create_authnz_external_dir_config,    /* create per-dir config */
  898.     NULL,             /* merge per-dir config - dflt is override */
  899.     create_authnz_external_svr_config, /* create per-server config */
  900.     NULL,             /* merge per-server config */
  901.     authnz_external_cmds,     /* command apr_table_t */
  902.     register_hooks        /* register hooks */
  903. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement