How to generate password for users and send them email? - bash

I have a file with the list of users, I found a way how to generate for each user random password, but didn't know how to select each user their username and password and send them via email (email example username#example.com)
the script sends each user an email with each password from the file, that is, if there are 5 users, then each of them will receive 5 emails and 5 different passwords.
Generate Password
#!/bin/bash
file=$(cat /tmp/user_names.txt)
for line in $file
do
passrand=$(openssl rand -base64 12)
echo -e "$line" "$passrand"
done
Send email
#!/bin/bash
for maillogin in $(cut -f1 -d ' ' /tmp/u_p.txt) || pass=$(cut -f2 -d' ' /tmp/u_p.txt)
do
for pass in $(cut -f2 -d' ' /tmp/u_p.txt)
do
echo "Hello your login is" $maillogin "and password is" $pass | mail -s "Test Mail" "${maillogin}#example.com"
done
done

Your first script is ok.
For the second, you need to read line after line. So, do not use nested loops to read login and password. Use read command and decompose line:
#!/bin/bash
UP_FILE="/tmp/u_p.txt"
while read -r
do
# maillogin <- line without any characters *after first* space (space included)
maillogin="${REPLY%% *}"
# pass <- line without any characters *before first* space (space included)
pass="${REPLY#* }"
echo "Hello your login is $maillogin and password is $pass" | mail -s "Test Mail" "${maillogin}#example.com"
done < "${UP_FILE}"

Related

If statement matching words separated by special char

I'm new to unix. I have a file with an unknown amount of lines in format: "password, username" and I'm trying to make a function that checks this file against user inputted login.
What I have so far:
Accounts file format:
AAA###, firstname.lastname
echo "Please enter Username:"
read username
if cut -d "," -f2 accounts | grep -w -q $username
then
echo "Success"
fi
This function will return Success for inputs "firstname" "lastname" and "firstname.lastname" when I only want it to return for "firstname.lastname"
Any help would be appreciated.
You could go for an exact match, with ^ and $ anchors, like this:
echo "Please enter Username:"
read username
if cut -d "," -f2 accounts | grep -q "^$username$"; then
echo "Success"
fi
While this would work even when the user gives an empty input, you might want to explicitly check for that.
If you loop over the file within the shell, you can use string equality operators instead of regular expressions:
read -rp "enter Username (first.last): " username
shopt -s extglob
found=false
while IFS=, read -r pass uname _othertext; do
# from your question, it looks like the separator is "comma space"
# so we'll remove leading whitespace from the $uname
if [[ "$username" = "${uname##+([[:blank:]])}" ]]; then
echo "Success"
found=true
break
fi
done < accounts
if ! $found; then
echo "$username not found in accounts file"
fi
while read loops in the shell are very slow compared to grep, but depending on the size of the accounts file you may not notice.
Based on your comment, the issue is that the field separator is a comma then a space, not just a comma. cut can't do multi-character delimiters, but awk can. In your code, replace
cut -d "," -f2
with
awk -F ", " '{print $2}'
By the way, there are a few things needed to guard against user input:
# Use "-r" to avoid backslash escapes.
read -rp "Please enter Username:" username
# Always quote variables ("$username").
# Use "grep -F" for fixed-string mode.
# Use "--" to prevent arguments being interpreted as options.
if awk -F ", " '{print $2}' accounts | grep -wqF -- "$username"; then
echo "Success"
fi

issue with my bash script

I'm quite new to bash. I'm trying to achieve a quite easy thing but it looks like extremely complicated...
I'm trying to read variables from a file (ip address, username, password) and connect to firewalls to change them.
The file is around 100 lines and I'm trying to read one by one, chose the IP address of the firewall from the 2nd column, first username and pass from the 3rd and 4th column, second username and pass from the 5th and the 6th column.
The file looks like:
Office1 IP uname1 pass1 uname2 pass2
Office2 IP uname1 pass1 uname2 pass2
All the raws are separated by tabs
The script looks like this one:
#!/bin/bash
office=`awk '{print $1}' TEST.txt`
user1=`awk '{print $3}' TEST.txt`
user2=`awk '{print $5}' TEST.txt`
password1=`awk '{print $4}' TEST.txt`
password2=`awk '{print $6}' TEST.txt`
/usr/bin/expect <<EOF
for p in `cat TEST.txt | awk '{print $2}'`
do
# echo $user1 ", " $password1", " $user2", "$password2"
set timeout 20
spawn telnet $p
expect "login:"
send "cipollone"
send \r
expect "password:"
send "mypass"
send \r
expect ">"
send "set admin user $user1 password $password1 privilege all"
send \r
expect ">"
send "set admin user $user2 password $password2 privilege all"
send \r
expect ">"
send "save"
send \r
expect ">"
send "exit"
send \r
send \r
send \r
# echo $office $p "DONE"
# echo \r
# echo $office $p "DONE" >> results.txt
# echo \r >> results.txt
exit
EOF
done < TEST.txt
The general structure of your script should be:
while read office ip user1 password1 user2 password2
do
/usr/bin/expect <<EOF
...
EOF
done < TEST.txt
Follow #Barmar's advice. Additionally:
for p in `cat TEST.txt | awk '{print $2}'` is not valid expect
when using here-docs, the terminating word EOF must appear without any leading whitespace.

Bash Script Help Needed

