source: trunk/gsdl/src/recpt/authenaction.cpp@ 727

Last change on this file since 727 was 722, checked in by davidb, 25 years ago

Collection building support through web pages
and internal and external link handling for collection documents

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 12.1 KB
Line 
1/**********************************************************************
2 *
3 * authenaction.cpp -- authenticating users
4 * Copyright (C) 1999 DigiLib Systems Limited, New Zealand
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 * $Id: authenaction.cpp 722 1999-10-19 03:23:46Z davidb $
25 *
26 *********************************************************************/
27
28/*
29 $Log$
30 Revision 1.8 1999/10/19 03:23:41 davidb
31 Collection building support through web pages
32 and internal and external link handling for collection documents
33
34 Revision 1.7 1999/09/07 23:04:29 rjmcnab
35 removed some compiler warnings
36
37 Revision 1.6 1999/09/07 04:56:52 sjboddie
38 added GPL notice
39
40 Revision 1.5 1999/09/02 00:23:24 rjmcnab
41 a couple of minor things
42
43 Revision 1.4 1999/07/30 02:24:43 sjboddie
44 added collectinfo argument to some functions
45
46 Revision 1.3 1999/07/13 23:23:26 rjmcnab
47 Put users in their own gdbm database. Moved a lot of functionality to usersdb
48
49 Revision 1.2 1999/07/11 10:47:32 rjmcnab
50 Got something basic working.
51
52 Revision 1.1 1999/07/10 22:19:29 rjmcnab
53 Initial revision.
54
55
56 */
57
58
59#include "authenaction.h"
60#include "fileutil.h"
61#include "cfgread.h"
62#include "cgiutils.h"
63#include "infodbclass.h"
64#include "gsdltimes.h"
65#include "userdb.h"
66
67
68///////////////
69// authenaction
70///////////////
71
72authenaction::authenaction () {
73 keydecay = 600; // 10 minutes
74 recpt = NULL;
75
76 // this action uses cgi variable "a"
77 cgiarginfo arg_ainfo;
78 arg_ainfo.shortname = "a";
79 arg_ainfo.longname = "action";
80 arg_ainfo.multiplechar = true;
81 arg_ainfo.defaultstatus = cgiarginfo::weak;
82 arg_ainfo.argdefault = "a";
83 arg_ainfo.savedarginfo = cgiarginfo::must;
84 argsinfo.addarginfo (NULL, arg_ainfo);
85
86 // "us"
87 arg_ainfo.shortname = "us";
88 arg_ainfo.longname = "user account status";
89 arg_ainfo.multiplechar = true;
90 arg_ainfo.defaultstatus = cgiarginfo::weak;
91 arg_ainfo.argdefault = "invalid";
92 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
93 argsinfo.addarginfo (NULL, arg_ainfo);
94
95 // "ug"
96 arg_ainfo.shortname = "ug";
97 arg_ainfo.longname = "user groups"; // comma seperated list
98 arg_ainfo.multiplechar = true;
99 arg_ainfo.defaultstatus = cgiarginfo::weak;
100 arg_ainfo.argdefault = "";
101 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
102 argsinfo.addarginfo (NULL, arg_ainfo);
103
104 // "un"
105 arg_ainfo.shortname = "un";
106 arg_ainfo.longname = "user name";
107 arg_ainfo.multiplechar = true;
108 arg_ainfo.defaultstatus = cgiarginfo::weak;
109 arg_ainfo.argdefault = "";
110 arg_ainfo.savedarginfo = cgiarginfo::must;
111 argsinfo.addarginfo (NULL, arg_ainfo);
112
113 // "pw"
114 arg_ainfo.shortname = "pw";
115 arg_ainfo.longname = "password";
116 arg_ainfo.multiplechar = true;
117 arg_ainfo.defaultstatus = cgiarginfo::weak;
118 arg_ainfo.argdefault = "";
119 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
120 argsinfo.addarginfo (NULL, arg_ainfo);
121
122 // "ky" - gives a specific user authentication for a
123 // limited amount of time
124 arg_ainfo.shortname = "ky";
125 arg_ainfo.longname = "user time key";
126 arg_ainfo.multiplechar = true;
127 arg_ainfo.defaultstatus = cgiarginfo::weak;
128 arg_ainfo.argdefault = "";
129 arg_ainfo.savedarginfo = cgiarginfo::must;
130 argsinfo.addarginfo (NULL, arg_ainfo);
131
132 // "ua" - ""=no, "1"=yes
133 arg_ainfo.shortname = "ua";
134 arg_ainfo.longname = "whether a user has been authenticated";
135 arg_ainfo.multiplechar = true;
136 arg_ainfo.defaultstatus = cgiarginfo::weak;
137 arg_ainfo.argdefault = "";
138 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
139 argsinfo.addarginfo (NULL, arg_ainfo);
140
141 // "er" - compressed arguments for the referer page
142 arg_ainfo.shortname = "er";
143 arg_ainfo.longname = "the compressed args of the refer page";
144 arg_ainfo.multiplechar = true;
145 arg_ainfo.defaultstatus = cgiarginfo::weak;
146 arg_ainfo.argdefault = "";
147 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
148 argsinfo.addarginfo (NULL, arg_ainfo);
149
150 // "uan" - whether user authentication is needed
151 arg_ainfo.shortname = "uan";
152 arg_ainfo.longname = "whether user authentication is needed";
153 arg_ainfo.multiplechar = true;
154 arg_ainfo.defaultstatus = cgiarginfo::weak;
155 arg_ainfo.argdefault = "";
156 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
157 argsinfo.addarginfo (NULL, arg_ainfo);
158}
159
160void authenaction::configure (const text_t &key, const text_tarray &cfgline) {
161 // get the password filename
162 if (cfgline.size() == 1) {
163 if (key == "usersfile") usersfile = cfgline[0];
164 else if (key == "keyfile") keyfile = cfgline[0];
165 else if (key == "keydecay") keydecay = cfgline[0].getint();
166 else if (key == "gsdlhome") {
167 if (usersfile.empty())
168 usersfile = filename_cat (cfgline[0], "etc", "users.db");
169 if (keyfile.empty())
170 keyfile = filename_cat (cfgline[0], "etc", "key.db");
171 }
172 }
173
174 action::configure (key, cfgline);
175}
176
177bool authenaction::init (ostream &logout) {
178 return action::init (logout);
179}
180
181bool authenaction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &/*args*/,
182 ostream &/*logout*/) {
183 return true;
184}
185
186// returns false if there is a major problem with the cgi arguments -- not
187// if authentication fails. If the authentication fails "un" will be empty
188bool authenaction::check_external_cgiargs (cgiargsinfoclass &argsinfo,
189 cgiargsclass &args,
190 outconvertclass &outconvert,
191 const text_t &saveconf,
192 ostream &logout) {
193 // failure means we have to redirect to this action to get authentication
194 // (if we are not already doing this)
195
196 userinfo_t thisuser;
197
198 text_t &args_uan = args["uan"]; text_t &args_un = args["un"];
199 text_t &args_pw = args["pw"]; text_t &args_us = args["us"];
200 text_t &args_ug = args["ug"]; text_t &args_ky = args["ky"];
201 text_t &args_ua = args["ua"]; text_t &args_a = args["a"];
202
203 // we must have a username and a password or a key to
204 // do any authentication
205 args_ua.clear(); // default = false;
206 if (args_un.empty() || args_pw.empty()) args_us = "invalid";
207 else args_us = "failed";
208
209 // make sure we have a username
210 if (!args_un.empty() && get_user_info (usersfile, args_un, thisuser)) {
211 if (!args_pw.empty()) {
212 // we are authenticating using a password
213 if (check_passwd (thisuser, args_pw)) args_ua = "1"; // succeeded
214
215 } else if (!args_ky.empty()) {
216 // we are authenticating using a key
217 if (check_key (keyfile, thisuser, args_ky, args_ug, keydecay)) args_ua = "1";
218 else args_us = "stalekey";
219 }
220 }
221
222 args_pw.clear(); // password goes no further
223 if (!args_ua.empty()) {
224 if (thisuser.enabled) {
225 bool haspermission = true;
226 // check to make sure the user is in the required group
227 if (!args_ug.empty()) {
228 haspermission = false;
229 text_t::const_iterator group_here = thisuser.groups.begin();
230 text_t::const_iterator group_end = thisuser.groups.end();
231 text_t thisgroup;
232 while (group_here != group_end) {
233 group_here = getdelimitstr (group_here, group_end, ',', thisgroup);
234 if (thisgroup == args_ug) {
235 haspermission = true;
236 break;
237 }
238 }
239 }
240
241 if (haspermission) {
242 // succeeded, get info about this user
243 // note: we don't need to set "ug" as it is already set to what it needs to be
244 args_us = "enabled";
245 args_ky = generate_key (keyfile, args_un); // new key
246
247 // delete old keys around every 50 accesses
248 if (rand()%50 == 1) remove_old_keys (keyfile, keydecay);
249
250 } else {
251 // succeeded, however, the user is not in the correct group
252 args_ua.clear();
253 args_us = "permissiondenied";
254 args_ky.clear();
255 }
256
257 } else {
258 // succeeded, however, the account is disabled
259 args_ua.clear();
260 args_us = "disabled";
261 args_ky.clear();
262 }
263
264 } else {
265 // failure, reset info about the user
266 args_ky.clear();
267 }
268
269 // we will have to redirect the user if authentication is needed,
270 // it failed, and we weren't on our way to be authenticated anyway
271 if ((!args_uan.empty()) && (args_ua.empty()) && (args_a != "a")) {
272 // need to save the current arguments in "er"
273 text_t &arg_er = args["er"];
274 if (!compress_save_args(argsinfo, saveconf, args, arg_er, outconvert, logout))
275 arg_er.clear();
276
277 // redirect to this action
278 args_a = "a";
279 }
280
281 return true;
282}
283
284void authenaction::get_cgihead_info (cgiargsclass &/*args*/, response_t &response,
285 text_t &response_data, ostream &/*logout*/) {
286 response = content;
287 response_data = "text/html";
288}
289
290void authenaction::define_internal_macros (const ColInfoResponse_t &/*collectinfo*/, displayclass &disp,
291 cgiargsclass &args, recptproto * /*collectproto*/,
292 ostream &/*logout*/) {
293 // sets _authen:messageextra_ based on the value of args["us"]
294 // _authen:hiddenargs_ to contain all the arguments that were
295 // explicitly set
296 disp.setmacro ("messagestatus", "authen", ("_authen:message" + args["us"]
297 + "_"));
298 // change style of header and footer if page is a frame
299 if (args["sp"] != "frameset") {
300 disp.setmacro ("header", "authen", "_status:infoheader_(Log in)");
301 disp.setmacro ("header", "authenok", "_status:infoheader_(Log in)");
302 disp.setmacro ("footer", "authen", "_status:infofooter_(Log in)");
303 disp.setmacro ("footer", "authenok", "_status:infofooter_(Log in)");
304 }
305 else {
306 // disp.setmacro ("header", "authen", "_Global:header_"); //****
307 // disp.setmacro ("header", "authenok", "_Global:header_");
308 // disp.setmacro ("footer", "authen", "_Global:footer_");
309 // disp.setmacro ("footer", "authenok", "_Global:footer_");
310 disp.setmacro ("header", "authen", "_:header_");
311 disp.setmacro ("header", "authenok", "_:header_");
312 disp.setmacro ("footer", "authen", "_:footer_");
313 disp.setmacro ("footer", "authenok", "_:footer_");
314 }
315
316
317 // get a list of saved configuration arguments (if possible)
318 text_t saveconf;
319 text_tset saveconfset;
320 if (recpt != NULL) {
321 saveconf = recpt->get_configinfo().saveconf;
322 splitchar (saveconf.begin(), saveconf.end(), '-', saveconfset);
323 }
324
325 text_t hiddenargs;
326 cgiargsclass::const_iterator args_here = args.begin();
327 cgiargsclass::const_iterator args_end = args.end();
328 while (args_here != args_end) {
329 // set this as a hidden argument if it came from the cgi arguments,
330 // its not the compressed arguments, the query string, a user name or
331 // password, and if it is not in the compressed arguments
332 if ((*args_here).second.source == cgiarg_t::cgi_arg &&
333 (*args_here).first != "e" && (*args_here).first != "q" &&
334 (*args_here).first != "un" && (*args_here).first != "pw" &&
335 saveconfset.find((*args_here).first) == saveconfset.end()) {
336 hiddenargs += "<input type=hidden name=\"" + (*args_here).first +
337 "\" value=\"_cgiarg" + (*args_here).first + "_\">\n";
338 }
339
340 args_here++;
341 }
342
343 disp.setmacro ("hiddenargs", "authen", hiddenargs);
344}
345
346void authenaction::define_external_macros (const ColInfoResponse_t &/*collectinfo*/, displayclass &/*disp*/,
347 cgiargsclass &/*args*/, recptproto * /*collectproto*/,
348 ostream &/*logout*/) {
349}
350
351bool authenaction::do_action (cgiargsclass &args, const ColInfoResponse_t &/*collectinfo*/,
352 recptproto * /*collectproto*/, displayclass &disp,
353 outconvertclass &outconvert, ostream &textout,
354 ostream &/*logout*/) {
355 if (args["us"] == "enabled") {
356 // have been authenticated
357 textout << outconvert << disp
358 << "_authenok:header_\n_authenok:content_\n_authenok:footer_\n";
359 return true;
360 }
361
362 // need to be authenticated
363 textout << outconvert << disp
364 << "_authen:header_\n_authen:content_\n_authen:footer_\n";
365
366 return true;
367}
Note: See TracBrowser for help on using the repository browser.