filter: Use lsu_merge_config_file_options().
[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 }