Skip to content

Commit

Permalink
check username and groupname before query
Browse files Browse the repository at this point in the history
  • Loading branch information
pyama86 committed Nov 2, 2023
1 parent 33e7dd0 commit eaa0850
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ ZLIB_VERSION=1.3
DIST ?= unknown
STNSD_VERSION=0.3.13

DIST_DIR:=/stns/tmp/$(DIST)
DIST_DIR:=$(shell pwd)/tmp/$(DIST)
SRC_DIR:=$(DIST_DIR)/src
STNS_DIR:=$(DIST_DIR)/stns
OPENSSL_DIR:=$(DIST_DIR)/openssl-$(OPENSSL_VERSION)
Expand Down
66 changes: 66 additions & 0 deletions stns.c
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,72 @@ int stns_exec_cmd(char *cmd, char *arg, stns_response_t *r)
return 1;
}

int is_valid_username(const char *username) {
if (username == NULL)
{
return 1;
}
size_t len = strlen(username);

// Check the length.
if (len == 0 || len > MAX_USERNAME_LENGTH)
{
return 1;
}

// The first character must be a alpha.
if (!(username[0] >= 'a' && username[0] <= 'z'))
{
return 1;
}

// The rest characters can be only alpha, digit, dash or underscore.
for (size_t i = 1; i < len; i++)
{
if (!(username[i] >= 'a' && username[i] <= 'z') &&
!(username[i] >= '0' && username[i] <= '9') &&
username[i] != '-' && username[i] != '_')
{
return 1;
}
}

return 0;
}

int is_valid_groupname(const char *groupname)
{
if (groupname == NULL)
{
return 1;
}
size_t len = strlen(groupname);

// Check the length.
if (len == 0 || len > MAX_GROUPNAME_LENGTH)
{
return 1;
}

// The first character must be a alpha.
if (!(groupname[0] >= 'a' && groupname[0] <= 'z'))
{
return 1;
}

// The rest characters can be only alpha, digit, dash or underscore.
for (size_t i = 1; i < len; i++)
{
if (!(groupname[i] >= 'a' && groupname[i] <= 'z') &&
!(groupname[i] >= '0' && groupname[i] <= '9') &&
groupname[i] != '-' && groupname[i] != '_')
{
return 1;
}
}

return 0;
}
extern int pthread_mutex_retrylock(pthread_mutex_t *mutex)
{
int i = 0;
Expand Down
14 changes: 12 additions & 2 deletions stns.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
#define STNS_HTTP_NOTFOUND 404L
#define STNS_LOCK_RETRY 3
#define STNS_LOCK_INTERVAL_MSEC 10

#define MAX_USERNAME_LENGTH 32
#define MAX_GROUPNAME_LENGTH 32
typedef struct stns_response_t stns_response_t;
struct stns_response_t {
char *data;
Expand Down Expand Up @@ -91,7 +92,8 @@ extern void set_user_highest_id(int);
extern void set_user_lowest_id(int);
extern void set_group_highest_id(int);
extern void set_group_lowest_id(int);

extern int is_valid_username(const char *username);
extern int is_valid_groupname(const char *username);
#define STNS_ENSURE_BY(method_key, key_type, key_name, json_type, json_key, match_method, resource, ltype) \
enum nss_status ensure_##resource##_by_##method_key(char *data, stns_conf_t *c, key_type key_name, \
struct resource *rbuf, char *buf, size_t buflen, int *errnop) \
Expand Down Expand Up @@ -330,6 +332,14 @@ extern void set_group_lowest_id(int);
return 1; \
}

#define USER_NAME_QUERY_AVAILABLE \
if (is_valid_username(name) != 0) \
return NSS_STATUS_NOTFOUND;

#define GROUP_NAME_QUERY_AVAILABLE \
if (is_valid_groupname(name) != 0) \
return NSS_STATUS_NOTFOUND;

#define USER_ID_QUERY_AVAILABLE \
if (!stns_user_highest_query_available(uid) || !stns_user_lowest_query_available(uid)) \
return NSS_STATUS_NOTFOUND;
Expand Down
2 changes: 1 addition & 1 deletion stns_group.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pthread_mutex_t grent_mutex = PTHREAD_MUTEX_INITIALIZER;
STNS_ENSURE_BY(name, const char *, group_name, string, name, (strcmp(current, group_name) == 0), group, GROUP)
STNS_ENSURE_BY(gid, gid_t, gid, number, id, current + (c->gid_shift) == gid, group, GROUP)

STNS_GET_SINGLE_VALUE_METHOD(getgrnam_r, const char *name, "groups?name=%s", name, group, , )
STNS_GET_SINGLE_VALUE_METHOD(getgrnam_r, const char *name, "groups?name=%s", name, group, GROUP_NAME_QUERY_AVAILABLE, )
STNS_GET_SINGLE_VALUE_METHOD(getgrgid_r, gid_t gid, "groups?id=%d", gid, group, GROUP_ID_QUERY_AVAILABLE,
-(c.gid_shift))
STNS_SET_ENTRIES(gr, GROUP, group, groups)
2 changes: 1 addition & 1 deletion stns_passwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ pthread_mutex_t pwent_mutex = PTHREAD_MUTEX_INITIALIZER;
STNS_ENSURE_BY(name, const char *, user_name, string, name, (strcmp(current, user_name) == 0), passwd, PASSWD)
STNS_ENSURE_BY(uid, uid_t, uid, number, id, current + (c->uid_shift) == uid, passwd, PASSWD)

STNS_GET_SINGLE_VALUE_METHOD(getpwnam_r, const char *name, "users?name=%s", name, passwd, , )
STNS_GET_SINGLE_VALUE_METHOD(getpwnam_r, const char *name, "users?name=%s", name, passwd, USER_NAME_QUERY_AVAILABLE, )
STNS_GET_SINGLE_VALUE_METHOD(getpwuid_r, uid_t uid, "users?id=%d", uid, passwd, USER_ID_QUERY_AVAILABLE, -(c.uid_shift))
STNS_SET_ENTRIES(pw, PASSWD, passwd, users)
2 changes: 1 addition & 1 deletion stns_shadow.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ pthread_mutex_t spent_mutex = PTHREAD_MUTEX_INITIALIZER;

STNS_ENSURE_BY(name, const char *, user_name, string, name, (strcmp(current, user_name) == 0), spwd, SHADOW)
STNS_ENSURE_BY(uid, uid_t, uid, number, id, current + (c->uid_shift) == uid, spwd, SHADOW)
STNS_GET_SINGLE_VALUE_METHOD(getspnam_r, const char *name, "users?name=%s", name, spwd, , )
STNS_GET_SINGLE_VALUE_METHOD(getspnam_r, const char *name, "users?name=%s", name, spwd, USER_NAME_QUERY_AVAILABLE, )
STNS_GET_SINGLE_VALUE_METHOD(getspuid_r, uid_t uid, "users?id=%d", uid, spwd, , -(c.uid_shift))
STNS_SET_ENTRIES(sp, SHADOW, spwd, users)
37 changes: 37 additions & 0 deletions stns_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,40 @@ Test(stns_request, http_request_notfound_with_cached)
cr_assert_eq(stns_request(&c, "status/404", &r), CURLE_HTTP_RETURNED_ERROR);
free(r.data);
}

Test(username_validation, valid_usernames) {
cr_assert(is_valid_username("username") == 0);
cr_assert(is_valid_username("user-name") == 0);
cr_assert(is_valid_username("username1") == 0);
}

Test(username_validation, invalid_usernames) {
cr_assert(is_valid_username("Username") == 1); // contains uppercase
cr_assert(is_valid_username("username!") == 1); // contains special char
cr_assert(is_valid_username("1username") == 1); // starts with digit
cr_assert(is_valid_username("") == 1); // empty string
cr_assert(is_valid_username(NULL) == 1); // NULL
char long_username[MAX_USERNAME_LENGTH + 2];
memset(long_username, 'a', sizeof(long_username) - 1);
long_username[sizeof(long_username) - 1] = '\0';
cr_assert(is_valid_username(long_username) == 1); // too long
}

Test(groupname_validation, valid_groupnames) {
cr_assert(is_valid_groupname("groupname") == 0);
cr_assert(is_valid_groupname("group-name") == 0);
cr_assert(is_valid_groupname("groupname1") == 0);
}

Test(groupname_validation, invalid_groupnames) {
cr_assert(is_valid_groupname("Groupname") == 1); // contains uppercase
cr_assert(is_valid_groupname("groupname!") == 1); // contains special char
cr_assert(is_valid_groupname("1groupname") == 1); // starts with digit
cr_assert(is_valid_groupname("") == 1); // empty string
cr_assert(is_valid_groupname(NULL) == 1); // NULL
// generate an overly long groupname
char long_groupname[MAX_GROUPNAME_LENGTH + 2];
memset(long_groupname, 'a', sizeof(long_groupname) - 1);
long_groupname[sizeof(long_groupname) - 1] = '\0';
cr_assert(is_valid_groupname(long_groupname) == 1); // too long
}

0 comments on commit eaa0850

Please sign in to comment.