Process substitution not working with sudo - bash

From a main bash script run as root, I want to execute a subprocess using sudo as unpriviledge user nobody; that subprocess should source a file, which content is provided by the main script.
I am trying to solve this using bash process substitution. But I cannot manage to get this to work.
Can someone tell me why the following script, ...
#! /bin/bash
sudo -u nobody \
bash -c 'source /dev/stdin || ls -l /dev/stdin /proc/self/fd/0 /proc/$$/fd/0; echo "A=$A"' \
< <(echo "A=$(ls /root/.profile)")
... when run as root, produces the following ouput ?
root#raspi:~# ./test3.sh
bash: line 1: /dev/stdin: Permission denied
lrwxrwxrwx 1 root root 15 Mar 20 20:55 /dev/stdin -> /proc/self/fd/0
lr-x------ 1 nobody nogroup 64 Aug 21 14:38 /proc/3243/fd/0 -> 'pipe:[79069]'
lr-x------ 1 nobody nogroup 64 Aug 21 14:38 /proc/self/fd/0 -> 'pipe:[79069]'
A=
I would expect reading from stdin to work because, as indicated by ls -l, read access to stdin is granted to nobody (which makes sense).
So why this does not work ? And is there any way to get this to work ?
Answers to this question did not help: as sample above shows, code in the <(...) bloc should access data that only root can.

To see why you have Permission denied, use ls -lL
sudo -u nobody \
bash -c 'source /dev/stdin || ls -lL /dev/stdin /proc/self/fd/0 /proc/$$/fd/0; echo "A=$A"' \
< <(echo "A=$(ls /root/.profile)")
To get around the error, use cat |
sudo -u nobody \
bash -c 'cat | { source /dev/stdin || ls -lL /dev/stdin /proc/self/fd/0 /proc/$$/fd/0; echo "A=$A"; }' \
< <(echo "A=$(ls /root/.profile)")

Related

How do I inject a variable value into a command that prompts for a password within a bash script [duplicate]

