Tomcat 7 SSL – Swapping a Cert out in the keystore

Posted by & filed under Server Admin.

I have a PKCS12 .pfx export of a cert that I need to import into a Tomcat keystore in order to update an expiring certificate.


Need to know a few things beforehand:

  • Tomcat keyfile path
  • Source store password for the pfx file
  • Source alias for the pfx
  • Dest source passwd
  • Dest source alias
keytool -importkeystore -srckeystore wildcard_2016.pfx -srcstoretype pkcs12 -srcstorepass changeit -srcalias 4b84576db-35ca-8dc45b92a -destkeystore C:\ibi\ssl\.keystore -deststoretype jks -deststorepass changeit! -destalias tomcat

In order to get the source alias from the new pfx file:

keytool -v -list -storetype pkcs12 -keystore wildcard_2016.pfx > output.txt

If you need to get the alias from the existing Tomcat keystore:

keytool -list -v -keystore C:\ssl\.keystore > tomcatkeystore.txt

Additionally, the above command can be used to verify the certificate, expiry date, etc.

Lastly, if you restart Tomcat and it throws errors like the following in the catalina log, you may need to reset the keystore password:

SEVERE: Failed to initialize end point associated with ProtocolHandler ["http-nio-443"] Cannot recover key
...more stack trace here...

Reset to the correct password as defined in the servver.xml keyStorePass parameter using the following command. You may need to adjust alias to your needs. You will be prompted for the new password, which should match the previously mentioned keyStorePass parameter.

keytool -keypasswd -new changeit -keystore C:\ssl\.keystore -storepass changeit -alias tomcat

You can also reset the password for the keystore itself (…):

PS C:\> .\keytool.exe -keypasswd -new REDACTED -keystore C:\.keystore -alias tomcat




Additional note — when trying to run the import command I was getting the following error:

Existing entry alias 2 exists, overwrite? [no]:  yes
keytool error: java.lang.Exception: Alias <2> does not exist

I ran the following to verify the alias is correct:

PS C:\> .\keytool.exe -list -keystore C:\server2017.pfx -storetype pkcs12        
Enter keystore password: 

Keystore type: PKCS12
Keystore provider: SunJSSE

Your keystore contains 1 entry

2, Mar 13, 2017, PrivateKeyEntry,
Certificate fingerprint (MD5): RE:DA:CT:ED:DE:AD:BE:EF

Key ID of 2 is displayed correctly here as well as a more verbose output also showed the same:

.\keytool.exe -list -v -keystore C:\server_2017.pfx

I then took the same .pfx file and checked it on a linux machine based on a hint from this stackoverflow on binary chars:

nate@beef:~/$ keytool -list -keystore server2017.pfx -storetype pkcs12
Enter keystore password:

Keystore type: PKCS12
Keystore provider: SunJSSE

Your keystore contains 1 entry

1, Mar 13, 2017, PrivateKeyEntry,
Certificate fingerprint (SHA1): RE:DA:CT:ED:DE:AD:BE:EF

And lo’ and behold it shows the alias is actually 1!


..Back in Windows land:

PS C:\> ./keytool -importkeystore -srckeystore C:\server2017.pfx -srcstoretype pkcs12 -srcstor
epass REDACTED -srcalias 1 -destkeystore C:\.keystore -deststoretype jks -deststorepass REDACTED -destalias tomcat
Existing entry alias 1 exists, overwrite? [no]:  yes

It accepted alias 1 instead and the cert imported correctly. I love Tomcat -_-





OpenSSL – Extracting a crt and key from a pkcs12 file

Posted by & filed under Linux, Server Admin.

Quick and dirty way to pull out the key and crt from a pkcs12 file:

openssl pkcs12 -in filename.pfx -nocerts -out filename.key

openssl pkcs12 -in filename.pfx -clcerts -nokeys -out filename.crt 

If you are using this for Apache and need to strip the password out of the certificate so Apache does not ask for it each time it starts:

openssl rsa -in /path/to/originalkeywithpass.key -out /path/to/newkeywithnopass.key

PHP: Displaying errors in the browser

Posted by & filed under PHP, Programming.

I run into this from time to time, and there are a few options for getting errors to display in browser when the server configuration is preventing it. .htaccess and php.ini can both be modified to allow this to happen. I have found a simpler way is to enable them via PHP:




Apache Scalp fixed XML file

Posted by & filed under Server Admin.

Needed to audit some apache logs, installed scalp, grabbed the XML, and it promptly puked:

web@web:~/apache-scalp$ python --log /var/log/apache2/access.log
Loading XML file 'default_filter.xml'...
The rule '(?:union\s*(?:all|distinct|[(!@]*)?\s*[([]*\s*select)|(?:\w\s+like\s+\")|(?:like\s*"\%)|(?:"\s*like\W*["\d])|(?:"\s*(?:n?and|x?or|not |\|\||\&\&)\s+[\s\w]+=\s*\w+\s*having)|(?:"\s*\*\s*\w+\W+")|(?:"\s*[^?\w\s=.,;)(]+\s*[(@"]*\s*\w+\W+\w)|(?:select\s*[\[\]()\s\w\.,"-]+from)|(?:find_in_set\s*\()' cannot be compiled properly

Seems there is some issue with the regex in the XML file. I found this handy thread which outlines the fixes:… and another person posted a XML will all the fixes:

Backup of the XML is below just in case pastebin goes down: default_filter (rename to .xml)

Google’s mod_pagespeed for Apache

Posted by & filed under Server Admin, Web Development.

mod_pagespeed speeds up your site and reduces page load time. This open-source Apache HTTP server module automatically applies web performance best practices to pages, and associated assets (CSS, JavaScript, images) without requiring that you modify your existing content or workflow.


Ubuntu, Apache2 and relaying mail thru an external relay

Posted by & filed under Server Admin.

I have a fresh Ubuntu 11 server installation with the LAMP stack installed. When I sent e-mail thru PHP, the message never left the server.

I believe there is a more kosher way to do this, but this is what worked for me.
=> Modify /etc/mail/
=> Locate the lines that say:

# “Smart” relay host (may be null)

=> Edit the DS line like so:

Restart the services… good to go.

Connecting to a MySQL Database with Apache and PHP with Ubuntu.

Posted by & filed under Uncategorized.

It’s this easy:

nriley@server:/var/www$ sudo apt-get install php5-odbc freetds-dev tdsodbc php5-sybase
nriley@server:/var/www$ sudo /etc/init.d/apache2 restart
nriley@server:/var/www$ php -m
[PHP Modules] 

Configuration under Yii is simple as well. Simply add a new item under components in main.php:

'connectwiseDb' => array(
            'class'            => 'CDbConnection',
		'connectionString' => ';dbname=databasename',
            'username'         => 'user',
            'password'         => 'pass',

.htaccess and Windows — oh noes!

Posted by & filed under Server Admin.

Windows sucks. But sometimes I have to deal with an even bigger abomination — Linux software on a Windows boxen! Today I had to get a .htaccess file working, and since unix paths can get a bit tricky on windows, I figured I’d jot down the steps:

In the htaccess.conf we need to do the following:

  1. Enable mod_rewrite in the LoadModule section
  2. Set “AllowOverride All”

I was using vhosts in this instance, so I needed to add the following to the appropriate <VirtualHost> section:

	    AllowOverride All
	    Options None
	    Order deny,allow

So now the entire <VirtualHost> block looks like:

    DocumentRoot "D:/htdocs/some.server"
    ErrorLog logs/
    CustomLog logs/ common

	    AllowOverride All
	    Options None
	    Order deny,allow


Lastly, my .htaccess file is pretty much setup like normal:

AuthUserFile "d:/secure/.htpasswd"
AuthType Basic
AuthName "Restricted Area -- All access is logged and monitored." 

require valid-user

The .htpasswd file can be generated using htpasswd — Apache packages the htpasswd in the bin directory. It will likely be somewhere like: C:\Program Files\Apache Software Foundation\Apache2.2\bin

htaccess -c -b .htpasswd username password

Toss the resulting file int he path defined by AuthUserFile in the .htaccess file and you are done!

.htaccess Notes

Posted by & filed under Uncategorized.

Quick notes on configuring password auth via .htaccess:

  • Step 1: Create the directory area and set permissions to read the area
  • Step 2: Create a file called .htaccess in the directory you want to protect
    In that file: 

    AuthUserFile /your/directory/here/.htpasswd
    AuthGroupFile /dev/null
    AuthName "Secure Document"
    AuthType Basic
    require valid-user

  • Step 3: Create a file called .htpasswd in the directory as set in the AuthUserFile directive in the .htaccess file
    You create this file by typing in the information below, at the system prompt, in the directory area to be protected: 

    htpasswd -c .htpasswd username

Configuring Yii to exclude index.php in the URL

Posted by & filed under PHP, Programming.

First of all, mod_rewrite needs to be enabled, and Apache configured to allow the use of .htaccess files (AllowOverride).

Secondly .htaccess in the root of the Yii app should be as such:

Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on
RewriteBase /

# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# Or just forward to index.php
RewriteRule . index.php

As a note, RewriteBase needs to be changed if the Yii app is located in a directory other than the site’s root.

.htaccess Cheat Sheet

Posted by & filed under Uncategorized.

Here is a simple cheatsheet for the .htaccess file:

Enable Directory Browsing

Options +Indexes
## block a few types of files from showing
IndexIgnore *.wmv *.mp4 *.avi

Disable Directory Browsing

Options All -Indexes

Customize Error Messages

ErrorDocument 403 /forbidden.html
ErrorDocument 404 /notfound.html
ErrorDocument 500 /servererror.html

Get SSI working with HTML/SHTML

AddType text/html .html
AddType text/html .shtml
AddHandler server-parsed .html
AddHandler server-parsed .shtml
# AddHandler server-parsed .htm

Change Default Page (order is followed!)

DirectoryIndex myhome.htm index.htm index.php

Block Users from accessing the site

order deny,allow
deny from
deny from
deny from
allow from all

Allow only LAN users

order deny,allow
deny from all
allow from

Redirect Visitors to New Page/Directory

Redirect oldpage.html
Redirect /olddir

Block site from specific referrers

RewriteEngine on
RewriteCond %{HTTP_REFERER} site-to-block\.com [NC]
RewriteCond %{HTTP_REFERER} site-to-block-2\.com [NC]
RewriteRule .* – [F]

Block Hot Linking/Bandwidth hogging

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?*$ [NC]
RewriteRule \.(gif|jpg)$ – [F]

Want to show a “Stealing is Bad” message too?

Add this below the Hot Link Blocking code:

RewriteRule \.(gif|jpg)$ [R,L]

Stop .htaccess (or any other file) from being viewed

order allow,deny
deny from all

Avoid the 500 Error

# Avoid 500 error by passing charset
AddDefaultCharset utf-8

Grant CGI Access in a directory

Options +ExecCGI
AddHandler cgi-script cgi pl
# To enable all scripts in a directory use the following
# SetHandler cgi-script

Password Protecting Directories

Use the .htaccess Password Generator and follow the brief instructions!

Change Script Extensions

AddType application/x-httpd-php .gne

gne will now be treated as PHP files! Similarly, x-httpd-cgi for CGI files, etc.

Use MD5 Digests

Performance may take a hit but if thats not a problem, this is a nice option to turn on.

ContentDigest On

The CheckSpelling Directive

From Jens Meiert: CheckSpelling corrects simple spelling errors (for example, if someone forgets a letter or if any character is just wrong). Just add CheckSpelling On to your htaccess file.

The ContentDigest Directive

As the Apache core features documentation says: “This directive enables the generation of Content-MD5 headers as defined in RFC1864 respectively RFC2068. The Content-MD5 header provides an end-to-end message integrity check (MIC) of the entity-body. A proxy or client may check this header for detecting accidental modification of the entity-body in transit.

Note that this can cause performance problems on your server since the message digest is computed on every request (the values are not cached). Content-MD5 is only sent for documents served by the core, and not by any module. For example, SSI documents, output from CGI scripts, and byte range responses do not have this header.”

To turn this on, just add ContentDigest On.

Enable Gzip – Save Bandwidth


# Combine the below two lines – I’ve split it up for presentation
AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css
application/x-javascript application/javascript


Turn off magic_quotes_gpc

# Only if you use PHP

php_flag magic_quotes_gpc off

Set an Expires header and enable Cache-Control

ExpiresActive On
ExpiresDefault “access plus 1 seconds”
ExpiresByType text/html “access plus 7200 seconds”
ExpiresByType image/gif “access plus 518400 seconds”
ExpiresByType image/jpeg “access plus 518400 seconds”
ExpiresByType image/png “access plus 518400 seconds”
ExpiresByType text/css “access plus 518400 seconds”
ExpiresByType text/javascript “access plus 216000 seconds”
ExpiresByType application/x-javascript “access plus 216000 seconds”

# Cache specified files for 6 days

Header set Cache-Control “max-age=518400, public”

# Cache HTML files for a couple hours

Header set Cache-Control “max-age=7200, private, must-revalidate”

# Cache PDFs for a day

Header set Cache-Control “max-age=86400, public”

# Cache Javascripts for 2.5 days

Header set Cache-Control “max-age=216000, private”

Detect iPhone Clients

Posted by & filed under iPhone, PHP.


  1. <?php if (strpos($_SERVER[‘HTTP_USER_AGENT’], ‘iPhone’) !== FALSE)
  2. { header(‘Location:’); }
  3. ?>


  1. RewriteEngine on
  2. RewriteCond ${HTTP_USER_AGENT} iPhone
  3. RewriteRule .*