Added support for threaded authentication modules. See
[yazproxy-moved-to-github.git] / src / modules.cpp
diff --git a/src/modules.cpp b/src/modules.cpp
new file mode 100644 (file)
index 0000000..4e7f473
--- /dev/null
@@ -0,0 +1,178 @@
+/* $Id: modules.cpp,v 1.1 2005-05-30 20:09:21 adam Exp $
+   Copyright (c) 1998-2005, Index Data.
+
+This file is part of the yaz-proxy.
+
+YAZ proxy 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 2, or (at your option) any later
+version.
+
+YAZ proxy 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 YAZ proxy; see the file LICENSE.  If not, write to the
+Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include <string.h>
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <yaz/nmem.h>
+#include <yazproxy/module.h>
+
+class Yaz_ProxyModule {
+    friend class Proxy_Msg;
+private:
+    void *m_dl_handle;                /* dlopen/close handle */
+    Yaz_ProxyModule_entry *m_entry;
+    Yaz_ProxyModule *m_next; 
+    void *m_user_handle;              /* user handle */
+public:
+    Yaz_ProxyModule(void *dl_handle, Yaz_ProxyModule_entry *ent,
+                   Yaz_ProxyModule *next);
+    ~Yaz_ProxyModule();
+    
+    Yaz_ProxyModule *get_next() { return m_next; };
+    int is_module(const char *name);
+    int authenticate(const char *target_name, void *element_ptr,
+                    const char *user, const char *group, const char *password);
+};
+
+int Yaz_ProxyModule::is_module(const char *name)
+{
+    if (!name || !strcmp(m_entry->module_name, name))
+       return 1;
+    return 0;
+}
+
+Yaz_ProxyModule::Yaz_ProxyModule(void *dl_handle, Yaz_ProxyModule_entry *ent,
+                                Yaz_ProxyModule *next)
+{
+    m_dl_handle = dl_handle;
+    m_entry = ent;
+    m_next = next;
+    m_user_handle = 0;
+    if (m_entry->int_version == 0)
+    {
+       struct Yaz_ProxyModule_int0 *int0 =
+           reinterpret_cast<Yaz_ProxyModule_int0 *>(m_entry->fl);
+       if (int0->init)
+           m_user_handle = (*int0->init)();
+    }
+}
+
+Yaz_ProxyModule::~Yaz_ProxyModule()
+{
+    if (m_entry->int_version == 0)
+    {
+       struct Yaz_ProxyModule_int0 *int0 =
+           reinterpret_cast<Yaz_ProxyModule_int0 *>(m_entry->fl);
+       if (int0->destroy)
+           (*int0->destroy)(m_user_handle);
+    }
+#if HAVE_DLFCN_H
+    dlclose(m_dl_handle);
+#endif
+}
+
+int Yaz_ProxyModule::authenticate(const char *name,
+                                 void *element_ptr,
+                                 const char *user, const char *group,
+                                 const char *password)
+{
+    if (m_entry->int_version == 0)
+    {
+       struct Yaz_ProxyModule_int0 *int0 =
+           reinterpret_cast<Yaz_ProxyModule_int0 *>(m_entry->fl);
+       
+       if (!int0->authenticate)
+           return YAZPROXY_RET_NOT_ME;
+       return (*int0->authenticate)(m_user_handle, name, element_ptr,
+                                    user, group, password);
+    }
+    return YAZPROXY_RET_NOT_ME;
+}
+
+Yaz_ProxyModules::Yaz_ProxyModules()
+{
+    m_list = 0;
+}
+
+
+Yaz_ProxyModules::~Yaz_ProxyModules()
+{
+    unload_modules();
+}
+
+void Yaz_ProxyModules::unload_modules()
+{
+    Yaz_ProxyModule *m = m_list;
+    while (m)
+    {
+       Yaz_ProxyModule *m_next = m->get_next();
+       delete m;
+       m = m_next;
+    }
+    m_list = 0;
+}
+
+
+int Yaz_ProxyModules::authenticate(const char *module_name,
+                                  const char *target_name, void *element_ptr,
+                                  const char *user,
+                                  const char *group,
+                                  const char *password)
+{
+    int ret = YAZPROXY_RET_NOT_ME;
+    Yaz_ProxyModule *m = m_list;
+    for (; m; m = m->get_next())
+    {
+       if (m->is_module(module_name))
+       {
+           ret = m->authenticate(target_name, element_ptr,
+                                      user, group, password);
+           if (ret != YAZPROXY_RET_NOT_ME)
+               break;
+       }
+    }
+    return ret;
+}
+
+int Yaz_ProxyModules::add_module(const char *fname)
+{
+#if HAVE_DLFCN_H
+    void *dl_handle = dlopen(fname, RTLD_NOW|RTLD_GLOBAL);
+    if (dl_handle)
+    {
+       Yaz_ProxyModule_entry *fl_ptr = 0;
+       fl_ptr = reinterpret_cast<Yaz_ProxyModule_entry *> 
+           (dlsym(dl_handle, "yazproxy_module"));
+       if (fl_ptr)
+       {
+           Yaz_ProxyModule *m = new Yaz_ProxyModule(dl_handle,
+                                                    fl_ptr,
+                                                    m_list);
+           m_list = m;
+
+           return 0;
+       }
+       else
+       {
+           return -1;
+           dlclose(dl_handle);
+       }
+    }
+    else
+       return -1;
+#else
+    return -1;
+#endif
+}
+