From f269333700038603703ec79c909d514bee731faf Mon Sep 17 00:00:00 2001 From: Andre Date: Wed, 1 Nov 2006 12:21:30 +0100 Subject: [PATCH] preparations for user list in memory 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. --- close_on_fork.c | 2 +- crypt.c | 7 ++-- crypt.h | 2 + dccp_send.c | 2 +- grab_client.c | 5 ++- http_send.c | 4 +- list.h | 11 +++--- ortp_send.c | 2 +- sched.c | 4 +- server.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ server.h | 21 +++++++++-- stat.c | 2 +- 12 files changed, 139 insertions(+), 22 deletions(-) diff --git a/close_on_fork.c b/close_on_fork.c index 74b41948..722e7509 100644 --- a/close_on_fork.c +++ b/close_on_fork.c @@ -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 653b1a24..c2b50a7e 100644 --- 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 82ed4f9d..d658f89b 100644 --- a/crypt.h +++ b/crypt.h @@ -1,3 +1,4 @@ +#include /** \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); diff --git a/dccp_send.c b/dccp_send.c index bb46678e..273961fc 100644 --- a/dccp_send.c +++ b/dccp_send.c @@ -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); } diff --git a/grab_client.c b/grab_client.c index 70b95f4f..50594f23 100644 --- a/grab_client.c +++ b/grab_client.c @@ -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); } /** diff --git a/http_send.c b/http_send.c index 1d970a5d..f06a5ac2 100644 --- a/http_send.c +++ b/http_send.c @@ -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 c85f50c7..486b9170 100644 --- 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); } /** diff --git a/ortp_send.c b/ortp_send.c index 15b97eb1..4dd19d7d 100644 --- a/ortp_send.c +++ b/ortp_send.c @@ -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 c2a0e64b..e122903e 100644 --- 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); } } diff --git a/server.c b/server.c index 9688c6cc..2b597147 100644 --- 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(); diff --git a/server.h b/server.h index 9d18561e..0077338b 100644 --- a/server.h +++ b/server.h @@ -19,7 +19,8 @@ /** \file server.h common server data structures */ #include "para.h" - +#include "list.h" +#include /** 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 8220fd27..caf432d9 100644 --- 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; -- 2.39.5