I am trying to do ssh-add from script (don't care about about security at the moment).
Now ssh prompts for passphrase, which needs to be automated, so i read couple of things like this and found expect.
And now i do following:
eval `ssh-agent -s`
script tmp.sh defined as :
#!/usr/bin/expect
spawn ssh-add /root/.ssh/id_rsa
expect "Enter passphrase for /root/.ssh/id_rsa:"
send "my_pass"
interact
./tmp.sh
ssh-add -l
If ssh-add would have worked it shows something like
4096 SHA256:wlfP/nhVSWXLcljBOen5GSYZXJGgfi/XJWfZeBwqRsM id_rsa (RSA)
But instead i get The agent has no identities. Seems like ssh-agent looses it's context.
Am open to other solutions to do this.
Personally, I find the use of expect a bit cumbersome. The following approach found how to make ssh-add read passphrase from a file rather informative.
So if your version of ssh-add allows the -p argument and you are not worried about security then this should work:
#!/bin/bash
# store a file somewheres with your passphrase. For example's sake
# I'll just use $HOME/.myscrt
<$HOME/.myscrt ssh-add -p ~/.ssh/id_rsa
Now if -p is not an option for you, I found the second method mildly ingenious:
#!/bin/bash
# Same passfile and some minor enhancements from the OP of the linked
# solution
PASS="$(<$HOME/.myscrt)"
# the following is just a one-liner method of making an executable
# one-line script echoing the password to STDOUT
install -vm700 <(echo "echo $PASS") "$PWD/ps.sh"
# then the magic happens. NOTE: your DISPLAY variable should be set
# for this method to work (see ssh-add(1))
[[ -z "$DISPLAY" ]] && export DISPLAY=:0
< id_rsa SSH_ASKPASS="$PWD/ps.sh" ssh-add - && shred -n3 -uz $PWD/ps.sh
When I tested the script I called "j", see below:
$ cd /tmp
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/me/.ssh/id_rsa): /tmp/id_rsa
Enter passphrase (empty for no passphrase): asdfasdf
Enter same passphrase again: asdfasdf
Your identification has been saved in /tmp/id_rsa.
Your public key has been saved in /tmp/id_rsa.pub.
The key fingerprint is:
ed:1a:ae:c7:ac:47:5e:31:98:8e:18:8f:1c:67:94:6d jimconn#redapt-240
The key's randomart image is:
+--[ RSA 2048]----+
| o |
| o E |
| . . o |
| o o o.o |
| . O oS .o |
| + o o.. |
| =... |
| .*o |
| o=o |
+-----------------+
$ echo 'asdfasdf' > ~/.myscrt
$ chmod 0600 ~/.myscrt
$ ls -altr ~/.myscrt
-rw------- 1 me me 9 Feb 16 19:00 /home/me/.myscrt
$ cat ~/.myscrt
asdfasdf
$ ls -ltr
total 12
-rw-r--r-- 1 me me 400 Feb 16 18:59 id_rsa.pub
-rw------- 1 me me 1766 Feb 16 18:59 id_rsa
-rwx------ 1 me me 151 Feb 16 19:04 j
$ cat j
#!/bin/bash
PASS="$(<$HOME/.myscrt)"
install -vm700 <(echo "echo $PASS") "$PWD/ps.sh"
cat id_rsa | SSH_ASKPASS="$PWD/ps.sh" ssh-add - && shred -n3 -uz $PWD/ps.sh
$ ./j
‘/dev/fd/63’ -> ‘/tmp/so/ps.sh’
Identity added: (stdin) ((stdin))
$ ls
id_rsa id_rsa.pub j
So, one thing to quickly note about this method is that listing the identities loaded into ssh-agent will only show that stdin was loaded:
$ ssh-add -D
All identities removed.
$ ssh-add -l
2048 ed:1a:ae:c7:ac:47:5e:31:98:8e:18:8f:1c:67:94:6d (stdin) (RSA)
$ ./j
‘/dev/fd/63’ -> ‘/tmp/so/ps.sh’
Identity added: (stdin) ((stdin))
$ ssh-add -l
2048 ed:1a:ae:c7:ac:47:5e:31:98:8e:18:8f:1c:67:94:6d (stdin) (RSA)
UPDATED BECAUSE THE FIRST ONE DID NOT WORK
I did not try this, but if it is realy about expect loosing the context, it might be a good idea to set it up later:
auto-passphrase-add.expect (replacing tmp.sh)
/usr/bin/expect
spawn ./ssh-agent-ssh-add.sh /root/.ssh/id_rsa
expect "Enter passphrase for /root/.ssh/id_rsa:"
send "my_pass"
interact
ssh-agent-ssh-add.sh
#!/bin/sh
eval `ssh-agent -s`
ssh-add "$#"

Behaviour of /dev/stdout in Cygwin

