how can I change the permissions of a linux socket file? - c

I have a program which creates a socket, and then I want to change the permissions of the socket file:
ret_val = chmod(filename, 0777);
, but it doesn't change, even though ret_val will be 0. If I try the same thing on a regular file, it works.
Any ideas?
P.S: I am running the program as root, so it has all the authority needed.

From man 7 unix:
In the Linux implementation, sockets which are visible in the file system
honor the permissions of the directory they are in. Their owner,
group and their permissions can be changed. Creation of a new socket
will fail if the process does not have write and search (execute) permission on the directory the socket is created in. Connecting to the
socket object requires read/write permission. This behavior differs
from many BSD-derived systems which ignore permissions for UNIX domain
sockets. Portable programs should not rely on this feature for security.
So if you want to control permissions on a socket, in order to be portable, you should instead control the permissions of the directory containing the socket.

https://stackoverflow.com/a/42955529/1425297
"If you want your socket world-writeable, the easiest way would be for you app to call this before your socket is created and bound: umask(0);"

Related

How to create a TCP-IP named socket file in Unix?

I found out that, under 'everything is a file' philosophy in Unix, even sockets are considered as files, and can be stored in a path in file system. So, I was trying to create a TCP-IP socket file out of curiosity.
This answer shows how to create a named Unix domain socket file. But struct sockaddr_in doesn't have sin_path field. So I have no idea how to create a named TCP-IP socket file. Can anyone tell me how to do this?
... even sockets are considered as files, and can be stored in a path in file system.
Not really. There are some sockets where the endpoint is represented by a file. These are UNIX domain sockets (AF_UNIX) and their is a variant which has a message semantic (SOCK_DGRAM) similar to UDP and one which has a stream semantic (SOCK_STREAM) similar to TCP.
But, UDP and TCP sockets have a no file representation in UNIX. They have a file descriptor though similar to normal files (and read and write system calls work with these), but they are not represented by a path in the file system.
There is also something like /dev/tcp/.. to deal with sockets inside the bash shell. But this is not an actual path on the file system either, but only a fancy syntax specific to the bash shell.
For more on this see also Wikipedia: Everything is a file which specifically notes:
... Therefore, a more accurate description of this feature is Everything is a file descriptor.

Linux Raw Socket Permissions Issue

