Skip to content

Commit 5abe811

Browse files
committed
mod_auth_mysql: Fix database table regression.
Commit ab56e96 moved DB_NAME_ARGS from mod_mysql.h to mod_auth_mysql, but replaced an argument with the hostname instead of the database hostname, causing database connections to fail. Fix this, and also add a test for user registration and authentication using MySQL, which would have caught this.
1 parent 11d992b commit 5abe811

File tree

4 files changed

+162
-10
lines changed

4 files changed

+162
-10
lines changed

modules/mod_auth_mysql.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ static char *dbusername = buf_dbusername;
5151
static char *dbpassword = buf_dbpassword;
5252
static char *dbname = buf_dbname;
5353

54-
#define DB_NAME_ARGS dbhostname, !strlen_zero(dbhostname) ? "." : ""
54+
/* database.table if database defined, just table otherwise */
55+
#define DB_NAME_ARGS dbname, !strlen_zero(dbname) ? "." : ""
5556

5657
static int register_phone = 1, register_address = 1, register_zip = 1, register_dob = 1, register_gender = 1, register_howheard = 1;
5758
static int verifyregisteremail = 0;
@@ -372,7 +373,7 @@ static int user_register(struct bbs_node *node)
372373
NONZERO_RETURN(res);
373374

374375
if (!bbs_str_isprint(fullname)) {
375-
NEG_RETURN(bbs_node_writef(node, "\n%sUsername contains disallowed characters%s\n", COLOR(TERM_COLOR_RED), COLOR_RESET));
376+
NEG_RETURN(bbs_node_writef(node, "\n%sName contains disallowed characters%s\n", COLOR(TERM_COLOR_RED), COLOR_RESET));
376377
} else {
377378
break;
378379
}

tests/configs/mod_auth_mysql.conf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[db]
2+
hostname=localhost
3+
username=bbs
4+
password=P@ssw0rdUShouldChAngE!
5+
database=bbs
6+
7+
[registration]
8+
phone=no
9+
address=no
10+
zip=no
11+
dob=no
12+
gender=no
13+
howheard=no
14+
verifyemail=no

tests/test.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ static const char *bbs_expect_str = NULL;
415415
/* used extern */
416416
int test_autorun = 1;
417417
int rand_alloc_fails = 0;
418+
int use_static_auth = 1;
418419

419420
static int soft_assertions_failed = 0;
420421

