2010-07-08 12:24:40 +00:00
|
|
|
/*
|
|
|
|
* uhub - A tiny ADC p2p connection hub
|
2011-01-06 11:25:44 +00:00
|
|
|
* Copyright (C) 2011, Jan Vidar Krey
|
2010-07-08 12:24:40 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "plugin_api/handle.h"
|
|
|
|
#include "util/memory.h"
|
|
|
|
#include "util/list.h"
|
|
|
|
#include "util/ipcalc.h"
|
2010-07-10 01:36:47 +00:00
|
|
|
#include "util/misc.h"
|
|
|
|
#include "util/log.h"
|
|
|
|
#include "util/config_token.h"
|
2010-07-08 12:24:40 +00:00
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
static void set_error_message(struct plugin_handle* plugin, const char* msg)
|
2010-07-29 06:41:26 +00:00
|
|
|
{
|
|
|
|
plugin->error_msg = msg;
|
|
|
|
}
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
struct acl_data
|
2010-07-08 12:24:40 +00:00
|
|
|
{
|
2010-07-10 01:36:47 +00:00
|
|
|
struct linked_list* users;
|
2010-07-29 06:43:22 +00:00
|
|
|
char* file;
|
|
|
|
int readonly;
|
|
|
|
int exclusive;
|
2010-07-08 12:24:40 +00:00
|
|
|
};
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
static void insert_user(struct linked_list* users, const char* nick, const char* pass, enum auth_credentials cred)
|
2010-07-08 12:24:40 +00:00
|
|
|
{
|
2010-07-10 01:36:47 +00:00
|
|
|
struct auth_info* data = (struct auth_info*) hub_malloc_zero(sizeof(struct auth_info));
|
|
|
|
strncpy(data->nickname, nick, MAX_NICK_LEN);
|
|
|
|
strncpy(data->password, pass, MAX_PASS_LEN);
|
|
|
|
data->credentials = cred;
|
|
|
|
list_append(users, data);
|
|
|
|
}
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
static void free_acl(struct acl_data* data)
|
|
|
|
{
|
|
|
|
if (!data)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (data->users)
|
|
|
|
{
|
|
|
|
list_clear(data->users, hub_free);
|
|
|
|
list_destroy(data->users);
|
|
|
|
}
|
|
|
|
hub_free(data->file);
|
|
|
|
hub_free(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct acl_data* parse_config(const char* line)
|
|
|
|
{
|
|
|
|
struct acl_data* data = (struct acl_data*) hub_malloc_zero(sizeof(struct acl_data));
|
|
|
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
|
|
|
char* token = cfg_token_get_first(tokens);
|
|
|
|
|
|
|
|
if (!data)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// set defaults
|
|
|
|
data->readonly = 1;
|
|
|
|
data->exclusive = 0;
|
|
|
|
data->users = list_create();
|
|
|
|
|
|
|
|
while (token)
|
|
|
|
{
|
|
|
|
char* split = strchr(token, '=');
|
|
|
|
size_t len = strlen(token);
|
|
|
|
size_t key = split ? (split - token) : len;
|
|
|
|
if (key == 4 && strncmp(token, "file", 4) == 0)
|
|
|
|
{
|
|
|
|
if (data->file)
|
|
|
|
hub_free(data->file);
|
|
|
|
data->file = strdup(split + 1);
|
|
|
|
}
|
|
|
|
else if (key == 8 && strncmp(token, "readonly", 8) == 0)
|
|
|
|
{
|
|
|
|
if (!string_to_boolean(split + 1, &data->readonly))
|
|
|
|
data->readonly = 1;
|
|
|
|
}
|
|
|
|
else if (key == 9 && strncmp(token, "exclusive", 9) == 0)
|
|
|
|
{
|
|
|
|
if (!string_to_boolean(split + 1, &data->exclusive))
|
|
|
|
data->exclusive = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cfg_tokens_free(tokens);
|
|
|
|
free_acl(data);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
token = cfg_token_get_next(tokens);
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg_tokens_free(tokens);
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2010-07-10 01:36:47 +00:00
|
|
|
static int parse_line(char* line, int line_count, void* ptr_data)
|
2010-07-08 12:24:40 +00:00
|
|
|
{
|
2010-07-10 01:36:47 +00:00
|
|
|
struct linked_list* users = (struct linked_list*) ptr_data;
|
2010-07-18 17:57:07 +00:00
|
|
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
2010-07-10 01:36:47 +00:00
|
|
|
enum auth_credentials cred;
|
2011-01-06 11:25:44 +00:00
|
|
|
char* credential;
|
|
|
|
char* username;
|
|
|
|
char* password;
|
2010-07-10 01:36:47 +00:00
|
|
|
|
2010-07-18 17:57:07 +00:00
|
|
|
if (cfg_token_count(tokens) == 0)
|
2010-07-29 08:39:34 +00:00
|
|
|
{
|
|
|
|
cfg_tokens_free(tokens);
|
2010-07-10 01:36:47 +00:00
|
|
|
return 0;
|
2010-07-29 08:39:34 +00:00
|
|
|
}
|
2010-07-10 01:36:47 +00:00
|
|
|
|
2010-07-18 17:57:07 +00:00
|
|
|
if (cfg_token_count(tokens) < 2)
|
2010-07-29 08:39:34 +00:00
|
|
|
{
|
|
|
|
cfg_tokens_free(tokens);
|
2010-07-18 17:57:07 +00:00
|
|
|
return -1;
|
2010-07-29 08:39:34 +00:00
|
|
|
}
|
2010-07-18 17:57:07 +00:00
|
|
|
|
2011-01-06 11:25:44 +00:00
|
|
|
credential = cfg_token_get_first(tokens);
|
|
|
|
username = cfg_token_get_next(tokens);
|
|
|
|
password = cfg_token_get_next(tokens);
|
2010-07-10 01:36:47 +00:00
|
|
|
|
2010-07-29 08:39:34 +00:00
|
|
|
if (!auth_string_to_cred(credential, &cred))
|
|
|
|
{
|
|
|
|
cfg_tokens_free(tokens);
|
2010-07-10 01:36:47 +00:00
|
|
|
return -1;
|
2010-07-29 08:39:34 +00:00
|
|
|
}
|
2010-07-10 01:36:47 +00:00
|
|
|
|
|
|
|
insert_user(users, username, password, cred);
|
|
|
|
cfg_tokens_free(tokens);
|
|
|
|
return 0;
|
2010-07-08 12:24:40 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
static struct acl_data* load_acl(const char* config, struct plugin_handle* handle)
|
2010-07-08 12:24:40 +00:00
|
|
|
{
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
struct acl_data* data = parse_config(config);
|
|
|
|
|
|
|
|
if (!data)
|
2010-07-29 06:41:26 +00:00
|
|
|
return 0;
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
if (!data->file || !*data->file)
|
2010-07-08 12:24:40 +00:00
|
|
|
{
|
2010-07-29 06:43:22 +00:00
|
|
|
free_acl(data); data = 0;
|
|
|
|
set_error_message(handle, "No configuration file given, missing \"file=<filename>\" configuration option.");
|
2010-07-08 12:24:40 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
if (file_read_lines(data->file, data->users, &parse_line) == -1)
|
2010-07-10 01:36:47 +00:00
|
|
|
{
|
2010-07-29 06:43:22 +00:00
|
|
|
fprintf(stderr, "Unable to load %s\n", data->file);
|
|
|
|
set_error_message(handle, "Unable to load file");
|
2010-07-10 01:36:47 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
return data;
|
2010-07-08 12:24:40 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
static void unload_acl(struct acl_data* data)
|
2010-07-08 12:24:40 +00:00
|
|
|
{
|
2010-07-29 06:43:22 +00:00
|
|
|
free_acl(data);
|
2010-07-08 12:24:40 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
static plugin_st get_user(struct plugin_handle* plugin, const char* nickname, struct auth_info* data)
|
2010-07-10 01:36:47 +00:00
|
|
|
{
|
2010-07-29 06:43:22 +00:00
|
|
|
struct acl_data* acl = (struct acl_data*) plugin->ptr;
|
|
|
|
struct auth_info* info = (struct auth_info*) list_get_first(acl->users);
|
|
|
|
while (info)
|
|
|
|
{
|
|
|
|
if (strcasecmp((char*)info->nickname, nickname) == 0)
|
|
|
|
{
|
|
|
|
memcpy(data, info, sizeof(struct auth_info));
|
|
|
|
return st_allow;
|
|
|
|
}
|
|
|
|
info = (struct auth_info*) list_get_next(acl->users);
|
|
|
|
}
|
|
|
|
if (acl->exclusive)
|
|
|
|
return st_deny;
|
|
|
|
return st_default;
|
2010-07-10 01:36:47 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
static plugin_st register_user(struct plugin_handle* plugin, struct auth_info* user)
|
2010-07-10 01:36:47 +00:00
|
|
|
{
|
2010-07-29 06:43:22 +00:00
|
|
|
struct acl_data* acl = (struct acl_data*) plugin->ptr;
|
|
|
|
if (acl->exclusive)
|
|
|
|
return st_deny;
|
|
|
|
return st_default;
|
2010-07-10 01:36:47 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* user)
|
2010-07-10 01:36:47 +00:00
|
|
|
{
|
2010-07-29 06:43:22 +00:00
|
|
|
struct acl_data* acl = (struct acl_data*) plugin->ptr;
|
|
|
|
if (acl->exclusive)
|
|
|
|
return st_deny;
|
|
|
|
return st_default;
|
2010-07-10 01:36:47 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* user)
|
2010-07-10 01:36:47 +00:00
|
|
|
{
|
2010-07-29 06:43:22 +00:00
|
|
|
struct acl_data* acl = (struct acl_data*) plugin->ptr;
|
|
|
|
if (acl->exclusive)
|
|
|
|
return st_deny;
|
|
|
|
return st_default;
|
2010-07-10 01:36:47 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
int plugin_register(struct plugin_handle* plugin, const char* config)
|
2010-07-08 12:24:40 +00:00
|
|
|
{
|
2010-08-30 09:54:34 +00:00
|
|
|
PLUGIN_INITIALIZE(plugin, "File authentication plugin", "0.1", "Authenticate users based on a read-only text file.");
|
2010-07-08 12:24:40 +00:00
|
|
|
|
2010-07-10 01:36:47 +00:00
|
|
|
// Authentication actions.
|
|
|
|
plugin->funcs.auth_get_user = get_user;
|
|
|
|
plugin->funcs.auth_register_user = register_user;
|
|
|
|
plugin->funcs.auth_update_user = update_user;
|
|
|
|
plugin->funcs.auth_delete_user = delete_user;
|
|
|
|
|
2010-07-29 06:41:26 +00:00
|
|
|
plugin->ptr = load_acl(config, plugin);
|
|
|
|
if (plugin->ptr)
|
|
|
|
return 0;
|
|
|
|
return -1;
|
2010-07-08 12:24:40 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 06:43:22 +00:00
|
|
|
int plugin_unregister(struct plugin_handle* plugin)
|
2010-07-08 12:24:40 +00:00
|
|
|
{
|
2010-07-18 17:57:07 +00:00
|
|
|
set_error_message(plugin, 0);
|
2010-07-08 12:24:40 +00:00
|
|
|
unload_acl(plugin->ptr);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|