kerbauth/libkrb5.php
changeset 0 5a5a654fae1a
equal deleted inserted replaced
-1:000000000000 0:5a5a654fae1a
       
     1 <?php
       
     2 
       
     3 class KerberosError extends Exception
       
     4 {
       
     5 }
       
     6 
       
     7 /**
       
     8  * Parse an INI file, specifically one in krb5.conf format.
       
     9  * @param string File to read
       
    10  * @return array
       
    11  */
       
    12 
       
    13 function krb5_read_ini_file($file)
       
    14 {
       
    15 	$fp = @fopen($file, 'r');
       
    16 	if ( !$fp )
       
    17 		return array();
       
    18 	$section = '';
       
    19 	$data = array();
       
    20 	
       
    21 	while ( !feof($fp) )
       
    22 	{
       
    23 		// read in line
       
    24 		$line = @fgets($fp, 8192);
       
    25 		
       
    26 		// trim and skip comments
       
    27 		$line = trim(preg_replace('/;.*$/', '', $line));
       
    28 		if ( empty($line) )
       
    29 			continue;
       
    30 		
       
    31 		if ( preg_match('/^\[(.+?)\]$/', $line, $match) )
       
    32 		{
       
    33 			// new section
       
    34 			$section = $match[1];
       
    35 			continue;
       
    36 		}
       
    37 		if ( count($parts = explode('=', $line)) == 2 )
       
    38 		{
       
    39 			list($name, $value) = $parts;
       
    40 		}
       
    41 		else
       
    42 		{
       
    43 			$name = $line;
       
    44 			$value = true;
       
    45 		}
       
    46 		$name = trim($name);
       
    47 		// ltrim to honor trailing spaces/tabs
       
    48 		$value = ltrim($value);
       
    49 		if ( $value === '{' )
       
    50 		{
       
    51 			$section .= ".$name";
       
    52 			$subsection = $name;
       
    53 			continue;
       
    54 		}
       
    55 		else if ( $name === '}' && isset($subsection) )
       
    56 		{
       
    57 			$section = substr($section, 0, strlen($section) - 1 - strlen($subsection));;
       
    58 			continue;
       
    59 		}
       
    60 		if ( !empty($section) )
       
    61 		{
       
    62 			$name = "$section.$name";
       
    63 		}
       
    64 		if ( $value === 'true' )
       
    65 			$value = true;
       
    66 		else if ( $value === 'false' )
       
    67 			$value = false;
       
    68 		else if ( ctype_digit($value) )
       
    69 			$value = intval($value);
       
    70 		$data[$name] = $value;
       
    71 	}
       
    72 	fclose($fp);
       
    73 	return $data;
       
    74 }
       
    75 
       
    76 function krb5_get_config()
       
    77 {
       
    78 	static $config = false;
       
    79 	if ( @file_exists('/etc/krb5.conf') && @is_readable('/etc/krb5.conf') )
       
    80 		return $config = krb5_read_ini_file('/etc/krb5.conf');
       
    81 	
       
    82 	return false;
       
    83 }
       
    84 
       
    85 function krb5_get_realm()
       
    86 {
       
    87 	if ( $config = krb5_get_config() )
       
    88 	{
       
    89 		if ( isset($config['libdefaults.default_realm']) )
       
    90 		{
       
    91 			return $config['libdefaults.default_realm'];
       
    92 		}
       
    93 	}
       
    94 	return false;
       
    95 }
       
    96 
       
    97 function krb5_detect_admin_server($realm = '__default__')
       
    98 {
       
    99 	if ( $config = krb5_get_config() )
       
   100 	{
       
   101 		if ( isset($config['libdefaults.default_realm']) )
       
   102 		{
       
   103 			$realm = ($realm == '__default__') ? $config['libdefaults.default_realm'] : $realm;
       
   104 			// we have the default realm; determine what the admin server is
       
   105 			if ( isset($config["realms.$realm.admin_server"]) )
       
   106 			{
       
   107 				return $config["realms.$realm.admin_server"];
       
   108 			}
       
   109 			// failing ini parsing, honor dns_lookup_kdc (this isn't strictly looking up KDCs, more the master, but this allows for configurability)
       
   110 			if ( isset($config['libdefaults.dns_lookup_kdc']) && $config['libdefaults.dns_lookup_kdc'] && function_exists('dns_get_record') )
       
   111 			{
       
   112 				// look it up
       
   113 				$dns_result = dns_get_record('_kerberos-master._udp.' . strtolower($realm), DNS_SRV);
       
   114 				// find result with lowest priority
       
   115 				$host = '';
       
   116 				$pri = 0x7FFFFFFF;
       
   117 				if ( $dns_result )
       
   118 				{
       
   119 					foreach ( $dns_result as $entry )
       
   120 					{
       
   121 						if ( $entry['pri'] < $pri )
       
   122 						{
       
   123 							$host = $entry['target'];
       
   124 						}
       
   125 					}
       
   126 					if ( !empty($host) )
       
   127 					{
       
   128 						return $host;
       
   129 					}
       
   130 				}
       
   131 			}
       
   132 		}
       
   133 	}
       
   134 	return false;
       
   135 }
       
   136 
       
   137 function krb5_verify_creds($username, $password)
       
   138 {
       
   139 	$realm = getConfig('kerb_realm', krb5_get_realm());
       
   140 	$server = getConfig('kerb_admin_server', krb5_detect_admin_server($realm));
       
   141 	
       
   142 	if ( empty($realm) || empty($server) )
       
   143 		throw new KerberosError("Empty realm or server");
       
   144 	
       
   145 	$result = kadm5_init_with_password($server, $realm, $username, $password);
       
   146 	if ( $result === FALSE )
       
   147 	{
       
   148 		return FALSE;
       
   149 	}
       
   150 	@kadm5_destroy($result);
       
   151 	return TRUE;
       
   152 }
       
   153