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