Changeset 13844
- Timestamp:
- 2007-02-01T16:30:11+13:00 (17 years ago)
- Location:
- trunk/gsdl/src/recpt
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gsdl/src/recpt/authenaction.cpp
r9620 r13844 169 169 if (args["uan"].empty()) return true; 170 170 171 userdbclass *user_database = new userdbclass(usersfile); 172 keydbclass *key_database = new keydbclass(keyfile); 171 173 172 174 // failure means we have to redirect to this action to get authentication … … 187 189 188 190 // make sure we have a username 189 if (!args_un.empty() && get_user_info (usersfile, args_un, thisuser)) {191 if (!args_un.empty() && (user_database->get_user_info (args_un, thisuser) == ERRNO_SUCCEED)) { 190 192 if (!args_pw.empty()) { 191 193 // we are authenticating using a password 192 if ( check_passwd (thisuser, args_pw)) args_ua = "1"; // succeeded194 if (user_database->check_passwd (thisuser.username, args_pw) == ERRNO_SUCCEED) args_ua = "1"; // succeeded 193 195 194 196 } else if (!args_ky.empty()) { 195 197 // we are authenticating using a key 196 if ( check_key (keyfile,thisuser, args_ky, args_ug, keydecay)) args_ua = "1";198 if (key_database->check_key(thisuser, args_ky, args_ug, keydecay)) args_ua = "1"; 197 199 else args_us = "stalekey"; 198 200 } … … 245 247 // note: we don't need to set "ug" as it is already set to what it needs to be 246 248 args_us = "enabled"; 247 args_ky = generate_key (keyfile,args_un); // new key249 args_ky = key_database->generate_key(args_un); // new key 248 250 249 251 // delete old keys around every 50 accesses 250 if (rand()%50 == 1) remove_old_keys (keyfile,keydecay);252 if (rand()%50 == 1) key_database->remove_old_keys(keydecay); 251 253 252 254 } else { -
trunk/gsdl/src/recpt/userdb.cpp
r9620 r13844 41 41 #endif 42 42 43 44 // few useful functions 45 46 text_t crypt_text (const text_t &text) { 47 static const char *salt = "Tp"; 48 text_t crypt_password; 49 50 if (text.empty()) return g_EmptyText; 51 52 // encrypt the password 53 char *text_cstr = text.getcstr(); 54 if (text_cstr == NULL) return g_EmptyText; 55 crypt_password = crypt(text_cstr, salt); 56 delete []text_cstr; 57 58 return crypt_password; 59 } 60 61 62 // username_ok tests to make sure a username is ok. a username 63 // must be at least 2 characters long, but no longer than 30 64 // characters long. it can contain the characters a-z A-Z 0-9 65 // . and _ 66 bool username_ok (const text_t &username) { 67 if (username.size() < 2 || username.size() > 30) return false; 68 69 text_t::const_iterator here = username.begin(); 70 text_t::const_iterator end = username.end(); 71 while (here != end) { 72 if ((*here >= 'a' && *here <= 'z') || 73 (*here >= 'A' && *here <= 'Z') || 74 (*here >= '0' && *here <= '9') || 75 *here == '.' || 76 *here == '_') { 77 // ok 78 } else return false; 79 ++here; 80 } 81 82 return true; 83 } 84 85 // password_ok tests to make sure a password is ok. a password 86 // must be at least 3 characters long but no longer than 8 characters 87 // long. it can contain any character in the range 0x20-0x7e 88 bool password_ok (const text_t &password) { 89 if (password.size() < 3 || password.size() > 8) return false; 90 91 text_t::const_iterator here = password.begin(); 92 text_t::const_iterator end = password.end(); 93 while (here != end) { 94 if (*here >= 0x20 && *here <= 0x7e) { 95 // ok 96 } else return false; 97 ++here; 98 } 99 100 return true; 101 } 102 103 104 105 106 ///////////// 107 // userinfo_t 108 ///////////// 43 //==========================================// 44 // userinfo_t functions (Start) // 45 //==========================================// 46 userinfo_t::userinfo_t() 47 { 48 clear(); 49 } 50 51 userinfo_t::~userinfo_t(){}; 109 52 110 53 void userinfo_t::clear () { … … 125 68 return *this; 126 69 } 127 128 129 130 // functions dealing with user databases 131 132 // returns true on success (in which case userinfo will contain 133 // the information for this user) 134 bool get_user_info (gdbmclass &userdb, const text_t &username, 135 userinfo_t &userinfo) { 136 userinfo.clear(); 70 //==========================================// 71 // userinfo_t functions (END) // 72 //==========================================// 73 74 //==========================================// 75 // userdbclass functions (Start) // 76 //==========================================// 77 userdbclass::userdbclass(const text_t &userdbfilename) 78 { 79 activated = (!userdb.opendatabase(userdbfilename, GDBM_WRCREAT, 1000, true)) ? false : true; 80 external_db = false; 81 } 82 83 userdbclass::userdbclass(const gdbmclass &external_userdb) 84 { 85 userdb = external_userdb; 86 activated = true; 87 external_db = true; 88 } 89 90 userdbclass::~userdbclass() 91 { 92 if (external_db == false) { userdb.closedatabase();} 93 } 94 95 // few useful functions 96 text_t userdbclass::crypt_text (const text_t &text) 97 { 98 static const char *salt = "Tp"; 99 text_t crypt_password; 137 100 138 infodbclass info; 139 if (userdb.getinfo (username, info)) { 140 userinfo.username = info["username"]; 141 userinfo.password = info["password"]; 142 userinfo.enabled = (info["enabled"] == "true"); 143 userinfo.groups = info["groups"]; 144 userinfo.comment = info["comment"]; 145 return true; 101 if (text.empty()) return g_EmptyText; 102 103 // encrypt the password 104 char *text_cstr = text.getcstr(); 105 if (text_cstr == NULL) return g_EmptyText; 106 crypt_password = crypt(text_cstr, salt); 107 delete []text_cstr; 108 109 return crypt_password; 110 } 111 112 // username_ok tests to make sure a username is ok. a username 113 // must be at least 2 characters long, but no longer than 30 114 // characters long. it can contain the characters a-z A-Z 0-9 115 // . and _ 116 bool userdbclass::username_ok (const text_t &username) 117 { 118 if (username.size() < 2 || username.size() > 30) return false; 119 120 text_t::const_iterator here = username.begin(); 121 text_t::const_iterator end = username.end(); 122 while (here != end) 123 { 124 if ((*here >= 'a' && *here <= 'z') || 125 (*here >= 'A' && *here <= 'Z') || 126 (*here >= '0' && *here <= '9') || 127 *here == '.' || 128 *here == '_') 129 { 130 // ok 131 } else return false; 132 ++here; 133 } 134 135 return true; 136 } 137 138 // password_ok tests to make sure a password is ok. a password 139 // must be at least 3 characters long but no longer than 8 characters 140 // long. it can contain any character in the range 0x20-0x7e 141 bool userdbclass::password_ok (const text_t &password) 142 { 143 if (password.size() < 3 || password.size() > 8) return false; 144 145 text_t::const_iterator here = password.begin(); 146 text_t::const_iterator end = password.end(); 147 while (here != end) { 148 if (*here >= 0x20 && *here <= 0x7e) 149 { 150 // ok 151 } else return false; 152 ++here; 146 153 } 147 154 148 return false; 149 } 150 151 bool get_user_info (const text_t &userdbfile, const text_t &username, 152 userinfo_t &userinfo) { 153 gdbmclass userdb; 154 if (!userdb.opendatabase(userdbfile, GDBM_READER, 1000, true)) { 155 /* if (!userdbfile.empty() && !file_exists (userdbfile) && 156 username == "admin") {*/ 157 if (!userdbfile.empty() && username == "admin") { 158 // no database -- create a database with an initial account 159 userinfo.clear(); 160 userinfo.username = "admin"; 161 userinfo.password = crypt_text("admin"); 162 userinfo.enabled = true; 163 userinfo.groups = "administrator,colbuilder"; 164 userinfo.comment = "change the password for this account as soon as possible"; 165 return set_user_info (userdbfile, username, userinfo); 166 } 167 return false; 168 } 169 170 bool success = get_user_info (userdb, username, userinfo); 171 userdb.closedatabase(); 172 173 return success; 174 } 175 176 // returns true on success 177 bool set_user_info (gdbmclass &userdb, const text_t &username, 178 const userinfo_t &userinfo) { 179 infodbclass info; 180 info["username"] = userinfo.username; 181 info["password"] = userinfo.password; 182 info["enabled"] = userinfo.enabled ? "true" : "false"; 183 info["groups"] = userinfo.groups; 184 info["comment"] = userinfo.comment; 185 186 return userdb.setinfo (username, info); 187 } 188 189 bool set_user_info (const text_t &userdbfile, const text_t &username, 190 const userinfo_t &userinfo) { 191 gdbmclass userdb; 192 if (!userdb.opendatabase(userdbfile, GDBM_WRCREAT, 1000, true)) return false; 193 194 bool success = set_user_info (userdb, username, userinfo); 195 userdb.closedatabase(); 196 197 return success; 198 } 199 200 // removes a user from the user database -- forever 201 void delete_user (gdbmclass &userdb, const text_t &username) { 202 userdb.deletekey (username); 203 } 204 205 void delete_user (const text_t &userdbfile, const text_t &username) { 206 gdbmclass userdb; 207 if (!userdb.opendatabase(userdbfile, GDBM_WRCREAT, 1000, true)) return; 208 209 delete_user (userdb, username); 210 userdb.closedatabase(); 211 } 212 213 // gets a list of all the users in the database. returns true 214 // on success 215 void get_user_list (gdbmclass &userdb, text_tarray &userlist) { 216 userlist.erase (userlist.begin(), userlist.end()); 217 218 text_t user = userdb.getfirstkey (); 219 while (!user.empty()) { 220 userlist.push_back(user); 221 user = userdb.getnextkey (user); 222 } 223 } 224 225 // returns true if the user's password is correct. 226 bool check_passwd (const userinfo_t &thisuser, const text_t &password) { 227 // couple of basic checks 228 if (thisuser.username.empty() || thisuser.password.empty() || 229 password.empty()) return false; 230 231 text_t crypt_password = crypt_text(password); 232 return (thisuser.password == crypt_password); 155 return true; 233 156 } 234 157 235 158 // removes spaces from user groups 236 text_t format_user_groups(const text_t user_groups){237 159 text_t userdbclass::format_user_groups(const text_t user_groups) 160 { 238 161 text_t new_groups = g_EmptyText; 239 162 text_t::const_iterator here = user_groups.begin(); 240 163 text_t::const_iterator end = user_groups.end(); 241 164 while (here != end) { 242 if (*here != ' '&& *here != '\t' && *here != '\n') { 243 new_groups.push_back(*here); 244 } 165 if (*here != ' '&& *here != '\t' && *here != '\n') 166 { 167 new_groups.push_back(*here); 168 } 245 169 ++here; 246 170 } … … 248 172 } 249 173 250 // functions dealing with databases of temporary keys 251 174 // functions dealing with user databases 175 // returns true on success (in which case userinfo will contain 176 // the information for this user) 177 // @return 0 success 178 // @return -1 database is not currently connected 179 // @return -2 not defined username 180 int userdbclass::get_user_info (const text_t &username, userinfo_t &userinfo) 181 { 182 // Let's make sure the connection has been established. 183 if (activated == true) 184 { 185 userinfo.clear(); 186 infodbclass info; 187 // See if we can get the user's infomration 188 if (userdb.getinfo (username, info)) 189 { 190 userinfo.username = info["username"]; 191 userinfo.password = info["password"]; 192 userinfo.enabled = (info["enabled"] == "true"); 193 userinfo.groups = info["groups"]; 194 userinfo.comment = info["comment"]; 195 return ERRNO_SUCCEED; 196 } 197 // If we failed to retrieve the users information, we should check if the username is admin or not. 198 // If it is the admin user, let's create a new account for the admin user. 199 else if (username == "admin") 200 { 201 userinfo.clear(); 202 userinfo.username = "admin"; 203 userinfo.password = crypt_text("admin"); 204 userinfo.enabled = true; 205 userinfo.groups = "administrator,colbuilder"; 206 userinfo.comment = "change the password for this account as soon as possible"; 207 // Return the set result. 208 return set_user_info (username, userinfo); 209 } 210 // The username is not found, return false 211 return ERRNO_USERNOTFOUND; 212 } 213 // Failed to connect to the database, return false. 214 return ERRNO_CONNECTIONFAILED; 215 } 216 217 // returns true on success 218 int userdbclass::set_user_info (const text_t &username, const userinfo_t &userinfo) 219 { 220 // Let's make sure the connection has been established. 221 if (activated == true) 222 { 223 infodbclass info; 224 info["username"] = userinfo.username; 225 info["password"] = userinfo.password; 226 info["enabled"] = userinfo.enabled ? "true" : "false"; 227 info["groups"] = userinfo.groups; 228 info["comment"] = userinfo.comment; 229 230 return (userdb.setinfo (username, info)) ? ERRNO_SUCCEED : ERRNO_GDBMACTIONFILED ; 231 } 232 return ERRNO_CONNECTIONFAILED; 233 } 234 235 // returns true if the user's password is correct. 236 int userdbclass::check_passwd (const text_t &username, const text_t &password) 237 { 238 userinfo_t thisuser; 239 int returned = get_user_info(username, thisuser); 240 if(returned != ERRNO_SUCCEED) return returned; 241 // couple of basic checks 242 if (thisuser.username.empty() || thisuser.password.empty() || 243 password.empty()) return ERRNO_MISSINGPASSWORD; 244 245 text_t crypt_password = crypt_text(password); 246 return (thisuser.password == crypt_password) ? ERRNO_SUCCEED : ERRNO_PASSWORDMISMATCH; 247 } 248 249 int userdbclass::add_user (const userinfo_t &userinfo) 250 { 251 // Let's make sure the connection has been established. 252 if (activated == true) 253 { 254 infodbclass info; 255 if (userdb.getinfo (userinfo.username, info)) 256 { 257 // There is an existing username already 258 return ERRNO_EXISTINGUSERNAME; 259 } 260 else 261 { 262 return set_user_info(userinfo.username, userinfo); 263 } 264 } 265 return ERRNO_CONNECTIONFAILED; 266 } 267 268 int userdbclass::edit_user (const userinfo_t &userinfo) 269 { 270 // Let's make sure the connection has been established. 271 if (activated == true) 272 { 273 infodbclass info; 274 if (userdb.getinfo (userinfo.username, info)) 275 { 276 return set_user_info(userinfo.username, userinfo); 277 } 278 else 279 { 280 // The user does not exist in the database. 281 return ERRNO_USERNOTFOUND; 282 } 283 } 284 return ERRNO_CONNECTIONFAILED; 285 } 286 287 int userdbclass::delete_user (const text_t &username) 288 { 289 // Let's make sure the connection has been established. 290 if (activated == true) 291 { 292 userdb.deletekey (username); 293 return ERRNO_SUCCEED; 294 } 295 return ERRNO_CONNECTIONFAILED; 296 } 297 298 // gets all the users' information in the database. returns true 299 // on success 300 int userdbclass::get_all_users(userinfo_tarray &userinfo_array) 301 { 302 // Let's make sure the connection has been established. 303 if (activated == true) 304 { 305 userinfo_array.erase(userinfo_array.begin(), userinfo_array.end()); 306 text_t user = userdb.getfirstkey(); 307 while (!user.empty()) { 308 userinfo_t one_userinfo; 309 int returned = get_user_info(user, one_userinfo); 310 if (returned != ERRNO_SUCCEED) return returned; 311 userinfo_array.push_back(one_userinfo); 312 user = userdb.getnextkey(user); 313 } 314 return ERRNO_SUCCEED; 315 } 316 return ERRNO_CONNECTIONFAILED; 317 } 318 319 // gets a list of all the users in the database. returns true 320 // on success 321 int userdbclass::get_user_list (text_tarray &userlist) 322 { 323 // Let's make sure the connection has been established. 324 if (activated == true) 325 { 326 userlist.erase (userlist.begin(), userlist.end()); 327 328 text_t user = userdb.getfirstkey (); 329 while (!user.empty()) { 330 userlist.push_back(user); 331 user = userdb.getnextkey (user); 332 } 333 return ERRNO_SUCCEED; 334 } 335 return ERRNO_CONNECTIONFAILED; 336 } 337 //==========================================// 338 // userdbclass functions (End) // 339 //==========================================// 340 341 //==========================================// 342 // keydbclass functions (Start) // 343 //==========================================// 344 keydbclass::keydbclass(const text_t &keydbfilename) 345 { 346 activated = (!keydb.opendatabase(keydbfilename, GDBM_WRCREAT, 1000, true)) ? false : true; 347 external_db = false; 348 } 349 350 keydbclass::keydbclass(const gdbmclass &external_keydb) 351 { 352 keydb = external_keydb; 353 activated = true; 354 external_db = true; 355 } 356 357 keydbclass::~keydbclass() 358 { 359 if (external_db == false) { keydb.closedatabase();} 360 } 252 361 // generates a random key for the user, stores it in the database and 253 362 // returns it so that it can be used in page generation 254 363 // returns "" on failure 255 text_t generate_key (gdbmclass &keydb, const text_t &username) { 256 static const char *numconvert = "0123456789abcdefghijklmnopqrstuvwxyz" 257 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 258 259 // loop looking for a suitable new key 260 text_t userkey; 261 text_t crypt_userkey; 262 do { 263 // convert to base 62 :-) 264 int userkey_int = rand (); 265 while (userkey_int > 0) { 266 userkey.push_back (numconvert[userkey_int%62]); 267 userkey_int /= 62; 268 } 269 270 // make sure this key is not in the database 271 crypt_userkey = crypt_text(userkey); 272 if (keydb.exists (crypt_userkey)) userkey.clear(); 273 } while (userkey.empty()); 274 275 // enter the key into the database 276 infodbclass keydata; 277 keydata["user"] = username; 278 keydata["time"] = time2text(time(NULL)); 279 280 if (!keydb.setinfo (crypt_userkey, keydata)) { 281 userkey.clear(); // failed 282 } 283 284 return userkey; 285 } 286 287 text_t generate_key (const text_t &keydbfile, const text_t &username) { 288 gdbmclass keydb; 289 if (!keydb.opendatabase(keydbfile, GDBM_WRCREAT, 1000, true)) return g_EmptyText; 290 291 text_t key = generate_key (keydb, username); 292 keydb.closedatabase(); 293 294 return key; 295 } 296 364 text_t keydbclass::generate_key (const text_t &username) 365 { 366 // Let's make sure the connection has been established. 367 if (activated == true) 368 { 369 static const char *numconvert = "0123456789abcdefghijklmnopqrstuvwxyz" 370 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 371 372 // loop looking for a suitable new key 373 text_t userkey; 374 text_t crypt_userkey; 375 do { 376 // convert to base 62 :-) 377 int userkey_int = rand (); 378 while (userkey_int > 0) 379 { 380 userkey.push_back (numconvert[userkey_int%62]); 381 userkey_int /= 62; 382 } 383 384 // make sure this key is not in the database 385 crypt_userkey = userdbclass::crypt_text(userkey); 386 if (keydb.exists (crypt_userkey)) userkey.clear(); 387 } while (userkey.empty()); 388 389 // enter the key into the database 390 infodbclass keydata; 391 keydata["user"] = username; 392 keydata["time"] = time2text(time(NULL)); 393 394 if (!keydb.setinfo (crypt_userkey, keydata)) 395 { 396 userkey.clear(); // failed 397 } 398 399 return userkey; 400 } 401 return ""; 402 } 297 403 298 404 // checks to see if there is a key for this particular user in the 299 405 // database that hasn't decayed. a short decay is used when group 300 406 // is set to administrator 301 bool check_key (gdbmclass &keydb, const userinfo_t &thisuser, 302 const text_t &key, const text_t &group, int keydecay) { 303 if (thisuser.username.empty() || key.empty()) return false; 304 305 // the keydecay is set to 5 minute for things requiring the 306 // administrator 307 // if (group == "administrator") keydecay = 300; 308 309 // success if there is a key in the key database that is owned by this 310 // user whose creation time is less that keydecay 311 text_t crypt_key = crypt_text(key); 312 infodbclass info; 313 if (keydb.getinfo (crypt_key, info)) { 314 if (info["user"] == thisuser.username) { 315 time_t keycreation = text2time (info["time"]); 316 if (keycreation != (time_t)-1 && difftime (text2time(time2text(time(NULL))), 317 keycreation) <= keydecay) { 318 // succeeded, update the key's time 319 info["time"] = time2text(time(NULL)); 320 keydb.setinfo (crypt_key, info); 321 return true; 322 } 323 } 324 } 325 326 return false;; 327 } 328 329 bool check_key (const text_t &keydbfile, const userinfo_t &thisuser, 330 const text_t &key, const text_t &group, int keydecay) { 331 gdbmclass keydb; 332 if (!keydb.opendatabase(keydbfile, GDBM_WRCREAT, 1000, true)) return false; 333 334 bool success = check_key (keydb, thisuser, key, group, keydecay); 335 keydb.closedatabase(); 336 337 return success; 338 } 339 407 bool keydbclass::check_key (const userinfo_t &thisuser, const text_t &key, const text_t &group, int keydecay) 408 { 409 // Let's make sure the connection has been established. 410 if (activated == true) 411 { 412 if (thisuser.username.empty() || key.empty()) return false; 413 414 // the keydecay is set to 5 minute for things requiring the 415 // administrator 416 // if (group == "administrator") keydecay = 300; 417 418 // success if there is a key in the key database that is owned by this 419 // user whose creation time is less that keydecay 420 text_t crypt_key = userdbclass::crypt_text(key); 421 infodbclass info; 422 if (keydb.getinfo (crypt_key, info)) { 423 if (info["user"] == thisuser.username) { 424 time_t keycreation = text2time (info["time"]); 425 if (keycreation != (time_t)-1 && difftime (text2time(time2text(time(NULL))), 426 keycreation) <= keydecay) { 427 // succeeded, update the key's time 428 info["time"] = time2text(time(NULL)); 429 keydb.setinfo (crypt_key, info); 430 return true; 431 } 432 } 433 } 434 } 435 return false; 436 } 340 437 341 438 // remove_old_keys will remove all keys created more than keydecay ago. 342 439 // use sparingly, it can be quite an expensive function 343 void remove_old_keys (const text_t &keydbfile, int keydecay) { 344 // open the key database 345 gdbmclass keydb; 346 if (!keydb.opendatabase(keydbfile, GDBM_WRCREAT, 1000, true)) return; 347 348 // get a list of keys created more than keydecay seconds agon 349 text_tarray oldkeys; 350 text_t key = keydb.getfirstkey (); 351 infodbclass info; 352 time_t timenow = text2time(time2text(time(NULL))); 353 time_t keycreation = (time_t)-1; 354 while (!key.empty()) { 355 if (keydb.getinfo (key, info)) { 356 keycreation = text2time (info["time"]); 357 if (keycreation != (time_t)-1 && difftime (timenow, keycreation) > keydecay) { 358 // found an old key 359 oldkeys.push_back(key); 360 } 361 } 362 363 key = keydb.getnextkey (key); 364 } 365 366 // delete the keys 367 text_tarray::iterator keys_here = oldkeys.begin(); 368 text_tarray::iterator keys_end = oldkeys.end(); 369 while (keys_here != keys_end) { 370 keydb.deletekey(*keys_here); 371 ++keys_here; 372 } 373 374 // close the key database 375 keydb.closedatabase(); 376 } 440 void keydbclass::remove_old_keys (int keydecay) 441 { 442 // Let's make sure the connection has been established. 443 if (activated == true) 444 { 445 // get a list of keys created more than keydecay seconds agon 446 text_tarray oldkeys; 447 text_t key = keydb.getfirstkey (); 448 infodbclass info; 449 time_t timenow = text2time(time2text(time(NULL))); 450 time_t keycreation = (time_t)-1; 451 while (!key.empty()) { 452 if (keydb.getinfo (key, info)) { 453 keycreation = text2time (info["time"]); 454 if (keycreation != (time_t)-1 && difftime (timenow, keycreation) > keydecay) { 455 // found an old key 456 oldkeys.push_back(key); 457 } 458 } 459 460 key = keydb.getnextkey (key); 461 } 462 463 // delete the keys 464 text_tarray::iterator keys_here = oldkeys.begin(); 465 text_tarray::iterator keys_end = oldkeys.end(); 466 while (keys_here != keys_end) { 467 keydb.deletekey(*keys_here); 468 ++keys_here; 469 } 470 } 471 } 472 //==========================================// 473 // keydbclass functions (End) // 474 //==========================================// -
trunk/gsdl/src/recpt/userdb.h
r2750 r13844 28 28 #define USERDB_H 29 29 30 #define ERRNO_SUCCEED 0 31 #define ERRNO_CONNECTIONFAILED -1 32 #define ERRNO_USERNOTFOUND -2 33 #define ERRNO_EXISTINGUSERNAME -3 34 #define ERRNO_MISSINGPASSWORD -4 35 #define ERRNO_PASSWORDMISMATCH -5 36 #define ERRNO_GDBMACTIONFILED -6 37 38 30 39 #include "infodbclass.h" 31 40 32 33 // the password line in the userinfo_t must be encrypted using 34 // this function 35 text_t crypt_text (const text_t &text); 36 37 // username_ok tests to make sure a username is ok. a username 38 // must be at least 2 characters long, but no longer than 30 39 // characters long. it can contain the characters a-z A-Z 0-9 40 // . and _ 41 bool username_ok (const text_t &username); 42 43 // password_ok tests to make sure a password is ok. a password 44 // must be at least 3 characters long but no longer than 8 characters 45 // long. it can contain any character in the range 0x20-0x7e 46 bool password_ok (const text_t &password); 47 48 49 // information about a single user 50 struct userinfo_t { 51 void clear (); 52 userinfo_t () {clear();} 53 userinfo_t &operator=(const userinfo_t &x); 54 41 // The user information object and it provides basic functions for the information object, such as clear and copy (=) functions; 42 class userinfo_t 43 { 44 public: 55 45 text_t username; 56 46 text_t password; … … 58 48 text_t groups; // comma separated list 59 49 text_t comment; 50 51 userinfo_t (); 52 virtual ~userinfo_t(); 53 userinfo_t &operator=(const userinfo_t &x); 54 void clear (); 60 55 }; 61 56 57 typedef vector<userinfo_t> userinfo_tarray; // more space efficient than text_tlist 62 58 63 // these functions deal with user and key databases that are already open 64 // they should have been opened with gdbmclass::opendatabase 65 // as soon as the databases are finished with they should be closed with 66 // gdbmclass::closedatabase so that another process can access the database 67 // 68 // some of the functions need the databases opened with write access, an 69 // appropriate call would be something like: 70 // 71 // success = keydb.opendatabase (keyfile, GDBM_WRCREAT, 1000); 72 // 73 // note: passwords and keys are encrypted, so you can't just compare passwords 74 // in a userinfo_t with a password given by the user. use check_passwd 59 class userdbclass 60 { 61 protected: 62 // The internal storage for the userdbfilename and the userdb object 63 gdbmclass userdb; 64 bool external_db; 65 bool activated; 66 67 public: 68 userdbclass (const text_t &userdbfilename); 69 userdbclass (const gdbmclass &external_userdb); 70 virtual ~userdbclass(); 75 71 72 //======== the static methods========// 73 // the password line in the userinfo_t must be encrypted using 74 // this function 75 static text_t crypt_text (const text_t &text); 76 // username_ok tests to make sure a username is ok. a username 77 // must be at least 2 characters long, but no longer than 30 78 // characters long. it can contain the characters a-z A-Z 0-9 79 // . and _ 80 static bool username_ok (const text_t &username); 81 // password_ok tests to make sure a password is ok. a password 82 // must be at least 3 characters long but no longer than 8 characters 83 // long. it can contain any character in the range 0x20-0x7e 84 static bool password_ok (const text_t &password); 85 // removes spaces from user groups 86 static text_t format_user_groups(const text_t user_groups); 87 88 //======== functions dealing with single user in the user databases ========// 89 // returns true on success (in which case userinfo will contain 90 // the information for this user) 91 int get_user_info (const text_t &username, userinfo_t &userinfo); 92 93 // returns true on success 94 int set_user_info (const text_t &username, const userinfo_t &userinfo); 95 96 // returns true if the user's password is correct. 97 int check_passwd (const text_t &username, const text_t &password); 98 99 // adds a user from the user database -- forever 100 int add_user (const userinfo_t &userinfo); 101 102 // edits a user from the user database -- forever 103 int edit_user (const userinfo_t &userinfo); 104 105 // removes a user from the user database -- forever 106 int delete_user (const text_t &username); 107 108 //======== functions dealing with multiple users in the user databases ========// 109 // gets all the users' information in the database. returns true 110 // on success 111 int get_all_users(userinfo_tarray &userinfo_array); 112 113 // gets a list of all the users in the database. returns true 114 // on success 115 int get_user_list (text_tarray &userlist); 116 }; 76 117 77 // functions dealing with user databases 78 79 // returns true on success (in which case userinfo will contain 80 // the information for this user) 81 bool get_user_info (gdbmclass &userdb, const text_t &username, 82 userinfo_t &userinfo); 83 bool get_user_info (const text_t &userdbfile, const text_t &username, 84 userinfo_t &userinfo); 85 86 // returns true on success 87 bool set_user_info (gdbmclass &userdb, const text_t &username, 88 const userinfo_t &userinfo); 89 bool set_user_info (const text_t &userdbfile, const text_t &username, 90 const userinfo_t &userinfo); 91 92 // removes a user from the user database -- forever 93 void delete_user (gdbmclass &userdb, const text_t &username); 94 void delete_user (const text_t &userdbfile, const text_t &username); 95 96 // gets a list of all the users in the database. returns true 97 // on success 98 void get_user_list (gdbmclass &userdb, text_tarray &userlist); 99 100 // returns true if the user's password is correct. 101 bool check_passwd (const userinfo_t &thisuser, const text_t &password); 102 103 // removes spaces from user groups 104 text_t format_user_groups(const text_t user_groups); 105 106 // functions dealing with databases of temporary keys 107 108 // generates a random key for the user, stores it in the database and 109 // returns it so that it can be used in page generation 110 // returns "" on failure 111 text_t generate_key (gdbmclass &keydb, const text_t &username); 112 text_t generate_key (const text_t &keydbfile, const text_t &username); 113 114 // checks to see if there is a key for this particular user in the 115 // database that hasn't decayed. a short decay is used when group 116 // is set to administrator 117 bool check_key (gdbmclass &keydb, const userinfo_t &thisuser, 118 const text_t &key, const text_t &group, int keydecay); 119 bool check_key (const text_t &keydbfile, const userinfo_t &thisuser, 120 const text_t &key, const text_t &group, int keydecay); 121 122 // remove_old_keys will remove all keys created more than keydecay ago. 123 // use sparingly, it can be quite an expensive function 124 void remove_old_keys (const text_t &keydbfile, int keydecay); 125 118 class keydbclass 119 { 120 protected: 121 // The internal storage for the userdbfilename and the userdb object 122 gdbmclass keydb; 123 bool external_db; 124 bool activated; 125 126 public: 127 keydbclass (const text_t &keydbfilename); 128 keydbclass (const gdbmclass &external_keydb); 129 virtual ~keydbclass(); 130 // functions dealing with databases of temporary keys 131 132 // generates a random key for the user, stores it in the database and 133 // returns it so that it can be used in page generation 134 // returns "" on failure 135 text_t generate_key (const text_t &username); 136 137 // checks to see if there is a key for this particular user in the 138 // database that hasn't decayed. a short decay is used when group 139 // is set to administrator 140 bool check_key (const userinfo_t &thisuser, const text_t &key, const text_t &group, int keydecay); 141 142 // remove_old_keys will remove all keys created more than keydecay ago. 143 // use sparingly, it can be quite an expensive function 144 void remove_old_keys (int keydecay); 145 }; 126 146 127 147 #endif -
trunk/gsdl/src/recpt/usersaction.cpp
r9620 r13844 29 29 #include "usersaction.h" 30 30 #include "fileutil.h" 31 #include "userdb.h"32 31 33 32 … … 195 194 ostream &logout) { 196 195 196 // open the user database (it will be used a lot) 197 user_database = new userdbclass(usersfile); 198 197 199 if (args["uma"] == "adduser" || args["uma"] == "edituser") { 198 200 // adduser is handled by edituser … … 217 219 << "_userslistusers:header_\n_userslistusers:contentstart_\n"; 218 220 219 220 // open the user database (it will be used a lot)221 gdbmclass userdb;222 221 text_tarray userlist; 223 if (userdb.opendatabase(usersfile, GDBM_READER, 1000, true)) { 224 // get user list 225 get_user_list (userdb, userlist); 226 } 222 // get user list 223 user_database->get_user_list (userlist); 227 224 228 225 // sort the list … … 234 231 text_tarray::iterator users_end = userlist.end(); 235 232 while (users_here != users_end) { 236 if ( get_user_info (userdb, *users_here, userinfo)) {233 if (user_database->get_user_info(*users_here, userinfo) == ERRNO_SUCCEED) { 237 234 textout << outconvert << disp 238 235 << "<tr><td bgcolor=\"\\#eeeeee\">" << userinfo.username << "</td>\n" … … 257 254 ++users_here; 258 255 } 259 260 userdb.closedatabase();261 256 262 257 textout << outconvert << disp … … 277 272 outconvertclass &outconvert, ostream &textout, 278 273 ostream &logout) { 274 279 275 userinfo_t userinfo; 280 276 text_t messagestatus; … … 285 281 noproblems = false; 286 282 287 } else if (!user name_ok (args["umun"])) {283 } else if (!userdbclass::username_ok (args["umun"])) { 288 284 // problem with username 289 285 noproblems = false; 290 286 messagestatus += "_users:messageinvalidusername_"; 291 287 292 } else if ( get_user_info (usersfile, args["umun"], userinfo)) {288 } else if (user_database->get_user_info (args["umun"], userinfo) == ERRNO_SUCCEED) { 293 289 if (args["uma"] == "adduser") { 294 290 // must not add a user that has the same name as another user … … 321 317 } 322 318 323 } else if (! password_ok(args["umpw"])) {319 } else if (!userdbclass::password_ok(args["umpw"])) { 324 320 noproblems = false; 325 321 messagestatus += "_users:messageinvalidpassword_"; … … 332 328 if (!args["umpw"].empty()) { 333 329 // only set the password if it is not empty 334 userinfo.password = crypt_text(args["umpw"]);330 userinfo.password = userdbclass::crypt_text(args["umpw"]); 335 331 } 336 332 userinfo.enabled = (args["umus"] == "enabled"); 337 userinfo.groups = format_user_groups(args["umug"]);333 userinfo.groups = userdbclass::format_user_groups(args["umug"]); 338 334 userinfo.comment = args["umc"]; 339 335 340 set_user_info (usersfile,args["umun"], userinfo);336 user_database->set_user_info (args["umun"], userinfo); 341 337 342 338 // show list of users … … 360 356 if (args["cm"] == "yes" && !args["umun"].empty()) { 361 357 // user confirmed the deletion of the user 362 delete_user (usersfile,args["umun"]);358 user_database->delete_user(args["umun"]); 363 359 } 364 360 … … 390 386 } else if (args["umnpw1"] != args["umnpw2"]) { 391 387 messagestatus = "_users:messagenewpassmismatch_"; 392 } else if (! password_ok(args["umnpw1"])) {388 } else if (!userdbclass::password_ok(args["umnpw1"])) { 393 389 messagestatus = "_users:messageinvalidpassword_"; 394 390 } else { 395 391 userinfo_t userinfo; 396 if ( get_user_info (usersfile, args["un"], userinfo)) {392 if (user_database->get_user_info (args["un"], userinfo) == ERRNO_SUCCEED) { 397 393 // check old password 398 if (userinfo.password != crypt_text(args["umpw"])) {394 if (userinfo.password != userdbclass::crypt_text(args["umpw"])) { 399 395 messagestatus = "_users:messagefailed_"; 400 396 401 397 } else { 402 userinfo.password = crypt_text(args["umnpw1"]);403 if ( set_user_info (usersfile, args["un"], userinfo)) {398 userinfo.password = userdbclass::crypt_text(args["umnpw1"]); 399 if (user_database->set_user_info (args["un"], userinfo) == ERRNO_SUCCEED) { 404 400 // everything is ok 405 401 textout << outconvert << disp -
trunk/gsdl/src/recpt/usersaction.h
r7375 r13844 33 33 #include "action.h" 34 34 #include "text_t.h" 35 #include "userdb.h" 35 36 36 37 … … 38 39 protected: 39 40 text_t usersfile; 41 userdbclass* user_database; 40 42 41 43 public:
Note:
See TracChangeset
for help on using the changeset viewer.