]> git.tuebingen.mpg.de Git - paraslash.git/blob - command.c
9cf8b049cf2acb76bbc4329b83472e2b74f17de9
[paraslash.git] / command.c
1 /*
2  * Copyright (C) 1997 Andre Noll <maan@tuebingen.mpg.de>
3  *
4  * Licensed under the GPL v2. For licencing details see COPYING.
5  */
6
7 /** \file command.c Client authentication and server commands. */
8
9 #include <netinet/in.h>
10 #include <sys/socket.h>
11 #include <regex.h>
12 #include <signal.h>
13 #include <sys/types.h>
14 #include <osl.h>
15 #include <arpa/inet.h>
16 #include <sys/un.h>
17 #include <netdb.h>
18 #include <lopsub.h>
19
20 #include "para.h"
21 #include "error.h"
22 #include "crypt.h"
23 #include "sideband.h"
24 #include "command.h"
25 #include "server.cmdline.h"
26 #include "string.h"
27 #include "afh.h"
28 #include "afs.h"
29 #include "server.h"
30 #include "list.h"
31 #include "send.h"
32 #include "sched.h"
33 #include "vss.h"
34 #include "net.h"
35 #include "daemon.h"
36 #include "fd.h"
37 #include "ipc.h"
38 #include "server_cmd.lsg.h"
39 #include "user_list.h"
40 #include "afs.command_list.h"
41 #include "signal.h"
42 #include "version.h"
43
44 #define SERVER_CMD_AUX_INFO(_arg) _arg,
45 static const unsigned server_command_perms[] = {LSG_SERVER_CMD_AUX_INFOS};
46 #undef SERVER_CMD_AUX_INFO
47 #define SERVER_CMD_AUX_INFO(_arg) #_arg,
48 static const char * const server_command_perms_txt[] = {LSG_SERVER_CMD_AUX_INFOS};
49 #undef SERVER_CMD_AUX_INFO
50
51 typedef int server_command_handler_t(struct command_context *);
52
53 /* Defines one command of para_server. */
54 struct server_command {
55         /* The name of the command. */
56         const char *name;
57         /* Pointer to the function that handles the command. */
58         server_command_handler_t *handler;
59         /* The privileges a user must have to execute this command. */
60         unsigned int perms;
61         /* One-line description of the command. */
62         const char *description;
63         /* Summary of the command line options. */
64         const char *usage;
65         /* The long help text. */
66         const char *help;
67 };
68
69 static struct server_command afs_cmds[] = {DEFINE_AFS_CMD_ARRAY};
70
71 /** Commands including options must be shorter than this. */
72 #define MAX_COMMAND_LEN 32768
73
74 extern int mmd_mutex;
75 extern struct misc_meta_data *mmd;
76 extern struct sender senders[];
77 int send_afs_status(struct command_context *cc, int parser_friendly);
78
79 static void dummy(__a_unused int s)
80 {
81 }
82
83 /*
84  * Compute human readable vss status text.
85  *
86  * We can't call vss_playing() and friends here because those functions read
87  * the flags from the primary mmd structure, so calling them from command
88  * handler context would require to take the mmd lock. At the time the function
89  * is called we already took a copy of the mmd structure and want to use the
90  * flags value of the copy for computing the vss status text.
91  */
92 static char *vss_status_tohuman(unsigned int flags)
93 {
94         if (flags & VSS_PLAYING)
95                 return para_strdup("playing");
96         if (flags & VSS_NEXT)
97                 return para_strdup("stopped");
98         return para_strdup("paused");
99 }
100
101 /*
102  * Never returns NULL.
103  */
104 static char *vss_get_status_flags(unsigned int flags)
105 {
106         char *msg = para_malloc(5 * sizeof(char));
107
108         msg[0] = (flags & VSS_PLAYING)? 'P' : '_';
109         msg[1] = (flags & VSS_NOMORE)? 'O' : '_';
110         msg[2] = (flags & VSS_NEXT)? 'N' : '_';
111         msg[3] = (flags & VSS_REPOS)? 'R' : '_';
112         msg[4] = '\0';
113         return msg;
114 }
115
116 static unsigned get_status(struct misc_meta_data *nmmd, bool parser_friendly,
117                 char **result)
118 {
119         char *status, *flags; /* vss status info */
120         /* nobody updates our version of "now" */
121         long offset = (nmmd->offset + 500) / 1000;
122         struct timeval current_time;
123         struct para_buffer b = {.flags = parser_friendly? PBF_SIZE_PREFIX : 0};
124
125         /* report real status */
126         status = vss_status_tohuman(nmmd->vss_status_flags);
127         flags = vss_get_status_flags(nmmd->vss_status_flags);
128         clock_get_realtime(&current_time);
129         /*
130          * The calls to WRITE_STATUS_ITEM() below never fail because
131          * b->max_size is zero (unlimited), see para_printf(). However, clang
132          * is not smart enough to prove this and complains nevertheless.
133          * Casting the return value to void silences clang.
134          */
135         (void)WRITE_STATUS_ITEM(&b, SI_STATUS, "%s\n", status);
136         (void)WRITE_STATUS_ITEM(&b, SI_STATUS_FLAGS, "%s\n", flags);
137         (void)WRITE_STATUS_ITEM(&b, SI_OFFSET, "%li\n", offset);
138         (void)WRITE_STATUS_ITEM(&b, SI_AFS_MODE, "%s\n", mmd->afs_mode_string);
139         (void)WRITE_STATUS_ITEM(&b, SI_STREAM_START, "%lu.%lu\n",
140                 (long unsigned)nmmd->stream_start.tv_sec,
141                 (long unsigned)nmmd->stream_start.tv_usec);
142         (void)WRITE_STATUS_ITEM(&b, SI_CURRENT_TIME, "%lu.%lu\n",
143                 (long unsigned)current_time.tv_sec,
144                 (long unsigned)current_time.tv_usec);
145         free(flags);
146         free(status);
147         *result = b.buf;
148         return b.offset;
149 }
150
151 /**
152  * Send a sideband packet through a blocking file descriptor.
153  *
154  * \param scc fd and crypto keys.
155  * \param buf The buffer to send.
156  * \param numbytes The size of \a buf.
157  * \param band The sideband designator of this packet.
158  * \param dont_free If true, never deallocate \a buf.
159  *
160  * The nonblock flag must be disabled for the file descriptor given by \a scc.
161  *
162  * Stream cipher encryption is automatically activated if necessary via the
163  * sideband transformation, depending on the value of \a band.
164  *
165  * \return Standard.
166  *
167  * \sa \ref send_sb_va().
168  */
169 int send_sb(struct stream_cipher_context *scc, void *buf, size_t numbytes,
170                 int band, bool dont_free)
171 {
172         int ret;
173         struct sb_context *sbc;
174         struct iovec iov[2];
175         sb_transformation trafo = band < SBD_PROCEED? NULL : sc_trafo;
176         struct sb_buffer sbb = SBB_INIT(band, buf, numbytes);
177
178         sbc = sb_new_send(&sbb, dont_free, trafo, scc->send);
179         do {
180                 ret = sb_get_send_buffers(sbc, iov);
181                 ret = xwritev(scc->fd, iov, ret);
182                 if (ret < 0)
183                         goto fail;
184         } while (sb_sent(sbc, ret) == false);
185         return 1;
186 fail:
187         sb_free(sbc);
188         return ret;
189 }
190
191 /**
192  * Create a variable sized buffer and send it as a sideband packet.
193  *
194  * \param scc Passed to \ref send_sb.
195  * \param band See \ref send_sb.
196  * \param fmt The format string.
197  *
198  * \return The return value of the underlying call to \ref send_sb.
199  */
200 __printf_3_4 int send_sb_va(struct stream_cipher_context *scc, int band,
201                 const char *fmt, ...)
202 {
203         va_list ap;
204         char *msg;
205         int ret;
206
207         va_start(ap, fmt);
208         ret = xvasprintf(&msg, fmt, ap);
209         va_end(ap);
210         return send_sb(scc, msg, ret, band, false);
211 }
212
213 /**
214  * Send an error message to a client.
215  *
216  * \param cc Client info.
217  * \param err The (positive) error code.
218  *
219  * \return The return value of the underlying call to send_sb_va().
220  */
221 int send_strerror(struct command_context *cc, int err)
222 {
223         return send_sb_va(&cc->scc, SBD_ERROR_LOG, "%s\n", para_strerror(err));
224 }
225
226 /**
227  * Send an error context to a client,
228  *
229  * \param cc Client info.
230  * \param errctx The error context string.
231  *
232  * \return The return value of the underlying call to send_sb_va().
233  *
234  * This function frees the error context string after it was sent.
235  */
236 int send_errctx(struct command_context *cc, char *errctx)
237 {
238         int ret;
239
240         if (!errctx)
241                 return 0;
242         ret = send_sb_va(&cc->scc, SBD_ERROR_LOG, "%s\n", errctx);
243         free(errctx);
244         return ret;
245 }
246
247 static int check_sender_args(struct command_context *cc,
248                 struct lls_parse_result *lpr, struct sender_command_data *scd)
249 {
250         int i, ret;
251         const char *subcmds[] = {SENDER_SUBCOMMANDS};
252         const char *arg;
253         char *errctx;
254         unsigned num_inputs = lls_num_inputs(lpr);
255
256         scd->sender_num = -1;
257         ret = lls(lls_check_arg_count(lpr, 2, INT_MAX, &errctx));
258         if (ret < 0) {
259                 send_errctx(cc, errctx);
260                 return ret;
261         }
262         arg = lls_input(0, lpr);
263         for (i = 0; senders[i].name; i++)
264                 if (!strcmp(senders[i].name, arg))
265                         break;
266         if (!senders[i].name)
267                 return -E_COMMAND_SYNTAX;
268         scd->sender_num = i;
269         arg = lls_input(1, lpr);
270         for (i = 0; subcmds[i]; i++)
271                 if (!strcmp(subcmds[i], arg))
272                         break;
273         if (!subcmds[i])
274                 return -E_COMMAND_SYNTAX;
275         scd->cmd_num = i;
276         if (!senders[scd->sender_num].client_cmds[scd->cmd_num])
277                 return -E_SENDER_CMD;
278         switch (scd->cmd_num) {
279         case SENDER_on:
280         case SENDER_off:
281                 if (num_inputs != 2)
282                         return -E_COMMAND_SYNTAX;
283                 break;
284         case SENDER_deny:
285         case SENDER_allow:
286                 if (num_inputs != 3 || parse_cidr(lls_input(2, lpr), scd->host,
287                                 sizeof(scd->host), &scd->netmask) == NULL)
288                         return -E_COMMAND_SYNTAX;
289                 break;
290         case SENDER_add:
291         case SENDER_delete:
292                 if (num_inputs != 3)
293                         return -E_COMMAND_SYNTAX;
294                 return parse_fec_url(lls_input(2, lpr), scd);
295         default:
296                 return -E_COMMAND_SYNTAX;
297         }
298         return 1;
299 }
300
301 /**
302  * Send a sideband packet through a blocking file descriptor.
303  *
304  * \param scc fd and crypto keys.
305  * \param expected_band The expected band designator.
306  * \param max_size Passed to \ref sb_new_recv().
307  * \param result Body of the sideband packet is returned here.
308  *
309  * If \a expected_band is not \p SBD_ANY, the band designator of the received
310  * sideband packet is compared to \a expected_band and a mismatch is considered
311  * an error.
312  *
313  * \return Standard.
314  */
315 int recv_sb(struct stream_cipher_context *scc,
316                 enum sb_designator expected_band,
317                 size_t max_size, struct iovec *result)
318 {
319         int ret;
320         struct sb_context *sbc;
321         struct iovec iov;
322         struct sb_buffer sbb;
323         sb_transformation trafo;
324
325         trafo = expected_band != SBD_ANY && expected_band < SBD_PROCEED?
326                 NULL : sc_trafo;
327         sbc = sb_new_recv(max_size, trafo, scc->recv);
328         for (;;) {
329                 sb_get_recv_buffer(sbc, &iov);
330                 ret = recv_bin_buffer(scc->fd, iov.iov_base, iov.iov_len);
331                 if (ret == 0)
332                         ret = -E_EOF;
333                 if (ret < 0)
334                         goto fail;
335                 ret = sb_received(sbc, ret, &sbb);
336                 if (ret < 0)
337                         goto fail;
338                 if (ret > 0)
339                         break;
340         }
341         ret = -E_BAD_BAND;
342         if (expected_band != SBD_ANY && sbb.band != expected_band)
343                 goto fail;
344         *result = sbb.iov;
345         return 1;
346 fail:
347         sb_free(sbc);
348         return ret;
349 }
350
351 static int com_sender(struct command_context *cc, struct lls_parse_result *lpr)
352 {
353         int i, ret = 0;
354         char *msg = NULL;
355         struct sender_command_data scd;
356
357         if (lls_num_inputs(lpr) == 0) {
358                 for (i = 0; senders[i].name; i++) {
359                         char *tmp;
360                         ret = xasprintf(&tmp, "%s%s\n", msg? msg : "",
361                                 senders[i].name);
362                         free(msg);
363                         msg = tmp;
364                 }
365                 return send_sb(&cc->scc, msg, ret, SBD_OUTPUT, false);
366         }
367         ret = check_sender_args(cc, lpr, &scd);
368         if (ret < 0) {
369                 if (scd.sender_num < 0)
370                         return ret;
371                 if (strcmp(lls_input(1, lpr), "status") == 0)
372                         msg = senders[scd.sender_num].status();
373                 else
374                         msg = senders[scd.sender_num].help();
375                 return send_sb(&cc->scc, msg, strlen(msg), SBD_OUTPUT, false);
376         }
377
378         switch (scd.cmd_num) {
379         case SENDER_add:
380         case SENDER_delete:
381                 assert(senders[scd.sender_num].resolve_target);
382                 ret = senders[scd.sender_num].resolve_target(lls_input(2, lpr),
383                         &scd);
384                 if (ret < 0)
385                         return ret;
386         }
387
388         for (i = 0; i < 10; i++) {
389                 mutex_lock(mmd_mutex);
390                 if (mmd->sender_cmd_data.cmd_num >= 0) {
391                         /* another sender command is active, retry in 100ms */
392                         struct timespec ts = {.tv_nsec = 100 * 1000 * 1000};
393                         mutex_unlock(mmd_mutex);
394                         nanosleep(&ts, NULL);
395                         continue;
396                 }
397                 mmd->sender_cmd_data = scd;
398                 mutex_unlock(mmd_mutex);
399                 break;
400         }
401         return (i < 10)? 1 : -E_LOCK;
402 }
403 EXPORT_SERVER_CMD_HANDLER(sender);
404
405 static int com_si(struct command_context *cc,
406                 __a_unused struct lls_parse_result *lpr)
407 {
408         char *msg, *ut;
409         int ret;
410
411         ut = daemon_get_uptime_str(now);
412         mutex_lock(mmd_mutex);
413         ret = xasprintf(&msg,
414                 "up: %s\nplayed: %u\n"
415                 "server_pid: %d\n"
416                 "afs_pid: %d\n"
417                 "connections (active/accepted/total): %u/%u/%u\n"
418                 "current loglevel: %s\n"
419                 "supported audio formats: %s\n",
420                 ut, mmd->num_played,
421                 (int)getppid(),
422                 (int)mmd->afs_pid,
423                 mmd->active_connections,
424                 mmd->num_commands,
425                 mmd->num_connects,
426                 conf.loglevel_arg,
427                 AUDIO_FORMAT_HANDLERS
428         );
429         mutex_unlock(mmd_mutex);
430         free(ut);
431         return send_sb(&cc->scc, msg, ret, SBD_OUTPUT, false);
432 }
433 EXPORT_SERVER_CMD_HANDLER(si);
434
435 static int com_version(struct command_context *cc, struct lls_parse_result *lpr)
436 {
437         char *msg;
438         size_t len;
439
440         if (SERVER_CMD_OPT_GIVEN(VERSION, VERBOSE, lpr))
441                 len = xasprintf(&msg, "%s", version_text("server"));
442         else
443                 len = xasprintf(&msg, "%s\n", version_single_line("server"));
444         return send_sb(&cc->scc, msg, len, SBD_OUTPUT, false);
445 }
446 EXPORT_SERVER_CMD_HANDLER(version);
447
448 /** These status items are cleared if no audio file is currently open. */
449 #define EMPTY_STATUS_ITEMS \
450         ITEM(PATH) \
451         ITEM(DIRECTORY) \
452         ITEM(BASENAME) \
453         ITEM(SCORE) \
454         ITEM(ATTRIBUTES_BITMAP) \
455         ITEM(ATTRIBUTES_TXT) \
456         ITEM(HASH) \
457         ITEM(IMAGE_ID) \
458         ITEM(IMAGE_NAME) \
459         ITEM(LYRICS_ID) \
460         ITEM(LYRICS_NAME) \
461         ITEM(BITRATE) \
462         ITEM(FORMAT) \
463         ITEM(FREQUENCY) \
464         ITEM(CHANNELS) \
465         ITEM(DURATION) \
466         ITEM(SECONDS_TOTAL) \
467         ITEM(NUM_PLAYED) \
468         ITEM(LAST_PLAYED) \
469         ITEM(TECHINFO) \
470         ITEM(ARTIST) \
471         ITEM(TITLE) \
472         ITEM(YEAR) \
473         ITEM(ALBUM) \
474         ITEM(COMMENT) \
475         ITEM(MTIME) \
476         ITEM(FILE_SIZE) \
477         ITEM(CHUNK_TIME) \
478         ITEM(NUM_CHUNKS) \
479         ITEM(AMPLIFICATION) \
480
481 /**
482  * Write a list of audio-file related status items with empty values.
483  *
484  * This is used by vss when currently no audio file is open.
485  */
486 static unsigned empty_status_items(bool parser_friendly, char **result)
487 {
488         char *esi;
489         unsigned len;
490
491         if (parser_friendly)
492                 len = xasprintf(&esi,
493                         #define ITEM(x) "0004 %02x:\n"
494                         EMPTY_STATUS_ITEMS
495                         #undef ITEM
496                         #define ITEM(x) , (unsigned) SI_ ## x
497                         EMPTY_STATUS_ITEMS
498                         #undef ITEM
499                 );
500         else
501                 len = xasprintf(&esi,
502                         #define ITEM(x) "%s:\n"
503                         EMPTY_STATUS_ITEMS
504                         #undef ITEM
505                         #define ITEM(x) ,status_item_list[SI_ ## x]
506                         EMPTY_STATUS_ITEMS
507                         #undef ITEM
508                 );
509         *result = esi;
510         return len;
511 }
512 #undef EMPTY_STATUS_ITEMS
513
514 static int com_stat(struct command_context *cc, struct lls_parse_result *lpr)
515 {
516         int ret;
517         struct misc_meta_data tmp, *nmmd = &tmp;
518         char *s;
519         bool parser_friendly = SERVER_CMD_OPT_GIVEN(STAT, PARSER_FRIENDLY,
520                 lpr) > 0;
521         uint32_t num = SERVER_CMD_UINT32_VAL(STAT, NUM, lpr);
522
523         para_sigaction(SIGUSR1, dummy);
524         for (;;) {
525                 /*
526                  * Copy the mmd structure to minimize the time we hold the mmd
527                  * lock.
528                  */
529                 mutex_lock(mmd_mutex);
530                 *nmmd = *mmd;
531                 mutex_unlock(mmd_mutex);
532                 ret = get_status(nmmd, parser_friendly, &s);
533                 ret = send_sb(&cc->scc, s, ret, SBD_OUTPUT, false);
534                 if (ret < 0)
535                         goto out;
536                 if (nmmd->vss_status_flags & VSS_NEXT) {
537                         char *esi;
538                         ret = empty_status_items(parser_friendly, &esi);
539                         ret = send_sb(&cc->scc, esi, ret, SBD_OUTPUT, false);
540                         if (ret < 0)
541                                 goto out;
542                 } else
543                         send_afs_status(cc, parser_friendly);
544                 ret = 1;
545                 if (num > 0 && !--num)
546                         goto out;
547                 sleep(50);
548                 ret = -E_SERVER_CRASH;
549                 if (getppid() == 1)
550                         goto out;
551         }
552 out:
553         return ret;
554 }
555 EXPORT_SERVER_CMD_HANDLER(stat);
556
557 /* fixed-length, human readable permission string */
558 const char *server_cmd_perms_str(unsigned int perms)
559 {
560         static char result[5];
561
562         result[0] = perms & AFS_READ? 'a' : '-';
563         result[1] = perms & AFS_WRITE? 'A' : '-';
564         result[2] = perms & VSS_READ? 'v' : '-';
565         result[3] = perms & VSS_WRITE? 'V' : '-';
566         result[4] = '\0';
567         return result;
568 }
569
570 static int send_list_of_commands(struct command_context *cc)
571 {
572         int i;
573         const struct lls_command *cmd;
574         char *msg = para_strdup("");
575
576         for (i = 1; (cmd = lls_cmd(i, server_cmd_suite)); i++) {
577                 const char *perms = server_cmd_perms_str(server_command_perms[i]);
578                 char *tmp = make_message("%s%s\t%s\t%s\n", msg,
579                         lls_command_name(cmd), perms, lls_purpose(cmd));
580                 free(msg);
581                 msg = tmp;
582         }
583         return send_sb(&cc->scc, msg, strlen(msg), SBD_OUTPUT, false);
584 }
585
586 /* returns string that must be freed by the caller */
587 static struct server_command *get_cmd_ptr(const char *name, char **handler)
588 {
589         struct server_command *cmd;
590
591         /* not found, look for commands supported by afs */
592         for (cmd = afs_cmds; cmd->name; cmd++)
593                 if (!strcmp(cmd->name, name)) {
594                         if (handler)
595                                 *handler = para_strdup("afs");
596                         return cmd;
597                 }
598         return NULL;
599 }
600
601 static int com_help(struct command_context *cc, struct lls_parse_result *lpr)
602 {
603         const char *perms;
604         char *long_help, *buf, *errctx;
605         int ret;
606         const struct lls_command *cmd;
607
608         ret = lls(lls_check_arg_count(lpr, 0, 1, &errctx));
609         if (ret < 0) {
610                 send_errctx(cc, errctx);
611                 return ret;
612         }
613         if (lls_num_inputs(lpr) == 0)
614                 return send_list_of_commands(cc);
615         /* argument given for help */
616         ret = lls(lls_lookup_subcmd(lls_input(0, lpr), server_cmd_suite,
617                 &errctx));
618         if (ret < 0) {
619                 send_errctx(cc, errctx);
620                 return ret;
621         }
622         cmd = lls_cmd(ret, server_cmd_suite);
623         perms = server_command_perms_txt[ret];
624         long_help = lls_long_help(cmd);
625         assert(long_help);
626         ret = xasprintf(&buf, "%spermissions: %s\n", long_help, perms);
627         free(long_help);
628         return send_sb(&cc->scc, buf, ret, SBD_OUTPUT, false);
629 }
630 EXPORT_SERVER_CMD_HANDLER(help);
631
632 static int com_hup(__a_unused struct command_context *cc,
633                 __a_unused struct lls_parse_result *lpr)
634 {
635         kill(getppid(), SIGHUP);
636         return 1;
637 }
638 EXPORT_SERVER_CMD_HANDLER(hup);
639
640 static int com_term(__a_unused struct command_context *cc,
641                 __a_unused struct lls_parse_result *lpr)
642 {
643         kill(getppid(), SIGTERM);
644         return 1;
645 }
646 EXPORT_SERVER_CMD_HANDLER(term);
647
648 static int com_play(__a_unused struct command_context *cc,
649                 __a_unused struct lls_parse_result *lpr)
650 {
651         mutex_lock(mmd_mutex);
652         mmd->new_vss_status_flags |= VSS_PLAYING;
653         mmd->new_vss_status_flags &= ~VSS_NOMORE;
654         mutex_unlock(mmd_mutex);
655         return 1;
656 }
657 EXPORT_SERVER_CMD_HANDLER(play);
658
659 static int com_stop(__a_unused struct command_context *cc,
660                 __a_unused struct lls_parse_result *lpr)
661 {
662         mutex_lock(mmd_mutex);
663         mmd->new_vss_status_flags &= ~VSS_PLAYING;
664         mmd->new_vss_status_flags &= ~VSS_REPOS;
665         mmd->new_vss_status_flags |= VSS_NEXT;
666         mutex_unlock(mmd_mutex);
667         return 1;
668 }
669 EXPORT_SERVER_CMD_HANDLER(stop);
670
671 static int com_pause(__a_unused struct command_context *cc,
672                 __a_unused struct lls_parse_result *lpr)
673 {
674         mutex_lock(mmd_mutex);
675         if (!vss_paused() && !vss_stopped()) {
676                 mmd->events++;
677                 mmd->new_vss_status_flags &= ~VSS_PLAYING;
678                 mmd->new_vss_status_flags &= ~VSS_NEXT;
679         }
680         mutex_unlock(mmd_mutex);
681         return 1;
682 }
683 EXPORT_SERVER_CMD_HANDLER(pause);
684
685 static int com_next(__a_unused struct command_context *cc,
686                 __a_unused struct lls_parse_result *lpr)
687 {
688         mutex_lock(mmd_mutex);
689         mmd->events++;
690         mmd->new_vss_status_flags |= VSS_NEXT;
691         mutex_unlock(mmd_mutex);
692         return 1;
693 }
694 EXPORT_SERVER_CMD_HANDLER(next);
695
696 static int com_nomore(__a_unused struct command_context *cc,
697                 __a_unused struct lls_parse_result *lpr)
698 {
699         mutex_lock(mmd_mutex);
700         if (vss_playing() || vss_paused())
701                 mmd->new_vss_status_flags |= VSS_NOMORE;
702         mutex_unlock(mmd_mutex);
703         return 1;
704 }
705 EXPORT_SERVER_CMD_HANDLER(nomore);
706
707 static int com_ff(__a_unused struct command_context *cc,
708                 struct lls_parse_result *lpr)
709 {
710         long promille;
711         int ret, backwards = 0;
712         unsigned i;
713         char c, *errctx;
714
715         ret = lls(lls_check_arg_count(lpr, 1, 1, &errctx));
716         if (ret < 0) {
717                 send_errctx(cc, errctx);
718                 return ret;
719         }
720         if (!(ret = sscanf(lls_input(0, lpr), "%u%c", &i, &c)))
721                 return -E_COMMAND_SYNTAX;
722         if (ret > 1 && c == '-')
723                 backwards = 1; /* jmp backwards */
724         mutex_lock(mmd_mutex);
725         ret = -E_NO_AUDIO_FILE;
726         if (!mmd->afd.afhi.chunks_total || !mmd->afd.afhi.seconds_total)
727                 goto out;
728         promille = (1000 * mmd->current_chunk) / mmd->afd.afhi.chunks_total;
729         if (backwards)
730                 promille -= 1000 * i / mmd->afd.afhi.seconds_total;
731         else
732                 promille += 1000 * i / mmd->afd.afhi.seconds_total;
733         if (promille < 0)
734                 promille = 0;
735         if (promille > 1000) {
736                 mmd->new_vss_status_flags |= VSS_NEXT;
737                 goto out;
738         }
739         mmd->repos_request = (mmd->afd.afhi.chunks_total * promille) / 1000;
740         mmd->new_vss_status_flags |= VSS_REPOS;
741         mmd->new_vss_status_flags &= ~VSS_NEXT;
742         mmd->events++;
743         ret = 1;
744 out:
745         mutex_unlock(mmd_mutex);
746         return ret;
747 }
748 EXPORT_SERVER_CMD_HANDLER(ff);
749
750 static int com_jmp(__a_unused struct command_context *cc,
751                 struct lls_parse_result *lpr)
752 {
753         long unsigned int i;
754         int ret;
755         char *errctx;
756
757         ret = lls(lls_check_arg_count(lpr, 1, 1, &errctx));
758         if (ret < 0) {
759                 send_errctx(cc, errctx);
760                 return ret;
761         }
762         if (sscanf(lls_input(0, lpr), "%lu", &i) <= 0)
763                 return -ERRNO_TO_PARA_ERROR(EINVAL);
764         mutex_lock(mmd_mutex);
765         ret = -E_NO_AUDIO_FILE;
766         if (!mmd->afd.afhi.chunks_total)
767                 goto out;
768         if (i > 100)
769                 i = 100;
770         PARA_INFO_LOG("jumping to %lu%%\n", i);
771         mmd->repos_request = (mmd->afd.afhi.chunks_total * i + 50) / 100;
772         PARA_INFO_LOG("sent: %lu, offset before jmp: %li\n",
773                 mmd->chunks_sent, mmd->offset);
774         mmd->new_vss_status_flags |= VSS_REPOS;
775         mmd->new_vss_status_flags &= ~VSS_NEXT;
776         ret = 1;
777         mmd->events++;
778 out:
779         mutex_unlock(mmd_mutex);
780         return ret;
781 }
782 EXPORT_SERVER_CMD_HANDLER(jmp);
783
784 static int com_tasks(struct command_context *cc,
785                 __a_unused struct lls_parse_result *lpr)
786 {
787         char *tl = server_get_tasks();
788         assert(tl);
789         return send_sb(&cc->scc, tl, strlen(tl), SBD_OUTPUT, false);
790 }
791 EXPORT_SERVER_CMD_HANDLER(tasks);
792
793 /*
794  * check if perms are sufficient to exec a command having perms cmd_perms.
795  * Returns 0 if perms are sufficient, -E_PERM otherwise.
796  */
797 static int check_perms(unsigned int perms, const struct server_command *cmd_ptr)
798 {
799         PARA_DEBUG_LOG("checking permissions\n");
800         return (cmd_ptr->perms & perms) < cmd_ptr->perms ? -E_PERM : 0;
801 }
802
803 static void reset_signals(void)
804 {
805         para_sigaction(SIGCHLD, SIG_IGN);
806         para_sigaction(SIGINT, SIG_DFL);
807         para_sigaction(SIGTERM, SIG_DFL);
808         para_sigaction(SIGHUP, SIG_DFL);
809 }
810
811 struct connection_features {
812         bool aes_ctr128_requested;
813 };
814
815 static int parse_auth_request(char *buf, int len, struct user **u,
816                 struct connection_features *cf)
817 {
818         int ret;
819         char *p, *username, **features = NULL;
820         size_t auth_rq_len = strlen(AUTH_REQUEST_MSG);
821
822         *u = NULL;
823         memset(cf, 0, sizeof(*cf));
824         if (len < auth_rq_len + 2)
825                 return -E_AUTH_REQUEST;
826         if (strncmp(buf, AUTH_REQUEST_MSG, auth_rq_len) != 0)
827                 return -E_AUTH_REQUEST;
828         username = buf + auth_rq_len;
829         p = strchr(username, ' ');
830         if (p) {
831                 int i;
832                 if (p == username)
833                         return -E_AUTH_REQUEST;
834                 *p = '\0';
835                 p++;
836                 create_argv(p, ",", &features);
837                 for (i = 0; features[i]; i++) {
838                         if (strcmp(features[i], "sideband") == 0)
839                                 continue;
840                         if (strcmp(features[i], "aes_ctr128") == 0)
841                                 cf->aes_ctr128_requested = true;
842                         else {
843                                 ret = -E_BAD_FEATURE;
844                                 goto out;
845                         }
846                 }
847         }
848         PARA_DEBUG_LOG("received auth request for user %s\n", username);
849         *u = lookup_user(username);
850         ret = 1;
851 out:
852         free_argv(features);
853         return ret;
854 }
855
856 #define HANDSHAKE_BUFSIZE 4096
857
858 static int run_command(struct command_context *cc, struct iovec *iov,
859                 const char *peername)
860 {
861         int ret, i;
862         char *p, *end;
863         struct server_command *cmd = NULL;
864         const struct lls_command *lcmd = NULL;
865         unsigned perms;
866         struct lls_parse_result *lpr;
867         char *errctx;
868
869         if (iov->iov_base == NULL || iov->iov_len == 0)
870                 return -ERRNO_TO_PARA_ERROR(EINVAL);
871         p = iov->iov_base;
872         p[iov->iov_len - 1] = '\0'; /* just to be sure */
873
874         ret = lls(lls_lookup_subcmd(p, server_cmd_suite, &errctx));
875         if (ret >= 0 && !strcmp(p, lls_command_name(lls_cmd(ret,
876                         server_cmd_suite)))) {
877                 perms = server_command_perms[ret];
878                 if ((perms & cc->u->perms) != perms)
879                         return -E_PERM;
880                 lcmd = lls_cmd(ret, server_cmd_suite);
881         } else {
882                 cmd = get_cmd_ptr(p, NULL);
883                 if (!cmd) {
884                         send_errctx(cc, errctx);
885                         return ret;
886                 }
887                 perms = cmd->perms;
888                 ret = check_perms(cc->u->perms, cmd);
889                 if (ret < 0)
890                         return ret;
891         }
892         end = iov->iov_base + iov->iov_len;
893         for (i = 0; p < end; i++)
894                 p += strlen(p) + 1;
895         cc->argc = i;
896         cc->argv = para_malloc((cc->argc + 1) * sizeof(char *));
897         for (i = 0, p = iov->iov_base; p < end; i++) {
898                 cc->argv[i] = para_strdup(p);
899                 p += strlen(p) + 1;
900         }
901         cc->argv[cc->argc] = NULL;
902         PARA_NOTICE_LOG("calling com_%s() for %s@%s\n", lcmd?
903                 lls_command_name(lcmd) : cmd->name, cc->u->name, peername);
904         if (lcmd) {
905                 ret = lls(lls_parse(cc->argc, cc->argv, lcmd, &lpr, &errctx));
906                 if (ret >= 0) {
907                         const struct server_cmd_user_data *ud = lls_user_data(lcmd);
908                         ret = ud->handler(cc, lpr);
909                         lls_free_parse_result(lpr, lcmd);
910                 } else
911                         send_errctx(cc, errctx);
912         } else {
913                 ret = cmd->handler(cc);
914         }
915         free_argv(cc->argv);
916         mutex_lock(mmd_mutex);
917         mmd->num_commands++;
918         if (ret >= 0 && (perms & AFS_WRITE))
919                 mmd->events++;
920         mutex_unlock(mmd_mutex);
921         return ret;
922 }
923
924 /**
925  * Perform user authentication and execute a command.
926  *
927  * \param fd The file descriptor to send output to.
928  * \param peername Identifies the connecting peer.
929  *
930  * Whenever para_server accepts an incoming tcp connection on the port it
931  * listens on, it forks and the resulting child calls this function.
932  *
933  * An RSA-based challenge/response is used to authenticate the peer. It that
934  * authentication succeeds, a random session key is generated and sent back to
935  * the peer, encrypted with its RSA public key. From this point on, all
936  * transfers are crypted with this session key.
937  *
938  * Next it is checked if the peer supplied a valid server command or a command
939  * for the audio file selector. If yes, and if the user has sufficient
940  * permissions to execute that command, the function calls the corresponding
941  * command handler which does argument checking and further processing.
942  *
943  * In order to cope with a DOS attacks, a timeout is set up which terminates
944  * the function if the connection was not authenticated when the timeout
945  * expires.
946  *
947  * \sa alarm(2), crypt.c, crypt.h
948  */
949 __noreturn void handle_connect(int fd, const char *peername)
950 {
951         int ret;
952         unsigned char rand_buf[CHALLENGE_SIZE + 2 * SESSION_KEY_LEN];
953         unsigned char challenge_hash[HASH_SIZE];
954         char *command = NULL, *buf = para_malloc(HANDSHAKE_BUFSIZE) /* must be on the heap */;
955         size_t numbytes;
956         struct command_context cc_struct = {.peer = peername}, *cc = &cc_struct;
957         struct iovec iov;
958         struct connection_features cf;
959
960         cc->scc.fd = fd;
961         reset_signals();
962         /* we need a blocking fd here as recv() might return EAGAIN otherwise. */
963         ret = mark_fd_blocking(fd);
964         if (ret < 0)
965                 goto net_err;
966         /* send Welcome message */
967         ret = write_va_buffer(fd, "This is para_server, version "
968                 PACKAGE_VERSION ".\n"
969                 "Features: sideband,aes_ctr128\n"
970         );
971         if (ret < 0)
972                 goto net_err;
973         /* recv auth request line */
974         ret = recv_buffer(fd, buf, HANDSHAKE_BUFSIZE);
975         if (ret < 0)
976                 goto net_err;
977         ret = parse_auth_request(buf, ret, &cc->u, &cf);
978         if (ret < 0)
979                 goto net_err;
980         if (cc->u) {
981                 get_random_bytes_or_die(rand_buf, sizeof(rand_buf));
982                 ret = pub_encrypt(cc->u->pubkey, rand_buf, sizeof(rand_buf),
983                         (unsigned char *)buf);
984                 if (ret < 0)
985                         goto net_err;
986                 numbytes = ret;
987         } else {
988                 /*
989                  * We don't want to reveal our user names, so we send a
990                  * challenge to the client even if the user does not exist, and
991                  * fail the authentication later.
992                  */
993                 numbytes = 256;
994                 get_random_bytes_or_die((unsigned char *)buf, numbytes);
995         }
996         PARA_DEBUG_LOG("sending %d byte challenge + session key (%zu bytes)\n",
997                 CHALLENGE_SIZE, numbytes);
998         ret = send_sb(&cc->scc, buf, numbytes, SBD_CHALLENGE, false);
999         buf = NULL;
1000         if (ret < 0)
1001                 goto net_err;
1002         ret = recv_sb(&cc->scc, SBD_CHALLENGE_RESPONSE,
1003                 HANDSHAKE_BUFSIZE, &iov);
1004         if (ret < 0)
1005                 goto net_err;
1006         buf = iov.iov_base;
1007         numbytes = iov.iov_len;
1008         PARA_DEBUG_LOG("received %zu bytes challenge response\n", numbytes);
1009         ret = -E_BAD_USER;
1010         if (!cc->u)
1011                 goto net_err;
1012         /*
1013          * The correct response is the hash of the first CHALLENGE_SIZE bytes
1014          * of the random data.
1015          */
1016         ret = -E_BAD_AUTH;
1017         if (numbytes != HASH_SIZE)
1018                 goto net_err;
1019         hash_function((char *)rand_buf, CHALLENGE_SIZE, challenge_hash);
1020         if (memcmp(challenge_hash, buf, HASH_SIZE))
1021                 goto net_err;
1022         /* auth successful */
1023         alarm(0);
1024         PARA_INFO_LOG("good auth for %s\n", cc->u->name);
1025         /* init stream cipher keys with the second part of the random buffer */
1026         cc->scc.recv = sc_new(rand_buf + CHALLENGE_SIZE, SESSION_KEY_LEN,
1027                 cf.aes_ctr128_requested);
1028         cc->scc.send = sc_new(rand_buf + CHALLENGE_SIZE + SESSION_KEY_LEN,
1029                 SESSION_KEY_LEN, cf.aes_ctr128_requested);
1030         ret = send_sb(&cc->scc, NULL, 0, SBD_PROCEED, false);
1031         if (ret < 0)
1032                 goto net_err;
1033         ret = recv_sb(&cc->scc, SBD_COMMAND, MAX_COMMAND_LEN, &iov);
1034         if (ret < 0)
1035                 goto net_err;
1036         ret = run_command(cc, &iov, peername);
1037         free(iov.iov_base);
1038         if (ret < 0)
1039                 goto err_out;
1040         if (ret >= 0)
1041                 goto out;
1042 err_out:
1043         if (send_strerror(cc, -ret) >= 0)
1044                 send_sb(&cc->scc, NULL, 0, SBD_EXIT__FAILURE, true);
1045 net_err:
1046         PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
1047 out:
1048         free(buf);
1049         free(command);
1050         mutex_lock(mmd_mutex);
1051         mmd->active_connections--;
1052         mutex_unlock(mmd_mutex);
1053         if (ret >= 0) {
1054                 ret = send_sb(&cc->scc, NULL, 0, SBD_EXIT__SUCCESS, true);
1055                 if (ret < 0)
1056                         PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
1057         }
1058         sc_free(cc->scc.recv);
1059         sc_free(cc->scc.send);
1060         exit(ret < 0? EXIT_FAILURE : EXIT_SUCCESS);
1061 }