summaryrefslogtreecommitdiffstats
path: root/checksetup.pl
diff options
context:
space:
mode:
authorjustdave%syndicomm.com <>2001-07-11 14:29:16 +0200
committerjustdave%syndicomm.com <>2001-07-11 14:29:16 +0200
commit022265211b1a3b3dad3fcf679756392c3eb6a285 (patch)
tree79c99d0bea86b527395b4aac32a37eef739c67dc /checksetup.pl
parentf208e298e2ac9836c8138449a0691f6deb850c4a (diff)
downloadbugzilla-022265211b1a3b3dad3fcf679756392c3eb6a285.tar.gz
bugzilla-022265211b1a3b3dad3fcf679756392c3eb6a285.tar.xz
Fix for bug 77473, bug 74032, and bug 85472: Passwords are no longer stored in plaintext in the database. Passwords are no longer encrypted with MySQL's ENCRYPT() function (because it doesn't work on some installs), but with Perl's crypt() function. The crypt-related routines now properly deal with salts so that they work on systems that use methods other than UNIX crypt to crypt the passwords (such as MD5). Checksetup.pl will walk through your database and re-crypt everyone's passwords based on the plaintext password entry, then drop the plaintext password column. As a consequence of no longer having a plaintext password, it is no longer possible to email someone their password, so the login screen has been changed to request a password reset instead. The user is emailed a temporary identifying token, with a link back to Bugzilla. They click on the link or paste it into their browser and Bugzilla allows them to change their password.
Patch by Myk Melez <myk@mozilla.org> r= justdave@syndicomm.com, jake@acutex.net
Diffstat (limited to 'checksetup.pl')
-rwxr-xr-xchecksetup.pl107
1 files changed, 98 insertions, 9 deletions
diff --git a/checksetup.pl b/checksetup.pl
index c314bad84..7102df13c 100755
--- a/checksetup.pl
+++ b/checksetup.pl
@@ -914,7 +914,7 @@ $table{groups} =
$table{logincookies} =
'cookie mediumint not null auto_increment primary key,
userid mediumint not null,
- cryptpassword varchar(64),
+ cryptpassword varchar(34),
hostname varchar(128),
lastused timestamp,
@@ -936,8 +936,7 @@ $table{products} =
$table{profiles} =
'userid mediumint not null auto_increment primary key,
login_name varchar(255) not null,
- password varchar(16),
- cryptpassword varchar(64),
+ cryptpassword varchar(34),
realname varchar(255),
groupset bigint not null,
disabledtext mediumtext,
@@ -1038,6 +1037,19 @@ $table{duplicates} =
'dupe_of mediumint(9) not null,
dupe mediumint(9) not null primary key';
+# 2001-06-21, myk@mozilla.org, bug 77473:
+# Stores the tokens users receive when they want to change their password
+# or email address. Tokens provide an extra measure of security for these changes.
+$table{tokens} =
+ 'userid mediumint not null ,
+ issuedate datetime not null ,
+ token varchar(16) not null primary key ,
+ tokentype varchar(8) not null ,
+ eventdata tinytext null ,
+
+ index(userid)';
+
+
###########################################################################
# Create tables
@@ -1417,12 +1429,15 @@ _End_Of_SQL_
system("stty","-echo"); # disable input echoing
while( $pass1 ne $pass2 ) {
- while( $pass1 eq "" ) {
+ while( $pass1 eq "" || $pass1 !~ /^[a-zA-Z0-9-_]{3,16}$/ ) {
print "Enter a password for the administrator account: ";
$pass1 = <STDIN>;
chomp $pass1;
if(! $pass1 ) {
print "\n\nIt's just plain stupid to not have a password. Try again!\n";
+ } elsif ( $pass1 !~ /^[a-zA-Z0-9-_]{3,16}$/ ) {
+ print "The password must be 3-16 characters in length
+ and contain only letters, numbers, hyphens (-), and underlines (_).";
}
}
print "\nPlease retype the password to verify: ";
@@ -1435,6 +1450,9 @@ _End_Of_SQL_
}
}
+ # Crypt the administrator's password
+ my $cryptedpassword = Crypt($pass1);
+
system("stty","echo"); # re-enable input echoing
$SIG{HUP} = 'DEFAULT'; # and remove our interrupt hooks
$SIG{INT} = 'DEFAULT';
@@ -1442,12 +1460,12 @@ _End_Of_SQL_
$SIG{TERM} = 'DEFAULT';
$realname = $dbh->quote($realname);
- $pass1 = $dbh->quote($pass1);
+ $cryptedpassword = $dbh->quote($cryptedpassword);
$dbh->do(<<_End_Of_SQL_);
INSERT INTO profiles
- (login_name, realname, password, cryptpassword, groupset)
- VALUES ($login, $realname, $pass1, encrypt($pass1), 0x7fffffffffffffff)
+ (login_name, realname, cryptpassword, groupset)
+ VALUES ($login, $realname, $cryptedpassword, 0x7fffffffffffffff)
_End_Of_SQL_
} else {
$dbh->do(<<_End_Of_SQL_);
@@ -1460,6 +1478,41 @@ _End_Of_SQL_
}
+sub Crypt {
+ # Crypts a password, generating a random salt to do it.
+ # Random salts are generated because the alternative is usually
+ # to use the first two characters of the password itself, and since
+ # the salt appears in plaintext at the beginning of the crypted
+ # password string this has the effect of revealing the first two
+ # characters of the password to anyone who views the crypted version.
+
+ my ($password) = @_;
+
+ # The list of characters that can appear in a salt. Salts and hashes
+ # are both encoded as a sequence of characters from a set containing
+ # 64 characters, each one of which represents 6 bits of the salt/hash.
+ # The encoding is similar to BASE64, the difference being that the
+ # BASE64 plus sign (+) is replaced with a forward slash (/).
+ my @saltchars = (0..9, 'A'..'Z', 'a'..'z', '.', '/');
+
+ # Generate the salt. We use an 8 character (48 bit) salt for maximum
+ # security on systems whose crypt uses MD5. Systems with older
+ # versions of crypt will just use the first two characters of the salt.
+ my $salt = '';
+ for ( my $i=0 ; $i < 8 ; ++$i ) {
+ $salt .= $saltchars[rand(64)];
+ }
+
+ # Crypt the password.
+ my $cryptedpassword = crypt($password, $salt);
+
+ # Return the crypted password.
+ return $cryptedpassword;
+}
+
+
+
+
###########################################################################
# Create initial test product if there are no products present.
###########################################################################
@@ -1808,10 +1861,10 @@ if (GetFieldDef('bugs', 'long_desc')) {
# him or something. Invent a new profile entry,
# disabled, just to represent him.
$dbh->do("INSERT INTO profiles " .
- "(login_name, password, cryptpassword," .
+ "(login_name, cryptpassword," .
" disabledtext) VALUES (" .
$dbh->quote($name) .
- ", 'okthen', encrypt('okthen'), " .
+ ", " . $dbh->quote(Crypt('okthen')) . ", " .
"'Account created only to maintain database integrity')");
$s2 = $dbh->prepare("SELECT LAST_INSERT_ID()");
$s2->execute();
@@ -2204,6 +2257,42 @@ if (-d 'shadow') {
DropField("profiles", "emailnotification");
DropField("profiles", "newemailtech");
+# 2001-06-12; myk@mozilla.org; bugs 74032, 77473:
+# Recrypt passwords using Perl &crypt instead of the mysql equivalent
+# and delete plaintext passwords from the database.
+if ( GetFieldDef('profiles', 'password') ) {
+
+ print <<ENDTEXT;
+Your current installation of Bugzilla stores passwords in plaintext
+in the database and uses mysql's encrypt function instead of Perl's
+crypt function to crypt passwords. Passwords are now going to be
+re-crypted with the Perl function, and plaintext passwords will be
+deleted from the database. This could take a while if your
+installation has many users.
+ENDTEXT
+
+ # Re-crypt everyone's password.
+ my $sth = $dbh->prepare("SELECT userid, password FROM profiles");
+ $sth->execute();
+
+ my $i = 1;
+
+ print "Fixing password #1... ";
+ while (my ($userid, $password) = $sth->fetchrow_array()) {
+ my $cryptpassword = $dbh->quote(Crypt($password));
+ $dbh->do("UPDATE profiles SET cryptpassword = $cryptpassword WHERE userid = $userid");
+ ++$i;
+ # Let the user know where we are at every 500 records.
+ print "$i... " if !($i%500);
+ }
+ print "$i... Done.\n";
+
+ # Drop the plaintext password field and resize the cryptpassword field.
+ DropField('profiles', 'password');
+ ChangeFieldType('profiles', 'cryptpassword', 'varchar(34)');
+
+}
+
#
# 2001-06-06 justdave@syndicomm.com:
# There was no index on the 'who' column in the long descriptions table.