X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=command.c;h=09f00f2f23d7479c5a567fa8fe85a357088b1ff0;hp=93c680583056d91e5c724a44d725e46724804ae2;hb=b59a2064b8dcc9fc83c32f14d6520b266d90a8cb;hpb=1cccf6fa93c251f8f2805aa5fb163741d851c051 diff --git a/command.c b/command.c index 93c68058..09f00f2f 100644 --- a/command.c +++ b/command.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1997-2013 Andre Noll + * Copyright (C) 1997-2014 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -115,7 +115,6 @@ static unsigned get_status(struct misc_meta_data *nmmd, int parser_friendly, char mtime[30] = ""; char *status, *flags; /* vss status info */ /* nobody updates our version of "now" */ - char *ut = get_server_uptime_str(NULL); long offset = (nmmd->offset + 500) / 1000; struct timeval current_time; struct tm mtime_tm; @@ -149,7 +148,6 @@ static unsigned get_status(struct misc_meta_data *nmmd, int parser_friendly, (long unsigned)current_time.tv_usec); free(flags); free(status); - free(ut); *result = b.buf; return b.offset; } @@ -346,7 +344,10 @@ static int com_sender(struct command_context *cc) if (ret < 0) { if (scd.sender_num < 0) return ret; - msg = senders[scd.sender_num].help(); + if (strcmp(cc->argv[2], "status") == 0) + msg = senders[scd.sender_num].status(); + else + msg = senders[scd.sender_num].help(); return send_sb(&cc->scc, msg, strlen(msg), SBD_OUTPUT, false); } @@ -366,7 +367,7 @@ static int com_sender(struct command_context *cc) usleep(100 * 1000); continue; } - memcpy(&mmd->sender_cmd_data, &scd, sizeof(scd)); + mmd->sender_cmd_data = scd; mutex_unlock(mmd_mutex); break; } @@ -376,28 +377,20 @@ static int com_sender(struct command_context *cc) /* server info */ static int com_si(struct command_context *cc) { - int i, ret; - char *msg, *ut, *sender_info = NULL; + int ret; + char *msg, *ut; if (cc->argc != 1) return -E_COMMAND_SYNTAX; mutex_lock(mmd_mutex); - for (i = 0; senders[i].name; i++) { - char *info = senders[i].info(); - sender_info = para_strcat(sender_info, info); - free(info); - } - ut = get_server_uptime_str(now); + ut = daemon_get_uptime_str(now); ret = xasprintf(&msg, - "version: %s\n" "up: %s\nplayed: %u\n" "server_pid: %d\n" "afs_pid: %d\n" "connections (active/accepted/total): %u/%u/%u\n" "current loglevel: %s\n" - "supported audio formats: %s\n" - "%s", - version_git(), + "supported audio formats: %s\n", ut, mmd->num_played, (int)getppid(), (int)mmd->afs_pid, @@ -405,12 +398,10 @@ static int com_si(struct command_context *cc) mmd->num_commands, mmd->num_connects, conf.loglevel_arg, - AUDIO_FORMAT_HANDLERS, - sender_info + AUDIO_FORMAT_HANDLERS ); mutex_unlock(mmd_mutex); free(ut); - free(sender_info); return send_sb(&cc->scc, msg, ret, SBD_OUTPUT, false); } @@ -559,6 +550,7 @@ static int send_list_of_commands(struct command_context *cc, struct server_comma msg = para_strcat(msg, tmp); free(tmp); } + assert(msg); return send_sb(&cc->scc, msg, strlen(msg), SBD_OUTPUT, false); } @@ -724,7 +716,7 @@ static int com_ff(struct command_context *cc) promille += 1000 * i / mmd->afd.afhi.seconds_total; if (promille < 0) promille = 0; - if (promille > 1000) { + if (promille > 1000) { mmd->new_vss_status_flags |= VSS_NEXT; goto out; } @@ -755,8 +747,8 @@ static int com_jmp(struct command_context *cc) if (i > 100) i = 100; PARA_INFO_LOG("jumping to %lu%%\n", i); - mmd->repos_request = (mmd->afd.afhi.chunks_total * i + 50)/ 100; - PARA_INFO_LOG("sent: %lu, offset before jmp: %lu\n", + mmd->repos_request = (mmd->afd.afhi.chunks_total * i + 50) / 100; + PARA_INFO_LOG("sent: %lu, offset before jmp: %lu\n", mmd->chunks_sent, mmd->offset); mmd->new_vss_status_flags |= VSS_REPOS; mmd->new_vss_status_flags &= ~VSS_NEXT; @@ -785,14 +777,20 @@ static void reset_signals(void) para_sigaction(SIGHUP, SIG_DFL); } -static int parse_auth_request(char *buf, int len, struct user **u) +struct connection_features { + bool sideband_requested; + bool aes_ctr128_requested; +}; + +static int parse_auth_request(char *buf, int len, struct user **u, + struct connection_features *cf) { int ret; char *p, *username, **features = NULL; size_t auth_rq_len = strlen(AUTH_REQUEST_MSG); - bool sideband_requested = false; *u = NULL; + memset(cf, 0, sizeof(*cf)); if (len < auth_rq_len + 2) return -E_AUTH_REQUEST; if (strncmp(buf, AUTH_REQUEST_MSG, auth_rq_len) != 0) @@ -808,18 +806,15 @@ static int parse_auth_request(char *buf, int len, struct user **u) create_argv(p, ",", &features); for (i = 0; features[i]; i++) { if (strcmp(features[i], "sideband") == 0) - sideband_requested = true; + cf->sideband_requested = true; + else if (strcmp(features[i], "aes_ctr128") == 0) + cf->aes_ctr128_requested = true; else { ret = -E_BAD_FEATURE; goto out; } } } - if (sideband_requested == false) { /* sideband is mandatory */ - PARA_ERROR_LOG("client did not request sideband\n"); - ret = -E_BAD_FEATURE; - goto out; - } PARA_DEBUG_LOG("received auth request for user %s\n", username); *u = lookup_user(username); ret = 1; @@ -868,24 +863,22 @@ out: * \param fd The file descriptor to send output to. * \param peername Identifies the connecting peer. * - * Whenever para_server accepts an incoming tcp connection on - * the port it listens on, it forks and the resulting child - * calls this function. + * Whenever para_server accepts an incoming tcp connection on the port it + * listens on, it forks and the resulting child calls this function. * - * An RSA-based challenge/response is used to authenticate - * the peer. It that authentication succeeds, a random - * session key is generated and sent back to the peer, - * encrypted with its RSA public key. From this point on, - * all transfers are crypted with this session key. + * An RSA-based challenge/response is used to authenticate the peer. It that + * authentication succeeds, a random session key is generated and sent back to + * the peer, encrypted with its RSA public key. From this point on, all + * transfers are crypted with this session key. * - * Next it is checked if the peer supplied a valid server command or a command - * for the audio file selector. If yes, and if the user has sufficient + * Next it is checked if the peer supplied a valid server command or a command + * for the audio file selector. If yes, and if the user has sufficient * permissions to execute that command, the function calls the corresponding * command handler which does argument checking and further processing. * - * In order to cope with a DOS attacks, a timeout is set up - * which terminates the function if the connection was not - * authenticated when the timeout expires. + * In order to cope with a DOS attacks, a timeout is set up which terminates + * the function if the connection was not authenticated when the timeout + * expires. * * \sa alarm(2), crypt.c, crypt.h */ @@ -894,10 +887,11 @@ __noreturn void handle_connect(int fd, const char *peername) int ret; unsigned char rand_buf[CHALLENGE_SIZE + 2 * SESSION_KEY_LEN]; unsigned char challenge_hash[HASH_SIZE]; - char *p, *command = NULL, *buf = para_malloc(HANDSHAKE_BUFSIZE) /* must be on the heap */; + char *command = NULL, *buf = para_malloc(HANDSHAKE_BUFSIZE) /* must be on the heap */; size_t numbytes; struct command_context cc_struct = {.peer = peername}, *cc = &cc_struct; struct iovec iov; + struct connection_features cf; cc->scc.fd = fd; reset_signals(); @@ -907,8 +901,8 @@ __noreturn void handle_connect(int fd, const char *peername) goto net_err; /* send Welcome message */ ret = write_va_buffer(fd, "This is para_server, version " - PACKAGE_VERSION ".\n" - "Features: sideband\n" + PACKAGE_VERSION ".\n" + "Features: sideband,aes_ctr128\n" ); if (ret < 0) goto net_err; @@ -916,12 +910,14 @@ __noreturn void handle_connect(int fd, const char *peername) ret = recv_buffer(fd, buf, HANDSHAKE_BUFSIZE); if (ret < 0) goto net_err; - ret = parse_auth_request(buf, ret, &cc->u); + ret = parse_auth_request(buf, ret, &cc->u, &cf); if (ret < 0) goto net_err; - p = buf + strlen(AUTH_REQUEST_MSG); - PARA_DEBUG_LOG("received auth request for user %s\n", p); - cc->u = lookup_user(p); + if (!cf.sideband_requested) { /* sideband is mandatory */ + PARA_ERROR_LOG("client did not request sideband\n"); + ret = -E_BAD_FEATURE; + goto net_err; + } if (cc->u) { get_random_bytes_or_die(rand_buf, sizeof(rand_buf)); ret = pub_encrypt(cc->u->pubkey, rand_buf, sizeof(rand_buf), @@ -938,7 +934,7 @@ __noreturn void handle_connect(int fd, const char *peername) numbytes = 256; get_random_bytes_or_die((unsigned char *)buf, numbytes); } - PARA_DEBUG_LOG("sending %u byte challenge + rc4 keys (%zu bytes)\n", + PARA_DEBUG_LOG("sending %u byte challenge + session key (%zu bytes)\n", CHALLENGE_SIZE, numbytes); ret = send_sb(&cc->scc, buf, numbytes, SBD_CHALLENGE, false); buf = NULL; @@ -968,8 +964,10 @@ __noreturn void handle_connect(int fd, const char *peername) alarm(0); PARA_INFO_LOG("good auth for %s\n", cc->u->name); /* init stream cipher keys with the second part of the random buffer */ - cc->scc.recv = sc_new(rand_buf + CHALLENGE_SIZE, SESSION_KEY_LEN); - cc->scc.send = sc_new(rand_buf + CHALLENGE_SIZE + SESSION_KEY_LEN, SESSION_KEY_LEN); + cc->scc.recv = sc_new(rand_buf + CHALLENGE_SIZE, SESSION_KEY_LEN, + cf.aes_ctr128_requested); + cc->scc.send = sc_new(rand_buf + CHALLENGE_SIZE + SESSION_KEY_LEN, + SESSION_KEY_LEN, cf.aes_ctr128_requested); ret = send_sb(&cc->scc, NULL, 0, SBD_PROCEED, false); if (ret < 0) goto net_err;