X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=command.c;h=b6861b88bbcb36621109f6d9ac7fe80546a42b35;hp=bbe0441bfef43c339c499cb197cffd64b0fec5eb;hb=3150a0caa27a34d44556fb77f4a5aebc3d978580;hpb=6d1b1feadb2e7221874b7be205c51e0fe56d0519 diff --git a/command.c b/command.c index bbe0441b..b6861b88 100644 --- a/command.c +++ b/command.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1997-2009 Andre Noll + * Copyright (C) 1997-2011 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -10,9 +10,8 @@ #include #include #include -#include -#include #include +#include #include "para.h" #include "error.h" @@ -23,10 +22,9 @@ #include "afh.h" #include "afs.h" #include "server.h" -#include "vss.h" #include "list.h" #include "send.h" -#include "rc4.h" +#include "vss.h" #include "net.h" #include "daemon.h" #include "fd.h" @@ -36,6 +34,7 @@ #include "afs_command_list.h" #include "sched.h" #include "signal.h" +#include "version.h" /** Commands including options must be shorter than this. */ #define MAX_COMMAND_LEN 32768 @@ -43,7 +42,7 @@ extern int mmd_mutex; extern struct misc_meta_data *mmd; extern struct sender senders[]; -int send_afs_status(struct rc4_context *rc4c, int parser_friendly); +int send_afs_status(struct stream_cipher_context *scc, int parser_friendly); const char *status_item_list[] = {STATUS_ITEM_ARRAY}; @@ -109,7 +108,8 @@ static char *get_status(struct misc_meta_data *nmmd, int parser_friendly) { char mtime[30] = ""; char *status, *flags; /* vss status info */ - char *ut = uptime_str(); + /* 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; @@ -123,16 +123,22 @@ static char *get_status(struct misc_meta_data *nmmd, int parser_friendly) strftime(mtime, 29, "%b %d %Y", &mtime_tm); } gettimeofday(¤t_time, NULL); - WRITE_STATUS_ITEM(&b, SI_FILE_SIZE, "%zu\n", nmmd->size / 1024); - WRITE_STATUS_ITEM(&b, SI_MTIME, "%s\n", mtime); - WRITE_STATUS_ITEM(&b, SI_STATUS, "%s\n", status); - WRITE_STATUS_ITEM(&b, SI_STATUS_FLAGS, "%s\n", flags); - WRITE_STATUS_ITEM(&b, SI_OFFSET, "%li\n", offset); - WRITE_STATUS_ITEM(&b, SI_AFS_MODE, "%s\n", mmd->afs_mode_string); - WRITE_STATUS_ITEM(&b, SI_STREAM_START, "%lu.%lu\n", + /* + * The calls to WRITE_STATUS_ITEM() below never fail because + * b->max_size is zero (unlimited), see para_printf(). However, clang + * is not smart enough to prove this and complains nevertheless. + * Casting the return value to void silences solves this. + */ + (void)WRITE_STATUS_ITEM(&b, SI_FILE_SIZE, "%zu\n", nmmd->size / 1024); + (void)WRITE_STATUS_ITEM(&b, SI_MTIME, "%s\n", mtime); + (void)WRITE_STATUS_ITEM(&b, SI_STATUS, "%s\n", status); + (void)WRITE_STATUS_ITEM(&b, SI_STATUS_FLAGS, "%s\n", flags); + (void)WRITE_STATUS_ITEM(&b, SI_OFFSET, "%li\n", offset); + (void)WRITE_STATUS_ITEM(&b, SI_AFS_MODE, "%s\n", mmd->afs_mode_string); + (void)WRITE_STATUS_ITEM(&b, SI_STREAM_START, "%lu.%lu\n", (long unsigned)nmmd->stream_start.tv_sec, (long unsigned)nmmd->stream_start.tv_usec); - WRITE_STATUS_ITEM(&b, SI_CURRENT_TIME, "%lu.%lu\n", + (void)WRITE_STATUS_ITEM(&b, SI_CURRENT_TIME, "%lu.%lu\n", (long unsigned)current_time.tv_sec, (long unsigned)current_time.tv_usec); free(flags); @@ -188,33 +194,42 @@ static int check_sender_args(int argc, char * const * argv, struct sender_comman return 1; } -int com_sender(struct rc4_context *rc4c, int argc, char * const * argv) +int com_sender(struct stream_cipher_context *scc, int argc, char * const * argv) { int i, ret; + char *msg = NULL; struct sender_command_data scd; if (argc < 2) { - char *msg = NULL; for (i = 0; senders[i].name; i++) { char *tmp = make_message("%s%s\n", msg? msg : "", senders[i].name); free(msg); msg = tmp; } - ret = rc4_send_buffer(rc4c, msg); + ret = sc_send_buffer(scc, msg); free(msg); return ret; } ret = check_sender_args(argc, argv, &scd); if (ret < 0) { - char *msg; if (scd.sender_num < 0) return ret; msg = senders[scd.sender_num].help(); - ret = rc4_send_buffer(rc4c, msg); + ret = sc_send_buffer(scc, msg); free(msg); return ret; } + + switch (scd.cmd_num) { + case SENDER_ADD: + case SENDER_DELETE: + assert(senders[scd.sender_num].resolve_target); + ret = senders[scd.sender_num].resolve_target(argv[3], &scd); + if (ret < 0) + return ret; + } + for (i = 0; i < 10; i++) { mutex_lock(mmd_mutex); if (mmd->sender_cmd_data.cmd_num >= 0) { @@ -230,7 +245,7 @@ int com_sender(struct rc4_context *rc4c, int argc, char * const * argv) } /* server info */ -int com_si(struct rc4_context *rc4c, int argc, __a_unused char * const * argv) +int com_si(struct stream_cipher_context *scc, int argc, __a_unused char * const * argv) { int i, ret; char *ut; @@ -244,8 +259,9 @@ int com_si(struct rc4_context *rc4c, int argc, __a_unused char * const * argv) sender_info = para_strcat(sender_info, info); free(info); } - ut = uptime_str(); - ret = rc4_send_va_buffer(rc4c, "up: %s\nplayed: %u\n" + ut = get_server_uptime_str(now); + ret = sc_send_va_buffer(scc, "version: " GIT_VERSION "\n" + "up: %s\nplayed: %u\n" "server_pid: %d\n" "afs_pid: %d\n" "connections (active/accepted/total): %u/%u/%u\n" @@ -259,7 +275,7 @@ int com_si(struct rc4_context *rc4c, int argc, __a_unused char * const * argv) mmd->num_commands, mmd->num_connects, conf.loglevel_arg, - supported_audio_formats(), + SERVER_AUDIO_FORMATS, sender_info ); mutex_unlock(mmd_mutex); @@ -269,11 +285,11 @@ int com_si(struct rc4_context *rc4c, int argc, __a_unused char * const * argv) } /* version */ -int com_version(struct rc4_context *rc4c, int argc, __a_unused char * const * argv) +int com_version(struct stream_cipher_context *scc, int argc, __a_unused char * const * argv) { if (argc != 1) return -E_COMMAND_SYNTAX; - return rc4_send_buffer(rc4c, VERSION_TEXT("server") + return sc_send_buffer(scc, VERSION_TEXT("server") "built: " BUILD_DATE "\n" UNAME_RS ", " CC_VERSION "\n" ); @@ -335,7 +351,7 @@ static char *empty_status_items(int parser_friendly) #undef EMPTY_STATUS_ITEMS /* stat */ -int com_stat(struct rc4_context *rc4c, int argc, char * const * argv) +int com_stat(struct stream_cipher_context *scc, int argc, char * const * argv) { int i, ret; struct misc_meta_data tmp, *nmmd = &tmp; @@ -370,7 +386,7 @@ int com_stat(struct rc4_context *rc4c, int argc, char * const * argv) for (;;) { mmd_dup(nmmd); s = get_status(nmmd, parser_friendly); - ret = rc4_send_buffer(rc4c, s); + ret = sc_send_buffer(scc, s); free(s); if (ret < 0) goto out; @@ -378,11 +394,11 @@ int com_stat(struct rc4_context *rc4c, int argc, char * const * argv) static char *esi; if (!esi) esi = empty_status_items(parser_friendly); - ret = rc4_send_buffer(rc4c, esi); + ret = sc_send_buffer(scc, esi); if (ret < 0) goto out; } else - send_afs_status(rc4c, parser_friendly); + send_afs_status(scc, parser_friendly); ret = 1; if (num > 0 && !--num) goto out; @@ -394,14 +410,14 @@ out: return ret; } -static int send_list_of_commands(struct rc4_context *rc4c, struct server_command *cmd, +static int send_list_of_commands(struct stream_cipher_context *scc, struct server_command *cmd, const char *handler) { int ret, i; for (i = 1; cmd->name; cmd++, i++) { char *perms = cmd_perms_itohuman(cmd->perms); - ret = rc4_send_va_buffer(rc4c, "%s\t%s\t%s\t%s\n", cmd->name, + ret = sc_send_va_buffer(scc, "%s\t%s\t%s\t%s\n", cmd->name, handler, perms, cmd->description); @@ -434,7 +450,7 @@ static struct server_command *get_cmd_ptr(const char *name, char **handler) } /* help */ -int com_help(struct rc4_context *rc4c, int argc, char * const * argv) +int com_help(struct stream_cipher_context *scc, int argc, char * const * argv) { struct server_command *cmd; char *perms, *handler; @@ -442,18 +458,16 @@ int com_help(struct rc4_context *rc4c, int argc, char * const * argv) if (argc < 2) { /* no argument given, print list of commands */ - if ((ret = send_list_of_commands(rc4c, server_cmds, "server")) < 0) + if ((ret = send_list_of_commands(scc, server_cmds, "server")) < 0) return ret; - return send_list_of_commands(rc4c, afs_cmds, "afs"); + return send_list_of_commands(scc, afs_cmds, "afs"); } /* argument given for help */ cmd = get_cmd_ptr(argv[1], &handler); - if (!cmd) { - free(handler); + if (!cmd) return -E_BAD_CMD; - } perms = cmd_perms_itohuman(cmd->perms); - ret = rc4_send_va_buffer(rc4c, + ret = sc_send_va_buffer(scc, "%s - %s\n\n" "handler: %s\n" "permissions: %s\n" @@ -472,7 +486,7 @@ int com_help(struct rc4_context *rc4c, int argc, char * const * argv) } /* hup */ -int com_hup(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv) +int com_hup(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv) { if (argc != 1) return -E_COMMAND_SYNTAX; @@ -481,7 +495,7 @@ int com_hup(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * con } /* term */ -int com_term(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv) +int com_term(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv) { if (argc != 1) return -E_COMMAND_SYNTAX; @@ -489,7 +503,7 @@ int com_term(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * co return 1; } -int com_play(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv) +int com_play(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv) { if (argc != 1) return -E_COMMAND_SYNTAX; @@ -502,7 +516,7 @@ int com_play(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * co } /* stop */ -int com_stop(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv) +int com_stop(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv) { if (argc != 1) return -E_COMMAND_SYNTAX; @@ -515,7 +529,7 @@ int com_stop(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * co } /* pause */ -int com_pause(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv) +int com_pause(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv) { if (argc != 1) return -E_COMMAND_SYNTAX; @@ -530,7 +544,7 @@ int com_pause(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * c } /* next */ -int com_next(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv) +int com_next(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv) { if (argc != 1) return -E_COMMAND_SYNTAX; @@ -542,7 +556,7 @@ int com_next(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * co } /* nomore */ -int com_nomore(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv) +int com_nomore(__a_unused struct stream_cipher_context *scc, int argc, __a_unused char * const * argv) { if (argc != 1) return -E_COMMAND_SYNTAX; @@ -554,7 +568,7 @@ int com_nomore(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * } /* ff */ -int com_ff(__a_unused struct rc4_context *rc4c, int argc, char * const * argv) +int com_ff(__a_unused struct stream_cipher_context *scc, int argc, char * const * argv) { long promille; int ret, backwards = 0; @@ -593,7 +607,7 @@ out: } /* jmp */ -int com_jmp(__a_unused struct rc4_context *rc4c, int argc, char * const * argv) +int com_jmp(__a_unused struct stream_cipher_context *scc, int argc, char * const * argv) { long unsigned int i; int ret; @@ -647,7 +661,7 @@ static struct server_command *parse_cmd(const char *cmdstr) return get_cmd_ptr(buf, NULL); } -static int read_command(struct rc4_context *rc4c, char **result) +static int read_command(struct stream_cipher_context *scc, char **result) { int ret; char buf[4096]; @@ -657,7 +671,7 @@ static int read_command(struct rc4_context *rc4c, char **result) size_t numbytes; char *p; - ret = rc4_recv_buffer(rc4c, buf, sizeof(buf)); + ret = sc_recv_buffer(scc, buf, sizeof(buf)); if (ret < 0) goto out; if (!ret) @@ -702,7 +716,7 @@ static void reset_signals(void) * calls this function. * * An RSA-based challenge/response is used to authenticate - * the peer. It that authentication succeeds, a random RC4 + * 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. @@ -716,53 +730,51 @@ static void reset_signals(void) * which terminates the function if the connection was not * authenticated when the timeout expires. * - * \sa alarm(2), rc4(3), crypt.c, crypt.h + * \sa alarm(2), crypt.c, crypt.h */ __noreturn void handle_connect(int fd, const char *peername) { int ret, argc; char buf[4096]; - unsigned char rand_buf[CHALLENGE_SIZE + 2 * RC4_KEY_LEN]; - unsigned char challenge_sha1[HASH_SIZE]; + unsigned char rand_buf[CHALLENGE_SIZE + 2 * SESSION_KEY_LEN]; + unsigned char challenge_hash[HASH_SIZE]; struct user *u; struct server_command *cmd = NULL; char **argv = NULL; char *p, *command = NULL; size_t numbytes; - struct rc4_context rc4c = {.fd = fd}; + struct stream_cipher_context scc = {.fd = fd}; reset_signals(); /* we need a blocking fd here as recv() might return EAGAIN otherwise. */ ret = mark_fd_blocking(fd); if (ret < 0) - goto err_out; + goto net_err; /* send Welcome message */ ret = send_va_buffer(fd, "This is para_server, version " PACKAGE_VERSION ".\n" ); if (ret < 0) - goto err_out; + goto net_err; /* recv auth request line */ ret = recv_buffer(fd, buf, sizeof(buf)); if (ret < 0) - goto err_out; + goto net_err; if (ret < 10) { ret = -E_AUTH_REQUEST; - goto err_out; + goto net_err; } - numbytes = ret; ret = -E_AUTH_REQUEST; if (strncmp(buf, AUTH_REQUEST_MSG, strlen(AUTH_REQUEST_MSG))) - goto err_out; + goto net_err; p = buf + strlen(AUTH_REQUEST_MSG); PARA_DEBUG_LOG("received auth request for user %s\n", p); - ret = -E_BAD_USER; u = lookup_user(p); if (u) { get_random_bytes_or_die(rand_buf, sizeof(rand_buf)); - ret = para_encrypt_buffer(u->rsa, rand_buf, sizeof(rand_buf), + ret = pub_encrypt(u->pubkey, rand_buf, sizeof(rand_buf), (unsigned char *)buf); if (ret < 0) - goto err_out; + goto net_err; numbytes = ret; } else { /* @@ -788,26 +800,25 @@ __noreturn void handle_connect(int fd, const char *peername) if (!u) goto net_err; /* - * The correct response is the sha1 of the first CHALLENGE_SIZE bytes + * The correct response is the hash of the first CHALLENGE_SIZE bytes * of the random data. */ ret = -E_BAD_AUTH; if (numbytes != HASH_SIZE) goto net_err; - sha1_hash((char *)rand_buf, CHALLENGE_SIZE, challenge_sha1); - if (memcmp(challenge_sha1, buf, HASH_SIZE)) + hash_function((char *)rand_buf, CHALLENGE_SIZE, challenge_hash); + if (memcmp(challenge_hash, buf, HASH_SIZE)) goto net_err; /* auth successful */ alarm(0); PARA_INFO_LOG("good auth for %s\n", u->name); - /* init rc4 keys with the second part of the random buffer */ - RC4_set_key(&rc4c.recv_key, RC4_KEY_LEN, rand_buf + CHALLENGE_SIZE); - RC4_set_key(&rc4c.send_key, RC4_KEY_LEN, rand_buf + CHALLENGE_SIZE - + RC4_KEY_LEN); - ret = rc4_send_buffer(&rc4c, PROCEED_MSG); + /* init stream cipher keys with the second part of the random buffer */ + scc.recv = sc_new(rand_buf + CHALLENGE_SIZE, SESSION_KEY_LEN); + scc.send = sc_new(rand_buf + CHALLENGE_SIZE + SESSION_KEY_LEN, SESSION_KEY_LEN); + ret = sc_send_buffer(&scc, PROCEED_MSG); if (ret < 0) goto net_err; - ret = read_command(&rc4c, &command); + ret = read_command(&scc, &command); if (ret == -E_COMMAND_SYNTAX) goto err_out; if (ret < 0) @@ -827,7 +838,7 @@ __noreturn void handle_connect(int fd, const char *peername) argc = ret; PARA_NOTICE_LOG("calling com_%s() for %s@%s\n", cmd->name, u->name, peername); - ret = cmd->handler(&rc4c, argc, argv); + ret = cmd->handler(&scc, argc, argv); free_argv(argv); mutex_lock(mmd_mutex); mmd->num_commands++; @@ -835,11 +846,13 @@ __noreturn void handle_connect(int fd, const char *peername) if (ret >= 0) goto out; err_out: - rc4_send_va_buffer(&rc4c, "%s\n", para_strerror(-ret)); + sc_send_va_buffer(&scc, "%s\n", para_strerror(-ret)); net_err: PARA_NOTICE_LOG("%s\n", para_strerror(-ret)); out: free(command); + sc_free(scc.recv); + sc_free(scc.send); mutex_lock(mmd_mutex); if (cmd && (cmd->perms & AFS_WRITE) && ret >= 0) mmd->events++;