<?php


/**
  * SquirrelMail Login Auth Plugin
  * Copyright (C) 2001 Tyler Akins
  * Copyright (C) 2004 Paul Lesneiwski <pdontthink@angrynerds.com>
  * This program is licensed under GPL. See COPYING for details
  *
  */


/**
  * Check if user has already authenticated themselves; 
  * can we skip login page?
  *
  */
function login_auth_skip_login_do()
{

   global $PHP_AUTH_USER, $PHP_AUTH_PW;
   sqgetGlobalVar('PHP_AUTH_USER', $PHP_AUTH_USER, SQ_SERVER);
   sqgetGlobalVar('PHP_AUTH_PW', $PHP_AUTH_PW, SQ_SERVER);


   // no user or pwd?  just log in as usual
   //
   if (empty($PHP_AUTH_USER) || empty($PHP_AUTH_PW))
      return;


   // try to log in with http-authenticated user info
   //
   include_once(SM_PATH . 'functions/imap.php');
   global $imapServerAddress, $imapPort, $onetimepad;


   $onetimepad = OneTimePadCreate(strlen($PHP_AUTH_PW));
   $key = OneTimePadEncrypt($PHP_AUTH_PW, $onetimepad);
   $imapConn = login_auth_sqimap_login($PHP_AUTH_USER, $key, $imapServerAddress, $imapPort, 1);


   if ($imapConn) 
   {
      global $login_auth_user, $login_auth_pass, $login_auth;
      $login_auth = 'YES';
      $login_auth_user = $PHP_AUTH_USER;
      $login_auth_pass = $PHP_AUTH_PW;
      sqsession_register($login_auth, 'login_auth');
      sqsession_register($login_auth_user, 'login_auth_user');
      sqsession_register($login_auth_pass, 'login_auth_pass');
      header('Location: ' . SM_PATH . 'src/redirect.php?login_username=login_auth');
      exit();
   }

}



/** 
  * Use correct login info from HTTP
  *
  */
function login_auth_login_before_do()
{

   global $plugins, $login_auth, $login_auth_user, $login_auth_pass,
          $just_logged_in, $login_username, $secretkey;

   sqgetGlobalVar('login_auth', $login_auth, SQ_SESSION);
   sqgetGlobalVar('login_auth_user', $login_auth_user, SQ_SESSION);
   sqgetGlobalVar('login_auth_pass', $login_auth_pass, SQ_SESSION);


   // user is logging in via normal means
   //
   if (empty($login_auth) || $login_auth !== 'YES')
      return;


   $login_username = $login_auth_user;
   $secretkey = $login_auth_pass;
   $just_logged_in = 1;


   // adjust for password forget plugin
   //
   if (in_array('password_forget', $plugins)) 
   {
      $login_username = 'login_auth_user';
      $secretkey = 'login_auth_pass';

      // in case password forget has already been called...
      //
      if (function_exists('password_forget_post_do')) password_forget_post_do();

   }

}



/**
  * Logs the user into the imap server.  If $hide is set, no error messages
  * will be displayed.  This function returns the imap connection handle.
  *
  * Stolen from functions/imap_general.php; we need our own version because
  * the one we took it from will only exit or show a login error page when
  * we have a bad login.  Instead, we only want to return FALSE in such a
  * case
  *
  */
