Make rc4 encryption/decryption more explicit.
authorAndre Noll <maan@systemlinux.org>
Sun, 14 Jun 2009 20:50:11 +0000 (22:50 +0200)
committerAndre Noll <maan@systemlinux.org>
Sun, 14 Jun 2009 20:50:11 +0000 (22:50 +0200)
The old code used a rather fancy way to (de)activate encryption on
a per fd basis: In net.c there was an array of rc4 keys, indexed by fd.
This is rather wastful because the array size is determined by the
highest fd for which encryption is activated.

It's also hard to comprehend and it's easy to get strange results if
one forgets to deactivate the encryption after the fd is closed.

This patch introduces a new structure, rc4_context, which consists of
an fd and the needed rc4 keys. Users explicitly call the new rc4 variants
of the receving/sending functions which take a pointer to a struct
rc4_context instead of a file descriptor but are otherwise identical.

Keep crypt simple!

23 files changed:
afs.c
afs.cmd
afs.h
aft.c
attribute.c
audiod.c
blob.c
client.c
client.h
client_common.c
command.c
command.h [new file with mode: 0644]
command_util.sh
crypt.c
crypt.h
grab_client.c
net.c
net.h
server.c
server.cmd
server.h
user_list.c
user_list.h

diff --git a/afs.c b/afs.c
index 72e2490e671fb4b5898bddea96cc922a1c435c25..c89e3cec68ce835d44b803ce1fc144948ab9d8e1 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -8,9 +8,12 @@
 
 #include <signal.h>
 #include <fnmatch.h>
 
 #include <signal.h>
 #include <fnmatch.h>
+#include <openssl/rc4.h>
+
 #include "server.cmdline.h"
 #include "para.h"
 #include "error.h"
 #include "server.cmdline.h"
 #include "para.h"
 #include "error.h"
+#include "crypt.h"
 #include "string.h"
 #include "afh.h"
 #include "afs.h"
 #include "string.h"
 #include "afh.h"
 #include "afs.h"
@@ -403,80 +406,6 @@ int string_compare(const struct osl_object *obj1, const struct osl_object *obj2)
        return strncmp(str1, str2, PARA_MIN(obj1->size, obj2->size));
 }
 
        return strncmp(str1, str2, PARA_MIN(obj1->size, obj2->size));
 }
 
-/*
- * write input from fd to dynamically allocated buffer,
- * but maximal max_size byte.
- */
-static int fd2buf(int fd, unsigned max_size, struct osl_object *obj)
-{
-       const size_t chunk_size = 1024;
-       size_t size = 2048, received = 0;
-       int ret;
-       char *buf = para_malloc(size);
-
-       for (;;) {
-               ret = recv_bin_buffer(fd, buf + received, chunk_size);
-               if (ret <= 0)
-                       break;
-               received += ret;
-               if (received + chunk_size >= size) {
-                       size *= 2;
-                       ret = -E_INPUT_TOO_LARGE;
-                       if (size > max_size)
-                               break;
-                       buf = para_realloc(buf, size);
-               }
-       }
-       obj->data = buf;
-       obj->size = received;
-       if (ret < 0)
-               free(buf);
-       return ret;
-}
-
-/**
- * Read data from a file descriptor, and send it to the afs process.
- *
- * \param fd File descriptor to read data from.
- * \param arg_obj Pointer to the arguments to \a f.
- * \param f The callback function.
- * \param max_len Don't read more than that many bytes from stdin.
- * \param result_handler See \ref send_callback_request.
- * \param private_result_data See \ref send_callback_request.
- *
- * This function is used by commands that wish to let para_server store
- * arbitrary data specified by the user (for instance the add_blob family of
- * commands). First, at most \a max_len bytes are read from \a fd, the result
- * is concatenated with the buffer given by \a arg_obj, and the combined buffer
- * is made available to the afs process via the callback method. See \ref
- * send_callback_request for details.
- *
- * \return Negative on errors, the return value of the underlying call to
- * send_callback_request() otherwise.
- */
-int stdin_command(int fd, struct osl_object *arg_obj, callback_function *f,
-               unsigned max_len, callback_result_handler *result_handler,
-               void *private_result_data)
-{
-       struct osl_object query, stdin_obj;
-       int ret;
-
-       ret = send_buffer(fd, AWAITING_DATA_MSG);
-       if (ret < 0)
-               return ret;
-       ret = fd2buf(fd, max_len, &stdin_obj);
-       if (ret < 0)
-               return ret;
-       query.size = arg_obj->size + stdin_obj.size;
-       query.data = para_malloc(query.size);
-       memcpy(query.data, arg_obj->data, arg_obj->size);
-       memcpy((char *)query.data + arg_obj->size, stdin_obj.data, stdin_obj.size);
-       free(stdin_obj.data);
-       ret = send_callback_request(f, &query, result_handler, private_result_data);
-       free(query.data);
-       return ret;
-}
-
 static int pass_afd(int fd, char *buf, size_t size)
 {
        struct msghdr msg = {.msg_iov = NULL};
 static int pass_afd(int fd, char *buf, size_t size)
 {
        struct msghdr msg = {.msg_iov = NULL};
@@ -652,21 +581,22 @@ out:
  * Result handler for sending data to the para_client process.
  *
  * \param result The data to be sent.
  * Result handler for sending data to the para_client process.
  *
  * \param result The data to be sent.
- * \param fd_ptr Pointer to the file descriptor.
+ * \param private Pointer to rc4 context.
  *
  *
- * \return The return value of the underlying call to send_bin_buffer().
+ * \return The return value of the underlying call to rc4_send_bin_buffer().
  *
  *
- * \sa \ref callback_result_handler.
+ * \sa \ref callback_result_handler, \ref rc4_send_bin_buffer().
  */
  */
-int send_result(struct osl_object *result, void *fd_ptr)
+int rc4_send_result(struct osl_object *result, void *private)
 {
 {
-       int fd = *(int *)fd_ptr;
+       struct rc4_context *rc4c = private;
+
        if (!result->size)
                return 1;
        if (!result->size)
                return 1;
-       return send_bin_buffer(fd, result->data, result->size);
+       return rc4_send_bin_buffer(rc4c, result->data, result->size);
 }
 
 }
 
-int com_select(int fd, int argc, char * const * const argv)
+int com_select(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        struct osl_object query;
 
 {
        struct osl_object query;
 
@@ -675,7 +605,7 @@ int com_select(int fd, int argc, char * const * const argv)
        query.data = argv[1];
        query.size = strlen(argv[1]) + 1;
        return send_callback_request(com_select_callback, &query,
        query.data = argv[1];
        query.size = strlen(argv[1]) + 1;
        return send_callback_request(com_select_callback, &query,
-               &send_result, &fd);
+               &rc4_send_result, rc4c);
 }
 
 static void init_admissible_files(char *arg)
 }
 
 static void init_admissible_files(char *arg)
@@ -1096,7 +1026,7 @@ out:
        free(buf);
 }
 
        free(buf);
 }
 
-int com_init(int fd, int argc, char * const * const argv)
+int com_init(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        int i, j, ret;
        uint32_t table_mask = (1 << (NUM_AFS_TABLES + 1)) - 1;
 {
        int i, j, ret;
        uint32_t table_mask = (1 << (NUM_AFS_TABLES + 1)) - 1;
@@ -1121,9 +1051,10 @@ int com_init(int fd, int argc, char * const * const argv)
                                return -E_BAD_TABLE_NAME;
                }
        }
                                return -E_BAD_TABLE_NAME;
                }
        }
-       ret = send_callback_request(create_tables_callback, &query, &send_result, &fd);
+       ret = send_callback_request(create_tables_callback, &query,
+               rc4_send_result, rc4c);
        if (ret < 0)
        if (ret < 0)
-               return send_va_buffer(fd, "%s\n", para_strerror(-ret));
+               return rc4_send_va_buffer(rc4c, "%s\n", para_strerror(-ret));
        return ret;
 }
 
        return ret;
 }
 
@@ -1141,7 +1072,7 @@ enum com_check_flags {
        CHECK_PLAYLISTS = 4
 };
 
        CHECK_PLAYLISTS = 4
 };
 
