aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile5
-rw-r--r--config.h10
-rw-r--r--general_network.c8
-rw-r--r--pseudoclients.c4
-rw-r--r--pseudoclients.h4
-rw-r--r--pseudoclients/haxserv.c30
-rw-r--r--pseudoclients/services.c147
8 files changed, 199 insertions, 10 deletions
diff --git a/.gitignore b/.gitignore
index 1ae34af..4d22872 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ core
.makeopts
output
pseudoclients/services.db
+pseudoclients/services.db-lock
diff --git a/Makefile b/Makefile
index c8f5dac..9a32b59 100644
--- a/Makefile
+++ b/Makefile
@@ -341,7 +341,8 @@ endif
ifeq ($(SERVICES_PSEUDOCLIENT),1)
SOFILES += pseudoclients/services.so
-CFLAGS += -DUSE_SERVICES_PSEUDOCLIENT
+CFLAGS += -DUSE_SERVICES_PSEUDOCLIENT $(shell pkg-config --cflags lmdb)
+LDFLAGS += $(shell pkg-config --libs lmdb)
USE_PSEUDOCLIENTS = 1
endif
@@ -442,7 +443,7 @@ HaxIRCd.so: $(OFILES) .makeopts Makefile
$(CC) $(CFLAGS) -fPIC -c $< -o $@
%.so: %.c
- $(CC) $(CFLAGS) -shared -fPIC $< -o $@
+ $(CC) $(CFLAGS) -shared -fPIC $< -o $@ $(LDFLAGS)
$(call DEPS,config,o)
diff --git a/config.h b/config.h
index ee86e61..2d99a0d 100644
--- a/config.h
+++ b/config.h
@@ -33,9 +33,9 @@
#include "general_network.h"
#include "protocols.h"
-// #define K * 1024
-// #define M * (1024 K)
-// #define G * (1024 M)
+// #define K * 1024LU
+// #define M * (1024LU K)
+// #define G * (1024LU M)
#ifdef USE_SERVER
struct server_config {
@@ -59,7 +59,7 @@ struct server_config {
struct string port; // = "4321",
};
extern struct server_config SERVER_CONFIG[]; // = {{...}, ...};
-extern size_t SERVER_CONFIG_LEN; // = sizeof(server_config)/sizeof(*server_config);
+extern size_t SERVER_CONFIG_LEN; // = sizeof(SERVER_CONFIG)/sizeof(*SERVER_CONFIG);
#endif
extern struct string SID; // = STRING("200");
@@ -127,4 +127,6 @@ extern struct string NICKSERV_HOST; // = STRING("localhost");
extern struct string NICKSERV_ADDRESS; // = STRING("/dev/null");
extern struct string SERVICES_CHANNEL; // = STRING("#services");
+
+extern size_t SERVICES_DB_MAX_SIZE; // = 100 M;
#endif
diff --git a/general_network.c b/general_network.c
index 70ebe60..f5ce1e3 100644
--- a/general_network.c
+++ b/general_network.c
@@ -395,6 +395,10 @@ int rename_user(struct string from, struct user_info *user, struct string nick,
protocols_propagate_rename_user(from, user, nick, timestamp, timestamp_str);
#endif
+#ifdef USE_PSEUDOCLIENTS
+ pseudoclients_handle_rename_user(from, user, nick, timestamp);
+#endif
+
free(user->nick.data);
user->nick.data = tmp;
memcpy(user->nick.data, nick.data, nick.len);
@@ -523,6 +527,10 @@ int set_cert(struct string from, struct user_info *user, struct string cert, str
protocols_propagate_set_cert(from, user, cert, source);
#endif
+#ifdef USE_PSEUDOCLIENTS
+ pseudoclients_handle_set_cert(from, user, cert, source);
+#endif
+
user->cert_ready = 1;
free(user->cert.data);
diff --git a/pseudoclients.c b/pseudoclients.c
index e2ca8ad..506a305 100644
--- a/pseudoclients.c
+++ b/pseudoclients.c
@@ -101,14 +101,14 @@ void pseudoclients_handle_privmsg(struct string from, struct string sender, stru
}
}
-void psuedoclients_handle_rename_user(struct string from, struct user_info *user, struct string nick, size_t timestamp) {
+void pseudoclients_handle_rename_user(struct string from, struct user_info *user, struct string nick, size_t timestamp) {
for (size_t i = 0; i < NUM_PSEUDOCLIENTS; i++) {
if (pseudoclients[i].active)
pseudoclients[i].handle_rename_user(from, user, nick, timestamp);
}
}
-void psuedoclients_handle_set_cert(struct string from, struct user_info *user, struct string cert, struct string source) {
+void pseudoclients_handle_set_cert(struct string from, struct user_info *user, struct string cert, struct string source) {
for (size_t i = 0; i < NUM_PSEUDOCLIENTS; i++) {
if (pseudoclients[i].active)
pseudoclients[i].handle_set_cert(from, user, cert, source);
diff --git a/pseudoclients.h b/pseudoclients.h
index 41123a0..0dddc72 100644
--- a/pseudoclients.h
+++ b/pseudoclients.h
@@ -65,5 +65,5 @@ extern struct pseudoclient pseudoclients[NUM_PSEUDOCLIENTS];
extern char reload_pseudoclients[NUM_PSEUDOCLIENTS];
void pseudoclients_handle_privmsg(struct string from, struct string source, struct string target, struct string msg);
-void psuedoclients_handle_rename_user(struct string from, struct user_info *user, struct string nick, size_t timestamp);
-void psuedoclients_handle_set_cert(struct string from, struct user_info *user, struct string cert, struct string source);
+void pseudoclients_handle_rename_user(struct string from, struct user_info *user, struct string nick, size_t timestamp);
+void pseudoclients_handle_set_cert(struct string from, struct user_info *user, struct string cert, struct string source);
diff --git a/pseudoclients/haxserv.c b/pseudoclients/haxserv.c
index cc69198..ba5b55a 100644
--- a/pseudoclients/haxserv.c
+++ b/pseudoclients/haxserv.c
@@ -939,6 +939,36 @@ int haxserv_pseudoclient_get_command(struct string from, struct string sender, s
{
struct string msg_parts[] = {
+ STRING("Account name: "),
+ user->account_name,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
+ STRING("TLS Cert: "),
+ user->cert,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
STRING("Server: "),
user->server,
};
diff --git a/pseudoclients/services.c b/pseudoclients/services.c
index 22051c0..3e593d5 100644
--- a/pseudoclients/services.c
+++ b/pseudoclients/services.c
@@ -24,12 +24,24 @@
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
+#include <lmdb.h>
+#include <stdlib.h>
+
#include "../config.h"
#include "../haxstring.h"
+#include "../haxstring_utils.h"
#include "../general_network.h"
#include "../pseudoclients.h"
#include "services.h"
+MDB_env *services_db_env;
+
+MDB_dbi services_nick_to_account;
+MDB_dbi services_cert_to_account;
+MDB_dbi services_account_to_nicks;
+MDB_dbi services_account_to_certs;
+MDB_dbi services_account_to_name;
+
int services_pseudoclient_init(void) {
return services_pseudoclient_post_reload();
}
@@ -54,6 +66,45 @@ int services_pseudoclient_post_reload(void) {
return 1;
}
+ if (mdb_env_create(&services_db_env) != 0)
+ return 1;
+ if (mdb_env_set_mapsize(services_db_env, SERVICES_DB_MAX_SIZE) != 0)
+ return 1;
+ if (mdb_env_set_maxdbs(services_db_env, 5) != 0) // nick->account + cert->account + account->nicks (also used for account list) + account->certs + account->name
+ return 1;
+ if (mdb_env_open(services_db_env, "./pseudoclients/services.db", MDB_NOSUBDIR | MDB_NOTLS | MDB_NORDAHEAD, 0600) != 0)
+ return 1;
+ {
+ int discard;
+ if (mdb_reader_check(services_db_env, &discard) != 0)
+ return 1;
+ }
+
+ MDB_txn *txn;
+ if (mdb_txn_begin(services_db_env, NULL, 0, &txn) != 0)
+ return 1;
+ if (mdb_dbi_open(txn, "nick_to_account", MDB_CREATE, &services_nick_to_account) != 0) {
+ mdb_txn_abort(txn);
+ return 1;
+ }
+ if (mdb_dbi_open(txn, "cert_to_account", MDB_CREATE, &services_cert_to_account) != 0) {
+ mdb_txn_abort(txn);
+ return 1;
+ }
+ if (mdb_dbi_open(txn, "account_to_nicks", MDB_CREATE | MDB_DUPSORT, &services_account_to_nicks) != 0) {
+ mdb_txn_abort(txn);
+ return 1;
+ }
+ if (mdb_dbi_open(txn, "account_to_certs", MDB_CREATE | MDB_DUPSORT, &services_account_to_certs) != 0) {
+ mdb_txn_abort(txn);
+ return 1;
+ }
+ if (mdb_dbi_open(txn, "account_to_name", MDB_CREATE, &services_account_to_name) != 0) {
+ mdb_txn_abort(txn);
+ return 1;
+ }
+ mdb_txn_commit(txn);
+
pseudoclients[SERVICES_PSEUDOCLIENT].init = services_pseudoclient_init;
pseudoclients[SERVICES_PSEUDOCLIENT].post_reload = services_pseudoclient_post_reload;
@@ -70,6 +121,8 @@ int services_pseudoclient_post_reload(void) {
}
int services_pseudoclient_pre_reload(void) {
+ mdb_env_close(services_db_env);
+
return 0;
}
@@ -82,6 +135,74 @@ int services_pseudoclient_allow_kick(struct string from, struct string source, s
}
void services_pseudoclient_handle_privmsg(struct string from, struct string source, struct string target, struct string msg) {
+ struct user_info *user = get_table_index(user_list, source);
+ if (!user)
+ return;
+
+ if (STRING_EQ(target, NICKSERV_UID)) {
+ if (STRING_EQ(msg, STRING("REGISTER")) && user->cert.len != 0) {
+ struct string nick_upper;
+ if (str_clone(&nick_upper, user->nick) != 0)
+ return;
+ for (size_t i = 0; i < nick_upper.len; i++)
+ nick_upper.data[i] = CASEMAP(nick_upper.data[i]);
+
+ MDB_txn *txn;
+ if (mdb_txn_begin(services_db_env, NULL, 0, &txn) != 0) {
+ free(nick_upper.data);
+ return;
+ }
+
+ MDB_val key = {
+ .mv_data = nick_upper.data,
+ .mv_size = nick_upper.len,
+ };
+ MDB_val data = key;
+
+ if (mdb_put(txn, services_account_to_nicks, &key, &data, MDB_NOOVERWRITE) != 0) {
+ mdb_txn_abort(txn);
+ free(nick_upper.data);
+ return;
+ }
+ if (mdb_put(txn, services_nick_to_account, &key, &data, MDB_NOOVERWRITE) != 0) {
+ mdb_txn_abort(txn);
+ free(nick_upper.data);
+ return;
+ }
+
+ data.mv_data = user->cert.data;
+ data.mv_size = user->cert.len;
+ if (mdb_put(txn, services_account_to_certs, &key, &data, MDB_NOOVERWRITE) != 0) {
+ mdb_txn_abort(txn);
+ free(nick_upper.data);
+ return;
+ }
+
+ data = key;
+ key.mv_data = user->cert.data;
+ key.mv_size = user->cert.len;
+ if (mdb_put(txn, services_cert_to_account, &key, &data, MDB_NOOVERWRITE) != 0) {
+ mdb_txn_abort(txn);
+ free(nick_upper.data);
+ return;
+ }
+
+ key = data;
+ data.mv_data = user->nick.data;
+ data.mv_size = user->nick.len;
+ if (mdb_put(txn, services_account_to_name, &key, &data, MDB_NOOVERWRITE) != 0) {
+ mdb_txn_abort(txn);
+ free(nick_upper.data);
+ return;
+ }
+
+ mdb_txn_commit(txn);
+ free(nick_upper.data);
+
+ set_account(SID, user, user->nick, NICKSERV_UID);
+ }
+ }
+
return;
}
@@ -90,5 +211,31 @@ void services_pseudoclient_handle_rename_user(struct string from, struct user_in
}
void services_pseudoclient_handle_set_cert(struct string from, struct user_info *user, struct string cert, struct string source) {
+ if (cert.len != 0) {
+ MDB_txn *txn;
+ if (mdb_txn_begin(services_db_env, NULL, MDB_RDONLY, &txn) != 0) {
+ return;
+ }
+
+ MDB_val key = {
+ .mv_data = cert.data,
+ .mv_size = cert.len,
+ };
+ MDB_val data;
+
+ if (mdb_get(txn, services_cert_to_account, &key, &data) != 0) {
+ mdb_txn_abort(txn);
+ return;
+ }
+ key = data;
+ if (mdb_get(txn, services_account_to_name, &key, &data) != 0) {
+ mdb_txn_abort(txn);
+ return;
+ }
+ mdb_txn_abort(txn);
+ struct string account = {.data = data.mv_data, .len = data.mv_size};
+ set_account(SID, user, account, NICKSERV_UID);
+ }
+
return;
}