]> CyberLeo.Net >> Repos - Github/YOURLS.git/blob - includes/functions-auth.php
Merge pull request #1336 from LeoColomb/Fix-Github
[Github/YOURLS.git] / includes / functions-auth.php
1 <?php
2 /**
3  * Check for valid user. Returns true or an error message
4  *
5  */
6 function yourls_is_valid_user() {
7         static $valid = false;
8         
9         if( $valid )
10                 return true;
11                 
12         $unfiltered_valid = false;
13
14         // Logout request
15         if( isset( $_GET['action'] ) && $_GET['action'] == 'logout' ) {
16                 yourls_do_action( 'logout' );
17                 yourls_store_cookie( null );
18                 return yourls__( 'Logged out successfully' );
19         }
20         
21         // Check cookies or login request. Login form has precedence.
22         global $yourls_user_passwords;
23         
24         yourls_do_action( 'pre_login' );
25
26         // Determine auth method and check credentials
27         if
28                 // API only: Secure (no login or pwd) and time limited token
29                 // ?timestamp=12345678&signature=md5(totoblah12345678)
30                 ( yourls_is_API() &&
31                   isset( $_REQUEST['timestamp'] ) && !empty($_REQUEST['timestamp'] ) &&
32                   isset( $_REQUEST['signature'] ) && !empty($_REQUEST['signature'] )
33                 )
34                 {
35                         yourls_do_action( 'pre_login_signature_timestamp' );
36                         $unfiltered_valid = yourls_check_signature_timestamp();
37                 }
38                 
39         elseif
40                 // API only: Secure (no login or pwd)
41                 // ?signature=md5(totoblah)
42                 ( yourls_is_API() &&
43                   !isset( $_REQUEST['timestamp'] ) &&
44                   isset( $_REQUEST['signature'] ) && !empty( $_REQUEST['signature'] )
45                 )
46                 {
47                         yourls_do_action( 'pre_login_signature' );
48                         $unfiltered_valid = yourls_check_signature();
49                 }
50         
51         elseif
52                 // API or normal: login with username & pwd
53                 ( isset( $_REQUEST['username'] ) && isset( $_REQUEST['password'] )
54                   && !empty( $_REQUEST['username'] ) && !empty( $_REQUEST['password']  ) )
55                 {
56                         yourls_do_action( 'pre_login_username_password' );
57                         $unfiltered_valid = yourls_check_username_password();
58                 }
59         
60         elseif
61                 // Normal only: cookies
62                 ( !yourls_is_API() && 
63                   isset( $_COOKIE['yourls_username'] ) && isset( $_COOKIE['yourls_password'] ) )
64                 {
65                         yourls_do_action( 'pre_login_cookie' );
66                         $unfiltered_valid = yourls_check_auth_cookie();
67                 }
68
69         $valid = yourls_apply_filter( 'is_valid_user', $unfiltered_valid );
70
71         // Login for the win!
72         if ( $valid ) {
73                 yourls_do_action( 'login' );
74                 // (Re)store encrypted cookie if needed and tell it's ok
75                 if ( !yourls_is_API() && $unfiltered_valid ) 
76                         yourls_store_cookie( YOURLS_USER );
77                 return true;
78         }
79         
80         // Login failed
81         yourls_do_action( 'login_failed' );
82
83         if ( isset( $_REQUEST['username'] ) || isset( $_REQUEST['password'] ) ) {
84                 return yourls__( 'Invalid username or password' );
85         } else {
86                 return yourls__( 'Please log in' );
87         }
88 }
89
90 /**
91  * Check auth against list of login=>pwd. Sets user if applicable, returns bool
92  *
93  */
94 function yourls_check_username_password() {
95         global $yourls_user_passwords;
96         if( isset( $yourls_user_passwords[ $_REQUEST['username'] ] ) && yourls_check_password_hash( $yourls_user_passwords[ $_REQUEST['username'] ], $_REQUEST['password'] ) ) {
97                 yourls_set_user( $_REQUEST['username'] );
98                 return true;
99         }
100         return false;
101 }
102
103 /**
104  * Check a REQUEST password sent in plain text against stored password which can be a salted hash
105  *
106  */
107 function yourls_check_password_hash( $stored, $plaintext ) {
108         if ( substr( $stored, 0, 4 ) == 'md5:' and strlen( $stored ) == 42 ) {
109                 // Stored password is a salted hash: "md5:<$r = rand(10000,99999)>:<md5($r.'thepassword')>"
110                 // And 42. Of course. http://www.google.com/search?q=the+answer+to+life+the+universe+and+everything
111                 list( $temp, $salt, $md5 ) = explode( ':', $stored );
112                 return( $stored == 'md5:'.$salt.':'.md5( $salt.$plaintext ) );
113         } else {
114                 // Password was sent in clear
115                 $message  = '';
116                 $message .= yourls__( '<strong>Notice</strong>: your password is stored as clear text in your <tt>config.php</tt>' );
117                 $message .= yourls__( 'Did you know you can easily improve the security of your YOURLS install by <strong>encrypting</strong> your password?' );
118                 $message .= yourls__( 'See <a href="http://yourls.org/userpassword">UsernamePassword</a> for details' );
119                 yourls_add_notice( $message, 'notice' );
120                 return( $stored == $plaintext );
121         }
122 }
123
124
125 /**
126  * Check auth against encrypted COOKIE data. Sets user if applicable, returns bool
127  *
128  */
129 function yourls_check_auth_cookie() {
130         global $yourls_user_passwords;
131         foreach( $yourls_user_passwords as $valid_user => $valid_password ) {
132                 if( 
133                         yourls_salt( $valid_user ) == $_COOKIE['yourls_username']
134                         && yourls_salt( $valid_password ) == $_COOKIE['yourls_password'] 
135                 ) {
136                         yourls_set_user( $valid_user );
137                         return true;
138                 }
139         }
140         return false;
141 }
142
143 /**
144  * Check auth against signature and timestamp. Sets user if applicable, returns bool
145  *
146  */
147 function yourls_check_signature_timestamp() {
148         // Timestamp in PHP : time()
149         // Timestamp in JS: parseInt(new Date().getTime() / 1000)
150         global $yourls_user_passwords;
151         foreach( $yourls_user_passwords as $valid_user => $valid_password ) {
152                 if (
153                         (
154                                 md5( $_REQUEST['timestamp'].yourls_auth_signature( $valid_user ) ) == $_REQUEST['signature']
155                                 or
156                                 md5( yourls_auth_signature( $valid_user ).$_REQUEST['timestamp'] ) == $_REQUEST['signature']
157                         )
158                         &&
159                         yourls_check_timestamp( $_REQUEST['timestamp'] )
160                         ) {
161                         yourls_set_user( $valid_user );
162                         return true;
163                 }
164         }
165         return false;
166 }
167
168 /**
169  * Check auth against signature. Sets user if applicable, returns bool
170  *
171  */
172 function yourls_check_signature() {
173         global $yourls_user_passwords;
174         foreach( $yourls_user_passwords as $valid_user => $valid_password ) {
175                 if ( yourls_auth_signature( $valid_user ) == $_REQUEST['signature'] ) {
176                         yourls_set_user( $valid_user );
177                         return true;
178                 }
179         }
180         return false;
181 }
182
183 /**
184  * Generate secret signature hash
185  *
186  */
187 function yourls_auth_signature( $username = false ) {
188         if( !$username && defined('YOURLS_USER') ) {
189                 $username = YOURLS_USER;
190         }
191         return ( $username ? substr( yourls_salt( $username ), 0, 10 ) : 'Cannot generate auth signature: no username' );
192 }
193
194 /**
195  * Check if timestamp is not too old
196  *
197  */
198 function yourls_check_timestamp( $time ) {
199         $now = time();
200         // Allow timestamp to be a little in the future or the past -- see Issue 766
201         return yourls_apply_filter( 'check_timestamp', abs( $now - $time ) < YOURLS_NONCE_LIFE, $time );
202 }
203
204 /**
205  * Store new cookie. No $user will delete the cookie.
206  *
207  */
208 function yourls_store_cookie( $user = null ) {
209         if( !$user ) {
210                 $pass = null;
211                 $time = time() - 3600;
212         } else {
213                 global $yourls_user_passwords;
214                 if( isset($yourls_user_passwords[$user]) ) {
215                         $pass = $yourls_user_passwords[$user];
216                 } else {
217                         die( 'Stealing cookies?' ); // This should never happen
218                 }
219                 $time = time() + YOURLS_COOKIE_LIFE;
220         }
221         
222         $domain   = yourls_apply_filter( 'setcookie_domain',   parse_url( YOURLS_SITE, 1 ) );
223         $secure   = yourls_apply_filter( 'setcookie_secure',   yourls_is_ssl() );
224         $httponly = yourls_apply_filter( 'setcookie_httponly', true );
225                 
226         if ( !headers_sent() ) {
227                 // Set httponly if the php version is >= 5.2.0
228                 if( version_compare( phpversion(), '5.2.0', 'ge' ) ) {
229                         setcookie('yourls_username', yourls_salt( $user ), $time, '/', $domain, $secure, $httponly );
230                         setcookie('yourls_password', yourls_salt( $pass ), $time, '/', $domain, $secure, $httponly );
231                 } else {
232                         setcookie('yourls_username', yourls_salt( $user ), $time, '/', $domain, $secure );
233                         setcookie('yourls_password', yourls_salt( $pass ), $time, '/', $domain, $secure );
234                 }
235         }
236 }
237
238 /**
239  * Set user name
240  *
241  */
242 function yourls_set_user( $user ) {
243         if( !defined( 'YOURLS_USER' ) )
244                 define( 'YOURLS_USER', $user );
245 }