· 9 years ago · Sep 18, 2017, 08:32 PM
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 */
78static char *auth_db_host = NULL,
79 *auth_db_name = NULL,
80 *auth_db_user = NULL,
81 *auth_db_pwd = NULL;
82
83static int auth_db_override = 1;
84
85char *tmp_host = NULL;
86char *auth_db_socket = NULL;
87long auth_db_port = -1;
88unsigned 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
112static int check_no_encryption(const char *passwd, char *enc_passwd)
113{
114 return (!strcmp(passwd, enc_passwd));
115}
116
117
118#ifdef CRYPT_DES
119static 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
130static 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
141static int check_crypt_encryption(const char *passwd, char *enc_passwd)
142{
143 return (!strcmp(crypt(passwd, enc_passwd), enc_passwd));
144}
145#endif
146
147char hex_digit(char c)
148{
149 if (c < 10) {
150 return c+'0';
151 } else {
152 return c-10+'a';
153 }
154}
155
156static 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
190static int check_PHP_MD5_encryption(const char *passwd, char *enc_passwd)
191{
192 return (!strcmp(md5_hex_hash(passwd), enc_passwd));
193}
194
195static 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
230static int check_SHA1Sum_encryption(const char *passwd, char *enc_passwd)
231{
232 return (!strcmp(sha1_hex_hash(passwd), enc_passwd));
233}
234
235
236static 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
244static 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
253typedef struct {
254 char *name;
255 int (*check_function)(const char *passwd, char *enc_passwd);
256 int flag;
257} encryption_type_entry;
258
259encryption_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
276static 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 */
294typedef 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
342module auth_mysql_module;
343
344static int open_auth_dblink(request_rec *r, mysql_auth_config_rec *sec);
345
346#ifdef APACHE2
347static apr_status_t
348#else
349static void
350#endif
351
352auth_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
368void mysql_auth_init_handler(server_rec *s, apr_pool_t *p)
369#else
370void 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
386void *create_mysql_auth_dir_config(apr_pool_t *p, char *d)
387#else
388void *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 */
463static 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 */
489static 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
512static char *mysql_escape(mysql_auth_config_rec *sec, request_rec *r, char *str, apr_pool_t *p)
513#else
514static 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 */
535static 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 */
543static 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 */
551static 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 */
570static 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 */
579static 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 */
587static 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 */
595static 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 */
607static 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 */
615static 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 */
640static 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
649static 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
658static 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
667static 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
676static 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
690static
691command_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
967command_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
1251static apr_status_t
1252#else
1253static void
1254#endif
1255auth_mysql_result_cleanup(void *result)
1256{
1257 mysql_free_result((MYSQL_RES *) result);
1258}
1259
1260#ifdef APACHE2
1261static void note_cleanups_for_mysql_auth_result(apr_pool_t *p, MYSQL_RES * result)
1262#else
1263static 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 */
1278static 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 */
1406static 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
1472static MYSQL_RES *safe_mysql_store_result(apr_pool_t *p, mysql_auth_config_rec *sec)
1473#else
1474static 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 */
1503static 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 */
1537static 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 */
1644static 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 */
1715int 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 */
1796int 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 */
1860int 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
1940static 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
1948module AP_MODULE_DECLARE_DATA auth_mysql_module =
1949{
1950STANDARD20_MODULE_STUFF,
1951create_mysql_auth_dir_config, /* dir config creater */
1952NULL, /* dir merger --- default is to override */
1953NULL, /* server config */
1954NULL, /* merge server config */
1955mysql_auth_cmds, /* command apr_table_t */
1956register_hooks /* register hooks */
1957};
1958#else
1959module 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