diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | config.h | 10 | ||||
-rw-r--r-- | general_network.c | 8 | ||||
-rw-r--r-- | pseudoclients.c | 4 | ||||
-rw-r--r-- | pseudoclients.h | 4 | ||||
-rw-r--r-- | pseudoclients/haxserv.c | 30 | ||||
-rw-r--r-- | pseudoclients/services.c | 147 |
8 files changed, 199 insertions, 10 deletions
@@ -7,3 +7,4 @@ core .makeopts output pseudoclients/services.db +pseudoclients/services.db-lock @@ -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) @@ -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; } |