Added an SQLite authentication backend.
This commit is contained in:
parent
93be2c584e
commit
55ffe46a38
|
@ -209,6 +209,10 @@ plugin_logging_TARGET := mod_logging.so
|
||||||
plugin_auth_SOURCES := src/plugins/mod_auth_simple.c
|
plugin_auth_SOURCES := src/plugins/mod_auth_simple.c
|
||||||
plugin_auth_TARGET := mod_auth_simple.so
|
plugin_auth_TARGET := mod_auth_simple.so
|
||||||
|
|
||||||
|
plugin_auth_sqlite_SOURCES := src/plugins/mod_auth_sqlite.c
|
||||||
|
plugin_auth_sqlite_TARGET := mod_auth_sqlite.so
|
||||||
|
plugin_auth_sqlite_LIBS := -lsqlite3
|
||||||
|
|
||||||
|
|
||||||
# Source to objects
|
# Source to objects
|
||||||
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
||||||
|
@ -221,7 +225,7 @@ adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
|
||||||
admin_OBJECTS := $(admin_SOURCES:.c=.o)
|
admin_OBJECTS := $(admin_SOURCES:.c=.o)
|
||||||
|
|
||||||
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(libutils_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(libutils_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||||
all_plugins := $(plugin_example_TARGET) $(plugin_logging_TARGET) $(plugin_auth_TARGET)
|
all_plugins := $(plugin_example_TARGET) $(plugin_logging_TARGET) $(plugin_auth_TARGET) $(plugin_auth_sqlite_TARGET)
|
||||||
|
|
||||||
uhub_BINARY=uhub$(BIN_EXT)
|
uhub_BINARY=uhub$(BIN_EXT)
|
||||||
adcrush_BINARY=adcrush$(BIN_EXT)
|
adcrush_BINARY=adcrush$(BIN_EXT)
|
||||||
|
@ -244,6 +248,9 @@ plugins: $(uhub_BINARY) $(all_plugins)
|
||||||
$(plugin_auth_TARGET): $(plugin_auth_SOURCES) $(libutils_OBJECTS)
|
$(plugin_auth_TARGET): $(plugin_auth_SOURCES) $(libutils_OBJECTS)
|
||||||
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||||
|
|
||||||
|
$(plugin_auth_sqlite_TARGET): $(plugin_auth_sqlite_SOURCES) $(libutils_OBJECTS)
|
||||||
|
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS) $(plugin_auth_sqlite_LIBS)
|
||||||
|
|
||||||
$(plugin_example_TARGET): $(plugin_example_SOURCES)
|
$(plugin_example_TARGET): $(plugin_example_SOURCES)
|
||||||
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
* uhub - A tiny ADC p2p connection hub
|
||||||
|
* Copyright (C) 2010, Jan Vidar Krey
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "plugin_api/handle.h"
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/list.h"
|
||||||
|
#include "util/ipcalc.h"
|
||||||
|
#include "util/misc.h"
|
||||||
|
#include "util/log.h"
|
||||||
|
#include "util/config_token.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void set_error_message(struct plugin_handle* plugin, const char* msg)
|
||||||
|
{
|
||||||
|
plugin->error_msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sql_data
|
||||||
|
{
|
||||||
|
int exclusive;
|
||||||
|
sqlite3* db;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sql_data* parse_config(const char* line, struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
struct sql_data* data = (struct sql_data*) hub_malloc_zero(sizeof(struct sql_data));
|
||||||
|
struct cfg_tokens* tokens = cfg_tokenize(line);
|
||||||
|
char* token = cfg_token_get_first(tokens);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
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 && data->db == 0)
|
||||||
|
{
|
||||||
|
if (sqlite3_open(split + 1, &data->db))
|
||||||
|
{
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key == 9 && strncmp(token, "exclusive", 9) == 0)
|
||||||
|
{
|
||||||
|
if (!string_to_boolean(split + 1, &data->exclusive))
|
||||||
|
data->exclusive = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_error_message(plugin, "Unable to parse startup parameters");
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
hub_free(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
token = cfg_token_get_next(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_tokens_free(tokens);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* sql_escape_string(const char* str)
|
||||||
|
{
|
||||||
|
static char out[1024];
|
||||||
|
size_t i = 0;
|
||||||
|
size_t n = 0;
|
||||||
|
for (; n < strlen(str); n++)
|
||||||
|
{
|
||||||
|
if (str[n] == '\'' || str[n] == '\\')
|
||||||
|
out[i++] = '\\';
|
||||||
|
out[i++] = str[n];
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_user_callback(void* ptr, int argc, char **argv, char **colName){
|
||||||
|
struct auth_info* data = (struct auth_info*) ptr;
|
||||||
|
int i;
|
||||||
|
for(i=0; i<argc; i++) {
|
||||||
|
if (strcmp(colName[i], "nickname") == 0)
|
||||||
|
strncpy(data->nickname, argv[i], MAX_NICK_LEN);
|
||||||
|
else if (strcmp(colName[i], "password") == 0)
|
||||||
|
strncpy(data->password, argv[i], MAX_PASS_LEN);
|
||||||
|
else if (strcmp(colName[i], "credentials") == 0)
|
||||||
|
{
|
||||||
|
auth_string_to_cred(colName[i], &data->credentials);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st get_user(struct plugin_handle* plugin, const char* nickname, struct auth_info* data)
|
||||||
|
{
|
||||||
|
struct sql_data* sql = (struct sql_data*) plugin->ptr;
|
||||||
|
char query[1024];
|
||||||
|
char* errMsg;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
snprintf(query, sizeof(query), "SELECT * FROM users WHERE nickname='%s';", sql_escape_string(nickname));
|
||||||
|
memset(data, 0, sizeof(struct auth_info));
|
||||||
|
|
||||||
|
rc = sqlite3_exec(sql->db, query , get_user_callback, data, &errMsg);
|
||||||
|
if( rc != SQLITE_OK ){
|
||||||
|
fprintf(stderr, "SQL error: %s\n", errMsg);
|
||||||
|
sqlite3_free(errMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return st_allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st register_user(struct plugin_handle* plugin, struct auth_info* user)
|
||||||
|
{
|
||||||
|
struct sql_data* sql = (struct sql_data*) plugin->ptr;
|
||||||
|
if (sql->exclusive)
|
||||||
|
return st_deny;
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st update_user(struct plugin_handle* plugin, struct auth_info* user)
|
||||||
|
{
|
||||||
|
struct sql_data* sql = (struct sql_data*) plugin->ptr;
|
||||||
|
if (sql->exclusive)
|
||||||
|
return st_deny;
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_st delete_user(struct plugin_handle* plugin, struct auth_info* user)
|
||||||
|
{
|
||||||
|
struct sql_data* sql = (struct sql_data*) plugin->ptr;
|
||||||
|
if (sql->exclusive)
|
||||||
|
return st_deny;
|
||||||
|
return st_default;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_register(struct plugin_handle* plugin, const char* config)
|
||||||
|
{
|
||||||
|
plugin->name = "SQLite authentication plugin";
|
||||||
|
plugin->version = "0.1";
|
||||||
|
plugin->description = "Authenticate users based on a SQLite database.";
|
||||||
|
plugin->plugin_api_version = PLUGIN_API_VERSION;
|
||||||
|
plugin->plugin_funcs_size = sizeof(struct plugin_funcs);
|
||||||
|
memset(&plugin->funcs, 0, sizeof(struct plugin_funcs));
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
plugin->ptr = parse_config(config, plugin);
|
||||||
|
if (plugin->ptr)
|
||||||
|
return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int plugin_unregister(struct plugin_handle* plugin)
|
||||||
|
{
|
||||||
|
set_error_message(plugin, 0);
|
||||||
|
struct sql_data* sql = (struct sql_data*) plugin->ptr;
|
||||||
|
sqlite3_close(sql->db);
|
||||||
|
hub_free(sql);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -75,3 +75,38 @@ const char* auth_cred_to_string(enum auth_credentials cred)
|
||||||
return "";
|
return "";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int auth_string_to_cred(const char* str, enum auth_credentials* out)
|
||||||
|
{
|
||||||
|
if (!str || !*str || !out)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (strlen(str))
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
if (!strcasecmp(str, "op")) { *out = auth_cred_operator; return 1; }
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
if (!strcasecmp(str, "bot")) { *out = auth_cred_bot; return 1; }
|
||||||
|
if (!strcasecmp(str, "reg")) { *out = auth_cred_user; return 1; }
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if (!strcasecmp(str, "user")) { *out = auth_cred_user; return 1; }
|
||||||
|
if (!strcasecmp(str, "link")) { *out = auth_cred_link; return 1; }
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
if (!strcasecmp(str, "admin")) { *out = auth_cred_admin; return 1; }
|
||||||
|
if (!strcasecmp(str, "super")) { *out = auth_cred_super; return 1; }
|
||||||
|
if (!strcasecmp(str, "guest")) { *out = auth_cred_guest; return 1; }
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
if (!strcasecmp(str, "operator")) { *out = auth_cred_operator; return 1; }
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -51,4 +51,7 @@ int auth_cred_is_registered(enum auth_credentials cred);
|
||||||
*/
|
*/
|
||||||
const char* auth_cred_to_string(enum auth_credentials cred);
|
const char* auth_cred_to_string(enum auth_credentials cred);
|
||||||
|
|
||||||
|
|
||||||
|
int auth_string_to_cred(const char* str, enum auth_credentials* out);
|
||||||
|
|
||||||
#endif /* HAVE_UHUB_CREDENTIALS_H */
|
#endif /* HAVE_UHUB_CREDENTIALS_H */
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
my $input = $ARGV[0];
|
||||||
|
|
||||||
|
open (FILE, "$input") || die "# Unable to open input file $input: $!";
|
||||||
|
my @lines = <FILE>;
|
||||||
|
close (FILE);
|
||||||
|
|
||||||
|
print "CREATE TABLE users(nickname CHAR(64) UNIQUE, password CHAR(64), credentials CHAR(5));\n";
|
||||||
|
|
||||||
|
foreach my $line (@lines) {
|
||||||
|
|
||||||
|
chomp($line);
|
||||||
|
|
||||||
|
$line =~ s/#.*//g;
|
||||||
|
|
||||||
|
next if ($line =~ /^\s*$/);
|
||||||
|
|
||||||
|
if ($line =~ /^\s*user_(op|admin|super|reg)\s*(.+):(.+)\s*/)
|
||||||
|
{
|
||||||
|
my $cred = $1;
|
||||||
|
my $nick = $2;
|
||||||
|
my $pass = $3;
|
||||||
|
|
||||||
|
$nick =~ s/'/\\'/g;
|
||||||
|
$pass =~ s/'/\\'/g;
|
||||||
|
|
||||||
|
print "INSERT INTO users VALUES('" . $nick . "', '" . $pass . "', '" . $cred . "');\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
# print "# Warning: Unrecognized line: \"" . $line . "\"\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue