|
@@ -0,0 +1,36 @@
|
|
|
+The socket creator
|
|
|
+==================
|
|
|
+
|
|
|
+The only thing we need higher rights than standard user is binding sockets to
|
|
|
+ports lower than 1024. So we will have a separate process that keeps the
|
|
|
+rights, while the rests drop them for security reasons.
|
|
|
+
|
|
|
+This process is the socket creator. Its goal is to be as simple as possible
|
|
|
+and to contain as little code as possible to minimise the amount of code
|
|
|
+running with higher privileges (to minimize the number of bugs and make
|
|
|
+checking/auditing it easier). It uses low-level OS API instead of some
|
|
|
+fancy library for that reason. It has only fixed-length reads so there's no
|
|
|
+place for buffer overruns.
|
|
|
+
|
|
|
+Protocol
|
|
|
+--------
|
|
|
+
|
|
|
+It talks with whoever started it by its stdin/stdout. It reads simple
|
|
|
+binary protocol from stdin and does what the commands ask. Command is a single
|
|
|
+byte (usually from the printable range, so it is easier to debug and guess
|
|
|
+what it does), followed by parameters.
|
|
|
+
|
|
|
+* 'T': It has no parameters. It asks the socket creator to terminate.
|
|
|
+
|
|
|
+* 'S' 'U|T' '4|6' port address: Asks it to create a port. First parameter
|
|
|
+ tels the socket type (either UDP or TCP). The second one is address family
|
|
|
+ (either IPv4 or IPv6). Then there's 2 bytes of the port number, in the
|
|
|
+ network byte order. The last one is either 4 or 16 bytes of address, as
|
|
|
+ they would be passed to bind (note that both parameters are already prepared,
|
|
|
+ like hton called on them).
|
|
|
+
|
|
|
+ The answer to this is either 'S' and then the socket is passed using sendmsg
|
|
|
+ if it is successful. If it fails, 'E' is returned, followed by either
|
|
|
+ 'S' or 'B' (either socket() or bind() call failed). Then there is one int
|
|
|
+ (architecture-dependent length and endianess), which is the errno value
|
|
|
+ after the failure.
|