#include "mysql.h"
#include "strlcpy.h"
#include <stdarg.h>
#include <time.h>
#ifdef HAVE_LIBMYSQLCLIENT
extern int enable_mysql;
// database information
char *DATABASE = NULL; // database name
char *HOSTNAME = NULL; // database hostname
char *USERNAME = NULL; // username for database
char *PASSWORD = NULL; // password for database
char *TABLE = NULL; // table name that holds the usernames
//
// passwd struct isn't really reentrant safe, we'll need to emulate the same expected behavior
// the user won't be expected to free it.
#define M_USER 32
#define M_PASS 14
#define M_GECOS 128
#define M_DIR 128
#define M_SHELL 64
struct passwd stPass;
struct spwd stShadow;
char pw_name[M_USER+1];
char pw_passwd[M_PASS+1];
char pw_gecos[M_GECOS+1];
char pw_dir[M_DIR+1];
char pw_shell[M_SHELL+1];
char sp_namp[M_USER+1];
char sp_pwdp[M_PASS+1];
int MSimpleStatement( MYSQL *m, const char *query, ... )
{
va_list ap;
char *pszQuery;
int iRes;
va_start( ap, query );
vasprintf( &pszQuery, query, ap );
va_end( ap );
if ( !pszQuery )
{
syslog( LOG_ERR, "MSimpleStatement Failed to allocate mem" );
return( -1 );
}
iRes = mysql_real_query( m, pszQuery, strlen( pszQuery ) );
if ( iRes != 0 )
{
syslog( LOG_ERR, "MSimpleStatement [%s] Failed!", pszQuery );
}
free( pszQuery );
return( iRes );
}
MYSQL_RES *UserLookup( const char *username )
{
char *pszQuery;
MYSQL *m;
MYSQL_RES *result;
int iRes;
m = mysql_init( 0 );
if ( !m )
{
syslog( LOG_ERR, "MySql failed to initialize." );
return( NULL );
}
if ( !mysql_real_connect( m, HOSTNAME, USERNAME, PASSWORD, DATABASE, 0, NULL, 0) )
{
syslog( LOG_ERR, "Could not connect to database." );
mysql_close( m );
return( NULL );
}
{ /* prevent SQL injections */
int i, max = strlen(username);
for (i=0;i<max;i++) {
if (username[i]=='\'') {
username[i] = '_';
}
}
// send the query
asprintf( &pszQuery, "SELECT username, uid, gid, password, homedir, shell, comment FROM %s where username = '%s'", TABLE, username );
iRes = mysql_real_query( m, pszQuery, strlen( pszQuery ) );
free( pszQuery );
if ( iRes != 0 )
{
syslog( LOG_ERR, "Mysql Query Failed [%s]", mysql_error( m ) );
mysql_close( m );
return( NULL );
}
result = mysql_store_result( m );
if ( !result )
{
syslog( LOG_ERR, "No Such User [%s]", username );
mysql_close( m );
return( NULL );
}
// mark them as showing up
if ( MSimpleStatement( m, "LOCK TABLES %s WRITE", TABLE ) == 0 )
MSimpleStatement( m, "UPDATE %s SET last = %u WHERE username = '%s'", TABLE, time( NULL ), username );
MSimpleStatement( m, "UNLOCK TABLES" );
return( result );
}
struct passwd *getMpwnam( const char *username )
{
struct passwd *pw;
MYSQL_RES *r;
MYSQL_ROW row;
// check to see if the user exists on the system first
pw = getpwnam( username );
if ( pw )
return( pw );
if (!enable_mysql) {
return NULL; /* the party is over here */
}
// now check our db
r = UserLookup( username );
if ( !r )
return( NULL );
row = mysql_fetch_row( r );
if ( !row )
{
syslog( LOG_ERR, "Mysql returned empty row" );
return( NULL );
}
// username
strlcpy(pw_name,row[0],sizeof(pw_name));
stPass.pw_name = (char *)&pw_name;
// uid, gid
stPass.pw_uid = atoi( row[1] );
stPass.pw_gid = atoi( row[2] );
// password
strlcpy(pw_passwd,row[3],sizeof(pw_passwd));
stPass.pw_passwd = (char *)&pw_passwd;
// home directory
strlcpy(pw_dir,row[4],sizeof(pw_dir));
stPass.pw_dir = (char *)&pw_dir;
// shell
strlcpy(pw_shell,row[5],sizeof(pw_shell));
stPass.pw_shell = (char *)&pw_shell;
// comment
strlcpy(pw_gecos,row[6],sizeof(pw_gecos));
stPass.pw_gecos = (char *)&pw_gecos;
mysql_free_result( r );
return( &stPass );
}
struct spwd *getMspnam( const char *username )
{
struct spwd *pw;
MYSQL_RES *r;
MYSQL_ROW row;
// check to see if the user exists on the system first
pw = getspnam( username );
if ( pw )
return( pw );
if (!enable_mysql) {
return NULL; /* the party is over here */
}
// now check our db
r = UserLookup( username );
if ( !r )
return( NULL );
row = mysql_fetch_row( r );
// username
strlcpy(sp_namp,row[0],sizeof(sp_namp));
stShadow.sp_namp = (char *)&sp_namp;
// password
strlcpy(sp_pwdp,row[3],sizeof(sp_pwdp));
stShadow.sp_pwdp = (char *)&sp_pwdp;
mysql_free_result( r );
return( &stShadow );
}
#endif /* HAVE_LIBMYSQLCLIENTCLIENT */
// just to keep compiler complaining about empty files
const int iFileUsed = 1;
syntax highlighted by Code2HTML, v. 0.9.1