/* eurephia_authplugin.c * * Copyright (C) 2013 David Sommerseth * * 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 3 of the License, 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, see . * */ /** * @file eurephia_authplugin.c * @author David Sommerseth * @date 2013-02-15 * * @brief Authentication plug-in framework for eurephia */ #include #include #include #include #include #define EUREPHIA_AUTHPLUGIN_C_ #define EUREPHIA_CONTEXT_H_ typedef struct __eurephiaCTX eurephiaCTX; #include #include #include #include #include #include #include #include eAuthPlugin * __eAuthPlugin_Setup(eurephiaCTX * ctx, const char * dlfilename, void * dlhandle); struct __PluginDataSplit { const char *dsofile; const char *configstr; }; /** * Splits the plug-in data from the database into a more easily managable * struct. This struct will only use pointers to the input string (dbstr) * And the input string will be slightly modified. * * The format of the input data is: * [] * * @param ret* The parsed result will be saved into in the provided struct * @param dbstr* The string returned by the database, containing plug-in data * * @return Data is returned via the ret* pointer */ void __split_plugin_data_str(struct __PluginDataSplit *ret, char *dbstr) { char *ptr = NULL; assert(ret != NULL); assert(dbstr != NULL); ret->dsofile = NULL; ret->configstr = NULL; /* The input string must start with '[' */ if (dbstr[0] != '[') { return; } /* Locate the ']' part. This will be replaced by a NULL terminator */ ptr = strpbrk(dbstr, "]"); if (ptr == NULL) { /* If not found, abort */ return; } dbstr[0] = 0; /* NULL terminate it on purpose */ ret->dsofile = dbstr+1; *ptr = 0; /* NULL terminate the ']' place */ ret->configstr = ptr+1; } eAuthPluginCTX * eAuthPlugin_Init(eurephiaCTX * ctx) { eurephiaVALUES *plgs = NULL, *plgptr; eAuthPluginCTX *apctx = NULL, *apctxhead = NULL; struct __PluginDataSplit plgdata; // Query the database for authentication plugins plgs = eDBget_plugins(ctx, "auth"); if (plgs == NULL) { return NULL; } // Parse the result, load plugins and save them into // separate auth plug-in contexts for (plgptr = plgs; plgptr != NULL; plgptr = plgptr->next) { // Ensure that we have value plug-in information if (plgptr == NULL || plgptr->key == NULL || plgptr->val == NULL) { continue; } __split_plugin_data_str(&plgdata, plgptr->val); // Create a plug-in context apctx = malloc_nullsafe(ctx, sizeof(eAuthPluginCTX)+2); // Save some metadata about this plugin apctx->filename = strdup(plgdata.dsofile); apctx->plgid = atoi_nullsafe(plgptr->key); apctx->next = NULL; // Open the plugin apctx->dlhandle = dlopen(apctx->filename, RTLD_NOW); if (apctx->dlhandle != NULL) { int success = 0; // If we got a handle to the plug-in, it up apctx->plugin = __eAuthPlugin_Setup(ctx, apctx->filename, apctx->dlhandle); if (apctx->plugin != NULL) { ePluginInfo *plginfo = apctx->plugin->PluginInfo(); eurephia_log(ctx, LOG_INFO, 1, "Loaded eurephia %s plugin: %s (v%s) %s", ePluginTypeString(plginfo), plginfo->name, plginfo->version, plginfo->copyright); // Initialise the plug-in success = apctx->plugin->PluginInit(ctx, plgdata.configstr); } if (success == 1) { // On success, add this plug-in to the context chain if( apctxhead != NULL ) { apctx->next = apctxhead; } apctxhead = apctx; } else { // On failure to setup the plug-in, disable it eurephia_log(ctx, LOG_FATAL, 0, "Failed to initialse eurephia plugin %s. " "Plug-in disabled.", apctx->filename); free_nullsafe(ctx, apctx->filename); dlclose(apctx->dlhandle); apctx->plgid = 0; apctx->next = NULL; free(apctx); } } else { // On failure to load the plug-in ... Report error and ignore plug-in. eurephia_log(ctx, LOG_FATAL, 0, "Could not load eurephia plugin %s", apctx->filename); eurephia_log(ctx, LOG_FATAL, 1, "dlopen error: %s", dlerror()); free_nullsafe(ctx, apctx->filename); apctx->plgid = 0; apctx->next = NULL; free(apctx); } } eFree_values(ctx, plgs); // Return the plug-in context chain return apctxhead; } eAuthPlugin * eAuthPlugin_Get(eAuthPluginCTX *apctx, const int plgid) { eAuthPluginCTX *ptr = apctx; if (apctx == NULL) { return NULL; } while (ptr) { // Return a pointer to the authentication plug-in functions // if found if (ptr->plgid == plgid) { return ptr->plugin; } ptr = ptr->next; } return NULL; } void _eAuthPlugin_Close(eurephiaCTX *ctx, eAuthPluginCTX *apctx) { eAuthPluginCTX *ptr = apctx, *next = NULL; while (ptr) { // Save a pointe to the next plug-in context next = ptr->next; ptr->next = NULL; if (ptr->plugin->PluginClose) { ptr->plugin->PluginClose(ctx); } // Close the plug-in handle if (ptr->dlhandle) { dlclose(ptr->dlhandle); } // Clean up memory allocated by the plug-in context free_nullsafe(ctx, ptr->filename); ptr->plgid = 0; free_nullsafe(ctx, ptr->plugin); free_nullsafe(ctx, ptr); // Go to next plug-in context ptr = next; } }