| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * auth.php |
| 5 | * |
| 6 | * Copyright (c) 1999-2002 The SquirrelMail Project Team |
| 7 | * Licensed under the GNU GPL. For full terms see the file COPYING. |
| 8 | * |
| 9 | * Contains functions used to do authentication. |
| 10 | * |
| 11 | * $Id$ |
| 12 | */ |
| 13 | |
| 14 | /* Put in a safety net here, in case a naughty admin didn't run conf.pl when they upgraded */ |
| 15 | |
| 16 | if (! isset($smtp_auth_mech)) { |
| 17 | $smtp_auth_mech = 'none'; |
| 18 | } |
| 19 | |
| 20 | if (! isset($imap_auth_mech)) { |
| 21 | $imap_auth_mech = 'plain'; |
| 22 | } |
| 23 | |
| 24 | if (! isset($use_imap_tls)) { |
| 25 | $use_imap_tls = false; |
| 26 | } |
| 27 | |
| 28 | if (! isset($use_smtp_tls)) { |
| 29 | $use_smtp_tls = false; |
| 30 | } |
| 31 | |
| 32 | function is_logged_in() { |
| 33 | |
| 34 | if ( sqsession_is_registered('user_is_logged_in') ) { |
| 35 | return; |
| 36 | } else { |
| 37 | global $PHP_SELF, $session_expired_post, |
| 38 | $session_expired_location; |
| 39 | |
| 40 | /* First we store some information in the new session to prevent |
| 41 | * information-loss. |
| 42 | */ |
| 43 | |
| 44 | $session_expired_post = $_POST; |
| 45 | $session_expired_location = $PHP_SELF; |
| 46 | if (!sqsession_is_registered('session_expired_post')) { |
| 47 | sqsession_register($session_expired_post,'session_expired_post'); |
| 48 | } |
| 49 | if (!sqsession_is_registered('session_expired_location')) { |
| 50 | sqsession_register($session_expired_location,'session_expired_location'); |
| 51 | } |
| 52 | include_once( '../functions/display_messages.php' ); |
| 53 | logout_error( _("You must be logged in to access this page.") ); |
| 54 | exit; |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | function cram_md5_response ($username,$password,$challenge) { |
| 59 | |
| 60 | /* Given the challenge from the server, supply the response using |
| 61 | cram-md5 (See RFC 2195 for details) |
| 62 | NOTE: Requires mhash extension to PHP |
| 63 | */ |
| 64 | $challenge=base64_decode($challenge); |
| 65 | $hash=bin2hex(mhash(MHASH_MD5,$challenge,$password)); |
| 66 | $response=base64_encode($username . " " . $hash) . "\r\n"; |
| 67 | return $response; |
| 68 | } |
| 69 | |
| 70 | function digest_md5_response ($username,$password,$challenge,$service,$host) { |
| 71 | /* Given the challenge from the server, calculate and return the response-string |
| 72 | for digest-md5 authentication. (See RFC 2831 for more details) */ |
| 73 | $result=digest_md5_parse_challenge($challenge); |
| 74 | |
| 75 | // verify server supports qop=auth |
| 76 | // $qop = explode(",",$result['qop']); |
| 77 | //if (!in_array("auth",$qop)) { |
| 78 | // rfc2831: client MUST fail if no qop methods supported |
| 79 | // return false; |
| 80 | //} |
| 81 | $cnonce = base64_encode(bin2hex(mhash(MHASH_MD5, microtime()))); |
| 82 | $ncount = "00000001"; |
| 83 | |
| 84 | /* This can be auth (authentication only), auth-int (integrity protection), or |
| 85 | auth-conf (confidentiality protection). Right now only auth is supported. |
| 86 | DO NOT CHANGE THIS VALUE */ |
| 87 | $qop_value = "auth"; |
| 88 | |
| 89 | $digest_uri_value = $service . '/' . $host; |
| 90 | |
| 91 | // build the $response_value |
| 92 | //FIXME This will probably break badly if a server sends more than one realm |
| 93 | $string_a1 = utf8_encode($username).":"; |
| 94 | $string_a1 .= utf8_encode($result['realm']).":"; |
| 95 | $string_a1 .= utf8_encode($password); |
| 96 | $string_a1 = mhash(MHASH_MD5, $string_a1); |
| 97 | $A1 = $string_a1 . ":" . $result['nonce'] . ":" . $cnonce; |
| 98 | $A1 = bin2hex(mhash(MHASH_MD5, $A1)); |
| 99 | $A2 = "AUTHENTICATE:$digest_uri_value"; |
| 100 | // If qop is auth-int or auth-conf, A2 gets a little extra |
| 101 | if ($qop_value != 'auth') { |
| 102 | $A2 .= ':00000000000000000000000000000000'; |
| 103 | } |
| 104 | $A2 = bin2hex(mhash(MHASH_MD5, $A2)); |
| 105 | |
| 106 | $string_response = $result['nonce'] . ':' . $ncount . ':' . $cnonce . ':' . $qop_value; |
| 107 | $response_value = bin2hex(mhash(MHASH_MD5, $A1.":".$string_response.":".$A2)); |
| 108 | |
| 109 | $reply = 'charset=utf-8,username="' . $username . '",realm="' . $result["realm"] . '",'; |
| 110 | $reply .= 'nonce="' . $result['nonce'] . '",nc=' . $ncount . ',cnonce="' . $cnonce . '",'; |
| 111 | $reply .= "digest-uri=\"$digest_uri_value\",response=$response_value"; |
| 112 | $reply .= ',qop=' . $qop_value; |
| 113 | $reply = base64_encode($reply); |
| 114 | return $reply . "\r\n"; |
| 115 | |
| 116 | } |
| 117 | |
| 118 | function digest_md5_parse_challenge($challenge) { |
| 119 | /* This function parses the challenge sent during DIGEST-MD5 authentication and |
| 120 | returns an array. See the RFC for details on what's in the challenge string. |
| 121 | */ |
| 122 | $challenge=base64_decode($challenge); |
| 123 | while (isset($challenge)) { |
| 124 | if ($challenge{0} == ',') { // First char is a comma, must not be 1st time through loop |
| 125 | $challenge=substr($challenge,1); |
| 126 | } |
| 127 | $key=explode('=',$challenge,2); |
| 128 | $challenge=$key[1]; |
| 129 | $key=$key[0]; |
| 130 | if ($challenge{0} == '"') { |
| 131 | // We're in a quoted value |
| 132 | // Drop the first quote, since we don't care about it |
| 133 | $challenge=substr($challenge,1); |
| 134 | // Now explode() to the next quote, which is the end of our value |
| 135 | $val=explode('"',$challenge,2); |
| 136 | $challenge=$val[1]; // The rest of the challenge, work on it in next iteration of loop |
| 137 | $value=explode(',',$val[0]); |
| 138 | // Now, for those quoted values that are only 1 piece.. |
| 139 | if (sizeof($value) == 1) { |
| 140 | $value=$value[0]; // Convert to non-array |
| 141 | } |
| 142 | } else { |
| 143 | // We're in a "simple" value - explode to next comma |
| 144 | $val=explode(',',$challenge,2); |
| 145 | if (isset($val[1])) { |
| 146 | $challenge=$val[1]; |
| 147 | } else { |
| 148 | unset($challenge); |
| 149 | } |
| 150 | $value=$val[0]; |
| 151 | } |
| 152 | $parsed["$key"]=$value; |
| 153 | } // End of while loop |
| 154 | return $parsed; |
| 155 | } |
| 156 | |
| 157 | ?> |