So I'm working on an assignment and I'm very close to getting it. Just having issues with the last part. Here is the whole problem I guess, just so you know what I'm trying to do -
Write a shell script called make_uid which creates user login names given a file containing the user's full name. Your script needs to read the newusers file, and for each name in the file create a login name which consists of the first character of the users first name, and up to 7 characters of their last name. If the last name is less than seven characters, use the entire last name. If the user only has one name, use whatever is provided as a name (in the newusers file) to generate an 8 character long login name. Note: login names need to be all lower case!
Once you have created a login name, you need to check the passwd file to make sure that the login name which you just created does not exist. If the name exists, chop off the last character of the name that you created, and add a digit (starting at 1) and check the passwd file again. Repeat this process until you create a unique user login name. Once you have a unique user name, append it to the passwd file, and continue processing the newusers file.
This is my code so far. At this point, it makes a full passwd file with all of the login names. I'm just having trouble with the final step of sorting through the list and editing duplicates accordingly.
#!/bin/bash
#Let's make some login names!
declare -a first
declare -a last
declare -a password
file=newusers
first=( $(cat $file | cut -b1 | tr "[:upper:]" "[:lower:]" | tr '\n' ' ') )
for (( i=0; i<${#first[#]}; i++)); do
echo ${first[i]} >> temp1
done
last=( $(cat $file | awk '{print $NF}' $file | cut -b1-7 | tr "[:upper:]" "[:lower:]"))
for (( i=0; i<${#last[#]}; i++)); do
echo ${last[i]} >> temp2
done
paste -d "" temp1 temp2 >> passwd
sort -o passwd passwd
more passwd
rm temp1 temp2
Well, I probably shouldn't be answering a homework assignment but maybe it will help you learn.
#!/bin/bash
infile=./newusers
outfile=./passwd
echo -n "" > $outfile
cat $infile | while read line; do
read firstName lastName < <(echo $line)
if [ -z "$lastName" ]; then
login=${firstName:0:8}
else
login=${firstName:0:1}${lastName:0:7}
fi
digit=1
while fgrep -q $login $outfile; do
login=${login%?}$digit
let digit++
done
echo $login >> $outfile
done
There may be some way to do the fgrep check in a single command instead of a loop but this is the most readable. Also, your problem statement didn't say what to do if the name was less than 8 characters so this solution doesn't address that and will produce passwords that are short if the names are short.
Edit: The fgrep loop assumes that there will be fewer than 10 duplicates. If not, you need to make it a bit more robust:
lastDigit="?"
nextDigit=1
while fgrep -q $login $outfile; do
login=${login%$lastDigit}$nextDigit
let lastDigit=nextDigit
let nextDigit++
done
Add all user names into another file before adding the digit. Use fgrep -xc theusername thisotherfile, this returns a digit. Append the digit to the login name if it's not 0.

Create users based on a text file using Bash script?

So, I have a text file that is organized like this
<username>:<fullname>:<usergroups>
I need to create a new user for each line and put them into their groups. I am stuck with trying to set username into a variable to use with useradd. I have tried using cut but it needs a file name, I can't just pass it a line.
Here is what I currently have:
#! /bin/bash
linesNum=1
while read line
do
echo
name=$( cut -d ":" -f1 $( line ) )
((lineNum+=1))
done < "users.txt"
Thanks for your help!
#!/bin/bash
while IFS=: read username fullname usergroups
do
useradd -G $usergroups -c "$fullname" $username
done < users.txt
fullname is the only string that should contains whitespace (hence the quotes), A list of usergroups should be separated from the next by a comma, with no intervening whitespace (so no quotes on that argument) and your username should not contain whitespace either.
Upate:
To get the list of usergroups to create first you can do this...
#!/bin/bash
while IFS=: read username fullname usergroups
do
echo $usergroups >> allgrouplist.txt
done < users.txt
while IFS=, read group
do
echo $group >> groups.txt
done < allgrouplist.txt
sort -u groups.txt | while read group
do
groupadd $group
done
This is a bit long winded, and could be compacted to avoid the use of the additional files allgrouplist.txt and groups.txt but I wanted to make this easy to read. For reference here's a more compact version.
sort -u < $(
echo $(while IFS=: read a b groups; do echo $groups; done < users.txt )
| while IFS=, read group; do echo $group; done )
| while read group
do
groupadd $group
done
(I screwed the compact version up a bit at first, it should be fine now, but please note I haven't tested this!)
IFS=: while read username fullname usergroups
do
useradd -G "$usergroups" -c "$fullname" "$username"
done < users.txt

encrypting/decrypting password stored in config file

I have a simple Bash script automating tasks which require password-based authentication.
Currently I store the credentials in plain text:
$ cat ~/.myconfig
username=foo
password=bar
Obviously that's bad - so I wonder whether there's a simple way to encrypt/decrypt the password using my public/private key pair. Using Yet Another Password for the encryption wouldn't gain much, so I want it to happen pretty much automatically.
I've done some research (around here and elsewhere), but am way out of my depth on this one...
You can store password into md5 sum, add some salt before.
create:
\#!/bin/bash
salt=12345_
protocol=sha1sum
read -p "Enter login: " username
read -p -s "Password: " pass1
read -p -s "Repeat: pass2
if [ "pass1 != pass2" ]; then echo "Pass missmatch"; exit 1; else password=pass1; fi
echo -en "$username " >> ./mypasswd
echo -e "${salt}${password} | $protocol | awk '{print $1}'" >> ./mypqsswd
read:
\#!/bin/bash
salt=12345_ #(samesalt)
protocol=sha1sum
read -p "Enter username: " username
read -p -s "Enter password: " password
if [ `grep $username ./mypasswd | awk '{print $2}' != `echo -e "`echo ${salt}${password} | $protocol | awk '{print $2}'`" ]; then echo -e "wrong username or password"; exit 127; else echo -e "login successfull"; fi
There's your code.
To automate your task means providing the password; it won't make a difference is you encrypt/obfuscate the password, you'll need to provide the decrypting too.
The only way around this dilemma is an agent-like program, as for example ssh-agent, which stores your passwords for you.
(edit: corrected link)
If you simply want to hide the password then store its SHA1 hash. The compare the hash of the entered password with your stored hash.

Resources