diff --git a/include/struct.h b/include/struct.h
index 2dba14c3..1eeb1a20 100644
--- a/include/struct.h
+++ b/include/struct.h
@@ -1161,8 +1161,8 @@ struct LocalClient {
 #endif
 	char *error_str;		/**< Quit reason set by dead_socket() in case of socket/buffer error, later used by exit_client() */
 	char sasl_agent[NICKLEN + 1];	/**< SASL: SASL Agent the user is interacting with */
-	unsigned char sasl_out;		/**< SASL: Number of outgoing sasl messages */
-	unsigned char sasl_complete;	/**< SASL: >0 if SASL authentication was successful */
+	unsigned char sasl_out;		/**< SASL: Indicates that sasl auth is in progress and sasl messages have been sent */
+	unsigned char sasl_complete;	/**< SASL: >0 if SASL authentication is successful. Only used to discard any repeated SVSLOGIN command */
 	char *sni_servername;		/**< Servername as sent by client via SNI (Server Name Indication) in SSL/TLS, otherwise NULL */
 	int cap_protocol;		/**< CAP protocol in use. At least 300 for any CAP capable client. 302 for 3.2, etc.. */
 	uint32_t nospoof;		/**< Anti-spoofing random number (used in user handshake PING/PONG) */
diff --git a/src/modules/sasl.c b/src/modules/sasl.c
index e4a22696..ea4af795 100644
--- a/src/modules/sasl.c
+++ b/src/modules/sasl.c
@@ -37,12 +37,13 @@ char *saslmechlist_serialize(ModData *m);
 void saslmechlist_unserialize(char *str, ModData *m);
 char *sasl_capability_parameter(Client *client);
 int sasl_server_synched(Client *client);
+static void abort_sasl_inform_agent(Client *);
 
 /* Macros */
 #define MSG_AUTHENTICATE "AUTHENTICATE"
 #define MSG_SASL "SASL"
 #define MSG_SVSLOGIN "SVSLOGIN"
-#define AGENT_SID(agent_p)	(agent_p->user != NULL ? agent_p->user->server : agent_p->name)
+#define AGENT_SID(agent)	(agent->user != NULL ? agent->user->server : agent->name)
 
 /* Variables */
 long CAP_SASL = 0L;
@@ -83,6 +84,13 @@ CMD_FUNC(cmd_svslogin)
 		if (!target || !MyConnect(target))
 			return;
 
+		/* reject repeated SVSLOGIN messages */
+		if ((target->local->sasl_complete == 0) && (target->local->sasl_out != 0))
+			target->local->sasl_complete = 2;
+		else if (target->local->sasl_complete++ == 1);
+		else
+			return;
+
 		if (target->user == NULL)
 			make_user(target);
 
@@ -93,13 +101,18 @@ CMD_FUNC(cmd_svslogin)
 			   BadPtr(target->user->username) ? "*" : target->user->username,
 			   BadPtr(target->user->realhost) ? "*" : target->user->realhost,
 			   target->user->svid, target->user->svid);
-
-		return;
 	}
-
 	/* not for us; propagate. */
-	sendto_server(client, 0, 0, NULL, ":%s SVSLOGIN %s %s %s",
-	    client->name, parv[1], parv[2], parv[3]);
+	else
+	{
+		Client *targetserver = NULL;
+
+		if ((targetserver = find_server(parv[1], NULL)) != NULL)
+		{
+			sendto_one(targetserver, NULL, ":%s SVSLOGIN %s %s %s",
+				client->name, parv[1], parv[2], parv[3]);
+		}
+	}
 }
 
 /*
@@ -124,12 +137,17 @@ CMD_FUNC(cmd_sasl)
 		if (!target || !MyConnect(target))
 			return;
 
-		if (target->user == NULL)
-			make_user(target);
+		/* reject SASL messages if auth session has been aborted */
+		if (target->local->sasl_out == 0)
+			return;
 
 		/* reject if another SASL agent is answering */
-		if (*target->local->sasl_agent && strcasecmp(client->name, target->local->sasl_agent))
-			return;
+		/* don't copy if client->name matches the existing sasl_agent string */
+		if (*target->local->sasl_agent)
+		{
+			if (strcasecmp(client->name, target->local->sasl_agent))
+				return;
+		}
 		else
 			strlcpy(target->local->sasl_agent, client->name, sizeof(target->local->sasl_agent));
 
