Mini Shell

Direktori : /opt/sharedrads/extras/
Upload File :
Current File : //opt/sharedrads/extras/makepasswd

#!/usr/bin/perl

#
# Program information.
#

$Program	= 'makepasswd';
$Version	= '1.10';
$Author		= 'Rob Levin <levin@openproject.net>';
$Date		= "Monday, 7 April 1999 at 22:56 (UCT)";
$Copyright	= '1997-1999';
$Description	= 'This program is extracted from the author\'s GPL\'ed mkircconf program.  '.
		  'It is used to create and/or encrypt true-random-seeded password strings.';

#
# Setup.
#

use	Getopt::Long;
use	FileHandle;
use	integer;
use	bytes;
use	Crypt::OpenSSL::Random;

#
# Set default values for options ("" to indicate not-specified).
#

$Chars = "";
$Clear = "";
$Count = "";
$Crypt = 0;
$CryptMd5 = 0;
$CryptSalt = "";
$MaxChars = "";
$MinChars = "";
$RandomSeed = "";
$RepeatPass = "";
$Rerandom = "";
$ShowHelp = 0;
$String = "";
$Verbose = 0;

#
# Limit and current value variables for execution.
#

$Error = 0;
$CharMin = 8;
$CharMax = 10;
$CharFormat = $CharMax + 3;
$CountUsed = 1;
$PasswordRepeat = 1;
$CurrentChar=$CharMin;
$Password = "";
$Randomize = 1;
$RandSeed = 0;
$RerandomCount = -1;
$RerandomNow = 1;
$SeedValue = 0;

#
# Crypt() mode set on the basis of options interpreted:
#
#    0   No related options yet interpreted.
#    1   Password generation will be done.
#    2   Password generation w/o encryption will be done.
#    3   Password generation and encryption will be done.
#    4   Encryption w/o password generation will be done.
#

$CryptMode = 0;

#
# Default characters for passwords include all lowercase
# and uppercase alphabetics, plus numerics 0-9.  Uppercase
# O and Z and lowercase k and l are omitted to improve
# hand-transcription clarity.
#

$StringUsed = "ABCDEFGHIJKLMNPQRSTUVWXYabcdefghijmnopqrstuvwxyz0123456789";
$ValString = length($StringUsed) - 1;

#
# Characters for salt construction.
#

$SaltList="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";

#
# Process the options.
#

&GetOptions
(
	'chars=i'		=> \$Chars,
	'clear=s'		=> \$OldClear,
	'clearfrom=s'		=> \$Clear,
	'count=i'		=> \$Count,
	'crypt!'		=> \$Crypt,
	'crypt-md5!'		=> \$CryptMd5,
	'cryptsalt=i'		=> \$CryptSalt,
	'help'			=> \$ShowHelp,
	'maxchars=i'		=> \$MaxChars,
	'minchars=i'		=> \$MinChars,
	'randomseed=i'		=> \$RandomSeed,
	'repeatpass=i'		=> \$RepeatPass,
	'rerandom=i'		=> \$Rerandom,
	'string=s'		=> \$String,
	'verbose!'		=> \$Verbose,
) or do
{
	$Error = 1;
};

$#ARGV != -1 and do
{
	print STDERR "$Program:  Non-argument options specified:  @ARGV\n";
	$Error = 1;
};

#
# If password generation option was specified with the old --clear,
# warn the user and exit
#
$OldClear ne "" and do
{
	print STDERR "$Program:  Option --clear is no longer present \n".
			"please use --clearfrom and supply a file for it.\n";
	$Error = 1;
};

#
# If password generation option was specified with --clearfrom, flag it.
#

$Clear ne "" and do
{
	(
		$Chars ne "" or
		$MaxChars ne "" or
		$MinChars ne "" or
		$Count ne "" or
		$String ne ""
	) and do
	{
		print STDERR "$Program:  Option --clearfrom may not be specified ".
			"with a password generation option.\n";
		print STDERR "$Program:  Password generation options are ".
			"--chars --minchars --maxchars --count --string.\n";
		$Error = 1;
	};
	$Crypt or $CryptMd5 or do
	{
		print STDERR "$Program:  Option --clearfrom may not be specified ".
			"without option --crypt or --crypt-md5.\n";
		$Error = 1;
	};
	open CLEARFROM, "$Clear" or do
	{
		print STDERR "$Program:  Could not read $Clear, error: $!\n";
		$Error = 1;
	};
	$Clear = <CLEARFROM>;
	$Clear =~ s/[\n]*$//;
	close CLEARFROM;
	$CryptMode = 4;
};

#
# If --chars was specified, process it.
#

$Chars ne "" and do
{
	($MinChars ne "" or $MaxChars ne "") and do
	{
		print STDERR "$Program:  May not specify --chars with --minchars or --maxchars.\n";
		$Error = 1;
	};
	$CryptMode == 0 and $CryptMode = 1;
	$CharMin = $Chars;
	$CharMax = $Chars;
	$CharFormat = $CharMax + 3;
};

#
# If --minchars was specified, process it.
#

$MinChars ne "" and do
{
	$Chars eq "" or do
	{
		print STDERR "$Program:  May not specify --minchars with --chars.\n";
		$Error = 1;
	};
	$CryptMode == 0 and $CryptMode = 1;
	$CharMin = $MinChars;
};

#
# If --maxchars was specified, process it.
#

$MaxChars ne "" and do
{
	$Chars eq "" or do
	{
		print STDERR "$Program:  May not specify --maxchars with --chars.\n";
		$Error = 1;
	};
	$CryptMode == 0 and $CryptMode = 1;
	$CharMax = $MaxChars;
	$CharFormat = $CharMax + 3;
};

#
# Make sure minimum character length is less than or equal to maximum.
#

$CharMin > $CharMax and do
{
	print STDERR "$Program:  Illegal value --minchars=$CharMin is larger than --maxchars=$CharMax.\n";
	$Error = 1;
};

#
# If --count was specified, process it.
#

$Count ne "" and do
{

#
# Make sure the password count is a positive number.
#

	$Count > 0 or do
	{
		print STDERR "$Program:  Number of passwords to be made must be positive\n";
		$Error = 1;
	};

#
# If so, finish processing it.
#

	$CryptMode == 0 and $CryptMode = 1;
	$CountUsed = $Count;
};

#
# If --string was specified, process it.
#

$String ne "" and do
{
	$CryptMode == 0 and $CryptMode = 1;
	$StringUsed = $String;
	$ValString = length($String) - 1;
};

#
# If --repeatpass was specified, process it.
#

$RepeatPass ne "" and do
{

#
# If --crypt is not set or --cryptsalt is set, disallow this parameter.
#

	$Crypt or $CryptMd5 or do
	{
		print STDERR "$Program:  To use --repeatpass, --crypt or --crypt-md5 must also be set.\n";
		$Error = 1;
	};
	$CryptSalt and do
	{
		print STDERR "$Program:  To use --repeatpass, --cryptsalt may not be set.\n";
		$Error = 1;
	};

#
# Make sure the password repeat count is a positive number.
#

	($RepeatPass > 0 and $RepeatPass < 4097) or do
	{
		print STDERR "$Program:  Password repeat count must be positive and less than 4097.\n";
		$Error = 1;
	};
	$CryptMode == 0 and $CryptMode = 1;
	$PasswordRepeat = $RepeatPass;
};

#
# If crypt mode is set to `password generation will be done, not yet known if
# encryption will be done,' fill in the blanks.  If crypt mode is not yet set,
# it's going to be `password generation will be done, encryption will not.'
#

$CryptMode == 1 and do
{
	$CryptMode += ($Crypt + 1);
};
$CryptMode == 0 and do
{
	$CryptMode = 2;
};

#
# If a cryptographic seed value was specified, process it.
#

$CryptSalt ne "" and do
{

#
# If --crypt wasn't specified, signal the error.
#

	$Crypt or do
	{
		print STDERR "$Program:  Option --cryptsalt may not be ".
			"specified without option --crypt.\n";
		$Error = 1;
	};

#
# Make sure the seed value is between 0 and 4095, inclusive.
#

	($CryptSalt > -1 and $CryptSalt <= 4096) or do
	{
		print STDERR "$Program:  Crypt() seed value must be zero thru 4096\n";
		$Error = 1;
	};

#
# If so, save the value.
#

	$SeedValue = $CryptSalt;
};

#
# If we're not in a password generation mode and --cryptsalt was set to a
# nonzero value, then we shouldn't have any randomization options.  If we
# do in that case, signal error and quit.
#

$CryptMode == 4 and $SeedValue and do
{
	$Randomize = 0;
	($RandomSeed ne "" or $Rerandom ne "") and do
	{
		print STDERR "$Program:  Options --randomseed and --rerandom may not be ".
			"specified unless password generation or random seed encryption ".
			"is performed.\n";
		$Error = 1;
	};
};

#
# If a random number seed was specified, check for a valid number and process it.
#

$RandomSeed ne "" and do
{
	($RandomSeed > -1 and $RandomSeed <= 2^32) or do
	{
		print STDERR "$Program:  Random number seed must be zero thru 2^32\n";
		$Error = 1;
	};
	$RandSeed = $RandomSeed;
};

#
# If a rerandomize character count was specified, check for a non-negative
# number and process it.
#

$Rerandom ne "" and do
{
	($ReRandom > -1) or do
	{
		print STDERR "$Program:  Rerandomize parameter must be zero or positive\n";
		$Error = 1;
	};
	$RerandomCount = $Rerandom;
	$RerandomCount or $RerandomCount--;
};

#
# If --help was specified, display the message and terminate with the exit
# code in $Error, which will be nonzero if a syntax error occurred.
#

$ShowHelp and do
{
	$Error and print STDERR "\n";
	Help();
	exit $Error;
};

#
# If an error occurred, display help message on STDERR and quit with the
# exit code in $Error.
#

$Error and do
{
	$Error and
		print STDERR "$Program:  For more information, type:  $Program --help\n";
	exit $Error;
};

#
# If verbose mode was selected, display the output header.
#

$PassLabel = $CryptLabel = "";
$Verbose and print "
$Program v$Version (c) $Copyright by $Author,
last modified $Date
All rights reserved by the author, licensed under GPL version 2.

";

#
# Process the number of passwords specified.  Terminate normally.
#

for ($ctr=0; $ctr < $CountUsed; $ctr++)
{
	ProcessPassword();
}
exit(0);

#
# sub Help:  Display help information on STDERR.
#

sub Help
{
	print STDERR
"$Program v$Version, a utility to generate and/or encrypt passwords.

Copyright (c) $Copyright by $Author.  All rights are reserved by
the author.  This program may be used under the terms of version 2 of the
GNU Public License.

Last modified on $Date.

Format:          $Program [option...]

Options are:

--chars=N        Generate passwords with exactly N characters (do not use with
                       options --minchars and --maxchars).
--clearfrom=FILE Use a clear password from FILE instead of generating passwords.
                       Requires the --crypt or --crypt-md5 option; may not be
                       used with options --chars, --maxchars, --minchars,
                       --count, --string, --nocrypt.  Trailing newlines are
                       ignored, other whitespace is not.
--count=N        Produce a total of N passwords (the default is one).
--crypt          Produce encrypted passwords.
--crypt-md5      Produce encrypted passwords using the MD5 digest (hash)
                       algorithm.
--cryptsalt=N    Use crypt() salt N, a positive number <= 4096.  If random
                       seeds are desired, specify a zero value (the default).
--help           Ignore other operands and produce only this help display.
--maxchars=N     Generate passwords with at most N characters (default=10).
--minchars=N     Generate passwords with at least N characters (default=8).
--nocrypt        Do not encrypt the generated password(s) (the default).
--noverbose      Display no labels on output (the default).
--randomseed=N   Use random number seed N, between 0 and 2^32 inclusive.  A zero
                       value results in a real-random seed.  This option
                       generates predictable passwords, and should normally
                       be avoided.
--rerandom=N     Set the random seed value every N values used.  Specify zero
                       to use a single seed value (the default).  Specify
                       one to get true-random passwords, but plan on hitting
                       the CONTROL key a lot while it's running. ;)
--repeatpass=N   Use each password N times (4096 maximum, --crypt or
                       --crypt-md5 must be set and --cryptsalt may not be set).
--string=STRING  Use the characters in STRING to generate random passwords.
--verbose        Display labelling information on output.
";
}

#
# sub NumBits(N):  Number of significant bits in N.
#

sub NumBits
{
	return length(sprintf('%b', $_[0]));
}

#
# sub Random(A, B):  Produce a random integer from A to B, inclusive.
#

sub Random
{
	$RerandomNow--;
 	$RerandomNow == 0 and do
	{
		SeedRandom();
		$RerandomNow = $RerandomCount;
	};
	$RerandomCount == -1 and do
	{
		$RerandomNow = $RerandomCount;
	};
	my $RandomOutputVal;
	if ($RandSeed)
	{
		$RandomOutputVal = rand($_[1]-$_[0]+1);
	}
	else
	{
		# Annoyingly, there's no Perl binding for
		# BN_pseudo_rand_range, so we have to emulate it.  We
		# repeatedly generate n-bit pseudo-random byte sequences
		# (with n = number of significant bits in range) until we
		# get something less than range.
		my $range = $_[1]-$_[0]+1;
		my $bits = NumBits($range);
		my $bytes = ($bits - 1) / 8 + 1;
		my $max = 1 << ($bytes * 8);
		$max -= $max % $range;
		while (1)
		{
			my $buf = Crypt::OpenSSL::Random::random_pseudo_bytes($bytes);
			my $val = 0;
			for my $byte (unpack('C*', $buf))
			{
				$val = ($val << 8) + $byte;
			}
			if ($val < $max)
			{
				# Using the modulus is OK here; we're
				# working with a byte stream, so the
				# low-order bits are no worse than any of
				# the others.
				$RandomOutputVal = $val % $range;
				last;
			}
		}
	}
	$RandomOutputVal=$RandomOutputVal+$_[0];
	$RandomOutputVal =~ s/\..*$//;
	$RandomOutputVal;
}

#
# sub SeedRandom:  Seed the random number function.
#

sub SeedRandom
{
	my $i;
	my $SeedOutput = $RandSeed;
	if ($SeedOutput)
	{
		srand $SeedOutput;
	}
	else
	{
		open(RANDOMSEED, "<:unix", "/dev/urandom") or die "Could not access a seed value.\n";
		$SeedOutput='';
		my $i=0;
		while ($i < 32)
		{
			my $r = read(RANDOMSEED, $SeedOutput, 32 - $i, $i);
			die "read /dev/urandom failed: $!\n" unless defined $r;
			$i += $r;
		}
		close(RANDOMSEED);
		Crypt::OpenSSL::Random::random_seed($SeedOutput);
		Crypt::OpenSSL::Random::random_status() or die "OpenSSL PRNG could not be sufficiently seeded.\n";
	};
}

#
# sub MakePassword(A, B):  Generate a password from A to B bytes in length.
#

sub MakePassword
{
	my $i;
	my $Password;

	if ($Clear)
	{
		$Password = $Clear;
	}
	else
	{
		my $Total = Random($CharMin, $CharMax);
		$Password = "";
		for (my $i=0; $i < $Total; $i++)
		{
			$Password .= substr($StringUsed, Random(0, $ValString), 1);
		}
	}
	$Password;
}

#
# sub MakeSalt(A):  Generate a crypt salt string from a number from 0 through 4095.
#

sub MakeSalt
{
	my $i = $_[0] >> 6;
	my $j = $_[0] % 64;
	my $SaltOut = substr($SaltList, $i, 1).substr($SaltList, $j, 1);
	$SaltOut;
}

