Skip to content

Commit 7ddd088

Browse files
authored
Merge pull request #100 from hessu/feature/disallow
config: Add DisallowIgateCall to drop packets by igate call or Q construct login: Don't reject missing version number for quirks-mode clients
2 parents fb006f9 + 1aeea44 commit 7ddd088

11 files changed

Lines changed: 111 additions & 11 deletions

File tree

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
build:
1111
strategy:
1212
matrix:
13-
os: [ ubuntu-latest, ubuntu-22.04 ]
13+
os: [ ubuntu-latest ]
1414
runs-on: ${{ matrix.os }}
1515

1616
steps:

doc/CONFIGURATION.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,12 @@ following callsigns are dropped by default: N0CALL* NOCALL* SERVER*
324324

325325
DisallowSourceCall P1RAT* P?ROT*
326326

327+
DisallowIgateCall makes the server drop packets which have the given callsign
328+
as one of the igate/receiver callsigns appearing after the Q construct in the
329+
path, even though they were injected at a different server.
330+
331+
DisallowIgateCall P1RAT* P?ROT*
332+
327333

328334
### Environment ###
329335

src/config.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ char *new_fake_version;
6767

6868
char **disallow_srccall_glob, **new_disallow_srccall_glob;
6969
char **disallow_login_glob, **new_disallow_login_glob;
70+
char **disallow_igate_glob, **new_disallow_igate_glob;
7071

7172
int listen_low_ports = 0; /* do we have any < 1024 ports set? need POSIX capabilities? */
7273

@@ -188,6 +189,7 @@ static struct cfgcmd cfg_cmds[] = {
188189
{ "fake_version", _CFUNC_ do_string, &new_fake_version },
189190
{ "disallowlogincall", _CFUNC_ do_string_array, &new_disallow_login_glob },
190191
{ "disallowsourcecall", _CFUNC_ do_string_array, &new_disallow_srccall_glob },
192+
{ "disallowigatecall", _CFUNC_ do_string_array, &new_disallow_igate_glob },
191193
{ NULL, NULL, NULL }
192194
};
193195

@@ -1405,7 +1407,19 @@ int read_config(void)
14051407
disallow_login_glob = NULL;
14061408
free_string_array(o);
14071409
}
1408-
1410+
1411+
if (new_disallow_igate_glob) {
1412+
char **o = disallow_igate_glob;
1413+
disallow_igate_glob = new_disallow_igate_glob;
1414+
new_disallow_igate_glob = NULL;
1415+
if (o)
1416+
free_string_array(o);
1417+
} else if (disallow_igate_glob) {
1418+
char **o = disallow_igate_glob;
1419+
disallow_igate_glob = NULL;
1420+
free_string_array(o);
1421+
}
1422+
14091423
/* validate uplink config: if there is a single 'multiro' connection
14101424
* configured, all of the uplinks must be 'multiro'
14111425
*/
@@ -1535,5 +1549,9 @@ void free_config(void)
15351549
free_string_array(disallow_login_glob);
15361550
disallow_login_glob = NULL;
15371551
}
1552+
if (disallow_igate_glob) {
1553+
free_string_array(disallow_igate_glob);
1554+
disallow_igate_glob = NULL;
1555+
}
15381556
}
15391557

src/config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ extern char *fake_version;
106106

107107
extern char **disallow_srccall_glob;
108108
extern char **disallow_login_glob;
109+
extern char **disallow_igate_glob;
109110

110111
extern char def_cfgfile[];
111112
extern char *cfgfile;

src/configure

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4040,9 +4040,12 @@ fi
40404040

40414041
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for macOS signature of pthread_setname_np" >&5
40424042
printf %s "checking for macOS signature of pthread_setname_np... " >&6; }
4043+
save_CFLAGS="$CFLAGS"
4044+
CFLAGS="$CFLAGS -Werror"
40434045
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
40444046
/* end confdefs.h. */
40454047
4048+
#define _GNU_SOURCE
40464049
#include <pthread.h>
40474050
void check_pthread_setname_np() {
40484051
pthread_setname_np("test");
@@ -4070,6 +4073,7 @@ printf "%s\n" "no" >&6; }
40704073
esac
40714074
fi
40724075
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
4076+
CFLAGS="$save_CFLAGS"
40734077

40744078

40754079

src/configure.ac

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,17 @@ dnl)
103103
AC_CHECK_LIB(pthread, pthread_setname_np, AC_DEFINE([HAVE_PTHREAD_SETNAME_NP], [], [pthread_setname_np available]))
104104

