Advertisement
Guest User

Untitled

a guest
Sep 18th, 2017
451
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 53.54 KB | None | 0 0
  1. /*
  2.  * Copyright (c) 2001 by J. R. Westmoreland <jr@jrw.org>
  3.  * Portions Copyright (c) 2002-2004 by Matthew Palmer <mpalmer@debian.org>
  4.  *
  5.  * Original module/version: mod_auth_mysql v2.20
  6.  * Originally written and maintained by Zeev Suraski <bourbon@netvision.net.il>
  7.  * A couple of fixes by Marschall Peter <Peter.Marschall@gedos.de>
  8.  * and Brent Metz <bmetz@thor.tjhsst.edu>
  9.  * MySQL/PHP style MD5 hashes, and an integration with the mod-auth-mysql
  10.  * maintained by Bill Joned by Matthew Palmer <mpalmer@debian.org>
  11.  *
  12.  * This version maintained by Matthew Palmer <mpalmer@debian.org>
  13.  *
  14.  * Please read the INSTALL and USAGE files for further information.
  15.  *
  16.  * 2004-02-01 MURAKAMI, takeshi <takeshi@softagency.co.jp>
  17.  * add port, socket
  18.  * 2004-02-07 MURAKAMI, takeshi <takeshi@softagency.co.jp>
  19.  * apache2
  20.  * 2004-09-20 Joseph Walton <joe@kafsemo.org>
  21.  * SHA1 hash support
  22.  */
  23.  
  24. #define AUTH_MYSQL_VERSION "4.3.9"
  25.  
  26. #include "config.h"
  27.  
  28. #ifdef APACHE2
  29. #define PALLOC apr_palloc
  30. #define PCALLOC apr_pcalloc
  31. #define SNPRINTF apr_snprintf
  32. #define PSTRDUP apr_pstrdup
  33. #define PSTRCAT apr_pstrcat
  34. #define APACHELOG(severity, handle, message...) ap_log_error(APLOG_MARK, APLOG_NOERRNO | severity, 0, handle->server, message)
  35. #else
  36. #define PALLOC ap_palloc
  37. #define PCALLOC ap_pcalloc
  38. #define SNPRINTF ap_snprintf
  39. #define PSTRDUP ap_pstrdup
  40. #define PSTRCAT ap_pstrcat
  41. #define APACHELOG(severity, handle, message...) ap_log_error(APLOG_MARK, APLOG_NOERRNO | severity, handle->server, message)
  42. #endif
  43.  
  44. #include <httpd.h>
  45. #include <http_config.h>
  46. #include <http_core.h>
  47. #include <http_protocol.h>
  48. #include <http_log.h>
  49. #ifdef APACHE2
  50. #include "http_request.h"   /* for ap_hook_(check_user_id | auth_checker)*/
  51. #include <apr_md5.h>
  52. #include <apr_sha1.h>
  53. #else
  54. #include <ap_md5.h>
  55. #include <ap_sha1.h>
  56. #endif
  57.  
  58. #include <mysql.h>
  59. #include <errmsg.h>
  60. #include <mysqld_error.h>
  61.  
  62. #ifdef HAVE_CRYPT_H
  63. #include <crypt.h>
  64. #endif
  65.  
  66. #ifndef TRUE
  67. #define TRUE 1
  68. #endif
  69. #ifndef FALSE
  70. #define FALSE 0
  71. #endif
  72.  
  73. /* This are the system-wide config options; the more specific options live in
  74.  * a mysql_auth_config_rec structure, one for each MySQL-configured directory.
  75.  */
  76. static char *auth_db_host = NULL,
  77.         *auth_db_name = NULL,
  78.         *auth_db_user = NULL,
  79.         *auth_db_pwd = NULL;
  80.  
  81. static int  auth_db_override = 1;
  82.  
  83. char *tmp_host = NULL;
  84. char *auth_db_socket = NULL;
  85. long auth_db_port = -1;
  86. unsigned long auth_db_client_flag = 0;
  87.  
  88. /* Support for general-purpose encryption schemes.  Should be fairly straightforward.
  89.  * We have a checking routine and a name for it (for AuthMySQL_Encryption_Types).
  90.  */
  91.  
  92. #define PLAINTEXT_ENCRYPTION_FLAG   1<<0
  93. #ifdef CRYPT_DES
  94. #define CRYPT_DES_ENCRYPTION_FLAG   1<<1
  95. #endif
  96. #define MYSQL_ENCRYPTION_FLAG       1<<2
  97. #ifdef CRYPT_MD5
  98. #define CRYPT_MD5_ENCRYPTION_FLAG   1<<3
  99. #endif
  100. #define PHP_MD5_ENCRYPTION_FLAG     1<<4
  101. #ifdef HAVE_CRYPT_H
  102. #define CRYPT_ENCRYPTION_FLAG       1<<5
  103. #endif
  104. #define SHA1SUM_ENCRYPTION_FLAG     1<<6
  105.  
  106. static int check_no_encryption(const char *passwd, char *enc_passwd)
  107. {
  108.     return (!strcmp(passwd, enc_passwd));
  109. }
  110.  
  111.  
  112. #ifdef CRYPT_DES
  113. static int check_crypt_des_encryption(const char *passwd, char *enc_passwd)
  114. {
  115.     /* Ensure that MD5 passwords aren't checked here */
  116.     if (!strncmp(enc_passwd, "$1$", 3)) {
  117.         return 0;
  118.     }
  119.     return (!strcmp(crypt(passwd, enc_passwd), enc_passwd));
  120. }
  121. #endif
  122.  
  123. #ifdef CRYPT_MD5
  124. static int check_crypt_MD5_encryption(const char *passwd, char *enc_passwd)
  125. {
  126.     /* Make sure only MD5 passwords are checked */
  127.     if (strncmp(enc_passwd, "$1$", 3)) {
  128.         return 0;
  129.     }
  130.     return (!strcmp(crypt(passwd, enc_passwd), enc_passwd));
  131. }
  132. #endif
  133.  
  134. #ifdef HAVE_CRYPT_H
  135. static int check_crypt_encryption(const char *passwd, char *enc_passwd)
  136. {
  137.     return (!strcmp(crypt(passwd, enc_passwd), enc_passwd));
  138. }
  139. #endif
  140.  
  141. char hex_digit(char c)
  142. {
  143.     if (c < 10) {
  144.         return c+'0';
  145.     } else {
  146.         return c-10+'a';
  147.     }
  148. }
  149.  
  150. static char *md5_hex_hash(const char *pass)
  151. {
  152.     unsigned char hash[16];
  153.     /* This makes this function *very* specialised.  Change this to
  154.      * use dynamic memory if you want to reuse it somewhere else */
  155.     static char real_hash[33];
  156.     int i;
  157. #ifdef APACHE2
  158.     apr_md5_ctx_t ct;
  159.  
  160.     apr_md5_init(&ct);
  161.     apr_md5_update(&ct, pass, strlen(pass));
  162.     apr_md5_final(hash, &ct);
  163. #else
  164.     AP_MD5_CTX ct;
  165.  
  166.     ap_MD5Init(&ct);
  167.     ap_MD5Update(&ct, pass, strlen(pass));
  168.     ap_MD5Final(hash, &ct);
  169. #endif
  170.    
  171.     /* Now we convert the 16 octet hash to a 32 byte hex string */
  172.     for (i = 0; i < 16; i++) {
  173.         real_hash[2*i+1] = hash[i] & 0xF;
  174.         real_hash[2*i] = (hash[i] & 0xF0) >> 4;
  175.     }
  176.     for (i = 0; i < 32; i++) {
  177.         real_hash[i] = hex_digit(real_hash[i]);
  178.     }
  179.     real_hash[32] = '\0';
  180.  
  181.     return real_hash;
  182. }
  183.  
  184. static int check_PHP_MD5_encryption(const char *passwd, char *enc_passwd)
  185. {
  186.     return (!strcmp(md5_hex_hash(passwd), enc_passwd));
  187. }
  188.  
  189. static char *sha1_hex_hash(const char *passwd)
  190. {
  191.     int i;
  192.  
  193. #ifdef APACHE2
  194.     apr_sha1_ctx_t ct;
  195.     char hash[APR_SHA1_DIGESTSIZE];
  196.     static char real_hash[APR_SHA1_DIGESTSIZE * 2 + 1];
  197.  
  198.     apr_sha1_init(&ct);
  199.     apr_sha1_update(&ct, passwd, strlen(passwd));
  200.     apr_sha1_final(hash, &ct);
  201. #else
  202.     AP_SHA1_CTX ct;
  203.     char hash[SHA_DIGESTSIZE];
  204.     static char real_hash[SHA_DIGESTSIZE * 2 + 1];
  205.  
  206.     ap_SHA1Init(&ct);
  207.     ap_SHA1Update(&ct, passwd, strlen(passwd));
  208.     ap_SHA1Final(hash, &ct);
  209. #endif
  210.  
  211.     /* Now we convert the 20 octet hash to a 40 byte hex string */
  212.     for (i = 0; i < sizeof(hash); i++) {
  213.         real_hash[2*i+1] = hash[i] & 0xF;
  214.         real_hash[2*i] = (hash[i] & 0xF0) >> 4;
  215.     }
  216.     for (i = 0; i < sizeof(real_hash); i++) {
  217.         real_hash[i] = hex_digit(real_hash[i]);
  218.     }
  219.     real_hash[sizeof(real_hash)-1] = '\0';
  220.  
  221.     return real_hash;
  222. }
  223.  
  224. static int check_SHA1Sum_encryption(const char *passwd, char *enc_passwd)
  225. {
  226.     return (!strcmp(sha1_hex_hash(passwd), enc_passwd));
  227. }
  228.  
  229.  
  230. static int check_mysql_encryption(const char *passwd, char *enc_passwd)
  231. {
  232.     char scrambled_passwd[32];
  233.    
  234.     make_scrambled_password(scrambled_passwd, passwd);
  235.     return (!strcmp(scrambled_passwd, enc_passwd));
  236. }
  237.  
  238. typedef struct {
  239.     char *name;
  240.     int (*check_function)(const char *passwd, char *enc_passwd);
  241.     int flag;
  242. } encryption_type_entry;
  243.  
  244. encryption_type_entry supported_encryption_types[] = {
  245.     { "Plaintext",      check_no_encryption,            PLAINTEXT_ENCRYPTION_FLAG },
  246. #if CRYPT_DES
  247.     { "Crypt_DES",      check_crypt_des_encryption,     CRYPT_DES_ENCRYPTION_FLAG },
  248. #endif
  249.     { "MySQL",      check_mysql_encryption,         MYSQL_ENCRYPTION_FLAG },
  250. #if CRYPT_MD5
  251.     { "Crypt_MD5",      check_crypt_MD5_encryption,     CRYPT_MD5_ENCRYPTION_FLAG },
  252. #endif
  253.     { "Crypt",      check_crypt_encryption,         CRYPT_ENCRYPTION_FLAG },
  254.     { "PHP_MD5",        check_PHP_MD5_encryption,       PHP_MD5_ENCRYPTION_FLAG },
  255.     { "SHA1Sum",    check_SHA1Sum_encryption, SHA1SUM_ENCRYPTION_FLAG},
  256.     /* add additional encryption types below */
  257.     { NULL,         NULL,                   0 }
  258. };
  259.  
  260. static int get_encryption_flag(const char *name)
  261. {
  262.     register encryption_type_entry *ete=supported_encryption_types;
  263.    
  264.     while (ete->name) {
  265.         if (!strcmp(ete->name, name)) {
  266.             return ete->flag;
  267.         }
  268.         ete++;
  269.     }
  270.     return 0;
  271. }
  272.  
  273. /* end of support for general-purpose encryption schemes */
  274.  
  275. /* Per-directory configuration structure.  One of these is created for each
  276.  * <Directory>...</Directory> and .htaccess file which requests authentication
  277.  */
  278. typedef struct {
  279.     char *dir;
  280.  
  281.     char *db_host;
  282.     char *db_socket;
  283.     unsigned int db_port;
  284.     char *db_user;
  285.     char *db_pwd;
  286.     char *db_name;
  287.    
  288.     MYSQL *dbh;
  289.  
  290.     /* Boolean options */
  291.     unsigned char persistent;
  292.     unsigned char enable_mysql_auth;
  293.  
  294.     /* Some MySQL errors are retryable; if we retry the operation
  295.      * by recursing into the same function, we set this so we don't
  296.      * recurse indefinitely if it's a permanent error.
  297.      */
  298.     unsigned char dbh_error_lastchance;
  299.  
  300.     char *user_table;
  301.     char *group_table;
  302.  
  303.     char *user_field;
  304.     char *password_field;
  305.     char *group_field;
  306.     char *group_user_field;
  307.     char *group_where_clause;
  308.     char *password_where_clause;
  309.        
  310.     int encryption_types;
  311.     unsigned char using_encryption_types;
  312.  
  313.     unsigned char allow_empty_passwords;
  314.     unsigned char authoritative;
  315.  
  316.     /* You're not going to believe this, but, near as I can tell, apache
  317.      * doesn't respect the last part of the config_rec.  May be an
  318.      * underflow in some code somewhere, but I'm not taking no chances
  319.      * with *my* config variables...
  320.      */
  321.     char sacrificial_lamb[15];
  322.  
  323. } mysql_auth_config_rec;
  324.  
  325. module auth_mysql_module;
  326.  
  327. #ifdef APACHE2
  328. static apr_status_t
  329. #else
  330. static void
  331. #endif
  332. auth_mysql_cleanup(void *ptr)
  333. {
  334.     mysql_auth_config_rec *sec = ptr;
  335.  
  336.     if (sec->dbh) {
  337. #ifdef DEBUG
  338.         syslog(LOG_DEBUG, "MAMDEBUG: Closing MySQL connection");
  339. #endif
  340.         mysql_close(sec->dbh);
  341.         sec->dbh = NULL;
  342.     }
  343. }
  344.  
  345. /* Do the magic required when the module is first loaded.
  346.  */
  347. #ifdef APACHE2
  348. void mysql_auth_init_handler(server_rec *s, apr_pool_t *p)
  349. #else
  350. void mysql_auth_init_handler(server_rec *s, pool *p)
  351. #endif
  352. {
  353. #ifdef APACHE2
  354. #else
  355. #if MODULE_MAGIC_NUMBER >= 19980527
  356.     ap_add_version_component("AuthMySQL/" AUTH_MYSQL_VERSION);
  357. #endif
  358. #endif
  359. }
  360.  
  361. /* Called each and every time a new per-directory configuration is
  362.  * created.  We just initialise variables and set defaults.  This is
  363.  * run *before* actual config takes place.
  364.  */
  365. #ifdef APACHE2
  366. void *create_mysql_auth_dir_config(apr_pool_t *p, char *d)
  367. #else
  368. void *create_mysql_auth_dir_config(pool *p, char *d)
  369. #endif
  370. {
  371. #ifdef DEBUG
  372.     int i;
  373. #endif
  374.  
  375.     mysql_auth_config_rec *sec = (mysql_auth_config_rec *) PCALLOC(p, sizeof(mysql_auth_config_rec));
  376.    
  377. #ifdef DEBUG
  378.     syslog(LOG_DEBUG, "MAMDEBUG: Now configuring server config for %s", d);
  379.     syslog(LOG_DEBUG, "MAMDEBUG: sizeof(mysql_auth_config_rec) = %i",
  380.                 sizeof(mysql_auth_config_rec));
  381. #endif
  382.  
  383.     sec->db_name = sec->db_socket = sec->db_user = sec->db_pwd = NULL;
  384.  
  385.     sec->dbh = NULL;
  386.     /* When the memory for this connection record is cleaned, we must
  387.      * be sure to close the DB connection, if it exists.  If this does
  388.      * not happen, we are in a world of pain.
  389.      */
  390. #ifdef APACHE2
  391.     apr_pool_cleanup_register(p, sec, auth_mysql_cleanup, apr_pool_cleanup_null);
  392. #else
  393.     ap_register_cleanup(p, sec, auth_mysql_cleanup, ap_null_cleanup);
  394. #endif
  395.  
  396.     sec->dir = d;
  397.    
  398.     sec->user_table = sec->group_table = NULL;
  399.     sec->user_field = sec->password_field = sec->group_field = NULL;
  400.     sec->group_where_clause = sec->password_where_clause = NULL;
  401.     sec->group_user_field = NULL;
  402.    
  403.     sec->authoritative = 1;
  404.     sec->allow_empty_passwords = 1;
  405.  
  406.     sec->dbh_error_lastchance = 0;
  407.  
  408. #ifdef DEBUG
  409.     syslog(LOG_DEBUG, "MAMDEBUG: Enabling MySQL auth by default");
  410. #endif
  411.     sec->enable_mysql_auth = 1;
  412.  
  413. #ifdef CRYPT_DES
  414.     sec->encryption_types = CRYPT_DES_ENCRYPTION_FLAG;
  415.     sec->using_encryption_types = 0;
  416. #else
  417.     sec->encryption_types = 0;
  418.     sec->using_encryption_types = 0;
  419. #endif
  420.  
  421.     sec->db_port = -1;
  422.    
  423. #ifdef DEBUG
  424.     syslog(LOG_DEBUG, "MAMDEBUG: Persistent is now ON");
  425. #endif
  426.     sec->persistent = 1;
  427.  
  428. #ifdef DEBUG
  429.     for (i = 0; i < 15; i++)
  430.     {
  431.         sec->sacrificial_lamb[i] = i % 10 + '0';
  432.     }
  433. #endif
  434.    
  435.     return sec;
  436. }
  437.  
  438. /* Helper function to make some decisions about whether to use crypted
  439.  * passwords in response to "AuthMySQL_Encrypted_Passwords on" in a config
  440.  * file.
  441.  * XXX DEPRECATED XXX
  442.  */
  443. static const char *set_crypted_password_flag(cmd_parms *cmd, void *sconf, int arg)
  444. {
  445.     mysql_auth_config_rec *sec = (mysql_auth_config_rec *) sconf;
  446.    
  447.     if (sec->using_encryption_types) {
  448.         /* This setting is ignored if we're using Encryption_Types */
  449.         return NULL;
  450.     }
  451. #ifdef CRYPT_DES
  452.     if (arg) {
  453.         sec->encryption_types |= CRYPT_DES_ENCRYPTION_FLAG;
  454.     } else {
  455.         sec->encryption_types &= ~CRYPT_DES_ENCRYPTION_FLAG;
  456.         if (!sec->encryption_types) {
  457.             sec->encryption_types = PLAINTEXT_ENCRYPTION_FLAG;
  458.         }
  459.     }
  460. #endif
  461.  
  462.     return NULL;
  463. }
  464.  
  465. /* Equivalent to set_crypted_password_flag above, except that this time we're
  466.  * talking about MySQL-style scrambled passwords instead.
  467.  * XXX DEPRECATED XXX
  468.  */
  469. static const char *set_scrambled_password_flag(cmd_parms *cmd, void *sconf, int arg)
  470. {
  471.     mysql_auth_config_rec *sec = (mysql_auth_config_rec *) sconf;
  472.  
  473.     if (sec->using_encryption_types) {
  474.         /* This setting is ignored if we're using Encryption_Types */
  475.         return NULL;
  476.     }
  477.     if (arg) {
  478.         sec->encryption_types |= MYSQL_ENCRYPTION_FLAG;
  479.     } else {
  480.         sec->encryption_types &= ~MYSQL_ENCRYPTION_FLAG;
  481.         if (!sec->encryption_types) {
  482.             sec->encryption_types = PLAINTEXT_ENCRYPTION_FLAG;
  483.         }
  484.     }
  485.     return NULL;
  486. }
  487.  
  488. /* Ensure that any string passed through us won't unduly upset the MySQL
  489.  * server when passed in as part of a query.
  490.  */
  491. #ifdef APACHE2
  492. static char *mysql_escape(char *str, apr_pool_t *p)
  493. #else
  494. static char *mysql_escape(char *str, pool *p)
  495. #endif
  496. {
  497.     char *dest;
  498.    
  499.     if (!str) {
  500.         return NULL;
  501.     }
  502.  
  503.     dest = (char *) PALLOC(p, strlen(str) * 2 + 1);
  504.     if (!dest) {
  505.         return str;
  506.     }
  507.    
  508.     mysql_escape_string(dest, str, strlen(str));
  509.    
  510.     return dest;
  511. }
  512.  
  513. /* Config helper to set the server-wide default database name.
  514.  */
  515. static const char *set_auth_mysql_db(cmd_parms * parms, void *dummy, const char *db)
  516. {
  517.     auth_db_name = (char *)db;
  518.     return NULL;
  519. }
  520.  
  521. /* Config helper to set the server-wide default database host.
  522.  */
  523. static const char *set_auth_mysql_host(cmd_parms *parms, void *dummy, const char *host)
  524. {
  525.     auth_db_host = (char *) host;
  526.     return NULL;
  527. }
  528.  
  529. /* Config helper to set server-wide defaults for database parameters.
  530.  */
  531. static const char *set_auth_mysql_info(cmd_parms * parms, void *dummy, const char *host, const char *user, const char *pwd)
  532. {
  533.     if (*host != '.') {
  534.         auth_db_host = (char *) host;
  535.     }
  536.  
  537.     if (*user != '.') {
  538.         auth_db_user = (char *)user;
  539.     }
  540.  
  541.     if (*pwd != '.') {
  542.         auth_db_pwd = (char *)pwd;
  543.     }
  544.  
  545.     return NULL;
  546. }
  547.  
  548. /* Config helper to set the server-wide default database username.
  549.  */
  550. static const char *set_auth_mysql_user(cmd_parms *parms, void *dummy, const char *user)
  551. {
  552.     auth_db_user = (char *)user;
  553.     return NULL;
  554. }
  555.  
  556. /* Config helper to set the server-wide default database password (coupled to
  557.  * the user specified above).
  558.  */
  559. static const char *set_auth_mysql_pwd(cmd_parms *parms, void *dummy, const char *pwd)
  560. {
  561.     auth_db_pwd = (char *)pwd;
  562.     return NULL;
  563. }
  564.  
  565. /* Set the server-wide database server socket.
  566.  */
  567. static const char *set_auth_mysql_socket(cmd_parms *parms, void *dummy, const char *sock)
  568. {
  569.     auth_db_socket = (char *)socket;
  570.     return NULL;
  571. }
  572.  
  573. /* Set the server-wide database server port.
  574.  */
  575. static const char *set_auth_mysql_port(cmd_parms *parms, void *dummy, const char *port)
  576. {
  577.     auth_db_port = (unsigned int) atoi(port);
  578.     return NULL;
  579. }
  580.  
  581. /* Config helper to judge whether to allow per-directory configs to override
  582.  * the server-wide defaults for database parameters.  The only reason this
  583.  * exists (instead of using an ap_set_flag_slot) is because this isn't part
  584.  * of a config structure, and I'm not sure how to set globals from the Apache
  585.  * config thing.
  586.  */
  587. static const char *set_auth_mysql_override(cmd_parms *parms, void *dummy, int arg)
  588. {
  589.     auth_db_override = arg;
  590.     return NULL;
  591. }
  592.  
  593. /* Config helper to set a selected encryption type.
  594.  */
  595. static const char *set_encryption_types(cmd_parms *cmd, void *sconf, const char *arg)
  596. {
  597.     mysql_auth_config_rec *sec = (mysql_auth_config_rec *) sconf;
  598.  
  599.     int new_encryption_flag = get_encryption_flag(arg);
  600.  
  601.     if (!new_encryption_flag) {
  602.         APACHELOG(APLOG_ERR, cmd, "Unsupported encryption type: %s", arg);
  603.         return NULL;
  604.     }
  605.  
  606.     if (!sec->using_encryption_types) {
  607.         sec->encryption_types = 0;
  608.         sec->using_encryption_types = 1;
  609.     }
  610.    
  611.     sec->encryption_types |= new_encryption_flag;
  612.    
  613.     return NULL;
  614. }
  615.  
  616. /* This pair of config helpers exist only because of varying semantics
  617.  * in the two versions of mod_auth_mysql I merged.  As soon as we have a
  618.  * consistent set of configuration primitives, these are going.
  619.  */
  620. static const char *set_non_persistent(cmd_parms *cmd, void *sconf, int arg)
  621. {
  622.     mysql_auth_config_rec *sec = (mysql_auth_config_rec *) sconf;
  623.  
  624.     sec->persistent = !arg;
  625.     APACHELOG(APLOG_DEBUG, cmd, "set_non_persistent: Setting persistent in %s to %i", sec->dir, sec->persistent);
  626.     return NULL;
  627. }
  628.  
  629. static const char *set_persistent(cmd_parms *cmd, void *sconf, int arg)
  630. {
  631.     mysql_auth_config_rec *sec = (mysql_auth_config_rec *) sconf;
  632.  
  633.     sec->persistent = arg;
  634.     APACHELOG(APLOG_DEBUG, cmd, "set_persistent: Setting persistent in %s to %i", sec->dir, sec->persistent);
  635.     return NULL;
  636. }
  637.  
  638. static const char *enable_mysql(cmd_parms *cmd, void *sconf, int arg)
  639. {
  640.     mysql_auth_config_rec *sec = (mysql_auth_config_rec *) sconf;
  641.  
  642.     sec->enable_mysql_auth = arg;
  643.     APACHELOG(APLOG_DEBUG, cmd, "enable_mysql: Setting enable_mysql_auth in %s to %i", sec->dir, sec->enable_mysql_auth);
  644.     return NULL;
  645. }
  646.  
  647. /* The command list.  What it's called, when it's legal to use it, and
  648.  * what to do when we find it.  Pretty cool, IMHO.
  649.  */
  650.  
  651. #ifdef APACHE2
  652. static
  653. command_rec mysql_auth_cmds[] = {
  654.    AP_INIT_TAKE3( "Auth_MySQL_Info",    set_auth_mysql_info,
  655.           NULL,
  656.           RSRC_CONF,    "host, user and password of the MySQL database" ),
  657.  
  658.    AP_INIT_TAKE1( "AuthMySQL_DefaultHost",  set_auth_mysql_host,
  659.           NULL,
  660.           RSRC_CONF,    "Default MySQL host" ),
  661.  
  662.    AP_INIT_TAKE1( "AuthMySQL_DefaultUser",  set_auth_mysql_user,
  663.           NULL,
  664.           RSRC_CONF,    "Default MySQL user" ),
  665.  
  666.    AP_INIT_TAKE1( "AuthMySQL_DefaultPassword",  set_auth_mysql_pwd,
  667.           NULL,
  668.           RSRC_CONF,    "Default MySQL password" ),
  669.  
  670.    AP_INIT_TAKE1( "Auth_MySQL_DefaultPort", set_auth_mysql_port,
  671.           NULL,
  672.           RSRC_CONF,    "Default MySQL server port" ),
  673.    
  674.    AP_INIT_TAKE1( "Auth_MySQL_DefaultSocket",   set_auth_mysql_socket,
  675.           NULL,
  676.           RSRC_CONF,    "Default MySQL server socket" ),
  677.        
  678.    AP_INIT_TAKE1( "Auth_MySQL_General_DB",  set_auth_mysql_db,
  679.           NULL,
  680.           RSRC_CONF,    "default database for MySQL authentication" ),
  681.  
  682.    AP_INIT_TAKE1( "AuthMySQL_DefaultDB",    set_auth_mysql_db,
  683.           NULL,
  684.           RSRC_CONF,    "default database for MySQL authentication" ),
  685.  
  686.    AP_INIT_TAKE1( "AuthMySQL_Host", ap_set_string_slot,
  687.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, db_host),
  688.           OR_AUTHCFG,   "database host" ),
  689.  
  690.    AP_INIT_TAKE1( "Auth_MySQL_Host",    ap_set_string_slot,
  691.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, db_host),
  692.           OR_AUTHCFG,   "database host" ),
  693.  
  694.    AP_INIT_TAKE1( "Auth_MySQL_Socket",  ap_set_string_slot,
  695.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, db_socket),
  696.           OR_AUTHCFG,   "database host socket" ),
  697.  
  698.    AP_INIT_TAKE1( "AuthMySQL_Socket",   ap_set_string_slot,
  699.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, db_socket),
  700.           OR_AUTHCFG,   "database host socket" ),
  701.  
  702.    AP_INIT_TAKE1( "Auth_MySQL_Port",    ap_set_string_slot,
  703.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, db_port),
  704.           OR_AUTHCFG,   "database host port" ),
  705.  
  706.    AP_INIT_TAKE1( "AuthMySQL_Port", ap_set_string_slot,
  707.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, db_port),
  708.           OR_AUTHCFG,   "database host port" ),
  709.  
  710.    AP_INIT_TAKE1( "Auth_MySQL_Username",    ap_set_string_slot,
  711.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, db_user),
  712.           OR_AUTHCFG,   "database user" ),
  713.  
  714.    AP_INIT_TAKE1( "AuthMySQL_User", ap_set_string_slot,
  715.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, db_user),
  716.           OR_AUTHCFG,   "database user" ),
  717.  
  718.    AP_INIT_TAKE1( "Auth_MySQL_Password",    ap_set_string_slot,
  719.         (void*)APR_XtOffsetOf(mysql_auth_config_rec, db_pwd),
  720.           OR_AUTHCFG,   "database password" ),
  721.  
  722.    AP_INIT_TAKE1( "AuthMySQL_Password",         ap_set_string_slot,
  723.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, db_pwd),
  724.           OR_AUTHCFG,   "database password" ),
  725.  
  726.    AP_INIT_TAKE1( "Auth_MySQL_DB",      ap_set_string_slot,
  727.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, db_name),
  728.           OR_AUTHCFG,   "database name" ),
  729.  
  730.    AP_INIT_TAKE1( "AuthMySQL_DB",   ap_set_string_slot,
  731.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, db_name),
  732.           OR_AUTHCFG,   "database name" ),
  733.  
  734.    AP_INIT_TAKE1( "Auth_MySQL_Password_Table",      ap_set_string_slot,
  735.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, user_table),
  736.           OR_AUTHCFG,   "Name of the MySQL table containing the password/user-name combination" ),
  737.  
  738.    AP_INIT_TAKE1( "AuthMySQL_Password_Table",       ap_set_string_slot,
  739.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, user_table),
  740.           OR_AUTHCFG,   "Name of the MySQL table containing the password/user-name combination" ),
  741.  
  742.    AP_INIT_TAKE1( "Auth_MySQL_Group_Table",     ap_set_string_slot,
  743.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, group_table),
  744.           OR_AUTHCFG,   "Name of the MySQL table containing the group-name/user-name combination; can be the same as the password-table." ),
  745.  
  746.    AP_INIT_TAKE1( "Auth_MySQL_Group_Clause",        ap_set_string_slot,
  747.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, group_where_clause),
  748.           OR_AUTHCFG,   "Additional WHERE clause for group/user-name lookup" ),
  749.  
  750.    AP_INIT_TAKE1( "AuthMySQL_Group_Table",      ap_set_string_slot,
  751.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, group_table),
  752.           OR_AUTHCFG,   "Name of the MySQL table containing the group-name/user-name combination; can be the same as the password-table." ),
  753.  
  754.    AP_INIT_TAKE1( "Auth_MySQL_Password_Field",      ap_set_string_slot,
  755.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, password_field),
  756.           OR_AUTHCFG,   "The name of the field in the MySQL password table" ),
  757.  
  758.    AP_INIT_TAKE1( "AuthMySQL_Password_Field",       ap_set_string_slot,
  759.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, password_field),
  760.           OR_AUTHCFG,   "The name of the field in the MySQL password table" ),
  761.  
  762.    AP_INIT_TAKE1( "Auth_MySQL_Password_Clause",     ap_set_string_slot,
  763.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, password_where_clause),
  764.           OR_AUTHCFG,   "Additional WHERE clause for group password/user-name lookup" ),
  765.  
  766.    AP_INIT_TAKE1( "Auth_MySQL_Username_Field",      ap_set_string_slot,
  767.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, user_field),
  768.           OR_AUTHCFG,   "The name of the user-name field in the MySQL password (and possibly group) table(s)." ),
  769.  
  770.    AP_INIT_TAKE1( "AuthMySQL_Username_Field",       ap_set_string_slot,
  771.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, user_field),
  772.           OR_AUTHCFG,   "The name of the user-name field in the MySQL password (and possibly group) table(s)." ),
  773.  
  774.    AP_INIT_TAKE1( "Auth_MySQL_Group_Field",     ap_set_string_slot,
  775.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, group_field),
  776.           OR_AUTHCFG,   "The name of the group field in the MySQL group table; must be set if you want to use groups." ),
  777.  
  778.    AP_INIT_TAKE1( "AuthMySQL_Group_Field",      ap_set_string_slot,
  779.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, group_field),
  780.           OR_AUTHCFG,   "The name of the group field in the MySQL group table; must be set if you want to use groups." ),
  781.  
  782.    AP_INIT_TAKE1( "Auth_MySQL_Group_User_Field",    ap_set_string_slot,
  783.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, group_user_field),
  784.           OR_AUTHCFG,   "The name of the user-name field in the MySQL group table; defaults to the same as the username field for the password table." ),
  785.  
  786.    AP_INIT_TAKE1( "AuthMySQL_Group_User_Field",     ap_set_string_slot,
  787.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, group_user_field),
  788.           OR_AUTHCFG,   "The name of the user-name field in the MySQL group table; defaults to the same as the username field for the password table." ),
  789.  
  790.    AP_INIT_FLAG( "Auth_MySQL_Empty_Passwords",      ap_set_flag_slot,
  791.          (void*)APR_XtOffsetOf(mysql_auth_config_rec, allow_empty_passwords),
  792.          OR_AUTHCFG,    "Enable (on) or disable (off) empty password strings; in which case any user password is accepted." ),
  793.  
  794.    AP_INIT_FLAG( "AuthMySQL_Empty_Passwords",       ap_set_flag_slot,
  795.          (void*)APR_XtOffsetOf(mysql_auth_config_rec, allow_empty_passwords),
  796.          OR_AUTHCFG,    "Enable (on) or disable (off) empty password strings; in which case any user password is accepted." ),
  797.  
  798.    AP_INIT_FLAG( "Auth_MySQL_Authoritative",        ap_set_flag_slot,
  799.          (void*)APR_XtOffsetOf(mysql_auth_config_rec, authoritative),
  800.          OR_AUTHCFG,    "When 'on' the MySQL database is taken to be authoritative and access control is not passed along to other db or access modules." ),
  801.  
  802.    AP_INIT_FLAG( "AuthMySQL_Authoritative",     ap_set_flag_slot,
  803.          (void*)APR_XtOffsetOf(mysql_auth_config_rec, authoritative),
  804.          OR_AUTHCFG,    "When 'on' the MySQL database is taken to be authoritative and access control is not passed along to other db or access modules." ),
  805.  
  806.    AP_INIT_FLAG( "AuthMySQL_AllowOverride",     set_auth_mysql_override,
  807.          NULL,
  808.          RSRC_CONF, "Allow directory overrides of configuration" ),
  809.  
  810.    AP_INIT_FLAG( "Auth_MySQL_Encrypted_Passwords",  set_crypted_password_flag,
  811.          NULL,
  812.          OR_AUTHCFG,    "When 'on' the password in the password table are taken to be crypt()ed using your machines crypt() function." ),
  813.  
  814.    AP_INIT_FLAG( "AuthMySQL_Encrypted_Passwords",   set_crypted_password_flag,
  815.           NULL,
  816.           OR_AUTHCFG,   "When 'on' the password in the password table are taken to be crypt()ed using your machines crypt() function." ),
  817.  
  818.    AP_INIT_FLAG( "Auth_MySQL_Scrambled_Passwords",  set_scrambled_password_flag,
  819.          NULL,
  820.          OR_AUTHCFG,    "When 'on' the password in the password table are taken to be scramble()d using mySQL's password() function." ),
  821.  
  822.    AP_INIT_FLAG( "AuthMySQL_Scrambled_Passwords",   set_scrambled_password_flag,
  823.          NULL,
  824.          OR_AUTHCFG,    "When 'on' the password in the password table are taken to be scramble()d using mySQL's password() function." ),
  825.  
  826.    AP_INIT_ITERATE( "Auth_MySQL_Encryption_Types",  set_encryption_types,
  827.           NULL,
  828.           OR_AUTHCFG,   "Encryption types to use" ),
  829.  
  830.    AP_INIT_ITERATE( "AuthMySQL_Encryption_Types",       set_encryption_types,
  831.           NULL,
  832.           OR_AUTHCFG,   "Encryption types to use" ),
  833.  
  834.    AP_INIT_FLAG( "Auth_MySQL_Non_Persistent",       set_non_persistent,
  835.          NULL,
  836.          OR_AUTHCFG,    "Use non-persistent MySQL links" ),
  837.  
  838.    AP_INIT_FLAG( "AuthMySQL_Persistent",        set_persistent,
  839.          NULL,
  840.          OR_AUTHCFG,    "Use non-persistent MySQL links" ),
  841.  
  842.    AP_INIT_FLAG( "Auth_MySQL",      enable_mysql,
  843.          NULL,
  844.          OR_AUTHCFG,    "Enable MySQL authentication" ),
  845.  
  846.    AP_INIT_FLAG( "AuthMySQL",       enable_mysql,
  847.          NULL,
  848.          OR_AUTHCFG,    "Enable MySQL authentication" ),
  849.  
  850.    AP_INIT_TAKE1( "Auth_MySQL_Where",       ap_set_string_slot,
  851.           (void*)APR_XtOffsetOf(mysql_auth_config_rec, password_where_clause),
  852.           OR_AUTHCFG,   "Additional WHERE clause for group password/user-name lookup" ),
  853.  
  854.   { NULL }
  855. };
  856. #else
  857. command_rec mysql_auth_cmds[] = {
  858.     { "Auth_MySQL_Info",            set_auth_mysql_info,
  859.       NULL,
  860.       RSRC_CONF,    TAKE3,  "host, user and password of the MySQL database" },
  861.  
  862.     { "AuthMySQL_DefaultHost",      set_auth_mysql_host,
  863.       NULL,
  864.       RSRC_CONF,    TAKE1,  "Default MySQL host" },
  865.  
  866.     { "AuthMySQL_DefaultUser",      set_auth_mysql_user,
  867.       NULL,
  868.       RSRC_CONF,    TAKE1,  "Default MySQL user" },
  869.  
  870.     { "AuthMySQL_DefaultPassword",      set_auth_mysql_pwd,
  871.       NULL,
  872.       RSRC_CONF,    TAKE1,  "Default MySQL password" },
  873.  
  874.     { "Auth_MySQL_DefaultPort",     set_auth_mysql_port,
  875.       NULL,
  876.       RSRC_CONF,    TAKE1,  "Default MySQL server port" },
  877.    
  878.     { "Auth_MySQL_DefaultSocket",       set_auth_mysql_socket,
  879.       NULL,
  880.       RSRC_CONF,    TAKE1,  "Default MySQL server socket" },
  881.        
  882.     { "Auth_MySQL_General_DB",      set_auth_mysql_db,
  883.       NULL,
  884.       RSRC_CONF,    TAKE1,  "default database for MySQL authentication" },
  885.      
  886.     { "AuthMySQL_DefaultDB",        set_auth_mysql_db,
  887.       NULL,
  888.       RSRC_CONF,    TAKE1,  "default database for MySQL authentication" },
  889.  
  890.     { "AuthMySQL_Host",         ap_set_string_slot,
  891.       (void *) XtOffsetOf(mysql_auth_config_rec, db_host),
  892.       OR_AUTHCFG,   TAKE1,  "database host" },
  893.  
  894.     { "Auth_MySQL_Host",            ap_set_string_slot,
  895.       (void *) XtOffsetOf(mysql_auth_config_rec, db_host),
  896.       OR_AUTHCFG,   TAKE1,  "database host" },
  897.  
  898.     { "Auth_MySQL_Socket",          ap_set_string_slot,
  899.       (void *) XtOffsetOf(mysql_auth_config_rec, db_socket),
  900.       OR_AUTHCFG,   TAKE1,  "database host socket" },
  901.  
  902.     { "Auth_MySQL_Port",            ap_set_string_slot,
  903.       (void *) XtOffsetOf(mysql_auth_config_rec, db_port),
  904.       OR_AUTHCFG,   TAKE1,  "database host socket" },
  905.  
  906.     { "Auth_MySQL_Username",        ap_set_string_slot,
  907.       (void *) XtOffsetOf(mysql_auth_config_rec, db_user),
  908.       OR_AUTHCFG,   TAKE1,  "database user" },
  909.      
  910.     { "AuthMySQL_User",         ap_set_string_slot,
  911.       (void *) XtOffsetOf(mysql_auth_config_rec, db_user),
  912.       OR_AUTHCFG,   TAKE1,  "database user" },
  913.      
  914.     { "Auth_MySQL_Password",        ap_set_string_slot,
  915.       (void *) XtOffsetOf(mysql_auth_config_rec, db_pwd),
  916.       OR_AUTHCFG,   TAKE1,  "database password" },
  917.      
  918.     { "AuthMySQL_Password",         ap_set_string_slot,
  919.       (void *) XtOffsetOf(mysql_auth_config_rec, db_pwd),
  920.       OR_AUTHCFG,   TAKE1,  "database password" },
  921.      
  922.     { "Auth_MySQL_DB",          ap_set_string_slot,
  923.       (void *) XtOffsetOf(mysql_auth_config_rec, db_name),
  924.       OR_AUTHCFG,   TAKE1,  "database name" },
  925.      
  926.     { "AuthMySQL_DB",           ap_set_string_slot,
  927.       (void *) XtOffsetOf(mysql_auth_config_rec, db_name),
  928.       OR_AUTHCFG,   TAKE1,  "database name" },
  929.      
  930.     { "Auth_MySQL_Password_Table",      ap_set_string_slot,
  931.       (void *) XtOffsetOf(mysql_auth_config_rec, user_table),
  932.       OR_AUTHCFG,   TAKE1,  "Name of the MySQL table containing the password/user-name combination" },
  933.      
  934.     { "AuthMySQL_Password_Table",       ap_set_string_slot,
  935.       (void *) XtOffsetOf(mysql_auth_config_rec, user_table),
  936.       OR_AUTHCFG,   TAKE1,  "Name of the MySQL table containing the password/user-name combination" },
  937.      
  938.     { "Auth_MySQL_Group_Table",     ap_set_string_slot,
  939.       (void *) XtOffsetOf(mysql_auth_config_rec, group_table),
  940.       OR_AUTHCFG,   TAKE1,  "Name of the MySQL table containing the group-name/user-name combination; can be the same as the password-table." },
  941.      
  942.     { "Auth_MySQL_Group_Clause",        ap_set_string_slot,
  943.       (void *) XtOffsetOf(mysql_auth_config_rec, group_where_clause),
  944.       OR_AUTHCFG,   TAKE1,  "Additional WHERE clause for group/user-name lookup" },
  945.      
  946.     { "AuthMySQL_Group_Table",      ap_set_string_slot,
  947.       (void *) XtOffsetOf(mysql_auth_config_rec, group_table),
  948.       OR_AUTHCFG,   TAKE1,  "Name of the MySQL table containing the group-name/user-name combination; can be the same as the password-table." },
  949.  
  950.     { "Auth_MySQL_Password_Field",      ap_set_string_slot,
  951.       (void *) XtOffsetOf(mysql_auth_config_rec, password_field),
  952.       OR_AUTHCFG,   TAKE1,  "The name of the field in the MySQL password table" },
  953.  
  954.     { "AuthMySQL_Password_Field",       ap_set_string_slot,
  955.       (void *) XtOffsetOf(mysql_auth_config_rec, password_field),
  956.       OR_AUTHCFG,   TAKE1,  "The name of the field in the MySQL password table" },
  957.  
  958.     { "Auth_MySQL_Password_Clause",     ap_set_string_slot,
  959.       (void *) XtOffsetOf(mysql_auth_config_rec, password_where_clause),
  960.       OR_AUTHCFG,   TAKE1,  "Additional WHERE clause for group password/user-name lookup" },
  961.  
  962.     { "Auth_MySQL_Username_Field",      ap_set_string_slot,
  963.       (void *) XtOffsetOf(mysql_auth_config_rec, user_field),
  964.       OR_AUTHCFG,   TAKE1,  "The name of the user-name field in the MySQL password (and possibly group) table(s)." },
  965.      
  966.     { "AuthMySQL_Username_Field",       ap_set_string_slot,
  967.       (void *) XtOffsetOf(mysql_auth_config_rec, user_field),
  968.       OR_AUTHCFG,   TAKE1,  "The name of the user-name field in the MySQL password (and possibly group) table(s)." },
  969.      
  970.     { "Auth_MySQL_Group_Field",     ap_set_string_slot,
  971.       (void *) XtOffsetOf(mysql_auth_config_rec, group_field),
  972.       OR_AUTHCFG,   TAKE1,  "The name of the group field in the MySQL group table; must be set if you want to use groups." },
  973.  
  974.     { "AuthMySQL_Group_Field",      ap_set_string_slot,
  975.       (void *) XtOffsetOf(mysql_auth_config_rec, group_field),
  976.       OR_AUTHCFG,   TAKE1,  "The name of the group field in the MySQL group table; must be set if you want to use groups." },
  977.  
  978.     { "Auth_MySQL_Group_User_Field",    ap_set_string_slot,
  979.       (void *) XtOffsetOf(mysql_auth_config_rec, group_user_field),
  980.       OR_AUTHCFG,   TAKE1,  "The name of the user-name field in the MySQL group table; defaults to the same as the username field for the password table." },
  981.  
  982.     { "AuthMySQL_Group_User_Field",     ap_set_string_slot,
  983.       (void *) XtOffsetOf(mysql_auth_config_rec, group_user_field),
  984.       OR_AUTHCFG,   TAKE1,  "The name of the user-name field in the MySQL group table; defaults to the same as the username field for the password table." },
  985.  
  986.     { "Auth_MySQL_Empty_Passwords",     ap_set_flag_slot,
  987.       (void *) XtOffsetOf(mysql_auth_config_rec, allow_empty_passwords),
  988.       OR_AUTHCFG,   FLAG,   "Enable (on) or disable (off) empty password strings; in which case any user password is accepted." },
  989.  
  990.     { "AuthMySQL_Empty_Passwords",      ap_set_flag_slot,
  991.       (void *) XtOffsetOf(mysql_auth_config_rec, allow_empty_passwords),
  992.       OR_AUTHCFG,   FLAG,   "Enable (on) or disable (off) empty password strings; in which case any user password is accepted." },
  993.  
  994.     { "Auth_MySQL_Authoritative",       ap_set_flag_slot,
  995.       (void *) XtOffsetOf(mysql_auth_config_rec, authoritative),
  996.       OR_AUTHCFG,   FLAG,   "When 'on' the MySQL database is taken to be authoritative and access control is not passed along to other db or access modules." },
  997.  
  998.     { "AuthMySQL_Authoritative",        ap_set_flag_slot,
  999.       (void *) XtOffsetOf(mysql_auth_config_rec, authoritative),
  1000.       OR_AUTHCFG,   FLAG,   "When 'on' the MySQL database is taken to be authoritative and access control is not passed along to other db or access modules." },
  1001.  
  1002.     { "AuthMySQL_AllowOverride",        set_auth_mysql_override,
  1003.       NULL,
  1004.       RSRC_CONF,    FLAG,   "Allow directory overrides of configuration" },
  1005.  
  1006.     { "Auth_MySQL_Encrypted_Passwords", set_crypted_password_flag,
  1007.       NULL,
  1008.       OR_AUTHCFG,   FLAG,   "When 'on' the password in the password table are taken to be crypt()ed using your machines crypt() function." },
  1009.  
  1010.     { "AuthMySQL_Encrypted_Passwords",  set_crypted_password_flag,
  1011.       NULL,
  1012.       OR_AUTHCFG,   FLAG,   "When 'on' the password in the password table are taken to be crypt()ed using your machines crypt() function." },
  1013.  
  1014.     { "Auth_MySQL_Scrambled_Passwords", set_scrambled_password_flag,
  1015.       NULL,
  1016.       OR_AUTHCFG,   FLAG,   "When 'on' the password in the password table are taken to be scramble()d using mySQL's password() function." },
  1017.  
  1018.     { "AuthMySQL_Scrambled_Passwords",  set_scrambled_password_flag,
  1019.       NULL,
  1020.       OR_AUTHCFG,   FLAG,   "When 'on' the password in the password table are taken to be scramble()d using mySQL's password() function." },
  1021.  
  1022.     { "Auth_MySQL_Encryption_Types",    set_encryption_types,
  1023.       NULL,
  1024.       OR_AUTHCFG,   ITERATE,"Encryption types to use" },
  1025.  
  1026.     { "AuthMySQL_Encryption_Types",     set_encryption_types,
  1027.       NULL,
  1028.       OR_AUTHCFG,   ITERATE,"Encryption types to use" },
  1029.  
  1030.     { "Auth_MySQL_Non_Persistent",      set_non_persistent,
  1031.       NULL,
  1032.       OR_AUTHCFG,   FLAG,   "Use non-persistent MySQL links" },
  1033.  
  1034.     { "AuthMySQL_Persistent",       set_persistent,
  1035.       NULL,
  1036.       OR_AUTHCFG,   FLAG,   "Use non-persistent MySQL links" },
  1037.  
  1038.     { "Auth_MySQL",             enable_mysql,
  1039.       NULL,
  1040.       OR_AUTHCFG,   FLAG,   "Enable MySQL authentication" },
  1041.  
  1042.     { "AuthMySQL",              enable_mysql,
  1043.       NULL,
  1044.       OR_AUTHCFG,   FLAG,   "Enable MySQL authentication" },
  1045.  
  1046.     { "Auth_MySQL_Where",           ap_set_string_slot,
  1047.       (void *) XtOffsetOf(mysql_auth_config_rec, password_where_clause),
  1048.       OR_AUTHCFG,   TAKE1,  "Additional WHERE clause for group password/user-name lookup" },
  1049.  
  1050.     { NULL }
  1051. };
  1052.  
  1053. /*  { "Auth_MySQL",             ap_set_flag_slot,       (void *) XtOffsetOf(mysql_auth_config_rec, enable_mysql_auth),      OR_AUTHCFG, FLAG,   "Enable (on) or disable (off) MySQL authentication." },
  1054.     { "AuthMySQL",              ap_set_flag_slot,       (void *) XtOffsetOf(mysql_auth_config_rec, enable_mysql_auth),      OR_AUTHCFG, FLAG,   "Enable (on) or disable (off) MySQL authentication." },
  1055. */
  1056.  
  1057.  
  1058. #endif
  1059.  
  1060. #ifdef APACHE2
  1061. static apr_status_t
  1062. #else
  1063. static void
  1064. #endif
  1065. auth_mysql_result_cleanup(void *result)
  1066. {
  1067.     mysql_free_result((MYSQL_RES *) result);
  1068. }
  1069.  
  1070. #ifdef APACHE2
  1071. static void note_cleanups_for_mysql_auth_result(apr_pool_t *p, MYSQL_RES * result)
  1072. #else
  1073. static void note_cleanups_for_mysql_auth_result(pool *p, MYSQL_RES * result)
  1074. #endif
  1075. {
  1076. #ifdef APACHE2
  1077.     apr_pool_cleanup_register(p, (void *) result, auth_mysql_result_cleanup, auth_mysql_result_cleanup);
  1078. #else
  1079.     ap_register_cleanup(p, (void *) result, auth_mysql_result_cleanup, auth_mysql_result_cleanup);
  1080. #endif
  1081.  
  1082. }
  1083.  
  1084. /* Make a MySQL database link open and ready for business.  Returns 0 on
  1085.  * success, or the MySQL error number which caused the failure if there was
  1086.  * some sort of problem.
  1087.  */
  1088. static int open_auth_dblink(request_rec *r, mysql_auth_config_rec *sec)
  1089. {
  1090.     char *host = "localhost", *socket = NULL;
  1091.     unsigned int port = 3306;
  1092.     char *dbname = auth_db_name, *user = auth_db_user, *pwd = auth_db_pwd;
  1093.     void (*sigpipe_handler)();
  1094.     unsigned long client_flag = 0;
  1095.  
  1096.     APACHELOG(APLOG_DEBUG, r, "Opening DB connection for %s", sec->dir);
  1097.    
  1098.     if (auth_db_host) {
  1099.         host = auth_db_host;
  1100.     }
  1101.  
  1102.     if (auth_db_socket)
  1103.     {
  1104.         socket = auth_db_socket;
  1105.     }
  1106.  
  1107.     if (auth_db_port != -1)
  1108.     {
  1109.         port = auth_db_port;
  1110.     }
  1111.    
  1112.     if (auth_db_override)
  1113.     {
  1114.         if (sec->db_socket)
  1115.         {
  1116.             socket = sec->db_socket;
  1117.         }
  1118.    
  1119.         if (sec->db_port != -1)
  1120.         {
  1121.             port = sec->db_port;
  1122.         }
  1123.        
  1124.         if (sec->db_host)
  1125.         {
  1126.             host = sec->db_host;
  1127.         }
  1128.  
  1129.         if (sec->db_user) {
  1130.             user = sec->db_user;
  1131.         }
  1132.  
  1133.         if (sec->db_pwd) {
  1134.             pwd = sec->db_pwd;
  1135.         }
  1136.  
  1137.         if (sec->db_name) {
  1138.             dbname = sec->db_name;
  1139.         }
  1140.     }
  1141.  
  1142.     if (!dbname || !dbname[0]) {
  1143.         /* It would be preferred if we had somewhere to connect to... */
  1144.         APACHELOG(APLOG_CRIT, r,
  1145.             "No database given - rather a problem.  Bailing out.");
  1146.         return CR_WRONG_HOST_INFO;
  1147.     }
  1148.  
  1149.     /* MySQL likes to throw the odd SIGPIPE now and then - ignore it for now */
  1150.     sigpipe_handler = signal(SIGPIPE, SIG_IGN);
  1151.        
  1152.     sec->dbh = mysql_init(NULL);
  1153.    
  1154.     if (!mysql_real_connect(sec->dbh, host, user, pwd, dbname, port, socket, client_flag)) {
  1155.         APACHELOG(APLOG_ERR, r,
  1156.              "Connection error: %s", mysql_error(sec->dbh));
  1157.         errno = mysql_errno(sec->dbh);
  1158.         mysql_close(sec->dbh);
  1159.         sec->dbh = NULL;
  1160.         return errno;
  1161.     }
  1162.  
  1163.     signal(SIGPIPE, sigpipe_handler);
  1164.    
  1165.     APACHELOG(APLOG_DEBUG, r, "Persistent in %s is %i", sec->dir, sec->persistent);
  1166.  
  1167.     if (!sec->persistent) {
  1168.         APACHELOG(APLOG_DEBUG, r, "Registering non-persistent for %s", sec->dir);
  1169. #ifdef APACHE2
  1170.         apr_pool_cleanup_register(r->pool, sec, auth_mysql_cleanup, apr_pool_cleanup_null);
  1171. #else
  1172.         ap_block_alarms();
  1173.         ap_register_cleanup(r->pool, sec, auth_mysql_cleanup, ap_null_cleanup);
  1174.         ap_unblock_alarms();
  1175. #endif
  1176.     }
  1177.  
  1178.     /* W00t!  We made it! */
  1179.     return 0;
  1180. }
  1181.  
  1182. /* Run a query against the database.  Doesn't assume nearly anything about
  1183.  * the state of affairs regarding the database connection.
  1184.  * Returns 0 on a successful query run, or the MySQL error number on
  1185.  * error.  It is the responsibility of the calling function to retrieve any
  1186.  * data which may have been obtained through the running of this function.
  1187.  */
  1188. static int safe_mysql_query(request_rec *r, char *query, mysql_auth_config_rec *sec)
  1189. {
  1190.     int error = CR_UNKNOWN_ERROR;
  1191.  
  1192.     APACHELOG(APLOG_DEBUG, r, "sec->dbh in %s is %p", sec->dir, sec->dbh);
  1193.     if (sec->dbh_error_lastchance)
  1194.     {
  1195.         APACHELOG(APLOG_DEBUG, r, "Last chance, bub");
  1196.     }
  1197.     else
  1198.     {
  1199.         APACHELOG(APLOG_DEBUG, r, "Ordinary query");
  1200.     }
  1201.    
  1202.     if (!sec->dbh) {
  1203.         APACHELOG(APLOG_DEBUG, r,
  1204.             "No DB connection open - firing one up");
  1205.         if ((error = open_auth_dblink(r, sec))) {
  1206.             APACHELOG(APLOG_DEBUG, r,
  1207.                 "open_auth_dblink returned %i", error);
  1208.             return error;
  1209.         }
  1210.  
  1211.         APACHELOG(APLOG_DEBUG, r,
  1212.             "Correctly opened a new DB connection");
  1213.     }
  1214.  
  1215.     APACHELOG(APLOG_DEBUG, r,
  1216.         "Running query: [%s]", query);
  1217.  
  1218.     if (mysql_query(sec->dbh, query)) {
  1219.         error = mysql_errno(sec->dbh);
  1220.        
  1221.         APACHELOG(APLOG_DEBUG, r,
  1222.             "Query maybe-failed: %s (%i), lastchance=%i", mysql_error(sec->dbh), error, sec->dbh_error_lastchance);
  1223.         APACHELOG(APLOG_DEBUG, r,
  1224.             "Error numbers of interest are %i (SG) and %i (SL)",
  1225.             CR_SERVER_GONE_ERROR, CR_SERVER_LOST);
  1226.         if (sec->dbh_error_lastchance)
  1227.         {
  1228.             /* No matter what error, we're moving out */
  1229.             return error;
  1230.         }
  1231.         else if (error == CR_SERVER_LOST || error == CR_SERVER_GONE_ERROR)
  1232.         {
  1233.             /* Try again, once more only */
  1234.             sec->dbh_error_lastchance = 1;
  1235.             sec->dbh = NULL;
  1236.             APACHELOG(APLOG_DEBUG, r, "Retrying query");
  1237.             return safe_mysql_query(r, query, sec);
  1238.         }
  1239.         else
  1240.         {
  1241.             return error;
  1242.         }
  1243.     }
  1244.  
  1245.     return 0;
  1246. }
  1247.  
  1248. /* Store the result of a query in a result structure, and return it.  It's
  1249.  * "safe" in the fact that a cleanup function is registered for the structure
  1250.  * so it will be tidied up after the request.
  1251.  * Returns the result data on success, or NULL if there was no data to retrieve.
  1252.  */
  1253. #ifdef APACHE2
  1254. static MYSQL_RES *safe_mysql_store_result(apr_pool_t *p, mysql_auth_config_rec *sec)
  1255. #else
  1256. static MYSQL_RES *safe_mysql_store_result(pool *p, mysql_auth_config_rec *sec)
  1257. #endif
  1258. {
  1259.     MYSQL_RES *result;
  1260. #ifdef APACHE2
  1261. #else  
  1262.     ap_block_alarms();
  1263. #endif
  1264.  
  1265.     result = mysql_store_result(sec->dbh);
  1266. #ifdef DEBUG
  1267.     syslog(LOG_DEBUG, "MAMDEBUG: Got %p for result", result);
  1268. #endif
  1269.  
  1270.     if (result) {
  1271.         note_cleanups_for_mysql_auth_result(p, result);
  1272.     }
  1273. #ifdef APACHE2
  1274. #else
  1275.     ap_unblock_alarms();
  1276. #endif
  1277.  
  1278.     return result;
  1279. }
  1280.  
  1281. /* Check the plaintext password given against the hashed version.  Go
  1282.  * through all configured encryption types looking for a match.
  1283.  * Returns 1 on a match, 0 on no match, and -1 on error.
  1284.  */
  1285. static int check_password(const char *plaintext, char *hashed, request_rec *r, mysql_auth_config_rec *sec)
  1286. {
  1287.     encryption_type_entry *ete;
  1288.    
  1289.     /* empty password support */
  1290.     if (sec->allow_empty_passwords && !strlen(hashed)) {
  1291.         APACHELOG(APLOG_INFO, r, "User successful on empty password");
  1292.         return 1;
  1293.     }
  1294.            
  1295.     for (ete=supported_encryption_types; ete->name; ete++) {
  1296.         if (sec->encryption_types & ete->flag) {
  1297.             APACHELOG(APLOG_DEBUG, r,
  1298.                 "Checking with %s", ete->name);
  1299.             if (ete->check_function(plaintext, hashed)) {
  1300.                 APACHELOG(APLOG_DEBUG, r, "Auth succeeded");
  1301.                 return 1;
  1302.             }
  1303.         }
  1304.     }
  1305.     APACHELOG(APLOG_DEBUG, r, "User failed all encryption types");
  1306.     return 0;
  1307. }
  1308.  
  1309. /* Checks whether the username and plaintext password match the user data
  1310.  * stored in the database, against all configured encryption schemes.
  1311.  * Returns 1 on successful match, 0 unsuccessful match, -1 on error.
  1312.  */
  1313. static int mysql_check_user_password(request_rec *r, char *user, const char *password, mysql_auth_config_rec *sec)
  1314. {
  1315.     char *auth_table = "mysql_auth", *auth_user_field = "username",
  1316.         *auth_password_field = "passwd", *auth_password_clause = "";
  1317.     char *query;
  1318.     char *esc_user = mysql_escape(user, r->pool);
  1319.     MYSQL_RES *result;
  1320.     MYSQL_ROW sql_row;
  1321.     int rv;
  1322.        
  1323.     if (sec->user_table) {
  1324.         auth_table = sec->user_table;
  1325.     }
  1326.     if (sec->user_field) {
  1327.         auth_user_field = sec->user_field;
  1328.     }
  1329.     if (sec->password_field) {
  1330.         auth_password_field = sec->password_field;
  1331.     }
  1332.     if (sec->password_where_clause) {
  1333.         auth_password_clause = sec->password_where_clause;
  1334.     }
  1335.     APACHELOG(APLOG_DEBUG, r,
  1336.         "Constructing password collection query with "
  1337.         "passfield=[%s], table=[%s], userfield=[%s], where_clause=[%s]", auth_password_field
  1338.                             , auth_table, esc_user,auth_password_clause);
  1339.  
  1340.     query = (char *) PSTRCAT(r->pool, "SELECT ", auth_password_field,
  1341.                     " FROM ", auth_table, " WHERE ",
  1342.                     auth_user_field, "='", esc_user, "'",
  1343.                     auth_password_clause, NULL);
  1344.     if (!query) {
  1345.         APACHELOG(APLOG_ERR, r,
  1346.             "Failed to create query string - we're in deep poopy");
  1347.         return -1;
  1348.     }
  1349.  
  1350.     if ((rv = safe_mysql_query(r, query, sec))) {
  1351.         if (sec->dbh)
  1352.         {
  1353.             APACHELOG(APLOG_ERR, r,
  1354.                 "Query call failed: %s (%i)", mysql_error(sec->dbh), rv);
  1355.         }
  1356.  
  1357.         APACHELOG(APLOG_DEBUG, r, "Failed query was: [%s]", query);
  1358.         return -1;
  1359.     }
  1360.  
  1361.     result = safe_mysql_store_result(r->pool, sec);
  1362.     if (!result) {
  1363.         APACHELOG(APLOG_ERR, r,
  1364.             "Failed to get MySQL result structure : %s", mysql_error(sec->dbh));
  1365.         return -1;
  1366.     }
  1367.     switch (mysql_num_rows(result)) {
  1368.         case 0:
  1369.             APACHELOG(APLOG_INFO, r, "User not found");
  1370.             return 0;
  1371.             break;
  1372.         case 1:
  1373.             sql_row = mysql_fetch_row(result);
  1374.             /* ensure we have a row, and non NULL value */
  1375.             if (!sql_row || !sql_row[0]) {
  1376.                 APACHELOG(APLOG_INFO, r,
  1377.                     "No row returned or NULL value: %s", mysql_error(sec->dbh));
  1378.                 return -1;
  1379.             }
  1380.            
  1381.             rv = check_password(password, sql_row[0], r, sec);
  1382.             if (rv == 0)
  1383.             {
  1384.                 APACHELOG(APLOG_INFO, r,
  1385.                     "Authentication failed for user %s", user);
  1386.             }
  1387.             return rv;
  1388.             break;
  1389.  
  1390.         default:
  1391.             APACHELOG(APLOG_ERR, r,
  1392.                 "Multiple password rows returned - this is what is known, in the industry, as a Bad Thing");
  1393.             return -1;
  1394.             break;
  1395.     }
  1396.  
  1397.     APACHELOG(APLOG_CRIT, r, "Can't happen - dropped out of switch!");
  1398.     return -1;
  1399. }
  1400.  
  1401. /* Has a look to see if the given user is a member of the named group.
  1402.  * Returns 0 if user is not a part of the group, 1 if he is, -1 on error.
  1403.  */
  1404. static int mysql_check_group(request_rec *r, char *user, char *group, mysql_auth_config_rec *sec)
  1405. {
  1406.     char *auth_table = "mysql_auth", *auth_group_field="groups", *auth_group_clause="";
  1407.     char *query;
  1408.     char *esc_user = mysql_escape(user, r->pool);
  1409.     char *esc_group = mysql_escape(group, r->pool);
  1410.     MYSQL_RES *result;
  1411.     MYSQL_ROW row;
  1412.     char *auth_user_field = "username";
  1413.  
  1414.     if (!group) {
  1415.         APACHELOG(APLOG_ERR, r, "No group specified");
  1416.         return 0;
  1417.     }
  1418.    
  1419.     if (sec->group_table) {
  1420.         auth_table = sec->group_table;
  1421.     }
  1422.  
  1423.     if (sec->user_field)
  1424.     {
  1425.         auth_user_field = sec->user_field;
  1426.     }
  1427.  
  1428.     if (sec->group_user_field) {
  1429.         auth_user_field = sec->group_user_field;
  1430.     }
  1431.        
  1432.     if (sec->group_field) {
  1433.         auth_group_field = sec->group_field;
  1434.     }
  1435.     if (sec->group_where_clause) {
  1436.         auth_group_clause = sec->group_where_clause;
  1437.     }
  1438.  
  1439.     APACHELOG(APLOG_DEBUG, r,
  1440.         "Making group query with auth_table=[%s], auth_user_field=[%s], "
  1441.         "esc_user=[%s], esc_group=[%s], auth_group_field=[%s], where_clause=[%s]",
  1442.         auth_table, auth_user_field, esc_user, esc_group, auth_group_field,auth_group_clause);
  1443.  
  1444.     query = (char *) PSTRCAT(r->pool, "SELECT count(*) FROM ", auth_table,
  1445.         " WHERE ", auth_user_field, "='", esc_user, "'",
  1446.         " and FIND_IN_SET('", esc_group, "',", auth_group_field, ")",
  1447.         auth_group_clause, NULL);
  1448.  
  1449.     APACHELOG(APLOG_DEBUG, r, "Group query created; [%s]", query);
  1450.        
  1451.     if (!query) {
  1452.         APACHELOG(APLOG_CRIT, r,
  1453.             "Failed to create group-check query - ran out of memory!");
  1454.         return -1;
  1455.     }
  1456.     if (safe_mysql_query(r, query, sec)) {
  1457.         APACHELOG(APLOG_CRIT, r, "Group query failed!");
  1458.         return -1;
  1459.     }
  1460.     result = safe_mysql_store_result(r->pool, sec);
  1461.     if (!result || (row=mysql_fetch_row(result))==NULL || !row[0]) {
  1462.         APACHELOG(APLOG_CRIT, r, "Store result failed - erp!");
  1463.         return -1;
  1464.     }
  1465.  
  1466.     return atoi(row[0]);
  1467. }
  1468.  
  1469. /* The apache-called function.  Note that this function says nothing about
  1470.  * what the user should be allowed to do - merely that they have proved they
  1471.  * are who they say they are.  Return OK if the user has proved their
  1472.  * identity, DECLINED if we are not taking any responsibility for them, or
  1473.  * some Apache error if there was a problem.
  1474.  */
  1475. int mysql_authenticate_basic_user(request_rec *r)
  1476. {
  1477.     mysql_auth_config_rec *sec = (mysql_auth_config_rec *) ap_get_module_config(r->per_dir_config, &auth_mysql_module);
  1478.     conn_rec *c = r->connection;
  1479.     const char *sent_pw;
  1480.     int res;
  1481.  
  1482.     APACHELOG(APLOG_DEBUG, r, "Handling an authentication request for section %s", sec->dir);
  1483.  
  1484. #ifdef DEBUG
  1485.     for (res = 0; res < 512; res++)
  1486.     {
  1487.         if (sec->sacrificial_lamb[res] == '\0')
  1488.         {
  1489.             sec->sacrificial_lamb[res] = 'n';
  1490.         }
  1491.         if (!isgraph(sec->sacrificial_lamb[res]))
  1492.         {
  1493.             sec->sacrificial_lamb[res] = ' ';
  1494.         }
  1495.     }
  1496.     sec->sacrificial_lamb[511] = '\0';
  1497.    
  1498.     syslog(LOG_DEBUG, "The contents of the lamb are %s", sec->sacrificial_lamb);
  1499. #endif
  1500.  
  1501.     if (!sec->enable_mysql_auth) {
  1502.         APACHELOG(APLOG_DEBUG, r,
  1503.             "Not running mod-auth-mysql for %s - disabled", r->unparsed_uri);
  1504.         return DECLINED;
  1505.     }
  1506.  
  1507.     /* use MySQL auth only if we have a database */
  1508.     if (!auth_db_name && !sec->db_name) {
  1509.         APACHELOG(APLOG_ERR, r,
  1510.             "Failed to run mod-auth-mysql for %s: No database name specified", r->unparsed_uri);
  1511.         return DECLINED;
  1512.     }
  1513.  
  1514.     /* obtain sent password */
  1515.     if ((res = ap_get_basic_auth_pw(r, &sent_pw))) {
  1516.         return res;
  1517.     }
  1518.  
  1519. #ifdef APACHE2
  1520.     APACHELOG(APLOG_DEBUG, r,
  1521.         "Starting basic user auth for [%s] in %s, child pid %i",
  1522.         r->user,
  1523.         sec->dir, getpid());
  1524. #else
  1525.     APACHELOG(APLOG_DEBUG, r,
  1526.         "Starting basic user auth for [%s] in %s, child pid %i",
  1527.         c->user,
  1528.         sec->dir, getpid());
  1529. #endif
  1530.  
  1531. #ifdef APACHE2
  1532.     switch (mysql_check_user_password(r, r->user, sent_pw, sec)) {
  1533. #else
  1534.     switch (mysql_check_user_password(r, c->user, sent_pw, sec)) {
  1535. #endif
  1536.         case 0:
  1537.             ap_note_basic_auth_failure(r);
  1538.             return HTTP_UNAUTHORIZED;
  1539.             break;
  1540.         case 1:
  1541.             return OK;
  1542.             break;
  1543.         case -1:
  1544.         default:
  1545.             APACHELOG(APLOG_DEBUG, r,
  1546.                 "mysql_check_user_password returned error");
  1547.             return HTTP_INTERNAL_SERVER_ERROR;
  1548.             break;
  1549.     }
  1550. }
  1551.  
  1552. /* Go through a 'requires' line configured for the module, and return OK
  1553.  * if the user satisfies the line, or some sort of failure return code
  1554.  * otherwise.
  1555.  */
  1556. int check_mysql_auth_require(char *user, const char *t, request_rec *r)
  1557. {
  1558.     mysql_auth_config_rec *sec = (mysql_auth_config_rec *) ap_get_module_config(r->per_dir_config, &auth_mysql_module);
  1559.     const char *w;
  1560.     int rv;
  1561.    
  1562.     w = ap_getword(r->pool, &t, ' ');
  1563.     /* If they're letting any old authenticated user, we're off the
  1564.      * hook!
  1565.      */
  1566.     if (!strcmp(w, "valid-user")) {
  1567.         return OK;
  1568.     }
  1569.  
  1570.     /* Checking a list of usernames */
  1571.     if (!strcmp(w, "user")) {
  1572.         while (t[0]) {
  1573.             w = ap_getword_conf(r->pool, &t);
  1574.             if (!strcmp(user, w)) {
  1575.                 return OK;
  1576.             }
  1577.         }
  1578.         /* Not found */
  1579.         return HTTP_UNAUTHORIZED;
  1580.     } else if (!strcmp(w, "group")) {
  1581.         /* This is the prickly one; checking whether the
  1582.          * user is a member of a listed group.
  1583.          */
  1584.         while (t[0])
  1585.         {
  1586.             w = ap_getword_conf(r->pool, &t);
  1587.             rv = mysql_check_group(r, user, (char *)w, sec);
  1588.            
  1589.             if (rv == 1)
  1590.             {
  1591.                 /* Yep, we're all good */
  1592.                 return OK;
  1593.             }
  1594.             else if (rv == -1)
  1595.             {
  1596.                 return HTTP_INTERNAL_SERVER_ERROR;
  1597.             }
  1598.         }
  1599.         /* Distinct lack of foundage */
  1600.         return HTTP_UNAUTHORIZED;
  1601.     }
  1602.     else
  1603.     {
  1604.         APACHELOG(APLOG_ERR, r, "Invalid argument to require: %s", w);
  1605.         return HTTP_INTERNAL_SERVER_ERROR;
  1606.     }
  1607.  
  1608.     APACHELOG(APLOG_ERR, r, "CAN'T HAPPEN: Dropped out of the bottom of check_mysql_auth_require!");
  1609.     return HTTP_INTERNAL_SERVER_ERROR;
  1610. }
  1611.  
  1612. /* This is the authorization step.  We're presuming that the user has
  1613.  * successfully negotiated the step of "I am who I say I am", now we're
  1614.  * checking to see if the user has permission to access this particular
  1615.  * resource.  As with mysql_authenticate_basic_user, above, we return OK if
  1616.  * the user is fit to proceed, DECLINED if we don't want to make a decision
  1617.  * either way, HTTP_UNAUTHORIZED if the user is not allowed, or some apache
  1618.  * error if there was a major problem.
  1619.  */
  1620. int mysql_check_auth(request_rec *r)
  1621. {
  1622.     mysql_auth_config_rec *sec = (mysql_auth_config_rec *) ap_get_module_config(r->per_dir_config, &auth_mysql_module);
  1623. #ifdef APACHE2
  1624.     char *user = r->user;
  1625. #else
  1626.     char *user = r->connection->user;
  1627. #endif
  1628.     int m = r->method_number;
  1629.     int rv;
  1630.     register int x;
  1631.     const char *t;
  1632. #ifdef APACHE2
  1633.     const apr_array_header_t *reqs_arr = ap_requires(r);
  1634. #else
  1635.     const array_header *reqs_arr = ap_requires(r);
  1636. #endif
  1637.     require_line *reqs;
  1638.  
  1639.     /* use MySQL auth only if we have a database */
  1640.     if (!auth_db_name && !sec->db_name) {
  1641.         return DECLINED;
  1642.     }
  1643.  
  1644.     /* What do we do if there's no requires line available?  Either say
  1645.      * "bad puppy" if we're king shit, or say "not my problem" otherwise.
  1646.      */
  1647.     if (!reqs_arr) {
  1648.         if (sec->authoritative) {
  1649.             APACHELOG(APLOG_ERR, r, "No requires line available");
  1650.             return HTTP_UNAUTHORIZED;
  1651.         } else {
  1652.             return DECLINED;
  1653.         }
  1654.     }
  1655.  
  1656.     /* This is an array of all the requires lines which apply to us.
  1657.      * There may be several, as in the case of something like:
  1658.      * require user foo bar
  1659.      * require group wombat
  1660.      * That is, the user either has to belong to the group 'wombat' or
  1661.      * be 'foo' or 'bar'.
  1662.      * We have to check them all.  Yuck.
  1663.      */
  1664.     reqs = (require_line *) reqs_arr->elts;
  1665.  
  1666.     for (x = 0; x < reqs_arr->nelts; x++) {
  1667.         /* mjp: WTF is this? */
  1668.         if (!(reqs[x].method_mask & (1 << m))) {
  1669.             continue;
  1670.         }
  1671.  
  1672.         t = reqs[x].requirement;
  1673.  
  1674.         /* OK, this might seem a little weird.  The logic is that,
  1675.          * if the user is approved, that's sufficient, so we can
  1676.          * return OK straight away.  Alternately, if there's an
  1677.          * error, we bomb the check and die.  The only circumstance
  1678.          * where we continue looping is when the user didn't pass this
  1679.          * check, but might pass a future one, so keep looking.
  1680.          */
  1681.         if ((rv = check_mysql_auth_require(user, t, r))
  1682.             != HTTP_UNAUTHORIZED)
  1683.         {
  1684.             return rv;
  1685.         }
  1686.     }
  1687.  
  1688.     /* We don't know, and we don't really care */
  1689.     if (!(sec->authoritative)) {
  1690.         return DECLINED;
  1691.     }
  1692.  
  1693.     ap_note_basic_auth_failure(r);
  1694.     return HTTP_UNAUTHORIZED;
  1695. }
  1696.  
  1697.  
  1698.  
  1699. #ifdef APACHE2
  1700. static void register_hooks(apr_pool_t *p)
  1701. {
  1702.     ap_hook_check_user_id(mysql_authenticate_basic_user, NULL, NULL, APR_HOOK_MIDDLE);
  1703.     ap_hook_auth_checker(mysql_check_auth, NULL, NULL, APR_HOOK_MIDDLE);
  1704. }
  1705. #endif
  1706.  
  1707. #ifdef APACHE2
  1708. module AP_MODULE_DECLARE_DATA auth_mysql_module =
  1709. {
  1710. STANDARD20_MODULE_STUFF,
  1711. create_mysql_auth_dir_config, /* dir config creater */
  1712. NULL,                       /* dir merger --- default is to override */
  1713. NULL,                       /* server config */
  1714. NULL,                       /* merge server config */
  1715. mysql_auth_cmds,              /* command apr_table_t */
  1716. register_hooks              /* register hooks */
  1717. };
  1718. #else
  1719. module auth_mysql_module =
  1720. {
  1721.     STANDARD_MODULE_STUFF,
  1722.     mysql_auth_init_handler,    /* initializer */
  1723.     create_mysql_auth_dir_config,   /* dir config creater */
  1724.     NULL,               /* dir merger --- default is to override */
  1725.     NULL,               /* server config */
  1726.     NULL,               /* merge server config */
  1727.     mysql_auth_cmds,        /* command table */
  1728.     NULL,               /* handlers */
  1729.     NULL,               /* filename translation */
  1730.     mysql_authenticate_basic_user,  /* check_user_id */
  1731.     mysql_check_auth,       /* check auth */
  1732.     NULL,               /* check access */
  1733.     NULL,               /* type_checker */
  1734.     NULL,               /* pre-run fixups */
  1735.     NULL                /* logger */
  1736. #if MODULE_MAGIC_NUMBER >= 19970103
  1737.     ,NULL               /* header parser */
  1738. #endif
  1739. #if MODULE_MAGIC_NUMBER >= 19970719
  1740.     ,NULL               /* child_init */
  1741. #endif
  1742. #if MODULE_MAGIC_NUMBER >= 19970728
  1743.     ,NULL               /* child_exit */
  1744. #endif
  1745. #if MODULE_MAGIC_NUMBER >= 19970902
  1746.     ,NULL               /* post read-request */
  1747. #endif
  1748. };
  1749. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement