#!/bin/sh - # # Script to generate good passwords (i.e. random and non-reproducible), # among other things. Type "genpwd -h" for usage information. # Works on FreeBSD. For other systems, you might have to change # a few of the *stat calls. # # Copyright (C) 2001 Oliver Fromme # 2-clause BSD-style license and disclaimer applies. # PATH=/bin:/usr/bin:/sbin:/usr/sbin CDEF="lludds" NDEF=8 WDEF=8 Usage() { ME=`basename $0` cat <<-tac >&2 Usage: $ME [-luds] [-c ] [-n ] [-w ] -l include lowercase letters -u include uppercase letters -d include digits -s include special characters -c include characters from -n print passwords (default: $NDEF) -w make characters per passwords (default: $WDEF) -m separate by spaces instead of newlines Repeat an option to use more of this kind of characters. The default is -$CDEF. Examples of advanced uses: If you're upset, use this command to express your feelings: $ME -w4 -n30 -cargl To generate a labyrinth, try this one: $ME -w20 -n20 -c'/\' tac exit 1 } CUSE="" NUSE=$NDEF WUSE=$WDEF CADD="" NEWL=1 # # The following emulates pretty well the standard UNIX # parsing of command line options and arguments. # while [ $# -gt 0 ]; do if [ "$GETC" = 1 ]; then CADD="$1$CADD" GETC=0 shift continue fi if [ "$GETN" = 1 ]; then NUSE="$1" GETN=0 shift continue fi if [ "$GETW" = 1 ]; then WUSE="$1" GETW=0 shift continue fi OPT="$1" if ! expr "x$OPT" : 'x-.[^-]*$' >/dev/null; then break # End of option parsing. fi while :; do OPT=`expr "x$OPT" : 'x.\(.*\)$'` case "$OPT" in "") shift break # End of this option string. ;; [luds]*) CUSE=`expr "$OPT" : '\(.\)'`$CUSE ;; m*) NEWL=0 ;; c) GETC=1 ;; c?*) CADD=`expr "x$OPT" : 'x.\(.*\)$'`"$CADD" OPT="" ;; n) GETN=1 ;; n?*) NUSE=`expr "x$OPT" : 'x.\(.*\)$'`"$CADD" OPT="" ;; w) GETW=1 ;; w?*) WUSE=`expr "x$OPT" : 'x.\(.*\)$'`"$CADD" OPT="" ;; -) shift break 2 # End of option parsing. ;; *) echo "\"$OPT\"" Usage ;; esac done done if [ $# -gt 0 -o "$GETC" = 1 -o "$GETN" = 1 -o "$GETW" = 1 ]; then # Some non-option arguments left, or option arguments missing. Usage fi if ! expr "$NUSE" : '[0-9][0-9]*$' >/dev/null; then # Not an integer number. Usage fi if ! expr "$WUSE" : '[0-9][0-9]*$' >/dev/null; then # Not an integer number. Usage fi if [ $WUSE -lt 1 ]; then Usage fi if [ -z "$CUSE" -a -z "$CADD" ]; then CUSE=$CDEF fi export CUSE CADD NUSE WUSE NEWL I=0 MAXBLA=`expr \( $NUSE \* $WUSE + 15 \) / 16` while [ $I -lt $MAXBLA ]; do { # Generate some non-reproducible "randomness" ... echo $$ if [ -r /dev/urandom ]; then dd if=/dev/urandom bs=16 count=1 2>/dev/null elif [ -r /dev/random ]; then dd if=/dev/random bs=16 count=1 2>/dev/null fi netstat -na netstat -bin netstat -s netstat -m ps -auxww iostat vmstat vmstat -i vmstat -s vmstat -m vmstat -z pstat -f pstat -t } 2>/dev/null \ | md5 I=`expr $I + 1` done \ | awk ' BEGIN { nuse = ENVIRON["NUSE"]; wuse = ENVIRON["WUSE"]; cuse = ENVIRON["CUSE"]; cset = ENVIRON["CADD"]; newl = ENVIRON["NEWL"]; for (i = 1; i <= length(cuse); i++) { ch = substr(cuse, i, 1); if (ch == "l") cset = "abcdefghijkmnpqrstuvwxyz" cset; else if (ch == "u") cset = "ABCDEFGHJKLMNPQRSTUVWXYZ" cset; else if (ch == "d") cset = "23456789" cset; else cset = "!@#$%&*-+=/." cset; } clen = length(cset); for (i = 0; i < 256; i++) { ch = substr(cset, 1 + i % clen, 1); c[sprintf("%02x", i)] = ch; c[sprintf("%02X", i)] = ch; } ccount = 0; lcount = 0; } { while ($0 ~ /^[0-9A-Fa-f][0-9A-Fa-f]/) { if (lcount >= nuse) exit; printf "%c", c[substr($0, 1, 2)]; if (++ccount % wuse == 0) { printf (newl ? "\n" : " "); lcount++; } $0 = substr($0, 3); } } END { if (ccount % wuse != 0 || !newl) printf "\n"; } ' #--