-int com_check(int fd, int argc, char * const * const argv)
+int com_check(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        unsigned flags = 0;
        int i, ret;
 {
        unsigned flags = 0;
        int i, ret;
@@ -1173,17 +1104,20 @@ int com_check(int fd, int argc, char * const * const argv)
        if (!flags)
                flags = ~0U;
        if (flags & CHECK_AFT) {
        if (!flags)
                flags = ~0U;
        if (flags & CHECK_AFT) {
-               ret = send_callback_request(aft_check_callback, NULL, send_result, &fd);
+               ret = send_callback_request(aft_check_callback, NULL,
+                       rc4_send_result, rc4c);
                if (ret < 0)
                        return ret;
        }
        if (flags & CHECK_PLAYLISTS) {
                if (ret < 0)
                        return ret;
        }
        if (flags & CHECK_PLAYLISTS) {
-               ret = send_callback_request(playlist_check_callback, NULL, send_result, &fd);
+               ret = send_callback_request(playlist_check_callback,
+                       NULL, rc4_send_result, rc4c);
                if (ret < 0)
                        return ret;
        }
        if (flags & CHECK_MOODS) {
                if (ret < 0)
                        return ret;
        }
        if (flags & CHECK_MOODS) {
-               ret = send_callback_request(mood_check_callback, NULL, send_result, &fd);
+               ret = send_callback_request(mood_check_callback, NULL,
+                       rc4_send_result, rc4c);
                if (ret < 0)
                        return ret;
        }
                if (ret < 0)
                        return ret;
        }
diff --git a/afs.cmd b/afs.cmd
index 0af4511302aa20a220907e79a35be20df04a2700..3173404623ccd5768753bfe4773eb1eb6a834221 100644 (file)
--- a/afs.cmd
+++ b/afs.cmd
@@ -3,7 +3,8 @@ SF: afs.c aft.c attribute.c
 HC: Prototypes for the commands of the audio file selector.
 CC: Array of commands for the audio file selector.
 AT: server_command
 HC: Prototypes for the commands of the audio file selector.
 CC: Array of commands for the audio file selector.
 AT: server_command
-IN: para error string afh afs server list user_list
+SI: openssl/rc4
+IN: para error crypt command string afh afs server list user_list
 SN: list of afs commands
 TM: mood lyr img pl
 ---
 SN: list of afs commands
 TM: mood lyr img pl
 ---
@@ -94,7 +95,7 @@ H:            -sa:  sort by audio format.
 ---
 N: lsatt
 P: AFS_READ
 ---
 N: lsatt
 P: AFS_READ
-D: List attributes
+D: List attributes.
 U: lsatt [-i] [-l] [-r] [pattern]
 H: Print the list of all defined attributes which match the
 H: given pattern. If no pattern is given, the full list is
 U: lsatt [-i] [-l] [-r] [pattern]
 H: Print the list of all defined attributes which match the
 H: given pattern. If no pattern is given, the full list is
@@ -257,7 +258,7 @@ H: loads the mood named 'foo'.
 ---
 T: add
 N: add@member@
 ---
 T: add
 N: add@member@
-O: int com_add@member@(int fd, int argc, char * const * const argv);
+O: int com_add@member@(struct rc4_context *rc4c, int argc, char * const * const argv);
 P: AFS_READ | AFS_WRITE
 D: Read data from stdin and add it as a blob to the @member@ table.
 U: add@member@ @member@_name
 P: AFS_READ | AFS_WRITE
 D: Read data from stdin and add it as a blob to the @member@ table.
 U: add@member@ @member@_name
@@ -270,7 +271,7 @@ H: given name already exists, its contents are replaced by the new data.
 ---
 T: cat
 N: cat@member@
 ---
 T: cat
 N: cat@member@
-O: int com_cat@member@(int fd, int argc, char * const * const argv);
+O: int com_cat@member@(struct rc4_context *rc4c, int argc, char * const * const argv);
 P: AFS_READ
 D: Dump the contents of a blob of type @member@ to stdout.
 U: cat@member@ @member@_name
 P: AFS_READ
 D: Dump the contents of a blob of type @member@ to stdout.
 U: cat@member@ @member@_name
@@ -280,7 +281,7 @@ H: they were previously added.
 ---
 T: ls
 N: ls@member@
 ---
 T: ls
 N: ls@member@
-O: int com_ls@member@(int fd, int argc, char * const * const argv);
+O: int com_ls@member@(struct rc4_context *rc4c, int argc, char * const * const argv);
 P: AFS_READ
 D: List blobs of type @member@ matching a pattern.
 U: ls@member@ [-i] [-l] [-r] [pattern]
 P: AFS_READ
 D: List blobs of type @member@ matching a pattern.
 U: ls@member@ [-i] [-l] [-r] [pattern]
@@ -300,7 +301,7 @@ H: -r       Reverse sort order.
 ---
 T: rm
 N: rm@member@
 ---
 T: rm
 N: rm@member@
-O: int com_rm@member@(int fd, int argc, char * const * const argv);
+O: int com_rm@member@(struct rc4_context *rc4c, int argc, char * const * const argv);
 P: AFS_READ | AFS_WRITE
 D: Remove blob(s) of type @member@ from the @member@ table.
 U: rm@member@ pattern...
 P: AFS_READ | AFS_WRITE
 D: Remove blob(s) of type @member@ from the @member@ table.
 U: rm@member@ pattern...
@@ -309,7 +310,7 @@ H: any given pattern.
 ---
 T: mv
 N: mv@member@
 ---
 T: mv
 N: mv@member@
-O: int com_mv@member@(int fd, int argc, char * const * const argv);
+O: int com_mv@member@(struct rc4_context *rc4c, int argc, char * const * const argv);
 P: AFS_READ | AFS_WRITE
 D: Rename a blob of type @member@.
 U: mv@member@ old_@member@_name new_@member@_name
 P: AFS_READ | AFS_WRITE
 D: Rename a blob of type @member@.
 U: mv@member@ old_@member@_name new_@member@_name
diff --git a/afs.h b/afs.h
index bcc36309dbda9c34a9a8c7298ecb8dab49298c8b..edeb348e33b05d57981fbf34013a142ed8d3df68 100644 (file)
--- a/afs.h
+++ b/afs.h
@@ -188,7 +188,7 @@ typedef void callback_function(int fd, const struct osl_object *);
  * \sa \ref send_callback_request().
  */
 typedef int callback_result_handler(struct osl_object *result, void *private);
  * \sa \ref send_callback_request().
  */
 typedef int callback_result_handler(struct osl_object *result, void *private);
-int send_result(struct osl_object *result, void *fd_ptr);
+int rc4_send_result(struct osl_object *result, void *private);
 int pass_buffer_as_shm(char *buf, size_t size, void *fd_ptr);
 
 __noreturn void afs_init(uint32_t cookie, int socket_fd);
 int pass_buffer_as_shm(char *buf, size_t size, void *fd_ptr);
 
 __noreturn void afs_init(uint32_t cookie, int socket_fd);
@@ -204,9 +204,6 @@ int send_option_arg_callback_request(struct osl_object *options,
 int send_standard_callback_request(int argc,  char * const * const argv,
                callback_function *f, callback_result_handler *result_handler,
                void *private_result_data);
 int send_standard_callback_request(int argc,  char * const * const argv,
                callback_function *f, callback_result_handler *result_handler,
                void *private_result_data);
-int stdin_command(int fd, struct osl_object *arg_obj, callback_function *f,
-               unsigned max_len, callback_result_handler *result_handler,
-               void *private_result_data);
 int string_compare(const struct osl_object *obj1, const struct osl_object *obj2);
 int for_each_matching_row(struct pattern_match_data *pmd);
 
 int string_compare(const struct osl_object *obj1, const struct osl_object *obj2);
 int for_each_matching_row(struct pattern_match_data *pmd);
 
diff --git a/aft.c b/aft.c
index 20fa3a96a4ccf1139d6d369ae8ff5764103e7822..e5409244c5a626204cb1e645ae52b903f2a49448 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -7,8 +7,11 @@
 /** \file aft.c Audio file table functions. */
 
 #include <dirent.h> /* readdir() */
 /** \file aft.c Audio file table functions. */
 
 #include <dirent.h> /* readdir() */
+#include <openssl/rc4.h>
+
 #include "para.h"
 #include "error.h"
 #include "para.h"
 #include "error.h"
+#include "crypt.h"
 #include "string.h"
 #include <sys/mman.h>
 #include <fnmatch.h>
 #include "string.h"
 #include <sys/mman.h>
 #include <fnmatch.h>
@@ -1409,7 +1412,7 @@ out:
 /*
  * TODO: flags -h (sort by hash)
  */
 /*
  * TODO: flags -h (sort by hash)
  */
-int com_ls(int fd, int argc, char * const * const argv)
+int com_ls(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        int i, ret;
        unsigned flags = 0;
 {
        int i, ret;
        unsigned flags = 0;
@@ -1518,7 +1521,7 @@ int com_ls(int fd, int argc, char * const * const argv)
        opts.mode = mode;
        opts.num_patterns = argc - i;
        ret = send_option_arg_callback_request(&query, opts.num_patterns,
        opts.mode = mode;
        opts.num_patterns = argc - i;
        ret = send_option_arg_callback_request(&query, opts.num_patterns,
-               argv + i, com_ls_callback, send_result, &fd);
+               argv + i, com_ls_callback, rc4_send_result, rc4c);
        return ret;
 }
 
        return ret;
 }
 
@@ -1805,8 +1808,8 @@ out:
 
 /** Used by com_add(). */
 struct private_add_data {
 
 /** Used by com_add(). */
 struct private_add_data {
-       /** The socket file descriptor. */
-       int fd;
+       /** The socket file descriptor, including rc4 keys. */
+       struct rc4_context *rc4c;
        /** The given add flags. */
        uint32_t flags;
 };
        /** The given add flags. */
        uint32_t flags;
 };
@@ -1861,7 +1864,8 @@ static int add_one_audio_file(const char *path, void *private_data)
        ret = 1;
        if (pb && (pad->flags & ADD_FLAG_LAZY)) { /* lazy is really cheap */
                if (pad->flags & ADD_FLAG_VERBOSE)
        ret = 1;
        if (pb && (pad->flags & ADD_FLAG_LAZY)) { /* lazy is really cheap */
                if (pad->flags & ADD_FLAG_VERBOSE)
-                       send_ret = send_va_buffer(pad->fd, "lazy-ignore: %s\n", path);
+                       send_ret = rc4_send_va_buffer(pad->rc4c,
+                               "lazy-ignore: %s\n", path);
                goto out_free;
        }
        /* We still want to add this file. Compute its hash. */
                goto out_free;
        }
        /* We still want to add this file. Compute its hash. */
@@ -1881,7 +1885,7 @@ static int add_one_audio_file(const char *path, void *private_data)
        ret = 1;
        if (pb && hs && hs == pb && !(pad->flags & ADD_FLAG_FORCE)) {
                if (pad->flags & ADD_FLAG_VERBOSE)
        ret = 1;
        if (pb && hs && hs == pb && !(pad->flags & ADD_FLAG_FORCE)) {
                if (pad->flags & ADD_FLAG_VERBOSE)
-                       send_ret = send_va_buffer(pad->fd,
+                       send_ret = rc4_send_va_buffer(pad->rc4c,
                                "%s exists, not forcing update\n", path);
                goto out_unmap;
        }
                                "%s exists, not forcing update\n", path);
                goto out_unmap;
        }
@@ -1899,13 +1903,13 @@ static int add_one_audio_file(const char *path, void *private_data)
        munmap(map.data, map.size);
        close(fd);
        if (pad->flags & ADD_FLAG_VERBOSE) {
        munmap(map.data, map.size);
        close(fd);
        if (pad->flags & ADD_FLAG_VERBOSE) {
-               send_ret = send_va_buffer(pad->fd, "adding %s\n", path);
+               send_ret = rc4_send_va_buffer(pad->rc4c, "adding %s\n", path);
                if (send_ret < 0)
                        goto out_free;
        }
        save_add_callback_buffer(hash, path, afhi_ptr, pad->flags, format_num, &obj);
        /* Ask afs to consider this entry for adding. */
                if (send_ret < 0)
                        goto out_free;
        }
        save_add_callback_buffer(hash, path, afhi_ptr, pad->flags, format_num, &obj);
        /* Ask afs to consider this entry for adding. */
-       ret = send_callback_request(com_add_callback, &obj, send_result, &pad->fd);
+       ret = send_callback_request(com_add_callback, &obj, rc4_send_result, pad->rc4c);
        goto out_free;
 
 out_unmap:
        goto out_free;
 
 out_unmap:
@@ -1913,8 +1917,8 @@ out_unmap:
        munmap(map.data, map.size);
 out_free:
        if (ret < 0 && send_ret >= 0)
        munmap(map.data, map.size);
 out_free:
        if (ret < 0 && send_ret >= 0)
-               send_ret = send_va_buffer(pad->fd, "failed to add %s (%s)\n", path,
-                       para_strerror(-ret));
+               send_ret = rc4_send_va_buffer(pad->rc4c,
+                       "failed to add %s (%s)\n", path, para_strerror(-ret));
        free(obj.data);
        if (afhi_ptr) {
                free(afhi_ptr->chunk_table);
        free(obj.data);
        if (afhi_ptr) {
                free(afhi_ptr->chunk_table);
@@ -1924,10 +1928,10 @@ out_free:
        return send_ret;
 }
 
        return send_ret;
 }
 
-int com_add(int fd, int argc, char * const * const argv)
+int com_add(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        int i, ret;
 {
        int i, ret;
-       struct private_add_data pad = {.fd = fd, .flags = 0};
+       struct private_add_data pad = {.rc4c = rc4c, .flags = 0};
        struct stat statbuf;
 
        for (i = 1; i < argc; i++) {
        struct stat statbuf;
 
        for (i = 1; i < argc; i++) {
@@ -1961,7 +1965,7 @@ int com_add(int fd, int argc, char * const * const argv)
                char *path;
                ret = verify_path(argv[i], &path);
                if (ret < 0) {
                char *path;
                ret = verify_path(argv[i], &path);
                if (ret < 0) {
-                       ret = send_va_buffer(fd, "%s: %s\n", argv[i],
+                       ret = rc4_send_va_buffer(rc4c, "%s: %s\n", argv[i],
                                para_strerror(-ret));
                        if (ret < 0)
                                return ret;
                                para_strerror(-ret));
                        if (ret < 0)
                                return ret;
@@ -1969,7 +1973,7 @@ int com_add(int fd, int argc, char * const * const argv)
                }
                ret = stat(path, &statbuf);
                if (ret < 0) {
                }
                ret = stat(path, &statbuf);
                if (ret < 0) {
-                       ret = send_va_buffer(fd, "failed to stat %s (%s)\n", path,
+                       ret = rc4_send_va_buffer(rc4c, "failed to stat %s (%s)\n", path,
                                strerror(errno));
                        free(path);
                        if (ret < 0)
                                strerror(errno));
                        free(path);
                        if (ret < 0)
@@ -1982,7 +1986,7 @@ int com_add(int fd, int argc, char * const * const argv)
                else
                        ret = add_one_audio_file(path, &pad);
                if (ret < 0) {
                else
                        ret = add_one_audio_file(path, &pad);
                if (ret < 0) {
-                       send_va_buffer(fd, "%s: %s\n", path, para_strerror(-ret));
+                       rc4_send_va_buffer(rc4c, "%s: %s\n", path, para_strerror(-ret));
                        free(path);
                        return ret;
                }
                        free(path);
                        return ret;
                }
@@ -2114,7 +2118,7 @@ static void com_touch_callback(int fd, const struct osl_object *query)
        free(tad.pb.buf);
 }
 
        free(tad.pb.buf);
 }
 
-int com_touch(int fd, int argc, char * const * const argv)
+int com_touch(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        struct com_touch_options cto = {
                .num_played = -1,
 {
        struct com_touch_options cto = {
                .num_played = -1,
@@ -2182,9 +2186,9 @@ int com_touch(int fd, int argc, char * const * const argv)
        if (i >= argc)
                return -E_AFT_SYNTAX;
        ret = send_option_arg_callback_request(&query, argc - i,
        if (i >= argc)
                return -E_AFT_SYNTAX;
        ret = send_option_arg_callback_request(&query, argc - i,
-               argv + i, com_touch_callback, send_result, &fd);
+               argv + i, com_touch_callback, rc4_send_result, rc4c);
        if (ret < 0)
        if (ret < 0)
-               send_va_buffer(fd, "%s\n", para_strerror(-ret));
+               rc4_send_va_buffer(rc4c, "%s\n", para_strerror(-ret));
        return ret;
 }
 
        return ret;
 }
 
@@ -2266,7 +2270,7 @@ static void com_rm_callback(int fd, const struct osl_object *query)
 }
 
 /* TODO options: -r (recursive) */
 }
 
 /* TODO options: -r (recursive) */
-int com_rm(int fd, int argc,  char * const * const argv)
+int com_rm(struct rc4_context *rc4c, int argc,  char * const * const argv)
 {
        uint32_t flags = 0;
        struct osl_object query = {.data = &flags, .size = sizeof(flags)};
 {
        uint32_t flags = 0;
        struct osl_object query = {.data = &flags, .size = sizeof(flags)};
@@ -2297,9 +2301,9 @@ int com_rm(int fd, int argc,  char * const * const argv)
        if (i >= argc)
                return -E_AFT_SYNTAX;
        ret = send_option_arg_callback_request(&query, argc - i, argv + i,
        if (i >= argc)
                return -E_AFT_SYNTAX;
        ret = send_option_arg_callback_request(&query, argc - i, argv + i,
-               com_rm_callback, send_result, &fd);
+               com_rm_callback, rc4_send_result, rc4c);
        if (ret < 0)
        if (ret < 0)
-               send_va_buffer(fd, "%s\n", para_strerror(-ret));
+               rc4_send_va_buffer(rc4c, "%s\n", para_strerror(-ret));
        return ret;
 }
 
        return ret;
 }
 
@@ -2414,7 +2418,7 @@ out:
        free(cad.pb.buf);
 }
 
        free(cad.pb.buf);
 }
 
-int com_cpsi(int fd, int argc,  char * const * const argv)
+int com_cpsi(struct rc4_context *rc4c, int argc,  char * const * const argv)
 {
        unsigned flags = 0;
        int i, ret;
 {
        unsigned flags = 0;
        int i, ret;
@@ -2459,9 +2463,9 @@ int com_cpsi(int fd, int argc,  char * const * const argv)
        if (!(flags & ~CPSI_FLAG_VERBOSE)) /* no copy flags given */
                flags = ~(unsigned)CPSI_FLAG_VERBOSE | flags;
        ret = send_option_arg_callback_request(&options, argc - i, argv + i,
        if (!(flags & ~CPSI_FLAG_VERBOSE)) /* no copy flags given */
                flags = ~(unsigned)CPSI_FLAG_VERBOSE | flags;
        ret = send_option_arg_callback_request(&options, argc - i, argv + i,
-               com_cpsi_callback, send_result, &fd);
+               com_cpsi_callback, rc4_send_result, rc4c);
        if (ret < 0)
        if (ret < 0)
-               send_va_buffer(fd, "%s\n", para_strerror(-ret));
+               rc4_send_va_buffer(rc4c, "%s\n", para_strerror(-ret));
        return ret;
 }
 
        return ret;
 }
 
index 30c12f1ca133a0caa98ac581ca1fc31aaf5c4909..ff284c3ad7e7822b136e7b788c8f13d17c40888b 100644 (file)
@@ -5,8 +5,12 @@
  */
 
 /** \file attribute.c Attribute handling functions. */
  */
 
 /** \file attribute.c Attribute handling functions. */
+
+#include <openssl/rc4.h>
+
 #include "para.h"
 #include "error.h"
 #include "para.h"
 #include "error.h"
+#include "crypt.h"
 #include "string.h"
 #include "afh.h"
 #include "afs.h"
 #include "string.h"
 #include "afh.h"
 #include "afs.h"
@@ -171,7 +175,7 @@ static void com_lsatt_callback(int fd, const struct osl_object *query)
        free(laad.pb.buf);
 }
 
        free(laad.pb.buf);
 }
 
-int com_lsatt(int fd, int argc, char * const * const argv)
+int com_lsatt(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        unsigned flags = 0;
        struct osl_object options = {.data = &flags, .size = sizeof(flags)};
 {
        unsigned flags = 0;
        struct osl_object options = {.data = &flags, .size = sizeof(flags)};
@@ -199,12 +203,12 @@ int com_lsatt(int fd, int argc, char * const * const argv)
                }
        }
        ret = send_option_arg_callback_request(&options, argc - i, argv + i,
                }
        }
        ret = send_option_arg_callback_request(&options, argc - i, argv + i,
-               com_lsatt_callback, send_result, &fd);
+               com_lsatt_callback, rc4_send_result, rc4c);
        if (!ret) {
                if (argc > 1)
        if (!ret) {
                if (argc > 1)
-                       ret = send_va_buffer(fd, "no matches\n");
+                       ret = rc4_send_va_buffer(rc4c, "no matches\n");
        } else if (ret < 0)
        } else if (ret < 0)
-               send_va_buffer(fd, "%s\n", para_strerror(-ret));
+               rc4_send_va_buffer(rc4c, "%s\n", para_strerror(-ret));
        return ret;
 }
 
        return ret;
 }
 