I have a script (executed with zsh 5.8; but this should not be relevant in this case) in a Cygwin environment, which takes as parameter the name of some output file and writes to this files via redirection in various places, like this:
outfile=$1
: >$outfile # Ensure that the file exists and is empty.
.... do some work
command_x >>$outfile
.... do more work
command_y >>$outfile
... and so on
I would like to modify the behviour of the script in that if no parameter is supplied, the output of the commands goes to standard output instead. I thought that it would be sufficient to modify the script in one line:
outfile=${1:-/dev/stdout}
But nothing is written to stdout. Investigating the case further, I found that instead a regular file named stdout had been created in the /dev directory. It seems that in the Cygwin environment, /dev/stdout does not represent the standard output of the process.
How would I achieve my goal under Cygwin?
UPDATE
As requested by #matzeri, here is a simple testcase:
echo x >/dev/stdout
Expected behaviour: Seeing x on stdout
Real behaviour: A regular file /dev/stdout has been created
on a standard windows installation the /dev/std* are a symlink to the /proc/self/fd/*
ls -l /dev/std*
lrwxrwxrwx 1 Marco Kein 15 Jun 19 2018 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 Marco Kein 15 Jun 19 2018 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 Marco Kein 15 Jun 19 2018 /dev/stdout -> /proc/self/fd/1
if for any reason that is not anymore true they can be recreated
by /etc/postinstall/bash.sh.done script
$ grep self /etc/postinstall/bash.sh.done
/bin/test -h /dev/stdin || ln -sf /proc/self/fd/0 /dev/stdin || result=1
/bin/test -h /dev/stdout || ln -sf /proc/self/fd/1 /dev/stdout || result=1
/bin/test -h /dev/stderr || ln -sf /proc/self/fd/2 /dev/stderr || result=1
/bin/test -h /dev/fd || ln -sf /proc/self/fd /dev/fd || result=1
In that condition the command
$ echo x > /dev/stdout
x
produces the expected output on both Bash and Zsh

sudo without password is not giving any output

all "myscript.sh" does right now is echo "hello".
[jack#server1 scripts]$ ./myscript.sh
hello
the root user gave me the option to run the script as root without a password but when I do, the script doesn't print the "hello"
[jack#server1 scripts]$ sudo ./myscript.sh
Password:
[jack#server1 scripts]$
what am I doing wrong here? do I need to add some kind of switch ?
I don't see anything about this in man sudo
by the way, obviously I don't have root access to configure anything about this
this is the content of the script:
#!/bin/bash +xv
echo "hello"
and about the permissions and ownership:
[jack#server1 scripts]$ls -l myscript.sh
-rwxrwxr-x 1 jack SiteAdmin 1279 Dec 4 07:54 myscript.sh

FTP not working UNIX

hi i have a script where i am performing sudo and going to particular directory,and within that directory editing files name as required. After getting required file name i want to FTP files on windows machine but script after reading FTP commands says-:
-bash: line 19: quote: command not found
-bash: line 20: quote: command not found
-bash: line 21: put: command not found
-bash: line 22: quit: command not found
My ftp is working if i run normally so it is some other problem.Script is below-:
#!/usr/bin/
path=/global/u70/glob
echo password | sudo -S -l
sudo /usr/bin/su - glob << 'EOF'
#ls -lrt
cd "$path"
pwd
for entry in $(ls -r)
do
if [ "$entry" = "ADM" ];then
cd "$entry"
FileName=$(ls -t | head -n1)
echo "$FileName"
FileNameIniKey=$(ls -t | head -n1 | cut -c 12-20)
echo "$FileNameIniKey"
echo "$xmlFileName" >> "$xmlFileNameIniKey.ini"
chmod 755 "$FileName"
chmod 755 "$FileNameIniKey.ini"
ftp -n hostname
quote USER ftp
quote PASS
put "$FileName"
quit
rm "$FileNameIniKey.ini"
fi
done
EOF
You can improve your questions and make them easier to answer and more useful for future readers by including a minimal, self-contained example. Here's an example:
#!/bin/bash
ftp -n mirrors.rit.edu
quote user anonymous
quote pass mypass
ls
When executed, you get a manual FTP session instead of a file listing:
$ ./myscript
Trying 2620:8d:8000:15:225:90ff:fefd:344c...
Connected to smoke.rc.rit.edu.
220 Welcome to mirrors.rit.edu.
ftp>
The problem is that you're assuming that a script is a series of strings that are automatically typed into a terminal. This is not true. It's a series of commands that are executed one after another.
Nothing happens with quote user anonymous until AFTER ftp has exited, and then it's run as a shell command instead of being written to the ftp command.
Instead, specify login credentials on the command line and then include commands in a here document:
ftp -n "ftp://anonymous:passwd#mirrors.rit.edu" << end
ls
end
This works as expected:
$ ./myscript
Trying 2620:8d:8000:15:225:90ff:fefd:344c...
Connected to smoke.rc.rit.edu.
220 Welcome to mirrors.rit.edu.
331 Please specify the password.
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
200 Switching to Binary mode.
229 Entering Extended Passive Mode (|||19986|).
150 Here comes the directory listing.
drwxrwxr-x 12 3002 1000 4096 Jul 11 20:00 CPAN
drwxrwsr-x 10 0 1001 4096 Jul 11 21:08 CRAN
drwxr-xr-x 18 1003 1000 4096 Jul 11 18:02 CTAN
drwxrwxr-x 5 89987 546 4096 Jul 10 10:00 FreeBSD
ftp -n "ftp://anonymous:passwd#mirrors.rit.edu" << end
Name or service not known

./script.sh: line 8: /etc/passwd: Permission denied

I have this script which I can't execute:
#!/bin/bash
USERS="/etc/passwd"
for user in `$USERS | cut -f 1 -d ':'`
do
echo $user
done
This is the output of ls -l script.sh:
-rwxrwxrwx 1 user user 94 Jul 30 21:24 script.sh
What am I doing wrong? :|
I also tried running it as root and with sudo and nothing worked...it's annoying...
You're trying to execute /etc/passwd and send the output to cut. You want to redirect the contents of the file:
for user in `cut -f 1 -d : < $USERS`

Resources