jcs
/subtext
/amendments
/137
session: Close on banned username login attempt, track logged-in status
Ignore sessions that haven't logged in yet, and don't show guest
        username in 'who' and logs.
        Also show whether a user is a sysop in 'who'.
    jcs made amendment 137 over 3 years ago
--- session.c	Sun Jun 12 09:38:55 2022
+++ session.c	Sun Jun 12 12:06:51 2022
@@ -113,6 +113,8 @@ session_run(struct uthread *uthread, void *arg)
 		return;
 	}
 
+	s->logged_in = 1;
+	
 	/* update session log */
 	if (s->user) {
 		s->user->last_seen_at = Time;
@@ -341,7 +343,9 @@ session_log(struct session *session, const char *forma
 	va_end(ap);
 
 	return logger_printf(logger, "[%s] [%s] %s", session->node,
-	  session->user ? session->user->username : "guest", session_log_tbuf);
+	  session->logged_in ?
+	  (session->user ? session->user->username : "guest") : "-",
+	  session_log_tbuf);
 }
 
 size_t
@@ -756,6 +760,12 @@ session_login(struct session *s)
 			return AUTH_USER_SIGNUP;
 		} else {
 			user = user_find_by_username(username);
+			
+			if (!user && user_username_is_banned(username)) {
+				session_log(s, "Attempted login as banned username %s",
+				  username);
+				return AUTH_USER_FAILED;
+			}
 		}
 		
 		if (s->autologin_username[0]) {
@@ -1198,6 +1208,7 @@ void
 session_who(struct session *s)
 {
 	char idle_s[20];
+	char username[20];
 	unsigned long idle;
 	short n;
 	
@@ -1207,7 +1218,7 @@ session_who(struct session *s)
 	session_flush(s);
 	
 	for (n = 0; n < MAX_SESSIONS; n++) {
-		if (sessions[n] == NULL)
+		if (sessions[n] == NULL || !sessions[n]->logged_in)
 			continue;
 			
 		idle = Time - sessions[n]->last_input_at;
@@ -1220,9 +1231,13 @@ session_who(struct session *s)
 		else
 			sprintf(idle_s, "%ldd", idle / (60 * 60 * 24));
 
+		snprintf(username, sizeof(username), "%s%s",
+		  sessions[n]->user ? sessions[n]->user->username : GUEST_USERNAME,
+		  sessions[n]->user && sessions[n]->user->is_sysop ? " (sysop)" : "");
+
 		session_printf(s, "%-7s %-20s %-7s %-6d %-6s\r\n",
 		  sessions[n]->node,
-		  sessions[n]->user ? sessions[n]->user->username : GUEST_USERNAME,
+		  username,
 		  sessions[n]->via,
 		  sessions[n]->tspeed,
 		  idle_s);
--- session.h	Sun Jun 12 09:24:34 2022
+++ session.h	Sun Jun 12 11:45:43 2022
@@ -89,6 +89,7 @@ struct session {
 	unsigned char chatting;
 	unsigned char chatting_with_node[10];
 	unsigned char chat_ring_idx;
+	unsigned char logged_in;
 	struct session_log log;
 	char autologin_username[DB_USERNAME_LENGTH + 1];
 	struct user *user;
--- telnet.c	Wed Jun  1 13:10:41 2022
+++ telnet.c	Sun Jun 12 08:41:43 2022
@@ -280,10 +280,7 @@ telnet_input(struct session *session)
 	unsigned char c;
 	char iac_out[8] = { IAC, 0 };
 	
-	if (session->ending)
-		return 0;
-		
-	if (node->ibuflen >= sizeof(node->ibuf))
+	if (session->ending || node->ibuflen >= sizeof(node->ibuf))
 		return 0;
 		
 	if (node->rcv_pb.ioResult > 0)
--- user.c	Wed Jun  8 10:39:02 2022
+++ user.c	Sun Jun 12 10:38:54 2022
@@ -213,19 +213,17 @@ user_set_password(struct user *user, const char *passw
 	memset(&salt, 0, sizeof(salt));
 }
 
-short
+bool
 user_valid_username(struct user *user, char *username, char **error)
 {
-	char *lower = NULL;
 	struct user *ouser;
 	unsigned long ouser_id;
 	size_t len, n;
 	char c;
-	short ret = 0;
 	
 	if (username == NULL) {
 		*error = xstrdup("username cannot be empty");
-		goto done;
+		return false;
 	}
 	
 	len = strlen(username);
@@ -233,11 +231,9 @@ user_valid_username(struct user *user, char *username,
 		*error = xmalloc(61);
 		snprintf(*error, 60, "username cannot be more than %d characters",
 		  DB_USERNAME_LENGTH);
-		goto done;
+		return false;
 	}
 	
-	lower = xmalloc(len + 1);
-	
 	for (n = 0; n < len; n++) {
 		c = username[n];
 		
@@ -245,25 +241,19 @@ user_valid_username(struct user *user, char *username,
 		  (c >= 'a' && c <= 'z') || c == '_')) {
 			*error = xstrdup("username cannot contain non-alphanumeric "
 			  "characters");
-			goto done;
+			return false;
 		}
-		
-		lower[n] = tolower(username[n]);
 	}
-	lower[len] = '\0';
 	
-	if (strcmp(GUEST_USERNAME, lower) == 0) {
+	if (strcasecmp(username, GUEST_USERNAME) == 0) {
 		*error = xstrdup("username is already in use");
-		goto done;
+		return false;
 	}
 	
-	if (!(user != NULL && user->is_sysop)) {
-		for (n = 0; n < nitems(BANNED_USERNAMES); n++) {
-			if (strcmp(lower, BANNED_USERNAMES[n]) == 0) {
-				*error = xstrdup("username is not permitted");
-				goto done;
-			}
-		}
+	if (!(user != NULL && user->is_sysop) &&
+	  user_username_is_banned(username)) {
+		*error = xstrdup("username is not permitted");
+		return false;
 	}
 	
 	if ((ouser = user_find_by_username(username))) {
@@ -272,16 +262,24 @@ user_valid_username(struct user *user, char *username,
 		
 		if (user == NULL || ouser_id != user->id) {
 			*error = xstrdup("username is already in use");
-			goto done;
+			return false;
 		}
 	}
 	
-	ret = 1;
+	return true;
+}
+
+bool
+user_username_is_banned(char *username)
+{
+	size_t n;
 	
-done:
-	if (lower != NULL)
-		free(lower);
-	return ret;
+	for (n = 0; n < nitems(BANNED_USERNAMES); n++) {
+		if (strcasecmp(username, BANNED_USERNAMES[n]) == 0)
+			return true;
+	}
+	
+	return false;
 }
 
 char *
--- user.h	Wed Jun  8 10:38:23 2022
+++ user.h	Sun Jun 12 10:39:41 2022
@@ -49,7 +49,8 @@ struct user * user_find_by_username(const char *userna
 struct username_cache * user_find_username(unsigned long id);
 short user_authenticate(struct user *user, const char *password);
 void user_set_password(struct user *user, const char *password);
-short user_valid_username(struct user *user, char *username, char **error);
+bool user_valid_username(struct user *user, char *username, char **error);
+bool user_username_is_banned(char *username);
 char * user_first_sysop_username(void);
 void user_change_password(struct session *s, struct user *user);
 void user_delete(struct user *user);