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

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

changed default timeout on authentication from 10 minutes to 30 minutes
and stopped treating the admin users any differently (i.e. admin
authentication also lasts 30 minutes (was 5 mins.))

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