jcs
/subtext
/amendments
/349
user: Handle malloc failure
jcs made amendment 349 about 1 year ago
--- user.c Thu Feb 23 17:10:10 2023
+++ user.c Wed Mar 1 19:44:21 2023
@@ -47,17 +47,19 @@ void
user_cache_usernames(void)
{
struct user user;
- struct username_cache *muser;
+ struct username_cache *muser, *new_username_cache;
struct bile_object *o;
- size_t nuser, len;
+ size_t new_nusers, nuser, len;
- if (db->username_cache != NULL)
- xfree(&db->username_cache);
+ new_nusers = bile_count_by_type(db->bile, DB_USER_RTYPE);
+ new_username_cache = xreallocarray(db->username_cache,
+ sizeof(struct username_cache), new_nusers);
+ if (new_username_cache == NULL)
+ return;
+
+ db->nusers = new_nusers;
+ db->username_cache = new_username_cache;
- db->nusers = bile_count_by_type(db->bile, DB_USER_RTYPE);
- db->username_cache = xmalloczero(sizeof(struct username_cache) *
- db->nusers, "username_cache");
-
nuser = 0;
while ((o = bile_get_nth_of_type(db->bile, nuser, DB_USER_RTYPE))) {
muser = &db->username_cache[nuser];
@@ -65,24 +67,28 @@ user_cache_usernames(void)
len = bile_read(db->bile, DB_USER_RTYPE, o->id, (char *)&user,
sizeof(user));
- if (len != sizeof(user))
+ if (len == sizeof(user))
+ strncpy(muser->username, user.username, sizeof(muser->username));
+ else {
warn("user_update_cache_map: user %lu read size %lu != %lu (%d)",
o->id, len, sizeof(user), bile_error(db->bile));
-
- strncpy(muser->username, user.username, sizeof(muser->username));
+ memset(muser->username, 0, sizeof(muser->username));
+ }
xfree(&o);
nuser++;
}
}
-void
+bool
user_save(struct user *user)
{
size_t len;
if (!user->id) {
user->id = bile_next_id(db->bile, DB_USER_RTYPE);
+ if (!user->id)
+ return false;
user->created_at = Time;
}
@@ -92,6 +98,7 @@ user_save(struct user *user)
panic("user_save: failed to write: %d", bile_error(db->bile));
bile_flush(db->bile, true);
+ return true;
}
struct user *
@@ -107,8 +114,9 @@ user_find(unsigned long id)
if (len != sizeof(struct user))
panic("user_find: bad user record size %lu != %lu", len,
sizeof(struct user));
- user = xmalloczero(sizeof(struct user), "user_find");
- memcpy(user, data, sizeof(struct user));
+ user = xmalloczero(sizeof(struct user));
+ if (user != NULL)
+ memcpy(user, data, sizeof(struct user));
xfree(&data);
return user;
}
@@ -161,7 +169,9 @@ user_authenticate(struct user *user, const char *passw
plen = strlen(password);
slen = SHA256_DIGEST_STRING_LENGTH - 1 + plen;
- salted = xmalloc(slen, "user_authenticate");
+ salted = xmalloc(slen);
+ if (salted == NULL)
+ return AUTH_USER_FAILED;
memcpy(salted, user->password_salt, SHA256_DIGEST_STRING_LENGTH - 1);
memcpy(salted + SHA256_DIGEST_STRING_LENGTH - 1, password, plen);
@@ -181,7 +191,7 @@ user_authenticate(struct user *user, const char *passw
return AUTH_USER_FAILED;
}
-void
+bool
user_set_password(struct user *user, const char *password)
{
char hash[SHA256_DIGEST_STRING_LENGTH];
@@ -200,7 +210,9 @@ user_set_password(struct user *user, const char *passw
plen = strlen(password);
slen = plen + sizeof(salt) - 1;
- salted = xmalloc(slen, "user_set_password");
+ salted = xmalloc(slen);
+ if (salted == NULL)
+ return false;
memcpy(salted, salt, sizeof(salt) - 1); /* exclude null */
memcpy(salted + sizeof(salt) - 1, password, plen);
SHA256Data((const u_int8_t *)salted, slen, hash);
@@ -211,6 +223,7 @@ user_set_password(struct user *user, const char *passw
memset(&hash, 0, sizeof(hash));
memset(&salt, 0, sizeof(salt));
+ return true;
}
bool
@@ -222,15 +235,16 @@ user_valid_username(struct user *user, char *username,
char c;
if (username == NULL) {
- *error = xstrdup("username cannot be empty", "user_valid_username");
+ *error = xstrdup("username cannot be empty");
return false;
}
len = strlen(username);
if (len > DB_USERNAME_LENGTH) {
- *error = xmalloc(61, "user_valid_username");
- snprintf(*error, 60, "username cannot be more than %d characters",
- DB_USERNAME_LENGTH);
+ *error = xmalloc(61);
+ if (*error)
+ snprintf(*error, 60, "username cannot be more than %d "
+ "characters", DB_USERNAME_LENGTH);
return false;
}
@@ -240,20 +254,19 @@ user_valid_username(struct user *user, char *username,
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') || c == '_')) {
*error = xstrdup("username cannot contain non-alphanumeric "
- "characters", "user_valid_username");
+ "characters");
return false;
}
}
if (strcasecmp(username, GUEST_USERNAME) == 0) {
- *error = xstrdup("username is already in use",
- "user_valid_username");
+ *error = xstrdup("username is already in use");
return false;
}
if (!(user != NULL && user->is_sysop) &&
user_username_is_banned(username)) {
- *error = xstrdup("username is not permitted", "user_valid_username");
+ *error = xstrdup("username is not permitted");
return false;
}
@@ -262,8 +275,7 @@ user_valid_username(struct user *user, char *username,
xfree(&ouser);
if (user == NULL || ouser_id != user->id) {
- *error = xstrdup("username is already in use",
- "user_valid_username");
+ *error = xstrdup("username is already in use");
return false;
}
}
@@ -298,7 +310,7 @@ user_first_sysop_username(void)
sizeof(user));
xfree(&o);
if (user.is_sysop) {
- ret = xstrdup(user.username, "user_first_sysop_username");
+ ret = xstrdup(user.username);
break;
}
nuser++;
@@ -348,15 +360,26 @@ user_change_password(struct session *s, struct user *u
if (strcmp(password_confirm, password) != 0) {
session_printf(s, "{{B}}Error:{{/B}} "
"Passwords do not match\r\n");
+ memset(password, 0, strlen(password));
xfree(&password);
- password = NULL;
+ memset(password_confirm, 0, strlen(password_confirm));
xfree(&password_confirm);
- password_confirm = NULL;
continue;
}
- user_set_password(user, password);
- user_save(user);
+ if (!user_set_password(user, password)) {
+ session_logf(s, "Failed saving new password");
+ session_printf(s, "{{B}}Error:{{/B}} "
+ "Failed saving new password\r\n");
+ break;
+ }
+
+ if (!user_save(user)) {
+ session_logf(s, "Failed saving user account");
+ session_printf(s, "{{B}}Error:{{/B}} "
+ "Failed saving user account\r\n");
+ break;
+ }
if (strcmp(s->user->username, user->username) == 0) {
session_logf(s, "User changed password");
@@ -372,10 +395,14 @@ user_change_password(struct session *s, struct user *u
break;
}
- if (password != NULL)
+ if (password != NULL) {
+ memset(password, 0, strlen(password));
xfree(&password);
- if (password_confirm != NULL)
+ }
+ if (password_confirm != NULL) {
+ memset(password_confirm, 0, strlen(password_confirm));
xfree(&password_confirm);
+ }
}
void
--- user.h Wed Sep 14 16:36:17 2022
+++ user.h Wed Mar 1 17:39:06 2023
@@ -44,12 +44,12 @@ struct username_cache {
};
void user_cache_usernames(void);
-void user_save(struct user *user);
+bool user_save(struct user *user);
struct user * user_find(unsigned long id);
struct user * user_find_by_username(const char *username);
struct username_cache * user_username(unsigned long id);
short user_authenticate(struct user *user, const char *password);
-void user_set_password(struct user *user, const char *password);
+bool user_set_password(struct user *user, const char *password);
bool user_valid_username(struct user *user, char *username, char **error);
bool user_username_is_banned(char *username);
char * user_first_sysop_username(void);