char *password = strchr(p, '\0')+1;
if (password > client->saslbuf + client->saslbufLen)
goto saslerr;
- job_password_check(client, username, password, "users", [client](int res) {
+ job_password_check<"users">(client, username, password, [client](int res) {
if (client->saslusername) {
if (res == 0) {
rpl_saslsuccess(), sendbuf(client);
memcpy(client->webirchostname, args[2], len);
memcpy(client->webirchostname+len, ".xmpp", sizeof(".xmpp"));
}
- job_password_check(client, args[1], args[0], "webirc", [client](int res) {
+ job_password_check<"webirc">(client, args[1], args[0], [client](int res) {
if (!(client->umode & UMODE_SECURE) || res != 0) {
delete[] client->webircpeername;
client->webircpeername = 0;
if (argc < 2)
return err_needmoreparams(client, command), sendbuf(client), 0;
stringlower(args[0]);
- job_password_check(client, args[0], args[1], "ops", [client](int res) {
+ job_password_check<"ops">(client, args[0], args[1], [client](int res) {
if (!(client->umode & UMODE_SECURE) || res != 0) {
err_passwdmismatch(client), sendbuf(client);
} else {
}
}
if (client->username[0] == '~' && client->pass_reg) {
- job_password_check(client, client->username+1, client->pass_reg, "users", [client](int res) {
+ job_password_check<"users">(client, client->username+1, client->pass_reg, [client](int res) {
if (client->passwait) {
client->passwait = 0;
if (!(client->umode & UMODE_SECURE) || res != 0) {
}
}
};
-void job_password_check(Client *client, const char *key, const char *pw, const char *fn, contproc_t&& then)
+static void job_password_check_internal(Client *client, const char *salt, const char *pw, contproc_t&& then)
{
- db::Statement stmt;
- std::string_view salt;
- if (fn == "ops"sv)
- stmt = db::disk("SELECT hash FROM ops WHERE account = ?;");
- else if (fn == "users"sv)
- stmt = db::disk("SELECT hash FROM users WHERE account = ?;");
- else if (fn == "webirc"sv)
- stmt = db::disk("SELECT hash FROM webirc WHERE account = ?;");
- else
- goto no_table;
-
- stmt.bind(1, key);
- if (stmt.step())
- salt = stmt.text(0);
-
-no_table:
// FIXME: make_shared only really needed here cuz std::function wants a copyable object
// C++23 adds a std::move_only_function
- job_add(client, [pw=std::make_shared<SecureStringWrapper>(pw), salt=std::make_shared<SecureStringWrapper>(salt.data())]() -> int {
+ job_add(client, [pw=std::make_shared<SecureStringWrapper>(pw), salt=std::make_shared<SecureStringWrapper>(salt)]() -> int {
if (!*salt)
return 1;
char *hash = password_crypt(*pw, *salt);
return rv;
}, std::move(then));
}
+template<size_t A, size_t B, size_t C>
+consteval static std::array<char, A+B+C-2> concat(const char (&a)[A], const char (&b)[B], const char (&c)[C]) {
+ std::array<char, A+B+C-2> arr;
+ std::copy_n(a, A-1, &arr[0]);
+ std::copy_n(b, B-1, &arr[A-1]);
+ std::copy_n(c, C, &arr[A+B-2]);
+ return arr;
+}
+template<Literal table>
+void job_password_check(Client *client, const char *key, const char *pw, contproc_t&& then)
+{
+ constexpr auto query = concat("SELECT hash FROM ", table.value, " WHERE account = ?;");
+ auto stmt = db::disk(std::string_view(query.data(), query.size()));
+ stmt.bind(1, key);
+ std::string_view salt;
+ if (stmt.step())
+ salt = stmt.text(0);
+ job_password_check_internal(client, salt.data(), pw, std::move(then));
+}
+template void job_password_check<"ops">(Client *client, const char *key, const char *pw, contproc_t&& then);
+template void job_password_check<"users">(Client *client, const char *key, const char *pw, contproc_t&& then);
+template void job_password_check<"webirc">(Client *client, const char *key, const char *pw, contproc_t&& then);
void job_process(void);
void job_add(Client *client, jobproc_t&& job, contproc_t&& then);
void job_kill(Client *client);
-void job_password_check(Client *client, const char *key, const char *pw, const char *fn, contproc_t&& then);
+template<size_t N>
+struct Literal {
+ char value[N];
+ consteval Literal(const char (&s)[N]) { std::copy_n(s, N, value); }
+};
+template<Literal table>
+void job_password_check(Client *client, const char *key, const char *pw, contproc_t&& then);
+extern template void job_password_check<"ops">(Client *client, const char *key, const char *pw, contproc_t&& then);
+extern template void job_password_check<"users">(Client *client, const char *key, const char *pw, contproc_t&& then);
+extern template void job_password_check<"webirc">(Client *client, const char *key, const char *pw, contproc_t&& then);
#endif