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

Last change on this file since 1796 was 1796, checked in by sjboddie, 23 years ago

Removed the "cp" and "sp" cgi arguments and used the "p" argument instead
(i.e. the "p" argument is now used in the page, status and collector
actions). I'd like to do this type of thing in lots of places where
different actions are using different cgi arguments to perform very
similar tasks. Fewer arguments are becoming more of a priority with our
ever expanding URLs, I'll leave it for a while though and make sure this
change doesn't cause any problems.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 10.9 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
161 // no need to go further unless authentication is
162 // required by this page
163 if (args["uan"].empty()) return true;
164
165
166 // failure means we have to redirect to this action to get authentication
167 // (if we are not already doing this)
168
169 userinfo_t thisuser;
170
171 text_t &args_uan = args["uan"]; text_t &args_un = args["un"];
172 text_t &args_pw = args["pw"]; text_t &args_us = args["us"];
173 text_t &args_ug = args["ug"]; text_t &args_ky = args["ky"];
174 text_t &args_ua = args["ua"]; text_t &args_a = args["a"];
175
176 // we must have a username and a password or a key to
177 // do any authentication
178 args_ua.clear(); // default = false;
179 if (args_un.empty() || args_pw.empty()) args_us = "invalid";
180 else args_us = "failed";
181
182 // make sure we have a username
183 if (!args_un.empty() && get_user_info (usersfile, args_un, thisuser)) {
184 if (!args_pw.empty()) {
185 // we are authenticating using a password
186 if (check_passwd (thisuser, args_pw)) args_ua = "1"; // succeeded
187
188 } else if (!args_ky.empty()) {
189 // we are authenticating using a key
190 if (check_key (keyfile, thisuser, args_ky, args_ug, keydecay)) args_ua = "1";
191 else args_us = "stalekey";
192 }
193 }
194
195 args_pw.clear(); // password goes no further
196 if (!args_ua.empty()) {
197 if (thisuser.enabled) {
198 bool haspermission = true;
199 // check to make sure the user is in the required group
200 if (!args_ug.empty()) {
201 haspermission = false;
202 text_t::const_iterator group_here = thisuser.groups.begin();
203 text_t::const_iterator group_end = thisuser.groups.end();
204 text_t thisgroup;
205 while (group_here != group_end) {
206 group_here = getdelimitstr (group_here, group_end, ',', thisgroup);
207 if (thisgroup == args_ug) {
208 haspermission = true;
209 break;
210 }
211 }
212 }
213
214 if (haspermission) {
215 // succeeded, get info about this user
216 // note: we don't need to set "ug" as it is already set to what it needs to be
217 args_us = "enabled";
218 args_ky = generate_key (keyfile, args_un); // new key
219
220 // delete old keys around every 50 accesses
221 if (rand()%50 == 1) remove_old_keys (keyfile, keydecay);
222
223 } else {
224 // succeeded, however, the user is not in the correct group
225 args_ua.clear();
226 args_us = "permissiondenied";
227 args_ky.clear();
228 }
229
230 } else {
231 // succeeded, however, the account is disabled
232 args_ua.clear();
233 args_us = "disabled";
234 args_ky.clear();
235 }
236
237 } else {
238 // failure, reset info about the user
239 args_ky.clear();
240 }
241
242 // we will have to redirect the user if authentication is needed,
243 // it failed, and we weren't on our way to be authenticated anyway
244 if ((!args_uan.empty()) && (args_ua.empty()) && (args_a != "a")) {
245 // need to save the current arguments in "er"
246 text_t &arg_er = args["er"];
247 if (!compress_save_args(argsinfo, saveconf, args, arg_er, outconvert, logout))
248 arg_er.clear();
249
250 // needs to be decoded for use within forms
251 decode_cgi_arg (arg_er);
252
253 // redirect to this action
254 args_a = "a";
255 }
256
257 return true;
258}
259
260void authenaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
261 response_t &response, text_t &response_data,
262 ostream &/*logout*/) {
263 response = content;
264 response_data = "text/html";
265}
266
267void authenaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
268 recptprotolistclass * /*protos*/, ostream &/*logout*/) {
269 // sets _authen:messageextra_ based on the value of args["us"]
270 // _authen:hiddenargs_ to contain all the arguments that were
271 // explicitly set
272 disp.setmacro ("messagestatus", "authen", ("_authen:message" + args["us"]
273 + "_"));
274 // change style of header and footer if page is a frame
275 if ((args["p"].empty()) || (args["p"] == "frameset")) {
276 disp.setmacro ("header", "authen", "_status:infoheader_(Log in)");
277 disp.setmacro ("header", "authenok", "_status:infoheader_(Log in)");
278 disp.setmacro ("footer", "authen", "_status:infofooter_(Log in)");
279 disp.setmacro ("footer", "authenok", "_status:infofooter_(Log in)");
280 }
281
282 // get a list of saved configuration arguments (if possible)
283 text_t saveconf;
284 text_tset saveconfset;
285 if (recpt != NULL) {
286 saveconf = recpt->get_configinfo().saveconf;
287 splitchar (saveconf.begin(), saveconf.end(), '-', saveconfset);
288 }
289
290 text_t hiddenargs;
291 cgiargsclass::const_iterator args_here = args.begin();
292 cgiargsclass::const_iterator args_end = args.end();
293 while (args_here != args_end) {
294 // set this as a hidden argument if it came from the cgi arguments,
295 // its not the compressed arguments, the query string, a user name or
296 // password, and if it is not in the compressed arguments
297 if ((*args_here).second.source == cgiarg_t::cgi_arg &&
298 (*args_here).first != "e" && (*args_here).first != "q" &&
299 (*args_here).first != "un" && (*args_here).first != "pw" &&
300 saveconfset.find((*args_here).first) == saveconfset.end()) {
301 hiddenargs += "<input type=hidden name=\"" + (*args_here).first +
302 "\" value=\"_cgiarg" + (*args_here).first + "_\">\n";
303 }
304
305 args_here++;
306 }
307
308 disp.setmacro ("hiddenargs", "authen", hiddenargs);
309}
310
311bool authenaction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/,
312 browsermapclass * /*browsers*/, displayclass &disp,
313 outconvertclass &outconvert, ostream &textout,
314 ostream &/*logout*/) {
315 if (args["us"] == "enabled") {
316 // have been authenticated
317 textout << outconvert << disp
318 << "_authenok:header_\n_authenok:content_\n_authenok:footer_\n";
319 return true;
320 }
321
322 // need to be authenticated
323 textout << outconvert << disp
324 << "_authen:header_\n_authen:content_\n_authen:footer_\n";
325
326 return true;
327}
Note: See TracBrowser for help on using the repository browser.