Skip to content

Commit

Permalink
Add: New --user-session-limit option
Browse files Browse the repository at this point in the history
The new option --user-session-limit allows limiting the number of
logged in sessions per user.
  • Loading branch information
timopollmeier committed Sep 4, 2023
1 parent 8117bd6 commit a08d49b
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 27 deletions.
3 changes: 3 additions & 0 deletions doc/gsad.8
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ Sets the maximum number of connections per ip. Use 0 for unlimited.
.BR --http-cors=\fICORS\fR
Set Cross-Origin Resource Sharing (CORS) allow origin http header.
.TP
.BR --user-session-limit=\fIMAX_SESSIONS\fR
Set maximum number of active sessions per user. 0 for unlimited.
.TP
.BR -? ", " --help
Show help.
.SH EXAMPLES
Expand Down
7 changes: 7 additions & 0 deletions doc/gsad.8.xml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
<optdesc><p>Do chroot and drop privileges.</p></optdesc>
</option>

<option>
<p><opt>--user-session-limit=<arg>MAX_SESSIONS</arg></opt></p>
<optdesc>
<p>Set maximum number of active sessions per user. 0 for unlimited.</p>
</optdesc>
</option>

<option>
<p><opt>-v, --verbose</opt></p>
<optdesc>
Expand Down
5 changes: 5 additions & 0 deletions doc/gsad.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ <h2>Options</h2>



<p><b>--user-session-limit=<em>MAX_SESSIONS</em></b></p>
<p>Set maximum number of active sessions per user. 0 for unlimited.</p>



<p><b>-v, --verbose</b></p>

<p>Print progress messages.</p>
Expand Down
7 changes: 7 additions & 0 deletions src/gsad.c
Original file line number Diff line number Diff line change
Expand Up @@ -2180,6 +2180,7 @@ main (int argc, char **argv)
static gboolean ignore_x_real_ip = FALSE;
static int per_ip_connection_limit = DEFAULT_GSAD_PER_IP_CONNECTION_LIMIT;
static int verbose = 0;
static int gsad_user_session_limit = 0;
GError *error = NULL;
GOptionContext *option_context;
static GOptionEntry option_entries[] = {
Expand Down Expand Up @@ -2266,6 +2267,10 @@ main (int argc, char **argv)
{"http-cors", 0, 0, G_OPTION_ARG_STRING, &http_cors,
"Set Cross-Origin Resource Sharing (CORS) allow origin http header ",
"<cors>"},
{"user-session-limit", '\0', 0, G_OPTION_ARG_INT,
&gsad_user_session_limit,
"Set maximum number of active sessions per user. 0 for unlimited.",
"<max-sessions>"},
{NULL}};

option_context =
Expand Down Expand Up @@ -2484,6 +2489,8 @@ main (int argc, char **argv)
}
}

set_user_session_limit (gsad_user_session_limit);

/* Register the cleanup function. */

if (atexit (&gsad_cleanup))
Expand Down
30 changes: 23 additions & 7 deletions src/gsad_gmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -11144,7 +11144,8 @@ save_my_settings_gmp (gvm_connection_t *connection, credentials_t *credentials,
if (gmp_success (entity) == 1)
{
user_set_password (user, passwd);
session_remove_other_sessions (user_get_token (user), user);
session_remove_other_sessions (user_get_token (user),
user_get_username (user));
user_changed = 1;
}
else
Expand Down Expand Up @@ -14525,16 +14526,13 @@ save_user_gmp (gvm_connection_t *connection, credentials_t *credentials,
case 0:
if (gmp_success (entity) == 1)
{
user_t *user = session_get_user_by_username (old_login);

if (user
&& (!str_equal (modify_password, "0")
|| !str_equal (old_login, login)))
if (!str_equal (modify_password, "0")
|| !str_equal (old_login, login))
{
/* logout all other user sessions if new password was set,
authentication type has changed or username has changed */
session_remove_other_sessions (user_get_token (current_user),
user);
old_login);
}

if (str_equal (old_login, user_get_username (current_user)))
Expand Down Expand Up @@ -16980,6 +16978,24 @@ login (http_connection_t *con, params_t *params,
user = user_add (login, password, timezone, role, capabilities,
language, pw_warning, client_address);

if (user == NULL)
{
status = MHD_HTTP_UNAUTHORIZED;
auth_reason = TOO_MANY_USER_SESSIONS;

g_warning ("Authentication failure for '%s' from %s."
" Too many sessions for user.",
login ?: "", client_address);

g_free (timezone);
g_free (capabilities);
g_free (language);
g_free (role);
g_free (pw_warning);

return handler_send_reauthentication (con, status, auth_reason);
}

g_message ("Authentication success for '%s' from %s", login ?: "",
client_address);

Expand Down
3 changes: 3 additions & 0 deletions src/gsad_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,9 @@ handler_send_reauthentication (http_connection_t *connection,
case LOGOUT:
msg = "Successfully logged out.";
break;
case TOO_MANY_USER_SESSIONS:
msg = "Login failed. Too many concurrent logins for user.";
break;
case UNKOWN_ERROR:
msg = "Unknown error.";
break;
Expand Down
1 change: 1 addition & 0 deletions src/gsad_http.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ enum authentication_reason
SESSION_EXPIRED,
BAD_MISSING_COOKIE,
BAD_MISSING_TOKEN,
TOO_MANY_USER_SESSIONS,
UNKOWN_ERROR,
};

Expand Down
31 changes: 19 additions & 12 deletions src/gsad_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "gsad_session.h"

#include "gsad_user.h"
#include "gsad_gmp_auth.h"
#include "utils.h" /* for str_equal */

#undef G_LOG_DOMAIN
Expand Down Expand Up @@ -107,15 +108,15 @@ session_get_user_by_id (const gchar *id)
}

/**
* Find the first user with the username
* Find all users with the given username
*
* @return Return a copy of the user or NULL if not found
* @return Return a list with copies of the users or NULL if not found
*/
user_t *
session_get_user_by_username (const gchar *username)
GList *
session_get_users_by_username (const gchar *username)
{
int index;
user_t *user = NULL;
GList *list = NULL;

g_mutex_lock (mutex);

Expand All @@ -126,14 +127,15 @@ session_get_user_by_username (const gchar *username)

if (str_equal (name, username))
{
user_t *user = NULL;
user = user_copy (item);
break;
list = g_list_prepend (list, user);
}
}

g_mutex_unlock (mutex);

return user;
return list;
}

/**
Expand Down Expand Up @@ -172,12 +174,12 @@ session_remove_user (const gchar *id)
/**
* @brief Removes all session of the user, except the one with the passed id.
*
* @param[in] id ID of the session to keep
* @param[in] user The user to logout.
* @param[in] keep_id ID of the session to keep
* @param[in] username The user to logout.
*
*/
void
session_remove_other_sessions (const gchar *id, user_t *user)
session_remove_other_sessions (const gchar *keep_id, const gchar *username)
{
int index;

Expand All @@ -189,12 +191,17 @@ session_remove_other_sessions (const gchar *id, user_t *user)

const gchar *itemtoken = user_get_token (item);
const gchar *itemname = user_get_username (item);
const gchar *username = user_get_username (user);

if (str_equal (itemname, username) && !str_equal (id, itemtoken))
if (str_equal (itemname, username) && !str_equal (keep_id, itemtoken))
{
const char *itempassword = user_get_password (item);

g_debug ("%s: logging out user '%s', token '%s'", __func__, itemname,
itemtoken);

if (itemname && itempassword)
logout_gmp (itemname, itempassword);

g_ptr_array_remove (users, (gpointer) item);

user_free (item);
Expand Down
6 changes: 3 additions & 3 deletions src/gsad_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ session_remove_user (const gchar *id);
user_t *
session_get_user_by_id (const gchar *id);

user_t *
session_get_user_by_username (const gchar *username);
GList *
session_get_users_by_username (const gchar *username);

void
session_remove_other_sessions (const gchar *id, user_t *user);
session_remove_other_sessions (const gchar *id, const gchar *user);

void
session_init ();
Expand Down
20 changes: 20 additions & 0 deletions src/gsad_settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ int unix_socket = 0;
*/
int use_secure_cookie = 1;

/**
* @brief The maximum number of logged in sessions per user.
*/
int user_session_limit = 0;

/**
* @brief Set the vendor version.
*
Expand Down Expand Up @@ -276,3 +281,18 @@ is_unix_socket ()
{
return unix_socket > 0;
}

void
set_user_session_limit (int new_limit)
{
if (new_limit >= 0)
user_session_limit = new_limit;
else
user_session_limit = 0;
}

int
get_user_session_limit ()
{
return user_session_limit;
}
6 changes: 6 additions & 0 deletions src/gsad_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,10 @@ get_guest_password ();
gboolean
is_ignore_http_x_real_ip ();

void
set_user_session_limit (int);

int
get_user_session_limit ();

#endif /* _GSAD_SETTINGS_H */
26 changes: 21 additions & 5 deletions src/gsad_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,15 +325,31 @@ user_add (const gchar *username, const gchar *password, const gchar *timezone,
const gchar *role, const gchar *capabilities, const gchar *language,
const gchar *pw_warning, const char *address)
{
user_t *user = session_get_user_by_username (username);
GList *current_user_item, *user_list;
user_t *user;
int session_count = 0;

if (user && user_session_expired (user))
user_list = current_user_item = session_get_users_by_username (username);
while (current_user_item)
{
if (user->username && user->password)
logout_gmp (user->username, user->password);
session_remove_user (user->token);
user = current_user_item->data;
if (user_session_expired (user))
{
if (user->username && user->password)
logout_gmp (user->username, user->password);
session_remove_user (user->token);
}
else
session_count ++;
user_free (user);
current_user_item = current_user_item->next;
}
g_list_free (user_list);

int session_limit = get_user_session_limit ();
if (session_limit && (session_count >= session_limit))

return NULL;

user = user_new_with_data (username, password, timezone, role, capabilities,
language, pw_warning, address);
Expand Down

0 comments on commit a08d49b

Please sign in to comment.