Project

General

Profile

« Previous | Next » 

Revision 7e83055a

Added by Jim Pingle over 5 years ago

CA/Cert/CRL code optimizations

While here, use the new download function when exporting items

View differences:

src/usr/local/www/system_camanager.php
63 63
	$act = $_REQUEST['act'];
64 64
}
65 65

  
66
if ($_POST['act'] == "del") {
67

  
68
	if (!isset($a_ca[$id])) {
69
		pfSenseHeader("system_camanager.php");
70
		exit;
71
	}
72

  
73
	/* Only remove CA reference when deleting. It can be reconnected if a new matching CA is imported */
74
	$index = count($a_cert) - 1;
75
	for (;$index >= 0; $index--) {
76
		if ($a_cert[$index]['caref'] == $a_ca[$id]['refid']) {
77
			unset($a_cert[$index]['caref']);
78
		}
79
	}
80

  
81
	/* Remove any CRLs for this CA, there is no way to recover the connection once the CA has been removed. */
82
	$index = count($a_crl) - 1;
83
	for (;$index >= 0; $index--) {
84
		if ($a_crl[$index]['caref'] == $a_ca[$id]['refid']) {
85
			unset($a_crl[$index]);
86
		}
87
	}
88

  
89
	$name = $a_ca[$id]['descr'];
90
	unset($a_ca[$id]);
91
	write_config();
92
	ca_setup_trust_store();
93
	$savemsg = sprintf(gettext("Certificate Authority %s and its CRLs (if any) successfully deleted."), htmlspecialchars($name));
66
/* Actions other than 'new' require an ID.
67
 * 'del' action must be submitted via POST. */
68
if ((!empty($act) &&
69
    ($act != 'new') &&
70
    !$a_ca[$id]) ||
71
    (($act == 'del') && empty($_POST))) {
94 72
	pfSenseHeader("system_camanager.php");
95 73
	exit;
96 74
}
97 75

  
98
if ($act == "edit") {
99
	if (!$a_ca[$id]) {
100
		pfSenseHeader("system_camanager.php");
101
		exit;
102
	}
103
	$pconfig['method'] = 'existing';
104
	$pconfig['descr']  = $a_ca[$id]['descr'];
105
	$pconfig['refid']  = $a_ca[$id]['refid'];
106
	$pconfig['cert']   = base64_decode($a_ca[$id]['crt']);
107
	$pconfig['serial'] = $a_ca[$id]['serial'];
108
	$pconfig['trust']  = ($a_ca[$id]['trust'] == 'enabled');
109
	$pconfig['randomserial']  = ($a_ca[$id]['randomserial'] == 'enabled');
110
	if (!empty($a_ca[$id]['prv'])) {
111
		$pconfig['key'] = base64_decode($a_ca[$id]['prv']);
112
	}
113
}
114

  
115
if ($act == "new") {
116
	$pconfig['method'] = $_POST['method'];
117
	$pconfig['keytype'] = "RSA";
118
	$pconfig['keylen'] = "2048";
119
	$pconfig['ecname'] = "brainpoolP256r1";
120
	$pconfig['digest_alg'] = "sha256";
121
	$pconfig['lifetime'] = $default_lifetime;
122
	$pconfig['dn_commonname'] = "internal-ca";
123
}
124

  
125
if ($act == "exp") {
126

  
127
	if (!$a_ca[$id]) {
128
		pfSenseHeader("system_camanager.php");
129
		exit;
130
	}
131

  
132
	$exp_name = urlencode("{$a_ca[$id]['descr']}.crt");
133
	$exp_data = base64_decode($a_ca[$id]['crt']);
134
	$exp_size = strlen($exp_data);
135

  
136
	header("Content-Type: application/octet-stream");
137
	header("Content-Disposition: attachment; filename={$exp_name}");
138
	header("Content-Length: $exp_size");
139
	echo $exp_data;
140
	exit;
141
}
142

  
143
if ($act == "expkey") {
144

  
145
	if (!$a_ca[$id]) {
76
switch ($act) {
77
	case 'del':
78
		/* Only remove CA reference when deleting. It can be reconnected if a new matching CA is imported */
79
		$index = count($a_cert) - 1;
80
		for (;$index >= 0; $index--) {
81
			if ($a_cert[$index]['caref'] == $a_ca[$id]['refid']) {
82
				unset($a_cert[$index]['caref']);
83
			}
84
		}
85
		/* Remove any CRLs for this CA, there is no way to recover the connection once the CA has been removed. */
86
		$index = count($a_crl) - 1;
87
		for (;$index >= 0; $index--) {
88
			if ($a_crl[$index]['caref'] == $a_ca[$id]['refid']) {
89
				unset($a_crl[$index]);
90
			}
91
		}
92
		$name = $a_ca[$id]['descr'];
93
		unset($a_ca[$id]);
94
		write_config();
95
		ca_setup_trust_store();
96
		$savemsg = sprintf(gettext("Certificate Authority %s and its CRLs (if any) successfully deleted."), htmlspecialchars($name));
146 97
		pfSenseHeader("system_camanager.php");
147 98
		exit;
148
	}
149

  
150
	$exp_name = urlencode("{$a_ca[$id]['descr']}.key");
151
	$exp_data = base64_decode($a_ca[$id]['prv']);
152
	$exp_size = strlen($exp_data);
153

  
154
	header("Content-Type: application/octet-stream");
155
	header("Content-Disposition: attachment; filename={$exp_name}");
156
	header("Content-Length: $exp_size");
157
	echo $exp_data;
158
	exit;
99
		break;
100
	case 'edit':
101
		/* Editing an existing CA, so populate values. */
102
		$pconfig['method'] = 'existing';
103
		$pconfig['descr']  = $a_ca[$id]['descr'];
104
		$pconfig['refid']  = $a_ca[$id]['refid'];
105
		$pconfig['cert']   = base64_decode($a_ca[$id]['crt']);
106
		$pconfig['serial'] = $a_ca[$id]['serial'];
107
		$pconfig['trust']  = ($a_ca[$id]['trust'] == 'enabled');
108
		$pconfig['randomserial']  = ($a_ca[$id]['randomserial'] == 'enabled');
109
		if (!empty($a_ca[$id]['prv'])) {
110
			$pconfig['key'] = base64_decode($a_ca[$id]['prv']);
111
		}
112
		break;
113
	case 'new':
114
		/* New CA, so set default values */
115
		$pconfig['method'] = $_POST['method'];
116
		$pconfig['keytype'] = "RSA";
117
		$pconfig['keylen'] = "2048";
118
		$pconfig['ecname'] = "brainpoolP256r1";
119
		$pconfig['digest_alg'] = "sha256";
120
		$pconfig['lifetime'] = $default_lifetime;
121
		$pconfig['dn_commonname'] = "internal-ca";
122
		break;
123
	case 'exp':
124
		/* Exporting a ca */
125
		send_user_download('data', base64_decode($a_ca[$id]['crt']), "{$a_ca[$id]['descr']}.crt");
126
		break;
127
	case 'expkey':
128
		/* Exporting a private key */
129
		send_user_download('data', base64_decode($a_ca[$id]['prv']), "{$a_ca[$id]['descr']}.key");
130
		break;
131
	default:
132
		break;
159 133
}
160 134

  
161 135
if ($_POST['save']) {
162

  
163 136
	unset($input_errors);
164 137
	$input_errors = array();
165 138
	$pconfig = $_POST;
166 139

  
167 140
	/* input validation */
168
	if ($pconfig['method'] == "existing") {
169
		$reqdfields = explode(" ", "descr cert");
170
		$reqdfieldsn = array(
171
			gettext("Descriptive name"),
172
			gettext("Certificate data"));
173
		if ($_POST['cert'] && (!strstr($_POST['cert'], "BEGIN CERTIFICATE") || !strstr($_POST['cert'], "END CERTIFICATE"))) {
174
			$input_errors[] = gettext("This certificate does not appear to be valid.");
175
		}
176
		if ($_POST['key'] && strstr($_POST['key'], "ENCRYPTED")) {
177
			$input_errors[] = gettext("Encrypted private keys are not yet supported.");
178
		}
179
		if (!$input_errors && !empty($_POST['key']) && cert_get_publickey($_POST['cert'], false) != cert_get_publickey($_POST['key'], false, 'prv')) {
180
			$input_errors[] = gettext("The submitted private key does not match the submitted certificate data.");
181
		}
182
		/* we must ensure the certificate is capable of acting as a CA
183
		 * https://redmine.pfsense.org/issues/7885
184
		 */
185
		if (!$input_errors) {
186
			$purpose = cert_get_purpose($_POST['cert'], false);
187
			if ($purpose['ca'] != 'Yes') {
188
				$input_errors[] = gettext("The submitted certificate does not appear to be a Certificate Authority, import it on the Certificates tab instead.");
141
	switch ($pconfig['method']) {
142
		case 'existing':
143
			$reqdfields = explode(" ", "descr cert");
144
			$reqdfieldsn = array(
145
				gettext("Descriptive name"),
146
				gettext("Certificate data"));
147
			if ($_POST['cert'] && (!strstr($_POST['cert'], "BEGIN CERTIFICATE") || !strstr($_POST['cert'], "END CERTIFICATE"))) {
148
				$input_errors[] = gettext("This certificate does not appear to be valid.");
189 149
			}
190
		}
191
	}
192
	if ($pconfig['method'] == "internal") {
193
		$reqdfields = explode(" ",
194
			"descr keylen ecname keytype lifetime dn_commonname");
195
		$reqdfieldsn = array(
196
			gettext("Descriptive name"),
197
			gettext("Key length"),
198
			gettext("Elliptic Curve Name"),
199
			gettext("Key type"),
200
			gettext("Lifetime"),
201
			gettext("Common Name"));
202
	}
203
	if ($pconfig['method'] == "intermediate") {
204
		$reqdfields = explode(" ",
205
			"descr caref keylen ecname keytype lifetime dn_commonname");
206
		$reqdfieldsn = array(
207
			gettext("Descriptive name"),
208
			gettext("Signing Certificate Authority"),
209
			gettext("Key length"),
210
			gettext("Elliptic Curve Name"),
211
			gettext("Key type"),
212
			gettext("Lifetime"),
213
			gettext("Common Name"));
150
			if ($_POST['key'] && strstr($_POST['key'], "ENCRYPTED")) {
151
				$input_errors[] = gettext("Encrypted private keys are not yet supported.");
152
			}
153
			if (!$input_errors && !empty($_POST['key']) && cert_get_publickey($_POST['cert'], false) != cert_get_publickey($_POST['key'], false, 'prv')) {
154
				$input_errors[] = gettext("The submitted private key does not match the submitted certificate data.");
155
			}
156
			/* we must ensure the certificate is capable of acting as a CA
157
			 * https://redmine.pfsense.org/issues/7885
158
			 */
159
			if (!$input_errors) {
160
				$purpose = cert_get_purpose($_POST['cert'], false);
161
				if ($purpose['ca'] != 'Yes') {
162
					$input_errors[] = gettext("The submitted certificate does not appear to be a Certificate Authority, import it on the Certificates tab instead.");
163
				}
164
			}
165
			break;
166
		case 'internal':
167
			$reqdfields = explode(" ",
168
				"descr keylen ecname keytype lifetime dn_commonname");
169
			$reqdfieldsn = array(
170
				gettext("Descriptive name"),
171
				gettext("Key length"),
172
				gettext("Elliptic Curve Name"),
173
				gettext("Key type"),
174
				gettext("Lifetime"),
175
				gettext("Common Name"));
176
			break;
177
		case 'intermediate':
178
			$reqdfields = explode(" ",
179
				"descr caref keylen ecname keytype lifetime dn_commonname");
180
			$reqdfieldsn = array(
181
				gettext("Descriptive name"),
182
				gettext("Signing Certificate Authority"),
183
				gettext("Key length"),
184
				gettext("Elliptic Curve Name"),
185
				gettext("Key type"),
186
				gettext("Lifetime"),
187
				gettext("Common Name"));
188
			break;
189
		default:
190
			break;
214 191
	}
215 192

  
216 193
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);

Also available in: Unified diff