Advertisement
Guest User

Untitled

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