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

Last change on this file since 379 was 374, checked in by rjmcnab, 25 years ago

Put users in their own gdbm database. Moved a lot of functionality to usersdb

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1/**********************************************************************
2 *
3 * authenaction.cpp -- authenticating users
4 * Copyright (C) 1999 DigiLib Systems Limited, New Zealand
5 *
6 * PUT COPYRIGHT NOTICE HERE
7 *
8 * $Id: authenaction.cpp 374 1999-07-13 23:23:26Z rjmcnab $
9 *
10 *********************************************************************/
11
12/*
13 $Log$
14 Revision 1.3 1999/07/13 23:23:26 rjmcnab
15 Put users in their own gdbm database. Moved a lot of functionality to usersdb
16
17 Revision 1.2 1999/07/11 10:47:32 rjmcnab
18 Got something basic working.
19
20 Revision 1.1 1999/07/10 22:19:29 rjmcnab
21 Initial revision.
22
23
24 */
25
26
27#include "authenaction.h"
28#include "fileutil.h"
29#include "cfgread.h"
30#include "cgiutils.h"
31#include "infodbclass.h"
32#include "gsdltimes.h"
33#include "userdb.h"
34
35
36///////////////
37// authenaction
38///////////////
39
40authenaction::authenaction () {
41 keydecay = 600; // 10 minutes
42 recpt = NULL;
43
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;
68 arg_ainfo.argdefault = "";
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;
77 arg_ainfo.argdefault = "";
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;
86 arg_ainfo.argdefault = "";
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;
96 arg_ainfo.argdefault = "";
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;
105 arg_ainfo.argdefault = "";
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;
114 arg_ainfo.argdefault = "";
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;
123 arg_ainfo.argdefault = "";
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 // get the password filename
130 if (cfgline.size() == 1) {
131 if (key == "usersfile") usersfile = cfgline[0];
132 else if (key == "keyfile") keyfile = cfgline[0];
133 else if (key == "keydecay") keydecay = cfgline[0].getint();
134 else if (key == "gsdlhome") {
135 if (usersfile.empty())
136 usersfile = filename_cat (cfgline[0], "etc", "users.db");
137 if (keyfile.empty())
138 keyfile = filename_cat (cfgline[0], "etc", "key.db");
139 }
140 }
141
142 action::configure (key, cfgline);
143}
144
145bool authenaction::init (ostream &logout) {
146 return action::init (logout);
147}
148
149bool authenaction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &/*args*/,
150 ostream &/*logout*/) {
151 return true;
152}
153
154// returns false if there is a major problem with the cgi arguments -- not
155// if authentication fails. If the authentication fails "un" will be empty
156bool authenaction::check_external_cgiargs (cgiargsinfoclass &argsinfo,
157 cgiargsclass &args,
158 outconvertclass &outconvert,
159 const text_t &saveconf,
160 ostream &logout) {
161 // failure means we have to redirect to this action to get authentication
162 // (if we are not already doing this)
163
164 userinfo_t thisuser;
165
166 text_t &args_uan = args["uan"]; text_t &args_un = args["un"];
167 text_t &args_pw = args["pw"]; text_t &args_us = args["us"];
168 text_t &args_ug = args["ug"]; text_t &args_ky = args["ky"];
169 text_t &args_ua = args["ua"];
170
171 // we must have a username and a password or a key to
172 // do any authentication
173 args_ua.clear(); // default = false;
174 if (args_un.empty() || args_pw.empty()) args_us = "invalid";
175 else args_us = "failed";
176
177 // make sure we have a username
178 if (!args_un.empty() && get_user_info (usersfile, args_un, thisuser)) {
179 if (!args_pw.empty()) {
180 // we are authenticating using a password
181 if (check_passwd (thisuser, args_pw)) args_ua = "1"; // succeeded
182
183 } else if (!args_ky.empty()) {
184 // we are authenticating using a key
185 if (check_key (keyfile, thisuser, args_ky, args_ug, keydecay)) args_ua = "1";
186 else args_us = "stalekey";
187 }
188 }
189
190 args_pw.clear(); // password goes no further
191 if (!args_ua.empty()) {
192 if (thisuser.enabled) {
193 bool haspermission = true;
194 // check to make sure the user is in the required group
195 if (!args_ug.empty()) {
196 haspermission = false;
197 text_t::const_iterator group_here = thisuser.groups.begin();
198 text_t::const_iterator group_end = thisuser.groups.end();
199 text_t thisgroup;
200 while (group_here != group_end) {
201 group_here = getdelimitstr (group_here, group_end, ',', thisgroup);
202 if (thisgroup == args_ug) {
203 haspermission = true;
204 break;
205 }
206 }
207 }
208
209 if (haspermission) {
210 // succeeded, get info about this user
211 // note: we don't need to set "ug" as it is already set to what it needs to be
212 args_us = "enabled";
213 args_ky = generate_key (keyfile, args_un); // new key
214
215 // delete old keys around every 50 accesses
216 if (rand()%50 == 1) remove_old_keys (keyfile, keydecay);
217
218 } else {
219 // succeeded, however, the user is not in the correct group
220 args_ua.clear();
221 args_us = "permissiondenied";
222 args_ug.clear();
223 args_ky.clear();
224 }
225
226 } else {
227 // succeeded, however, the account is disabled
228 args_ua.clear();
229 args_us = "disabled";
230 args_ug.clear();
231 args_ky.clear();
232 }
233
234 } else {
235 // failure, reset info about the user
236 args_ug.clear();
237 args_ky.clear();
238 }
239
240 // we will have to redirect the user if authentication is needed,
241 // it failed, and we weren't on our way to be authenticated anyway
242 if (!args_uan.empty() && args_ua.empty() && args["a"] != "a") {
243 // need to save the current arguments in "er"
244 text_t &arg_er = args["er"];
245 if (!compress_save_args(argsinfo, saveconf, args, arg_er, outconvert, logout))
246 arg_er.clear();
247
248 // redirect to this action
249 args["a"] = "a";
250 }
251
252 return true;
253}
254
255void authenaction::get_cgihead_info (cgiargsclass &/*args*/, response_t &response,
256 text_t &response_data, ostream &/*logout*/) {
257 response = content;
258 response_data = "text/html";
259}
260
261void authenaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
262 recptproto */*collectproto*/, ostream &/*logout*/) {
263 // sets _authen:messageextra_ based on the value of args["us"]
264 // _authen:hiddenargs_ to contain all the arguments that were
265 // explicitly set
266 disp.setmacro ("messagestatus", "authen", ("_authen:message" + args["us"]
267 + "_"));
268
269 // get a list of saved configuration arguments (if possible)
270 text_t saveconf;
271 text_tset saveconfset;
272 if (recpt != NULL) {
273 saveconf = recpt->get_configinfo().saveconf;
274 splitchar (saveconf.begin(), saveconf.end(), '-', saveconfset);
275 }
276
277 text_t hiddenargs;
278 cgiargsclass::const_iterator args_here = args.begin();
279 cgiargsclass::const_iterator args_end = args.end();
280 while (args_here != args_end) {
281 // set this as a hidden argument if it came from the cgi arguments,
282 // its not the compressed arguments, the query string, a user name or
283 // password, and if it is not in the compressed arguments
284 if ((*args_here).second.source == cgiarg_t::cgi_arg &&
285 (*args_here).first != "e" && (*args_here).first != "q" &&
286 (*args_here).first != "un" && (*args_here).first != "pw" &&
287 saveconfset.find((*args_here).first) == saveconfset.end()) {
288 hiddenargs += "<input type=hidden name=\"" + (*args_here).first +
289 "\" value=\"_cgiarg" + (*args_here).first + "_\">\n";
290 }
291
292 args_here++;
293 }
294
295 disp.setmacro ("hiddenargs", "authen", hiddenargs);
296}
297
298void authenaction::define_external_macros (displayclass &/*disp*/, cgiargsclass &/*args*/,
299 recptproto */*collectproto*/, ostream &/*logout*/) {
300}
301
302bool authenaction::do_action (cgiargsclass &args, recptproto */*collectproto*/,
303 displayclass &disp, outconvertclass &outconvert,
304 ostream &textout, ostream &/*logout*/) {
305 if (args["us"] == "enabled") {
306 // have been authenticated
307 textout << outconvert << disp
308 << "_authenok:header_\n_authenok:content_\n_authenok:footer_\n";
309 return true;
310 }
311
312 // need to be authenticated
313 textout << outconvert << disp
314 << "_authen:header_\n_authen:content_\n_authen:footer_\n";
315
316 return true;
317}
Note: See TracBrowser for help on using the repository browser.