Blame view

sources/apps/files_encryption/lib/keymanager.php 17.2 KB
03e52840d   Kload   Init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  <?php
  
  /**
   * ownCloud
   *
   * @author Bjoern Schiessle
   * @copyright 2012 Bjoern Schiessle <schiessle@owncloud.com>
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
   * License as published by the Free Software Foundation; either
   * version 3 of the License, or any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
   *
   * You should have received a copy of the GNU Affero General Public
   * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
   *
   */
  
  namespace OCA\Encryption;
  
  /**
6d9380f96   Cédric Dupont   Update sources OC...
27
   * Class to manage storage and retrieval of encryption keys
03e52840d   Kload   Init
28
29
30
31
32
   * @note Where a method requires a view object, it's root must be '/'
   */
  class Keymanager {
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
33
  	 * retrieve the ENCRYPTED private key from a user
03e52840d   Kload   Init
34
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
35
  	 * @param \OC\Files\View $view
03e52840d   Kload   Init
36
37
38
39
  	 * @param string $user
  	 * @return string private key or false (hopefully)
  	 * @note the key returned by this method must be decrypted before use
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
40
  	public static function getPrivateKey(\OC\Files\View $view, $user) {
03e52840d   Kload   Init
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  
  		$path = '/' . $user . '/' . 'files_encryption' . '/' . $user . '.private.key';
  		$key = false;
  
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
  
  		if ($view->file_exists($path)) {
  			$key = $view->file_get_contents($path);
  		}
  
  		\OC_FileProxy::$enabled = $proxyStatus;
  
  		return $key;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
58
59
60
  	 * retrieve public key for a specified user
  	 * @param \OC\Files\View $view
  	 * @param string $userId
03e52840d   Kload   Init
61
62
  	 * @return string public key or false
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
63
  	public static function getPublicKey(\OC\Files\View $view, $userId) {
03e52840d   Kload   Init
64
65
66
67
68
69
70
71
72
73
74
75
76
  
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
  
  		$result = $view->file_get_contents('/public-keys/' . $userId . '.public.key');
  
  		\OC_FileProxy::$enabled = $proxyStatus;
  
  		return $result;
  
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
77
78
79
  	 * Retrieve a user's public and private key
  	 * @param \OC\Files\View $view
  	 * @param string $userId
03e52840d   Kload   Init
80
81
  	 * @return array keys: privateKey, publicKey
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
82
  	public static function getUserKeys(\OC\Files\View $view, $userId) {
03e52840d   Kload   Init
83
84
85
86
87
88
89
90
91
  
  		return array(
  			'publicKey' => self::getPublicKey($view, $userId),
  			'privateKey' => self::getPrivateKey($view, $userId)
  		);
  
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
92
93
  	 * Retrieve public keys for given users
  	 * @param \OC\Files\View $view
03e52840d   Kload   Init
94
95
96
  	 * @param array $userIds
  	 * @return array of public keys for the specified users
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
97
  	public static function getPublicKeys(\OC\Files\View $view, array $userIds) {
03e52840d   Kload   Init
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  
  		$keys = array();
  
  		foreach ($userIds as $userId) {
  
  			$keys[$userId] = self::getPublicKey($view, $userId);
  
  		}
  
  		return $keys;
  
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
112
  	 * store file encryption key
03e52840d   Kload   Init
113
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
114
  	 * @param \OC\Files\View $view
31b7f2792   Kload   Upgrade to ownclo...
115
  	 * @param \OCA\Encryption\Util $util
03e52840d   Kload   Init
116
  	 * @param string $path relative path of the file, including filename
31b7f2792   Kload   Upgrade to ownclo...
117
  	 * @param string $catfile keyfile content
03e52840d   Kload   Init
118
119
120
121
  	 * @return bool true/false
  	 * @note The keyfile is not encrypted here. Client code must
  	 * asymmetrically encrypt the keyfile before passing it to this method
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
122
  	public static function setFileKey(\OC\Files\View $view, $util, $path, $catfile) {
03e52840d   Kload   Init
123
124
125
  
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
03e52840d   Kload   Init
126
127
128
129
130
131
132
133
  		list($owner, $filename) = $util->getUidAndFilename($path);
  
  		// in case of system wide mount points the keys are stored directly in the data directory
  		if ($util->isSystemWideMountPoint($filename)) {
  			$basePath = '/files_encryption/keyfiles';
  		} else {
  			$basePath = '/' . $owner . '/files_encryption/keyfiles';
  		}
6d9380f96   Cédric Dupont   Update sources OC...
134
  		$targetPath = self::keySetPreparation($view, $filename, $basePath);
03e52840d   Kload   Init
135
136
  
  		// try reusing key file if part file
31b7f2792   Kload   Upgrade to ownclo...
137
  		if (Helper::isPartialFilePath($targetPath)) {
03e52840d   Kload   Init
138
139
  
  			$result = $view->file_put_contents(
31b7f2792   Kload   Upgrade to ownclo...
140
  				$basePath . '/' . Helper::stripPartialFileExtension($targetPath) . '.key', $catfile);
03e52840d   Kload   Init
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  
  		} else {
  
  			$result = $view->file_put_contents($basePath . '/' . $targetPath . '.key', $catfile);
  
  		}
  
  		\OC_FileProxy::$enabled = $proxyStatus;
  
  		return $result;
  
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
155
156
  	 * retrieve keyfile for an encrypted file
  	 * @param \OC\Files\View $view
31b7f2792   Kload   Upgrade to ownclo...
157
  	 * @param \OCA\Encryption\Util $util
6d9380f96   Cédric Dupont   Update sources OC...
158
  	 * @param string|false $filePath
03e52840d   Kload   Init
159
160
161
162
163
  	 * @internal param \OCA\Encryption\file $string name
  	 * @return string file key or false
  	 * @note The keyfile returned is asymmetrically encrypted. Decryption
  	 * of the keyfile must be performed by client code
  	 */
31b7f2792   Kload   Upgrade to ownclo...
164
  	public static function getFileKey($view, $util, $filePath) {
03e52840d   Kload   Init
165

03e52840d   Kload   Init
166
167
  
  		list($owner, $filename) = $util->getUidAndFilename($filePath);
31b7f2792   Kload   Upgrade to ownclo...
168
  		$filename = Helper::stripPartialFileExtension($filename);
03e52840d   Kload   Init
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
  		$filePath_f = ltrim($filename, '/');
  
  		// in case of system wide mount points the keys are stored directly in the data directory
  		if ($util->isSystemWideMountPoint($filename)) {
  			$keyfilePath = '/files_encryption/keyfiles/' . $filePath_f . '.key';
  		} else {
  			$keyfilePath = '/' . $owner . '/files_encryption/keyfiles/' . $filePath_f . '.key';
  		}
  
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
  
  		if ($view->file_exists($keyfilePath)) {
  
  			$result = $view->file_get_contents($keyfilePath);
  
  		} else {
  
  			$result = false;
  
  		}
  
  		\OC_FileProxy::$enabled = $proxyStatus;
  
  		return $result;
  
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
198
  	 * Delete a keyfile
03e52840d   Kload   Init
199
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
200
  	 * @param \OC\Files\View $view
03e52840d   Kload   Init
201
  	 * @param string $path path of the file the key belongs to
a293d369c   Kload   Update sources to...
202
  	 * @param string $userId the user to whom the file belongs
03e52840d   Kload   Init
203
204
205
206
  	 * @return bool Outcome of unlink operation
  	 * @note $path must be relative to data/user/files. e.g. mydoc.txt NOT
  	 *       /data/admin/files/mydoc.txt
  	 */
a293d369c   Kload   Update sources to...
207
  	public static function deleteFileKey($view, $path, $userId=null) {
03e52840d   Kload   Init
208
209
  
  		$trimmed = ltrim($path, '/');
a293d369c   Kload   Update sources to...
210
211
212
213
214
215
216
217
218
  		if ($trimmed === '') {
  			\OCP\Util::writeLog('Encryption library',
  				'Can\'t delete file-key empty path given!', \OCP\Util::ERROR);
  			return false;
  		}
  
  		if ($userId === null) {
  			$userId = Helper::getUser($path);
  		}
31b7f2792   Kload   Upgrade to ownclo...
219
  		$util = new Util($view, $userId);
03e52840d   Kload   Init
220
221
222
223
224
225
226
227
  
  		if($util->isSystemWideMountPoint($path)) {
  			$keyPath = '/files_encryption/keyfiles/' . $trimmed;
  		} else {
  			$keyPath = '/' . $userId . '/files_encryption/keyfiles/' . $trimmed;
  		}
  
  		$result = false;
6d9380f96   Cédric Dupont   Update sources OC...
228
  		$fileExists = $view->file_exists('/' . $userId . '/files/' . $trimmed);
03e52840d   Kload   Init
229

6d9380f96   Cédric Dupont   Update sources OC...
230
231
  		if ($view->is_dir($keyPath) && !$fileExists) {
  			\OCP\Util::writeLog('files_encryption', 'deleteFileKey: delete file key: ' . $keyPath, \OCP\Util::DEBUG);
03e52840d   Kload   Init
232
  			$result = $view->unlink($keyPath);
6d9380f96   Cédric Dupont   Update sources OC...
233
234
235
  		} elseif ($view->file_exists($keyPath . '.key') && !$fileExists) {
  			\OCP\Util::writeLog('files_encryption', 'deleteFileKey: delete file key: ' . $keyPath, \OCP\Util::DEBUG);
  			$result = $view->unlink($keyPath . '.key');
03e52840d   Kload   Init
236

03e52840d   Kload   Init
237
  		}
6d9380f96   Cédric Dupont   Update sources OC...
238
  		if ($fileExists) {
03e52840d   Kload   Init
239
  			\OCP\Util::writeLog('Encryption library',
6d9380f96   Cédric Dupont   Update sources OC...
240
241
242
243
  					'Did not delete the file key, file still exists: ' . '/' . $userId . '/files/' . $trimmed, \OCP\Util::ERROR);
  		} elseif (!$result) {
  			\OCP\Util::writeLog('Encryption library',
  					'Could not delete keyfile; does not exist: "' . $keyPath, \OCP\Util::ERROR);
03e52840d   Kload   Init
244
245
246
247
248
249
250
  		}
  
  		return $result;
  
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
251
  	 * store private key from the user
03e52840d   Kload   Init
252
253
254
255
256
  	 * @param string $key
  	 * @return bool
  	 * @note Encryption of the private key must be performed by client code
  	 * as no encryption takes place here
  	 */
f7d878ff1   kload   [enh] Update to 7...
257
  	public static function setPrivateKey($key, $user = '') {
03e52840d   Kload   Init
258

f7d878ff1   kload   [enh] Update to 7...
259
260
261
262
263
  		if ($user === '') {
  			$user = \OCP\User::getUser();
  		}
  
  		$header = Crypt::generateHeader();
03e52840d   Kload   Init
264

6d9380f96   Cédric Dupont   Update sources OC...
265
  		$view = new \OC\Files\View('/' . $user . '/files_encryption');
03e52840d   Kload   Init
266
267
268
  
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
6d9380f96   Cédric Dupont   Update sources OC...
269
  		if (!$view->file_exists('')) {
03e52840d   Kload   Init
270
  			$view->mkdir('');
6d9380f96   Cédric Dupont   Update sources OC...
271
  		}
03e52840d   Kload   Init
272

f7d878ff1   kload   [enh] Update to 7...
273
  		$result = $view->file_put_contents($user . '.private.key', $header . $key);
03e52840d   Kload   Init
274
275
276
277
278
279
280
281
  
  		\OC_FileProxy::$enabled = $proxyStatus;
  
  		return $result;
  
  	}
  
  	/**
f7d878ff1   kload   [enh] Update to 7...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  	 * write private system key (recovery and public share key) to disk
  	 *
  	 * @param string $key encrypted key
  	 * @param string $keyName name of the key file
  	 * @return boolean
  	 */
  	public static function setPrivateSystemKey($key, $keyName) {
  
  		$header = Crypt::generateHeader();
  
  		$view = new \OC\Files\View('/owncloud_private_key');
  
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
  
  		if (!$view->file_exists('')) {
  			$view->mkdir('');
  		}
  
  		$result = $view->file_put_contents($keyName, $header . $key);
  
  		\OC_FileProxy::$enabled = $proxyStatus;
  
  		return $result;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
309
  	 * store share key
03e52840d   Kload   Init
310
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
311
  	 * @param \OC\Files\View $view
03e52840d   Kload   Init
312
  	 * @param string $path where the share key is stored
6d9380f96   Cédric Dupont   Update sources OC...
313
  	 * @param string $shareKey
03e52840d   Kload   Init
314
315
316
317
  	 * @return bool true/false
  	 * @note The keyfile is not encrypted here. Client code must
  	 * asymmetrically encrypt the keyfile before passing it to this method
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
318
  	private static function setShareKey(\OC\Files\View $view, $path, $shareKey) {
03e52840d   Kload   Init
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
  
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
  
  		$result = $view->file_put_contents($path, $shareKey);
  
  		\OC_FileProxy::$enabled = $proxyStatus;
  
  		if (is_int($result) && $result > 0) {
  			return true;
  		} else {
  			return false;
  		}
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
335
336
  	 * store multiple share keys for a single file
  	 * @param \OC\Files\View $view
31b7f2792   Kload   Upgrade to ownclo...
337
338
  	 * @param \OCA\Encryption\Util $util
  	 * @param string $path
03e52840d   Kload   Init
339
340
341
  	 * @param array $shareKeys
  	 * @return bool
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
342
  	public static function setShareKeys(\OC\Files\View $view, $util, $path, array $shareKeys) {
03e52840d   Kload   Init
343
344
345
  
  		// $shareKeys must be  an array with the following format:
  		// [userId] => [encrypted key]
03e52840d   Kload   Init
346
347
348
349
350
351
352
353
354
  
  		list($owner, $filename) = $util->getUidAndFilename($path);
  
  		// in case of system wide mount points the keys are stored directly in the data directory
  		if ($util->isSystemWideMountPoint($filename)) {
  			$basePath = '/files_encryption/share-keys';
  		} else {
  			$basePath = '/' . $owner . '/files_encryption/share-keys';
  		}
6d9380f96   Cédric Dupont   Update sources OC...
355
  		$shareKeyPath = self::keySetPreparation($view, $filename, $basePath);
03e52840d   Kload   Init
356
357
358
359
360
361
  
  		$result = true;
  
  		foreach ($shareKeys as $userId => $shareKey) {
  
  			// try reusing key file if part file
31b7f2792   Kload   Upgrade to ownclo...
362
363
  			if (Helper::isPartialFilePath($shareKeyPath)) {
  				$writePath = $basePath . '/' . Helper::stripPartialFileExtension($shareKeyPath) . '.' . $userId . '.shareKey';
03e52840d   Kload   Init
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
  			} else {
  				$writePath = $basePath . '/' . $shareKeyPath . '.' . $userId . '.shareKey';
  			}
  
  			if (!self::setShareKey($view, $writePath, $shareKey)) {
  
  				// If any of the keys are not set, flag false
  				$result = false;
  			}
  		}
  
  		// Returns false if any of the keys weren't set
  		return $result;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
380
381
  	 * retrieve shareKey for an encrypted file
  	 * @param \OC\Files\View $view
03e52840d   Kload   Init
382
  	 * @param string $userId
31b7f2792   Kload   Upgrade to ownclo...
383
  	 * @param \OCA\Encryption\Util $util
03e52840d   Kload   Init
384
  	 * @param string $filePath
03e52840d   Kload   Init
385
386
387
388
  	 * @return string file key or false
  	 * @note The sharekey returned is encrypted. Decryption
  	 * of the keyfile must be performed by client code
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
389
  	public static function getShareKey(\OC\Files\View $view, $userId, $util, $filePath) {
03e52840d   Kload   Init
390
391
392
393
  
  		// try reusing key file if part file
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
03e52840d   Kload   Init
394
  		list($owner, $filename) = $util->getUidAndFilename($filePath);
31b7f2792   Kload   Upgrade to ownclo...
395
  		$filename = Helper::stripPartialFileExtension($filename);
03e52840d   Kload   Init
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
  		// in case of system wide mount points the keys are stored directly in the data directory
  		if ($util->isSystemWideMountPoint($filename)) {
  			$shareKeyPath = '/files_encryption/share-keys/' . $filename . '.' . $userId . '.shareKey';
  		} else {
  			$shareKeyPath = '/' . $owner . '/files_encryption/share-keys/' . $filename . '.' . $userId . '.shareKey';
  		}
  
  		if ($view->file_exists($shareKeyPath)) {
  
  			$result = $view->file_get_contents($shareKeyPath);
  
  		} else {
  
  			$result = false;
  
  		}
  
  		\OC_FileProxy::$enabled = $proxyStatus;
  
  		return $result;
  
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
420
421
  	 * delete all share keys of a given file
  	 * @param \OC\Files\View $view
03e52840d   Kload   Init
422
423
424
  	 * @param string $userId owner of the file
  	 * @param string $filePath path to the file, relative to the owners file dir
  	 */
a293d369c   Kload   Update sources to...
425
426
427
  	public static function delAllShareKeys($view, $userId, $filePath) {
  
  		$filePath = ltrim($filePath, '/');
6d9380f96   Cédric Dupont   Update sources OC...
428
429
430
431
432
  		if ($view->file_exists('/' . $userId . '/files/' . $filePath)) {
  			\OCP\Util::writeLog('Encryption library',
  					'File still exists, stop deleting share keys!', \OCP\Util::ERROR);
  			return false;
  		}
a293d369c   Kload   Update sources to...
433
434
435
436
437
  		if ($filePath === '') {
  			\OCP\Util::writeLog('Encryption library',
  					'Can\'t delete share-keys empty path given!', \OCP\Util::ERROR);
  			return false;
  		}
03e52840d   Kload   Init
438
439
440
441
442
443
444
445
  
  		$util = new util($view, $userId);
  
  		if ($util->isSystemWideMountPoint($filePath)) {
  			$baseDir = '/files_encryption/share-keys/';
  		} else {
  			$baseDir = $userId . '/files_encryption/share-keys/';
  		}
6d9380f96   Cédric Dupont   Update sources OC...
446
  		$result = true;
03e52840d   Kload   Init
447

a293d369c   Kload   Update sources to...
448
  		if ($view->is_dir($baseDir . $filePath)) {
6d9380f96   Cédric Dupont   Update sources OC...
449
450
  			\OCP\Util::writeLog('files_encryption', 'delAllShareKeys: delete share keys: ' . $baseDir . $filePath, \OCP\Util::DEBUG);
  			$result = $view->unlink($baseDir . $filePath);
03e52840d   Kload   Init
451
  		} else {
a293d369c   Kload   Update sources to...
452
453
454
455
456
  			$parentDir = dirname($baseDir . $filePath);
  			$filename = pathinfo($filePath, PATHINFO_BASENAME);
  			foreach($view->getDirectoryContent($parentDir) as $content) {
  				$path = $content['path'];
  				if (self::getFilenameFromShareKey($content['name'])  === $filename) {
6d9380f96   Cédric Dupont   Update sources OC...
457
458
  					\OCP\Util::writeLog('files_encryption', 'dellAllShareKeys: delete share keys: ' . '/' . $userId . '/' . $path, \OCP\Util::DEBUG);
  					$result &= $view->unlink('/' . $userId . '/' . $path);
03e52840d   Kload   Init
459
460
461
  				}
  			}
  		}
6d9380f96   Cédric Dupont   Update sources OC...
462
463
  
  		return (bool)$result;
03e52840d   Kload   Init
464
465
466
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
467
468
469
470
471
472
  	 * Delete a single user's shareKey for a single file
  	 *
  	 * @param \OC\Files\View $view relative to data/
  	 * @param array $userIds list of users we want to remove
  	 * @param string $filename the owners name of the file for which we want to remove the users relative to data/user/files
  	 * @param string $owner owner of the file
03e52840d   Kload   Init
473
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
474
  	public static function delShareKey($view, $userIds, $filename, $owner) {
03e52840d   Kload   Init
475
476
477
  
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
6d9380f96   Cédric Dupont   Update sources OC...
478
  		$util = new Util($view, $owner);
03e52840d   Kload   Init
479
480
481
482
483
484
485
486
  
  		if ($util->isSystemWideMountPoint($filename)) {
  			$shareKeyPath = \OC\Files\Filesystem::normalizePath('/files_encryption/share-keys/' . $filename);
  		} else {
  			$shareKeyPath = \OC\Files\Filesystem::normalizePath('/' . $owner . '/files_encryption/share-keys/' . $filename);
  		}
  
  		if ($view->is_dir($shareKeyPath)) {
6d9380f96   Cédric Dupont   Update sources OC...
487
  			self::recursiveDelShareKeys($shareKeyPath, $userIds, $owner, $view);
03e52840d   Kload   Init
488
489
490
491
  
  		} else {
  
  			foreach ($userIds as $userId) {
6d9380f96   Cédric Dupont   Update sources OC...
492
493
494
495
496
497
498
  				if ($userId === $owner && $view->file_exists('/' . $owner . '/files/' . $filename)) {
  					\OCP\Util::writeLog('files_encryption', 'Tried to delete owner key, but the file still exists!', \OCP\Util::FATAL);
  					continue;
  				}
  				$result = $view->unlink($shareKeyPath . '.' . $userId . '.shareKey');
  				\OCP\Util::writeLog('files_encryption', 'delShareKey: delete share key: ' . $shareKeyPath . '.' . $userId . '.shareKey' , \OCP\Util::DEBUG);
  				if (!$result) {
03e52840d   Kload   Init
499
500
501
502
  					\OCP\Util::writeLog('Encryption library',
  						'Could not delete shareKey; does not exist: "' . $shareKeyPath . '.' . $userId
  						. '.shareKey"', \OCP\Util::ERROR);
  				}
03e52840d   Kload   Init
503
504
505
506
507
508
509
  			}
  		}
  
  		\OC_FileProxy::$enabled = $proxyStatus;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
510
  	 * recursively delete share keys from given users
03e52840d   Kload   Init
511
512
513
  	 *
  	 * @param string $dir directory
  	 * @param array $userIds user ids for which the share keys should be deleted
6d9380f96   Cédric Dupont   Update sources OC...
514
515
  	 * @param string $owner owner of the file
  	 * @param \OC\Files\View $view view relative to data/
03e52840d   Kload   Init
516
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
  	private static function recursiveDelShareKeys($dir, $userIds, $owner, $view) {
  
  		$dirContent = $view->opendir($dir);
  		$dirSlices = explode('/', ltrim($dir, '/'));
  		$realFileDir = '/' . $owner . '/files/' . implode('/', array_slice($dirSlices, 3)) . '/';
  
  		if (is_resource($dirContent)) {
  			while (($file = readdir($dirContent)) !== false) {
  				if (!\OC\Files\Filesystem::isIgnoredDir($file)) {
  					if ($view->is_dir($dir . '/' . $file)) {
  						self::recursiveDelShareKeys($dir . '/' . $file, $userIds, $owner, $view);
  					} else {
  						$realFile = $realFileDir . self::getFilenameFromShareKey($file);
  						foreach ($userIds as $userId) {
  							if (preg_match("/(.*)." . $userId . ".shareKey/", $file)) {
  								if ($userId === $owner &&
  										$view->file_exists($realFile)) {
  									\OCP\Util::writeLog('files_encryption', 'original file still exists, keep owners share key!', \OCP\Util::ERROR);
  									continue;
  								}
  								\OCP\Util::writeLog('files_encryption', 'recursiveDelShareKey: delete share key: ' . $file, \OCP\Util::DEBUG);
  								$view->unlink($dir . '/' . $file);
  							}
  						}
  					}
  				}
03e52840d   Kload   Init
543
  			}
6d9380f96   Cédric Dupont   Update sources OC...
544
  			closedir($dirContent);
03e52840d   Kload   Init
545
546
547
548
  		}
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
549
550
551
  	 * Make preparations to vars and filesystem for saving a keyfile
  	 * @param string|boolean $path
  	 * @param string $basePath
03e52840d   Kload   Init
552
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
553
  	protected static function keySetPreparation(\OC\Files\View $view, $path, $basePath) {
03e52840d   Kload   Init
554
555
556
557
558
559
560
561
562
563
  
  		$targetPath = ltrim($path, '/');
  
  		$path_parts = pathinfo($targetPath);
  
  		// If the file resides within a subdirectory, create it
  		if (
  			isset($path_parts['dirname'])
  			&& !$view->file_exists($basePath . '/' . $path_parts['dirname'])
  		) {
6d9380f96   Cédric Dupont   Update sources OC...
564
  			$sub_dirs = explode('/', $basePath . '/' . $path_parts['dirname']);
03e52840d   Kload   Init
565
566
567
568
569
570
571
572
573
574
575
576
  			$dir = '';
  			foreach ($sub_dirs as $sub_dir) {
  				$dir .= '/' . $sub_dir;
  				if (!$view->is_dir($dir)) {
  					$view->mkdir($dir);
  				}
  			}
  		}
  
  		return $targetPath;
  
  	}
a293d369c   Kload   Update sources to...
577
578
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
579
  	 * extract filename from share key name
a293d369c   Kload   Update sources to...
580
  	 * @param string $shareKey (filename.userid.sharekey)
6d9380f96   Cédric Dupont   Update sources OC...
581
  	 * @return string|false filename or false
a293d369c   Kload   Update sources to...
582
583
584
585
586
587
588
589
590
591
592
  	 */
  	protected static function getFilenameFromShareKey($shareKey) {
  		$parts = explode('.', $shareKey);
  
  		$filename = false;
  		if(count($parts) > 2) {
  			$filename = implode('.', array_slice($parts, 0, count($parts)-2));
  		}
  
  		return $filename;
  	}
03e52840d   Kload   Init
593
  }