/* 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 #include #include #include /* 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); }