@@ -272,7 +276,7 @@ out:
                PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
 }
 
                PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
 }
 
-int com_setatt(__a_unused int fd, int argc, char * const * const argv)
+int com_setatt(__a_unused struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        if (argc < 3)
                return -E_ATTR_SYNTAX;
 {
        if (argc < 3)
                return -E_ATTR_SYNTAX;
@@ -353,16 +357,16 @@ out:
        free(pb.buf);
 }
 
        free(pb.buf);
 }
 
-int com_addatt(int fd, int argc, char * const * const argv)
+int com_addatt(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        int ret;
 
        if (argc < 2)
                return -E_ATTR_SYNTAX;
        ret = send_standard_callback_request(argc - 1, argv + 1, com_addatt_callback,
 {
        int ret;
 
        if (argc < 2)
                return -E_ATTR_SYNTAX;
        ret = send_standard_callback_request(argc - 1, argv + 1, com_addatt_callback,
-               send_result, &fd);
+               rc4_send_result, rc4c);
        if (ret < 0)
        if (ret < 0)
-               send_va_buffer(fd, "%s\n", para_strerror(-ret));
+               rc4_send_va_buffer(rc4c, "%s\n", para_strerror(-ret));
        return ret;
 }
 
        return ret;
 }
 
@@ -396,16 +400,16 @@ out:
        free(pb.buf);
 }
 
        free(pb.buf);
 }
 
-int com_mvatt(int fd, int argc, char * const * const argv)
+int com_mvatt(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        int ret;
 
        if (argc != 3)
                return -E_ATTR_SYNTAX;
        ret = send_standard_callback_request(argc - 1, argv + 1, com_mvatt_callback,
 {
        int ret;
 
        if (argc != 3)
                return -E_ATTR_SYNTAX;
        ret = send_standard_callback_request(argc - 1, argv + 1, com_mvatt_callback,
-               send_result, &fd);
+               rc4_send_result, rc4c);
        if (ret < 0)
        if (ret < 0)
-               send_va_buffer(fd, "%s\n", para_strerror(-ret));
+               rc4_send_va_buffer(rc4c, "%s\n", para_strerror(-ret));
        return ret;
 }
 
        return ret;
 }
 
@@ -468,16 +472,16 @@ static void com_rmatt_callback(int fd, const struct osl_object *query)
        free(raad.pb.buf);
 }
 
        free(raad.pb.buf);
 }
 
-int com_rmatt(int fd, int argc, char * const * const argv)
+int com_rmatt(struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        int ret;
 
        if (argc < 2)
                return -E_ATTR_SYNTAX;
        ret = send_standard_callback_request(argc - 1, argv + 1, com_rmatt_callback,
 {
        int ret;
 
        if (argc < 2)
                return -E_ATTR_SYNTAX;
        ret = send_standard_callback_request(argc - 1, argv + 1, com_rmatt_callback,
-               send_result, &fd);
+               rc4_send_result, rc4c);
        if (ret < 0)
        if (ret < 0)
-               send_va_buffer(fd, "%s\n", para_strerror(-ret));
+               rc4_send_va_buffer(rc4c, "%s\n", para_strerror(-ret));
        return ret;
 }
 
        return ret;
 }
 
index eb3b200ae6e5969be231c8be3e169d52e4430873..4a88cc884f774b2c5850b5a5b92ad23a117355a0 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -8,9 +8,11 @@
 #include <sys/types.h>
 #include <dirent.h>
 #include <signal.h>
 #include <sys/types.h>
 #include <dirent.h>
 #include <signal.h>
+#include <openssl/rc4.h>
 
 #include "para.h"
 #include "error.h"
 
 #include "para.h"
 #include "error.h"
+#include "crypt.h"
 #include "audiod.cmdline.h"
 #include "list.h"
 #include "sched.h"
 #include "audiod.cmdline.h"
 #include "list.h"
 #include "sched.h"
diff --git a/blob.c b/blob.c
index dbabba224ded1d96e8d8175b42181d3221df6e52..5905c9ad660cd93360fe77ef50ff81c4fe2a39df 100644 (file)
--- a/blob.c
+++ b/blob.c
@@ -7,8 +7,11 @@
 /** \file blob.c Macros and functions for blob handling. */
 
 #include <fnmatch.h>
 /** \file blob.c Macros and functions for blob handling. */
 
 #include <fnmatch.h>
+#include <openssl/rc4.h>
+
 #include "para.h"
 #include "error.h"
 #include "para.h"
 #include "error.h"
+#include "crypt.h"
 #include "string.h"
 #include "afh.h"
 #include "afs.h"
 #include "string.h"
 #include "afh.h"
 #include "afs.h"
@@ -116,7 +119,7 @@ static void com_lsblob_callback(struct osl_table *table,
        free(lbad.pb.buf);
 }
 
        free(lbad.pb.buf);
 }
 
-static int com_lsblob(callback_function *f, int fd, int argc, char * const * const argv)
+static int com_lsblob(callback_function *f, struct rc4_context *rc4c, int argc, char * const * const argv)
 {
        uint32_t flags = 0;
        struct osl_object options = {.data = &flags, .size = sizeof(flags)};
 {
        uint32_t flags = 0;
        struct osl_object options = {.data = &flags, .size = sizeof(flags)};
@@ -147,7 +150,7 @@ static int com_lsblob(callback_function *f, int fd, int argc, char * const * con
 //     if (argc > i)
 //             return -E_BLOB_SYNTAX;
        return send_option_arg_callback_request(&options, argc - i,
 //     if (argc > i)
 //             return -E_BLOB_SYNTAX;
        return send_option_arg_callback_request(&options, argc - i,
-               argv + i, f, send_result, &fd);
+               argv + i, f, rc4_send_result, rc4c);
 }
 
 static int cat_blob(struct osl_table *table, struct osl_row *row,
 }
 
 static int cat_blob(struct osl_table *table, struct osl_row *row,
@@ -180,12 +183,13 @@ static void com_catblob_callback(struct osl_table *table, int fd,
        for_each_matching_row(&pmd);
 }
 
        for_each_matching_row(&pmd);
 }
 
-static int com_catblob(callback_function *f, int fd, int argc,
+static int com_catblob(callback_function *f, struct rc4_context *rc4c, int argc,
                char * const * const argv)
 {
        if (argc < 2)
                return -E_BLOB_SYNTAX;
                char * const * const argv)
 {
        if (argc < 2)
                return -E_BLOB_SYNTAX;
-       return send_standard_callback_request(argc - 1, argv + 1, f, send_result, &fd);
+       return send_standard_callback_request(argc - 1, argv + 1, f,
+               rc4_send_result, rc4c);
 }
 
 /** Used for removing rows from a blob table. */
 }
 
 /** Used for removing rows from a blob table. */
@@ -248,13 +252,13 @@ out:
        free(rmbd.pb.buf);
 }
 
        free(rmbd.pb.buf);
 }
 
-static int com_rmblob(callback_function *f, int fd, int argc,
+static int com_rmblob(callback_function *f, struct rc4_context *rc4c, int argc,
                char * const * const argv)
 {
        if (argc < 2)
                return -E_MOOD_SYNTAX;
        return send_option_arg_callback_request(NULL, argc - 1, argv + 1, f,
                char * const * const argv)
 {
        if (argc < 2)
                return -E_MOOD_SYNTAX;
        return send_option_arg_callback_request(NULL, argc - 1, argv + 1, f,
-               send_result, &fd);
+               rc4_send_result, rc4c);
 }
 
 static void com_addblob_callback(struct osl_table *table, __a_unused int fd,
 }
 
 static void com_addblob_callback(struct osl_table *table, __a_unused int fd,
@@ -326,7 +330,82 @@ out:
                PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
 }
 
                PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
 }
 
-static int com_addblob(callback_function *f, int fd, int argc,
+/*
+ * write input from fd to dynamically allocated buffer,
+ * but maximal max_size byte.
+ */
+static int fd2buf(struct rc4_context *rc4c, unsigned max_size, struct osl_object *obj)
+{
+       const size_t chunk_size = 1024;
+       size_t size = 2048, received = 0;
+       int ret;
+       char *buf = para_malloc(size);
+
+       for (;;) {
+               ret = rc4_recv_bin_buffer(rc4c, buf + received, chunk_size);
+               if (ret <= 0)
+                       break;
+               received += ret;
+               if (received + chunk_size >= size) {
+                       size *= 2;
+                       ret = -E_INPUT_TOO_LARGE;
+                       if (size > max_size)
+                               break;
+                       buf = para_realloc(buf, size);
+               }
+       }
+       obj->data = buf;
+       obj->size = received;
+       if (ret < 0)
+               free(buf);
+       return ret;
+}
+
+/*
+ * Read data from a file descriptor, and send it to the afs process.
+ *
+ * \param rc4c crypt context containing the file descriptor to read data from.
+ * \param arg_obj Pointer to the arguments to \a f.
+ * \param f The callback function.
+ * \param max_len Don't read more than that many bytes from stdin.
+ * \param result_handler See \ref send_callback_request.
+ * \param private_result_data See \ref send_callback_request.
+ *
+ * This function is used by commands that wish to let para_server store
+ * arbitrary data specified by the user (for instance the add_blob family of
+ * commands). First, at most \a max_len bytes are read and decrypted from the
+ * file descriptor given by \a rc4c. The result is concatenated with the buffer
+ * given by \a arg_obj, and the combined buffer is made available to the afs
+ * process via the callback method. See \ref send_callback_request for details.
+ *
+ * \return Negative on errors, the return value of the underlying call to
+ * send_callback_request() otherwise.
+ */
+static int stdin_command(struct rc4_context *rc4c, struct osl_object *arg_obj,
+               callback_function *f, unsigned max_len,
+               callback_result_handler *result_handler,
+               void *private_result_data)
+{
+       struct osl_object query, stdin_obj;
+       int ret;
+
+       ret = rc4_send_buffer(rc4c, AWAITING_DATA_MSG);
+       if (ret < 0)
+               return ret;
+       ret = fd2buf(rc4c, max_len, &stdin_obj);
+       if (ret < 0)
+               return ret;
+       query.size = arg_obj->size + stdin_obj.size;
+       query.data = para_malloc(query.size);
+       memcpy(query.data, arg_obj->data, arg_obj->size);
+       memcpy((char *)query.data + arg_obj->size, stdin_obj.data, stdin_obj.size);
+       free(stdin_obj.data);
+       ret = send_callback_request(f, &query, result_handler, private_result_data);
+       free(query.data);
+       return ret;
+}
+
+static int com_addblob(callback_function *f, struct rc4_context *rc4c, int argc,
                char * const * const argv)
 {
        struct osl_object arg_obj;
                char * const * const argv)
 {
        struct osl_object arg_obj;
@@ -337,7 +416,7 @@ static int com_addblob(callback_function *f, int fd, int argc,
                return -E_BLOB_SYNTAX;
        arg_obj.size = strlen(argv[1]) + 1;
        arg_obj.data = (char *)argv[1];
                return -E_BLOB_SYNTAX;
        arg_obj.size = strlen(argv[1]) + 1;
        arg_obj.data = (char *)argv[1];
-       return stdin_command(fd, &arg_obj, f, 10 * 1024 * 1024, NULL, NULL);
+       return stdin_command(rc4c, &arg_obj, f, 10 * 1024 * 1024, NULL, NULL);
 }
 
 /* FIXME: Print output to client, not to log file */
 }
 
 /* FIXME: Print output to client, not to log file */
@@ -363,7 +442,7 @@ out:
                PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
 }
 
                PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
 }
 
