OSDN Git Service

pkwk_hash_compute(): Simplify. Remove scheme aliases will not be used so much
[pukiwiki/pukiwiki.git] / lib / auth.php
1 <?php
2 // PukiWiki - Yet another WikiWikiWeb clone
3 // $Id: auth.php,v 1.16 2005/06/04 00:55:22 henoheno Exp $
4 // Copyright (C) 2003-2005 PukiWiki Developers Team
5 // License: GPL v2 or (at your option) any later version
6 //
7 // Authentication related functions
8
9 define('PKWK_PASSPHRASE_LIMIT_LENGTH', 512);
10
11 // Passwd-auth related ----
12
13 function pkwk_login($pass = '')
14 {
15         global $adminpass;
16
17         if (! PKWK_READONLY && isset($adminpass) &&
18                 pkwk_hash_compute($adminpass, $pass) === $adminpass) {
19                 return TRUE;
20         } else {
21                 sleep(2);       // Blocking brute force attack
22                 return FALSE;
23         }
24 }
25
26 // Compute RFC2307 'userPassword' value, like slappasswd (OpenLDAP)
27 // $scheme : Specify '{scheme}' or '{scheme}salt'
28 // $phrase : Pass-phrase
29 // $prefix : Output with a scheme-prefix or not
30 // $canonical : Correct or Preserve $scheme prefix
31 function pkwk_hash_compute($scheme = '{php_md5}', $phrase = '', $prefix = TRUE, $canonical = FALSE)
32 {
33         if (strlen($phrase) > PKWK_PASSPHRASE_LIMIT_LENGTH)
34                 die('pkwk_hash_compute(): malicious message length');
35
36         // With a {scheme}salt or not
37         $matches = array();
38         if (preg_match('/^(\{.+\})(.*)$/', $scheme, $matches)) {
39                 $scheme = & $matches[1];
40                 $salt   = & $matches[2];
41         } else {
42                 $scheme  = ''; // Cleartext
43                 $salt    = '';
44         }
45
46         // Compute and add a scheme-prefix
47         switch (strtolower($scheme)) {
48
49         // PHP crypt()
50         case '{x-php-crypt}' :
51                 $hash = ($prefix ? ($canonical ? '{x-php-crypt}' : $scheme) : '') .
52                         ($salt != '' ? crypt($phrase, $salt) : crypt($phrase));
53                 break;
54
55         // PHP md5()
56         case '{x-php-md5}'   :
57                 $hash = ($prefix ? ($canonical ? '{x-php-md5}' : $scheme) : '') .
58                         md5($phrase);
59                 break;
60
61         // PHP sha1()
62         case '{x-php-sha1}'  :
63                 $hash = ($prefix ? ($canonical ? '{x-php-sha1}' : $scheme) : '') .
64                         sha1($phrase);
65                 break;
66
67         // LDAP CRYPT
68         case '{crypt}'       :
69                 $hash = ($prefix ? ($canonical ? '{CRYPT}' : $scheme) : '') .
70                         ($salt != '' ? crypt($phrase, $salt) : crypt($phrase));
71                 break;
72
73         // LDAP MD5
74         case '{md5}'         :
75                 $hash = ($prefix ? ($canonical ? '{MD5}' : $scheme) : '') .
76                         base64_encode(hex2bin(md5($phrase)));
77                 break;
78
79         // LDAP SMD5
80         case '{smd5}'        :
81                 // MD5 Key length = 128bits = 16bytes
82                 $salt = ($salt != '' ? substr(base64_decode($salt), 16) : substr(crypt(''), -8));
83                 $hash = ($prefix ? ($canonical ? '{SMD5}' : $scheme) : '') .
84                         base64_encode(hex2bin(md5($phrase . $salt)) . $salt);
85                 break;
86
87         // LDAP SHA
88         case '{sha}'         :
89                 $hash = ($prefix ? ($canonical ? '{SHA}' : $scheme) : '') .
90                         base64_encode(hex2bin(sha1($phrase)));
91                 break;
92
93         // LDAP SSHA
94         case '{ssha}'        :
95                 // SHA-1 Key length = 160bits = 20bytes
96                 $salt = ($salt != '' ? substr(base64_decode($salt), 20) : substr(crypt(''), -8));
97                 $hash = ($prefix ? ($canonical ? '{SSHA}' : $scheme) : '') .
98                         base64_encode(hex2bin(sha1($phrase . $salt)) . $salt);
99                 break;
100
101         // LDAP CLEARTEXT and just cleartext
102         case '{cleartext}'   : /* FALLTHROUGH */
103         case ''              :
104                 $hash = ($prefix ? ($canonical ? '' : $scheme) : '') .
105                         $phrase; // Keep NO prefix with $canonical
106                 break;
107
108         // Invalid scheme
109         default:
110                 $hash = FALSE;
111                 break;
112         }
113
114         return $hash;
115 }
116
117
118 // Basic-auth related ----
119
120 // Check edit-permission
121 function check_editable($page, $auth_flag = TRUE, $exit_flag = TRUE)
122 {
123         global $script, $_title_cannotedit, $_msg_unfreeze;
124
125         if (edit_auth($page, $auth_flag, $exit_flag) && is_editable($page)) {
126                 // Editable
127                 return TRUE;
128         } else {
129                 // Not editable
130                 if ($exit_flag === FALSE) {
131                         return FALSE; // Without exit
132                 } else {
133                         // With exit
134                         $body = $title = str_replace('$1',
135                                 htmlspecialchars(strip_bracket($page)), $_title_cannotedit);
136                         if (is_freeze($page))
137                                 $body .= '(<a href="' . $script . '?cmd=unfreeze&amp;page=' .
138                                         rawurlencode($page) . '">' . $_msg_unfreeze . '</a>)';
139                         $page = str_replace('$1', make_search($page), $_title_cannotedit);
140                         catbody($title, $page, $body);
141                         exit;
142                 }
143         }
144 }
145
146 // Check read-permission
147 function check_readable($page, $auth_flag = TRUE, $exit_flag = TRUE)
148 {
149         return read_auth($page, $auth_flag, $exit_flag);
150 }
151
152 function edit_auth($page, $auth_flag = TRUE, $exit_flag = TRUE)
153 {
154         global $edit_auth, $edit_auth_pages, $_title_cannotedit;
155         return $edit_auth ?  basic_auth($page, $auth_flag, $exit_flag,
156                 $edit_auth_pages, $_title_cannotedit) : TRUE;
157 }
158
159 function read_auth($page, $auth_flag = TRUE, $exit_flag = TRUE)
160 {
161         global $read_auth, $read_auth_pages, $_title_cannotread;
162         return $read_auth ?  basic_auth($page, $auth_flag, $exit_flag,
163                 $read_auth_pages, $_title_cannotread) : TRUE;
164 }
165
166 // Basic authentication
167 function basic_auth($page, $auth_flag, $exit_flag, $auth_pages, $title_cannot)
168 {
169         global $auth_method_type, $auth_users, $_msg_auth;
170
171         // Checked by:
172         $target_str = '';
173         if ($auth_method_type == 'pagename') {
174                 $target_str = $page; // Page name
175         } else if ($auth_method_type == 'contents') {
176                 $target_str = join('', get_source($page)); // Its contents
177         }
178
179         $user_list = array();
180         foreach($auth_pages as $key=>$val)
181                 if (preg_match($key, $target_str))
182                         $user_list = array_merge($user_list, explode(',', $val));
183
184         if (empty($user_list)) return TRUE; // No limit
185
186         $matches = array();
187         if (! isset($_SERVER['PHP_AUTH_USER']) &&
188                 ! isset($_SERVER ['PHP_AUTH_PW']) &&
189                 isset($_SERVER['HTTP_AUTHORIZATION']) &&
190                 preg_match('/^Basic (.*)$/', $_SERVER['HTTP_AUTHORIZATION'], $matches))
191         {
192
193                 // Basic-auth with $_SERVER['HTTP_AUTHORIZATION']
194                 list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
195                         explode(':', base64_decode($matches[1]));
196         }
197
198         if (PKWK_READONLY ||
199                 ! isset($_SERVER['PHP_AUTH_USER']) ||
200                 ! in_array($_SERVER['PHP_AUTH_USER'], $user_list) ||
201                 ! isset($auth_users[$_SERVER['PHP_AUTH_USER']]) ||
202                 pkwk_hash_compute($auth_users[$_SERVER['PHP_AUTH_USER']],
203                         $_SERVER['PHP_AUTH_PW']) !== $auth_users[$_SERVER['PHP_AUTH_USER']])
204         {
205                 // Auth failed
206                 pkwk_common_headers();
207                 if ($auth_flag) {
208                         header('WWW-Authenticate: Basic realm="' . $_msg_auth . '"');
209                         header('HTTP/1.0 401 Unauthorized');
210                 }
211                 if ($exit_flag) {
212                         $body = $title = str_replace('$1',
213                                 htmlspecialchars(strip_bracket($page)), $title_cannot);
214                         $page = str_replace('$1', make_search($page), $title_cannot);
215                         catbody($title, $page, $body);
216                         exit;
217                 }
218                 return FALSE;
219         } else {
220                 return TRUE;
221         }
222 }
223 ?>