Owner cannot create file in folder with all permission Linux - linux

I'm trying to create few files under folder with script, but not able to.
following is the folder privilege under which some files are to be created
su pnaid
The partial script content, responsible to create folder and create files in it
MKDIR_CMD="/bin/mkdir -p \"${PATH_TO_WRITE}\" > /dev/null 2>&1"
"${MKDIR_CMD}"
echo "Checking Dir Path exist"
if [ -d "${PATH_TO_WRITE}" ]; then
echo "Calling another script to create files under this folder"
"/createFiles.sh \"${PATH_TO_WRITE}\""
else
echo "WARNING: unable to create folder"
The parent folder to the $(PATH_TO_WRITE) has following privileges
drwxr-x---. 2 pnaid pnaid 4096 Dec 3 12:31 work_directory
Each time the statement "WARNING: unable to create folder" is displayed.
I tried creating a folder with pnaid user having 777 permission and feeding that in script instead of "${MKDIR_CMD}", in that case the statement "Calling another script to create files under this folder" is displayed but the other script is not able to write to this folder.
Also the echo statements from createFiles.sh when called from original script are not displayed, is there any way to view it.
If we perform the same commands on shell prompt instead of script, the commands work and desired output is obtained; i.e. folder is created with all the files in it.
Also the same script works if we run it with user root.
I believe this should work across Linux flavors, in this case I'm using CentOS
Please help me resolve this issue and let me know if I have missed mentioning any details.
Thanks

This line:
"${MKDIR_CMD}"
will not work. It treats the entire value of $MKDIR_COMMAND as the name of the program to run, it doesn't split it into the program and arguments, because you put quotes around it. Also, redirections are not processed when expanding a variable.
You need to use eval to re-parse the string:
eval "$MKDIR_CMD"
You have the same problem with:
"/createFiles.sh \"${PATH_TO_WRITE}\""
This should be:
/createFiles.sh "$PATH_TO_WRITE"
These problems don't depend on permissions, I doubt the script really works when run as root.
Here's a related question that shows how to store command parameters best in variables:
Setting an argument with bash
However, the solution there (using an array instead of a string) won't work if you're also storing shell operators like redirection.

Related

Linux setuid bit [duplicate]

I created this simple script to allow the user to remove files created by the web server in his home directory without giving him "su". Both scripts are set with "chmod 4750".
The craziest thing is that they DID work and now they don't. Here's the scripts:
#!/bin/bash
# Ask for directory to delete
echo "Enter the file or directory you would like to delete, the assumed path is /home/user"
read DIRECTORY
rm -rf /home/user/"$DIRECTORY"
echo "Deleting /home/user/$DIRECTORY ..."
exit 0
2:
#!/bin/bash
# Reset permissions
echo "Resetting the ownership of the contents of /home/user to user."
chown -R user /home/user
exit 0
I will make them a little more advanced and work for multiple users but right now I cannot even get the simple version to work. It works when run as root of course. It used to work when run as user 'user' but now it doesn't. I get this:
user#dev:/home/user$ delete.sh
Enter the file or directory you would like to delete, the assumed path is /home/user/[your input]
test-dir
rm: cannot remove ‘/home/user/test-dir/test-file’: Permission denied
Deleting /home/user/test-dir ...
and
chown: changing ownership of ‘/home/user/test-dir’: Operation not permitted
What can possibly be the problem?
-rwsr-x--- 1 root user 291 Nov 6 05:23 delete.sh
-rwsr-x--- 1 root user 177 Nov 6 05:45 perms.sh
There is a pretty comprehansive answer at https://unix.stackexchange.com/questions/364/allow-setuid-on-shell-scripts
Bottom line is that there are two main points against it:
A race condition between when the Kernel opens the file to find which interpreter it should execute and when the interpreter opens the file to read the script.
Shell scripts which execute many external programs without proper checks can be fooled into executing the wrong program (e.g. using malicious PATH), or expand variables in a broken way (e.g. having white space in variable values), and generally it has less control on how well the external programs it executes handle the input.
Historically, there was a famous bug in the original Bourne shell (at least on 4.2BSD, which is where I saw this in action) which allowed anyone to get interactive root shell by creating a symlink called -i to a suid shell script. That's possibly the original trigger for this being prohibited.
EDIT: To answer "How do I fix it" - configure sudo to allow users to execute only these scripts as user root, and perhaps use a trick like in https://stackoverflow.com/a/4598126/164137 to find the original user's name and force operation on their own home directory, instead of letting them pass in any arbitrary input (i.e. in their current state, nothing in the scripts you include in your question prevents user1 from executing the scripts and passing them users2's directory, or any directory for that matter)

Qmail/popuser Environment Permissions (Linux/CentOS)