#
# sub CryptPassword(A, B):  Encrypt the password provided; keep a running
# list of codes used as long as B is true.
#

sub CryptPassword
{
	my $ThisSeed = $SeedValue;
	if ($ThisSeed)
	{
		$ThisSeed--;
	}
	else
	{
		$_[1] or do
		{
			%UsedSeed = ();
		};
		$ThisSeed = Random(0, 4095);
		do
		{
			$ThisSeed = Random(0, 4095);
		}
		until not exists $UsedSeed{$ThisSeed};
		$UsedSeed{$ThisSeed} = $ThisSeed;
	}
	crypt($_[0], MakeSalt($ThisSeed));
}

#
# sub Md5Base64Char(A): Base-64-encode a character from an MD5 digest.
#

sub Md5Base64Char
{
	my $map64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
	my $char = shift;
	$char = 0 if $char < 0;
	$char = 63 if $char > 63;
	substr($map64, $char, 1);
}

#
# sub MakeMd5Salt(A, B):  Generate a crypt salt string from a number from 0
# through 4095.
#

sub MakeMd5Salt
{
	my $md5 = Digest::MD5->new();
	$md5->add(time);
	$md5->add($$);
	$md5->add($_[0]);
	$md5->add($_[1]);
	my $digest = $md5->digest;
	$digest = substr($digest, 0, 8);
	my $salt;
	for my $char (map { ord($_) & 077 } split //, $digest)
	{
		$salt .= Md5Base64Char($char);
	}
	$salt;
}

#
# sub CryptMd5Password(A, B):  Encrypt the password provided using the
# MD5 digest algorithm; keep a running list of codes used as long as B is
# true.
#

sub CryptMd5Password
{
	my $password = $_[0];
	eval "use Crypt::PasswdMD5";
	if ($@)
	{
		print STDERR "$Program:  Could not load the Crypt::PasswdMD5 library, cannot use --crypt-md5\n".
			"This may be due to an invalid or incomplete Perl installation\n.";
		exit 1;
	};

	my $ThisSeed = $SeedValue;
	if ($ThisSeed)
	{
		$ThisSeed--;
	}
	else
	{
		$_[1] or do
		{
			%UsedSeed = ();
		};
		$ThisSeed = Random(0, 4095);
		do
		{
			$ThisSeed = Random(0, 4095);
		}
		until not exists $UsedSeed{$ThisSeed};
		$UsedSeed{$ThisSeed} = $ThisSeed;
	}

	my $salt = MakeMd5Salt($password, $ThisSeed);
	unix_md5_crypt($password, $salt);
}

#
# sub ProcessPassword(A):  Process the password provided.
#

sub ProcessPassword
{
	my $i;
	my $Password = "";
	my $CryptedPass = "";
	my $PaddedPass = "";

	$Password = MakePassword();
	$Crypt and $PaddedPass = sprintf "%-$CharFormat"."s", $Password;
	$CryptMd5 and $PaddedPass = sprintf "%-$CharFormat"."s", $Password;
	$Verbose and do
	{
		$PassLabel="Password=";
		$CryptLabel="Encrypted String=";
		$EmptyPassword=sprintf "%-$CharFormat"."s", "";
		$ctr and $Verbose and print "\n";
	};
	for ($i = 0; $i < $PasswordRepeat; $i++)
	{
		if ($Crypt)
		{

			$CryptedPass = CryptPassword($Password, $i);
			print "$PassLabel"."$PaddedPass"."$CryptLabel"."$CryptedPass\n";
			$Verbose and $PaddedPass = $EmptyPassword;
		}
		elsif ($CryptMd5)
		{
			$CryptedPass = CryptMd5Password($Password);
			print "$PassLabel"."$PaddedPass"."$CryptLabel"."$CryptedPass\n";
			$Verbose and $PaddedPass = $EmptyPassword;
		}
		else
		{
			print "$PassLabel"."$Password\n";
		}
		$Verbose and do
		{
			$PassLabel="         ";
			$CryptLabel="                 ";
		};
	}
}

Zerion Mini Shell 1.0