Haskell - System.Process gives an error when password is required - shell

I am creating a Haskell program to automatically add a user to the system and then add it to samba, but it asks password, and I would like to use the same. I did not find any parameter we can use with smbclient to achieve such goal. What can I do?
Here is my code:
import System.Environment(getArgs)
import System.Process (createProcess, shell)
main = do
(user:pass:_) <- getArgs
putStrLn $ "Creating user " ++ user ++ " " ++ pass ++ "..."
callCommand $ "useradd " ++ user
callCommand $ "echo \"" ++ user ++ "\":\"" ++ pass ++ "\" | chpasswd"
putStrLn $ "User Created. Adding it to samba..."
callCommand $ "smbpasswd -a " ++ user
callCommand = createProcess . shell
Result:
-bash# runghc test.hs testUser 12345
Creating user testUser 12345...
User Created. Adding it to samba...
chpasswd: (user testUser) pam_chauthtok() failed, error:
Authentication token manipulation error
chpasswd: (line 1, user testUser) password not changed
-bash# New SMB password:
Retype new SMB password:
Failed to add entry for user testUser.
Can I pass the pass argument received from user to the smbclient program (or press Enter automatically), and avoid this error?

Use readCreateProcess:
readCreateProcess :: CreateProcess -> String -> IO String
The additional String will be passed to the command as standard input.

Related

how to alias `read -p` on linux bash and store the user input in variable

