sasl_user_can_login(struct sasl_session *const restrict p)
{
	// source_mu is the user whose credentials we verified ("authentication id" / authcid)
	// target_mu is the user who will be ultimately logged in ("authorization id" / authzid)
	struct myuser *source_mu;
	struct myuser *target_mu;

	if (! *p->authceid || ! (source_mu = myuser_find_uid(p->authceid)))
		return NULL;

	if (! *p->authzeid)
	{
		target_mu = source_mu;

		(void) mowgli_strlcpy(p->authzid, p->authcid, sizeof p->authzid);
		(void) mowgli_strlcpy(p->authzeid, p->authceid, sizeof p->authzeid);
	}
	else if (! (target_mu = myuser_find_uid(p->authzeid)))
		return NULL;

	if (! sasl_may_impersonate(source_mu, target_mu))
	{
		(void) logcommand(p->si, CMDLOG_LOGIN, "denied IMPERSONATE by \2%s\2 to \2%s\2",
		                                       entity(source_mu)->name, entity(target_mu)->name);
		return NULL;
	}

	if (! (target_mu->flags & MU_LOGINNOLIMIT)
		&& !has_priv_myuser(target_mu, PRIV_LOGIN_NOLIMIT)
		&& MOWGLI_LIST_LENGTH(&target_mu->logins) >= me.maxlogins)
	{
		(void) logcommand(p->si, CMDLOG_LOGIN, "failed LOGIN to \2%s\2 (too many logins)",
		                                       entity(target_mu)->name);
		return NULL;
	}

	/* We just did SASL authentication for a user.  With IRCds which do not
	 * have unique UIDs for users, we will likely be expecting the login
	 * data to be bursted.  As a result, we should give the core a heads'
	 * up that this is going to happen so that hooks will be properly
	 * fired...
	 */
	if (ircd->flags & IRCD_SASL_USE_PUID)
	{
		target_mu->flags &= ~MU_NOBURSTLOGIN;
		target_mu->flags |= MU_PENDINGLOGIN;
	}

	if (target_mu != source_mu)
		(void) logcommand(p->si, CMDLOG_LOGIN, "allowed IMPERSONATE by \2%s\2 to \2%s\2",
		                                       entity(source_mu)->name, entity(target_mu)->name);

	return target_mu;
}
sasl_user_can_login(struct sasl_session *const restrict p)
{
	 
	 
	struct myuser *source_mu;
	struct myuser *target_mu;

	if (! *p->authceid || ! (source_mu = myuser_find_uid(p->authceid)))
		return NULL;

	if (! *p->authzeid)
	{
		target_mu = source_mu;

		(void) mowgli_strlcpy(p->authzid, p->authcid, sizeof p->authzid);
		(void) mowgli_strlcpy(p->authzeid, p->authceid, sizeof p->authzeid);
	}
	else if (! (target_mu = myuser_find_uid(p->authzeid)))
		return NULL;

	if (! sasl_may_impersonate(source_mu, target_mu))
	{
		(void) logcommand(p->si, CMDLOG_LOGIN, "denied IMPERSONATE by \2%s\2 to \2%s\2",
		                                       entity(source_mu)->name, entity(target_mu)->name);
		return NULL;
	}

	if (! (target_mu->flags & MU_LOGINNOLIMIT)
		&& !has_priv_myuser(target_mu, PRIV_LOGIN_NOLIMIT)
		&& MOWGLI_LIST_LENGTH(&target_mu->logins) >= me.maxlogins)
	{
		(void) logcommand(p->si, CMDLOG_LOGIN, "failed LOGIN to \2%s\2 (too many logins)",
		                                       entity(target_mu)->name);
		return NULL;
	}

	 
	if (ircd->flags & IRCD_SASL_USE_PUID)
	{
		target_mu->flags &= ~MU_NOBURSTLOGIN;
		target_mu->flags |= MU_PENDINGLOGIN;
	}

	if (target_mu != source_mu)
		(void) logcommand(p->si, CMDLOG_LOGIN, "allowed IMPERSONATE by \2%s\2 to \2%s\2",
		                                       entity(source_mu)->name, entity(target_mu)->name);

	return target_mu;
}