Skip to content
This repository has been archived by the owner on Dec 14, 2020. It is now read-only.

Commit

Permalink
openvpn: Implement support for extra-certs (intermediate chain certs)
Browse files Browse the repository at this point in the history
  • Loading branch information
RMerl committed Sep 9, 2015
1 parent 8d489d5 commit 9fbaf62
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 26 deletions.
24 changes: 23 additions & 1 deletion release/src/router/httpd/openvpn_options.c
Expand Up @@ -554,6 +554,28 @@ add_option (char *p[], int line, int unit)
return VPN_UPLOAD_NEED_STATIC;
}
}
else if (streq (p[0], "extra-certs") && p[1])
{
if (streq (p[1], INLINE_FILE_TAG) && p[2])
{
sprintf(buf, "vpn_crt_client%d_extra", unit);
#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS)
snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, buf);
fp = fopen(file_path, "w");
if(fp) {
fprintf(fp, "%s", strstr(p[2], "-----BEGIN"));
fclose(fp);
}
else
#endif
write_encoded_crt(buf, strstr(p[2], "-----BEGIN"));
}
else
{
return VPN_UPLOAD_NEED_EXTRA;
}
}

else if (streq (p[0], "auth-user-pass"))
{
sprintf(buf, "vpn_client%d_userauth", unit);
Expand Down Expand Up @@ -694,7 +716,7 @@ void reset_client_setting(int unit){
snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, nv);
unlink(file_path);
#endif
sprintf(nv, "vpn_crt_client%d_crl", unit);
sprintf(nv, "vpn_crt_client%d_extra", unit);
nvram_set(nv, "");
#if defined(RTCONFIG_JFFS2) || defined(RTCONFIG_BRCM_NAND_JFFS2) || defined(RTCONFIG_UBIFS)
snprintf(file_path, sizeof(file_path) -1, "%s/%s", OVPN_FS_PATH, nv);
Expand Down
1 change: 1 addition & 0 deletions release/src/router/httpd/openvpn_options.h
Expand Up @@ -6,6 +6,7 @@
#define VPN_UPLOAD_NEED_KEY 4
#define VPN_UPLOAD_NEED_STATIC 8
#define VPN_UPLOAD_NEED_CRL 16
#define VPN_UPLOAD_NEED_EXTRA 24

#define MAX_PARMS 16

Expand Down
36 changes: 36 additions & 0 deletions release/src/router/httpd/web.c
Expand Up @@ -1558,6 +1558,21 @@ ej_vpn_crt_server(int eid, webs_t wp, int argc, char **argv) {
}
websWrite(wp, "'];\n");

//vpn_crt_server_extra
memset(buf, 0, sizeof(buf));
memset(file_name, 0, sizeof(file_name));
sprintf(file_name, "vpn_crt_server%d_extra", idx);
get_parsed_crt(file_name, buf, sizeof(buf));
websWrite(wp, "%s=['", file_name);
for (c = buf; *c; c++) {
if (isprint(*c) &&
*c != '"' && *c != '&' && *c != '<' && *c != '>')
websWrite(wp, "%c", *c);
else
websWrite(wp, "&#%d", *c);
}
websWrite(wp, "'];\n");

websWrite(wp, "\n");
}
return 0;
Expand Down Expand Up @@ -1647,6 +1662,21 @@ ej_vpn_crt_client(int eid, webs_t wp, int argc, char **argv) {
}
websWrite(wp, "'];\n");

//vpn_crt_client_extra
memset(buf, 0, sizeof(buf));
memset(file_name, 0, sizeof(file_name));
sprintf(file_name, "vpn_crt_client%d_extra", idx);
get_parsed_crt(file_name, buf, sizeof(buf));
websWrite(wp, "%s=['", file_name);
for (c = buf; *c; c++) {
if (isprint(*c) &&
*c != '"' && *c != '&' && *c != '<' && *c != '>')
websWrite(wp, "%c", *c);
else
websWrite(wp, "&#%d", *c);
}
websWrite(wp, "'];\n");

websWrite(wp, "\n");
}
return 0;
Expand Down Expand Up @@ -7828,6 +7858,12 @@ do_vpnupload_cgi(char *url, FILE *stream)
sprintf(nv, "vpn_crt_server%s_crl", unit);
set_crt_parsed(nv, VPN_CLIENT_UPLOAD);
}
else if(!strcmp(filetype, "extra")) {
sprintf(nv, "vpn_crt_client%s_extra", unit);
set_crt_parsed(nv, VPN_CLIENT_UPLOAD);
state = nvram_get_int("vpn_upload_state");
nvram_set_int("vpn_upload_state", state & (~VPN_UPLOAD_NEED_EXTRA));
}
}
else
{
Expand Down
38 changes: 38 additions & 0 deletions release/src/router/rc/openvpn.c
Expand Up @@ -311,6 +311,9 @@ void start_vpnclient(int clientNum)
if ( !ovpn_crt_is_empty(&buffer[0]) )
fprintf(fp, "crl-verify crl.pem\n");

sprintf(&buffer[0], "vpn_crt_client%d_extra", clientNum);
if ( !ovpn_crt_is_empty(&buffer[0]) )
fprintf(fp, "extra-certs extra.pem\n");
}
else if ( cryptMode == SECRET )
{
Expand Down Expand Up @@ -399,6 +402,17 @@ void start_vpnclient(int clientNum)
fprintf(fp, "%s", get_parsed_crt(&buffer[0], buffer2, sizeof(buffer2)));
fclose(fp);
}

sprintf(&buffer[0], "vpn_crt_client%d_extra", clientNum);
if ( !ovpn_crt_is_empty(&buffer[0]) )
{
sprintf(&buffer[0], "/etc/openvpn/client%d/extra.pem", clientNum);
fp = fopen(&buffer[0], "w");
chmod(&buffer[0], S_IRUSR|S_IWUSR);
sprintf(&buffer[0], "vpn_crt_client%d_extra", clientNum);
fprintf(fp, "%s", get_parsed_crt(&buffer[0], buffer2, sizeof(buffer2)));
fclose(fp);
}
}
sprintf(&buffer[0], "vpn_client%d_hmac", clientNum);
if ( cryptMode == SECRET || (cryptMode == TLS && nvram_get_int(&buffer[0]) >= 0) )
Expand Down Expand Up @@ -1021,6 +1035,10 @@ void start_vpnserver(int serverNum)
sprintf(&buffer[0], "vpn_crt_server%d_crl", serverNum);
if ( !ovpn_crt_is_empty(&buffer[0]) )
fprintf(fp, "crl-verify crl.pem\n");
sprintf(&buffer[0], "vpn_crt_server%d_extra", serverNum);
if ( !ovpn_crt_is_empty(&buffer[0]) )
fprintf(fp, "extra-certs extra.pem\n");

}
else if ( cryptMode == SECRET )
{
Expand Down Expand Up @@ -1181,6 +1199,18 @@ void start_vpnserver(int serverNum)
fprintf(fp, "%s", get_parsed_crt(&buffer[0], buffer2, sizeof(buffer2)));
fclose(fp);
}

sprintf(&buffer[0], "vpn_crt_server%d_extra", serverNum);
if ( !ovpn_crt_is_empty(&buffer[0]) )
{
sprintf(&buffer[0], "/etc/openvpn/server%d/extra.pem", serverNum);
fp = fopen(&buffer[0], "w");
chmod(&buffer[0], S_IRUSR|S_IWUSR);
sprintf(&buffer[0], "vpn_crt_server%d_extra", serverNum);
fprintf(fp, "%s", get_parsed_crt(&buffer[0], buffer2, sizeof(buffer2)));
fclose(fp);
}

}

sprintf(&buffer[0], "vpn_crt_server%d_ca", serverNum);
Expand All @@ -1189,6 +1219,14 @@ void start_vpnserver(int serverNum)
if (buffer2[strlen(buffer2)-1] != '\n') fprintf(fp_client, "\n"); // Append newline if missing
fprintf(fp_client, "</ca>\n");

sprintf(&buffer[0], "vpn_crt_server%d_extra", serverNum);
if ( !ovpn_crt_is_empty(&buffer[0]) ) {
fprintf(fp_client, "<extra-certs>\n");
fprintf(fp_client, "%s", get_parsed_crt(&buffer[0], buffer2, sizeof(buffer2)));
if (buffer2[strlen(buffer2)-1] != '\n') fprintf(fp_client, "\n"); // Append newline if missing
fprintf(fp_client, "</extra-certs>\n");
}

// Only do this if we do not have both userauth and useronly enabled at the same time
if ( !(userauth && useronly) ) {
/*
Expand Down
14 changes: 14 additions & 0 deletions release/src/router/www/Advanced_OpenVPNClient_Content.asp
Expand Up @@ -240,13 +240,15 @@ function setTLSTable(unit) {
document.getElementById('edit_vpn_crt_client_key').value = vpn_crt_client1_key[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.getElementById('edit_vpn_crt_client_static').value = vpn_crt_client1_static[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.getElementById('edit_vpn_crt_client_crl').value = vpn_crt_client1_crl[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.getElementById('edit_vpn_crt_client_extra').value = vpn_crt_client1_extra[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
break;
case "2" :
document.getElementById('edit_vpn_crt_client_ca').value = vpn_crt_client2_ca[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.getElementById('edit_vpn_crt_client_crt').value = vpn_crt_client2_crt[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.getElementById('edit_vpn_crt_client_key').value = vpn_crt_client2_key[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.getElementById('edit_vpn_crt_client_static').value = vpn_crt_client2_static[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.getElementById('edit_vpn_crt_client_crl').value = vpn_crt_client2_crl[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.getElementById('edit_vpn_crt_client_extra').value = vpn_crt_client2_extra[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
break;
/*
case "3" :
Expand Down Expand Up @@ -340,23 +342,27 @@ function save_Keys(){
document.form.vpn_crt_client1_key.value = document.getElementById('edit_vpn_crt_client_key').value;
document.form.vpn_crt_client1_static.value = document.getElementById('edit_vpn_crt_client_static').value;
document.form.vpn_crt_client1_crl.value = document.getElementById('edit_vpn_crt_client_crl').value;
document.form.vpn_crt_client1_extra.value = document.getElementById('edit_vpn_crt_client_extra').value;
document.form.vpn_crt_client1_ca.disabled = false;
document.form.vpn_crt_client1_crt.disabled = false;
document.form.vpn_crt_client1_key.disabled = false;
document.form.vpn_crt_client1_static.disabled = false;
document.form.vpn_crt_client1_crl.disabled = false;
document.form.vpn_crt_client1_extra.disabled = false;
break;
case "2" :
document.form.vpn_crt_client2_ca.value = document.getElementById('edit_vpn_crt_client_ca').value;
document.form.vpn_crt_client2_crt.value = document.getElementById('edit_vpn_crt_client_crt').value;
document.form.vpn_crt_client2_key.value = document.getElementById('edit_vpn_crt_client_key').value;
document.form.vpn_crt_client2_static.value = document.getElementById('edit_vpn_crt_client_static').value;
document.form.vpn_crt_client2_crl.value = document.getElementById('edit_vpn_crt_client_crl').value;
document.form.vpn_crt_client2_extra.value = document.getElementById('edit_vpn_crt_client_extra').value;
document.form.vpn_crt_client2_ca.disabled = false;
document.form.vpn_crt_client2_crt.disabled = false;
document.form.vpn_crt_client2_key.disabled = false;
document.form.vpn_crt_client2_static.disabled = false;
document.form.vpn_crt_client2_crl.disabled = false;
document.form.vpn_crt_client2_extra.disabled = false;
break;
/*
case "3" :
Expand Down Expand Up @@ -765,6 +771,12 @@ function validate_ipcidr(obj){
<textarea rows="8" class="textarea_ssh_table" id="edit_vpn_crt_client_crl" name="edit_vpn_crt_client_crl" cols="65" maxlength="3499"></textarea>
</td>
</tr>
<tr>
<th id="manualKey">Extra Chain Certificates (Optional)</th>
<td>
<textarea rows="8" class="textarea_ssh_table"id="edit_vpn_crt_client_extra" name="edit_vpn_crt_client_extra" cols="65" maxlength="3499"></textarea>
</td>
</tr>
</table>
</td>
</tr>
Expand Down Expand Up @@ -804,11 +816,13 @@ function validate_ipcidr(obj){
<input type="hidden" name="vpn_crt_client1_key" value="" disabled>
<input type="hidden" name="vpn_crt_client1_static" value="" disabled>
<input type="hidden" name="vpn_crt_client1_crl" value="" disabled>
<input type="hidden" name="vpn_crt_client1_extra" value="" disabled>
<input type="hidden" name="vpn_crt_client2_ca" value="" disabled>
<input type="hidden" name="vpn_crt_client2_crt" value="" disabled>
<input type="hidden" name="vpn_crt_client2_key" value="" disabled>
<input type="hidden" name="vpn_crt_client2_static" value="" disabled>
<input type="hidden" name="vpn_crt_client2_crl" value="" disabled>
<input type="hidden" name="vpn_crt_client2_extra" value="" disabled>
<input type="hidden" name="vpn_crt_client3_ca" value="" disabled>
<input type="hidden" name="vpn_crt_client3_crt" value="" disabled>
<input type="hidden" name="vpn_crt_client3_key" value="" disabled>
Expand Down
41 changes: 16 additions & 25 deletions release/src/router/www/Advanced_VPN_OpenVPN.asp
Expand Up @@ -376,13 +376,15 @@ function applyRule(){
document.openvpnTLSKeyForm.vpn_crt_server1_key.disabled = true;
document.openvpnTLSKeyForm.vpn_crt_server1_dh.disabled = true;
document.openvpnTLSKeyForm.vpn_crt_server1_crl.disabled = true;
document.openvpnTLSKeyForm.vpn_crt_server1_extra.disabled = true;
document.openvpnTLSKeyForm.vpn_crt_server1_static.disabled = true;
document.openvpnTLSKeyForm.vpn_crt_server2_ca.disabled = true;
document.openvpnTLSKeyForm.vpn_crt_server2_crt.disabled = true;
document.openvpnTLSKeyForm.vpn_crt_server2_key.disabled = true;
document.openvpnTLSKeyForm.vpn_crt_server2_dh.disabled = true;
document.openvpnTLSKeyForm.vpn_crt_server2_crl.disabled = true;
document.openvpnTLSKeyForm.vpn_crt_server2_static.disabled = true;
document.openvpnTLSKeyForm.vpn_crt_server2_extra.disabled = true;
var get_group_value = function () {
var rule_num = document.getElementById("openvpnd_clientlist_table").rows.length;
Expand Down Expand Up @@ -788,13 +790,15 @@ function updateCRTValue(){
document.openvpnTLSKeyForm.edit_vpn_crt_server_dh.value = vpn_crt_server1_dh[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.openvpnTLSKeyForm.edit_vpn_crt_server_crl.value = vpn_crt_server1_crl[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.openvpnTLSKeyForm.edit_vpn_crt_server_static.value = vpn_crt_server1_static[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.openvpnTLSKeyForm.edit_vpn_crt_server_extra.value = vpn_crt_server1_extra[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
} else if (openvpn_unit == 2) {
document.openvpnTLSKeyForm.edit_vpn_crt_server_ca.value = vpn_crt_server2_ca[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.openvpnTLSKeyForm.edit_vpn_crt_server_crt.value = vpn_crt_server2_crt[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.openvpnTLSKeyForm.edit_vpn_crt_server_key.value = vpn_crt_server2_key[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.openvpnTLSKeyForm.edit_vpn_crt_server_dh.value = vpn_crt_server2_dh[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.openvpnTLSKeyForm.edit_vpn_crt_server_crl.value = vpn_crt_server2_crl[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.openvpnTLSKeyForm.edit_vpn_crt_server_static.value = vpn_crt_server2_static[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
document.openvpnTLSKeyForm.edit_vpn_crt_server_extra.value = vpn_crt_server2_extra[0].replace(/&#10/g, "\n").replace(/&#13/g, "\r");
}
}
})
Expand Down Expand Up @@ -922,30 +926,6 @@ function cancel_Key_panel() {
$("#tlsKey_panel").fadeOut(300);
}
/*
function openvpn_decodeKeys(entities){
var expr;
if (entities == 1)
expr = new RegExp('&#62;','gm');
else
expr = new RegExp('>','gm');
document.openvpnTLSKeyForm.edit_vpn_crt_server1_static.value = document.openvpnTLSKeyForm.edit_vpn_crt_server1_static.value.replace(expr,"\r\n");
document.openvpnTLSKeyForm.edit_vpn_crt_server1_ca.value = document.openvpnTLSKeyForm.edit_vpn_crt_server1_ca.value.replace(expr,"\r\n");
document.openvpnTLSKeyForm.edit_vpn_crt_server1_key.value = document.openvpnTLSKeyForm.edit_vpn_crt_server1_key.value.replace(expr,"\r\n");
document.openvpnTLSKeyForm.edit_vpn_crt_server1_crt.value = document.openvpnTLSKeyForm.edit_vpn_crt_server1_crt.value.replace(expr,"\r\n");
document.openvpnTLSKeyForm.edit_vpn_crt_server1_dh.value = document.openvpnTLSKeyForm.edit_vpn_crt_server1_dh.value.replace(expr,"\r\n");
document.openvpnTLSKeyForm.edit_vpn_crt_server1_crl.value = document.openvpnTLSKeyForm.edit_vpn_crt_server1_crl.value.replace(expr,"\r\n");
document.openvpnTLSKeyForm.edit_vpn_crt_server2_static.value = document.openvpnTLSKeyForm.edit_vpn_crt_server2_static.value.replace(expr,"\r\n");
document.openvpnTLSKeyForm.edit_vpn_crt_server2_ca.value = document.openvpnTLSKeyForm.edit_vpn_crt_server2_ca.value.replace(expr,"\r\n");
document.openvpnTLSKeyForm.edit_vpn_crt_server2_key.value = document.openvpnTLSKeyForm.edit_vpn_crt_server2_key.value.replace(expr,"\r\n");
document.openvpnTLSKeyForm.edit_vpn_crt_server2_crt.value = document.openvpnTLSKeyForm.edit_vpn_crt_server2_crt.value.replace(expr,"\r\n");
document.openvpnTLSKeyForm.edit_vpn_crt_server2_dh.value = document.openvpnTLSKeyForm.edit_vpn_crt_server2_dh.value.replace(expr,"\r\n");
document.openvpnTLSKeyForm.edit_vpn_crt_server2_crl.value = document.openvpnTLSKeyForm.edit_vpn_crt_server2_crl.value.replace(expr,"\r\n");
}
*/
function save_keys() {
if (openvpn_unit == "1") {
Expand All @@ -955,25 +935,29 @@ function save_keys() {
document.openvpnTLSKeyForm.vpn_crt_server1_dh.value = document.openvpnTLSKeyForm.edit_vpn_crt_server_dh.value;
document.openvpnTLSKeyForm.vpn_crt_server1_crl.value = document.openvpnTLSKeyForm.edit_vpn_crt_server_crl.value;
document.openvpnTLSKeyForm.vpn_crt_server1_static.value = document.openvpnTLSKeyForm.edit_vpn_crt_server_static.value;
document.openvpnTLSKeyForm.vpn_crt_server1_extra.value = document.openvpnTLSKeyForm.edit_vpn_crt_server_extra.value;
document.openvpnTLSKeyForm.vpn_crt_server1_static.disabled = false;
document.openvpnTLSKeyForm.vpn_crt_server1_ca.disabled = false;
document.openvpnTLSKeyForm.vpn_crt_server1_crt.disabled = false;
document.openvpnTLSKeyForm.vpn_crt_server1_key.disabled = false;
document.openvpnTLSKeyForm.vpn_crt_server1_dh.disabled = false;
document.openvpnTLSKeyForm.vpn_crt_server1_crl.disabled = false;
document.openvpnTLSKeyForm.vpn_crt_server1_extra.disabled = false;
} else {
document.openvpnTLSKeyForm.vpn_crt_server2_ca.value = document.openvpnTLSKeyForm.edit_vpn_crt_server_ca.value;
document.openvpnTLSKeyForm.vpn_crt_server2_crt.value = document.openvpnTLSKeyForm.edit_vpn_crt_server_crt.value;
document.openvpnTLSKeyForm.vpn_crt_server2_key.value = document.openvpnTLSKeyForm.edit_vpn_crt_server_key.value;
document.openvpnTLSKeyForm.vpn_crt_server2_dh.value = document.openvpnTLSKeyForm.edit_vpn_crt_server_dh.value;
document.openvpnTLSKeyForm.vpn_crt_server2_crl.value = document.openvpnTLSKeyForm.edit_vpn_crt_server_crl.value;
document.openvpnTLSKeyForm.vpn_crt_server2_static.value = document.openvpnTLSKeyForm.edit_vpn_crt_server_static.value;
document.openvpnTLSKeyForm.vpn_crt_server2_extra.value = document.openvpnTLSKeyForm.edit_vpn_crt_server_extra.value;
document.openvpnTLSKeyForm.vpn_crt_server2_static.disabled = false;
document.openvpnTLSKeyForm.vpn_crt_server2_ca.disabled = false;
document.openvpnTLSKeyForm.vpn_crt_server2_crt.disabled = false;
document.openvpnTLSKeyForm.vpn_crt_server2_key.disabled = false;
document.openvpnTLSKeyForm.vpn_crt_server2_dh.disabled = false;
document.openvpnTLSKeyForm.vpn_crt_server2_crl.disabled = false;
document.openvpnTLSKeyForm.vpn_crt_server2_extra.disabled = false;
}
document.openvpnTLSKeyForm.submit();
cancel_Key_panel();
Expand All @@ -1000,12 +984,14 @@ function save_keys() {
<input type="hidden" name="vpn_crt_server1_crt" value="" disabled>
<input type="hidden" name="vpn_crt_server1_key" value="" disabled>
<input type="hidden" name="vpn_crt_server1_dh" value="" disabled>
<input type="hidden" name="vpn_crt_server1_crl" value="" disabled>
<input type="hidden" name="vpn_crt_server1_crl" value="" disabled>
<input type="hidden" name="vpn_crt_server1_extra" value="" disabled>
<input type="hidden" name="vpn_crt_server2_ca" value="" disabled>
<input type="hidden" name="vpn_crt_server2_crt" value="" disabled>
<input type="hidden" name="vpn_crt_server2_key" value="" disabled>
<input type="hidden" name="vpn_crt_server2_dh" value="" disabled>
<input type="hidden" name="vpn_crt_server2_crl" value="" disabled>
<input type="hidden" name="vpn_crt_server2_extra" value="" disabled>
<input type="hidden" name="vpn_crt_server1_static" value="" disabled>
<input type="hidden" name="vpn_crt_server2_static" value="" disabled>
<tr>
Expand Down Expand Up @@ -1061,6 +1047,11 @@ function save_keys() {
<textarea rows="8" class="textarea_ssh_table" id="edit_vpn_crt_server_crl" name="edit_vpn_crt_server_crl" cols="65" maxlength="3499"></textarea>
</td>
</tr>
<tr id="edit_tls6">
<th>Extra Chain Certificates (Optional)</th>
<td><textarea rows="8" class="textarea_ssh_table" id="edit_vpn_crt_server_extra" name="edit_vpn_crt_server_extra" cols="65" maxlength="3499"></textarea>
</td>
</tr>
</table>
</td>
</tr>
Expand Down

0 comments on commit 9fbaf62

Please sign in to comment.