OSDN Git Service

Better late than never. Added simple credits, workdays(years), and license notificati...
[pukiwiki/pukiwiki.git] / lib / auth.php
1 <?php
2 // PukiWiki - Yet another WikiWikiWeb clone
3 // $Id: auth.php,v 1.13 2005/04/29 09:10:11 henoheno Exp $
4 // Copywrite (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 salt or not
37         $matches = array();
38         if (preg_match('/^(\{.+\})(.*)$/', $scheme, $matches)) {
39                 $scheme = $matches[1];
40                 $salt   = $matches[2];
41         } else if ($scheme != '') {
42                 $scheme = '{CLEARTEXT}';
43         }
44
45         // Compute and add a scheme-prefix
46         switch (strtolower($scheme)) {
47         case '{x-php-crypt}' : /* FALLTHROUGH */
48         case '{php_crypt}'   :
49                 $hash = ($prefix ? ($canonical ? '{x-php-crypt}' : $scheme) : '') .
50                         ($salt != '' ? crypt($phrase, $salt) : crypt($phrase));
51                 break;
52         case '{x-php-md5}'   : /* FALLTHROUGH */
53         case '{php_md5}'     :
54                 $hash = ($prefix ? ($canonical ? '{x-php-md5}' : $scheme) : '') .
55                         md5($phrase);
56                 break;
57         case '{x-php-sha1}'  : /* FALLTHROUGH */
58         case '{php_sha1}'    :
59                 $hash = ($prefix ? ($canonical ? '{x-php-sha1}' : $scheme) : '') .
60                         sha1($phrase);
61                 break;
62
63         case '{crypt}'       : /* FALLTHROUGH */
64         case '{ldap_crypt}'  :
65                 $hash = ($prefix ? ($canonical ? '{CRYPT}' : $scheme) : '') .
66                         ($salt != '' ? crypt($phrase, $salt) : crypt($phrase));
67                 break;
68
69         case '{md5}'         : /* FALLTHROUGH */
70         case '{ldap_md5}'    :
71                 $hash = ($prefix ? ($canonical ? '{MD5}' : $scheme) : '') .
72                         base64_encode(hex2bin(md5($phrase)));
73                 break;
74         case '{smd5}'        : /* FALLTHROUGH */
75         case '{ldap_smd5}'   :
76                 // MD5 Key length = 128bits = 16bytes
77                 $salt = ($salt != '' ? substr(base64_decode($salt), 16) : substr(crypt(''), -8));
78                 $hash = ($prefix ? ($canonical ? '{SMD5}' : $scheme) : '') .
79                         base64_encode(hex2bin(md5($phrase . $salt)) . $salt);
80                 break;
81
82         case '{sha}'         : /* FALLTHROUGH */
83         case '{ldap_sha}'    :
84                 $hash = ($prefix ? ($canonical ? '{SHA}' : $scheme) : '') .
85                         base64_encode(hex2bin(sha1($phrase)));
86                 break;
87         case '{ssha}'        : /* FALLTHROUGH */
88         case '{ldap_ssha}'   :
89                 // SHA-1 Key length = 160bits = 20bytes
90                 $salt = ($salt != '' ? substr(base64_decode($salt), 20) : substr(crypt(''), -8));
91                 $hash = ($prefix ? ($canonical ? '{SSHA}' : $scheme) : '') .
92                         base64_encode(hex2bin(sha1($phrase . $salt)) . $salt);
93                 break;
94
95         case '{cleartext}'   : /* FALLTHROUGH */
96         case '{clear}'       : /* FALLTHROUGH */
97         case ''              :
98                 $hash = & $phrase; break; // Creartext, keep NO prefix
99
100         default:
101                 $hash = FALSE; break; // Invalid scheme
102         }
103
104         return $hash;
105 }
106
107
108 // Basic-auth related ----
109
110 // Check edit-permission
111 function check_editable($page, $auth_flag = TRUE, $exit_flag = TRUE)
112 {
113         global $script, $_title_cannotedit, $_msg_unfreeze;
114
115         if (edit_auth($page, $auth_flag, $exit_flag) && is_editable($page)) {
116                 // Editable
117                 return TRUE;
118         } else {
119                 // Not editable
120                 if ($exit_flag === FALSE) {
121                         return FALSE; // Without exit
122                 } else {
123                         // With exit
124                         $body = $title = str_replace('$1',
125                                 htmlspecialchars(strip_bracket($page)), $_title_cannotedit);
126                         if (is_freeze($page))
127                                 $body .= '(<a href="' . $script . '?cmd=unfreeze&amp;page=' .
128                                         rawurlencode($page) . '">' . $_msg_unfreeze . '</a>)';
129                         $page = str_replace('$1', make_search($page), $_title_cannotedit);
130                         catbody($title, $page, $body);
131                         exit;
132                 }
133         }
134 }
135
136 // Check read-permission
137 function check_readable($page, $auth_flag = TRUE, $exit_flag = TRUE)
138 {
139         return read_auth($page, $auth_flag, $exit_flag);
140 }
141
142 function edit_auth($page, $auth_flag = TRUE, $exit_flag = TRUE)
143 {
144         global $edit_auth, $edit_auth_pages, $_title_cannotedit;
145         return $edit_auth ?  basic_auth($page, $auth_flag, $exit_flag,
146                 $edit_auth_pages, $_title_cannotedit) : TRUE;
147 }
148
149 function read_auth($page, $auth_flag = TRUE, $exit_flag = TRUE)
150 {
151         global $read_auth, $read_auth_pages, $_title_cannotread;
152         return $read_auth ?  basic_auth($page, $auth_flag, $exit_flag,
153                 $read_auth_pages, $_title_cannotread) : TRUE;
154 }
155
156 // Basic authentication
157 function basic_auth($page, $auth_flag, $exit_flag, $auth_pages, $title_cannot)
158 {
159         global $auth_method_type, $auth_users, $_msg_auth;
160
161         // Checked by:
162         $target_str = '';
163         if ($auth_method_type == 'pagename') {
164                 $target_str = $page; // Page name
165         } else if ($auth_method_type == 'contents') {
166                 $target_str = join('', get_source($page)); // Its contents
167         }
168
169         $user_list = array();
170         foreach($auth_pages as $key=>$val)
171                 if (preg_match($key, $target_str))
172                         $user_list = array_merge($user_list, explode(',', $val));
173
174         if (empty($user_list)) return TRUE; // No limit
175
176         $matches = array();
177         if (! isset($_SERVER['PHP_AUTH_USER']) &&
178                 ! isset($_SERVER ['PHP_AUTH_PW']) &&
179                 isset($_SERVER['HTTP_AUTHORIZATION']) &&
180                 preg_match('/^Basic (.*)$/', $_SERVER['HTTP_AUTHORIZATION'], $matches))
181         {
182
183                 // Basic-auth with $_SERVER['HTTP_AUTHORIZATION']
184                 list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
185                         explode(':', base64_decode($matches[1]));
186         }
187
188         if (PKWK_READONLY ||
189                 ! isset($_SERVER['PHP_AUTH_USER']) ||
190                 ! in_array($_SERVER['PHP_AUTH_USER'], $user_list) ||
191                 ! isset($auth_users[$_SERVER['PHP_AUTH_USER']]) ||
192                 pkwk_hash_compute($auth_users[$_SERVER['PHP_AUTH_USER']],
193                         $_SERVER['PHP_AUTH_PW']) !== $auth_users[$_SERVER['PHP_AUTH_USER']])
194         {
195                 // Auth failed
196                 pkwk_common_headers();
197                 if ($auth_flag) {
198                         header('WWW-Authenticate: Basic realm="' . $_msg_auth . '"');
199                         header('HTTP/1.0 401 Unauthorized');
200                 }
201                 if ($exit_flag) {
202                         $body = $title = str_replace('$1',
203                                 htmlspecialchars(strip_bracket($page)), $title_cannot);
204                         $page = str_replace('$1', make_search($page), $title_cannot);
205                         catbody($title, $page, $body);
206                         exit;
207                 }
208                 return FALSE;
209         } else {
210                 return TRUE;
211         }
212 }
213 ?>