All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.vzakharchenko.radius.radius.handlers.session.AccountingSessionManager Maven / Gradle / Ivy

package com.github.vzakharchenko.radius.radius.handlers.session;

import com.github.vzakharchenko.radius.RadiusHelper;
import com.github.vzakharchenko.radius.configuration.RadiusConfigHelper;
import com.github.vzakharchenko.radius.models.CoASettings;
import com.github.vzakharchenko.radius.providers.IRadiusCOAProvider;
import com.github.vzakharchenko.radius.radius.RadiusLibraryUtils;
import com.github.vzakharchenko.radius.radius.handlers.clientconnection.RadiusClientConnection;
import com.github.vzakharchenko.radius.radius.holder.IRadiusUserInfo;
import com.github.vzakharchenko.radius.radius.holder.IRadiusUserInfoBuilder;
import com.github.vzakharchenko.radius.radius.holder.IRadiusUserInfoGetter;
import com.github.vzakharchenko.radius.radius.holder.RadiusUserInfoBuilder;
import org.keycloak.common.ClientConnection;
import org.keycloak.common.util.Time;
import org.keycloak.models.*;
import org.tinyradius.packet.AccountingRequest;
import org.tinyradius.util.RadiusEndpoint;

import java.util.List;
import java.util.Objects;

import static com.github.vzakharchenko.radius.radius.handlers.session.RadiusAccountState.UNSUPPORTED;

public class AccountingSessionManager implements IAccountingSessionManager {

    public static final String RADIUS_SESSION_ID = "RADIUS_SESSION_ID";
    public static final String ACCT_SESSION_ID = "Acct-Session-Id";
    public static final String ACCT_STATUS_TYPE = "Acct-Status-Type";
    private final KeycloakSession session;
    private final AccountingRequest accountingRequest;
    private final RadiusEndpoint endpoint;
    private IRadiusUserInfoGetter radiusUserInfoGetter;
    private String userName;
    private UserSessionModel sessionModel;
    private boolean isLogout;
    private AuthenticatedClientSessionModel authClientSession;

    public AccountingSessionManager(AccountingRequest accountingRequest,
                                    KeycloakSession session,
                                    RadiusEndpoint endpoint) {
        this.session = session;
        this.accountingRequest = accountingRequest;
        this.endpoint = endpoint;
    }


    @Override
    public IAccountingSessionManager init() {

        IRadiusUserInfoBuilder radiusUserInfoBuilder = RadiusUserInfoBuilder.create();
        RealmModel realm = RadiusHelper.getRealm(session, accountingRequest);
        radiusUserInfoBuilder.realmModel(realm);
        userName = RadiusLibraryUtils.getUserName(accountingRequest);
        UserModel user = RadiusLibraryUtils.getUserModel(session, userName, realm);
        radiusUserInfoBuilder.userModel(user);
        radiusUserInfoBuilder.addPassword(RadiusLibraryUtils
                .getServiceAccountPassword(user, realm));
        ClientConnection clientConnection = new RadiusClientConnection(endpoint.getAddress(),
                accountingRequest);
        radiusUserInfoBuilder.clientConnection(clientConnection).address(endpoint.getAddress())
                .clientModel(RadiusLibraryUtils.getClient(clientConnection,
                        session, realm)).radiusSecret(endpoint.getSecret());
        this.radiusUserInfoGetter = radiusUserInfoBuilder.getRadiusUserInfoGetter();
        KeycloakSessionUtils.addRadiusUserInfo(session, radiusUserInfoGetter);
        return this;
    }

    @Override
    public IAccountingSessionManager updateContext() {
        KeycloakSessionUtils.context(session, radiusUserInfoGetter);
        return this;
    }


    private AuthenticatedClientSessionModel findAuthClientSession(
            UserSessionModel sm,
            String sessionId) {
        return sm.getAuthenticatedClientSessions().values().stream().filter(
                acsm ->
                        Objects.equals(acsm.getNote(RADIUS_SESSION_ID), sessionId))
                .findFirst().orElse(null);
    }

    private UserSessionModel getSession(String sessionId) {
        IRadiusUserInfo radiusUserInfo = radiusUserInfoGetter.getRadiusUserInfo();
        List userSessions = session.sessions()
                .getUserSessions(radiusUserInfo.getRealmModel(),
                        radiusUserInfo.getClientModel());

        return userSessions.stream().filter(sm -> {
                    authClientSession =
                            findAuthClientSession(sm, sessionId);
                    return authClientSession != null &&
                            Objects.equals(sm.getUser().getId(),
                                    radiusUserInfo.getUserModel().getId());
                }
        ).findFirst().orElse(null);
    }

    private void initSession(String sessionId) {
        CoASettings coA = RadiusConfigHelper.getConfig().getRadiusSettings().getCoASettings();
        IRadiusCOAProvider provider = session.getProvider(IRadiusCOAProvider.class);
        if (provider != null && coA.isUseCoAPackage()) {
            provider.initSession(accountingRequest, session, authClientSession
                    .getUserSession().getId());
        }
        authClientSession.setNote(RADIUS_SESSION_ID, sessionId);
    }

    private UserSessionModel startSession(String sessionId) {
        if (sessionModel == null) {
            IRadiusUserInfo radiusUserInfo = radiusUserInfoGetter.getRadiusUserInfo();
            UserSessionProvider sessions = session.sessions();
            sessionModel = sessions.createUserSession(
                    radiusUserInfo.getRealmModel(), radiusUserInfo.getUserModel(), userName,
                    radiusUserInfo.getClientConnection().getLocalAddr(),
                    "radius", false, null, null);
            authClientSession = sessions
                    .createClientSession(radiusUserInfo.getRealmModel(),
                            radiusUserInfo.getClientModel(), sessionModel);
            initSession(sessionId);
        }
        return sessionModel;
    }

    private RadiusAccountState getRadiusAccountState() {
        String accountStatusType = RadiusLibraryUtils.getAttributeValue(accountingRequest,
                ACCT_STATUS_TYPE);
        return RadiusAccountState
                .getByRadiusState(accountStatusType);
    }

    @Override
    public IAccountingSessionManager manageSession() {
        String sessionId = RadiusLibraryUtils.getAttributeValue(accountingRequest,
                ACCT_SESSION_ID);
        RadiusAccountState radiusAccountState = getRadiusAccountState();
        sessionModel = getSession(sessionId);
        switch (radiusAccountState) {
            case START:
                sessionModel = startSession(sessionId);
                break;
            case STOP:
                removeSession();
                break;
            case UNSUPPORTED:
                break;
            default:
                updateSession();
                break;
        }
        return this;
    }

    private void removeSession() {
        if (sessionModel != null) {
            session.sessions().removeUserSession(radiusUserInfoGetter
                    .getRadiusUserInfo().getRealmModel(), sessionModel);
        }
        isLogout = true;
    }

    @Override
    public boolean isValidSession() {
        return sessionModel != null && !isLogout;
    }


    @Override
    public void logout() {
        RadiusAccountState radiusAccountState = getRadiusAccountState();
        CoASettings coA = RadiusConfigHelper.getConfig().getRadiusSettings().getCoASettings();
        if (radiusAccountState != UNSUPPORTED && coA.isUseCoAPackage()) {
            IRadiusCOAProvider provider = session.getProvider(IRadiusCOAProvider.class);
            if (provider != null) {
                provider.logout(accountingRequest, session);
            }
        }
    }

    private void updateSession() {
        if (sessionModel != null) {
            sessionModel.setLastSessionRefresh(Time.currentTime());
            authClientSession.setTimestamp(Time.currentTime());
        }
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy