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

Last change on this file since 546 was 543, checked in by rjmcnab, 25 years ago

removed some compiler warnings

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