remote pool_handle_t
[tlspool] / lib / libtlspool_posix.c
1 /* This file is #include'd by libtlspool.c */
2 #define closesocket(s) close(s)
3
4 int os_sendmsg_command(int poolfd, struct tlspool_command *cmd, int fd) {
5         struct iovec iov;
6         struct cmsghdr *cmsg;
7         struct msghdr mh = { 0 };
8         iov.iov_base = cmd;
9         iov.iov_len = sizeof(struct tlspool_command);
10         mh.msg_iov = &iov;
11         mh.msg_iovlen = 1;
12         if (fd >= 0) {
13                 char anc[CMSG_SPACE(sizeof(int))];
14                 mh.msg_control = anc;
15                 mh.msg_controllen = sizeof (anc);
16                 cmsg = CMSG_FIRSTHDR (&mh);
17                 cmsg->cmsg_level = SOL_SOCKET;
18                 cmsg->cmsg_type = SCM_RIGHTS;
19                 *(int *)CMSG_DATA(cmsg) = fd;
20                 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
21         }
22         return sendmsg (poolfd, &mh, MSG_NOSIGNAL);
23 }
24
25
26 int os_recvmsg_command(int poolfd, struct tlspool_command *cmd) {
27         struct iovec iov;
28         struct cmsghdr *cmsg;
29         struct msghdr mh = { 0 };
30         iov.iov_base = cmd;
31         iov.iov_len = sizeof (struct tlspool_command);
32         mh.msg_iov = &iov;
33         mh.msg_iovlen = 1;
34         //NOT-USED// mh.msg_control = anc;
35         //NOT-USED// mh.msg_controllen = sizeof (anc);
36         return recvmsg (poolfd, &mh, MSG_NOSIGNAL);
37 }
38 /*
39  * converts IPPROTO_* to SOCK_*, returns -1 if invalid protocol
40  */
41 int ipproto_to_sockettype(uint8_t ipproto) {
42         return ipproto == IPPROTO_TCP ? SOCK_STREAM : ipproto == IPPROTO_UDP ? SOCK_DGRAM : ipproto == IPPROTO_SCTP ? SOCK_SEQPACKET : -1;
43 }
44
45 /*
46  * The namedconnect() function is called by tlspool_starttls() when the
47  * identities have been exchanged, and established, in the TLS handshake.
48  * This is the point at which a connection to the plaintext side is
49  * needed, and a callback to namedconnect() is made to find a handle for
50  * it.  The function is called with a version of the tlsdata that has
51  * been updated by the TLS Pool to hold the local and remote identities. 
52  *
53  * When the namedconnect argument passed to tlspool_starttls() is NULL,
54  * this default function is used instead of the possible override by the
55  * caller.  This interprets the privdata handle as an (int *) holding
56  * a file descriptor.  If its value is valid, that is, >= 0, it will be
57  * returned directly; otherwise, a socketpair is constructed, one of the
58  * sockets is stored in privdata for use by the caller and the other is
59  * returned as the connected file descriptor for use by the TLS Pool.
60  * This means that the privdata must be properly initialised for this
61  * use, with either -1 (to create a socketpair) or the TLS Pool's
62  * plaintext file descriptor endpoint.  The file handle returned in
63  * privdata, if it is >= 0, should be closed by the caller, both in case
64  * of success and failure.
65  *
66  * The return value should be -1 on error, with errno set, or it should
67  * be a valid file handle that can be passed back to the TLS Pool to
68  * connect to.
69  */
70 int tlspool_namedconnect_default (starttls_t *tlsdata, void *privdata) {
71         int plainfd;
72         int soxx[2];
73         int type = ipproto_to_sockettype (tlsdata->ipproto);
74         if (type == -1) {
75                 errno = EINVAL;
76                 return -1;
77         }
78         if (socketpair (AF_UNIX, type, 0, soxx) == 0)
79         {
80                 // printf("DEBUG: socketpair succeeded\n");
81                 /* Socketpair created */
82                 plainfd = soxx [0];
83                 * (int *) privdata = soxx [1];
84         } else {
85                 /* Socketpair failed */
86                 // printf("DEBUG: socketpair failed\n");
87                 plainfd = -1;
88         }
89         return plainfd;
90 }
91
92 /* Determine an upper limit for simultaneous STARTTLS threads, based on the
93  * number of available file descriptors.  Note: The result is cached, so
94  * don't use root to increase beyond max in setrlimit() after calling this.
95  */
96 int tlspool_simultaneous_starttls(void) {
97         static int simu = -1;
98         if (simu < 0) {
99                 struct rlimit rlimit_nofile;
100                 if (getrlimit (RLIMIT_NOFILE, &rlimit_nofile) == -1) {
101                         syslog (LOG_NOTICE, "Failed to determine simultaneous STARTTLS: %s", strerror (errno));
102                         rlimit_nofile.rlim_max = 1024;  // Pick something
103                 }
104                 simu = rlimit_nofile.rlim_max / 2;  // 2 FDs per STARTTLS
105         }
106         return simu;
107 }
108
109 int os_usleep(unsigned int usec) {
110         return usleep(usec);
111 }
112
113 int open_pool (void *path) {
114         struct sockaddr_un sun;
115         //
116         // Setup path information -- value and size were checked
117         memset (&sun, 0, sizeof (sun));
118         strcpy (sun.sun_path, (char *) path);
119         sun.sun_family = AF_UNIX;
120         int newpoolfd = socket (AF_UNIX, SOCK_STREAM, 0);
121         if (newpoolfd >= 0) {
122                 if (connect (newpoolfd, (struct sockaddr *) &sun, SUN_LEN (&sun)) != 0) {
123                         tlspool_close_poolhandle (newpoolfd);
124                         newpoolfd = -1;
125                 }
126         }
127 // printf ("DEBUG: Trying new poolfd %d for path %s\n", newpoolfd, sun.sun_path);
128         return newpoolfd;
129 }