/* Copyright (C) 1999 Beau Kuiper
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "config.h"
#include "auth.h"
#include <string.h>
#include <sys/time.h>
#include <pwd.h>
#include <mysql.h>
/* This file contains code to autheticate against mysql servers */
#define ENCRYPTED_NONE 0
#define ENCRYPTED_MYSQL 1
#define ENCRYPTED_CRYPT 2
typedef struct
{
char *password;
char *homedir;
char *rootdir;
int uid;
int gid;
int encrypted;
} PASSWDSTRUCT;
void *gethandle(void *peer, void *tset, char *username, int *err)
{
MYSQL *sql = NULL;
MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL;
PASSWDSTRUCT *newhandle;
int section;
char *sqlserver;
char *sqlencryption;
char *sqlusername;
char *sqlpassword;
char *sqldatabase;
int sqlport;
char *sqltable;
char *sqlquery, *query = NULL;
section = auth_getcursectionid(peer);
newhandle = (PASSWDSTRUCT *)mallocwrapper(sizeof(PASSWDSTRUCT));
/* read info from config file */
sqlserver = mktokconfstr(tset, section, "mysql_host", "localhost");
sqlusername = mktokconfstr(tset, section, "mysql_user", NULL);
sqlpassword = mktokconfstr(tset, section, "mysql_password", NULL);
sqldatabase = mktokconfstr(tset, section, "mysql_database", NULL);
sqltable = mktokconfstr(tset, section, "mysql_table", "users");
sqlport = mktokconfint(tset, section, "mysql_port", "%d", NULL, 0);
sqlencryption = mktokconfstr(tset, section, "mysql_encryption", "mysql");
sqlquery = mktokconfstr(tset, section, "mysql_query", NULL);
if (!sqlusername)
{
log_addentry(MYLOG_INFO, NULL, "libauthmysql REQUIRES mysql_user to connect to sql server");
goto error;
}
if (!sqlpassword)
{
log_addentry(MYLOG_INFO, NULL, "libauthmysql REQUIRES mysql_password to connect to sql server");
goto error;
}
if (!sqldatabase)
{
log_addentry(MYLOG_INFO, NULL, "libauthmysql REQUIRES mysql_database to connect to sql server");
goto error;
}
if (strcasecmp(sqlencryption, "mysql") == 0)
newhandle->encrypted = ENCRYPTED_MYSQL;
else if (strcasecmp(sqlencryption, "plaintext") == 0)
newhandle->encrypted = ENCRYPTED_NONE;
else if (strcasecmp(sqlencryption, "crypt") == 0)
newhandle->encrypted = ENCRYPTED_CRYPT;
else
{
log_addentry(MYLOG_INFO, NULL, "libauthmysql REQUIRES mysql_encryption to be set to either plaintext, mysql, crypt");
goto error;
}
if (!sqlquery)
query = safe_snprintf("SELECT password,homedir,rootdir,uid,gid FROM %s WHERE username='%s'", sqltable, username);
else
query = strdupwrapper(sqlquery);
/* connect to sql server */
sql = mysql_init(NULL);
if (!mysql_real_connect(sql, sqlserver, sqlusername, sqlpassword,
sqldatabase, sqlport, NULL, 0))
{
log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("libauthmysql could not connect to SQL server: %s", mysql_error(sql)));
goto error;
}
/* perform sql query */
if (mysql_query(sql, query) != 0)
{
log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("libauthmysql could not perform query on SQL server: %s", mysql_error(sql)));
goto error;
}
if (mysql_field_count(sql) != 5)
{
log_addentry(MYLOG_INFO, NULL,
"libauthmysql, mysql_query setting incorrectly set");
goto error;
}
/* get result data */
if ((result = mysql_store_result(sql)) == NULL)
{
log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("libauthmysql could not get results from SQL query: %s", mysql_error(sql)));
goto error;
}
/* if we got no rows, then the user does not exist */
if (mysql_num_rows(result) == 0)
{
freewrapper(newhandle);
newhandle = NULL;
*err = AUTH_USERNKNOW;
goto cleanup;
}
if (mysql_num_rows(result) > 1)
{
log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("libauthmysql got more than 1 result for query on user '%s'", username));
goto error;
}
/* decode row */
row = mysql_fetch_row(result);
if (!row[0] || !row[1] || !row[2] || !row[3] || !row[4])
{
log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("libauthmysql found NULL values in SQL result for user '%s'", username));
goto error;
}
if (sscanf(row[3], "%d", &(newhandle->uid)) != 1)
{
log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("libauthmysql could not decode uid of user '%s'", username));
goto error;
}
if (sscanf(row[4], "%d", &(newhandle->gid)) != 1)
{
log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("libauthmysql could not decode gid of user '%s'", username));
goto error;
}
newhandle->password = strdupwrapper(row[0]);
newhandle->homedir = strdupwrapper(row[1]);
newhandle->rootdir = strdupwrapper(row[2]);
/* we are FINALLY DONE!, clean up and go home! */
*err = AUTH_OK;
goto cleanup;
error:
*err = AUTH_ERROR;
freewrapper(newhandle);
newhandle = NULL;
cleanup:
if (query) freewrapper(query);
if (result) mysql_free_result(result);
if (sql) mysql_close(sql);
freewrapper(sqlserver);
if (sqlusername) freewrapper(sqlusername);
if (sqlpassword) freewrapper(sqlpassword);
if (sqldatabase) freewrapper(sqldatabase);
freewrapper(sqltable);
freewrapper(sqlencryption);
if (sqlquery) freewrapper(sqlquery);
return(newhandle);
}
void freehandle(void *handle)
{
PASSWDSTRUCT *h = (PASSWDSTRUCT *)handle;
size_t sl = strlen(h->password);
/* destroy record of password */
memset(h->password, 0, sl);
freewrapper(h->password);
freewrapper(h->homedir);
freewrapper(h->rootdir);
freewrapper(h);
}
int chkpasswd(void *handle, char *password, char **errmsg)
{
PASSWDSTRUCT *h = (PASSWDSTRUCT *)handle;
char pass2[1024];
switch(h->encrypted)
{
case ENCRYPTED_NONE:
return(strcmp(password, h->password) == 0);
case ENCRYPTED_CRYPT:
return(chkpassword(h->password, password));
case ENCRYPTED_MYSQL:
make_scrambled_password(pass2, password);
return(strcmp(h->password, pass2) == 0);
default:
return(FALSE);
}
return(FALSE);
}
char *gethomedir(void *h)
{
return(((PASSWDSTRUCT *)h)->homedir);
}
char *getrootdir(void *h)
{
return(((PASSWDSTRUCT *)h)->rootdir);
}
uid_t getuseruid(void *h)
{
return(((PASSWDSTRUCT *)h)->uid);
}
gid_t getusergid(void *h)
{
return(((PASSWDSTRUCT *)h)->gid);
}
syntax highlighted by Code2HTML, v. 0.9.1