예제 #1
0
 public static function auth_user()
 {
     $isLocal = self::is_local();
     $headers = apache_request_headers();
     $myplex_token = $headers['X-Plex-Token'];
     if (empty($myplex_token)) {
         $myplex_token = $_REQUEST['X-Plex-Token'];
     }
     if (!$isLocal) {
         $match_users = AmpConfig::get('plex_match_email');
         $myplex_username = $headers['X-Plex-Username'];
         if (empty($myplex_token)) {
             // Never fail OPTIONS requests
             if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
                 self::setPlexHeader($headers);
                 exit;
             } else {
                 debug_event('Access Control', 'Authentication token is missing.', '3');
                 self::createError(401);
             }
         }
         $createSession = false;
         Session::gc();
         $username = "";
         $email = trim(Session::read((string) $myplex_token));
         if (empty($email)) {
             $createSession = true;
             $xml = self::get_server_authtokens();
             $validToken = false;
             foreach ($xml->access_token as $tk) {
                 if ((string) $tk['token'] == $myplex_token) {
                     $username = (string) $tk['username'];
                     // We should apply filter and access restriction to shared sections only, but that's not easily possible with current Ampache architecture
                     $validToken = true;
                     break;
                 }
             }
             if (!$validToken) {
                 debug_event('Access Control', 'Auth-Token ' . $myplex_token . ' invalid for this server.', '3');
                 self::createError(401);
             }
         }
         // Need to get a match between Plex and Ampache users
         if ($match_users) {
             if (!AmpConfig::get('access_control')) {
                 debug_event('Access Control', 'Error Attempted to use Plex with Access Control turned off and plex/ampache link enabled.', '3');
                 self::createError(401);
             }
             if (empty($email)) {
                 $xml = self::get_users_account();
                 if ((string) $xml->username == $username) {
                     $email = (string) $xml->email;
                 } else {
                     $xml = self::get_server_friends();
                     foreach ($xml->User as $xuser) {
                         if ((string) $xuser['username'] == $username) {
                             $email = (string) $xuser['email'];
                         }
                     }
                 }
             }
             if (!empty($email)) {
                 $user = User::get_from_email($email);
             }
             if (!isset($user) || !$user->id) {
                 debug_event('Access Denied', 'Unable to get an Ampache user match for email ' . $email, '3');
                 self::createError(401);
             } else {
                 $username = $user->username;
                 if (!Access::check_network('init-api', $username, 5)) {
                     debug_event('Access Denied', 'Unauthorized access attempt to Plex [' . $_SERVER['REMOTE_ADDR'] . ']', '3');
                     self::createError(401);
                 } else {
                     $GLOBALS['user'] = $user;
                     $GLOBALS['user']->load_playlist();
                 }
             }
         } else {
             $email = $username;
             $username = null;
             $GLOBALS['user'] = new User();
             $GLOBALS['user']->load_playlist();
         }
         if ($createSession) {
             // Create an Ampache session from Plex authtoken
             Session::create(array('type' => 'api', 'sid' => $myplex_token, 'username' => $username, 'value' => $email));
         }
     } else {
         AmpConfig::set('cookie_path', '/', true);
         $sid = $_COOKIE[AmpConfig::get('session_name')];
         if (!$sid) {
             $sid = $myplex_token;
             if ($sid) {
                 session_id($sid);
                 Session::create_cookie();
             }
         }
         if (!empty($sid) && Session::exists('api', $sid)) {
             Session::check();
             $GLOBALS['user'] = User::get_from_username($_SESSION['userdata']['username']);
         } else {
             $GLOBALS['user'] = new User();
             $data = array('type' => 'api', 'sid' => $sid);
             Session::create($data);
             Session::check();
         }
         $GLOBALS['user']->load_playlist();
     }
 }
예제 #2
0
    echo XML_Data::error('501', T_('Access Control not Enabled'));
    exit;
}
/**
 * Verify the existance of the Session they passed in we do allow them to
 * login via this interface so we do have an exception for action=login
 */
