/* 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 <msql.h>
/* This file contains code to autheticate against msql servers */
#define ENCRYPTED_NONE 0
#define ENCRYPTED_CRYPT 1
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)
{
int sqlhandle = -1;
m_result *result = NULL;
m_row row = NULL;
PASSWDSTRUCT *newhandle;
int section;
char *sqlserver;
char *sqlencryption;
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, "msql_host", NULL);
sqldatabase = mktokconfstr(tset, section, "msql_database", NULL);
sqltable = mktokconfstr(tset, section, "msql_table", "users");
sqlport = mktokconfint(tset, section, "msql_port", "%d", NULL, 0);
sqlencryption = mktokconfstr(tset, section, "msql_encryption", "crypt");
sqlquery = mktokconfstr(tset, section, "msql_query", NULL);
if (!sqldatabase)
{
log_addentry(MYLOG_INFO, NULL, "libauthmsql REQUIRES msql_database to connect to sql server");
goto error;
}
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, "libauthmsql REQUIRES msql_encryption to be set to either plaintext or 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 */
if ((sqlhandle = msqlConnect(sqlserver)) == -1)
{
log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("libauthmsql could not connect to SQL server: %s", msqlErrMsg));
goto error;
}
if (msqlSelectDB(sqlhandle, sqldatabase) == -1)
{
log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("libauthmsql could not connect to SQL database '%s': %s", sqldatabase, msqlErrMsg));
goto error;
}
/* perform sql query */
if (msqlQuery(sqlhandle, query) == -1)
{
log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("libauthmsql could not perform query on SQL server: %s", msqlErrMsg));
goto error;
}
/* get result data */
result = msqlStoreResult();
if (msqlNumFields(result) != 5)
{
log_addentry(MYLOG_INFO, NULL,
"libauthmsql, msql_query setting incorrectly set");
goto error;
}
/* if we got no rows, then the user does not exist */
if (msqlNumRows(result) == 0)
{
freewrapper(newhandle);
newhandle = NULL;
*err = AUTH_USERNKNOW;
goto cleanup;
}
if (msqlNumRows(result) > 1)
{
log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("libauthmsql got more than 1 result for query on user '%s'", username));
goto error;
}
/* decode row */
row = msqlFetchRow(result);
if (!row[0] || !row[1] || !row[2] || !row[3] || !row[4])
{
log_giveentry(MYLOG_INFO, NULL,
safe_snprintf("libauthmsql 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("libauthmsql 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("libauthmsql 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) msqlFreeResult(result);
if (sqlhandle != -1) msqlClose(sqlhandle);
if (sqlserver) freewrapper(sqlserver);
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;
switch(h->encrypted)
{
case ENCRYPTED_NONE:
return(strcmp(password, h->password) == 0);
case ENCRYPTED_CRYPT:
return(chkpassword(h->password, password));
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