Hi,
Symark Software has decided to use the openssl software in one of our
commercial products. Since this software is open source, I have decided
to contribute to it by making a GUI for the CA utility (basically CA.sh
but at a lower level). Its not bullet-proof and certainly isn't complete,
but I thought people would like to use it anyway. It would be especially useful
to beginners since it makes things easy to do. I hope you want to include
it in your distribution. Thanks for the SSL software! Support will be available
as I have time. I'll try to improve it eventually too.
NOTES: 1. This script uses expectk.
2. The openssl executable must be in your path.
3. The OPENSSL_CONF environment variable must be set properly.
---------------------------------------------------------------------------
Andy Moskoff e-mail: [EMAIL PROTECTED]
Senior Software Engineer
Symark Software
#!/bin/sh
#\
exec expectk -f "$0" ${1+"$@"}
# Copyright (c) 2000 Symark Software Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. All advertising materials mentioning features or use of this
# software must display the following acknowledgment:
# "This product includes software developed by Symark Software
# for use in the OpenSSL Toolkit. (http://www.symark.com/)"
#
# 4. Redistributions of any form whatsoever must retain the following
# acknowledgment:
# "This product includes software developed by Symark Software
# for use in the OpenSSL Toolkit (http://www.symark.com/)"
#
# THIS SOFTWARE IS PROVIDED BY SYMARK SOFTWARE ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SYMARK SOFTWARE OR
# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
# OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Procedure to create panel for new certificate requests
#
proc newreq { w m } {
global tkca_newreq
global tkca
# Set the following values then generate the request
# Country Name (2 letter code) [AU]:
# State or Province Name (full name) [Some-State]:
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:
# Email Address []:
# Remove existing window if any...
catch "destroy [winfo children $w]"
catch "destroy [winfo children $m]"
# Enable Pass Phrase Option
.main.menubar.options.menu entryconfigure 0 -state normal
set tkca(passphrase) 1
# Set defaults
set tkca(title) "Generate a Certificate Request"
set tkca_newreq(cc) US
set tkca_newreq(st) California
set tkca_newreq(ln) "Westlake Village"
set tkca_newreq(org) "Symark Software"
set tkca_newreq(ou) Engineering
set tkca_newreq(cn) Symark
set tkca_newreq(email) [EMAIL PROTECTED]
set tkca_newreq(passphrase) {}
set tkca_newreq(newreq) newreq.pem
set tkca_newreq(days) 10
# New request panel
label $w.l_cc -text "Country Code"
entry $w.e_cc -width 3 -textvariable tkca_newreq(cc)
label $w.l_st -text "State or Province Name"
entry $w.e_st -width 25 -textvariable tkca_newreq(st)
label $w.l_ln -text "Locality Name"
entry $w.e_ln -width 25 -textvariable tkca_newreq(ln)
label $w.l_org -text "Organization Name"
entry $w.e_org -width 25 -textvariable tkca_newreq(org)
label $w.l_ou -text "Organization Unit"
entry $w.e_ou -width 25 -textvariable tkca_newreq(ou)
label $w.l_cn -text "Common Name"
entry $w.e_cn -width 25 -textvariable tkca_newreq(cn)
label $w.l_email -text "Email Address"
entry $w.e_email -width 25 -textvariable tkca_newreq(email)
label $w.l_pass -text "Pass Phrase"
entry $w.e_pass -width 20 -show "#" -textvariable tkca_newreq(passphrase)
label $w.l_newreq -text "Put certificate request in"
entry $w.e_newreq -width 25 -textvariable tkca_newreq(newreq)
label $w.l_days -text "No. of days certificate valid"
entry $w.e_days -width 4 -textvariable tkca_newreq(days)
button $m.ok -text "OK" -default active -command mknewreq
pack $m.ok -pady 5
grid $w.l_cc $w.e_cc -sticky w
grid $w.l_st $w.e_st -sticky w
grid $w.l_ln $w.e_ln -sticky w
grid $w.l_org $w.e_org -sticky w
grid $w.l_ou $w.e_ou -sticky w
grid $w.l_cn $w.e_cn -sticky w
grid $w.l_email $w.e_email -sticky w
grid $w.l_pass $w.e_pass -sticky w
grid $w.l_newreq $w.e_newreq -sticky w
grid $w.l_days $w.e_days -sticky w
}
#
# Procedure to make new certificate request
#
proc mknewreq { args } {
global tkca
global tkca_newreq
# Check which command to use
if { $tkca(useCAshell) } {
spawn $tkca(openssldir)/CA.sh -newreq
expect "CA certificate filename (or enter to create)"
exp_send "\r"
} else {
# Don't use the pass phrase if specified
if { $tkca(passphrase) == 0 } {
spawn $tkca(openssldir)/openssl req -new -nodes -keyout \
$tkca_newreq(newreq) -out $tkca_newreq(newreq) \
-days $tkca_newreq(days)
} else {
spawn $tkca(openssldir)/openssl req -new -keyout \
$tkca_newreq(newreq) -out $tkca_newreq(newreq) \
-days $tkca_newreq(days)
# Supply a pass phrase
expect "Enter PEM pass phrase"
exp_send "$tkca_newreq(passphrase)\r"
expect "Verifying password - Enter PEM pass phrase"
exp_send "$tkca_newreq(passphrase)\r"
}
}
expect "Country Name"
exp_send "$tkca_newreq(cc)\r"
expect "State or Province Name"
exp_send "$tkca_newreq(st)\r"
expect "Locality Name"
exp_send "$tkca_newreq(ln)\r"
expect "Organization Name"
exp_send "$tkca_newreq(org)\r"
expect "Organizational Unit Name"
exp_send "$tkca_newreq(ou)\r"
expect "Common Name"
exp_send "$tkca_newreq(cn)\r"
expect "Email Address"
exp_send "$tkca_newreq(email)\r"
exp_send "\r"
expect "challenge password"
exp_send "\r"
expect "optional company name"
exp_send "\r"
}
#
# Procedure to create panel for new certificate authority
#
proc newca { w m } {
global tkca_newca
global tkca
# Set the following values then generate the CA
# Country Name (2 letter code) [AU]:
# State or Province Name (full name) [Some-State]:
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:
# Email Address []:
# Remove existing window if any...
catch "destroy [winfo children $w]"
catch "destroy [winfo children $m]"
# Disable Pass Phrase Option
.main.menubar.options.menu entryconfigure 0 -state disabled
set tkca(passphrase) 1
# Set defaults
set tkca(title) "Create a Certificate Authority"
set tkca_newca(cc) US
set tkca_newca(st) California
set tkca_newca(ln) "Westlake Village"
set tkca_newca(org) "Symark Software"
set tkca_newca(ou) Engineering
set tkca_newca(cn) Symark
set tkca_newca(email) [EMAIL PROTECTED]
set tkca_newca(cadir) [pwd]/demoCA
set tkca_newca(days) 180
set tkca_newca(passphrase) {}
set tkca_newca(certs) $tkca_newca(cadir)/certs
set tkca_newca(crl) $tkca_newca(cadir)/crl
set tkca_newca(newcerts) $tkca_newca(cadir)/newcerts
set tkca_newca(private) $tkca_newca(cadir)/private
set tkca_newca(serial) $tkca_newca(cadir)/serial
set tkca_newca(index) $tkca_newca(cadir)/index.txt
set tkca_newca(certfile) $tkca_newca(cadir)/cacert.pem
set tkca_newca(keyfile) $tkca_newca(cadir)/private/cakey.pem
# Panel to generate CA
label $w.l_cc -text "Country Code"
entry $w.e_cc -width 3 -textvariable tkca_newca(cc)
label $w.l_st -text "State or Province Name"
entry $w.e_st -width 25 -textvariable tkca_newca(st)
label $w.l_ln -text "Locality Name"
entry $w.e_ln -width 25 -textvariable tkca_newca(ln)
label $w.l_org -text "Organization Name"
entry $w.e_org -width 25 -textvariable tkca_newca(org)
label $w.l_ou -text "Organization Unit"
entry $w.e_ou -width 25 -textvariable tkca_newca(ou)
label $w.l_cn -text "Common Name"
entry $w.e_cn -width 25 -textvariable tkca_newca(cn)
label $w.l_email -text "Email Address"
entry $w.e_email -width 25 -textvariable tkca_newca(email)
label $w.l_pass -text "Pass Phrase"
entry $w.e_pass -width 20 -show "#" -textvariable tkca_newca(passphrase)
label $w.l_cadir -text "CA directory"
entry $w.e_cadir -width 25 -textvariable tkca_newca(cadir)
label $w.l_days -text "No. of days certificate valid"
entry $w.e_days -width 4 -textvariable tkca_newca(days)
button $m.ok -text "OK" -default active -command mknewca
pack $m.ok -pady 5
grid $w.l_cc $w.e_cc -sticky w
grid $w.l_st $w.e_st -sticky w
grid $w.l_ln $w.e_ln -sticky w
grid $w.l_org $w.e_org -sticky w
grid $w.l_ou $w.e_ou -sticky w
grid $w.l_cn $w.e_cn -sticky w
grid $w.l_email $w.e_email -sticky w
grid $w.l_pass $w.e_pass -sticky w
grid $w.l_cadir $w.e_cadir -sticky w
grid $w.l_days $w.e_days -sticky w
}
#
# Procedure to create panel to make a certificate authority
#
proc mknewca { args } {
global tkca
global tkca_newca
# Make directory hierarchy
file mkdir $tkca_newca(cadir)
file mkdir $tkca_newca(certs)
file mkdir $tkca_newca(crl)
file mkdir $tkca_newca(newcerts)
file mkdir $tkca_newca(private)
exec echo "01" > $tkca_newca(serial)
exec touch $tkca_newca(index)
# Check which command to use
if { $tkca(useCAshell) } {
spawn $tkca(openssldir)/CA.sh -newca
expect "CA certificate filename (or enter to create)"
exp_send "\r"
} else {
spawn $tkca(openssldir)/openssl req -new -x509 -keyout \
$tkca_newca(keyfile) -out $tkca_newca(certfile) \
-days $tkca_newca(days)
}
expect "Enter PEM pass phrase"
exp_send "$tkca_newca(passphrase)\r"
expect "Verifying password - Enter PEM pass phrase"
exp_send "$tkca_newca(passphrase)\r"
expect "Country Name"
exp_send "$tkca_newca(cc)\r"
expect "State or Province Name"
exp_send "$tkca_newca(st)\r"
expect "Locality Name"
exp_send "$tkca_newca(ln)\r"
expect "Organization Name"
exp_send "$tkca_newca(org)\r"
expect "Organizational Unit Name"
exp_send "$tkca_newca(ou)\r"
expect "Common Name"
exp_send "$tkca_newca(cn)\r"
expect "Email Address"
exp_send "$tkca_newca(email)\r"
exp_send "\r"
}
#
# Procedure to create panel for signing a certificate
#
proc sign { w m } {
global tkca_sign
global tkca
# Remove existing window if any...
catch "destroy [winfo children $w]"
catch "destroy [winfo children $m]"
# Set defaults
set tkca(title) "Sign a Certificate Request"
set tkca_sign(req) newreq.pem
set tkca_sign(sign) newcert.pem
# Sign certificate panel
label $w.l_req -text "Get certificate request in"
entry $w.e_req -width 25 -textvariable tkca_sign(req)
label $w.l_sign -text "Put signed certificate in"
entry $w.e_sign -width 25 -textvariable tkca_sign(sign)
label $w.l_pass -text "CA pass phrase"
entry $w.e_pass -width 20 -show "#" -textvariable tkca_sign(passphrase)
button $m.ok -text "OK" -default active -command mksign
pack $m.ok -pady 5
grid $w.l_req $w.e_req -sticky w
grid $w.l_sign $w.e_sign -sticky w
grid $w.l_pass $w.e_pass -sticky w
}
#
# Procedure to create panel for revoking a certificate
#
proc revoke { w m } {
global tkca_revoke
global tkca
# Remove existing window if any...
catch "destroy [winfo children $w]"
catch "destroy [winfo children $m]"
# Set defaults
set tkca(title) "Revoke a Certificate"
set tkca_revoke(certf) newcert.pem
set tkca_revoke(serialno) {}
set tkca_revoke(passphrase) {}
# Sign certificate panel
label $w.l_certf -text "Certificate File"
entry $w.e_certf -width 25 -textvariable tkca_revoke(certf)
#label $w.l_or -text " or "
#label $w.l_serialno -text "Serial Number"
#entry $w.e_serialno -width 20 -textvariable tkca_revoke(serialno)
label $w.l_pass -text "CA pass phrase"
entry $w.e_pass -width 20 -show "#" -textvariable tkca_revoke(passphrase)
button $m.ok -text "OK" -default active -command mkrevoke
pack $m.ok -pady 5
grid $w.l_certf $w.e_certf -sticky w
#grid $w.l_serialno $w.e_serialno -sticky w
grid $w.l_pass $w.e_pass -sticky w
}
#
# Procedure to revoke a certificate
#
proc mkrevoke { args } {
global tkca_revoke
global tkca
spawn $tkca(openssldir)/openssl ca -revoke $tkca_revoke(certf)
expect "Enter PEM pass phrase"
exp_send "$tkca_revoke(passphrase)\r"
expect "Data Base Updated"
exp_send "\r"
}
#
# Procedure to sign a certificate
#
proc mksign { args } {
global tkca
global tkca_sign
# Check which command to use
if { $tkca(useCAshell) } {
spawn $tkca(openssldir)/CA.sh -sign
} else {
spawn $tkca(openssldir)/openssl ca -policy policy_anything \
-out $tkca_sign(sign) -infiles $tkca_sign(req)
}
expect "Enter PEM pass phrase"
exp_send "$tkca_sign(passphrase)\r"
expect "Sign the certificate?"
exp_send "y\r"
expect "certificate requests certified"
exp_send "y\r"
expect "Data Base Updated"
exp_send "\r"
}
#
# Procedure to show the active CA's database (index.txt)
#
proc show_db { args } {
}
#
# Main
#
proc main { args } {
global tcl_platform
global auto_path
global tkca_newca
global tkca
lappend auto_path .
# Don't map window to screen yet
wm withdraw .
# Initialize local values
set tkca(openssldir) /usr/local/src/openssl-0.9.4/apps
set tkca(useCAshell) 0
# Create the main menu
frame .main -relief groove -borderwidth 1
pack .main -side top -fill both -expand true
# Create a menubar
frame .main.menubar -relief groove -borderwidth 1
pack .main.menubar -side top -fill x
# Create a title
label .main.title -textvariable tkca(title) -relief groove -borderwidth 1
pack .main.title -side top -fill x
# Create a form area
frame .main.form -relief groove -borderwidth 1
pack .main.form -side top -fill both -expand true
# Create button action area
frame .main.actions -relief groove -borderwidth 1
pack .main.actions -side bottom -fill x
# Create "File" pulldown
menubutton .main.menubar.file -text "File" -menu .main.menubar.file.menu -under 0
menu .main.menubar.file.menu -tearoff 0
pack .main.menubar.file -side left -fill x
# Create "Options" pulldown
menubutton .main.menubar.options -text "Options" -menu .main.menubar.options.menu
-under 0
menu .main.menubar.options.menu -tearoff 0
pack .main.menubar.options -side left -fill x
# Create "Help" pulldown
menubutton .main.menubar.help -text "Help" -menu .main.menubar.help.menu -under 0
menu .main.menubar.help.menu -tearoff 0
pack .main.menubar.help -side right -fill x
# Add items to "File" pulldown menu
.main.menubar.file.menu add command -label "New CA" -under 0 \
-command {newca .main.form .main.actions}
.main.menubar.file.menu add command -label "New Request" -under 0 \
-command {newreq .main.form .main.actions}
.main.menubar.file.menu add command -label "Sign Request" -under 0 \
-command {sign .main.form .main.actions}
.main.menubar.file.menu add command -label "Revoke Certificate" -under 0 \
-command {revoke .main.form .main.actions}
.main.menubar.file.menu add command -label "Show CA database" -under 0 \
-command {show_db}
.main.menubar.file.menu add separator
.main.menubar.file.menu add command -label "Exit" -under 0 -command {destroy .}
# Add items to "Options" pulldown menu
set tkca(passphrase) 1
.main.menubar.options.menu add checkbutton -label "Use Pass Phrase" \
-variable tkca(passphrase) -onvalue 1 -offvalue 0 -under 0
# Add items to "Help" pulldown menu
.main.menubar.help.menu add command -label "Concepts..." -under 0
.main.menubar.help.menu add command -label "Reference..." -under 6
# Map main window
wm deiconify .
raise .
focus -force .
wm geometry . 450x350+50+50
wm title . "Certificate Authority Utility"
}
main