Skip to content

Commit 9dfddfc

Browse files
committed
libnss_tcb: Disallow potentially-malicious user names in getspnam(3).
Signed-off-by: Björn Esser <[email protected]>
1 parent 0f4837b commit 9dfddfc

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

ChangeLog

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
2021-12-18 Björn Esser <besser82 at fedoraproject.org>
1+
2024-12-20 Björn Esser <besser82 at fedoraproject.org>
2+
3+
libnss_tcb: Disallow potentially-malicious user names in getspnam(3).
4+
* libs/nss.c (_nss_tcb_getspnam_r): Check for potentially-malicious
5+
user names, and bail out in case.
6+
7+
2024-12-18 Björn Esser <besser82 at fedoraproject.org>
28

39
libtcb: Add versioning to exported symbols.
410
This change is implemented for adding some interfaces to libtcb to

libs/nss.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,30 @@ int _nss_tcb_endspent(void)
2727
return 1;
2828
}
2929

30+
/* IEEE Std 1003.1-2001 allows only the following characters to appear
31+
in group- and usernames: letters, digits, underscores, periods,
32+
<at>-signs (@), and dashes. The name may not start with a dash or @.
33+
The "$" sign is allowed at the end of usernames to allow typical
34+
Samba machine accounts. */
35+
static int
36+
is_valid_username (const char *un)
37+
{
38+
if (!un || !*un || un[0] == '-' || un[0] == '@' ||
39+
/* curdir || parentdir */
40+
!strcmp(un, ".") || !strcmp(un, ".."))
41+
return 0;
42+
43+
do {
44+
char c = *un++;
45+
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
46+
(c >= '0' && c <= '9') || c == '-' || c == '.' ||
47+
c == '@' || c == '_' || (!*un && c == '$')))
48+
return 0;
49+
} while (*un);
50+
51+
return 1;
52+
}
53+
3054
static FILE *tcb_safe_open(const char *file, const char *name)
3155
{
3256
gid_t grplist[TCB_NGROUPS];
@@ -64,12 +88,18 @@ int _nss_tcb_getspnam_r(const char *name, struct spwd *__result_buf,
6488
char *file;
6589
int retval, saved_errno;
6690

91+
/* Disallow potentially-malicious user names */
92+
if (!is_valid_username(name)) {
93+
errno = ENOENT;
94+
return NSS_STATUS_NOTFOUND;
95+
}
96+
6797
if (asprintf(&file, TCB_FMT, name) < 0)
6898
return NSS_STATUS_TRYAGAIN;
6999
f = tcb_safe_open(file, name);
70100
free(file);
71101
if (!f)
72-
return NSS_STATUS_UNAVAIL;
102+
return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
73103

74104
retval = fgetspent_r(f, __result_buf, __buffer, __buflen, __result);
75105
saved_errno = errno;

0 commit comments

Comments
 (0)