1 /* This file is part of YAZ proxy
2 Copyright (C) 1998-2008 Index Data
4 YAZ proxy is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
9 YAZ proxy is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <yazproxy/module.h>
30 #include <libxml/parser.h>
31 #include <libxml/tree.h>
32 #include <libxml/xinclude.h>
33 #include <libxslt/xsltutils.h>
34 #include <libxslt/transform.h>
39 unsigned int a1, a2, a3, a4;
44 return 0; // no private data for handler
47 void my_destroy(void *p)
49 // private data destroy
52 void zero_address(IP_ADDRESS *addr)
54 addr->a1 = addr->a2 = addr->a3 = addr->a4 = 0;
57 int str_to_address(const char *str, IP_ADDRESS *addr)
60 return sscanf(str, "%3u.%3u.%3u.%3u", &addr->a1, &addr->a2, &addr->a3, &addr->a4);
63 void str_to_address_range(const char *str,
70 int num = sscanf(str, "%15[^-]-%15s", lo, hi);
74 // Create a range from a single address or a part of it (e.g. 192.168)
75 num = str_to_address(lo, range_lo);
78 range_hi->a1 = range_lo->a1;
79 range_hi->a2 = range_hi->a3 = range_hi->a4 = 255;
83 range_hi->a1 = range_lo->a1;
84 range_hi->a2 = range_lo->a2;
85 range_hi->a3 = range_hi->a4 = 255;
89 range_hi->a1 = range_lo->a1;
90 range_hi->a2 = range_lo->a2;
91 range_hi->a3 = range_lo->a3;
96 range_hi->a1 = range_lo->a1;
97 range_hi->a2 = range_lo->a2;
98 range_hi->a3 = range_lo->a3;
99 range_hi->a4 = range_lo->a4;
104 // If a range is specified, both ends need to be full addresses
105 if (str_to_address(lo, range_lo) != 4 || str_to_address(hi, range_hi) != 4)
107 zero_address(range_lo);
108 zero_address(range_hi);
112 unsigned int address_to_int(IP_ADDRESS addr)
114 return addr.a1 << 24 | addr.a2 << 16 | addr.a3 << 8 | addr.a4;
117 int my_authenticate(void *user_handle,
118 const char *target_name,
120 const char *user, const char *group, const char *password,
123 // see if we have an "args" attribute
124 const char *args = 0;
126 xmlNodePtr ptr = (xmlNodePtr) element_ptr;
127 struct _xmlAttr *attr;
129 for (attr = ptr->properties; attr; attr = attr->next)
131 if (!strcmp((const char *) attr->name, "args") &&
132 attr->children && attr->children->type == XML_TEXT_NODE)
133 args = (const char *) attr->children->content;
136 // args holds args (or NULL if none are provided)
138 yaz_log(YLOG_LOG, "Authentication: authenticating user %s, address %s", user ? user : "(none)", peer_IP ? peer_IP : "-");
140 // authentication handler
141 char user_file[255], ip_file[255];
144 sscanf(args, "%254[^:]:%254s", user_file, ip_file);
146 yaz_log(YLOG_DEBUG, "Authentication: user file: %s, ip file: %s", user_file, ip_file);
148 // Check if the IP address is listed in the file of allowed address ranges.
149 // The format of the file:
152 // 192.168.0.1-192.168.0.200
153 int status = YAZPROXY_RET_PERM;
154 if (*ip_file && peer_IP)
156 yaz_log(YLOG_DEBUG, "Authentication: checking ip address");
158 const char *pIP = peer_IP;
159 if (strncmp(pIP, "tcp:", 4) == 0)
161 if (strncmp(pIP, "::ffff:", 7) == 0)
163 IP_ADDRESS peer_address;
164 if (str_to_address(pIP, &peer_address) != 4)
165 yaz_log(YLOG_WARN, "Authentication: could not decode peer IP address %s properly", pIP);
166 unsigned int peer_address_int = address_to_int(peer_address);
168 FILE *f = fopen(ip_file, "r");
171 yaz_log(YLOG_WARN, "Authentication: could not open ip authentication file %s", ip_file);
172 return YAZPROXY_RET_PERM;
182 char *comment_pos = strchr(line, '#');
186 IP_ADDRESS range_lo, range_hi;
187 str_to_address_range(line, &range_lo, &range_hi);
188 if (address_to_int(range_lo) <= peer_address_int && peer_address_int <= address_to_int(range_hi))
190 status = YAZPROXY_RET_OK;
195 if (status == YAZPROXY_RET_OK)
197 yaz_log(YLOG_LOG, "Authentication: IP address %s allowed", pIP);
198 return YAZPROXY_RET_OK;
202 if (!user || !password || !*user_file)
204 yaz_log(YLOG_LOG, "Authentication: anonymous authentication failed");
205 return YAZPROXY_RET_PERM;
210 struct tm *local_time = localtime(¤t_time);
211 char current_date[10];
212 sprintf(current_date, "%04d%02d%02d", local_time->tm_year + 1900, local_time->tm_mon + 1, local_time->tm_mday);
214 FILE *f = fopen(user_file, "r");
217 yaz_log(YLOG_WARN, "Authentication: could not open user authentication file %s", user_file);
218 return YAZPROXY_RET_PERM;
226 char *p = strchr(line, '\n');
229 char f_user[255], f_password[255], f_expiry[255];
233 sscanf(line, "%254[^:]:%254[^:]:%254s", f_user, f_password, f_expiry);
235 if (strcmp(user, f_user) == 0 && strcmp(password, f_password) == 0 && (!*f_expiry || strcmp(current_date, f_expiry) <= 0))
237 status = YAZPROXY_RET_OK;
242 yaz_log(YLOG_LOG, "Authentication: %s for user %s", status == YAZPROXY_RET_OK ? "successful" : "failed", user);
246 Yaz_ProxyModule_int0 interface0 = {
252 Yaz_ProxyModule_entry yazproxy_module = {
253 0, // interface version
255 "Helsinki Module for YAZ Proxy",// description
262 * indent-tabs-mode: nil
264 * vim: shiftwidth=4 tabstop=8 expandtab