summaryrefslogtreecommitdiffstats
path: root/auth/eurephia_authplugin_driver.c
blob: 1eb76b103064d400386598d3d2bbf5181b912346 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*  eurephia_authplugin_driver.c
 *
 *  Copyright (C) 2013          David Sommerseth <dazo@users.sourceforge.net>
 *
 *  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 <http://www.gnu.org/licenses/>.
 *
 */

/**
 * @file   eurephia_authplugin_driver.c
 * @author David Sommerseth <dazo@users.sourceforge.net>
 * @date   2013-02-15
 *
 * @brief  Functions for preparing the plug-in pointers for the eAuthPluginCTX
 */

#include <string.h>
#include <dlfcn.h>
#include <assert.h>

#include <eurephia_context.h>
#include <eurephia_authplugin_driver.h>
#include <eurephia_nullsafe.h>
#include <eurephia_log.h>
#include <eurephia_getsym.h>

/**
 * Opens an eurephia plug-in and retrieves a copy of the plug-in information.
 * NB!  The returned ePluginInfo struct must be explicitly freed, as this is
 * a malloced memory region containing a copy of the plug-in info.
 *
 * @param eurephiaCTX*  Pointer to the current eurephia context
 * @param dlfilename    String containing the filename to the plug-in to inspect
 *
 * @return Returns a pointer to a copy of the plug-in information on success.  Otherwise
 *         NULL.  If not NULL, this result must be freed by using ePluginInfoFree()
 */
ePluginInfoRW* ePluginInspect(eurephiaCTX * ctx, const char * dlfilename)
{
        ePluginInfo *plginf = NULL;
        ePluginInfoRW *ret = NULL;
        void *dlhandle = NULL;
        ePluginInfo * (*PluginInfo)();

        assert(ctx != NULL);
        assert(dlfilename != NULL);

        dlhandle = dlopen(dlfilename, RTLD_NOW);
        if (dlhandle == NULL) {
                eurephia_log(ctx, LOG_FATAL, 0, "Could not load eurephia plugin %s",
                             dlfilename);
                eurephia_log(ctx, LOG_FATAL, 1, "dlopen error: %s", dlerror());
                return NULL;
        }

        PluginInfo = eGetSym(ctx, dlhandle, "PluginInfo");
        if (ctx->fatal_error > 0) {
                dlclose(dlhandle);
                return NULL;
        }

        plginf = PluginInfo();

        /* Make a copy of the plug-in info, so we can close the plug-in */
        ret = malloc_nullsafe(ctx, sizeof(ePluginInfo)+2);
        ret->name = strdup_nullsafe((char *) plginf->name);
        ret->version = strdup_nullsafe((char *) plginf->version);
        ret->copyright = strdup_nullsafe((char *) plginf->copyright);
        ret->pluginType = plginf->pluginType;
        ret->APIversion = plginf->APIversion;

        dlclose(dlhandle);
        return ret;
}


/**
 *  Frees the memory allocated by ePluginInspect()
 *
 *  @param eurephiaCTX*   Pointer to the current eurephia context
 *  @param ePluginInfo*   Pointer to the ePluginInfo buffer to be freed
 */
void ePluginInfoFree(eurephiaCTX *ctx, ePluginInfoRW *plginf)
{
        assert( ctx != NULL );
        assert( plginf != NULL );

        free_nullsafe(ctx, plginf->name);
        free_nullsafe(ctx, plginf->version);
        free_nullsafe(ctx, plginf->copyright);
        free_nullsafe(ctx, plginf);
}


/**
 *  Helper function used by eAuthPlugin_Init().  This will look-up symbols in an
 *  external authenticaion plug-in (.so file) which the eurephia context allows.
 *  The available functions, based on the eurephia context, will be returned
 *  via the eAuthPlugin struct.
 *
 *  @param eurephiaCTX* Pointer to the current eurephia context
 *  @param dlfilename*  String pointer to the auth-plugin filename, used in error messages only
 *  @param dlhandle*    The dl handle returned by dlopen() for the auth-plugin to setup
 *
 *  @return On success it returns a pointer to an eAuthPlugin struct which defines all available
 *          functions in the authentication plug-in.  Otherwise NULL is returned.
 */
eAuthPlugin * __eAuthPlugin_Setup(eurephiaCTX * ctx, const char * dlfilename, void * dlhandle)
{
        eAuthPlugin *ret = NULL;
        ePluginInfo *plginfo = NULL;

        // Ensure we have sane contexts
        assert(ctx != NULL);
        assert(ctx->fatal_error == 0);
        assert(dlhandle != NULL);

        // Allocate memory to the plug-in function pointers,
        // saved in a eAuthPlugin struct
        ret = malloc_nullsafe(ctx, sizeof(struct __eAuthPlugin)+2);
        ret->PluginInfo = eGetSym(ctx, dlhandle, "PluginInfo");
        ret->PluginInit = eGetSym(ctx, dlhandle, "PluginInit");
        ret->PluginClose = eGetSym_optional(ctx, dlhandle, "PluginClose");

        // If any of the eGetSym() triggered a fatal error,
        // reset the fatality mark and return with a failure code
        if (ctx->fatal_error > 0) {
                free_nullsafe(ctx, ret);
                ctx->fatal_error = 0;
                return NULL;
        }

        // Grap the API version for this plugin
        plginfo = ret->PluginInfo();
        if (plginfo->pluginType != eptAUTH) {
                eurephia_log(ctx, LOG_FATAL, 0,
                             "Plug-in %s is not an authentication plug-in", dlfilename);
                free_nullsafe(ctx, ret);
                return NULL;
        }

        // Only allow the following functions if the eurephia context is
        // based on a admin interface or the openvpn authentication plug-in.
        if ((ctx->context_type == ECTX_PLUGIN_AUTH) ||
            (ctx->context_type == ECTX_ADMIN_CONSOLE) ||
            (ctx->context_type == ECTX_ADMIN_WEB) ) {
                switch( plginfo->APIversion ) {
                case 1:
                        ret->AuthenticateUser = eGetSym(ctx, dlhandle,
                                                        "AuthenticateUser");
                        break;
                default:
                        eurephia_log(ctx, LOG_CRIT, 0, "Invalid API version reported "
                                     "in %s: APIversion=%i.  Plug-in disabled",
                                     dlfilename, plginfo->APIversion);
                        memset(ret, 0, sizeof(eAuthPlugin));
                        free_nullsafe(ctx, ret);
                        return NULL;
                }
        }

        // Only allow the following functions if we're in a
        // administration context
        if ((ctx->context_type == ECTX_ADMIN_CONSOLE) ||
            (ctx->context_type == ECTX_ADMIN_WEB)) {
                switch( plginfo->APIversion ) {
                case 1:
                        ret->ChangePassword = eGetSym_optional(ctx, dlhandle,
                                                               "ChangePassword");
                        break;
                default:
                        eurephia_log(ctx, LOG_CRIT, 0, "Invalid API version reported "
                                     "in %s: APIversion=%i.  Plug-in disabled",
                                     dlfilename, plginfo->APIversion);
                        memset(ret, 0, sizeof(eAuthPlugin));
                        free_nullsafe(ctx, ret);
                        return NULL;
                }
        }

        // Return a struct containing the plug-in functions
        return ret;
}