I am trying to get a mail-receiving script working, but I am getting a permissions error when it tries to copy files to where I need them.
We're running a Linux/CentOS/Plesk webserver. I have qmail set to pipe messages that a certain address receives to a shell script. That script is supposed to write the messages to a file and copy them to one of the server's vhost subscriptions so that they can be accessed by code running via the webserver.
I can get the messages passed to the shell script no problem, and it can successfully write the received message to a file in the local directory (the recipient's folder in /var/qmail/mailnames/). When the script tries to copy the message file to the correct vhost directory, however, I get a 'permission denied' error.
--
.qmail (file piping mail to parse_mail.sh - included for clarity, this part is working as intended):
| true
| /bin/bash parse_mail.sh &> parse_mail_sh.log
--
parse_mail.sh:
echo "Start parse_mail $(date)";
u=$(/bin/id -u -n);
echo "running as ${u}";
umask 000;
# random tag name
templ='message';
rand=$(awk -vmin=100000000 -vmax=999999999 'BEGIN{srand(); print
int(min+rand()*(max-min+1))}');
tag=$templ$rand;
echo "Create dir ${tag}/";
/bin/mkdir $tag;
echo "Write message into ${tag}/";
/bin/cp /dev/stdin ${tag}/message.txt;
echo "Copy message to message_files/";
/bin/cp ${tag}/message.txt /var/www/vhosts/subscription/httpdocs/subfolder/message_files/${tag}_content.txt
echo "Remove ${tag}/";
/bin/rm -R ${tag};
echo "End parse_mail";
--
parse_mail_sh.log log shows:
Start parse_mail Thu Jul 18 11:07:06 EDT 2019
running as popuser
Create dir message494556566/
Write message into message494556566/
Copy message to message_files/
/bin/cp: failed to access '/var/www/vhosts/subscription/httpdocs/subfolder/message_files/message494556566_content.txt': Permission denied
Remove message494556566/
End parse_mail
--
Pretty straight-forward, right? 'popuser' just doesn't have permission to write to this other directory.
Except, here's the odd thing:
I'm not an expert, but I generally understand how unix/linux permissions work. I believe popuser DOES have the requisite permissions to access and write to the directory - the intervening directory structure is traversable, and I've added popuser to the groups necessary to write to that specific subscription folder.
I can su to popuser in the terminal and cd up and down the directory structure, and copy/create files in the correct places. I can even run the mail-receiving script from the terminal AS popuser, and it works perfectly. It only throws the error when triggered on receiving mail.
I assume this means that there is some difference in the environment popuser is operating in via qmail as opposed to the terminal - I just haven't been able to track down exactly what that might be (or find articles online about it).
Or perhaps I misunderstanding how something works? Like I said, not an expert...
So my question is:
Why can't the parse_mail.sh script successfully copy the created file to the indicated message_files/ directory when a message is received by qmail, given that that same script CAN do so when executed by the same system user (popuser) when run via the terminal?
After several days of fighting with this, I discovered the problem.
I had made all of the correct changes, but the system hadn't caught up.
I had restarted various services in PLESK - including the "POP/mail server"- but apparently postfix is not something you can control from there.
When I stopped and then restarted Postfix, my script suddenly worked.
My only theory is that perhaps 'popuser' was operating through postfix on an old session that didn't have my user group changes - which might explain why I could perform the operations via a popuser terminal, but the mail processor could not.

Bash script failing to execute bash script

I'm trying to run a script that installs some files in a directory a user specifies. Once the user specifies the directory, I'd like to transfer the main file to that directory so it can perform so more tasks there before ultimately deleting itself once complete.
#prompt for directory in which to build project
read -p "Drag and drop the directory in which you'd like to build this project: "
echo "reply is $REPLY"
cp ./myScript.sh $REPLY
/bin/bash $REPLY/myScript.sh
I've got the script to execute the file from this question. I tried doing it with source $REPLY/myScript.sh as well as simply sh $REPLY/myScript.sh. I get the error /path/to/file/ is a directory
It must be that it doesn't known I'm trying to run myScript.sh, but I don't understand how I've given it a directory.
A likely cause is that drag-and-drop is putting whitespace after the directory name.
Thus:
/bin/bash $REPLY/myScript.sh
would be running
/bin/bash /path/to/directory /myScript.sh
A simple fix, if that's only a standard space, would be:
/bin/bash "${REPLY% }/myScript.sh"
You are missing the variable in read command so obiously it will fail as whatever you are reading is not getting stored. You can replace the read command as follows.
#prompt for directory in which to build project
read -p "Drag and drop the directory in which you'd like to build this project: " REPLY

Run bash script as if I it was executed from a different directory

Maybe the title is a bit "stupid" but I do not know how to express my question and how to search for the question also, even if it is something very simple.
I have a set of scripts that produce a set of reports in the folder they are executed by. For example I have the script "my_script.sh" in the folder /a/folder/ and in this folder a set of output is stored. Since I have a lot of experiments that I want to let them run for the whole week I was thinking of creating a bash script that will call all the other scripts.
But the output will be stored in the folder that the global script is present.
For example:
/global/folder/global_script.sh
---> All the output is stored in this folder.
The global_script.sh may contain something like this:
/experiments/exp1/script1.sh >report1.txt
/experiments/exp1/script2.sh >report2.txt
/experiments/exp1/script2.sh >report3.txt
And I want the output of the bash scripts to be in their folder and not in the global folder.
Currently I am doing this manually navigating to the folder and executing the script.
(Ok I can change the code and use absolute paths! but is any better way to do that? )
you could change the working directory before you execute each script, or redirect the output to the directory you want:
cd /experiments/exp1/
sh /experiments/exp1/script1.sh >report1.txt
or
sh /experiments/exp1/script1.sh > /experiments/exp1/report1.txt
What's wrong with simply changing directory?
cd /experiments/exp1
./script1.sh >report1.txt
./script2.sh >report2.txt
./script2.sh >report3.txt

print a message to the terminal when the user changes to a specific directory?

Is it possible, in unix, to make it so that a system message appears once a user has changed (cd) to a particular directory?
I know about motd, but I'm wondering if there is something similar to that for navigating in the shell. For instance, if I typed
cd /etc/apache2/
a message could be printed to the screen...something like:
"The latest configuration modified in this directory was..."
"Please be careful modifying ... and ..."
something that all users could potentially see?
You could create a script file in each folder that you want to have execute when entering the folder. Then you can use the environment variable PROMPT_COMMAND to check for it and execute. For example:
export PROMPT_COMMAND='test -x ./.prompt_command && ./.prompt_command'
This will execute a script called .prompt_command in the current folder only if it exists and has its executable bit set.

Resources