-static int com_mvblob(callback_function *f, __a_unused int fd,
+static int com_mvblob(callback_function *f, __a_unused struct rc4_context *rc4c,
                int argc, char * const * const argv)
 {
        if (argc != 3)
                int argc, char * const * const argv)
 {
        if (argc != 3)
@@ -377,9 +456,9 @@ static int com_mvblob(callback_function *f, __a_unused int fd,
        { \
                return com_ ## cmd_name ## blob_callback(table_name ## _table, fd, query); \
        } \
        { \
                return com_ ## cmd_name ## blob_callback(table_name ## _table, fd, query); \
        } \
-       int com_ ## cmd_name ## cmd_prefix(int fd, int argc, char * const * const argv) \
+       int com_ ## cmd_name ## cmd_prefix(struct rc4_context *rc4c, int argc, char * const * const argv) \
        { \
        { \
-               return com_ ## cmd_name ## blob(com_ ## cmd_name ## cmd_prefix ## _callback, fd, argc, argv); \
+               return com_ ## cmd_name ## blob(com_ ## cmd_name ## cmd_prefix ## _callback, rc4c, argc, argv); \
        }
 
 static int blob_get_name_by_id(struct osl_table *table, uint32_t id,
        }
 
 static int blob_get_name_by_id(struct osl_table *table, uint32_t id,
index 003c1e609f8ce1e606fecd9ad3b7092e76987936..fef6ba4a5bc4194048a951d9ceb657d91d14e4ae 100644 (file)
--- a/client.c
+++ b/client.c
@@ -6,9 +6,12 @@
 
 /** \file client.c the client program used to connect to para_server */
 
 
 /** \file client.c the client program used to connect to para_server */
 
+#include <openssl/rc4.h>
+
 #include "para.h"
 #include "list.h"
 #include "sched.h"
 #include "para.h"
 #include "list.h"
 #include "sched.h"
+#include "crypt.h"
 #include "client.cmdline.h"
 #include "string.h"
 #include "stdin.h"
 #include "client.cmdline.h"
 #include "string.h"
 #include "stdin.h"
index c6d5c75d1ebf1e70a7dbeafa5ca10f60a2e00592..fa965c354997ff9fef38ebba8b8220412ffeab84 100644 (file)
--- a/client.h
+++ b/client.h
@@ -41,8 +41,8 @@ enum {
 struct client_task {
        /** the state of the connection */
        int status;
 struct client_task {
        /** the state of the connection */
        int status;
-       /** the file descriptor */
-       int fd;
+       /** The file descriptor and the rc4 keys. */
+       struct rc4_context rc4c;
        /** the configuration (including the command) */
        struct client_args_info conf;
        /** the config file for client options */
        /** the configuration (including the command) */
        struct client_args_info conf;
        /** the config file for client options */
@@ -51,10 +51,6 @@ struct client_task {
        char *key_file;
        /** paraslash user name */
        char *user;
        char *key_file;
        /** paraslash user name */
        char *user;
-       /** session key for receiving data */
-       RC4_KEY rc4_recv_key;
-       /** session key for sending data */
-       RC4_KEY rc4_send_key;
        /** the client task structure */
        struct task task;
        /** the buffer used for handshake and receiving */
        /** the client task structure */
        struct task task;
        /** the buffer used for handshake and receiving */
index deb3a26ded485f79855516fcd2c1c5f9772761b6..b1eaa78b2db7563b699c6993509e738b12f665a8 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <sys/types.h>
 #include <dirent.h>
 
 #include <sys/types.h>
 #include <dirent.h>
+#include <openssl/rc4.h>
 
 #include "para.h"
 #include "error.h"
 
 #include "para.h"
 #include "error.h"
 #include "client.cmdline.h"
 #include "client.h"
 
 #include "client.cmdline.h"
 #include "client.h"
 
-/*
- * Rc4-encrypt data before sending.
- *
- * \param len The number of bytes to encrypt.
- * \param indata Pointer to the input data of length \a len to be encrypted.
- * \param outdata Result-pointer that holds the encrypted data.
- * \param private_data Contains the rc4 key.
- */
-static void rc4_send(unsigned long len, const unsigned char *indata,
-               unsigned char *outdata, void *private_data)
-{
-       struct client_task *ct = private_data;
-       RC4(&ct->rc4_send_key, len, indata, outdata);
-}
-
-/*
- * Rc4-decrypt received data.
- *
- * Parameters are identical to those of rc4_send.
- */
-static void rc4_recv(unsigned long len, const unsigned char *indata,
-               unsigned char *outdata, void *private_data)
-{
-       struct client_task *ct = private_data;
-       RC4(&ct->rc4_recv_key, len, indata, outdata);
-}
-
 /**
  * Close the connection to para_server and free all resources.
  *
 /**
  * Close the connection to para_server and free all resources.
  *
@@ -60,10 +34,8 @@ void client_close(struct client_task *ct)
 {
        if (!ct)
                return;
 {
        if (!ct)
                return;
-       if (ct->fd >= 0) {
-               disable_crypt(ct->fd);
-               close(ct->fd);
-       }
+       if (ct->rc4c.fd >= 0)
+               close(ct->rc4c.fd);
        free(ct->buf);
        free(ct->user);
        free(ct->config_file);
        free(ct->buf);
        free(ct->user);
        free(ct->config_file);
@@ -92,27 +64,27 @@ static void client_pre_select(struct sched *s, struct task *t)
 
        ct->check_r = 0;
        ct->check_w = 0;
 
        ct->check_r = 0;
        ct->check_w = 0;
-       if (ct->fd < 0)
+       if (ct->rc4c.fd < 0)
                return;
        switch (ct->status) {
        case CL_CONNECTED:
        case CL_SENT_AUTH:
        case CL_SENT_CH_RESPONSE:
        case CL_SENT_COMMAND:
                return;
        switch (ct->status) {
        case CL_CONNECTED:
        case CL_SENT_AUTH:
        case CL_SENT_CH_RESPONSE:
        case CL_SENT_COMMAND:
-               para_fd_set(ct->fd, &s->rfds, &s->max_fileno);
+               para_fd_set(ct->rc4c.fd, &s->rfds, &s->max_fileno);
                ct->check_r = 1;
                return;
 
        case CL_RECEIVED_WELCOME:
        case CL_RECEIVED_CHALLENGE:
        case CL_RECEIVED_PROCEED:
                ct->check_r = 1;
                return;
 
        case CL_RECEIVED_WELCOME:
        case CL_RECEIVED_CHALLENGE:
        case CL_RECEIVED_PROCEED:
-               para_fd_set(ct->fd, &s->wfds, &s->max_fileno);
+               para_fd_set(ct->rc4c.fd, &s->wfds, &s->max_fileno);
                ct->check_w = 1;
                return;
 
        case CL_RECEIVING:
                if (ct->loaded < CLIENT_BUFSIZE - 1) {
                ct->check_w = 1;
                return;
 
        case CL_RECEIVING:
                if (ct->loaded < CLIENT_BUFSIZE - 1) {
-                       para_fd_set(ct->fd, &s->rfds, &s->max_fileno);
+                       para_fd_set(ct->rc4c.fd, &s->rfds, &s->max_fileno);
                        ct->check_r = 1;
                }
                return;
                        ct->check_r = 1;
                }
                return;
@@ -121,7 +93,7 @@ static void client_pre_select(struct sched *s, struct task *t)
                        return;
                if (*ct->in_loaded) {
                        PARA_INFO_LOG("loaded: %zd\n", *ct->in_loaded);
                        return;
                if (*ct->in_loaded) {
                        PARA_INFO_LOG("loaded: %zd\n", *ct->in_loaded);
-                       para_fd_set(ct->fd, &s->wfds, &s->max_fileno);
+                       para_fd_set(ct->rc4c.fd, &s->wfds, &s->max_fileno);
                        ct->check_w = 1;
                } else {
                        if (*ct->in_error) {
                        ct->check_w = 1;
                } else {
                        if (*ct->in_error) {
@@ -136,8 +108,14 @@ static void client_pre_select(struct sched *s, struct task *t)
 
 static ssize_t client_recv_buffer(struct client_task *ct)
 {
 
 static ssize_t client_recv_buffer(struct client_task *ct)
 {
-       ssize_t ret = recv_buffer(ct->fd, ct->buf + ct->loaded,
-               CLIENT_BUFSIZE - ct->loaded);
+       ssize_t ret;
+
+       if (ct->status < CL_RECEIVED_PROCEED)
+               ret = recv_buffer(ct->rc4c.fd, ct->buf + ct->loaded,
+                       CLIENT_BUFSIZE - ct->loaded);
+       else
+               ret = rc4_recv_buffer(&ct->rc4c, ct->buf + ct->loaded,
+                       CLIENT_BUFSIZE - ct->loaded);
        if (!ret)
                return -E_SERVER_EOF;
        if (ret > 0)
        if (!ret)
                return -E_SERVER_EOF;
        if (ret > 0)
@@ -164,13 +142,13 @@ static void client_post_select(struct sched *s, struct task *t)
        struct client_task *ct = container_of(t, struct client_task, task);
 
        t->error = 0;
        struct client_task *ct = container_of(t, struct client_task, task);
 
        t->error = 0;
-       if (ct->fd < 0)
+       if (ct->rc4c.fd < 0)
                return;
        if (!ct->check_r && !ct->check_w)
                return;
                return;
        if (!ct->check_r && !ct->check_w)
                return;
-       if (ct->check_r && !FD_ISSET(ct->fd, &s->rfds))
+       if (ct->check_r && !FD_ISSET(ct->rc4c.fd, &s->rfds))
                return;
                return;
-       if (ct->check_w && !FD_ISSET(ct->fd, &s->wfds))
+       if (ct->check_w && !FD_ISSET(ct->rc4c.fd, &s->wfds))
                return;
        switch (ct->status) {
        case CL_CONNECTED: /* receive welcome message */
                return;
        switch (ct->status) {
        case CL_CONNECTED: /* receive welcome message */
@@ -181,7 +159,7 @@ static void client_post_select(struct sched *s, struct task *t)
        case CL_RECEIVED_WELCOME: /* send auth command */
                sprintf(ct->buf, "auth rc4 %s", ct->user);
                PARA_INFO_LOG("--> %s\n", ct->buf);
        case CL_RECEIVED_WELCOME: /* send auth command */
                sprintf(ct->buf, "auth rc4 %s", ct->user);
                PARA_INFO_LOG("--> %s\n", ct->buf);
-               t->error = send_buffer(ct->fd, ct->buf);
+               t->error = send_buffer(ct->rc4c.fd, ct->buf);
                if (t->error >= 0)
                        ct->status = CL_SENT_AUTH;
                return;
                if (t->error >= 0)
                        ct->status = CL_SENT_AUTH;
                return;
@@ -204,7 +182,7 @@ static void client_post_select(struct sched *s, struct task *t)
                return;
        case CL_RECEIVED_CHALLENGE: /* send decrypted challenge */
                PARA_INFO_LOG("--> %lu\n", ct->challenge_nr);
                return;
        case CL_RECEIVED_CHALLENGE: /* send decrypted challenge */
                PARA_INFO_LOG("--> %lu\n", ct->challenge_nr);
-               t->error = send_va_buffer(ct->fd, "%s%lu", CHALLENGE_RESPONSE_MSG,
+               t->error = send_va_buffer(ct->rc4c.fd, "%s%lu", CHALLENGE_RESPONSE_MSG,
                        ct->challenge_nr);
                if (t->error > 0)
                        ct->status = CL_SENT_CH_RESPONSE;
                        ct->challenge_nr);
                if (t->error > 0)
                        ct->status = CL_SENT_CH_RESPONSE;
@@ -232,9 +210,8 @@ static void client_post_select(struct sched *s, struct task *t)
                        bytes_received - PROCEED_MSG_LEN - 1);
                if (t->error < 0)
                        return;
                        bytes_received - PROCEED_MSG_LEN - 1);
                if (t->error < 0)
                        return;
-               RC4_set_key(&ct->rc4_send_key, RC4_KEY_LEN, rc4_buf);
-               RC4_set_key(&ct->rc4_recv_key, RC4_KEY_LEN, rc4_buf + RC4_KEY_LEN);
-               enable_crypt(ct->fd, rc4_recv, rc4_send, ct);
+               RC4_set_key(&ct->rc4c.send_key, RC4_KEY_LEN, rc4_buf);
+               RC4_set_key(&ct->rc4c.recv_key, RC4_KEY_LEN, rc4_buf + RC4_KEY_LEN);
                ct->status = CL_RECEIVED_PROCEED;
                return;
                }
                ct->status = CL_RECEIVED_PROCEED;
                return;
                }
@@ -250,7 +227,7 @@ static void client_post_select(struct sched *s, struct task *t)
                }
                command = para_strcat(command, EOC_MSG "\n");
                PARA_DEBUG_LOG("--> %s\n", command);
                }
                command = para_strcat(command, EOC_MSG "\n");
                PARA_DEBUG_LOG("--> %s\n", command);
-               t->error = send_buffer(ct->fd, command);
+               t->error = rc4_send_buffer(&ct->rc4c, command);
                free(command);
                if (t->error > 0)
                        ct->status = CL_SENT_COMMAND;
                free(command);
                if (t->error > 0)
                        ct->status = CL_SENT_COMMAND;
@@ -268,7 +245,7 @@ static void client_post_select(struct sched *s, struct task *t)
                return;
        case CL_SENDING: /* FIXME: might block */
                PARA_INFO_LOG("loaded: %zd\n", *ct->in_loaded);
                return;
        case CL_SENDING: /* FIXME: might block */
                PARA_INFO_LOG("loaded: %zd\n", *ct->in_loaded);
-               t->error = send_bin_buffer(ct->fd, ct->inbuf, *ct->in_loaded);
+               t->error = rc4_send_bin_buffer(&ct->rc4c, ct->inbuf, *ct->in_loaded);
                if (t->error < 0)
                        return;
                *ct->in_loaded = 0;
                if (t->error < 0)
                        return;
                *ct->in_loaded = 0;
@@ -284,14 +261,14 @@ static int client_connect(struct client_task *ct)
 {
        int ret;
 
 {
        int ret;
 
-       ct->fd = -1;
+       ct->rc4c.fd = -1;
        ret = makesock(AF_UNSPEC, IPPROTO_TCP, 0, ct->conf.hostname_arg,
                ct->conf.server_port_arg);
        if (ret < 0)
                return ret;
        ret = makesock(AF_UNSPEC, IPPROTO_TCP, 0, ct->conf.hostname_arg,
                ct->conf.server_port_arg);
        if (ret < 0)
                return ret;
-       ct->fd = ret;
+       ct->rc4c.fd = ret;
        ct->status = CL_CONNECTED;
        ct->status = CL_CONNECTED;
-       ret = mark_fd_nonblocking(ct->fd);
+       ret = mark_fd_nonblocking(ct->rc4c.fd);
        if (ret < 0)
                goto err_out;
        ct->task.pre_select = client_pre_select;
        if (ret < 0)
                goto err_out;
        ct->task.pre_select = client_pre_select;
@@ -300,8 +277,8 @@ static int client_connect(struct client_task *ct)
        register_task(&ct->task);
        return 1;
 err_out:
        register_task(&ct->task);
        return 1;
 err_out:
-       close(ct->fd);
-       ct->fd = -1;
+       close(ct->rc4c.fd);
+       ct->rc4c.fd = -1;
        return ret;
 }
 
        return ret;
 }
 
@@ -329,7 +306,7 @@ int client_open(int argc, char *argv[], struct client_task **ct_ptr,
 
        ct->buf = para_malloc(CLIENT_BUFSIZE);
        *ct_ptr = ct;
 
        ct->buf = para_malloc(CLIENT_BUFSIZE);
        *ct_ptr = ct;
-       ct->fd = -1;
+       ct->rc4c.fd = -1;
        ret = -E_CLIENT_SYNTAX;
        if (client_cmdline_parser(argc, argv, &ct->conf))
                goto out;
        ret = -E_CLIENT_SYNTAX;
        if (client_cmdline_parser(argc, argv, &ct->conf))
                goto out;
index ab765a1bc895a5cde555234755ba9ecb16b4c0fe..4b3a155277fbdde2ead5c0ba8ed238770b710169 100644 (file)
--- a/command.c
+++ b/command.c
@@ -14,6 +14,8 @@
 
 #include "para.h"
 #include "error.h"
 
 #include "para.h"
 #include "error.h"
+#include "crypt.h"
+#include "command.h"
 #include "server.cmdline.h"
 #include "string.h"
 #include "afh.h"
 #include "server.cmdline.h"
 #include "string.h"
 #include "afh.h"
 /** Commands including options must be shorter than this. */
 #define MAX_COMMAND_LEN 32768
 
 /** Commands including options must be shorter than this. */
 #define MAX_COMMAND_LEN 32768
 
-static RC4_KEY rc4_recv_key;
-static RC4_KEY rc4_send_key;
 static unsigned char rc4_buf[2 * RC4_KEY_LEN];
 
 extern int mmd_mutex;
 extern struct misc_meta_data *mmd;
 extern struct sender senders[];
 
 static unsigned char rc4_buf[2 * RC4_KEY_LEN];
 
 extern int mmd_mutex;
 extern struct misc_meta_data *mmd;
 extern struct sender senders[];
 
+static void init_rc4_keys(struct rc4_context *rcc)
+{
+       get_random_bytes_or_die(rc4_buf, 2 * RC4_KEY_LEN);
+       RC4_set_key(&rcc->recv_key, RC4_KEY_LEN, rc4_buf);
+       RC4_set_key(&rcc->send_key, RC4_KEY_LEN, rc4_buf + RC4_KEY_LEN);
+}
+
 static void dummy(__a_unused int s)
 {
 }
 static void dummy(__a_unused int s)
 {
 }
@@ -208,7 +215,7 @@ static int check_sender_args(int argc, char * const * argv, struct sender_comman
        return 1;
 }
 
        return 1;
 }
 
-int com_sender(int fd, int argc, char * const * argv)
+int com_sender(struct rc4_context *rc4c, int argc, char * const * argv)
 {
        int i, ret;
        struct sender_command_data scd;
 {
        int i, ret;
        struct sender_command_data scd;
@@ -221,7 +228,7 @@ int com_sender(int fd, int argc, char * const * argv)
                        free(msg);
                        msg = tmp;
                }
                        free(msg);
                        msg = tmp;
                }
-               ret = send_buffer(fd, msg);
+               ret = rc4_send_buffer(rc4c, msg);
                free(msg);
                return ret;
        }
                free(msg);
                return ret;
        }
@@ -231,7 +238,7 @@ int com_sender(int fd, int argc, char * const * argv)
                if (scd.sender_num < 0)
                        return ret;
                msg = senders[scd.sender_num].help();
                if (scd.sender_num < 0)
                        return ret;
                msg = senders[scd.sender_num].help();
-               ret = send_buffer(fd, msg);
+               ret = rc4_send_buffer(rc4c, msg);
                free(msg);
                return ret;
        }
                free(msg);
                return ret;
        }