I need to set alias for this command below but am unable to.
read -p 'Enter namespc: ' rvar
setting alias as a shorcut:
export gvar="read -p 'Enter namespc: ' rvar"
Actual Result:
$gvar
-bash: read: `namespc:': not a valid identifier
Expected: should list below to user on prompt and then save its value in rvar.
$gvar
Enter namespc:
echo $rvar
testspace
Use a function instead of a variable (or an alias).
gvar () {
read -p 'Enter names-can: ' rvar
}
Ah Just realised, i need to use Alias not export.
answer is
alias gvar="read -p 'Enter namespc: ' rvar"
then call
gvar and echo $rvar to validate

Testing if a docopt command-line option is set in nim

I'm trying to write a nim program that can read either from the standard input or from a file given as a command-line option. I use docopt to parse the command line.
import docopt
const doc = """
This program takes input from a file or from stdin.
Usage:
testinput [-i <filename> | --input <filename>]
-h --help Show this help message and exit.
-i --input <filename> File to use as input.
"""
when isMainModule:
let args = docopt(doc)
var inFilename: string
for opt, val in args.pairs():
case opt
of "-i", "--input":
inFilename = $args[opt]
else:
echo "Unknown option" & opt
quit(QuitFailure)
let inputSource =
if inFilename.isNil:
stdin
else:
echo "We have inFilename: " & inFilename
open(inFilename)
The program compiles.
It doesn't crash when I give it a file on the command line:
$ ./testinput -i testinput.nim
We have inFilename: testinput.nim
But I get an IOError if I try to feed it from its stdin:
$ ./testinput < testinput.nim
We have inFilename: nil
testinput.nim(28) testinput
system.nim(2833) sysFatal
Error: unhandled exception: cannot open: nil [IOError]
How come inFilename.isNil is false, and yet the execution of the else branch tells me that inFilename "is" nil?
Is there a correct and elegant way to do this, using docopt?
I'm not familiar with docopt, but it seems to create an entry for each option in the doc, not for the options specified by user so your code's been getting args == {"--input": nil} and stringifying the nil.
The following will work correctly:
import docopt
const doc = """
This program takes input from a file or from stdin.
Usage:
testinput [-i <filename> | --input <filename>]
-h --help Show this help message and exit.
-i --input <filename> File to use as input.
"""
when isMainModule:
let args = docopt(doc)
var inFilename: string
if args["--input"]:
inFilename = $args["--input"]
if not inFilename.isNil:
echo "We have inFilename: " & inFilename
let inputSource =
if inFilename.isNil:
stdin
else:
open(inFilename)
Also note that you don't have to check for "-i" option as docopt knows it's an alias to "--input".
Instead of transforming the value of the option into a string with $, one can keep it as a Value, which is the type returned by docopt.
According to the documentation:
vkNone (No Value)
This kind of Value appears when there is an option which hasn't been set and has no default. It is false when converted toBool
One can apparently use the value of the option in a boolean expression, and it seems to be automatically interpreted as a bool:
import docopt
const doc = """
This program takes input from a file or from stdin.
Usage:
testinput [-i <filename> | --input <filename>]
-h --help Show this help message and exit.
-i --input <filename> File to use as input.
"""
when isMainModule:
let args = docopt(doc)
var inFilename: Value
for opt, val in args.pairs():
case opt
of "-i", "--input":
inFilename = val
else:
echo "Unknown option" & opt
quit(QuitFailure)
let inputSource =
if not bool(inFilename):
stdin
else:
echo "We have inFilename: " & $inFilename
open($inFilename)
Another usage of this behaviour is given in this other anwser, and avoids setting the variable, therefore keeping it nil.

Jacl script behaves wrongly in case of special characters \ ! ; $

Hi I have written one jacl script which is not working properly in case of ; $ ! \
test.jacl
set password [ lindex $argv 1 ]
puts "Hello your entered password is $password"
Script OUTPUT
When I run
../test.jacl testUser Foo\b4r*
it returns
Hello your entered password is Foob4r*
CASE 2:
../test.jacl testUser Foo$b4r*
OUTPUT
Hello your entered password is Foo*
CASE 3:
../test.jacl testUser Foo;b4r*
OUTPUT
Hello your entered password is Foo
CASE 3:
../test.jacl testUser Foo!b4r*
OUTPUT
-bash: !b4r*: event not found
Kindly suggest best way to overcome this problem

Changing an AIX password via script?

I am trying to change a password of a user via script. I cannot use sudo as there is a feature that requires the user to change the password again if another user changes their password.
AIX is running on the system.
unfortunately, chpasswd is unavailable.
I have expected installed, but I am having trouble with that also.
here is what I thought would work
echo "oldpassword\nnewpasswd123\nnewpasswd123" | passwd user
However once run the script I am prompted with please enter user's old password
shouldn't they all be echoed in?
I am a beginner with shell scripting and this has been baffled.
You can try:
echo "USERNAME:NEWPASSWORD" | chpasswd
Use GNU passwd stdin flag.
From the man page:
--stdin
This option is used to indicate that passwd should read the new password from standard input, which can be a pipe.
NOTE: Only for root user.
Example
$ adduser foo
$ echo "NewPass" |passwd foo --stdin
Changing password for user foo.
passwd: all authentication tokens updated successfully.
Alternatively you can use expect, this simple code will do the trick:
#!/usr/bin/expect
spawn passwd foo
expect "password:"
send "Xcv15kl\r"
expect "Retype new password:"
send "Xcv15kl\r"
interact
Results
$ ./passwd.xp
spawn passwd foo
Changing password for user foo.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
In addition to the other suggestions, you can also achieve this using a HEREDOC.
In your immediate case, this might look like:
$ /usr/bin/passwd root <<EOF
test
test
EOF
You need echo -e for the newline characters to take affect
you wrote
echo "oldpassword\nnewpasswd123\nnewpasswd123" | passwd user
you should try
echo -e "oldpassword\nnewpasswd123\nnewpasswd123" | passwd user
more than likely, you will not need the oldpassword\n portion of that command, you should just need the two new passwords. Don't forget to use single quotes around exclamation points!
echo -e "new"'!'"passwd123\nnew"'!'"passwd123" | passwd user
You can try :
echo -e "newpasswd123\nnnewpasswd123" | passwd user
Just this
passwd <<EOF
oldpassword
newpassword
newpassword
EOF
Actual output from ubuntu machine (sorry no AIX available to me):
user#host:~$ passwd <<EOF
oldpassword
newpassword
newpassword
EOF
Changing password for user.
(current) UNIX password: Enter new UNIX password: Retype new UNIX password:
passwd: password updated successfully
user#host:~$
This is from : Script to change password on linux servers over ssh
The script below will need to be saved as a file (eg ./passwdWrapper) and made executable (chmod u+x ./passwdWrapper)
#!/usr/bin/expect -f
#wrapper to make passwd(1) be non-interactive
#username is passed as 1st arg, passwd as 2nd
set username [lindex $argv 0]
set password [lindex $argv 1]
set serverid [lindex $argv 2]
set newpassword [lindex $argv 3]
spawn ssh $serverid passwd
expect "assword:"
send "$password\r"
expect "UNIX password:"
send "$password\r"
expect "password:"
send "$newpassword\r"
expect "password:"
send "$newpassword\r"
expect eof
Then you can run ./passwdWrapper $user $password $server $newpassword which will actually change the password.
Note: This requires that you install expect on the machine from which you will be running the command. (sudo apt-get install expect) The script works on CentOS 5/6 and Ubuntu 14.04, but if the prompts in passwd change, you may have to tweak the expect lines.
Here is the script...
#!/bin/bash
echo "Please enter username:"
read username
echo "Please enter the new password:"
read -s password1
echo "Please repeat the new password:"
read -s password2
# Check both passwords match
if [ $password1 != $password2 ]; then
echo "Passwords do not match"
exit
fi
# Does User exist?
id $username &> /dev/null
if [ $? -eq 0 ]; then
echo "$username exists... changing password."
else
echo "$username does not exist - Password could not be updated for $username"; exit
fi
# Change password
echo -e "$password1\n$password1" | passwd $username
Refer the link below as well...
http://www.putorius.net/2013/04/bash-script-to-change-users-password.html
You can try
LINUX
echo password | passwd username --stdin
UNIX
echo username:password | chpasswd -c
If you dont use "-c" argument, you need to change password next time.
If you can use ansible, and set the sudo rights in it, then you can easily use this script. If you're wanting to script something like this, it means you need to do it on more than one system. Therefore, you should try to automate that as well.
For me this worked in a vagrant VM:
sudo /usr/bin/passwd root <<EOF
12345678
12345678
EOF
printf "oldpassword/nnewpassword/nnewpassword" | passwd user
#!/usr/bin/python
import random
import string
import smtplib
import sys
import os
from subprocess import call
import socket
user = sys.argv[1]
receivers = ["%s#domain.com" %user]
'''This will generate a 30 character random password'''
def genrandpwd():
return ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits + string.ascii_uppercase + string.punctuation) for _ in range(30))
def change_passwd(user, password):
p = os.popen("/usr/bin/passwd %s" %user, "w")
p.write(password)
p.write("\n")
p.write(password)
p.close()
def chage(user):
agepasswd = call(["/usr/bin/chage", "-d", "0", "%s" %user])
def mailpwd(user, password):
sender = "admin#%s" %socket.gethostname()
subj = "!!!IMPORTANT!!!, Unix password changed for user %s" %user
text = "The password for the %s user has changed, the new password is:\n\n %s \n\n Note: The system will force to change the password upon initial login. Please use the password provided in the mail as your current password and type the password of your choice as the New password" %(user, password)
message = message = 'Subject: %s\n\n%s' % (subj, text)
smtpObj = smtplib.SMTP('mailrelay-server.domain.com')
smtpObj.sendmail(sender, receivers, message)
smtpObj.quit()
def main():
newpwd = genrandpwd()
change_passwd(user, newpwd)
chage(user)
mailpwd(user, newpwd)
if __name__ == "__main__":
main()

Hide password using expect script

I used the script to log into the power broker and connected
ssh through the network. As per my knowledge every single more is
tracked. I am ok with that.
My question is how to hide the password, below sample I tried:
#!/usr/bin/expect -f
set timeout 2
spawn pbrun /bin/su - big_admin
expect {
"Password for casper#BIG_BANK.COM:" {send "foobar_pass!\r" ; exp_continue }
"*$*" ;
}
interact
I tried storing my password in a /home/casper/.password and then doing a chmod 400 on it and then
putting it in the {send "/home/casper/.password\r" exp continue}, but it did not work.
Any ideas?
Source : http://wiki.tcl.tk/3594
Procedure to encrypt device passwords
Takes pd (password list to be encrypted) and filename (name of file for resulting encrypted password list) as input
Returns nothing
Format of the list of passwords (current and older generations by device type?) depends on how calling program needs them - suggest separated by \n character for readability
proc utility_encrypt {pd filename} {
global key HOME
#catch [exec echo "$pd" | des -e -k $key -b > $HOME/pwdir/$filename]
catch [exec des -e -k $key -b > [file join $HOME pwdir $filename] << $pd]
return
}
Procedure to decrypt device passwords
Takes filename (name of password file to decrypt)
Returns dpd (list of passwords in plaintext)
proc utility_decrypt filename {
global key HOME
catch {exec cat $HOME/pwdir/$filename | des -d -b -k $key} dpd
# Some people write the previous command as
# catch {exec des -d -b -k $key < $HOME/pwdir/$filename} dpd
return $dpd
}

Resources