external sources.
-<<YAZ Proxy involved in Character Set and Language Negotiation. Added
+
+Started work on facility for module loading (plugins). Initial
+effort is to be able to authenticate via a module. See mod_sample.cpp.
+
+YAZ Proxy involved in Character Set and Language Negotiation. Added
support for client's side negotiation record (high priority). Added
support for new elements of YAZ Proxy config file - negotiation-charset,
-negotiation-lang for parent element target.>>
+negotiation-lang for parent element target.
--- 0.9 2005/02/07
AC_CHECK_FUNCS(setrlimit getrlimit gettimeofday)
AC_CHECK_HEADERS(pwd.h sys/resource.h sys/stat.h sys/time.h sys/types.h sys/wait.h unistd.h)
+AC_CHECK_LIB(dl,dlopen)
dnl
dnl ----- libXSLT
AC_SUBST(XSLT_LIBS)
<?xml version="1.0"?>
-<!-- $Id: config.xml,v 1.7 2004-11-09 14:24:22 adam Exp $ -->
+<!-- $Id: config.xml,v 1.8 2005-02-11 15:19:07 adam Exp $ -->
<proxy xmlns="http://indexdata.dk/yazproxy/schema/0.8/"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<!-- Config can be checked with xerces-c++: PParse -n -s config.xml -->
<target name="localhost" default="1">
+ <negotiation-charset>iso-8859-1</negotiation-charset>
<url>localhost:9999</url>
<target-timeout>30</target-timeout>
<client-timeout>60</client-timeout>
+ <authentication handler="pipe" args="authenticate.pl"/>
<keepalive>
<bandwidth>1000000</bandwidth>
<pdu>1000</pdu>
<preinit>0</preinit>
<xi:include href="explain.xml"/>
<cql2rpn>pqf.properties</cql2rpn>
- <authentication>adam/x</authentication>
</target>
<target name="*">
<target-timeout>60</target-timeout>
</target>
<max-clients>50</max-clients>
<log>client-requests server-requests</log>
+ <module>../src/.libs/mod_proxy_sample.so</module>
</proxy>
-pkginclude_HEADERS = proxy.h bw.h
+pkginclude_HEADERS = proxy.h bw.h module.h
--- /dev/null
+/* $Id: module.h,v 1.1 2005-02-11 15:19:08 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.
+ */
+
+#ifndef YAZ_PROXY_MODULE_H
+#define YAZ_PROXY_MODULE_H_INCLUDED
+
+struct Yaz_ProxyModule_entry {
+ int int_version;
+ char *module_name;
+ char *module_description;
+ void *fl;
+};
+
+#define YAZPROXY_RET_NOT_ME 0 /* Did not catch it. pass to other handler */
+#define YAZPROXY_RET_OK 1 /* OK, grabbed */
+#define YAZPROXY_RET_PERM 2 /* Permissiong denied, reject etc. */
+
+struct Yaz_ProxyModule_int0 {
+ void *(*init)(void);
+ void (*destroy)(void *handle);
+ int (*authenticate)(void *handle,
+ const char *user, const char *group, const char *pw);
+};
+
+#endif
-/* $Id: proxy.h,v 1.11 2005-02-10 08:09:42 oleg Exp $
- Copyright (c) 1998-2004, Index Data.
+/* $Id: proxy.h,v 1.12 2005-02-11 15:19:08 adam Exp $
+ Copyright (c) 1998-2005, Index Data.
This file is part of the yaz-proxy.
Odr_oid *syntax, Z_RecordComposition *comp,
char **addinfo, char **stylesheet, char **schema,
char **backend_type, char **backend_charset,
- char **usemarcon_ini_stage1, char **usemarcon_ini_stage2
- );
+ char **usemarcon_ini_stage1, char **usemarcon_ini_stage2);
+
+ int check_authentication(const char *user, const char *group,
+ const char *password);
char *get_explain_doc(ODR odr, const char *name, const char *db,
int *len);
const char *get_explain_name(const char *db, const char **backend_db);
Z_GDU *m_bw_hold_PDU;
int m_max_record_retrieve;
void handle_max_record_retrieve(Z_APDU *apdu);
+ int handle_authentication(Z_APDU *apdu);
void display_diagrecs(Z_DiagRec **pp, int num);
Z_Records *create_nonSurrogateDiagnostics(ODR o, int error,
const char *addinfo);
-## $Id: Makefile.am,v 1.4 2004-12-03 15:50:53 adam Exp $
+## $Id: Makefile.am,v 1.5 2005-02-11 15:19:08 adam Exp $
AM_CXXFLAGS = $(YAZPPINC) -I$(srcdir)/../include $(XSLT_CFLAGS) $(USEMARCONINC)
LDADD=libyazproxy.la $(YAZPPLALIB) $(XSLT_LIBS) $(USEMARCONLALIB)
libyazproxy_la_LIBADD = $(XSLT_LIBS)
+
+# Modules
+mod_proxy_sample_la_SOURCES = mod_sample.cpp
+mod_proxy_sample_la_LDFLAGS = -rpath $(pkglibdir) -module -avoid-version
+
+pkglib_LTLIBRARIES = mod_proxy_sample.la
--- /dev/null
+/* $Id: mod_sample.cpp,v 1.1 2005-02-11 15:19:08 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>
+#include <stdio.h>
+
+#include <yazproxy/module.h>
+
+void *my_init(void)
+{
+ return 0; // no private data for handler
+}
+
+void my_destroy(void *p)
+{
+ // private data destroy
+}
+
+int my_authenticate(void *p, const char *user, const char *group,
+ const char *password)
+{
+ fprintf(stderr, "my_authenticate: user=%s group=%s\n",
+ user ? user : "none", group ? group : "none");
+ // authentication handler
+ if (!user && !group && !password)
+ return YAZPROXY_RET_OK; // OK if anonymous
+ if (user && !strcmp(user, "guest")
+ && password && !strcmp(password, "guest")) // or guest guest
+ return YAZPROXY_RET_OK;
+ return YAZPROXY_RET_PERM; // fail otherwise
+}
+
+Yaz_ProxyModule_int0 interface0 = {
+ my_init,
+ my_destroy,
+ my_authenticate
+};
+
+Yaz_ProxyModule_entry yazproxy_module = {
+ 0, // interface version
+ "sample", // name
+ "Sample Module for YAZ Proxy",// description
+ &interface0
+};
+
-/* $Id: proxyp.h,v 1.1 2004-12-03 14:28:18 adam Exp $
- Copyright (c) 1998-2004, Index Data.
+/* $Id: proxyp.h,v 1.2 2005-02-11 15:19:08 adam Exp $
+ Copyright (c) 1998-2005, Index Data.
This file is part of the yaz-proxy.
#endif
#include <yazproxy/proxy.h>
+#include <yazproxy/module.h>
class Yaz_usemarcon {
public:
-/* $Id: yaz-proxy-config.cpp,v 1.14 2005-02-10 08:09:42 oleg Exp $
- Copyright (c) 1998-2004, Index Data.
+/* $Id: yaz-proxy-config.cpp,v 1.15 2005-02-11 15:19:08 adam Exp $
+ Copyright (c) 1998-2005, Index Data.
This file is part of the yaz-proxy.
*/
#include <ctype.h>
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
#include <yaz/log.h>
#include "proxyp.h"
+
+class Yaz_ProxyModule {
+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 authenticate(const char *user, const char *group, const char *password);
+};
+
+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);
+ }
+ dlclose(m_dl_handle);
+}
+
+int Yaz_ProxyModule::authenticate(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, user, group, password);
+ }
+ return YAZPROXY_RET_NOT_ME;
+}
+
class Yaz_ProxyConfigP {
friend class Yaz_ProxyConfig;
- int m_copy;
+ Yaz_ProxyModule *m_modules;
int mycmp(const char *hay, const char *item, size_t len);
int match_list(int v, const char *m);
int atoi_l(const char **cp);
#if HAVE_XSLT
+ void load_modules(void);
+ void unload_modules(void);
int check_schema(xmlNodePtr ptr, Z_RecordComposition *comp,
const char *schema_identifier);
xmlDocPtr m_docPtr;
int get_explain_ptr(const char *host, const char *db,
xmlNodePtr *ptr_target, xmlNodePtr *ptr_explain);
#endif
+ Yaz_ProxyConfigP();
+ ~Yaz_ProxyConfigP();
};
-Yaz_ProxyConfig::Yaz_ProxyConfig()
+Yaz_ProxyConfigP::Yaz_ProxyConfigP()
{
- m_cp = new Yaz_ProxyConfigP;
- m_cp->m_copy = 0;
#if HAVE_XSLT
- m_cp->m_docPtr = 0;
- m_cp->m_proxyPtr = 0;
+ m_docPtr = 0;
+ m_proxyPtr = 0;
#endif
+ m_modules = 0;
}
-Yaz_ProxyConfig::~Yaz_ProxyConfig()
+Yaz_ProxyConfigP::~Yaz_ProxyConfigP()
{
#if HAVE_XSLT
- if (!m_cp->m_copy && m_cp->m_docPtr)
- xmlFreeDoc(m_cp->m_docPtr);
+ if (m_docPtr)
+ xmlFreeDoc(m_docPtr);
#endif
+}
+
+Yaz_ProxyConfig::Yaz_ProxyConfig()
+{
+ m_cp = new Yaz_ProxyConfigP;
+}
+
+Yaz_ProxyConfig::~Yaz_ProxyConfig()
+{
delete m_cp;
}
+#if HAVE_XSLT
+void Yaz_ProxyConfigP::unload_modules()
+{
+ yaz_log(YLOG_WARN, "unload_modules not implemented yet");
+}
+#endif
+
+#if HAVE_XSLT
+void Yaz_ProxyConfigP::load_modules()
+{
+ if (!m_proxyPtr)
+ return;
+ xmlNodePtr ptr;
+ for (ptr = m_proxyPtr->children; ptr; ptr = ptr->next)
+ {
+ const char *fname;
+ if (ptr->type == XML_ELEMENT_NODE
+ && !strcmp((const char *) ptr->name, "module")
+ && (fname = get_text(ptr)))
+ {
+#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_modules);
+ m_modules = m;
+ yaz_log(YLOG_LOG, "Loading %s OK", fname);
+ }
+ else
+ {
+ yaz_log(YLOG_WARN, "Loading %s FAIL: missing yazproxy_module symbol", fname);
+ dlclose(dl_handle);
+ }
+ }
+ else
+ yaz_log(YLOG_WARN, "Loading %s FAIL: dlopen failed", fname);
+#else
+ yaz_log(YLOG_WARN, "Loading &s FAIL: dl unsupported", fname);
+#endif
+ }
+ }
+}
+#endif
+
int Yaz_ProxyConfig::read_xml(const char *fname)
{
#if HAVE_XSLT
if (m_cp->m_docPtr)
xmlFreeDoc(m_cp->m_docPtr);
m_cp->m_docPtr = ndoc;
+
+ m_cp->unload_modules();
+ m_cp->load_modules();
return 0;
#else
return -2;
}
+int Yaz_ProxyConfig::check_authentication(const char *user,
+ const char *group,
+ const char *password)
+{
+ Yaz_ProxyModule *m = m_cp->m_modules;
+
+ int ret = YAZPROXY_RET_NOT_ME;
+ for (; m; m = m->get_next())
+ {
+ ret = m->authenticate(user, group, password);
+ if (ret != YAZPROXY_RET_NOT_ME)
+ break;
+ }
+ if (ret == YAZPROXY_RET_PERM)
+ return 0;
+ return 1;
+}
+
int Yaz_ProxyConfig::check_syntax(ODR odr, const char *name,
Odr_oid *syntax, Z_RecordComposition *comp,
char **addinfo,
-/* $Id: yaz-proxy.cpp,v 1.21 2005-02-10 19:17:44 adam Exp $
+/* $Id: yaz-proxy.cpp,v 1.22 2005-02-11 15:19:08 adam Exp $
Copyright (c) 1998-2005, Index Data.
This file is part of the yaz-proxy.
if (auth)
m_proxy_authentication = (char *) xstrdup (auth);
}
+
void Yaz_Proxy::set_proxy_negotiation (const char *charset, const char *lang)
{
yaz_log(YLOG_LOG, "%sSet the proxy negotiation: charset to '%s', "
if (lang)
m_proxy_negotiation_lang = (char *) xstrdup (lang);
}
+
Yaz_ProxyConfig *Yaz_Proxy::check_reconfigure()
{
if (m_parent)
return apdu;
}
+int Yaz_Proxy::handle_authentication(Z_APDU *apdu)
+{
+ if (apdu->which != Z_APDU_initRequest)
+ return 1; // pass if no init request
+ Z_InitRequest *req = apdu->u.initRequest;
+
+ Yaz_ProxyConfig *cfg = check_reconfigure();
+ if (!cfg)
+ return 1; // pass if no config
+
+ int ret;
+ if (req->idAuthentication == 0)
+ {
+ ret = cfg->check_authentication(0, 0, 0);
+ }
+ else if (req->idAuthentication->which == Z_IdAuthentication_idPass)
+ {
+ ret = cfg->check_authentication(
+ req->idAuthentication->u.idPass->userId,
+ req->idAuthentication->u.idPass->groupId,
+ req->idAuthentication->u.idPass->password);
+ }
+ else if (req->idAuthentication->which == Z_IdAuthentication_open)
+ {
+ char user[64], pass[64];
+ *user = '\0';
+ *pass = '\0';
+ sscanf(req->idAuthentication->u.open, "%63[^/]/%63s", user, pass);
+ ret = cfg->check_authentication(user, 0, pass);
+ }
+ else
+ ret = cfg->check_authentication(0, 0, 0);
+ return ret;
+}
+
Z_APDU *Yaz_Proxy::handle_syntax_validation(Z_APDU *apdu)
{
m_marcxml_flag = 0;
}
m_client->m_init_flag = 1;
}
+
+ if (!handle_authentication(apdu))
+ {
+ Z_APDU *apdu_reject = zget_APDU(odr_encode(), Z_APDU_initResponse);
+ *apdu_reject->u.initResponse->result = 0;
+ send_to_client(apdu_reject);
+
+ shutdown();
+ return;
+ }
+
handle_max_record_retrieve(apdu);
if (apdu)