be more carful wrt. signed vs. unsigned argument passing
[paraslash.git] / net.c
1 /*
2  * Copyright (C) 2005-2007 Andre Noll <maan@systemlinux.org>
3  *
4  *     This program is free software; you can redistribute it and/or modify
5  *     it under the terms of the GNU General Public License as published by
6  *     the Free Software Foundation; either version 2 of the License, or
7  *     (at your option) any later version.
8  *
9  *     This program is distributed in the hope that it will be useful,
10  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *     GNU General Public License for more details.
13  *
14  *     You should have received a copy of the GNU General Public License
15  *     along with this program; if not, write to the Free Software
16  *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17  */
18
19 /** \file net.c networking-related helper functions */
20
21 #include "para.h"
22 #include "net.h"
23 #include "string.h"
24 #include "error.h"
25
26
27 /** holds information about one encrypted connection */
28 struct crypt_data {
29         /** function used to decrypt received data */
30         crypt_function *recv;
31         /** function used to encrypt data to be sent */
32         crypt_function *send;
33         /** context-dependent data, passed to \a recv() and \a send() */
34         void *private_data;
35 };
36 /** array holding per fd crypt data per */
37 static struct crypt_data *crypt_data_array;
38 /** current size of the crypt data array */
39 static unsigned cda_size = 0;
40
41
42 /**
43  * activate encryption for one file descriptor
44  *
45  * \param fd the file descriptor
46  * \param recv_f the function used for decrypting received data
47  * \param send_f the function used for encrypting before sending
48  * \param private_data user data supplied by the caller
49  */
50 void enable_crypt(int fd, crypt_function *recv_f, crypt_function *send_f,
51         void *private_data)
52 {
53         if (fd + 1 > cda_size) {
54                 crypt_data_array = para_realloc(crypt_data_array,
55                         (fd + 1) * sizeof(struct crypt_data));
56                 memset(crypt_data_array + cda_size, 0,
57                         (fd + 1 - cda_size) * sizeof(struct crypt_data));
58                 cda_size = fd + 1;
59         }
60         crypt_data_array[fd].recv = recv_f;
61         crypt_data_array[fd].send = send_f;
62         crypt_data_array[fd].private_data = private_data;
63         PARA_INFO_LOG("rc4 encryption activated for fd %d\n", fd);
64 }
65
66 /**
67  * deactivate encryption for a given fd
68  *
69  * \param fd the file descriptor
70  *
71  * This must be called if and only if \p fd was activated via enable_crypt().
72  */
73 void disable_crypt(int fd)
74 {
75         if (cda_size < fd + 1)
76                 return;
77         crypt_data_array[fd].recv = NULL;
78         crypt_data_array[fd].send = NULL;
79         crypt_data_array[fd].private_data = NULL;
80 }
81
82
83 /**
84  * initialize a struct sockaddr_in
85  *
86  * \param addr A pointer to the struct to be initialized
87  * \param port The port number to use
88  * \param he The address to use
89  *
90  * If \a he is null (server mode), \a addr->sin_addr is initialized with \p
91  * INADDR_ANY.  Otherwise, the address given by \a he is copied to addr.
92  */
93 void init_sockaddr(struct sockaddr_in *addr, int port, const struct hostent *he)
94 {
95         /* host byte order */
96         addr->sin_family = AF_INET;
97         /* short, network byte order */
98         addr->sin_port = htons(port);
99         if (he)
100                 addr->sin_addr = *((struct in_addr *)he->h_addr);
101         else
102                 addr->sin_addr.s_addr = INADDR_ANY;
103         /* zero the rest of the struct */
104         memset(&addr->sin_zero, '\0', 8);
105 }
106
107 /*
108  * send out a buffer, resend on short writes
109  *
110  * \param fd the file descriptor
111  * \param buf The buffer to be sent
112  * \param len The length of \a buf
113  *
114  * Due to circumstances beyond your control, the kernel might not send all the
115  * data out in one chunk, and now, my friend, it's up to us to get the data out
116  * there (Beej's Guide to Network Programming).
117  *
118  * \return This function returns 1 on success and \a -E_SEND on errors. The
119  * number of bytes actually sent is stored upon successful return in \a len.
120  */
121 static int sendall(int fd, const char *buf, size_t *len)
122 {
123         size_t total = 0, bytesleft = *len; /* how many we have left to send */
124         int n = -1;
125
126         while (total < *len) {
127                 n = send(fd, buf + total, bytesleft, 0);
128                 if (n == -1)
129                         break;
130                 total += n;
131                 bytesleft -= n;
132                 if (total < *len)
133                         PARA_DEBUG_LOG("short write (%zd byte(s) left)",
134                                 *len - total);
135         }
136         *len = total; /* return number actually sent here */
137         return n == -1? -E_SEND : 1; /* return 1 on success */
138 }
139
140 /**
141  * encrypt and send buffer
142  *
143  * \param fd:  the file descriptor
144  * \param buf the buffer to be encrypted and sent
145  * \param len the length of \a buf
146  *
147  * Check if encrytpion is available. If yes, encrypt the given buffer.  Send out
148  * the buffer, encrypted or not, and try to resend the remaing part in case of
149  * short writes.
150  *
151  * \return Positive on success, \p -E_SEND on errors.
152  */
153 int send_bin_buffer(int fd, const char *buf, size_t len)
154 {
155         int ret;
156         crypt_function *cf = NULL;
157
158         if (!len)
159                 PARA_CRIT_LOG("%s", "len == 0\n");
160         if (fd + 1 <= cda_size)
161                 cf = crypt_data_array[fd].send;
162         if (cf) {
163                 void *private = crypt_data_array[fd].private_data;
164                 unsigned char *outbuf = para_malloc(len);
165                 (*cf)(len, (unsigned char *)buf, outbuf, private);
166                 ret = sendall(fd, (char *)outbuf, &len);
167                 free(outbuf);
168         } else
169                 ret = sendall(fd, buf, &len);
170         return ret;
171 }
172
173 /**
174  * encrypt and send null terminated buffer.
175  *
176  * \param fd the file descriptor
177  * \param buf the null-terminated buffer to be send
178  *
179  * This is equivalent to send_bin_buffer(fd, buf, strlen(buf)).
180  *
181  * \return Positive on success, \p -E_SEND on errors.
182  */
183 int send_buffer(int fd, const char *buf)
184 {
185         return send_bin_buffer(fd, buf, strlen(buf));
186 }
187
188
189 /**
190  * send and encrypt a buffer given by a format string
191  *
192  * \param fd the file descriptor
193  * \param fmt a format string
194  *
195  * \return Positive on success, \p -E_SEND on errors.
196  */
197 __printf_2_3 int send_va_buffer(int fd, const char *fmt, ...)
198 {
199         char *msg;
200         int ret;
201
202         PARA_VSPRINTF(fmt, msg);
203         ret = send_buffer(fd, msg);
204         free(msg);
205         return ret;
206 }
207
208 /**
209  * receive and decrypt.
210  *
211  * \param fd the file descriptor
212  * \param buf the buffer to write the decrypted data to
213  * \param size the size of \a buf
214  *
215  * Receive at most \a size bytes from filedescriptor fd. If encryption is
216  * available, decrypt the received buffer.
217  *
218  * \return The number of bytes received on success. On receive errors, -E_RECV
219  * is returned. On crypt errors, the corresponding crypt error number is
220  * returned.
221  *
222  * \sa recv(2)
223  */
224 __must_check int recv_bin_buffer(int fd, char *buf, size_t size)
225 {
226         ssize_t n;
227         crypt_function *cf = NULL;
228
229         if (fd + 1 <= cda_size)
230                 cf = crypt_data_array[fd].recv;
231         if (cf) {
232                 unsigned char *tmp = para_malloc(size);
233                 void *private = crypt_data_array[fd].private_data;
234                 n = recv(fd, tmp, size, 0);
235                 if (n > 0) {
236                         size_t numbytes = n;
237                         unsigned char *b = (unsigned char *)buf;
238                         (*cf)(numbytes, tmp, b, private);
239                 }
240                 free(tmp);
241         } else
242                 n = recv(fd, buf, size, 0);
243         if (n == -1)
244                 n = -E_RECV;
245         return n;
246 }
247
248 /**
249  * receive, decrypt and write terminating NULL byte
250  *
251  * \param fd the file descriptor
252  * \param buf the buffer to write the decrypted data to
253  * \param size the size of \a buf
254  *
255  * Read and decrypt at most \a size - 1 bytes from file descriptor \a fd and
256  * write a NULL byte at the end of the received data.
257  *
258  * \return: The return value of the underlying call to \a recv_bin_buffer().
259  *
260  * \sa recv_bin_buffer()
261  */
262 int recv_buffer(int fd, char *buf, size_t size)
263 {
264         int n;
265
266         if (!size)
267                 return -E_RECV;
268         n = recv_bin_buffer(fd, buf, size - 1);
269         if (n >= 0)
270                 buf[n] = '\0';
271         else
272                 *buf = '\0';
273         return n;
274 }
275
276 /**
277  * wrapper around gethostbyname
278  *
279  * \param host hostname or IPv4 address
280  * \param ret the hostent structure is returned here
281  *
282  * \return positive on success, negative on errors. On success, \a ret
283  * contains the return value of the underlying gethostbyname() call.
284  *
285  * \sa gethostbyname(2)
286  */
287 int get_host_info(char *host, struct hostent **ret)
288 {
289         PARA_INFO_LOG("getting host info of %s\n", host);
290         /* FIXME: gethostbyname() is obsolete */
291         *ret = gethostbyname(host);
292         return *ret? 1 : -E_HOST_INFO;
293 }
294
295 /**
296  * a wrapper around socket(2)
297  *
298  * Create an IPv4 socket for sequenced, reliable, two-way, connection-based
299  * byte streams.
300  *
301  * \return The socket fd on success, -E_SOCKET on errors.
302  *
303  * \sa socket(2)
304  */
305 int get_socket(void)
306 {
307         int socket_fd;
308
309         if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
310                 return -E_SOCKET;
311         return socket_fd;
312 }
313
314 /**
315  * a wrapper around connect(2)
316  *
317  * \param fd the file descriptor
318  * \param their_addr the address to connect
319  *
320  * \return \p -E_CONNECT on errors, 1 on success
321  *
322  * \sa connect(2)
323  */
324 int para_connect(int fd, struct sockaddr_in *their_addr)
325 {
326         int ret;
327
328         if ((ret = connect(fd, (struct sockaddr *)their_addr,
329                         sizeof(struct sockaddr))) == -1)
330                 return -E_CONNECT;
331         return 1;
332 }
333
334 /**
335  * paraslash's wrapper around the accept system call
336  *
337  * \param fd the listening socket
338  * \param addr structure which is filled in with the address of the peer socket
339  * \param size should contain the size of the structure pointed to by \a addr
340  *
341  * Accept incoming connections on \a addr. Retry if interrupted.
342  *
343  * \return The new file descriptor on success, \a -E_ACCEPT on errors.
344  *
345  * \sa accept(2).
346  */
347 int para_accept(int fd, void *addr, socklen_t size)
348 {
349         int new_fd;
350
351         do
352                 new_fd = accept(fd, (struct sockaddr *) addr, &size);
353         while (new_fd < 0 && errno == EINTR);
354         return new_fd < 0? -E_ACCEPT : new_fd;
355 }
356
357 static int setserversockopts(int socket_fd)
358 {
359         int yes = 1;
360
361         if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes,
362                         sizeof(int)) == -1)
363                 return -E_SETSOCKOPT;
364         return 1;
365 }
366
367 /**
368  * prepare a structure for \p AF_UNIX socket addresses
369  *
370  * \param u pointer to the struct to be prepared
371  * \param name the socket pathname
372  *
373  * This just copies \a name to the sun_path component of \a u.
374  *
375  * \return Positive on success, \p -E_NAME_TOO_LONG if \a name is longer
376  * than \p UNIX_PATH_MAX.
377  */
378 int init_unix_addr(struct sockaddr_un *u, const char *name)
379 {
380         if (strlen(name) >= UNIX_PATH_MAX)
381                 return -E_NAME_TOO_LONG;
382         memset(u->sun_path, 0, UNIX_PATH_MAX);
383         u->sun_family = PF_UNIX;
384         strcpy(u->sun_path, name);
385         return 1;
386 }
387
388 /**
389  * prepare, create, and bind and socket for local communication
390  *
391  * \param name the socket pathname
392  * \param unix_addr pointer to the \p AF_UNIX socket structure
393  * \param mode the desired mode of the socket
394  *
395  * This functions creates a local socket for sequenced, reliable,
396  * two-way, connection-based byte streams.
397  *
398  * \return The file descriptor, on success, negative on errors.
399  *
400  * \sa socket(2)
401  * \sa bind(2)
402  * \sa chmod(2)
403  */
404 int create_pf_socket(const char *name, struct sockaddr_un *unix_addr,
405                 mode_t mode)
406 {
407         int fd, ret;
408
409         fd = socket(PF_UNIX, SOCK_STREAM, 0);
410         if (fd < 0)
411                 return -E_SOCKET;
412 //      unlink(name);
413         ret = init_unix_addr(unix_addr, name);
414         if (ret < 0)
415                 return ret;
416         if (bind(fd, (struct sockaddr *) unix_addr, UNIX_PATH_MAX) < 0)
417                 return -E_BIND;
418         if (chmod(name, mode) < 0)
419                 return -E_CHMOD;
420         return fd;
421 }
422
423 #ifndef HAVE_UCRED
424 ssize_t send_cred_buffer(int sock, char *buf)
425 {
426         return send_buffer(sock, buf);
427 }
428 int recv_cred_buffer(int fd, char *buf, size_t size)
429 {
430         return recv_buffer(fd, buf, size) > 0? 1 : -E_RECVMSG;
431 }
432 #else /* HAVE_UCRED */
433 /**
434  * send NULL terminated buffer and Unix credentials of the current process
435  *
436  * \param sock the socket file descriptor
437  * \param buf the buffer to be sent
438  *
439  * \return On success, this call returns the number of characters sent.  On
440  * error, \p -E_SENDMSG ist returned.
441  *
442  * \sa  okir's Black Hats Manual
443  * \sa sendmsg(2)
444  */
445 ssize_t send_cred_buffer(int sock, char *buf)
446 {
447         char control[sizeof(struct cmsghdr) + 10];
448         struct msghdr msg;
449         struct cmsghdr *cmsg;
450         static struct iovec iov;
451         struct ucred c;
452         int ret;
453
454         /* Response data */
455         iov.iov_base = buf;
456         iov.iov_len  = strlen(buf);
457         c.pid = getpid();
458         c.uid = getuid();
459         c.gid = getgid();
460         /* compose the message */
461         memset(&msg, 0, sizeof(msg));
462         msg.msg_iov = &iov;
463         msg.msg_iovlen = 1;
464         msg.msg_control = control;
465         msg.msg_controllen = sizeof(control);
466         /* attach the ucred struct */
467         cmsg = CMSG_FIRSTHDR(&msg);
468         cmsg->cmsg_level = SOL_SOCKET;
469         cmsg->cmsg_type = SCM_CREDENTIALS;
470         cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
471         *(struct ucred *)CMSG_DATA(cmsg) = c;
472         msg.msg_controllen = cmsg->cmsg_len;
473         ret = sendmsg(sock, &msg, 0);
474         if (ret  < 0)
475                 ret = -E_SENDMSG;
476         return ret;
477 }
478
479 static void dispose_fds(int *fds, unsigned num)
480 {
481         int i;
482
483         for (i = 0; i < num; i++)
484                 close(fds[i]);
485 }
486
487 /**
488  * receive a buffer and the Unix credentials of the sending process
489  *
490  * \param fd the socket file descriptor
491  * \param buf the buffer to store the message
492  * \param size the size of \a buffer
493  *
494  * \return negative on errors, the user id on success.
495  *
496  * \sa okir's Black Hats Manual
497  * \sa recvmsg(2)
498  */
499 int recv_cred_buffer(int fd, char *buf, size_t size)
500 {
501         char control[255];
502         struct msghdr msg;
503         struct cmsghdr *cmsg;
504         struct iovec iov;
505         int result = 0;
506         int yes = 1;
507         struct ucred cred;
508
509         setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &yes, sizeof(int));
510         memset(&msg, 0, sizeof(msg));
511         memset(buf, 0, size);
512         iov.iov_base = buf;
513         iov.iov_len = size;
514         msg.msg_iov = &iov;
515         msg.msg_iovlen = 1;
516         msg.msg_control = control;
517         msg.msg_controllen = sizeof(control);
518         if (recvmsg(fd, &msg, 0) < 0)
519                 return -E_RECVMSG;
520         result = -E_SCM_CREDENTIALS;
521         cmsg = CMSG_FIRSTHDR(&msg);
522         while (cmsg) {
523                 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type
524                                 == SCM_CREDENTIALS) {
525                         memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred));
526                         result = cred.uid;
527                 } else
528                         if (cmsg->cmsg_level == SOL_SOCKET
529                                         && cmsg->cmsg_type == SCM_RIGHTS) {
530                                 dispose_fds((int *) CMSG_DATA(cmsg),
531                                         (cmsg->cmsg_len - CMSG_LEN(0))
532                                         / sizeof(int));
533                         }
534                 cmsg = CMSG_NXTHDR(&msg, cmsg);
535         }
536         return result;
537 }
538 #endif /* HAVE_UCRED */
539
540 /** how many pending connections queue will hold */
541 #define BACKLOG 10
542
543 /**
544  * create a socket, bind it and listen
545  *
546  * \param port the tcp port to listen on
547  *
548  * \return The file descriptor of the created socket, negative
549  * on errors.
550  *
551  * \sa get_socket()
552  * \sa setsockopt(2)
553  * \sa bind(2)
554  * \sa listen(2)
555  */
556 int init_tcp_socket(int port)
557 {
558         struct sockaddr_in my_addr;
559         int fd, ret = get_socket();
560
561         if (ret < 0)
562                 return ret;
563         fd = ret;
564         ret = setserversockopts(fd);
565         if (ret < 0)
566                 goto err;
567         init_sockaddr(&my_addr, port, NULL);
568         ret = -E_BIND;
569         if (bind(fd, (struct sockaddr *)&my_addr,
570                         sizeof(struct sockaddr)) == -1) {
571                 PARA_CRIT_LOG("bind error: %s\n", strerror(errno));
572                 goto err;
573         }
574         ret = -E_LISTEN;
575         if (listen(fd, BACKLOG) == -1)
576                 goto err;
577         PARA_INFO_LOG("listening on port %d, fd %d\n", port, fd);
578         return fd;
579 err:
580         close(fd);
581         return ret;
582 }
583
584 /**
585  * receive a buffer and check for a pattern
586  *
587  * \param fd the file descriptor to receive from
588  * \param pattern the expected pattern
589  * \param bufsize the size of the internal buffer
590  *
591  * \return Positive if \a pattern was received, negative otherwise.
592  *
593  * This function creates a buffer of size \a bufsize and tries
594  * to receive at most \a bufsize bytes from file descriptor \a fd.
595  * If at least \p strlen(\a pattern) bytes were received, the beginning of
596  * the received buffer is compared with \a pattern, ignoring case.
597  *
598  * \sa recv_buffer()
599  * \sa strncasecmp(3)
600  */
601 int recv_pattern(int fd, const char *pattern, size_t bufsize)
602 {
603         size_t len = strlen(pattern);
604         char *buf = para_malloc(bufsize + 1);
605         int ret = -E_RECV_PATTERN, n = recv_buffer(fd, buf, bufsize);
606
607         if (n < len)
608                 goto out;
609         if (strncasecmp(buf, pattern, len))
610                 goto out;
611         ret = 1;
612 out:
613         if (ret < 0) {
614                 PARA_NOTICE_LOG("n = %d, did not receive pattern '%s'\n", n, pattern);
615                 if (n > 0)
616                         PARA_NOTICE_LOG("recvd: %s\n", buf);
617         }
618         free(buf);
619         return ret;
620 }