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

Last change on this file since 755 was 755, checked in by sjboddie, 25 years ago

changed arguments passed to many functions

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