Changeset 374 for trunk/gsdl/src/recpt/authenaction.cpp
- Timestamp:
- 1999-07-14T11:23:26+12:00 (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gsdl/src/recpt/authenaction.cpp
r369 r374 12 12 /* 13 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 14 17 Revision 1.2 1999/07/11 10:47:32 rjmcnab 15 18 Got something basic working. … … 28 31 #include "infodbclass.h" 29 32 #include "gsdltimes.h" 30 31 32 ///////////////////////// 33 // a few useful functions 34 ///////////////////////// 35 36 37 // reads in the password file. It returns true if successful 38 // format is: username password status [groups] 39 static bool read_passwd (const text_t &passwd_filename, userinfo_tmap &userinfo) { 40 text_tarray passwdline; 41 userinfo_t thisuserinfo; 42 43 userinfo.erase(userinfo.begin(), userinfo.end()); 44 45 char *cstr = passwd_filename.getcstr(); 46 ifstream passwdin (cstr); 47 delete cstr; 48 49 if (passwdin) { 50 while (read_cfg_line(passwdin, passwdline) >= 0) { 51 if (passwdline.size () >= 3) { 52 // get the information about the user 53 thisuserinfo.clear(); 54 thisuserinfo.username = passwdline[0]; 55 thisuserinfo.password = passwdline[1]; 56 if (passwdline[2] == "enabled") thisuserinfo.status = userinfo_t::enabled; 57 else thisuserinfo.status = userinfo_t::disabled; 58 if (passwdline.size() >= 4) thisuserinfo.groups = passwdline[3]; 59 60 // insert the user information into the map 61 if (!thisuserinfo.username.empty()) { 62 userinfo[thisuserinfo.username] = thisuserinfo; 63 } 64 } 65 } 66 67 passwdin.close (); 68 return true; 69 } 70 71 return false; 72 } 73 74 // returns true if the user was found, false otherwise 75 static bool get_user_info (const userinfo_tmap &userinfo, const text_t &username, 76 userinfo_t &thisuser) { 77 thisuser.clear(); 78 79 userinfo_tmap::const_iterator thisuser_here = userinfo.find (username); 80 if (thisuser_here != userinfo.end()) { 81 thisuser = (*thisuser_here).second; 82 return true; 83 } 84 85 return false; 86 } 87 88 // return true if the password matches, false if it doesn't 89 static bool check_passwd (const userinfo_t &thisuser, const text_t &password) { 90 if (!thisuser.username.empty() && !thisuser.password.empty() && 91 !password.empty() && thisuser.password == password) return true; 92 93 return false; 94 } 95 96 // returns true if the key is still valid for this user, 97 // and false otherwise 98 static bool check_key (const text_t &keyfile, const userinfo_t &thisuser, 99 const text_t &key, const text_t &group, int keydecay, 100 ostream &logout) { 101 outconvertclass text_t2ascii; 102 103 if (keyfile.empty() || thisuser.username.empty() || 104 key.empty()) return false; 105 106 // the keydecay is set to 1/2 minute for things requiring the 107 // administrator 108 if (group == "administrator") keydecay = 30; 109 110 // open the key database 111 gdbmclass keydb; 112 if (!keydb.opendatabase (keyfile, GDBM_WRCREAT, 1000)) { 113 logout << text_t2ascii << "Error: write open failed for key database \"" 114 << keyfile << "\"\n"; 115 return false; // failed 116 } 117 118 // success if there is a key in the key database that is owned by this 119 // user whose creation time is less that keydecay 120 infodbclass info; 121 bool success = false; 122 if (keydb.getinfo (key, info)) { 123 if (info["user"] == thisuser.username) { 124 time_t keycreation = text2time (info["time"]); 125 if (keycreation == (time_t)-1) { 126 logout << text_t2ascii << "Error: failed to convert an authentication " 127 "key into its equivalent time_t. Time text was \"" << info["time"] 128 << "\" for key \"" << key << "\"\n"; 129 130 } else if (difftime (time(NULL), keycreation) <= keydecay) { 131 // succeeded, update the key's time 132 success = true; 133 info["time"] = time2text(time(NULL)); 134 if (!keydb.setinfo (key, info)) { 135 logout << text_t2ascii << "Error: setinfo failed for key database \"" 136 << keyfile << "\"\n"; 137 } 138 } 139 } 140 } 141 142 // close the database 143 keydb.closedatabase(); 144 145 return success; 146 } 147 148 149 static text_t generate_key (const text_t &keyfile, const text_t &username, 150 ostream &logout) { 151 static const char *numconvert = "0123456789abcdefghijklmnopqrstuvwxyz" 152 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 153 outconvertclass text_t2ascii; 154 155 // open the key database 156 gdbmclass keydb; 157 if (!keydb.opendatabase (keyfile, GDBM_WRCREAT, 1000)) { 158 logout << text_t2ascii << "Error: write open failed for key database \"" 159 << keyfile << "\"\n"; 160 return ""; // failed 161 } 162 163 // loop looking for a suitable new key 164 text_t userkey; 165 do { 166 int userkey_int = rand (); 167 while (userkey_int > 0) { 168 userkey.push_back (numconvert[userkey_int%62]); 169 userkey_int /= 62; 170 } 171 172 // make sure this key is not in the database 173 if (keydb.exists (userkey)) userkey.clear(); 174 } while (userkey.empty()); 175 176 // enter the key into the database 177 infodbclass keydata; 178 keydata["user"] = username; 179 keydata["time"] = time2text(time(NULL)); 180 181 if (!keydb.setinfo (userkey, keydata)) { 182 logout << text_t2ascii << "Error: setinfo failed for key database \"" 183 << keyfile << "\"\n"; 184 userkey.clear(); // failed 185 } 186 187 // close the database 188 keydb.closedatabase(); 189 190 return userkey; 191 } 192 193 194 ///////////// 195 // userinfo_t 196 ///////////// 197 198 199 void userinfo_t::clear () { 200 username.clear(); 201 password.clear(); 202 status = invalid; 203 groups.clear(); 204 } 205 33 #include "userdb.h" 206 34 207 35 … … 301 129 // get the password filename 302 130 if (cfgline.size() == 1) { 303 if (key == " passwdfile") passwdfile = cfgline[0];131 if (key == "usersfile") usersfile = cfgline[0]; 304 132 else if (key == "keyfile") keyfile = cfgline[0]; 305 133 else if (key == "keydecay") keydecay = cfgline[0].getint(); 306 134 else if (key == "gsdlhome") { 307 if ( passwdfile.empty())308 passwdfile = filename_cat (cfgline[0], "etc", "passwd");135 if (usersfile.empty()) 136 usersfile = filename_cat (cfgline[0], "etc", "users.db"); 309 137 if (keyfile.empty()) 310 138 keyfile = filename_cat (cfgline[0], "etc", "key.db"); … … 316 144 317 145 bool authenaction::init (ostream &logout) { 318 outconvertclass text_t2ascii;319 320 // read in the password file321 if (!read_passwd (passwdfile, userinfo)) {322 logout << text_t2ascii << "Error: could not read in the password file "323 << passwdfile << "\n";324 return false;325 }326 327 146 return action::init (logout); 328 147 } … … 340 159 const text_t &saveconf, 341 160 ostream &logout) { 342 // success will be dealt with using a redirect in get_cgihead_info if neede343 161 // failure means we have to redirect to this action to get authentication 344 162 // (if we are not already doing this) … … 346 164 userinfo_t thisuser; 347 165 348 text_t &args_uan = args["uan"]; 349 text_t &args_un = args["un"]; 350 text_t &args_pw = args["pw"]; 351 text_t &args_us = args["us"]; 352 text_t &args_ug = args["ug"]; 353 text_t &args_ky = args["ky"]; 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"]; 354 169 text_t &args_ua = args["ua"]; 355 170 171 // we must have a username and a password or a key to 172 // do any authentication 356 173 args_ua.clear(); // default = false; 357 174 if (args_un.empty() || args_pw.empty()) args_us = "invalid"; … … 359 176 360 177 // make sure we have a username 361 if (!args_un.empty() && get_user_info (user info, args_un, thisuser)) {178 if (!args_un.empty() && get_user_info (usersfile, args_un, thisuser)) { 362 179 if (!args_pw.empty()) { 363 180 // we are authenticating using a password 364 if (check_passwd (thisuser, args_pw)) { 365 args_ua = "1"; // succeeded 366 } 181 if (check_passwd (thisuser, args_pw)) args_ua = "1"; // succeeded 367 182 368 183 } else if (!args_ky.empty()) { 369 184 // we are authenticating using a key 370 if (check_key (keyfile, thisuser, args_ky, args_ug, keydecay, logout)) 371 args_ua = "1"; 185 if (check_key (keyfile, thisuser, args_ky, args_ug, keydecay)) args_ua = "1"; 372 186 else args_us = "stalekey"; 373 187 } … … 375 189 376 190 args_pw.clear(); // password goes no further 377 378 191 if (!args_ua.empty()) { 379 if (thisuser.status==userinfo_t::enabled) { 192 if (thisuser.enabled) { 193 bool haspermission = true; 380 194 // check to make sure the user is in the required group 381 195 if (!args_ug.empty()) { 382 thisuser.status = userinfo_t::permissiondenied;196 haspermission = false; 383 197 text_t::const_iterator group_here = thisuser.groups.begin(); 384 198 text_t::const_iterator group_end = thisuser.groups.end(); … … 387 201 group_here = getdelimitstr (group_here, group_end, ',', thisgroup); 388 202 if (thisgroup == args_ug) { 389 thisuser.status = userinfo_t::enabled;203 haspermission = true; 390 204 break; 391 205 } … … 393 207 } 394 208 395 if ( thisuser.status==userinfo_t::enabled) {209 if (haspermission) { 396 210 // succeeded, get info about this user 397 // note: we don't need to set "ug" as it is already set to 398 // what it needs to be 211 // note: we don't need to set "ug" as it is already set to what it needs to be 399 212 args_us = "enabled"; 400 args_ky = generate_key (keyfile, args_un, logout); // new key 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); 401 217 402 218 } else { … … 406 222 args_ug.clear(); 407 223 args_ky.clear(); 408 409 224 } 225 410 226 } else { 411 227 // succeeded, however, the account is disabled
Note:
See TracChangeset
for help on using the changeset viewer.