From 7163b9178c89a7fc866dd33309ca6a1067758b92 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Sat, 25 Mar 2006 10:56:28 +0000 Subject: [PATCH] New Helsinki University Module. By Ere Maijala --- src/Makefile.am | 8 +- src/mod_helsinki.cpp | 266 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 src/mod_helsinki.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 9f712f5..d117d71 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -## $Id: Makefile.am,v 1.11 2005-10-27 22:38:03 adam Exp $ +## $Id: Makefile.am,v 1.12 2006-03-25 10:56:28 adam Exp $ AM_CXXFLAGS = $(YAZPPINC) -I$(srcdir)/../include $(XSLT_CFLAGS) $(USEMARCONINC) @@ -27,4 +27,8 @@ libyazproxy_la_LIBADD = $(XSLT_LIBS) mod_proxy_sample_la_SOURCES = mod_sample.cpp mod_proxy_sample_la_LDFLAGS = -rpath $(pkglibdir) -module -avoid-version -pkglib_LTLIBRARIES = mod_proxy_sample.la +mod_proxy_helsinki_la_SOURCES = mod_helsinki.cpp +mod_proxy_helsinki_la_LDFLAGS = -rpath $(pkglibdir) -module -avoid-version + +pkglib_LTLIBRARIES = mod_proxy_sample.la mod_proxy_helsinki.la + diff --git a/src/mod_helsinki.cpp b/src/mod_helsinki.cpp new file mode 100644 index 0000000..5558c87 --- /dev/null +++ b/src/mod_helsinki.cpp @@ -0,0 +1,266 @@ +/* $Id: mod_helsinki.cpp,v 1.1 2006-03-25 10:56:28 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 +#include +#include + +#include + +#include + +#include + +#if HAVE_XSLT +#include +#include +#include +#include +#include +#endif + +struct IP_ADDRESS +{ + unsigned int a1, a2, a3, a4; +}; + +void *my_init(void) +{ + return 0; // no private data for handler +} + +void my_destroy(void *p) +{ + // private data destroy +} + +void zero_address(IP_ADDRESS *addr) +{ + addr->a1 = addr->a2 = addr->a3 = addr->a4 = 0; +} + +int str_to_address(const char *str, IP_ADDRESS *addr) +{ + zero_address(addr); + return sscanf(str, "%3u.%3u.%3u.%3u", &addr->a1, &addr->a2, &addr->a3, &addr->a4); +} + +void str_to_address_range(const char *str, + IP_ADDRESS *range_lo, + IP_ADDRESS *range_hi) +{ + char lo[16], hi[16]; + *lo = '\0'; + *hi = '\0'; + int num = sscanf(str, "%15[^-]-%15s", lo, hi); + + if (num == 1) + { + // Create a range from a single address or a part of it (e.g. 192.168) + num = str_to_address(lo, range_lo); + if (num == 1) + { + range_hi->a1 = range_lo->a1; + range_hi->a2 = range_hi->a3 = range_hi->a4 = 255; + } + else if (num == 2) + { + range_hi->a1 = range_lo->a1; + range_hi->a2 = range_lo->a2; + range_hi->a3 = range_hi->a4 = 255; + } + else if (num == 3) + { + range_hi->a1 = range_lo->a1; + range_hi->a2 = range_lo->a2; + range_hi->a3 = range_lo->a3; + range_hi->a4 = 255; + } + else + { + range_hi->a1 = range_lo->a1; + range_hi->a2 = range_lo->a2; + range_hi->a3 = range_lo->a3; + range_hi->a4 = range_lo->a4; + } + return; + } + + // If a range is specified, both ends need to be full addresses + if (str_to_address(lo, range_lo) != 4 || str_to_address(hi, range_hi) != 4) + { + zero_address(range_lo); + zero_address(range_hi); + } +} + +unsigned int address_to_int(IP_ADDRESS addr) +{ + return addr.a1 << 24 | addr.a2 << 16 | addr.a3 << 8 | addr.a4; +} + +int my_authenticate(void *user_handle, + const char *target_name, + void *element_ptr, + const char *user, const char *group, const char *password, + const char *peer_IP) +{ + // see if we have an "args" attribute + const char *args = 0; +#if HAVE_XSLT + xmlNodePtr ptr = (xmlNodePtr) element_ptr; + struct _xmlAttr *attr; + + for (attr = ptr->properties; attr; attr = attr->next) + { + if (!strcmp((const char *) attr->name, "args") && + attr->children && attr->children->type == XML_TEXT_NODE) + args = (const char *) attr->children->content; + } +#endif + // args holds args (or NULL if none are provided) + + yaz_log(YLOG_LOG, "Authentication: authenticating user %s, address %s", user ? user : "-", peer_IP ? peer_IP : "-"); + + // authentication handler + char user_file[255], ip_file[255]; + *user_file = '\0'; + *ip_file = '\0'; + sscanf(args, "%254[^:]:%254s", user_file, ip_file); + + yaz_log(YLOG_LOG, "Authentication: user file: %s, ip file: %s", user_file, ip_file); + + // Check if the IP address is listed in the file of allowed address ranges. + // The format of the file: + // 192.168.0 + // 192.168.0.100 + // 192.168.0.1-192.168.0.200 + int status = YAZPROXY_RET_PERM; + if (ip_file && peer_IP) + { + yaz_log(YLOG_LOG, "Authentication: checking ip address"); + + const char *pIP = peer_IP; + if (strncmp(pIP, "tcp:", 4) == 0) + pIP += 4; + IP_ADDRESS peer_address; + if (str_to_address(pIP, &peer_address) != 4) + yaz_log(YLOG_WARN, "Authentication: could not decode peer IP address %s properly", pIP); + unsigned int peer_address_int = address_to_int(peer_address); + + FILE *f = fopen(ip_file, "r"); + if (!f) + { + yaz_log(YLOG_WARN, "Authentication: could not open ip authentication file %s", ip_file); + return YAZPROXY_RET_PERM; + } + while (!feof(f)) + { + char line[255]; + *line = '\0'; + fgets(line, 254, f); + line[254] = '\0'; + + // Remove comments + char *comment_pos = strchr(line, '#'); + if (comment_pos) + *comment_pos = '\0'; + + IP_ADDRESS range_lo, range_hi; + str_to_address_range(line, &range_lo, &range_hi); + if (address_to_int(range_lo) <= peer_address_int && peer_address_int <= address_to_int(range_hi)) + { + status = YAZPROXY_RET_OK; + break; + } + } + fclose(f); + if (status == YAZPROXY_RET_OK) + { + yaz_log(YLOG_LOG, "Authentication: IP address %s allowed", pIP); + return YAZPROXY_RET_OK; + } + } + + if (!user || !password || !*user_file) + { + yaz_log(YLOG_WARN, "Authentication: no user name, password or user file specified"); + return YAZPROXY_RET_PERM; + } + + time_t current_time; + time(¤t_time); + struct tm *local_time = localtime(¤t_time); + char current_date[10]; + sprintf(current_date, "%04d%02d%02d", local_time->tm_year + 1900, local_time->tm_mon + 1, local_time->tm_mday); + + FILE *f = fopen(user_file, "r"); + if (!f) + { + yaz_log(YLOG_WARN, "Authentication: could not open user authentication file %s", user_file); + return YAZPROXY_RET_PERM; + } + while (!feof(f)) + { + char line[255]; + *line = '\0'; + fgets(line, 254, f); + line[254] = '\0'; + char *p = strchr(line, '\n'); + if (p) *p = '\0'; + + char f_user[255], f_password[255], f_expiry[255]; + *f_user = '\0'; + *f_password = '\0'; + *f_expiry = '\0'; + sscanf(line, "%254[^:]:%254[^:]:%254s", f_user, f_password, f_expiry); + + if (strcmp(user, f_user) == 0 && strcmp(password, f_password) == 0 && (!*f_expiry || strcmp(current_date, f_expiry) <= 0)) + { + status = YAZPROXY_RET_OK; + break; + } + } + fclose(f); + yaz_log(YLOG_LOG, "Authentication: %s for user %s", status == YAZPROXY_RET_OK ? "successful" : "failed", user); + return status; +} + +Yaz_ProxyModule_int0 interface0 = { + my_init, + my_destroy, + my_authenticate +}; + +Yaz_ProxyModule_entry yazproxy_module = { + 0, // interface version + "helsinki", // name + "Helsinki Module for YAZ Proxy",// description + &interface0 +}; + +/* + * Local variables: + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ -- 1.7.10.4