Added a Module Config option to use a text box for entering secondary group members, rather than the left/right user chooser.
Created a page for exporting groups to a batch file, for importing on other systems.
Added support for creating, deleting and modifying groups from a batch file. This is similar to the long-standing batch user management functionality.
+Added support for Blowfish password hashing, which can be enabled on the Module Config page. On Solaris systems, it will be used if enabled in /etc/security/policy.conf. Requires the Crypt::Eksblowfish::Bcrypt Perl module though.
gid_calc=GID Calculation Method,4,0-Berkeley cksum,1-Custom mkgid program
new_user_group=Create new group for new users?,1,1-Yes,0-No
new_user_gid=Assign same ID to new user and group?,1,1-Yes,0-No
-md5=Password encryption method,1,2-MD5,1-Determine automatically,0-DES crypt
+md5=Password encryption method,1,2-MD5,1-Determine automatically,0-DES crypt,3-Blowfish
alias_check=Check for sendmail alias clashes?,1,1-Yes,0-No
delete_only=Only delete files owned by user?,1,1-Yes,0-No
max_length=Maximum user and group name length,3,Unlimited
usave_eoffice=Office cannot contain a : character
usave_eworkph=Work phone cannot contain a : character
usave_ehomeph=Home phone cannot contain a : character
-usave_edigestmd5=Your system has MD5 passwords enabled, but neither the perl MD5 or Digest::MD5 module is not installed.<p>To force the use of normal encrypted passwords, adjust your <a href='$1'>module configuration</a>.<p>Or have Webmin <a href='$2'>download and install</a> the Digest::MD5 module for you.
+usave_edigestmd5=Your system has MD5 passwords enabled, but the Perl <tt>$3</tt> module is not installed.<p>To force the use of normal encrypted passwords, adjust your <a href='$1'>module configuration</a>.<p>Or have Webmin <a href='$2'>download and install</a> the <tt>$3</tt> module for you.
+usave_edigestblowfish=Your system has MD5 passwords enabled, but the Perl <tt>$3</tt> module is not installed.<p>To force the use of normal encrypted passwords, adjust your <a href='$1'>module configuration</a>.<p>Or have Webmin <a href='$2'>download and install</a> the <tt>$3</tt> module for you.
usave_emaking=Before update command failed : $1
usave_epasswd_min=Password must be at least $1 letters long
usave_epasswd_re=Password does not match regexp $1
sub encrypt_sha1_hash
{
local ($pass, $salt) = @_;
+# XXX not done yet??
+}
+
+# check_blowfish()
+# Returns an missing Perl module if blowfish is not available, undef if OK
+sub check_blowfish
+{
+eval "use Crypt::Eksblowfish::Bcrypt";
+return $@ ? "Crypt::Eksblowfish::Bcrypt" : undef;
+}
+
+# encrypt_blowfish(password, [salt])
+# Returns a string encrypted in blowfish format, suitable for /etc/shadow
+sub encrypt_blowfish
+{
+local ($passwd, $salt) = @_;
+local ($plain, $base64);
+eval "use Crypt::Eksblowfish::Bcrypt";
+if (!$salt) {
+ # Generate a 22-character base-64 format salt
+ &seed_random();
+ while(length($base64) < 22) {
+ $plain .= chr(int(rand()*96)+32);
+ $base64 = Crypt::Eksblowfish::Bcrypt::en_base64($plain);
+ }
+ $base64 = substr($base64, 0, 22);
+ $salt = '$2$'.'08'.'$'.$base64;
+ }
+return Crypt::Eksblowfish::Bcrypt::bcrypt($passwd, $salt);
}
1;
}
# use_md5()
-# Returns 1 if MD5 encryption should be used
+# Returns 1 if MD5 encryption should be used, 2 if blowfish
sub use_md5
{
local $lref = &read_file_lines("/etc/security/policy.conf");
$l =~ /^CRYPT_DEFAULT\s*=\s*'([^']*)'/ ||
$l =~ /^CRYPT_DEFAULT\s*=\s*(\S+)/) {
return 1 if ($1 eq "1");
+ return 2 if ($1 eq "2a");
}
}
return 0;
sub encrypt_password
{
local ($pass, $salt) = @_;
-local $md5 = 0;
+local $format = 0;
if ($gconfig{'os_type'} eq 'macos' && &passfiles_type() == 7) {
# New OSX directory service uses SHA1 for passwords!
$salt ||= chr(int(rand(26))+65).chr(int(rand(26))+65).
}
elsif ($config{'md5'} == 2) {
# Always use MD5
- $md5 = 1;
+ $format = 1;
+ }
+elsif ($config{'md5'} == 3) {
+ # Always use blowfish
+ $format = 2;
}
elsif ($config{'md5'} == 1 && !$config{'skip_md5'}) {
# Up to system
- $md5 = &use_md5() if (defined(&use_md5));
+ $format = &use_md5() if (defined(&use_md5));
}
if ($no_encrypt_password) {
# Some operating systems don't do any encryption!
return $pass;
}
-elsif ($md5) {
+elsif ($format == 1) {
# MD5 encryption is selected .. use it if possible
local $err = &check_md5();
if ($err) {
- &header($text{'error'}, "");
- print "<hr><p>\n";
+ &ui_print_header(undef, $text{'error'}, "");
print &text('usave_edigestmd5',
"/config.cgi?$module_name",
- "/cpan/download.cgi?source=3&cpan=$err"),
+ "/cpan/download.cgi?source=3&cpan=$err", $err),
"<p>\n";
- print "<hr>\n";
- &footer("", $text{'index_return'});
+ &ui_print_footer("", $text{'index_return'});
exit;
}
return &encrypt_md5($pass, $salt);
}
+elsif ($format == 2) {
+ # Blowfish is selected .. use it if possible
+ local $err = &check_blowfish();
+ if ($err) {
+ &ui_print_header(undef, $text{'error'}, "");
+ print &text('usave_edigestblowfish',
+ "/config.cgi?$module_name",
+ "/cpan/download.cgi?source=3&cpan=$err", $err),
+ "<p>\n";
+ &ui_print_footer("", $text{'index_return'});
+ exit;
+ }
+ return &encrypt_blowfish($pass, $salt);
+ }
else {
# Just do old-style crypt() DES encryption
$salt ||= chr(int(rand(26))+65) . chr(int(rand(26))+65);