source: main/trunk/greenstone2/runtime-src/src/recpt/usersaction.cpp@ 28913

Last change on this file since 28913 was 28913, checked in by ak19, 10 years ago

6th commit for security of cgiargs. Looked over all occurrences of setmacro in *action.cpp files

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 14.6 KB
Line 
1/**********************************************************************
2 *
3 * usersaction.cpp -- managing 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 "gsdl_modules_cfg.h"
27#ifdef GSDL_USE_USERS_ACTION
28
29#include "usersaction.h"
30#include "fileutil.h"
31
32
33///////////////
34// usersaction
35///////////////
36
37usersaction::usersaction () {
38 // this action uses cgi variable "a"
39 cgiarginfo arg_ainfo;
40 arg_ainfo.shortname = "a";
41 arg_ainfo.longname = "action";
42 arg_ainfo.multiplechar = true;
43 arg_ainfo.multiplevalue = false;
44 arg_ainfo.defaultstatus = cgiarginfo::weak;
45 arg_ainfo.argdefault = "um"; // user management
46 arg_ainfo.savedarginfo = cgiarginfo::must;
47 argsinfo.addarginfo (NULL, arg_ainfo);
48
49 // "uma"
50 arg_ainfo.shortname = "uma";
51 arg_ainfo.longname = "user management action";
52 arg_ainfo.multiplechar = true;
53 arg_ainfo.multiplevalue = false;
54 arg_ainfo.defaultstatus = cgiarginfo::weak;
55 arg_ainfo.argdefault = "listusers";
56 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
57 argsinfo.addarginfo (NULL, arg_ainfo);
58
59 // "umun"
60 arg_ainfo.shortname = "umun";
61 arg_ainfo.longname = "user management user name";
62 arg_ainfo.multiplechar = true;
63 arg_ainfo.multiplevalue = false;
64 arg_ainfo.defaultstatus = cgiarginfo::weak;
65 arg_ainfo.argdefault = g_EmptyText;
66 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
67 argsinfo.addarginfo (NULL, arg_ainfo);
68
69 // "umpw"
70 arg_ainfo.shortname = "umpw";
71 arg_ainfo.longname = "user management password";
72 arg_ainfo.multiplechar = true;
73 arg_ainfo.multiplevalue = false;
74 arg_ainfo.defaultstatus = cgiarginfo::weak;
75 arg_ainfo.argdefault = g_EmptyText;
76 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
77 argsinfo.addarginfo (NULL, arg_ainfo);
78
79 // "umnpw1"
80 arg_ainfo.shortname = "umnpw1";
81 arg_ainfo.longname = "user management new password 1";
82 arg_ainfo.multiplechar = true;
83 arg_ainfo.multiplevalue = false;
84 arg_ainfo.defaultstatus = cgiarginfo::weak;
85 arg_ainfo.argdefault = g_EmptyText;
86 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
87 argsinfo.addarginfo (NULL, arg_ainfo);
88
89 // "umnpw2"
90 arg_ainfo.shortname = "umnpw2";
91 arg_ainfo.longname = "user management new password 2";
92 arg_ainfo.multiplechar = true;
93 arg_ainfo.multiplevalue = false;
94 arg_ainfo.defaultstatus = cgiarginfo::weak;
95 arg_ainfo.argdefault = g_EmptyText;
96 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
97 argsinfo.addarginfo (NULL, arg_ainfo);
98
99 // "umus"
100 arg_ainfo.shortname = "umus";
101 arg_ainfo.longname = "user management account status";
102 arg_ainfo.multiplechar = true;
103 arg_ainfo.multiplevalue = false;
104 arg_ainfo.defaultstatus = cgiarginfo::weak;
105 arg_ainfo.argdefault = g_EmptyText;
106 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
107 argsinfo.addarginfo (NULL, arg_ainfo);
108
109 // "umug"
110 arg_ainfo.shortname = "umug";
111 arg_ainfo.longname = "user management groups"; // comma seperated list
112 arg_ainfo.multiplechar = true;
113 arg_ainfo.multiplevalue = false;
114 arg_ainfo.defaultstatus = cgiarginfo::weak;
115 arg_ainfo.argdefault = g_EmptyText;
116 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
117 argsinfo.addarginfo (NULL, arg_ainfo);
118
119 // "umc"
120 arg_ainfo.shortname = "umc";
121 arg_ainfo.longname = "user management comment";
122 arg_ainfo.multiplechar = true;
123 arg_ainfo.multiplevalue = false;
124 arg_ainfo.defaultstatus = cgiarginfo::weak;
125 arg_ainfo.argdefault = g_EmptyText;
126 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
127 argsinfo.addarginfo (NULL, arg_ainfo);
128
129 // "bcp"
130 arg_ainfo.shortname = "bcp";
131 arg_ainfo.longname = "change password submit button";
132 arg_ainfo.multiplechar = true;
133 arg_ainfo.multiplevalue = false;
134 arg_ainfo.defaultstatus = cgiarginfo::weak;
135 arg_ainfo.argdefault = g_EmptyText;
136 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
137 argsinfo.addarginfo (NULL, arg_ainfo);
138
139 // "beu"
140 arg_ainfo.shortname = "beu";
141 arg_ainfo.longname = "edit user submit button";
142 arg_ainfo.multiplechar = true;
143 arg_ainfo.multiplevalue = false;
144 arg_ainfo.defaultstatus = cgiarginfo::weak;
145 arg_ainfo.argdefault = g_EmptyText;
146 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
147 argsinfo.addarginfo (NULL, arg_ainfo);
148
149 // "cm"
150 arg_ainfo.shortname = "cm";
151 arg_ainfo.longname = "confirm an action";
152 arg_ainfo.multiplechar = true;
153 arg_ainfo.multiplevalue = false;
154 arg_ainfo.defaultstatus = cgiarginfo::weak;
155 arg_ainfo.argdefault = g_EmptyText;
156 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
157 argsinfo.addarginfo (NULL, arg_ainfo);
158}
159
160void usersaction::configure (const text_t &key, const text_tarray &cfgline) {
161 action::configure (key, cfgline);
162}
163
164bool usersaction::init (ostream &logout) {
165
166 if (dbhome.empty()) {
167 logout << "ERROR (usersaction::init) dbhome is not set\n";
168 return false;
169 }
170
171 return action::init (logout);
172}
173
174bool usersaction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &args,
175 recptprotolistclass * /*protos*/, ostream &/*logout*/) {
176 args["uan"] = "1"; // user authentication is needed
177
178 if (args["uma"] == "changepasswd") {
179 // no particular group is needed to change a password
180 args["ug"].clear();
181 } else {
182 // administrator is needed for all other management tasks
183 args["ug"] = "administrator";
184 }
185
186 return true;
187}
188
189void usersaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
190 response_t &response, text_t &response_data,
191 ostream &/*logout*/) {
192 response = content;
193 response_data = "text/html";
194}
195
196bool usersaction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/,
197 browsermapclass * /*browsers*/, displayclass &disp,
198 outconvertclass &outconvert, ostream &textout,
199 ostream &logout) {
200
201 if (args["uma"] == "adduser" || args["uma"] == "edituser") {
202 // adduser is handled by edituser
203 return do_edituser (args, disp, outconvert, textout, logout);
204
205 } else if (args["uma"] == "deleteuser") {
206 return do_deleteuser (args, disp, outconvert, textout, logout);
207
208 } else if (args["uma"] == "changepasswd") {
209 return do_changepasswd (args, disp, outconvert, textout, logout);
210 }
211
212 // default
213 return do_listusers (args, disp, outconvert, textout, logout);
214}
215
216bool usersaction::do_listusers (cgiargsclass &/*args*/, displayclass &disp,
217 outconvertclass &outconvert, ostream &textout,
218 ostream &/*logout*/) {
219
220 textout << outconvert << disp
221 << "_userslistusers:header_\n_userslistusers:contentstart_\n";
222
223 text_tarray userlist;
224 // get user list
225 user_database->get_user_list (userlist);
226
227 // sort the list
228 sort(userlist.begin(), userlist.end());
229
230 // output the information for each user
231 userinfo_t userinfo;
232 text_tarray::iterator users_here = userlist.begin();
233 text_tarray::iterator users_end = userlist.end();
234 while (users_here != users_end) {
235 if (user_database->get_user_info(*users_here, userinfo) == ERRNO_SUCCEED) {
236 textout << outconvert << disp
237 << "<tr><td bgcolor=\"\\#eeeeee\">" << encodeForHTML(userinfo.username) << "</td>\n"
238 << "<td bgcolor=\"\\#eeeeee\">" << (char *) (userinfo.enabled ? "enabled" : "disabled") << "</td>\n"
239 << "<td bgcolor=\"\\#eeeeee\">" << encodeForHTML(userinfo.groups) << "&nbsp;</td>\n"
240 << "<td bgcolor=\"\\#eeeeee\">" << encodeForHTML(userinfo.comment) << "&nbsp;</td>\n"
241 << "<td><a href=\"_httpcurrentdocument_&a=um&uma=edituser&umun="
242 << encodeForHTML(userinfo.username) << "\">_userslistusers:textedituser_</a> "
243 << "<a href=\"_httpcurrentdocument_&a=um&uma=deleteuser&umun="
244 << encodeForHTML(userinfo.username) << "\">_userslistusers:textdeleteuser_</a>"
245 << "</td></tr>\n\n";
246
247 } else {
248 textout << outconvert << disp
249 << "<tr><td bgcolor=\"\\#eeeeee\">" << *users_here << "</td>\n"
250 << "<td bgcolor=\"\\#eeeeee\">&nbsp;</td>\n"
251 << "<td bgcolor=\"\\#eeeeee\">&nbsp;</td>\n"
252 << "<td bgcolor=\"\\#eeeeee\">&nbsp;</td>\n"
253 << "<td>&nbsp;</td></tr>\n\n";
254 }
255
256 ++users_here;
257 }
258
259 textout << outconvert << disp
260 << "_userslistusers:contentend_\n_userslistusers:footer_\n";
261 return true;
262}
263
264void usersaction::define_user_macros (cgiargsclass &args, displayclass &disp) {
265 disp.setmacro ("usersargun", "users", args["umun"]);
266 disp.setmacro ("usersargpw", "users", args["umpw"]);
267 disp.setmacro ("usersargus", "users", args["umus"]);
268 disp.setmacro ("usersargug", "users", args["umug"]);
269 disp.setmacro ("usersargc", "users", args["umc"]);
270
271 disp.setmacro ("usersargunAttrsafe", "users", encodeForHTMLAttr(args["umun"]));
272 disp.setmacro ("usersargpwAttrsafe", "users", encodeForHTMLAttr(args["umpw"]));
273 disp.setmacro ("usersargusAttrsafe", "users", encodeForHTMLAttr(args["umus"])); // unused in users.dm or other macro files, but setting this attrsafe'd macro in parallel with the other usersarg* values here.
274 disp.setmacro ("usersargugAttrsafe", "users", encodeForHTMLAttr(args["umug"]));
275 disp.setmacro ("usersargcAttrsafe", "users", encodeForHTMLAttr(args["umc"]));
276
277}
278
279
280bool usersaction::do_edituser (cgiargsclass &args, displayclass &disp,
281 outconvertclass &outconvert, ostream &textout,
282 ostream &logout) {
283
284 userinfo_t userinfo;
285 text_t messagestatus;
286 bool noproblems = true;
287
288 // fill in defaults from user database (if appropriate)
289 if (args["umun"].empty()) {
290 noproblems = false;
291
292 } else if (!userdbclass::username_ok (args["umun"])) {
293 // problem with username
294 noproblems = false;
295 messagestatus += "_users:messageinvalidusername_";
296
297 } else if (user_database->get_user_info (args["umun"], userinfo) == ERRNO_SUCCEED) {
298 if (args["uma"] == "adduser") {
299 // must not add a user that has the same name as another user
300 noproblems = false;
301 messagestatus += "_users:messageuserexists_";
302
303 } else {
304 // only fill in the data if there is no user status defined
305 if (args["umus"].empty()) {
306 args["umus"] = userinfo.enabled ? "enabled" : "disabled";
307 if (args["umug"].empty()) args["umug"] = userinfo.groups;
308 if (args["umc"].empty()) args["umc"] = userinfo.comment;
309 }
310 }
311 }
312
313 // fill in the user status default
314 if (args["umus"].empty()) {
315 noproblems = false;
316 args["umus"] = "enabled";
317 }
318
319 // make sure the password is ok
320 if (args["umpw"].empty()) {
321 // password must not be empty if none were supplied from database
322 // and we have had no other problems
323 if (userinfo.password.empty() && noproblems) {
324 noproblems = false;
325 messagestatus += "_users:messageemptypassword_";
326 }
327
328 } else if (!userdbclass::password_ok(args["umpw"])) {
329 noproblems = false;
330 messagestatus += "_users:messageinvalidpassword_";
331 }
332
333 // set this info if no problems have been encounted
334 // and the submit button was pressed
335 if (noproblems && !args["beu"].empty()) {
336 userinfo.username = args["umun"];
337 if (!args["umpw"].empty()) {
338 // only set the password if it is not empty
339 userinfo.password = userdbclass::crypt_text(args["umpw"]);
340 }
341 userinfo.enabled = (args["umus"] == "enabled");
342 userinfo.groups = userdbclass::format_user_groups(args["umug"]);
343 userinfo.comment = args["umc"];
344
345 user_database->set_user_info (args["umun"], userinfo);
346
347 // show list of users
348 return do_listusers (args, disp, outconvert, textout, logout);
349 }
350
351 // define the macros for the user
352 define_user_macros (args, disp);
353 disp.setmacro ("messagestatus", "users", messagestatus);
354
355 textout << outconvert << disp
356 << "_usersedituser:header_\n_usersedituser:content_\n_usersedituser:footer_\n";
357
358 return true;
359}
360
361bool usersaction::do_deleteuser (cgiargsclass &args, displayclass &disp,
362 outconvertclass &outconvert, ostream &textout,
363 ostream &logout) {
364 if (!args["cm"].empty()) {
365 if (args["cm"] == "yes" && !args["umun"].empty()) {
366 // user confirmed the deletion of the user
367 user_database->delete_user(args["umun"]);
368 }
369
370 // redirect the user back to the listusers page
371 return do_listusers (args, disp, outconvert, textout, logout);
372 }
373
374 define_user_macros (args, disp);
375 textout << outconvert << disp
376 << "_usersdeleteuser:header_\n_usersdeleteuser:content_\n_usersdeleteuser:footer_\n";
377
378 return true;
379}
380
381bool usersaction::do_changepasswd (cgiargsclass &args, displayclass &disp,
382 outconvertclass &outconvert, ostream &textout,
383 ostream &/*logout*/) {
384 text_t messagestatus;
385
386 if (!args["bcp"].empty()) {
387 if (args["un"].empty()) {
388 messagestatus = "_users:messageusernameempty_";
389 } else if (args["umpw"].empty()) {
390 messagestatus = "_users:messagepasswordempty_";
391 } else if (args["umnpw1"].empty()) {
392 messagestatus = "_users:messagenewpass1empty_";
393 } else if (args["umnpw2"].empty()) {
394 messagestatus = "_users:messagenewpass2empty_";
395 } else if (args["umnpw1"] != args["umnpw2"]) {
396 messagestatus = "_users:messagenewpassmismatch_";
397 } else if (!userdbclass::password_ok(args["umnpw1"])) {
398 messagestatus = "_users:messageinvalidpassword_";
399 } else {
400 userinfo_t userinfo;
401 if (user_database->get_user_info (args["un"], userinfo) == ERRNO_SUCCEED) {
402 // check old password
403 if (userinfo.password != userdbclass::crypt_text(args["umpw"])) {
404 messagestatus = "_users:messagefailed_";
405
406 } else {
407 userinfo.password = userdbclass::crypt_text(args["umnpw1"]);
408 if (user_database->set_user_info (args["un"], userinfo) == ERRNO_SUCCEED) {
409 // everything is ok
410 textout << outconvert << disp
411 << "_userschangepasswdok:header_\n"
412 "_userschangepasswdok:content_\n"
413 "_userschangepasswdok:footer_\n";
414 return true;
415 }
416 }
417 }
418 }
419 }
420
421 disp.setmacro ("messagestatus", "users", messagestatus);
422
423 textout << outconvert << disp
424 << "_userschangepasswd:header_\n"
425 "_userschangepasswd:content_\n"
426 "_userschangepasswd:footer_\n";
427
428 return true;
429}
430
431#endif //GSDL_USE_USERS_ACTION
Note: See TracBrowser for help on using the repository browser.