@@ -140,7 +158,12 @@ CMD_FUNC(cmd_sasl)
 		}
 		else if (*parv[3] == 'D')
 		{
+			/* reset to allow other sasl agents to answer our SASL message */
 			*target->local->sasl_agent = '\0';
+			/* Now, we reset our sasl_out counter to indicate that the sasl server is aware that
+			 * the sasl auth is (un)successful. This action prevents us from sending unnecessary
+			 * sasl abort messages to the sasl server */
+			target->local->sasl_out = 0;
 			if (*parv[4] == 'F')
 			{
 				target->local->since += 7; /* bump fakelag due to failed authentication attempt */
@@ -156,13 +179,25 @@ CMD_FUNC(cmd_sasl)
 		}
 		else if (*parv[3] == 'M')
 			sendnumeric(target, RPL_SASLMECHS, parv[4]);
-
-		return;
 	}
-
 	/* not for us; propagate. */
-	sendto_server(client, 0, 0, NULL, ":%s SASL %s %s %c %s %s",
-	    client->name, parv[1], parv[2], *parv[3], parv[4], parc > 5 ? parv[5] : "");
+	else
+	{
+		Client *targetserver = NULL;
+
+		if(*parv[1] == '*')
+		{
+			/* XXX: Remove this in the next major release, we're keeping this for v4 compatibility sake.
+			 * Sending a network-wide sasl message which is addressed to '*' is a bad idea */
+			sendto_server(client, 0, 0, NULL, ":%s SASL %s %s %c %s %s",
+				client->name, parv[1], parv[2], *parv[3], parv[4], parc > 5 ? parv[5] : "");
+		}
+		else if ((targetserver = find_server(parv[1], NULL)) != NULL)
+		{
+			sendto_one(targetserver, NULL, ":%s SASL %s %s %c %s %s",
+				client->name, parv[1], parv[2], *parv[3], parv[4], parc > 5 ? parv[5] : "");
+		}
+	}
 }
 
 /*
@@ -172,71 +207,112 @@ CMD_FUNC(cmd_sasl)
  */
 CMD_FUNC(cmd_authenticate)
 {
-	Client *agent_p = NULL;
+	Client *agent = NULL;
+	Client *saslserv = NULL;
 
 	/* Failing to use CAP REQ for sasl is a protocol violation. */
 	if (!SASL_SERVER || !MyConnect(client) || BadPtr(parv[1]) || !HasCapability(client, "sasl"))
 		return;
 
-	if ((parv[1][0] == ':') || strchr(parv[1], ' '))
+	if ((parv[1][0] == ':') || strchr(parv[1], ' ') || !strcmp(parv[1], "*"))
 	{
-		sendnumeric(client, ERR_CANNOTDOCOMMAND, "AUTHENTICATE", "Invalid parameter");
+		sendnumeric(client, ERR_SASLABORTED);
+		if (client->local->sasl_out != 0)
+			abort_sasl_inform_agent(client);
 		return;
 	}
 
 	if (strlen(parv[1]) > 400)
 	{
 		sendnumeric(client, ERR_SASLTOOLONG);
+		if (client->local->sasl_out != 0)
+			abort_sasl_inform_agent(client);
 		return;
 	}
 
+	/* logically we need to reset the sasl_complete counter because sasl auth has been restarted */
+	client->local->sasl_complete = 0;
+
 	if (*client->local->sasl_agent)
-		agent_p = find_client(client->local->sasl_agent, NULL);
+		agent = find_client(client->local->sasl_agent, NULL);
 
-	if (agent_p == NULL)
+	saslserv = find_client(SASL_SERVER, NULL);
+
+	/* If user is trying to auth for the first time or trying to reauth, agent needs to be NULL 
+	 * in order to send the information below */
+	if (agent == NULL)
 	{
+		/* Don't bother to abort_sasl_inform_agent() because we do not have a destination to send
+		 * the sasl abort message to. */
+		if (saslserv == NULL)
+		{
+			sendnumeric(client, ERR_SASLABORTED);
+			client->local->sasl_out = 0;
+			*client->local->sasl_agent = '\0';
+			return;
+		}
+
 		char *addr = BadPtr(client->ip) ? "0" : client->ip;
 		char *certfp = moddata_client_get(client, "certfp");
 
-		sendto_server(NULL, 0, 0, NULL, ":%s SASL %s %s H %s %s",
-		    me.name, SASL_SERVER, client->id, addr, addr);
+		sendto_one(saslserv, NULL, ":%s SASL %s %s H %s %s",
+			me.name, SASL_SERVER, client->id, addr, addr);
 
 		if (certfp)
-			sendto_server(NULL, 0, 0, NULL, ":%s SASL %s %s S %s %s",
-			    me.name, SASL_SERVER, client->id, parv[1], certfp);
+			sendto_one(saslserv, NULL, ":%s SASL %s %s S %s %s",
+				me.name, SASL_SERVER, client->id, parv[1], certfp);
 		else
-			sendto_server(NULL, 0, 0, NULL, ":%s SASL %s %s S %s",
-			    me.name, SASL_SERVER, client->id, parv[1]);
+			sendto_one(saslserv, NULL, ":%s SASL %s %s S %s",
+				me.name, SASL_SERVER, client->id, parv[1]);
+
+		/* sasl_agent also indicates if sasl server has replied our sasl message. If it hasn't
+		 * replied and user chooses to redo auths process, we have the freedom to resend the
+		 * information above. Hence do not set the value of sasl_agent here! */
 	}
 	else
-		sendto_server(NULL, 0, 0, NULL, ":%s SASL %s %s C %s",
-		    me.name, AGENT_SID(agent_p), client->id, parv[1]);
+	{
+		sendto_one(agent, NULL, ":%s SASL %s %s C %s",
+			me.name, AGENT_SID(agent), client->id, parv[1]);
+	}
 
 	client->local->sasl_out++;
 }
 
