Tuesday, January 29, 2008

Getting a Commercial Digital Certificate

I need to acquire a digital certificate to be used for encrypting files prior to uploading it to a bank's online service. Three commercial Certificate Authorities (CAs) were recommended by the bank, namely: Entrust, Thawte and Verisign.

I was given six (6) characteristics of what I should be looking for. These items cover specs like the type of MDA, encryption algo, key size, certificate export formats, etc. Couldn't I just have the SKU number?

An SKU would have been most useful. The CA websites and storefronts were basically stocked with a slew of server SSL products -- my digital certificate is buried in some obscure page somewhere. Before I entirely lost my shopping appetite, Verisign's livechat popped into peripheral view. Good thing! I was about to put this off for another day.

After a couple of minutes, I got my answer. I need a Class 1 Digital ID and the product page is tucked here. Thawte has a livechat button, too -- but after three reps and twice the wait, I was informed politely that Thawte does not sell client certificates for commercial use. Entrust has no livechat and email response is rather sluggish.

You can purchase a Verisign Digital ID online for US$19.95 per year. A 60-day trial is also available for free. International customers, though, are served by the VeriSign Trust Network of International affiliates. That's me! I pray that dealing with their local affiliate is just as breezy.

Monday, January 21, 2008

A Tcl Web Service client for KnowledgeTree Document Management System

Sometime last year, I dabbled with KnowledgeTree's web services and (somehow I've forgotten why) I ended up with a Tcl client to perform a document upload.

Before I lose this chunk of code or forget about it altogether (and it happens a lot), I decided to post it here:

package require SOAP
package require http
package require TclCurl

set prx ""
set url ""
set usr "admin"
set pas "admin"
set ipa "any"

set upf "upload-me.txt"
set typ "multipart/form-data"

proc log_it { chn msg } {
set stm [clock format [clock seconds] -format "%Y/%m/%d %H:%M:%S %a"]
puts $chn "$stm : $msg"

SOAP::create kt_login \
-proxy $prx \
-params { "username" "string" "password" "string" "ip" "string"} \
-name login
SOAP::create kt_add_document \
-proxy $prx \
-params { "session_id" "string" "folder_id" "int" "title" "string" "filename" "string" \
"documentype" "string" "tempfilename" "string" } \
-name add_document
SOAP::create kt_logout \
-proxy $prx \
-params { "session_id" "string"} \
-name logout

set log "debug.log"

if { [catch {open $log a} out] } {
puts stderr "Error: $out"
set out "stderr"

set rsp [kt_login $usr $pas $ipa]
set sta [lindex $rsp 1]
set ses [lindex $rsp 3]
log_it $out "Login: status ($sta); session ($ses)"

set opt "session_id $ses action A"
set crl [curl::init]
set rsp [$crl configure -url $url -bodyvar rsp -post 1 \
-httppost [list name "file1" file $upf contenttype $typ] \
-httppost [list name "session_id" contents $ses] \
-httppost [list name "action" contents A] \
-httppost [list name "output" contents php] \
catch { $crl perform } curlErrorNumber
if { $curlErrorNumber != 0 } {
error [curl::easystrerror $curlErrorNumber]
$crl cleanup

log_it $out "Upload: response ($rsp)"

set ps1 [string first "\"tmp_name\";s:" $rsp 0]
set ps2 [string first ":\"" $rsp [expr $ps1 + 12]]
set ps3 [string first "\";s:5:\"error\"" $rsp 0]
set tmp [string range $rsp [expr $ps2 + 2] [expr $ps3 - 1]]

# Define folder where to upload files
set fld 1;
set ttl "My Document";
set doc "Default"

set rsp [kt_add_document $ses $fld $ttl $upf $doc $tmp]
log_it $out "Add Document: response ($rsp)"

set rsp [kt_logout $ses]
log_it $out "Logout: response ($rsp)"

close $out

The upload facility is implemented by upload.php and returns a response coming out of php's serialize() function. I've mangled upload.php to return a response in xml or json format. The code changes are posted in the Knowledgetree community forum here.

The above Tcl code digests the php's serialize() output.

For xml output, here are the relevant changes:

set crl [curl::init]
set rsp [$crl configure -url $url -bodyvar xml -post 1 \
-httppost [list name "file1" file $upf contenttype $typ] \
-httppost [list name "session_id" contents $ses] \
-httppost [list name "action" contents A] \
-httppost [list name "output" contents xml] \
set top [dom parse $xml]
set sel [$top selectNodes /results/uploads/document/tmp_name/text()]
set tmp [$sel nodeValue]
$top delete

And for json..

set rsp [$crl configure -url $url -bodyvar rsp -post 1 \
-httppost [list name "file1" file $upf contenttype $typ] \
-httppost [list name "session_id" contents $ses] \
-httppost [list name "action" contents A] \
-httppost [list name "output" contents json] \
set ps1 [string first "\"tmp_name\":\"" $rsp 0]
set ps2 [string first "\",\"error\"" $rsp 0]
set tmp [string range $rsp [expr $ps1 + 12] [expr $ps2 - 1]]

Check the contents of debug.log for any errors. A successful operation produces this output: