Function Security_Services(@Service, @Params)
/***********************************************************************************************************************

    This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
    permission from SRP Computer Solutions, Inc.

    Name        :   Security_Services

    Description :   Handler program for all module related services.

    Notes       :   The generic parameters should contain all the necessary information to process the services. Often
                    this will be information like the data Record and Key ID.

    Parameters  :
        Service         [in] -- Name of the service being requested
        Param1-10   [in/out] -- Additional request parameter holders
        Response       [out] -- Response to be sent back to the Controller (MCP) or requesting procedure

    Metadata    :
        @@REGISTER_SERVICES_MODULE(Security)

    History     :   (Date, Initials, Notes)
        05/18/17    dmb     Original programmer. - [EPIOI-8]
        02/13/18    dmb     Added GetAccessLevel service.
        02/13/18    dmb     Added ValidateAuthenticationRequests service.

***********************************************************************************************************************/

#pragma precomp SRP_PreCompiler

$insert LOGICAL
$insert SERVICE_SETUP
$insert DICT_EQUATES
$insert FILE.SYSTEM.EQUATES
$insert RLIST_EQUATES
$insert AD_GROUP_VALIDATION_REQUESTS_EQUATES
$insert MSG_EQUATES

Declare subroutine  Memory_Services, Database_Services, SRP_Stopwatch, Error_Services, RTP57, Set_Status, WinYield
Declare subroutine  Sleepery, Yield, Messaging_Services
Declare function    Memory_Services, Database_Services, Security_Services, SRP_Sort_Array, obj_Tables, Error_Services
Declare function    GetTickCount, MemberOf, Active_Directory_Services, Dialog_Box, Msg, SRP_Logon, Rti_Ldap_Groups_For_User

GoToService else
    Error_Services('Set', Service : ' is not a valid service request within the ' : ServiceModule : ' services module.')
end

Return Response else ''


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//----------------------------------------------------------------------------------------------------------------------
// AuthenticateLSLCredentials
//
// Authenticates an LSL username and password (not SSO/AD credentials).
//----------------------------------------------------------------------------------------------------------------------
Service AuthenticateLSLCredentials(LSLUsername, LSLPassword)

    Response = False$
    If ( (LSLUsername NE '') and (LSLPassword NE '') ) then
        Convert @Lower_Case to @Upper_Case in LSLUsername
        Convert @Lower_Case to @Upper_Case in LSLPassword
        If RowExists('LSL_USERS', LSLUsername) then
            Password = Xlate('LSL_USERS', LSLUsername, 'PASSWORD', 'X')
            If LSLPassword EQ Password then
                Response = True$
            end else
                Error_Services('Add', 'Incorrect password entered for LSL username: ':LSLUsername:'.')
            end
        end else
            Error_Services('Add', 'Invalid LSL username ':LSLUsername:'.')
        end
    end else
        Error_Services('Add', 'LSLUSername or LSLPassword not supplied in service ':Service:'.') 
    end

end service


//----------------------------------------------------------------------------------------------------------------------
// HasIPData
//
// Table    - Database table name. - [Required]
// KeyID    - Key ID of the row being examined. - [Required]
//
// Returns a boolean flag indicating whether the indicated table and Key ID has IP data that is governed by Export
// Control.
//----------------------------------------------------------------------------------------------------------------------
Service HasIPData(Table, KeyID)

    ServiceKeyID   := '*' : Table : '*' : KeyID
    IPData          = Memory_Services('GetValue', ServiceKeyID, True$, 3600)

    If IPData EQ '' then
        If Table NE '' AND KeyID NE '' then
            FileError   = @File_Error
            Memory_Services('SetValue', 'SuspendAuthentication', True$)
            IPData      = Xlate(Table, KeyID, 'EXPORT_CONTROL', 'X')
            Memory_Services('SetValue', 'SuspendAuthentication', False$)
            @File_Error = FileError
        end else
            Error_Services('Add', 'Table or KeyID argument is missing in the ' : Service : ' service.')
        end
        If IPData EQ '' then IPData = False$
    end

    Response    = IPData

end service


//----------------------------------------------------------------------------------------------------------------------
// UserHasECPrivilege
//
// UserName - Name of the user being checked. - [Required]
//
// Returns a boolean flag indicating whether the indicated user has the privelege to access export control data.
//----------------------------------------------------------------------------------------------------------------------
Service UserHasECPrivilege(UserName)

    ServiceKeyID   := '*' : UserName
    HasECPrivilege  = Memory_Services('GetValue', ServiceKeyID, True$, 3600)

    If HasECPrivilege EQ '' then
        If UserName NE '' then
            FileError   = @File_Error
            if (MemberOf(UserName, 'NON_EC')) then
                HasECPrivilege   = False$
            end else
                HasECPrivilege   = True$
            end
            Memory_Services('SetValue', ServiceKeyID, HasECPrivilege)
            @File_Error = FileError
        end else
            Error_Services('Add', 'UserName argument is missing in the ' : Service : ' service.')
        end
        If HasECPrivilege EQ '' then HasECPrivilege = True$
    end

    Response    = HasECPrivilege

end service


//----------------------------------------------------------------------------------------------------------------------
// DataAccessAllowed
//
// Table    - Database table name. - [Required]
// KeyID    - Key ID of the row being examined. - [Required]
// UserName - Name of the user being checked. - [Required]
//
// Returns a boolean flag indicating whether the indicated user has access to the table and KeyID.
//----------------------------------------------------------------------------------------------------------------------
Service DataAccessAllowed(Table, KeyID, UserName)

    ServiceKeyID   := '*' : Table : '*' : KeyID : '*' : UserName
    SuspendAuth     = Memory_Services('GetValue', 'SuspendAuthentication')
    AccessAllowed   = Memory_Services('GetValue', ServiceKeyID, True$, 3600)

    If (SuspendAuth EQ False$) OR (SuspendAuth EQ '') then
        If AccessAllowed EQ '' then
            If Table NE '' AND KeyID NE '' AND UserName NE '' then
                FileError   = @File_Error
                HasIPData   = Security_Services('HasIPData', Table, KeyID)
                If HasIPData then
                    AccessAllowed   = Security_Services('UserHasECPrivilege', UserName)
                end else
                    AccessAllowed   = True$
                end
                Memory_Services('SetValue', ServiceKeyID, AccessAllowed)
                @File_Error = FileError
            end else
                Error_Services('Add', 'Table, KeyID, or UserName argument is missing in the ' : Service : ' service.')
            end
            If AccessAllowed EQ '' then AccessAllowed = True$
        end
    end else
        AccessAllowed = True$
    end

    Response    = AccessAllowed

end service


//----------------------------------------------------------------------------------------------------------------------
// GetAccessLevel
//
// Username - Plain text user name. This can be formatted as just the user name or in UPN format (e.g., User@Domain)
// Password - Plain text password.
// Domain   - Domain to authenticate the username against. If empty then a chain of default domains will be used.
//
// Attempts to get the access level for the indicated username: -1 = No access; 0 = User; 1 = Administrator; 2 = System
// Administrator. This relies upon the ValidateAuthenticationRequests service.
//----------------------------------------------------------------------------------------------------------------------
Service GetAccessLevel(Username, Password, Domain)

    AccessLevel     = -1    ; // Assume no access for now.
    If ( (Username NE '') and (Password NE '') ) then 
        // Validate the username and password against one of the approved non-EC domains.
        ValidUser  = False$    ; // Assume not valid for now.
        If Domain NE '' then
            // User has specified their domain with their username. Parse this out and use this domain only.
            Domains     = Domain
        end else
            Domains     = 'MESSR001.infineon.com,MESSR002.infineon.com,na.infineon.com,na,infineon.com'
        end
        For Each Domain in Domains using ','
            ValidUser = Active_Directory_Services('AuthenticateUser', Username, Password, Domain)
            If ValidUser EQ True$ then AccessLevel = 2
        Until ValidUser EQ True$
        Next Domain
    end
    Response = AccessLevel

return


