source: gsdl/trunk/runtime-src/src/recpt/authenaction.cpp@ 20798

Last change on this file since 20798 was 20798, checked in by ak19, 15 years ago

Cosmetic adjustments to the code (use of curly brackets on single-line if and else statements).

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 11.7 KB
RevLine 
[363]1/**********************************************************************
2 *
3 * authenaction.cpp -- authenticating users
4 * Copyright (C) 1999 DigiLib Systems Limited, New Zealand
5 *
[533]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.
[363]9 *
[533]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 *
[363]24 *********************************************************************/
25
[7371]26#include "gsdl_modules_cfg.h"
27#ifdef GSDL_USE_AUTHEN_ACTION
28
[363]29#include "authenaction.h"
30#include "fileutil.h"
31#include "cfgread.h"
32#include "cgiutils.h"
[369]33#include "gsdltimes.h"
[363]34
35
36///////////////
37// authenaction
38///////////////
39
40authenaction::authenaction () {
[1402]41 keydecay = 1800; // 30 minutes
[369]42 recpt = NULL;
43
[363]44 // this action uses cgi variable "a"
45 cgiarginfo arg_ainfo;
46 arg_ainfo.shortname = "a";
47 arg_ainfo.longname = "action";
48 arg_ainfo.multiplechar = true;
49 arg_ainfo.defaultstatus = cgiarginfo::weak;
50 arg_ainfo.argdefault = "a";
51 arg_ainfo.savedarginfo = cgiarginfo::must;
52 argsinfo.addarginfo (NULL, arg_ainfo);
53
54 // "us"
55 arg_ainfo.shortname = "us";
56 arg_ainfo.longname = "user account status";
57 arg_ainfo.multiplechar = true;
58 arg_ainfo.defaultstatus = cgiarginfo::weak;
59 arg_ainfo.argdefault = "invalid";
60 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
61 argsinfo.addarginfo (NULL, arg_ainfo);
62
63 // "ug"
64 arg_ainfo.shortname = "ug";
65 arg_ainfo.longname = "user groups"; // comma seperated list
66 arg_ainfo.multiplechar = true;
67 arg_ainfo.defaultstatus = cgiarginfo::weak;
[7425]68 arg_ainfo.argdefault = g_EmptyText;
[363]69 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
70 argsinfo.addarginfo (NULL, arg_ainfo);
71
72 // "un"
73 arg_ainfo.shortname = "un";
74 arg_ainfo.longname = "user name";
75 arg_ainfo.multiplechar = true;
76 arg_ainfo.defaultstatus = cgiarginfo::weak;
[7425]77 arg_ainfo.argdefault = g_EmptyText;
[363]78 arg_ainfo.savedarginfo = cgiarginfo::must;
79 argsinfo.addarginfo (NULL, arg_ainfo);
80
81 // "pw"
82 arg_ainfo.shortname = "pw";
83 arg_ainfo.longname = "password";
84 arg_ainfo.multiplechar = true;
85 arg_ainfo.defaultstatus = cgiarginfo::weak;
[7425]86 arg_ainfo.argdefault = g_EmptyText;
[363]87 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
88 argsinfo.addarginfo (NULL, arg_ainfo);
89
90 // "ky" - gives a specific user authentication for a
91 // limited amount of time
92 arg_ainfo.shortname = "ky";
93 arg_ainfo.longname = "user time key";
94 arg_ainfo.multiplechar = true;
95 arg_ainfo.defaultstatus = cgiarginfo::weak;
[7425]96 arg_ainfo.argdefault = g_EmptyText;
[363]97 arg_ainfo.savedarginfo = cgiarginfo::must;
98 argsinfo.addarginfo (NULL, arg_ainfo);
99
100 // "ua" - ""=no, "1"=yes
101 arg_ainfo.shortname = "ua";
102 arg_ainfo.longname = "whether a user has been authenticated";
103 arg_ainfo.multiplechar = true;
104 arg_ainfo.defaultstatus = cgiarginfo::weak;
[7425]105 arg_ainfo.argdefault = g_EmptyText;
[363]106 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
107 argsinfo.addarginfo (NULL, arg_ainfo);
108
109 // "er" - compressed arguments for the referer page
110 arg_ainfo.shortname = "er";
111 arg_ainfo.longname = "the compressed args of the refer page";
112 arg_ainfo.multiplechar = true;
113 arg_ainfo.defaultstatus = cgiarginfo::weak;
[7425]114 arg_ainfo.argdefault = g_EmptyText;
[363]115 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
116 argsinfo.addarginfo (NULL, arg_ainfo);
117
118 // "uan" - whether user authentication is needed
119 arg_ainfo.shortname = "uan";
120 arg_ainfo.longname = "whether user authentication is needed";
121 arg_ainfo.multiplechar = true;
122 arg_ainfo.defaultstatus = cgiarginfo::weak;
[7425]123 arg_ainfo.argdefault = g_EmptyText;
[363]124 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
125 argsinfo.addarginfo (NULL, arg_ainfo);
126}
127
128void authenaction::configure (const text_t &key, const text_tarray &cfgline) {
129 action::configure (key, cfgline);
130}
131
132bool authenaction::init (ostream &logout) {
[15589]133 if (dbhome.empty()) {
134 logout << "ERROR (authenaction::init) dbhome is not set\n";
[2212]135 return false;
136 }
137
[363]138 return action::init (logout);
139}
140
141bool authenaction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &/*args*/,
[3546]142 recptprotolistclass * /*protos*/, ostream &/*logout*/) {
[363]143 return true;
144}
145
146// returns false if there is a major problem with the cgi arguments -- not
147// if authentication fails. If the authentication fails "un" will be empty
148bool authenaction::check_external_cgiargs (cgiargsinfoclass &argsinfo,
149 cgiargsclass &args,
150 outconvertclass &outconvert,
[7432]151 const text_t &saveconf,
[363]152 ostream &logout) {
[1505]153
154 // no need to go further unless authentication is
155 // required by this page
[20798]156 if (args["uan"].empty()) {
157 return true;
158 }
[1505]159
[363]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
[374]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"];
[507]168 text_t &args_ua = args["ua"]; text_t &args_a = args["a"];
[374]169
170 // we must have a username and a password or a key to
171 // do any authentication
[363]172 args_ua.clear(); // default = false;
[20798]173 if (args_un.empty() || args_pw.empty()) {
174 args_us = "invalid";
175 }
176 else {
177 args_us = "failed";
178 }
[363]179
[14269]180 // make sure we have a username
181 int status = user_database->get_user_info (args_un, thisuser);
182 if (!args_un.empty() && (status == ERRNO_SUCCEED)) {
[363]183 if (!args_pw.empty()) {
184 // we are authenticating using a password
[20798]185 if (user_database->check_passwd (thisuser.username, args_pw) == ERRNO_SUCCEED) {
186 args_ua = "1"; // succeeded
187 }
[363]188
189 } else if (!args_ky.empty()) {
190 // we are authenticating using a key
[20798]191 if (key_database->check_key(thisuser, args_ky, args_ug, keydecay)) {
192 args_ua = "1";
193 }
194 else {
195 args_us = "stalekey";
196 }
[363]197 }
198 }
199
200 args_pw.clear(); // password goes no further
201 if (!args_ua.empty()) {
[374]202 if (thisuser.enabled) {
203 bool haspermission = true;
[4974]204
[369]205 // check to make sure the user is in the required group
[4974]206 // one group is available only at the moment.
207 // this is what we are changing !
208
[369]209 if (!args_ug.empty()) {
[4974]210
[20798]211 // Since we receive a comma separated list
[4974]212 // of groups like mygroup,yourgroup,ourgroup
213 // we want to split them into individual groups
214 // and examine them. This is what is done here.
215
216 text_tset splitgrps;
217 text_t::const_iterator split_here = args_ug.begin();
218 text_t::const_iterator split_end = args_ug.end();
219
220 splitchar(split_here,split_end,',',splitgrps);
221
222 haspermission = false;
223
224 // This examines the current user to be authenticated and
225 // tries to see if he or she is in the group that we have in
226 // thisuser structure. We compare args_ua contents with that
227 // of the user database.
228
229 text_t::const_iterator group_here = thisuser.groups.begin();
230 text_t::const_iterator group_end = thisuser.groups.end();
231 text_t thisgroup;
[369]232 while (group_here != group_end) {
[4974]233 group_here = getdelimitstr (group_here, group_end, ',', thisgroup);
234 if (splitgrps.find(thisgroup) != splitgrps.end() )
235 {
236 haspermission = true;
237 break;
238 }
[369]239 }
240 }
[4974]241
[374]242 if (haspermission) {
[4974]243 // succeeded, get info about this user
244 // note: we don't need to set "ug" as it is already set to what it needs to be
245 args_us = "enabled";
[13844]246 args_ky = key_database->generate_key(args_un); // new key
[4974]247
[374]248 // delete old keys around every 50 accesses
[13844]249 if (rand()%50 == 1) key_database->remove_old_keys(keydecay);
[369]250
251 } else {
252 // succeeded, however, the user is not in the correct group
[4974]253 args_ua.clear();
254 args_us = "permissiondenied";
255 args_ky.clear();
[369]256 }
[4974]257
[363]258 } else {
[4974]259 // succeeded, however, the account is disabled
[363]260 args_ua.clear();
261 args_us = "disabled";
262 args_ky.clear();
263 }
264
265 } else {
266 // failure, reset info about the user
267 args_ky.clear();
268 }
269
270 // we will have to redirect the user if authentication is needed,
271 // it failed, and we weren't on our way to be authenticated anyway
[507]272 if ((!args_uan.empty()) && (args_ua.empty()) && (args_a != "a")) {
[363]273 // need to save the current arguments in "er"
274 text_t &arg_er = args["er"];
[20798]275 if (!compress_save_args(argsinfo, saveconf, args, arg_er, outconvert, logout)) {
[363]276 arg_er.clear();
[20798]277 }
[363]278
[1432]279 // needs to be decoded for use within forms
280 decode_cgi_arg (arg_er);
281
[363]282 // redirect to this action
[507]283 args_a = "a";
[363]284 }
[14014]285
[363]286 return true;
287}
288
[755]289void authenaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
290 response_t &response, text_t &response_data,
291 ostream &/*logout*/) {
[363]292 response = content;
293 response_data = "text/html";
294}
295
[755]296void authenaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
297 recptprotolistclass * /*protos*/, ostream &/*logout*/) {
[363]298 // sets _authen:messageextra_ based on the value of args["us"]
[369]299 // _authen:hiddenargs_ to contain all the arguments that were
300 // explicitly set
[363]301 disp.setmacro ("messagestatus", "authen", ("_authen:message" + args["us"]
[369]302 + "_"));
[722]303 // change style of header and footer if page is a frame
[1796]304 if ((args["p"].empty()) || (args["p"] == "frameset")) {
[722]305 disp.setmacro ("header", "authen", "_status:infoheader_(Log in)");
306 disp.setmacro ("header", "authenok", "_status:infoheader_(Log in)");
307 disp.setmacro ("footer", "authen", "_status:infofooter_(Log in)");
308 disp.setmacro ("footer", "authenok", "_status:infofooter_(Log in)");
309 }
[369]310
311 // get a list of saved configuration arguments (if possible)
[7432]312 text_t saveconf;
[369]313 text_tset saveconfset;
314 if (recpt != NULL) {
[7432]315 saveconf = recpt->get_configinfo().saveconf;
316 splitchar (saveconf.begin(), saveconf.end(), '-', saveconfset);
[369]317 }
318
319 text_t hiddenargs;
320 cgiargsclass::const_iterator args_here = args.begin();
321 cgiargsclass::const_iterator args_end = args.end();
322 while (args_here != args_end) {
323 // set this as a hidden argument if it came from the cgi arguments,
324 // its not the compressed arguments, the query string, a user name or
[3423]325 // password, or collect.cfg, and if it is not in the compressed arguments
[369]326 if ((*args_here).second.source == cgiarg_t::cgi_arg &&
327 (*args_here).first != "e" && (*args_here).first != "q" &&
328 (*args_here).first != "un" && (*args_here).first != "pw" &&
[3423]329 (*args_here).first != "cfgfile" &&
[369]330 saveconfset.find((*args_here).first) == saveconfset.end()) {
331 hiddenargs += "<input type=hidden name=\"" + (*args_here).first +
332 "\" value=\"_cgiarg" + (*args_here).first + "_\">\n";
333 }
[9620]334 ++args_here;
[369]335 }
336
337 disp.setmacro ("hiddenargs", "authen", hiddenargs);
[363]338}
339
[755]340bool authenaction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/,
341 browsermapclass * /*browsers*/, displayclass &disp,
[421]342 outconvertclass &outconvert, ostream &textout,
343 ostream &/*logout*/) {
[363]344 if (args["us"] == "enabled") {
345 // have been authenticated
346 textout << outconvert << disp
347 << "_authenok:header_\n_authenok:content_\n_authenok:footer_\n";
348 return true;
349 }
[755]350
[363]351 // need to be authenticated
352 textout << outconvert << disp
353 << "_authen:header_\n_authen:content_\n_authen:footer_\n";
354
355 return true;
356}
[7371]357
358#endif //GSDL_USE_AUTHEN_ACTION
Note: See TracBrowser for help on using the repository browser.