• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

yapet/pwgen/pwgen.cc

Go to the documentation of this file.
00001 // $Id: pwgen.cc 3343 2010-09-17 18:36:31Z java $
00002 //
00003 // Copyright (C) 2009-2010  Rafael Ostertag
00004 //
00005 // This file is part of YAPET.
00006 //
00007 // YAPET is free software: you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the Free Software
00009 // Foundation, either version 3 of the License, or (at your option) any later
00010 // version.
00011 //
00012 // YAPET is distributed in the hope that it will be useful, but WITHOUT ANY
00013 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 // FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00015 // details.
00016 //
00017 // You should have received a copy of the GNU General Public License along with
00018 // YAPET.  If not, see <http://www.gnu.org/licenses/>.
00019 //
00020 
00021 #ifdef HAVE_CONFIG_H
00022 # include <config.h>
00023 #endif
00024 
00025 #if !defined(NDEBUG) && defined(HAVE_ASSERT_H)
00026 # include <assert.h>
00027 #endif
00028 
00029 #include "../../intl.h"
00030 
00031 #include "pwgen.h"
00032 
00033 using namespace YAPET::PWGEN;
00034 
00041 void
00042 PWGen::sanitize_password() throw(std::logic_error) {
00043     if ( (static_cast<size_t>(cp->numPoolsAllocated()) > password_len) ||
00044      (cp->numPoolsNotRead() == 0))  /* No can do */ return;
00045 
00046     for (register size_t pwit_outer = 0; pwit_outer < password_len; pwit_outer++) {
00047     assert(password[pwit_outer] != '\0');
00048 
00049     char c_outer = password[pwit_outer];
00050     SUBPOOLS c_outer_pool = cp->fromPool(c_outer);
00051     // Search for characters from same pool
00052     for (register size_t pwit_inner = 0; pwit_inner < password_len; pwit_inner++) {
00053         if (cp->numPoolsNotRead() == 0) return;
00054         assert(password[pwit_inner] != '\0');
00055         char c_inner = password[pwit_inner];
00056         if (pwit_inner != pwit_outer &&
00057         c_outer_pool == cp->fromPool(c_inner)) {
00058         const_cast<char*>(password)[pwit_outer] = getCharFromUnusedPools();
00059         break;
00060         }
00061     }
00062     if (cp->numPoolsNotRead() == 0) return;
00063     }
00064 }
00065 
00066 char
00067 PWGen::getCharFromUnusedPools() throw(std::logic_error) {
00068     char suggestion = 0;
00069     if (cp->numPoolsNotRead() > 0) {
00070     // Find out which one(s) are not read
00071     int not_read = cp->getAllocatedPools() & 
00072         ~ cp->getPoolsWithRead();
00073     
00074     // Iterate over the bits, until we find a pool from
00075     // which we will grab a character. And since this pool
00076     // was never used before, we don't even have to care
00077     // about duplicates...
00078     for (int pool_it=YAPET::PWGEN::LETTERS;
00079          pool_it <= YAPET::PWGEN::OTHER;
00080          pool_it = pool_it << 1) {
00081         if ( not_read & pool_it) {
00082         size_t pool_start;
00083         // Since cp->getPoolPos the length of the pool
00084         // returns, we use this to get the random
00085         // number which we simply can add to
00086         // pool_start.
00087         //
00088         // We must not forget to subtract 1 from the
00089         // return value, else we might get an out of
00090         // range error
00091         size_t random_val = (*rng)(cp->getPoolPos((YAPET::PWGEN::SUBPOOLS)pool_it,
00092                               &pool_start)-1); 
00093         suggestion = (*cp)[pool_start + random_val];
00094         return suggestion;
00095         } 
00096     } // for (int i=...
00097     } else {
00098     assert(0);
00099     throw std::logic_error(_("Cannot get character from unused pool because no unused pools are available"));
00100     }
00101     assert(0);
00102     return -1;
00103 }
00104 
00105 void
00106 PWGen::init (int p, RNGENGINE rnge) throw (std::runtime_error) {
00107     cp = new CharacterPool (p);
00108     rng = new RNG(rnge);
00109 }
00110 
00111 PWGen::PWGen (SUBPOOLS p, RNGENGINE rnge) throw (std::runtime_error) : cp (NULL), rng(NULL), password (NULL), password_len (0) {
00112     init (p, rnge);
00113     assert (cp != NULL);
00114     assert (rng != NULL);
00115     assert (password == NULL);
00116 }
00117 
00118 PWGen::PWGen (int p, RNGENGINE rnge) throw (std::runtime_error) : cp (NULL), rng(NULL), password (NULL), password_len (0) {
00119     init (p, rnge);
00120     assert (cp != NULL);
00121     assert (rng != NULL);
00122     assert (password == NULL);
00123 }
00124 
00125 //
00126 // Copy Constructor
00127 //
00128 PWGen::PWGen (const PWGen& pw) throw() : cp (NULL), rng(NULL), password (NULL), password_len (0) {
00129     assert (pw.cp != NULL);
00130     assert (pw.rng != NULL);
00131     cp = new CharacterPool (* (pw.cp) );
00132     rng = new RNG(*(pw.rng));
00133     assert (cp != NULL);
00134     assert (rng != NULL);
00135 
00136     if (pw.password != NULL) {
00137         assert (pw.password_len > 0);
00138         password = new char[pw.password_len + 1];
00139         memcpy ( (void*) password, pw.password, pw.password_len);
00140         // Don't forget to zero terminate!
00141         const_cast<char*>(password) [pw.password_len + 1] = '\0';
00142         password_len = pw.password_len;
00143     }
00144 }
00145 
00146 PWGen::~PWGen() throw() {
00147     assert (cp != NULL);
00148     assert (rng != NULL);
00149     delete cp;
00150     delete rng;
00151 
00152     if (password_len != 0) assert (password != NULL);
00153 
00154     if (password != NULL) {
00155         assert (password_len > 0);
00156         memset ( (void*) password, 0, password_len);
00157         delete[] password;
00158     }
00159 }
00160 
00161 void
00162 PWGen::setNewPool (int p) throw (std::runtime_error) {
00163     assert (cp != NULL);
00164     delete cp;
00165     cp = new CharacterPool (p);
00166     assert (cp != NULL);
00167 }
00168 
00169 void
00170 PWGen::setNewRNG (RNGENGINE rnge) throw (std::runtime_error) {
00171     assert (rng != NULL);
00172     delete rng;
00173     rng = new RNG (rnge);
00174     assert (rng != NULL);
00175 }
00176 
00177 void
00178 PWGen::generatePassword (size_t len) throw (std::logic_error) {
00179     if (len == 0) return;
00180 
00181     if (password != NULL) {
00182         assert (password_len > 0);
00183         memset ( (void*) password, 0, password_len);
00184         delete[] password;
00185     }
00186 
00187     password_len = len;
00188     password = new char[password_len + 1];
00189     cp->resetPoolsWithRead();
00190     
00191     for (size_t pw_it = 0; pw_it < password_len; pw_it++) {
00192 RESTART:
00193         char suggestion = (*cp) [(*rng) (cp->getPoolLength() ) ];
00194     if (static_cast<size_t>(cp->getPoolLength()) >= password_len) {
00195         // We can avoid repeating characters
00196         for (size_t pos = 0; pos < pw_it; pos++) {
00197         if (suggestion == password[pos]) {
00198             //
00199             // We found a duplicate
00200             //
00201             if (static_cast<size_t>(cp->numPoolsAllocated()) >= password_len &&
00202             cp->numPoolsNotRead() > 0) {
00203             // make sure all pools are read from
00204             suggestion = getCharFromUnusedPools();
00205             break;
00206             }
00207         }
00208         }
00209     }
00210         
00211         // We want to avoid spaces at the beginning or end of the password
00212         if ( (pw_it == 0) || (pw_it == password_len - 1) ) {
00213 #if defined(HAVE_ISBLANK) || defined(HAVE_ISSPACE)
00214 # ifdef HAVE_ISBLANK
00215         
00216             if (isblank (suggestion) != 0)
00217                 goto RESTART;
00218         
00219 # else
00220 
00221             if (isspace (suggestion) != 0)
00222                 goto RESTART;
00223 
00224 # endif // HAVE_ISBLANK
00225 #else // defined(HAVE_ISBLANK) || defined(HAVE_ISSPACE)
00226 
00227             if (suggestion == ' ')
00228                 goto RESTART;
00229 
00230 #endif // defined(HAVE_ISBLANK) || defined(HAVE_ISSPACE)
00231         } // if ( (i == 0) || (i == password_len - 1) ) 
00232 
00233         const_cast<char*>(password) [pw_it] = suggestion;
00234     } // for (size_t i = 0; i < password_len; i++) 
00235 
00236     // Don't forget to zero terminate!
00237     const_cast<char*>(password) [password_len] = '\0';
00238 
00239     sanitize_password();
00240 #ifndef NDEBUG
00241     // Make sure we used at least one character from each pool
00242     if (static_cast<size_t>(cp->numPoolsAllocated()) <= password_len) {
00243     assert(cp->numPoolsNotRead() == 0);
00244     }
00245 #endif
00246 }
00247 
00248 const char*
00249 PWGen::getPassword() const throw() {
00250     assert ( ( (password != NULL) && (password_len > 0) ) ||
00251              ( (password == NULL) && (password_len == 0) ) );
00252 
00253     if (password == NULL) return NULL;
00254 
00255     assert (password[password_len] == '\0');
00256     return password;
00257 }
00258 
00259 const PWGen&
00260 PWGen::operator= (const PWGen & pw) throw() {
00261     assert (cp != NULL);
00262     assert (rng != NULL);
00263 
00264     if (&pw == this) return *this;
00265 
00266     delete cp;
00267     cp = new CharacterPool (* (pw.cp) );
00268     delete rng;
00269     rng = new RNG (* (pw.rng) );
00270 
00271     if (password != NULL) {
00272         assert (password_len > 0);
00273         memset ( (void*) password, 0, password_len);
00274         delete[] password;
00275     }
00276 
00277     if (pw.password != NULL) {
00278         assert (pw.password_len > 0);
00279         password = new char[pw.password_len];
00280         memcpy ( (void*) password, pw.password, pw.password_len);
00281         // Don't forget to zero terminate
00282         const_cast<char*>(password) [pw.password_len + 1] = '\0';
00283         password_len = pw.password_len;
00284     }
00285 
00286     return *this;
00287 }

Generated on Sun Sep 19 2010 15:37:14 for YAPET by  doxygen 1.7.1