Passed
Push — master ( 2845a0...496a8d )
by Robin
18:21 queued 13s
created
lib/private/Security/CertificateManager.php 2 patches
Indentation   +244 added lines, -244 removed lines patch added patch discarded remove patch
@@ -44,248 +44,248 @@
 block discarded – undo
44 44
  * Manage trusted certificates for users
45 45
  */
46 46
 class CertificateManager implements ICertificateManager {
47
-	protected View $view;
48
-	protected IConfig $config;
49
-	protected LoggerInterface $logger;
50
-	protected ISecureRandom $random;
51
-
52
-	private ?string $bundlePath = null;
53
-
54
-	public function __construct(View $view,
55
-								IConfig $config,
56
-								LoggerInterface $logger,
57
-								ISecureRandom $random) {
58
-		$this->view = $view;
59
-		$this->config = $config;
60
-		$this->logger = $logger;
61
-		$this->random = $random;
62
-	}
63
-
64
-	/**
65
-	 * Returns all certificates trusted by the user
66
-	 *
67
-	 * @return \OCP\ICertificate[]
68
-	 */
69
-	public function listCertificates(): array {
70
-		if (!$this->config->getSystemValueBool('installed', false)) {
71
-			return [];
72
-		}
73
-
74
-		$path = $this->getPathToCertificates() . 'uploads/';
75
-		if (!$this->view->is_dir($path)) {
76
-			return [];
77
-		}
78
-		$result = [];
79
-		$handle = $this->view->opendir($path);
80
-		if (!is_resource($handle)) {
81
-			return [];
82
-		}
83
-		while (false !== ($file = readdir($handle))) {
84
-			if ($file != '.' && $file != '..') {
85
-				try {
86
-					$content = $this->view->file_get_contents($path . $file);
87
-					if ($content !== false) {
88
-						$result[] = new Certificate($content, $file);
89
-					} else {
90
-						$this->logger->error("Failed to read certificate from $path");
91
-					}
92
-				} catch (\Exception $e) {
93
-					$this->logger->error("Failed to read certificate from $path", ['exception' => $e]);
94
-				}
95
-			}
96
-		}
97
-		closedir($handle);
98
-		return $result;
99
-	}
100
-
101
-	private function hasCertificates(): bool {
102
-		if (!$this->config->getSystemValueBool('installed', false)) {
103
-			return false;
104
-		}
105
-
106
-		$path = $this->getPathToCertificates() . 'uploads/';
107
-		if (!$this->view->is_dir($path)) {
108
-			return false;
109
-		}
110
-		$result = [];
111
-		$handle = $this->view->opendir($path);
112
-		if (!is_resource($handle)) {
113
-			return false;
114
-		}
115
-		while (false !== ($file = readdir($handle))) {
116
-			if ($file !== '.' && $file !== '..') {
117
-				return true;
118
-			}
119
-		}
120
-		closedir($handle);
121
-		return false;
122
-	}
123
-
124
-	/**
125
-	 * create the certificate bundle of all trusted certificated
126
-	 */
127
-	public function createCertificateBundle(): void {
128
-		$path = $this->getPathToCertificates();
129
-		$certs = $this->listCertificates();
130
-
131
-		if (!$this->view->file_exists($path)) {
132
-			$this->view->mkdir($path);
133
-		}
134
-
135
-		$defaultCertificates = file_get_contents(\OC::$SERVERROOT . '/resources/config/ca-bundle.crt');
136
-		if (strlen($defaultCertificates) < 1024) { // sanity check to verify that we have some content for our bundle
137
-			// log as exception so we have a stacktrace
138
-			$e = new \Exception('Shipped ca-bundle is empty, refusing to create certificate bundle');
139
-			$this->logger->error($e->getMessage(), ['exception' => $e]);
140
-			return;
141
-		}
142
-
143
-		$certPath = $path . 'rootcerts.crt';
144
-		$tmpPath = $certPath . '.tmp' . $this->random->generate(10, ISecureRandom::CHAR_DIGITS);
145
-		$fhCerts = $this->view->fopen($tmpPath, 'w');
146
-
147
-		if (!is_resource($fhCerts)) {
148
-			throw new \RuntimeException('Unable to open file handler to create certificate bundle "' . $tmpPath . '".');
149
-		}
150
-
151
-		// Write user certificates
152
-		foreach ($certs as $cert) {
153
-			$file = $path . '/uploads/' . $cert->getName();
154
-			$data = $this->view->file_get_contents($file);
155
-			if (strpos($data, 'BEGIN CERTIFICATE')) {
156
-				fwrite($fhCerts, $data);
157
-				fwrite($fhCerts, "\r\n");
158
-			}
159
-		}
160
-
161
-		// Append the default certificates
162
-		fwrite($fhCerts, $defaultCertificates);
163
-
164
-		// Append the system certificate bundle
165
-		$systemBundle = $this->getCertificateBundle();
166
-		if ($systemBundle !== $certPath && $this->view->file_exists($systemBundle)) {
167
-			$systemCertificates = $this->view->file_get_contents($systemBundle);
168
-			fwrite($fhCerts, $systemCertificates);
169
-		}
170
-
171
-		fclose($fhCerts);
172
-
173
-		$this->view->rename($tmpPath, $certPath);
174
-	}
175
-
176
-	/**
177
-	 * Save the certificate and re-generate the certificate bundle
178
-	 *
179
-	 * @param string $certificate the certificate data
180
-	 * @param string $name the filename for the certificate
181
-	 * @return \OCP\ICertificate
182
-	 * @throws \Exception If the certificate could not get added
183
-	 */
184
-	public function addCertificate(string $certificate, string $name): ICertificate {
185
-		if (!Filesystem::isValidPath($name) or Filesystem::isFileBlacklisted($name)) {
186
-			throw new \Exception('Filename is not valid');
187
-		}
188
-		$this->bundlePath = null;
189
-
190
-		$dir = $this->getPathToCertificates() . 'uploads/';
191
-		if (!$this->view->file_exists($dir)) {
192
-			$this->view->mkdir($dir);
193
-		}
194
-
195
-		try {
196
-			$file = $dir . $name;
197
-			$certificateObject = new Certificate($certificate, $name);
198
-			$this->view->file_put_contents($file, $certificate);
199
-			$this->createCertificateBundle();
200
-			return $certificateObject;
201
-		} catch (\Exception $e) {
202
-			throw $e;
203
-		}
204
-	}
205
-
206
-	/**
207
-	 * Remove the certificate and re-generate the certificate bundle
208
-	 *
209
-	 * @param string $name
210
-	 * @return bool
211
-	 */
212
-	public function removeCertificate(string $name): bool {
213
-		if (!Filesystem::isValidPath($name)) {
214
-			return false;
215
-		}
216
-		$this->bundlePath = null;
217
-
218
-		$path = $this->getPathToCertificates() . 'uploads/';
219
-		if ($this->view->file_exists($path . $name)) {
220
-			$this->view->unlink($path . $name);
221
-			$this->createCertificateBundle();
222
-		}
223
-		return true;
224
-	}
225
-
226
-	/**
227
-	 * Get the path to the certificate bundle
228
-	 *
229
-	 * @return string
230
-	 */
231
-	public function getCertificateBundle(): string {
232
-		return $this->getPathToCertificates() . 'rootcerts.crt';
233
-	}
234
-
235
-	/**
236
-	 * Get the full local path to the certificate bundle
237
-	 * @throws \Exception when getting bundle path fails
238
-	 */
239
-	public function getAbsoluteBundlePath(): string {
240
-		try {
241
-			if ($this->bundlePath === null) {
242
-				if (!$this->hasCertificates()) {
243
-					$this->bundlePath = \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
244
-				}
245
-
246
-				if ($this->needsRebundling()) {
247
-					$this->createCertificateBundle();
248
-				}
249
-
250
-				$certificateBundle = $this->getCertificateBundle();
251
-				$this->bundlePath = $this->view->getLocalFile($certificateBundle) ?: null;
252
-
253
-				if ($this->bundlePath === null) {
254
-					throw new \RuntimeException('Unable to get certificate bundle "' . $certificateBundle . '".');
255
-				}
256
-			}
257
-			return $this->bundlePath;
258
-		} catch (\Exception $e) {
259
-			$this->logger->error('Failed to get absolute bundle path. Fallback to default ca-bundle.crt', ['exception' => $e]);
260
-			return \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
261
-		}
262
-	}
263
-
264
-	private function getPathToCertificates(): string {
265
-		return '/files_external/';
266
-	}
267
-
268
-	/**
269
-	 * Check if we need to re-bundle the certificates because one of the sources has updated
270
-	 *
271
-	 * @return bool
272
-	 */
273
-	private function needsRebundling(): bool {
274
-		$targetBundle = $this->getCertificateBundle();
275
-		if (!$this->view->file_exists($targetBundle)) {
276
-			return true;
277
-		}
278
-
279
-		$sourceMTime = $this->getFilemtimeOfCaBundle();
280
-		return $sourceMTime > $this->view->filemtime($targetBundle);
281
-	}
282
-
283
-	/**
284
-	 * get mtime of ca-bundle shipped by Nextcloud
285
-	 *
286
-	 * @return int
287
-	 */
288
-	protected function getFilemtimeOfCaBundle(): int {
289
-		return filemtime(\OC::$SERVERROOT . '/resources/config/ca-bundle.crt');
290
-	}
47
+    protected View $view;
48
+    protected IConfig $config;
49
+    protected LoggerInterface $logger;
50
+    protected ISecureRandom $random;
51
+
52
+    private ?string $bundlePath = null;
53
+
54
+    public function __construct(View $view,
55
+                                IConfig $config,
56
+                                LoggerInterface $logger,
57
+                                ISecureRandom $random) {
58
+        $this->view = $view;
59
+        $this->config = $config;
60
+        $this->logger = $logger;
61
+        $this->random = $random;
62
+    }
63
+
64
+    /**
65
+     * Returns all certificates trusted by the user
66
+     *
67
+     * @return \OCP\ICertificate[]
68
+     */
69
+    public function listCertificates(): array {
70
+        if (!$this->config->getSystemValueBool('installed', false)) {
71
+            return [];
72
+        }
73
+
74
+        $path = $this->getPathToCertificates() . 'uploads/';
75
+        if (!$this->view->is_dir($path)) {
76
+            return [];
77
+        }
78
+        $result = [];
79
+        $handle = $this->view->opendir($path);
80
+        if (!is_resource($handle)) {
81
+            return [];
82
+        }
83
+        while (false !== ($file = readdir($handle))) {
84
+            if ($file != '.' && $file != '..') {
85
+                try {
86
+                    $content = $this->view->file_get_contents($path . $file);
87
+                    if ($content !== false) {
88
+                        $result[] = new Certificate($content, $file);
89
+                    } else {
90
+                        $this->logger->error("Failed to read certificate from $path");
91
+                    }
92
+                } catch (\Exception $e) {
93
+                    $this->logger->error("Failed to read certificate from $path", ['exception' => $e]);
94
+                }
95
+            }
96
+        }
97
+        closedir($handle);
98
+        return $result;
99
+    }
100
+
101
+    private function hasCertificates(): bool {
102
+        if (!$this->config->getSystemValueBool('installed', false)) {
103
+            return false;
104
+        }
105
+
106
+        $path = $this->getPathToCertificates() . 'uploads/';
107
+        if (!$this->view->is_dir($path)) {
108
+            return false;
109
+        }
110
+        $result = [];
111
+        $handle = $this->view->opendir($path);
112
+        if (!is_resource($handle)) {
113
+            return false;
114
+        }
115
+        while (false !== ($file = readdir($handle))) {
116
+            if ($file !== '.' && $file !== '..') {
117
+                return true;
118
+            }
119
+        }
120
+        closedir($handle);
121
+        return false;
122
+    }
123
+
124
+    /**
125
+     * create the certificate bundle of all trusted certificated
126
+     */
127
+    public function createCertificateBundle(): void {
128
+        $path = $this->getPathToCertificates();
129
+        $certs = $this->listCertificates();
130
+
131
+        if (!$this->view->file_exists($path)) {
132
+            $this->view->mkdir($path);
133
+        }
134
+
135
+        $defaultCertificates = file_get_contents(\OC::$SERVERROOT . '/resources/config/ca-bundle.crt');
136
+        if (strlen($defaultCertificates) < 1024) { // sanity check to verify that we have some content for our bundle
137
+            // log as exception so we have a stacktrace
138
+            $e = new \Exception('Shipped ca-bundle is empty, refusing to create certificate bundle');
139
+            $this->logger->error($e->getMessage(), ['exception' => $e]);
140
+            return;
141
+        }
142
+
143
+        $certPath = $path . 'rootcerts.crt';
144
+        $tmpPath = $certPath . '.tmp' . $this->random->generate(10, ISecureRandom::CHAR_DIGITS);
145
+        $fhCerts = $this->view->fopen($tmpPath, 'w');
146
+
147
+        if (!is_resource($fhCerts)) {
148
+            throw new \RuntimeException('Unable to open file handler to create certificate bundle "' . $tmpPath . '".');
149
+        }
150
+
151
+        // Write user certificates
152
+        foreach ($certs as $cert) {
153
+            $file = $path . '/uploads/' . $cert->getName();
154
+            $data = $this->view->file_get_contents($file);
155
+            if (strpos($data, 'BEGIN CERTIFICATE')) {
156
+                fwrite($fhCerts, $data);
157
+                fwrite($fhCerts, "\r\n");
158
+            }
159
+        }
160
+
161
+        // Append the default certificates
162
+        fwrite($fhCerts, $defaultCertificates);
163
+
164
+        // Append the system certificate bundle
165
+        $systemBundle = $this->getCertificateBundle();
166
+        if ($systemBundle !== $certPath && $this->view->file_exists($systemBundle)) {
167
+            $systemCertificates = $this->view->file_get_contents($systemBundle);
168
+            fwrite($fhCerts, $systemCertificates);
169
+        }
170
+
171
+        fclose($fhCerts);
172
+
173
+        $this->view->rename($tmpPath, $certPath);
174
+    }
175
+
176
+    /**
177
+     * Save the certificate and re-generate the certificate bundle
178
+     *
179
+     * @param string $certificate the certificate data
180
+     * @param string $name the filename for the certificate
181
+     * @return \OCP\ICertificate
182
+     * @throws \Exception If the certificate could not get added
183
+     */
184
+    public function addCertificate(string $certificate, string $name): ICertificate {
185
+        if (!Filesystem::isValidPath($name) or Filesystem::isFileBlacklisted($name)) {
186
+            throw new \Exception('Filename is not valid');
187
+        }
188
+        $this->bundlePath = null;
189
+
190
+        $dir = $this->getPathToCertificates() . 'uploads/';
191
+        if (!$this->view->file_exists($dir)) {
192
+            $this->view->mkdir($dir);
193
+        }
194
+
195
+        try {
196
+            $file = $dir . $name;
197
+            $certificateObject = new Certificate($certificate, $name);
198
+            $this->view->file_put_contents($file, $certificate);
199
+            $this->createCertificateBundle();
200
+            return $certificateObject;
201
+        } catch (\Exception $e) {
202
+            throw $e;
203
+        }
204
+    }
205
+
206
+    /**
207
+     * Remove the certificate and re-generate the certificate bundle
208
+     *
209
+     * @param string $name
210
+     * @return bool
211
+     */
212
+    public function removeCertificate(string $name): bool {
213
+        if (!Filesystem::isValidPath($name)) {
214
+            return false;
215
+        }
216
+        $this->bundlePath = null;
217
+
218
+        $path = $this->getPathToCertificates() . 'uploads/';
219
+        if ($this->view->file_exists($path . $name)) {
220
+            $this->view->unlink($path . $name);
221
+            $this->createCertificateBundle();
222
+        }
223
+        return true;
224
+    }
225
+
226
+    /**
227
+     * Get the path to the certificate bundle
228
+     *
229
+     * @return string
230
+     */
231
+    public function getCertificateBundle(): string {
232
+        return $this->getPathToCertificates() . 'rootcerts.crt';
233
+    }
234
+
235
+    /**
236
+     * Get the full local path to the certificate bundle
237
+     * @throws \Exception when getting bundle path fails
238
+     */
239
+    public function getAbsoluteBundlePath(): string {
240
+        try {
241
+            if ($this->bundlePath === null) {
242
+                if (!$this->hasCertificates()) {
243
+                    $this->bundlePath = \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
244
+                }
245
+
246
+                if ($this->needsRebundling()) {
247
+                    $this->createCertificateBundle();
248
+                }
249
+
250
+                $certificateBundle = $this->getCertificateBundle();
251
+                $this->bundlePath = $this->view->getLocalFile($certificateBundle) ?: null;
252
+
253
+                if ($this->bundlePath === null) {
254
+                    throw new \RuntimeException('Unable to get certificate bundle "' . $certificateBundle . '".');
255
+                }
256
+            }
257
+            return $this->bundlePath;
258
+        } catch (\Exception $e) {
259
+            $this->logger->error('Failed to get absolute bundle path. Fallback to default ca-bundle.crt', ['exception' => $e]);
260
+            return \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
261
+        }
262
+    }
263
+
264
+    private function getPathToCertificates(): string {
265
+        return '/files_external/';
266
+    }
267
+
268
+    /**
269
+     * Check if we need to re-bundle the certificates because one of the sources has updated
270
+     *
271
+     * @return bool
272
+     */
273
+    private function needsRebundling(): bool {
274
+        $targetBundle = $this->getCertificateBundle();
275
+        if (!$this->view->file_exists($targetBundle)) {
276
+            return true;
277
+        }
278
+
279
+        $sourceMTime = $this->getFilemtimeOfCaBundle();
280
+        return $sourceMTime > $this->view->filemtime($targetBundle);
281
+    }
282
+
283
+    /**
284
+     * get mtime of ca-bundle shipped by Nextcloud
285
+     *
286
+     * @return int
287
+     */
288
+    protected function getFilemtimeOfCaBundle(): int {
289
+        return filemtime(\OC::$SERVERROOT . '/resources/config/ca-bundle.crt');
290
+    }
291 291
 }
