$NetBSD: patch-aa,v 1.3 2007/02/25 15:51:50 sborrill Exp $ --- mod_auth_mysql.c.orig 2007-02-25 16:15:13.000000000 +0000 +++ mod_auth_mysql.c 2007-02-25 16:15:13.000000000 +0000 @@ -189,7 +189,9 @@ #include "http_core.h" #include "http_log.h" #include "http_protocol.h" +#include "apr_strings.h" #include +#include /* * structure to hold the configuration details for the request @@ -221,34 +223,26 @@ static MYSQL *mysql_handle = NULL; * Callback to close mysql handle when necessary. Also called when a * child httpd process is terminated. */ -static void +static apr_status_t mod_auth_mysql_cleanup (void *notused) { if (mysql_handle) mysql_close(mysql_handle); mysql_handle = NULL; /* make sure we don't try to use it later */ + return APR_SUCCESS; } /* * empty function necessary because register_cleanup requires it as one * of its parameters */ -static void +static apr_status_t mod_auth_mysql_cleanup_child (void *notused) { /* nothing */ + return APR_SUCCESS; } /* - * handler to do cleanup on child exit - */ -static void -child_exit(server_rec *s, pool *p) -{ - mod_auth_mysql_cleanup(NULL); -} - - -/* * open connection to DB server if necessary. Return TRUE if connection * is good, FALSE if not able to connect. If false returned, reason * for failure has been logged to error_log file already. @@ -274,22 +268,28 @@ open_db_handle(request_rec *r, mysql_aut db_host = m->mysqlhost; } - mysql_handle=mysql_connect(&mysql_conn,db_host,m->mysqluser,m->mysqlpasswd); + if (mysql_init(&mysql_conn) == NULL) { + ap_log_error (APLOG_MARK, APLOG_ERR, 0, r->server, + "mysql_init() failed"); + return FALSE; + } + mysql_handle=mysql_real_connect(&mysql_conn,db_host,m->mysqluser,m->mysqlpasswd, + NULL, 0, NULL, 0); if (mysql_handle) { if (!m->mysqlKeepAlive) { /* close when request done */ - ap_register_cleanup(r->pool, (void *)NULL, - mod_auth_mysql_cleanup, - mod_auth_mysql_cleanup_child); + apr_pool_cleanup_register(r->pool, r->server, + mod_auth_mysql_cleanup, + mod_auth_mysql_cleanup_child); } /* ELSE... * Child process is notified when it is terminated so we * do a graceful close to the server in that handler. */ } else { /* failed to get MySQL connection */ - ap_log_error (APLOG_MARK, APLOG_ERR, r->server, + ap_log_error (APLOG_MARK, APLOG_ERR, 0, r->server, "MySQL error: %s", mysql_error(&mysql_conn)); return FALSE; } @@ -299,9 +299,9 @@ open_db_handle(request_rec *r, mysql_aut static void * -create_mysql_auth_dir_config (pool *p, char *d) +create_mysql_auth_dir_config (apr_pool_t *p, char *d) { - mysql_auth_config_rec *m = ap_pcalloc (p, sizeof(mysql_auth_config_rec)); + mysql_auth_config_rec *m = apr_pcalloc (p, sizeof(mysql_auth_config_rec)); if (!m) return NULL; /* failure to get memory is a bad thing */ /* defaults values */ @@ -316,45 +316,45 @@ create_mysql_auth_dir_config (pool *p, c static command_rec mysql_auth_cmds[] = { - { "AuthMySQLHost", ap_set_string_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqlhost), - OR_AUTHCFG, TAKE1, "mysql server host name" }, - { "AuthMySQLUser", ap_set_string_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqluser), - OR_AUTHCFG, TAKE1, "mysql server user name" }, - { "AuthMySQLPassword", ap_set_string_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqlpasswd), - OR_AUTHCFG, TAKE1, "mysql server user password" }, - { "AuthMySQLDB", ap_set_string_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqlDB), - OR_AUTHCFG, TAKE1, "mysql database name" }, - { "AuthMySQLUserTable", ap_set_string_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqlpwtable), - OR_AUTHCFG, TAKE1, "mysql user table name" }, - { "AuthMySQLGroupTable", ap_set_string_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqlgrptable), - OR_AUTHCFG, TAKE1, "mysql group table name" }, - { "AuthMySQLNameField", ap_set_string_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqlNameField), - OR_AUTHCFG, TAKE1, "mysql User ID field name within table" }, - { "AuthMySQLGroupField", ap_set_string_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqlGroupField), - OR_AUTHCFG, TAKE1, "mysql Group field name within table" }, - { "AuthMySQLPasswordField", ap_set_string_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqlPasswordField), - OR_AUTHCFG, TAKE1, "mysql Password field name within table" }, - { "AuthMySQLCryptedPasswords", ap_set_flag_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqlCrypted), - OR_AUTHCFG, FLAG, "mysql passwords are stored encrypted if On" }, - { "AuthMySQLKeepAlive", ap_set_flag_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqlKeepAlive), - OR_AUTHCFG, FLAG, "mysql connection kept open across requests if On" }, - { "AuthMySQLAuthoritative", ap_set_flag_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqlAuthoritative), - OR_AUTHCFG, FLAG, "mysql lookup is authoritative if On" }, - { "AuthMySQLNoPasswd", ap_set_flag_slot, - (void*)XtOffsetOf(mysql_auth_config_rec, mysqlNoPasswd), - OR_AUTHCFG, FLAG, "If On, only check if user exists; ignore password" }, + AP_INIT_TAKE1("AuthMySQLHost", ap_set_string_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqlhost), + OR_AUTHCFG, "mysql server host name"), + AP_INIT_TAKE1("AuthMySQLUser", ap_set_string_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqluser), + OR_AUTHCFG, "mysql server user name"), + AP_INIT_TAKE1("AuthMySQLPassword", ap_set_string_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqlpasswd), + OR_AUTHCFG, "mysql server user password"), + AP_INIT_TAKE1("AuthMySQLDB", ap_set_string_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqlDB), + OR_AUTHCFG, "mysql database name"), + AP_INIT_TAKE1("AuthMySQLUserTable", ap_set_string_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqlpwtable), + OR_AUTHCFG, "mysql user table name"), + AP_INIT_TAKE1("AuthMySQLGroupTable", ap_set_string_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqlgrptable), + OR_AUTHCFG, "mysql group table name"), + AP_INIT_TAKE1("AuthMySQLNameField", ap_set_string_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqlNameField), + OR_AUTHCFG, "mysql User ID field name within table"), + AP_INIT_TAKE1("AuthMySQLGroupField", ap_set_string_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqlGroupField), + OR_AUTHCFG, "mysql Group field name within table"), + AP_INIT_TAKE1("AuthMySQLPasswordField", ap_set_string_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqlPasswordField), + OR_AUTHCFG, "mysql Password field name within table"), + AP_INIT_FLAG("AuthMySQLCryptedPasswords", ap_set_flag_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqlCrypted), + OR_AUTHCFG, "mysql passwords are stored encrypted if On"), + AP_INIT_FLAG("AuthMySQLKeepAlive", ap_set_flag_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqlKeepAlive), + OR_AUTHCFG, "mysql connection kept open across requests if On"), + AP_INIT_FLAG("AuthMySQLAuthoritative", ap_set_flag_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqlAuthoritative), + OR_AUTHCFG, "mysql lookup is authoritative if On"), + AP_INIT_FLAG("AuthMySQLNoPasswd", ap_set_flag_slot, + (void*)APR_OFFSETOF(mysql_auth_config_rec, mysqlNoPasswd), + OR_AUTHCFG, "If On, only check if user exists; ignore password"), { NULL } }; @@ -379,7 +379,7 @@ get_mysql_pw(request_rec *r, char *user, } if (mysql_select_db(mysql_handle,m->mysqlDB) != 0) { - ap_log_error (APLOG_MARK, APLOG_ERR, r->server, + ap_log_error (APLOG_MARK, APLOG_ERR, 0, r->server, "MySQL error: %s", mysql_error(mysql_handle)); return NULL; } @@ -394,13 +394,13 @@ get_mysql_pw(request_rec *r, char *user, } ulen = strlen(user); - sql_safe_user = ap_pcalloc(r->pool, ulen*2+1); - mysql_escape_string(sql_safe_user,user,ulen); - ap_snprintf(query,sizeof(query)-1,"SELECT %s FROM %s WHERE %s='%s'", - m->mysqlPasswordField, m->mysqlpwtable, - m->mysqlNameField, sql_safe_user); + sql_safe_user = apr_pcalloc(r->pool, ulen*2+1); + mysql_real_escape_string(mysql_handle,sql_safe_user,user,ulen); + apr_snprintf(query,sizeof(query)-1,"SELECT %s FROM %s WHERE %s='%s'", + m->mysqlPasswordField, m->mysqlpwtable, + m->mysqlNameField, sql_safe_user); if (mysql_query(mysql_handle, query) != 0) { - ap_log_error (APLOG_MARK, APLOG_ERR, r->server, + ap_log_error (APLOG_MARK, APLOG_ERR, 0, r->server, "MySQL error %s: %s", mysql_error(mysql_handle),r->uri); return NULL; } @@ -409,10 +409,10 @@ get_mysql_pw(request_rec *r, char *user, if (result && (mysql_num_rows(result) == 1)) { MYSQL_ROW data = mysql_fetch_row(result); if (data[0]) { - pw = ap_pstrdup(r->pool, data[0]); + pw = apr_pstrdup(r->pool, data[0]); } else { /* no password in mysql table returns NULL */ /* this should never happen, but test for it anyhow */ - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "MySQL user %s has no valid password: %s", user, r->uri); mysql_free_result(result); return NULL; @@ -443,19 +443,19 @@ get_mysql_groups(request_rec *r, char *u } if (mysql_select_db(mysql_handle,m->mysqlDB) != 0) { - ap_log_error (APLOG_MARK, APLOG_ERR, r->server, + ap_log_error (APLOG_MARK, APLOG_ERR, 0, r->server, "MySQL error %s: %s", mysql_error(mysql_handle),r->uri); return NULL; } ulen = strlen(user); - sql_safe_user = ap_pcalloc(r->pool, ulen*2+1); + sql_safe_user = apr_pcalloc(r->pool, ulen*2+1); mysql_escape_string(sql_safe_user,user,ulen); - ap_snprintf(query,sizeof(query)-1,"SELECT %s FROM %s WHERE %s='%s'", - m->mysqlGroupField, m->mysqlgrptable, - m->mysqlNameField, sql_safe_user); + apr_snprintf(query,sizeof(query)-1,"SELECT %s FROM %s WHERE %s='%s'", + m->mysqlGroupField, m->mysqlgrptable, + m->mysqlNameField, sql_safe_user); if (mysql_query(mysql_handle, query) != 0) { - ap_log_error (APLOG_MARK, APLOG_ERR, r->server, + ap_log_error (APLOG_MARK, APLOG_ERR, 0, r->server, "MySQL error %s: %s", mysql_error(mysql_handle),r->uri); return NULL; } @@ -463,12 +463,12 @@ get_mysql_groups(request_rec *r, char *u result = mysql_store_result(mysql_handle); if (result && (mysql_num_rows(result) > 0)) { int i = mysql_num_rows(result); - list = (char **)ap_pcalloc(r->pool, sizeof(char *) * (i+1)); + list = (char **)apr_pcalloc(r->pool, sizeof(char *) * (i+1)); list[i] = NULL; /* last element in array is NULL */ while (i--) { /* populate the array elements */ MYSQL_ROW data = mysql_fetch_row(result); if (data[0]) - list[i] = ap_pstrdup(r->pool, data[0]); + list[i] = apr_pstrdup(r->pool, data[0]); else list[i] = ""; /* if no data, make it empty, not NULL */ } @@ -499,15 +499,15 @@ mysql_authenticate_basic_user (request_r if(!sec->mysqlpwtable) /* not configured for mysql authorization */ return DECLINED; - if(!(real_pw = get_mysql_pw(r, c->user, sec))) { + if(!(real_pw = get_mysql_pw(r, r->user, sec))) { /* user not found in database */ if (!sec->mysqlAuthoritative) return DECLINED; /* let other schemes find user */ - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, - "MySQL user %s not found: %s", c->user, r->uri); + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "MySQL user %s not found: %s", r->user, r->uri); ap_note_basic_auth_failure (r); - return AUTH_REQUIRED; + return HTTP_UNAUTHORIZED; } /* if we don't require password, just return ok since they exist */ @@ -517,10 +517,10 @@ mysql_authenticate_basic_user (request_r /* compare the password, possibly encrypted */ if(strcmp(real_pw, sec->mysqlCrypted ? crypt(sent_pw,real_pw) : sent_pw)) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, - "user %s: password mismatch: %s", c->user, r->uri); + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "user %s: password mismatch: %s", r->user, r->uri); ap_note_basic_auth_failure (r); - return AUTH_REQUIRED; + return HTTP_UNAUTHORIZED; } return OK; } @@ -534,10 +534,10 @@ mysql_check_auth(request_rec *r) mysql_auth_config_rec *sec = (mysql_auth_config_rec *)ap_get_module_config(r->per_dir_config, &mysql_auth_module); - char *user = r->connection->user; + char *user = r->user; int method = r->method_number; - const array_header *reqs_arr = ap_requires(r); + const apr_array_header_t *reqs_arr = ap_requires(r); require_line *reqs = reqs_arr ? (require_line *)reqs_arr->elts : NULL; register int x; @@ -560,11 +560,11 @@ mysql_check_auth(request_rec *r) if(!strcmp(want,"group")) { /* check for list of groups from database only first time thru */ if (!groups && !(groups = get_mysql_groups(r, user, sec))) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "mysql user %s not in group table %s: %s", user, sec->mysqlgrptable, r->uri); ap_note_basic_auth_failure(r); - return AUTH_REQUIRED; + return HTTP_UNAUTHORIZED; } /* loop through list of groups specified in htaccess file */ @@ -578,35 +578,39 @@ mysql_check_auth(request_rec *r) ++i; } } - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "mysql user %s not in right group: %s",user,r->uri); ap_note_basic_auth_failure(r); - return AUTH_REQUIRED; + return HTTP_UNAUTHORIZED; } } return DECLINED; } +static void +child_init(apr_pool_t *p, server_rec *s) +{ + apr_pool_cleanup_register(p, s, + mod_auth_mysql_cleanup, + mod_auth_mysql_cleanup_child); +} + +static void +register_hooks(apr_pool_t *p) +{ + ap_hook_child_init(child_init, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_check_user_id(mysql_authenticate_basic_user, + NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_auth_checker(mysql_check_auth, NULL, NULL, APR_HOOK_MIDDLE); +} -module mysql_auth_module = { - STANDARD_MODULE_STUFF, - NULL, /* initializer */ +module AP_MODULE_DECLARE_DATA mysql_auth_module = { + STANDARD20_MODULE_STUFF, create_mysql_auth_dir_config, /* dir config creater */ NULL, /* dir merger --- default is to override */ NULL, /* server config */ NULL, /* merge server config */ mysql_auth_cmds, /* command table */ - NULL, /* handlers */ - NULL, /* filename translation */ - mysql_authenticate_basic_user, /* check_user_id */ - mysql_check_auth, /* check auth */ - NULL, /* check access */ - NULL, /* type_checker */ - NULL, /* fixups */ - NULL, /* logger */ - NULL, /* header parser */ - NULL, /* child_init */ - child_exit, /* child_exit */ - NULL /* post read-request */ + register_hooks /* register hooks */ };