move LOAD_PUBLIC_KEY and LOAD_PRIVATE_KEY to crypt.h
[paraslash.git] / server.c
index c7e681264cddcd3fe7223b2492485be97869f4cc..7d7953215b7a8a0c7a52bc1c0c39d3eb432d54ef 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;
@@ -57,7 +58,8 @@ struct misc_meta_data *mmd;
  * senders.
 */
 struct server_args_info conf;
-char *user_list = NULL;
+char *user_list_file = 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 *);
@@ -221,11 +223,11 @@ static void parse_config(int override)
                cf = conf.config_file_arg;
        else
                cf = make_message("%s/.paraslash/server.conf", home);
-       free(user_list);
+       free(user_list_file);
        if (!conf.user_list_given)
-               user_list = make_message("%s/.paraslash/server.users", home);
+               user_list_file = make_message("%s/.paraslash/server.users", home);
        else
-               user_list = para_strdup(conf.user_list_arg);
+               user_list_file = para_strdup(conf.user_list_arg);
        ret = stat(cf, &statbuf);
        if (ret && conf.config_file_given) {
                ret = -1;
@@ -251,8 +253,8 @@ out:
        free(home);
        if (ret > 0)
                return;
-       free(user_list);
-       user_list = NULL;
+       free(user_list_file);
+       user_list_file = NULL;
        exit(EXIT_FAILURE);
 }
 
@@ -274,6 +276,110 @@ 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_file, "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, LOAD_PUBLIC_KEY);
+               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();
+}
+
+/**
+ * lookup user in user_list.
+ *
+ * \param user: must initially contain the name of the user and is filled
+ * in by this function on success.
+ *
+ * \return 1 on success and < 0 on errors.
+ */
+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 -E_BAD_USER;
+}
+
 static void init_selector(void)
 {
        int i, ret;
@@ -302,11 +408,18 @@ random:
 
 static unsigned init_network(void)
 {
-       int sockfd = init_tcp_socket(conf.port_arg);
+       int fd, ret = init_tcp_socket(conf.port_arg);
 
-       if (sockfd < 0)
-               exit(EXIT_FAILURE);
-       return sockfd;
+       if (ret < 0)
+               goto err;
+       fd = ret;
+       ret = mark_fd_nonblock(fd);
+       if (ret < 0)
+               goto err;
+       return fd;
+err:
+       PARA_EMERG_LOG("%s\n", PARA_STRERROR(-ret));
+       exit(EXIT_FAILURE);
 }
 
 static void init_random_seed(void)
@@ -346,6 +459,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();