Please login to merge, or discard this patch.
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
 			return [];
72 72
 		}
73 73
 
74
-		$path = $this->getPathToCertificates() . 'uploads/';
74
+		$path = $this->getPathToCertificates().'uploads/';
75 75
 		if (!$this->view->is_dir($path)) {
76 76
 			return [];
77 77
 		}
@@ -83,7 +83,7 @@  discard block
 block discarded – undo
83 83
 		while (false !== ($file = readdir($handle))) {
84 84
 			if ($file != '.' && $file != '..') {
85 85
 				try {
86
-					$content = $this->view->file_get_contents($path . $file);
86
+					$content = $this->view->file_get_contents($path.$file);
87 87
 					if ($content !== false) {
88 88
 						$result[] = new Certificate($content, $file);
89 89
 					} else {
@@ -103,7 +103,7 @@  discard block
 block discarded – undo
103 103
 			return false;
104 104
 		}
105 105
 
106
-		$path = $this->getPathToCertificates() . 'uploads/';
106
+		$path = $this->getPathToCertificates().'uploads/';
107 107
 		if (!$this->view->is_dir($path)) {
108 108
 			return false;
109 109
 		}
@@ -132,7 +132,7 @@  discard block
 block discarded – undo
132 132
 			$this->view->mkdir($path);
133 133
 		}
134 134
 
135
-		$defaultCertificates = file_get_contents(\OC::$SERVERROOT . '/resources/config/ca-bundle.crt');
135
+		$defaultCertificates = file_get_contents(\OC::$SERVERROOT.'/resources/config/ca-bundle.crt');
136 136
 		if (strlen($defaultCertificates) < 1024) { // sanity check to verify that we have some content for our bundle
137 137
 			// log as exception so we have a stacktrace
138 138
 			$e = new \Exception('Shipped ca-bundle is empty, refusing to create certificate bundle');
@@ -140,17 +140,17 @@  discard block
 block discarded – undo
140 140
 			return;
141 141
 		}
142 142
 
143
-		$certPath = $path . 'rootcerts.crt';
144
-		$tmpPath = $certPath . '.tmp' . $this->random->generate(10, ISecureRandom::CHAR_DIGITS);
143
+		$certPath = $path.'rootcerts.crt';
144
+		$tmpPath = $certPath.'.tmp'.$this->random->generate(10, ISecureRandom::CHAR_DIGITS);
145 145
 		$fhCerts = $this->view->fopen($tmpPath, 'w');
146 146
 
147 147
 		if (!is_resource($fhCerts)) {
148
-			throw new \RuntimeException('Unable to open file handler to create certificate bundle "' . $tmpPath . '".');
148
+			throw new \RuntimeException('Unable to open file handler to create certificate bundle "'.$tmpPath.'".');
149 149
 		}
150 150
 
151 151
 		// Write user certificates
152 152
 		foreach ($certs as $cert) {
153
-			$file = $path . '/uploads/' . $cert->getName();
153
+			$file = $path.'/uploads/'.$cert->getName();
154 154
 			$data = $this->view->file_get_contents($file);
155 155
 			if (strpos($data, 'BEGIN CERTIFICATE')) {
156 156
 				fwrite($fhCerts, $data);
@@ -187,13 +187,13 @@  discard block
 block discarded – undo
187 187
 		}
188 188
 		$this->bundlePath = null;
189 189
 
190
-		$dir = $this->getPathToCertificates() . 'uploads/';
190
+		$dir = $this->getPathToCertificates().'uploads/';
191 191
 		if (!$this->view->file_exists($dir)) {
192 192
 			$this->view->mkdir($dir);
193 193
 		}
194 194
 
195 195
 		try {
196
-			$file = $dir . $name;
196
+			$file = $dir.$name;
197 197
 			$certificateObject = new Certificate($certificate, $name);
198 198
 			$this->view->file_put_contents($file, $certificate);
199 199
 			$this->createCertificateBundle();
@@ -215,9 +215,9 @@  discard block
 block discarded – undo
215 215
 		}
216 216
 		$this->bundlePath = null;
217 217
 
218
-		$path = $this->getPathToCertificates() . 'uploads/';
219
-		if ($this->view->file_exists($path . $name)) {
220
-			$this->view->unlink($path . $name);
218
+		$path = $this->getPathToCertificates().'uploads/';
219
+		if ($this->view->file_exists($path.$name)) {
220
+			$this->view->unlink($path.$name);
221 221
 			$this->createCertificateBundle();
222 222
 		}
223 223
 		return true;
@@ -229,7 +229,7 @@  discard block
 block discarded – undo
229 229
 	 * @return string
230 230
 	 */
231 231
 	public function getCertificateBundle(): string {
232
-		return $this->getPathToCertificates() . 'rootcerts.crt';
232
+		return $this->getPathToCertificates().'rootcerts.crt';
233 233
 	}
234 234
 
235 235
 	/**
@@ -240,7 +240,7 @@  discard block
 block discarded – undo
240 240
 		try {
241 241
 			if ($this->bundlePath === null) {
242 242
 				if (!$this->hasCertificates()) {
243
-					$this->bundlePath = \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
243
+					$this->bundlePath = \OC::$SERVERROOT.'/resources/config/ca-bundle.crt';
244 244
 				}
245 245
 
246 246
 				if ($this->needsRebundling()) {
@@ -251,13 +251,13 @@  discard block
 block discarded – undo
251 251
 				$this->bundlePath = $this->view->getLocalFile($certificateBundle) ?: null;
252 252
 
253 253
 				if ($this->bundlePath === null) {
254
-					throw new \RuntimeException('Unable to get certificate bundle "' . $certificateBundle . '".');
254
+					throw new \RuntimeException('Unable to get certificate bundle "'.$certificateBundle.'".');
255 255
 				}
256 256
 			}
257 257
 			return $this->bundlePath;
258 258
 		} catch (\Exception $e) {
259 259
 			$this->logger->error('Failed to get absolute bundle path. Fallback to default ca-bundle.crt', ['exception' => $e]);
260
-			return \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
260
+			return \OC::$SERVERROOT.'/resources/config/ca-bundle.crt';
261 261
 		}
262 262
 	}
263 263
 
@@ -286,6 +286,6 @@  discard block
 block discarded – undo
286 286
 	 * @return int
287 287
 	 */
288 288
 	protected function getFilemtimeOfCaBundle(): int {
289
-		return filemtime(\OC::$SERVERROOT . '/resources/config/ca-bundle.crt');
289
+		return filemtime(\OC::$SERVERROOT.'/resources/config/ca-bundle.crt');
290 290
 	}
291 291
 }
Please login to merge, or discard this patch.