49
46
#include <unistd.h>
49
#include "k5-platform.h"
51
#if USE_DLOPEN && USE_CFBUNDLE
52
#include <CoreFoundation/CoreFoundation.h>
54
/* Currently CoreFoundation only exists on the Mac so we just use
55
* pthreads directly to avoid creating empty function calls on other
56
* platforms. If a thread initializer ever gets created in the common
57
* plugin code, move this there */
58
static pthread_mutex_t krb5int_bundle_mutex = PTHREAD_MUTEX_INITIALIZER;
52
61
#include <stdarg.h>
53
62
static void Tprintf (const char *fmt, ...)
70
#if !defined (USE_DLOPEN) && !defined (USE_CFBUNDLE)
79
#if !defined (USE_DLOPEN) && !defined (_WIN32)
86
long d_ino; /* inode (always 1 in WIN32) */
87
off_t d_off; /* offset to this dirent */
88
unsigned short d_reclen; /* length of d_name */
89
char d_name[_MAX_FNAME+1]; /* filename (null terminated) */
93
long handle; /* _findfirst/_findnext handle */
94
short offset; /* offset into directory */
95
short finished; /* 1 if there are not more files */
96
struct _finddata_t fileinfo;/* from _findfirst/_findnext */
97
char *dir; /* the dir we are reading */
98
struct dirent dent; /* the dirent to return */
101
DIR * opendir(const char *dir)
108
filespec = malloc(strlen(dir) + 2 + 1);
109
strcpy(filespec, dir);
110
index = strlen(filespec) - 1;
111
if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))
112
filespec[index] = '\0';
113
strcat(filespec, "/*");
115
dp = (DIR *)malloc(sizeof(DIR));
118
dp->dir = strdup(dir);
120
if ((handle = _findfirst(filespec, &(dp->fileinfo))) < 0) {
137
struct dirent * readdir(DIR *dp)
139
if (!dp || dp->finished) return NULL;
141
if (dp->offset != 0) {
142
if (_findnext(dp->handle, &(dp->fileinfo)) < 0) {
149
strncpy(dp->dent.d_name, dp->fileinfo.name, _MAX_FNAME);
151
dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name);
152
dp->dent.d_off = dp->offset;
157
int closedir(DIR *dp)
160
_findclose(dp->handle);
161
if (dp->dir) free(dp->dir);
75
168
long KRB5_CALLCONV
76
169
krb5int_open_plugin (const char *filepath, struct plugin_file_handle **h, struct errinfo *ep)
91
184
htmp = calloc (1, sizeof (*htmp)); /* calloc initializes ptrs to NULL */
92
if (htmp == NULL) { err = errno; }
185
if (htmp == NULL) { err = ENOMEM; }
96
if (!err && (statbuf.st_mode & S_IFMT) == S_IFREG) {
189
if (!err && ((statbuf.st_mode & S_IFMT) == S_IFREG
191
|| (statbuf.st_mode & S_IFMT) == S_IFDIR
192
#endif /* USE_CFBUNDLE */
97
194
void *handle = NULL;
197
char executablepath[MAXPATHLEN];
199
if ((statbuf.st_mode & S_IFMT) == S_IFDIR) {
201
CFStringRef pluginString = NULL;
202
CFURLRef pluginURL = NULL;
203
CFBundleRef pluginBundle = NULL;
204
CFURLRef executableURL = NULL;
206
/* Lock around CoreFoundation calls since objects are refcounted
207
* and the refcounts are not thread-safe. Using pthreads directly
208
* because this code is Mac-specific */
209
lock_err = pthread_mutex_lock(&krb5int_bundle_mutex);
210
if (lock_err) { err = lock_err; }
213
pluginString = CFStringCreateWithCString (kCFAllocatorDefault,
215
kCFStringEncodingASCII);
216
if (pluginString == NULL) { err = ENOMEM; }
220
pluginURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault,
222
kCFURLPOSIXPathStyle,
224
if (pluginURL == NULL) { err = ENOMEM; }
228
pluginBundle = CFBundleCreate (kCFAllocatorDefault, pluginURL);
229
if (pluginBundle == NULL) { err = ENOENT; } /* XXX need better error */
233
executableURL = CFBundleCopyExecutableURL (pluginBundle);
234
if (executableURL == NULL) { err = ENOMEM; }
238
if (!CFURLGetFileSystemRepresentation (executableURL,
240
(UInt8 *)executablepath,
241
sizeof (executablepath))) {
247
/* override the path the caller passed in */
248
filepath = executablepath;
251
if (executableURL != NULL) { CFRelease (executableURL); }
252
if (pluginBundle != NULL) { CFRelease (pluginBundle); }
253
if (pluginURL != NULL) { CFRelease (pluginURL); }
254
if (pluginString != NULL) { CFRelease (pluginString); }
256
/* unlock after CFRelease calls since they modify refcounts */
257
if (!lock_err) { pthread_mutex_unlock (&krb5int_bundle_mutex); }
259
#endif /* USE_CFBUNDLE */
99
262
#define PLUGIN_DLOPEN_FLAGS (RTLD_NOW | RTLD_LOCAL | RTLD_GROUP)
101
264
#define PLUGIN_DLOPEN_FLAGS (RTLD_NOW | RTLD_LOCAL)
105
267
handle = dlopen(filepath, PLUGIN_DLOPEN_FLAGS);
106
268
if (handle == NULL) {
120
282
if (handle != NULL) { dlclose (handle); }
125
if (!err && (statbuf.st_mode & S_IFMT) == S_IFDIR) {
126
CFStringRef pluginPath = NULL;
127
CFURLRef pluginURL = NULL;
128
CFBundleRef pluginBundle = NULL;
131
pluginPath = CFStringCreateWithCString (kCFAllocatorDefault, filepath,
132
kCFStringEncodingASCII);
133
if (pluginPath == NULL) { err = ENOMEM; }
137
pluginURL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, pluginPath,
138
kCFURLPOSIXPathStyle, true);
139
if (pluginURL == NULL) { err = ENOMEM; }
143
pluginBundle = CFBundleCreate (kCFAllocatorDefault, pluginURL);
144
if (pluginBundle == NULL) { err = ENOENT; } /* XXX need better error */
148
if (!CFBundleIsExecutableLoaded (pluginBundle)) {
149
int loaded = CFBundleLoadExecutable (pluginBundle);
150
if (!loaded) { err = ENOENT; } /* XXX need better error */
284
#endif /* USE_DLOPEN */
287
if (!err && (statbuf.st_mode & S_IFMT) == S_IFREG) {
288
HMODULE handle = NULL;
290
handle = LoadLibrary(filepath);
291
if (handle == NULL) {
292
Tprintf ("Unable to load dll: %s\n", filepath);
293
err = ENOENT; /* XXX */
294
krb5int_set_error (ep, err, "%s", "unable to load dll");
156
htmp->bundle = pluginBundle;
157
pluginBundle = NULL; /* htmp->bundle takes ownership */
299
htmp->hinstPlugin = handle;
160
if (pluginBundle != NULL) { CFRelease (pluginBundle); }
161
if (pluginURL != NULL) { CFRelease (pluginURL); }
162
if (pluginPath != NULL) { CFRelease (pluginPath); }
166
308
if (!err && !got_plugin) {
167
309
err = ENOENT; /* no plugin or no way to load plugins */
203
if (!err && !sym && (h->bundle != NULL)) {
204
CFStringRef cfsymname = NULL;
207
cfsymname = CFStringCreateWithCString (kCFAllocatorDefault, csymname,
208
kCFStringEncodingASCII);
209
if (cfsymname == NULL) { err = ENOMEM; }
214
sym = CFBundleGetFunctionPointerForName (h->bundle, cfsymname);
216
sym = CFBundleGetDataPointerForName (h->bundle, cfsymname);
218
if (sym == NULL) { err = ENOENT; } /* XXX */
221
if (cfsymname != NULL) { CFRelease (cfsymname); }
348
if (!err && !sym && (h->hinstPlugin != NULL)) {
349
sym = GetProcAddress(h->hinstPlugin, csymname);
351
const char *e = "unable to get dll symbol"; /* XXX copy and save away */
352
Tprintf ("GetProcAddress(%s): %s\n", csymname, GetLastError());
353
err = ENOENT; /* XXX */
354
krb5int_set_error(ep, err, "%s", e);
357
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
358
FORMAT_MESSAGE_FROM_SYSTEM,
361
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
365
fprintf (stderr, "unable to get dll symbol, %s\n", (LPCTSTR)lpMsgBuf);
225
372
if (!err && (sym == NULL)) {
226
373
err = ENOENT; /* unimplemented */
260
407
if (h->dlhandle != NULL) { dlclose(h->dlhandle); }
263
/* Do not call CFBundleUnloadExecutable because it's not ref counted.
264
* CFRelease will unload the bundle if the internal refcount goes to zero. */
265
if (h->bundle != NULL) { CFRelease (h->bundle); }
410
if (h->hinstPlugin != NULL) { FreeLibrary(h->hinstPlugin); }
300
449
*harray = calloc (1, sizeof (**harray)); /* calloc initializes to NULL */
301
if (*harray == NULL) { err = errno; }
450
if (*harray == NULL) { err = ENOMEM; }
307
krb5int_plugin_file_handle_array_add (struct plugin_file_handle ***harray, int *count,
456
krb5int_plugin_file_handle_array_add (struct plugin_file_handle ***harray, size_t *count,
308
457
struct plugin_file_handle *p)
311
460
struct plugin_file_handle **newharray = NULL;
312
int newcount = *count + 1;
461
size_t newcount = *count + 1;
314
463
newharray = realloc (*harray, ((newcount + 1) * sizeof (**harray))); /* +1 for NULL */
315
464
if (newharray == NULL) {
318
467
newharray[newcount - 1] = p;
319
468
newharray[newcount] = NULL;
339
488
#if TARGET_OS_MAC
340
#define FILEEXTS { "", ".bundle", ".so", NULL }
489
#define FILEEXTS { "", ".bundle", ".dylib", ".so", NULL }
341
490
#elif defined(_WIN32)
342
491
#define FILEEXTS { "", ".dll", NULL }
365
514
static const char *const fileexts[] = FILEEXTS;
366
515
char **tempnames = NULL;
516
size_t bases_count = 0;
517
size_t exts_count = 0;
520
if (!filebases) { err = EINVAL; }
521
if (!filenames) { err = EINVAL; }
371
for (i = 0; filebases[i] != NULL; i++, count++);
372
for (i = 0; fileexts[i] != NULL; i++, count++);
373
tempnames = calloc (count, sizeof (char *));
374
if (tempnames == NULL) { err = errno; }
524
for (i = 0; filebases[i]; i++) { bases_count++; }
525
for (i = 0; fileexts[i]; i++) { exts_count++; }
526
tempnames = calloc ((bases_count * exts_count)+1, sizeof (char *));
527
if (!tempnames) { err = ENOMEM; }
379
for (i = 0; !err && (filebases[i] != NULL); i++) {
380
size_t baselen = strlen (filebases[i]);
381
for (j = 0; !err && (fileexts[j] != NULL); j++) {
382
size_t len = baselen + strlen (fileexts[j]) + 2; /* '.' + NULL */
383
tempnames[i+j] = malloc (len * sizeof (char));
384
if (tempnames[i+j] == NULL) {
387
sprintf (tempnames[i+j], "%s%s", filebases[i], fileexts[j]);
532
for (i = 0; !err && filebases[i]; i++) {
533
for (j = 0; !err && fileexts[j]; j++) {
534
if (asprintf(&tempnames[(i*exts_count)+j], "%s%s",
535
filebases[i], fileexts[j]) < 0) {
536
tempnames[(i*exts_count)+j] = NULL;
541
tempnames[bases_count * exts_count] = NULL; /* NUL-terminate */
436
586
char *filepath = NULL;
439
filepath = malloc (dirnamelen + strlen (filenames[j]) + 1); /* NULL */
440
if (filepath == NULL) {
443
sprintf (filepath, "%s/%s", dirnames[i], filenames[j]);
589
if (asprintf(&filepath, "%s/%s", dirnames[i], filenames[j]) < 0) {
474
621
int len = NAMELEN (d);
475
filepath = malloc (dirnamelen + len + 1); /* NULL */
476
if (filepath == NULL) {
479
sprintf (filepath, "%s/%*s", dirnames[i], len, d->d_name);
622
if (asprintf(&filepath, "%s/%*s", dirnames[i], len, d->d_name) < 0) {