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; }
int _sasl_locate_entry(void *library, const char *entryname, void **entry_point) { #ifdef DO_DLOPEN /* note that we still check for known problem systems in * case we are cross-compiling */ #if defined(DLSYM_NEEDS_UNDERSCORE) || (defined(__OpenBSD__) && !defined(__ELF__)) char adj_entryname[1024]; #else #define adj_entryname entryname #endif if(!entryname) { _sasl_log(NULL, SASL_LOG_ERR, "no entryname in _sasl_locate_entry"); return SASL_BADPARAM; } if(!library) { _sasl_log(NULL, SASL_LOG_ERR, "no library in _sasl_locate_entry"); return SASL_BADPARAM; } if(!entry_point) { _sasl_log(NULL, SASL_LOG_ERR, "no entrypoint output pointer in _sasl_locate_entry"); return SASL_BADPARAM; } #if defined(DLSYM_NEEDS_UNDERSCORE) || (defined(__OpenBSD__) && !defined(__ELF__)) snprintf(adj_entryname, sizeof adj_entryname, "_%s", entryname); #endif *entry_point = NULL; *entry_point = dlsym(library, adj_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", adj_entryname, dlerror()); #endif return SASL_FAIL; } return SASL_OK; #else return SASL_FAIL; #endif /* DO_DLOPEN */ }
/* add an auxiliary property plugin */ int sasl_auxprop_add_plugin(const char *plugname, sasl_auxprop_init_t *auxpropfunc) { int result, out_version; auxprop_plug_list_t *new_item; sasl_auxprop_plug_t *plug; result = auxpropfunc(sasl_global_utils, SASL_AUXPROP_PLUG_VERSION, &out_version, &plug, plugname); if(result != SASL_OK) { _sasl_log(NULL, SASL_LOG_ERR, "auxpropfunc error %s\n", sasl_errstring(result, NULL, NULL)); return result; } /* We require that this function is implemented */ if(!plug->auxprop_lookup) return SASL_BADPROT; new_item = sasl_ALLOC(sizeof(auxprop_plug_list_t)); if(!new_item) return SASL_NOMEM; /* These will load from least-important to most important */ new_item->plug = plug; new_item->next = auxprop_head; auxprop_head = new_item; return SASL_OK; }
/* 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; }
/* add an auxiliary property plugin */ int sasl_auxprop_add_plugin(const char *plugname, sasl_auxprop_init_t *auxpropfunc) { int result = sasl_auxprop_add_plugin_nolog(plugname, auxpropfunc); if(result != SASL_OK) { _sasl_log(NULL, SASL_LOG_ERR, "auxpropfunc error %s\n", sasl_errstring(result, NULL, NULL)); } return result; }
/* clear values and optionally requests from property context * ctx -- property context * requests -- 0 = don't clear requests, 1 = clear requests */ void prop_clear(struct propctx *ctx, int requests) { struct proppool *new_pool, *tmp; unsigned i; /* We're going to need a new proppool once we reset things */ new_pool = alloc_proppool(ctx->mem_base->size + (ctx->used_values+1) * sizeof(struct propval)); if (new_pool == NULL) { _sasl_log(NULL, SASL_LOG_ERR, "failed to allocate memory\n"); exit(1); } if(requests) { /* We're wiping the whole shebang */ ctx->used_values = 0; } else { /* Need to keep around old requets */ struct propval *new_values = (struct propval *)new_pool->data; for(i=0; i<ctx->used_values; i++) { new_values[i].name = ctx->values[i].name; } } while(ctx->mem_base) { tmp = ctx->mem_base; ctx->mem_base = tmp->next; sasl_FREE(tmp); } /* Update allocation-related metadata */ ctx->allocated_values = ctx->used_values+1; new_pool->unused = new_pool->size - (ctx->allocated_values * sizeof(struct propval)); /* Setup pointers for the values array */ ctx->values = (struct propval *)new_pool->data; ctx->prev_val = NULL; /* Setup the pools */ ctx->mem_base = ctx->mem_cur = new_pool; /* Reset list_end and data_end for the new memory pool */ ctx->list_end = (char **)((char *)ctx->mem_base->data + ctx->allocated_values * sizeof(struct propval)); ctx->data_end = (char *)ctx->mem_base->data + ctx->mem_base->size; return; }
/* loads a plugin library */ static int _tsasl_get_plugin(TCHAR *tfile, const sasl_callback_t *verifyfile_cb, void **libraryptr) { HINSTANCE library = NULL; lib_list_t *newhead; char *file; int retCode = SASL_OK; if (sizeof(TCHAR) != sizeof(char)) { file = _sasl_wchar_to_utf8(tfile); if (!file) { retCode = SASL_NOMEM; goto cleanup; } } else { file = (char*)tfile; } retCode = ((sasl_verifyfile_t *)(verifyfile_cb->proc)) (verifyfile_cb->context, file, SASL_VRFY_PLUGIN); if (retCode != SASL_OK) goto cleanup; newhead = sasl_ALLOC(sizeof(lib_list_t)); if (!newhead) { retCode = SASL_NOMEM; goto cleanup; } if (!(library = LoadLibrary(tfile))) { _sasl_log(NULL, SASL_LOG_ERR, "unable to LoadLibrary %s: %s", file, GetLastError()); sasl_FREE(newhead); retCode = SASL_FAIL; goto cleanup; } newhead->library = library; newhead->next = lib_list_head; lib_list_head = newhead; *libraryptr = library; cleanup: if (sizeof(TCHAR) != sizeof(char)) { sasl_FREE(file); } return retCode; }
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) { #ifdef DO_DLOPEN int r = 0; int flag; void *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; #ifdef RTLD_NOW flag = RTLD_NOW; #else flag = 0; #endif newhead = sasl_ALLOC(sizeof(lib_list_t)); if(!newhead) return SASL_NOMEM; if (!(library = dlopen(file, flag))) { _sasl_log(NULL, SASL_LOG_ERR, "unable to dlopen %s: %s", file, dlerror()); sasl_FREE(newhead); return SASL_FAIL; } newhead->library = library; newhead->next = lib_list_head; lib_list_head = newhead; *libraryptr = library; return SASL_OK; #else return SASL_FAIL; #endif /* DO_DLOPEN */ }
/* Do the callbacks for auxprop stores */ int sasl_auxprop_store(sasl_conn_t *conn, struct propctx *ctx, const char *user) { sasl_getopt_t *getopt; int ret, found = 0; void *context; const char *plist = NULL; auxprop_plug_list_t *ptr; sasl_server_params_t *sparams = NULL; unsigned userlen = 0; if (ctx) { if (!conn || !user) return SASL_BADPARAM; sparams = ((sasl_server_conn_t *) conn)->sparams; userlen = (unsigned) strlen(user); } /* Pickup getopt callback from the connection, if conn is not NULL */ if(_sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) { ret = getopt(context, NULL, "auxprop_plugin", &plist, NULL); if(ret != SASL_OK) plist = NULL; } ret = SASL_OK; if(!plist) { /* Do store in all plugins */ for(ptr = auxprop_head; ptr && ret == SASL_OK; ptr = ptr->next) { found=1; if (ptr->plug->auxprop_store) ret = ptr->plug->auxprop_store(ptr->plug->glob_context, sparams, ctx, user, userlen); } } else { char *pluginlist = NULL, *freeptr = NULL, *thisplugin = NULL; if(_sasl_strdup(plist, &pluginlist, NULL) != SASL_OK) return SASL_FAIL; thisplugin = freeptr = pluginlist; /* Do store in all *specified* plugins, in order */ while(*thisplugin) { char *p; int last=0; while(*thisplugin && isspace((int)*thisplugin)) thisplugin++; if(!(*thisplugin)) break; for(p = thisplugin;*p != '\0' && !isspace((int)*p); p++); if(*p == '\0') last = 1; else *p='\0'; for(ptr = auxprop_head; ptr && ret == SASL_OK; ptr = ptr->next) { /* Skip non-matching plugins */ if((!ptr->plug->name || strcasecmp(ptr->plug->name, thisplugin))) continue; found=1; if (ptr->plug->auxprop_store) ret = ptr->plug->auxprop_store(ptr->plug->glob_context, sparams, ctx, user, userlen); } if(last) break; thisplugin = p+1; } sasl_FREE(freeptr); } if(!found) { _sasl_log(NULL, SASL_LOG_ERR, "could not find auxprop plugin, was searching for %s", plist ? plist : "[all]"); return SASL_FAIL; } return ret; }
/* Do the callbacks for auxprop lookups */ void _sasl_auxprop_lookup(sasl_server_params_t *sparams, unsigned flags, const char *user, unsigned ulen) { sasl_getopt_t *getopt; int ret, found = 0; void *context; const char *plist = NULL; auxprop_plug_list_t *ptr; if(_sasl_getcallback(sparams->utils->conn, SASL_CB_GETOPT, &getopt, &context) == SASL_OK) { ret = getopt(context, NULL, "auxprop_plugin", &plist, NULL); if(ret != SASL_OK) plist = NULL; } if(!plist) { /* Do lookup in all plugins */ for(ptr = auxprop_head; ptr; ptr = ptr->next) { found=1; ptr->plug->auxprop_lookup(ptr->plug->glob_context, sparams, flags, user, ulen); } } else { char *pluginlist = NULL, *freeptr = NULL, *thisplugin = NULL; if(_sasl_strdup(plist, &pluginlist, NULL) != SASL_OK) return; thisplugin = freeptr = pluginlist; /* Do lookup in all *specified* plugins, in order */ while(*thisplugin) { char *p; int last=0; while(*thisplugin && isspace((int)*thisplugin)) thisplugin++; if(!(*thisplugin)) break; for(p = thisplugin;*p != '\0' && !isspace((int)*p); p++); if(*p == '\0') last = 1; else *p='\0'; for(ptr = auxprop_head; ptr; ptr = ptr->next) { /* Skip non-matching plugins */ if(!ptr->plug->name || strcasecmp(ptr->plug->name, thisplugin)) continue; found=1; ptr->plug->auxprop_lookup(ptr->plug->glob_context, sparams, flags, user, ulen); } if(last) break; thisplugin = p+1; } sasl_FREE(freeptr); } if(!found) _sasl_log(sparams->utils->conn, SASL_LOG_DEBUG, "could not find auxprop plugin, was searching for '%s'", plist ? plist : "[all]"); }
/* 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; const add_plugin_list_t *cur_ep; #ifdef DO_DLOPEN char str[PATH_MAX], tmp[PATH_MAX+2], prefix[PATH_MAX+2]; /* 1 for '/' 1 for trailing '\0' */ char c; int pos; const char *path=NULL; int position; DIR *dp; struct dirent *dir; #endif #ifndef PIC add_plugin_t *add_plugin; _sasl_plug_type type; _sasl_plug_rec *p; #endif 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; #ifndef PIC /* do all the static plugins first */ for(cur_ep = entrypoints; cur_ep->entryname; cur_ep++) { /* What type of plugin are we looking for? */ if(!strcmp(cur_ep->entryname, "sasl_server_plug_init")) { type = SERVER; add_plugin = (add_plugin_t *)sasl_server_add_plugin; } else if (!strcmp(cur_ep->entryname, "sasl_client_plug_init")) { type = CLIENT; add_plugin = (add_plugin_t *)sasl_client_add_plugin; } else if (!strcmp(cur_ep->entryname, "sasl_auxprop_plug_init")) { type = AUXPROP; add_plugin = (add_plugin_t *)sasl_auxprop_add_plugin; } else if (!strcmp(cur_ep->entryname, "sasl_canonuser_init")) { type = CANONUSER; add_plugin = (add_plugin_t *)sasl_canonuser_add_plugin; } else { /* What are we looking for then? */ return SASL_FAIL; } for (p=_sasl_static_plugins; p->type; p++) { if(type == p->type) result = add_plugin(p->name, p->plug); } } #endif /* !PIC */ /* only do the following if: * * we support dlopen() * AND we are not staticly compiled * OR we are staticly compiled and TRY_DLOPEN_WHEN_STATIC is defined */ #if defined(DO_DLOPEN) && (defined(PIC) || (!defined(PIC) && defined(TRY_DLOPEN_WHEN_STATIC))) /* 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++; str[pos]=c; pos++; } while ((c!=':') && (c!='=') && (c!=0)); str[pos-1]='\0'; strcpy(prefix,str); strcat(prefix,"/"); if ((dp=opendir(str)) !=NULL) /* ignore errors */ { while ((dir=readdir(dp)) != NULL) { size_t length; void *library; char *c; char plugname[PATH_MAX]; char name[PATH_MAX]; length = NAMLEN(dir); if (length < 4) continue; /* can not possibly be what we're looking for */ if (length + pos>=PATH_MAX) continue; /* too big */ if (strcmp(dir->d_name + (length - strlen(SO_SUFFIX)), SO_SUFFIX) && strcmp(dir->d_name + (length - strlen(LA_SUFFIX)), LA_SUFFIX)) continue; memcpy(name,dir->d_name,length); name[length]='\0'; result = _parse_la(prefix, name, tmp); if(result != SASL_OK) continue; /* skip "lib" and cut off suffix -- this only need be approximate */ strcpy(plugname, name + 3); c = strchr(plugname, (int)'.'); if(c) *c = '\0'; result = _sasl_get_plugin(tmp, 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); /* If this fails, it's not the end of the world */ } } closedir(dp); } else { _sasl_log(NULL, SASL_LOG_DEBUG, "looking for plugins in '%s', failed to open directory, error: %s", str, strerror(errno)); } } while ((c!='=') && (c!=0)); #endif /* defined(DO_DLOPEN) && (!defined(PIC) || (defined(PIC) && defined(TRY_DLOPEN_WHEN_STATIC))) */ return SASL_OK; }
static int _parse_la(const char *prefix, const char *in, char *out) { FILE *file; size_t length; char line[MAX_LINE]; char *ntmp = NULL; if(!in || !out || !prefix || out == in) return SASL_BADPARAM; /* Set this so we can detect failure */ *out = '\0'; length = strlen(in); if (strcmp(in + (length - strlen(LA_SUFFIX)), LA_SUFFIX)) { if(!strcmp(in + (length - strlen(SO_SUFFIX)),SO_SUFFIX)) { /* check for a .la file */ strcpy(line, prefix); strcat(line, in); length = strlen(line); *(line + (length - strlen(SO_SUFFIX))) = '\0'; strcat(line, LA_SUFFIX); file = fopen(line, "r"); if(file) { /* We'll get it on the .la open */ fclose(file); return SASL_FAIL; } } strcpy(out, prefix); strcat(out, in); return SASL_OK; } strcpy(line, prefix); strcat(line, in); file = fopen(line, "r"); if(!file) { _sasl_log(NULL, SASL_LOG_WARN, "unable to open LA file: %s", line); return SASL_FAIL; } while(!feof(file)) { if(!fgets(line, MAX_LINE, file)) break; if(line[strlen(line) - 1] != '\n') { _sasl_log(NULL, SASL_LOG_WARN, "LA file has too long of a line: %s", in); return SASL_BUFOVER; } if(line[0] == '\n' || line[0] == '#') continue; if(!strncmp(line, "dlname=", sizeof("dlname=") - 1)) { /* We found the line with the name in it */ char *end; char *start; size_t len; end = strrchr(line, '\''); if(!end) continue; start = &line[sizeof("dlname=")-1]; len = strlen(start); if(len > 3 && start[0] == '\'') { ntmp=&start[1]; *end='\0'; /* Do we have dlname="" ? */ if(ntmp == end) { _sasl_log(NULL, SASL_LOG_DEBUG, "dlname is empty in .la file: %s", in); return SASL_FAIL; } strcpy(out, prefix); strcat(out, ntmp); } break; } } if(ferror(file) || feof(file)) { _sasl_log(NULL, SASL_LOG_WARN, "Error reading .la: %s\n", in); fclose(file); return SASL_FAIL; } fclose(file); if(!(*out)) { _sasl_log(NULL, SASL_LOG_WARN, "Could not find a dlname line in .la file: %s", in); return SASL_FAIL; } return SASL_OK; }
/* 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; }
/* Do the callbacks for auxprop lookups */ int _sasl_auxprop_lookup(sasl_server_params_t *sparams, unsigned flags, const char *user, unsigned ulen) { sasl_getopt_t *getopt; int ret, found = 0; void *context; const char *plist = NULL; auxprop_plug_list_t *ptr; int result = SASL_NOMECH; if(_sasl_getcallback(sparams->utils->conn, SASL_CB_GETOPT, (sasl_callback_ft *)&getopt, &context) == SASL_OK) { ret = getopt(context, NULL, "auxprop_plugin", &plist, NULL); if(ret != SASL_OK) plist = NULL; } if(!plist) { /* Do lookup in all plugins */ /* TODO: Ideally, each auxprop plugin should be marked if its failure should be ignored or treated as a fatal error of the whole lookup. */ for(ptr = auxprop_head; ptr; ptr = ptr->next) { found=1; ret = ptr->plug->auxprop_lookup(ptr->plug->glob_context, sparams, flags, user, ulen); result = _sasl_account_status (result, ret); } } else { char *pluginlist = NULL, *freeptr = NULL, *thisplugin = NULL; if(_sasl_strdup(plist, &pluginlist, NULL) != SASL_OK) return SASL_NOMEM; thisplugin = freeptr = pluginlist; /* Do lookup in all *specified* plugins, in order */ while(*thisplugin) { char *p; int last=0; while(*thisplugin && isspace((int)*thisplugin)) thisplugin++; if(!(*thisplugin)) break; for(p = thisplugin;*p != '\0' && !isspace((int)*p); p++); if(*p == '\0') last = 1; else *p='\0'; for(ptr = auxprop_head; ptr; ptr = ptr->next) { /* Skip non-matching plugins */ if(!ptr->plug->name || strcasecmp(ptr->plug->name, thisplugin)) continue; found=1; ret = ptr->plug->auxprop_lookup(ptr->plug->glob_context, sparams, flags, user, ulen); result = _sasl_account_status (result, ret); } if(last) break; thisplugin = p+1; } sasl_FREE(freeptr); } if(!found) { _sasl_log(sparams->utils->conn, SASL_LOG_DEBUG, "could not find auxprop plugin, was searching for '%s'", plist ? plist : "[all]"); } return result; }
/* 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; TCHAR cur_dir[PATH_MAX], full_name[PATH_MAX+2], prefix[PATH_MAX+2]; /* 1 for '\\' 1 for trailing '\0' */ TCHAR * pattern; TCHAR c; int pos; int retCode = SASL_OK; char *utf8path = NULL; TCHAR *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 _tfinddata_t finddata; /* data returned by _findnext() */ size_t prefix_len; /* for static plugins */ add_plugin_t *add_plugin; _sasl_plug_type type; _sasl_plug_rec *p; 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; /* do all the static plugins first */ for (cur_ep = entrypoints; cur_ep->entryname; cur_ep++) { /* What type of plugin are we looking for? */ if (!strcmp(cur_ep->entryname, "sasl_server_plug_init")) { type = SERVER; add_plugin = (add_plugin_t *)sasl_server_add_plugin; } else if (!strcmp(cur_ep->entryname, "sasl_client_plug_init")) { type = CLIENT; add_plugin = (add_plugin_t *)sasl_client_add_plugin; } else if (!strcmp(cur_ep->entryname, "sasl_auxprop_plug_init")) { type = AUXPROP; add_plugin = (add_plugin_t *)sasl_auxprop_add_plugin; } else if (!strcmp(cur_ep->entryname, "sasl_canonuser_init")) { type = CANONUSER; add_plugin = (add_plugin_t *)sasl_canonuser_add_plugin; } else { /* What are we looking for then? */ return SASL_FAIL; } for (p = _sasl_static_plugins; p->type; p++) { if (type == p->type) result = add_plugin(p->name, p->plug); } } /* get the path to the plugins */ result = ((sasl_getpath_t *)(getpath_cb->proc))(getpath_cb->context, &utf8path); if (result != SASL_OK) return result; if (!utf8path) return SASL_FAIL; if (sizeof(TCHAR) == sizeof(char)) { path = (TCHAR*)utf8path; } else { path = _sasl_utf8_to_wchar(utf8path); if (!path) return SASL_FAIL; } if (_tcslen(path) >= PATH_MAX) { /* no you can't buffer overrun */ retCode = SASL_FAIL; goto cleanup; } 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 (_tstat (cur_dir, &statbuf) < 0) { continue; } if ((statbuf.st_mode & S_IFDIR) == 0) { continue; } _tcscpy(prefix, cur_dir); prefix_len = _tcslen (prefix); /* : Don't append trailing \ unless required */ if (prefix[prefix_len-1] != '\\') { _tcscat(prefix,_T("\\")); prefix_len++; } pattern = prefix; /* : Check that we have enough space for "*.dll" */ if ((prefix_len + DLL_MASK_LEN) > (sizeof(prefix) / sizeof(TCHAR) - 1)) { _sasl_log(NULL, SASL_LOG_WARN, "plugin search mask is too big"); continue; } _tcscat (prefix + prefix_len, _T("*") DLL_SUFFIX); fhandle = _tfindfirst (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 = _tcslen(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 (_tcscmp(finddata.name + (length - _tcslen(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 */ _tcscpy (full_name, prefix); _tcscat (full_name, finddata.name); /* cut off .dll suffix -- this only need be approximate */ if (sizeof(TCHAR) != sizeof(char)) { if (WideCharToMultiByte(CP_UTF8, 0, finddata.name, -1, plugname, sizeof(plugname), NULL, NULL) == 0) { // in case of unicode use utf8 continue; } } else { _tcscpy((TCHAR*)plugname, finddata.name); // w/o unicode local enconding is fine } c = strchr(plugname, '.'); if (c != NULL) *c = '\0'; result = _tsasl_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 (_tfindnext (fhandle, &finddata) == 0); _findclose (fhandle); } while ((c!='=') && (c!=0)); cleanup: if (sizeof(TCHAR) != sizeof(char)) { sasl_FREE(path); /* It's always allocated in coversion to wchar */ } return retCode; }