-static int abort_sasl(Client *client)
+/* Informs sasl agents that SASL authentication has been aborted
+ *
+ * Since we now inform sasl server of any aborted sasl auth that is _in progress_, this
+ * function has been modified and now it is also being called in cmd_authenticate function
+ *
+ * Careful, always check values of sasl_out before calling this function because we no
+ * longer do condition checking internally.
+ *
+ * Also, note that the appropriate numerics need to be sent independently! */
+static void abort_sasl_inform_agent(Client *client)
 {
-	if (client->local->sasl_out == 0 || client->local->sasl_complete)
-		return 0;
+	Client *saslserv = NULL;
+	if(SASL_SERVER)
+		saslserv = find_client(SASL_SERVER, NULL);
 
-	client->local->sasl_out = client->local->sasl_complete = 0;
-	sendnumeric(client, ERR_SASLABORTED);
+	client->local->sasl_out = 0;
 
 	if (*client->local->sasl_agent)
 	{
-		Client *agent_p = find_client(client->local->sasl_agent, NULL);
-
-		if (agent_p != NULL)
+		Client *agent = find_client(client->local->sasl_agent, NULL);
+		/* reset to allow other sasl agents to answer our SASL message */
+		*client->local->sasl_agent = '\0';
+		if (agent != NULL)
 		{
-			sendto_server(NULL, 0, 0, NULL, ":%s SASL %s %s D A",
-			    me.name, AGENT_SID(agent_p), client->id);
-			return 0;
+			sendto_one(agent, NULL, ":%s SASL %s %s D A",
+				me.name, AGENT_SID(agent), client->id);
+			return;
 		}
 	}
 
-	sendto_server(NULL, 0, 0, NULL, ":%s SASL * %s D A", me.name, client->id);
-	return 0;
+	/* We need to inform the sasl agent that client's SASL auth has been aborted but in
+	 * the scenario below, we do not know who the agent is. Starting from v5.0 we only
+	 * inform SASL_SERVER instead of broadcasting sasl abort message network-wide. */
+	if(saslserv)
+		sendto_one(saslserv, NULL, ":%s SASL %s %s D A", me.name, SASL_SERVER, client->id);
 }
 
 /** Is this capability visible?
@@ -266,12 +342,22 @@ int sasl_capability_visible(Client *client)
 
 int sasl_connect(Client *client)
 {
-	return abort_sasl(client);
+	if (client->local->sasl_out != 0)
+	{
+		sendnumeric(client, ERR_SASLABORTED);
+		abort_sasl_inform_agent(client);
+	}
+	return 0;
 }
 
 int sasl_quit(Client *client, MessageTag *mtags, char *comment)
 {
-	return abort_sasl(client);
+	if (client->local->sasl_out != 0)
+	{
+		sendnumeric(client, ERR_SASLABORTED);
+		abort_sasl_inform_agent(client);
+	}
+	return 0;
 }
 
 int sasl_server_quit(Client *client, MessageTag *mtags)
