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

Reply via email to