Skip to content

Instantly share code, notes, and snippets.

@aaronpk

aaronpk/inc.php Secret

Created January 31, 2014 20:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aaronpk/f193641cc45cd21f766c to your computer and use it in GitHub Desktop.
Save aaronpk/f193641cc45cd21f766c to your computer and use it in GitHub Desktop.
<?php
$requestDir = '/web/sites/pin13.net/ssl/indiewebcamp/requests';
function get($key, $default=NULL) {
return array_key_exists($key, $_GET) ? $_GET[$key] : $default;
}
function post($key, $default=NULL) {
return array_key_exists($key, $_POST) ? $_POST[$key] : $default;
}
function mailer() {
$mailer = new PHPMailer();
$mailer->isSMTP();
$mailer->Host = 'email-smtp.us-east-1.amazonaws.com';
$mailer->Username = 'XXX';
$mailer->Password = 'XXX';
$mailer->SMTPAuth = true;
$mailer->SMTPSecure = 'tls';
return $mailer;
}
function sign_csr($csrFile, $signedFile) {
ob_start();
echo shell_exec('openssl ca -batch -config /web/sites/pin13.net/ssl/indiewebcamp/openssl.conf -in '.$csrFile.' -out '.$signedFile.' 2>&1');
return ob_get_clean();
}
function get_domain_from_cert($crtFile) {
$crt = shell_exec('openssl x509 -in '.$crtFile.' -text -noout');
if(preg_match('/Subject:.+CN=([^\/]+)/', $crt, $match)) {
return $match[1];
} else {
return false;
}
}
function get_domain_from_csr($csrFile) {
$csr = shell_exec('openssl req -in '.$csrFile.' -text -noout');
if(preg_match('/Subject:.+CN=([^\/]+)/', $csr, $match)) {
return $match[1];
} else {
return false;
}
}
function get_email_from_csr($csrFile) {
$csr = shell_exec('openssl req -in '.$csrFile.' -text -noout');
if(preg_match('/Subject:.+CN=[^\/]+\/.*emailAddress=(.+)/', $csr, $match)) {
return $match[1];
} else {
return false;
}
}
function get_csr_info($csrFile) {
$csr = shell_exec('openssl req -in '.$csrFile.' -text -noout');
return $csr;
}
function verify_crt_file($crtFile) {
$cert = file_get_contents($crtFile);
if(preg_match('/-----BEGIN CERTIFICATE-----.+-----END CERTIFICATE-----/sm', $cert, $match)) {
return true;
} else {
return false;
}
}
function send_crt_file($domain, $crtFile) {
$cert = file_get_contents($crtFile);
if(preg_match('/-----BEGIN CERTIFICATE-----.+-----END CERTIFICATE-----/sm', $cert, $match)) {
// Download the file
header('Content-type: application/x-x509-ca-cert');
header('Content-disposition: attachment; filename="'.$domain.'.crt"');
echo $match[0];
} else {
return false;
}
}
<h1>IndieWebCamp SSL Certificates</h1>
<h2>Request an SSL Certificate</h2>
<form action="submit-csr.php" method="post">
Paste your CSR below (<a href="#quick-help">quick ref for generating a CSR</a>)<br>
<textarea name="csr" cols="40" rows="6"></textarea>
<br>
<input type="submit" value="Submit">
</form>
<p>If your request is for a domain that ends in ".dev", it will be automatically signed and you will be able to download the certificate immediately. Otherwise, the request will require approval and you will receive an email with your signed certificate after it is complete.</p>
<p>(Make sure to include your email address when you generate the CSR, so that the system knows where to send your signed certificate!)</p>
<hr>
<h3 id="quick-help">Quick Help</h3>
<p>Generate a private key:</p>
<pre>openssl genrsa -des3 -out server.pem 2048</pre>
<p>Generate a certificate signing request (CSR)</p>
<pre>openssl req -out request.csr -key server.pem -new</pre>
<p>View a CSR's details</p>
<pre>openssl req -text -noout -verify -in request.csr</pre>
<p>View a certificate</p>
<pre>openssl x509 -in example.dev.crt -text -noout</pre>
<hr>
<h3 id="root-certificate">Root Certificate</h3>
<p>In order to avoid the SSL certificate warning from your browser when visiting a site that uses your new certificate, you'll need to add the IndieWebCamp certificate authority to your system.</p>
<p><a href="indiewebcamp-root-certificate.pem">indiewebcamp-root-certificate.pem</a></p>
<p>Opening this file on OS X will prompt you to add it to your keychain. Once you do that, your browser should recognize any site signed by this root certificate.</p>
<hr>
<h3 id="apache">Apache</h3>
<p>Sample Apache virtual host configuration</p>
<pre><?php echo htmlspecialchars('
<VirtualHost *:443>
ServerAlias example.dev
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLCertificateFile /etc/httpd/conf.d/example.dev.crt
SSLCertificateKeyFile /etc/httpd/conf.d/server.pem
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
... (your normal config stuff here)
</VirtualHost>'); ?>
</pre>
<h3 id="nginx">nginx</h3>
<p>Sample nginx virtual host configuration</p>
<pre><?php echo htmlspecialchars('
server {
listen *:443;
server_name example.dev;
ssl on;
ssl_certificate /etc/nginx/conf.d/example.dev.crt;
ssl_certificate_key /etc/nginx/conf.d/server.pem;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
... (your normal config stuff here)
}
'); ?>
</pre>
<hr>
<p>By <a href="http://aaronparecki.com/">Aaron Parecki</a></p>
<?php
include('inc.php');
require_once('PHPMailer/PHPMailerAutoload.php');
if(post('csr')) {
$requestDate = date('Ymd-His');
$requestFile = $requestDir . '/csr-'.$requestDate.'.csr';
// Write the csr to a file so we can work with it
file_put_contents($requestFile, post('csr'));
// Get the common name in the CSR
if($domain=get_domain_from_csr($requestFile)) {
if(preg_match('/\.dev$/', $domain)) {
$certFilename = 'csr-'.date('Ymd-His').'.crt';
$signedFile = $requestDir . '/' . $certFilename;
// Auto-sign any *.dev cert
$result = sign_csr($requestFile, $signedFile);
if(verify_crt_file($signedFile)) {
echo '<p>Your certificate is ready!</p>';
echo '<p><a href="download.php?certificate=' . $certFilename . '">Download your certificate</a></p>';
} else {
echo '<p>Unable to generate the certificate!</p>';
echo '<p><pre>' . $result . '</pre></p>';
echo '<p>Please let <a href="http://aaronparecki.com/">aaronpk</a> know!</p>';
}
unlink($requestFile);
@unlink($signedfile);
} else {
// Queue the request and email the requester as well as myself
if($email=get_email_from_csr($requestFile)) {
$mailer = mailer();
$mailer->AddAddress('aaron@parecki.com');
$mailer->SetFrom('certificates@pin13.net');
$mailer->Subject = 'Certificate Signing Request: '.$domain;
$mailer->isHTML(true);
$mailer->Body = '<p>A certificate request was submitted by ' . $email . ' for <a href="http://' . $domain . '">' . $domain . '</a></p>'."\n".
'<p><a href="https://ssl.pin13.net/indiewebcamp/sign/?req='.$requestDate.'">Approve the request</a></p>';
$mailer->Send();
echo '<p>Your request for an SSL certificate for <b>' . $domain . '</b> was sent. Your certificate will be emailed to you at <b>' . $email . '</b> when it is approved.</p>';
} else {
echo '<p>Couldn\'t find your email address in the CSR. Make sure to include your email address in the CSR and try again.</p>';
unlink($requestFile);
}
}
} else {
echo "<p>Unable to read the CSR!</p>";
unlink($requestFile);
}
} else {
header('Location: index.php');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment