preparations for user list in memory
authorAndre <maan@meins.(none)>
Wed, 1 Nov 2006 11:21:30 +0000 (12:21 +0100)
committerAndre <maan@meins.(none)>
Wed, 1 Nov 2006 11:21:30 +0000 (12:21 +0100)
The idea is to not lookup the user file/rsa key for
each connection/each buffer to be sent, but to load
it only once on startup.

This patch

* renames list_add to para_list_add, as list_add is
an exported symbol of mysql.h

* makes get_key of crypt.c non-static and renames it to get_rsa_key.
It is used from server.c to load the rsa key.

* introduces struct _user, the new struct to hold user info. It is
meant to replace the current struct user soon.

* Introdoces init_user_list(), populate_user_list() and _get_user()
in server.c. The latter is meant to replace get_user() of command.c

The new functions are not used yet.

12 files changed:
close_on_fork.c
crypt.c
crypt.h
dccp_send.c
grab_client.c
http_send.c
list.h
ortp_send.c
sched.c
server.c
server.h
stat.c

index 74b4194..722e750 100644 (file)
@@ -50,7 +50,7 @@ void add_close_on_fork_list(int fd)
                initialized = 1;
        }
        cof->fd = fd;
-       list_add(&cof->node, &close_on_fork_list);
+       para_list_add(&cof->node, &close_on_fork_list);
 }
 
 
diff --git a/crypt.c b/crypt.c
index 653b1a2..c2b50a7 100644 (file)
--- a/crypt.c
+++ b/crypt.c
@@ -46,7 +46,8 @@ static EVP_PKEY *load_key(const char *file, int private)
        return pkey;
 }
 
