sessions.php
author Dan
Fri, 12 Jun 2009 13:49:22 -0400
changeset 77 e5f1f45ea7e2
parent 74 7719085707d8
permissions -rw-r--r--
Added ability to configure from iPhone; changed up iPhone interface a bit

<?php

/**
 * Greyhound - real web management for Amarok
 * Copyright (C) 2008 Dan Fuhry
 *
 * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
 */

function greyhound_login_page($httpd, $socket)
{
  if ( session_check() )
  {
    $httpd->header('HTTP/1.1 307 Temporary Redirect');
    $httpd->header('Location: /');
    
    return;
  }
  $tried = false;
  $success = false;
  if ( isset($_POST['username']) && isset($_POST['password']) )
  {
    $tried = true;
    if ( $sessionid = login($_POST['username'], $_POST['password']) )
    {
      $success = true;
      $httpd->setcookie('grey_session', $sessionid, time() + ( 86400 * 3650 ));
    }
  }
  
  global $theme;
  $iphone = ( ( strpos($_SERVER['HTTP_USER_AGENT'], 'iPhone') ||
       strpos($_SERVER['HTTP_USER_AGENT'], 'iPod') ||
       strpos($_SERVER['HTTP_USER_AGENT'], 'BlackBerry') ||
       isset($_GET['m']) )
       && !isset($_GET['f'])
       );
  $theme_id = ( $iphone ) ? 'iphone' : $theme;
  $smarty = load_theme($theme_id);
  
  $smarty->assign('theme', $theme_id);
  $smarty->assign('greyhound_version', GREY_VERSION);
  $smarty->assign('tried', $tried);
  $smarty->assign('success', $success);
  $smarty->display('login.tpl');
}

function greyhound_logout($httpd, $socket)
{
  // destroy the session
  if ( isset($_COOKIE['grey_session']) )
  {
    load_session_data();
    global $session_data;
    unset($session_data[$_COOKIE['grey_session']]);
    session_commit_db();
  }
  
  $httpd->setcookie('grey_session', '', time() - 864000);
  $httpd->header('HTTP/1.1 307 Temporary Redirect');
  $httpd->header('Location: /');
}

/**
 * Check to see if we're logged in
 */

function session_check()
{
  global $use_auth, $auth_data;
  
  if ( !$use_auth )
    return true;
  
  if ( isset($_COOKIE['grey_session']) )
  {
    load_session_data();
    global $session_data;
    if ( isset($session_data[$_COOKIE['grey_session']]) )
    {
      // has a cookie with a valid session ID, check credentials
      $session =& $session_data[$_COOKIE['grey_session']];
      if ( isset($auth_data[$session['user']]) )
      {
        $password =& $auth_data[$session['user']];
        if ( $session['hash'] === hmac_md5($password, $session['salt']) )
        {
          // session is valid, logged in
          return $session['user'];
        }
      }
    }
  }
  return ( $use_auth ) ? false : true;
}

function login($username, $password)
{
  global $use_auth, $auth_data;
  if ( !$use_auth )
    return false;
  
  if ( isset($auth_data[$username]) )
  {
    if ( $auth_data[$username] === $password )
    {
      return create_session($username, $password);
    }
  }
  return false;
}

function create_session($username, $password)
{
  load_session_data();
  global $session_data;
  
  $sessid = md5(sha1(microtime() . mt_rand()));
  $salt = md5(sha1(md5(mt_rand() . microtime() . microtime() . mt_rand())));
  
  $session_data[$sessid] = array(
      'user' => $username,
      'hash' => hmac_md5($password, $salt),
      'salt' => $salt
    );
  session_commit_db();
  
  return $sessid;
}

function var_export_string($arr)
{
  ob_start();
  var_export($arr);
  $r = ob_get_contents();
  ob_end_clean();
  return $r;
}

function session_commit_db()
{
  global $session_data;
  $d = var_export_string($session_data);
  $fp = @fopen('./session_db.php', 'w');
  if ( !$fp )
  {
    warning('Could not open the session database for writing. Logins may not work.');
    return false;
  }
  $d = <<<EOF
<?php

// Automatically generated session database for Greyhound. Do not edit this file!

\$GLOBALS['session_data'] = $d;
EOF;
  
  fwrite($fp, $d);
  fclose($fp);
  
  return true;
}

function load_session_data()
{
  if ( file_exists('./session_db.php') )
  {
    require('./session_db.php');
  }
  else
  {
    $GLOBALS['session_data'] = array();
  }
}

$session_data = array();

/*
 * All this HMAC stuff is ported (ok, copied and pasted) from Enano.
 * Hey, I own the copyright on it.
 */

function hmac_core($message, $key, $hashfunc)
{
  if ( strlen($key) % 2 == 1 )
    $key .= '0';
  
  if ( strlen($key) > 128 )
    $key = $hashfunc($key);
  
  while ( strlen($key) < 128 )
  {
    $key .= '00';
  }
  $opad = hmac_hexbytearray($key);
  $ipad = $opad;
  for ( $i = 0; $i < count($ipad); $i++ )
  {
    $opad[$i] = $opad[$i] ^ 0x5c;
    $ipad[$i] = $ipad[$i] ^ 0x36;
  }
  $opad = hmac_bytearraytostring($opad);
  $ipad = hmac_bytearraytostring($ipad);
  return $hashfunc($opad . hexdecode($hashfunc($ipad . $message)));
}

function hmac_hexbytearray($val)
{
  $val = hexdecode($val);
  return hmac_bytearray($val);
}

function hmac_bytearray($val)
{
  $val = str_split($val, 1);
  foreach ( $val as &$char )
  {
    $char = ord($char);
  }
  return $val;
}

function hmac_bytearraytostring($val)
{
  foreach ( $val as &$char )
  {
    $char = chr($char);
  }
  return implode('', $val);
}

function hmac_md5($message, $key)
{
  return hmac_core($message, $key, 'md5');
}

?>