1 #include <config.h>
2 #include "sharedanced.h"
3 #ifdef HAVE_SETLOCALE
4 # include <locale.h>
5 #endif
6 #include "log.h"
7 
8 #ifdef WITH_DMALLOC
9 # include <dmalloc.h>
10 #endif
11 
fd_nonblock(const int fd)12 void fd_nonblock(const int fd)
13 {
14     while (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) != 0 &&
15            (errno == EINTR || errno == EAGAIN));
16 }
17 
safe_write(const int fd,const void * buf_,size_t count)18 int safe_write(const int fd, const void *buf_, size_t count)
19 {
20     ssize_t written;
21     register const char *buf = buf_;
22 
23     while (count > (size_t) 0U) {
24         for (;;) {
25             if ((written = write(fd, buf, count)) <= (ssize_t) 0) {
26                 if (errno == EAGAIN) {
27                     sleep(1);
28                 } else if (errno != EINTR) {
29                     return -1;
30                 }
31                 continue;
32             }
33             break;
34         }
35         buf += written;
36         count -= written;
37     }
38     return 0;
39 }
40 
client_disconnect(Client * const client)41 static void client_disconnect(Client * const client)
42 {
43     if (client->client_fd != -1) {
44         logfile(LOG_DEBUG, _("client_disconnect: closing fd #%d"),
45                 client->client_fd);
46         (void) close(client->client_fd);
47         client->client_fd = -1;
48     }
49     if (client->read_mapped_zone != NULL) {
50         (void) munmap(client->read_mapped_zone,
51                       client->read_mapped_zone_length);
52         client->read_mapped_zone = NULL;
53         client->read_mapped_zone_length = (size_t) 0U;
54     }
55     if (client->read_fd != -1) {
56         (void) close(client->read_fd);
57         client->read_fd = -1;
58     }
59     if (client->write_fd != -1) {
60         (void) close(client->write_fd);
61         client->write_fd = -1;
62     }
63     if (client->returncode_bufev != NULL) {
64         bufferevent_free(client->returncode_bufev);
65         client->returncode_bufev = NULL;
66     }
67     free(client->read_buf);
68     client->read_buf = NULL;
69     free(client);
70 }
71 
returncode_bufferev_read_cb(struct bufferevent * bufferev,void * client_)72 static void returncode_bufferev_read_cb(struct bufferevent *bufferev,
73                                         void *client_)
74 {
75     (void) bufferev;
76     (void) client_;
77     logfile(LOG_DEBUG, _("returncode_bufferev_read_cb"));
78 }
79 
returncode_bufferev_write_cb(struct bufferevent * bufferev,void * client_)80 static void returncode_bufferev_write_cb(struct bufferevent *bufferev,
81                                          void *client_)
82 {
83     Client * const client = client_;
84 
85     (void) bufferev;
86     logfile(LOG_DEBUG, _("Return code successfully written for fd #%d"),
87             client->client_fd);
88     client_disconnect(client);
89 }
90 
returncode_bufferev_error_cb(struct bufferevent * const bufferev,short what,void * client_)91 static void returncode_bufferev_error_cb(struct bufferevent * const bufferev,
92                                          short what, void *client_)
93 {
94     Client * const client = client_;
95 
96     (void) bufferev;
97     logfile(LOG_DEBUG, _("Error %d when sending return code to fd #%d"),
98             (int) what, client->client_fd);
99     client_disconnect(client);
100 }
101 
validate_key(const unsigned char * buf,size_t size)102 static int validate_key(const unsigned char *buf, size_t size)
103 {
104     if (size <= (size_t) 0U) {
105         return -2;
106     }
107     do {
108         size--;
109         if (buf[size] < 32U || buf[size] > 126U ||
110             buf[size] == '.' || buf[size] == '/') {
111             return -1;
112         }
113     } while (size > (size_t) 0U);
114 
115     return 0;
116 }
117 
client_process_store(Client * const client)118 static int client_process_store(Client * const client)
119 {
120     char *store_file;
121     char *store_file_tmp;
122     char *store_file_pnt;
123     char *store_file_tmp_pnt;
124     size_t sizeof_store_file;
125     size_t sizeof_store_file_tmp;
126 
127     logfile(LOG_DEBUG, _("client_process_store, fd #%d"), client->client_fd);
128     if (client->offset_read_buf < (size_t) 10U) {
129         return -1;
130     }
131     sizeof_store_file = (sizeof "/") - (size_t) 1U +
132         client->key_len + (size_t) 1U;
133     if ((store_file = ALLOCA(sizeof_store_file)) == NULL) {
134         logfile(LOG_ERR, _("Out of stack for ALLOCA"));
135         return -1;
136     }
137     store_file_pnt = store_file;
138     *store_file_pnt++ = '/';
139     if (validate_key(client->read_buf + (size_t) 9U, client->key_len) != 0) {
140         ALLOCA_FREE(store_file);
141         logfile(LOG_WARNING, _("Invalid key name"));
142         return -1;
143     }
144     memcpy(store_file_pnt, client->read_buf + (size_t) 9U, client->key_len);
145     store_file_pnt += client->key_len;
146     *store_file_pnt = 0;
147 
148     sizeof_store_file_tmp = (sizeof "/") - (size_t) 1U +
149         sizeof STOREFILE_TMP_PREFIX - (size_t) 1U +
150         client->key_len + (size_t) 1U;
151     if ((store_file_tmp = ALLOCA(sizeof_store_file_tmp)) == NULL) {
152         logfile(LOG_ERR, _("Out of stack for ALLOCA"));
153         ALLOCA_FREE(store_file);
154         return -1;
155     }
156     store_file_tmp_pnt = store_file_tmp;
157     *store_file_tmp_pnt++ = '/';
158     memcpy(store_file_tmp_pnt, STOREFILE_TMP_PREFIX,
159            sizeof STOREFILE_TMP_PREFIX - (size_t) 1U);
160     store_file_tmp_pnt += sizeof STOREFILE_TMP_PREFIX - (size_t) 1U;
161     memcpy(store_file_tmp_pnt,
162            client->read_buf + (size_t) 9U, client->key_len);
163     store_file_tmp_pnt += client->key_len;
164     *store_file_tmp_pnt = 0;
165 
166     logfile(LOG_DEBUG, _("Creating [%s]"), store_file_tmp);
167     if ((client->write_fd =
168          open(store_file_tmp, O_CREAT | O_NOFOLLOW | O_WRONLY | O_TRUNC,
169               (mode_t) 0600)) == -1) {
170         logfile(LOG_WARNING, _("Unable to create [%s]: [%s]"), store_file,
171                 strerror(errno));
172         ALLOCA_FREE(store_file);
173         ALLOCA_FREE(store_file_tmp);
174         return -1;
175     }
176     logfile(LOG_DEBUG, _("[%s] = fd #%d"), store_file, client->write_fd);
177     if (safe_write(client->write_fd,
178                    client->read_buf + (size_t) 9U + client->key_len,
179                    client->data_len) < 0) {
180         logfile(LOG_WARNING, _("Write error: [%s]"), strerror(errno));
181     }
182     (void) close(client->write_fd);
183     client->write_fd = -1;
184     logfile(LOG_DEBUG,
185             _("Renaming [%s] to [%s]"), store_file_tmp, store_file);
186     if (rename(store_file_tmp, store_file) != 0) {
187         logfile(LOG_WARNING, _("Unable to rename [%s] to [%s]: [%s]"),
188                 store_file_tmp, store_file, strerror(errno));
189         (void) unlink(store_file_tmp);
190         ALLOCA_FREE(store_file);
191         ALLOCA_FREE(store_file_tmp);
192         return -1;
193     }
194     ALLOCA_FREE(store_file);
195     ALLOCA_FREE(store_file_tmp);
196     if ((client->returncode_bufev =
197          bufferevent_new(client->client_fd,
198                          returncode_bufferev_read_cb,
199                          returncode_bufferev_write_cb,
200                          returncode_bufferev_error_cb,
201                          client)) == NULL) {
202         logfile(LOG_WARNING, _("Unable to create a bufferevent for fd #%d"),
203                 client->client_fd);
204     }
205     (void) bufferevent_write(client->returncode_bufev, (void *) RETURNCODE_OK,
206                              sizeof RETURNCODE_OK - (size_t) 1U);
207 
208     return 0;
209 }
210 
client_process_fetch(Client * const client)211 static int client_process_fetch(Client * const client)
212 {
213     char *store_file;
214     char *store_file_pnt;
215     size_t sizeof_store_file;
216     struct stat st;
217 
218     logfile(LOG_DEBUG, _("client_process_fetch, fd #%d"), client->client_fd);
219     if (client->offset_read_buf < (size_t) 6U) {
220         return -1;
221     }
222     sizeof_store_file = (sizeof "/") - (size_t) 1U +
223         client->key_len + (size_t) 1U;
224     if ((store_file = ALLOCA(sizeof_store_file)) == NULL) {
225         logfile(LOG_WARNING, _("Out of stack for ALLOCA"));
226         return -1;
227     }
228     store_file_pnt = store_file;
229     *store_file_pnt++ = '/';
230     if (validate_key(client->read_buf + (size_t) 5U, client->key_len) != 0) {
231         ALLOCA_FREE(store_file);
232         logfile(LOG_WARNING, _("Invalid key name"));
233         return -1;
234     }
235     memcpy(store_file_pnt, client->read_buf + (size_t) 5U, client->key_len);
236     store_file_pnt += client->key_len;
237     *store_file_pnt = 0;
238     logfile(LOG_DEBUG, _("Reading [%s]"), store_file);
239     if ((client->read_fd = open(store_file, O_RDONLY)) == -1) {
240         logfile(LOG_DEBUG, _("Unable to fetch [%s]: [%s]"), store_file,
241                 strerror(errno));
242         ALLOCA_FREE(store_file);
243         return -1;
244     }
245     logfile(LOG_DEBUG, _("[%s] = fd #%d"), store_file, client->read_fd);
246     ALLOCA_FREE(store_file);
247     if (fstat(client->read_fd, &st) != 0 || st.st_size <= (off_t) 0) {
248         logfile(LOG_DEBUG, _("Unable to stat a previous key (%s) : [%s]"),
249                 store_file, strerror(errno));
250         (void) close(client->read_fd);
251         client->read_fd = -1;
252         ALLOCA_FREE(store_file);
253         return -1;
254     }
255     if ((client->read_mapped_zone = mmap(NULL, st.st_size, PROT_READ,
256                                          MAP_SHARED, client->read_fd,
257                                          (off_t) 0)) == NULL) {
258         logfile(LOG_WARNING, _("Unable to map in memory: [%s]"),
259                 strerror(errno));
260         (void) close(client->read_fd);
261         client->read_fd = -1;
262         ALLOCA_FREE(store_file);
263         return -1;
264     }
265     client->read_mapped_zone_length = st.st_size;
266     if ((client->returncode_bufev =
267          bufferevent_new(client->client_fd,
268                          returncode_bufferev_read_cb,
269                          returncode_bufferev_write_cb,
270                          returncode_bufferev_error_cb,
271                          client)) == NULL) {
272         logfile(LOG_WARNING, _("Unable to create a bufferevent for fd #%d"),
273                 client->client_fd);
274     }
275     (void) bufferevent_write(client->returncode_bufev,
276                              client->read_mapped_zone,
277                              client->read_mapped_zone_length);
278 
279     return 0;
280 }
281 
client_process_delete(Client * const client)282 static int client_process_delete(Client * const client)
283 {
284     char *store_file;
285     char *store_file_pnt;
286     size_t sizeof_store_file;
287 
288     logfile(LOG_DEBUG, _("client_process_delete, fd #%d"), client->client_fd);
289     if (client->offset_read_buf < (size_t) 6U) {
290         return -1;
291     }
292     sizeof_store_file = (sizeof "/") - (size_t) 1U +
293         client->key_len + (size_t) 1U;
294     if ((store_file = ALLOCA(sizeof_store_file)) == NULL) {
295         logfile(LOG_WARNING, _("Out of stack for ALLOCA"));
296         return -1;
297     }
298     store_file_pnt = store_file;
299     *store_file_pnt++ = '/';
300     if (validate_key(client->read_buf + (size_t) 5U, client->key_len) != 0) {
301         ALLOCA_FREE(store_file);
302         logfile(LOG_WARNING, _("Invalid key name"));
303         return -1;
304     }
305     memcpy(store_file_pnt, client->read_buf + (size_t) 5U, client->key_len);
306     store_file_pnt += client->key_len;
307     *store_file_pnt = 0;
308     logfile(LOG_DEBUG, _("Deleting [%s]"), store_file);
309     if (unlink(store_file) != 0) {
310         logfile(LOG_INFO, _("Unable to delete [%s]: [%s]"), store_file,
311                 strerror(errno));
312         ALLOCA_FREE(store_file);
313         return -1;
314     }
315     if ((client->returncode_bufev =
316          bufferevent_new(client->client_fd,
317                          returncode_bufferev_read_cb,
318                          returncode_bufferev_write_cb,
319                          returncode_bufferev_error_cb,
320                          client)) == NULL) {
321         logfile(LOG_WARNING, _("Unable to create a bufferevent for fd #%d"),
322                 client->client_fd);
323     }
324     (void) bufferevent_write(client->returncode_bufev, (void *) RETURNCODE_OK,
325                              sizeof RETURNCODE_OK - (size_t) 1U);
326 
327     return 0;
328 }
329 
client_read(const int client_fd,short event,void * client_)330 static void client_read(const int client_fd, short event, void *client_)
331 {
332     Client * const client = client_;
333     size_t needed_size;
334     ssize_t readen;
335 
336     if (event == EV_TIMEOUT) {
337         logfile(LOG_DEBUG, _("Timeout on descriptor #%d"), client->client_fd);
338         client_disconnect(client);
339         return;
340     }
341     needed_size = client->offset_read_buf + read_chunk_size;
342     if (client->sizeof_read_buf < needed_size) {
343         unsigned char *tmp_buf;
344 
345         if ((tmp_buf = realloc(client->read_buf,
346                                needed_size)) == NULL) {
347             logfile(LOG_ERR, _("Out of memory for client read buffers"));
348             client_disconnect(client);
349             return;
350         }
351         client->read_buf = tmp_buf;
352         client->sizeof_read_buf = needed_size;
353     }
354     readen = read
355         (client->client_fd,
356          client->read_buf + client->offset_read_buf,
357          client->sizeof_read_buf - client->offset_read_buf);
358     if (readen <= (ssize_t) 0) {
359         if (errno == EINTR || errno == EAGAIN) {
360             logfile(LOG_DEBUG, _("Interrupted read for fd #%d: [%s]"),
361                     client_fd, strerror(errno));
362             event_add(&client->ev_client_read, &timeout);
363             return;
364         }
365         if (readen == (ssize_t) 0) {
366             logfile(LOG_DEBUG, _("Descriptor #%d has disconnected"),
367                     client->client_fd);
368         } else {
369             logfile(LOG_DEBUG,
370                     _("Descriptor #%d has disconnected with error [%s]"),
371                     strerror(errno));
372         }
373         client_disconnect(client);
374         return;
375     }
376     client->offset_read_buf += readen;
377     logfile(LOG_DEBUG, _("Activity on client #%d (%d) offset=%lu"),
378             client->client_fd, event,
379             (unsigned int) client->offset_read_buf);
380     if (client->client_command == CC_UNDEF) {
381         if (client->read_buf[0] == CC_FETCH &&
382             client->offset_read_buf > 5) {
383             client->key_len =
384                 client->read_buf[1] << 24 | client->read_buf[2] << 16 |
385                 client->read_buf[3] << 8 | client->read_buf[4];
386             client->total_len = (size_t) 1U + (size_t) 4U + client->key_len;
387             client->client_command = CC_FETCH;
388         } else if (client->read_buf[0] == CC_DELETE &&
389             client->offset_read_buf > 5) {
390             client->key_len =
391                 client->read_buf[1] << 24 | client->read_buf[2] << 16 |
392                 client->read_buf[3] << 8 | client->read_buf[4];
393             client->total_len = (size_t) 1U + (size_t) 4U + client->key_len;
394             client->client_command = CC_DELETE;
395         } else if (client->read_buf[0] == CC_STORE &&
396             client->offset_read_buf > 9) {
397             client->key_len =
398                 client->read_buf[1] << 24 | client->read_buf[2] << 16 |
399                 client->read_buf[3] << 8 | client->read_buf[4];
400             client->data_len =
401                 client->read_buf[5] << 24 | client->read_buf[6] << 16 |
402                 client->read_buf[7] << 8 | client->read_buf[8];
403             client->total_len = (size_t) 1U + (size_t) 4U + (size_t) 4U +
404                 client->key_len + client->data_len;
405             client->client_command = CC_STORE;
406         } else if (client->offset_read_buf > 0 &&
407                    client->read_buf[0] != CC_STORE &&
408                    client->read_buf[0] != CC_FETCH) {
409             logfile(LOG_WARNING, _("Unknown command [%d], good bye."),
410                     (int) client->read_buf[0]);
411             client_disconnect(client);
412             return;
413         }
414     }
415     if (client->total_len > (size_t) 0U &&
416         client->offset_read_buf == client->total_len) {
417         if (client->client_command == CC_STORE) {
418             if (client_process_store(client) < 0) {
419                 client_disconnect(client);
420             }
421             return;
422         } else if (client->client_command == CC_DELETE) {
423             if (client_process_delete(client) < 0) {
424                 client_disconnect(client);
425             }
426             return;
427         } else if (client->client_command == CC_FETCH) {
428             if (client_process_fetch(client) < 0) {
429                 client_disconnect(client);
430             }
431             return;
432         } else {
433             logfile(LOG_ERR, _("Unknown but ok command?"));
434         }
435         client_disconnect(client);
436         return;
437     }
438     if (client->total_len > (size_t) 0U &&
439         client->offset_read_buf > client->total_len) {
440         logfile(LOG_WARNING,
441                 _("Request too long total len = %lu, now = %lu. Good bye."),
442                 (unsigned long) client->total_len,
443                 (unsigned long) client->offset_read_buf);
444         client_disconnect(client);
445         return;
446     }
447     if (client->offset_read_buf >= max_read_size) {
448         logfile(LOG_WARNING,
449                 _("Request too long max = %lu, now = %lu. Good bye."),
450                 (unsigned long) max_read_size,
451                 (unsigned long) client->offset_read_buf);
452         client_disconnect(client);
453         return;
454     }
455     event_add(&client->ev_client_read, &timeout);
456 }
457 
new_client(const int listen_fd,short event,void * ev)458 void new_client(const int listen_fd, short event, void *ev)
459 {
460     Client *client;
461     struct sockaddr_storage client_sa;
462     socklen_t client_sa_len = sizeof client_sa;
463     int client_fd;
464 
465     (void) ev;
466     if ((event & EV_READ) == 0) {
467         logfile(LOG_DEBUG, _("Wrong event %d received on fd #%d"),
468                 (int) event, listen_fd);
469         return;
470     }
471     memset(&client_sa, 0, sizeof client_sa);
472     if ((client_fd = accept(listen_fd, (struct sockaddr *) &client_sa,
473                             &client_sa_len)) < 0) {
474         logfile(LOG_DEBUG, _("accept(): [%s]"), strerror(errno));
475         return;
476     }
477     if (client_sa_len <= (socklen_t) 0U) {
478         (void) close(client_fd);
479         return;
480     }
481     fd_nonblock(client_fd);
482     if ((client = malloc(sizeof *client)) == NULL) {
483         (void) close(client_fd);
484         logfile(LOG_ERR, _("Out of memory to accept a new client"));
485         return;
486     }
487     client->client_fd = client_fd;
488     client->read_buf = NULL;
489     client->sizeof_read_buf = (size_t) 0U;
490     client->offset_read_buf = (size_t) 0U;
491     client->client_command = CC_UNDEF;
492     client->key_len = (size_t) 0U;
493     client->data_len = (size_t) 0U;
494     client->total_len = (size_t) 0U;
495     client->write_fd = -1;
496     client->read_fd = -1;
497     client->read_mapped_zone = NULL;
498     client->read_mapped_zone_length = (size_t) 0U;
499     client->returncode_bufev = NULL;
500     event_set(&client->ev_client_read, client_fd, EV_READ,
501               client_read, client);
502     event_add(&client->ev_client_read, &timeout);
503     logfile(LOG_DEBUG, _("New client on fd #%d"), client_fd);
504 }
505