function login_auth_sqimap_login($username, $password, $imap_server_address, $imap_port, $hide)
{
    global $color, $squirrelmail_language, $onetimepad, $use_imap_tls, $imap_auth_mech;

    if (!isset($onetimepad) || empty($onetimepad)) {
        sqgetglobalvar('onetimepad' , $onetimepad , SQ_SESSION );
    }
    $imap_server_address = sqimap_get_user_server($imap_server_address, $username);
        $host=$imap_server_address;

        if (($use_imap_tls == true) and (check_php_version(4,3)) and (extension_loaded('openssl'))) {
          /* Use TLS by prefixing "tls://" to the hostname */
          $imap_server_address = 'tls://' . $imap_server_address;
        }

    $imap_stream = fsockopen ( $imap_server_address, $imap_port, $error_number, $error_string, 15);

    /* Do some error correction */
    if (!$imap_stream) {
        if (!$hide) {
            set_up_language($squirrelmail_language, true);
            require_once(SM_PATH . 'functions/display_messages.php');
            $string = sprintf (_("Error connecting to IMAP server: %s.") .
                              "<br>\r\n", $imap_server_address) .
                      "$error_number : $error_string<br>\r\n";
            logout_error($string,$color);
        }
        exit;
    }

    $server_info = fgets ($imap_stream, 1024);

    /* Decrypt the password */
    $password = OneTimePadDecrypt($password, $onetimepad);

        if (($imap_auth_mech == 'cram-md5') OR ($imap_auth_mech == 'digest-md5')) {
      // We're using some sort of authentication OTHER than plain or login
          $tag=sqimap_session_id(false);
          if ($imap_auth_mech == 'digest-md5') {
            $query = $tag . " AUTHENTICATE DIGEST-MD5\r\n";
          } elseif ($imap_auth_mech == 'cram-md5') {
            $query = $tag . " AUTHENTICATE CRAM-MD5\r\n";
          }
          fputs($imap_stream,$query);
          $answer=sqimap_fgets($imap_stream);
          // Trim the "+ " off the front
          $response=explode(" ",$answer,3);
          if ($response[0] == '+') {
            // Got a challenge back
                $challenge=$response[1];
                if ($imap_auth_mech == 'digest-md5') {
                  $reply = digest_md5_response($username,$password,$challenge,'imap',$host);
                } elseif ($imap_auth_mech == 'cram-md5') {
                  $reply = cram_md5_response($username,$password,$challenge);
                }
                fputs($imap_stream,$reply);
                $read=sqimap_fgets($imap_stream);
                if ($imap_auth_mech == 'digest-md5') {
                  // DIGEST-MD5 has an extra step..
                  if (substr($read,0,1) == '+') { // OK so far..
                    fputs($imap_stream,"\r\n");
                    $read=sqimap_fgets($imap_stream);
                  }
                }
                $results=explode(" ",$read,3);
                $response=$results[1];
                $message=$results[2];
      } else {
                // Fake the response, so the error trap at the bottom will work
                $response="BAD";
                $message='IMAP server does not appear to support the authentication method selected.';
                $message .= '  Please contact your system administrator.';
      }
    } elseif ($imap_auth_mech == 'login') {
          // Original IMAP login code
      $query = 'LOGIN "' . quoteimap($username) .  '" "' . quoteimap($password) . '"';
      $read = sqimap_run_command ($imap_stream, $query, false, $response, $message);
    } elseif ($imap_auth_mech == 'plain') {
                /* Replace this with SASL PLAIN if it ever gets implemented */
                $response="BAD";
                $message='SquirrelMail does not support SASL PLAIN yet. Rerun conf.pl and use login instead.';
        } else {
                $response="BAD";
                $message="Internal SquirrelMail error - unknown IMAP authentication method chosen.  Please contact the developers.";
        }

        /* If the connection was not successful, lets see why */
    if ($response != 'OK') {
        if (!$hide) {
            if ($response != 'NO') {
                /* "BAD" and anything else gets reported here. */
                $message = htmlspecialchars($message);
                set_up_language($squirrelmail_language, true);
                require_once(SM_PATH . 'functions/display_messages.php');
                if ($response == 'BAD') {
                    $string = sprintf (_("Bad request: %s")."<br>\r\n", $message);
                } else {
                    $string = sprintf (_("Unknown error: %s") . "<br>\n", $message);
                }
                if (isset($read) && is_array($read)) {
                    $string .= '<br>' . _("Read data:") . "<br>\n";
                    foreach ($read as $line) {
                        $string .= htmlspecialchars($line) . "<br>\n";
                    }
                }
                error_box($string,$color);
                exit;
            } else {
                /*
                 * If the user does not log in with the correct
                 * username and password it is not possible to get the
                 * correct locale from the user's preferences.
                 * Therefore, apply the same hack as on the login
                 * screen.
                 *
                 * $squirrelmail_language is set by a cookie when
                 * the user selects language and logs out
                 */

                set_up_language($squirrelmail_language, true);
                include_once(SM_PATH . 'functions/display_messages.php' );
                sqsession_destroy();
                logout_error( _("Unknown user or password incorrect.") );
                exit;
            }
        } else {
            // THIS IS THE ONLY CHANGE FOR LOGIN_AUTH PLUGIN:
            //exit;
            return FALSE;
        }
    }
    return $imap_stream;
}



?>
