Failed Conditions
Push — develop ( 431393...f3c588 )
by Reüel
06:11
created

src/Settings.php (10 issues)

1
<?php
2
3
namespace Pronamic\WordPress\Pay\Gateways\IDealAdvancedV3;
4
5
use Pronamic\WordPress\Pay\Core\GatewaySettings;
6
7
/**
8
 * Title: iDEAL Advanced v3 gateway settings
9
 * Description:
10
 * Copyright: 2005-2019 Pronamic
11
 * Company: Pronamic
12
 *
13
 * @author  Remco Tolsma
14
 * @version 2.0.0
15
 * @since   1.1.2
16
 */
17
class Settings extends GatewaySettings {
18
	/**
19
	 * Settings constructor.
20
	 */
21
	public function __construct() {
22
		// Filters.
23
		add_filter( 'pronamic_pay_gateway_fields', array( $this, 'fields' ) );
24
25
		// Actions.
26
		add_action( 'current_screen', array( $this, 'maybe_download_private_certificate' ) );
27
		add_action( 'current_screen', array( $this, 'maybe_download_private_key' ) );
28
	}
29
30
	/**
31
	 * Fields.
32
	 *
33
	 * @param array $fields Settings fields.
34
	 *
35
	 * @return array
36
	 */
37
	public function fields( array $fields ) {
38
		/*
39
		 * Private Key and Certificate
40
		 */
41
42
		// Private key and certificate information.
43
		$fields[] = array(
44
			'section'  => 'ideal',
45
			'methods'  => array( 'ideal-advanced-v3' ),
46
			'title'    => __( 'Private key and certificate', 'pronamic_ideal' ),
47
			'type'     => 'description',
48
			'callback' => array( $this, 'field_security' ),
49
		);
50
51
		// Organization.
52
		$fields[] = array(
53
			'filter'   => FILTER_SANITIZE_STRING,
54
			'section'  => 'ideal',
55
			'methods'  => array( 'ideal-advanced-v3' ),
56
			'group'    => 'pk-cert',
57
			'meta_key' => '_pronamic_gateway_organization',
58
			'title'    => __( 'Organization', 'pronamic_ideal' ),
59
			'type'     => 'text',
60
			'tooltip'  => __( 'Organization name, e.g. Pronamic', 'pronamic_ideal' ),
61
		);
62
63
		// Organization Unit.
64
		$fields[] = array(
65
			'filter'   => FILTER_SANITIZE_STRING,
66
			'section'  => 'ideal',
67
			'methods'  => array( 'ideal-advanced-v3' ),
68
			'group'    => 'pk-cert',
69
			'meta_key' => '_pronamic_gateway_organization_unit',
70
			'title'    => __( 'Organization Unit', 'pronamic_ideal' ),
71
			'type'     => 'text',
72
			'tooltip'  => __( 'Organization unit, e.g. Administration', 'pronamic_ideal' ),
73
		);
74
75
		// Locality.
76
		$fields[] = array(
77
			'filter'   => FILTER_SANITIZE_STRING,
78
			'section'  => 'ideal',
79
			'methods'  => array( 'ideal-advanced-v3' ),
80
			'group'    => 'pk-cert',
81
			'meta_key' => '_pronamic_gateway_locality',
82
			'title'    => __( 'City', 'pronamic_ideal' ),
83
			'type'     => 'text',
84
			'tooltip'  => __( 'City, e.g. Amsterdam', 'pronamic_ideal' ),
85
		);
86
87
		// State or Province.
88
		$fields[] = array(
89
			'filter'   => FILTER_SANITIZE_STRING,
90
			'section'  => 'ideal',
91
			'methods'  => array( 'ideal-advanced-v3' ),
92
			'group'    => 'pk-cert',
93
			'meta_key' => '_pronamic_gateway_state_or_province',
94
			'title'    => __( 'State / province', 'pronamic_ideal' ),
95
			'type'     => 'text',
96
			'tooltip'  => __( 'State or province, e.g. Friesland', 'pronamic_ideal' ),
97
		);
98
99
		// Country.
100
		$locale = explode( '_', get_locale() );
101
102
		$locale = array_pop( $locale );
103
104
		$fields[] = array(
105
			'filter'      => FILTER_SANITIZE_STRING,
106
			'section'     => 'ideal',
107
			'methods'     => array( 'ideal-advanced-v3' ),
108
			'group'       => 'pk-cert',
109
			'meta_key'    => '_pronamic_gateway_country',
110
			'title'       => __( 'Country', 'pronamic_ideal' ),
111
			'type'        => 'text',
112
			'tooltip'     => sprintf(
113
				'%s %s (ISO-3166-1 alpha-2)',
114
				__( '2 letter country code, e.g.', 'pronamic_ideal' ),
115
				strtoupper( $locale )
116
			),
117
			'size'        => 2,
118
			'description' => sprintf(
119
				'%s %s',
120
				__( '2 letter country code, e.g.', 'pronamic_ideal' ),
121
				strtoupper( $locale )
122
			),
123
		);
124
125
		// Email Address.
126
		$fields[] = array(
127
			'filter'   => FILTER_SANITIZE_STRING,
128
			'section'  => 'ideal',
129
			'methods'  => array( 'ideal-advanced-v3' ),
130
			'group'    => 'pk-cert',
131
			'meta_key' => '_pronamic_gateway_email',
132
			'title'    => __( 'E-mail address', 'pronamic_ideal' ),
133
			'tooltip'  => sprintf(
134
				/* translators: %s: admin email */
135
				__( 'E-mail address, e.g. %s', 'pronamic_ideal' ),
136
				get_option( 'admin_email' )
0 ignored issues
show
It seems like get_option('admin_email') can also be of type false; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

136
				/** @scrutinizer ignore-type */ get_option( 'admin_email' )
Loading history...
137
			),
138
			'type'     => 'text',
139
		);
140
141
		// Number Days Valid.
142
		$fields[] = array(
143
			'filter'   => FILTER_SANITIZE_NUMBER_INT,
144
			'section'  => 'ideal',
145
			'methods'  => array( 'ideal-advanced-v3' ),
146
			'group'    => 'pk-cert',
147
			'meta_key' => '_pronamic_gateway_number_days_valid',
148
			'title'    => __( 'Number Days Valid', 'pronamic_ideal' ),
149
			'type'     => 'text',
150
			'default'  => 1825,
151
			'tooltip'  => __( 'Number of days the generated certificate will be valid for, e.g. 1825 days for the maximum duration of 5 years.', 'pronamic_ideal' ),
152
		);
153
154
		// Private Key Password.
155
		$fields[] = array(
156
			'filter'   => FILTER_SANITIZE_STRING,
157
			'section'  => 'ideal',
158
			'methods'  => array( 'ideal-advanced-v3' ),
159
			'group'    => 'pk-cert',
160
			'meta_key' => '_pronamic_gateway_ideal_private_key_password',
161
			'title'    => __( 'Private Key Password', 'pronamic_ideal' ),
162
			'type'     => 'text',
163
			'classes'  => array( 'regular-text', 'code' ),
164
			'default'  => wp_generate_password(),
165
			'tooltip'  => __( 'A random password which will be used for the generation of the private key and certificate.', 'pronamic_ideal' ),
166
		);
167
168
		// Private Key.
169
		$fields[] = array(
170
			'filter'   => FILTER_SANITIZE_STRING,
171
			'section'  => 'ideal',
172
			'methods'  => array( 'ideal-advanced-v3' ),
173
			'group'    => 'pk-cert',
174
			'meta_key' => '_pronamic_gateway_ideal_private_key',
175
			'title'    => __( 'Private Key', 'pronamic_ideal' ),
176
			'type'     => 'textarea',
177
			'callback' => array( $this, 'field_private_key' ),
178
			'classes'  => array( 'code' ),
179
			'tooltip'  => __( 'The private key is used for secure communication with the payment provider. If left empty, the private key will be generated using the given private key password.', 'pronamic_ideal' ),
180
		);
181
182
		// Private Certificate.
183
		$fields[] = array(
184
			'filter'   => FILTER_SANITIZE_STRING,
185
			'section'  => 'ideal',
186
			'methods'  => array( 'ideal-advanced-v3' ),
187
			'group'    => 'pk-cert',
188
			'meta_key' => '_pronamic_gateway_ideal_private_certificate',
189
			'title'    => __( 'Private Certificate', 'pronamic_ideal' ),
190
			'type'     => 'textarea',
191
			'callback' => array( $this, 'field_private_certificate' ),
192
			'classes'  => array( 'code' ),
193
			'tooltip'  => __( 'The certificate is used for secure communication with the payment provider. If left empty, the certificate will be generated using the private key and given organization details.', 'pronamic_ideal' ),
194
		);
195
196
		// Transaction feedback.
197
		$fields[] = array(
198
			'section' => 'ideal',
199
			'methods' => array( 'ideal-advanced-v3' ),
200
			'title'   => __( 'Transaction feedback', 'pronamic_ideal' ),
201
			'type'    => 'description',
202
			'html'    => sprintf(
203
				'<span class="dashicons dashicons-yes"></span> %s',
204
				__( 'Payment status updates will be processed without any additional configuration.', 'pronamic_ideal' )
205
			),
206
		);
207
208
		// Return.
209
		return $fields;
210
	}
211
212
	/**
213
	 * Field security
214
	 *
215
	 * @param array $field Field.
216
	 */
217
	public function field_security( $field ) {
218
		$certificate = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_certificate', true );
0 ignored issues
show
It seems like get_the_ID() can also be of type false; however, parameter $post_id of get_post_meta() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

218
		$certificate = get_post_meta( /** @scrutinizer ignore-type */ get_the_ID(), '_pronamic_gateway_ideal_private_certificate', true );
Loading history...
219
220
		?>
221
		<p>
222
			<?php if ( empty( $certificate ) ) : ?>
223
224
				<span
225
					class="dashicons dashicons-no"></span> <?php esc_html_e( 'The private key and certificate have not yet been configured.', 'pronamic_ideal' ); ?>
226
				<br/>
227
228
				<br/>
229
230
				<?php esc_html_e( 'A private key and certificate are required for communication with the payment provider. Enter the organization details from the iDEAL account below to generate these required files.', 'pronamic_ideal' ); ?>
231
232
			<?php else : ?>
233
234
				<span
235
					class="dashicons dashicons-yes"></span> <?php esc_html_e( 'A private key and certificate have been configured. The certificate must be uploaded to the payment provider dashboard to complete configuration.', 'pronamic_ideal' ); ?>
236
				<br/>
237
238
				<br/>
239
240
				<?php
241
242
				submit_button(
243
					__( 'Download certificate', 'pronamic_ideal' ),
244
					'secondary',
245
					'download_private_certificate',
246
					false
247
				);
248
249
				?>
250
251
				<a class="pronamic-pay-btn-link" href="#" id="pk-cert-fields-toggle"><?php esc_html_e( 'Show details…', 'pronamic_ideal' ); ?></a>
252
253
			<?php endif; ?>
254
		</p>
255
		<?php
256
	}
257
258
	/**
259
	 * Field private key.
260
	 *
261
	 * @param array $field Field.
262
	 */
263
	public function field_private_key( $field ) {
264
		$private_key          = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_key', true );
0 ignored issues
show
It seems like get_the_ID() can also be of type false; however, parameter $post_id of get_post_meta() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

264
		$private_key          = get_post_meta( /** @scrutinizer ignore-type */ get_the_ID(), '_pronamic_gateway_ideal_private_key', true );
Loading history...
265
		$private_key_password = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_key_password', true );
266
		$number_days_valid    = get_post_meta( get_the_ID(), '_pronamic_gateway_number_days_valid', true );
267
268
		$filename = __( 'ideal.key', 'pronamic_ideal' );
269
270
		if ( ! empty( $private_key_password ) && ! empty( $number_days_valid ) ) {
271
			$command = sprintf(
272
				'openssl genrsa -aes128 -out %s -passout pass:%s 2048',
273
				escapeshellarg( $filename ),
274
				escapeshellarg( $private_key_password )
275
			);
276
277
			?>
278
279
			<p><?php esc_html_e( 'OpenSSL command', 'pronamic_ideal' ); ?></p>
280
			<input id="pronamic_ideal_openssl_command_key" name="pronamic_ideal_openssl_command_key" value="<?php echo esc_attr( $command ); ?>" type="text" class="large-text code" readonly="readonly"/>
281
282
			<?php
283
		} else {
284
			printf(
285
				'<p class="pronamic-pay-description description">%s</p>',
286
				esc_html__( 'Leave empty and save the configuration to generate the private key or view the OpenSSL command.', 'pronamic_ideal' )
287
			);
288
		}
289
290
		?>
291
		<p>
292
			<?php
293
294
			if ( ! empty( $private_key ) ) {
295
				submit_button(
296
					__( 'Download', 'pronamic_ideal' ),
297
					'secondary',
298
					'download_private_key',
299
					false
300
				);
301
302
				echo ' ';
303
			}
304
305
			printf(
306
				'<label class="pronamic-pay-form-control-file-button button">%s <input type="file" name="%s" /></label>',
307
				esc_html__( 'Upload', 'pronamic_ideal' ),
308
				'_pronamic_gateway_ideal_private_key_file'
309
			);
310
311
			?>
312
		</p>
313
		<?php
314
	}
315
316
	/**
317
	 * Field private certificate.
318
	 *
319
	 * @param array $field Field.
320
	 */
321
	public function field_private_certificate( $field ) {
322
		$certificate = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_certificate', true );
0 ignored issues
show
It seems like get_the_ID() can also be of type false; however, parameter $post_id of get_post_meta() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

322
		$certificate = get_post_meta( /** @scrutinizer ignore-type */ get_the_ID(), '_pronamic_gateway_ideal_private_certificate', true );
Loading history...
323
324
		$private_key_password = get_post_meta( get_the_ID(), '_pronamic_gateway_ideal_private_key_password', true );
325
		$number_days_valid    = get_post_meta( get_the_ID(), '_pronamic_gateway_number_days_valid', true );
326
327
		$filename_key = __( 'ideal.key', 'pronamic_ideal' );
328
		$filename_cer = __( 'ideal.cer', 'pronamic_ideal' );
329
330
		// @link http://www.openssl.org/docs/apps/req.html
331
		$subj_args = array(
332
			'C'            => get_post_meta( get_the_ID(), '_pronamic_gateway_country', true ),
333
			'ST'           => get_post_meta( get_the_ID(), '_pronamic_gateway_state_or_province', true ),
334
			'L'            => get_post_meta( get_the_ID(), '_pronamic_gateway_locality', true ),
335
			'O'            => get_post_meta( get_the_ID(), '_pronamic_gateway_organization', true ),
336
			'OU'           => get_post_meta( get_the_ID(), '_pronamic_gateway_organization_unit', true ),
337
			'CN'           => get_post_meta( get_the_ID(), '_pronamic_gateway_organization', true ),
338
			'emailAddress' => get_post_meta( get_the_ID(), '_pronamic_gateway_email', true ),
339
		);
340
341
		$subj_args = array_filter( $subj_args );
342
343
		$subj = '';
344
		foreach ( $subj_args as $type => $value ) {
345
			$subj .= '/' . $type . '=' . addslashes( $value );
346
		}
347
348
		if ( ! empty( $subj ) ) {
349
			$command = trim(
350
				sprintf(
351
					'openssl req -x509 -sha256 -new -key %s -passin pass:%s -days %s -out %s %s',
352
					escapeshellarg( $filename_key ),
353
					escapeshellarg( $private_key_password ),
0 ignored issues
show
It seems like $private_key_password can also be of type false; however, parameter $arg of escapeshellarg() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

353
					escapeshellarg( /** @scrutinizer ignore-type */ $private_key_password ),
Loading history...
354
					escapeshellarg( $number_days_valid ),
355
					escapeshellarg( $filename_cer ),
356
					empty( $subj ) ? '' : sprintf( '-subj %s', escapeshellarg( $subj ) )
357
				)
358
			);
359
360
			?>
361
362
			<p><?php esc_html_e( 'OpenSSL command', 'pronamic_ideal' ); ?></p>
363
			<input id="pronamic_ideal_openssl_command_certificate" name="pronamic_ideal_openssl_command_certificate" value="<?php echo esc_attr( $command ); ?>" type="text" class="large-text code" readonly="readonly"/>
364
365
			<?php
366
		} else {
367
			printf(
368
				'<p class="pronamic-pay-description description">%s</p>',
369
				esc_html__( 'Leave empty and save the configuration to generate the certificate or view the OpenSSL command.', 'pronamic_ideal' )
370
			);
371
		}
372
373
		if ( ! empty( $certificate ) ) {
374
			$fingerprint = Security::get_sha_fingerprint( $certificate );
375
			$fingerprint = str_split( $fingerprint, 2 );
376
			$fingerprint = implode( ':', $fingerprint );
377
378
			echo '<dl>';
379
380
			echo '<dt>', esc_html__( 'SHA Fingerprint', 'pronamic_ideal' ), '</dt>';
381
			echo '<dd>', esc_html( $fingerprint ), '</dd>';
382
383
			$info = openssl_x509_parse( $certificate );
384
385
			if ( $info ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $info of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
386
				$date_format = __( 'M j, Y @ G:i', 'pronamic_ideal' );
387
388
				if ( isset( $info['validFrom_time_t'] ) ) {
389
					echo '<dt>', esc_html__( 'Valid From', 'pronamic_ideal' ), '</dt>';
390
					echo '<dd>', esc_html( date_i18n( $date_format, $info['validFrom_time_t'] ) ), '</dd>';
391
				}
392
393
				if ( isset( $info['validTo_time_t'] ) ) {
394
					echo '<dt>', esc_html__( 'Valid To', 'pronamic_ideal' ), '</dt>';
395
					echo '<dd>', esc_html( date_i18n( $date_format, $info['validTo_time_t'] ) ), '</dd>';
396
				}
397
			}
398
399
			echo '</dl>';
400
		}
401
402
		?>
403
		<p>
404
			<?php
405
406
			if ( ! empty( $certificate ) ) {
407
				submit_button(
408
					__( 'Download', 'pronamic_ideal' ),
409
					'secondary',
410
					'download_private_certificate',
411
					false
412
				);
413
414
				echo ' ';
415
			}
416
417
			printf(
418
				'<label class="pronamic-pay-form-control-file-button button">%s <input type="file" name="%s" /></label>',
419
				esc_html__( 'Upload', 'pronamic_ideal' ),
420
				'_pronamic_gateway_ideal_private_certificate_file'
421
			);
422
423
			?>
424
		</p>
425
		<?php
426
	}
427
428
	/**
429
	 * Download private certificate
430
	 */
431
	public function maybe_download_private_certificate() {
432
		if ( filter_has_var( INPUT_POST, 'download_private_certificate' ) ) {
433
			$post_id = filter_input( INPUT_POST, 'post_ID', FILTER_SANITIZE_STRING );
434
435
			$filename = sprintf( 'ideal-private-certificate-%s.cer', $post_id );
436
437
			header( 'Content-Description: File Transfer' );
438
			header( 'Content-Disposition: attachment; filename=' . $filename );
439
			header( 'Content-Type: application/x-x509-ca-cert; charset=' . get_option( 'blog_charset' ), true );
0 ignored issues
show
Are you sure get_option('blog_charset') of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

439
			header( 'Content-Type: application/x-x509-ca-cert; charset=' . /** @scrutinizer ignore-type */ get_option( 'blog_charset' ), true );
Loading history...
440
441
			echo get_post_meta( $post_id, '_pronamic_gateway_ideal_private_certificate', true ); // xss ok.
0 ignored issues
show
Are you sure get_post_meta($post_id, ...ate_certificate', true) of type false|mixed|string can be used in echo? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

441
			echo /** @scrutinizer ignore-type */ get_post_meta( $post_id, '_pronamic_gateway_ideal_private_certificate', true ); // xss ok.
Loading history...
442
443
			exit;
444
		}
445
	}
446
447
	/**
448
	 * Download private key
449
	 */
450
	public function maybe_download_private_key() {
451
		if ( filter_has_var( INPUT_POST, 'download_private_key' ) ) {
452
			$post_id = filter_input( INPUT_POST, 'post_ID', FILTER_SANITIZE_STRING );
453
454
			$filename = sprintf( 'ideal-private-key-%s.key', $post_id );
455
456
			header( 'Content-Description: File Transfer' );
457
			header( 'Content-Disposition: attachment; filename=' . $filename );
458
			header( 'Content-Type: application/pgp-keys; charset=' . get_option( 'blog_charset' ), true );
0 ignored issues
show
Are you sure get_option('blog_charset') of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

458
			header( 'Content-Type: application/pgp-keys; charset=' . /** @scrutinizer ignore-type */ get_option( 'blog_charset' ), true );
Loading history...
459
460
			echo get_post_meta( $post_id, '_pronamic_gateway_ideal_private_key', true ); // xss ok.
0 ignored issues
show
Are you sure get_post_meta($post_id, ...eal_private_key', true) of type false|mixed|string can be used in echo? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

460
			echo /** @scrutinizer ignore-type */ get_post_meta( $post_id, '_pronamic_gateway_ideal_private_key', true ); // xss ok.
Loading history...
461
462
			exit;
463
		}
464
	}
465
466
	/**
467
	 * Save post.
468
	 *
469
	 * @param array $data Data.
470
	 */
471
	public function save_post( $data ) {
472
		// Files.
473
		$files = array(
474
			'_pronamic_gateway_ideal_private_key_file' => '_pronamic_gateway_ideal_private_key',
475
			'_pronamic_gateway_ideal_private_certificate_file' => '_pronamic_gateway_ideal_private_certificate',
476
		);
477
478
		foreach ( $files as $name => $meta_key ) {
479
			if ( isset( $_FILES[ $name ] ) && UPLOAD_ERR_OK === $_FILES[ $name ]['error'] ) { // WPCS: input var okay.
480
				$value = file_get_contents( $_FILES[ $name ]['tmp_name'] ); // WPCS: input var okay. // WPCS: sanitization ok.
481
482
				$data[ $meta_key ] = $value;
483
			}
484
		}
485
486
		// Generate private key and certificate.
487
		if ( empty( $data['_pronamic_gateway_ideal_private_key_password'] ) ) {
488
			// Without private key password we can't create private key and certifiate.
489
			return $data;
490
		}
491
492
		if ( ! in_array( 'aes-128-cbc', openssl_get_cipher_methods(), true ) ) {
493
			// Without AES-128-CBC ciphter method we can't create private key and certificate.
494
			return $data;
495
		}
496
497
		// Private key.
498
		$pkey = openssl_pkey_get_private( $data['_pronamic_gateway_ideal_private_key'], $data['_pronamic_gateway_ideal_private_key_password'] );
499
500
		if ( false === $pkey ) {
501
			// If we can't open the private key we will create a new private key and certificate.
502
			if ( defined( 'OPENSSL_CIPHER_AES_128_CBC' ) ) {
503
				$cipher = OPENSSL_CIPHER_AES_128_CBC;
504
			} elseif ( defined( 'OPENSSL_CIPHER_3DES' ) ) {
505
				// @link https://www.pronamic.nl/wp-content/uploads/2011/12/iDEAL_Advanced_PHP_EN_V2.2.pdf
506
				$cipher = OPENSSL_CIPHER_3DES;
507
			} else {
508
				// Unable to create private key without cipher.
509
				return $data;
510
			}
511
512
			$args = array(
513
				'digest_alg'             => 'SHA256',
514
				'private_key_bits'       => 2048,
515
				'private_key_type'       => OPENSSL_KEYTYPE_RSA,
516
				'encrypt_key'            => true,
517
				'encrypt_key_cipher'     => $cipher,
518
				'subjectKeyIdentifier'   => 'hash',
519
				'authorityKeyIdentifier' => 'keyid:always,issuer:always',
520
				'basicConstraints'       => 'CA:true',
521
			);
522
523
			$pkey = openssl_pkey_new( $args );
524
525
			if ( false === $pkey ) {
526
				return $data;
527
			}
528
529
			// Export key.
530
			$result = openssl_pkey_export( $pkey, $private_key, $data['_pronamic_gateway_ideal_private_key_password'], $args );
531
532
			if ( false === $result ) {
533
				return $data;
534
			}
535
536
			$data['_pronamic_gateway_ideal_private_key'] = $private_key;
537
			// Delete private certificate since this is no longer valid.
538
			$data['_pronamic_gateway_ideal_private_certificate'] = null;
539
		}
540
541
		// Certificate.
542
		if ( empty( $data['_pronamic_gateway_ideal_private_certificate'] ) ) {
543
			$required_keys = array(
544
				'countryName',
545
				'stateOrProvinceName',
546
				'localityName',
547
				'organizationName',
548
				'commonName',
549
				'emailAddress',
550
			);
551
552
			$distinguished_name = array(
553
				'countryName'            => $data['_pronamic_gateway_country'],
554
				'stateOrProvinceName'    => $data['_pronamic_gateway_state_or_province'],
555
				'localityName'           => $data['_pronamic_gateway_locality'],
556
				'organizationName'       => $data['_pronamic_gateway_organization'],
557
				'organizationalUnitName' => $data['_pronamic_gateway_organization_unit'],
558
				'commonName'             => $data['_pronamic_gateway_organization'],
559
				'emailAddress'           => $data['_pronamic_gateway_email'],
560
			);
561
562
			$distinguished_name = array_filter( $distinguished_name );
563
564
			/*
565
			 * Create certificate only if distinguished name contains all required elements
566
			 *
567
			 * @link http://stackoverflow.com/questions/13169588/how-to-check-if-multiple-array-keys-exists
568
			 */
569
			if ( count( array_intersect_key( array_flip( $required_keys ), $distinguished_name ) ) === count( $required_keys ) ) {
570
				$csr = openssl_csr_new( $distinguished_name, $pkey );
571
572
				$cert = openssl_csr_sign( $csr, null, $pkey, $data['_pronamic_gateway_number_days_valid'], $args, time() );
573
574
				openssl_x509_export( $cert, $certificate );
575
576
				$data['_pronamic_gateway_ideal_private_certificate'] = $certificate;
577
			}
578
		}
579
580
		return $data;
581
	}
582
}
583