Keep Server Online
If you find the Apache Lounge, the downloads and overall help useful, please express your satisfaction with a donation.
or
A donation makes a contribution towards the costs, the time and effort that's going in this site and building.
Thank You! Steffen
Your donations will help to keep this site alive and well, and continuing building binaries. Apache Lounge is not sponsored.
| |
|
Topic: help|compile modded mod_auth_mysql under windows |
|
Author |
|
eviatar
Joined: 31 Dec 2010 Posts: 2
|
Posted: Fri 31 Dec '10 16:31 Post subject: help|compile modded mod_auth_mysql under windows |
|
|
hi folks and gals
im new to this site and heard alot about it's great and professional community
ive got a little problem:
im running on my server the folowing:
windows server 2003 R2
Apache 2.2.11 httpd
mysql 5.1.33 as DB
ive managed to put my hands on mod_auth_mysql compiled for win32 and it's working great.
the problem (in short) is:
mod_auth_mysql does not allow to include "salt" encryption addon for MD5 method. it's only allowes that approach in Crypt() method.
im running a vbulletin forum which uses md5+salt encryption for authentication proccess.
ive made some changes to mod_auth_mysql.c to correspond vbulletin's passwords policy - btw: feel free to use the source for you'r own needs
ive been struggling about it a whole week till now, and couldn't compile my mod under win32 enviroment.
perhaps someone here could please assist/compile that mod (attached) for win32 uses? (server & db versions mentioned above)
tnx in advance for all helpers!
here's my code:
Code: | /* ====================================================================
* Copyright (c) 1995 The Apache Group. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* 4. The names "Apache Server" and "Apache Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 5. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
* IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Group and was originally based
* on public domain software written at the National Center for
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
* For more information on the Apache Group and the Apache HTTP server
* project, please see <http://www.apache.org/>.
*
*/
/*
* http_auth_msql: authentication
*
* Rob McCool & Brian Behlendorf.
*
* Adapted to Shambhala by rst.
*
* converted to use MySQL by Vivek Khera <khera@kciLink.com>
*
* Previously maintained by Sam Brauer <sbrauer@users.sourceforge.net> (Thanks, Sam!)
* Now maintained by Jerry Stuckle <jstuckle@users.sourceforge.net)
*
* 2002-08-09: ported to Apache-2.x
* 2002-09-06: merged Apache1 and Apache2 code together with #ifdef's
* 2002-09-08: merged in some contributed patches:
* - added AuthMySQLUserCondition and AuthMySQLGroupCondition,
* based on a patch from Lukas Gradl <l.gradl@business-solutions.at>
* - added AuthMySQLScrambledPasswords based on patch from
* Chris Hamilton <chris@turlyming.com>
* 2002-09-12: released on sourceforge.net
* 2002-09-16: released on sourceforge.net (after change to README)
* 2003-03-16:
* - added Artur Kedzierski's mysql 4 change to
* use mysql_real_connect().
* - added Martin Willner's patch for MD5 support (enable by defining
* MD5_ENABLED).
* - moved usage notes to README file and updated a bit.
* 2003-03-19: added Iain Patterson's patch to call mysql_init() before mysql_real_connect().
* 2003-05-10: removed the old MD5 stuff that depended on openssl and replaced with a call to apache's ap_md5() function.
* 2004-08-27:
* - added Ariel Arjona's code to resolve compile problems due to missing/incorrect headers
* - added code based on Jorge Jimenez's patch to support non-standard sockets and ports
* - released updated copy as version 2.0.0 (new version numbering system to match other projects)
* 2004-09-08: (Version 2.5.0)
* merged in code based on contribuited patches:
* - added AuthMySQLPort and AuthMySQLSocket options based on patches by Douglas Maske and Jorge Jimenez
* - added missing #include statements based on patch by Ariel Arjona
* 2004-09-21: (Version 2.6.0)
* - fixed error when compiling for Apache 1.x.
* - rewrote some of the code to get rid of many of the #ifdef statements
* - added code based on Andrew Gwozdziewycz's patch to enable AuthMySQLSaltField
* - added code based on Hatamoto's patch to enable AuthMySQLEnable
* - added new parameter AuthMySQLPwEncryption to set encryption type
* - depricated the following parameters:
*
* AuthMySQLCryptedPasswords
* AuthMySQLScrambledPasswords
* AuthMySQLMD5Passwords
*
* - added compile time default values for the following configuration paramters:
*
* Configuration Parameter Option
* ----------------------- ------
* AuthMySQLHost HOST
* AuthMySQLPort PORT
* AuthMySQLSocket SOCKET
* AuthMySQLUser USER
* AuthMySQLPassword PASSWORD
* AuthMySQLDB DB
* AuthMySQLPwTable PWTABLE
* AuthMySQlNameField NAMEFIELD
* AuthMySQLPasswordField PASSWORDFIELD
* AuthMySQLPwEncryption ENCRYPTION
* AuthMySQLSaltField SALT
* AuthMySQLKeepAlive KEEPALIVE
* AuthMySQLAuthoritative AUTHORITATIVE
* AuthMySQLNoPassword NOPASSWORD
* AuthMySQLEnable ENABLE
*
* - Removed requirement to define APACHE1 on command line for Apache 1.x
* (now the default).
* 2004-10-04: (Version 2.6.1)
* - Changed code to return immediately when module is disabled (minor bug fix)
*/
/*
* Module definition information - the part between the -START and -END
* lines below is used by Configure. This could be stored in a separate
* instead.
*
* MODULE-DEFINITION-START
* Name: mysql_auth_module
* ConfigStart
MYSQL_LIB="-L/usr/local/lib/mysql -lmysqlclient -lm -lz"
if [ "X$MYSQL_LIB" != "X" ]; then
LIBS="$LIBS $MYSQL_LIB"
echo " + using $MYSQL_LIB for MySQL support"
fi
* ConfigEnd
* MODULE-DEFINITION-END
*/
#define STRING(x) STR(x) /* Used to build strings from compile options */
#define STR(x) #x
/* set any defaults not specified at compile time */
#ifdef HOST /* Host to use */
#define _HOST STRING(HOST)
#else
#define _HOST 0 /* Will default to localhost */
#endif
#ifdef PORT /* The port to use */
#define _PORT PORT
#else
#define _PORT MYSQL_PORT /* Use the one from MySQL */
#endif
#ifdef SOCKET /* UNIX socket */
#define _SOCKET STRING(SOCKET)
#else
#define _SOCKET MYSQL_UNIX_ADDR
#endif
#ifdef USER /* Authorized user */
#define _USER STRING(USER)
#else
#define _USER 0 /* User must be specified in config */
#endif
#ifdef PASSWORD /* Default password */
#define _PASSWORD STRING(PASSWORD)
#else
#define _PASSWORD 0 /* Password must be specified in config */
#endif
#ifdef DB /* Default database */
#define _DB STRING(DB)
#else
#define _DB "test" /* Test database */
#endif
#ifdef PWTABLE /* Password table */
#define _PWTABLE STRING(PWTABLE)
#else
#define _PWTABLE "user_info" /* Default is user_info */
#endif
#ifdef NAMEFIELD /* Name column in password table */
#define _NAMEFIELD STRING(NAMEFIELD)
#else
#define _NAMEFIELD "user_name" /* Default is "user_name" */
#endif
#ifdef PASSWORDFIELD /* Password column in password table */
#define _PASSWORDFIELD STRING(PASSWORDFIELD)
#else
#define _PASSWORDFIELD "user_password" /* Default is user_password */
#endif
#ifdef ENCRYPTION /* Encryption type */
#define _ENCRYPTION STRING(ENCRYPTION)
#else
#define _ENCRYPTION 0 /* Will default to "crypt" in code */
#endif
#ifdef SALTFIELD /* If a salt column is not defined */
#define _SALTFIELD STRING(SALTFIELD)
#else
#define _SALTFIELD "<none>" /* Default is no salt */
#endif
#ifdef KEEPALIVE /* Keep the connection alive */
#define _KEEPALIVE KEEPALIVE
#else
#define _KEEPALIVE 0 /* Do not keep it alive */
#endif
#ifdef AUTHORITATIVE /* If we are the last word */
#define _AUTHORITATIVE AUTHORITATIVE
#else
#define _AUTHORITATIVE 1 /* Yes, we are */
#endif
#ifdef NOPASSWORD /* If password not needed */
#define _NOPASSWORD NOPASSWORD
#else
#define _NOPASSWORD 0 /* It is required */
#endif
#ifdef ENABLE /* If we are to be enabled */
#define _ENABLE ENABLE
#else
#define _ENABLE 1 /* Assume we are */
#endif
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
#ifdef APACHE2
#define PCALLOC apr_pcalloc
#define SNPRINTF apr_snprintf
#define PSTRDUP apr_pstrdup
#include "http_request.h" /* for ap_hook_(check_user_id | auth_checker)*/
#include "ap_compat.h"
#include "apr_strings.h"
#include "crypt.h"
#define LOG_ERROR1(lvl, stat, rqst, msg, parm) \
ap_log_rerror (APLOG_MARK, lvl, stat, rqst, msg, parm)
#define LOG_ERROR2(lvl, stat, rqst, msg, parm1, parm2) \
ap_log_rerror (APLOG_MARK, lvl, stat, rqst, msg, parm1, parm2)
#define LOG_ERROR3(lvl, stat, rqst, msg, parm1, parm2, parm3) \
ap_log_rerror (APLOG_MARK, lvl, stat, rqst, msg, parm1, parm2, parm3)
#define APACHE_FUNC static apr_status_t
#define APACHE_FUNC_RETURN(rc) return rc
#define NOT_AUTHORIZED HTTP_UNAUTHORIZED
#else
#define PCALLOC ap_pcalloc
#define SNPRINTF ap_snprintf
#define PSTRDUP ap_pstrdup
#include <stdlib.h>
#define LOG_ERROR1(lvl, stat, rqst, msg, parm) \
ap_log_error(APLOG_MARK, lvl, rqst->server, msg, parm)
#define LOG_ERROR2(lvl, stat, rqst, msg, parm1, parm2) \
ap_log_error(APLOG_MARK, lvl, rqst->server, msg, parm1, parm2)
#define LOG_ERROR3(lvl, stat, rqst, msg, parm1, parm2, parm3) \
ap_log_error(APLOG_MARK, lvl, rqst->server, msg, parm1, parm2, parm3)
#define APACHE_FUNC static void
#define APACHE_FUNC_RETURN(rc) return
#define NOT_AUTHORIZED AUTH_REQUIRED
#endif
#include "util_md5.h"
#include <mysql.h>
/* Password encryption defines */
#define PW_ENCRYPT_UNDEFINED -1
#define PW_ENCRYPT_NONE 0
#define PW_ENCRYPT_CRYPT 1
#define PW_ENCRYPT_SCRAMBLED 2
#define PW_ENCRYPT_MD5 3
/*
* structure to hold the configuration details for the request
*/
typedef struct {
char *mysqlhost; /* host name of db server */
#ifdef APACHE2
int mysqlport; /* port number of db server */
#else
char * mysqlport; /* port number of db server */
#endif
char *mysqlsocket; /* socket path of db server */
char *mysqluser; /* user ID to connect to db server */
char *mysqlpasswd; /* password to connect to db server */
char *mysqlDB; /* DB name */
char *mysqlpwtable; /* user password table */
char *mysqlgrptable; /* user group table */
char *mysqlNameField; /* field in password/grp table with username */
char *mysqlPasswordField; /* field in password table with password */
char *mysqlGroupField; /* field in group table with group name */
char *mysqlEncryptionField; /* encryption type for passwords */
int mysqlCrypted; /* are passwords encrypted? */
int mysqlScrambled; /* are passwords scrambled? */
int mysqlMD5; /* are passwords MD5? */
char *mysqlSaltField; /* salt for scrambled password */
int mysqlKeepAlive; /* keep connection persistent? */
int mysqlAuthoritative; /* are we authoritative? */
int mysqlNoPasswd; /* do we ignore password? */
int mysqlEnable; /* do we bother trying to auth at all? */
char *mysqlUserCondition; /* Condition to add to the user where-clause in select query */
char *mysqlGroupCondition; /* Condition to add to the group where-clause in select query */
} mysql_auth_config_rec;
/*
* Global handle to db. If not null, assume it is still valid.
* MySQL in recent incarnations will re-connect automatically if the
* connection is closed, so we don't worry about that here.
*/
static MYSQL *mysql_handle = NULL;
/*
* Callback to close mysql handle when necessary. Also called when a
* child httpd process is terminated.
*/
APACHE_FUNC
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 */
APACHE_FUNC_RETURN(0);
}
/*
* empty function necessary because register_cleanup requires it as one
* of its parameters
*/
APACHE_FUNC
mod_auth_mysql_cleanup_child (void *notused)
{
/* nothing */
APACHE_FUNC_RETURN(0);
}
#ifndef APACHE2
/*
* handler to do cleanup on child exit
*/
static void
child_exit(server_rec *s, pool *p)
{
mod_auth_mysql_cleanup(NULL);
}
#endif
/*
* 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.
*/
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
static int
open_db_handle(request_rec *r, mysql_auth_config_rec *m)
{
static MYSQL mysql_conn;
char *db_host;
if (mysql_handle) return TRUE; /* already open */
mysql_handle = mysql_init(&mysql_conn);
if (! mysql_handle) {
LOG_ERROR1(APLOG_ERR, 0, r, "MySQL ERROR: %s", mysql_error(&mysql_conn));
}
if (!m->mysqlhost || strcmp(m->mysqlhost,"localhost") == 0) {
db_host = NULL;
} else {
db_host = m->mysqlhost;
}
#ifdef APACHE2
mysql_handle=mysql_real_connect(&mysql_conn,db_host,m->mysqluser,m->mysqlpasswd, NULL, m->mysqlport, m->mysqlsocket, 0);
#else
mysql_handle=mysql_real_connect(&mysql_conn,db_host,m->mysqluser,m->mysqlpasswd, NULL, atoi(m->mysqlport), m->mysqlsocket, 0);
#endif
if (mysql_handle) {
if (!m->mysqlKeepAlive) {
/* close when request done */
#ifdef APACHE2
apr_pool_cleanup_register
#else
ap_register_cleanup
#endif
(r->pool, (void *)NULL,
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 */
LOG_ERROR1(APLOG_ERR, 0, r, "MySQL ERROR: %s", mysql_error(&mysql_conn));
return FALSE;
}
return TRUE;
}
static void *
#ifdef APACHE2
create_mysql_auth_dir_config (apr_pool_t *p, char *d)
#else
create_mysql_auth_dir_config (pool *p, char *d)
#endif
{
mysql_auth_config_rec *m = PCALLOC(p, sizeof(mysql_auth_config_rec));
if (!m) return NULL; /* failure to get memory is a bad thing */
/* default values */
m->mysqlhost = _HOST;
#ifdef APACHE2
m->mysqlport = _PORT;
#else
m->mysqlport = STRING(_PORT);
#endif
m->mysqlsocket = _SOCKET;
m->mysqluser = _USER;
m->mysqlpasswd = _PASSWORD;
m->mysqlDB = _DB;
m->mysqlpwtable = _PWTABLE;
m->mysqlgrptable = 0; /* user group table */
m->mysqlNameField = _NAMEFIELD; /* default user name field */
m->mysqlPasswordField = _PASSWORDFIELD; /* default user password field */
m->mysqlEncryptionField = _ENCRYPTION; /* default encryption is encrypted */
m->mysqlCrypted = 1; /* passwords are encrypted */
m->mysqlMD5 = 0; /* passwords are not MD5 encrypted */
m->mysqlScrambled = 0; /* passwords are not scrambled */
m->mysqlSaltField = _SALTFIELD; /* default is scramble password against itself */
m->mysqlKeepAlive = _KEEPALIVE; /* do not keep persistent connection */
m->mysqlAuthoritative = _AUTHORITATIVE; /* we are authoritative source for users */
m->mysqlNoPasswd = _NOPASSWORD; /* we require password */
m->mysqlEnable = _ENABLE; /* authorization on by default */
m->mysqlUserCondition = 0; /* No condition to add to the user
where-clause in select query */
m->mysqlGroupCondition = 0; /* No condition to add to the group
where-clause in select query */
return (void *)m;
}
#ifdef APACHE2
static
command_rec mysql_auth_cmds[] = {
AP_INIT_TAKE1("AuthMySQLHost", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlhost),
OR_AUTHCFG, "mysql server host name"),
AP_INIT_TAKE1("AuthMySQLPort", ap_set_int_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlport),
OR_AUTHCFG, "mysql server port number"),
AP_INIT_TAKE1("AuthMySQLSocket", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlsocket),
OR_AUTHCFG, "mysql server socket path"),
AP_INIT_TAKE1("AuthMySQLUser", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqluser),
OR_AUTHCFG, "mysql server user name"),
AP_INIT_TAKE1("AuthMySQLPassword", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlpasswd),
OR_AUTHCFG, "mysql server user password"),
AP_INIT_TAKE1("AuthMySQLDB", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlDB),
OR_AUTHCFG, "mysql database name"),
AP_INIT_TAKE1("AuthMySQLUserTable", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlpwtable),
OR_AUTHCFG, "mysql user table name"),
AP_INIT_TAKE1("AuthMySQLGroupTable", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlgrptable),
OR_AUTHCFG, "mysql group table name"),
AP_INIT_TAKE1("AuthMySQLNameField", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlNameField),
OR_AUTHCFG, "mysql User ID field name within table"),
AP_INIT_TAKE1("AuthMySQLGroupField", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlGroupField),
OR_AUTHCFG, "mysql Group field name within table"),
AP_INIT_TAKE1("AuthMySQLPasswordField", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlPasswordField),
OR_AUTHCFG, "mysql Password field name within table"),
AP_INIT_TAKE1("AuthMySQLPwEncryption", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlEncryptionField),
OR_AUTHCFG, "mysql password encryption method"),
AP_INIT_FLAG("AuthMySQLCryptedPasswords", ap_set_flag_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlCrypted),
OR_AUTHCFG, "mysql passwords are stored encrypted if On"),
AP_INIT_FLAG("AuthMySQLScrambledPasswords", ap_set_flag_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlScrambled),
OR_AUTHCFG, "mysql passwords are stored scrambled if On"),
AP_INIT_FLAG("AuthMySQLMD5Passwords", ap_set_flag_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlMD5),
OR_AUTHCFG, "mysql passwords are stored as MD5 if On"),
AP_INIT_TAKE1("AuthMySQLSaltField", ap_set_string_slot,
(void*) APR_XtOffsetOf(mysql_auth_config_rec, mysqlSaltField),
OR_AUTHCFG, "mysql salfe field name within table"),
AP_INIT_FLAG("AuthMySQLKeepAlive", ap_set_flag_slot,
(void *) APR_XtOffsetOf(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_XtOffsetOf(mysql_auth_config_rec, mysqlAuthoritative),
OR_AUTHCFG, "mysql lookup is authoritative if On"),
AP_INIT_FLAG("AuthMySQLNoPasswd", ap_set_flag_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlNoPasswd),
OR_AUTHCFG, "If On, only check if user exists; ignore password"),
AP_INIT_FLAG("AuthMySQLEnable", ap_set_flag_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlEnable),
OR_AUTHCFG, "enable mysql authorization"),
AP_INIT_TAKE1("AuthMySQLUserCondition", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlUserCondition),
OR_AUTHCFG, "condition to add to user where-clause"),
AP_INIT_TAKE1("AuthMySQLGroupCondition", ap_set_string_slot,
(void *) APR_XtOffsetOf(mysql_auth_config_rec, mysqlGroupCondition),
OR_AUTHCFG, "condition to add to group where-clause"),
{ NULL }
};
#else
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" },
{ "AuthMySQLSocket", ap_set_string_slot,
(void*)XtOffsetOf(mysql_auth_config_rec, mysqlsocket),
OR_AUTHCFG, TAKE1, "mysql server socket path" },
{ "AuthMySQLPort", ap_set_string_slot,
(void*)XtOffsetOf(mysql_auth_config_rec, mysqlport),
OR_AUTHCFG, TAKE1, "mysql server port number" },
{ "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" },
{ "AuthMySQLPwEncryption", ap_set_string_slot,
(void *)XtOffsetOf(mysql_auth_config_rec, mysqlEncryptionField),
OR_AUTHCFG, TAKE1, "mysql password encryption method" },
{ "AuthMySQLCryptedPasswords", ap_set_flag_slot,
(void*)XtOffsetOf(mysql_auth_config_rec, mysqlCrypted),
OR_AUTHCFG, FLAG, "mysql passwords are stored encrypted if On" },
{ "AuthMySQLScrambledPasswords", ap_set_flag_slot,
(void*)XtOffsetOf(mysql_auth_config_rec, mysqlScrambled),
OR_AUTHCFG, FLAG, "mysql passwords are stored scrambled if On" },
{ "AuthMySQLMD5Passwords", ap_set_flag_slot,
(void*)XtOffsetOf(mysql_auth_config_rec, mysqlMD5),
OR_AUTHCFG, FLAG, "mysql passwords are stored as MD5 if On" },
{ "AuthMySQLSaltField", ap_set_string_slot,
(void *)XtOffsetOf(mysql_auth_config_rec, mysqlSaltField),
OR_AUTHCFG, TAKE1, "mysql salt field name within table" },
{ "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" },
{ "AuthMySQLEnable", ap_set_flag_slot,
(void *)XtOffsetOf(mysql_auth_config_rec, mysqlEnable),
OR_AUTHCFG, FLAG, "enable mysql authorization"},
{ "AuthMySQLUserCondition", ap_set_string_slot,
(void*)XtOffsetOf(mysql_auth_config_rec, mysqlUserCondition),
OR_AUTHCFG, TAKE1, "condition to add to user where-clause" },
{ "AuthMySQLGroupCondition", ap_set_string_slot,
(void*)XtOffsetOf(mysql_auth_config_rec, mysqlGroupCondition),
OR_AUTHCFG, TAKE1, "condition to add to group where-clause" },
{ NULL }
};
#endif
module mysql_auth_module;
/*
* Fetch and return password string from database for named user.
* If we are in NoPasswd mode, returns user name instead.
* If user or password not found, returns NULL
*/
static char *
get_mysql_pw(request_rec *r, char *user, mysql_auth_config_rec *m, const char ** psalt)
{
MYSQL_RES *result;
char *pw = NULL; /* password retrieved */
char *sql_safe_user = NULL;
int ulen;
char query[MAX_STRING_LEN];
if(!open_db_handle(r,m)) {
return NULL; /* failure reason already logged */
}
if (mysql_select_db(mysql_handle,m->mysqlDB) != 0) {
LOG_ERROR1(APLOG_ERR, 0, r, "MySQL ERROR: %s", mysql_error(mysql_handle));
return NULL;
}
/*
* If we are not checking for passwords, there may not be a password field
* in the database. We just look up the name field value in this case
* since it is guaranteed to exist.
*/
if (m->mysqlNoPasswd) {
m->mysqlPasswordField = m->mysqlNameField;
}
ulen = strlen(user);
sql_safe_user = PCALLOC(r->pool, ulen*2+1);
mysql_escape_string(sql_safe_user,user,ulen);
if (psalt) { /* If a salt was requested */
if (m->mysqlUserCondition) {
SNPRINTF(query,sizeof(query)-1,"SELECT %s, %s FROM %s WHERE %s='%s' AND %s",
m->mysqlPasswordField, m->mysqlSaltField, m->mysqlpwtable,
m->mysqlNameField, sql_safe_user, m->mysqlUserCondition);
} else {
SNPRINTF(query,sizeof(query)-1,"SELECT %s, %s FROM %s WHERE %s='%s'",
m->mysqlPasswordField, m->mysqlSaltField, m->mysqlpwtable,
m->mysqlNameField, sql_safe_user);
}
} else {
if (m->mysqlUserCondition) {
SNPRINTF(query,sizeof(query)-1,"SELECT %s FROM %s WHERE %s='%s' AND %s",
m->mysqlPasswordField, m->mysqlpwtable,
m->mysqlNameField, sql_safe_user, m->mysqlUserCondition);
} else {
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) {
LOG_ERROR2(APLOG_ERR, 0, r, "MySQL ERROR: %s: %s", mysql_error(mysql_handle), r->uri);
return NULL;
}
result = mysql_store_result(mysql_handle);
/*if (result && (mysql_num_rows(result) == 1)) {*/
if (result && (mysql_num_rows(result) >= 1)) {
MYSQL_ROW data = mysql_fetch_row(result);
if (data[0]) {
pw = (char *) PSTRDUP(r->pool, data[0]);
} else { /* no password in mysql table returns NULL */
/* this should never happen, but test for it anyhow */
LOG_ERROR2(APLOG_NOERRNO|APLOG_ERR, 0, r, "MySQL user %s has no valid password: %s", user, r->uri);
mysql_free_result(result);
return NULL;
}
if (psalt) {
if (data[1]) {
*psalt = (char *) PSTRDUP(r->pool, data[1]);
} else { /* no alt in mysql table returns NULL */
/* this should never happen, but test for it anyhow */
LOG_ERROR2(APLOG_NOERRNO|APLOG_ERR, 0, r, "MySQL user %s has no valid salt: %s", user, r->uri);
mysql_free_result(result);
return NULL;
}
}
}
if (result) mysql_free_result(result);
return pw;
}
/*
* get list of groups from database. Returns array of pointers to strings
* the last of which is NULL. returns NULL pointer if user is not member
* of any groups.
*/
static char **
get_mysql_groups(request_rec *r, char *user, mysql_auth_config_rec *m)
{
MYSQL_RES *result;
char **list = NULL;
char query[MAX_STRING_LEN];
char *sql_safe_user;
int ulen;
if(!open_db_handle(r,m)) {
return NULL; /* failure reason already logged */
}
if (mysql_select_db(mysql_handle,m->mysqlDB) != 0) {
LOG_ERROR2(APLOG_ERR, 0, r, "MySQL error %s: %s", mysql_error(mysql_handle),r->uri);
return NULL;
}
ulen = strlen(user);
sql_safe_user = PCALLOC(r->pool, ulen*2+1);
mysql_escape_string(sql_safe_user,user,ulen);
if (m->mysqlGroupCondition) {
SNPRINTF(query,sizeof(query)-1,"SELECT %s FROM %s WHERE %s='%s' AND %s",
m->mysqlGroupField, m->mysqlgrptable,
m->mysqlNameField, sql_safe_user, m->mysqlGroupCondition);
} else {
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) {
LOG_ERROR2(APLOG_ERR, 0, r, "MySQL error %s: %s", mysql_error(mysql_handle),r->uri);
return NULL;
}
result = mysql_store_result(mysql_handle);
if (result && (mysql_num_rows(result) > 0)) {
int i = mysql_num_rows(result);
list = (char **) 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] = (char *) PSTRDUP(r->pool, data[0]);
else
list[i] = ""; /* if no data, make it empty, not NULL */
}
}
if (result) mysql_free_result(result);
return list;
}
/*
* callback from Apache to do the authentication of the user to his
* password.
*/
static int
mysql_authenticate_basic_user (request_rec *r)
{
int passwords_match = 0; /* Assume no match */
char *user;
mysql_auth_config_rec *sec =
(mysql_auth_config_rec *)ap_get_module_config (r->per_dir_config,
&mysql_auth_module);
// LOG_ERROR1(APLOG_NOERRNO, 0, r, "MySQL authentication for user %s", user);
const char *sent_pw, *real_pw, *salt = 0;
int encryption_type = PW_ENCRYPT_UNDEFINED;
int res;
char *scrambled_sent_pw;
if (!sec->mysqlEnable) /* no mysql authorization */
return DECLINED;
if ((res = ap_get_basic_auth_pw (r, &sent_pw)) != OK)
return res;
/* Determine the encryption method */
if (sec->mysqlEncryptionField) {
if (strcasecmp(sec->mysqlEncryptionField, "none") == 0)
encryption_type = PW_ENCRYPT_NONE;
else if (strcasecmp(sec->mysqlEncryptionField, "crypt") == 0)
encryption_type = PW_ENCRYPT_CRYPT;
else if (strcasecmp(sec->mysqlEncryptionField, "scrambled") == 0)
encryption_type = PW_ENCRYPT_SCRAMBLED;
else if (strcasecmp(sec->mysqlEncryptionField, "md5") == 0)
encryption_type = PW_ENCRYPT_MD5;
else {
LOG_ERROR1(APLOG_NOERRNO|APLOG_ERR, 0, r, "mysql invalid encryption method %s", sec->mysqlEncryptionField);
ap_note_basic_auth_failure(r);
return NOT_AUTHORIZED;
}
}
if (encryption_type == PW_ENCRYPT_UNDEFINED) {
if (sec->mysqlCrypted == 1) /* are passwords encrypted? */
encryption_type = PW_ENCRYPT_CRYPT;
else if (sec->mysqlScrambled == 1) /* are passwords scrambled? */
encryption_type = PW_ENCRYPT_SCRAMBLED;
else if (sec->mysqlMD5 == 1) /* are passwords MD5? */
encryption_type = PW_ENCRYPT_MD5;
else
encryption_type = PW_ENCRYPT_NONE;
}
#ifdef APACHE2
user = r->user;
#else
user = r->connection->user;
#endif
if ((encryption_type == PW_ENCRYPT_CRYPT || encryption_type == PW_ENCRYPT_MD5) && /* Salt is only for crypt'd passwords */
sec->mysqlSaltField /* Salt field is not blank */
&& (strcasecmp ("<none>", sec->mysqlSaltField) != 0)) { /* Salt field != "<none>" */
real_pw = get_mysql_pw(r, user, sec, &salt);
} else {
real_pw = get_mysql_pw(r, user, sec, NULL); /* Don't ask for a salt */
salt = real_pw;
}
if(!real_pw)
{
/* user not found in database */
LOG_ERROR2(APLOG_NOERRNO|APLOG_ERR, 0, r, "MySQL user %s not found: %s", user, r->uri);
ap_note_basic_auth_failure (r);
if (!sec->mysqlAuthoritative)
return DECLINED; /* let other schemes find user */
else
return NOT_AUTHORIZED;
}
/* if we don't require password, just return ok since they exist */
if (sec->mysqlNoPasswd) {
return OK;
}
switch (encryption_type) {
case PW_ENCRYPT_SCRAMBLED:
/* if scrambled, compare the scrambled password */
scrambled_sent_pw = PCALLOC(r->pool, 33);
make_scrambled_password(scrambled_sent_pw, sent_pw);
if(strcmp(real_pw, scrambled_sent_pw) == 0) {
passwords_match = 1;
}
break;
case PW_ENCRYPT_MD5:
if(strcmp(real_pw,ap_md5(r->pool, strcat(ap_md5(r->pool,(const unsigned char *) sent_pw),salt))) == 0) {
else if(strcmp(real_pw,ap_md5(r->pool, (const unsigned char *) sent_pw)) == 0) {
passwords_match = 1;
}
}
break;
case PW_ENCRYPT_CRYPT:
/* salt will contain either the salt or real_pw */
if (strcmp(real_pw, crypt(sent_pw, salt)) == 0) {
passwords_match = 1;
}
break;
case PW_ENCRYPT_NONE:
if (strcmp(real_pw, sent_pw) == 0)
passwords_match = 1;
break;
default: /* Should never get here, but just in case... */
/* this should never happen, but test for it anyhow */
LOG_ERROR2(APLOG_NOERRNO|APLOG_ERR, 0, r,
"auth_mysql: Internal error: invalid authentication method %d: %s", encryption_type, r->uri);
ap_note_basic_auth_failure (r);
return NOT_AUTHORIZED;
}
if(passwords_match) {
return OK;
} else {
LOG_ERROR2(APLOG_NOERRNO|APLOG_ERR, 0, r,
"user %s: password mismatch: %s", user, r->uri);
ap_note_basic_auth_failure (r);
return NOT_AUTHORIZED;
}
}
/*
* check if user is member of at least one of the necessary group(s)
*/
static int
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);
#ifdef APACHE2
char *user = r->user;
#else
char *user = r->connection->user;
#endif
int method = r->method_number;
#ifdef APACHE2
const apr_array_header_t *reqs_arr = ap_requires(r);
#else
const array_header *reqs_arr = ap_requires(r);
#endif
require_line *reqs = reqs_arr ? (require_line *)reqs_arr->elts : NULL;
register int x;
char **groups = NULL;
if (!sec->mysqlGroupField) return DECLINED; /* not doing groups here */
if (!reqs_arr) return DECLINED; /* no "require" line in access config */
/* if the group table is not specified, use the same as for password */
if (!sec->mysqlgrptable) sec->mysqlgrptable = sec->mysqlpwtable;
for(x = 0; x < reqs_arr->nelts; x++) {
const char *t, *want;
if (!(reqs[x].method_mask & (1 << method))) continue;
t = reqs[x].requirement;
want = ap_getword(r->pool, &t, ' ');
if(!strcmp(want,"group")) {
/* check for list of groups from database only first time thru */
if (!groups && !(groups = get_mysql_groups(r, user, sec))) {
LOG_ERROR3(APLOG_NOERRNO|APLOG_ERR, 0, r,
"mysql user %s not in group table %s: %s",
user, sec->mysqlgrptable, r->uri);
ap_note_basic_auth_failure(r);
return NOT_AUTHORIZED;
}
/* loop through list of groups specified in htaccess file */
while(t[0]) {
int i = 0;
want = ap_getword(r->pool, &t, ' ');
/* compare against each group to which this user belongs */
while(groups[i]) { /* last element is NULL */
if(!strcmp(groups[i],want))
return OK; /* we found the user! */
++i;
}
}
LOG_ERROR2(APLOG_NOERRNO|APLOG_ERR, 0, r,
"mysql user %s not in right group: %s",user,r->uri);
ap_note_basic_auth_failure(r);
return NOT_AUTHORIZED;
}
}
return DECLINED;
}
#ifdef APACHE2
static void register_hooks(apr_pool_t *p)
{
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);
}
#endif
#ifdef APACHE2
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 apr_table_t */
register_hooks /* register hooks */
};
#else
module mysql_auth_module = {
STANDARD_MODULE_STUFF,
NULL, /* initializer */
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 */
};
#endif |
best regards.
edit: i need this mod urgently. im willing to pay up to 5$ to the developer who can compile that mod for me asap. please contact me at: evy@bezeqint.net |
|
Back to top |
|
Sob
Joined: 19 Apr 2008 Posts: 30
|
Posted: Sat 01 Jan '11 5:03 Post subject: |
|
|
Your code doesn't compile. It's just misplaced bracket, but when fixed, it still doesn't work, because you're not setting 'passwords_match'. And even with that fixed, I think it's wrong, because strcat() appends second parameter to first, but ap_md5() allocates buffer only for the hash itself. Anyone correct me if I'm wrong.
I asked uncle Google and there are at least two different modules with same name:
http://sourceforge.net/projects/modauthmysql/
http://www.heuer.org/mod_auth_mysql/
Yours is older version from first link. So I took the newest one (it should have some bugs fixed and code looks better) and added special password type 'vbulletin'. Result is here:
http://web.hisoftware.cz/sob/download/mod_auth_mysql-3.0.0-mod1.zip
It contains modified source and info how to compile it. Also included is compiled x86 module (httpd 2.2.17, MySQL 5.1.4). It should probably work with other versions too. It had no problem with my old MySQL 4.1, so your 5.1.33 must work too. And also different httpd version is usually no problem, if not too different.
As usual, no guarantees, just "works for me". |
|
Back to top |
|
eviatar
Joined: 31 Dec 2010 Posts: 2
|
Posted: Sat 01 Jan '11 16:05 Post subject: |
|
|
Sob wrote: | Your code doesn't compile. It's just misplaced bracket, but when fixed, it still doesn't work, because you're not setting 'passwords_match'. And even with that fixed, I think it's wrong, because strcat() appends second parameter to first, but ap_md5() allocates buffer only for the hash itself. Anyone correct me if I'm wrong.
I asked uncle Google and there are at least two different modules with same name:
http://sourceforge.net/projects/modauthmysql/
http://www.heuer.org/mod_auth_mysql/
Yours is older version from first link. So I took the newest one (it should have some bugs fixed and code looks better) and added special password type 'vbulletin'. Result is here:
http://web.hisoftware.cz/sob/download/mod_auth_mysql-3.0.0-mod1.zip
It contains modified source and info how to compile it. Also included is compiled x86 module (httpd 2.2.17, MySQL 5.1.4). It should probably work with other versions too. It had no problem with my old MySQL 4.1, so your 5.1.33 must work too. And also different httpd version is usually no problem, if not too different.
As usual, no guarantees, just "works for me". |
Sob: you are the MAN!
thanks a bounch m8!
well, ive tested it and it does working like a charm.
just have one little problem tho: you have commented out the "AuthMySQLKeepAlive" function.. that func is critical for large-scale websites and prevents the module from utilizing the "MaxRequests" modifier under httpd.conf..
the above flag is "off" by default, which means that every request remains active until the session is dropped. and thats a major issue.
if you could please refactor and rebuild the mod again - i'll appreciate it a ton.
tnx in advance! |
|
Back to top |
|
Sob
Joined: 19 Apr 2008 Posts: 30
|
Posted: Sat 01 Jan '11 19:28 Post subject: |
|
|
I didn't remove AuthMySQLKeepAlive option. Module author did, see changelog:
Quote: | Removed the AuthMySQLKeepAlive parameter, which doesn't work and causes problems. |
I tried to unblock it again and it does work. Well, at least with my very limited testing (just few requests). MySQL log shows no more reconnections for every request, only queries using same connection. But still I can't say that I know exactly what I'm doing here. So be warned..
http://web.hisoftware.cz/sob/download/mod_auth_mysql-3.0.0-mod2.zip |
|
Back to top |
|
ecourt
Joined: 23 Nov 2012 Posts: 3 Location: KY USA
|
Posted: Sun 25 Nov '12 2:16 Post subject: thanks |
|
|
hey, I grabbed your copy of mod_auth_mysql.
compiles fine, (one strange error, but just a warning)
mod_auth_mysql.c: In function 'str_format':
mod_auth_mysql.c:924: warning: format '%d' expects type 'int', but argument 7 has type 'long int'
still compiles, and works, problem is, when I set AuthMySQLPwEncryption vbulletin
and when I try to authenticate, I get this in the apache logs..
[client 10.10.10.56] mysql invalid encryption method VBULLETIN
Any help is appreciated. I know this is an old post,
Apache 2.215
CentOS 6.3 64 bit |
|
Back to top |
|
Sob
Joined: 19 Apr 2008 Posts: 30
|
Posted: Sun 02 Dec '12 23:47 Post subject: |
|
|
Most likely cause is that _VBULLETIN is not defined. Just add:
Code: | #define _VBULLETIN 1 |
on the first line of mod_auth_mysql.c and recompile. |
|
Back to top |
|
|
|
|
|
|