LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   php htpasswd authentication (https://www.linuxquestions.org/questions/programming-9/php-htpasswd-authentication-4175446215/)

adambot 01-18-2013 01:40 PM

php htpasswd authentication
 
I am trying to get php to authenticate against my .htpasswd, however, it never finishes, but rather keeps giving me the username/password dialog

here is my code:
Code:

<?php
if( !($passwd = @fopen( "./.htpasswd", "r" )))
{  echo "Cannot open password file.";
  exit;
}

if( !$PHP_AUTH_USER )
{  Header( "WWW-authenticate: basic realm=\"Realm\"" );
  Header( "HTTP/1.0 401 Unauthorized" );
  echo "Text to see if user hits 'Cancel'";
  exit;
}

// file format => username:passwd{\n}
while( $pwent = fgets( $passwd, 100 ))
{  $part = split( ":", ereg_replace( "\n", "", $pwent ));
  if( $part[0] != $PHP_AUTH_USER )
      continue;

  // Username was found - verify passwd
  if( $part[1] !=
        // The crypt salt is stored as chars 1&2 of passwd
        crypt( $PHP_AUTH_PW, substr( $part[1], 0, 2 )))
      break;

  echo "Hello $PHP_AUTH_USER.<p>\n";
}

// This only has effect of no text was output previously, so
//  it is ignored in all cases except authentication error.
@Header( "HTTP/1.0 401 Unauthorized" );
?>

Thanks!

YankeePride13 01-18-2013 02:55 PM

You don't need to use PHP to authenticate via htpasswd. Just drop a htaccess file at the top of the directory you want to protect and have it link to the htpasswd file.

adambot 01-18-2013 03:32 PM

Quote:

Originally Posted by YankeePride13 (Post 4873110)
You don't need to use PHP to authenticate via htpasswd. Just drop a htaccess file at the top of the directory you want to protect and have it link to the htpasswd file.

I know that, however, i am going to be experimenting with 2 factor authentication and would like to be able to have everything portal based rather than use apache's basic authentication.

sundialsvcs 01-18-2013 04:45 PM

Unfortunately, "you're missing the point."

".htpasswd" is strictly for use by Apache: your (PHP or what-have-you) script will never be invoked at all unless that level of authentication is cleared. Hence, your code never has to be concerned with it.

To put it another way: there is nothing that 'your code' can possibly add to it. If you want there to be another "factor," it can't have anything to do with ".htpasswd" since that is by-definition only one factor, and that factor has already been cleared. Any attempt by you to make further use of that factor ... does not introduce another factor.

adambot 01-18-2013 05:13 PM

Quote:

Originally Posted by sundialsvcs (Post 4873160)
Unfortunately, "you're missing the point."

".htpasswd" is strictly for use by Apache: your (PHP or what-have-you) script will never be invoked at all unless that level of authentication is cleared. Hence, your code never has to be concerned with it.

To put it another way: there is nothing that 'your code' can possibly add to it. If you want there to be another "factor," it can't have anything to do with ".htpasswd" since that is by-definition only one factor, and that factor has already been cleared. Any attempt by you to make further use of that factor ... does not introduce another factor.

http://koivi.com/archives/php-http-auth/
https://www.duosecurity.com/docs/duoweb

clearly 2 factor authentication is possible, the second factor would then be invoked where the echo "hello... currently is.

thanks!
Adam

adambot 01-19-2013 09:53 AM

Here is the final code that i was able to get to work:

Code:

<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL | E_STRICT);

if( !($passwd = @fopen( "./.htpasswd", "r" )))
{  echo "Cannot open password file.";
  exit;
}

if (!isset($_SERVER['PHP_AUTH_USER']))
{  Header( "WWW-authenticate: basic realm=\"Realm\"" );
  Header( "HTTP/1.0 401 Unauthorized" );
  echo "Text to see if user hits 'Cancel'";
  exit;
}

while( $pwent = fgets( $passwd, 100 )) {
  $part = explode( ":", chop($pwent));
  $pass = explode( "\$", $part[1]);

  $plainpasswd=$_SERVER['PHP_AUTH_PW'];
  $salt=$pass[2];
  $len = strlen($plainpasswd);
  $text = $plainpasswd.'$apr1$'.$salt;
  $bin = pack("H32", md5($plainpasswd.$salt.$plainpasswd));
  for($i = $len; $i > 0; $i -= 16) { $text .= substr($bin, 0, min(16, $i)); }
  for($i = $len; $i > 0; $i >>= 1) { $text .= ($i & 1) ? chr(0) : $plainpasswd{0}; }
  $bin = pack("H32", md5($text));
  for($i = 0; $i < 1000; $i++) {
      $new = ($i & 1) ? $plainpasswd : $bin;
      if ($i % 3) $new .= $salt;
      if ($i % 7) $new .= $plainpasswd;
      $new .= ($i & 1) ? $bin : $plainpasswd;
      $bin = pack("H32", md5($new));
  }
  $tmp="";
  for ($i = 0; $i < 5; $i++) {
      $k = $i + 6;
      $j = $i + 12;
      if ($j == 16) $j = 5;
      $tmp = $bin[$i].$bin[$k].$bin[$j].$tmp;
  }
  $tmp = chr(0).chr(0).$bin[11].$tmp;
  $tmp = strtr(strrev(substr(base64_encode($tmp), 2)),
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
  "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
  $hashedpasswd = "$"."apr1"."$".$salt."$".$tmp;

  if (($_SERVER['PHP_AUTH_USER'] == $part[0]) && ($hashedpasswd == $part[1]))
  {
      echo "Now you are Logged In";
      exit;
  }

}

// This only has effect of no text was output previously, so
//  it is ignored in all cases except authentication error.
Header( "HTTP/1.0 401 Unauthorized" );
echo "No Match";
?>

Quote:

Originally Posted by sundialsvcs (Post 4873160)
".htpasswd" is strictly for use by Apache: your (PHP or what-have-you) script will never be invoked at all unless that level of authentication is cleared. Hence, your code never has to be concerned with it.

as you can see it is possible to use the .htpasswd file instead of needing a database for password authentication through php because there is no .htaccess, just a .htpasswd so the file is still protected via the apache config


All times are GMT -5. The time now is 02:06 PM.