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

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

added GPL notice

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