-static int get_key(char *key_file, RSA **rsa, int private)
+
+int get_rsa_key(char *key_file, RSA **rsa, int private)
 {
        EVP_PKEY *key = load_key(key_file, private);
 
@@ -77,7 +78,7 @@ int para_decrypt_buffer(char *key_file, unsigned char *outbuf, unsigned char *in
                        int rsa_inlen)
 {
        RSA *rsa;
-       int ret = get_key(key_file, &rsa, LOAD_PRIVATE_KEY);
+       int ret = get_rsa_key(key_file, &rsa, LOAD_PRIVATE_KEY);
 
        if (ret < 0)
                return ret;
@@ -128,7 +129,7 @@ int para_encrypt_buffer(char *key_file, unsigned char *inbuf,
                const unsigned len, unsigned char *outbuf)
 {
        RSA *rsa;
-       int ret = get_key(key_file, &rsa, LOAD_PUBLIC_KEY);
+       int ret = get_rsa_key(key_file, &rsa, LOAD_PUBLIC_KEY);
 
        if (ret < 0)
                return ret;
diff --git a/crypt.h b/crypt.h
index 82ed4f9..d658f89 100644 (file)
--- a/crypt.h
+++ b/crypt.h
@@ -1,3 +1,4 @@
+#include <openssl/pem.h>
 /** \file crypt.h prototypes for the RSA crypt functions */
 int para_decrypt_challenge(char *key_file, long unsigned *challenge_nr,
        unsigned char *buf, int rsa_inlen);
@@ -7,3 +8,4 @@ int para_encrypt_buffer(char *key_file, unsigned char *inbuf, const unsigned len
        unsigned char *outbuf);
 int para_decrypt_buffer(char *key_file, unsigned char *outbuf, unsigned char *inbuf,
        int rsa_inlen);
+int get_rsa_key(char *key_file, RSA **rsa, int private);
index bb46678..273961f 100644 (file)
@@ -76,7 +76,7 @@ static void dccp_post_select(fd_set *rfds, __a_unused fd_set *wfds)
        }
        PARA_NOTICE_LOG("connection from %s\n", inet_ntoa(dc->addr.sin_addr));
        dc->fd = ret;
-       list_add(&dc->node, &clients);
+       para_list_add(&dc->node, &clients);
        add_close_on_fork_list(dc->fd);
        mark_fd_nonblock(dc->fd);
 }
index 70b95f4..50594f2 100644 (file)
@@ -33,6 +33,7 @@
 #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;
@@ -123,7 +124,7 @@ static void add_inactive_gc(struct grab_client *gc)
 {
        PARA_INFO_LOG("adding grab client %p (fd %d) to inactive list\n",
                gc, gc->fd);
-       list_add(&gc->node, &inactive_grab_client_list);
+       para_list_add(&gc->node, &inactive_grab_client_list);
 }
 
 static void gc_free(struct grab_client *gc)
@@ -164,7 +165,7 @@ void activate_grab_client(struct grab_client *gc, struct filter_node *fn)
 {
        PARA_INFO_LOG("activating %p (fd %d, filter node: %p)\n", gc, gc->fd, fn);
        list_del(&gc->node);
-       list_add(&gc->fcb.node, &fn->callbacks);
+       para_list_add(&gc->fcb.node, &fn->callbacks);
 }
 
 /**
index 1d970a5..f06a5ac 100644 (file)
@@ -323,7 +323,7 @@ static void http_post_select(fd_set *rfds, fd_set *wfds)
        PARA_INFO_LOG("accepted client #%d: %s (fd %d)\n", numclients,
                CLIENT_ADDR(hc), hc->fd);
        numclients++;
-       list_add(&hc->node, &clients);
+       para_list_add(&hc->node, &clients);
        add_close_on_fork_list(hc->fd);
        mark_fd_nonblock(hc->fd);
        return;
@@ -432,7 +432,7 @@ static void add_perm_list_entry(struct sender_command_data *scd)
        ai->netmask = scd->netmask;
        PARA_INFO_LOG("adding %s/%i to access list\n", inet_ntoa(ai->addr),
                ai->netmask);
-       list_add(&ai->node, &access_perm_list);
+       para_list_add(&ai->node, &access_perm_list);
 }
 
 static int http_com_deny(struct sender_command_data *scd)
diff --git a/list.h b/list.h
index c85f50c..486b917 100644 (file)
--- a/list.h
+++ b/list.h
@@ -56,14 +56,15 @@ static inline void __list_add(struct list_head *new,
 }
 
 /**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
+ * add a new entry
+ *
+ * \param new: new entry to be added
+ * \param head: list head to add it after
  *
  * Insert a new entry after the specified head.
  * This is good for implementing stacks.
  */
-static inline void list_add(struct list_head *new, struct list_head *head)
+static inline void para_list_add(struct list_head *new, struct list_head *head)
 {
        __list_add(new, head, head->next);
 }
@@ -115,7 +116,7 @@ static inline void list_del(struct list_head *entry)
 static inline void list_move(struct list_head *list, struct list_head *head)
 {
         __list_del(list->prev, list->next);
-        list_add(list, head);
+        para_list_add(list, head);
 }
 
 /**
index 15b97eb..4dd19d7 100644 (file)
@@ -249,7 +249,7 @@ static void ortp_add_target(int port, struct in_addr *addr)
        ot->addr = *addr;
        PARA_INFO_LOG("adding to target list (%s:%d)\n",
                TARGET_ADDR(ot), ot->port);
-       list_add(&ot->node, &targets);
+       para_list_add(&ot->node, &targets);
 }
 
 static int ortp_com_add(struct sender_command_data *scd)
diff --git a/sched.c b/sched.c
index c2a0e64..e122903 100644 (file)
--- a/sched.c
+++ b/sched.c
@@ -125,11 +125,11 @@ void register_task(struct task *t)
        PARA_INFO_LOG("registering %s (%p)\n", t->status, t);
        if (t->pre_select) {
                PARA_DEBUG_LOG("pre_select: %p\n", &t->pre_select);
-               list_add(&t->pre_select_node, &pre_select_list);
+               para_list_add(&t->pre_select_node, &pre_select_list);
        }
        if (t->post_select) {
                PARA_DEBUG_LOG("post_select: %p\n", &t->pre_select);
-               list_add(&t->post_select_node, &post_select_list);
+               para_list_add(&t->post_select_node, &post_select_list);
        }
 }
 
index 9688c6c..2b59714 100644 (file)
--- a/server.c
+++ b/server.c
@@ -42,6 +42,7 @@
 #include "string.h"
 #include "ipc.h"
 #include "fd.h"
+#include "crypt.h"
 
 /** define the array of error lists needed by para_server */
 INIT_SERVER_ERRLISTS;
@@ -58,6 +59,7 @@ struct misc_meta_data *mmd;
 */
 struct server_args_info conf;
 char *user_list = NULL;
+struct list_head _user_list;
 extern void dccp_send_init(struct sender *);
 extern void http_send_init(struct sender *);
 extern void ortp_send_init(struct sender *);
@@ -274,6 +276,102 @@ static void setup_signal_handling(void)
        }
 }
 
