Skip to content
session.cpp 8.08 KiB
Newer Older
/*******************************************************************************
 * Copyright (c) 2025, Jan Koester jan.koester@gmx.net
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * Neither the name of the <organization> nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

jan.koester's avatar
jan.koester committed
#include <cstring>

#include "session.h"
jan.koester's avatar
jan.koester committed
#include "backend.h"
#include "group.h"
#include "types.h"
jan.koester's avatar
jan.koester committed
#include "authdb.h"
jan.koester's avatar
jan.koester committed

authdb::SessionData::SessionData(uuid_t sessionid, uuid_t userid, uuid_t domainid,
                                 uuid_t *group,size_t groupsize){
    uuid_copy(_sid,sessionid);
    uuid_copy(_uid,userid);
    uuid_copy(_did,domainid);

    _member.count = groupsize;
    _member.gid = new uuid_t[groupsize];

    for(size_t i =0; i<groupsize; ++i){
        uuid_copy(_member.gid[i],group[i]);
    }

    _next=nullptr;
}

authdb::SessionData::~SessionData(){
    delete[] _member.gid;
}

jan.koester's avatar
jan.koester committed
void authdb::SessionData::getUid(uuid_t& dest) const{
jan.koester's avatar
jan.koester committed
    uuid_copy(dest,_uid);
}

jan.koester's avatar
jan.koester committed
void authdb::SessionData::getSid(uuid_t& dest) const{
jan.koester's avatar
jan.koester committed
    uuid_copy(dest,_sid);
}

jan.koester's avatar
jan.koester committed
void authdb::SessionData::getDid(uuid_t& dest) const{
    uuid_copy(dest,_did);
}
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
const char * authdb::SessionData::getUsername() const{
    return _username.c_str();
}


jan.koester's avatar
jan.koester committed
bool authdb::SessionData::isMemberOf(const uuid_t& gid){
    for(size_t i=0; i<_member.count; ++i){
        if(uuid_compare(_member.gid[i],gid)==0)
            return true;
    }
    return false;
}

jan.koester's avatar
jan.koester committed
const authdb::SessionData * authdb::SessionData::next() const{
jan.koester's avatar
jan.koester committed
    return _next;
}

jan.koester's avatar
jan.koester committed


authdb::Session::Session(){
    _firstData=nullptr;
    _lastData=nullptr;
}

authdb::Session::~Session(){
}

jan.koester's avatar
jan.koester committed
const authdb::SessionData * authdb::Session::addSession(AuthBackend &backend,uuid_t domainid,uuid_t userid){
jan.koester's avatar
jan.koester committed
    Group group;

    SessionData::Groups grpdat;

    grpdat.count=0;

jan.koester's avatar
jan.koester committed
    std::string username;

jan.koester's avatar
jan.koester committed
    size_t rd=sizeof(authdb::AuthHeader),end=backend.end();
    while(rd<end){
        authdb::AuthData::Record cur;

        cur.type=EmptyData;

        backend.setPos(rd);
        backend.read((unsigned char*)&cur,sizeof(AuthData::Record));

        rd=backend.getPos()+cur.datasize;

jan.koester's avatar
jan.koester committed
        if(cur.type == UserData && strcmp(cur.fieldname,"username")==0
            && uuid_compare(cur.uuid,userid)==0){

            char *tmp=new char[cur.datasize];
jan.koester's avatar
jan.koester committed
            backend.read((unsigned char*)tmp,cur.datasize);
jan.koester's avatar
jan.koester committed
            username=tmp;
            delete[] tmp;
        }

jan.koester's avatar
jan.koester committed
        if(cur.type == GroupData && strcmp(cur.fieldname,"groupname")==0){
            class GroupData grpi(cur.uuid);
            size_t upos=sizeof(authdb::AuthHeader);
            group.info(backend,grpi,upos);

            if(grpi.isMember(userid))
                ++grpdat.count;
        }
    }

    grpdat.gid = new uuid_t[grpdat.count];

    size_t count=0;

    while(rd<end){
        authdb::AuthData::Record cur;

        cur.type=EmptyData;

        backend.setPos(rd);
        backend.read((unsigned char*)&cur,sizeof(AuthData::Record));

        rd=backend.getPos()+cur.datasize;

        if(cur.type == GroupData && strcmp(cur.fieldname,"groupname")==0){
            class GroupData grpi(cur.uuid);
            size_t upos=sizeof(authdb::AuthHeader);
            group.info(backend,grpi,upos);

            if(grpi.isMember(userid))
                uuid_copy(grpdat.gid[count++],cur.uuid);
        }
    }

jan.koester's avatar
jan.koester committed
    uuid_t sid;
    uuid_generate(sid);

jan.koester's avatar
jan.koester committed
    if(!_firstData){
        _firstData=new SessionData(sid,userid,domainid,grpdat.gid,grpdat.count);
        _lastData=_firstData;
    }else{
        _lastData->_next=new SessionData(sid,userid,domainid,grpdat.gid,grpdat.count);
        _lastData=_lastData->_next;
    }

jan.koester's avatar
jan.koester committed
    _lastData->_username=username;

jan.koester's avatar
jan.koester committed
    return _lastData;
}

jan.koester's avatar
jan.koester committed
const authdb::SessionData * authdb::Session::getSession(uuid_t sessionid) const{
    for(const SessionData *cur=firstData(); cur; cur=cur->next()){
        if(uuid_compare(cur->_sid,sessionid)==0)
jan.koester's avatar
jan.koester committed
            return cur;
    }
    return nullptr;
jan.koester's avatar
jan.koester committed
}
jan.koester's avatar
jan.koester committed

void authdb::Session::remSession(uuid_t sessionid){
    SessionData *prev=nullptr;

    for(SessionData *cur=_firstData; cur; cur=cur->_next){
jan.koester's avatar
jan.koester committed
        if(uuid_compare(cur->_sid,sessionid)==0){
jan.koester's avatar
jan.koester committed
            if(prev)
                prev->_next=cur->_next;

            if(cur==_firstData)
                _firstData=cur->_next;

            if(cur==_lastData)
                _lastData=prev;

            cur->_next=nullptr;
            delete cur;
jan.koester's avatar
jan.koester committed
            break;
jan.koester's avatar
jan.koester committed
        }
        prev=cur;
    }
}
jan.koester's avatar
jan.koester committed

jan.koester's avatar
jan.koester committed
void authdb::Session::relSession(AuthBackend &backend,uuid_t sessionid){
    Group group;

    SessionData::Groups grpdat;

    grpdat.count=0;

    std::string username;

    SessionData *cursess=nullptr;

    for(SessionData *cur=_firstData; cur; cur=cur->_next){
        if(uuid_compare(cur->_sid,sessionid)==0){
            cursess=cur;
            break;
        }
    }

    if(!cursess)
        throw AuthBackendError("reload session: sessionid not found !");

    size_t rd=sizeof(authdb::AuthHeader),end=backend.end();
    while(rd<end){
        authdb::AuthData::Record cur;

        cur.type=EmptyData;

        backend.setPos(rd);
        backend.read((unsigned char*)&cur,sizeof(AuthData::Record));

        rd=backend.getPos()+cur.datasize;

        if(cur.type == UserData && strcmp(cur.fieldname,"username")==0
            && uuid_compare(cur.uuid,cursess->_uid)==0){

            char *tmp=new char[cur.datasize];
            backend.read((unsigned char*)tmp,cur.datasize);
            username=tmp;
            delete[] tmp;
        }

        if(cur.type == GroupData && strcmp(cur.fieldname,"groupname")==0){
            class GroupData grpi(cur.uuid);
            size_t upos=sizeof(authdb::AuthHeader);
            group.info(backend,grpi,upos);

            if(grpi.isMember(cursess->_uid))
                ++grpdat.count;
        }
    }

jan.koester's avatar
jan.koester committed
    delete[] grpdat.gid;

jan.koester's avatar
jan.koester committed
    grpdat.gid = new uuid_t[grpdat.count];

    size_t count=0;

    while(rd<end){
        authdb::AuthData::Record cur;

        cur.type=EmptyData;

        backend.setPos(rd);
        backend.read((unsigned char*)&cur,sizeof(AuthData::Record));

        rd=backend.getPos()+cur.datasize;

        if(cur.type == GroupData && strcmp(cur.fieldname,"groupname")==0){
            class GroupData grpi(cur.uuid);
            size_t upos=sizeof(authdb::AuthHeader);
            group.info(backend,grpi,upos);

            if(grpi.isMember(cursess->_uid))
                uuid_copy(grpdat.gid[count++],cur.uuid);
        }
    }

jan.koester's avatar
jan.koester committed
    if(grpdat.count<__UINTMAX_MAX__){
        cursess->_member.gid=new uuid_t[grpdat.count];
        for(size_t i=0; i<grpdat.count; ++i)
            uuid_copy(cursess->_member.gid[i],grpdat.gid[i]);
        cursess->_member.count=grpdat.count;
    }
jan.koester's avatar
jan.koester committed
const authdb::SessionData * authdb::Session::firstData() const{
jan.koester's avatar
jan.koester committed
    return _firstData;
}