1 /*
2 * uhub - A tiny ADC p2p connection hub
3 * Copyright (C) 2007-2014, Jan Vidar Krey
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #include "plugin_api/handle.h"
21 #include "util/memory.h"
22 #include "util/list.h"
23 #include "util/misc.h"
24 #include "util/log.h"
25 #include "util/config_token.h"
26
set_error_message(struct plugin_handle * plugin,const char * msg)27 static void set_error_message(struct plugin_handle* plugin, const char* msg)
28 {
29 plugin->error_msg = msg;
30 }
31
32 struct acl_data
33 {
34 struct linked_list* users;
35 char* file;
36 int readonly;
37 int exclusive;
38 };
39
insert_user(struct linked_list * users,const char * nick,const char * pass,enum auth_credentials cred)40 static void insert_user(struct linked_list* users, const char* nick, const char* pass, enum auth_credentials cred)
41 {
42 struct auth_info* data = (struct auth_info*) hub_malloc_zero(sizeof(struct auth_info));
43 strncpy(data->nickname, nick, MAX_NICK_LEN);
44 strncpy(data->password, pass, MAX_PASS_LEN);
45 data->credentials = cred;
46 list_append(users, data);
47 }
48
free_acl(struct acl_data * data)49 static void free_acl(struct acl_data* data)
50 {
51 if (!data)
52 return;
53
54 if (data->users)
55 {
56 list_clear(data->users, hub_free);
57 list_destroy(data->users);
58 }
59 hub_free(data->file);
60 hub_free(data);
61 }
62
parse_config(const char * line)63 static struct acl_data* parse_config(const char* line)
64 {
65 struct acl_data* data = (struct acl_data*) hub_malloc_zero(sizeof(struct acl_data));
66 struct cfg_tokens* tokens = cfg_tokenize(line);
67 char* token = cfg_token_get_first(tokens);
68
69 if (!data)
70 return 0;
71
72 // set defaults
73 data->readonly = 1;
74 data->exclusive = 0;
75 data->users = list_create();
76
77 while (token)
78 {
79 char* split = strchr(token, '=');
80 size_t len = strlen(token);
81 size_t key = split ? (split - token) : len;
82 if (key == 4 && strncmp(token, "file", 4) == 0)
83 {
84 if (data->file)
85 hub_free(data->file);
86 data->file = strdup(split + 1);
87 }
88 else if (key == 8 && strncmp(token, "readonly", 8) == 0)
89 {
90 if (!string_to_boolean(split + 1, &data->readonly))
91 data->readonly = 1;
92 }
93 else if (key == 9 && strncmp(token, "exclusive", 9) == 0)
94 {
95 if (!string_to_boolean(split + 1, &data->exclusive))
96 data->exclusive = 1;
97 }
98 else
99 {
100 cfg_tokens_free(tokens);
101 free_acl(data);
102 return 0;
103 }
104
105 token = cfg_token_get_next(tokens);
106 }
107
108 cfg_tokens_free(tokens);
109 return data;
110 }
111
parse_line(char * line,int line_count,void * ptr_data)112 static int parse_line(char* line, int line_count, void* ptr_data)
113 {
114 struct linked_list* users = (struct linked_list*) ptr_data;
115 struct cfg_tokens* tokens = cfg_tokenize(line);
116 enum auth_credentials cred;
117 char* credential;
118 char* username;
119 char* password;
120
121 if (cfg_token_count(tokens) == 0)
122 {
123 cfg_tokens_free(tokens);
124 return 0;
125 }
126
127 if (cfg_token_count(tokens) < 2)
128 {
129 cfg_tokens_free(tokens);
130 return -1;
131 }
132
133 credential = cfg_token_get_first(tokens);
134 username = cfg_token_get_next(tokens);
135 password = cfg_token_get_next(tokens);
136
137 if (!auth_string_to_cred(credential, &cred))
138 {
139 cfg_tokens_free(tokens);
140 return -1;
141 }
142
143 insert_user(users, username, password, cred);
144 cfg_tokens_free(tokens);
145 return 0;
146 }
147
load_acl(const char * config,struct plugin_handle * handle)148 static struct acl_data* load_acl(const char* config, struct plugin_handle* handle)
149 {
150
151 struct acl_data* data = parse_config(config);
152
153 if (!data)
154 return 0;
155
156 if (!data->file || !*data->file)
157 {
158 free_acl(data); data = 0;
159 set_error_message(handle, "No configuration file given, missing \"file=<filename>\" configuration option.");
160 return 0;
161 }
162
163 if (file_read_lines(data->file, data->users, &parse_line) == -1)
164 {
165 fprintf(stderr, "Unable to load %s\n", data->file);
166 set_error_message(handle, "Unable to load file");
167 }
168
169 return data;
170 }
171
unload_acl(struct acl_data * data)172 static void unload_acl(struct acl_data* data)
173 {
174 free_acl(data);
175 }
176
get_user(struct plugin_handle * plugin,const char * nickname,struct auth_info * data)177 static plugin_st get_user(struct plugin_handle* plugin, const char* nickname, struct auth_info* data)
178 {
179 struct acl_data* acl = (struct acl_data*) plugin->ptr;
180 struct auth_info* info;
181 LIST_FOREACH(struct auth_info*, info, acl->users,
182 {
183 if (strcasecmp((char*)info->nickname, nickname) == 0)
184 {
185 memcpy(data, info, sizeof(struct auth_info));
186 return st_allow;
187 }
188 });
189 if (acl->exclusive)
190 return st_deny;
191 return st_default;
192 }
193
register_user(struct plugin_handle * plugin,struct auth_info * user)194 static plugin_st register_user(struct plugin_handle* plugin, struct auth_info* user)
195 {
196 struct acl_data* acl = (struct acl_data*) plugin->ptr;
197 if (acl->exclusive)
198 return st_deny;
199 return st_default;
200 }
201
update_user(struct plugin_handle * plugin,struct auth_info * user)202 static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* user)
203 {
204 struct acl_data* acl = (struct acl_data*) plugin->ptr;
205 if (acl->exclusive)
206 return st_deny;
207 return st_default;
208 }
209
delete_user(struct plugin_handle * plugin,struct auth_info * user)210 static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* user)
211 {
212 struct acl_data* acl = (struct acl_data*) plugin->ptr;
213 if (acl->exclusive)
214 return st_deny;
215 return st_default;
216 }
217
plugin_register(struct plugin_handle * plugin,const char * config)218 PLUGIN_API int plugin_register(struct plugin_handle* plugin, const char* config)
219 {
220 PLUGIN_INITIALIZE(plugin, "File authentication plugin", "0.1", "Authenticate users based on a read-only text file.");
221
222 // Authentication actions.
223 plugin->funcs.auth_get_user = get_user;
224 plugin->funcs.auth_register_user = register_user;
225 plugin->funcs.auth_update_user = update_user;
226 plugin->funcs.auth_delete_user = delete_user;
227
228 plugin->ptr = load_acl(config, plugin);
229 if (plugin->ptr)
230 return 0;
231 return -1;
232 }
233
plugin_unregister(struct plugin_handle * plugin)234 PLUGIN_API int plugin_unregister(struct plugin_handle* plugin)
235 {
236 set_error_message(plugin, 0);
237 unload_acl(plugin->ptr);
238 return 0;
239 }
240
241