+/*
+ * lookup user in user_list file. Fills in a user struct containing
+ * filename of the user's public key as well as the permissions of that user.
+ * Returns 1 on success, 0 if user does not exist and < 0 on errors.
+ */
+static void populate_user_list(void) {
+       FILE *file_ptr = NULL;
+       char *char_ptr;
+       char line[MAXLINE];
+       /* keyword, user, key, perms */
+       char w[MAXLINE], n[MAXLINE], k[MAXLINE], p[MAXLINE], tmp[4][MAXLINE];
+       int num, ret;
+
+       file_ptr = fopen(user_list, "r");
+       ret = -E_USERLIST;
+       if (!file_ptr)
+               goto out;
+       for (;;) {
+               struct _user *u;
+               ret = para_fgets(line, MAXLINE, file_ptr);
+               if (ret < 0)
+                       PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
+               if (ret <= 0)
+                       break;
+               if (sscanf(line,"%200s %200s %200s %200s", w, n, k, p) < 3)
+                       continue;
+               if (strcmp(w, "user"))
+                       continue;
+               PARA_DEBUG_LOG("found entry for %s\n", n);
+               u = para_malloc(sizeof(struct _user));
+               u->name = para_strdup(n);
+               u->rsa = para_malloc(sizeof(RSA));
+               ret = get_rsa_key(k, &u->rsa, 0 /* public */);
+               if (ret < 0)
+                       break;
+               u->perms = 0;
+               char_ptr = p;
+               num = sscanf(char_ptr, "%200[A-Z_],%200[A-Z_],%200[A-Z_],%200[A-Z_]",
+                       tmp[0], tmp[1], tmp[2], tmp[3]);
+               PARA_DEBUG_LOG("found %i perm entries\n", num);
+               u->perms = 0;
+               while (num > 0) {
+                       num--;
+                       if (!strcmp(tmp[num], "AFS_READ"))
+                               u->perms |= AFS_READ;
+                       else if (!strcmp(tmp[num], "AFS_WRITE"))
+                               u->perms |= AFS_WRITE;
+                       else if (!strcmp(tmp[num], "DB_READ"))
+                               u->perms |= DB_READ;
+                       else if (!strcmp(tmp[num], "DB_WRITE"))
+                               u->perms |= DB_WRITE;
+                       else /* unknown permission */
+                               PARA_WARNING_LOG("unknown permission: %s\n",
+                                       tmp[num]);
+               }
+               para_list_add(&u->node, &_user_list);
+       }
+out:
+       if (file_ptr)
+               fclose(file_ptr);
+       if (ret >= 0)
+               return;
+       PARA_EMERG_LOG("%s\n", PARA_STRERROR(-ret));
+       exit(EXIT_FAILURE);
+}
+
+static void init_user_list(void)
+{
+       struct _user *u, *tmp;
+       static int initialized;
+
+       if (initialized) {
+               list_for_each_entry_safe(u, tmp, &_user_list, node) {
+                       list_del(&u->node);
+                       free(u->name);
+                       free(u->rsa);
+                       free(u);
+               }
+       } else
+               INIT_LIST_HEAD(&_user_list);
+       initialized = 1;
+       populate_user_list();
+}
+
+int _get_user(struct _user *user)
+{
+       struct _user *u;
+       list_for_each_entry(u, &_user_list, node) {
+               if (strcmp(u->name, user->name))
+                       continue;
+               *user = *u;
+               return 1;
+       }
+       return 0;
+}
+
 static void init_selector(void)
 {
        int i, ret;
@@ -353,6 +451,7 @@ static unsigned do_inits(int argc, char **argv)
        log_welcome("para_server", conf.loglevel_arg);
        shm_init(); /* init mmd struct */
        server_uptime(UPTIME_SET); /* reset server uptime */
+       init_user_list();
        /* become daemon */
        if (conf.daemon_given)
                daemon_init();
index 9d18561..0077338 100644 (file)
--- a/server.h
+++ b/server.h
@@ -19,7 +19,8 @@
 /** \file server.h common server data structures */
 
 #include "para.h"
-
+#include "list.h"
+#include <openssl/pem.h>
 
 /** size of the selector_info and audio_file info strings of struct misc_meta_data */
 #define MMD_INFO_SIZE 16384
@@ -38,11 +39,22 @@ enum {DB_READ = 1, DB_WRITE = 2, AFS_READ = 4, AFS_WRITE = 8};
  * data needed to authenticate the user
  */
 struct user{
-/** the username */
+       /** the username */
        char name[MAXLINE];
-/** full path to the public RSA key */
+       /** full path to the public RSA key */
        char pubkey_file[_POSIX_PATH_MAX];
-/** the privileges of this user */
+       /** the privileges of this user */
+       unsigned int perms;
+};
+
+struct _user {
+       /** the position of this user in the list of users */
+       struct list_head node;
+       /** the username */
+       char *name;
+       /**  the public RSA key */
+       RSA *rsa;
+       /** the privileges that this user has */
        unsigned int perms;
 };
 
@@ -152,5 +164,6 @@ struct misc_meta_data{
 extern struct server_args_info conf;
 
 int handle_connect(int fd, struct sockaddr_in *addr);
+int _get_user(struct _user *user);
 void mmd_unlock(void);
 void mmd_lock(void);
diff --git a/stat.c b/stat.c
index 8220fd2..caf432d 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -123,7 +123,7 @@ int stat_client_add(int fd, long unsigned mask)
        new_client = para_malloc(sizeof(struct stat_client));
        new_client->fd = fd;
        new_client->item_mask = mask;
-       list_add(&new_client->node, &client_list);
+       para_list_add(&new_client->node, &client_list);
        dump_stat_client_list();
        num_clients++;
        return 1;