I'm creating a raw ethernet socket in a C application, e.g.
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
and its returning -1 indicating an error
I'm pretty sure its a permissions issue - You can only open a raw socket if you have a UID of 0 (root) or have the CAP_NET_RAW capability
I don't think running the application as root is reasonable, therefore my question is how can I 'add' the CAP_NET_RAW capability permission to my user account?
From http://manpages.ubuntu.com/manpages/zesty/en/man7/packet.7.html
In order to create a packet socket, a process must have the CAP_NET_RAW
capability in the user namespace that governs its network namespace.
But how does one achieve that end?
You set the capabilities on the executable that needs that capability, not a user account. The syntax is
setcap cap_net_raw,cap_net_admin=eip ./your_exeutable
(Note, you need to run setcap as root, so use e.g. sudo setcap ... Also make sure there are no space characters in cap_net_raw,cap_net_admin=eip
Being able to read all network packets is considered a severe security risk, that is why this needs a privileged account.
You can make the application "suid root" to elevate your own rights when starting this application as a "normal" user. But that is a security risk as well and needs a bit of thorough thinking when designing the application (it should at least give up the higher privilege as soon as it doesn't need it any more - i.e. after having opened the raw socket).
You cannot add the CAP_NET_RAW permission to your account, because capabilities on Linux do not follow users. They follow executables.
To make this work, you need to add the CAP_NET_RAW capability to your compiled executable. See the setcap command in order to see how to do that.

Bind a web server to port 80 without being root

I've written my own web server in C. How can I bind it to port 80 without being root so that the security is not being compromised (buffer overflows etc.)?
Should I simply forward any traffic from another "stable" server that runs on port 80?
Using a forward proxy is indeed the easiest and most recommended solution. It also has the advantage of filtering horribly invalid requests before they even reach your self-written server.
In case your application uses the user's ip address for something remember to retrieve it from whatever header your webserver uses (X-Client-IP etc.). However, only do so for requests that really come from your webserver, otherwise users can spoof their IP. You can do so by checking if the request came from your IP and only check the header in this case or simply make your application bind to localhost.
Another solution would be granting the program the CAP_NET_BIND_SERVICE capability. This requires root to use setcap cap_net_bind_service=ep /path/to/the/executable - since the flag is stored in a filesystem attribute, it will be lost when copying the file to another system or recompiling the application.
Of course you could also make your program setuid root and then switch to an unprivileged user right after calling bind(). However, depending on how your program works and what it does this might not be a good idea - for example, if it needs to close and reopen the listening socket for some reason it would require a full restart of the process.
An alternative to calling bind() as root, then dropping privileges, is to have a root process that creates the socket and binds it, and then passes the listening socket to the unprivileged process over a UNIX-domain socket connection using a SCM_RIGHTS message.
if you want to bind your server to port 80 you must do that as root and afterwards drop the privileges.
bind(sockfd, addr, addrlen);
/* process is running as root, drop privileges after bind*/
if (setgid(groupid) != 0)
errx(1, "setgid: Unable to drop group privileges: %s", strerror(errno));
if (setuid(userid) != 0)
errx(1, "setuid: Unable to drop user privileges: %S", strerror(errno));
How can I bind it to port 80 without being root so that the security is not being compromised (buffer overflows etc.)
not running as root does not make your system more secure it just adds another layer to exploit.
So instead of thinking about how not to run as root, please ensure that you do not use any known-insecure functions like strcpy(), sprintf(), etc. but instead use strncpy(), snprintf(), etc.
Well as you know all ports under 1024 in Unix require root privileges to open.
On a Unix system you do not want as few applications as possible running with root privileges.
It is and will always be a big safety risk.
An alternative is to use iptables to redirect the port 80 traffic to a more harmless port like 8080. Here is a description on how to set it up.
Iptables is not the easiest tool to setup, but once you have mastered it, it is very useful and powerful (and secure).
I worked on this problem for quite some time and came to the conclusion that systemd + iptables is the solution, and not Capabilities, as elaborated in great detail here.

Code for directory monitor using Unix concepts in C language

On a server, a process monitors the files in a Unix file system.
If a client sends the file name to be monitored, the server has to send the report to the client whether that file got changed or deleted.
For server-client communication, we should use either message queues or sockets.
For every change in the file, the server has to notify that change.
For all changes in all files, the server has to maintain one logfile so that user can view it through the command line interface.
Server could use two threads: one for communication, the other for monitoring.
How can you do this efficiently?
Have a look at inotify at http://en.wikipedia.org/wiki/Inotify - linux only I'm afraid.
BSD has kqueue - see http://en.wikipedia.org/wiki/Kqueue.
See also:
http://benkibbey.wordpress.com/bubblegum/

What are named pipes?

What are they and how do they work?
Context happens to be SQL Server
Both on Windows and POSIX systems, named-pipes provide a way for inter-process communication to occur among processes running on the same machine. What named pipes give you is a way to send your data without having the performance penalty of involving the network stack.
Just like you have a server listening to a IP address/port for incoming requests, a server can also set up a named pipe which can listen for requests. In either cases, the client process (or the DB access library) must know the specific address (or pipe name) to send the request. Often, a commonly used standard default exists (much like port 80 for HTTP, SQL server uses port 1433 in TCP/IP; \\.\pipe\sql\query for a named pipe).
By setting up additional named pipes, you can have multiple DB servers running, each with its own request listeners.
The advantage of named pipes is that it is usually much faster, and frees up network stack resources.
--
BTW, in the Windows world, you can also have named pipes to remote machines -- but in that case, the named pipe is transported over TCP/IP, so you will lose performance. Use named pipes for local machine communication.
Unix and Windows both have things called "Named pipes", but they behave differently. On Unix, a named pipe is a one-way street which typically has just one reader and one writer - the writer writes, and the reader reads, you get it?
On Windows, the thing called a "Named pipe" is an IPC object more like a TCP socket - things can flow both ways and there is some metadata (You can obtain the credentials of the thing on the other end etc).
Unix named pipes appear as a special file in the filesystem and can be accessed with normal file IO commands including the shell. Windows ones don't, and need to be opened with a special system call (after which they behave mostly like a normal win32 handle).
Even more confusing, Unix has something called a "Unix socket" or AF_UNIX socket, which works more like (but not completely like) a win32 "named pipe", being bidirectional.
Linux Pipes
First In First Out (FIFO) interproccess communication mechanism.
Unnamed Pipes
On the command line, represented by a "|" between two commands.
Named Pipes
A FIFO special file. Once created, you can use the pipe just like a normal file(open, close, write, read, etc).
To create a named pipe, called "myPipe", from the command line (man page):
mkfifo myPipe
To create a named pipe from c, where "pathname" is the name you would like the pipe to have and "mode" contains the permissions you want the pipe to have (man page):
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
According to Wikipedia:
[...] A traditional pipe is "unnamed" because it exists anonymously and persists only for as long as the process is running. A named pipe is system-persistent and exists beyond the life of the process and must be "unlinked" or deleted once it is no longer being used. Processes generally attach to the named pipe (usually appearing as a file) to perform IPC (inter-process communication).
Compare
echo "test" | wc
to
mkdnod apipe p
wc apipe
wc will block until
echo "test" > apipe
executes
This is an exeprt from Technet (so not sure why the marked answer says named pipes are faster??):
Named Pipes vs. TCP/IP Sockets
In a fast local area network (LAN) environment, Transmission Control Protocol/Internet Protocol (TCP/IP) Sockets and Named Pipes clients are comparable with regard to performance. However, the performance difference between the TCP/IP Sockets and Named Pipes clients becomes apparent with slower networks, such as across wide area networks (WANs) or dial-up networks. This is because of the different ways the interprocess communication (IPC) mechanisms communicate between peers.
For named pipes, network communications are typically more interactive. A peer does not send data until another peer asks for it using a read command. A network read typically involves a series of peek named pipes messages before it starts to read the data. These can be very costly in a slow network and cause excessive network traffic, which in turn affects other network clients.
It is also important to clarify if you are talking about local pipes or network pipes. If the server application is running locally on the computer that is running an instance of SQL Server, the local Named Pipes protocol is an option. Local named pipes runs in kernel mode and is very fast.
For TCP/IP Sockets, data transmissions are more streamlined and have less overhead. Data transmissions can also take advantage of TCP/IP Sockets performance enhancement mechanisms such as windowing, delayed acknowledgements, and so on. This can be very helpful in a slow network. Depending on the type of applications, such performance differences can be significant.
TCP/IP Sockets also support a backlog queue. This can provide a limited smoothing effect compared to named pipes that could lead to pipe-busy errors when you are trying to connect to SQL Server.
Generally, TCP/IP is preferred in a slow LAN, WAN, or dial-up network, whereas named pipes can be a better choice when network speed is not the issue, as it offers more functionality, ease of use, and configuration options.
Pipes are a way of streaming data between applications. Under Linux I use this all the time to stream the output of one process into another. This is anonymous because the destination app has no idea where that input-stream comes from. It doesn't need to.
A named pipe is just a way of actively hooking onto an existing pipe and hoovering-up its data. It's for situations where the provider doesn't know what clients will be eating the data.
Inter-process communication (mostly) for Windows Applications. Similar to using sockets to communicate between applications in Unix.
MSDN
Named pipes in a unix/linux context can be used to make two different shells to communicate since a shell just can't share anything with another.
Furthermore, one script instantiated twice in the same shell can't share anything through the two instances. I found a use for named pipes when coding a daemon that contains the start() and stop() function, and I wanted to use the same script to perform the two actions.
Without named pipes (or any kind of semaphore) starting the script in the background is not a problem. The thing is when it finishes you just can't access the instance in background.
So when you want to send him the stop command you just can't: running the same script without named pipes and calling the stop() function won't do anything since you are actually running another instance.
The solution was to implement two pipes, one READ and the other WRITE when you start the daemon. Then make him, among its other tasks, listen to the READ pipe. Then the Stop() function contains a command that will write a message in the pipe, that will be handled by the background running script that will perform an exit 0. This way our second instance of the same script has only on task to do: tell the first instance to stop.
This way one and only one script can start and stop itself.
Of course you have different ways to do it by triggering the stop via a touch for example. But this one is nice and interesting to code.
Named pipes is a windows system for inter-process communication. In the case of SQL server, if the server is on the same machine as the client, then it is possible to use named pipes to tranfer the data, as opposed to TCP/IP.

Resources