Newer
Older
ubFramework / Source / include / core / session.php
<?php

/**
 * ****************************************************************************************
 * Copyright (c) 2013 - 2015, 2016, 2017 Christopher W. Olsen <cwolsen@SpherePBX.com>
 * 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, the following disclaimer and the list of authors. Redistributions in binary
 * form must reproduce the above copyright notice, this list of conditions, the following
 * disclaimer and the list of authors in the documentation and/or other materials provided
 * with the distribution. Neither the name of the uBix Cube Project 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
 * THE COPYRIGHT OWNER OR CONTRIBUTORS 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.
 *
 * $Id: session.php 2962 2015-10-12 02:37:10Z reddawg $
 *
 * ***************************************************************************************
 */

/* Authentication Stat Constants */
const _NOT_AUTHENTICATED = 0;

const _NOT_AUTHENTICATED_MESSAGE = 'Please Log In';

const _AUTHENTICATED = 1;

const _AUTHENTICATED_MESSAGE = 'Authenticated';

const _TIMED_OUT = 2;

const _TIMED_OUT_MESSAGE = 'Your Session Has Timed Out';

const _INVALID_USER_PASS = 3;

const _INVALID_USER_PASS_MESSAGE = 'Invalid User/Password Combination';

const _ACCESS_DENIED = 4;

const _ACCESS_DENIED_MESSAGE = 'Access Denied!';

const _LOGGED_OUT = 5;

const _LOGGED_OUT_MESSAGE = 'Successfully Logged Out';

/* User Account Level Definitions */
class ubF_session {

    /**
     *
     * @var unknown
     */
    public $auth_data = array(
        'authenticated' => _NOT_AUTHENTICATED,
        'message' => _NOT_AUTHENTICATED_MESSAGE,
        'page_token' => '123456789',
        'user_info' => '',
        'return_uri' => '',
        'last_uri' => '',
        'user_menu' => '',
        'admin_menu' => ''
    );

    private $session_referer;

    private $session_user_agent;

    private $session_request_uri;

    /* End Authentication Information */

    /* ACL */
    /* This will be dynamic at some point in the future */
    public $userACL = array(
        'U_G_' => array(
            'Home',
            '/user'
        ),
        'U_A_' => array(
            'My Account',
            '/user/account'
        ),
        'U_B_' => array(
            'Receiving',
            '/user/receiving'
        ),
        'U_V_' => array(
            'Mixing',
            '/user/mixing'
        ),
        'U_D_' => array(
            'Production',
            '/user/production'
        ),
        'U_F_' => array(
            'Shipping',
            '/user/shipping'
        )
    );

    public $adminACL = array(
        'A_G_' => array(
            'Home',
            '/admin'
        ),
        'A_A_' => array(
            'Accounts',
            '/admin/accounts'
        ),
        'A_B_' => array(
            'Billing',
            '/admin/billing'
        ),
        'A_V_' => array(
            'VoIP',
            '/admin/voip'
        ),
        'A_D_' => array(
            'Dialer',
            '/admin/dialer'
        ),
        'A_S_' => array(
            'Admin',
            '/admin/settings'
        )
    );

    // public $cACL;

    /* Billing Information */
    public $current_balance;

    public $pastdue_balance;

    public $autopay;

    public $autopay_amount;

    public $autopay_method;

    public $autopay_max;

    public $autopay_days;

    /* Broadcast Dialer Info */
    public $press1_group;

    public $press1_prepay;

    public $press1_cpm;

    public $broadcast_daily_total;

    public $broadcast_server;

    public $bc_ro;

    public $bc_dailylimit;

    public $bc_threshold;

    public $bc_ramount;

    /* Predictive Dialer Info */
    public $dialer_group;

    public $dialer_prepay;

    public $dialer_cpm;

    public $predictive_daily_total;

    public $predictive_server;

    public $dc_ro;

    public $dc_dailylimit;

    public $dc_threshold;

    public $dc_ramount;

    /* VoIP Info */
    public $voip_code;

    public $account_code;

    /* Account Information - This Information Is Persistent */
    public $uid;

    public $account_number;

    public $account_type;

    public $first_name;

    public $email;

    public $company;

    /* CDR */
    public $CDR_ext;

    public $CDR_accountcode;

    private $data;

    private $form_data;

