#include <stdio.h>
#include <io.h>
#include <sys/stat.h>
#include <config.h>
#include <sasl.h>
#include "saslint.h"
#define DLL_SUFFIX ".dll"
#define DLL_MASK "*" DLL_SUFFIX
#define DLL_MASK_LEN 5
const int _is_sasl_server_static = 0;
typedef struct lib_list
{
struct lib_list *next;
HMODULE library;
} lib_list_t;
static lib_list_t *lib_list_head = NULL;
int _sasl_locate_entry(void *library,
const char *entryname,
void **entry_point)
{
if(entryname == NULL) {
_sasl_log(NULL, SASL_LOG_ERR,
"no entryname in _sasl_locate_entry");
return SASL_BADPARAM;
}
if(library == NULL) {
_sasl_log(NULL, SASL_LOG_ERR,
"no library in _sasl_locate_entry");
return SASL_BADPARAM;
}
if(entry_point == NULL) {
_sasl_log(NULL, SASL_LOG_ERR,
"no entrypoint output pointer in _sasl_locate_entry");
return SASL_BADPARAM;
}
*entry_point = GetProcAddress(library, entryname);
if (*entry_point == NULL) {
#if 0
_sasl_log(NULL, SASL_LOG_DEBUG,
"unable to get entry point %s: %s", entryname,
GetLastError());
#endif
return SASL_FAIL;
}
return SASL_OK;
}
static int _sasl_plugin_load(char *plugin, void *library,
const char *entryname,
int (*add_plugin)(const char *, void *))
{
void *entry_point;
int result;
result = _sasl_locate_entry(library, entryname, &entry_point);
if(result == SASL_OK) {
result = add_plugin(plugin, entry_point);
if(result != SASL_OK)
_sasl_log(NULL, SASL_LOG_DEBUG,
"_sasl_plugin_load failed on %s for plugin: %s\n",
entryname, plugin);
}
return result;
}
int _sasl_get_plugin(const char *file,
const sasl_callback_t *verifyfile_cb,
void **libraryptr)
{
int r = 0;
HINSTANCE library;
lib_list_t *newhead;
r = ((sasl_verifyfile_t *)(verifyfile_cb->proc))
(verifyfile_cb->context, file, SASL_VRFY_PLUGIN);
if (r != SASL_OK) return r;
newhead = sasl_ALLOC(sizeof(lib_list_t));
if(!newhead) return SASL_NOMEM;
if (!(library = LoadLibrary (file))) {
_sasl_log(NULL, SASL_LOG_ERR,
"unable to LoadLibrary %s: %s", file, GetLastError());
sasl_FREE(newhead);
return SASL_FAIL;
}
newhead->library = library;
newhead->next = lib_list_head;
lib_list_head = newhead;
*libraryptr = library;
return SASL_OK;
}
int _sasl_load_plugins(const add_plugin_list_t *entrypoints,
const sasl_callback_t *getpath_cb,
const sasl_callback_t *verifyfile_cb)
{
int result;
char cur_dir[PATH_MAX], full_name[PATH_MAX+2], prefix[PATH_MAX+2];
char * pattern;
char c;
int pos;
const char *path=NULL;
int position;
const add_plugin_list_t *cur_ep;
struct stat statbuf;
intptr_t fhandle;
struct _finddata_t finddata;
size_t prefix_len;
if (! entrypoints
|| ! getpath_cb
|| getpath_cb->id != SASL_CB_GETPATH
|| ! getpath_cb->proc
|| ! verifyfile_cb
|| verifyfile_cb->id != SASL_CB_VERIFYFILE
|| ! verifyfile_cb->proc)
return SASL_BADPARAM;
result = ((sasl_getpath_t *)(getpath_cb->proc))(getpath_cb->context,
&path);
if (result != SASL_OK) return result;
if (! path) return SASL_FAIL;
if (strlen(path) >= PATH_MAX) {
return SASL_FAIL;
}
position=0;
do {
pos=0;
do {
c=path[position];
position++;
cur_dir[pos]=c;
pos++;
} while ((c!=PATHS_DELIMITER) && (c!=0));
cur_dir[pos-1]='\0';
if (stat (cur_dir, &statbuf) < 0) {
continue;
}
if ((statbuf.st_mode & S_IFDIR) == 0) {
continue;
}
strcpy (prefix, cur_dir);
prefix_len = strlen (prefix);
if (prefix[prefix_len-1] != '\\') {
strcat (prefix,"\\");
prefix_len++;
}
pattern = prefix;
if ((prefix_len + DLL_MASK_LEN) > (sizeof(prefix) - 1)) {
_sasl_log(NULL, SASL_LOG_WARN, "plugin search mask is too big");
continue;
}
strcat (prefix + prefix_len, "*" DLL_SUFFIX);
fhandle = _findfirst (pattern, &finddata);
if (fhandle == -1) {
continue;
}
prefix[prefix_len] = '\0';
do {
size_t length;
void *library;
char *c;
char plugname[PATH_MAX];
length = strlen(finddata.name);
if (length < 5) {
continue;
}
if (length + prefix_len >= PATH_MAX) continue;
if (stricmp(finddata.name + (length - strlen(DLL_SUFFIX)), DLL_SUFFIX) != 0) {
continue;
}
if ((finddata.attrib & _A_SUBDIR) == _A_SUBDIR) {
continue;
}
strcpy (full_name, prefix);
strcat (full_name, finddata.name);
strcpy (plugname, finddata.name);
c = strrchr(plugname, '.');
if (c != NULL) *c = '\0';
result = _sasl_get_plugin (full_name, verifyfile_cb, &library);
if (result != SASL_OK) {
continue;
}
for (cur_ep = entrypoints; cur_ep->entryname; cur_ep++) {
_sasl_plugin_load(plugname, library, cur_ep->entryname,
cur_ep->add_plugin);
}
} while (_findnext (fhandle, &finddata) == 0);
_findclose (fhandle);
} while ((c!='=') && (c!=0));
return SASL_OK;
}
int
_sasl_done_with_plugins(void)
{
lib_list_t *libptr, *libptr_next;
for(libptr = lib_list_head; libptr; libptr = libptr_next) {
libptr_next = libptr->next;
if (libptr->library != NULL) {
FreeLibrary(libptr->library);
}
sasl_FREE(libptr);
}
lib_list_head = NULL;
return SASL_OK;
}