source: branches/New_Config_Format-branch/gsdl/src/recpt/authenaction.cpp@ 1279

Last change on this file since 1279 was 1279, checked in by sjboddie, 24 years ago

merged changes to trunk into New_Config_Format branch

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