@@ -250,7 +257,7 @@ int com_sender(int fd, int argc, char * const * argv)
 }
 
 /* server info */
 }
 
 /* server info */
-int com_si(int fd, int argc, __a_unused char * const * argv)
+int com_si(struct rc4_context *rc4c, int argc, __a_unused char * const * argv)
 {
        int i, ret;
        char *ut;
 {
        int i, ret;
        char *ut;
@@ -267,7 +274,7 @@ int com_si(int fd, int argc, __a_unused char * const * argv)
                sender_list = para_strcat(sender_list, " ");
        }
        ut = uptime_str();
                sender_list = para_strcat(sender_list, " ");
        }
        ut = uptime_str();
-       ret = send_va_buffer(fd, "up: %s\nplayed: %u\n"
+       ret = rc4_send_va_buffer(rc4c, "up: %s\nplayed: %u\n"
                "server_pid: %d\n"
                "afs_pid: %d\n"
                "connections (active/accepted/total): %u/%u/%u\n"
                "server_pid: %d\n"
                "afs_pid: %d\n"
                "connections (active/accepted/total): %u/%u/%u\n"
@@ -294,18 +301,18 @@ int com_si(int fd, int argc, __a_unused char * const * argv)
 }
 
 /* version */
 }
 
 /* version */
-int com_version(int fd, int argc, __a_unused char * const * argv)
+int com_version(struct rc4_context *rc4c, int argc, __a_unused char * const * argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
-       return send_buffer(fd, VERSION_TEXT("server")
+       return rc4_send_buffer(rc4c, VERSION_TEXT("server")
                "built: " BUILD_DATE "\n"
                UNAME_RS ", " CC_VERSION "\n"
        );
 }
 
 /* stat */
                "built: " BUILD_DATE "\n"
                UNAME_RS ", " CC_VERSION "\n"
        );
 }
 
 /* stat */
-int com_stat(int fd, int argc, char * const * argv)
+int com_stat(struct rc4_context *rc4c, int argc, char * const * argv)
 {
        int ret, num = 0;/* status will be printed that many
                          * times. num <= 0 means: print forever
 {
        int ret, num = 0;/* status will be printed that many
                          * times. num <= 0 means: print forever
@@ -321,7 +328,7 @@ int com_stat(int fd, int argc, char * const * argv)
 
                mmd_dup(nmmd);
                s = get_status(nmmd);
 
                mmd_dup(nmmd);
                s = get_status(nmmd);
-               ret = send_buffer(fd, s);
+               ret = rc4_send_buffer(rc4c, s);
                free(s);
                if (ret < 0)
                        goto out;
                free(s);
                if (ret < 0)
                        goto out;
@@ -336,14 +343,14 @@ out:
        return ret;
 }
 
        return ret;
 }
 
-static int send_list_of_commands(int fd, struct server_command *cmd,
+static int send_list_of_commands(struct rc4_context *rc4c, struct server_command *cmd,
                const char *handler)
 {
        int ret, i;
 
        for (i = 1; cmd->name; cmd++, i++) {
                char *perms = cmd_perms_itohuman(cmd->perms);
                const char *handler)
 {
        int ret, i;
 
        for (i = 1; cmd->name; cmd++, i++) {
                char *perms = cmd_perms_itohuman(cmd->perms);
-               ret = send_va_buffer(fd, "%s\t%s\t%s\t%s\n", cmd->name,
+               ret = rc4_send_va_buffer(rc4c, "%s\t%s\t%s\t%s\n", cmd->name,
                        handler,
                        perms,
                        cmd->description);
                        handler,
                        perms,
                        cmd->description);
@@ -376,7 +383,7 @@ static struct server_command *get_cmd_ptr(const char *name, char **handler)
 }
 
 /* help */
 }
 
 /* help */
-int com_help(int fd, int argc, char * const * argv)
+int com_help(struct rc4_context *rc4c, int argc, char * const * argv)
 {
        struct server_command *cmd;
        char *perms, *handler;
 {
        struct server_command *cmd;
        char *perms, *handler;
@@ -384,9 +391,9 @@ int com_help(int fd, int argc, char * const * argv)
 
        if (argc < 2) {
                /* no argument given, print list of commands */
 
        if (argc < 2) {
                /* no argument given, print list of commands */
-               if ((ret = send_list_of_commands(fd, server_cmds, "server")) < 0)
+               if ((ret = send_list_of_commands(rc4c, server_cmds, "server")) < 0)
                        return ret;
                        return ret;
-               return send_list_of_commands(fd, afs_cmds, "afs");
+               return send_list_of_commands(rc4c, afs_cmds, "afs");
        }
        /* argument given for help */
        cmd = get_cmd_ptr(argv[1], &handler);
        }
        /* argument given for help */
        cmd = get_cmd_ptr(argv[1], &handler);
@@ -395,7 +402,7 @@ int com_help(int fd, int argc, char * const * argv)
                return -E_BAD_CMD;
        }
        perms = cmd_perms_itohuman(cmd->perms);
                return -E_BAD_CMD;
        }
        perms = cmd_perms_itohuman(cmd->perms);
-       ret = send_va_buffer(fd,
+       ret = rc4_send_va_buffer(rc4c,
                "%s - %s\n\n"
                "handler: %s\n"
                "permissions: %s\n"
                "%s - %s\n\n"
                "handler: %s\n"
                "permissions: %s\n"
@@ -414,7 +421,7 @@ int com_help(int fd, int argc, char * const * argv)
 }
 
 /* hup */
 }
 
 /* hup */
-int com_hup(__a_unused int fd, int argc, __a_unused char * const * argv)
+int com_hup(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -423,7 +430,7 @@ int com_hup(__a_unused int fd, int argc, __a_unused char * const * argv)
 }
 
 /* term */
 }
 
 /* term */
-int com_term(__a_unused int fd, int argc, __a_unused char * const * argv)
+int com_term(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -431,7 +438,7 @@ int com_term(__a_unused int fd, int argc, __a_unused char * const * argv)
        return 1;
 }
 
        return 1;
 }
 
-int com_play(__a_unused int fd, int argc, __a_unused char * const * argv)
+int com_play(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -444,7 +451,7 @@ int com_play(__a_unused int fd, int argc, __a_unused char * const * argv)
 }
 
 /* stop */
 }
 
 /* stop */
-int com_stop(__a_unused int fd, int argc, __a_unused char * const * argv)
+int com_stop(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -457,7 +464,7 @@ int com_stop(__a_unused int fd, int argc, __a_unused char * const * argv)
 }
 
 /* pause */
 }
 
 /* pause */
-int com_pause(__a_unused int fd, int argc, __a_unused char * const * argv)
+int com_pause(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -472,7 +479,7 @@ int com_pause(__a_unused int fd, int argc, __a_unused char * const * argv)
 }
 
 /* next */
 }
 
 /* next */
-int com_next(__a_unused int fd, int argc, __a_unused char * const * argv)
+int com_next(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -484,7 +491,7 @@ int com_next(__a_unused int fd, int argc, __a_unused char * const * argv)
 }
 
 /* nomore */
 }
 
 /* nomore */
-int com_nomore(__a_unused int fd, int argc, __a_unused char * const * argv)
+int com_nomore(__a_unused struct rc4_context *rc4c, int argc, __a_unused char * const * argv)
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
 {
        if (argc != 1)
                return -E_COMMAND_SYNTAX;
@@ -496,7 +503,7 @@ int com_nomore(__a_unused int fd, int argc, __a_unused char * const * argv)
 }
 
 /* ff */
 }
 
 /* ff */
-int com_ff(__a_unused int fd, int argc, char * const * argv)
+int com_ff(__a_unused struct rc4_context *rc4c, int argc, char * const * argv)
 {
        long promille;
        int ret, backwards = 0;
 {
        long promille;
        int ret, backwards = 0;
@@ -535,7 +542,7 @@ out:
 }
 
 /* jmp */
 }
 
 /* jmp */
-int com_jmp(__a_unused int fd, int argc, char * const * argv)
+int com_jmp(__a_unused struct rc4_context *rc4c, int argc, char * const * argv)
 {
        long unsigned int i;
        int ret;
 {
        long unsigned int i;
        int ret;
@@ -589,29 +596,7 @@ static struct server_command *parse_cmd(const char *cmdstr)
        return get_cmd_ptr(buf, NULL);
 }
 
        return get_cmd_ptr(buf, NULL);
 }
 
-static void init_rc4_keys(void)
-{
-       get_random_bytes_or_die(rc4_buf, 2 * RC4_KEY_LEN);
-       PARA_DEBUG_LOG("rc4 keys initialized (%u:%u)\n",
-               (unsigned char) rc4_buf[0],
-               (unsigned char) rc4_buf[RC4_KEY_LEN]);
-       RC4_set_key(&rc4_recv_key, RC4_KEY_LEN, rc4_buf);
-       RC4_set_key(&rc4_send_key, RC4_KEY_LEN, rc4_buf + RC4_KEY_LEN);
-}
-
-static void rc4_recv(unsigned long len, const unsigned char *indata,
-               unsigned char *outdata, __a_unused void *private_data)
-{
-       RC4(&rc4_recv_key, len, indata, outdata);
-}
-
-static void rc4_send(unsigned long len, const unsigned char *indata,
-               unsigned char *outdata, __a_unused void *private_data)
-{
-       RC4(&rc4_send_key, len, indata, outdata);
-}
-
-static int read_command(int fd, char **result)
+static int read_command(struct rc4_context *rc4c, char **result)
 {
        int ret;
        char buf[4096];
 {
        int ret;
        char buf[4096];
@@ -621,7 +606,7 @@ static int read_command(int fd, char **result)
                size_t numbytes;
                char *p;
 
                size_t numbytes;
                char *p;
 
-               ret = recv_buffer(fd, buf, sizeof(buf));
+               ret = rc4_recv_buffer(rc4c, buf, sizeof(buf));
                if (ret < 0)
                        goto out;
                if (!ret)
                if (ret < 0)
                        goto out;
                if (!ret)
@@ -693,6 +678,7 @@ __noreturn void handle_connect(int fd, const char *peername)
        char **argv = NULL;
        char *p, *command = NULL;
        size_t numbytes;
        char **argv = NULL;
        char *p, *command = NULL;
        size_t numbytes;
+       struct rc4_context rc4c = {.fd = fd};
 
        reset_signals();
        /* we need a blocking fd here as recv() might return EAGAIN otherwise. */
 
        reset_signals();
        /* we need a blocking fd here as recv() might return EAGAIN otherwise. */
@@ -747,7 +733,7 @@ __noreturn void handle_connect(int fd, const char *peername)
        /* auth successful, send 'Proceed' message */
        PARA_INFO_LOG("good auth for %s (%lu)\n", u->name, challenge_nr);
        sprintf(buf, "%s", PROCEED_MSG);
        /* auth successful, send 'Proceed' message */
        PARA_INFO_LOG("good auth for %s (%lu)\n", u->name, challenge_nr);
        sprintf(buf, "%s", PROCEED_MSG);
-       init_rc4_keys();
+       init_rc4_keys(&rc4c);
        /* Should we also encrypt the proceed message? */
        ret = para_encrypt_buffer(u->rsa, rc4_buf, 2 * RC4_KEY_LEN,
                (unsigned char *)buf + PROCEED_MSG_LEN + 1);
        /* Should we also encrypt the proceed message? */
        ret = para_encrypt_buffer(u->rsa, rc4_buf, 2 * RC4_KEY_LEN,
                (unsigned char *)buf + PROCEED_MSG_LEN + 1);
@@ -757,8 +743,7 @@ __noreturn void handle_connect(int fd, const char *peername)
        ret = send_bin_buffer(fd, buf, numbytes);
        if (ret < 0)
                goto net_err;
        ret = send_bin_buffer(fd, buf, numbytes);
        if (ret < 0)
                goto net_err;
-       enable_crypt(fd, rc4_recv, rc4_send, NULL);
-       ret = read_command(fd, &command);
+       ret = read_command(&rc4c, &command);
        if (ret == -E_COMMAND_SYNTAX)
                goto err_out;
        if (ret < 0)
        if (ret == -E_COMMAND_SYNTAX)
                goto err_out;
        if (ret < 0)
@@ -776,14 +761,14 @@ __noreturn void handle_connect(int fd, const char *peername)
        argc = split_args(command, &argv, "\n");
        PARA_NOTICE_LOG("calling com_%s() for %s@%s\n", cmd->name, u->name,
                        peername);
        argc = split_args(command, &argv, "\n");
        PARA_NOTICE_LOG("calling com_%s() for %s@%s\n", cmd->name, u->name,
                        peername);
-       ret = cmd->handler(fd, argc, argv);
+       ret = cmd->handler(&rc4c, argc, argv);
        mutex_lock(mmd_mutex);
        mmd->num_commands++;
        mutex_unlock(mmd_mutex);
        if (ret >= 0)
                goto out;
 err_out:
        mutex_lock(mmd_mutex);
        mmd->num_commands++;
        mutex_unlock(mmd_mutex);
        if (ret >= 0)
                goto out;
 err_out:
-       send_va_buffer(fd, "%s\n", para_strerror(-ret));
+       rc4_send_va_buffer(&rc4c, "%s\n", para_strerror(-ret));
 net_err:
        PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
 out:
 net_err:
        PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
 out:
diff --git a/command.h b/command.h
new file mode 100644 (file)
index 0000000..347dd81
--- /dev/null
+++ b/command.h
@@ -0,0 +1,19 @@
+/** \file command.h The structure of server and afs commands. */
+
+/**
+ * Defines one command of para_server.
+ */
+struct server_command {
+       /** The name of the command. */
+       const char *name;
+       /** Pointer to the function that handles the command. */
+       int (*handler)(struct rc4_context *, int, char * const * const);
+       /** The privileges a user must have to execute this command. */
+       unsigned int perms;
+       /** One-line description of the command. */
+       const char *description;
+       /** Summary of the command line options. */
+       const char *usage;
+       /** The long help text. */
+       const char *help;
+};
index 62ad96638c16c56b1a010f662d1affb4accf0bc1..44b4ee1856e5eee158b7d108a171abf5077712a7 100755 (executable)
@@ -26,6 +26,12 @@ read_header()
                AT:)
                        array_type="$value"
                        ;;
                AT:)
                        array_type="$value"
                        ;;
