mirror of
https://github.com/deltachat/deltachat-core.git
synced 2025-10-05 10:39:27 +02:00
330 lines
8.5 KiB
C
330 lines
8.5 KiB
C
/* windlopen.c--Windows dynamic loader interface
|
|
* Ryan Troll
|
|
* $Id: windlopen.c,v 1.17 2009/01/25 20:20:57 mel Exp $
|
|
*/
|
|
/*
|
|
* Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
*
|
|
* 3. The name "Carnegie Mellon University" must not be used to
|
|
* endorse or promote products derived from this software without
|
|
* prior written permission. For permission or any other legal
|
|
* details, please contact
|
|
* Office of Technology Transfer
|
|
* Carnegie Mellon University
|
|
* 5000 Forbes Avenue
|
|
* Pittsburgh, PA 15213-3890
|
|
* (412) 268-4387, fax: (412) 268-7395
|
|
* tech-transfer@andrew.cmu.edu
|
|
*
|
|
* 4. Redistributions of any form whatsoever must retain the following
|
|
* acknowledgment:
|
|
* "This product includes software developed by Computing Services
|
|
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
|
|
*
|
|
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
|
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
|
|
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
|
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#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;
|
|
|
|
/* : inefficient representation, but works */
|
|
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 /* This message appears to confuse people */
|
|
_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;
|
|
}
|
|
|
|
/* loads a plugin library */
|
|
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;
|
|
}
|
|
|
|
/* undoes actions done by _sasl_get_plugin */
|
|
void _sasl_remove_last_plugin()
|
|
{
|
|
lib_list_t *last_plugin = lib_list_head;
|
|
lib_list_head = lib_list_head->next;
|
|
if (last_plugin->library) {
|
|
FreeLibrary(last_plugin->library);
|
|
}
|
|
sasl_FREE(last_plugin);
|
|
}
|
|
|
|
/* gets the list of mechanisms */
|
|
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];
|
|
/* 1 for '\\' 1 for trailing '\0' */
|
|
char * pattern;
|
|
char c;
|
|
int pos;
|
|
const char *path=NULL;
|
|
int position;
|
|
const add_plugin_list_t *cur_ep;
|
|
struct stat statbuf; /* filesystem entry information */
|
|
intptr_t fhandle; /* file handle for _findnext function */
|
|
struct _finddata_t finddata; /* data returned by _findnext() */
|
|
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;
|
|
|
|
/* get the path to the plugins */
|
|
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) { /* no you can't buffer overrun */
|
|
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';
|
|
|
|
|
|
/* : check to make sure that a valid directory name was passed in */
|
|
if (stat (cur_dir, &statbuf) < 0) {
|
|
continue;
|
|
}
|
|
if ((statbuf.st_mode & S_IFDIR) == 0) {
|
|
continue;
|
|
}
|
|
|
|
strcpy (prefix, cur_dir);
|
|
prefix_len = strlen (prefix);
|
|
|
|
/* : Don't append trailing \ unless required */
|
|
if (prefix[prefix_len-1] != '\\') {
|
|
strcat (prefix,"\\");
|
|
prefix_len++;
|
|
}
|
|
|
|
pattern = prefix;
|
|
|
|
/* : Check that we have enough space for "*.dll" */
|
|
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) { /* no matching files */
|
|
continue;
|
|
}
|
|
|
|
/* : Truncate "*.dll" */
|
|
prefix[prefix_len] = '\0';
|
|
|
|
do {
|
|
size_t length;
|
|
void *library;
|
|
char *c;
|
|
char plugname[PATH_MAX];
|
|
int entries;
|
|
|
|
length = strlen(finddata.name);
|
|
if (length < 5) { /* At least <Ch>.dll */
|
|
continue; /* can not possibly be what we're looking for */
|
|
}
|
|
|
|
/* : Check for overflow */
|
|
if (length + prefix_len >= PATH_MAX) continue; /* too big */
|
|
|
|
if (stricmp(finddata.name + (length - strlen(DLL_SUFFIX)), DLL_SUFFIX) != 0) {
|
|
continue;
|
|
}
|
|
|
|
/* : Check that it is not a directory */
|
|
if ((finddata.attrib & _A_SUBDIR) == _A_SUBDIR) {
|
|
continue;
|
|
}
|
|
|
|
/* : Construct full name from prefix and name */
|
|
|
|
strcpy (full_name, prefix);
|
|
strcat (full_name, finddata.name);
|
|
|
|
/* cut off .dll suffix -- this only need be approximate */
|
|
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;
|
|
}
|
|
|
|
entries = 0;
|
|
for (cur_ep = entrypoints; cur_ep->entryname; cur_ep++) {
|
|
result = _sasl_plugin_load(plugname,
|
|
library,
|
|
cur_ep->entryname,
|
|
cur_ep->add_plugin);
|
|
if (result == SASL_OK) {
|
|
++entries;
|
|
}
|
|
/* If this fails, it's not the end of the world */
|
|
}
|
|
if (entries == 0) {
|
|
_sasl_remove_last_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;
|
|
}
|