@@ -1070,6 +1071,7 @@ static int run_test(const char *filename, int multiple)
10701071
goto cleanup;
10711072
}
10721073
option_autoload_all = option_use_mysql = rand_alloc_fails = 0;
1074+
use_static_auth = 1;
10731075
test_autorun = 1;
10741076
startup_run_unit_tests = 0;
10751077
if (testmod->pre) {
@@ -1082,7 +1084,9 @@ static int run_test(const char *filename, int multiple)
10821084
goto cleanup;
10831085
}
10841086
fprintf(modulefp, "[general]\r\nautoload=no\r\n\r\n[modules]\r\n");
1085-
test_load_module("mod_auth_static.so"); /* Always load this module */
1087+
if (use_static_auth) {
1088+
test_load_module("mod_auth_static.so"); /* Always load this module, unless told not to */
1089+
}
10861090
res = testmod->pre();
10871091
if (res) {
10881092
goto cleanup;
@@ -1107,13 +1111,15 @@ static int run_test(const char *filename, int multiple)
11071111
fprintf(modulefp, "[nodes]\r\naskdimensions=no\r\n"); /* Only needed for test_menus */
11081112
fclose(modulefp);
11091113
}
1110-
modulefp = fopen(TEST_CONFIG_DIR "/mod_auth_static.conf", "w");
1111-
if (modulefp) {
1112-
fprintf(modulefp, "[users]\r\n%s=%s\r\n", TEST_USER, TEST_HASH);
1113-
fprintf(modulefp, "%s=%s\r\n", TEST_USER2, TEST_HASH2);
1114-
fprintf(modulefp, "%s=%s\r\n", TEST_USER3, TEST_HASH3);
1115-
fprintf(modulefp, "%s=%s\r\n", TEST_USER4, TEST_HASH4);
1116-
fclose(modulefp);
1114+
if (use_static_auth) {
1115+
modulefp = fopen(TEST_CONFIG_DIR "/mod_auth_static.conf", "w");
1116+
if (modulefp) {
1117+
fprintf(modulefp, "[users]\r\n%s=%s\r\n", TEST_USER, TEST_HASH);
1118+
fprintf(modulefp, "%s=%s\r\n", TEST_USER2, TEST_HASH2);
1119+
fprintf(modulefp, "%s=%s\r\n", TEST_USER3, TEST_HASH3);
1120+
fprintf(modulefp, "%s=%s\r\n", TEST_USER4, TEST_HASH4);
1121+
fclose(modulefp);
1122+
}
11171123
}
11181124
if (option_autoload_all) {
11191125
if (system("cp " TEST_CONFIGS_SRC_DIR "/*.conf " TEST_CONFIG_DIR)) {

tests/test_auth_mysql.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* LBBS -- The Lightweight Bulletin Board System
3+
*
4+
* Copyright (C) 2025, Naveen Albert
5+
*
6+
* Naveen Albert <bbs@phreaknet.org>
7+
*
8+
* This program is free software, distributed under the terms of
9+
* the GNU General Public License Version 2. See the LICENSE file
10+
* at the top of the source tree.
11+
*/
12+
13+
/*! \file
14+
*
15+
* \brief MySQL User Registration/Authentication Tests
16+
*
17+
* \author Naveen Albert <bbs@phreaknet.org>
18+
*/
19+
20+
#include "test.h"
21+
#include "ansi.h"
22+
23+
#include <stdlib.h>
24+
#include <stdio.h>
25+
#include <unistd.h>
26+
#include <string.h>
27+
28+
extern int use_static_auth;
29+
30+
static int pre(void)
31+
{
32+
test_preload_module("mod_mysql.so");
33+
test_load_module("mod_auth_mysql.so");
34+
test_load_module("mod_menu_handlers.so");
35+
test_load_module("mod_node_callbacks.so");
36+
test_load_module("net_telnet.so");
37+
38+
test_use_mysql(); /* Run the database for this test */
39+
use_static_auth = 0; /* Use database for authentication, don't load mod_auth_static */
40+
41+
/* no net_telnet.conf needed, defaults are sufficient */
42+
TEST_ADD_CONFIG("menus.conf");
43+
TEST_ADD_CONFIG("mod_mysql.conf");
44+
TEST_ADD_CONFIG("mod_auth_mysql.conf");
45+
return 0;
46+
}
47+
48+
static int run(void)
49+
{
50+
int clientfd;
51+
int res = -1;
52+
53+
clientfd = test_make_socket(23);
54+
REQUIRE_FD(clientfd);
55+
56+
if (test_ansi_handshake(clientfd)) {
57+
goto cleanup;
58+
}
59+
60+
CLIENT_EXPECT_EVENTUALLY(clientfd, "Hit a key");
61+
SWRITE(clientfd, " "); /* Hit a key */
62+
63+
#define CRLF "\r\n"
64+
65+
/* New User */
66+
CLIENT_EXPECT_EVENTUALLY(clientfd, "Login:");
67+
SWRITE(clientfd, "New");
68+
SWRITE(clientfd, CRLF); /* CR NUL -> CR logic in pty.c only handles if the sequence is by itself */
69+
70+
CLIENT_EXPECT_EVENTUALLY(clientfd, "full real name");
71+
SWRITE(clientfd, "John Smith");
72+
SWRITE(clientfd, CRLF);
73+
74+
CLIENT_EXPECT_EVENTUALLY(clientfd, "username");
75+
SWRITE(clientfd, TEST_USER);
76+
SWRITE(clientfd, CRLF);
77+
78+
CLIENT_EXPECT_EVENTUALLY(clientfd, "Password");
79+
SWRITE(clientfd, TEST_PASS);
80+
SWRITE(clientfd, CRLF);
81+
82+
CLIENT_EXPECT_EVENTUALLY(clientfd, "Confirm Password");
83+
SWRITE(clientfd, TEST_PASS);
84+
SWRITE(clientfd, CRLF);
85+
86+
CLIENT_EXPECT_EVENTUALLY(clientfd, "Network mail address");
87+
SWRITE(clientfd, TEST_EMAIL);
88+
SWRITE(clientfd, CRLF);
89+
90+
CLIENT_EXPECT_EVENTUALLY(clientfd, "City");
91+
SWRITE(clientfd, "Anytown");
92+
SWRITE(clientfd, CRLF);
93+
94+
CLIENT_EXPECT_EVENTUALLY(clientfd, "State");
95+
SWRITE(clientfd, "NY");
96+
SWRITE(clientfd, CRLF);
97+
98+
CLIENT_EXPECT_EVENTUALLY(clientfd, "information correct?");
99+
SWRITE(clientfd, "y");
100+
101+
CLIENT_EXPECT_EVENTUALLY(clientfd, "Registration successful");
102+
SWRITE(clientfd, " ");
103+
104+
/* Now, log in fresh */
105+
close(clientfd);
106+
clientfd = test_make_socket(23);
107+
REQUIRE_FD(clientfd);
108+
109+
if (test_ansi_handshake(clientfd)) {
110+
goto cleanup;
111+
}
112+
113+
CLIENT_EXPECT_EVENTUALLY(clientfd, "Hit a key");
114+
SWRITE(clientfd, " "); /* Hit a key */
115+
116+
/* Must always use CLIENT_EXPECT_EVENTUALLY since our input is also echoed back to us */
117+
CLIENT_EXPECT_EVENTUALLY(clientfd, "Login");
118+
SWRITE(clientfd, TEST_USER "\n");
119+
120+
CLIENT_EXPECT_EVENTUALLY(clientfd, "Password");
121+
SWRITE(clientfd, TEST_PASS "\n");
122+
CLIENT_EXPECT_EVENTUALLY(clientfd, "at welcome menu via T");
123+
124+
res = 0;
125+
126+
cleanup:
127+
close_if(clientfd);
128+
return res;
129+
}
130+
131+
TEST_MODULE_INFO_STANDARD("MySQL User Authentication Tests");

0 commit comments

Comments
 (0)