105105
AC_MSG_CHECKING([for macOS signature of pthread_setname_np])
106+
dnl _GNU_SOURCE must be defined before including pthread.h so that glibc
107+
dnl exposes the (two-argument) Linux prototype - just like hlog.c does.
108+
dnl Without it the function is undeclared on glibc and the single-argument
109+
dnl call below compiles as an implicit declaration, falsely detecting the
110+
dnl macOS signature. -Werror makes the wrong number of arguments fatal so
111+
dnl the test result is reliable.
112+
save_CFLAGS="$CFLAGS"
113+
CFLAGS="$CFLAGS -Werror"
106114
AC_COMPILE_IFELSE(
107115
[AC_LANG_PROGRAM([[
116+
#define _GNU_SOURCE
108117
#include <pthread.h>
109118
void check_pthread_setname_np() {
110119
pthread_setname_np("test");
@@ -114,6 +123,7 @@ AC_COMPILE_IFELSE(
114123
AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_MACOS], [1], [pthread_setname_np has macOS signature])],
115124
[AC_MSG_RESULT(no)]
116125
)
126+
CFLAGS="$save_CFLAGS"
117127

118128
dnl Solaris resolver solution:
119129
AC_SUBST(LIBGETNAMEINFO)

src/incoming.c

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ const char *inerr_labels[] = {
8181
"inerr_empty",
8282
"disallow_srccall",
8383
"disallow_dx",
84-
"disallow_msg_dst"
84+
"disallow_msg_dst",
85+
"disallow_igatecall"
8586
};
8687

8788
#define incoming_strerror(i) ((i <= 0 && i >= INERR_MIN) ? inerr_labels[i * -1] : inerr_labels[0])
@@ -679,10 +680,40 @@ int check_path_calls(const char *via_start, const char *path_end)
679680
}
680681

681682
//hlog(LOG_DEBUG, "check_path_calls returning %d", calls);
682-
683+
683684
return calls;
684685
}
685686

687+
/*
688+
* Check the comma-delimited fields starting at the Q construct (q_start)
689+
* and ending at path_end against the disallow_igate_glob set. This covers
690+
* both the Q construct itself (e.g. qAY) and the igate/receiver callsigns
691+
* following it, so a configured glob can drop based on either.
692+
* q_start points to the 'q' of the Q construct, path_end to the ':'.
693+
* Returns -1 if a disallowed field is found, 0 otherwise.
694+
*/
695+
696+
static int check_igate_calls(const char *q_start, const char *path_end)
697+
{
698+
const char *p = q_start;
699+
const char *e;
700+
701+
while (p < path_end) {
702+
e = p;
703+
/* find end of this path callsign */
704+
while (*e != ',' && e < path_end)
705+
e++;
706+
707+
/* check the field (the q construct itself, or an igate call) */
708+
if (check_call_glob_match(disallow_igate_glob, p, e-p))
709+
return -1;
710+
711+
p = e + 1;
712+
}
713+
714+
return 0;
715+
}
716+
686717
/*
687718
* Handle incoming messages to SERVER
688719
*/
@@ -951,7 +982,12 @@ int incoming_parse(struct worker_t *self, struct client_t *c, char *s, int len)
951982
hlog(LOG_DEBUG, "%s/%s: q construct drop: %d", c->addr_rem, c->username, path_append_len);
952983
return path_append_len;
953984
}
954-
985+
986+
/* check if any of the igate callsigns after the Q construct are disallowed */
987+
if (disallow_igate_glob && q_start != NULL && q_start >= s && q_start < path_end
988+
&& check_igate_calls(q_start, path_end) == -1)
989+
return INERR_DIS_IGATECALL; /* disallowed igate callsign */
990+
955991
/* get a packet buffer */
956992
int new_len;
957993
if (q_replace)

src/login.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -365,16 +365,31 @@ int login_handler(struct worker_t *self, struct client_t *c, int l4proto, char *
365365
break;
366366
}
367367

368-
if ((i+2 < argc && strcasecmp(argv[i+2], "filter") == 0) || (i+2 >= argc)) {
368+
const char *app_name = argv[i+1];
369+
const char *app_ver = (i+2 < argc) ? argv[i+2] : "";
370+
/* If the software name and version are not separated by a
371+
* space, the filter/udp keyword (or nothing) ends up as the
372+
* version number.
373+
*/
374+
int ver_missing = (i+2 >= argc) || (strcasecmp(app_ver, "filter") == 0);
375+
376+
/* set app name and version, which also determines whether
377+
* this is a known-broken client running in quirks mode
378+
*/
379+
login_set_app_name(c, app_name, app_ver);
380+
i += 2;
381+
382+
/* reject logins with a missing version number, unless the
383+
* client is in quirks mode (known-broken software, which
384+
* often does not send a proper version number)
385+
*/
386+
if (ver_missing && !c->quirks_mode) {
369387
hlog(LOG_WARNING, "%s/%s: vers app '%s' ver '%s': software name and version are not separated by a space",
370-
c->addr_rem, username, argv[i+1], argv[i+2]);
388+
c->addr_rem, username, app_name, app_ver);
371389
rc = client_printf(self, c, "# Invalid login: software name and version are not separated by a space\r\n");
372390
goto failed_login;
373391
}
374392

375-
login_set_app_name(c, argv[i+1], (i+2 < argc) ? argv[i+2] : "");
376-
i += 2;
377-
378393
} else if (strcasecmp(argv[i], "udp") == 0) {
379394
if (++i >= argc) {
380395
hlog(LOG_WARNING, "%s/%s: Missing UDP port number after UDP command", c->addr_rem, username);

src/worker.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,9 @@ struct client_heard_t {
224224
#define INERR_DIS_SRCCALL -33
225225
#define INERR_DIS_DX -34
226226
#define INERR_DIS_MSG_DST -35
227+
#define INERR_DIS_IGATECALL -36
227228

228-
#define INERR_MIN -35 /* MINIMUM VALUE FOR INERR, GROW WHEN NEEDED! */
229+
#define INERR_MIN -36 /* MINIMUM VALUE FOR INERR, GROW WHEN NEEDED! */
229230
/* WHEN ADDING STUFF HERE, REMEMBER TO UPDATE inerr_labels IN incoming.c. Thanks! */
230231
#define INERR_BUCKETS (INERR_MIN*-1 + 1)
231232

tests/cfg-aprsc/basic

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,5 @@ FileLimit 10000
8787
# Additional callsigns blocked
8888
DisallowSourceCall N7CALL N8CALL* *DROP DRG* OH?DRU O*ZZZ
8989
DisallowLoginCall LOGINA LOGINB *prrej mi*rej sufre*
90+
DisallowIgateCall IGDROP IG8CALL* *IGREJ IGR* OH?IGA qAY
9091

0 commit comments

Comments
 (0)