ogg_afh_common.c: Add missing whitespace to log message.
[paraslash.git] / user_list.c
1 /* Copyright (C) 2006 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
2
3 /** \file user_list.c User handling for para_server. */
4
5 #include <regex.h>
6 #include <sys/types.h>
7
8 #include "para.h"
9 #include "error.h"
10 #include "crypt.h"
11 #include "fd.h"
12 #include "string.h"
13 #include "list.h"
14 #include "user_list.h"
15
16 static struct list_head user_list;
17
18 /*
19  * Fill the list of users known to para_server.
20  *
21  * Populates a linked list of all users in \a user_list_file.  Returns on
22  * success, calls exit() on errors.
23  */
24 static void populate_user_list(char *user_list_file)
25 {
26         int ret = -E_USERLIST;
27         FILE *file_ptr = fopen(user_list_file, "r");
28
29         if (!file_ptr)
30                 goto err;
31         for (;;) {
32                 int num;
33                 char line[255];
34                 /* keyword, name, key, perms */
35                 char w[255], n[255], k[255], p[255], tmp[4][255];
36                 struct user *u;
37                 struct asymmetric_key *pubkey;
38
39                 ret = para_fgets(line, sizeof(line), file_ptr);
40                 if (ret <= 0)
41                         break;
42                 if (sscanf(line,"%200s %200s %200s %200s", w, n, k, p) < 3)
43                         continue;
44                 if (strcmp(w, "user"))
45                         continue;
46                 PARA_DEBUG_LOG("found entry for user %s\n", n);
47                 ret = get_public_key(k, &pubkey);
48                 if (ret < 0) {
49                         PARA_NOTICE_LOG("skipping entry for user %s: %s\n", n,
50                                 para_strerror(-ret));
51                         continue;
52                 }
53                 /*
54                  * In order to encrypt len := CHALLENGE_SIZE + 2 * SESSION_KEY_LEN
55                  * bytes using RSA_public_encrypt() with EME-OAEP padding mode,
56                  * RSA_size(rsa) must be greater than len + 41. So ignore keys
57                  * which are too short. For details see RSA_public_encrypt(3).
58                  */
59                 if (ret <= CHALLENGE_SIZE + 2 * SESSION_KEY_LEN + 41) {
60                         PARA_WARNING_LOG("public key %s too short (%d)\n",
61                                 k, ret);
62                         free_public_key(pubkey);
63                         continue;
64                 }
65                 u = para_malloc(sizeof(*u));
66                 u->name = para_strdup(n);
67                 u->pubkey = pubkey;
68                 u->perms = 0;
69                 num = sscanf(p, "%200[A-Z_],%200[A-Z_],%200[A-Z_],%200[A-Z_]",
70                         tmp[0], tmp[1], tmp[2], tmp[3]);
71                 PARA_DEBUG_LOG("found %i perm entries\n", num);
72                 while (num > 0) {
73                         num--;
74                         if (!strcmp(tmp[num], "VSS_READ"))
75                                 u->perms |= VSS_READ;
76                         else if (!strcmp(tmp[num], "VSS_WRITE"))
77                                 u->perms |= VSS_WRITE;
78                         else if (!strcmp(tmp[num], "AFS_READ"))
79                                 u->perms |= AFS_READ;
80                         else if (!strcmp(tmp[num], "AFS_WRITE"))
81                                 u->perms |= AFS_WRITE;
82                         else /* unknown permission */
83                                 PARA_WARNING_LOG("ignoring unknown permission: %s\n",
84                                         tmp[num]);
85                 }
86                 para_list_add(&u->node, &user_list);
87         }
88         fclose(file_ptr);
89         if (ret >= 0)
90                 return;
91 err:
92         PARA_EMERG_LOG("%s\n", para_strerror(-ret));
93         exit(EXIT_FAILURE);
94 }
95
96 /**
97  * Initialize the list of users allowed to connect to para_server.
98  *
99  * \param user_list_file The file containing access information.
100  *
101  * If this function is called for the second time, the contents of the
102  * previous call are discarded, i.e. the user list is reloaded.
103  */
104 void init_user_list(char *user_list_file)
105 {
106         struct user *u, *tmp;
107         static int initialized;
108
109         if (initialized) {
110                 list_for_each_entry_safe(u, tmp, &user_list, node) {
111                         list_del(&u->node);
112                         free(u->name);
113                         free_public_key(u->pubkey);
114                         free(u);
115                 }
116         } else
117                 INIT_LIST_HEAD(&user_list);
118         initialized = 1;
119         populate_user_list(user_list_file);
120 }
121
122 /**
123  * Lookup a user in the user list.
124  *
125  * \param name The name of the user.
126  *
127  * \return A pointer to the corresponding user struct if the user was found, \p
128  * NULL otherwise.
129  */
130 struct user *lookup_user(const char *name)
131 {
132         struct user *u;
133         list_for_each_entry(u, &user_list, node) {
134                 if (strcmp(u->name, name))
135                         continue;
136                 return u;
137         }
138         return NULL;
139 }