Blame view

sources/apps/files_encryption/lib/keymanager.php 16.5 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
257
258
259
  	 * @param string $key
  	 * @return bool
  	 * @note Encryption of the private key must be performed by client code
  	 * as no encryption takes place here
  	 */
  	public static function setPrivateKey($key) {
  
  		$user = \OCP\User::getUser();
6d9380f96   Cédric Dupont   Update sources OC...
260
  		$view = new \OC\Files\View('/' . $user . '/files_encryption');
03e52840d   Kload   Init
261
262
263
  
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
6d9380f96   Cédric Dupont   Update sources OC...
264
  		if (!$view->file_exists('')) {
03e52840d   Kload   Init
265
  			$view->mkdir('');
6d9380f96   Cédric Dupont   Update sources OC...
266
  		}
03e52840d   Kload   Init
267
268
269
270
271
272
273
274
275
276
  
  		$result = $view->file_put_contents($user . '.private.key', $key);
  
  		\OC_FileProxy::$enabled = $proxyStatus;
  
  		return $result;
  
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
277
  	 * store share key
03e52840d   Kload   Init
278
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
279
  	 * @param \OC\Files\View $view
03e52840d   Kload   Init
280
  	 * @param string $path where the share key is stored
6d9380f96   Cédric Dupont   Update sources OC...
281
  	 * @param string $shareKey
03e52840d   Kload   Init
282
283
284
285
  	 * @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...
286
  	private static function setShareKey(\OC\Files\View $view, $path, $shareKey) {
03e52840d   Kload   Init
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  
  		$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...
303
304
  	 * store multiple share keys for a single file
  	 * @param \OC\Files\View $view
31b7f2792   Kload   Upgrade to ownclo...
305
306
  	 * @param \OCA\Encryption\Util $util
  	 * @param string $path
03e52840d   Kload   Init
307
308
309
  	 * @param array $shareKeys
  	 * @return bool
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
310
  	public static function setShareKeys(\OC\Files\View $view, $util, $path, array $shareKeys) {
03e52840d   Kload   Init
311
312
313
  
  		// $shareKeys must be  an array with the following format:
  		// [userId] => [encrypted key]
03e52840d   Kload   Init
314
315
316
317
318
319
320
321
322
  
  		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...
323
  		$shareKeyPath = self::keySetPreparation($view, $filename, $basePath);
03e52840d   Kload   Init
324
325
326
327
328
329
  
  		$result = true;
  
  		foreach ($shareKeys as $userId => $shareKey) {
  
  			// try reusing key file if part file
31b7f2792   Kload   Upgrade to ownclo...
330
331
  			if (Helper::isPartialFilePath($shareKeyPath)) {
  				$writePath = $basePath . '/' . Helper::stripPartialFileExtension($shareKeyPath) . '.' . $userId . '.shareKey';
03e52840d   Kload   Init
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  			} 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...
348
349
  	 * retrieve shareKey for an encrypted file
  	 * @param \OC\Files\View $view
03e52840d   Kload   Init
350
  	 * @param string $userId
31b7f2792   Kload   Upgrade to ownclo...
351
  	 * @param \OCA\Encryption\Util $util
03e52840d   Kload   Init
352
  	 * @param string $filePath
03e52840d   Kload   Init
353
354
355
356
  	 * @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...
357
  	public static function getShareKey(\OC\Files\View $view, $userId, $util, $filePath) {
03e52840d   Kload   Init
358
359
360
361
  
  		// try reusing key file if part file
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
03e52840d   Kload   Init
362
  		list($owner, $filename) = $util->getUidAndFilename($filePath);
31b7f2792   Kload   Upgrade to ownclo...
363
  		$filename = Helper::stripPartialFileExtension($filename);
03e52840d   Kload   Init
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
  		// 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...
388
389
  	 * delete all share keys of a given file
  	 * @param \OC\Files\View $view
03e52840d   Kload   Init
390
391
392
  	 * @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...
393
394
395
  	public static function delAllShareKeys($view, $userId, $filePath) {
  
  		$filePath = ltrim($filePath, '/');
6d9380f96   Cédric Dupont   Update sources OC...
396
397
398
399
400
  		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...
401
402
403
404
405
  		if ($filePath === '') {
  			\OCP\Util::writeLog('Encryption library',
  					'Can\'t delete share-keys empty path given!', \OCP\Util::ERROR);
  			return false;
  		}
03e52840d   Kload   Init
406
407
408
409
410
411
412
413
  
  		$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...
414
  		$result = true;
03e52840d   Kload   Init
415

a293d369c   Kload   Update sources to...
416
  		if ($view->is_dir($baseDir . $filePath)) {
6d9380f96   Cédric Dupont   Update sources OC...
417
418
  			\OCP\Util::writeLog('files_encryption', 'delAllShareKeys: delete share keys: ' . $baseDir . $filePath, \OCP\Util::DEBUG);
  			$result = $view->unlink($baseDir . $filePath);
03e52840d   Kload   Init
419
  		} else {
a293d369c   Kload   Update sources to...
420
421
422
423
424
  			$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...
425
426
  					\OCP\Util::writeLog('files_encryption', 'dellAllShareKeys: delete share keys: ' . '/' . $userId . '/' . $path, \OCP\Util::DEBUG);
  					$result &= $view->unlink('/' . $userId . '/' . $path);
03e52840d   Kload   Init
427
428
429
  				}
  			}
  		}
6d9380f96   Cédric Dupont   Update sources OC...
430
431
  
  		return (bool)$result;
03e52840d   Kload   Init
432
433
434
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
435
436
437
438
439
440
  	 * 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
441
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
442
  	public static function delShareKey($view, $userIds, $filename, $owner) {
03e52840d   Kload   Init
443
444
445
  
  		$proxyStatus = \OC_FileProxy::$enabled;
  		\OC_FileProxy::$enabled = false;
6d9380f96   Cédric Dupont   Update sources OC...
446
  		$util = new Util($view, $owner);
03e52840d   Kload   Init
447
448
449
450
451
452
453
454
  
  		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...
455
  			self::recursiveDelShareKeys($shareKeyPath, $userIds, $owner, $view);
03e52840d   Kload   Init
456
457
458
459
  
  		} else {
  
  			foreach ($userIds as $userId) {
6d9380f96   Cédric Dupont   Update sources OC...
460
461
462
463
464
465
466
  				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
467
468
469
470
  					\OCP\Util::writeLog('Encryption library',
  						'Could not delete shareKey; does not exist: "' . $shareKeyPath . '.' . $userId
  						. '.shareKey"', \OCP\Util::ERROR);
  				}
03e52840d   Kload   Init
471
472
473
474
475
476
477
  			}
  		}
  
  		\OC_FileProxy::$enabled = $proxyStatus;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
478
  	 * recursively delete share keys from given users
03e52840d   Kload   Init
479
480
481
  	 *
  	 * @param string $dir directory
  	 * @param array $userIds user ids for which the share keys should be deleted
6d9380f96   Cédric Dupont   Update sources OC...
482
483
  	 * @param string $owner owner of the file
  	 * @param \OC\Files\View $view view relative to data/
03e52840d   Kload   Init
484
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
  	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
511
  			}
6d9380f96   Cédric Dupont   Update sources OC...
512
  			closedir($dirContent);
03e52840d   Kload   Init
513
514
515
516
  		}
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
517
518
519
  	 * Make preparations to vars and filesystem for saving a keyfile
  	 * @param string|boolean $path
  	 * @param string $basePath
03e52840d   Kload   Init
520
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
521
  	protected static function keySetPreparation(\OC\Files\View $view, $path, $basePath) {
03e52840d   Kload   Init
522
523
524
525
526
527
528
529
530
531
  
  		$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...
532
  			$sub_dirs = explode('/', $basePath . '/' . $path_parts['dirname']);
03e52840d   Kload   Init
533
534
535
536
537
538
539
540
541
542
543
544
  			$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...
545
546
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
547
  	 * extract filename from share key name
a293d369c   Kload   Update sources to...
548
  	 * @param string $shareKey (filename.userid.sharekey)
6d9380f96   Cédric Dupont   Update sources OC...
549
  	 * @return string|false filename or false
a293d369c   Kload   Update sources to...
550
551
552
553
554
555
556
557
558
559
560
  	 */
  	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
561
  }