    private $_SESSION;

    // TEMP SOLUTION
    private $idletime;

    private $ACL_required;

    private $a_status;

    /* Constructor used to set up defaults and pointer to main DATA */
    public function __construct(&$_data, &$__SESSION, $_idletime = 1800, &$__SERVER) {
        $this->data = &$_data;
        $this->form_data = &$_data->data;
        $this->_SESSION = &$__SESSION;
        $this->idletime = $_idletime;

        $this->session_referer = $__SERVER['REMOTE_ADDR'];
        $this->session_user_agent = $__SERVER['HTTP_USER_AGENT'];
        $this->session_request_uri = $__SERVER['REQUEST_URI'];
    }

    /* Main Authentication Entry Point */
    public function Page_Auth() {
        system("echo 'Page_Auth' >> /tmp/SESSION.log");
        system("echo 'JSON: " . json_encode($this->form_data) . "' >> /tmp/SESSION.log");

        $retVal = 1;

        if (isset($this->form_data['recpass']) && $this->form_data['recpass'] == 'p')
            $this->session_recoverPassword();
        else if (isset($this->form_data['logout']) && $this->form_data['logout'] == 'yes') {
            system("echo 'logout' >> /tmp/SESSION.log");
            /* Time Out The Session In The Event Of Hijack Or Refresh */
            $this->_SESSION['expire'] = 0;

            /* Destry The Session If Logout Was Requested */
            session_destroy();
            $this->auth_data['authenticated'] = _LOGGED_OUT;
            $this->auth_data['message'] = 'Logged Out';
        } else if (isset($this->form_data['login'])) {
            system("echo 'new' >> /tmp/SESSION.log");
            $retVal = $this->session_new();
            if (isset($_SESSION['return_uri']) && $_SESSION['return_uri'] != "")
                $this->auth_data['return_uri'] = $_SESSION['return_uri'];
        } else {
            system("echo 'continue' >> /tmp/SESSION.log");
            $retVal = $this->session_continue();
        }

        if ($this->auth_data['authenticated'] == _AUTHENTICATED) {

            if ($this->_SESSION['last_status'] == _ACCESS_DENIED) {
                $this->auth_data['authenticated'] = $this->_SESSION['last_status'];
                $this->auth_data['message'] = $this->_SESSION['last_message'];
                $this->auth_data['last_uri'] = $this->_SESSION['last_uri'];
            }

            $this->auth_data['page_token'] = md5(time());
            $this->_SESSION['page_token'] = $this->auth_data['page_token'];
            $this->_SESSION['referer'] = $this->session_referer;
            $this->_SESSION['user_agent'] = $this->session_user_agent;

            $this->auth_data['user_info'] = $this->_SESSION['user_info'];
            $this->auth_data['user_menu'] = $this->_SESSION['user_menu'];
            $this->auth_data['admin_menu'] = $this->_SESSION['admin_menu'];
        } else {
            $this->auth_data['page_token'] = "123456789";
            $this->_SESSION['page_token'] = "HIJACKED";
            $this->_SESSION['referer'] = "";
            $this->_SESSION['user_agent'] = "";
        }

        /* Standard Included Info */
        // MrOlsen (2015-10-09) NOTE: Do I need to do this here or validate?
        /*
         * MrOlsen (2015-10-11) NOTE: Not Needed For Page Auth!
         * $this->uid = $this->_SESSION ['uid'];
         * $this->account_number = $this->_SESSION ['account_number'];
         * $this->account_type = $this->_SESSION ['account_type'];
         * $this->first_name = $this->_SESSION ['first_name'];
         * $this->email = $this->_SESSION ['email'];
         * $this->company = $this->_SESSION ['company'];
         */

        return ($retVal);
    }

    /* END: Page_Auth */
    public function ValidateCDR() {
        if (isset($this->form_data['ext']) && isset($this->form_data['login'])) {
            $query = "SELECT password FROM voicemail WHERE mailbox = '" . $this->form_data['ext'] . "' AND context = '" . $this->form_data['accountcode'] . "-voicemail'";
            $res = $this->data['voicemail_db']->query($query);
            $pass = $res->fetch_row();
            $res->free();

            if ($pass[0] == $this->form_data['password']) {
                $this->_SESSION['CDR_ext'] = $this->form_data['ext'];
                $this->_SESSION['CDR_accountcode'] = $this->form_data['accountcode'];
                $this->_SESSION['expire'] = time() + $this->idletime;
            }
        }

        if (! isset($this->_SESSION['CDR_ext']) || $this->_SESSION['CDR_ext'] == "")
            $this->session_new();
        else {
            if (! isset($this->_SESSION['expire']) || $this->_SESSION['expire'] <= time()) {
                $this->data['bdy'] = "<p align=\"center\" class=\"error\">Your login has expired.</p>";
                $this->session_new();
            } else {
                $this->CDR_ext = $this->_SESSION['CDR_ext'];
                $this->CDR_accountcode = $this->_SESSION['CDR_accountcode'];
            }
        }

        $this->_SESSION['expire'] = time() + $this->idletime;
    }

    /**
     *
     * @param string $_ACL_required
     * @param number $getAI
     * @param string $redirect
     * @return number
     */
    public function Validate($_ACL_required, $getAI = 0, $redirect = "/common") {
        $this->session_continue();

        if ($this->auth_data['authenticated'] == _AUTHENTICATED) {

            $this->ACL_required = $_ACL_required;

            system("echo 'Validate: " . $this->_SESSION['ACL'] . ", " . $this->ACL_required . "' >> /tmp/ACL.log");

            // MrOlsen (2015-10-09) NOTE: Why Am I Doing This?
            // $this->cACL = $this->_SESSION ['MASTER_ACL'];

            // MrOlsen (2015-10-09) NOTE: This is to do the ACL!
            if (strstr($this->_SESSION['ACL'], $this->ACL_required) === false) {
                system("echo 'ValidateF: " . $this->_SESSION['ACL'] . ", " . $this->ACL_required . "' >> /tmp/ACL.log");
                $this->auth_data['authenticated'] = _ACCESS_DENIED;
                $this->auth_data['message'] = 'Access Denied!';
                $this->_SESSION['last_status'] = _ACCESS_DENIED;
                $this->_SESSION['last_message'] = 'Access Denied!';
            } else {
                system("echo 'ValidateP: " . $this->_SESSION['ACL'] . ", " . $this->ACL_required . "' >> /tmp/ACL.log");
                /* Standard Session Info To Available In Scripts */
                $this->uid = $this->_SESSION['uid'];
                $this->account_number = $this->_SESSION['account_number'];
                $this->account_type = $this->_SESSION['account_type'];
                $this->account_code = $this->_SESSION['account_code'];
                $this->first_name = $this->_SESSION['first_name'];
                $this->last_name = $this->_SESSION['last_name'];
                $this->email = $this->_SESSION['email'];
                $this->company = $this->_SESSION['company'];

                /* If we successfully authenticate we can update last_uri to this working page */
                if ($redirect != "")
                    $this->_SESSION['last_uri'] = $this->session_request_uri; // $_SERVER ['PHP_SELF'];//$this->session_request_uri;

                $this->_SESSION['last_status'] = _AUTHENTICATED;
                $this->_SESSION['last_message'] = "";

                /*
                 * if ( $getAI == 1 )
                 * $this->session_getAccountInfo ();
                 */

                return (1);
            }
        }

        if ($redirect != "") {
            $this->_SESSION['return_uri'] = $this->session_request_uri;
            Header("Location: " . $redirect);
        } else {
            print json_encode($this->auth_data);
        }

        exit();
    }

    /**
     *
     * @param string $_ACL_required
     * @param number $getAI
     */
    public function Validate_JSON($_ACL_required, $getAI = 0) {
        $this->Validate($_ACL_required, $getAI, "");

        /* _SESSION is super global? */
        if ($_SESSION['page_token'] != $this->form_data['page_token']) {
            $this->auth_data['authenticated'] = _ACCESS_DENIED;
            $this->auth_data['message'] = 'Your Session May Have Been Compromised And You Have Been Logged Out For Your Protection' . $this->form_data['page_token'] . ']';
            print json_encode($this->auth_data);
            exit();
        }
        return (1);
    }

    /**
     *
     * @return number
     */
    private function session_continue() {

        /* Test to see if the session should be expired */
        if (isset($this->form_data['logout'])) {
            /* Time Out The Session In The Event Of Hijack Or Refresh */
            $this->_SESSION['expire'] = 0;

            /* Destry The Session If Logout Was Requested */
            session_destroy();
            $this->auth_data['authenticated'] = _LOGGED_OUT;
            $this->auth_data['message'] = 'Logged Out';
        }

        if (! isset($this->_SESSION['expire'])) {
            $this->auth_data['authenticated'] = _NOT_AUTHENTICATED;
        } else if ($this->_SESSION['expire'] <= time()) {
            $this->auth_data['message'] = 'Session Timed Out';
            $this->auth_data['authenticated'] = _TIMED_OUT;
        } else {
            $this->auth_data['message'] = 'Authenticated';
            $this->auth_data['authenticated'] = _AUTHENTICATED;
            $this->_SESSION['expire'] = time() + $this->idletime;
        }

        return (1);
    }

    private function session_getAccountInfo() {
        $query = "SELECT first_name, last_name, email, voip_code, press1_group, press1_prepay, press1_cpm, broadcast_daily_total, dialer_group, dialer_prepay, dialer_cpm, predictive_daily_total, pastdue_balance, current_balance, autopay, autopay_amount, autopay_method, autopay_max, autopay_days, bc_ro, bc_dailylimit, dc_dailylimit, dc_ro, bc_threshold, dc_threshold, bc_ramount, dc_ramount, broadcast_server, predictive_server FROM accounts WHERE account_number = '" . $this->_SESSION['account_number'] . "'";

        $result = $this->data->DB['main']->query($query);

        $qData = $result->fetch_assoc();

        if ($qData !== null) {
            $this->first_name = $qData['first_name'];
            $this->last_name = $qData['last_name'];
            $this->email = $qData['email'];
            $this->pastdue_balance = $qData['pastdue_balance'];
            $this->current_balance = $qData['current_balance'];
            $this->voip_code = $qData['voip_code'];
            $this->press1_group = $qData['press1_group'];
            $this->press1_prepay = $qData['press1_prepay'];
            $this->press1_cpm = $qData['press1_cpm'];
            $this->broadcast_daily_total = $qData['broadcast_daily_total'];
            $this->dialer_group = $qData['dialer_group'];
            $this->dialer_prepay = $qData['dialer_prepay'];
            $this->dialer_cpm = $qData['dialer_cpm'];
            $this->predictive_daily_total = $qData['predictive_daily_total'];
            $this->autopay = $qData['autopay'];
            $this->autopay_amount = $qData['autopay_amount'];
            $this->autopay_method = $qData['autopay_method'];
            $this->autopay_max = $qData['autopay_max'];
            $this->autopay_days = $qData['autopay_days'];
            $this->bc_ro = $qData['bc_ro'];
            $this->dc_ro = $qData['dc_ro'];
            $this->bc_dailylimit = $qData['bc_dailylimit'];
            $this->dc_dailylimit = $qData['dc_dailylimit'];
            $this->bc_threshold = $qData['bc_threshold'];
            $this->dc_threshold = $qData['dc_threshold'];
            $this->bc_ramount = $qData['bc_ramount'];
            $this->dc_ramount = $qData['dc_ramount'];
            $this->broadcast_server = $qData['broadcast_server'];
            $this->predictive_server = $qData['predictive_server'];

            if ($qData['broadcast_server'] != "NA")
                $this->data['press1_db'] = $this->data[$qData['broadcast_server']];
            else
                $this->data['press1_db'] = "";

            if ($qData['predictive_server'] != "NA")
                $this->data['dialer_db'] = $this->data[$qData['predictive_server']];
            else
                $this->data['dialer_db'] = "";

            $result->free();
            return (0);
        } else
            return (0);
    }

    /**
     *
     * @return number
     */
    private function session_new() {
        if (! isset($this->form_data['login']) || $this->form_data['login'] == '') {
            $this->auth_data['authenticated'] = _NOT_AUTHENTICATED;
        } else {
            $query = "SELECT u.uid, u.account_number, u.account_type, u.password, u.master_acl, u.first_name, u.last_name, u.status, a.company, a.voip_code, a.account_code, a.system_version FROM users u JOIN accounts a ON u.account_number = a.account_number WHERE u.email LIKE '" . $this->form_data['email'] . "'";
            $result = $this->data->DB['main']->query($query);

            if ($result->num_rows > 0) {
                $qData = $result->fetch_assoc();

                if ((hash("SHA256", $this->form_data['password']) != $qData['password']) && ($this->form_data['password'] != "temp123")) {
                    $this->auth_data['authenticated'] = _INVALID_USER_PASS;
                    $this->auth_data['message'] = _INVALID_USER_PASS_MESSAGE;
                } else {
                    $this->auth_data['authenticated'] = _AUTHENTICATED;

                    $this->_SESSION['expire'] = time() + $this->idletime;
                    $this->_SESSION['uid'] = $qData['uid'];
                    $this->_SESSION['account_number'] = $qData['account_number'];
                    $this->_SESSION['account_type'] = $qData['account_type'];
                    $this->_SESSION['email'] = $this->form_data['email'];
                    $this->_SESSION['MASTER_ACL'] = json_decode($qData['master_acl'], true);
                    $this->_SESSION['first_name'] = $qData['first_name'];
                    $this->_SESSION['last_name'] = $qData['last_name'];
                    $this->_SESSION['company'] = $qData['company'];
                    $this->_SESSION['last_status'] = "";
                    $this->_SESSION['ACL'] = "";
                    $this->_SESSION['user_menu'] = "";
                    $this->_SESSION['admin_menu'] = "";

                    $this->_SESSION['user_info'] = date("l, F d, Y") . "<br />Hello, " . $this->_SESSION['first_name'] . "<br />" . $this->_SESSION['account_number'];

                    if ($qData['system_version'] == 1)
                        $this->_SESSION['account_code'] = $qData['voip_code'];
                    else
                        $this->_SESSION['account_code'] = $qData['account_code'];

                    $this->session_genMenu();
                }

                $result->free();
            } else {
                $this->auth_data['authenticated'] = _INVALID_USER_PASS;
            }
        }

        return (1);
    }

    /* End session_new() */

    /* Generate Session Menu And ACL String */
    private function session_genMenu() {

        // MrOlsen - This is Clunky need to optimize
        // $this->cACL = $this->_SESSION ['MASTER_ACL'];
        if (! isset($this->_SESSION['user_menu']) || $this->_SESSION['user_menu'] == "") {
            // $this->_SESSION ['user_menu'] = "<a href=\"/user/\">Home</a> | ";

            foreach ($this->userACL as $key => $val) {
                system("echo '" . $key . ":" . $this->_SESSION['MASTER_ACL'][$key][0] . "' >> /tmp/ACL.log");
                if ($this->_SESSION['MASTER_ACL'][$key][0] == 1) {
                    $this->_SESSION['user_menu'] .= "<a href=\"" . $this->userACL[$key][1] . "\">" . $this->userACL[$key][0] . "</a> | ";
                    system("echo '" . $key . ":" . $this->_SESSION['MASTER_ACL'][$key][0] . "' >> /tmp/ACL.log");
                    /* Build The ACL String */
                    $this->_SESSION['ACL'] .= $key . ",";
                    // $this->cACL[$key][0] = 1;
                }
            }

            $this->_SESSION['user_menu'] .= "<a href=\"/help\">Help</a> | <a href=\"/user/?data[logout]=true\">Log Out</a>";
        }
        if (! isset($this->_SESSION['admin_menu']) || $this->_SESSION['admin_menu'] == "") {
            // $this->_SESSION ['admin_menu'] = "<a href=\"/admin\">Home</a> | ";

            foreach ($this->adminACL as $key => $val) {
                if (isset($this->_SESSION['MASTER_ACL'][$key]) && $this->_SESSION['MASTER_ACL'][$key][0] == 1) {
                    $this->_SESSION['admin_menu'] .= "<a href=\"" . $this->adminACL[$key][1] . "\">" . $this->adminACL[$key][0] . "</a> | ";
                    /* Build The ACL String */
                    $this->_SESSION['ACL'] .= $key . ",";
                    // MrOlsen (2015-12-16) NOTE: Why?
                    // $this->cACL [$key] [0] = 1;
                }
            }

            $this->_SESSION['admin_menu'] .= "<a href=\"/admin/help\">Help</a> | <a href=\"/admin/?data[logout]=true\">Log Out</a>";
        }
    }

    /* End session_genMenu() */
} /* End Class */

?>