Parcourir la source

Reworked ejabberd authentification

tags/3.5.1
Michael Vogel il y a 2 ans
Parent
révision
c6f50d0468
2 fichiers modifiés avec 209 ajouts et 121 suppressions
  1. 200
    121
      include/auth_ejabberd.php
  2. 9
    0
      include/dba.php

+ 200
- 121
include/auth_ejabberd.php Voir le fichier

@@ -47,11 +47,10 @@ require_once("boot.php");
47 47
 
48 48
 global $a, $db;
49 49
 
50
-if(is_null($a)) {
50
+if (is_null($a))
51 51
 	$a = new App;
52
-}
53 52
 
54
-if(is_null($db)) {
53
+if (is_null($db)) {
55 54
 	@include(".htconfig.php");
56 55
 	require_once("include/dba.php");
57 56
 	$db = new dba($db_host, $db_user, $db_pass, $db_data);
@@ -66,142 +65,206 @@ $bDebug	= get_config('jabber','debug');
66 65
 
67 66
 $oAuth = new exAuth($sLogFile, $bDebug);
68 67
 
69
-class exAuth
70
-{
68
+class exAuth {
71 69
 	private $sLogFile;
72 70
 	private $bDebug;
73 71
 
74 72
 	private $rLogFile;
75 73
 
76
-	public function __construct($sLogFile, $bDebug)
77
-	{
78
-		global $a, $db;
74
+	/**
75
+	 * @brief Create the class and do the authentification studd
76
+	 *
77
+	 * @param string $sLogFile The logfile name
78
+	 * @param boolean $bDebug Debug mode
79
+	 */
80
+	public function __construct($sLogFile, $bDebug) {
81
+		global $db;
79 82
 
80 83
 		// setter
81 84
 		$this->sLogFile 	= $sLogFile;
82 85
 		$this->bDebug		= $bDebug;
83 86
 
84
-		// ovo ne provjeravamo jer ako ne mozes kreirati log file, onda si u kvascu :)
87
+		// Open the logfile if the logfile name is defined
85 88
 		if ($this->sLogFile != '')
86 89
 			$this->rLogFile = fopen($this->sLogFile, "a") or die("Error opening log file: ". $this->sLogFile);
87 90
 
88 91
 		$this->writeLog("[exAuth] start");
89 92
 
90
-		// ovdje bi trebali biti spojeni na MySQL, imati otvoren log i zavrtit cekalicu
93
+		// We are connected to the SQL server and are having a log file.
91 94
 		do {
92
-			$iHeader	= fgets(STDIN, 3);
93
-			$aLength 	= unpack("n", $iHeader);
94
-			$iLength	= $aLength["1"];
95
-			if($iLength > 0) {
96
-				// ovo znaci da smo nesto dobili
97
-				$sData = fgets(STDIN, $iLength + 1);
98
-				$this->writeDebugLog("[debug] received data: ". $sData);
99
-				$aCommand = explode(":", $sData);
100
-				if (is_array($aCommand)){
101
-					switch ($aCommand[0]){
102
-						case "isuser":
103
-							// provjeravamo je li korisnik dobar
104
-							if (!isset($aCommand[1])){
105
-								$this->writeLog("[exAuth] invalid isuser command, no username given");
106
-								fwrite(STDOUT, pack("nn", 2, 0));
107
-							} else {
108
-								// ovdje provjeri je li korisnik OK
109
-								$sUser = str_replace(array("%20", "(a)"), array(" ", "@"), $aCommand[1]);
110
-								$this->writeDebugLog("[debug] checking isuser for ". $sUser);
111
-								$sQuery = "SELECT `uid` FROM `user` WHERE `nickname`='". $db->escape($sUser) ."'";
112
-								$this->writeDebugLog("[debug] using query ". $sQuery);
113
-								if ($oResult = q($sQuery)){
114
-									if ($oResult) {
115
-										// korisnik OK
116
-										$this->writeLog("[exAuth] valid user: ". $sUser);
117
-										fwrite(STDOUT, pack("nn", 2, 1));
118
-									} else {
119
-										// korisnik nije OK
120
-										$this->writeLog("[exAuth] invalid user: ". $sUser);
121
-										fwrite(STDOUT, pack("nn", 2, 0));
122
-									}
123
-									//$oResult->close();
124
-								} else {
125
-									$this->writeLog("[MySQL] invalid query: ". $sQuery);
126
-									fwrite(STDOUT, pack("nn", 2, 0));
127
-								}
128
-							}
95
+			// Quit if the database connection went down
96
+			if (!$db->connected()) {
97
+				$this->writeDebugLog("[debug] the database connection went down");
98
+				return;
99
+			}
100
+
101
+			$iHeader = fgets(STDIN, 3);
102
+			$aLength = unpack("n", $iHeader);
103
+			$iLength = $aLength["1"];
104
+
105
+			// No data? Then quit
106
+			if ($iLength == 0) {
107
+				$this->writeDebugLog("[debug] we got no data");
108
+				return;
109
+			}
110
+
111
+			// Fetching the data
112
+			$sData = fgets(STDIN, $iLength + 1);
113
+			$this->writeDebugLog("[debug] received data: ". $sData);
114
+			$aCommand = explode(":", $sData);
115
+			if (is_array($aCommand)) {
116
+				switch ($aCommand[0]) {
117
+					case "isuser":
118
+						// Check the existance of a given username
119
+						$this->isuser($aCommand);
129 120
 						break;
130
-						case "auth":
131
-							// provjeravamo autentifikaciju korisnika
132
-							if (sizeof($aCommand) != 4){
133
-								$this->writeLog("[exAuth] invalid auth command, data missing");
134
-								fwrite(STDOUT, pack("nn", 2, 0));
135
-							} else {
136
-								// ovdje provjeri prijavu
137
-								$sUser = str_replace(array("%20", "(a)"), array(" ", "@"), $aCommand[1]);
138
-								$this->writeDebugLog("[debug] doing auth for ".$sUser."@".$aCommand[2]);
139
-
140
-								// If the hostnames doesn't match, we try to authenticate remotely
141
-								if ($a->get_hostname() != $aCommand[2])
142
-									$Error = !$this->check_credentials($aCommand[2], $aCommand[1], $aCommand[3], true);
143
-								else {
144
-
145
-									//$sQuery = "SELECT `uid`, `password` FROM `user` WHERE `password`='".hash('whirlpool',$aCommand[3])."' AND `nickname`='". $db->escape($sUser) ."'";
146
-									$sQuery = "SELECT `uid`, `password` FROM `user` WHERE `nickname`='". $db->escape($sUser) ."'";
147
-									$this->writeDebugLog("[debug] using query ". $sQuery);
148
-									if ($oResult = q($sQuery)){
149
-										$uid = $oResult[0]["uid"];
150
-										$Error = ($oResult[0]["password"] != hash('whirlpool',$aCommand[3]));
151
-									} else {
152
-										$this->writeLog("[MySQL] invalid query: ". $sQuery);
153
-										$Error = true;
154
-										$uid = -1;
155
-									}
156
-									if ($Error) {
157
-										$oConfig = q("SELECT `v` FROM `pconfig` WHERE `uid`=%d AND `cat` = 'xmpp' AND `k`='password' LIMIT 1;", intval($uid));
158
-										$this->writeLog("[exAuth] got password ".$oConfig[0]["v"]);
159
-										$Error = ($aCommand[3] != $oConfig[0]["v"]);
160
-									}
161
-								}
162
-								if ($Error) {
163
-									$this->writeLog("[exAuth] authentification failed for user ". $sUser ."@". $aCommand[2]);
164
-									fwrite(STDOUT, pack("nn", 2, 0));
165
-								} else {
166
-									$this->writeLog("[exAuth] authentificated user ". $sUser ."@". $aCommand[2]);
167
-									fwrite(STDOUT, pack("nn", 2, 1));
168
-								}
169
-							}
121
+					case "auth":
122
+						// Check if the givven password is correct
123
+						$this->auth($aCommand);
170 124
 						break;
171
-						case "setpass":
172
-							// postavljanje zaporke, onemoguceno
173
-							$this->writeLog("[exAuth] setpass command disabled");
174
-							fwrite(STDOUT, pack("nn", 2, 0));
125
+					case "setpass":
126
+						// We don't accept the setting of passwords here
127
+						$this->writeLog("[exAuth] setpass command disabled");
128
+						fwrite(STDOUT, pack("nn", 2, 0));
175 129
 						break;
176
-						default:
177
-							// ako je uhvaceno ista drugo
178
-							$this->writeLog("[exAuth] unknown command ". $aCommand[0]);
179
-							fwrite(STDOUT, pack("nn", 2, 0));
130
+					default:
131
+						// We don't know the given command
132
+						$this->writeLog("[exAuth] unknown command ". $aCommand[0]);
133
+						fwrite(STDOUT, pack("nn", 2, 0));
180 134
 						break;
181
-					}
182
-				} else {
183
-					$this->writeDebugLog("[debug] invalid command string");
184
-					fwrite(STDOUT, pack("nn", 2, 0));
185 135
 				}
136
+			} else {
137
+				$this->writeDebugLog("[debug] invalid command string");
138
+				fwrite(STDOUT, pack("nn", 2, 0));
186 139
 			}
187
-			unset ($iHeader);
188
-			unset ($aLength);
189
-			unset ($iLength);
190
-			unset($aCommand);
191 140
 		} while (true);
192 141
 	}
193 142
 
194
-	public function __destruct()
195
-	{
196
-		// zatvori log file
197
-		$this->writeLog("[exAuth] stop");
143
+	/**
144
+	 * @brief Check if the given username exists
145
+	 *
146
+	 * @param string $aCommand The command string
147
+	 */
148
+	private function isuser($aCommand) {
149
+		global $a;
150
+
151
+		// Check if there is a username
152
+		if (!isset($aCommand[1])) {
153
+			$this->writeLog("[exAuth] invalid isuser command, no username given");
154
+			fwrite(STDOUT, pack("nn", 2, 0));
155
+		} else {
156
+			// Now we check if the given user is valid
157
+			$sUser = str_replace(array("%20", "(a)"), array(" ", "@"), $aCommand[1]);
158
+			$this->writeDebugLog("[debug] checking isuser for ". $sUser."@".$aCommand[2]);
159
+
160
+			// If the hostnames doesn't match, we try to check remotely
161
+			if ($a->get_hostname() != $aCommand[2])
162
+				$found = $this->check_user($aCommand[2], $aCommand[1], true);
163
+			else {
164
+				$sQuery = "SELECT `uid` FROM `user` WHERE `nickname`='".dbesc($sUser)."'";
165
+				$this->writeDebugLog("[debug] using query ". $sQuery);
166
+				$r = q($sQuery);
167
+				$found = dbm::is_result($r);
168
+			}
169
+			if ($found) {
170
+				// The user is okay
171
+				$this->writeLog("[exAuth] valid user: ". $sUser);
172
+				fwrite(STDOUT, pack("nn", 2, 1));
173
+			} else {
174
+				// The user isn't okay
175
+				$this->writeLog("[exAuth] invalid user: ". $sUser);
176
+				fwrite(STDOUT, pack("nn", 2, 0));
177
+			}
178
+		}
179
+	}
198 180
 
199
-		if (is_resource($this->rLogFile)){
200
-			fclose($this->rLogFile);
181
+	/**
182
+	 * @brief Check remote user existance via HTTP(S)
183
+	 *
184
+	 * @param string $host The hostname
185
+	 * @param string $user Username
186
+	 * @param boolean $ssl Should the check be done via SSL?
187
+	 *
188
+	 * @return boolean Was the user found?
189
+	 */
190
+	private function check_user($host, $user, $ssl) {
191
+
192
+		$url = ($ssl ? "https":"http")."://".$host."/noscrape/".$user;
193
+
194
+		$data = z_fetch_url($url);
195
+
196
+		if (!is_array($data))
197
+			return(false);
198
+
199
+		if ($data["return_code"] != "200")
200
+			return(false);
201
+
202
+		$json = @json_decode($data["body"]);
203
+		if (!is_object($json))
204
+			return(false);
205
+
206
+		return($json->nick == $user);
207
+	}
208
+
209
+	/**
210
+	 * @brief Authenticate the givven user and password
211
+	 *
212
+	 * @param string $aCommand The command string
213
+	 */
214
+	private function auth($aCommand) {
215
+		global $a;
216
+
217
+		// check user authentication
218
+		if (sizeof($aCommand) != 4) {
219
+			$this->writeLog("[exAuth] invalid auth command, data missing");
220
+			fwrite(STDOUT, pack("nn", 2, 0));
221
+		} else {
222
+			// We now check if the password match
223
+			$sUser = str_replace(array("%20", "(a)"), array(" ", "@"), $aCommand[1]);
224
+			$this->writeDebugLog("[debug] doing auth for ".$sUser."@".$aCommand[2]);
225
+
226
+			// If the hostnames doesn't match, we try to authenticate remotely
227
+			if ($a->get_hostname() != $aCommand[2])
228
+				$Error = !$this->check_credentials($aCommand[2], $aCommand[1], $aCommand[3], true);
229
+			else {
230
+				$sQuery = "SELECT `uid`, `password` FROM `user` WHERE `nickname`='".dbesc($sUser)."'";
231
+				$this->writeDebugLog("[debug] using query ". $sQuery);
232
+				if ($oResult = q($sQuery)) {
233
+					$uid = $oResult[0]["uid"];
234
+					$Error = ($oResult[0]["password"] != hash('whirlpool',$aCommand[3]));
235
+				} else {
236
+					$this->writeLog("[MySQL] invalid query: ". $sQuery);
237
+					$Error = true;
238
+					$uid = -1;
239
+				}
240
+				if ($Error) {
241
+					$oConfig = q("SELECT `v` FROM `pconfig` WHERE `uid` = %d AND `cat` = 'xmpp' AND `k`='password' LIMIT 1;", intval($uid));
242
+					$this->writeLog("[exAuth] got password ".$oConfig[0]["v"]);
243
+					$Error = ($aCommand[3] != $oConfig[0]["v"]);
244
+				}
245
+			}
246
+			if ($Error) {
247
+				$this->writeLog("[exAuth] authentification failed for user ".$sUser."@". $aCommand[2]);
248
+				fwrite(STDOUT, pack("nn", 2, 0));
249
+			} else {
250
+				$this->writeLog("[exAuth] authentificated user ".$sUser."@".$aCommand[2]);
251
+				fwrite(STDOUT, pack("nn", 2, 1));
252
+			}
201 253
 		}
202 254
 	}
203 255
 
256
+	/**
257
+	 * @brief Check remote credentials via HTTP(S)
258
+	 *
259
+	 * @param string $host The hostname
260
+	 * @param string $user Username
261
+	 * @param string $password Password
262
+	 * @param boolean $ssl Should the check be done via SSL?
263
+	 *
264
+	 * @return boolean Are the credentials okay?
265
+	 */
204 266
 	private function check_credentials($host, $user, $password, $ssl) {
267
+		$this->writeDebugLog("[debug] check credentials for user ".$user." on ".$host);
205 268
 
206 269
 		$url = ($ssl ? "https":"http")."://".$host."/api/account/verify_credentials.json";
207 270
 
@@ -219,24 +282,40 @@ class exAuth
219 282
 		$http_code = $curl_info["http_code"];
220 283
 		curl_close($ch);
221 284
 
222
-		return($http_code == 200);
285
+		$this->writeDebugLog("[debug] got HTTP code ".$http_code);
286
+
287
+		return ($http_code == 200);
223 288
 	}
224 289
 
225
-	private function writeLog($sMessage)
226
-	{
227
-		if (is_resource($this->rLogFile)) {
228
-			fwrite($this->rLogFile, date("r") ." ". $sMessage ."\n");
229
-		}
290
+	/**
291
+	 * @brief write data to the logfile
292
+	 *
293
+	 * @param string $sMessage The logfile message
294
+	 */
295
+	private function writeLog($sMessage) {
296
+		if (is_resource($this->rLogFile))
297
+			fwrite($this->rLogFile, date("r")." ".$sMessage."\n");
230 298
 	}
231 299
 
232
-	private function writeDebugLog($sMessage)
233
-	{
234
-		if ($this->bDebug){
300
+	/**
301
+	 * @brief write debug data to the logfile
302
+	 *
303
+	 * @param string $sMessage The logfile message
304
+	 */
305
+	private function writeDebugLog($sMessage) {
306
+		if ($this->bDebug)
235 307
 			$this->writeLog($sMessage);
236
-		}
237 308
 	}
238 309
 
310
+	/**
311
+	 * @brief destroy the class
312
+	 */
313
+	public function __destruct() {
314
+		// close the log file
315
+		$this->writeLog("[exAuth] stop");
316
+
317
+		if (is_resource($this->rLogFile))
318
+			fclose($this->rLogFile);
319
+	}
239 320
 }
240 321
 ?>
241
-
242
-

+ 9
- 0
include/dba.php Voir le fichier

@@ -249,6 +249,15 @@ class dba {
249 249
 		}
250 250
 	}
251 251
 
252
+	function connected() {
253
+		if ($this->mysqli)
254
+			$connected = $this->db->ping();
255
+		else
256
+			$connected = mysql_ping($this->db);
257
+
258
+		return $connected;
259
+	}
260
+
252 261
 	function __destruct() {
253 262
 		if ($this->db)
254 263
 			if($this->mysqli)

Chargement…
Annuler
Enregistrer