//----------------------------------------------------------------------------------------------------------------------
// GetADGroups
//
// Returns an @FM delimited list of AD (active directory) groups that the indicated user belongs to.
//----------------------------------------------------------------------------------------------------------------------
Service GetADGroups(Username, Domain)

    ADGroups    = ''

    If (Username NE '') AND (Domain NE '') then
        ADGroups  = Active_Directory_Services('GetADGroups', Username, Domain)
    end else
        Error_Services('Add', 'Username or Domain arguments was missing in the ' : Service : ' service.')
    end

    Response    = ADGroups

end service


//----------------------------------------------------------------------------------------------------------------------
// ValidateAuthenticationRequests
//
// Service that attempts to validate all authentication requests. These requests are queued in the
// AD_GROUP_VALIDATION_REQUESTS table.
//----------------------------------------------------------------------------------------------------------------------
Service ValidateAuthenticationRequests()

    hValidationRequests = Database_Services('GetTableHandle', 'AD_GROUP_VALIDATION_REQUESTS')
    If Error_Services('NoError') then
        Sentence    = 'SELECT AD_GROUP_VALIDATION_REQUESTS WITH VALIDATION_DATE EQ "" BY REQUEST_DATE BY REQUEST_TIME'
        Set_Status(0)
        RList(Sentence, TARGET_ACTIVELIST$, '', '', '')
        EOF         = False$
        Loop
            ReadNext RequestKeyID else EOF = True$
        Until EOF
            Lock hValidationRequests, RequestKeyID then
                AccessLevel = -1
                RequestRow  = Database_Services('ReadDataRow', 'AD_GROUP_VALIDATION_REQUESTS', RequestKeyID)
                Username    = Field(RequestKeyID, '*', 3, 1)
                Password    = RequestRow<AD_GROUP_VALIDATION_REQUESTS.PASSWORD$>
                Domain      = RequestRow<AD_GROUP_VALIDATION_REQUESTS.DOMAIN$>
                // Validate the username and password against one of the approved non-EC domains.
                ValidUser   = False$    ; // Assume not valid for now.
                If Domain NE '' then
                    // User has specified their domain with their username. Parse this out and use this domain only.
                    Domains     = Domain
                end else
                    Domains     = 'MESSR001.infineon.com,MESSR002.infineon.com,na.infineon.com,na,infineon.com'
                end
                For Each Domain in Domains using ','
                    ValidUser = Active_Directory_Services('AuthenticateUser', Username, Password, Domain)
                    If ValidUser EQ True$ then AccessLevel = 2
                Until ValidUser EQ True$
                    Sleepery(10)
                    WinYield()
                    Yield();Yield();Yield();Yield();Yield();Yield();Yield();Yield()
                Next Domain
                RequestRow<AD_GROUP_VALIDATION_REQUESTS.ACCESS_LEVEL$>      = AccessLevel
                RequestRow<AD_GROUP_VALIDATION_REQUESTS.VALIDATION_DATE$>   = Date()
                RequestRow<AD_GROUP_VALIDATION_REQUESTS.VALIDATION_TIME$>   = Time()
                Database_Services('WriteDataRow', 'AD_GROUP_VALIDATION_REQUESTS', RequestKeyID, RequestRow, True$)
                Unlock hValidationRequests, RequestKeyID else Null
            end
        Repeat
    end

end service


//----------------------------------------------------------------------------------------------------------------------
// GetLSLUser
//
// Returns the LSL user associated to the indicated AD username.
//----------------------------------------------------------------------------------------------------------------------
Service GetLSLUser(Username)

    LSLUser         = ''

    ADtoLSLUserMap  = Database_Services('ReadDataRow', 'APP_INFO', 'AD_TO_LSL_USER_MAP')
    If Error_Services('NoError') then
        ADUsernames = ADtoLSLUserMap<1>
        Convert @Upper_Case to @Lower_Case in ADUsernames
        Convert @Upper_Case to @Lower_Case in Username
        Locate Username in ADUsernames using @VM setting vPos then
            LSLUser = ADtoLSLUserMap<2, vPos>
        end
    end

    Response    = LSLUser

end service