if (!Session::exists('api', $_REQUEST['auth']) and $_REQUEST['action'] != 'handshake' and $_REQUEST['action'] != 'ping') {
    debug_event('Access Denied', 'Invalid Session attempt to API [' . $_REQUEST['action'] . ']', '3');
    ob_end_clean();
    echo XML_Data::error('401', T_('Session Expired'));
    exit;
}
// If the session exists then let's try to pull some data from it to see if we're still allowed to do this
$username = $_REQUEST['action'] == 'handshake' || $_REQUEST['action'] == 'ping' ? $_REQUEST['user'] : Session::username($_REQUEST['auth']);
if (!Access::check_network('init-api', $username, 5)) {
    debug_event('Access Denied', 'Unauthorized access attempt to API [' . $_SERVER['REMOTE_ADDR'] . ']', '3');
    ob_end_clean();
    echo XML_Data::error('403', T_('Unauthorized access attempt to API - ACL Error'));
    exit;
}
if ($_REQUEST['action'] != 'handshake' and $_REQUEST['action'] != 'ping') {
    Session::extend($_REQUEST['auth']);
    $GLOBALS['user'] = User::get_from_username($username);
}
// Get the list of possible methods for the Ampache API
$methods = get_class_methods('api');
// Define list of internal functions that should be skipped
$internal_functions = array('set_filter');
// Recurse through them and see if we're calling one of them
foreach ($methods as $method) {
예제 #3
0
 /**
  * handshake
  *
  * This is the function that handles verifying a new handshake
  * Takes a timestamp, auth key, and username.
  */
 public static function handshake($input)
 {
     $timestamp = preg_replace('/[^0-9]/', '', $input['timestamp']);
     $passphrase = $input['auth'];
     if (empty($passphrase)) {
         $passphrase = $_POST['auth'];
     }
     $username = trim($input['user']);
     $ip = $_SERVER['REMOTE_ADDR'];
     $version = $input['version'];
     // Log the attempt
     debug_event('API', "Handshake Attempt, IP:{$ip} User:{$username} Version:{$version}", 5);
     // Version check shouldn't be soo restrictive... only check with initial version to not break clients compatibility
     if (intval($version) < self::$auth_version) {
         debug_event('API', 'Login Failed: version too old', 1);
         Error::add('api', T_('Login Failed: version too old'));
         return false;
     }
     $user_id = -1;
     // Grab the correct userid
     if (!$username) {
         $client = User::get_from_apikey($passphrase);
         if ($client) {
             $user_id = $client->id;
         }
     } else {
         $client = User::get_from_username($username);
         $user_id = $client->id;
     }
     // Log this attempt
     debug_event('API', "Login Attempt, IP:{$ip} Time: {$timestamp} User:{$username} ({$user_id}) Auth:{$passphrase}", 1);
     if ($user_id > 0 && Access::check_network('api', $user_id, 5, $ip)) {
         // Authentication with user/password, we still need to check the password
         if ($username) {
             // If the timestamp isn't within 30 minutes sucks to be them
             if ($timestamp < time() - 1800 || $timestamp > time() + 1800) {
                 debug_event('API', 'Login Failed: timestamp out of range ' . $timestamp . '/' . time(), 1);
                 Error::add('api', T_('Login Failed: timestamp out of range'));
                 return false;
             }
             // Now we're sure that there is an ACL line that matches
             // this user or ALL USERS, pull the user's password and
             // then see what we come out with
             $realpwd = $client->get_password();
             if (!$realpwd) {
                 debug_event('API', 'Unable to find user with userid of ' . $user_id, 1);
                 Error::add('api', T_('Invalid Username/Password'));
                 return false;
             }
             $sha1pass = hash('sha256', $timestamp . $realpwd);
             if ($sha1pass !== $passphrase) {
                 $client = null;
             }
         } else {
             $timestamp = time();
         }
         if ($client) {
             // Create the session
             $data = array();
             $data['username'] = $client->username;
             $data['type'] = 'api';
             $data['value'] = $timestamp;
             $token = Session::create($data);
             debug_event('API', 'Login Success, passphrase matched', 1);
             // We need to also get the 'last update' of the
             // catalog information in an RFC 2822 Format
             $sql = 'SELECT MAX(`last_update`) AS `update`, MAX(`last_add`) AS `add`, MAX(`last_clean`) AS `clean` FROM `catalog`';
             $db_results = Dba::read($sql);
             $row = Dba::fetch_assoc($db_results);
             // Now we need to quickly get the song totals
             $sql = 'SELECT COUNT(`id`) AS `song`, ' . 'COUNT(DISTINCT(`album`)) AS `album`, ' . 'COUNT(DISTINCT(`artist`)) AS `artist` ' . 'FROM `song`';
             $db_results = Dba::read($sql);
             $counts = Dba::fetch_assoc($db_results);
             // Next the video counts
             $sql = "SELECT COUNT(`id`) AS `video` FROM `video`";
             $db_results = Dba::read($sql);
             $vcounts = Dba::fetch_assoc($db_results);
             $sql = "SELECT COUNT(`id`) AS `playlist` FROM `playlist`";
             $db_results = Dba::read($sql);
             $playlist = Dba::fetch_assoc($db_results);
             $sql = "SELECT COUNT(`id`) AS `catalog` FROM `catalog` WHERE `catalog_type`='local'";
             $db_results = Dba::read($sql);
             $catalog = Dba::fetch_assoc($db_results);
             echo XML_Data::keyed_array(array('auth' => $token, 'api' => self::$version, 'session_expire' => date("c", time() + AmpConfig::get('session_length') - 60), 'update' => date("c", $row['update']), 'add' => date("c", $row['add']), 'clean' => date("c", $row['clean']), 'songs' => $counts['song'], 'albums' => $counts['album'], 'artists' => $counts['artist'], 'playlists' => $playlist['playlist'], 'videos' => $vcounts['video'], 'catalogs' => $catalog['catalog']));
             return true;
         }
         // match
     }
     // end while
     debug_event('API', 'Login Failed, unable to match passphrase', '1');
     XML_Data::error('401', T_('Error Invalid Handshake - ') . T_('Invalid Username/Password'));
 }
예제 #4
0
파일: index.php 프로젝트: ivan801/ampache
    } else {
        fpassthru($fp);
    }
    fclose($fp);
    exit;
}
// if they are trying to download and they can
// Prevent the script from timing out
set_time_limit(0);
// We're about to start. Record this user's IP.
if (AmpConfig::get('track_user_ip')) {
    $GLOBALS['user']->insert_ip_history();
}
$force_downsample = false;
if (AmpConfig::get('downsample_remote')) {
    if (!Access::check_network('network', $GLOBALS['user']->id, '0')) {
        debug_event('play', 'Downsampling enabled for non-local address ' . $_SERVER['REMOTE_ADDR'], 5);
        $force_downsample = true;
    }
}
debug_event('play', 'Playing file (' . $media->file . '}...', 5);
debug_event('play', 'Media type {' . $media->type . '}', 5);
$cpaction = $_REQUEST['custom_play_action'];
// Determine whether to transcode
$transcode = false;
// transcode_to should only have an effect if the media is the wrong format
$transcode_to = $transcode_to == $media->type ? null : $transcode_to;
debug_event('play', 'Custom play action {' . $cpaction . '}', 5);
debug_event('play', 'Transcode to {' . $transcode_to . '}', 5);
// If custom play action, do not try to transcode
if (!$cpaction) {
예제 #5
0
파일: login.php 프로젝트: nioc/ampache
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */
/* We have to create a cookie here because IIS
 * can't handle Cookie + Redirect
 */
Session::create_cookie();
Preference::init();
/**
 * If Access Control is turned on then we don't
 * even want them to be able to get to the login
 * page if they aren't in the ACL
 */
if (AmpConfig::get('access_control')) {
    if (!Access::check_network('interface', '', '5')) {
        debug_event('UI::access_denied', 'Access Denied:' . $_SERVER['REMOTE_ADDR'] . ' is not in the Interface Access list', '3');
        UI::access_denied();
        exit;
    }
}
// access_control is enabled
/* Clean Auth values */
unset($auth);
if (empty($_REQUEST['step'])) {
    /* Check for posted username and password, or appropriate environment variable if using HTTP auth */
    if ($_POST['username'] || in_array('http', AmpConfig::get('auth_methods')) && ($_SERVER['REMOTE_USER'] || $_SERVER['HTTP_REMOTE_USER'])) {
        /* If we are in demo mode let's force auth success */
        if (AmpConfig::get('demo_mode')) {
            $auth['success'] = true;
            $auth['info']['username'] = '******';
예제 #6
0
파일: index.php 프로젝트: nioc/ampache
    exit;
}
// Authenticate the user here
if ($channel->is_private) {
    $is_auth = false;
    if (isset($_SERVER['PHP_AUTH_USER'])) {
        $htusername = $_SERVER['PHP_AUTH_USER'];
        $htpassword = $_SERVER['PHP_AUTH_PW'];
        $auth = Auth::login($htusername, $htpassword);
        if ($auth['success']) {
            $username = $auth['username'];
            $GLOBALS['user'] = new User($username);
            $is_auth = true;
            Preference::init();
            if (AmpConfig::get('access_control')) {
                if (!Access::check_network('stream', $GLOBALS['user']->id, '25') and !Access::check_network('network', $GLOBALS['user']->id, '25')) {
                    debug_event('UI::access_denied', "Streaming Access Denied: " . $_SERVER['REMOTE_ADDR'] . " does not have stream level access", '3');
                    UI::access_denied();
                    exit;
                }
            }
        }
    }
    if (!$is_auth) {
        header('WWW-Authenticate: Basic realm="Ampache Channel Authentication"');
        header('HTTP/1.0 401 Unauthorized');
        echo T_('Unauthorized.');
        exit;
    }
}
$url = 'http://' . $channel->interface . ':' . $channel->port . '/' . $_REQUEST['target'];