+               SI:)
+                       for i in $value; do
+                               system_includes="$system_includes
+#include <$i.h>"
+                       done
+                       ;;
                IN:)
                        for i in $value; do
                                includes="$includes
                IN:)
                        for i in $value; do
                                includes="$includes
@@ -198,7 +204,7 @@ dump_proto()
        echo '/**'
        echo " * $desc_txt"
        echo ' *'
        echo '/**'
        echo " * $desc_txt"
        echo ' *'
-       echo ' * \param fd The file descriptor to send output to.'
+       echo ' * \param rc4c The rc4 crypt context.'
        if test $line_handler -eq 0; then
                echo ' * \param argc The number of arguments.'
                echo ' * \param argv The argument vector.'
        if test $line_handler -eq 0; then
                echo ' * \param argc The number of arguments.'
                echo ' * \param argv The argument vector.'
@@ -273,6 +279,7 @@ template_loop()
 com_c_file()
 {
        echo "/** \file $output_file.c $c_file_comment */"
 com_c_file()
 {
        echo "/** \file $output_file.c $c_file_comment */"
+       echo "$system_includes"
        echo "$includes"
        echo "struct $array_type $array_name[] = {"
        while : ; do
        echo "$includes"
        echo "struct $array_type $array_name[] = {"
        while : ; do
diff --git a/crypt.c b/crypt.c
index 580974d7d74a6b97d1f4b2d6a436adc98ba7408b..679ba35dd07d59ec184942524f8a1bb0be786939 100644 (file)
--- a/crypt.c
+++ b/crypt.c
@@ -6,13 +6,18 @@
 
 /** \file crypt.c openssl-based RSA encryption/decryption routines */
 
 
 /** \file crypt.c openssl-based RSA encryption/decryption routines */
 
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/rc4.h>
+
 #include "para.h"
 #include "error.h"
 #include "string.h"
 #include "crypt.h"
 #include "para.h"
 #include "error.h"
 #include "string.h"
 #include "crypt.h"
-#include <openssl/rand.h>
-#include <openssl/err.h>
-
+#include "fd.h"
 /**
  * Fill a buffer with random content.
  *
 /**
  * Fill a buffer with random content.
  *
@@ -218,3 +223,110 @@ int para_encrypt_challenge(RSA* rsa, long unsigned challenge_nr,
        return ret;
 }
 
        return ret;
 }
 
+/**
+ * Encrypt and send a buffer.
+ *
+ * \param rc4c The rc4 crypt context.
+ * \param buf The buffer to send.
+ * \param len The size of \a buf in bytes.
+ *
+ * \return The return value of the underyling call to write_all().
+ *
+ * \sa \ref write_all(), RC4(3).
+ */
+int rc4_send_bin_buffer(struct rc4_context *rc4c, const char *buf, size_t len)
+{
+       int ret;
+       unsigned char *tmp;
+
+       assert(len);
+       tmp = para_malloc(len);
+       RC4(&rc4c->send_key, len, (const unsigned char *)buf, tmp);
+       ret = write_all(rc4c->fd, (char *)tmp, &len);
+       free(tmp);
+       return ret;
+}
+
+/**
+ * Encrypt and send a \p NULL-terminated buffer.
+ *
+ * \param rc4c The rc4 crypt context.
+ * \param buf The buffer to send.
+ *
+ * \return The return value of the underyling call to rc4_send_bin_buffer().
+ */
+int rc4_send_buffer(struct rc4_context *rc4c, const char *buf)
+{
+       return rc4_send_bin_buffer(rc4c, buf, strlen(buf));
+}
+
+/**
+ * Format, encrypt and send a buffer.
+ *
+ * \param rc4c The rc4 crypt context.
+ * \param fmt A format string.
+ *
+ * \return The return value of the underyling call to rc4_send_buffer().
+ */
+__printf_2_3 int rc4_send_va_buffer(struct rc4_context *rc4c, const char *fmt, ...)
+{
+       char *msg;
+       int ret;
+
+       PARA_VSPRINTF(fmt, msg);
+       ret = rc4_send_buffer(rc4c, msg);
+       free(msg);
+       return ret;
+}
+
+/**
+ * Receive a buffer and decrypt it.
+ *
+ * \param rc4c The rc4 crypt context.
+ * \param buf The buffer to write the decrypted data to.
+ * \param size The size of \a buf.
+ *
+ * \return The number of bytes received on success, negative on errors, zero if
+ * the peer has performed an orderly shutdown.
+ *
+ * \sa recv(2), RC4(3).
+ */
+int rc4_recv_bin_buffer(struct rc4_context *rc4c, char *buf, size_t size)
+{
+       unsigned char *tmp = para_malloc(size);
+       ssize_t ret = recv(rc4c->fd, tmp, size, 0);
+
+       if (ret > 0)
+               RC4(&rc4c->recv_key, ret, tmp, (unsigned char *)buf);
+       else if (ret < 0)
+               ret = -ERRNO_TO_PARA_ERROR(errno);
+       free(tmp);
+       return ret;
+}
+
+/**
+ * Receive a buffer, decrypt it and write terminating NULL byte.
+ *
+ * \param rc4c The rc4 crypt context.
+ * \param buf The buffer to write the decrypted data to.
+ * \param size The size of \a buf.
+ *
+ * Read at most \a size - 1 bytes from file descriptor given by \a rc4c,
+ * decrypt the received data and write a NULL byte at the end of the decrypted
+ * data.
+ *
+ * \return The return value of the underlying call to \ref
+ * rc4_recv_bin_buffer().
+ */
+int rc4_recv_buffer(struct rc4_context *rc4c, char *buf, size_t size)
+{
+       int n;
+
+       assert(size);
+       n = rc4_recv_bin_buffer(rc4c, buf, size - 1);
+       if (n >= 0)
+               buf[n] = '\0';
+       else
+               *buf = '\0';
+       return n;
+}
diff --git a/crypt.h b/crypt.h
index 1ed3985d444e3d6445cb691f6f6478a68e760edb..c430406f3c269b7d23e0d05fd95a8fe01bfe2f8a 100644 (file)
--- a/crypt.h
+++ b/crypt.h
@@ -21,6 +21,17 @@ void rsa_free(RSA *rsa);
 void get_random_bytes_or_die(unsigned char *buf, int num);
 void init_random_seed_or_die(void);
 
 void get_random_bytes_or_die(unsigned char *buf, int num);
 void init_random_seed_or_die(void);
 
+struct rc4_context {
+       int fd;
+       RC4_KEY recv_key;
+       RC4_KEY send_key;
+};
+int rc4_send_bin_buffer(struct rc4_context *rc4c, const char *buf, size_t len);
+int rc4_send_buffer(struct rc4_context *rc4c, const char *buf);
+__printf_2_3 int rc4_send_va_buffer(struct rc4_context *rc4c, const char *fmt, ...);
+int rc4_recv_bin_buffer(struct rc4_context *rcc, char *buf, size_t size);
+int rc4_recv_buffer(struct rc4_context *rcc, char *buf, size_t size);
+
 /** \cond used to distinguish between loading of private/public key */
 #define LOAD_PUBLIC_KEY 0
 #define LOAD_PRIVATE_KEY 1
 /** \cond used to distinguish between loading of private/public key */
 #define LOAD_PUBLIC_KEY 0
 #define LOAD_PRIVATE_KEY 1
index e419a723b9b856ddbc595c6130951c86d4e3155a..ccfdb0c8e129ffea3aafa15ca8d6cbdb9933e53e 100644 (file)
@@ -25,7 +25,6 @@
 #include "error.h"
 #include "string.h"
 #include "fd.h"
 #include "error.h"
 #include "string.h"
 #include "fd.h"
-#include "crypt.h"
 
 /** Grab clients that are not yet attached to a filter node. */
 struct list_head inactive_grab_client_list;
 
 /** Grab clients that are not yet attached to a filter node. */
 struct list_head inactive_grab_client_list;
diff --git a/net.c b/net.c
index 7207e528f8c1dd781858d88d8d1761782494c99f..f10afb71e31f0a1e7178972102b22c0feb01bfcc 100644 (file)
--- a/net.c
+++ b/net.c
 
 #include <dirent.h>
 #include <regex.h>
 
 #include <dirent.h>
 #include <regex.h>
+#include <openssl/rc4.h>
 
 #include "para.h"
 #include "error.h"
 
 #include "para.h"
 #include "error.h"
+#include "crypt.h"
 #include "net.h"
 #include "string.h"
 #include "fd.h"
 
 #include "net.h"
 #include "string.h"
 #include "fd.h"
 
-
-/** Information about one encrypted connection. */
-struct crypt_data {
-       /** Function used to decrypt received data. */
-       crypt_function *recv;
-       /** Function used to encrypt data to be sent. */
-       crypt_function *send;
-       /**
-        * Context-dependent data (crypt keys), passed verbatim to the above
-        * crypt functions.
-        */
-       void *private_data;
-};
-/** Array holding per fd crypt data. */
-static struct crypt_data *crypt_data_array;
-/** Current size of the crypt data array. */
-static unsigned cda_size = 0;
-
-/**
- * Activate encryption for one file descriptor.
- *
- * \param fd The file descriptor.
- * \param recv_f The function used for decrypting received data.
- * \param send_f The function used for encrypting before sending.
- * \param private_data User data supplied by the caller.
- */
-void enable_crypt(int fd, crypt_function *recv_f, crypt_function *send_f,
-       void *private_data)
-{
-       if (fd + 1 > cda_size) {
-               crypt_data_array = para_realloc(crypt_data_array,
-                       (fd + 1) * sizeof(struct crypt_data));
-               memset(crypt_data_array + cda_size, 0,
-                       (fd + 1 - cda_size) * sizeof(struct crypt_data));
-               cda_size = fd + 1;
-       }
-       crypt_data_array[fd].recv = recv_f;
-       crypt_data_array[fd].send = send_f;
-       crypt_data_array[fd].private_data = private_data;
-       PARA_INFO_LOG("rc4 encryption activated for fd %d\n", fd);
-}
-
-/**
- * Deactivate encryption for a given fd.
- *
- * \param fd The file descriptor.
- *
- * This must be called if and only if \p fd was activated via enable_crypt().
- */
-void disable_crypt(int fd)
-{
-       if (cda_size < fd + 1)
-               return;
-       crypt_data_array[fd].recv = NULL;
-       crypt_data_array[fd].send = NULL;
-       crypt_data_array[fd].private_data = NULL;
-}
-
 /**
  * Match string as a candidate IPv4 address.
  *
 /**
  * Match string as a candidate IPv4 address.
  *
@@ -487,41 +431,26 @@ struct in_addr extract_v4_addr(const struct sockaddr_storage *ss)
 }
 
 /**
 }
 
 /**
- * Encrypt and send a binary buffer.
+ * Send a binary buffer.
  *
  * \param fd The file descriptor.
  *
  * \param fd The file descriptor.
- * \param buf The buffer to be encrypted and sent.
+ * \param buf The buffer to be sent.
  * \param len The length of \a buf.
  *
  * \param len The length of \a buf.
  *
- * Check if encryption is available. If yes, encrypt the given buffer.  Send
- * out the buffer, encrypted or not, and try to resend the remaining part in
- * case of short writes.
+ * Send out the buffer and try to resend the remaining part in case of short
+ * writes.
  *
  * \return Standard.
  */
 int send_bin_buffer(int fd, const char *buf, size_t len)
 {
  *
  * \return Standard.
  */
 int send_bin_buffer(int fd, const char *buf, size_t len)
 {
-       int ret;
-       crypt_function *cf = NULL;
-
        if (!len)
                PARA_CRIT_LOG("len == 0\n");
        if (!len)
                PARA_CRIT_LOG("len == 0\n");
-       if (fd + 1 <= cda_size)
-               cf = crypt_data_array[fd].send;
-       if (cf) {
-               void *private = crypt_data_array[fd].private_data;
-               /* RC4 may write more than len to the output buffer */
-               unsigned char *outbuf = para_malloc(ROUND_UP(len, 8));
-               (*cf)(len, (unsigned char *)buf, outbuf, private);
-               ret = write_all(fd, (char *)outbuf, &len);
-               free(outbuf);
-       } else
-               ret = write_all(fd, buf, &len);
-       return ret;
+       return write_all(fd, buf, &len);
 }
 
 /**
 }
 
 /**
- * Encrypt and send null terminated buffer.
+ * Send a \p NULL-terminated buffer.
  *
  * \param fd The file descriptor.
  * \param buf The null-terminated buffer to be send.
  *
  * \param fd The file descriptor.
  * \param buf The null-terminated buffer to be send.
@@ -535,9 +464,8 @@ int send_buffer(int fd, const char *buf)
        return send_bin_buffer(fd, buf, strlen(buf));
 }
 
        return send_bin_buffer(fd, buf, strlen(buf));
 }
 
-
 /**
 /**
- * Send and encrypt a buffer given by a format string.
+ * Send a buffer given by a format string.
  *
  * \param fd The file descriptor.
  * \param fmt A format string.
  *
  * \param fd The file descriptor.
  * \param fmt A format string.
@@ -556,51 +484,37 @@ __printf_2_3 int send_va_buffer(int fd, const char *fmt, ...)
 }
 
 /**
 }
 
 /**
- * Receive and decrypt.
+ * Receive data from a file descriptor.
  *
  * \param fd The file descriptor.
  *
  * \param fd The file descriptor.
- * \param buf The buffer to write the decrypted data to.
+ * \param buf The buffer to write the data to.
  * \param size The size of \a buf.
  *
  * \param size The size of \a buf.
  *
- * Receive at most \a size bytes from file descriptor \a fd. If encryption is
- * available, decrypt the received buffer.
+ * Receive at most \a size bytes from file descriptor \a fd.
  *
  *
- * \return The number of bytes received on success, negative on errors.
+ * \return The number of bytes received on success, negative on errors, zero if
+ * the peer has performed an orderly shutdown.
  *
  *
- * \sa recv(2)
+ * \sa recv(2).
  */
 __must_check int recv_bin_buffer(int fd, char *buf, size_t size)
 {
        ssize_t n;
  */
 __must_check int recv_bin_buffer(int fd, char *buf, size_t size)
 {
        ssize_t n;
-       crypt_function *cf = NULL;
-
-       if (fd + 1 <= cda_size)
-               cf = crypt_data_array[fd].recv;
-       if (cf) {
-               unsigned char *tmp = para_malloc(size);
-               void *private = crypt_data_array[fd].private_data;
-               n = recv(fd, tmp, size, 0);
-               if (n > 0) {
-                       size_t numbytes = n;
-                       unsigned char *b = (unsigned char *)buf;
-                       (*cf)(numbytes, tmp, b, private);
-               }
-               free(tmp);
-       } else
-               n = recv(fd, buf, size, 0);
+
+       n = recv(fd, buf, size, 0);
        if (n == -1)
                return -ERRNO_TO_PARA_ERROR(errno);
        return n;
 }
 
 /**
        if (n == -1)
                return -ERRNO_TO_PARA_ERROR(errno);
        return n;
 }
 
 /**
- * Receive, decrypt and write terminating NULL byte.
+ * Receive and write terminating NULL byte.
  *
  * \param fd The file descriptor.
  *
  * \param fd The file descriptor.
- * \param buf The buffer to write the decrypted data to.
+ * \param buf The buffer to write the data to.
  * \param size The size of \a buf.
  *
  * \param size The size of \a buf.
  *
- * Read and decrypt at most \a size - 1 bytes from file descriptor \a fd and
+ * Read at most \a size - 1 bytes from file descriptor \a fd and
  * write a NULL byte at the end of the received data.
  *
  * \return The return value of the underlying call to \a recv_bin_buffer().
  * write a NULL byte at the end of the received data.
  *
  * \return The return value of the underlying call to \a recv_bin_buffer().
diff --git a/net.h b/net.h
index 11b1708f4382f831b99a027db94fc92737fa0035..b85403fdbfee4771bdec019409348e01a2f684ce 100644 (file)
--- a/net.h
+++ b/net.h
@@ -78,15 +78,13 @@ extern int para_listen(unsigned l3type, unsigned l4type, unsigned short port);
 extern char *local_name(int sockfd);
 extern char *remote_name(int sockfd);
 
 extern char *local_name(int sockfd);
 extern char *remote_name(int sockfd);
 
-/** used to crypt the communication between para_server and para_client */
-typedef void crypt_function(unsigned long len,
-       const unsigned char *indata, unsigned char *outdata, void *private_data);
-
-int send_buffer(int, const char *);
 int send_bin_buffer(int, const char *, size_t);
 int send_bin_buffer(int, const char *, size_t);
+int send_buffer(int, const char *);
 __printf_2_3 int send_va_buffer(int fd, const char *fmt, ...);
 __printf_2_3 int send_va_buffer(int fd, const char *fmt, ...);
-int recv_buffer(int fd, char *buf, size_t size);
+
 int recv_bin_buffer(int fd, char *buf, size_t size);
 int recv_bin_buffer(int fd, char *buf, size_t size);
+int recv_buffer(int fd, char *buf, size_t size);
+
 int para_accept(int, void *addr, socklen_t size);
 int create_local_socket(const char *name, struct sockaddr_un *unix_addr,
        mode_t mode);
 int para_accept(int, void *addr, socklen_t size);
 int create_local_socket(const char *name, struct sockaddr_un *unix_addr,
        mode_t mode);
@@ -94,6 +92,3 @@ int create_remote_socket(const char *name);
 int recv_cred_buffer(int, char *, size_t);
 ssize_t send_cred_buffer(int, char*);
 int recv_pattern(int fd, const char *pattern, size_t bufsize);
 int recv_cred_buffer(int, char *, size_t);
 ssize_t send_cred_buffer(int, char*);
 int recv_pattern(int fd, const char *pattern, size_t bufsize);
-void enable_crypt(int fd, crypt_function *recv_f, crypt_function *send_f,
-       void *private_data);
-void disable_crypt(int fd);
index 6c3373d330412448e96fef0feaf00d652ec525c3..8c61732592269301e22bd4ecfffc0c5cf5571ceb 100644 (file)
--- a/server.c
+++ b/server.c
 #include <signal.h>
 #include <dirent.h>
 #include <sys/time.h>
 #include <signal.h>
 #include <dirent.h>
 #include <sys/time.h>
+#include <openssl/rc4.h>
 
 #include "para.h"
 #include "error.h"
 
 #include "para.h"
 #include "error.h"
+#include "crypt.h"
 #include "server.cmdline.h"
 #include "afh.h"
 #include "string.h"
 #include "server.cmdline.h"
 #include "afh.h"
 #include "string.h"
index a6b512fe0fab2145af31fb2c4c7b8e5479641cc2..d574d2c89c0be38b42902bd8108c40472a79424c 100644 (file)
@@ -3,7 +3,8 @@ SF: command.c
 HC: prototypes for the server command handlers
 CC: array of server commands
 AT: server_command
 HC: prototypes for the server command handlers
 CC: array of server commands
 AT: server_command
-IN: para error string afh afs server list user_list
+SI: openssl/rc4
+IN: para error crypt command string afh afs server list user_list
 SN: list of server commands
 ---
 N: ff
 SN: list of server commands
 ---
 N: ff
index cf17c0ef06c362bb046f9ae538dc44f297497222..a814aff07d0285aa666872b5158ea3f278b41faf 100644 (file)
--- a/server.h
+++ b/server.h
 /** The maximum length of the host component in an URL */
 #define MAX_HOSTLEN    256
 
 /** The maximum length of the host component in an URL */
 #define MAX_HOSTLEN    256
 
-/**
- * Defines one command of para_server.
- */
-struct server_command {
-       /** The name of the command. */
-       const char *name;
-       /** Pointer to the function that handles the command. */
-       int (*handler)(int, int, char * const * const);
-       /** The privileges a user must have to execute this command. */
-       unsigned int perms;
-       /** One-line description of the command. */
-       const char *description;
-       /** Summary of the command line options. */
-       const char *usage;
-       /** The long help text. */
-       const char *help;
-};
 
 /** Holds the arguments for the para_server's sender command. */
 struct sender_command_data{
 
 /** Holds the arguments for the para_server's sender command. */
 struct sender_command_data{
index 63bfdfc259878402f3f70c2a5c62be5d5fa96ce9..840802b33ba811816e3459284cd471644b134bb8 100644 (file)
@@ -8,9 +8,11 @@
 
 #include <sys/types.h>
 #include <dirent.h>
 
 #include <sys/types.h>
 #include <dirent.h>
+#include <openssl/rc4.h>
 
 #include "para.h"
 #include "error.h"
 
 #include "para.h"
 #include "error.h"
+#include "crypt.h"
 #include "fd.h"
 #include "string.h"
 #include "list.h"
 #include "fd.h"
 #include "string.h"
 #include "list.h"
index 5baceacc1c9b98f339defec5e05049862c0be9b8..e95747c4fb192c29136fc5e736761dd847192d58 100644 (file)
@@ -6,8 +6,6 @@
 
 /** \file user_list.h exported functions from user_list.c */
 
 
 /** \file user_list.h exported functions from user_list.c */
 
-#include "crypt.h"
-
 /**
  * permission flags that can be set individually for any server command
  *
 /**
  * permission flags that can be set individually for any server command
  *