I am coding a small piece of C program. Basically, in the folder will have to file: secret.txt and code.c. I want my user cannot use any means to directly print out the secret.txt in terminal by 'cat', 'head', etc. but they can read it from a C program.
How they can read it (in my C code):
if (<some conditional>){
system("\bin\cat secret.txt");
}
I have tried to set the permissions of secret.txt as 440, the executable code as 4711. The file secret.txt is owned by root:root. And normal user can execute the code. However, in the program, it keeps saying permission denied.
How can I do this?
It would be very difficult (and wouldn't make that much sense usually) to deny a specific program from reading a file.
In Linux, permissions work per user, so if the c program and cat run with the same (effective) user-id, they will have the same permissions (generally).
The best way to solve it, if I correctly understood your intentions, is to compile your program, chown it to root, and make it a setuid binary (meaning that it will run with the permissions of "root" and not "user"). This way, it will run as root and be able to access the file.
Related
my question is super beginner! In my C program, I want to set the SUID bit (root permission) before creating a raw socket and then I want to switch back to normal permission after I have created it. Before I used to run my code using command sudo ./client which gave the whole executable root permissions. I want to give root permissions only to the point where I create the socket, so that I can run my code using simply ./client.
EDIT: Realized that I have to set the SUID bit and not the sticky bit for how I want the executable to behave.
The original version of the question was confusing the sticky bit (S_ISVTX) with the SUID or set UID bit (S_ISUID). It has since been updated.
To make the program run with root privileges while creating the raw socket, you would create your executable by compiling it as normal, and then have root take ownership of the executable (chown root ./client) and set the permissions (chmod 4555 ./client). Note that the permissions are carefully chosen and do not allow either group or others to write to the program (modify the executable). The fact that the owner, root, has no write permission does not stop root from writing to the file — though root won't want to change it often. Normally, root would copy the program to some directory where ordinary users cannot make changes. That might conceivably be /usr/local/bin, or it might be somewhere else.
Note that the permissions are set on the executable, not the source code (see the original version of the question), and must be set before the program is run.
Inside the program, after creating the raw socket, you could remove the root privileges, thereby avoiding many security issues in the code after that, by executing: setuid(getuid()). This changes the effective UID back to the same as the real UID. Note that the POSIX specification for setuid()
says:
If the process has appropriate privileges, setuid() shall set the real user ID, effective user ID, and the saved set-user-ID of the calling process to uid.
A program that is SUID to root has 'appropriate privileges'; there is no going back. Using seteuid()
(as originally suggested) would not be as safe as using setuid().
I'm writing a program in C that will have to check a configuration file every time it starts to set some variables.
At the first start of the program I suppose there won't be any configuration file, so I need to create it (with default settings).
I've been said configurations files of program belongs to the folder /etc, more specifically to a particular folder created on purpose for the program itself (i.e. /etc/myprog). Here comes the first question I should have asked: is it true? Why /etc?
In any case I tried to create that file using this:
open("/etc/myprog/myprog.conf", O_WRONLY | O_CREAT, 0644);
the open returns -1 and sets errno global variable to 2 (i.e. folder does not exist).
If I try to create the file straight inside /etc (therefore "/etc/myprog.conf" as first argument of the open) I get instead an errno set to 13 (i.e. permission denied).
Is there a way to grant my program permissions to write in /etc?
EDIT: I see most users are suggesting to use sudo. If possible I would have preferred to avoid this option as this file has to be created just once (at the first start). Maybe I should make 2 different executables? (e.g. myprog_bootstrap and myprog, having to run only the first one with sudo)
You need root privileges to create a file in /etc. Run your executable with sudo in front:
sudo executable_name
Another possibility might be to make your executable setuid. Your program would then call very appropriately the setreuid(2) system call.
However, be very careful. Programs like /bin/login (or /usr/bin/sudo itself) are coded this way, but any subtle error in your program opens a can of worms of security holes. So please be paranoid when writing such a code, and get it reviewed by someone else.
Perhaps a better approach might be to have your installation procedure make /etc/yourfile some symlink (created once at installation time to some writable file elsewhere) ....
BTW, you might create a group for your program, and make -at installation time- the /etc/yourfile writable to the group, and make your program setgid.
Or even, dedicate a user for your program, and have this /etc/yourfile belonging to that user.
Or, at installation time, have the /etc/myprog/ directory created and belonging to the appropriate user (or group) and being writable to that user (or group).
PS. Read also Advanced Linux Programming, capabilities(7), credentials(7) and execve(2)
I know how to get the stdout into a file using dup/dup2 system calls, but how do I get the entire output that would be normally shown on my terminal(including the prompt that says my username along with the $ symbol and the current working directory) to a file?
Yes you can, but this may be difficult in many details (depending on your expert level). For the shell to behave normally (I would mean exactly as in a terminal), then it needs to interact with a terminal (special system object). So you need to create a program that behave like a terminal, this what pseudo-terminals devices (/dev) are intended for. Read documentation about this to implement it but roughly, your application should behave like the user so should be connected to the slave side of the pseudo-terminal, and the shell to the master side of the pseudo-terminal. Then you can easily log real inputs made by the user and catch outputs made by the shell.
Can't comment cause of low reputation.
I would say there is no way to do that inside a code in C. Instead, you could use bash for example to redirect everything to a file, and leave the code in C as it is.
In this way you have all the info you want to save: prompt, current directory, call to the program (including flags), and of course the output of the program.
Well, you can do:
-For bash prompt PS1: Echo expanded PS1 (in case you want it expanded, if not there is a simple way to do it just echong PS1)
- For executed command: https://unix.stackexchange.com/questions/169259/how-to-capture-command-line-input-into-logfile-and-execute-it-at-the-same-time
- Standard output and error output: Redirect stderr and stdout in a Bash script
And that's all you want to capture, I think.
Look up the script command in Unix systems. If you want to capture all keyboard and std in/out for a command, use the script executable. If you want to see how it's done, look up the source.
My C program (on Linux) needs to delete a file, say, /home/me/myfile, here is how I do it in my program
...
system ("rm -f /home/me/myfile");
...
When running this program, I got a message saying permission denied. BTW, ls -al /home/me/myfile returns -rw-r--r--
However, under the same user account and in the same shell I execute the C program, I can simple delete the file by typing rm -f /home/me/myfile
What did I miss here?
Thanks,
Update: Using remove(/home/me/myfile) or unlink(/home/me/myfile), the file can be deleted in my program.
For a start, it's the permissions on the directory that control whether you can delete a file.
But, having said that, there are numerous things that could be different between the two situations. Your program might be running as a different user (such as with the SETUID bit), the path may be different, leading to a different rm being run, the program may set up a chroot jail so that it can no longer even see the file (though that may manifest as a different error), and so forth. The possibilities are rather large.
However, C provides a call to delete files, called unlink - you should use that in preference and then check errno.
I would suggest checking the output of which rm in both cases, along with the full details of the file and executable, owner and permissions.
I am using Ubuntu Lucid Lynx
is it possible to write data in a file through a C program which has read only permission. If it's not possible, then is there any way to give sudo access to the C program.
For files without permissions, I would save the data in a string. Then i would open the file with write option:
FILE *fp = fopen(file_path,"w")
fputs(string,fp);
fclose(fp);
No you cannot write to a read-only file, that would undermine the whole point of read-only. As for giving root access to a c program, you could always run it as root or as someone who has permissions to modify the file.
If you are the owner of the file you can change the permissions with chmod. If you are not the owner you can use setuid bit to acces the file, but this really should be avoided.
It is not possible to have the program elevate itself to sudo status while its running.
And that is a bloody good thing.
If that was possible every virus would have the ability to take over any system.
The program needs to be started with the proper access-rights from the start.
In Unix generally what you'd want to do is make the program's executable owned by root, world executable, then set the SUID bit on it.
chown root filename
chmod 4775 filename
See chomd docs for exactly what the bits mean, but all together this means that whenever someone runs this executable, they get the executable process' user ID set to the owner's (root).
You can, but not in a standard cross-platform way.
On Unix systems, use chmod. It should be in <sys/stat.h>
See this link.
If you need root privilage, try:
if(fp == NULL)
execvp("sudo", argv);