summaryrefslogtreecommitdiff
path: root/security/nss/cmd
diff options
context:
space:
mode:
authorcvs2hg <devnull@localhost>2013-02-21 22:12:45 +0100
committercvs2hg <devnull@localhost>2013-02-21 22:12:45 +0100
commitba0cbe2c7d3c2b7640fb84c36f02aab0459c4e0b (patch)
tree916501d96e0b3a1edc1aa75f66ecf79c6abf814c /security/nss/cmd
parent52117abf63f8c4dbeb439c0dec376989845de7c6 (diff)
parentdb9894ead5167463ea02f460e3b4e66221d6d60e (diff)
downloadnss-hg-ba0cbe2c7d3c2b7640fb84c36f02aab0459c4e0b.tar.gz
artificial changeset: close fixup head 3836ae9d564a for tag Makefile
Diffstat (limited to 'security/nss/cmd')
-rw-r--r--security/nss/cmd/.cvsignore1
-rw-r--r--security/nss/cmd/Makefile182
-rw-r--r--security/nss/cmd/SSLsample/Makefile44
-rw-r--r--security/nss/cmd/SSLsample/Makefile.NSS58
-rw-r--r--security/nss/cmd/SSLsample/NSPRerrs.h133
-rw-r--r--security/nss/cmd/SSLsample/README43
-rw-r--r--security/nss/cmd/SSLsample/SECerrs.h441
-rw-r--r--security/nss/cmd/SSLsample/SSLerrs.h366
-rw-r--r--security/nss/cmd/SSLsample/client.c453
-rw-r--r--security/nss/cmd/SSLsample/client.mn50
-rwxr-xr-xsecurity/nss/cmd/SSLsample/gencerts79
-rw-r--r--security/nss/cmd/SSLsample/make.client78
-rw-r--r--security/nss/cmd/SSLsample/make.server77
-rwxr-xr-xsecurity/nss/cmd/SSLsample/nmakefile95.nss60
-rwxr-xr-xsecurity/nss/cmd/SSLsample/nmakefilent.nss59
-rw-r--r--security/nss/cmd/SSLsample/server.c822
-rw-r--r--security/nss/cmd/SSLsample/server.mn48
-rw-r--r--security/nss/cmd/SSLsample/sslerror.h110
-rw-r--r--security/nss/cmd/SSLsample/sslsample.c591
-rw-r--r--security/nss/cmd/SSLsample/sslsample.h178
-rw-r--r--security/nss/cmd/addbuiltin/Makefile76
-rw-r--r--security/nss/cmd/addbuiltin/addbuiltin.c357
-rw-r--r--security/nss/cmd/addbuiltin/manifest.mn49
-rw-r--r--security/nss/cmd/atob/Makefile76
-rw-r--r--security/nss/cmd/atob/atob.c177
-rw-r--r--security/nss/cmd/atob/makefile.win155
-rw-r--r--security/nss/cmd/atob/manifest.mn50
-rw-r--r--security/nss/cmd/bltest/Makefile82
-rw-r--r--security/nss/cmd/bltest/blapitest.c2572
-rw-r--r--security/nss/cmd/bltest/manifest.mn54
-rw-r--r--security/nss/cmd/bltest/tests/README49
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/iv01
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/key01
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/aes_cbc/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/key01
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/aes_ecb/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/des3_cbc/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/des3_cbc/iv01
-rw-r--r--security/nss/cmd/bltest/tests/des3_cbc/key01
-rw-r--r--security/nss/cmd/bltest/tests/des3_cbc/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/des3_cbc/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/des3_ecb/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/des3_ecb/key01
-rw-r--r--security/nss/cmd/bltest/tests/des3_ecb/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/des3_ecb/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/des_cbc/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/des_cbc/iv01
-rw-r--r--security/nss/cmd/bltest/tests/des_cbc/key01
-rw-r--r--security/nss/cmd/bltest/tests/des_cbc/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/des_cbc/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/des_ecb/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/des_ecb/key01
-rw-r--r--security/nss/cmd/bltest/tests/des_ecb/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/des_ecb/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/dsa/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/dsa/key06
-rw-r--r--security/nss/cmd/bltest/tests/dsa/keyseed01
-rw-r--r--security/nss/cmd/bltest/tests/dsa/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/dsa/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/dsa/pqg04
-rw-r--r--security/nss/cmd/bltest/tests/dsa/sigseed01
-rw-r--r--security/nss/cmd/bltest/tests/md2/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/md2/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/md2/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/md5/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/md5/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/md5/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_cbc/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_cbc/iv01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_cbc/key01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_cbc/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rc2_cbc/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_ecb/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_ecb/key01
-rw-r--r--security/nss/cmd/bltest/tests/rc2_ecb/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rc2_ecb/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rc4/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/rc4/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/rc4/key01
-rw-r--r--security/nss/cmd/bltest/tests/rc4/key11
-rw-r--r--security/nss/cmd/bltest/tests/rc4/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rc4/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rc4/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/rc5_cbc/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/rc5_cbc/iv01
-rw-r--r--security/nss/cmd/bltest/tests/rc5_cbc/key01
-rw-r--r--security/nss/cmd/bltest/tests/rc5_cbc/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rc5_cbc/params02
-rw-r--r--security/nss/cmd/bltest/tests/rc5_cbc/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rc5_ecb/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/rc5_ecb/key01
-rw-r--r--security/nss/cmd/bltest/tests/rc5_ecb/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rc5_ecb/params02
-rw-r--r--security/nss/cmd/bltest/tests/rc5_ecb/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/rsa/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/rsa/key04
-rw-r--r--security/nss/cmd/bltest/tests/rsa/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/rsa/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha1/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/sha1/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha1/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha256/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/sha256/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/sha256/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha256/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha256/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/sha384/ciphertext01
-rw-r--r--security/nss/cmd/bltest/tests/sha384/ciphertext11
-rw-r--r--security/nss/cmd/bltest/tests/sha384/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha384/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha384/plaintext11
-rw-r--r--security/nss/cmd/bltest/tests/sha512/ciphertext02
-rw-r--r--security/nss/cmd/bltest/tests/sha512/ciphertext12
-rw-r--r--security/nss/cmd/bltest/tests/sha512/numtests1
-rw-r--r--security/nss/cmd/bltest/tests/sha512/plaintext01
-rw-r--r--security/nss/cmd/bltest/tests/sha512/plaintext11
-rw-r--r--security/nss/cmd/btoa/Makefile75
-rw-r--r--security/nss/cmd/btoa/btoa.c196
-rw-r--r--security/nss/cmd/btoa/makefile.win130
-rw-r--r--security/nss/cmd/btoa/manifest.mn49
-rw-r--r--security/nss/cmd/certcgi/HOWTO.txt168
-rw-r--r--security/nss/cmd/certcgi/Makefile76
-rw-r--r--security/nss/cmd/certcgi/ca.html48
-rw-r--r--security/nss/cmd/certcgi/ca_form.html385
-rw-r--r--security/nss/cmd/certcgi/certcgi.c2434
-rw-r--r--security/nss/cmd/certcgi/index.html956
-rw-r--r--security/nss/cmd/certcgi/main.html105
-rw-r--r--security/nss/cmd/certcgi/manifest.mn50
-rw-r--r--security/nss/cmd/certcgi/nscp_ext_form.html113
-rw-r--r--security/nss/cmd/certcgi/stnd_ext_form.html247
-rw-r--r--security/nss/cmd/certutil/Makefile76
-rw-r--r--security/nss/cmd/certutil/certutil.c2885
-rw-r--r--security/nss/cmd/certutil/keystuff.c411
-rw-r--r--security/nss/cmd/certutil/makefile.win155
-rw-r--r--security/nss/cmd/certutil/manifest.mn52
-rw-r--r--security/nss/cmd/checkcert/Makefile76
-rw-r--r--security/nss/cmd/checkcert/checkcert.c640
-rw-r--r--security/nss/cmd/checkcert/makefile.win130
-rw-r--r--security/nss/cmd/checkcert/manifest.mn47
-rw-r--r--security/nss/cmd/cmdlib/Makefile75
-rw-r--r--security/nss/cmd/cmdlib/cmdline.c474
-rw-r--r--security/nss/cmd/cmdlib/cmdutil.h115
-rw-r--r--security/nss/cmd/cmdlib/config.mk43
-rw-r--r--security/nss/cmd/cmdlib/manifest.mn49
-rw-r--r--security/nss/cmd/crlutil/Makefile76
-rw-r--r--security/nss/cmd/crlutil/crlutil.c478
-rw-r--r--security/nss/cmd/crlutil/makefile.win130
-rw-r--r--security/nss/cmd/crlutil/manifest.mn53
-rw-r--r--security/nss/cmd/crmf-cgi/Makefile81
-rw-r--r--security/nss/cmd/crmf-cgi/config.mk44
-rw-r--r--security/nss/cmd/crmf-cgi/crmfcgi.c1124
-rw-r--r--security/nss/cmd/crmf-cgi/crmfcgi.html165
-rw-r--r--security/nss/cmd/crmf-cgi/manifest.mn61
-rw-r--r--security/nss/cmd/crmftest/Makefile99
-rw-r--r--security/nss/cmd/crmftest/config.mk43
-rw-r--r--security/nss/cmd/crmftest/manifest.mn53
-rw-r--r--security/nss/cmd/crmftest/testcrmf.c1533
-rw-r--r--security/nss/cmd/dbck/Makefile75
-rw-r--r--security/nss/cmd/dbck/dbck.c1869
-rw-r--r--security/nss/cmd/dbck/manifest.mn49
-rw-r--r--security/nss/cmd/dbtest/Makefile88
-rw-r--r--security/nss/cmd/dbtest/dbtest.c181
-rw-r--r--security/nss/cmd/dbtest/makefile.win130
-rw-r--r--security/nss/cmd/dbtest/manifest.mn50
-rw-r--r--security/nss/cmd/derdump/Makefile76
-rw-r--r--security/nss/cmd/derdump/derdump.c135
-rw-r--r--security/nss/cmd/derdump/makefile.win130
-rw-r--r--security/nss/cmd/derdump/manifest.mn49
-rw-r--r--security/nss/cmd/digest/Makefile76
-rw-r--r--security/nss/cmd/digest/digest.c254
-rw-r--r--security/nss/cmd/digest/makefile.win130
-rw-r--r--security/nss/cmd/digest/manifest.mn50
-rw-r--r--security/nss/cmd/ilock/Makefile75
-rw-r--r--security/nss/cmd/ilock/ilock.c199
-rw-r--r--security/nss/cmd/ilock/manifest.mn44
-rw-r--r--security/nss/cmd/include/secnew.h163
-rw-r--r--security/nss/cmd/keyutil/Makefile73
-rw-r--r--security/nss/cmd/keyutil/keyutil.c340
-rw-r--r--security/nss/cmd/keyutil/manifest.mn50
-rw-r--r--security/nss/cmd/lib/Makefile76
-rw-r--r--security/nss/cmd/lib/NSPRerrs.h150
-rw-r--r--security/nss/cmd/lib/SECerrs.h476
-rw-r--r--security/nss/cmd/lib/SSLerrs.h366
-rw-r--r--security/nss/cmd/lib/berparse.c404
-rw-r--r--security/nss/cmd/lib/config.mk43
-rw-r--r--security/nss/cmd/lib/derprint.c619
-rw-r--r--security/nss/cmd/lib/ffs.c48
-rw-r--r--security/nss/cmd/lib/makefile.win66
-rw-r--r--security/nss/cmd/lib/manifest.mn53
-rw-r--r--security/nss/cmd/lib/seccnames.c204
-rw-r--r--security/nss/cmd/lib/secerror.c107
-rw-r--r--security/nss/cmd/lib/secpwd.c199
-rw-r--r--security/nss/cmd/lib/secutil.c2622
-rw-r--r--security/nss/cmd/lib/secutil.h327
-rw-r--r--security/nss/cmd/makefile.inc84
-rw-r--r--security/nss/cmd/makefile.win48
-rw-r--r--security/nss/cmd/makepqg/Makefile77
-rw-r--r--security/nss/cmd/makepqg/makefile.win156
-rw-r--r--security/nss/cmd/makepqg/makepqg.c290
-rw-r--r--security/nss/cmd/makepqg/manifest.mn47
-rw-r--r--security/nss/cmd/makepqg/testit.ksh41
-rw-r--r--security/nss/cmd/manifest.mn90
-rw-r--r--security/nss/cmd/modutil/Makefile80
-rw-r--r--security/nss/cmd/modutil/README7
-rw-r--r--security/nss/cmd/modutil/config.mk77
-rw-r--r--security/nss/cmd/modutil/error.h182
-rw-r--r--security/nss/cmd/modutil/install-ds.c1541
-rw-r--r--security/nss/cmd/modutil/install-ds.h290
-rw-r--r--security/nss/cmd/modutil/install.c985
-rw-r--r--security/nss/cmd/modutil/install.h130
-rw-r--r--security/nss/cmd/modutil/installparse.c429
-rw-r--r--security/nss/cmd/modutil/installparse.h3
-rw-r--r--security/nss/cmd/modutil/installparse.l166
-rw-r--r--security/nss/cmd/modutil/installparse.y133
-rw-r--r--security/nss/cmd/modutil/instsec.c178
-rw-r--r--security/nss/cmd/modutil/lex.Pk11Install_yy.c1691
-rw-r--r--security/nss/cmd/modutil/manifest.mn62
-rw-r--r--security/nss/cmd/modutil/modutil.c999
-rw-r--r--security/nss/cmd/modutil/modutil.h67
-rw-r--r--security/nss/cmd/modutil/pk11.c919
-rw-r--r--security/nss/cmd/modutil/pk11jar.html309
-rw-r--r--security/nss/cmd/modutil/rules.mk54
-rw-r--r--security/nss/cmd/modutil/specification.html351
-rw-r--r--security/nss/cmd/ocspclnt/Makefile73
-rw-r--r--security/nss/cmd/ocspclnt/manifest.mn54
-rw-r--r--security/nss/cmd/ocspclnt/ocspclnt.c1221
-rw-r--r--security/nss/cmd/oidcalc/Makefile76
-rw-r--r--security/nss/cmd/oidcalc/manifest.mn47
-rw-r--r--security/nss/cmd/oidcalc/oidcalc.c117
-rw-r--r--security/nss/cmd/p7content/Makefile75
-rw-r--r--security/nss/cmd/p7content/manifest.mn43
-rw-r--r--security/nss/cmd/p7content/p7content.c271
-rw-r--r--security/nss/cmd/p7env/Makefile75
-rw-r--r--security/nss/cmd/p7env/manifest.mn43
-rw-r--r--security/nss/cmd/p7env/p7env.c273
-rw-r--r--security/nss/cmd/p7sign/Makefile75
-rw-r--r--security/nss/cmd/p7sign/manifest.mn43
-rw-r--r--security/nss/cmd/p7sign/p7sign.c292
-rw-r--r--security/nss/cmd/p7verify/Makefile75
-rw-r--r--security/nss/cmd/p7verify/manifest.mn43
-rw-r--r--security/nss/cmd/p7verify/p7verify.c305
-rw-r--r--security/nss/cmd/pk12util/Makefile76
-rw-r--r--security/nss/cmd/pk12util/manifest.mn51
-rw-r--r--security/nss/cmd/pk12util/pk12util.c867
-rw-r--r--security/nss/cmd/pk12util/pk12util.h69
-rw-r--r--security/nss/cmd/pkiutil/Makefile76
-rw-r--r--security/nss/cmd/pkiutil/manifest.mn47
-rw-r--r--security/nss/cmd/pkiutil/pkiutil.c373
-rw-r--r--security/nss/cmd/pkiutil/platlibs.mk53
-rw-r--r--security/nss/cmd/platlibs.mk219
-rw-r--r--security/nss/cmd/platrules.mk47
-rw-r--r--security/nss/cmd/pp/Makefile75
-rw-r--r--security/nss/cmd/pp/manifest.mn47
-rw-r--r--security/nss/cmd/pp/pp.c176
-rw-r--r--security/nss/cmd/rsaperf/Makefile84
-rw-r--r--security/nss/cmd/rsaperf/defkey.c202
-rw-r--r--security/nss/cmd/rsaperf/manifest.mn52
-rw-r--r--security/nss/cmd/rsaperf/rsaperf.c402
-rw-r--r--security/nss/cmd/samples/cert15
-rw-r--r--security/nss/cmd/samples/cert0bin0 -> 505 bytes
-rw-r--r--security/nss/cmd/samples/cert1bin0 -> 515 bytes
-rw-r--r--security/nss/cmd/samples/cert2bin0 -> 528 bytes
-rw-r--r--security/nss/cmd/samples/pkcs7.berbin0 -> 1771 bytes
-rw-r--r--security/nss/cmd/samples/pkcs7bday.berbin0 -> 1881 bytes
-rw-r--r--security/nss/cmd/samples/pkcs7cnet.berbin0 -> 3330 bytes
-rw-r--r--security/nss/cmd/samples/pkcs7news.berbin0 -> 255328 bytes
-rw-r--r--security/nss/cmd/samples/x509v3.derbin0 -> 463 bytes
-rw-r--r--security/nss/cmd/samples/x509v3.txt10
-rw-r--r--security/nss/cmd/sdrtest/Makefile73
-rw-r--r--security/nss/cmd/sdrtest/manifest.mn54
-rw-r--r--security/nss/cmd/sdrtest/sdrtest.c305
-rw-r--r--security/nss/cmd/selfserv/Makefile74
-rw-r--r--security/nss/cmd/selfserv/makefile.win136
-rw-r--r--security/nss/cmd/selfserv/manifest.mn48
-rw-r--r--security/nss/cmd/selfserv/selfserv.c1752
-rw-r--r--security/nss/cmd/shlibsign/Makefile110
-rw-r--r--security/nss/cmd/shlibsign/mangle/Makefile75
-rw-r--r--security/nss/cmd/shlibsign/mangle/mangle.c166
-rw-r--r--security/nss/cmd/shlibsign/mangle/manifest.mn52
-rw-r--r--security/nss/cmd/shlibsign/manifest.mn60
-rw-r--r--security/nss/cmd/shlibsign/shlibsign.c427
-rw-r--r--security/nss/cmd/shlibsign/sign.cmd19
-rw-r--r--security/nss/cmd/shlibsign/sign.sh51
-rw-r--r--security/nss/cmd/signtool/Makefile71
-rw-r--r--security/nss/cmd/signtool/README119
-rw-r--r--security/nss/cmd/signtool/certgen.c713
-rw-r--r--security/nss/cmd/signtool/javascript.c1790
-rw-r--r--security/nss/cmd/signtool/list.c278
-rw-r--r--security/nss/cmd/signtool/manifest.mn57
-rw-r--r--security/nss/cmd/signtool/sign.c861
-rw-r--r--security/nss/cmd/signtool/signtool.c1054
-rw-r--r--security/nss/cmd/signtool/signtool.h140
-rw-r--r--security/nss/cmd/signtool/util.c990
-rw-r--r--security/nss/cmd/signtool/verify.c382
-rw-r--r--security/nss/cmd/signtool/zip.c678
-rw-r--r--security/nss/cmd/signtool/zip.h100
-rw-r--r--security/nss/cmd/signver/Makefile71
-rwxr-xr-xsecurity/nss/cmd/signver/examples/1/form.pl50
-rw-r--r--security/nss/cmd/signver/examples/1/signedForm.html84
-rw-r--r--security/nss/cmd/signver/examples/1/signedForm.nt.html84
-rwxr-xr-xsecurity/nss/cmd/signver/examples/1/signedForm.pl88
-rw-r--r--security/nss/cmd/signver/manifest.mn54
-rw-r--r--security/nss/cmd/signver/pk7print.c922
-rw-r--r--security/nss/cmd/signver/signver.c455
-rw-r--r--security/nss/cmd/smimetools/Makefile73
-rw-r--r--security/nss/cmd/smimetools/cmsutil.c1450
-rw-r--r--security/nss/cmd/smimetools/manifest.mn45
-rw-r--r--security/nss/cmd/smimetools/rules.mk37
-rwxr-xr-xsecurity/nss/cmd/smimetools/smime576
-rw-r--r--security/nss/cmd/sslstrength/Makefile82
-rw-r--r--security/nss/cmd/sslstrength/manifest.mn50
-rw-r--r--security/nss/cmd/sslstrength/sslstr.cgi296
-rw-r--r--security/nss/cmd/sslstrength/sslstrength.c622
-rwxr-xr-xsecurity/nss/cmd/sslstrength/sslwrap181
-rw-r--r--security/nss/cmd/ssltap/Makefile79
-rw-r--r--security/nss/cmd/ssltap/config.mk52
-rw-r--r--security/nss/cmd/ssltap/manifest.mn51
-rw-r--r--security/nss/cmd/ssltap/ssltap-manual.html199
-rw-r--r--security/nss/cmd/ssltap/ssltap.c1334
-rw-r--r--security/nss/cmd/strsclnt/Makefile75
-rw-r--r--security/nss/cmd/strsclnt/manifest.mn47
-rw-r--r--security/nss/cmd/strsclnt/strsclnt.c1175
-rw-r--r--security/nss/cmd/swfort/Makefile108
-rw-r--r--security/nss/cmd/swfort/instinit/Makefile75
-rw-r--r--security/nss/cmd/swfort/instinit/instinit.c421
-rw-r--r--security/nss/cmd/swfort/instinit/manifest.mn46
-rw-r--r--security/nss/cmd/swfort/manifest.mn38
-rw-r--r--security/nss/cmd/swfort/newuser/Makefile83
-rw-r--r--security/nss/cmd/swfort/newuser/manifest.mn45
-rw-r--r--security/nss/cmd/swfort/newuser/mktst.c254
-rw-r--r--security/nss/cmd/swfort/newuser/newuser.c1133
-rw-r--r--security/nss/cmd/tests/Makefile73
-rw-r--r--security/nss/cmd/tests/manifest.mn49
-rw-r--r--security/nss/cmd/tests/remtest.c162
-rw-r--r--security/nss/cmd/tstclnt/Makefile84
-rw-r--r--security/nss/cmd/tstclnt/makefile.win130
-rw-r--r--security/nss/cmd/tstclnt/manifest.mn50
-rw-r--r--security/nss/cmd/tstclnt/tstclnt.c779
-rw-r--r--security/nss/cmd/ttformat/Makefile74
-rw-r--r--security/nss/cmd/ttformat/manifest.mn48
-rwxr-xr-xsecurity/nss/cmd/ttformat/nClient49
-rwxr-xr-xsecurity/nss/cmd/ttformat/nServ49
-rwxr-xr-xsecurity/nss/cmd/ttformat/redux.pl77
-rw-r--r--security/nss/cmd/ttformat/reduxhwm.pl33
-rw-r--r--security/nss/cmd/ttformat/ttformat.c135
-rw-r--r--security/nss/cmd/vfychain/Makefile82
-rw-r--r--security/nss/cmd/vfychain/manifest.mn51
-rw-r--r--security/nss/cmd/vfychain/vfychain.c438
-rw-r--r--security/nss/cmd/vfyserv/Makefile84
-rw-r--r--security/nss/cmd/vfyserv/makefile.win130
-rw-r--r--security/nss/cmd/vfyserv/manifest.mn51
-rw-r--r--security/nss/cmd/vfyserv/vfyserv.c458
-rw-r--r--security/nss/cmd/vfyserv/vfyserv.h182
-rw-r--r--security/nss/cmd/vfyserv/vfyutil.c714
-rw-r--r--security/nss/cmd/zlib/Makefile75
-rw-r--r--security/nss/cmd/zlib/README99
-rw-r--r--security/nss/cmd/zlib/adler32.c48
-rw-r--r--security/nss/cmd/zlib/compress.c57
-rw-r--r--security/nss/cmd/zlib/config.mk70
-rw-r--r--security/nss/cmd/zlib/crc32.c162
-rw-r--r--security/nss/cmd/zlib/deflate.c1209
-rw-r--r--security/nss/cmd/zlib/deflate.h275
-rw-r--r--security/nss/cmd/zlib/example.c503
-rw-r--r--security/nss/cmd/zlib/gzio.c537
-rw-r--r--security/nss/cmd/zlib/infblock.c406
-rw-r--r--security/nss/cmd/zlib/infblock.h37
-rw-r--r--security/nss/cmd/zlib/infcodes.c247
-rw-r--r--security/nss/cmd/zlib/infcodes.h27
-rw-r--r--security/nss/cmd/zlib/inffast.c168
-rw-r--r--security/nss/cmd/zlib/inffast.h17
-rw-r--r--security/nss/cmd/zlib/inffixed.h151
-rw-r--r--security/nss/cmd/zlib/inflate.c346
-rw-r--r--security/nss/cmd/zlib/inftrees.c479
-rw-r--r--security/nss/cmd/zlib/inftrees.h59
-rw-r--r--security/nss/cmd/zlib/infutil.c87
-rw-r--r--security/nss/cmd/zlib/infutil.h99
-rw-r--r--security/nss/cmd/zlib/makefile.win91
-rw-r--r--security/nss/cmd/zlib/maketree.c85
-rw-r--r--security/nss/cmd/zlib/manifest.mn60
-rw-r--r--security/nss/cmd/zlib/minigzip.c246
-rw-r--r--security/nss/cmd/zlib/netscape_mods.doc43
-rw-r--r--security/nss/cmd/zlib/trees.c1143
-rw-r--r--security/nss/cmd/zlib/trees.h128
-rw-r--r--security/nss/cmd/zlib/uncompr.c58
-rw-r--r--security/nss/cmd/zlib/zconf.h190
-rw-r--r--security/nss/cmd/zlib/zip16.def24
-rw-r--r--security/nss/cmd/zlib/zlib.h892
-rw-r--r--security/nss/cmd/zlib/zutil.c215
-rw-r--r--security/nss/cmd/zlib/zutil.h211
393 files changed, 81144 insertions, 0 deletions
diff --git a/security/nss/cmd/.cvsignore b/security/nss/cmd/.cvsignore
new file mode 100644
index 000000000..6329db22e
--- /dev/null
+++ b/security/nss/cmd/.cvsignore
@@ -0,0 +1 @@
+.gdbinit
diff --git a/security/nss/cmd/Makefile b/security/nss/cmd/Makefile
new file mode 100644
index 000000000..5e716b9b3
--- /dev/null
+++ b/security/nss/cmd/Makefile
@@ -0,0 +1,182 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../..
+DEPTH = ../..
+
+include manifest.mn
+include $(CORE_DEPTH)/coreconf/config.mk
+
+# These sources were once in this directory, but now are gone.
+MISSING_SOURCES = \
+ addcert.c \
+ berparse.c \
+ cert.c \
+ key.c \
+ key_rand.c \
+ keygen.c \
+ sec_fe.c \
+ sec_read.c \
+ secarb.c \
+ secutil.c \
+ $(NULL)
+
+# we don't build these any more, but the sources are still here
+OBSOLETE = \
+ berdec.c \
+ berdump.c \
+ cypher.c \
+ dumpcert.c \
+ listcerts.c \
+ mkdongle.c \
+ p12exprt.c \
+ p12imprt.c \
+ rc4.c \
+ sign.c \
+ unwrap.c \
+ vector.c \
+ verify.c \
+ wrap.c \
+ $(NULL)
+
+# the base files for the executables
+# hey -- keep these alphabetical, please
+EXEC_SRCS = \
+ $(NULL)
+
+# files that generate two separate objects and executables
+# BI_SRCS = \
+# keyutil.c \
+# p7env.c \
+# tstclnt.c \
+# $(NULL)
+
+# -I$(CORE_DEPTH)/security/lib/cert \
+# -I$(CORE_DEPTH)/security/lib/key \
+# -I$(CORE_DEPTH)/security/lib/util \
+
+INCLUDES += \
+ -I$(DIST)/../public/security \
+ -I./include \
+ $(NULL)
+
+TBD_DIRS = rsh rshd rdist ssld
+
+# For the time being, sec stuff is export only
+# US_FLAGS = -DEXPORT_VERSION -DUS_VERSION
+
+US_FLAGS = -DEXPORT_VERSION
+EXPORT_FLAGS = -DEXPORT_VERSION
+
+BASE_LIBS = \
+ $(DIST)/lib/libdbm.$(LIB_SUFFIX) \
+ $(DIST)/lib/libxp.$(LIB_SUFFIX) \
+ $(DIST)/lib/libnspr.$(LIB_SUFFIX) \
+ $(NULL)
+
+# $(DIST)/lib/libpurenspr.$(LIB_SUFFIX) \
+
+#There is a circular dependancy in security/lib, and here is a gross fix
+SEC_LIBS = \
+ $(DIST)/lib/libsecnav.$(LIB_SUFFIX) \
+ $(DIST)/lib/libssl.$(LIB_SUFFIX) \
+ $(DIST)/lib/libpkcs7.$(LIB_SUFFIX) \
+ $(DIST)/lib/libcert.$(LIB_SUFFIX) \
+ $(DIST)/lib/libkey.$(LIB_SUFFIX) \
+ $(DIST)/lib/libsecmod.$(LIB_SUFFIX) \
+ $(DIST)/lib/libcrypto.$(LIB_SUFFIX) \
+ $(DIST)/lib/libsecutil.$(LIB_SUFFIX) \
+ $(DIST)/lib/libssl.$(LIB_SUFFIX) \
+ $(DIST)/lib/libpkcs7.$(LIB_SUFFIX) \
+ $(DIST)/lib/libcert.$(LIB_SUFFIX) \
+ $(DIST)/lib/libkey.$(LIB_SUFFIX) \
+ $(DIST)/lib/libsecmod.$(LIB_SUFFIX) \
+ $(DIST)/lib/libcrypto.$(LIB_SUFFIX) \
+ $(DIST)/lib/libsecutil.$(LIB_SUFFIX) \
+ $(DIST)/lib/libhash.$(LIB_SUFFIX) \
+ $(NULL)
+
+MYLIB = lib/$(OBJDIR)/libsectool.$(LIB_SUFFIX)
+
+US_LIBS = $(MYLIB) $(SEC_LIBS) $(BASE_LIBS) $(MYLIB) $(BASE_LIBS)
+EX_LIBS = $(MYLIB) $(SEC_LIBS) $(BASE_LIBS) $(MYLIB) $(BASE_LIBS)
+
+REQUIRES = libxp nspr security
+
+CSRCS = $(EXEC_SRCS) $(BI_SRCS)
+
+OBJS = $(CSRCS:.c=.o) $(BI_SRCS:.c=-us.o) $(BI_SRCS:.c=-ex.o)
+
+PROGS = $(addprefix $(OBJDIR)/, $(EXEC_SRCS:.c=$(BIN_SUFFIX)))
+US_PROGS = $(addprefix $(OBJDIR)/, $(BI_SRCS:.c=-us$(BIN_SUFFIX)))
+EX_PROGS = $(addprefix $(OBJDIR)/, $(BI_SRCS:.c=-ex$(BIN_SUFFIX)))
+
+
+NON_DIRS = $(PROGS) $(US_PROGS) $(EX_PROGS)
+TARGETS = $(NON_DIRS)
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+
+ifneq ($(OS_TARGET),OS2)
+$(OBJDIR)/%-us.o: %.c
+ @$(MAKE_OBJDIR)
+ $(CCF) -o $@ $(US_FLAGS) -c $*.c
+
+$(OBJDIR)/%-ex.o: %.c
+ @$(MAKE_OBJDIR)
+ $(CCF) -o $@ $(EXPORT_FLAGS) -c $*.c
+
+$(OBJDIR)/%.o: %.c
+ @$(MAKE_OBJDIR)
+ $(CCF) -o $@ $(EXPORT_FLAGS) -c $*.c
+
+$(US_PROGS):$(OBJDIR)/%-us: $(OBJDIR)/%-us.o $(US_LIBS)
+ @$(MAKE_OBJDIR)
+ $(CCF) -o $@ $(OBJDIR)/$*-us.o $(LDFLAGS) $(US_LIBS) $(OS_LIBS)
+
+$(EX_PROGS):$(OBJDIR)/%-ex: $(OBJDIR)/%-ex.o $(EX_LIBS)
+ @$(MAKE_OBJDIR)
+ $(CCF) -o $@ $(OBJDIR)/$*-ex.o $(LDFLAGS) $(EX_LIBS) $(OS_LIBS)
+
+$(PROGS):$(OBJDIR)/%: $(OBJDIR)/%.o $(EX_LIBS)
+ @$(MAKE_OBJDIR)
+ $(CCF) -o $@ $@.o $(LDFLAGS) $(EX_LIBS) $(OS_LIBS)
+
+#install:: $(TARGETS)
+# $(INSTALL) $(TARGETS) $(DIST)/bin
+endif
+
+symbols::
+ @echo "TARGETS = $(TARGETS)"
diff --git a/security/nss/cmd/SSLsample/Makefile b/security/nss/cmd/SSLsample/Makefile
new file mode 100644
index 000000000..cf741f387
--- /dev/null
+++ b/security/nss/cmd/SSLsample/Makefile
@@ -0,0 +1,44 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+# do these once for each target program
+all default export libs program install release_export::
+ $(MAKE) -f make.client $@
+ $(MAKE) -f make.server $@
+
+# only do these things once for the whole directory
+depend dependclean clean clobber realclean clobber_all release_classes release_clean release_cpdistdir release_export release_jars release_md release_policy show::
+ $(MAKE) -f make.client $@
+
+
diff --git a/security/nss/cmd/SSLsample/Makefile.NSS b/security/nss/cmd/SSLsample/Makefile.NSS
new file mode 100644
index 000000000..0a3545f4f
--- /dev/null
+++ b/security/nss/cmd/SSLsample/Makefile.NSS
@@ -0,0 +1,58 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+ARCH := $(shell uname)
+
+ifeq ($(ARCH), SunOS)
+ DEFINES = -KPIC -DSVR4 -DSOLARIS -DSYSV -D__svr4 -D__svr4__ \
+ -D_REENTRANT -DSOLARIS2_5 -D_SVID_GETTOD -DXP_UNIX -UDEBUG -DNDEBUG \
+ -DXP_UNIX
+ INCPATH = -I. -I../include/dbm -I../include/nspr -I../include/security
+ LIBPATH = -L../lib
+ LIBS = -lnss -lssl -lpkcs7 -lpkcs12 -lsecmod -lcert -lkey \
+ -lcrypto -lsecutil -lhash -ldbm -lplc4 -lplds4 -lnspr4 -lsocket -lnsl
+ CFLAGS = -g
+ CC = cc
+endif # SunOS
+
+# The rules to build the sample apps appear below.
+
+server:
+ $(CC) $(CFLAGS) $@.c -o $@ $(DEFINES) $(INCPATH) $(LIBPATH) $(LIBS)
+
+client:
+ $(CC) $(CFLAGS) $@.c -o $@ $(DEFINES) $(INCPATH) $(LIBPATH) $(LIBS)
+
+clean:
+ rm -fr server client server.o client.o
+
diff --git a/security/nss/cmd/SSLsample/NSPRerrs.h b/security/nss/cmd/SSLsample/NSPRerrs.h
new file mode 100644
index 000000000..bacdef6b2
--- /dev/null
+++ b/security/nss/cmd/SSLsample/NSPRerrs.h
@@ -0,0 +1,133 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+/* General NSPR 2.0 errors */
+/* Caller must #include "prerror.h" */
+
+ER2( PR_OUT_OF_MEMORY_ERROR, "Memory allocation attempt failed." )
+ER2( PR_BAD_DESCRIPTOR_ERROR, "Invalid file descriptor." )
+ER2( PR_WOULD_BLOCK_ERROR, "The operation would have blocked." )
+ER2( PR_ACCESS_FAULT_ERROR, "Invalid memory address argument." )
+ER2( PR_INVALID_METHOD_ERROR, "Invalid function for file type." )
+ER2( PR_ILLEGAL_ACCESS_ERROR, "Invalid memory address argument." )
+ER2( PR_UNKNOWN_ERROR, "Some unknown error has occurred." )
+ER2( PR_PENDING_INTERRUPT_ERROR,"Operation interrupted by another thread." )
+ER2( PR_NOT_IMPLEMENTED_ERROR, "function not implemented." )
+ER2( PR_IO_ERROR, "I/O function error." )
+ER2( PR_IO_TIMEOUT_ERROR, "I/O operation timed out." )
+ER2( PR_IO_PENDING_ERROR, "I/O operation on busy file descriptor." )
+ER2( PR_DIRECTORY_OPEN_ERROR, "The directory could not be opened." )
+ER2( PR_INVALID_ARGUMENT_ERROR, "Invalid function argument." )
+ER2( PR_ADDRESS_NOT_AVAILABLE_ERROR, "Network address not available (in use?)." )
+ER2( PR_ADDRESS_NOT_SUPPORTED_ERROR, "Network address type not supported." )
+ER2( PR_IS_CONNECTED_ERROR, "Already connected." )
+ER2( PR_BAD_ADDRESS_ERROR, "Network address is invalid." )
+ER2( PR_ADDRESS_IN_USE_ERROR, "Local Network address is in use." )
+ER2( PR_CONNECT_REFUSED_ERROR, "Connection refused by peer." )
+ER2( PR_NETWORK_UNREACHABLE_ERROR, "Network address is presently unreachable." )
+ER2( PR_CONNECT_TIMEOUT_ERROR, "Connection attempt timed out." )
+ER2( PR_NOT_CONNECTED_ERROR, "Network file descriptor is not connected." )
+ER2( PR_LOAD_LIBRARY_ERROR, "Failure to load dynamic library." )
+ER2( PR_UNLOAD_LIBRARY_ERROR, "Failure to unload dynamic library." )
+ER2( PR_FIND_SYMBOL_ERROR,
+"Symbol not found in any of the loaded dynamic libraries." )
+ER2( PR_INSUFFICIENT_RESOURCES_ERROR, "Insufficient system resources." )
+ER2( PR_DIRECTORY_LOOKUP_ERROR,
+"A directory lookup on a network address has failed." )
+ER2( PR_TPD_RANGE_ERROR,
+"Attempt to access a TPD key that is out of range." )
+ER2( PR_PROC_DESC_TABLE_FULL_ERROR, "Process open FD table is full." )
+ER2( PR_SYS_DESC_TABLE_FULL_ERROR, "System open FD table is full." )
+ER2( PR_NOT_SOCKET_ERROR,
+"Network operation attempted on non-network file descriptor." )
+ER2( PR_NOT_TCP_SOCKET_ERROR,
+"TCP-specific function attempted on a non-TCP file descriptor." )
+ER2( PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "TCP file descriptor is already bound." )
+ER2( PR_NO_ACCESS_RIGHTS_ERROR, "Access Denied." )
+ER2( PR_OPERATION_NOT_SUPPORTED_ERROR,
+"The requested operation is not supported by the platform." )
+ER2( PR_PROTOCOL_NOT_SUPPORTED_ERROR,
+"The host operating system does not support the protocol requested." )
+ER2( PR_REMOTE_FILE_ERROR, "Access to the remote file has been severed." )
+ER2( PR_BUFFER_OVERFLOW_ERROR,
+"The value requested is too large to be stored in the data buffer provided." )
+ER2( PR_CONNECT_RESET_ERROR, "TCP connection reset by peer." )
+ER2( PR_RANGE_ERROR, "Unused." )
+ER2( PR_DEADLOCK_ERROR, "The operation would have deadlocked." )
+ER2( PR_FILE_IS_LOCKED_ERROR, "The file is already locked." )
+ER2( PR_FILE_TOO_BIG_ERROR,
+"Write would result in file larger than the system allows." )
+ER2( PR_NO_DEVICE_SPACE_ERROR, "The device for storing the file is full." )
+ER2( PR_PIPE_ERROR, "Unused." )
+ER2( PR_NO_SEEK_DEVICE_ERROR, "Unused." )
+ER2( PR_IS_DIRECTORY_ERROR,
+"Cannot perform a normal file operation on a directory." )
+ER2( PR_LOOP_ERROR, "Symbolic link loop." )
+ER2( PR_NAME_TOO_LONG_ERROR, "File name is too long." )
+ER2( PR_FILE_NOT_FOUND_ERROR, "File not found." )
+ER2( PR_NOT_DIRECTORY_ERROR,
+"Cannot perform directory operation on a normal file." )
+ER2( PR_READ_ONLY_FILESYSTEM_ERROR,
+"Cannot write to a read-only file system." )
+ER2( PR_DIRECTORY_NOT_EMPTY_ERROR,
+"Cannot delete a directory that is not empty." )
+ER2( PR_FILESYSTEM_MOUNTED_ERROR,
+"Cannot delete or rename a file object while the file system is busy." )
+ER2( PR_NOT_SAME_DEVICE_ERROR,
+"Cannot rename a file to a file system on another device." )
+ER2( PR_DIRECTORY_CORRUPTED_ERROR,
+"The directory object in the file system is corrupted." )
+ER2( PR_FILE_EXISTS_ERROR,
+"Cannot create or rename a filename that already exists." )
+ER2( PR_MAX_DIRECTORY_ENTRIES_ERROR,
+"Directory is full. No additional filenames may be added." )
+ER2( PR_INVALID_DEVICE_STATE_ERROR,
+"The required device was in an invalid state." )
+ER2( PR_DEVICE_IS_LOCKED_ERROR, "The device is locked." )
+ER2( PR_NO_MORE_FILES_ERROR, "No more entries in the directory." )
+ER2( PR_END_OF_FILE_ERROR, "Encountered end of file." )
+ER2( PR_FILE_SEEK_ERROR, "Seek error." )
+ER2( PR_FILE_IS_BUSY_ERROR, "The file is busy." )
+ER2( PR_IN_PROGRESS_ERROR,
+"Operation is still in progress (probably a non-blocking connect)." )
+ER2( PR_ALREADY_INITIATED_ERROR,
+"Operation has already been initiated (probably a non-blocking connect)." )
+
+#ifdef PR_GROUP_EMPTY_ERROR
+ER2( PR_GROUP_EMPTY_ERROR, "The wait group is empty." )
+#endif
+
+#ifdef PR_INVALID_STATE_ERROR
+ER2( PR_INVALID_STATE_ERROR, "Object state improper for request." )
+#endif
+
+ER2( PR_MAX_ERROR, "Placeholder for the end of the list" )
diff --git a/security/nss/cmd/SSLsample/README b/security/nss/cmd/SSLsample/README
new file mode 100644
index 000000000..2c4c09110
--- /dev/null
+++ b/security/nss/cmd/SSLsample/README
@@ -0,0 +1,43 @@
+These sample programs can be built in either of two ways:
+1) is the NSS source tree, using the coreconf build system, and
+2) stand alone (as part of the NSS distribution).
+
+The following makefiles are used only when building in the NSS source tree
+using coreconf. These are NOT part of the distribution.
+
+Makefile
+client.mn
+server.mn
+config.mk
+make.client
+make.server
+
+The following makefiles are used only when building in the NSS distribution.
+These files are part of the distribution.
+
+Makefile.NSS
+nmakefile95.nss
+nmakefilent.nss
+
+
+The following source files are common to both build environments and are
+part of the distribution.
+
+NSPRerrs.h
+SECerrs.h
+SSLerrs.h
+client.c
+getopt.c
+server.c
+sslerror.h
+
+In the NSS 2.0 distribution, the sample code and makefiles are in a
+directory named "samples". The directories relevant to building
+in the distributed tree are:
+
+./samples
+./include/dbm
+./include/nspr
+./include/security
+./lib
+
diff --git a/security/nss/cmd/SSLsample/SECerrs.h b/security/nss/cmd/SSLsample/SECerrs.h
new file mode 100644
index 000000000..2059df6a2
--- /dev/null
+++ b/security/nss/cmd/SSLsample/SECerrs.h
@@ -0,0 +1,441 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/* General security error codes */
+/* Caller must #include "secerr.h" */
+
+ER3(SEC_ERROR_IO, SEC_ERROR_BASE + 0,
+"An I/O error occurred during security authorization.")
+
+ER3(SEC_ERROR_LIBRARY_FAILURE, SEC_ERROR_BASE + 1,
+"security library failure.")
+
+ER3(SEC_ERROR_BAD_DATA, SEC_ERROR_BASE + 2,
+"security library: received bad data.")
+
+ER3(SEC_ERROR_OUTPUT_LEN, SEC_ERROR_BASE + 3,
+"security library: output length error.")
+
+ER3(SEC_ERROR_INPUT_LEN, SEC_ERROR_BASE + 4,
+"security library has experienced an input length error.")
+
+ER3(SEC_ERROR_INVALID_ARGS, SEC_ERROR_BASE + 5,
+"security library: invalid arguments.")
+
+ER3(SEC_ERROR_INVALID_ALGORITHM, SEC_ERROR_BASE + 6,
+"security library: invalid algorithm.")
+
+ER3(SEC_ERROR_INVALID_AVA, SEC_ERROR_BASE + 7,
+"security library: invalid AVA.")
+
+ER3(SEC_ERROR_INVALID_TIME, SEC_ERROR_BASE + 8,
+"Improperly formatted time string.")
+
+ER3(SEC_ERROR_BAD_DER, SEC_ERROR_BASE + 9,
+"security library: improperly formatted DER-encoded message.")
+
+ER3(SEC_ERROR_BAD_SIGNATURE, SEC_ERROR_BASE + 10,
+"Peer's certificate has an invalid signature.")
+
+ER3(SEC_ERROR_EXPIRED_CERTIFICATE, SEC_ERROR_BASE + 11,
+"Peer's Certificate has expired.")
+
+ER3(SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_BASE + 12,
+"Peer's Certificate has been revoked.")
+
+ER3(SEC_ERROR_UNKNOWN_ISSUER, SEC_ERROR_BASE + 13,
+"Peer's Certificate issuer is not recognized.")
+
+ER3(SEC_ERROR_BAD_KEY, SEC_ERROR_BASE + 14,
+"Peer's public key is invalid.")
+
+ER3(SEC_ERROR_BAD_PASSWORD, SEC_ERROR_BASE + 15,
+"The security password entered is incorrect.")
+
+ER3(SEC_ERROR_RETRY_PASSWORD, SEC_ERROR_BASE + 16,
+"New password entered incorrectly. Please try again.")
+
+ER3(SEC_ERROR_NO_NODELOCK, SEC_ERROR_BASE + 17,
+"security library: no nodelock.")
+
+ER3(SEC_ERROR_BAD_DATABASE, SEC_ERROR_BASE + 18,
+"security library: bad database.")
+
+ER3(SEC_ERROR_NO_MEMORY, SEC_ERROR_BASE + 19,
+"security library: memory allocation failure.")
+
+ER3(SEC_ERROR_UNTRUSTED_ISSUER, SEC_ERROR_BASE + 20,
+"Peer's certificate issuer has been marked as not trusted by the user.")
+
+ER3(SEC_ERROR_UNTRUSTED_CERT, SEC_ERROR_BASE + 21,
+"Peer's certificate has been marked as not trusted by the user.")
+
+ER3(SEC_ERROR_DUPLICATE_CERT, (SEC_ERROR_BASE + 22),
+"Certificate already exists in your database.")
+
+ER3(SEC_ERROR_DUPLICATE_CERT_NAME, (SEC_ERROR_BASE + 23),
+"Downloaded certificate's name duplicates one already in your database.")
+
+ER3(SEC_ERROR_ADDING_CERT, (SEC_ERROR_BASE + 24),
+"Error adding certificate to database.")
+
+ER3(SEC_ERROR_FILING_KEY, (SEC_ERROR_BASE + 25),
+"Error refiling the key for this certificate.")
+
+ER3(SEC_ERROR_NO_KEY, (SEC_ERROR_BASE + 26),
+"The private key for this certificate cannot be found in key database")
+
+ER3(SEC_ERROR_CERT_VALID, (SEC_ERROR_BASE + 27),
+"This certificate is valid.")
+
+ER3(SEC_ERROR_CERT_NOT_VALID, (SEC_ERROR_BASE + 28),
+"This certificate is not valid.")
+
+ER3(SEC_ERROR_CERT_NO_RESPONSE, (SEC_ERROR_BASE + 29),
+"Cert Library: No Response")
+
+ER3(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, (SEC_ERROR_BASE + 30),
+"The certificate issuer's certificate has expired. Check your system date and time.")
+
+ER3(SEC_ERROR_CRL_EXPIRED, (SEC_ERROR_BASE + 31),
+"The CRL for the certificate's issuer has expired. Update it or check your system data and time.")
+
+ER3(SEC_ERROR_CRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 32),
+"The CRL for the certificate's issuer has an invalid signature.")
+
+ER3(SEC_ERROR_CRL_INVALID, (SEC_ERROR_BASE + 33),
+"New CRL has an invalid format.")
+
+ER3(SEC_ERROR_EXTENSION_VALUE_INVALID, (SEC_ERROR_BASE + 34),
+"Certificate extension value is invalid.")
+
+ER3(SEC_ERROR_EXTENSION_NOT_FOUND, (SEC_ERROR_BASE + 35),
+"Certificate extension not found.")
+
+ER3(SEC_ERROR_CA_CERT_INVALID, (SEC_ERROR_BASE + 36),
+"Issuer certificate is invalid.")
+
+ER3(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, (SEC_ERROR_BASE + 37),
+"Certificate path length constraint is invalid.")
+
+ER3(SEC_ERROR_CERT_USAGES_INVALID, (SEC_ERROR_BASE + 38),
+"Certificate usages field is invalid.")
+
+ER3(SEC_INTERNAL_ONLY, (SEC_ERROR_BASE + 39),
+"**Internal ONLY module**")
+
+ER3(SEC_ERROR_INVALID_KEY, (SEC_ERROR_BASE + 40),
+"The key does not support the requested operation.")
+
+ER3(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 41),
+"Certificate contains unknown critical extension.")
+
+ER3(SEC_ERROR_OLD_CRL, (SEC_ERROR_BASE + 42),
+"New CRL is not later than the current one.")
+
+ER3(SEC_ERROR_NO_EMAIL_CERT, (SEC_ERROR_BASE + 43),
+"Not encrypted or signed: you do not yet have an email certificate.")
+
+ER3(SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, (SEC_ERROR_BASE + 44),
+"Not encrypted: you do not have certificates for each of the recipients.")
+
+ER3(SEC_ERROR_NOT_A_RECIPIENT, (SEC_ERROR_BASE + 45),
+"Cannot decrypt: you are not a recipient, or matching certificate and \
+private key not found.")
+
+ER3(SEC_ERROR_PKCS7_KEYALG_MISMATCH, (SEC_ERROR_BASE + 46),
+"Cannot decrypt: key encryption algorithm does not match your certificate.")
+
+ER3(SEC_ERROR_PKCS7_BAD_SIGNATURE, (SEC_ERROR_BASE + 47),
+"Signature verification failed: no signer found, too many signers found, \
+or improper or corrupted data.")
+
+ER3(SEC_ERROR_UNSUPPORTED_KEYALG, (SEC_ERROR_BASE + 48),
+"Unsupported or unknown key algorithm.")
+
+ER3(SEC_ERROR_DECRYPTION_DISALLOWED, (SEC_ERROR_BASE + 49),
+"Cannot decrypt: encrypted using a disallowed algorithm or key size.")
+
+
+/* Fortezza Alerts */
+ER3(XP_SEC_FORTEZZA_BAD_CARD, (SEC_ERROR_BASE + 50),
+"Fortezza card has not been properly initialized. \
+Please remove it and return it to your issuer.")
+
+ER3(XP_SEC_FORTEZZA_NO_CARD, (SEC_ERROR_BASE + 51),
+"No Fortezza cards Found")
+
+ER3(XP_SEC_FORTEZZA_NONE_SELECTED, (SEC_ERROR_BASE + 52),
+"No Fortezza card selected")
+
+ER3(XP_SEC_FORTEZZA_MORE_INFO, (SEC_ERROR_BASE + 53),
+"Please select a personality to get more info on")
+
+ER3(XP_SEC_FORTEZZA_PERSON_NOT_FOUND, (SEC_ERROR_BASE + 54),
+"Personality not found")
+
+ER3(XP_SEC_FORTEZZA_NO_MORE_INFO, (SEC_ERROR_BASE + 55),
+"No more information on that Personality")
+
+ER3(XP_SEC_FORTEZZA_BAD_PIN, (SEC_ERROR_BASE + 56),
+"Invalid Pin")
+
+ER3(XP_SEC_FORTEZZA_PERSON_ERROR, (SEC_ERROR_BASE + 57),
+"Couldn't initialize Fortezza personalities.")
+/* end fortezza alerts. */
+
+ER3(SEC_ERROR_NO_KRL, (SEC_ERROR_BASE + 58),
+"No KRL for this site's certificate has been found.")
+
+ER3(SEC_ERROR_KRL_EXPIRED, (SEC_ERROR_BASE + 59),
+"The KRL for this site's certificate has expired.")
+
+ER3(SEC_ERROR_KRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 60),
+"The KRL for this site's certificate has an invalid signature.")
+
+ER3(SEC_ERROR_REVOKED_KEY, (SEC_ERROR_BASE + 61),
+"The key for this site's certificate has been revoked.")
+
+ER3(SEC_ERROR_KRL_INVALID, (SEC_ERROR_BASE + 62),
+"New KRL has an invalid format.")
+
+ER3(SEC_ERROR_NEED_RANDOM, (SEC_ERROR_BASE + 63),
+"security library: need random data.")
+
+ER3(SEC_ERROR_NO_MODULE, (SEC_ERROR_BASE + 64),
+"security library: no security module can perform the requested operation.")
+
+ER3(SEC_ERROR_NO_TOKEN, (SEC_ERROR_BASE + 65),
+"The security card or token does not exist, needs to be initialized, or has been removed.")
+
+ER3(SEC_ERROR_READ_ONLY, (SEC_ERROR_BASE + 66),
+"security library: read-only database.")
+
+ER3(SEC_ERROR_NO_SLOT_SELECTED, (SEC_ERROR_BASE + 67),
+"No slot or token was selected.")
+
+ER3(SEC_ERROR_CERT_NICKNAME_COLLISION, (SEC_ERROR_BASE + 68),
+"A certificate with the same nickname already exists.")
+
+ER3(SEC_ERROR_KEY_NICKNAME_COLLISION, (SEC_ERROR_BASE + 69),
+"A key with the same nickname already exists.")
+
+ER3(SEC_ERROR_SAFE_NOT_CREATED, (SEC_ERROR_BASE + 70),
+"error while creating safe object")
+
+ER3(SEC_ERROR_BAGGAGE_NOT_CREATED, (SEC_ERROR_BASE + 71),
+"error while creating baggage object")
+
+ER3(XP_JAVA_REMOVE_PRINCIPAL_ERROR, (SEC_ERROR_BASE + 72),
+"Couldn't remove the principal")
+
+ER3(XP_JAVA_DELETE_PRIVILEGE_ERROR, (SEC_ERROR_BASE + 73),
+"Couldn't delete the privilege")
+
+ER3(XP_JAVA_CERT_NOT_EXISTS_ERROR, (SEC_ERROR_BASE + 74),
+"This principal doesn't have a certificate")
+
+ER3(SEC_ERROR_BAD_EXPORT_ALGORITHM, (SEC_ERROR_BASE + 75),
+"Required algorithm is not allowed.")
+
+ER3(SEC_ERROR_EXPORTING_CERTIFICATES, (SEC_ERROR_BASE + 76),
+"Error attempting to export certificates.")
+
+ER3(SEC_ERROR_IMPORTING_CERTIFICATES, (SEC_ERROR_BASE + 77),
+"Error attempting to import certificates.")
+
+ER3(SEC_ERROR_PKCS12_DECODING_PFX, (SEC_ERROR_BASE + 78),
+"Unable to import. Decoding error. File not valid.")
+
+ER3(SEC_ERROR_PKCS12_INVALID_MAC, (SEC_ERROR_BASE + 79),
+"Unable to import. Invalid MAC. Incorrect password or corrupt file.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, (SEC_ERROR_BASE + 80),
+"Unable to import. MAC algorithm not supported.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE,(SEC_ERROR_BASE + 81),
+"Unable to import. Only password integrity and privacy modes supported.")
+
+ER3(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, (SEC_ERROR_BASE + 82),
+"Unable to import. File structure is corrupt.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, (SEC_ERROR_BASE + 83),
+"Unable to import. Encryption algorithm not supported.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, (SEC_ERROR_BASE + 84),
+"Unable to import. File version not supported.")
+
+ER3(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT,(SEC_ERROR_BASE + 85),
+"Unable to import. Incorrect privacy password.")
+
+ER3(SEC_ERROR_PKCS12_CERT_COLLISION, (SEC_ERROR_BASE + 86),
+"Unable to import. Same nickname already exists in database.")
+
+ER3(SEC_ERROR_USER_CANCELLED, (SEC_ERROR_BASE + 87),
+"The user pressed cancel.")
+
+ER3(SEC_ERROR_PKCS12_DUPLICATE_DATA, (SEC_ERROR_BASE + 88),
+"Not imported, already in database.")
+
+ER3(SEC_ERROR_MESSAGE_SEND_ABORTED, (SEC_ERROR_BASE + 89),
+"Message not sent.")
+
+ER3(SEC_ERROR_INADEQUATE_KEY_USAGE, (SEC_ERROR_BASE + 90),
+"Certificate key usage inadequate for attempted operation.")
+
+ER3(SEC_ERROR_INADEQUATE_CERT_TYPE, (SEC_ERROR_BASE + 91),
+"Certificate type not approved for application.")
+
+ER3(SEC_ERROR_CERT_ADDR_MISMATCH, (SEC_ERROR_BASE + 92),
+"Address in signing certificate does not match address in message headers.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, (SEC_ERROR_BASE + 93),
+"Unable to import. Error attempting to import private key.")
+
+ER3(SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, (SEC_ERROR_BASE + 94),
+"Unable to import. Error attempting to import certificate chain.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, (SEC_ERROR_BASE + 95),
+"Unable to export. Unable to locate certificate or key by nickname.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, (SEC_ERROR_BASE + 96),
+"Unable to export. Private Key could not be located and exported.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_WRITE, (SEC_ERROR_BASE + 97),
+"Unable to export. Unable to write the export file.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_READ, (SEC_ERROR_BASE + 98),
+"Unable to import. Unable to read the import file.")
+
+ER3(SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, (SEC_ERROR_BASE + 99),
+"Unable to export. Key database corrupt or deleted.")
+
+ER3(SEC_ERROR_KEYGEN_FAIL, (SEC_ERROR_BASE + 100),
+"Unable to generate public/private key pair.")
+
+ER3(SEC_ERROR_INVALID_PASSWORD, (SEC_ERROR_BASE + 101),
+"Password entered is invalid. Please pick a different one.")
+
+ER3(SEC_ERROR_RETRY_OLD_PASSWORD, (SEC_ERROR_BASE + 102),
+"Old password entered incorrectly. Please try again.")
+
+ER3(SEC_ERROR_BAD_NICKNAME, (SEC_ERROR_BASE + 103),
+"Certificate nickname already in use.")
+
+ER3(SEC_ERROR_NOT_FORTEZZA_ISSUER, (SEC_ERROR_BASE + 104),
+"Peer FORTEZZA chain has a non-FORTEZZA Certificate.")
+
+/* ER3(SEC_ERROR_UNKNOWN, (SEC_ERROR_BASE + 105), */
+
+ER3(SEC_ERROR_JS_INVALID_MODULE_NAME, (SEC_ERROR_BASE + 106),
+"Invalid module name.")
+
+ER3(SEC_ERROR_JS_INVALID_DLL, (SEC_ERROR_BASE + 107),
+"Invalid module path/filename")
+
+ER3(SEC_ERROR_JS_ADD_MOD_FAILURE, (SEC_ERROR_BASE + 108),
+"Unable to add module")
+
+ER3(SEC_ERROR_JS_DEL_MOD_FAILURE, (SEC_ERROR_BASE + 109),
+"Unable to delete module")
+
+ER3(SEC_ERROR_OLD_KRL, (SEC_ERROR_BASE + 110),
+"New KRL is not later than the current one.")
+
+ER3(SEC_ERROR_CKL_CONFLICT, (SEC_ERROR_BASE + 111),
+"New CKL has different issuer than current CKL. Delete current CKL.")
+
+ER3(SEC_ERROR_CERT_NOT_IN_NAME_SPACE, (SEC_ERROR_BASE + 112),
+"The Certifying Authority for this certificate is not permitted to issue a \
+certificate with this name.")
+
+ER3(SEC_ERROR_KRL_NOT_YET_VALID, (SEC_ERROR_BASE + 113),
+"The key revocation list for this certificate is not yet valid.")
+
+ER3(SEC_ERROR_CRL_NOT_YET_VALID, (SEC_ERROR_BASE + 114),
+"The certificate revocation list for this certificate is not yet valid.")
+
+ER3(SEC_ERROR_UNKNOWN_CERT, (SEC_ERROR_BASE + 115),
+"The requested certificate could not be found.")
+
+ER3(SEC_ERROR_UNKNOWN_SIGNER, (SEC_ERROR_BASE + 116),
+"The signer's certificate could not be found.")
+
+ER3(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, (SEC_ERROR_BASE + 117),
+"The location for the certificate status server has invalid format.")
+
+ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, (SEC_ERROR_BASE + 118),
+"The OCSP response cannot be fully decoded; it is of an unknown type.")
+
+ER3(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, (SEC_ERROR_BASE + 119),
+"The OCSP server returned unexpected/invalid HTTP data.")
+
+ER3(SEC_ERROR_OCSP_MALFORMED_REQUEST, (SEC_ERROR_BASE + 120),
+"The OCSP server found the request to be corrupted or improperly formed.")
+
+ER3(SEC_ERROR_OCSP_SERVER_ERROR, (SEC_ERROR_BASE + 121),
+"The OCSP server experienced an internal error.")
+
+ER3(SEC_ERROR_OCSP_TRY_SERVER_LATER, (SEC_ERROR_BASE + 122),
+"The OCSP server suggests trying again later.")
+
+ER3(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, (SEC_ERROR_BASE + 123),
+"The OCSP server requires a signature on this request.")
+
+ER3(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, (SEC_ERROR_BASE + 124),
+"The OCSP server has refused this request as unauthorized.")
+
+ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, (SEC_ERROR_BASE + 125),
+"The OCSP server returned an unrecognizable status.")
+
+ER3(SEC_ERROR_OCSP_UNKNOWN_CERT, (SEC_ERROR_BASE + 126),
+"The OCSP server has no status for the certificate.")
+
+ER3(SEC_ERROR_OCSP_NOT_ENABLED, (SEC_ERROR_BASE + 127),
+"You must enable OCSP before performing this operation.")
+
+ER3(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, (SEC_ERROR_BASE + 128),
+"You must set the OCSP default responder before performing this operation.")
+
+ER3(SEC_ERROR_OCSP_MALFORMED_RESPONSE, (SEC_ERROR_BASE + 129),
+"The response from the OCSP server was corrupted or improperly formed.")
+
+ER3(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, (SEC_ERROR_BASE + 130),
+"The signer of the OCSP response is not authorized to give status for \
+this certificate.")
+
+ER3(SEC_ERROR_OCSP_FUTURE_RESPONSE, (SEC_ERROR_BASE + 131),
+"The OCSP response is not yet valid (contains a date in the future).")
+
+ER3(SEC_ERROR_OCSP_OLD_RESPONSE, (SEC_ERROR_BASE + 132),
+"The OCSP response contains out-of-date information.")
diff --git a/security/nss/cmd/SSLsample/SSLerrs.h b/security/nss/cmd/SSLsample/SSLerrs.h
new file mode 100644
index 000000000..06803b849
--- /dev/null
+++ b/security/nss/cmd/SSLsample/SSLerrs.h
@@ -0,0 +1,366 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/* SSL-specific security error codes */
+/* caller must include "sslerr.h" */
+
+ER3(SSL_ERROR_EXPORT_ONLY_SERVER, SSL_ERROR_BASE + 0,
+"Unable to communicate securely. Peer does not support high-grade encryption.")
+
+ER3(SSL_ERROR_US_ONLY_SERVER, SSL_ERROR_BASE + 1,
+"Unable to communicate securely. Peer requires high-grade encryption which is not supported.")
+
+ER3(SSL_ERROR_NO_CYPHER_OVERLAP, SSL_ERROR_BASE + 2,
+"Cannot communicate securely with peer: no common encryption algorithm(s).")
+
+ER3(SSL_ERROR_NO_CERTIFICATE, SSL_ERROR_BASE + 3,
+"Unable to find the certificate or key necessary for authentication.")
+
+ER3(SSL_ERROR_BAD_CERTIFICATE, SSL_ERROR_BASE + 4,
+"Unable to communicate securely with peer: peers's certificate was rejected.")
+
+/* unused (SSL_ERROR_BASE + 5),*/
+
+ER3(SSL_ERROR_BAD_CLIENT, SSL_ERROR_BASE + 6,
+"The server has encountered bad data from the client.")
+
+ER3(SSL_ERROR_BAD_SERVER, SSL_ERROR_BASE + 7,
+"The client has encountered bad data from the server.")
+
+ER3(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE, SSL_ERROR_BASE + 8,
+"Unsupported certificate type.")
+
+ER3(SSL_ERROR_UNSUPPORTED_VERSION, SSL_ERROR_BASE + 9,
+"Peer using unsupported version of security protocol.")
+
+/* unused (SSL_ERROR_BASE + 10),*/
+
+ER3(SSL_ERROR_WRONG_CERTIFICATE, SSL_ERROR_BASE + 11,
+"Client authentication failed: private key in key database does not match public key in certificate database.")
+
+ER3(SSL_ERROR_BAD_CERT_DOMAIN, SSL_ERROR_BASE + 12,
+"Unable to communicate securely with peer: requested domain name does not match the server's certificate.")
+
+/* SSL_ERROR_POST_WARNING (SSL_ERROR_BASE + 13),
+ defined in sslerr.h
+*/
+
+ER3(SSL_ERROR_SSL2_DISABLED, (SSL_ERROR_BASE + 14),
+"Peer only supports SSL version 2, which is locally disabled.")
+
+
+ER3(SSL_ERROR_BAD_MAC_READ, (SSL_ERROR_BASE + 15),
+"SSL received a record with an incorrect Message Authentication Code.")
+
+ER3(SSL_ERROR_BAD_MAC_ALERT, (SSL_ERROR_BASE + 16),
+"SSL peer reports incorrect Message Authentication Code.")
+
+ER3(SSL_ERROR_BAD_CERT_ALERT, (SSL_ERROR_BASE + 17),
+"SSL peer cannot verify your certificate.")
+
+ER3(SSL_ERROR_REVOKED_CERT_ALERT, (SSL_ERROR_BASE + 18),
+"SSL peer rejected your certificate as revoked.")
+
+ER3(SSL_ERROR_EXPIRED_CERT_ALERT, (SSL_ERROR_BASE + 19),
+"SSL peer rejected your certificate as expired.")
+
+ER3(SSL_ERROR_SSL_DISABLED, (SSL_ERROR_BASE + 20),
+"Cannot connect: SSL is disabled.")
+
+ER3(SSL_ERROR_FORTEZZA_PQG, (SSL_ERROR_BASE + 21),
+"Cannot connect: SSL peer is in another FORTEZZA domain.")
+
+
+ER3(SSL_ERROR_UNKNOWN_CIPHER_SUITE , (SSL_ERROR_BASE + 22),
+"An unknown SSL cipher suite has been requested.")
+
+ER3(SSL_ERROR_NO_CIPHERS_SUPPORTED , (SSL_ERROR_BASE + 23),
+"No cipher suites are present and enabled in this program.")
+
+ER3(SSL_ERROR_BAD_BLOCK_PADDING , (SSL_ERROR_BASE + 24),
+"SSL received a record with bad block padding.")
+
+ER3(SSL_ERROR_RX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 25),
+"SSL received a record that exceeded the maximum permissible length.")
+
+ER3(SSL_ERROR_TX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 26),
+"SSL attempted to send a record that exceeded the maximum permissible length.")
+
+/*
+ * Received a malformed (too long or short or invalid content) SSL handshake.
+ */
+ER3(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST , (SSL_ERROR_BASE + 27),
+"SSL received a malformed Hello Request handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO , (SSL_ERROR_BASE + 28),
+"SSL received a malformed Client Hello handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_SERVER_HELLO , (SSL_ERROR_BASE + 29),
+"SSL received a malformed Server Hello handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CERTIFICATE , (SSL_ERROR_BASE + 30),
+"SSL received a malformed Certificate handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 31),
+"SSL received a malformed Server Key Exchange handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CERT_REQUEST , (SSL_ERROR_BASE + 32),
+"SSL received a malformed Certificate Request handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_HELLO_DONE , (SSL_ERROR_BASE + 33),
+"SSL received a malformed Server Hello Done handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CERT_VERIFY , (SSL_ERROR_BASE + 34),
+"SSL received a malformed Certificate Verify handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 35),
+"SSL received a malformed Client Key Exchange handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_FINISHED , (SSL_ERROR_BASE + 36),
+"SSL received a malformed Finished handshake message.")
+
+/*
+ * Received a malformed (too long or short) SSL record.
+ */
+ER3(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER , (SSL_ERROR_BASE + 37),
+"SSL received a malformed Change Cipher Spec record.")
+
+ER3(SSL_ERROR_RX_MALFORMED_ALERT , (SSL_ERROR_BASE + 38),
+"SSL received a malformed Alert record.")
+
+ER3(SSL_ERROR_RX_MALFORMED_HANDSHAKE , (SSL_ERROR_BASE + 39),
+"SSL received a malformed Handshake record.")
+
+ER3(SSL_ERROR_RX_MALFORMED_APPLICATION_DATA , (SSL_ERROR_BASE + 40),
+"SSL received a malformed Application Data record.")
+
+/*
+ * Received an SSL handshake that was inappropriate for the state we're in.
+ * E.g. Server received message from server, or wrong state in state machine.
+ */
+ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST , (SSL_ERROR_BASE + 41),
+"SSL received an unexpected Hello Request handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO , (SSL_ERROR_BASE + 42),
+"SSL received an unexpected Client Hello handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO , (SSL_ERROR_BASE + 43),
+"SSL received an unexpected Server Hello handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CERTIFICATE , (SSL_ERROR_BASE + 44),
+"SSL received an unexpected Certificate handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 45),
+"SSL received an unexpected Server Key Exchange handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST , (SSL_ERROR_BASE + 46),
+"SSL received an unexpected Certificate Request handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE , (SSL_ERROR_BASE + 47),
+"SSL received an unexpected Server Hello Done handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY , (SSL_ERROR_BASE + 48),
+"SSL received an unexpected Certificate Verify handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 49),
+"SSL received an unexpected Cllient Key Exchange handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_FINISHED , (SSL_ERROR_BASE + 50),
+"SSL received an unexpected Finished handshake message.")
+
+/*
+ * Received an SSL record that was inappropriate for the state we're in.
+ */
+ER3(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER , (SSL_ERROR_BASE + 51),
+"SSL received an unexpected Change Cipher Spec record.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 52),
+"SSL received an unexpected Alert record.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE , (SSL_ERROR_BASE + 53),
+"SSL received an unexpected Handshake record.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA, (SSL_ERROR_BASE + 54),
+"SSL received an unexpected Application Data record.")
+
+/*
+ * Received record/message with unknown discriminant.
+ */
+ER3(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE , (SSL_ERROR_BASE + 55),
+"SSL received a record with an unknown content type.")
+
+ER3(SSL_ERROR_RX_UNKNOWN_HANDSHAKE , (SSL_ERROR_BASE + 56),
+"SSL received a handshake message with an unknown message type.")
+
+ER3(SSL_ERROR_RX_UNKNOWN_ALERT , (SSL_ERROR_BASE + 57),
+"SSL received an alert record with an unknown alert description.")
+
+/*
+ * Received an alert reporting what we did wrong. (more alerts above)
+ */
+ER3(SSL_ERROR_CLOSE_NOTIFY_ALERT , (SSL_ERROR_BASE + 58),
+"SSL peer has closed this connection.")
+
+ER3(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 59),
+"SSL peer was not expecting a handshake message it received.")
+
+ER3(SSL_ERROR_DECOMPRESSION_FAILURE_ALERT , (SSL_ERROR_BASE + 60),
+"SSL peer was unable to succesfully decompress an SSL record it received.")
+
+ER3(SSL_ERROR_HANDSHAKE_FAILURE_ALERT , (SSL_ERROR_BASE + 61),
+"SSL peer was unable to negotiate an acceptable set of security parameters.")
+
+ER3(SSL_ERROR_ILLEGAL_PARAMETER_ALERT , (SSL_ERROR_BASE + 62),
+"SSL peer rejected a handshake message for unacceptable content.")
+
+ER3(SSL_ERROR_UNSUPPORTED_CERT_ALERT , (SSL_ERROR_BASE + 63),
+"SSL peer does not support certificates of the type it received.")
+
+ER3(SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT , (SSL_ERROR_BASE + 64),
+"SSL peer had some unspecified issue with the certificate it received.")
+
+
+ER3(SSL_ERROR_GENERATE_RANDOM_FAILURE , (SSL_ERROR_BASE + 65),
+"SSL experienced a failure of its random number generator.")
+
+ER3(SSL_ERROR_SIGN_HASHES_FAILURE , (SSL_ERROR_BASE + 66),
+"Unable to digitally sign data required to verify your certificate.")
+
+ER3(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE , (SSL_ERROR_BASE + 67),
+"SSL was unable to extract the public key from the peer's certificate.")
+
+ER3(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 68),
+"Unspecified failure while processing SSL Server Key Exchange handshake.")
+
+ER3(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 69),
+"Unspecified failure while processing SSL Client Key Exchange handshake.")
+
+ER3(SSL_ERROR_ENCRYPTION_FAILURE , (SSL_ERROR_BASE + 70),
+"Bulk data encryption algorithm failed in selected cipher suite.")
+
+ER3(SSL_ERROR_DECRYPTION_FAILURE , (SSL_ERROR_BASE + 71),
+"Bulk data decryption algorithm failed in selected cipher suite.")
+
+ER3(SSL_ERROR_SOCKET_WRITE_FAILURE , (SSL_ERROR_BASE + 72),
+"Attempt to write encrypted data to underlying socket failed.")
+
+ER3(SSL_ERROR_MD5_DIGEST_FAILURE , (SSL_ERROR_BASE + 73),
+"MD5 digest function failed.")
+
+ER3(SSL_ERROR_SHA_DIGEST_FAILURE , (SSL_ERROR_BASE + 74),
+"SHA-1 digest function failed.")
+
+ER3(SSL_ERROR_MAC_COMPUTATION_FAILURE , (SSL_ERROR_BASE + 75),
+"MAC computation failed.")
+
+ER3(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE , (SSL_ERROR_BASE + 76),
+"Failure to create Symmetric Key context.")
+
+ER3(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE , (SSL_ERROR_BASE + 77),
+"Failure to unwrap the Symmetric key in Client Key Exchange message.")
+
+ER3(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED , (SSL_ERROR_BASE + 78),
+"SSL Server attempted to use domestic-grade public key with export cipher suite.")
+
+ER3(SSL_ERROR_IV_PARAM_FAILURE , (SSL_ERROR_BASE + 79),
+"PKCS11 code failed to translate an IV into a param.")
+
+ER3(SSL_ERROR_INIT_CIPHER_SUITE_FAILURE , (SSL_ERROR_BASE + 80),
+"Failed to initialize the selected cipher suite.")
+
+ER3(SSL_ERROR_SESSION_KEY_GEN_FAILURE , (SSL_ERROR_BASE + 81),
+"Client failed to generate session keys for SSL session.")
+
+ER3(SSL_ERROR_NO_SERVER_KEY_FOR_ALG , (SSL_ERROR_BASE + 82),
+"Server has no key for the attempted key exchange algorithm.")
+
+ER3(SSL_ERROR_TOKEN_INSERTION_REMOVAL , (SSL_ERROR_BASE + 83),
+"PKCS#11 token was inserted or removed while operation was in progress.")
+
+ER3(SSL_ERROR_TOKEN_SLOT_NOT_FOUND , (SSL_ERROR_BASE + 84),
+"No PKCS#11 token could be found to do a required operation.")
+
+ER3(SSL_ERROR_NO_COMPRESSION_OVERLAP , (SSL_ERROR_BASE + 85),
+"Cannot communicate securely with peer: no common compression algorithm(s).")
+
+ER3(SSL_ERROR_HANDSHAKE_NOT_COMPLETED , (SSL_ERROR_BASE + 86),
+"Cannot initiate another SSL handshake until current handshake is complete.")
+
+ER3(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE , (SSL_ERROR_BASE + 87),
+"Received incorrect handshakes hash values from peer.")
+
+ER3(SSL_ERROR_CERT_KEA_MISMATCH , (SSL_ERROR_BASE + 88),
+"The certificate provided cannot be used with the selected key exchange algorithm.")
+
+ER3(SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA , (SSL_ERROR_BASE + 89),
+"No certificate authority is trusted for SSL client authentication.")
+
+ER3(SSL_ERROR_SESSION_NOT_FOUND , (SSL_ERROR_BASE + 90),
+"Client's SSL session ID not found in server's session cache.")
+
+ER3(SSL_ERROR_DECRYPTION_FAILED_ALERT , (SSL_ERROR_BASE + 91),
+"Peer was unable to decrypt an SSL record it received.")
+
+ER3(SSL_ERROR_RECORD_OVERFLOW_ALERT , (SSL_ERROR_BASE + 92),
+"Peer received an SSL record that was longer than is permitted.")
+
+ER3(SSL_ERROR_UNKNOWN_CA_ALERT , (SSL_ERROR_BASE + 93),
+"Peer does not recognize and trust the CA that issued your certificate.")
+
+ER3(SSL_ERROR_ACCESS_DENIED_ALERT , (SSL_ERROR_BASE + 94),
+"Peer received a valid certificate, but access was denied.")
+
+ER3(SSL_ERROR_DECODE_ERROR_ALERT , (SSL_ERROR_BASE + 95),
+"Peer could not decode an SSL handshake message.")
+
+ER3(SSL_ERROR_DECRYPT_ERROR_ALERT , (SSL_ERROR_BASE + 96),
+"Peer reports failure of signature verification or key exchange.")
+
+ER3(SSL_ERROR_EXPORT_RESTRICTION_ALERT , (SSL_ERROR_BASE + 97),
+"Peer reports negotiation not in compliance with export regulations.")
+
+ER3(SSL_ERROR_PROTOCOL_VERSION_ALERT , (SSL_ERROR_BASE + 98),
+"Peer reports incompatible or unsupported protocol version.")
+
+ER3(SSL_ERROR_INSUFFICIENT_SECURITY_ALERT , (SSL_ERROR_BASE + 99),
+"Server requires ciphers more secure than those supported by client.")
+
+ER3(SSL_ERROR_INTERNAL_ERROR_ALERT , (SSL_ERROR_BASE + 100),
+"Peer reports it experienced an internal error.")
+
+ER3(SSL_ERROR_USER_CANCELED_ALERT , (SSL_ERROR_BASE + 101),
+"Peer user canceled handshake.")
+
+ER3(SSL_ERROR_NO_RENEGOTIATION_ALERT , (SSL_ERROR_BASE + 102),
+"Peer does not permit renegotiation of SSL security parameters.")
+
diff --git a/security/nss/cmd/SSLsample/client.c b/security/nss/cmd/SSLsample/client.c
new file mode 100644
index 000000000..e5cd1013c
--- /dev/null
+++ b/security/nss/cmd/SSLsample/client.c
@@ -0,0 +1,453 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/****************************************************************************
+ * SSL client program that sets up a connection to SSL server, transmits *
+ * some data and then reads the reply *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "prerror.h"
+
+#include "pk11func.h"
+#include "secitem.h"
+
+
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "nss.h"
+
+#include "sslsample.h"
+
+#define RD_BUF_SIZE (60 * 1024)
+
+extern int ssl2CipherSuites[];
+extern int ssl3CipherSuites[];
+
+GlobalThreadMgr threadMGR;
+char *certNickname = NULL;
+char *hostName = NULL;
+char *password = NULL;
+unsigned short port = 0;
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-n rsa_nickname] [-p port] [-d dbdir] [-c connections]\n"
+ " [-w dbpasswd] [-C cipher(s)] hostname\n",
+ progName);
+ exit(1);
+}
+
+PRFileDesc *
+setupSSLSocket(PRNetAddr *addr)
+{
+ PRFileDesc *tcpSocket;
+ PRFileDesc *sslSocket;
+ PRSocketOptionData socketOption;
+ PRStatus prStatus;
+ SECStatus secStatus;
+
+#if 0
+retry:
+#endif
+
+ tcpSocket = PR_NewTCPSocket();
+ if (tcpSocket == NULL) {
+ errWarn("PR_NewTCPSocket");
+ }
+
+ /* Make the socket blocking. */
+ socketOption.option = PR_SockOpt_Nonblocking;
+ socketOption.value.non_blocking = PR_FALSE;
+
+ prStatus = PR_SetSocketOption(tcpSocket, &socketOption);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_SetSocketOption");
+ goto loser;
+ }
+
+#if 0
+ /* Verify that a connection can be made to the socket. */
+ prStatus = PR_Connect(tcpSocket, addr, PR_INTERVAL_NO_TIMEOUT);
+ if (prStatus != PR_SUCCESS) {
+ PRErrorCode err = PR_GetError();
+ if (err == PR_CONNECT_REFUSED_ERROR) {
+ PR_Close(tcpSocket);
+ PR_Sleep(PR_MillisecondsToInterval(10));
+ fprintf(stderr, "Connection to port refused, retrying.\n");
+ goto retry;
+ }
+ errWarn("PR_Connect");
+ goto loser;
+ }
+#endif
+
+ /* Import the socket into the SSL layer. */
+ sslSocket = SSL_ImportFD(NULL, tcpSocket);
+ if (!sslSocket) {
+ errWarn("SSL_ImportFD");
+ goto loser;
+ }
+
+ /* Set configuration options. */
+ secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_OptionSet:SSL_SECURITY");
+ goto loser;
+ }
+
+ secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT");
+ goto loser;
+ }
+
+ /* Set SSL callback routines. */
+ secStatus = SSL_GetClientAuthDataHook(sslSocket,
+ (SSLGetClientAuthData)myGetClientAuthData,
+ (void *)certNickname);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_GetClientAuthDataHook");
+ goto loser;
+ }
+
+ secStatus = SSL_AuthCertificateHook(sslSocket,
+ (SSLAuthCertificate)myAuthCertificate,
+ (void *)CERT_GetDefaultCertDB());
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_AuthCertificateHook");
+ goto loser;
+ }
+
+ secStatus = SSL_BadCertHook(sslSocket,
+ (SSLBadCertHandler)myBadCertHandler, NULL);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_BadCertHook");
+ goto loser;
+ }
+
+ secStatus = SSL_HandshakeCallback(sslSocket,
+ (SSLHandshakeCallback)myHandshakeCallback,
+ NULL);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_HandshakeCallback");
+ goto loser;
+ }
+
+ return sslSocket;
+
+loser:
+
+ PR_Close(tcpSocket);
+ return NULL;
+}
+
+
+const char requestString[] = {"GET /testfile HTTP/1.0\r\n\r\n" };
+
+SECStatus
+handle_connection(PRFileDesc *sslSocket, int connection)
+{
+ int countRead = 0;
+ PRInt32 numBytes;
+ char *readBuffer;
+
+ readBuffer = PORT_Alloc(RD_BUF_SIZE);
+ if (!readBuffer) {
+ exitErr("PORT_Alloc");
+ }
+
+ /* compose the http request here. */
+
+ numBytes = PR_Write(sslSocket, requestString, strlen(requestString));
+ if (numBytes <= 0) {
+ errWarn("PR_Write");
+ PR_Free(readBuffer);
+ readBuffer = NULL;
+ return SECFailure;
+ }
+
+ /* read until EOF */
+ while (PR_TRUE) {
+ numBytes = PR_Read(sslSocket, readBuffer, RD_BUF_SIZE);
+ if (numBytes == 0) {
+ break; /* EOF */
+ }
+ if (numBytes < 0) {
+ errWarn("PR_Read");
+ break;
+ }
+ countRead += numBytes;
+ fprintf(stderr, "***** Connection %d read %d bytes (%d total).\n",
+ connection, numBytes, countRead );
+ readBuffer[numBytes] = '\0';
+ fprintf(stderr, "************\n%s\n************\n", readBuffer);
+ }
+
+ printSecurityInfo(sslSocket);
+
+ PR_Free(readBuffer);
+ readBuffer = NULL;
+
+ /* Caller closes the socket. */
+
+ fprintf(stderr,
+ "***** Connection %d read %d bytes total.\n",
+ connection, countRead);
+
+ return SECSuccess; /* success */
+}
+
+/* one copy of this function is launched in a separate thread for each
+** connection to be made.
+*/
+SECStatus
+do_connects(void *a, int connection)
+{
+ PRNetAddr *addr = (PRNetAddr *)a;
+ PRFileDesc *sslSocket;
+ PRHostEnt hostEntry;
+ char buffer[PR_NETDB_BUF_SIZE];
+ PRStatus prStatus;
+ PRIntn hostenum;
+ SECStatus secStatus;
+
+ /* Set up SSL secure socket. */
+ sslSocket = setupSSLSocket(addr);
+ if (sslSocket == NULL) {
+ errWarn("setupSSLSocket");
+ return SECFailure;
+ }
+
+ secStatus = SSL_SetPKCS11PinArg(sslSocket, password);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_SetPKCS11PinArg");
+ return secStatus;
+ }
+
+ secStatus = SSL_SetURL(sslSocket, hostName);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_SetURL");
+ return secStatus;
+ }
+
+ /* Prepare and setup network connection. */
+ prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_GetHostByName");
+ return SECFailure;
+ }
+
+ hostenum = PR_EnumerateHostEnt(0, &hostEntry, port, addr);
+ if (hostenum == -1) {
+ errWarn("PR_EnumerateHostEnt");
+ return SECFailure;
+ }
+
+ prStatus = PR_Connect(sslSocket, addr, PR_INTERVAL_NO_TIMEOUT);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_Connect");
+ return SECFailure;
+ }
+
+ /* Established SSL connection, ready to send data. */
+#if 0
+ secStatus = SSL_ForceHandshake(sslSocket);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_ForceHandshake");
+ return secStatus;
+ }
+#endif
+
+ secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_FALSE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ prStatus = PR_Close(sslSocket);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_Close");
+ }
+ return secStatus;
+ }
+
+ secStatus = handle_connection(sslSocket, connection);
+ if (secStatus != SECSuccess) {
+ errWarn("handle_connection");
+ return secStatus;
+ }
+
+ PR_Close(sslSocket);
+ return SECSuccess;
+}
+
+void
+client_main(unsigned short port,
+ int connections,
+ const char * hostName)
+{
+ int i;
+ SECStatus secStatus;
+ PRStatus prStatus;
+ PRInt32 rv;
+ PRNetAddr addr;
+ PRHostEnt hostEntry;
+ char buffer[256];
+
+ /* Setup network connection. */
+ prStatus = PR_GetHostByName(hostName, buffer, 256, &hostEntry);
+ if (prStatus != PR_SUCCESS) {
+ exitErr("PR_GetHostByName");
+ }
+
+ rv = PR_EnumerateHostEnt(0, &hostEntry, port, &addr);
+ if (rv < 0) {
+ exitErr("PR_EnumerateHostEnt");
+ }
+
+ secStatus = launch_thread(&threadMGR, do_connects, &addr, 1);
+ if (secStatus != SECSuccess) {
+ exitErr("launch_thread");
+ }
+
+ if (connections > 1) {
+ /* wait for the first connection to terminate, then launch the rest. */
+ reap_threads(&threadMGR);
+ /* Start up the connections */
+ for (i = 2; i <= connections; ++i) {
+ secStatus = launch_thread(&threadMGR, do_connects, &addr, i);
+ if (secStatus != SECSuccess) {
+ errWarn("launch_thread");
+ }
+ }
+ }
+
+ reap_threads(&threadMGR);
+ destroy_thread_data(&threadMGR);
+}
+
+int
+main(int argc, char **argv)
+{
+ char * certDir = ".";
+ char * progName = NULL;
+ int connections = 1;
+ char * cipherString = NULL;
+ SECStatus secStatus;
+ PLOptState * optstate;
+ PLOptStatus status;
+
+ /* Call the NSPR initialization routines */
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ progName = PL_strdup(argv[0]);
+
+ hostName = NULL;
+ optstate = PL_CreateOptState(argc, argv, "C:c:d:n:p:w:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch(optstate->option) {
+ case 'C' : cipherString = PL_strdup(optstate->value); break;
+ case 'c' : connections = PORT_Atoi(optstate->value); break;
+ case 'd' : certDir = PL_strdup(optstate->value); break;
+ case 'n' : certNickname = PL_strdup(optstate->value); break;
+ case 'p' : port = PORT_Atoi(optstate->value); break;
+ case 'w' : password = PL_strdup(optstate->value); break;
+ case '\0': hostName = PL_strdup(optstate->value); break;
+ default : Usage(progName);
+ }
+ }
+
+ if (port == 0 || hostName == NULL)
+ Usage(progName);
+
+ if (certDir == NULL) {
+ certDir = PR_smprintf("%s/.netscape", getenv("HOME"));
+ }
+
+ /* Set our password function callback. */
+ PK11_SetPasswordFunc(myPasswd);
+
+ /* Initialize the NSS libraries. */
+ secStatus = NSS_Init(certDir);
+ if (secStatus != SECSuccess) {
+ exitErr("NSS_Init");
+ }
+
+ /* All cipher suites except RSA_NULL_MD5 are enabled by Domestic Policy. */
+ NSS_SetDomesticPolicy();
+ SSL_CipherPrefSetDefault(SSL_RSA_WITH_NULL_MD5, PR_TRUE);
+
+ /* all the SSL2 and SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ int ndx;
+
+ /* disable all the ciphers, then enable the ones we want. */
+ disableAllSSLCiphers();
+
+ while (0 != (ndx = *cipherString++)) {
+ int *cptr;
+ int cipher;
+
+ if (! isalpha(ndx))
+ Usage(progName);
+ cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
+ for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
+ /* do nothing */;
+ if (cipher) {
+ SSL_CipherPrefSetDefault(cipher, PR_TRUE);
+ }
+ }
+ }
+
+ client_main(port, connections, hostName);
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ PR_Cleanup();
+ return 0;
+}
+
diff --git a/security/nss/cmd/SSLsample/client.mn b/security/nss/cmd/SSLsample/client.mn
new file mode 100644
index 000000000..5c7fa3d7c
--- /dev/null
+++ b/security/nss/cmd/SSLsample/client.mn
@@ -0,0 +1,50 @@
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+MODULE = nss
+
+EXPORTS =
+
+CSRCS = client.c \
+ sslsample.c \
+ $(NULL)
+
+PROGRAM = client
+
+REQUIRES = dbm
+
+IMPORTS = nss/lib/nss
+
+DEFINES = -DNSPR20
+
diff --git a/security/nss/cmd/SSLsample/gencerts b/security/nss/cmd/SSLsample/gencerts
new file mode 100755
index 000000000..80be66a43
--- /dev/null
+++ b/security/nss/cmd/SSLsample/gencerts
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+#
+# Script to generate sample db files neccessary for SSL.
+
+# Directory for db's, use in all subsequent -d flags.
+rm -rf SampleCertDBs
+mkdir SampleCertDBs
+
+# Password to use.
+echo sample > passfile
+
+# Generate the db files, using the above password.
+certutil -N -d SampleCertDBs -f passfile
+
+# Generate the CA cert. This cert is self-signed and only useful for
+# test purposes. Set the trust bits to allow it to sign SSL client/server
+# certs.
+certutil -S -n SampleRootCA -x -t "CTu,CTu,CTu" \
+ -s "CN=My Sample Root CA, O=My Organization" \
+ -m 25000 -o ./SampleCertDBs/SampleRootCA.crt \
+ -d SampleCertDBs -f passfile
+
+# Generate the server cert. This cert is signed by the CA cert generated
+# above. The CN must be hostname.domain.[com|org|net|...].
+certutil -S -n SampleSSLServerCert -c SampleRootCA -t "u,u,u" \
+ -s "CN=$HOSTNAME.$MYDOMAIN, O=$HOSTNAME Corp." \
+ -m 25001 -o ./SampleCertDBs/SampleSSLServer.crt \
+ -d SampleCertDBs -f passfile
+
+# Generate the client cert. This cert is signed by the CA cert generated
+# above.
+certutil -S -n SampleSSLClientCert -c SampleRootCA -t "u,u,u" \
+ -s "CN=My Client Cert, O=Client Organization" \
+ -m 25002 -o ./SampleCertDBs/SampleSSLClient.crt \
+ -d SampleCertDBs -f passfile
+
+# Verify the certificates.
+certutil -V -u V -n SampleSSLServerCert -d SampleCertDBs
+certutil -V -u C -n SampleSSLClientCert -d SampleCertDBs
+
+# Remove unneccessary files.
+rm -f passfile
+rm -f tempcert*
+
+# You are now ready to run your client/server! Example command lines:
+# server -n SampleSSLServerCert -p 8080 -d SampleCertDBs -w sample -c e -R
+# client -n SampleSSLClientCert -p 8080 -d SampleCertDBs -w sample -c 2 trane.mcom.com
diff --git a/security/nss/cmd/SSLsample/make.client b/security/nss/cmd/SSLsample/make.client
new file mode 100644
index 000000000..3dd7705e3
--- /dev/null
+++ b/security/nss/cmd/SSLsample/make.client
@@ -0,0 +1,78 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include client.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#include $(CORE_DEPTH)/$(MODULE)/config/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+#CC = cc
+
+
diff --git a/security/nss/cmd/SSLsample/make.server b/security/nss/cmd/SSLsample/make.server
new file mode 100644
index 000000000..7969df798
--- /dev/null
+++ b/security/nss/cmd/SSLsample/make.server
@@ -0,0 +1,77 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include server.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#include $(CORE_DEPTH)/$(MODULE)/config/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
diff --git a/security/nss/cmd/SSLsample/nmakefile95.nss b/security/nss/cmd/SSLsample/nmakefile95.nss
new file mode 100755
index 000000000..5684478cd
--- /dev/null
+++ b/security/nss/cmd/SSLsample/nmakefile95.nss
@@ -0,0 +1,60 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+# NSS 2.6.2 Sample Win95 Makefile
+#
+#
+# This nmake file will build server.c and client.c on Windows 95.
+#
+
+DEFINES=-D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG -DWIN32 -D_WINDOWS
+
+INCPATH=/I. /I..\include\dbm /I..\include\nspr /I..\include\security
+
+LIBS=nss.lib ssl.lib pkcs7.lib pkcs12.lib secmod.lib cert.lib key.lib crypto.lib secutil.lib hash.lib dbm.lib libplc3.lib libplds3.lib libnspr3.lib wsock32.lib
+
+CFLAGS=-O2 -MD -W3 -nologo
+
+CC=cl
+
+LDOPTIONS=/link /LIBPATH:..\lib /nodefaultlib:libcd.lib /subsystem:console
+
+server:
+ $(CC) $(CFLAGS) $(INCPATH) /Feserver server.c getopt.c $(LIBS) $(DEFINES) $(LDOPTIONS)
+
+client:
+ $(CC) $(CFLAGS) $(INCPATH) /Feclient client.c getopt.c $(LIBS) $(DEFINES) $(LDOPTIONS)
+
+clean:
+ del /S server.exe client.exe server.lib server.exp client.lib client.exp server.obj client.obj getopt.obj
+
diff --git a/security/nss/cmd/SSLsample/nmakefilent.nss b/security/nss/cmd/SSLsample/nmakefilent.nss
new file mode 100755
index 000000000..9d2d1ccc4
--- /dev/null
+++ b/security/nss/cmd/SSLsample/nmakefilent.nss
@@ -0,0 +1,59 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+# NSS 2.6.2 Sample NT Makefile
+#
+#
+# This nmake file will build server.c and client.c on Windows NT 4 SP3.
+#
+
+DEFINES=-D_X86_ -GT -DWINNT -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG -DWIN32 -D_WINDOWS
+INCPATH=-I. -I..\include\dbm -I..\include\nspr -I..\include\security
+
+LIBS=nss.lib ssl.lib pkcs7.lib pkcs12.lib secmod.lib cert.lib key.lib crypto.lib secutil.lib hash.lib dbm.lib libplc3.lib libplds3.lib libnspr3.lib wsock32.lib
+
+CFLAGS=-O2 -MD -W3 -nologo
+
+CC=cl
+
+LDOPTIONS=/link /LIBPATH:..\lib /nodefaultlib:libcd.lib /subsystem:console
+
+server:
+ $(CC) $(CFLAGS) /Feserver server.c getopt.c $(LIBS) $(DEFINES) $(INCPATH) $(LDOPTIONS)
+
+client:
+ $(CC) $(CFLAGS) /Feclient client.c getopt.c $(LIBS) $(DEFINES) $(INCPATH) $(LDOPTIONS)
+
+clean:
+ del /S server.exe client.exe server.lib server.exp client.lib client.exp server.obj client.obj getopt.obj
+
diff --git a/security/nss/cmd/SSLsample/server.c b/security/nss/cmd/SSLsample/server.c
new file mode 100644
index 000000000..08c20a5a4
--- /dev/null
+++ b/security/nss/cmd/SSLsample/server.c
@@ -0,0 +1,822 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/****************************************************************************
+ * SSL server program listens on a port, accepts client connection, reads *
+ * request and responds to it *
+ ****************************************************************************/
+
+/* Generic header files */
+
+#include <stdio.h>
+#include <string.h>
+
+/* NSPR header files */
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "prerror.h"
+#include "prnetdb.h"
+
+/* NSS header files */
+
+#include "pk11func.h"
+#include "secitem.h"
+#include "ssl.h"
+#include "certt.h"
+#include "nss.h"
+#include "secrng.h"
+#include "secder.h"
+#include "key.h"
+#include "sslproto.h"
+
+/* Custom header files */
+
+#include "sslsample.h"
+
+#ifndef PORT_Sprintf
+#define PORT_Sprintf sprintf
+#endif
+
+#define REQUEST_CERT_ONCE 1
+#define REQUIRE_CERT_ONCE 2
+#define REQUEST_CERT_ALL 3
+#define REQUIRE_CERT_ALL 4
+
+/* Global variables */
+GlobalThreadMgr threadMGR;
+char *password = NULL;
+CERTCertificate *cert = NULL;
+SECKEYPrivateKey *privKey = NULL;
+int stopping;
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+
+"Usage: %s -n rsa_nickname -p port [-3RFrf] [-w password]\n"
+" [-c ciphers] [-d dbdir] \n"
+"-3 means disable SSL v3\n"
+"-r means request certificate on first handshake.\n"
+"-f means require certificate on first handshake.\n"
+"-R means request certificate on all handshakes.\n"
+"-F means require certificate on all handshakes.\n"
+"-c ciphers Letter(s) chosen from the following list\n"
+"A SSL2 RC4 128 WITH MD5\n"
+"B SSL2 RC4 128 EXPORT40 WITH MD5\n"
+"C SSL2 RC2 128 CBC WITH MD5\n"
+"D SSL2 RC2 128 CBC EXPORT40 WITH MD5\n"
+"E SSL2 DES 64 CBC WITH MD5\n"
+"F SSL2 DES 192 EDE3 CBC WITH MD5\n"
+"\n"
+"a SSL3 FORTEZZA DMS WITH FORTEZZA CBC SHA\n"
+"b SSL3 FORTEZZA DMS WITH RC4 128 SHA\n"
+"c SSL3 RSA WITH RC4 128 MD5\n"
+"d SSL3 RSA WITH 3DES EDE CBC SHA\n"
+"e SSL3 RSA WITH DES CBC SHA\n"
+"f SSL3 RSA EXPORT WITH RC4 40 MD5\n"
+"g SSL3 RSA EXPORT WITH RC2 CBC 40 MD5\n"
+"h SSL3 FORTEZZA DMS WITH NULL SHA\n"
+"i SSL3 RSA WITH NULL MD5\n"
+"j SSL3 RSA FIPS WITH 3DES EDE CBC SHA\n"
+"k SSL3 RSA FIPS WITH DES CBC SHA\n"
+"l SSL3 RSA EXPORT WITH DES CBC SHA\t(new)\n"
+"m SSL3 RSA EXPORT WITH RC4 56 SHA\t(new)\n",
+ progName);
+ exit(1);
+}
+
+/* Function: readDataFromSocket()
+ *
+ * Purpose: Parse an HTTP request by reading data from a GET or POST.
+ *
+ */
+SECStatus
+readDataFromSocket(PRFileDesc *sslSocket, DataBuffer *buffer, char **fileName)
+{
+ char *post;
+ int numBytes = 0;
+ int newln = 0; /* # of consecutive newlns */
+
+ /* Read data while it comes in from the socket. */
+ while (PR_TRUE) {
+ buffer->index = 0;
+ newln = 0;
+
+ /* Read the buffer. */
+ numBytes = PR_Read(sslSocket, &buffer->data[buffer->index],
+ buffer->remaining);
+ if (numBytes <= 0) {
+ errWarn("PR_Read");
+ return SECFailure;
+ }
+ buffer->dataEnd = buffer->dataStart + numBytes;
+
+ /* Parse the input, starting at the beginning of the buffer.
+ * Stop when we detect two consecutive \n's (or \r\n's)
+ * as this signifies the end of the GET or POST portion.
+ * The posted data follows.
+ */
+ while (buffer->index < buffer->dataEnd && newln < 2) {
+ int octet = buffer->data[buffer->index++];
+ if (octet == '\n') {
+ newln++;
+ } else if (octet != '\r') {
+ newln = 0;
+ }
+ }
+
+ /* Came to the end of the buffer, or second newline.
+ * If we didn't get an empty line ("\r\n\r\n"), then keep on reading.
+ */
+ if (newln < 2)
+ continue;
+
+ /* we're at the end of the HTTP request.
+ * If the request is a POST, then there will be one more
+ * line of data.
+ * This parsing is a hack, but ok for SSL test purposes.
+ */
+ post = PORT_Strstr(buffer->data, "POST ");
+ if (!post || *post != 'P')
+ break;
+
+ /* It's a post, so look for the next and final CR/LF. */
+ /* We should parse content length here, but ... */
+ while (buffer->index < buffer->dataEnd && newln < 3) {
+ int octet = buffer->data[buffer->index++];
+ if (octet == '\n') {
+ newln++;
+ }
+ }
+
+ if (newln == 3)
+ break;
+ }
+
+ /* Have either (a) a complete get, (b) a complete post, (c) EOF */
+
+ /* Execute a "GET " operation. */
+ if (buffer->index > 0 && PORT_Strncmp(buffer->data, "GET ", 4) == 0) {
+ int fnLength;
+
+ /* File name is the part after "GET ". */
+ fnLength = strcspn(buffer->data + 5, " \r\n");
+ *fileName = (char *)PORT_Alloc(fnLength + 1);
+ PORT_Strncpy(*fileName, buffer->data + 5, fnLength);
+ (*fileName)[fnLength] = '\0';
+ }
+
+ return SECSuccess;
+}
+
+/* Function: authenticateSocket()
+ *
+ * Purpose: Configure a socket for SSL.
+ *
+ *
+ */
+PRFileDesc *
+setupSSLSocket(PRFileDesc *tcpSocket, int requestCert)
+{
+ PRFileDesc *sslSocket;
+ SSLKEAType certKEA;
+ int certErr = 0;
+ SECStatus secStatus;
+
+ /* Set the appropriate flags. */
+
+ sslSocket = SSL_ImportFD(NULL, tcpSocket);
+ if (sslSocket == NULL) {
+ errWarn("SSL_ImportFD");
+ goto loser;
+ }
+
+ secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_OptionSet SSL_SECURITY");
+ goto loser;
+ }
+
+ secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_SERVER");
+ goto loser;
+ }
+
+ secStatus = SSL_OptionSet(sslSocket, SSL_REQUEST_CERTIFICATE,
+ (requestCert >= REQUEST_CERT_ONCE));
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_OptionSet:SSL_REQUEST_CERTIFICATE");
+ goto loser;
+ }
+
+ secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_CERTIFICATE,
+ (requestCert == REQUIRE_CERT_ONCE));
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_OptionSet:SSL_REQUIRE_CERTIFICATE");
+ goto loser;
+ }
+
+ /* Set the appropriate callback routines. */
+
+ secStatus = SSL_AuthCertificateHook(sslSocket, myAuthCertificate,
+ CERT_GetDefaultCertDB());
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_AuthCertificateHook");
+ goto loser;
+ }
+
+ secStatus = SSL_BadCertHook(sslSocket,
+ (SSLBadCertHandler)myBadCertHandler, &certErr);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_BadCertHook");
+ goto loser;
+ }
+
+ secStatus = SSL_HandshakeCallback(sslSocket,
+ (SSLHandshakeCallback)myHandshakeCallback,
+ NULL);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_HandshakeCallback");
+ goto loser;
+ }
+
+ secStatus = SSL_SetPKCS11PinArg(sslSocket, password);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_HandshakeCallback");
+ goto loser;
+ }
+
+ certKEA = NSS_FindCertKEAType(cert);
+
+ secStatus = SSL_ConfigSecureServer(sslSocket, cert, privKey, certKEA);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_ConfigSecureServer");
+ goto loser;
+ }
+
+ return sslSocket;
+
+loser:
+
+ PR_Close(tcpSocket);
+ return NULL;
+}
+
+/* Function: authenticateSocket()
+ *
+ * Purpose: Perform client authentication on the socket.
+ *
+ */
+SECStatus
+authenticateSocket(PRFileDesc *sslSocket, PRBool requireCert)
+{
+ CERTCertificate *cert;
+ SECStatus secStatus;
+
+ /* Returns NULL if client authentication is not enabled or if the
+ * client had no certificate. */
+ cert = SSL_PeerCertificate(sslSocket);
+ if (cert) {
+ /* Client had a certificate, so authentication is through. */
+ CERT_DestroyCertificate(cert);
+ return SECSuccess;
+ }
+
+ /* Request client to authenticate itself. */
+ secStatus = SSL_OptionSet(sslSocket, SSL_REQUEST_CERTIFICATE, PR_TRUE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_OptionSet:SSL_REQUEST_CERTIFICATE");
+ return SECFailure;
+ }
+
+ /* If desired, require client to authenticate itself. Note
+ * SSL_REQUEST_CERTIFICATE must also be on, as above. */
+ secStatus = SSL_OptionSet(sslSocket, SSL_REQUIRE_CERTIFICATE, requireCert);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_OptionSet:SSL_REQUIRE_CERTIFICATE");
+ return SECFailure;
+ }
+
+ /* Having changed socket configuration parameters, redo handshake. */
+ secStatus = SSL_ReHandshake(sslSocket, PR_TRUE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_ReHandshake");
+ return SECFailure;
+ }
+
+ /* Force the handshake to complete before moving on. */
+ secStatus = SSL_ForceHandshake(sslSocket);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_ForceHandshake");
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+/* Function: writeDataToSocket
+ *
+ * Purpose: Write the client's request back to the socket. If the client
+ * requested a file, dump it to the socket.
+ *
+ */
+SECStatus
+writeDataToSocket(PRFileDesc *sslSocket, DataBuffer *buffer, char *fileName)
+{
+ int headerLength;
+ int numBytes;
+ char messageBuffer[120];
+ PRFileDesc *local_file_fd = NULL;
+ char header[] = "<html><body><h1>Sample SSL server</h1><br><br>";
+ char filehd[] = "<h2>The file you requested:</h2><br>";
+ char reqhd[] = "<h2>This is your request:</h2><br>";
+ char link[] = "Try getting a <a HREF=\"../testfile\">file</a><br>";
+ char footer[] = "<br><h2>End of request.</h2><br></body></html>";
+
+ headerLength = PORT_Strlen(defaultHeader);
+
+ /* Write a header to the socket. */
+ numBytes = PR_Write(sslSocket, header, PORT_Strlen(header));
+ if (numBytes < 0) {
+ errWarn("PR_Write");
+ goto loser;
+ }
+
+ if (fileName) {
+ PRFileInfo info;
+ PRStatus prStatus;
+
+ /* Try to open the local file named.
+ * If successful, then write it to the client.
+ */
+ prStatus = PR_GetFileInfo(fileName, &info);
+ if (prStatus != PR_SUCCESS ||
+ info.type != PR_FILE_FILE ||
+ info.size < 0) {
+ PORT_Free(fileName);
+ /* Maybe a GET not sent from client.c? */
+ goto writerequest;
+ }
+
+ local_file_fd = PR_Open(fileName, PR_RDONLY, 0);
+ if (local_file_fd == NULL) {
+ PORT_Free(fileName);
+ goto writerequest;
+ }
+
+ /* Write a header to the socket. */
+ numBytes = PR_Write(sslSocket, filehd, PORT_Strlen(filehd));
+ if (numBytes < 0) {
+ errWarn("PR_Write");
+ goto loser;
+ }
+
+ /* Transmit the local file prepended by the default header
+ * across the socket.
+ */
+ numBytes = PR_TransmitFile(sslSocket, local_file_fd,
+ defaultHeader, headerLength,
+ PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+
+ /* Error in transmission. */
+ if (numBytes < 0) {
+ errWarn("PR_TransmitFile");
+ /*
+ i = PORT_Strlen(errString);
+ PORT_Memcpy(buf, errString, i);
+ */
+ /* Transmitted bytes successfully. */
+ } else {
+ numBytes -= headerLength;
+ fprintf(stderr, "PR_TransmitFile wrote %d bytes from %s\n",
+ numBytes, fileName);
+ }
+
+ PORT_Free(fileName);
+ PR_Close(local_file_fd);
+ }
+
+writerequest:
+
+ /* Write a header to the socket. */
+ numBytes = PR_Write(sslSocket, reqhd, PORT_Strlen(reqhd));
+ if (numBytes < 0) {
+ errWarn("PR_Write");
+ goto loser;
+ }
+
+ /* Write the buffer data to the socket. */
+ if (buffer->index <= 0) {
+ /* Reached the EOF. Report incomplete transaction to socket. */
+ PORT_Sprintf(messageBuffer,
+ "GET or POST incomplete after %d bytes.\r\n",
+ buffer->dataEnd);
+ numBytes = PR_Write(sslSocket, messageBuffer,
+ PORT_Strlen(messageBuffer));
+ if (numBytes < 0) {
+ errWarn("PR_Write");
+ goto loser;
+ }
+ } else {
+ /* Display the buffer data. */
+ fwrite(buffer->data, 1, buffer->index, stdout);
+ /* Write the buffer data to the socket. */
+ numBytes = PR_Write(sslSocket, buffer->data, buffer->index);
+ if (numBytes < 0) {
+ errWarn("PR_Write");
+ goto loser;
+ }
+ /* Display security information for the socket. */
+ printSecurityInfo(sslSocket);
+ /* Write any discarded data out to the socket. */
+ if (buffer->index < buffer->dataEnd) {
+ PORT_Sprintf(buffer->data, "Discarded %d characters.\r\n",
+ buffer->dataEnd - buffer->index);
+ numBytes = PR_Write(sslSocket, buffer->data,
+ PORT_Strlen(buffer->data));
+ if (numBytes < 0) {
+ errWarn("PR_Write");
+ goto loser;
+ }
+ }
+ }
+
+ /* Write a footer to the socket. */
+ numBytes = PR_Write(sslSocket, footer, PORT_Strlen(footer));
+ if (numBytes < 0) {
+ errWarn("PR_Write");
+ goto loser;
+ }
+
+ /* Write a link to the socket. */
+ numBytes = PR_Write(sslSocket, link, PORT_Strlen(link));
+ if (numBytes < 0) {
+ errWarn("PR_Write");
+ goto loser;
+ }
+
+ /* Complete the HTTP transaction. */
+ numBytes = PR_Write(sslSocket, "EOF\r\n\r\n\r\n", 9);
+ if (numBytes < 0) {
+ errWarn("PR_Write");
+ goto loser;
+ }
+
+ /* Do a nice shutdown if asked. */
+ if (!strncmp(buffer->data, stopCmd, strlen(stopCmd))) {
+ stopping = 1;
+ }
+ return SECSuccess;
+
+loser:
+
+ /* Do a nice shutdown if asked. */
+ if (!strncmp(buffer->data, stopCmd, strlen(stopCmd))) {
+ stopping = 1;
+ }
+ return SECFailure;
+}
+
+/* Function: int handle_connection()
+ *
+ * Purpose: Thread to handle a connection to a socket.
+ *
+ */
+SECStatus
+handle_connection(void *tcp_sock, int requestCert)
+{
+ PRFileDesc * tcpSocket = (PRFileDesc *)tcp_sock;
+ PRFileDesc * sslSocket = NULL;
+ SECStatus secStatus = SECFailure;
+ PRStatus prStatus;
+ PRSocketOptionData socketOption;
+ DataBuffer buffer;
+ char * fileName = NULL;
+
+ /* Initialize the data buffer. */
+ memset(buffer.data, 0, BUFFER_SIZE);
+ buffer.remaining = BUFFER_SIZE;
+ buffer.index = 0;
+ buffer.dataStart = 0;
+ buffer.dataEnd = 0;
+
+ /* Make sure the socket is blocking. */
+ socketOption.option = PR_SockOpt_Nonblocking;
+ socketOption.value.non_blocking = PR_FALSE;
+ PR_SetSocketOption(tcpSocket, &socketOption);
+
+ sslSocket = setupSSLSocket(tcpSocket, requestCert);
+ if (sslSocket == NULL) {
+ errWarn("setupSSLSocket");
+ goto cleanup;
+ }
+
+ secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_TRUE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ goto cleanup;
+ }
+
+ /* Read data from the socket, parse it for HTTP content.
+ * If the user is requesting/requiring authentication, authenticate
+ * the socket. Then write the result back to the socket. */
+ fprintf(stdout, "\nReading data from socket...\n\n");
+ secStatus = readDataFromSocket(sslSocket, &buffer, &fileName);
+ if (secStatus != SECSuccess) {
+ goto cleanup;
+ }
+ if (requestCert >= REQUEST_CERT_ALL) {
+ fprintf(stdout, "\nAuthentication requested.\n\n");
+ secStatus = authenticateSocket(sslSocket,
+ (requestCert == REQUIRE_CERT_ALL));
+ if (secStatus != SECSuccess) {
+ goto cleanup;
+ }
+ }
+
+ fprintf(stdout, "\nWriting data to socket...\n\n");
+ secStatus = writeDataToSocket(sslSocket, &buffer, fileName);
+
+cleanup:
+
+ /* Close down the socket. */
+ prStatus = PR_Close(tcpSocket);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_Close");
+ }
+
+ return secStatus;
+}
+
+/* Function: int accept_connection()
+ *
+ * Purpose: Thread to accept a connection to the socket.
+ *
+ */
+SECStatus
+accept_connection(void *listener, int requestCert)
+{
+ PRFileDesc *listenSocket = (PRFileDesc*)listener;
+ PRNetAddr addr;
+ PRStatus prStatus;
+
+ /* XXX need an SSL socket here? */
+ while (!stopping) {
+ PRFileDesc *tcpSocket;
+ SECStatus result;
+
+ fprintf(stderr, "\n\n\nAbout to call accept.\n");
+
+ /* Accept a connection to the socket. */
+ tcpSocket = PR_Accept(listenSocket, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (tcpSocket == NULL) {
+ errWarn("PR_Accept");
+ break;
+ }
+
+ /* Accepted the connection, now handle it. */
+ result = launch_thread(&threadMGR, handle_connection,
+ tcpSocket, requestCert);
+
+ if (result != SECSuccess) {
+ prStatus = PR_Close(tcpSocket);
+ if (prStatus != PR_SUCCESS) {
+ exitErr("PR_Close");
+ }
+ break;
+ }
+ }
+
+ fprintf(stderr, "Closing listen socket.\n");
+
+ prStatus = PR_Close(listenSocket);
+ if (prStatus != PR_SUCCESS) {
+ exitErr("PR_Close");
+ }
+ return SECSuccess;
+}
+
+/* Function: void server_main()
+ *
+ * Purpose: This is the server's main function. It configures a socket
+ * and listens to it.
+ *
+ */
+void
+server_main(
+ unsigned short port,
+ int requestCert,
+ SECKEYPrivateKey * privKey,
+ CERTCertificate * cert,
+ PRBool disableSSL3)
+{
+ SECStatus secStatus;
+ PRStatus prStatus;
+ PRFileDesc * listenSocket;
+ PRNetAddr addr;
+ PRSocketOptionData socketOption;
+
+ /* Create a new socket. */
+ listenSocket = PR_NewTCPSocket();
+ if (listenSocket == NULL) {
+ exitErr("PR_NewTCPSocket");
+ }
+
+ /* Set socket to be blocking -
+ * on some platforms the default is nonblocking.
+ */
+ socketOption.option = PR_SockOpt_Nonblocking;
+ socketOption.value.non_blocking = PR_FALSE;
+
+ prStatus = PR_SetSocketOption(listenSocket, &socketOption);
+ if (prStatus != PR_SUCCESS) {
+ exitErr("PR_SetSocketOption");
+ }
+
+ /* This cipher is not on by default. The Acceptance test
+ * would like it to be. Turn this cipher on.
+ */
+ secStatus = SSL_CipherPrefSetDefault(SSL_RSA_WITH_NULL_MD5, PR_TRUE);
+ if (secStatus != SECSuccess) {
+ exitErr("SSL_CipherPrefSetDefault:SSL_RSA_WITH_NULL_MD5");
+ }
+
+ /* Configure the network connection. */
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_INADDR_ANY;
+ addr.inet.port = PR_htons(port);
+
+ /* Bind the address to the listener socket. */
+ prStatus = PR_Bind(listenSocket, &addr);
+ if (prStatus != PR_SUCCESS) {
+ exitErr("PR_Bind");
+ }
+
+ /* Listen for connection on the socket. The second argument is
+ * the maximum size of the queue for pending connections.
+ */
+ prStatus = PR_Listen(listenSocket, 5);
+ if (prStatus != PR_SUCCESS) {
+ exitErr("PR_Listen");
+ }
+
+ /* Launch thread to handle connections to the socket. */
+ secStatus = launch_thread(&threadMGR, accept_connection,
+ listenSocket, requestCert);
+ if (secStatus != SECSuccess) {
+ PR_Close(listenSocket);
+ } else {
+ reap_threads(&threadMGR);
+ destroy_thread_data(&threadMGR);
+ }
+}
+
+/* Function: int main()
+ *
+ * Purpose: Parses command arguments and configures SSL server.
+ *
+ */
+int
+main(int argc, char **argv)
+{
+ char * progName = NULL;
+ char * nickName = NULL;
+ char * cipherString = NULL;
+ char * dir = ".";
+ int requestCert = 0;
+ unsigned short port = 0;
+ SECStatus secStatus;
+ PRBool disableSSL3 = PR_FALSE;
+ PLOptState * optstate;
+ PLOptStatus status;
+
+ /* Zero out the thread manager. */
+ PORT_Memset(&threadMGR, 0, sizeof(threadMGR));
+
+ progName = PL_strdup(argv[0]);
+
+ optstate = PL_CreateOptState(argc, argv, "3FRc:d:fp:n:rw:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch(optstate->option) {
+ case '3': disableSSL3 = PR_TRUE; break;
+ case 'F': requestCert = REQUIRE_CERT_ALL; break;
+ case 'R': requestCert = REQUEST_CERT_ALL; break;
+ case 'c': cipherString = PL_strdup(optstate->value); break;
+ case 'd': dir = PL_strdup(optstate->value); break;
+ case 'f': requestCert = REQUIRE_CERT_ONCE; break;
+ case 'n': nickName = PL_strdup(optstate->value); break;
+ case 'p': port = PORT_Atoi(optstate->value); break;
+ case 'r': requestCert = REQUEST_CERT_ONCE; break;
+ case 'w': password = PL_strdup(optstate->value); break;
+ default:
+ case '?': Usage(progName);
+ }
+ }
+
+ if (nickName == NULL || port == 0)
+ Usage(progName);
+
+ /* Call the NSPR initialization routines. */
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ /* Set the cert database password callback. */
+ PK11_SetPasswordFunc(myPasswd);
+
+ /* Initialize NSS. */
+ secStatus = NSS_Init(dir);
+ if (secStatus != SECSuccess) {
+ exitErr("NSS_Init");
+ }
+
+ /* Set the policy for this server (REQUIRED - no default). */
+ secStatus = NSS_SetDomesticPolicy();
+ if (secStatus != SECSuccess) {
+ exitErr("NSS_SetDomesticPolicy");
+ }
+
+ /* XXX keep this? */
+ /* all the SSL2 and SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ int ndx;
+
+ /* disable all the ciphers, then enable the ones we want. */
+ disableAllSSLCiphers();
+
+ while (0 != (ndx = *cipherString++)) {
+ int *cptr;
+ int cipher;
+
+ if (! isalpha(ndx))
+ Usage(progName);
+ cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
+ for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
+ /* do nothing */;
+ if (cipher) {
+ SECStatus status;
+ status = SSL_CipherPrefSetDefault(cipher, PR_TRUE);
+ if (status != SECSuccess)
+ errWarn("SSL_CipherPrefSetDefault()");
+ }
+ }
+ }
+
+ /* Get own certificate and private key. */
+ cert = PK11_FindCertFromNickname(nickName, password);
+ if (cert == NULL) {
+ exitErr("PK11_FindCertFromNickname");
+ }
+
+ privKey = PK11_FindKeyByAnyCert(cert, password);
+ if (privKey == NULL) {
+ exitErr("PK11_FindKeyByAnyCert");
+ }
+
+ /* Configure the server's cache for a multi-process application
+ * using default timeout values (24 hrs) and directory location (/tmp).
+ */
+ SSL_ConfigMPServerSIDCache(256, 0, 0, NULL);
+
+ /* Launch server. */
+ server_main(port, requestCert, privKey, cert, disableSSL3);
+
+ /* Shutdown NSS and exit NSPR gracefully. */
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ PR_Cleanup();
+ return 0;
+}
diff --git a/security/nss/cmd/SSLsample/server.mn b/security/nss/cmd/SSLsample/server.mn
new file mode 100644
index 000000000..3ce1181d9
--- /dev/null
+++ b/security/nss/cmd/SSLsample/server.mn
@@ -0,0 +1,48 @@
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+MODULE = nss
+
+EXPORTS =
+
+CSRCS = server.c \
+ sslsample.c \
+ $(NULL)
+
+PROGRAM = server
+
+REQUIRES = dbm
+
+DEFINES = -DNSPR20
+
diff --git a/security/nss/cmd/SSLsample/sslerror.h b/security/nss/cmd/SSLsample/sslerror.h
new file mode 100644
index 000000000..8ad908569
--- /dev/null
+++ b/security/nss/cmd/SSLsample/sslerror.h
@@ -0,0 +1,110 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "nspr.h"
+
+struct tuple_str {
+ PRErrorCode errNum;
+ const char * errString;
+};
+
+typedef struct tuple_str tuple_str;
+
+#define ER2(a,b) {a, b},
+#define ER3(a,b,c) {a, c},
+
+#include "secerr.h"
+#include "sslerr.h"
+
+const tuple_str errStrings[] = {
+
+/* keep this list in asceding order of error numbers */
+#include "SSLerrs.h"
+#include "SECerrs.h"
+#include "NSPRerrs.h"
+
+};
+
+const PRInt32 numStrings = sizeof(errStrings) / sizeof(tuple_str);
+
+/* Returns a UTF-8 encoded constant error string for "errNum".
+ * Returns NULL of errNum is unknown.
+ */
+const char *
+SSL_Strerror(PRErrorCode errNum) {
+ PRInt32 low = 0;
+ PRInt32 high = numStrings - 1;
+ PRInt32 i;
+ PRErrorCode num;
+ static int initDone;
+
+ /* make sure table is in ascending order.
+ * binary search depends on it.
+ */
+ if (!initDone) {
+ PRErrorCode lastNum = (PRInt32)0x80000000;
+ for (i = low; i <= high; ++i) {
+ num = errStrings[i].errNum;
+ if (num <= lastNum) {
+ fprintf(stderr,
+"sequence error in error strings at item %d\n"
+"error %d (%s)\n"
+"should come after \n"
+"error %d (%s)\n",
+ i, lastNum, errStrings[i-1].errString,
+ num, errStrings[i].errString);
+ }
+ lastNum = num;
+ }
+ initDone = 1;
+ }
+
+ /* Do binary search of table. */
+ while (low + 1 < high) {
+ i = (low + high) / 2;
+ num = errStrings[i].errNum;
+ if (errNum == num)
+ return errStrings[i].errString;
+ if (errNum < num)
+ high = i;
+ else
+ low = i;
+ }
+ if (errNum == errStrings[low].errNum)
+ return errStrings[low].errString;
+ if (errNum == errStrings[high].errNum)
+ return errStrings[high].errString;
+ return NULL;
+}
diff --git a/security/nss/cmd/SSLsample/sslsample.c b/security/nss/cmd/SSLsample/sslsample.c
new file mode 100644
index 000000000..5a25b940d
--- /dev/null
+++ b/security/nss/cmd/SSLsample/sslsample.c
@@ -0,0 +1,591 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "sslsample.h"
+#include "sslerror.h"
+
+/* Declare SSL cipher suites. */
+
+int ssl2CipherSuites[] = {
+ SSL_EN_RC4_128_WITH_MD5, /* A */
+ SSL_EN_RC4_128_EXPORT40_WITH_MD5, /* B */
+ SSL_EN_RC2_128_CBC_WITH_MD5, /* C */
+ SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */
+ SSL_EN_DES_64_CBC_WITH_MD5, /* E */
+ SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* F */
+ 0
+};
+
+int ssl3CipherSuites[] = {
+ SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* a */
+ SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, /* b */
+ SSL_RSA_WITH_RC4_128_MD5, /* c */
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
+ SSL_RSA_WITH_DES_CBC_SHA, /* e */
+ SSL_RSA_EXPORT_WITH_RC4_40_MD5, /* f */
+ SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* g */
+ SSL_FORTEZZA_DMS_WITH_NULL_SHA, /* h */
+ SSL_RSA_WITH_NULL_MD5, /* i */
+ SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, /* j */
+ SSL_RSA_FIPS_WITH_DES_CBC_SHA, /* k */
+ TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
+ TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, /* m */
+ 0
+};
+
+/**************************************************************************
+**
+** SSL callback routines.
+**
+**************************************************************************/
+
+/* Function: char * myPasswd()
+ *
+ * Purpose: This function is our custom password handler that is called by
+ * SSL when retreiving private certs and keys from the database. Returns a
+ * pointer to a string that with a password for the database. Password pointer
+ * should point to dynamically allocated memory that will be freed later.
+ */
+char *
+myPasswd(PK11SlotInfo *info, PRBool retry, void *arg)
+{
+ char * passwd = NULL;
+
+ if ( (!retry) && arg ) {
+ passwd = PORT_Strdup((char *)arg);
+ }
+
+ return passwd;
+}
+
+/* Function: SECStatus myAuthCertificate()
+ *
+ * Purpose: This function is our custom certificate authentication handler.
+ *
+ * Note: This implementation is essentially the same as the default
+ * SSL_AuthCertificate().
+ */
+SECStatus
+myAuthCertificate(void *arg, PRFileDesc *socket,
+ PRBool checksig, PRBool isServer)
+{
+
+ SECCertUsage certUsage;
+ CERTCertificate * cert;
+ void * pinArg;
+ char * hostName;
+ SECStatus secStatus;
+
+ if (!arg || !socket) {
+ errWarn("myAuthCertificate");
+ return SECFailure;
+ }
+
+ /* Define how the cert is being used based upon the isServer flag. */
+
+ certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
+
+ cert = SSL_PeerCertificate(socket);
+
+ pinArg = SSL_RevealPinArg(socket);
+
+ secStatus = CERT_VerifyCertNow((CERTCertDBHandle *)arg,
+ cert,
+ checksig,
+ certUsage,
+ pinArg);
+
+ /* If this is a server, we're finished. */
+ if (isServer || secStatus != SECSuccess) {
+ CERT_DestroyCertificate(cert);
+ return secStatus;
+ }
+
+ /* Certificate is OK. Since this is the client side of an SSL
+ * connection, we need to verify that the name field in the cert
+ * matches the desired hostname. This is our defense against
+ * man-in-the-middle attacks.
+ */
+
+ /* SSL_RevealURL returns a hostName, not an URL. */
+ hostName = SSL_RevealURL(socket);
+
+ if (hostName && hostName[0]) {
+ secStatus = CERT_VerifyCertName(cert, hostName);
+ } else {
+ PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0);
+ secStatus = SECFailure;
+ }
+
+ if (hostName)
+ PR_Free(hostName);
+
+ CERT_DestroyCertificate(cert);
+ return secStatus;
+}
+
+/* Function: SECStatus myBadCertHandler()
+ *
+ * Purpose: This callback is called when the incoming certificate is not
+ * valid. We define a certain set of parameters that still cause the
+ * certificate to be "valid" for this session, and return SECSuccess to cause
+ * the server to continue processing the request when any of these conditions
+ * are met. Otherwise, SECFailure is return and the server rejects the
+ * request.
+ */
+SECStatus
+myBadCertHandler(void *arg, PRFileDesc *socket)
+{
+
+ SECStatus secStatus = SECFailure;
+ PRErrorCode err;
+
+ /* log invalid cert here */
+
+ if (!arg) {
+ return secStatus;
+ }
+
+ *(PRErrorCode *)arg = err = PORT_GetError();
+
+ /* If any of the cases in the switch are met, then we will proceed */
+ /* with the processing of the request anyway. Otherwise, the default */
+ /* case will be reached and we will reject the request. */
+
+ switch (err) {
+ case SEC_ERROR_INVALID_AVA:
+ case SEC_ERROR_INVALID_TIME:
+ case SEC_ERROR_BAD_SIGNATURE:
+ case SEC_ERROR_EXPIRED_CERTIFICATE:
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ case SEC_ERROR_UNTRUSTED_CERT:
+ case SEC_ERROR_CERT_VALID:
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ case SEC_ERROR_CRL_EXPIRED:
+ case SEC_ERROR_CRL_BAD_SIGNATURE:
+ case SEC_ERROR_EXTENSION_VALUE_INVALID:
+ case SEC_ERROR_CA_CERT_INVALID:
+ case SEC_ERROR_CERT_USAGES_INVALID:
+ case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:
+ secStatus = SECSuccess;
+ break;
+ default:
+ secStatus = SECFailure;
+ break;
+ }
+
+ printf("Bad certificate: %d, %s\n", err, SSL_Strerror(err));
+
+ return secStatus;
+}
+
+/* Function: SECStatus ownGetClientAuthData()
+ *
+ * Purpose: This callback is used by SSL to pull client certificate
+ * information upon server request.
+ */
+SECStatus
+myGetClientAuthData(void *arg,
+ PRFileDesc *socket,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+
+ CERTCertificate * cert;
+ SECKEYPrivateKey * privKey;
+ char * chosenNickName = (char *)arg;
+ void * proto_win = NULL;
+ SECStatus secStatus = SECFailure;
+
+ proto_win = SSL_RevealPinArg(socket);
+
+ if (chosenNickName) {
+ cert = PK11_FindCertFromNickname(chosenNickName, proto_win);
+ if (cert) {
+ privKey = PK11_FindKeyByAnyCert(cert, proto_win);
+ if (privKey) {
+ secStatus = SECSuccess;
+ } else {
+ CERT_DestroyCertificate(cert);
+ }
+ }
+ } else { /* no nickname given, automatically find the right cert */
+ CERTCertNicknames *names;
+ int i;
+
+ names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
+ SEC_CERT_NICKNAMES_USER, proto_win);
+
+ if (names != NULL) {
+ for(i = 0; i < names->numnicknames; i++ ) {
+
+ cert = PK11_FindCertFromNickname(names->nicknames[i],
+ proto_win);
+ if (!cert) {
+ continue;
+ }
+
+ /* Only check unexpired certs */
+ if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE)
+ != secCertTimeValid ) {
+ CERT_DestroyCertificate(cert);
+ continue;
+ }
+
+ secStatus = NSS_CmpCertChainWCANames(cert, caNames);
+ if (secStatus == SECSuccess) {
+ privKey = PK11_FindKeyByAnyCert(cert, proto_win);
+ if (privKey) {
+ break;
+ }
+ secStatus = SECFailure;
+ break;
+ }
+ CERT_FreeNicknames(names);
+ } /* for loop */
+ }
+ }
+
+ if (secStatus == SECSuccess) {
+ *pRetCert = cert;
+ *pRetKey = privKey;
+ }
+
+ return secStatus;
+}
+
+/* Function: SECStatus myHandshakeCallback()
+ *
+ * Purpose: Called by SSL to inform application that the handshake is
+ * complete. This function is mostly used on the server side of an SSL
+ * connection, although it is provided for a client as well.
+ * Useful when a non-blocking SSL_ReHandshake or SSL_ResetHandshake
+ * is used to initiate a handshake.
+ *
+ * A typical scenario would be:
+ *
+ * 1. Server accepts an SSL connection from the client without client auth.
+ * 2. Client sends a request.
+ * 3. Server determines that to service request it needs to authenticate the
+ * client and initiates another handshake requesting client auth.
+ * 4. While handshake is in progress, server can do other work or spin waiting
+ * for the handshake to complete.
+ * 5. Server is notified that handshake has been successfully completed by
+ * the custom handshake callback function and it can service the client's
+ * request.
+ *
+ * Note: This function is not implemented in this sample, as we are using
+ * blocking sockets.
+ */
+SECStatus
+myHandshakeCallback(PRFileDesc *socket, void *arg)
+{
+ printf("Handshake has completed, ready to send data securely.\n");
+ return SECSuccess;
+}
+
+
+/**************************************************************************
+**
+** Routines for disabling SSL ciphers.
+**
+**************************************************************************/
+
+void
+disableAllSSLCiphers(void)
+{
+ const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
+ int i = SSL_NumImplementedCiphers;
+ SECStatus rv;
+
+ /* disable all the SSL3 cipher suites */
+ while (--i >= 0) {
+ PRUint16 suite = cipherSuites[i];
+ rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
+ if (rv != SECSuccess) {
+ printf("SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n",
+ suite, i);
+ errWarn("SSL_CipherPrefSetDefault");
+ exit(2);
+ }
+ }
+}
+
+/**************************************************************************
+**
+** Error and information routines.
+**
+**************************************************************************/
+
+void
+errWarn(char *function)
+{
+ PRErrorCode errorNumber = PR_GetError();
+ const char * errorString = SSL_Strerror(errorNumber);
+
+ printf("Error in function %s: %d\n - %s\n",
+ function, errorNumber, errorString);
+}
+
+void
+exitErr(char *function)
+{
+ errWarn(function);
+ /* Exit gracefully. */
+ /* ignoring return value of NSS_Shutdown as code exits with 1*/
+ (void) NSS_Shutdown();
+ PR_Cleanup();
+ exit(1);
+}
+
+void
+printSecurityInfo(PRFileDesc *fd)
+{
+ char * cp; /* bulk cipher name */
+ char * ip; /* cert issuer DN */
+ char * sp; /* cert subject DN */
+ int op; /* High, Low, Off */
+ int kp0; /* total key bits */
+ int kp1; /* secret key bits */
+ int result;
+ SSL3Statistics * ssl3stats = SSL_GetStatistics();
+
+ result = SSL_SecurityStatus(fd, &op, &cp, &kp0, &kp1, &ip, &sp);
+ if (result != SECSuccess)
+ return;
+ printf("bulk cipher %s, %d secret key bits, %d key bits, status: %d\n"
+ "subject DN: %s\n"
+ "issuer DN: %s\n", cp, kp1, kp0, op, sp, ip);
+ PR_Free(cp);
+ PR_Free(ip);
+ PR_Free(sp);
+
+ printf("%ld cache hits; %ld cache misses, %ld cache not reusable\n",
+ ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses,
+ ssl3stats->hch_sid_cache_not_ok);
+
+}
+
+
+/**************************************************************************
+** Begin thread management routines and data.
+**************************************************************************/
+
+void
+thread_wrapper(void * arg)
+{
+ GlobalThreadMgr *threadMGR = (GlobalThreadMgr *)arg;
+ perThread *slot = &threadMGR->threads[threadMGR->index];
+
+ /* wait for parent to finish launching us before proceeding. */
+ PR_Lock(threadMGR->threadLock);
+ PR_Unlock(threadMGR->threadLock);
+
+ slot->rv = (* slot->startFunc)(slot->a, slot->b);
+
+ PR_Lock(threadMGR->threadLock);
+ slot->running = rs_zombie;
+
+ /* notify the thread exit handler. */
+ PR_NotifyCondVar(threadMGR->threadEndQ);
+
+ PR_Unlock(threadMGR->threadLock);
+}
+
+SECStatus
+launch_thread(GlobalThreadMgr *threadMGR,
+ startFn *startFunc,
+ void *a,
+ int b)
+{
+ perThread *slot;
+ int i;
+
+ if (!threadMGR->threadStartQ) {
+ threadMGR->threadLock = PR_NewLock();
+ threadMGR->threadStartQ = PR_NewCondVar(threadMGR->threadLock);
+ threadMGR->threadEndQ = PR_NewCondVar(threadMGR->threadLock);
+ }
+ PR_Lock(threadMGR->threadLock);
+ while (threadMGR->numRunning >= MAX_THREADS) {
+ PR_WaitCondVar(threadMGR->threadStartQ, PR_INTERVAL_NO_TIMEOUT);
+ }
+ for (i = 0; i < threadMGR->numUsed; ++i) {
+ slot = &threadMGR->threads[i];
+ if (slot->running == rs_idle)
+ break;
+ }
+ if (i >= threadMGR->numUsed) {
+ if (i >= MAX_THREADS) {
+ /* something's really wrong here. */
+ PORT_Assert(i < MAX_THREADS);
+ PR_Unlock(threadMGR->threadLock);
+ return SECFailure;
+ }
+ ++(threadMGR->numUsed);
+ PORT_Assert(threadMGR->numUsed == i + 1);
+ slot = &threadMGR->threads[i];
+ }
+
+ slot->a = a;
+ slot->b = b;
+ slot->startFunc = startFunc;
+
+ threadMGR->index = i;
+
+ slot->prThread = PR_CreateThread(PR_USER_THREAD,
+ thread_wrapper, threadMGR,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD, 0);
+
+ if (slot->prThread == NULL) {
+ PR_Unlock(threadMGR->threadLock);
+ printf("Failed to launch thread!\n");
+ return SECFailure;
+ }
+
+ slot->inUse = 1;
+ slot->running = 1;
+ ++(threadMGR->numRunning);
+ PR_Unlock(threadMGR->threadLock);
+ printf("Launched thread in slot %d \n", threadMGR->index);
+
+ return SECSuccess;
+}
+
+SECStatus
+reap_threads(GlobalThreadMgr *threadMGR)
+{
+ perThread * slot;
+ int i;
+
+ if (!threadMGR->threadLock)
+ return 0;
+ PR_Lock(threadMGR->threadLock);
+ while (threadMGR->numRunning > 0) {
+ PR_WaitCondVar(threadMGR->threadEndQ, PR_INTERVAL_NO_TIMEOUT);
+ for (i = 0; i < threadMGR->numUsed; ++i) {
+ slot = &threadMGR->threads[i];
+ if (slot->running == rs_zombie) {
+ /* Handle cleanup of thread here. */
+ printf("Thread in slot %d returned %d\n", i, slot->rv);
+
+ /* Now make sure the thread has ended OK. */
+ PR_JoinThread(slot->prThread);
+ slot->running = rs_idle;
+ --threadMGR->numRunning;
+
+ /* notify the thread launcher. */
+ PR_NotifyCondVar(threadMGR->threadStartQ);
+ }
+ }
+ }
+
+ /* Safety Sam sez: make sure count is right. */
+ for (i = 0; i < threadMGR->numUsed; ++i) {
+ slot = &threadMGR->threads[i];
+ if (slot->running != rs_idle) {
+ fprintf(stderr, "Thread in slot %d is in state %d!\n",
+ i, slot->running);
+ }
+ }
+ PR_Unlock(threadMGR->threadLock);
+ return 0;
+}
+
+void
+destroy_thread_data(GlobalThreadMgr *threadMGR)
+{
+ PORT_Memset(threadMGR->threads, 0, sizeof(threadMGR->threads));
+
+ if (threadMGR->threadEndQ) {
+ PR_DestroyCondVar(threadMGR->threadEndQ);
+ threadMGR->threadEndQ = NULL;
+ }
+ if (threadMGR->threadStartQ) {
+ PR_DestroyCondVar(threadMGR->threadStartQ);
+ threadMGR->threadStartQ = NULL;
+ }
+ if (threadMGR->threadLock) {
+ PR_DestroyLock(threadMGR->threadLock);
+ threadMGR->threadLock = NULL;
+ }
+}
+
+/**************************************************************************
+** End thread management routines.
+**************************************************************************/
+
+void
+lockedVars_Init( lockedVars * lv)
+{
+ lv->count = 0;
+ lv->waiters = 0;
+ lv->lock = PR_NewLock();
+ lv->condVar = PR_NewCondVar(lv->lock);
+}
+
+void
+lockedVars_Destroy( lockedVars * lv)
+{
+ PR_DestroyCondVar(lv->condVar);
+ lv->condVar = NULL;
+
+ PR_DestroyLock(lv->lock);
+ lv->lock = NULL;
+}
+
+void
+lockedVars_WaitForDone(lockedVars * lv)
+{
+ PR_Lock(lv->lock);
+ while (lv->count > 0) {
+ PR_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(lv->lock);
+}
+
+int /* returns count */
+lockedVars_AddToCount(lockedVars * lv, int addend)
+{
+ int rv;
+
+ PR_Lock(lv->lock);
+ rv = lv->count += addend;
+ if (rv <= 0) {
+ PR_NotifyCondVar(lv->condVar);
+ }
+ PR_Unlock(lv->lock);
+ return rv;
+}
diff --git a/security/nss/cmd/SSLsample/sslsample.h b/security/nss/cmd/SSLsample/sslsample.h
new file mode 100644
index 000000000..ca6b6a489
--- /dev/null
+++ b/security/nss/cmd/SSLsample/sslsample.h
@@ -0,0 +1,178 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifndef SSLSAMPLE_H
+#define SSLSAMPLE_H
+
+/* Generic header files */
+
+#include <stdio.h>
+#include <string.h>
+
+/* NSPR header files */
+
+#include "nspr.h"
+#include "prerror.h"
+#include "prnetdb.h"
+
+/* NSS header files */
+
+#include "pk11func.h"
+#include "secitem.h"
+#include "ssl.h"
+#include "certt.h"
+#include "nss.h"
+#include "secrng.h"
+#include "secder.h"
+#include "key.h"
+#include "sslproto.h"
+
+/* Custom header files */
+
+/*
+#include "sslerror.h"
+*/
+
+#define BUFFER_SIZE 10240
+
+/* Declare SSL cipher suites. */
+
+extern int cipherSuites[];
+extern int ssl2CipherSuites[];
+extern int ssl3CipherSuites[];
+
+/* Data buffer read from a socket. */
+typedef struct DataBufferStr {
+ char data[BUFFER_SIZE];
+ int index;
+ int remaining;
+ int dataStart;
+ int dataEnd;
+} DataBuffer;
+
+/* SSL callback routines. */
+
+char * myPasswd(PK11SlotInfo *info, PRBool retry, void *arg);
+
+SECStatus myAuthCertificate(void *arg, PRFileDesc *socket,
+ PRBool checksig, PRBool isServer);
+
+SECStatus myBadCertHandler(void *arg, PRFileDesc *socket);
+
+SECStatus myHandshakeCallback(PRFileDesc *socket, void *arg);
+
+SECStatus myGetClientAuthData(void *arg, PRFileDesc *socket,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey);
+
+/* Disable all v2/v3 SSL ciphers. */
+
+void disableAllSSLCiphers(void);
+
+
+/* Error and information utilities. */
+
+void errWarn(char *function);
+
+void exitErr(char *function);
+
+void printSecurityInfo(PRFileDesc *fd);
+
+/* Some simple thread management routines. */
+
+#define MAX_THREADS 32
+
+typedef SECStatus startFn(void *a, int b);
+
+typedef enum { rs_idle = 0, rs_running = 1, rs_zombie = 2 } runState;
+
+typedef struct perThreadStr {
+ PRFileDesc *a;
+ int b;
+ int rv;
+ startFn *startFunc;
+ PRThread *prThread;
+ PRBool inUse;
+ runState running;
+} perThread;
+
+typedef struct GlobalThreadMgrStr {
+ PRLock *threadLock;
+ PRCondVar *threadStartQ;
+ PRCondVar *threadEndQ;
+ perThread threads[MAX_THREADS];
+ int index;
+ int numUsed;
+ int numRunning;
+} GlobalThreadMgr;
+
+void thread_wrapper(void * arg);
+
+SECStatus launch_thread(GlobalThreadMgr *threadMGR,
+ startFn *startFunc, void *a, int b);
+
+SECStatus reap_threads(GlobalThreadMgr *threadMGR);
+
+void destroy_thread_data(GlobalThreadMgr *threadMGR);
+
+/* Management of locked variables. */
+
+struct lockedVarsStr {
+ PRLock * lock;
+ int count;
+ int waiters;
+ PRCondVar * condVar;
+};
+
+typedef struct lockedVarsStr lockedVars;
+
+void lockedVars_Init(lockedVars *lv);
+
+void lockedVars_Destroy(lockedVars *lv);
+
+void lockedVars_WaitForDone(lockedVars *lv);
+
+int lockedVars_AddToCount(lockedVars *lv, int addend);
+
+/* Buffer stuff. */
+
+static const char stopCmd[] = { "GET /stop " };
+static const char defaultHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: SSL sample server\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+};
+
+#endif
diff --git a/security/nss/cmd/addbuiltin/Makefile b/security/nss/cmd/addbuiltin/Makefile
new file mode 100644
index 000000000..8650a607d
--- /dev/null
+++ b/security/nss/cmd/addbuiltin/Makefile
@@ -0,0 +1,76 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/addbuiltin/addbuiltin.c b/security/nss/cmd/addbuiltin/addbuiltin.c
new file mode 100644
index 000000000..86161c94a
--- /dev/null
+++ b/security/nss/cmd/addbuiltin/addbuiltin.c
@@ -0,0 +1,357 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * Tool for converting builtin CA certs.
+ *
+ * $Id$
+ */
+
+#include "nss.h"
+#include "cert.h"
+#include "certdb.h"
+#include "secutil.h"
+#include "pk11func.h"
+
+void dumpbytes(unsigned char *buf, int len)
+{
+ int i;
+ for (i=0; i < len; i++) {
+ if ((i !=0) && ((i & 0xf) == 0)) {
+ printf("\n");
+ }
+ printf("\\%03o",buf[i]);
+ }
+ printf("\n");
+}
+
+char *getTrustString(unsigned int trust)
+{
+ if (trust & CERTDB_TRUSTED) {
+ if (trust & CERTDB_TRUSTED_CA) {
+ return "CKT_NETSCAPE_TRUSTED_DELEGATOR|CKT_NETSCAPE_TRUSTED";
+ } else {
+ return "CKT_NETSCAPE_TRUSTED";
+ }
+ } else {
+ if (trust & CERTDB_TRUSTED_CA) {
+ return "CKT_NETSCAPE_TRUSTED_DELEGATOR";
+ } else {
+ return "CKT_NETSCAPE_VALID";
+ }
+ }
+ return "CKT_NETSCAPE_VALID"; /* not reached */
+}
+
+static const SEC_ASN1Template serialTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(CERTCertificate,serialNumber) },
+ { 0 }
+};
+
+static SECStatus
+ConvertCertificate(SECItem *sdder, char *nickname, CERTCertTrust *trust)
+{
+ SECStatus rv = SECSuccess;
+ CERTCertificate *cert;
+ unsigned char sha1_hash[SHA1_LENGTH];
+ unsigned char md5_hash[MD5_LENGTH];
+ SECItem *serial = NULL;
+
+ cert = CERT_DecodeDERCertificate(sdder, PR_FALSE, nickname);
+ if (!cert) {
+ return SECFailure;
+ }
+ serial = SEC_ASN1EncodeItem(NULL,NULL,cert,serialTemplate);
+ if (!serial) {
+ return SECFailure;
+ }
+
+ printf("\n#\n# Certificate \"%s\"\n#\n",nickname);
+ printf("CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE\n");
+ printf("CKA_TOKEN CK_BBOOL CK_TRUE\n");
+ printf("CKA_PRIVATE CK_BBOOL CK_FALSE\n");
+ printf("CKA_MODIFIABLE CK_BBOOL CK_FALSE\n");
+ printf("CKA_LABEL UTF8 \"%s\"\n",nickname);
+ printf("CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509\n");
+ printf("CKA_SUBJECT MULTILINE_OCTAL\n");
+ dumpbytes(cert->derSubject.data,cert->derSubject.len);
+ printf("END\n");
+ printf("CKA_ID UTF8 \"0\"\n");
+ printf("CKA_ISSUER MULTILINE_OCTAL\n");
+ dumpbytes(cert->derIssuer.data,cert->derIssuer.len);
+ printf("END\n");
+ printf("CKA_SERIAL_NUMBER MULTILINE_OCTAL\n");
+ dumpbytes(serial->data,serial->len);
+ printf("END\n");
+ printf("CKA_VALUE MULTILINE_OCTAL\n");
+ dumpbytes(sdder->data,sdder->len);
+ printf("END\n");
+
+ PK11_HashBuf(SEC_OID_SHA1, sha1_hash, sdder->data, sdder->len);
+ PK11_HashBuf(SEC_OID_MD5, md5_hash, sdder->data, sdder->len);
+ printf("\n# Trust for Certificate \"%s\"\n",nickname);
+ printf("CKA_CLASS CK_OBJECT_CLASS CKO_NETSCAPE_TRUST\n");
+ printf("CKA_TOKEN CK_BBOOL CK_TRUE\n");
+ printf("CKA_PRIVATE CK_BBOOL CK_FALSE\n");
+ printf("CKA_MODIFIABLE CK_BBOOL CK_FALSE\n");
+ printf("CKA_LABEL UTF8 \"%s\"\n",nickname);
+ printf("CKA_CERT_SHA1_HASH MULTILINE_OCTAL\n");
+ dumpbytes(sha1_hash,SHA1_LENGTH);
+ printf("END\n");
+ printf("CKA_CERT_MD5_HASH MULTILINE_OCTAL\n");
+ dumpbytes(md5_hash,MD5_LENGTH);
+ printf("END\n");
+
+ printf("CKA_ISSUER MULTILINE_OCTAL\n");
+ dumpbytes(cert->derIssuer.data,cert->derIssuer.len);
+ printf("END\n");
+ printf("CKA_SERIAL_NUMBER MULTILINE_OCTAL\n");
+ dumpbytes(serial->data,serial->len);
+ printf("END\n");
+
+ printf("CKA_TRUST_SERVER_AUTH CK_TRUST %s\n",
+ getTrustString(trust->sslFlags));
+ printf("CKA_TRUST_EMAIL_PROTECTION CK_TRUST %s\n",
+ getTrustString(trust->emailFlags));
+ printf("CKA_TRUST_CODE_SIGNING CK_TRUST %s\n",
+ getTrustString(trust->objectSigningFlags));
+#ifdef notdef
+ printf("CKA_TRUST_CLIENT_AUTH CK_TRUST CKT_NETSCAPE_TRUSTED\n");*/
+ printf("CKA_TRUST_DIGITAL_SIGNATURE CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR\n");
+ printf("CKA_TRUST_NON_REPUDIATION CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR\n");
+ printf("CKA_TRUST_KEY_ENCIPHERMENT CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR\n");
+ printf("CKA_TRUST_DATA_ENCIPHERMENT CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR\n");
+ printf("CKA_TRUST_KEY_AGREEMENT CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR\n");
+ printf("CKA_TRUST_KEY_CERT_SIGN CK_TRUST CKT_NETSCAPE_TRUSTED_DELEGATOR\n");
+#endif
+
+
+ PORT_Free(sdder->data);
+ return(rv);
+
+}
+
+printheader() {
+ printf("# \n"
+ "# The contents of this file are subject to the Mozilla Public\n"
+ "# License Version 1.1 (the \"License\"); you may not use this file\n"
+ "# except in compliance with the License. You may obtain a copy of\n"
+ "# the License at http://www.mozilla.org/MPL/\n"
+ "# \n"
+ "# Software distributed under the License is distributed on an \"AS\n"
+ "# IS\" basis, WITHOUT WARRANTY OF ANY KIND, either express or\n"
+ "# implied. See the License for the specific language governing\n"
+ "# rights and limitations under the License.\n"
+ "# \n"
+ "# The Original Code is the Netscape security libraries.\n"
+ "# \n"
+ "# The Initial Developer of the Original Code is Netscape\n"
+ "# Communications Corporation. Portions created by Netscape are \n"
+ "# Copyright (C) 1994-2000 Netscape Communications Corporation. All\n"
+ "# Rights Reserved.\n"
+ "# \n"
+ "# Contributor(s):\n"
+ "# \n"
+ "# Alternatively, the contents of this file may be used under the\n"
+ "# terms of the GNU General Public License Version 2 or later (the\n"
+ "# \"GPL\"), in which case the provisions of the GPL are applicable \n"
+ "# instead of those above. If you wish to allow use of your \n"
+ "# version of this file only under the terms of the GPL and not to\n"
+ "# allow others to use your version of this file under the MPL,\n"
+ "# indicate your decision by deleting the provisions above and\n"
+ "# replace them with the notice and other provisions required by\n"
+ "# the GPL. If you do not delete the provisions above, a recipient\n"
+ "# may use your version of this file under either the MPL or the\n"
+ "# GPL.\n"
+ "#\n"
+ "CVS_ID \"@(#) $RCSfile$ $Revision$ $Date$ $Name$\"\n"
+ "\n"
+ "#\n"
+ "# certdata.txt\n"
+ "#\n"
+ "# This file contains the object definitions for the certs and other\n"
+ "# information \"built into\" NSS.\n"
+ "#\n"
+ "# Object definitions:\n"
+ "#\n"
+ "# Certificates\n"
+ "#\n"
+ "# -- Attribute -- -- type -- -- value --\n"
+ "# CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE\n"
+ "# CKA_TOKEN CK_BBOOL CK_TRUE\n"
+ "# CKA_PRIVATE CK_BBOOL CK_FALSE\n"
+ "# CKA_MODIFIABLE CK_BBOOL CK_FALSE\n"
+ "# CKA_LABEL UTF8 (varies)\n"
+ "# CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509\n"
+ "# CKA_SUBJECT DER+base64 (varies)\n"
+ "# CKA_ID byte array (varies)\n"
+ "# CKA_ISSUER DER+base64 (varies)\n"
+ "# CKA_SERIAL_NUMBER DER+base64 (varies)\n"
+ "# CKA_VALUE DER+base64 (varies)\n"
+ "# CKA_NETSCAPE_EMAIL ASCII7 (unused here)\n"
+ "#\n"
+ "# Trust\n"
+ "#\n"
+ "# -- Attribute -- -- type -- -- value --\n"
+ "# CKA_CLASS CK_OBJECT_CLASS CKO_TRUST\n"
+ "# CKA_TOKEN CK_BBOOL CK_TRUE\n"
+ "# CKA_PRIVATE CK_BBOOL CK_FALSE\n"
+ "# CKA_MODIFIABLE CK_BBOOL CK_FALSE\n"
+ "# CKA_LABEL UTF8 (varies)\n"
+ "# CKA_ISSUER DER+base64 (varies)\n"
+ "# CKA_SERIAL_NUMBER DER+base64 (varies)\n"
+ "# CKA_CERT_HASH binary+base64 (varies)\n"
+ "# CKA_EXPIRES CK_DATE (not used here)\n"
+ "# CKA_TRUST_DIGITAL_SIGNATURE CK_TRUST (varies)\n"
+ "# CKA_TRUST_NON_REPUDIATION CK_TRUST (varies)\n"
+ "# CKA_TRUST_KEY_ENCIPHERMENT CK_TRUST (varies)\n"
+ "# CKA_TRUST_DATA_ENCIPHERMENT CK_TRUST (varies)\n"
+ "# CKA_TRUST_KEY_AGREEMENT CK_TRUST (varies)\n"
+ "# CKA_TRUST_KEY_CERT_SIGN CK_TRUST (varies)\n"
+ "# CKA_TRUST_CRL_SIGN CK_TRUST (varies)\n"
+ "# CKA_TRUST_SERVER_AUTH CK_TRUST (varies)\n"
+ "# CKA_TRUST_CLIENT_AUTH CK_TRUST (varies)\n"
+ "# CKA_TRUST_CODE_SIGNING CK_TRUST (varies)\n"
+ "# CKA_TRUST_EMAIL_PROTECTION CK_TRUST (varies)\n"
+ "# CKA_TRUST_IPSEC_END_SYSTEM CK_TRUST (varies)\n"
+ "# CKA_TRUST_IPSEC_TUNNEL CK_TRUST (varies)\n"
+ "# CKA_TRUST_IPSEC_USER CK_TRUST (varies)\n"
+ "# CKA_TRUST_TIME_STAMPING CK_TRUST (varies)\n"
+ "# (other trust attributes can be defined)\n"
+ "#\n"
+ "\n"
+ "#\n"
+ "# The object to tell NSS that this is a root list and we don't\n"
+ "# have to go looking for others.\n"
+ "#\n"
+ "BEGINDATA\n"
+ "CKA_CLASS CK_OBJECT_CLASS CKO_NETSCAPE_BUILTIN_ROOT_LIST\n"
+ "CKA_TOKEN CK_BBOOL CK_TRUE\n"
+ "CKA_PRIVATE CK_BBOOL CK_FALSE\n"
+ "CKA_MODIFIABLE CK_BBOOL CK_FALSE\n"
+ "CKA_LABEL UTF8 \"Mozilla Builtin Roots\"\n");
+}
+
+static void Usage(char *progName)
+{
+ fprintf(stderr, "%s -n nickname -t trust\n", progName);
+ fprintf(stderr,
+ "read a der-encoded cert from stdin in, and output\n"
+ "it to stdout in a format suitable for the builtin root module.\n"
+ "example: %s -n MyCA -t \"C,C,C\" < myca.der >> certdata.txt\n"
+ "(pipe through atob if the cert is b64-encoded)\n");
+ fprintf(stderr, "%15s nickname to assign to builtin cert.\n",
+ "-n nickname");
+ fprintf(stderr, "%15s default trust flags (cCTpPuw).\n",
+ "-t trust");
+ exit(-1);
+}
+
+enum {
+ opt_Input = 0,
+ opt_Nickname,
+ opt_Trust
+};
+
+static secuCommandFlag addbuiltin_options[] =
+{
+ { /* opt_Input */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Trust */ 't', PR_TRUE, 0, PR_FALSE }
+};
+
+main(int argc, char **argv)
+{
+ SECStatus rv;
+ char *nickname;
+ char *trusts;
+ char *progName;
+ PRFileDesc *infile;
+ CERTCertTrust trust = { 0 };
+ SECItem derCert = { 0 };
+
+ secuCommand addbuiltin = { 0 };
+ addbuiltin.numOptions = sizeof(addbuiltin_options)/sizeof(secuCommandFlag);
+ addbuiltin.options = addbuiltin_options;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &addbuiltin);
+
+ if (rv != SECSuccess)
+ Usage(progName);
+
+ if (!addbuiltin.options[opt_Nickname].activated &&
+ !addbuiltin.options[opt_Trust].activated) {
+ fprintf(stderr, "%s: you must specify both a nickname and trust.\n");
+ Usage(progName);
+ }
+
+ if (addbuiltin.options[opt_Input].activated) {
+ infile = PR_Open(addbuiltin.options[opt_Input].arg, PR_RDONLY, 00660);
+ if (!infile) {
+ fprintf(stderr, "%s: failed to open input file.\n");
+ exit(1);
+ }
+ } else {
+ infile = PR_STDIN;
+ }
+
+ nickname = strdup(addbuiltin.options[opt_Nickname].arg);
+ trusts = strdup(addbuiltin.options[opt_Trust].arg);
+
+ NSS_NoDB_Init(NULL);
+
+ rv = CERT_DecodeTrustString(&trust, trusts);
+ if (rv) {
+ fprintf(stderr, "%s: incorrectly formatted trust string.\n", progName);
+ Usage(progName);
+ }
+
+ SECU_FileToItem(&derCert, infile);
+
+ /*printheader();*/
+
+ rv = ConvertCertificate(&derCert, nickname, &trust);
+ if (rv) {
+ fprintf(stderr, "%s: failed to convert certificate.\n", progName);
+ exit(1);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return(SECSuccess);
+}
diff --git a/security/nss/cmd/addbuiltin/manifest.mn b/security/nss/cmd/addbuiltin/manifest.mn
new file mode 100644
index 000000000..b800ed92a
--- /dev/null
+++ b/security/nss/cmd/addbuiltin/manifest.mn
@@ -0,0 +1,49 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ addbuiltin.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = dbm seccmd
+
+PROGRAM = addbuiltin
+
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/atob/Makefile b/security/nss/cmd/atob/Makefile
new file mode 100644
index 000000000..ff6f06e7e
--- /dev/null
+++ b/security/nss/cmd/atob/Makefile
@@ -0,0 +1,76 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/atob/atob.c b/security/nss/cmd/atob/atob.c
new file mode 100644
index 000000000..8d632b6bf
--- /dev/null
+++ b/security/nss/cmd/atob/atob.c
@@ -0,0 +1,177 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "plgetopt.h"
+#include "secutil.h"
+#include "nssb64.h"
+#include <errno.h>
+
+#if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
+#if !defined(WIN32)
+extern int fread(char *, size_t, size_t, FILE*);
+extern int fwrite(char *, size_t, size_t, FILE*);
+extern int fprintf(FILE *, char *, ...);
+#endif
+#endif
+
+#if defined(WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+static PRInt32
+output_binary (void *arg, const unsigned char *obuf, PRInt32 size)
+{
+ FILE *outFile = arg;
+ int nb;
+
+ nb = fwrite(obuf, 1, size, outFile);
+ if (nb != size) {
+ PORT_SetError(SEC_ERROR_IO);
+ return -1;
+ }
+
+ return nb;
+}
+
+static SECStatus
+decode_file(FILE *outFile, FILE *inFile)
+{
+ NSSBase64Decoder *cx;
+ int nb;
+ SECStatus status = SECFailure;
+ char ibuf[4096];
+
+ cx = NSSBase64Decoder_Create(output_binary, outFile);
+ if (!cx) {
+ return -1;
+ }
+
+ for (;;) {
+ if (feof(inFile)) break;
+ nb = fread(ibuf, 1, sizeof(ibuf), inFile);
+ if (nb != sizeof(ibuf)) {
+ if (nb == 0) {
+ if (ferror(inFile)) {
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
+ }
+ /* eof */
+ break;
+ }
+ }
+
+ status = NSSBase64Decoder_Update(cx, ibuf, nb);
+ if (status != SECSuccess) goto loser;
+ }
+
+ return NSSBase64Decoder_Destroy(cx, PR_FALSE);
+
+ loser:
+ (void) NSSBase64Decoder_Destroy(cx, PR_TRUE);
+ return status;
+}
+
+static void Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+ char *progName;
+ SECStatus rv;
+ FILE *inFile, *outFile;
+ PLOptState *optstate;
+ PLOptStatus status;
+
+ inFile = 0;
+ outFile = 0;
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ /* Parse command line arguments */
+ optstate = PL_CreateOptState(argc, argv, "i:o:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'i':
+ inFile = fopen(optstate->value, "r");
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "wb");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+ }
+ }
+ if (!inFile) inFile = stdin;
+ if (!outFile) {
+#if defined(WIN32)
+ int smrv = _setmode(_fileno(stdout), _O_BINARY);
+ if (smrv == -1) {
+ fprintf(stderr,
+ "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
+ progName);
+ return smrv;
+ }
+#endif
+ outFile = stdout;
+ }
+ rv = decode_file(outFile, inFile);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
+ progName, PORT_GetError(), errno);
+ return -1;
+ }
+ return 0;
+}
diff --git a/security/nss/cmd/atob/makefile.win b/security/nss/cmd/atob/makefile.win
new file mode 100644
index 000000000..ecccc7bf3
--- /dev/null
+++ b/security/nss/cmd/atob/makefile.win
@@ -0,0 +1,155 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+#cannot define PROGRAM in manifest compatibly with NT and UNIX
+PROGRAM = atob
+PROGRAM = ./$(OBJDIR)/$(PROGRAM).exe
+include <$(DEPTH)\config\config.mak>
+
+# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
+# rules.mak will append C_OBJS onto OBJS.
+# OBJS = $(CSRCS:.c=.obj)
+
+# include files are looked for in $LINCS and $INCS.
+# $LINCS is in manifest.mnw, computed from REQUIRES=
+INCS = $(INCS) \
+ -I$(DEPTH)/security/lib/cert \
+ -I../include \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+ $(NULL)
+
+
+WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
+
+# these files are the content of libdbm
+DBM_LIB = \
+ $(WINFE)/DB.obj \
+ $(WINFE)/HASH.obj \
+ $(WINFE)/H_BIGKEY.obj \
+ $(WINFE)/H_PAGE.obj \
+ $(WINFE)/H_LOG2.obj \
+ $(WINFE)/H_FUNC.obj \
+ $(WINFE)/HASH_BUF.obj \
+ $(NULL)
+
+MOZ_LIBS = \
+ $(WINFE)/ALLXPSTR.obj \
+ $(WINFE)/XP_ERROR.obj \
+ $(WINFE)/XPASSERT.obj \
+ $(WINFE)/XP_REG.obj \
+ $(WINFE)/XP_TRACE.obj \
+ $(DBM_LIB) \
+ $(WINFE)/XP_STR.obj \
+ $(WINFE)/MKTEMP.obj \
+ $(NULL)
+
+SEC_LIBS = \
+ $(DIST)/lib/cert$(MOZ_BITS).lib \
+ $(DIST)/lib/crypto$(MOZ_BITS).lib \
+ $(DIST)/lib/hash$(MOZ_BITS).lib \
+ $(DIST)/lib/key$(MOZ_BITS).lib \
+ $(DIST)/lib/pkcs7$(MOZ_BITS).lib \
+ $(DIST)/lib/secmod$(MOZ_BITS).lib \
+ $(DIST)/lib/secutl$(MOZ_BITS).lib \
+ $(DIST)/lib/ssl$(MOZ_BITS).lib \
+ $(NULL)
+
+LLFLAGS = $(LLFLAGS) \
+ ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
+ $(SEC_LIBS) \
+ $(MOZ_LIBS) \
+ $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
+ $(LIBNSPR) \
+ $(NULL)
+
+
+# awt3240.lib # brpref32.lib # cert32.lib
+# crypto32.lib # dllcom.lib # editor32.lib
+# edpref32.lib # edtplug.lib # font.lib
+# hash32.lib # htmldg32.lib # img32.lib
+# javart32.lib # jbn3240.lib # jdb3240.lib
+# jmc.lib # jpeg3240.lib # jpw3240.lib
+# jrt3240.lib # js3240.lib # jsd3240.lib
+# key32.lib # libapplet32.lib # libnjs32.lib
+# libnsc32.lib # libreg32.lib # mm3240.lib
+# mnpref32.lib # netcst32.lib # nsdlg32.lib
+# nsldap32.lib # nsldaps32.lib # nsn32.lib
+# pkcs1232.lib # pkcs732.lib # pr3240.lib
+# prefui32.lib # prefuuid.lib # secmod32.lib
+# secnav32.lib # secutl32.lib # softup32.lib
+# sp3240.lib # ssl32.lib # uni3200.lib
+# unicvt32.lib # win32md.lib # winfont.lib
+# xppref32.lib # zlib32.lib
+
+include <$(DEPTH)\config\rules.mak>
+
+INSTALL = $(MAKE_INSTALL)
+
+objs: $(OBJS)
+
+$(PROGRAM)::
+ $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
+
+programs: $(PROGRAM)
+
+install:: $(TARGETS)
+ $(INSTALL) $(TARGETS) $(DIST)/bin
+
+# ALLXPSTR.obj XP_ALLOC.obj XP_HASH.obj XP_RGB.obj XP_WRAP.obj
+# CXPRINT.obj XP_C.cl XP_LIST.obj XP_SEC.obj netscape.exp
+# CXPRNDLG.obj XP_CNTXT.obj XP_MD5.obj XP_STR.obj xp.pch
+# EXPORT.obj XP_CORE.obj XP_MESG.obj XP_THRMO.obj xppref32.dll
+# XPASSERT.obj XP_ERROR.obj XP_RECT.obj XP_TIME.obj
+# XPLOCALE.obj XP_FILE.obj XP_REG.obj XP_TRACE.obj
+
+
+symbols:
+ @echo "CSRCS = $(CSRCS)"
+ @echo "INCS = $(INCS)"
+ @echo "OBJS = $(OBJS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "TARGETS = $(TARGETS)"
+ @echo "DIST = $(DIST)"
+ @echo "VERSION_NUMBER = $(VERSION_NUMBER)"
+ @echo "WINFE = $(WINFE)"
+ @echo "DBM_LIB = $(DBM_LIB)"
+ @echo "INSTALL = $(INSTALL)"
+
diff --git a/security/nss/cmd/atob/manifest.mn b/security/nss/cmd/atob/manifest.mn
new file mode 100644
index 000000000..f6c20bf19
--- /dev/null
+++ b/security/nss/cmd/atob/manifest.mn
@@ -0,0 +1,50 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = atob.c
+
+PROGRAM = atob
+
diff --git a/security/nss/cmd/bltest/Makefile b/security/nss/cmd/bltest/Makefile
new file mode 100644
index 000000000..c99a3c017
--- /dev/null
+++ b/security/nss/cmd/bltest/Makefile
@@ -0,0 +1,82 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+#MKPROG = purify -cache-dir=/u/mcgreer/pcache -best-effort \
+# -always-use-cache-dir $(CC)
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#EXTRA_SHARED_LIBS += \
+# -L/usr/lib \
+# -lposix4 \
+# $(NULL)
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/bltest/blapitest.c b/security/nss/cmd/bltest/blapitest.c
new file mode 100644
index 000000000..b3000b257
--- /dev/null
+++ b/security/nss/cmd/bltest/blapitest.c
@@ -0,0 +1,2572 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "blapi.h"
+#include "secrng.h"
+#include "prmem.h"
+#include "prprf.h"
+#include "prtime.h"
+#include "prsystem.h"
+#include "plstr.h"
+#include "nssb64.h"
+#include "secutil.h"
+#include "plgetopt.h"
+#include "softoken.h"
+#include "nss.h"
+
+/* Temporary - add debugging ouput on windows for RSA to track QA failure */
+#ifdef _WIN32
+#define TRACK_BLTEST_BUG
+ char __bltDBG[] = "BLTEST DEBUG";
+#endif
+
+char *progName;
+char *testdir = NULL;
+
+#define BLTEST_DEFAULT_CHUNKSIZE 4096
+
+#define WORDSIZE sizeof(unsigned long)
+
+#define CHECKERROR(rv, ln) \
+ if (rv) { \
+ PRErrorCode prerror = PR_GetError(); \
+ PR_fprintf(PR_STDERR, "%s: ERR %d (%s) at line %d.\n", progName, \
+ prerror, SECU_Strerror(prerror), ln); \
+ exit(-1); \
+ }
+
+/* Macros for performance timing. */
+#define TIMESTART() \
+ time1 = PR_IntervalNow();
+
+#define TIMEFINISH(time, reps) \
+ time2 = (PRIntervalTime)(PR_IntervalNow() - time1); \
+ time1 = PR_IntervalToMilliseconds(time2); \
+ time = ((double)(time1))/reps;
+
+static void Usage()
+{
+#define PRINTUSAGE(subject, option, predicate) \
+ fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate);
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "[-DEHSV]", "List available cipher modes"); /* XXX */
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-E -m mode ", "Encrypt a buffer");
+ PRINTUSAGE("", "", "[-i plaintext] [-o ciphertext] [-k key] [-v iv]");
+ PRINTUSAGE("", "", "[-b bufsize] [-g keysize] [-e exp] [-r rounds]");
+ PRINTUSAGE("", "", "[-w wordsize] [-p repetitions]");
+ PRINTUSAGE("", "-m", "cipher mode to use");
+ PRINTUSAGE("", "-i", "file which contains input buffer");
+ PRINTUSAGE("", "-o", "file for output buffer");
+ PRINTUSAGE("", "-k", "file which contains key");
+ PRINTUSAGE("", "-v", "file which contains initialization vector");
+ PRINTUSAGE("", "-b", "size of input buffer");
+ PRINTUSAGE("", "-g", "key size (in bytes)");
+ PRINTUSAGE("", "-p", "do performance test");
+ PRINTUSAGE("(rsa)", "-e", "rsa public exponent");
+ PRINTUSAGE("(rc5)", "-r", "number of rounds");
+ PRINTUSAGE("(rc5)", "-w", "wordsize (32 or 64)");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-D -m mode", "Decrypt a buffer");
+ PRINTUSAGE("", "", "[-i plaintext] [-o ciphertext] [-k key] [-v iv]");
+ PRINTUSAGE("", "", "[-p repetitions]");
+ PRINTUSAGE("", "-m", "cipher mode to use");
+ PRINTUSAGE("", "-i", "file which contains input buffer");
+ PRINTUSAGE("", "-o", "file for output buffer");
+ PRINTUSAGE("", "-k", "file which contains key");
+ PRINTUSAGE("", "-v", "file which contains initialization vector");
+ PRINTUSAGE("", "-p", "do performance test");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-H -m mode", "Hash a buffer");
+ PRINTUSAGE("", "", "[-i plaintext] [-o hash]");
+ PRINTUSAGE("", "", "[-b bufsize]");
+ PRINTUSAGE("", "", "[-p repetitions]");
+ PRINTUSAGE("", "-m", "cipher mode to use");
+ PRINTUSAGE("", "-i", "file which contains input buffer");
+ PRINTUSAGE("", "-o", "file for hash");
+ PRINTUSAGE("", "-b", "size of input buffer");
+ PRINTUSAGE("", "-p", "do performance test");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-S -m mode", "Sign a buffer");
+ PRINTUSAGE("", "", "[-i plaintext] [-o signature] [-k key]");
+ PRINTUSAGE("", "", "[-b bufsize]");
+ PRINTUSAGE("", "", "[-p repetitions]");
+ PRINTUSAGE("", "-m", "cipher mode to use");
+ PRINTUSAGE("", "-i", "file which contains input buffer");
+ PRINTUSAGE("", "-o", "file for signature");
+ PRINTUSAGE("", "-k", "file which contains key");
+ PRINTUSAGE("", "-p", "do performance test");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-V -m mode", "Verify a signed buffer");
+ PRINTUSAGE("", "", "[-i plaintext] [-s signature] [-k key]");
+ PRINTUSAGE("", "", "[-p repetitions]");
+ PRINTUSAGE("", "-m", "cipher mode to use");
+ PRINTUSAGE("", "-i", "file which contains input buffer");
+ PRINTUSAGE("", "-s", "file which contains signature of input buffer");
+ PRINTUSAGE("", "-k", "file which contains key");
+ PRINTUSAGE("", "-p", "do performance test");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-N -m mode -b bufsize",
+ "Create a nonce plaintext and key");
+ PRINTUSAGE("", "", "[-g keysize] [-u cxreps]");
+ PRINTUSAGE("", "-g", "key size (in bytes)");
+ PRINTUSAGE("", "-u", "number of repetitions of context creation");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-F", "Run the FIPS self-test");
+ fprintf(stderr, "\n");
+ PRINTUSAGE(progName, "-T [-m mode1,mode2...]", "Run the BLAPI self-test");
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+/* Helper functions for ascii<-->binary conversion/reading/writing */
+
+/* XXX argh */
+struct item_with_arena {
+ SECItem *item;
+ PRArenaPool *arena;
+};
+
+static PRInt32
+get_binary(void *arg, const unsigned char *ibuf, PRInt32 size)
+{
+ struct item_with_arena *it = arg;
+ SECItem *binary = it->item;
+ SECItem *tmp;
+ int index;
+ if (binary->data == NULL) {
+ tmp = SECITEM_AllocItem(it->arena, NULL, size);
+ binary->data = tmp->data;
+ binary->len = tmp->len;
+ index = 0;
+ } else {
+ SECITEM_ReallocItem(NULL, binary, binary->len, binary->len + size);
+ index = binary->len;
+ }
+ PORT_Memcpy(&binary->data[index], ibuf, size);
+ return binary->len;
+}
+
+static SECStatus
+atob(SECItem *ascii, SECItem *binary, PRArenaPool *arena)
+{
+ SECStatus status;
+ NSSBase64Decoder *cx;
+ struct item_with_arena it;
+ int len;
+ binary->data = NULL;
+ binary->len = 0;
+ it.item = binary;
+ it.arena = arena;
+ len = (strcmp(&ascii->data[ascii->len-2],"\r\n")) ?
+ ascii->len : ascii->len-2;
+ cx = NSSBase64Decoder_Create(get_binary, &it);
+ status = NSSBase64Decoder_Update(cx, (const char *)ascii->data, len);
+ status = NSSBase64Decoder_Destroy(cx, PR_FALSE);
+ return status;
+}
+
+static PRInt32
+output_ascii(void *arg, const char *obuf, PRInt32 size)
+{
+ PRFileDesc *outfile = arg;
+ PRInt32 nb = PR_Write(outfile, obuf, size);
+ if (nb != size) {
+ PORT_SetError(SEC_ERROR_IO);
+ return -1;
+ }
+ return nb;
+}
+
+static SECStatus
+btoa_file(SECItem *binary, PRFileDesc *outfile)
+{
+ SECStatus status;
+ NSSBase64Encoder *cx;
+ SECItem ascii;
+ ascii.data = NULL;
+ ascii.len = 0;
+ if (binary->len == 0)
+ return SECSuccess;
+ cx = NSSBase64Encoder_Create(output_ascii, outfile);
+ status = NSSBase64Encoder_Update(cx, binary->data, binary->len);
+ status = NSSBase64Encoder_Destroy(cx, PR_FALSE);
+ status = PR_Write(outfile, "\r\n", 2);
+ return status;
+}
+
+SECStatus
+hex_from_2char(unsigned char *c2, unsigned char *byteval)
+{
+ int i;
+ unsigned char offset;
+ *byteval = 0;
+ for (i=0; i<2; i++) {
+ if (c2[i] >= '0' && c2[i] <= '9') {
+ offset = c2[i] - '0';
+ *byteval |= offset << 4*(1-i);
+ } else if (c2[i] >= 'a' && c2[i] <= 'f') {
+ offset = c2[i] - 'a';
+ *byteval |= (offset + 10) << 4*(1-i);
+ } else if (c2[i] >= 'A' && c2[i] <= 'F') {
+ offset = c2[i] - 'A';
+ *byteval |= (offset + 10) << 4*(1-i);
+ } else {
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+}
+
+SECStatus
+char2_from_hex(unsigned char byteval, unsigned char *c2)
+{
+ int i;
+ unsigned char offset;
+ for (i=0; i<2; i++) {
+ offset = (byteval >> 4*(1-i)) & 0x0f;
+ if (offset < 10) {
+ c2[i] = '0' + offset;
+ } else {
+ c2[i] = 'A' + offset - 10;
+ }
+ }
+ return SECSuccess;
+}
+
+void
+serialize_key(SECItem *it, int ni, PRFileDesc *file)
+{
+ unsigned char len[4];
+ int i;
+ SECStatus status;
+ NSSBase64Encoder *cx;
+ SECItem ascii;
+ ascii.data = NULL;
+ ascii.len = 0;
+ cx = NSSBase64Encoder_Create(output_ascii, file);
+ for (i=0; i<ni; i++, it++) {
+ len[0] = (it->len >> 24) & 0xff;
+ len[1] = (it->len >> 16) & 0xff;
+ len[2] = (it->len >> 8) & 0xff;
+ len[3] = (it->len & 0xff);
+ status = NSSBase64Encoder_Update(cx, len, 4);
+ status = NSSBase64Encoder_Update(cx, it->data, it->len);
+ }
+ status = NSSBase64Encoder_Destroy(cx, PR_FALSE);
+ status = PR_Write(file, "\r\n", 2);
+}
+
+void
+key_from_filedata(PRArenaPool *arena, SECItem *it, int ni, SECItem *filedata)
+{
+ int fpos = 0;
+ int i;
+ unsigned char *buf = filedata->data;
+ for (i=0; i<ni; i++, it++) {
+ it->len = (buf[fpos++] & 0xff) << 24;
+ it->len |= (buf[fpos++] & 0xff) << 16;
+ it->len |= (buf[fpos++] & 0xff) << 8;
+ it->len |= (buf[fpos++] & 0xff);
+ if (it->len > 0) {
+ it->data = PORT_ArenaAlloc(arena, it->len);
+ PORT_Memcpy(it->data, &buf[fpos], it->len);
+ } else {
+ it->data = NULL;
+ }
+ fpos += it->len;
+ }
+}
+
+static RSAPrivateKey *
+rsakey_from_filedata(SECItem *filedata)
+{
+ RSAPrivateKey *key;
+ PRArenaPool *arena;
+ arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
+ key = (RSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(RSAPrivateKey));
+ key->arena = arena;
+ key_from_filedata(arena, &key->version, 9, filedata);
+ return key;
+}
+
+static PQGParams *
+pqg_from_filedata(SECItem *filedata)
+{
+ PQGParams *pqg;
+ PRArenaPool *arena;
+ arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
+ pqg = (PQGParams *)PORT_ArenaZAlloc(arena, sizeof(PQGParams));
+ pqg->arena = arena;
+ key_from_filedata(arena, &pqg->prime, 3, filedata);
+ return pqg;
+}
+
+static DSAPrivateKey *
+dsakey_from_filedata(SECItem *filedata)
+{
+ DSAPrivateKey *key;
+ PRArenaPool *arena;
+ arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
+ key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
+ key->params.arena = arena;
+ key_from_filedata(arena, &key->params.prime, 5, filedata);
+ return key;
+}
+
+static void
+dump_pqg(PQGParams *pqg)
+{
+ SECU_PrintInteger(stdout, &pqg->prime, "PRIME:", 0);
+ SECU_PrintInteger(stdout, &pqg->subPrime, "SUBPRIME:", 0);
+ SECU_PrintInteger(stdout, &pqg->base, "BASE:", 0);
+}
+
+static void
+dump_dsakey(DSAPrivateKey *key)
+{
+ dump_pqg(&key->params);
+ SECU_PrintInteger(stdout, &key->publicValue, "PUBLIC VALUE:", 0);
+ SECU_PrintInteger(stdout, &key->privateValue, "PRIVATE VALUE:", 0);
+}
+
+static void
+dump_rsakey(RSAPrivateKey *key)
+{
+ SECU_PrintInteger(stdout, &key->version, "VERSION:", 0);
+ SECU_PrintInteger(stdout, &key->modulus, "MODULUS:", 0);
+ SECU_PrintInteger(stdout, &key->publicExponent, "PUBLIC EXP:", 0);
+ SECU_PrintInteger(stdout, &key->privateExponent, "PRIVATE EXP:", 0);
+ SECU_PrintInteger(stdout, &key->prime1, "CRT PRIME 1:", 0);
+ SECU_PrintInteger(stdout, &key->prime2, "CRT PRIME 2:", 0);
+ SECU_PrintInteger(stdout, &key->exponent1, "CRT EXP 1:", 0);
+ SECU_PrintInteger(stdout, &key->exponent2, "CRT EXP 2:", 0);
+ SECU_PrintInteger(stdout, &key->coefficient, "CRT COEFFICIENT:", 0);
+}
+
+typedef enum {
+ bltestBase64Encoded, /* Base64 encoded ASCII */
+ bltestBinary, /* straight binary */
+ bltestHexSpaceDelim, /* 0x12 0x34 0xab 0xCD ... */
+ bltestHexStream /* 1234abCD ... */
+} bltestIOMode;
+
+typedef struct
+{
+ SECItem buf;
+ SECItem pBuf;
+ bltestIOMode mode;
+ PRFileDesc* file;
+} bltestIO;
+
+typedef SECStatus (* bltestSymmCipherFn)(void *cx,
+ unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen);
+
+typedef SECStatus (* bltestPubKeyCipherFn)(void *key,
+ SECItem *output,
+ const SECItem *input);
+
+typedef SECStatus (* bltestHashCipherFn)(unsigned char *dest,
+ const unsigned char *src,
+ uint32 src_length);
+
+typedef enum {
+ bltestINVALID = -1,
+ bltestDES_ECB, /* Symmetric Key Ciphers */
+ bltestDES_CBC, /* . */
+ bltestDES_EDE_ECB, /* . */
+ bltestDES_EDE_CBC, /* . */
+ bltestRC2_ECB, /* . */
+ bltestRC2_CBC, /* . */
+ bltestRC4, /* . */
+ bltestRC5_ECB, /* . */
+ bltestRC5_CBC, /* . */
+ bltestAES_ECB, /* . */
+ bltestAES_CBC, /* . */
+ bltestRSA, /* Public Key Ciphers */
+ bltestDSA, /* . (Public Key Sig.) */
+ bltestMD2, /* Hash algorithms */
+ bltestMD5, /* . */
+ bltestSHA1, /* . */
+ bltestSHA256, /* . */
+ bltestSHA384, /* . */
+ bltestSHA512, /* . */
+ NUMMODES
+} bltestCipherMode;
+
+static char *mode_strings[] =
+{
+ "des_ecb",
+ "des_cbc",
+ "des3_ecb",
+ "des3_cbc",
+ "rc2_ecb",
+ "rc2_cbc",
+ "rc4",
+ "rc5_ecb",
+ "rc5_cbc",
+ "aes_ecb",
+ "aes_cbc",
+ "rsa",
+ /*"pqg",*/
+ "dsa",
+ "md2",
+ "md5",
+ "sha1",
+ "sha256",
+ "sha384",
+ "sha512",
+};
+
+typedef struct
+{
+ bltestIO key;
+ bltestIO iv;
+} bltestSymmKeyParams;
+
+typedef struct
+{
+ bltestIO key;
+ bltestIO iv;
+ int rounds;
+ int wordsize;
+} bltestRC5Params;
+
+typedef struct
+{
+ bltestIO key;
+ int keysizeInBits;
+ RSAPrivateKey *rsakey;
+} bltestRSAParams;
+
+typedef struct
+{
+ bltestIO key;
+ bltestIO pqgdata;
+ unsigned int j;
+ bltestIO keyseed;
+ bltestIO sigseed;
+ bltestIO sig; /* if doing verify, have additional input */
+ PQGParams *pqg;
+ DSAPrivateKey *dsakey;
+} bltestDSAParams;
+
+typedef struct
+{
+ bltestIO key; /* unused */
+ PRBool restart;
+} bltestHashParams;
+
+typedef union
+{
+ bltestIO key;
+ bltestSymmKeyParams sk;
+ bltestRC5Params rc5;
+ bltestRSAParams rsa;
+ bltestDSAParams dsa;
+ bltestHashParams hash;
+} bltestParams;
+
+typedef struct
+{
+ PRArenaPool *arena;
+ /* cipher context */
+ void *cx;
+ /* I/O streams */
+ bltestIO input;
+ bltestIO output;
+ /* Cipher-specific parameters */
+ bltestParams params;
+ /* Cipher mode */
+ bltestCipherMode mode;
+ /* Cipher function (encrypt/decrypt/sign/verify/hash) */
+ union {
+ bltestSymmCipherFn symmkeyCipher;
+ bltestPubKeyCipherFn pubkeyCipher;
+ bltestHashCipherFn hashCipher;
+ } cipher;
+ /* performance testing */
+ int repetitions;
+ int cxreps;
+ double cxtime;
+ double optime;
+} bltestCipherInfo;
+
+PRBool
+is_symmkeyCipher(bltestCipherMode mode)
+{
+ /* change as needed! */
+ if (mode >= bltestDES_ECB && mode <= bltestAES_CBC)
+ return PR_TRUE;
+ return PR_FALSE;
+}
+
+PRBool
+is_pubkeyCipher(bltestCipherMode mode)
+{
+ /* change as needed! */
+ if (mode >= bltestRSA && mode <= bltestDSA)
+ return PR_TRUE;
+ return PR_FALSE;
+}
+
+PRBool
+is_hashCipher(bltestCipherMode mode)
+{
+ /* change as needed! */
+ if (mode >= bltestMD2 && mode <= bltestSHA512)
+ return PR_TRUE;
+ return PR_FALSE;
+}
+
+PRBool
+is_sigCipher(bltestCipherMode mode)
+{
+ /* change as needed! */
+ if (mode >= bltestDSA && mode <= bltestDSA)
+ return PR_TRUE;
+ return PR_FALSE;
+}
+
+PRBool
+cipher_requires_IV(bltestCipherMode mode)
+{
+ /* change as needed! */
+ if (mode == bltestDES_CBC || mode == bltestDES_EDE_CBC ||
+ mode == bltestRC2_CBC || mode == bltestRC5_CBC ||
+ mode == bltestAES_CBC)
+ return PR_TRUE;
+ return PR_FALSE;
+}
+
+SECStatus finishIO(bltestIO *output, PRFileDesc *file);
+
+SECStatus
+setupIO(PRArenaPool *arena, bltestIO *input, PRFileDesc *file,
+ char *str, int numBytes)
+{
+ SECStatus rv = SECSuccess;
+ SECItem fileData;
+ SECItem *in;
+ unsigned char *tok;
+ unsigned int i, j;
+
+ if (file && (numBytes == 0 || file == PR_STDIN)) {
+ /* grabbing data from a file */
+ rv = SECU_FileToItem(&fileData, file);
+ if (rv != SECSuccess) {
+ PR_Close(file);
+ return SECFailure;
+ }
+ in = &fileData;
+ } else if (str) {
+ /* grabbing data from command line */
+ fileData.data = str;
+ fileData.len = PL_strlen(str);
+ in = &fileData;
+ } else if (file) {
+ /* create nonce */
+ SECITEM_AllocItem(arena, &input->buf, numBytes);
+ RNG_GenerateGlobalRandomBytes(input->buf.data, numBytes);
+ return finishIO(input, file);
+ } else {
+ return SECFailure;
+ }
+
+ switch (input->mode) {
+ case bltestBase64Encoded:
+ rv = atob(in, &input->buf, arena);
+ break;
+ case bltestBinary:
+ if (in->data[in->len-1] == '\n') --in->len;
+ if (in->data[in->len-1] == '\r') --in->len;
+ SECITEM_CopyItem(arena, &input->buf, in);
+ break;
+ case bltestHexSpaceDelim:
+ SECITEM_AllocItem(arena, &input->buf, in->len/5);
+ for (i=0, j=0; i<in->len; i+=5, j++) {
+ tok = &in->data[i];
+ if (tok[0] != '0' || tok[1] != 'x' || tok[4] != ' ')
+ /* bad hex token */
+ break;
+
+ rv = hex_from_2char(&tok[2], input->buf.data + j);
+ if (rv)
+ break;
+ }
+ break;
+ case bltestHexStream:
+ SECITEM_AllocItem(arena, &input->buf, in->len/2);
+ for (i=0, j=0; i<in->len; i+=2, j++) {
+ tok = &in->data[i];
+ rv = hex_from_2char(tok, input->buf.data + j);
+ if (rv)
+ break;
+ }
+ break;
+ }
+
+ if (file)
+ SECITEM_FreeItem(&fileData, PR_FALSE);
+ return rv;
+}
+
+SECStatus
+finishIO(bltestIO *output, PRFileDesc *file)
+{
+ SECStatus rv = SECSuccess;
+ PRInt32 nb;
+ unsigned char byteval;
+ SECItem *it;
+ char hexstr[5];
+ unsigned int i;
+ if (output->pBuf.len > 0) {
+ it = &output->pBuf;
+ } else {
+ it = &output->buf;
+ }
+ switch (output->mode) {
+ case bltestBase64Encoded:
+ rv = btoa_file(it, file);
+ break;
+ case bltestBinary:
+ nb = PR_Write(file, it->data, it->len);
+ rv = (nb == (PRInt32)it->len) ? SECSuccess : SECFailure;
+ break;
+ case bltestHexSpaceDelim:
+ hexstr[0] = '0';
+ hexstr[1] = 'x';
+ hexstr[4] = ' ';
+ for (i=0; i<it->len; i++) {
+ byteval = it->data[i];
+ rv = char2_from_hex(byteval, hexstr + 2);
+ nb = PR_Write(file, hexstr, 5);
+ if (rv)
+ break;
+ }
+ PR_Write(file, "\n", 1);
+ break;
+ case bltestHexStream:
+ for (i=0; i<it->len; i++) {
+ byteval = it->data[i];
+ rv = char2_from_hex(byteval, hexstr);
+ if (rv)
+ break;
+ nb = PR_Write(file, hexstr, 2);
+ }
+ PR_Write(file, "\n", 1);
+ break;
+ }
+ return rv;
+}
+
+void
+bltestCopyIO(PRArenaPool *arena, bltestIO *dest, bltestIO *src)
+{
+ SECITEM_CopyItem(arena, &dest->buf, &src->buf);
+ if (src->pBuf.len > 0) {
+ dest->pBuf.len = src->pBuf.len;
+ dest->pBuf.data = dest->buf.data + (src->pBuf.data - src->buf.data);
+ }
+ dest->mode = src->mode;
+ dest->file = src->file;
+}
+
+void
+misalignBuffer(PRArenaPool *arena, bltestIO *io, int off)
+{
+ ptrdiff_t offset = (ptrdiff_t)io->buf.data % WORDSIZE;
+ int length = io->buf.len;
+ if (offset != off) {
+ SECITEM_ReallocItem(arena, &io->buf, length, length + 2*WORDSIZE);
+ io->buf.len = length + 2*WORDSIZE; /* why doesn't realloc do this? */
+ /* offset may have changed? */
+ offset = (ptrdiff_t)io->buf.data % WORDSIZE;
+ if (offset != off) {
+ memmove(io->buf.data + off, io->buf.data, length);
+ io->pBuf.data = io->buf.data + off;
+ io->pBuf.len = length;
+ } else {
+ io->pBuf.data = io->buf.data;
+ io->pBuf.len = length;
+ }
+ } else {
+ io->pBuf.data = io->buf.data;
+ io->pBuf.len = length;
+ }
+}
+
+SECStatus
+des_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return DES_Encrypt((DESContext *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+des_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return DES_Decrypt((DESContext *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+rc2_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return RC2_Encrypt((RC2Context *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+rc2_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return RC2_Decrypt((RC2Context *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+rc4_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return RC4_Encrypt((RC4Context *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+rc4_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return RC4_Decrypt((RC4Context *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+aes_Encrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return AES_Encrypt((AESContext *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+aes_Decrypt(void *cx, unsigned char *output, unsigned int *outputLen,
+ unsigned int maxOutputLen, const unsigned char *input,
+ unsigned int inputLen)
+{
+ return AES_Decrypt((AESContext *)cx, output, outputLen, maxOutputLen,
+ input, inputLen);
+}
+
+SECStatus
+rsa_PublicKeyOp(void *key, SECItem *output, const SECItem *input)
+{
+ return RSA_PublicKeyOp((RSAPublicKey *)key, output->data, input->data);
+}
+
+SECStatus
+rsa_PrivateKeyOp(void *key, SECItem *output, const SECItem *input)
+{
+ return RSA_PrivateKeyOp((RSAPrivateKey *)key, output->data, input->data);
+}
+
+SECStatus
+dsa_signDigest(void *key, SECItem *output, const SECItem *input)
+{
+ return DSA_SignDigest((DSAPrivateKey *)key, output, input);
+}
+
+SECStatus
+dsa_verifyDigest(void *key, SECItem *output, const SECItem *input)
+{
+ return DSA_VerifyDigest((DSAPublicKey *)key, output, input);
+}
+
+SECStatus
+bltest_des_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ PRIntervalTime time1, time2;
+ bltestSymmKeyParams *desp = &cipherInfo->params.sk;
+ int minorMode;
+ int i;
+ switch (cipherInfo->mode) {
+ case bltestDES_ECB: minorMode = NSS_DES; break;
+ case bltestDES_CBC: minorMode = NSS_DES_CBC; break;
+ case bltestDES_EDE_ECB: minorMode = NSS_DES_EDE3; break;
+ case bltestDES_EDE_CBC: minorMode = NSS_DES_EDE3_CBC; break;
+ default:
+ return SECFailure;
+ }
+ cipherInfo->cx = (void*)DES_CreateContext(desp->key.buf.data,
+ desp->iv.buf.data,
+ minorMode, encrypt);
+ if (cipherInfo->cxreps > 0) {
+ DESContext **dummycx;
+ dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(DESContext *));
+ TIMESTART();
+ for (i=0; i<cipherInfo->cxreps; i++) {
+ dummycx[i] = (void*)DES_CreateContext(desp->key.buf.data,
+ desp->iv.buf.data,
+ minorMode, encrypt);
+ }
+ TIMEFINISH(cipherInfo->cxtime, 1.0);
+ for (i=0; i<cipherInfo->cxreps; i++) {
+ DES_DestroyContext(dummycx[i], PR_TRUE);
+ }
+ PORT_Free(dummycx);
+ }
+ if (encrypt)
+ cipherInfo->cipher.symmkeyCipher = des_Encrypt;
+ else
+ cipherInfo->cipher.symmkeyCipher = des_Decrypt;
+ return SECSuccess;
+}
+
+SECStatus
+bltest_rc2_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ PRIntervalTime time1, time2;
+ bltestSymmKeyParams *rc2p = &cipherInfo->params.sk;
+ int minorMode;
+ int i;
+ switch (cipherInfo->mode) {
+ case bltestRC2_ECB: minorMode = NSS_RC2; break;
+ case bltestRC2_CBC: minorMode = NSS_RC2_CBC; break;
+ default:
+ return SECFailure;
+ }
+ cipherInfo->cx = (void*)RC2_CreateContext(rc2p->key.buf.data,
+ rc2p->key.buf.len,
+ rc2p->iv.buf.data,
+ minorMode,
+ rc2p->key.buf.len);
+ if (cipherInfo->cxreps > 0) {
+ RC2Context **dummycx;
+ dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(RC2Context *));
+ TIMESTART();
+ for (i=0; i<cipherInfo->cxreps; i++) {
+ dummycx[i] = (void*)RC2_CreateContext(rc2p->key.buf.data,
+ rc2p->key.buf.len,
+ rc2p->iv.buf.data,
+ minorMode,
+ rc2p->key.buf.len);
+ }
+ TIMEFINISH(cipherInfo->cxtime, 1.0);
+ for (i=0; i<cipherInfo->cxreps; i++) {
+ RC2_DestroyContext(dummycx[i], PR_TRUE);
+ }
+ PORT_Free(dummycx);
+ }
+ if (encrypt)
+ cipherInfo->cipher.symmkeyCipher = rc2_Encrypt;
+ else
+ cipherInfo->cipher.symmkeyCipher = rc2_Decrypt;
+ return SECSuccess;
+}
+
+SECStatus
+bltest_rc4_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ PRIntervalTime time1, time2;
+ int i;
+ bltestSymmKeyParams *rc4p = &cipherInfo->params.sk;
+ cipherInfo->cx = (void*)RC4_CreateContext(rc4p->key.buf.data,
+ rc4p->key.buf.len);
+ if (cipherInfo->cxreps > 0) {
+ RC4Context **dummycx;
+ dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(RC4Context *));
+ TIMESTART();
+ for (i=0; i<cipherInfo->cxreps; i++) {
+ dummycx[i] = (void*)RC4_CreateContext(rc4p->key.buf.data,
+ rc4p->key.buf.len);
+ }
+ TIMEFINISH(cipherInfo->cxtime, 1.0);
+ for (i=0; i<cipherInfo->cxreps; i++) {
+ RC4_DestroyContext(dummycx[i], PR_TRUE);
+ }
+ PORT_Free(dummycx);
+ }
+ if (encrypt)
+ cipherInfo->cipher.symmkeyCipher = rc4_Encrypt;
+ else
+ cipherInfo->cipher.symmkeyCipher = rc4_Decrypt;
+ return SECSuccess;
+}
+
+SECStatus
+bltest_rc5_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+#if NSS_SOFTOKEN_DOES_RC5
+ PRIntervalTime time1, time2;
+ bltestRC5Params *rc5p = &cipherInfo->params.rc5;
+ int minorMode;
+ switch (cipherInfo->mode) {
+ case bltestRC5_ECB: minorMode = NSS_RC5; break;
+ case bltestRC5_CBC: minorMode = NSS_RC5_CBC; break;
+ default:
+ return SECFailure;
+ }
+ TIMESTART();
+ cipherInfo->cx = (void*)RC5_CreateContext(&rc5p->key.buf,
+ rc5p->rounds, rc5p->wordsize,
+ rc5p->iv.buf.data, minorMode);
+ TIMEFINISH(cipherInfo->cxtime, 1.0);
+ if (encrypt)
+ cipherInfo->cipher.symmkeyCipher = RC5_Encrypt;
+ else
+ cipherInfo->cipher.symmkeyCipher = RC5_Decrypt;
+ return SECSuccess;
+#else
+ return SECFailure;
+#endif
+}
+
+SECStatus
+bltest_aes_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ PRIntervalTime time1, time2;
+ bltestSymmKeyParams *aesp = &cipherInfo->params.sk;
+ int minorMode;
+ int i;
+ /* XXX */ int keylen, blocklen;
+ keylen = aesp->key.buf.len;
+ blocklen = cipherInfo->input.pBuf.len;
+ switch (cipherInfo->mode) {
+ case bltestAES_ECB: minorMode = NSS_AES; break;
+ case bltestAES_CBC: minorMode = NSS_AES_CBC; break;
+ default:
+ return SECFailure;
+ }
+ cipherInfo->cx = (void*)AES_CreateContext(aesp->key.buf.data,
+ aesp->iv.buf.data,
+ minorMode, encrypt,
+ keylen, blocklen);
+ if (cipherInfo->cxreps > 0) {
+ AESContext **dummycx;
+ dummycx = PORT_Alloc(cipherInfo->cxreps * sizeof(AESContext *));
+ TIMESTART();
+ for (i=0; i<cipherInfo->cxreps; i++) {
+ dummycx[i] = (void*)AES_CreateContext(aesp->key.buf.data,
+ aesp->iv.buf.data,
+ minorMode, encrypt,
+ keylen, blocklen);
+ }
+ TIMEFINISH(cipherInfo->cxtime, 1.0);
+ for (i=0; i<cipherInfo->cxreps; i++) {
+ AES_DestroyContext(dummycx[i], PR_TRUE);
+ }
+ PORT_Free(dummycx);
+ }
+ if (encrypt)
+ cipherInfo->cipher.symmkeyCipher = aes_Encrypt;
+ else
+ cipherInfo->cipher.symmkeyCipher = aes_Decrypt;
+ return SECSuccess;
+}
+
+SECStatus
+bltest_rsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ int i;
+ RSAPrivateKey **dummyKey;
+ PRIntervalTime time1, time2;
+ bltestRSAParams *rsap = &cipherInfo->params.rsa;
+ /* RSA key gen was done during parameter setup */
+ cipherInfo->cx = cipherInfo->params.rsa.rsakey;
+ /* For performance testing */
+ if (cipherInfo->cxreps > 0) {
+ /* Create space for n private key objects */
+ dummyKey = (RSAPrivateKey **)PORT_Alloc(cipherInfo->cxreps *
+ sizeof(RSAPrivateKey *));
+ /* Time n keygens, storing in the array */
+ TIMESTART();
+ for (i=0; i<cipherInfo->cxreps; i++)
+ dummyKey[i] = RSA_NewKey(rsap->keysizeInBits,
+ &rsap->rsakey->publicExponent);
+ TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps);
+ /* Free the n key objects */
+ for (i=0; i<cipherInfo->cxreps; i++)
+ PORT_FreeArena(dummyKey[i]->arena, PR_TRUE);
+ PORT_Free(dummyKey);
+ }
+ if (encrypt) {
+ /* Have to convert private key to public key. Memory
+ * is freed with private key's arena */
+ RSAPublicKey *pubkey;
+ RSAPrivateKey *key = (RSAPrivateKey *)cipherInfo->cx;
+ pubkey = (RSAPublicKey *)PORT_ArenaAlloc(key->arena,
+ sizeof(RSAPublicKey));
+ pubkey->modulus.len = key->modulus.len;
+ pubkey->modulus.data = key->modulus.data;
+ pubkey->publicExponent.len = key->publicExponent.len;
+ pubkey->publicExponent.data = key->publicExponent.data;
+ cipherInfo->cx = (void *)pubkey;
+ cipherInfo->cipher.pubkeyCipher = rsa_PublicKeyOp;
+ } else {
+ cipherInfo->cipher.pubkeyCipher = rsa_PrivateKeyOp;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+bltest_pqg_init(bltestDSAParams *dsap)
+{
+ SECStatus rv, res;
+ PQGVerify *vfy = NULL;
+ rv = PQG_ParamGen(dsap->j, &dsap->pqg, &vfy);
+ CHECKERROR(rv, __LINE__);
+ rv = PQG_VerifyParams(dsap->pqg, vfy, &res);
+ CHECKERROR(res, __LINE__);
+ CHECKERROR(rv, __LINE__);
+ return rv;
+}
+
+SECStatus
+bltest_dsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ int i;
+ DSAPrivateKey **dummyKey;
+ PQGParams *dummypqg;
+ PRIntervalTime time1, time2;
+ bltestDSAParams *dsap = &cipherInfo->params.dsa;
+ PQGVerify *ignore = NULL;
+ /* DSA key gen was done during parameter setup */
+ cipherInfo->cx = cipherInfo->params.dsa.dsakey;
+ /* For performance testing */
+ if (cipherInfo->cxreps > 0) {
+ /* Create space for n private key objects */
+ dummyKey = (DSAPrivateKey **)PORT_ZAlloc(cipherInfo->cxreps *
+ sizeof(DSAPrivateKey *));
+ /* Time n keygens, storing in the array */
+ TIMESTART();
+ for (i=0; i<cipherInfo->cxreps; i++) {
+ dummypqg = NULL;
+ PQG_ParamGen(dsap->j, &dummypqg, &ignore);
+ DSA_NewKey(dummypqg, &dummyKey[i]);
+ }
+ TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps);
+ /* Free the n key objects */
+ for (i=0; i<cipherInfo->cxreps; i++)
+ PORT_FreeArena(dummyKey[i]->params.arena, PR_TRUE);
+ PORT_Free(dummyKey);
+ }
+ if (!dsap->pqg && dsap->pqgdata.buf.len > 0) {
+ dsap->pqg = pqg_from_filedata(&dsap->pqgdata.buf);
+ }
+ if (!cipherInfo->cx && dsap->key.buf.len > 0) {
+ cipherInfo->cx = dsakey_from_filedata(&dsap->key.buf);
+ }
+ if (encrypt) {
+ cipherInfo->cipher.pubkeyCipher = dsa_signDigest;
+ } else {
+ /* Have to convert private key to public key. Memory
+ * is freed with private key's arena */
+ DSAPublicKey *pubkey;
+ DSAPrivateKey *key = (DSAPrivateKey *)cipherInfo->cx;
+ pubkey = (DSAPublicKey *)PORT_ArenaZAlloc(key->params.arena,
+ sizeof(DSAPublicKey));
+ pubkey->params.prime.len = key->params.prime.len;
+ pubkey->params.prime.data = key->params.prime.data;
+ pubkey->params.subPrime.len = key->params.subPrime.len;
+ pubkey->params.subPrime.data = key->params.subPrime.data;
+ pubkey->params.base.len = key->params.base.len;
+ pubkey->params.base.data = key->params.base.data;
+ pubkey->publicValue.len = key->publicValue.len;
+ pubkey->publicValue.data = key->publicValue.data;
+ cipherInfo->cipher.pubkeyCipher = dsa_verifyDigest;
+ }
+ return SECSuccess;
+}
+
+/* XXX unfortunately, this is not defined in blapi.h */
+SECStatus
+md2_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length)
+{
+ unsigned int len;
+ MD2Context *cx = MD2_NewContext();
+ if (cx == NULL) return SECFailure;
+ MD2_Begin(cx);
+ MD2_Update(cx, src, src_length);
+ MD2_End(cx, dest, &len, MD2_LENGTH);
+ MD2_DestroyContext(cx, PR_TRUE);
+ return SECSuccess;
+}
+
+SECStatus
+md2_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
+{
+ MD2Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ SECStatus rv = SECSuccess;
+ cx = MD2_NewContext();
+ MD2_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3)/ 4;
+ for (i=0; i < 4 && src_length > 0; i++) {
+ MD2_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
+ len = MD2_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ MD2_Flatten(cx, cxbytes);
+ cx_cpy = MD2_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: MD2_Resurrect failed!\n", progName);
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ MD2_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: MD2_restart failed!\n", progName);
+ goto finish;
+ }
+ MD2_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ MD2_End(cx, dest, &len, MD2_LENGTH);
+finish:
+ MD2_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+md5_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
+{
+ SECStatus rv = SECSuccess;
+ MD5Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ cx = MD5_NewContext();
+ MD5_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3)/ 4;
+ for (i=0; i < 4 && src_length > 0; i++) {
+ MD5_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
+ len = MD5_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ MD5_Flatten(cx, cxbytes);
+ cx_cpy = MD5_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: MD5_Resurrect failed!\n", progName);
+ rv = SECFailure;
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ MD5_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: MD5_restart failed!\n", progName);
+ goto finish;
+ }
+ MD5_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ MD5_End(cx, dest, &len, MD5_LENGTH);
+finish:
+ MD5_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+sha1_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
+{
+ SECStatus rv = SECSuccess;
+ SHA1Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ cx = SHA1_NewContext();
+ SHA1_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3)/ 4;
+ for (i=0; i < 4 && src_length > 0; i++) {
+ SHA1_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
+ len = SHA1_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ SHA1_Flatten(cx, cxbytes);
+ cx_cpy = SHA1_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: SHA1_Resurrect failed!\n", progName);
+ rv = SECFailure;
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ SHA1_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: SHA1_restart failed!\n", progName);
+ goto finish;
+ }
+ SHA1_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ SHA1_End(cx, dest, &len, MD5_LENGTH);
+finish:
+ SHA1_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+SHA256_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
+{
+ SECStatus rv = SECSuccess;
+ SHA256Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ cx = SHA256_NewContext();
+ SHA256_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3)/ 4;
+ for (i=0; i < 4 && src_length > 0; i++) {
+ SHA256_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
+ len = SHA256_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ SHA256_Flatten(cx, cxbytes);
+ cx_cpy = SHA256_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: SHA256_Resurrect failed!\n", progName);
+ rv = SECFailure;
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ SHA256_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: SHA256_restart failed!\n", progName);
+ goto finish;
+ }
+ SHA256_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ SHA256_End(cx, dest, &len, MD5_LENGTH);
+finish:
+ SHA256_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+SHA384_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
+{
+ SECStatus rv = SECSuccess;
+ SHA384Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ cx = SHA384_NewContext();
+ SHA384_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3)/ 4;
+ for (i=0; i < 4 && src_length > 0; i++) {
+ SHA384_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
+ len = SHA384_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ SHA384_Flatten(cx, cxbytes);
+ cx_cpy = SHA384_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: SHA384_Resurrect failed!\n", progName);
+ rv = SECFailure;
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ SHA384_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: SHA384_restart failed!\n", progName);
+ goto finish;
+ }
+ SHA384_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ SHA384_End(cx, dest, &len, MD5_LENGTH);
+finish:
+ SHA384_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+SHA512_restart(unsigned char *dest, const unsigned char *src, uint32 src_length)
+{
+ SECStatus rv = SECSuccess;
+ SHA512Context *cx, *cx_cpy;
+ unsigned char *cxbytes;
+ unsigned int len;
+ unsigned int i, quarter;
+ cx = SHA512_NewContext();
+ SHA512_Begin(cx);
+ /* divide message by 4, restarting 3 times */
+ quarter = (src_length + 3)/ 4;
+ for (i=0; i < 4 && src_length > 0; i++) {
+ SHA512_Update(cx, src + i*quarter, PR_MIN(quarter, src_length));
+ len = SHA512_FlattenSize(cx);
+ cxbytes = PORT_Alloc(len);
+ SHA512_Flatten(cx, cxbytes);
+ cx_cpy = SHA512_Resurrect(cxbytes, NULL);
+ if (!cx_cpy) {
+ PR_fprintf(PR_STDERR, "%s: SHA512_Resurrect failed!\n", progName);
+ rv = SECFailure;
+ goto finish;
+ }
+ rv = PORT_Memcmp(cx, cx_cpy, len);
+ if (rv) {
+ SHA512_DestroyContext(cx_cpy, PR_TRUE);
+ PR_fprintf(PR_STDERR, "%s: SHA512_restart failed!\n", progName);
+ goto finish;
+ }
+ SHA512_DestroyContext(cx_cpy, PR_TRUE);
+ PORT_Free(cxbytes);
+ src_length -= quarter;
+ }
+ SHA512_End(cx, dest, &len, MD5_LENGTH);
+finish:
+ SHA512_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+SECStatus
+pubkeyInitKey(bltestCipherInfo *cipherInfo, PRFileDesc *file,
+ int keysize, int exponent)
+{
+ int i;
+ SECStatus rv = SECSuccess;
+ bltestRSAParams *rsap;
+ bltestDSAParams *dsap;
+ switch (cipherInfo->mode) {
+ case bltestRSA:
+ rsap = &cipherInfo->params.rsa;
+ if (keysize > 0) {
+ SECItem expitem = { 0, 0, 0 };
+ SECITEM_AllocItem(cipherInfo->arena, &expitem, sizeof(int));
+ for (i = 1; i <= sizeof(int); i++)
+ expitem.data[i-1] = exponent >> (8*(sizeof(int) - i));
+ rsap->rsakey = RSA_NewKey(keysize * 8, &expitem);
+ serialize_key(&rsap->rsakey->version, 9, file);
+ rsap->keysizeInBits = keysize * 8;
+ } else {
+ setupIO(cipherInfo->arena, &cipherInfo->params.key, file, NULL, 0);
+ rsap->rsakey = rsakey_from_filedata(&cipherInfo->params.key.buf);
+ rsap->keysizeInBits = rsap->rsakey->modulus.len * 8;
+ }
+ break;
+ case bltestDSA:
+ dsap = &cipherInfo->params.dsa;
+ if (keysize > 0) {
+ dsap->j = PQG_PBITS_TO_INDEX(8*keysize);
+ if (!dsap->pqg)
+ bltest_pqg_init(dsap);
+ rv = DSA_NewKey(dsap->pqg, &dsap->dsakey);
+ CHECKERROR(rv, __LINE__);
+ serialize_key(&dsap->dsakey->params.prime, 5, file);
+ } else {
+ setupIO(cipherInfo->arena, &cipherInfo->params.key, file, NULL, 0);
+ dsap->dsakey = dsakey_from_filedata(&cipherInfo->params.key.buf);
+ dsap->j = PQG_PBITS_TO_INDEX(8*dsap->dsakey->params.prime.len);
+ }
+ break;
+ default:
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+cipherInit(bltestCipherInfo *cipherInfo, PRBool encrypt)
+{
+ PRBool restart;
+ switch (cipherInfo->mode) {
+ case bltestDES_ECB:
+ case bltestDES_CBC:
+ case bltestDES_EDE_ECB:
+ case bltestDES_EDE_CBC:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+ return bltest_des_init(cipherInfo, encrypt);
+ break;
+ case bltestRC2_ECB:
+ case bltestRC2_CBC:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+ return bltest_rc2_init(cipherInfo, encrypt);
+ break;
+ case bltestRC4:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+ return bltest_rc4_init(cipherInfo, encrypt);
+ break;
+ case bltestRC5_ECB:
+ case bltestRC5_CBC:
+#if NSS_SOFTOKEN_DOES_RC5
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+#endif
+ return bltest_rc5_init(cipherInfo, encrypt);
+ break;
+ case bltestAES_ECB:
+ case bltestAES_CBC:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+ return bltest_aes_init(cipherInfo, encrypt);
+ break;
+ case bltestRSA:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ cipherInfo->input.pBuf.len);
+ return bltest_rsa_init(cipherInfo, encrypt);
+ break;
+ case bltestDSA:
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ DSA_SIGNATURE_LEN);
+ return bltest_dsa_init(cipherInfo, encrypt);
+ break;
+ case bltestMD2:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ MD2_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? md2_restart : md2_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestMD5:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ MD5_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? md5_restart : MD5_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestSHA1:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA1_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? sha1_restart : SHA1_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestSHA256:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA256_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? SHA256_restart
+ : SHA256_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestSHA384:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA384_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? SHA384_restart
+ : SHA384_HashBuf;
+ return SECSuccess;
+ break;
+ case bltestSHA512:
+ restart = cipherInfo->params.hash.restart;
+ SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf,
+ SHA512_LENGTH);
+ cipherInfo->cipher.hashCipher = (restart) ? SHA512_restart
+ : SHA512_HashBuf;
+ return SECSuccess;
+ break;
+ default:
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+dsaOp(bltestCipherInfo *cipherInfo)
+{
+ PRIntervalTime time1, time2;
+ SECStatus rv = SECSuccess;
+ int i;
+ int maxLen = cipherInfo->output.pBuf.len;
+ SECItem dummyOut = { 0, 0, 0 };
+ SECITEM_AllocItem(NULL, &dummyOut, maxLen);
+ if (cipherInfo->cipher.pubkeyCipher == dsa_signDigest) {
+ if (cipherInfo->params.dsa.sigseed.buf.len > 0) {
+ rv = DSA_SignDigestWithSeed((DSAPrivateKey *)cipherInfo->cx,
+ &cipherInfo->output.pBuf,
+ &cipherInfo->input.pBuf,
+ cipherInfo->params.dsa.sigseed.buf.data);
+ CHECKERROR(rv, __LINE__);
+ TIMESTART();
+ for (i=0; i<cipherInfo->repetitions; i++) {
+ rv |= DSA_SignDigestWithSeed((DSAPrivateKey *)cipherInfo->cx,
+ &dummyOut,
+ &cipherInfo->input.pBuf,
+ cipherInfo->params.dsa.sigseed.buf.data);
+ }
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ CHECKERROR(rv, __LINE__);
+ } else {
+ rv = DSA_SignDigest((DSAPrivateKey *)cipherInfo->cx,
+ &cipherInfo->output.pBuf,
+ &cipherInfo->input.pBuf);
+ CHECKERROR(rv, __LINE__);
+ TIMESTART();
+ for (i=0; i<cipherInfo->repetitions; i++) {
+ DSA_SignDigest((DSAPrivateKey *)cipherInfo->cx, &dummyOut,
+ &cipherInfo->input.pBuf);
+ }
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ }
+ bltestCopyIO(cipherInfo->arena, &cipherInfo->params.dsa.sig,
+ &cipherInfo->output);
+ } else {
+ rv = DSA_VerifyDigest((DSAPublicKey *)cipherInfo->cx,
+ &cipherInfo->params.dsa.sig.buf,
+ &cipherInfo->input.pBuf);
+ CHECKERROR(rv, __LINE__);
+ TIMESTART();
+ for (i=0; i<cipherInfo->repetitions; i++) {
+ DSA_VerifyDigest((DSAPublicKey *)cipherInfo->cx,
+ &cipherInfo->params.dsa.sig.buf,
+ &cipherInfo->input.pBuf);
+ }
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ }
+ SECITEM_FreeItem(&dummyOut, PR_FALSE);
+ return rv;
+}
+
+SECStatus
+cipherDoOp(bltestCipherInfo *cipherInfo)
+{
+ PRIntervalTime time1, time2;
+ SECStatus rv = SECSuccess;
+ int i, len;
+ int maxLen = cipherInfo->output.pBuf.len;
+ unsigned char *dummyOut;
+ if (cipherInfo->mode == bltestDSA)
+ return dsaOp(cipherInfo);
+ dummyOut = PORT_Alloc(maxLen);
+ if (is_symmkeyCipher(cipherInfo->mode)) {
+ rv = (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx,
+ cipherInfo->output.pBuf.data,
+ &len, maxLen,
+ cipherInfo->input.pBuf.data,
+ cipherInfo->input.pBuf.len);
+ TIMESTART();
+ for (i=0; i<cipherInfo->repetitions; i++) {
+ (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx, dummyOut,
+ &len, maxLen,
+ cipherInfo->input.pBuf.data,
+ cipherInfo->input.pBuf.len);
+
+ }
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ } else if (is_pubkeyCipher(cipherInfo->mode)) {
+ rv = (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx,
+ &cipherInfo->output.pBuf,
+ &cipherInfo->input.pBuf);
+ TIMESTART();
+ for (i=0; i<cipherInfo->repetitions; i++) {
+ SECItem dummy;
+ dummy.data = dummyOut;
+ dummy.len = maxLen;
+ (*cipherInfo->cipher.pubkeyCipher)(cipherInfo->cx, &dummy,
+ &cipherInfo->input.pBuf);
+ }
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ } else if (is_hashCipher(cipherInfo->mode)) {
+ rv = (*cipherInfo->cipher.hashCipher)(cipherInfo->output.pBuf.data,
+ cipherInfo->input.pBuf.data,
+ cipherInfo->input.pBuf.len);
+ TIMESTART();
+ for (i=0; i<cipherInfo->repetitions; i++) {
+ (*cipherInfo->cipher.hashCipher)(dummyOut,
+ cipherInfo->input.pBuf.data,
+ cipherInfo->input.pBuf.len);
+ }
+ TIMEFINISH(cipherInfo->optime, 1.0);
+ }
+ PORT_Free(dummyOut);
+ return rv;
+}
+
+SECStatus
+cipherFinish(bltestCipherInfo *cipherInfo)
+{
+ switch (cipherInfo->mode) {
+ case bltestDES_ECB:
+ case bltestDES_CBC:
+ case bltestDES_EDE_ECB:
+ case bltestDES_EDE_CBC:
+ DES_DestroyContext((DESContext *)cipherInfo->cx, PR_TRUE);
+ break;
+ case bltestAES_ECB:
+ case bltestAES_CBC:
+ AES_DestroyContext((AESContext *)cipherInfo->cx, PR_TRUE);
+ break;
+ case bltestRC2_ECB:
+ case bltestRC2_CBC:
+ RC2_DestroyContext((RC2Context *)cipherInfo->cx, PR_TRUE);
+ break;
+ case bltestRC4:
+ RC4_DestroyContext((RC4Context *)cipherInfo->cx, PR_TRUE);
+ break;
+#if NSS_SOFTOKEN_DOES_RC5
+ case bltestRC5_ECB:
+ case bltestRC5_CBC:
+ RC5_DestroyContext((RC5Context *)cipherInfo->cx, PR_TRUE);
+ break;
+#endif
+ case bltestRSA: /* keys are alloc'ed within cipherInfo's arena, */
+ case bltestDSA: /* will be freed with it. */
+ case bltestMD2: /* hash contexts are ephemeral */
+ case bltestMD5:
+ case bltestSHA1:
+ case bltestSHA256:
+ case bltestSHA384:
+ case bltestSHA512:
+ return SECSuccess;
+ break;
+ default:
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+void
+print_exponent(SECItem *exp)
+{
+ int i;
+ int e = 0;
+ if (exp->len <= 4) {
+ for (i=exp->len; i >=0; --i) e |= exp->data[exp->len-i] << 8*(i-1);
+ fprintf(stdout, "%12d", e);
+ } else {
+ e = 8*exp->len;
+ fprintf(stdout, "~2**%-8d", e);
+ }
+}
+
+void
+dump_performance_info(bltestCipherInfo *info, PRBool encrypt, PRBool cxonly)
+{
+ PRBool td = PR_TRUE;
+ fprintf(stdout, "#%9s", "mode");
+ fprintf(stdout, "%12s", "in");
+print_td:
+ switch (info->mode) {
+ case bltestDES_ECB:
+ case bltestDES_CBC:
+ case bltestDES_EDE_ECB:
+ case bltestDES_EDE_CBC:
+ case bltestAES_ECB:
+ case bltestAES_CBC:
+ case bltestRC2_ECB:
+ case bltestRC2_CBC:
+ case bltestRC4:
+ if (td)
+ fprintf(stdout, "%8s", "symmkey");
+ else
+ fprintf(stdout, "%8d", 8*info->params.sk.key.buf.len);
+ break;
+#if NSS_SOFTOKEN_DOES_RC5
+ case bltestRC5_ECB:
+ case bltestRC5_CBC:
+ if (info->params.sk.key.buf.len > 0)
+ printf("symmetric key(bytes)=%d,", info->params.sk.key.buf.len);
+ if (info->rounds > 0)
+ printf("rounds=%d,", info->params.rc5.rounds);
+ if (info->wordsize > 0)
+ printf("wordsize(bytes)=%d,", info->params.rc5.wordsize);
+ break;
+#endif
+ case bltestRSA:
+ if (td) {
+ fprintf(stdout, "%8s", "rsa_mod");
+ fprintf(stdout, "%12s", "rsa_pe");
+ } else {
+ fprintf(stdout, "%8d", info->params.rsa.keysizeInBits);
+ print_exponent(&info->params.rsa.rsakey->publicExponent);
+ }
+ break;
+ case bltestDSA:
+ if (td)
+ fprintf(stdout, "%8s", "pqg_mod");
+ else
+ fprintf(stdout, "%8d", PQG_INDEX_TO_PBITS(info->params.dsa.j));
+ break;
+ case bltestMD2:
+ case bltestMD5:
+ case bltestSHA1:
+ case bltestSHA256:
+ case bltestSHA384:
+ case bltestSHA512:
+ default:
+ break;
+ }
+ if (!td) {
+ fprintf(stdout, "%8d", info->repetitions);
+ fprintf(stdout, "%8d", info->cxreps);
+ fprintf(stdout, "%12.3f", info->cxtime);
+ fprintf(stdout, "%12.3f", info->optime);
+ fprintf(stdout, "\n");
+ return;
+ }
+
+ fprintf(stdout, "%8s", "opreps");
+ fprintf(stdout, "%8s", "cxreps");
+ fprintf(stdout, "%12s", "context");
+ fprintf(stdout, "%12s", "op");
+ fprintf(stdout, "\n");
+ fprintf(stdout, "%8s", mode_strings[info->mode]);
+ fprintf(stdout, "_%c", (cxonly) ? 'c' : (encrypt) ? 'e' : 'd');
+ fprintf(stdout, "%12d", info->input.buf.len * info->repetitions);
+
+ td = !td;
+ goto print_td;
+}
+
+void
+printmodes()
+{
+ bltestCipherMode mode;
+ int nummodes = sizeof(mode_strings) / sizeof(char *);
+ fprintf(stderr, "%s: Available modes (specify with -m):\n", progName);
+ for (mode=0; mode<nummodes; mode++)
+ fprintf(stderr, "%s\n", mode_strings[mode]);
+}
+
+bltestCipherMode
+get_mode(const char *modestring)
+{
+ bltestCipherMode mode;
+ int nummodes = sizeof(mode_strings) / sizeof(char *);
+ for (mode=0; mode<nummodes; mode++)
+ if (PL_strcmp(modestring, mode_strings[mode]) == 0)
+ return mode;
+ fprintf(stderr, "%s: invalid mode: %s\n", progName, modestring);
+ return bltestINVALID;
+}
+
+void
+load_file_data(PRArenaPool *arena, bltestIO *data,
+ char *fn, bltestIOMode ioMode)
+{
+ PRFileDesc *file;
+ data->mode = ioMode;
+ data->file = NULL; /* don't use -- not saving anything */
+ data->pBuf.data = NULL;
+ data->pBuf.len = 0;
+ file = PR_Open(fn, PR_RDONLY, 00660);
+ if (file)
+ setupIO(arena, data, file, NULL, 0);
+}
+
+void
+get_params(PRArenaPool *arena, bltestParams *params,
+ bltestCipherMode mode, int j)
+{
+ char filename[256];
+ char *modestr = mode_strings[mode];
+#if NSS_SOFTOKEN_DOES_RC5
+ FILE *file;
+ char *mark, *param, *val;
+ int index = 0;
+#endif
+ switch (mode) {
+ case bltestDES_CBC:
+ case bltestDES_EDE_CBC:
+ case bltestRC2_CBC:
+ case bltestAES_CBC:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "iv", j);
+ load_file_data(arena, &params->sk.iv, filename, bltestBinary);
+ case bltestDES_ECB:
+ case bltestDES_EDE_ECB:
+ case bltestRC2_ECB:
+ case bltestRC4:
+ case bltestAES_ECB:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
+ load_file_data(arena, &params->sk.key, filename, bltestBinary);
+ break;
+#if NSS_SOFTOKEN_DOES_RC5
+ case bltestRC5_ECB:
+ case bltestRC5_CBC:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "iv", j);
+ load_file_data(arena, &params->sk.iv, filename, bltestBinary);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
+ load_file_data(arena, &params->sk.key, filename, bltestBinary);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
+ "params", j);
+ file = fopen(filename, "r");
+ if (!file) return;
+ param = malloc(100);
+ len = fread(param, 1, 100, file);
+ while (index < len) {
+ mark = PL_strchr(param, '=');
+ *mark = '\0';
+ val = mark + 1;
+ mark = PL_strchr(val, '\n');
+ *mark = '\0';
+ if (PL_strcmp(param, "rounds") == 0) {
+ params->rc5.rounds = atoi(val);
+ } else if (PL_strcmp(param, "wordsize") == 0) {
+ params->rc5.wordsize = atoi(val);
+ }
+ index += PL_strlen(param) + PL_strlen(val) + 2;
+ param = mark + 1;
+ }
+ break;
+#endif
+ case bltestRSA:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
+ load_file_data(arena, &params->rsa.key, filename, bltestBase64Encoded);
+ params->rsa.rsakey = rsakey_from_filedata(&params->key.buf);
+ break;
+ case bltestDSA:
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j);
+ load_file_data(arena, &params->dsa.key, filename, bltestBase64Encoded);
+ params->dsa.dsakey = dsakey_from_filedata(&params->key.buf);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "pqg", j);
+ load_file_data(arena, &params->dsa.pqgdata, filename,
+ bltestBase64Encoded);
+ params->dsa.pqg = pqg_from_filedata(&params->dsa.pqgdata.buf);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "keyseed", j);
+ load_file_data(arena, &params->dsa.keyseed, filename,
+ bltestBase64Encoded);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j);
+ load_file_data(arena, &params->dsa.sigseed, filename,
+ bltestBase64Encoded);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext",j);
+ load_file_data(arena, &params->dsa.sig, filename, bltestBase64Encoded);
+ break;
+ case bltestMD2:
+ case bltestMD5:
+ case bltestSHA1:
+ case bltestSHA256:
+ case bltestSHA384:
+ case bltestSHA512:
+ /*params->hash.restart = PR_TRUE;*/
+ params->hash.restart = PR_FALSE;
+ break;
+ default:
+ break;
+ }
+}
+
+SECStatus
+verify_self_test(bltestIO *result, bltestIO *cmp, bltestCipherMode mode,
+ PRBool forward, SECStatus sigstatus)
+{
+ int res;
+ char *modestr = mode_strings[mode];
+ res = SECITEM_CompareItem(&result->pBuf, &cmp->buf);
+ if (is_sigCipher(mode)) {
+ if (forward) {
+ if (res == 0) {
+ printf("Signature self-test for %s passed.\n", modestr);
+ } else {
+ printf("Signature self-test for %s failed!\n", modestr);
+ }
+ } else {
+ if (sigstatus == SECSuccess) {
+ printf("Verification self-test for %s passed.\n", modestr);
+ } else {
+ printf("Verification self-test for %s failed!\n", modestr);
+ }
+ }
+ return sigstatus;
+ } else if (is_hashCipher(mode)) {
+ if (res == 0) {
+ printf("Hash self-test for %s passed.\n", modestr);
+ } else {
+ printf("Hash self-test for %s failed!\n", modestr);
+ }
+ } else {
+ if (forward) {
+ if (res == 0) {
+ printf("Encryption self-test for %s passed.\n", modestr);
+ } else {
+ printf("Encryption self-test for %s failed!\n", modestr);
+ }
+ } else {
+ if (res == 0) {
+ printf("Decryption self-test for %s passed.\n", modestr);
+ } else {
+ printf("Decryption self-test for %s failed!\n", modestr);
+ }
+ }
+ }
+ return (res != 0);
+}
+
+static SECStatus
+blapi_selftest(bltestCipherMode *modes, int numModes, int inoff, int outoff,
+ PRBool encrypt, PRBool decrypt)
+{
+ bltestCipherInfo cipherInfo;
+ bltestIO pt, ct;
+ bltestCipherMode mode;
+ bltestParams *params;
+ int i, j, nummodes;
+ char *modestr;
+ char filename[256];
+ PRFileDesc *file;
+ PRArenaPool *arena;
+ SECItem item;
+ PRBool finished;
+ SECStatus rv = SECSuccess, srv;
+
+ PORT_Memset(&cipherInfo, 0, sizeof(cipherInfo));
+ arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
+ cipherInfo.arena = arena;
+
+ finished = PR_FALSE;
+ nummodes = (numModes == 0) ? NUMMODES : numModes;
+ for (i=0; i < nummodes && !finished; i++) {
+ if (i == bltestRC5_ECB || i == bltestRC5_CBC) continue;
+ if (numModes > 0)
+ mode = modes[i];
+ else
+ mode = i;
+ if (mode == bltestINVALID) {
+ fprintf(stderr, "%s: Skipping invalid mode.\n",progName);
+ continue;
+ }
+ modestr = mode_strings[mode];
+ cipherInfo.mode = mode;
+ params = &cipherInfo.params;
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Self-Testing RSA\n", __bltDBG);
+ }
+#endif
+ /* get the number of tests in the directory */
+ sprintf(filename, "%s/tests/%s/%s", testdir, modestr, "numtests");
+ file = PR_Open(filename, PR_RDONLY, 00660);
+ if (!file) {
+ fprintf(stderr, "%s: File %s does not exist.\n", progName,filename);
+ return SECFailure;
+ }
+ rv = SECU_FileToItem(&item, file);
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Loaded data from %s\n", __bltDBG, filename);
+ }
+#endif
+ PR_Close(file);
+ /* loop over the tests in the directory */
+ for (j=0; j<(int)(item.data[0] - '0'); j++) { /* XXX bug when > 10 */
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Executing self-test #%d\n", __bltDBG, j);
+ }
+#endif
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
+ "plaintext", j);
+ load_file_data(arena, &pt, filename, (mode == bltestDSA) ?
+ bltestBase64Encoded : bltestBinary);
+ sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr,
+ "ciphertext", j);
+ load_file_data(arena, &ct, filename, bltestBase64Encoded);
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Loaded data for self-test #%d\n", __bltDBG, j);
+ }
+#endif
+ get_params(arena, params, mode, j);
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Got parameters for #%d\n", __bltDBG, j);
+ }
+#endif
+ /* Forward Operation (Encrypt/Sign/Hash)
+ ** Align the input buffer (plaintext) according to request
+ ** then perform operation and compare to ciphertext
+ */
+ /* XXX for now */
+ rv = SECSuccess;
+ if (encrypt) {
+ bltestCopyIO(arena, &cipherInfo.input, &pt);
+ misalignBuffer(arena, &cipherInfo.input, inoff);
+ memset(&cipherInfo.output.buf, 0, sizeof cipherInfo.output.buf);
+ rv |= cipherInit(&cipherInfo, PR_TRUE);
+ misalignBuffer(arena, &cipherInfo.output, outoff);
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Inited cipher context and buffers for #%d\n", __bltDBG, j);
+ }
+#endif
+ rv |= cipherDoOp(&cipherInfo);
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Performed encrypt for #%d\n", __bltDBG, j);
+ }
+#endif
+ rv |= cipherFinish(&cipherInfo);
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Finished encrypt for #%d\n", __bltDBG, j);
+ }
+#endif
+ rv |= verify_self_test(&cipherInfo.output,
+ &ct, mode, PR_TRUE, 0);
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Verified self-test for #%d\n", __bltDBG, j);
+ }
+#endif
+ /* If testing hash, only one op to test */
+ if (is_hashCipher(mode))
+ continue;
+ /*if (rv) return rv;*/
+ }
+ if (!decrypt)
+ continue;
+ /* XXX for now */
+ rv = SECSuccess;
+ /* Reverse Operation (Decrypt/Verify)
+ ** Align the input buffer (ciphertext) according to request
+ ** then perform operation and compare to plaintext
+ */
+ if (mode != bltestDSA)
+ bltestCopyIO(arena, &cipherInfo.input, &ct);
+ else
+ bltestCopyIO(arena, &cipherInfo.input, &pt);
+ misalignBuffer(arena, &cipherInfo.input, inoff);
+ memset(&cipherInfo.output.buf, 0, sizeof cipherInfo.output.buf);
+ rv |= cipherInit(&cipherInfo, PR_FALSE);
+ misalignBuffer(arena, &cipherInfo.output, outoff);
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Inited cipher context and buffers for #%d\n", __bltDBG, j);
+ }
+#endif
+ srv = SECSuccess;
+ srv |= cipherDoOp(&cipherInfo);
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Performed decrypt for #%d\n", __bltDBG, j);
+ }
+#endif
+ rv |= cipherFinish(&cipherInfo);
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Finished decrypt for #%d\n", __bltDBG, j);
+ }
+#endif
+ rv |= verify_self_test(&cipherInfo.output,
+ &pt, mode, PR_FALSE, srv);
+#ifdef TRACK_BLTEST_BUG
+ if (mode == bltestRSA) {
+ fprintf(stderr, "[%s] Verified self-test for #%d\n", __bltDBG, j);
+ }
+#endif
+ /*if (rv) return rv;*/
+ }
+ }
+ return rv;
+}
+
+SECStatus
+dump_file(bltestCipherMode mode, char *filename)
+{
+ bltestIO keydata;
+ PRArenaPool *arena = NULL;
+ arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
+ if (mode == bltestRSA) {
+ RSAPrivateKey *key;
+ load_file_data(arena, &keydata, filename, bltestBase64Encoded);
+ key = rsakey_from_filedata(&keydata.buf);
+ dump_rsakey(key);
+ } else if (mode == bltestDSA) {
+#if 0
+ PQGParams *pqg;
+ get_file_data(filename, &item, PR_TRUE);
+ pqg = pqg_from_filedata(&item);
+ dump_pqg(pqg);
+#endif
+ DSAPrivateKey *key;
+ load_file_data(arena, &keydata, filename, bltestBase64Encoded);
+ key = dsakey_from_filedata(&keydata.buf);
+ dump_dsakey(key);
+ }
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECFailure;
+}
+
+/* bltest commands */
+enum {
+ cmd_Decrypt = 0,
+ cmd_Encrypt,
+ cmd_FIPS,
+ cmd_Hash,
+ cmd_Nonce,
+ cmd_Dump,
+ cmd_Sign,
+ cmd_SelfTest,
+ cmd_Verify
+};
+
+/* bltest options */
+enum {
+ opt_B64 = 0,
+ opt_BufSize,
+ opt_Restart,
+ opt_SelfTestDir,
+ opt_Exponent,
+ opt_SigFile,
+ opt_KeySize,
+ opt_Hex,
+ opt_Input,
+ opt_PQGFile,
+ opt_Key,
+ opt_HexWSpc,
+ opt_Mode,
+ opt_Output,
+ opt_Repetitions,
+ opt_ZeroBuf,
+ opt_Rounds,
+ opt_Seed,
+ opt_SigSeedFile,
+ opt_CXReps,
+ opt_IV,
+ opt_WordSize,
+ opt_UseSeed,
+ opt_UseSigSeed,
+ opt_SeedFile,
+ opt_InputOffset,
+ opt_OutputOffset,
+ opt_MonteCarlo,
+ opt_CmdLine
+};
+
+static secuCommandFlag bltest_commands[] =
+{
+ { /* cmd_Decrypt */ 'D', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Encrypt */ 'E', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_FIPS */ 'F', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Hash */ 'H', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Nonce */ 'N', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Dump */ 'P', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Sign */ 'S', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_SelfTest */ 'T', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Verify */ 'V', PR_FALSE, 0, PR_FALSE }
+};
+
+static secuCommandFlag bltest_options[] =
+{
+ { /* opt_B64 */ 'a', PR_FALSE, 0, PR_FALSE },
+ { /* opt_BufSize */ 'b', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Restart */ 'c', PR_FALSE, 0, PR_FALSE },
+ { /* opt_SelfTestDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Exponent */ 'e', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SigFile */ 'f', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeySize */ 'g', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Hex */ 'h', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Input */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PQGFile */ 'j', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Key */ 'k', PR_TRUE, 0, PR_FALSE },
+ { /* opt_HexWSpc */ 'l', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Mode */ 'm', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Output */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Repetitions */ 'p', PR_TRUE, 0, PR_FALSE },
+ { /* opt_ZeroBuf */ 'q', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Rounds */ 'r', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Seed */ 's', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SigSeedFile */ 't', PR_TRUE, 0, PR_FALSE },
+ { /* opt_CXReps */ 'u', PR_TRUE, 0, PR_FALSE },
+ { /* opt_IV */ 'v', PR_TRUE, 0, PR_FALSE },
+ { /* opt_WordSize */ 'w', PR_TRUE, 0, PR_FALSE },
+ { /* opt_UseSeed */ 'x', PR_FALSE, 0, PR_FALSE },
+ { /* opt_UseSigSeed */ 'y', PR_FALSE, 0, PR_FALSE },
+ { /* opt_SeedFile */ 'z', PR_FALSE, 0, PR_FALSE },
+ { /* opt_InputOffset */ '1', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OutputOffset */ '2', PR_TRUE, 0, PR_FALSE },
+ { /* opt_MonteCarlo */ '3', PR_FALSE, 0, PR_FALSE },
+ { /* opt_CmdLine */ '-', PR_FALSE, 0, PR_FALSE }
+};
+
+int main(int argc, char **argv)
+{
+ char *infileName, *outfileName, *keyfileName, *ivfileName;
+ SECStatus rv;
+
+ bltestCipherInfo cipherInfo;
+ bltestParams *params;
+ PRFileDesc *file, *infile, *outfile;
+ char *instr = NULL;
+ PRArenaPool *arena;
+ bltestIOMode ioMode;
+ int keysize, bufsize, exponent;
+ int i, commandsEntered;
+ int inoff, outoff;
+
+ secuCommand bltest;
+ bltest.numCommands = sizeof(bltest_commands) / sizeof(secuCommandFlag);
+ bltest.numOptions = sizeof(bltest_options) / sizeof(secuCommandFlag);
+ bltest.commands = bltest_commands;
+ bltest.options = bltest_options;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName+1 : argv[0];
+
+ rv = RNG_RNGInit();
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+ RNG_SystemInfoForRNG();
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &bltest);
+
+ PORT_Memset(&cipherInfo, 0, sizeof(cipherInfo));
+ arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE);
+ cipherInfo.arena = arena;
+ params = &cipherInfo.params;
+ /* set some defaults */
+ infileName = outfileName = keyfileName = ivfileName = NULL;
+
+ /* Check the number of commands entered on the command line. */
+ commandsEntered = 0;
+ for (i=0; i<bltest.numCommands; i++)
+ if (bltest.commands[i].activated)
+ commandsEntered++;
+
+ if (commandsEntered > 1 &&
+ !(commandsEntered == 2 && bltest.commands[cmd_SelfTest].activated)) {
+ fprintf(stderr, "%s: one command at a time!\n", progName);
+ Usage();
+ }
+ if (commandsEntered == 0) {
+ fprintf(stderr, "%s: you must enter a command!\n", progName);
+ Usage();
+ }
+
+ if (bltest.commands[cmd_Sign].activated)
+ bltest.commands[cmd_Encrypt].activated = PR_TRUE;
+ if (bltest.commands[cmd_Verify].activated)
+ bltest.commands[cmd_Decrypt].activated = PR_TRUE;
+ if (bltest.commands[cmd_Hash].activated)
+ bltest.commands[cmd_Encrypt].activated = PR_TRUE;
+
+ inoff = outoff = 0;
+ if (bltest.options[opt_InputOffset].activated)
+ inoff = PORT_Atoi(bltest.options[opt_InputOffset].arg);
+ if (bltest.options[opt_OutputOffset].activated)
+ outoff = PORT_Atoi(bltest.options[opt_OutputOffset].arg);
+
+ testdir = (bltest.options[opt_SelfTestDir].activated) ?
+ strdup(bltest.options[opt_SelfTestDir].arg) : ".";
+
+ /*
+ * Handle three simple cases first
+ */
+
+ /* Do BLAPI self-test */
+ if (bltest.commands[cmd_SelfTest].activated) {
+ PRBool encrypt = PR_TRUE, decrypt = PR_TRUE;
+ /* user may specified a set of ciphers to test. parse them. */
+ bltestCipherMode modesToTest[NUMMODES];
+ int numModesToTest = 0;
+ char *tok, *str;
+ str = bltest.options[opt_Mode].arg;
+ while (str) {
+ tok = strchr(str, ',');
+ if (tok) *tok = '\0';
+ modesToTest[numModesToTest++] = get_mode(str);
+ if (tok) {
+ *tok = ',';
+ str = tok + 1;
+ } else {
+ break;
+ }
+ }
+ if (bltest.commands[cmd_Decrypt].activated &&
+ !bltest.commands[cmd_Encrypt].activated)
+ encrypt = PR_FALSE;
+ if (bltest.commands[cmd_Encrypt].activated &&
+ !bltest.commands[cmd_Decrypt].activated)
+ decrypt = PR_FALSE;
+ return blapi_selftest(modesToTest, numModesToTest, inoff, outoff,
+ encrypt, decrypt);
+ }
+
+ /* Do FIPS self-test */
+ if (bltest.commands[cmd_FIPS].activated) {
+ CK_RV ckrv = pk11_fipsPowerUpSelfTest();
+ fprintf(stdout, "CK_RV: %ld.\n", ckrv);
+ return 0;
+ }
+
+ /*
+ * Check command line arguments for Encrypt/Decrypt/Hash/Sign/Verify
+ */
+
+ if ((bltest.commands[cmd_Decrypt].activated ||
+ bltest.commands[cmd_Verify].activated) &&
+ bltest.options[opt_BufSize].activated) {
+ fprintf(stderr, "%s: cannot use a nonce as input to decrypt/verify.\n",
+ progName);
+ Usage();
+ }
+
+ if (bltest.options[opt_Mode].activated) {
+ cipherInfo.mode = get_mode(bltest.options[opt_Mode].arg);
+ if (cipherInfo.mode == bltestINVALID) {
+ fprintf(stderr, "%s: Invalid mode \"%s\"\n", progName,
+ bltest.options[opt_Mode].arg);
+ Usage();
+ }
+ } else {
+ fprintf(stderr, "%s: You must specify a cipher mode with -m.\n",
+ progName);
+ Usage();
+ }
+
+ if (bltest.options[opt_Repetitions].activated) {
+ cipherInfo.repetitions = PORT_Atoi(bltest.options[opt_Repetitions].arg);
+ } else {
+ cipherInfo.repetitions = 0;
+ }
+
+
+ if (bltest.options[opt_CXReps].activated) {
+ cipherInfo.cxreps = PORT_Atoi(bltest.options[opt_CXReps].arg);
+ } else {
+ cipherInfo.cxreps = 0;
+ }
+
+ /* Dump a file (rsakey, dsakey, etc.) */
+ if (bltest.commands[cmd_Dump].activated) {
+ return dump_file(cipherInfo.mode, bltest.options[opt_Input].arg);
+ }
+
+ /* default input mode is binary */
+ ioMode = (bltest.options[opt_B64].activated) ? bltestBase64Encoded :
+ (bltest.options[opt_Hex].activated) ? bltestHexStream :
+ (bltest.options[opt_HexWSpc].activated) ? bltestHexSpaceDelim :
+ bltestBinary;
+
+ if (bltest.options[opt_KeySize].activated)
+ keysize = PORT_Atoi(bltest.options[opt_KeySize].arg);
+ else
+ keysize = 0;
+
+ if (bltest.options[opt_Exponent].activated)
+ exponent = PORT_Atoi(bltest.options[opt_Exponent].arg);
+ else
+ exponent = 65537;
+
+ /* Set up an encryption key. */
+ keysize = 0;
+ file = NULL;
+ if (is_symmkeyCipher(cipherInfo.mode)) {
+ char *keystr = NULL; /* if key is on command line */
+ if (bltest.options[opt_Key].activated) {
+ if (bltest.options[opt_CmdLine].activated) {
+ keystr = bltest.options[opt_Key].arg;
+ } else {
+ file = PR_Open(bltest.options[opt_Key].arg, PR_RDONLY, 00660);
+ }
+ } else {
+ if (bltest.options[opt_KeySize].activated)
+ keysize = PORT_Atoi(bltest.options[opt_KeySize].arg);
+ else
+ keysize = 8; /* use 64-bit default (DES) */
+ /* save the random key for reference */
+ file = PR_Open("tmp.key", PR_WRONLY|PR_CREATE_FILE, 00660);
+ }
+ params->key.mode = ioMode;
+ setupIO(cipherInfo.arena, &params->key, file, keystr, keysize);
+ if (file)
+ PR_Close(file);
+ } else if (is_pubkeyCipher(cipherInfo.mode)) {
+ if (bltest.options[opt_Key].activated) {
+ file = PR_Open(bltest.options[opt_Key].arg, PR_RDONLY, 00660);
+ } else {
+ if (bltest.options[opt_KeySize].activated)
+ keysize = PORT_Atoi(bltest.options[opt_KeySize].arg);
+ else
+ keysize = 64; /* use 512-bit default */
+ file = PR_Open("tmp.key", PR_WRONLY|PR_CREATE_FILE, 00660);
+ }
+ params->key.mode = bltestBase64Encoded;
+ pubkeyInitKey(&cipherInfo, file, keysize, exponent);
+ PR_Close(file);
+ }
+
+ /* set up an initialization vector. */
+ if (cipher_requires_IV(cipherInfo.mode)) {
+ char *ivstr = NULL;
+ bltestSymmKeyParams *skp;
+ file = NULL;
+ if (cipherInfo.mode == bltestRC5_CBC)
+ skp = (bltestSymmKeyParams *)&params->rc5;
+ else
+ skp = &params->sk;
+ if (bltest.options[opt_IV].activated) {
+ if (bltest.options[opt_CmdLine].activated) {
+ ivstr = bltest.options[opt_IV].arg;
+ } else {
+ file = PR_Open(bltest.options[opt_IV].arg, PR_RDONLY, 00660);
+ }
+ } else {
+ /* save the random iv for reference */
+ file = PR_Open("tmp.iv", PR_WRONLY|PR_CREATE_FILE, 00660);
+ }
+ memset(&skp->iv, 0, sizeof skp->iv);
+ skp->iv.mode = ioMode;
+ setupIO(cipherInfo.arena, &skp->iv, file, ivstr, keysize);
+ if (file)
+ PR_Close(file);
+ }
+
+ if (bltest.commands[cmd_Verify].activated) {
+ if (!bltest.options[opt_SigFile].activated) {
+ fprintf(stderr, "%s: You must specify a signature file with -f.\n",
+ progName);
+ exit(-1);
+ }
+ file = PR_Open(bltest.options[opt_SigFile].arg, PR_RDONLY, 00660);
+ memset(&cipherInfo.params.dsa.sig, 0, sizeof(bltestIO));
+ cipherInfo.params.dsa.sig.mode = ioMode;
+ setupIO(cipherInfo.arena, &cipherInfo.params.dsa.sig, file, NULL, 0);
+ }
+
+ if (bltest.options[opt_PQGFile].activated) {
+ file = PR_Open(bltest.options[opt_PQGFile].arg, PR_RDONLY, 00660);
+ params->dsa.pqgdata.mode = bltestBase64Encoded;
+ setupIO(cipherInfo.arena, &params->dsa.pqgdata, file, NULL, 0);
+ }
+
+ /* Set up the input buffer */
+ if (bltest.options[opt_Input].activated) {
+ if (bltest.options[opt_CmdLine].activated) {
+ instr = bltest.options[opt_Input].arg;
+ infile = NULL;
+ } else {
+ /* form file name from testdir and input arg. */
+ char * filename = bltest.options[opt_Input].arg;
+ if (bltest.options[opt_SelfTestDir].activated &&
+ testdir && filename && filename[0] != '/')
+ filename = PR_smprintf("%s/tests/%s/%s", testdir,
+ mode_strings[cipherInfo.mode], filename);
+ infile = PR_Open(filename, PR_RDONLY, 00660);
+ }
+ } else if (bltest.options[opt_BufSize].activated) {
+ /* save the random plaintext for reference */
+ infile = PR_Open("tmp.in", PR_WRONLY|PR_CREATE_FILE, 00660);
+ } else {
+ infile = PR_STDIN;
+ }
+ if (!infile) {
+ fprintf(stderr, "%s: Failed to open input file.\n", progName);
+ exit(-1);
+ }
+ cipherInfo.input.mode = ioMode;
+
+ /* Set up the output stream */
+ if (bltest.options[opt_Output].activated) {
+ /* form file name from testdir and input arg. */
+ char * filename = bltest.options[opt_Output].arg;
+ if (bltest.options[opt_SelfTestDir].activated &&
+ testdir && filename && filename[0] != '/')
+ filename = PR_smprintf("%s/tests/%s/%s", testdir,
+ mode_strings[cipherInfo.mode], filename);
+ outfile = PR_Open(filename, PR_WRONLY|PR_CREATE_FILE, 00660);
+ } else {
+ outfile = PR_STDOUT;
+ }
+ if (!outfile) {
+ fprintf(stderr, "%s: Failed to open output file.\n", progName);
+ exit(-1);
+ }
+ cipherInfo.output.mode = ioMode;
+ if (bltest.options[opt_SelfTestDir].activated && ioMode == bltestBinary)
+ cipherInfo.output.mode = bltestBase64Encoded;
+
+ if (is_hashCipher(cipherInfo.mode))
+ cipherInfo.params.hash.restart = bltest.options[opt_Restart].activated;
+
+ bufsize = 0;
+ if (bltest.options[opt_BufSize].activated)
+ bufsize = PORT_Atoi(bltest.options[opt_BufSize].arg);
+
+ /*infile = NULL;*/
+ setupIO(cipherInfo.arena, &cipherInfo.input, infile, instr, bufsize);
+ misalignBuffer(cipherInfo.arena, &cipherInfo.input, inoff);
+
+ cipherInit(&cipherInfo, bltest.commands[cmd_Encrypt].activated);
+ misalignBuffer(cipherInfo.arena, &cipherInfo.output, outoff);
+
+ if (!bltest.commands[cmd_Nonce].activated) {
+ if (bltest.options[opt_MonteCarlo].activated) {
+ int mciter;
+ for (mciter=0; mciter<10000; mciter++) {
+ cipherDoOp(&cipherInfo);
+ memcpy(cipherInfo.input.buf.data,
+ cipherInfo.output.buf.data,
+ cipherInfo.input.buf.len);
+ }
+ } else {
+ cipherDoOp(&cipherInfo);
+ }
+ cipherFinish(&cipherInfo);
+ finishIO(&cipherInfo.output, outfile);
+ }
+
+ if (cipherInfo.repetitions > 0 || cipherInfo.cxreps > 0)
+ dump_performance_info(&cipherInfo,
+ bltest.commands[cmd_Encrypt].activated,
+ (cipherInfo.repetitions == 0));
+
+ if (infile && infile != PR_STDIN)
+ PR_Close(infile);
+ if (outfile && outfile != PR_STDOUT)
+ PR_Close(outfile);
+ PORT_FreeArena(cipherInfo.arena, PR_TRUE);
+
+ /*NSS_Shutdown();*/
+
+ return SECSuccess;
+}
diff --git a/security/nss/cmd/bltest/manifest.mn b/security/nss/cmd/bltest/manifest.mn
new file mode 100644
index 000000000..2bbe10999
--- /dev/null
+++ b/security/nss/cmd/bltest/manifest.mn
@@ -0,0 +1,54 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+CORE_DEPTH = ../../..
+
+MODULE = nss
+
+REQUIRES = seccmd dbm
+
+INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
+
+PROGRAM = bltest
+
+ USE_STATIC_LIBS = 1
+
+EXPORTS = \
+ $(NULL)
+
+PRIVATE_EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ blapitest.c \
+ $(NULL)
+
diff --git a/security/nss/cmd/bltest/tests/README b/security/nss/cmd/bltest/tests/README
new file mode 100644
index 000000000..9982a2f15
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/README
@@ -0,0 +1,49 @@
+This directory contains a set of tests for each cipher supported by
+BLAPI. Each subdirectory contains known plaintext and ciphertext pairs
+(and keys and/or iv's if needed). The tests can be run as a full set
+with:
+ bltest -T
+or as subsets, for example:
+ bltest -T -m des_ecb,md2,rsa
+
+In each subdirectory, the plaintext, key, and iv are ascii, and treated
+as such. The ciphertext is base64-encoded to avoid the hassle of binary
+files.
+
+To add a test, incremement the value in the numtests file. Create a
+plaintext, key, and iv file, such that the name of the file is
+incrememted one from the last set of tests. For example, if you are
+adding the second test, put your data in files named plaintext1, key1,
+and iv1 (ignoring key and iv if they are not needed, of course). Make
+sure your key and iv are the correct number of bytes for your cipher (a
+trailing \n is okay, but any other trailing bytes will be used!). Once
+you have your input data, create output data by running bltest on a
+trusted implementation. For example, for a new DES ECB test, run
+ bltest -E -m des_ecb -i plaintext1 -k key1 -o ciphertext1 -a in the
+tests/des_ecb directory. Then run
+ bltest -T des_ecb from the cmd/bltest directory in the tree of the
+implementation you want to test.
+
+Note that the -a option above is important, it tells bltest to expect
+the input to be straight ASCII, and not base64 encoded binary!
+
+Special cases:
+
+RC5:
+RC5 can take additional parameters, the number of rounds to perform and
+the wordsize to use. The number of rounds is between is between 0 and
+255, and the wordsize is either is either 16, 32, or 64 bits (at this
+time only 32-bit is supported). These parameters are specified in a
+paramsN file, where N is an index as above. The format of the file is
+"rounds=R\nwordsize=W\n".
+
+public key modes (RSA and DSA):
+Asymmetric key ciphers use keys with special properties, so creating a
+key file with "Mozilla!" in it will not get you very far! To create a
+public key, run bltest with the plaintext you want to encrypt, using a
+trusted implementation. bltest will generate a key and store it in
+"tmp.key", rename that file to keyN. For example:
+ bltest -E -m rsa -i plaintext0 -o ciphertext0 -e 65537 -g 32 -a
+ mv tmp.key key0
+
+[note: specifying a keysize (-g) when using RSA is important!]
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/ciphertext0 b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext0
new file mode 100644
index 000000000..040a397d7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/ciphertext0
@@ -0,0 +1 @@
+oJLgOzZ1GiWt3DGo2sPKaA==
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/iv0 b/security/nss/cmd/bltest/tests/aes_cbc/iv0
new file mode 100644
index 000000000..4e65bc034
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/iv0
@@ -0,0 +1 @@
+qwertyuiopasdfgh
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/key0 b/security/nss/cmd/bltest/tests/aes_cbc/key0
new file mode 100644
index 000000000..13911cc29
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/key0
@@ -0,0 +1 @@
+fedcba9876543210
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/numtests b/security/nss/cmd/bltest/tests/aes_cbc/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/aes_cbc/plaintext0 b/security/nss/cmd/bltest/tests/aes_cbc/plaintext0
new file mode 100644
index 000000000..8d6a8d555
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_cbc/plaintext0
@@ -0,0 +1 @@
+0123456789abcdef
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/ciphertext0 b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext0
new file mode 100644
index 000000000..d6818c1d0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/ciphertext0
@@ -0,0 +1 @@
+PVuaCIiaKQhblgFCbVMTTg==
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/key0 b/security/nss/cmd/bltest/tests/aes_ecb/key0
new file mode 100644
index 000000000..13911cc29
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/key0
@@ -0,0 +1 @@
+fedcba9876543210
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/numtests b/security/nss/cmd/bltest/tests/aes_ecb/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/aes_ecb/plaintext0 b/security/nss/cmd/bltest/tests/aes_ecb/plaintext0
new file mode 100644
index 000000000..8d6a8d555
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/aes_ecb/plaintext0
@@ -0,0 +1 @@
+0123456789abcdef
diff --git a/security/nss/cmd/bltest/tests/des3_cbc/ciphertext0 b/security/nss/cmd/bltest/tests/des3_cbc/ciphertext0
new file mode 100644
index 000000000..61dae3192
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_cbc/ciphertext0
@@ -0,0 +1 @@
+KV3MDNGKWOc=
diff --git a/security/nss/cmd/bltest/tests/des3_cbc/iv0 b/security/nss/cmd/bltest/tests/des3_cbc/iv0
new file mode 100644
index 000000000..97b5955f7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_cbc/iv0
@@ -0,0 +1 @@
+12345678
diff --git a/security/nss/cmd/bltest/tests/des3_cbc/key0 b/security/nss/cmd/bltest/tests/des3_cbc/key0
new file mode 100644
index 000000000..588efd111
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_cbc/key0
@@ -0,0 +1 @@
+abcdefghijklmnopqrstuvwx
diff --git a/security/nss/cmd/bltest/tests/des3_cbc/numtests b/security/nss/cmd/bltest/tests/des3_cbc/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_cbc/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/des3_cbc/plaintext0 b/security/nss/cmd/bltest/tests/des3_cbc/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_cbc/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/des3_ecb/ciphertext0 b/security/nss/cmd/bltest/tests/des3_ecb/ciphertext0
new file mode 100644
index 000000000..76dc820d3
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_ecb/ciphertext0
@@ -0,0 +1 @@
+RgckVNh4QcM=
diff --git a/security/nss/cmd/bltest/tests/des3_ecb/key0 b/security/nss/cmd/bltest/tests/des3_ecb/key0
new file mode 100644
index 000000000..588efd111
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_ecb/key0
@@ -0,0 +1 @@
+abcdefghijklmnopqrstuvwx
diff --git a/security/nss/cmd/bltest/tests/des3_ecb/numtests b/security/nss/cmd/bltest/tests/des3_ecb/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_ecb/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/des3_ecb/plaintext0 b/security/nss/cmd/bltest/tests/des3_ecb/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des3_ecb/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/des_cbc/ciphertext0 b/security/nss/cmd/bltest/tests/des_cbc/ciphertext0
new file mode 100644
index 000000000..67d2ad1aa
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_cbc/ciphertext0
@@ -0,0 +1 @@
+Perdg9FMYQ4=
diff --git a/security/nss/cmd/bltest/tests/des_cbc/iv0 b/security/nss/cmd/bltest/tests/des_cbc/iv0
new file mode 100644
index 000000000..97b5955f7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_cbc/iv0
@@ -0,0 +1 @@
+12345678
diff --git a/security/nss/cmd/bltest/tests/des_cbc/key0 b/security/nss/cmd/bltest/tests/des_cbc/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_cbc/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/des_cbc/numtests b/security/nss/cmd/bltest/tests/des_cbc/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_cbc/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/des_cbc/plaintext0 b/security/nss/cmd/bltest/tests/des_cbc/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_cbc/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/des_ecb/ciphertext0 b/security/nss/cmd/bltest/tests/des_ecb/ciphertext0
new file mode 100644
index 000000000..8be22fa5c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_ecb/ciphertext0
@@ -0,0 +1 @@
+3bNoWzzNiFc=
diff --git a/security/nss/cmd/bltest/tests/des_ecb/key0 b/security/nss/cmd/bltest/tests/des_ecb/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_ecb/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/des_ecb/numtests b/security/nss/cmd/bltest/tests/des_ecb/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_ecb/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/des_ecb/plaintext0 b/security/nss/cmd/bltest/tests/des_ecb/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/des_ecb/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/dsa/ciphertext0 b/security/nss/cmd/bltest/tests/dsa/ciphertext0
new file mode 100644
index 000000000..8e7150562
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/ciphertext0
@@ -0,0 +1 @@
+fB0bnKWvjT6X5NIkZ5l/Y/DXZ6QNI6j0iPhR/ZERkfj67xRnTWY1cg==
diff --git a/security/nss/cmd/bltest/tests/dsa/key0 b/security/nss/cmd/bltest/tests/dsa/key0
new file mode 100644
index 000000000..e582eeb04
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/key0
@@ -0,0 +1,6 @@
+AAAAQI3ypJRJInaqPSV1m7BoacvqwNg6+40M98u4Mk8NeILl0HYvxbchDq/C6a2s
+Mqt6rElpPfv4NyTC7Ac27jHIApEAAAAUx3MhjHN+yO6ZO08t7TD0jtrOkV8AAABA
+Ym0CeDnqChNBMWOlW0y1ACmdVSKVbO/LO/8Q85nOLC5xy53l+iS6v1jlt5Uhklyc
+xC6fb0ZLCIzFcq9T5teIAgAAAEAZExhx11sWEqgZ8p140bDXNG96p3u2KoWb/WxW
+ddqdIS06Nu8Wcu9mC4x8JVzA7HSFj7oz9EwGaZYwp2sDDuMzAAAAFCBwsyI9ujcv
+3hwP/HsuO0mLJgYU
diff --git a/security/nss/cmd/bltest/tests/dsa/keyseed0 b/security/nss/cmd/bltest/tests/dsa/keyseed0
new file mode 100644
index 000000000..6eea359db
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/keyseed0
@@ -0,0 +1 @@
+AAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/security/nss/cmd/bltest/tests/dsa/numtests b/security/nss/cmd/bltest/tests/dsa/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/dsa/plaintext0 b/security/nss/cmd/bltest/tests/dsa/plaintext0
new file mode 100644
index 000000000..48fbdb6fd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/plaintext0
@@ -0,0 +1 @@
+qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
diff --git a/security/nss/cmd/bltest/tests/dsa/pqg0 b/security/nss/cmd/bltest/tests/dsa/pqg0
new file mode 100644
index 000000000..f16326ccc
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/pqg0
@@ -0,0 +1,4 @@
+AAAAQI3ypJRJInaqPSV1m7BoacvqwNg6+40M98u4Mk8NeILl0HYvxbchDq/C6a2s
+Mqt6rElpPfv4NyTC7Ac27jHIApEAAAAUx3MhjHN+yO6ZO08t7TD0jtrOkV8AAABA
+Ym0CeDnqChNBMWOlW0y1ACmdVSKVbO/LO/8Q85nOLC5xy53l+iS6v1jlt5Uhklyc
+xC6fb0ZLCIzFcq9T5teIAg==
diff --git a/security/nss/cmd/bltest/tests/dsa/sigseed0 b/security/nss/cmd/bltest/tests/dsa/sigseed0
new file mode 100644
index 000000000..05d7fd2d6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/dsa/sigseed0
@@ -0,0 +1 @@
+aHpm2QZI+ZOGfhIfTd+d2wEgVYQ=
diff --git a/security/nss/cmd/bltest/tests/md2/ciphertext0 b/security/nss/cmd/bltest/tests/md2/ciphertext0
new file mode 100644
index 000000000..22e1fc496
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/md2/ciphertext0
@@ -0,0 +1 @@
+CS/UNcrWhB5Knt7Gf8Tz3Q==
diff --git a/security/nss/cmd/bltest/tests/md2/numtests b/security/nss/cmd/bltest/tests/md2/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/md2/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/md2/plaintext0 b/security/nss/cmd/bltest/tests/md2/plaintext0
new file mode 100644
index 000000000..dce2994ba
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/md2/plaintext0
@@ -0,0 +1 @@
+16-bytes to MD2.
diff --git a/security/nss/cmd/bltest/tests/md5/ciphertext0 b/security/nss/cmd/bltest/tests/md5/ciphertext0
new file mode 100644
index 000000000..ea11ee523
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/md5/ciphertext0
@@ -0,0 +1 @@
+XN8lnQuWAiMqmSGfvd8Hdw==
diff --git a/security/nss/cmd/bltest/tests/md5/numtests b/security/nss/cmd/bltest/tests/md5/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/md5/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/md5/plaintext0 b/security/nss/cmd/bltest/tests/md5/plaintext0
new file mode 100644
index 000000000..5ae3875e2
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/md5/plaintext0
@@ -0,0 +1 @@
+63-byte input to MD5 can be a bit tricky, but no problems here.
diff --git a/security/nss/cmd/bltest/tests/rc2_cbc/ciphertext0 b/security/nss/cmd/bltest/tests/rc2_cbc/ciphertext0
new file mode 100644
index 000000000..d964ef864
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_cbc/ciphertext0
@@ -0,0 +1 @@
+3ki6eVsWpY8=
diff --git a/security/nss/cmd/bltest/tests/rc2_cbc/iv0 b/security/nss/cmd/bltest/tests/rc2_cbc/iv0
new file mode 100644
index 000000000..97b5955f7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_cbc/iv0
@@ -0,0 +1 @@
+12345678
diff --git a/security/nss/cmd/bltest/tests/rc2_cbc/key0 b/security/nss/cmd/bltest/tests/rc2_cbc/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_cbc/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/rc2_cbc/numtests b/security/nss/cmd/bltest/tests/rc2_cbc/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_cbc/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/rc2_cbc/plaintext0 b/security/nss/cmd/bltest/tests/rc2_cbc/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_cbc/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/rc2_ecb/ciphertext0 b/security/nss/cmd/bltest/tests/rc2_ecb/ciphertext0
new file mode 100644
index 000000000..337d30765
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_ecb/ciphertext0
@@ -0,0 +1 @@
+WT+tc4fANhQ=
diff --git a/security/nss/cmd/bltest/tests/rc2_ecb/key0 b/security/nss/cmd/bltest/tests/rc2_ecb/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_ecb/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/rc2_ecb/numtests b/security/nss/cmd/bltest/tests/rc2_ecb/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_ecb/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/rc2_ecb/plaintext0 b/security/nss/cmd/bltest/tests/rc2_ecb/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc2_ecb/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/rc4/ciphertext0 b/security/nss/cmd/bltest/tests/rc4/ciphertext0
new file mode 100644
index 000000000..004f13472
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/ciphertext0
@@ -0,0 +1 @@
+34sTZJtr20k=
diff --git a/security/nss/cmd/bltest/tests/rc4/ciphertext1 b/security/nss/cmd/bltest/tests/rc4/ciphertext1
new file mode 100644
index 000000000..6050da4c6
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/ciphertext1
@@ -0,0 +1 @@
+34sTZJtr20nGP6VxS3BIBxxIYm6QGIa1rehFHn51z9M=
diff --git a/security/nss/cmd/bltest/tests/rc4/key0 b/security/nss/cmd/bltest/tests/rc4/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/rc4/key1 b/security/nss/cmd/bltest/tests/rc4/key1
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/key1
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/rc4/numtests b/security/nss/cmd/bltest/tests/rc4/numtests
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/rc4/plaintext0 b/security/nss/cmd/bltest/tests/rc4/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/rc4/plaintext1 b/security/nss/cmd/bltest/tests/rc4/plaintext1
new file mode 100644
index 000000000..d41abc7b8
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc4/plaintext1
@@ -0,0 +1 @@
+Mozilla!Mozilla!Mozilla!Mozilla!
diff --git a/security/nss/cmd/bltest/tests/rc5_cbc/ciphertext0 b/security/nss/cmd/bltest/tests/rc5_cbc/ciphertext0
new file mode 100644
index 000000000..544713b33
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_cbc/ciphertext0
@@ -0,0 +1 @@
+qsv4Fn2J6d0=
diff --git a/security/nss/cmd/bltest/tests/rc5_cbc/iv0 b/security/nss/cmd/bltest/tests/rc5_cbc/iv0
new file mode 100644
index 000000000..97b5955f7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_cbc/iv0
@@ -0,0 +1 @@
+12345678
diff --git a/security/nss/cmd/bltest/tests/rc5_cbc/key0 b/security/nss/cmd/bltest/tests/rc5_cbc/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_cbc/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/rc5_cbc/numtests b/security/nss/cmd/bltest/tests/rc5_cbc/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_cbc/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/rc5_cbc/params0 b/security/nss/cmd/bltest/tests/rc5_cbc/params0
new file mode 100644
index 000000000..d68e0362d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_cbc/params0
@@ -0,0 +1,2 @@
+rounds=10
+wordsize=4
diff --git a/security/nss/cmd/bltest/tests/rc5_cbc/plaintext0 b/security/nss/cmd/bltest/tests/rc5_cbc/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_cbc/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/rc5_ecb/ciphertext0 b/security/nss/cmd/bltest/tests/rc5_ecb/ciphertext0
new file mode 100644
index 000000000..133777dd0
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_ecb/ciphertext0
@@ -0,0 +1 @@
+4ZKK/1v5Ohc=
diff --git a/security/nss/cmd/bltest/tests/rc5_ecb/key0 b/security/nss/cmd/bltest/tests/rc5_ecb/key0
new file mode 100644
index 000000000..65513c116
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_ecb/key0
@@ -0,0 +1 @@
+zyxwvuts
diff --git a/security/nss/cmd/bltest/tests/rc5_ecb/numtests b/security/nss/cmd/bltest/tests/rc5_ecb/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_ecb/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/rc5_ecb/params0 b/security/nss/cmd/bltest/tests/rc5_ecb/params0
new file mode 100644
index 000000000..d68e0362d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_ecb/params0
@@ -0,0 +1,2 @@
+rounds=10
+wordsize=4
diff --git a/security/nss/cmd/bltest/tests/rc5_ecb/plaintext0 b/security/nss/cmd/bltest/tests/rc5_ecb/plaintext0
new file mode 100644
index 000000000..5513e438c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rc5_ecb/plaintext0
@@ -0,0 +1 @@
+Mozilla!
diff --git a/security/nss/cmd/bltest/tests/rsa/ciphertext0 b/security/nss/cmd/bltest/tests/rsa/ciphertext0
new file mode 100644
index 000000000..943ea599a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa/ciphertext0
@@ -0,0 +1 @@
+qPVrXv0y3SC5rY44bIi6GE4Aec8uDpHH7/cCg0FU5as=
diff --git a/security/nss/cmd/bltest/tests/rsa/key0 b/security/nss/cmd/bltest/tests/rsa/key0
new file mode 100644
index 000000000..1352fe986
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa/key0
@@ -0,0 +1,4 @@
+AAAAAAAAACC5lyu2K2ro8YGnvOCKaL1sFX1HEIblIVbuMXsa8oeFSwAAAAERAAAA
+IBXVjKwFG6LvPG4WOIjBBzmxGNpkQwDs3W5qZcXVzqahAAAAEOEOH/WnhZCJyM39
+oNfhf18AAAAQ0xvmxqXXs3L62xxogUl9lQAAABAaeiHgqkvy4wiQtG1Gkv/tAAAA
+EMaw2TNu6SFdKFXAYluQdjEAAAAQi0u+IlgKCt/hatGAsTrfzQ==
diff --git a/security/nss/cmd/bltest/tests/rsa/numtests b/security/nss/cmd/bltest/tests/rsa/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/rsa/plaintext0 b/security/nss/cmd/bltest/tests/rsa/plaintext0
new file mode 100644
index 000000000..d915bc88c
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/rsa/plaintext0
@@ -0,0 +1 @@
+512bitsforRSAPublicKeyEncryption
diff --git a/security/nss/cmd/bltest/tests/sha1/ciphertext0 b/security/nss/cmd/bltest/tests/sha1/ciphertext0
new file mode 100644
index 000000000..1fe4bd2bd
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha1/ciphertext0
@@ -0,0 +1 @@
+cDSMAygXMPIJZC5bntZ4ZhecQ9g=
diff --git a/security/nss/cmd/bltest/tests/sha1/numtests b/security/nss/cmd/bltest/tests/sha1/numtests
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha1/numtests
@@ -0,0 +1 @@
+1
diff --git a/security/nss/cmd/bltest/tests/sha1/plaintext0 b/security/nss/cmd/bltest/tests/sha1/plaintext0
new file mode 100644
index 000000000..863e79c65
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha1/plaintext0
@@ -0,0 +1 @@
+A cage went in search of a bird.
diff --git a/security/nss/cmd/bltest/tests/sha256/ciphertext0 b/security/nss/cmd/bltest/tests/sha256/ciphertext0
new file mode 100644
index 000000000..07e2ff14f
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha256/ciphertext0
@@ -0,0 +1 @@
+ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=
diff --git a/security/nss/cmd/bltest/tests/sha256/ciphertext1 b/security/nss/cmd/bltest/tests/sha256/ciphertext1
new file mode 100644
index 000000000..2ab6e1da5
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha256/ciphertext1
@@ -0,0 +1 @@
+JI1qYdIGOLjlwCaTDD5gOaM85Flk/yFn9uzt1BnbBsE=
diff --git a/security/nss/cmd/bltest/tests/sha256/numtests b/security/nss/cmd/bltest/tests/sha256/numtests
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha256/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/sha256/plaintext0 b/security/nss/cmd/bltest/tests/sha256/plaintext0
new file mode 100644
index 000000000..8baef1b4a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha256/plaintext0
@@ -0,0 +1 @@
+abc
diff --git a/security/nss/cmd/bltest/tests/sha256/plaintext1 b/security/nss/cmd/bltest/tests/sha256/plaintext1
new file mode 100644
index 000000000..afb5dce5d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha256/plaintext1
@@ -0,0 +1 @@
+abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq
diff --git a/security/nss/cmd/bltest/tests/sha384/ciphertext0 b/security/nss/cmd/bltest/tests/sha384/ciphertext0
new file mode 100644
index 000000000..c94f91e22
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha384/ciphertext0
@@ -0,0 +1 @@
+ywB1P0WjXou1oD1pmsZQBycsMqsO3tFjGotgWkP/W+2AhgcroefMI1i67KE0yCWn
diff --git a/security/nss/cmd/bltest/tests/sha384/ciphertext1 b/security/nss/cmd/bltest/tests/sha384/ciphertext1
new file mode 100644
index 000000000..833f06d84
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha384/ciphertext1
@@ -0,0 +1 @@
+CTMMM/cRR+g9GS/Hgs0bR1MRGxc7OwXSL6CAhuOw9xL8x8caVX4tuWbD6fqRdGA5
diff --git a/security/nss/cmd/bltest/tests/sha384/numtests b/security/nss/cmd/bltest/tests/sha384/numtests
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha384/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/sha384/plaintext0 b/security/nss/cmd/bltest/tests/sha384/plaintext0
new file mode 100644
index 000000000..8baef1b4a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha384/plaintext0
@@ -0,0 +1 @@
+abc
diff --git a/security/nss/cmd/bltest/tests/sha384/plaintext1 b/security/nss/cmd/bltest/tests/sha384/plaintext1
new file mode 100644
index 000000000..94fcc2b29
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha384/plaintext1
@@ -0,0 +1 @@
+abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu
diff --git a/security/nss/cmd/bltest/tests/sha512/ciphertext0 b/security/nss/cmd/bltest/tests/sha512/ciphertext0
new file mode 100644
index 000000000..8b626e237
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha512/ciphertext0
@@ -0,0 +1,2 @@
+3a81oZNherrMQXNJriBBMRLm+k6JqX6iCp7u5ktV05ohkpkqJ0/BqDa6PCOj/uu9
+RU1EI2Q86A4qmslPpUyknw==
diff --git a/security/nss/cmd/bltest/tests/sha512/ciphertext1 b/security/nss/cmd/bltest/tests/sha512/ciphertext1
new file mode 100644
index 000000000..c02d1752d
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha512/ciphertext1
@@ -0,0 +1,2 @@
+jpWbddrjE9qM9PcoFPwUP493ecbrn3+hcpmurbaIkBhQHSieSQD35DMbmd7EtUM6
+x9Mp7rbdJlReluVbh0vpCQ==
diff --git a/security/nss/cmd/bltest/tests/sha512/numtests b/security/nss/cmd/bltest/tests/sha512/numtests
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha512/numtests
@@ -0,0 +1 @@
+2
diff --git a/security/nss/cmd/bltest/tests/sha512/plaintext0 b/security/nss/cmd/bltest/tests/sha512/plaintext0
new file mode 100644
index 000000000..8baef1b4a
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha512/plaintext0
@@ -0,0 +1 @@
+abc
diff --git a/security/nss/cmd/bltest/tests/sha512/plaintext1 b/security/nss/cmd/bltest/tests/sha512/plaintext1
new file mode 100644
index 000000000..94fcc2b29
--- /dev/null
+++ b/security/nss/cmd/bltest/tests/sha512/plaintext1
@@ -0,0 +1 @@
+abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu
diff --git a/security/nss/cmd/btoa/Makefile b/security/nss/cmd/btoa/Makefile
new file mode 100644
index 000000000..763faa253
--- /dev/null
+++ b/security/nss/cmd/btoa/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/btoa/btoa.c b/security/nss/cmd/btoa/btoa.c
new file mode 100644
index 000000000..d58805c65
--- /dev/null
+++ b/security/nss/cmd/btoa/btoa.c
@@ -0,0 +1,196 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "plgetopt.h"
+#include "secutil.h"
+#include "nssb64.h"
+#include <errno.h>
+
+#if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
+#if !defined(WIN32)
+extern int fread(char *, size_t, size_t, FILE*);
+extern int fwrite(char *, size_t, size_t, FILE*);
+extern int fprintf(FILE *, char *, ...);
+#endif
+#endif
+
+#if defined(WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+static PRInt32
+output_ascii (void *arg, const char *obuf, PRInt32 size)
+{
+ FILE *outFile = arg;
+ int nb;
+
+ nb = fwrite(obuf, 1, size, outFile);
+ if (nb != size) {
+ PORT_SetError(SEC_ERROR_IO);
+ return -1;
+ }
+
+ return nb;
+}
+
+static SECStatus
+encode_file(FILE *outFile, FILE *inFile)
+{
+ NSSBase64Encoder *cx;
+ int nb;
+ SECStatus status = SECFailure;
+ unsigned char ibuf[4096];
+
+ cx = NSSBase64Encoder_Create(output_ascii, outFile);
+ if (!cx) {
+ return -1;
+ }
+
+ for (;;) {
+ if (feof(inFile)) break;
+ nb = fread(ibuf, 1, sizeof(ibuf), inFile);
+ if (nb != sizeof(ibuf)) {
+ if (nb == 0) {
+ if (ferror(inFile)) {
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
+ }
+ /* eof */
+ break;
+ }
+ }
+
+ status = NSSBase64Encoder_Update(cx, ibuf, nb);
+ if (status != SECSuccess) goto loser;
+ }
+
+ status = NSSBase64Encoder_Destroy(cx, PR_FALSE);
+ if (status != SECSuccess)
+ return status;
+
+ /*
+ * Add a trailing CRLF. Note this must be done *after* the call
+ * to Destroy above (because only then are we sure all data has
+ * been written out).
+ */
+ fwrite("\r\n", 1, 2, outFile);
+ return SECSuccess;
+
+ loser:
+ (void) NSSBase64Encoder_Destroy(cx, PR_TRUE);
+ return status;
+}
+
+static void Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+ char *progName;
+ SECStatus rv;
+ FILE *inFile, *outFile;
+ PLOptState *optstate;
+ PLOptStatus status;
+
+ inFile = 0;
+ outFile = 0;
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName+1 : argv[0];
+
+ /* Parse command line arguments */
+ optstate = PL_CreateOptState(argc, argv, "i:o:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ default:
+ Usage(progName);
+ break;
+
+ case 'i':
+ inFile = fopen(optstate->value, "rb");
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+ }
+ }
+ if (status == PL_OPT_BAD)
+ Usage(progName);
+ if (!inFile) {
+#if defined(WIN32)
+ /* If we're going to read binary data from stdin, we must put stdin
+ ** into O_BINARY mode or else incoming \r\n's will become \n's.
+ */
+
+ int smrv = _setmode(_fileno(stdin), _O_BINARY);
+ if (smrv == -1) {
+ fprintf(stderr,
+ "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
+ progName);
+ return smrv;
+ }
+#endif
+ inFile = stdin;
+ }
+ if (!outFile)
+ outFile = stdout;
+ rv = encode_file(outFile, inFile);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
+ progName, PORT_GetError(), errno);
+ return -1;
+ }
+ return 0;
+}
diff --git a/security/nss/cmd/btoa/makefile.win b/security/nss/cmd/btoa/makefile.win
new file mode 100644
index 000000000..28d3ee873
--- /dev/null
+++ b/security/nss/cmd/btoa/makefile.win
@@ -0,0 +1,130 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+#cannot define PROGRAM in manifest compatibly with NT and UNIX
+PROGRAM = btoa
+PROGRAM = ./$(OBJDIR)/$(PROGRAM).exe
+include <$(DEPTH)\config\config.mak>
+
+# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
+# rules.mak will append C_OBJS onto OBJS.
+# OBJS = $(CSRCS:.c=.obj)
+
+# include files are looked for in $LINCS and $INCS.
+# $LINCS is in manifest.mnw, computed from REQUIRES=
+INCS = $(INCS) \
+ -I$(DEPTH)/security/lib/cert \
+ -I../include \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+ $(NULL)
+
+
+WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
+
+# these files are the content of libdbm
+DBM_LIB = \
+ $(WINFE)/DB.obj \
+ $(WINFE)/HASH.obj \
+ $(WINFE)/H_BIGKEY.obj \
+ $(WINFE)/H_PAGE.obj \
+ $(WINFE)/H_LOG2.obj \
+ $(WINFE)/H_FUNC.obj \
+ $(WINFE)/HASH_BUF.obj \
+ $(NULL)
+
+MOZ_LIBS = \
+ $(WINFE)/ALLXPSTR.obj \
+ $(WINFE)/XP_ERROR.obj \
+ $(WINFE)/XPASSERT.obj \
+ $(WINFE)/XP_REG.obj \
+ $(WINFE)/XP_TRACE.obj \
+ $(DBM_LIB) \
+ $(WINFE)/XP_STR.obj \
+ $(WINFE)/MKTEMP.obj \
+ $(NULL)
+
+SEC_LIBS = \
+ $(DIST)/lib/cert$(MOZ_BITS).lib \
+ $(DIST)/lib/crypto$(MOZ_BITS).lib \
+ $(DIST)/lib/hash$(MOZ_BITS).lib \
+ $(DIST)/lib/key$(MOZ_BITS).lib \
+ $(DIST)/lib/pkcs7$(MOZ_BITS).lib \
+ $(DIST)/lib/secmod$(MOZ_BITS).lib \
+ $(DIST)/lib/secutl$(MOZ_BITS).lib \
+ $(DIST)/lib/ssl$(MOZ_BITS).lib \
+ $(NULL)
+
+LLFLAGS = $(LLFLAGS) \
+ ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
+ $(SEC_LIBS) \
+ $(MOZ_LIBS) \
+ $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
+ $(LIBNSPR) \
+ $(NULL)
+
+
+include <$(DEPTH)\config\rules.mak>
+
+INSTALL = $(MAKE_INSTALL)
+
+objs: $(OBJS)
+
+$(PROGRAM)::
+ $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
+
+programs: $(PROGRAM)
+
+install:: $(TARGETS)
+ $(INSTALL) $(TARGETS) $(DIST)/bin
+
+
+symbols:
+ @echo "CSRCS = $(CSRCS)"
+ @echo "INCS = $(INCS)"
+ @echo "OBJS = $(OBJS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "TARGETS = $(TARGETS)"
+ @echo "DIST = $(DIST)"
+ @echo "VERSION_NUMBER = $(VERSION_NUMBER)"
+ @echo "WINFE = $(WINFE)"
+ @echo "DBM_LIB = $(DBM_LIB)"
+ @echo "INSTALL = $(INSTALL)"
+
diff --git a/security/nss/cmd/btoa/manifest.mn b/security/nss/cmd/btoa/manifest.mn
new file mode 100644
index 000000000..b82b26a5c
--- /dev/null
+++ b/security/nss/cmd/btoa/manifest.mn
@@ -0,0 +1,49 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# MODULE is implicitly REQUIRED, doesn't need to be listed below.
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = btoa.c
+
+PROGRAM = btoa
+
diff --git a/security/nss/cmd/certcgi/HOWTO.txt b/security/nss/cmd/certcgi/HOWTO.txt
new file mode 100644
index 000000000..f02ad32fd
--- /dev/null
+++ b/security/nss/cmd/certcgi/HOWTO.txt
@@ -0,0 +1,168 @@
+ How to setup your very own Cert-O-Matic Root CA server
+
+***** BEGIN LICENSE BLOCK *****
+Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+The contents of this file are subject to the Mozilla Public License Version
+1.1 (the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+for the specific language governing rights and limitations under the
+License.
+
+The Original Code is Netscape security libraries.
+
+The Initial Developer of the Original Code is Netscape Communications
+Corporation. Portions created by the Initial Developer are
+Copyright (C) 2001 the Initial Developer. All Rights Reserved.
+
+Contributor(s):
+
+Alternatively, the contents of this file may be used under the terms of
+either the GNU General Public License Version 2 or later (the "GPL"), or
+the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+in which case the provisions of the GPL or the LGPL are applicable instead
+of those above. If you wish to allow use of your version of this file only
+under the terms of either the GPL or the LGPL, and not to allow others to
+use your version of this file under the terms of the MPL, indicate your
+decision by deleting the provisions above and replace them with the notice
+and other provisions required by the GPL or the LGPL. If you do not delete
+the provisions above, a recipient may use your version of this file under
+the terms of any one of the MPL, the GPL or the LGPL.
+
+***** END LICENSE BLOCK *****
+
+ How to setup your very own Cert-O-Matic Root CA server
+
+The program certcgi is part of a small test CA that is used inside
+Netscape by the NSS development team. That CA is affectionately known
+as "Cert-O-Matic" or "Cert-O-Matic II". It presently runs on a server
+named interzone.mcom.com inside Netscape's firewall.
+
+If you wish to setup your own Cert-O-Matic, here are directions.
+
+Disclaimer: This program does not follow good practices for root CAs.
+It should be used only for playing/testing and never for production use.
+Remember, you've been warned!
+
+Cert-O-Matic consists of some html files, shell scripts, one executable
+program that uses NSS and NSPR, the usual set of NSS .db files, and a file
+in which to remember the serial number of the last cert issued. The
+html files and the source to the executable program are in this directory.
+Sample shell scripts are shown below.
+
+The shell scripts and executable program run as CGI "scripts". The
+entire thing runs on an ordinary http web server. It would also run on
+an https web server. The shell scripts and html files must be
+customized for the server on which they run.
+
+The package assumes you have a "document root" directory $DOCROOT, and a
+"cgi-bin" directory $CGIBIN. In this example, the document root is
+assumed to be located in /var/www/htdocs, and the cgi-bin directory in
+/var/www/cgi-bin.
+
+The server is assumed to run all cgi scripts as the user "nobody".
+The names of the cgi scripts run directly by the server all end in .cgi
+because some servers like it that way.
+
+Instructions:
+
+- Create directory $DOCROOT/certomatic
+- Copy the following files from nss/cmd/certcgi to $DOCROOT/certomatic
+ ca.html index.html main.html nscp_ext_form.html stnd_ext_form.html
+- Edit the html files, substituting the name of your own server for the
+ server named in those files.
+- In some web page (e.g. your server's home page), provide an html link to
+ $DOCROOT/certomatic/index.html. This is where users start to get their
+ own certs from certomatic.
+- give these files and directories appropriate permissions.
+
+- Create directories $CGIBIN/certomatic and $CGIBIN/certomatic/bin
+ make sure that $CGIBIN/certomatic is writable by "nobody"
+
+- Create a new set of NSS db files there with the following command:
+
+ certutil -N -d $CGIBIN/certomatic
+
+- when certutil prompts you for the password, enter the word foo
+ because that is compiled into the certcgi program.
+
+- Create the new Root CA cert with this command
+
+ certutil -S -x -d $CGIBIN/certomatic -n "Cert-O-Matic II" \
+ -s "CN=Cert-O-Matic II, O=Cert-O-Matic II" -t TCu,cu,cu -k rsa \
+ -g 1024 -m 10001 -v 60
+
+ (adjust the -g, -m and -v parameters to taste. -s and -x must be as
+shown.)
+
+- dump out the new root CA cert in base64 encoding:
+
+ certutil -d $CGIBIN/certomatic -L -n "Cert-O-Matic II" -a > \
+ $CGIBIN/certomatic/root.cacert
+
+- In $CGIBIN/certomatic/bin add two shell scripts - one to download the
+ root CA cert on demand, and one to run the certcgi program.
+
+download.cgi, the script to install the root CA cert into a browser on
+demand, is this:
+
+#!/bin/sh
+echo "Content-type: application/x-x509-ca-cert"
+echo
+cat $CGIBIN/certomatic/root.cacert
+
+You'll have to put the real path into that cat command because CGIBIN
+won't be defined when this script is run by the server.
+
+certcgi.cgi, the script to run the certcgi program is similar to this:
+
+#!/bin/sh
+cd $CGIBIN/certomatic/bin
+LD_LIBRARY_PATH=$PLATFORM/lib
+export LD_LIBRARY_PATH
+$PLATFORM/bin/certcgi $* 2>&1
+
+Where $PLATFORM/lib is where the NSPR nad NSS DSOs are located, and
+$PLATFORM/bin is where certcgi is located. PLATFORM is not defined when
+the server runs this script, so you'll have to substitute the right value
+in your script. certcgi requires that the working directory be one level
+below the NSS DBs, that is, the DBs are accessed in the directory "..".
+
+You'll want to provide an html link somewhere to the script that downloads
+the root.cacert file. You'll probably want to put that next to the link
+that loads the index.html page. On interzone, this is done with the
+following html:
+
+<a href="/certomatic/index.html">Cert-O-Matic II Root CA server</a>
+<p>
+<a href="/cgi-bin/certomatic/bin/download.cgi">Download and trust Root CA
+certificate</a>
+
+The index.html file in this directory invokes the certcgi.cgi script with
+the form post method, so if you change the name of the certcgi.cgi script,
+you'll also have to change the index.html file in $DOCROOT/certomatic
+
+The 4 files used by the certcgi program (the 3 NSS DBs, and the serial
+number file) are not required to live in $CGIBIN/certomatic, but they are
+required to live in $CWD/.. when certcgi starts.
+
+Known bugs:
+
+1. Because multiple of these CAs exist simultaneously, it would be best if
+they didn't all have to be called "Cert-O-Matic II", but that string is
+presently hard coded into certcgi.c.
+
+2. the html files in this directory contain numerous extraneous <FORM> tags
+which appear to use the post method and have action URLS that are never
+actually used. burp.cgi and echoform.cgi are never actually used. This
+should be cleaned up.
+
+3. The html files use <layer> tags which are supported only in Netscape
+Navigator and Netscape Communication 4.x browsers. The html files do
+not work as intended with Netscape 6.x, Mozilla or Microsoft IE browsers.
+The html files should be fixed to work with all those named browsers.
+
diff --git a/security/nss/cmd/certcgi/Makefile b/security/nss/cmd/certcgi/Makefile
new file mode 100644
index 000000000..573c12cac
--- /dev/null
+++ b/security/nss/cmd/certcgi/Makefile
@@ -0,0 +1,76 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/certcgi/ca.html b/security/nss/cmd/certcgi/ca.html
new file mode 100644
index 000000000..b9ffd8238
--- /dev/null
+++ b/security/nss/cmd/certcgi/ca.html
@@ -0,0 +1,48 @@
+<!--
+ - The contents of this file are subject to the Mozilla Public
+ - License Version 1.1 (the "License"); you may not use this file
+ - except in compliance with the License. You may obtain a copy of
+ - the License at http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS
+ - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ - implied. See the License for the specific language governing
+ - rights and limitations under the License.
+ -
+ - The Original Code is the Netscape security libraries.
+ -
+ - The Initial Developer of the Original Code is Netscape
+ - Communications Corporation. Portions created by Netscape are
+ - Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ - Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the
+ - terms of the GNU General Public License Version 2 or later (the
+ - "GPL"), in which case the provisions of the GPL are applicable
+ - instead of those above. If you wish to allow use of your
+ - version of this file only under the terms of the GPL and not to
+ - allow others to use your version of this file under the MPL,
+ - indicate your decision by deleting the provisions above and
+ - replace them with the notice and other provisions required by
+ - the GPL. If you do not delete the provisions above, a recipient
+ - may use your version of this file under either the MPL or the
+ - GPL.
+ -->
+
+<form method="post" name="ca_form" action="mailto:jerdonek@netscape.com">
+<input type="radio" name="caChoiceradio" value="SignWithDefaultkey"
+ onClick="{parent.choice_change(this.form)}">
+ Use the Cert-O-matic certificate to issue the cert</p>
+<input type="radio" name="caChoiceradio" value="SignWithRandomChain"
+ onClick="{parent.choice_change(this.form)}"> Use a
+ <input type="text" size="2" maxsize="2" name="autoCAs"> CA long
+ automatically generated chain ending with the Cert-O-Matic Cert
+ (18 maximum)</p>
+<input type="radio" name="caChoiceradio" value="SignWithSpecifiedChain"
+ onClick="{parent.choice_change(this.form)}"> Use a
+ <input type="text" size="1" maxlength="1" name="manCAs"
+ onChange="{parent.ca_num_change(this.value,this.form)}"> CA long
+ user input chain ending in the Cert-O-Matic Cert.</p>
+</form>
diff --git a/security/nss/cmd/certcgi/ca_form.html b/security/nss/cmd/certcgi/ca_form.html
new file mode 100644
index 000000000..43042cb64
--- /dev/null
+++ b/security/nss/cmd/certcgi/ca_form.html
@@ -0,0 +1,385 @@
+<html>
+<!--
+ - The contents of this file are subject to the Mozilla Public
+ - License Version 1.1 (the "License"); you may not use this file
+ - except in compliance with the License. You may obtain a copy of
+ - the License at http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS
+ - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ - implied. See the License for the specific language governing
+ - rights and limitations under the License.
+ -
+ - The Original Code is the Netscape security libraries.
+ -
+ - The Initial Developer of the Original Code is Netscape
+ - Communications Corporation. Portions created by Netscape are
+ - Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ - Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the
+ - terms of the GNU General Public License Version 2 or later (the
+ - "GPL"), in which case the provisions of the GPL are applicable
+ - instead of those above. If you wish to allow use of your
+ - version of this file only under the terms of the GPL and not to
+ - allow others to use your version of this file under the MPL,
+ - indicate your decision by deleting the provisions above and
+ - replace them with the notice and other provisions required by
+ - the GPL. If you do not delete the provisions above, a recipient
+ - may use your version of this file under either the MPL or the
+ - GPL.
+ -->
+ <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi">
+ <table border=0 cellspacing=10 cellpadding=0>
+ <tr>
+ <td>
+ Common Name:</td><td> <input type="text" name="name" onChange="{window.top.reset_subject('CN=', value, form)}"></p>
+ </td>
+ <td></td><td></td><td>
+ Mail: </td><td><input type="text" name="email" onChange="var temp;{if (email_type[0].checked) {temp = 'MAIL='} else {temp = 'E='}} ;{window.top.reset_subject(temp, value, form)}"></p>
+ RFC 1274<input type="radio" name="email_type" value="1" onClick="window.top.switch_mail(form)">
+ e-mail<input type="radio" name="email_type" value="2" checked onClick="window.top.switch_mail(form)"></td>
+ <tr>
+ <td>
+ Organization: </td><td> <input type="text" name="org" onChange="{window.top.reset_subject('O=', value, form)}"></p></td>
+ <td></td><td></td><td>
+ Organizational Unit: </td><td><input type="text" name="org_unit" onChange="{window.top.reset_subject('OU=', value, form)}"></p></td>
+ <tr>
+ <td>
+ RFC 1274 UID: </td><td><input type="text" name="uid" onChange="{window.top.reset_subject('UID=', value, form)}"></p></td>
+ <td></td><td></td><td>
+ Locality: </td><td><input type="text" name="loc" onChange="{window.top.reset_subject('L=', value, form)}"></p></td>
+ <tr>
+ <td>
+ State or Province: </td><td><input type="text" name="state" onChange="{window.top.reset_subject('ST=', value, form)}"></p></td>
+ <td></td><td></td><td>
+ Country: </td><td><input type="text" size="2" maxsize="2" name="country" onChange="{window.top.reset_subject('C=', value, form)}"></p></td>
+ </table>
+ <table border=0 cellspacing=10 cellpadding=0>
+ <tr>
+ <td>
+ Serial Number:</p>
+ <DD>
+ <input type="radio" name="serial" value="auto" checked> Auto Generate</P>
+ <DD>
+ <input type="radio" name="serial" value="input">
+ Use this value: <input type="text" name="serial_value" size="8" maxlength="8"></p>
+ </td>
+ <td></td><td></td><td></td><td></td>
+ <td>
+ X.509 version:</p>
+ <DD>
+ <input type="radio" name="ver" value="1" checked> Version 1</p>
+ <DD>
+ <input type="radio" name="ver" value="3"> Version 3</P></td>
+ <td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
+ <td>
+ Key Type:</p>
+ <DD>
+ <input type="radio" name="keyType" value="rsa" checked> RSA</p>
+ <DD>
+ <input type="radio" name="keyType" value="dsa"> DSA</P></td>
+ </table>
+ DN: <input type="text" name="subject" size="70" onChange="{window.top.reset_subjectFields(form)}"></P>
+ <Select name="keysize">
+ <option>1024 (High Grade)
+ <option>768 (Medium Grade)
+ <option>512 (Low Grade)
+ </select>
+ </p>
+ <hr>
+ </p>
+ <table border=1 cellspacing=5 cellpadding=5>
+ <tr>
+ <td>
+ <b>Netscape Certificate Type: </b></p>
+ Activate extension: <input type="checkbox" name="netscape-cert-type"></P>
+ Critical: <input type="checkbox" name="netscape-cert-type-crit">
+ <td>
+ <input type="checkbox" name="netscape-cert-type-ssl-client"> SSL Client</P>
+ <input type="checkbox" name="netscape-cert-type-ssl-server"> SSL Server</P>
+ <input type="checkbox" name="netscape-cert-type-smime"> S/MIME</P>
+ <input type="checkbox" name="netscape-cert-type-object-signing"> Object Signing</P>
+ <input type="checkbox" name="netscape-cert-type-reserved"> Reserved for future use (bit 4)</P>
+ <input type="checkbox" name="netscape-cert-type-ssl-ca"> SSL CA</P>
+ <input type="checkbox" name="netscape-cert-type-smime-ca"> S/MIME CA</P>
+ <input type="checkbox" name="netscape-cert-type-object-signing-ca"> Object Signing CA</P>
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Base URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-base-url"></P>
+ Critical: <input type="checkbox" name="netscape-base-url-crit">
+ <td>
+ <input type="text" name="netscape-base-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Revocation URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-revocation-url"></P>
+ Critical: <input type="checkbox" name="netscape-revocation-url-crit">
+ <td>
+ <input type="text" name="netscape-revocation-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape CA Revocation URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-ca-revocation-url"></P>
+ Critical: <input type="checkbox" name="netscape-ca-revocation-url-crit">
+ <td>
+ <input type="text" name="netscape-ca-revocation-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Certificate Renewal URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-cert-renewal-url"></P>
+ Critical: <input type="checkbox" name="netscape-cert-renewal-url-crit">
+ <td>
+ <input type="text" name="netscape-cert-renewal-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape CA Policy URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-ca-policy-url"></P>
+ Critical: <input type="checkbox" name="netscape-ca-policy-url-crit">
+ <td>
+ <input type="text" name="netscape-ca-policy-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape SSL Server Name:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-ssl-server-name"></P>
+ Critical: <input type="checkbox" name="netscape-ssl-server-name-crit">
+ <td>
+ <input type="text" name="netscape-ssl-server-name-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Comment:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-comment"></P>
+ Critical: <input type="checkbox" name="netscape-comment-crit">
+ <td>
+ <textarea name="netscape-comment-text" rows="5" cols="50"></textarea>
+ </tr>
+ </table>
+ </p>
+ <hr>
+ </p>
+ <table border=1 cellspacing=5 cellpadding=5>
+ <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi">
+ <tr>
+ <td>
+ <b>Key Usage: </b></p>
+ Activate extension: <input type="checkbox" name="keyUsage"></P>
+ Critical: <input type="checkbox" name="keyUsage-crit">
+ <td>
+ <input type="checkbox" name="keyUsage-digitalSignature"> Digital Signature</P>
+ <input type="checkbox" name="keyUsage-nonRepudiation"> Non Repudiation</P>
+ <input type="checkbox" name="keyUsage-keyEncipherment"> Key Encipherment</P>
+ <input type="checkbox" name="keyUsage-dataEncipherment"> Data Encipherment</P>
+ <input type="checkbox" name="keyUsage-keyAgreement"> Key Agreement</P>
+ <input type="checkbox" name="keyUsage-keyCertSign"> Key Certificate Signing</P>
+ <input type="checkbox" name="keyUsage-cRLSign"> CRL Signing</P>
+ </tr>
+ <tr>
+ <td>
+ <b>Extended Key Usage: </b></p>
+ Activate extension: <input type="checkbox" name="extKeyUsage"></P>
+ Critical: <input type="checkbox" name="extKeyUsage-crit">
+ <td>
+ <input type="checkbox" name="extKeyUsage-serverAuth"> Server Auth</P>
+ <input type="checkbox" name="extKeyUsage-clientAuth"> Client Auth</P>
+ <input type="checkbox" name="extKeyUsage-codeSign"> Code Signing</P>
+ <input type="checkbox" name="extKeyUsage-emailProtect"> Email Protection</P>
+ <input type="checkbox" name="extKeyUsage-timeStamp"> Timestamp</P>
+ <input type="checkbox" name="extKeyUsage-ocspResponder"> OCSP Responder</P>
+ <input type="checkbox" name="extKeyUsage-NS-govtApproved"> Step-up</P>
+ </tr>
+ <tr>
+ <td>
+ <b>Basic Constraints:</b></p>
+ Activate extension: <input type="checkbox" name="basicConstraints"></P>
+ Critical: <input type="checkbox" name="basicConstraints-crit">
+ <td>
+ CA:</p>
+ <dd><input type=radio name="basicConstraints-cA-radio" value="CA"> True</p>
+ <dd><input type=radio name="basicConstraints-cA-radio" value="NotCA"> False</p>
+ <input type="checkbox" name="basicConstraints-pathLengthConstraint">
+ Include Path length: <input type="text" name="basicConstraints-pathLengthConstraint-text" size="2"></p>
+ </tr>
+ <tr>
+ <td>
+ <b>Authority Key Identifier:</b></p>
+ Activate extension: <input type="checkbox" name="authorityKeyIdentifier">
+ <td>
+ <input type="radio" name="authorityKeyIdentifier-radio" value="keyIdentifier"> Key Identider</p>
+ <input type="radio" name="authorityKeyIdentifier-radio" value="authorityCertIssuer"> Issuer Name and Serial number</p>
+ </tr>
+ <tr>
+ <td>
+ <b>Subject Key Identifier:</b></p>
+ Activate extension: <input type="checkbox" name="subjectKeyIdentifier">
+ <td>
+ Key Identifier:
+ <input type="text" name="subjectKeyIdentifier-text"></p>
+ This is an:<p>
+ <dd><dd><input type="radio" name="subjectKeyIdentifier-radio" value="ascii"> ascii text value<p>
+ <dd><dd><input type="radio" name="subjectKeyIdentifier-radio" value="hex"> hex value<p>
+ </tr>
+ <tr>
+ <td>
+ <b>Private Key Usage Period:</b></p>
+ Activate extension: <input type="checkbox" name="privKeyUsagePeriod"></p>
+ Critical: <input type="checkbox" name="privKeyUsagePeriod-crit">
+ <td>
+ Use:</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-radio" value="notBefore"> Not Before</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-radio" value="notAfter"> Not After</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-radio" value="both" > Both</p>
+ <b>Not to be used to sign before:</b></p>
+ <dd><input type="radio" name="privKeyUsagePeriod-notBefore-radio" value="auto"> Set to time of certificate issue</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-notBefore-radio" value="manual"> Use This value</p>
+ <dd><dd>(YYYY/MM/DD HH:MM:SS):
+ <input type="text" name="privKeyUsagePeriod-notBefore-year" size="4" maxlength="4">/
+ <input type="text" name="privKeyUsagePeriod-notBefore-month" size="2" maxlength="2">/
+ <input type="text" name="privKeyUsagePeriod-notBefore-day" size="2" maxlength="2">
+ <input type="text" name="privKeyUsagePeriod-notBefore-hour" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notBefore-minute" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notBefore-second" size="2" maxlength="2"></p>
+ <b>Not to be used to sign after:</b></p>
+ <dd>(YYYY/MM/DD HH:MM:SS):
+ <input type="text" name="privKeyUsagePeriod-notAfter-year" size="4" maxlength="4">/
+ <input type="text" name="privKeyUsagePeriod-notAfter-month" size="2" maxlength="2">/
+ <input type="text" name="privKeyUsagePeriod-notAfter-day" size="2" maxlength="2">
+ <input type="text" name="privKeyUsagePeriod-notAfter-hour" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notAfter-minute" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notAfter-second" size="2" maxlength="2"></p>
+ </tr>
+ <tr>
+ <td>
+ <b>Subject Alternative Name:</b></p>
+ Activate extension: <input type="checkbox" name="SubAltName"></P>
+ Critical: <input type="checkbox" name="SubAltName-crit">
+ <td>
+ <table>
+ <tr>
+ <td>
+ General Names:</p>
+ <select name="SubAltNameSelect" multiple size="10">
+ </select></p></p>
+ <input type="button" name="SubAltName-add" value="Add" onClick="{parent.addSubAltName(this.form)}">
+ <input type="button" name="SubAltName-delete" value="Delete" onClick="parent.deleteSubAltName(this.form)">
+ </td><td>
+ <table><tr><td>
+ Name Type: </td></tr><tr><td>
+ <input type="radio" name="SubAltNameRadio" value="otherName" onClick="parent.setSubAltNameType(form)"> Other Name,
+ OID: <input type="text" name="SubAltNameOtherNameOID" size="6"> </td><td>
+ <input type="radio" name="SubAltNameRadio" value="rfc822Name" onClick="parent.setSubAltNameType(form)"> RFC 822 Name</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="dnsName" onClick="parent.setSubAltNameType(form)"> DNS Name </td><td>
+ <input type="radio" name="SubAltNameRadio" value="x400" onClick="parent.setSubAltNameType(form)"> X400 Address</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="directoryName" onClick="parent.setSubAltNameType(form)"> Directory Name</td><td>
+ <input type="radio" name="SubAltNameRadio" value="ediPartyName" onClick="parent.setSubAltNameType(form)"> EDI Party Name</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="URL" onClick="parent.setSubAltNameType(form)"> Uniform Resource Locator</td><td>
+ <input type="radio" name="SubAltNameRadio" value="ipAddress" onClick="parent.setSubAltNameType(form)"> IP Address</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="regID"onClick="parent.setSubAltNameType(form)"> Registered ID</td><td>
+ <input type="radio" name="SubAltNameRadio" value="nscpNickname" onClick="parent.setSubAltNameType(form)"> Netscape Certificate Nickname</td><td></tr>
+ </table>
+ Name: <input type="text" name="SubAltNameText">
+ Binary Encoded: <input type="checkbox" name="SubAltNameDataType" value="binary" onClick="parent.setSubAltNameType(form)"></p>
+ </tr>
+ </table>
+ </tr>
+
+
+ <tr>
+ <td>
+ <b>Issuer Alternative Name:</b></p>
+ Activate extension: <input type="checkbox" name="IssuerAltName"></P>
+ Critical: <input type="checkbox" name="IssuerAltName-crit">
+ <td>
+ <input type="radio" name="IssuerAltNameSourceRadio" value="auto"> Use the Subject Alternative Name from the Issuers Certificate</p>
+ <input type="radio" name="IssuerAltNameSourceRadio" value="man"> Use this Name:
+ <table>
+ <tr>
+ <td>
+ General Names:</p>
+ <select name="IssuerAltNameSelect" multiple size="10">
+ </select></p></p>
+ <input type="button" name="IssuerAltName-add" value="Add" onClick="{parent.addIssuerAltName(this.form)}">
+ <input type="button" name="IssuerAltName-delete" value="Delete" onClick="parent.deleteIssuerAltName(this.form)">
+ </td><td>
+ <table><tr><td>
+ Name Type: </td></tr><tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="otherName" onClick="parent.setIssuerAltNameType(form)"> Other Name,
+ OID: <input type="text" name="IssuerAltNameOtherNameOID" size="6"> </td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="rfc822Name" onClick="parent.setIssuerAltNameType(form)"> RFC 822 Name</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="dnsName" onClick="parent.setIssuerAltNameType(form)"> DNS Name </td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="x400" onClick="parent.setIssuerAltNameType(form)"> X400 Address</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="directoryName" onClick="parent.setIssuerAltNameType(form)"> Directory Name</td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="ediPartyName" onClick="parent.setIssuerAltNameType(form)"> EDI Party Name</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="URL" onClick="parent.setIssuerAltNameType(form)"> Uniform Resource Locator</td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="ipAddress" onClick="parent.setIssuerAltNameType(form)"> IP Address</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="regID" onClick="parent.setIssuerAltNameType(form)"> Registered ID</td><td></tr>
+ </table>
+ Name: <input type="text" name="IssuerAltNameText">
+ Binary Encoded: <input type="checkbox" name="IssuerAltNameDataType" value="binary" onClick="parent.setIssuerAltNameType(form)"></p>
+ </tr>
+ </table>
+ </tr>
+
+ <tr>
+ <td>
+ <b>Name Constraints:</b></p>
+ Activate extension: <input type="checkbox" name="NameConstraints"></P>
+ <td>
+ <table>
+ <tr>
+ <td>
+ Name Constraints:</p>
+
+
+ <select name="NameConstraintSelect" multiple size="10">
+ </select></p></p>
+ <input type="button" name="NameConstraint-add" value="Add" onClick="{parent.addNameConstraint(this.form)}">
+ <input type="button" name="NameConstraint-delete" value="Delete" onClick="parent.deleteNameConstraint(this.form)">
+ </td><td>
+ <table><tr><td>
+ Name Type: </td></tr><tr><td>
+ <input type="radio" name="NameConstraintRadio" value="otherName" onClick="parent.setNameConstraintNameType(form)"> Other Name,
+ OID: <input type="text" name="NameConstraintOtherNameOID" size="6"> </td><td>
+ <input type="radio" name="NameConstraintRadio" value="rfc822Name" onClick="parent.setNameConstraintNameType(form)"> RFC 822 Name</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="dnsName" onClick="parent.setNameConstraintNameType(form)"> DNS Name </td><td>
+ <input type="radio" name="NameConstraintRadio" value="x400" onClick="parent.setNameConstraintNameType(form)"> X400 Address</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="directoryName" onClick="parent.setNameConstraintNameType(form)"> Directory Name</td><td>
+ <input type="radio" name="NameConstraintRadio" value="ediPartyName" onClick="parent.setNameConstraintNameType(form)"> EDI Party Name</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="URL" onClick="parent.setNameConstraintNameType(form)"> Uniform Resource Locator</td><td>
+ <input type="radio" name="NameConstraintRadio" value="ipAddress" onClick="parent.setNameConstraintNameType(form)"> IP Address</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="regID" onClick="parent.setNameConstraintNameType(form)"> Registered ID</td><td></tr>
+ </table>
+ Name: <input type="text" name="NameConstraintText">
+ Binary Encoded: <input type="checkbox" name="NameConstraintNameDataType" value="binary" onClick="parent.setNameConstraintNameType(form)"></p>
+ Constraint type:<p>
+ <dd><input type="radio" name="NameConstraintTypeRadio" value="permited"> permited<p>
+ <dd><input type="radio" name="NameConstraintTypeRadio" value="excluded"> excluded<p>
+ Minimum: <input type="text" name="NameConstraintMin" size="8" maxlength="8"></p>
+ Maximum: <input type="text" name="NameConstraintMax" size="8" maxlength="8"></p>
+
+
+
+ </tr>
+ </table>
+ </tr>
+ </table>
+ </form>
+
+
+
+
+
+
+
+
+
+
diff --git a/security/nss/cmd/certcgi/certcgi.c b/security/nss/cmd/certcgi/certcgi.c
new file mode 100644
index 000000000..5377a76a7
--- /dev/null
+++ b/security/nss/cmd/certcgi/certcgi.c
@@ -0,0 +1,2434 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/* Cert-O-Matic CGI */
+
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+#include "pk11func.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "secder.h"
+#include "genname.h"
+#include "xconst.h"
+#include "secutil.h"
+#include "pqgutil.h"
+#include "certxutl.h"
+#include "secrng.h" /* for RNG_ */
+#include "nss.h"
+
+
+/* #define TEST 1 */
+/* #define FILEOUT 1 */
+/* #define OFFLINE 1 */
+#define START_FIELDS 100
+#define PREFIX_LEN 6
+#define SERIAL_FILE "../serial"
+#define DB_DIRECTORY ".."
+
+static char *progName;
+
+typedef struct PairStr Pair;
+
+struct PairStr {
+ char *name;
+ char *data;
+};
+
+
+char prefix[PREFIX_LEN];
+
+
+const SEC_ASN1Template CERTIA5TypeTemplate[] = {
+ { SEC_ASN1_IA5_STRING }
+};
+
+
+
+SECKEYPrivateKey *privkeys[9] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL};
+
+
+#ifdef notdef
+const SEC_ASN1Template CERT_GeneralNameTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate }
+};
+#endif
+
+
+static void
+error_out(char *error_string)
+{
+ printf("Content-type: text/plain\n\n");
+ printf(error_string);
+ fflush(stderr);
+ fflush(stdout);
+ exit(1);
+}
+
+static void
+error_allocate(void)
+{
+ error_out("ERROR: Unable to allocate memory");
+}
+
+
+static char *
+make_copy_string(char *read_pos,
+ int length,
+ char sentinal_value)
+ /* copys string from to a new string it creates and
+ returns a pointer to the new string */
+{
+ int remaining = length;
+ char *write_pos;
+ char *new;
+
+ new = write_pos = (char *) PORT_Alloc (length);
+ if (new == NULL) {
+ error_allocate();
+ }
+ while (*read_pos != sentinal_value) {
+ if (remaining == 1) {
+ remaining += length;
+ length = length * 2;
+ new = PORT_Realloc(new,length);
+ if (new == NULL) {
+ error_allocate();
+ }
+ write_pos = new + length - remaining;
+ }
+ *write_pos = *read_pos;
+ ++write_pos;
+ ++read_pos;
+ remaining = remaining - 1;
+ }
+ *write_pos = '\0';
+ return new;
+}
+
+
+static char *
+PasswordStub(PK11SlotInfo *slot,
+ void *cx)
+{
+ return NULL;
+}
+
+
+static SECStatus
+clean_input(Pair *data)
+ /* converts the non-alphanumeric characters in a form post
+ from hex codes back to characters */
+{
+ int length;
+ int hi_digit;
+ int low_digit;
+ char character;
+ char *begin_pos;
+ char *read_pos;
+ char *write_pos;
+ PRBool name = PR_TRUE;
+
+ begin_pos = data->name;
+ while (begin_pos != NULL) {
+ length = strlen(begin_pos);
+ read_pos = write_pos = begin_pos;
+ while ((read_pos - begin_pos) < length) {
+ if (*read_pos == '+') {
+ *read_pos = ' ';
+ }
+ if (*read_pos == '%') {
+ hi_digit = *(read_pos + 1);
+ low_digit = *(read_pos +2);
+ read_pos += 3;
+ if (isdigit(hi_digit)){
+ hi_digit = hi_digit - '0';
+ } else {
+ hi_digit = toupper(hi_digit);
+ if (isxdigit(hi_digit)) {
+ hi_digit = (hi_digit - 'A') + 10;
+ } else {
+ error_out("ERROR: Form data incorrectly formated");
+ }
+ }
+ if (isdigit(low_digit)){
+ low_digit = low_digit - '0';
+ } else {
+ low_digit = toupper(low_digit);
+ if ((low_digit >='A') && (low_digit <= 'F')) {
+ low_digit = (low_digit - 'A') + 10;
+ } else {
+ error_out("ERROR: Form data incorrectly formated");
+ }
+ }
+ character = (hi_digit << 4) | low_digit;
+ if (character != 10) {
+ *write_pos = character;
+ ++write_pos;
+ }
+ } else {
+ *write_pos = *read_pos;
+ ++write_pos;
+ ++read_pos;
+ }
+ }
+ *write_pos = '\0';
+ if (name == PR_TRUE) {
+ begin_pos = data->data;
+ name = PR_FALSE;
+ } else {
+ data++;
+ begin_pos = data->name;
+ name = PR_TRUE;
+ }
+ }
+ return SECSuccess;
+}
+
+static char *
+make_name(char *new_data)
+ /* gets the next field name in the input string and returns
+ a pointer to a string containing a copy of it */
+{
+ int length = 20;
+ char *name;
+
+ name = make_copy_string(new_data, length, '=');
+ return name;
+}
+
+static char *
+make_data(char *new_data)
+ /* gets the data for the next field in the input string
+ and returns a pointer to a string containing it */
+{
+ int length = 100;
+ char *data;
+ char *read_pos;
+
+ read_pos = new_data;
+ while (*(read_pos - 1) != '=') {
+ ++read_pos;
+ }
+ data = make_copy_string(read_pos, length, '&');
+ return data;
+}
+
+
+static Pair
+make_pair(char *new_data)
+ /* makes a pair name/data pair from the input string */
+{
+ Pair temp;
+
+ temp.name = make_name(new_data);
+ temp.data = make_data(new_data);
+ return temp;
+}
+
+
+
+static Pair *
+make_datastruct(char *data, int len)
+ /* parses the input from the form post into a data
+ structure of field name/data pairs */
+{
+ Pair *datastruct;
+ Pair *current;
+ char *curr_pos;
+ int fields = START_FIELDS;
+ int remaining = START_FIELDS;
+
+ curr_pos = data;
+ datastruct = current = (Pair *) PORT_Alloc(fields * sizeof(Pair));
+ if (datastruct == NULL) {
+ error_allocate();
+ }
+ while (curr_pos - data < len) {
+ if (remaining == 1) {
+ remaining += fields;
+ fields = fields * 2;
+ datastruct = (Pair *) PORT_Realloc
+ (datastruct, fields * sizeof(Pair));
+ if (datastruct == NULL) {
+ error_allocate();
+ }
+ current = datastruct + (fields - remaining);
+ }
+ *current = make_pair(curr_pos);
+ while (*curr_pos != '&') {
+ ++curr_pos;
+ }
+ ++curr_pos;
+ ++current;
+ remaining = remaining - 1;
+ }
+ current->name = NULL;
+ return datastruct;
+}
+
+static char *
+return_name(Pair *data_struct,
+ int n)
+ /* returns a pointer to the name of the nth
+ (starting from 0) item in the data structure */
+{
+ char *name;
+
+ if ((data_struct + n)->name != NULL) {
+ name = (data_struct + n)->name;
+ return name;
+ } else {
+ return NULL;
+ }
+}
+
+static char *
+return_data(Pair *data_struct,int n)
+ /* returns a pointer to the data of the nth (starting from 0)
+ itme in the data structure */
+{
+ char *data;
+
+ data = (data_struct + n)->data;
+ return data;
+}
+
+
+static char *
+add_prefix(char *field_name)
+{
+ extern char prefix[PREFIX_LEN];
+ int i = 0;
+ char *rv;
+ char *write;
+
+ rv = write = PORT_Alloc(PORT_Strlen(prefix) + PORT_Strlen(field_name) + 1);
+ for(i = 0; i < PORT_Strlen(prefix); i++) {
+ *write = prefix[i];
+ write++;
+ }
+ *write = '\0';
+ rv = PORT_Strcat(rv,field_name);
+ return rv;
+}
+
+
+static char *
+find_field(Pair *data,
+ char *field_name,
+ PRBool add_pre)
+ /* returns a pointer to the data of the first pair
+ thats name matches the string it is passed */
+{
+ int i = 0;
+ char *retrieved;
+ int found = 0;
+
+ if (add_pre) {
+ field_name = add_prefix(field_name);
+ }
+ while(return_name(data, i) != NULL) {
+ if (PORT_Strcmp(return_name(data, i), field_name) == 0) {
+ retrieved = return_data(data, i);
+ found = 1;
+ break;
+ }
+ i++;
+ }
+ if (!found) {
+ retrieved = NULL;
+ }
+ return retrieved;
+}
+
+static PRBool
+find_field_bool(Pair *data,
+ char *fieldname,
+ PRBool add_pre)
+{
+ char *rv;
+
+ rv = find_field(data, fieldname, add_pre);
+
+ if ((rv != NULL) && (PORT_Strcmp(rv, "true")) == 0) {
+ return PR_TRUE;
+ } else {
+ return PR_FALSE;
+ }
+}
+
+static char *
+update_data_by_name(Pair *data,
+ char *field_name,
+ char *new_data)
+ /* replaces the data in the data structure associated with
+ a name with new data, returns null if not found */
+{
+ int i = 0;
+ int found = 0;
+ int length = 100;
+ char *new;
+
+ while (return_name(data, i) != NULL) {
+ if (PORT_Strcmp(return_name(data, i), field_name) == 0) {
+ new = make_copy_string( new_data, length, '\0');
+ PORT_Free(return_data(data, i));
+ found = 1;
+ (*(data + i)).data = new;
+ break;
+ }
+ i++;
+ }
+ if (!found) {
+ new = NULL;
+ }
+ return new;
+}
+
+static char *
+update_data_by_index(Pair *data,
+ int n,
+ char *new_data)
+ /* replaces the data of a particular index in the data structure */
+{
+ int length = 100;
+ char *new;
+
+ new = make_copy_string(new_data, length, '\0');
+ PORT_Free(return_data(data, n));
+ (*(data + n)).data = new;
+ return new;
+}
+
+
+static Pair *
+add_field(Pair *data,
+ char* field_name,
+ char* field_data)
+ /* adds a new name/data pair to the data structure */
+{
+ int i = 0;
+ int j;
+ int name_length = 100;
+ int data_length = 100;
+
+ while(return_name(data, i) != NULL) {
+ i++;
+ }
+ j = START_FIELDS;
+ while ( j < (i + 1) ) {
+ j = j * 2;
+ }
+ if (j == (i + 1)) {
+ data = (Pair *) PORT_Realloc(data, (j * 2) * sizeof(Pair));
+ if (data == NULL) {
+ error_allocate();
+ }
+ }
+ (*(data + i)).name = make_copy_string(field_name, name_length, '\0');
+ (*(data + i)).data = make_copy_string(field_data, data_length, '\0');
+ (data + i + 1)->name = NULL;
+ return data;
+}
+
+
+static CERTCertificateRequest *
+makeCertReq(Pair *form_data,
+ int which_priv_key)
+ /* makes and encodes a certrequest */
+{
+
+ PK11SlotInfo *slot;
+ CERTCertificateRequest *certReq = NULL;
+ CERTSubjectPublicKeyInfo *spki;
+ SECKEYPrivateKey *privkey = NULL;
+ SECKEYPublicKey *pubkey = NULL;
+ CERTName *name;
+ char *key;
+ extern SECKEYPrivateKey *privkeys[9];
+ int keySizeInBits;
+ char *challenge = "foo";
+ SECStatus rv = SECSuccess;
+ PQGParams *pqgParams = NULL;
+ PQGVerify *pqgVfy = NULL;
+
+ name = CERT_AsciiToName(find_field(form_data, "subject", PR_TRUE));
+ if (name == NULL) {
+ error_out("ERROR: Unable to create Subject Name");
+ }
+ key = find_field(form_data, "key", PR_TRUE);
+ if (key == NULL) {
+ switch (*find_field(form_data, "keysize", PR_TRUE)) {
+ case '0':
+ keySizeInBits = 2048;
+ break;
+ case '1':
+ keySizeInBits = 1024;
+ break;
+ case '2':
+ keySizeInBits = 512;
+ break;
+ default:
+ error_out("ERROR: Unsupported Key length selected");
+ }
+ if (find_field_bool(form_data, "keyType-dsa", PR_TRUE)) {
+ rv = PQG_ParamGen(keySizeInBits, &pqgParams, &pqgVfy);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to generate PQG parameters");
+ }
+ slot = PK11_GetBestSlot(CKM_DSA_KEY_PAIR_GEN, NULL);
+ privkey = PK11_GenerateKeyPair(slot, CKM_DSA_KEY_PAIR_GEN,
+ pqgParams,&pubkey, PR_FALSE,
+ PR_TRUE, NULL);
+ } else {
+ privkey = SECKEY_CreateRSAPrivateKey(keySizeInBits, &pubkey, NULL);
+ }
+ privkeys[which_priv_key] = privkey;
+ spki = SECKEY_CreateSubjectPublicKeyInfo(pubkey);
+ } else {
+ spki = SECKEY_ConvertAndDecodePublicKeyAndChallenge(key, challenge,
+ NULL);
+ if (spki == NULL) {
+ error_out("ERROR: Unable to decode Public Key and Challenge String");
+ }
+ }
+ certReq = CERT_CreateCertificateRequest(name, spki, NULL);
+ if (certReq == NULL) {
+ error_out("ERROR: Unable to create Certificate Request");
+ }
+ if (pubkey != NULL) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+ if (spki != NULL) {
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ }
+ if (pqgParams != NULL) {
+ PQG_DestroyParams(pqgParams);
+ }
+ if (pqgVfy != NULL) {
+ PQG_DestroyVerify(pqgVfy);
+ }
+ return certReq;
+}
+
+
+
+static CERTCertificate *
+MakeV1Cert(CERTCertDBHandle *handle,
+ CERTCertificateRequest *req,
+ char *issuerNameStr,
+ PRBool selfsign,
+ int serialNumber,
+ int warpmonths,
+ Pair *data)
+{
+ CERTCertificate *issuerCert = NULL;
+ CERTValidity *validity;
+ CERTCertificate *cert = NULL;
+ PRExplodedTime printableTime;
+ PRTime now,
+ after;
+ SECStatus rv;
+
+
+
+ if ( !selfsign ) {
+ issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
+ if (!issuerCert) {
+ error_out("ERROR: Could not find issuer's certificate");
+ return NULL;
+ }
+ }
+ if (find_field_bool(data, "manValidity", PR_TRUE)) {
+ rv = DER_AsciiToTime(&now, find_field(data, "notBefore", PR_TRUE));
+ } else {
+ now = PR_Now();
+ }
+ PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
+ if ( warpmonths ) {
+ printableTime.tm_month += warpmonths;
+ now = PR_ImplodeTime (&printableTime);
+ PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
+ }
+ if (find_field_bool(data, "manValidity", PR_TRUE)) {
+ rv = DER_AsciiToTime(&after, find_field(data, "notAfter", PR_TRUE));
+ PR_ExplodeTime (after, PR_GMTParameters, &printableTime);
+ } else {
+ printableTime.tm_month += 3;
+ after = PR_ImplodeTime (&printableTime);
+ }
+ /* note that the time is now in micro-second unit */
+ validity = CERT_CreateValidity (now, after);
+
+ if ( selfsign ) {
+ cert = CERT_CreateCertificate
+ (serialNumber,&(req->subject), validity, req);
+ } else {
+ cert = CERT_CreateCertificate
+ (serialNumber,&(issuerCert->subject), validity, req);
+ }
+
+ CERT_DestroyValidity(validity);
+ if ( issuerCert ) {
+ CERT_DestroyCertificate (issuerCert);
+ }
+ return(cert);
+}
+
+static int
+get_serial_number(Pair *data)
+{
+ int serial = 0;
+ int error;
+ char *filename = SERIAL_FILE;
+ char *SN;
+ FILE *serialFile;
+
+
+ if (find_field_bool(data, "serial-auto", PR_TRUE)) {
+ serialFile = fopen(filename, "r");
+ if (serialFile != NULL) {
+ fread(&serial, sizeof(int), 1, serialFile);
+ if (ferror(serialFile) != 0) {
+ error_out("Error: Unable to read serial number file");
+ }
+ if (serial == 4294967295) {
+ serial = 21;
+ }
+ fclose(serialFile);
+ ++serial;
+ serialFile = fopen(filename,"w");
+ if (serialFile == NULL) {
+ error_out("ERROR: Unable to open serial number file for writing");
+ }
+ fwrite(&serial, sizeof(int), 1, serialFile);
+ if (ferror(serialFile) != 0) {
+ error_out("Error: Unable to write to serial number file");
+ }
+ } else {
+ fclose(serialFile);
+ serialFile = fopen(filename,"w");
+ if (serialFile == NULL) {
+ error_out("ERROR: Unable to open serial number file");
+ }
+ serial = 21;
+ fwrite(&serial, sizeof(int), 1, serialFile);
+ if (ferror(serialFile) != 0) {
+ error_out("Error: Unable to write to serial number file");
+ }
+ error = ferror(serialFile);
+ if (error != 0) {
+ error_out("ERROR: Unable to write to serial file");
+ }
+ }
+ fclose(serialFile);
+ } else {
+ SN = find_field(data, "serial_value", PR_TRUE);
+ while (*SN != '\0') {
+ serial = serial * 16;
+ if ((*SN >= 'A') && (*SN <='F')) {
+ serial += *SN - 'A' + 10;
+ } else {
+ if ((*SN >= 'a') && (*SN <='f')) {
+ serial += *SN - 'a' + 10;
+ } else {
+ serial += *SN - '0';
+ }
+ }
+ ++SN;
+ }
+ }
+ return serial;
+}
+
+
+
+typedef SECStatus (* EXTEN_VALUE_ENCODER)
+ (PRArenaPool *extHandle, void *value, SECItem *encodedValue);
+
+static SECStatus
+EncodeAndAddExtensionValue(
+ PRArenaPool *arena,
+ void *extHandle,
+ void *value,
+ PRBool criticality,
+ int extenType,
+ EXTEN_VALUE_ENCODER EncodeValueFn)
+{
+ SECItem encodedValue;
+ SECStatus rv;
+
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+ rv = (*EncodeValueFn)(arena, value, &encodedValue);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to encode extension value");
+ }
+ rv = CERT_AddExtension
+ (extHandle, extenType, &encodedValue, criticality, PR_TRUE);
+ return (rv);
+}
+
+
+
+static SECStatus
+AddKeyUsage (void *extHandle,
+ Pair *data)
+{
+ SECItem bitStringValue;
+ unsigned char keyUsage = 0x0;
+
+ if (find_field_bool(data,"keyUsage-digitalSignature", PR_TRUE)){
+ keyUsage |= (0x80 >> 0);
+ }
+ if (find_field_bool(data,"keyUsage-nonRepudiation", PR_TRUE)){
+ keyUsage |= (0x80 >> 1);
+ }
+ if (find_field_bool(data,"keyUsage-keyEncipherment", PR_TRUE)){
+ keyUsage |= (0x80 >> 2);
+ }
+ if (find_field_bool(data,"keyUsage-dataEncipherment", PR_TRUE)){
+ keyUsage |= (0x80 >> 3);
+ }
+ if (find_field_bool(data,"keyUsage-keyAgreement", PR_TRUE)){
+ keyUsage |= (0x80 >> 4);
+ }
+ if (find_field_bool(data,"keyUsage-keyCertSign", PR_TRUE)) {
+ keyUsage |= (0x80 >> 5);
+ }
+ if (find_field_bool(data,"keyUsage-cRLSign", PR_TRUE)) {
+ keyUsage |= (0x80 >> 6);
+ }
+
+ bitStringValue.data = &keyUsage;
+ bitStringValue.len = 1;
+
+ return (CERT_EncodeAndAddBitStrExtension
+ (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
+ (find_field_bool(data, "keyUsage-crit", PR_TRUE))));
+
+}
+
+static CERTOidSequence *
+CreateOidSequence(void)
+{
+ CERTOidSequence *rv = (CERTOidSequence *)NULL;
+ PRArenaPool *arena = (PRArenaPool *)NULL;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if( (PRArenaPool *)NULL == arena ) {
+ goto loser;
+ }
+
+ rv = (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence));
+ if( (CERTOidSequence *)NULL == rv ) {
+ goto loser;
+ }
+
+ rv->oids = (SECItem **)PORT_ArenaZAlloc(arena, sizeof(SECItem *));
+ if( (SECItem **)NULL == rv->oids ) {
+ goto loser;
+ }
+
+ rv->arena = arena;
+ return rv;
+
+ loser:
+ if( (PRArenaPool *)NULL != arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return (CERTOidSequence *)NULL;
+}
+
+static SECStatus
+AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
+{
+ SECItem **oids;
+ PRUint32 count = 0;
+ SECOidData *od;
+
+ od = SECOID_FindOIDByTag(oidTag);
+ if( (SECOidData *)NULL == od ) {
+ return SECFailure;
+ }
+
+ for( oids = os->oids; (SECItem *)NULL != *oids; oids++ ) {
+ count++;
+ }
+
+ /* ArenaZRealloc */
+
+ {
+ PRUint32 i;
+
+ oids = (SECItem **)PORT_ArenaZAlloc(os->arena, sizeof(SECItem *) * (count+2));
+ if( (SECItem **)NULL == oids ) {
+ return SECFailure;
+ }
+
+ for( i = 0; i < count; i++ ) {
+ oids[i] = os->oids[i];
+ }
+
+ /* ArenaZFree(os->oids); */
+ }
+
+ os->oids = oids;
+ os->oids[count] = &od->oid;
+
+ return SECSuccess;
+}
+
+static SECItem *
+EncodeOidSequence(CERTOidSequence *os)
+{
+ SECItem *rv;
+ extern const SEC_ASN1Template CERT_OidSeqTemplate[];
+
+ rv = (SECItem *)PORT_ArenaZAlloc(os->arena, sizeof(SECItem));
+ if( (SECItem *)NULL == rv ) {
+ goto loser;
+ }
+
+ if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) {
+ goto loser;
+ }
+
+ return rv;
+
+ loser:
+ return (SECItem *)NULL;
+}
+
+static SECStatus
+AddExtKeyUsage(void *extHandle, Pair *data)
+{
+ SECStatus rv;
+ CERTOidSequence *os;
+ SECItem *value;
+ PRBool crit;
+
+ os = CreateOidSequence();
+ if( (CERTOidSequence *)NULL == os ) {
+ return SECFailure;
+ }
+
+ if( find_field_bool(data, "extKeyUsage-serverAuth", PR_TRUE) ) {
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
+ if( SECSuccess != rv ) goto loser;
+ }
+
+ if( find_field_bool(data, "extKeyUsage-clientAuth", PR_TRUE) ) {
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
+ if( SECSuccess != rv ) goto loser;
+ }
+
+ if( find_field_bool(data, "extKeyUsage-codeSign", PR_TRUE) ) {
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
+ if( SECSuccess != rv ) goto loser;
+ }
+
+ if( find_field_bool(data, "extKeyUsage-emailProtect", PR_TRUE) ) {
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
+ if( SECSuccess != rv ) goto loser;
+ }
+
+ if( find_field_bool(data, "extKeyUsage-timeStamp", PR_TRUE) ) {
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
+ if( SECSuccess != rv ) goto loser;
+ }
+
+ if( find_field_bool(data, "extKeyUsage-ocspResponder", PR_TRUE) ) {
+ rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
+ if( SECSuccess != rv ) goto loser;
+ }
+
+ if( find_field_bool(data, "extKeyUsage-NS-govtApproved", PR_TRUE) ) {
+ rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
+ if( SECSuccess != rv ) goto loser;
+ }
+
+ value = EncodeOidSequence(os);
+
+ crit = find_field_bool(data, "extKeyUsage-crit", PR_TRUE);
+
+ rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, value,
+ crit, PR_TRUE);
+ /*FALLTHROUGH*/
+ loser:
+ CERT_DestroyOidSequence(os);
+ return rv;
+}
+
+static SECStatus
+AddSubKeyID(void *extHandle,
+ Pair *data,
+ CERTCertificate *subjectCert)
+{
+ SECItem encodedValue;
+ SECStatus rv;
+ char *read;
+ char *write;
+ char *first;
+ char character;
+ int high_digit = 0,
+ low_digit = 0;
+ int len;
+ PRBool odd = PR_FALSE;
+
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+ first = read = write = find_field(data,"subjectKeyIdentifier-text",
+ PR_TRUE);
+ len = PORT_Strlen(first);
+ odd = ((len % 2) != 0 ) ? PR_TRUE : PR_FALSE;
+ if (find_field_bool(data, "subjectKeyIdentifier-radio-hex", PR_TRUE)) {
+ if (odd) {
+ error_out("ERROR: Improperly formated subject key identifier, hex values must be expressed as an octet string");
+ }
+ while (*read != '\0') {
+ if (!isxdigit(*read)) {
+ error_out("ERROR: Improperly formated subject key identifier");
+ }
+ *read = toupper(*read);
+ if ((*read >= 'A') && (*read <= 'F')) {
+ high_digit = *read - 'A' + 10;
+ } else {
+ high_digit = *read - '0';
+ }
+ ++read;
+ if (!isxdigit(*read)) {
+ error_out("ERROR: Improperly formated subject key identifier");
+ }
+ *read = toupper(*read);
+ if ((*read >= 'A') && (*read <= 'F')) {
+ low_digit = *(read) - 'A' + 10;
+ } else {
+ low_digit = *(read) - '0';
+ }
+ character = (high_digit << 4) | low_digit;
+ *write = character;
+ ++write;
+ ++read;
+ }
+ *write = '\0';
+ len = write - first;
+ }
+ subjectCert->subjectKeyID.data = (unsigned char *) find_field
+ (data,"subjectKeyIdentifier-text", PR_TRUE);
+ subjectCert->subjectKeyID.len = len;
+ rv = CERT_EncodeSubjectKeyID
+ (NULL, find_field(data,"subjectKeyIdentifier-text", PR_TRUE),
+ len, &encodedValue);
+ if (rv) {
+ return (rv);
+ }
+ return (CERT_AddExtension(extHandle, SEC_OID_X509_SUBJECT_KEY_ID,
+ &encodedValue, PR_FALSE, PR_TRUE));
+}
+
+
+static SECStatus
+AddAuthKeyID (void *extHandle,
+ Pair *data,
+ char *issuerNameStr,
+ CERTCertDBHandle *handle)
+{
+ CERTAuthKeyID *authKeyID = NULL;
+ PRArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+ CERTCertificate *issuerCert = NULL;
+ CERTGeneralName *genNames;
+ CERTName *directoryName = NULL;
+
+
+ issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( !arena ) {
+ error_allocate();
+ }
+
+ authKeyID = PORT_ArenaZAlloc (arena, sizeof (CERTAuthKeyID));
+ if (authKeyID == NULL) {
+ error_allocate();
+ }
+ if (find_field_bool(data, "authorityKeyIdentifier-radio-keyIdentifier",
+ PR_TRUE)) {
+ authKeyID->keyID.data = PORT_ArenaAlloc (arena, PORT_Strlen
+ ((char *)issuerCert->subjectKeyID.data));
+ if (authKeyID->keyID.data == NULL) {
+ error_allocate();
+ }
+ PORT_Memcpy (authKeyID->keyID.data, issuerCert->subjectKeyID.data,
+ authKeyID->keyID.len =
+ PORT_Strlen((char *)issuerCert->subjectKeyID.data));
+ } else {
+
+ PORT_Assert (arena);
+ genNames = (CERTGeneralName *) PORT_ArenaZAlloc (arena, (sizeof(CERTGeneralName)));
+ if (genNames == NULL){
+ error_allocate();
+ }
+ genNames->l.next = genNames->l.prev = &(genNames->l);
+ genNames->type = certDirectoryName;
+
+ directoryName = CERT_AsciiToName(issuerCert->subjectName);
+ if (!directoryName) {
+ error_out("ERROR: Unable to create Directory Name");
+ }
+ rv = CERT_CopyName (arena, &genNames->name.directoryName,
+ directoryName);
+ CERT_DestroyName (directoryName);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to copy Directory Name");
+ }
+ authKeyID->authCertIssuer = genNames;
+ if (authKeyID->authCertIssuer == NULL && SECFailure ==
+ PORT_GetError ()) {
+ error_out("ERROR: Unable to get Issuer General Name for Authority Key ID Extension");
+ }
+ authKeyID->authCertSerialNumber = issuerCert->serialNumber;
+ }
+ rv = EncodeAndAddExtensionValue(arena, extHandle, authKeyID, PR_FALSE,
+ SEC_OID_X509_AUTH_KEY_ID,
+ (EXTEN_VALUE_ENCODER)
+ CERT_EncodeAuthKeyID);
+ if (arena) {
+ PORT_FreeArena (arena, PR_FALSE);
+ }
+ return (rv);
+}
+
+
+static SECStatus
+AddPrivKeyUsagePeriod(void *extHandle,
+ Pair *data,
+ CERTCertificate *cert)
+{
+ char *notBeforeStr;
+ char *notAfterStr;
+ PRArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+ PKUPEncodedContext *pkup;
+
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( !arena ) {
+ error_allocate();
+ }
+ pkup = PORT_ArenaZAlloc (arena, sizeof (PKUPEncodedContext));
+ if (pkup == NULL) {
+ error_allocate();
+ }
+ notBeforeStr = (char *) PORT_Alloc(16 );
+ notAfterStr = (char *) PORT_Alloc(16 );
+ *notBeforeStr = '\0';
+ *notAfterStr = '\0';
+ pkup->arena = arena;
+ pkup->notBefore.len = 0;
+ pkup->notBefore.data = NULL;
+ pkup->notAfter.len = 0;
+ pkup->notAfter.data = NULL;
+ if (find_field_bool(data, "privKeyUsagePeriod-radio-notBefore", PR_TRUE) ||
+ find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) {
+ pkup->notBefore.len = 15;
+ pkup->notBefore.data = (unsigned char *)notBeforeStr;
+ if (find_field_bool(data, "privKeyUsagePeriod-notBefore-radio-manual",
+ PR_TRUE)) {
+ PORT_Strcat(notBeforeStr,find_field(data,
+ "privKeyUsagePeriod-notBefore-year",
+ PR_TRUE));
+ PORT_Strcat(notBeforeStr,find_field(data,
+ "privKeyUsagePeriod-notBefore-month",
+ PR_TRUE));
+ PORT_Strcat(notBeforeStr,find_field(data,
+ "privKeyUsagePeriod-notBefore-day",
+ PR_TRUE));
+ PORT_Strcat(notBeforeStr,find_field(data,
+ "privKeyUsagePeriod-notBefore-hour",
+ PR_TRUE));
+ PORT_Strcat(notBeforeStr,find_field(data,
+ "privKeyUsagePeriod-notBefore-minute",
+ PR_TRUE));
+ PORT_Strcat(notBeforeStr,find_field(data,
+ "privKeyUsagePeriod-notBefore-second",
+ PR_TRUE));
+ if ((*(notBeforeStr + 14) != '\0') ||
+ (!isdigit(*(notBeforeStr + 13))) ||
+ (*(notBeforeStr + 12) >= '5' && *(notBeforeStr + 12) <= '0') ||
+ (!isdigit(*(notBeforeStr + 11))) ||
+ (*(notBeforeStr + 10) >= '5' && *(notBeforeStr + 10) <= '0') ||
+ (!isdigit(*(notBeforeStr + 9))) ||
+ (*(notBeforeStr + 8) >= '2' && *(notBeforeStr + 8) <= '0') ||
+ (!isdigit(*(notBeforeStr + 7))) ||
+ (*(notBeforeStr + 6) >= '3' && *(notBeforeStr + 6) <= '0') ||
+ (!isdigit(*(notBeforeStr + 5))) ||
+ (*(notBeforeStr + 4) >= '1' && *(notBeforeStr + 4) <= '0') ||
+ (!isdigit(*(notBeforeStr + 3))) ||
+ (!isdigit(*(notBeforeStr + 2))) ||
+ (!isdigit(*(notBeforeStr + 1))) ||
+ (!isdigit(*(notBeforeStr + 0))) ||
+ (*(notBeforeStr + 8) == '2' && *(notBeforeStr + 9) >= '4') ||
+ (*(notBeforeStr + 6) == '3' && *(notBeforeStr + 7) >= '1') ||
+ (*(notBeforeStr + 4) == '1' && *(notBeforeStr + 5) >= '2')) {
+ error_out("ERROR: Improperly formated private key usage period");
+ }
+ *(notBeforeStr + 14) = 'Z';
+ *(notBeforeStr + 15) = '\0';
+ } else {
+ if ((*(cert->validity.notBefore.data) > '5') ||
+ ((*(cert->validity.notBefore.data) == '5') &&
+ (*(cert->validity.notBefore.data + 1) != '0'))) {
+ PORT_Strcat(notBeforeStr, "19");
+ } else {
+ PORT_Strcat(notBeforeStr, "20");
+ }
+ PORT_Strcat(notBeforeStr, (char *)cert->validity.notBefore.data);
+ }
+ }
+ if (find_field_bool(data, "privKeyUsagePeriod-radio-notAfter", PR_TRUE) ||
+ find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) {
+ pkup->notAfter.len = 15;
+ pkup->notAfter.data = (unsigned char *)notAfterStr;
+ PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-year",
+ PR_TRUE));
+ PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-month",
+ PR_TRUE));
+ PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-day",
+ PR_TRUE));
+ PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-hour",
+ PR_TRUE));
+ PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-minute",
+ PR_TRUE));
+ PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-second",
+ PR_TRUE));
+ if ((*(notAfterStr + 14) != '\0') ||
+ (!isdigit(*(notAfterStr + 13))) ||
+ (*(notAfterStr + 12) >= '5' && *(notAfterStr + 12) <= '0') ||
+ (!isdigit(*(notAfterStr + 11))) ||
+ (*(notAfterStr + 10) >= '5' && *(notAfterStr + 10) <= '0') ||
+ (!isdigit(*(notAfterStr + 9))) ||
+ (*(notAfterStr + 8) >= '2' && *(notAfterStr + 8) <= '0') ||
+ (!isdigit(*(notAfterStr + 7))) ||
+ (*(notAfterStr + 6) >= '3' && *(notAfterStr + 6) <= '0') ||
+ (!isdigit(*(notAfterStr + 5))) ||
+ (*(notAfterStr + 4) >= '1' && *(notAfterStr + 4) <= '0') ||
+ (!isdigit(*(notAfterStr + 3))) ||
+ (!isdigit(*(notAfterStr + 2))) ||
+ (!isdigit(*(notAfterStr + 1))) ||
+ (!isdigit(*(notAfterStr + 0))) ||
+ (*(notAfterStr + 8) == '2' && *(notAfterStr + 9) >= '4') ||
+ (*(notAfterStr + 6) == '3' && *(notAfterStr + 7) >= '1') ||
+ (*(notAfterStr + 4) == '1' && *(notAfterStr + 5) >= '2')) {
+ error_out("ERROR: Improperly formated private key usage period");
+ }
+ *(notAfterStr + 14) = 'Z';
+ *(notAfterStr + 15) = '\0';
+ }
+
+ PORT_Assert (arena);
+
+ rv = EncodeAndAddExtensionValue(arena, extHandle, pkup,
+ find_field_bool(data,
+ "privKeyUsagePeriod-crit",
+ PR_TRUE),
+ SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD,
+ (EXTEN_VALUE_ENCODER)
+ CERT_EncodePublicKeyUsagePeriod);
+ if (arena) {
+ PORT_FreeArena (arena, PR_FALSE);
+ }
+ if (notBeforeStr != NULL) {
+ PORT_Free(notBeforeStr);
+ }
+ if (notAfterStr != NULL) {
+ PORT_Free(notAfterStr);
+ }
+ return (rv);
+}
+
+static SECStatus
+AddBasicConstraint(void *extHandle,
+ Pair *data)
+{
+ CERTBasicConstraints basicConstraint;
+ SECItem encodedValue;
+ SECStatus rv;
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+ basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
+ basicConstraint.isCA = (find_field_bool(data,"basicConstraints-cA-radio-CA",
+ PR_TRUE));
+ if (find_field_bool(data,"basicConstraints-pathLengthConstraint", PR_TRUE)){
+ basicConstraint.pathLenConstraint = atoi
+ (find_field(data,"basicConstraints-pathLengthConstraint-text",
+ PR_TRUE));
+ }
+
+ rv = CERT_EncodeBasicConstraintValue (NULL, &basicConstraint,
+ &encodedValue);
+ if (rv)
+ return (rv);
+ rv = CERT_AddExtension(extHandle, SEC_OID_X509_BASIC_CONSTRAINTS,
+ &encodedValue,
+ (find_field_bool(data,"basicConstraints-crit",
+ PR_TRUE)), PR_TRUE);
+
+ PORT_Free (encodedValue.data);
+ return (rv);
+}
+
+
+
+static SECStatus
+AddNscpCertType (void *extHandle,
+ Pair *data)
+{
+ SECItem bitStringValue;
+ unsigned char CertType = 0x0;
+
+ if (find_field_bool(data,"netscape-cert-type-ssl-client", PR_TRUE)){
+ CertType |= (0x80 >> 0);
+ }
+ if (find_field_bool(data,"netscape-cert-type-ssl-server", PR_TRUE)){
+ CertType |= (0x80 >> 1);
+ }
+ if (find_field_bool(data,"netscape-cert-type-smime", PR_TRUE)){
+ CertType |= (0x80 >> 2);
+ }
+ if (find_field_bool(data,"netscape-cert-type-object-signing", PR_TRUE)){
+ CertType |= (0x80 >> 3);
+ }
+ if (find_field_bool(data,"netscape-cert-type-reserved", PR_TRUE)){
+ CertType |= (0x80 >> 4);
+ }
+ if (find_field_bool(data,"netscape-cert-type-ssl-ca", PR_TRUE)) {
+ CertType |= (0x80 >> 5);
+ }
+ if (find_field_bool(data,"netscape-cert-type-smime-ca", PR_TRUE)) {
+ CertType |= (0x80 >> 6);
+ }
+ if (find_field_bool(data,"netscape-cert-type-object-signing-ca", PR_TRUE)) {
+ CertType |= (0x80 >> 7);
+ }
+
+ bitStringValue.data = &CertType;
+ bitStringValue.len = 1;
+
+ return (CERT_EncodeAndAddBitStrExtension
+ (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
+ (find_field_bool(data, "netscape-cert-type-crit", PR_TRUE))));
+}
+
+
+static SECStatus
+add_IA5StringExtension(void *extHandle,
+ char *string,
+ PRBool crit,
+ int idtag)
+{
+ SECItem encodedValue;
+ SECStatus rv;
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+
+ rv = CERT_EncodeIA5TypeExtension(NULL, string, &encodedValue);
+ if (rv) {
+ return (rv);
+ }
+ return (CERT_AddExtension(extHandle, idtag, &encodedValue, crit, PR_TRUE));
+}
+
+static SECItem *
+string_to_oid(char *string)
+{
+ int i;
+ int length = 20;
+ int remaining;
+ int first_value;
+ int second_value;
+ int value;
+ int oidLength;
+ unsigned char *oidString;
+ unsigned char *write;
+ unsigned char *read;
+ unsigned char *temp;
+ SECItem *oid;
+
+
+ remaining = length;
+ i = 0;
+ while (*string == ' ') {
+ string++;
+ }
+ while (isdigit(*(string + i))) {
+ i++;
+ }
+ if (*(string + i) == '.') {
+ *(string + i) = '\0';
+ } else {
+ error_out("ERROR: Improperly formated OID");
+ }
+ first_value = atoi(string);
+ if (first_value < 0 || first_value > 2) {
+ error_out("ERROR: Improperly formated OID");
+ }
+ string += i + 1;
+ i = 0;
+ while (isdigit(*(string + i))) {
+ i++;
+ }
+ if (*(string + i) == '.') {
+ *(string + i) = '\0';
+ } else {
+ error_out("ERROR: Improperly formated OID");
+ }
+ second_value = atoi(string);
+ if (second_value < 0 || second_value > 39) {
+ error_out("ERROR: Improperly formated OID");
+ }
+ oidString = PORT_ZAlloc(2);
+ *oidString = (first_value * 40) + second_value;
+ *(oidString + 1) = '\0';
+ oidLength = 1;
+ string += i + 1;
+ i = 0;
+ temp = write = PORT_ZAlloc(length);
+ while (*string != '\0') {
+ value = 0;
+ while(isdigit(*(string + i))) {
+ i++;
+ }
+ if (*(string + i) == '\0') {
+ value = atoi(string);
+ string += i;
+ } else {
+ if (*(string + i) == '.') {
+ *(string + i) = '\0';
+ value = atoi(string);
+ string += i + 1;
+ } else {
+ *(string + i) = '\0';
+ i++;
+ value = atoi(string);
+ while (*(string + i) == ' ')
+ i++;
+ if (*(string + i) != '\0') {
+ error_out("ERROR: Improperly formated OID");
+ }
+ }
+ }
+ i = 0;
+ while (value != 0) {
+ if (remaining < 1) {
+ remaining += length;
+ length = length * 2;
+ temp = PORT_Realloc(temp, length);
+ write = temp + length - remaining;
+ }
+ *write = (value & 0x7f) | (0x80);
+ write++;
+ remaining--;
+ value = value >> 7;
+ }
+ *temp = *temp & (0x7f);
+ oidLength += write - temp;
+ oidString = PORT_Realloc(oidString, (oidLength + 1));
+ read = write - 1;
+ write = oidLength + oidString - 1;
+ for (i = 0; i < (length - remaining); i++) {
+ *write = *read;
+ write--;
+ read++;
+ }
+ write = temp;
+ remaining = length;
+ }
+ *(oidString + oidLength) = '\0';
+ oid = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
+ oid->data = oidString;
+ oid->len = oidLength;
+ PORT_Free(temp);
+ return oid;
+}
+
+static SECItem *
+string_to_ipaddress(char *string)
+{
+ int i = 0;
+ int value;
+ int j = 0;
+ SECItem *ipaddress;
+
+
+ while (*string == ' ') {
+ string++;
+ }
+ ipaddress = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
+ ipaddress->data = PORT_ZAlloc(9);
+ while (*string != '\0' && j < 8) {
+ while (isdigit(*(string + i))) {
+ i++;
+ }
+ if (*(string + i) == '.') {
+ *(string + i) = '\0';
+ value = atoi(string);
+ string = string + i + 1;
+ i = 0;
+ } else {
+ if (*(string + i) == '\0') {
+ value = atoi(string);
+ string = string + i;
+ i = 0;
+ } else {
+ *(string + i) = '\0';
+ while (*(string + i) == ' ') {
+ i++;
+ }
+ if (*(string + i) == '\0') {
+ value = atoi(string);
+ string = string + i;
+ i = 0;
+ } else {
+ error_out("ERROR: Improperly formated IP Address");
+ }
+ }
+ }
+ if (value >= 0 || value < 256) {
+ *(ipaddress->data + j) = value;
+ } else {
+ error_out("ERROR: Improperly formated IP Address");
+ }
+ j++;
+ }
+ *(ipaddress->data + j) = '\0';
+ if (j != 4 && j != 8) {
+ error_out("ERROR: Improperly formated IP Address");
+ }
+ ipaddress->len = j;
+ return ipaddress;
+}
+
+static SECItem *
+string_to_binary(char *string)
+{
+ SECItem *rv;
+ int high_digit;
+ int low_digit;
+
+ rv = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
+ if (rv == NULL) {
+ error_allocate();
+ }
+ rv->data = (unsigned char *) PORT_ZAlloc((PORT_Strlen(string))/3 + 2);
+ while (!isxdigit(*string)) {
+ string++;
+ }
+ rv->len = 0;
+ while (*string != '\0') {
+ if (isxdigit(*string)) {
+ if (*string >= '0' && *string <= '9') {
+ high_digit = *string - '0';
+ } else {
+ *string = toupper(*string);
+ high_digit = *string - 'A';
+ }
+ string++;
+ if (*string >= '0' && *string <= '9') {
+ low_digit = *string - '0';
+ } else {
+ *string = toupper(*string);
+ low_digit = *string = 'A';
+ }
+ (rv->len)++;
+ } else {
+ if (*string == ':') {
+ string++;
+ } else {
+ if (*string == ' ') {
+ while (*string == ' ') {
+ string++;
+ }
+ }
+ if (*string != '\0') {
+ error_out("ERROR: Improperly formated binary encoding");
+ }
+ }
+ }
+ }
+
+ return rv;
+}
+
+static SECStatus
+MakeGeneralName(char *name,
+ CERTGeneralName *genName,
+ PRArenaPool *arena)
+{
+ SECItem *oid;
+ SECOidData *oidData;
+ SECItem *ipaddress;
+ SECItem *temp = NULL;
+ int i;
+ int nameType;
+ PRBool binary = PR_FALSE;
+ SECStatus rv = SECSuccess;
+ PRBool nickname;
+
+ PORT_Assert(genName);
+ PORT_Assert(arena);
+ nameType = *(name + PORT_Strlen(name) - 1) - '0';
+ if (nameType == 0 && *(name +PORT_Strlen(name) - 2) == '1') {
+ nickname = PR_TRUE;
+ nameType = certOtherName;
+ }
+ if (nameType < 1 || nameType > 9) {
+ error_out("ERROR: Unknown General Name Type");
+ }
+ *(name + PORT_Strlen(name) - 4) = '\0';
+ genName->type = nameType;
+
+ switch (genName->type) {
+ case certURI:
+ case certRFC822Name:
+ case certDNSName: {
+ genName->name.other.data = (unsigned char *)name;
+ genName->name.other.len = PORT_Strlen(name);
+ break;
+ }
+
+ case certIPAddress: {
+ ipaddress = string_to_ipaddress(name);
+ genName->name.other.data = ipaddress->data;
+ genName->name.other.len = ipaddress->len;
+ break;
+ }
+
+ case certRegisterID: {
+ oid = string_to_oid(name);
+ genName->name.other.data = oid->data;
+ genName->name.other.len = oid->len;
+ break;
+ }
+
+ case certEDIPartyName:
+ case certX400Address: {
+
+ genName->name.other.data = PORT_ArenaAlloc (arena,
+ PORT_Strlen (name) + 2);
+ if (genName->name.other.data == NULL) {
+ error_allocate();
+ }
+
+ PORT_Memcpy (genName->name.other.data + 2, name, PORT_Strlen (name));
+ /* This may not be accurate for all cases.
+ For now, use this tag type */
+ genName->name.other.data[0] = (char)(((genName->type - 1) &
+ 0x1f)| 0x80);
+ genName->name.other.data[1] = (char)PORT_Strlen (name);
+ genName->name.other.len = PORT_Strlen (name) + 2;
+ break;
+ }
+
+ case certOtherName: {
+ i = 0;
+ if (!nickname) {
+ while (!isdigit(*(name + PORT_Strlen(name) - i))) {
+ i++;
+ }
+ if (*(name + PORT_Strlen(name) - i) == '1') {
+ binary = PR_TRUE;
+ } else {
+ binary = PR_FALSE;
+ }
+ while (*(name + PORT_Strlen(name) - i) != '-') {
+ i++;
+ }
+ *(name + PORT_Strlen(name) - i - 1) = '\0';
+ i = 0;
+ while (*(name + i) != '-') {
+ i++;
+ }
+ *(name + i - 1) = '\0';
+ oid = string_to_oid(name + i + 2);
+ } else {
+ oidData = SECOID_FindOIDByTag(SEC_OID_NETSCAPE_NICKNAME);
+ oid = &oidData->oid;
+ while (*(name + PORT_Strlen(name) - i) != '-') {
+ i++;
+ }
+ *(name + PORT_Strlen(name) - i) = '\0';
+ }
+ genName->name.OthName.oid.data = oid->data;
+ genName->name.OthName.oid.len = oid->len;
+ if (binary) {
+ temp = string_to_binary(name);
+ genName->name.OthName.name.data = temp->data;
+ genName->name.OthName.name.len = temp->len;
+ } else {
+ temp = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
+ if (temp == NULL) {
+ error_allocate();
+ }
+ temp->data = (unsigned char *)name;
+ temp->len = PORT_Strlen(name);
+ SEC_ASN1EncodeItem (arena, &(genName->name.OthName.name), temp,
+ CERTIA5TypeTemplate);
+ }
+ PORT_Free(temp);
+ break;
+ }
+
+ case certDirectoryName: {
+ CERTName *directoryName = NULL;
+
+ directoryName = CERT_AsciiToName (name);
+ if (!directoryName) {
+ error_out("ERROR: Improperly formated alternative name");
+ break;
+ }
+ rv = CERT_CopyName (arena, &genName->name.directoryName,
+ directoryName);
+ CERT_DestroyName (directoryName);
+
+ break;
+ }
+ }
+ genName->l.next = &(genName->l);
+ genName->l.prev = &(genName->l);
+ return rv;
+}
+
+
+static CERTGeneralName *
+MakeAltName(Pair *data,
+ char *which,
+ PRArenaPool *arena)
+{
+ CERTGeneralName *SubAltName;
+ CERTGeneralName *current;
+ CERTGeneralName *newname;
+ char *name = NULL;
+ SECStatus rv = SECSuccess;
+ int len;
+
+
+ len = PORT_Strlen(which);
+ name = find_field(data, which, PR_TRUE);
+ SubAltName = current = (CERTGeneralName *) PORT_ZAlloc
+ (sizeof(CERTGeneralName));
+ if (current == NULL) {
+ error_allocate();
+ }
+ while (name != NULL) {
+
+ rv = MakeGeneralName(name, current, arena);
+
+ if (rv != SECSuccess) {
+ break;
+ }
+ if (*(which + len -1) < '9') {
+ *(which + len - 1) = *(which + len - 1) + 1;
+ } else {
+ if (isdigit(*(which + len - 2) )) {
+ *(which + len - 2) = *(which + len - 2) + 1;
+ *(which + len - 1) = '0';
+ } else {
+ *(which + len - 1) = '1';
+ *(which + len) = '0';
+ *(which + len + 1) = '\0';
+ len++;
+ }
+ }
+ len = PORT_Strlen(which);
+ name = find_field(data, which, PR_TRUE);
+ if (name != NULL) {
+ newname = (CERTGeneralName *) PORT_ZAlloc(sizeof(CERTGeneralName));
+ if (newname == NULL) {
+ error_allocate();
+ }
+ current->l.next = &(newname->l);
+ newname->l.prev = &(current->l);
+ current = newname;
+ newname = NULL;
+ } else {
+ current->l.next = &(SubAltName->l);
+ SubAltName->l.prev = &(current->l);
+ }
+ }
+ if (rv == SECFailure) {
+ return NULL;
+ }
+ return SubAltName;
+}
+
+static CERTNameConstraints *
+MakeNameConstraints(Pair *data,
+ PRArenaPool *arena)
+{
+ CERTNameConstraints *NameConstraints;
+ CERTNameConstraint *current = NULL;
+ CERTNameConstraint *last_permited = NULL;
+ CERTNameConstraint *last_excluded = NULL;
+ char *constraint = NULL;
+ char *which;
+ SECStatus rv = SECSuccess;
+ int len;
+ int i;
+ long max;
+ long min;
+ PRBool permited;
+
+
+ NameConstraints = (CERTNameConstraints *) PORT_ZAlloc
+ (sizeof(CERTNameConstraints));
+ which = make_copy_string("NameConstraintSelect0", 25,'\0');
+ len = PORT_Strlen(which);
+ constraint = find_field(data, which, PR_TRUE);
+ NameConstraints->permited = NameConstraints->excluded = NULL;
+ while (constraint != NULL) {
+ current = (CERTNameConstraint *) PORT_ZAlloc
+ (sizeof(CERTNameConstraint));
+ if (current == NULL) {
+ error_allocate();
+ }
+ i = 0;
+ while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
+ i++;
+ }
+ *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
+ max = (long) atoi(constraint + PORT_Strlen(constraint) + 3);
+ if (max > 0) {
+ (void) SEC_ASN1EncodeInteger(arena, &current->max, max);
+ }
+ i = 0;
+ while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
+ i++;
+ }
+ *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
+ min = (long) atoi(constraint + PORT_Strlen(constraint) + 3);
+ (void) SEC_ASN1EncodeInteger(arena, &current->min, min);
+ while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
+ i++;
+ }
+ *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
+ if (*(constraint + PORT_Strlen(constraint) + 3) == 'p') {
+ permited = PR_TRUE;
+ } else {
+ permited = PR_FALSE;
+ }
+ rv = MakeGeneralName(constraint, &(current->name), arena);
+
+ if (rv != SECSuccess) {
+ break;
+ }
+ if (*(which + len - 1) < '9') {
+ *(which + len - 1) = *(which + len - 1) + 1;
+ } else {
+ if (isdigit(*(which + len - 2) )) {
+ *(which + len - 2) = *(which + len - 2) + 1;
+ *(which + len - 1) = '0';
+ } else {
+ *(which + len - 1) = '1';
+ *(which + len) = '0';
+ *(which + len + 1) = '\0';
+ len++;
+ }
+ }
+ len = PORT_Strlen(which);
+ if (permited) {
+ if (NameConstraints->permited == NULL) {
+ NameConstraints->permited = last_permited = current;
+ }
+ last_permited->l.next = &(current->l);
+ current->l.prev = &(last_permited->l);
+ last_permited = current;
+ } else {
+ if (NameConstraints->excluded == NULL) {
+ NameConstraints->excluded = last_excluded = current;
+ }
+ last_excluded->l.next = &(current->l);
+ current->l.prev = &(last_excluded->l);
+ last_excluded = current;
+ }
+ constraint = find_field(data, which, PR_TRUE);
+ if (constraint != NULL) {
+ current = (CERTNameConstraint *) PORT_ZAlloc(sizeof(CERTNameConstraint));
+ if (current == NULL) {
+ error_allocate();
+ }
+ }
+ }
+ if (NameConstraints->permited != NULL) {
+ last_permited->l.next = &(NameConstraints->permited->l);
+ NameConstraints->permited->l.prev = &(last_permited->l);
+ }
+ if (NameConstraints->excluded != NULL) {
+ last_excluded->l.next = &(NameConstraints->excluded->l);
+ NameConstraints->excluded->l.prev = &(last_excluded->l);
+ }
+ if (which != NULL) {
+ PORT_Free(which);
+ }
+ if (rv == SECFailure) {
+ return NULL;
+ }
+ return NameConstraints;
+}
+
+
+
+static SECStatus
+AddAltName(void *extHandle,
+ Pair *data,
+ char *issuerNameStr,
+ CERTCertDBHandle *handle,
+ int type)
+{
+ PRBool autoIssuer = PR_FALSE;
+ PRArenaPool *arena = NULL;
+ CERTGeneralName *genName = NULL;
+ CERTName *directoryName = NULL;
+ char *which = NULL;
+ char *name = NULL;
+ SECStatus rv = SECSuccess;
+ SECItem *issuersAltName = NULL;
+ CERTCertificate *issuerCert = NULL;
+ void *mark = NULL;
+
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ error_allocate();
+ }
+ if (type == 0) {
+ which = make_copy_string("SubAltNameSelect0", 20,'\0');
+ genName = MakeAltName(data, which, arena);
+ } else {
+ if (autoIssuer) {
+ autoIssuer = find_field_bool(data,"IssuerAltNameSourceRadio-auto",
+ PR_TRUE);
+ issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
+ rv = cert_FindExtension((*issuerCert).extensions,
+ SEC_OID_X509_SUBJECT_ALT_NAME,
+ issuersAltName);
+ if (issuersAltName == NULL) {
+ name = PORT_Alloc(PORT_Strlen((*issuerCert).subjectName) + 4);
+ PORT_Strcpy(name, (*issuerCert).subjectName);
+ PORT_Strcat(name, " - 5");
+ }
+ } else {
+ which = make_copy_string("IssuerAltNameSelect0", 20,'\0');
+ genName = MakeAltName(data, which, arena);
+ }
+ }
+ if (type == 0) {
+ EncodeAndAddExtensionValue(arena, extHandle, genName,
+ find_field_bool(data, "SubAltName-crit",
+ PR_TRUE),
+ SEC_OID_X509_SUBJECT_ALT_NAME,
+ (EXTEN_VALUE_ENCODER)
+ CERT_EncodeAltNameExtension);
+
+ } else {
+ if (autoIssuer && (name == NULL)) {
+ rv = CERT_AddExtension
+ (extHandle, SEC_OID_X509_ISSUER_ALT_NAME, issuersAltName,
+ find_field_bool(data, "IssuerAltName-crit", PR_TRUE), PR_TRUE);
+ } else {
+ EncodeAndAddExtensionValue(arena, extHandle, genName,
+ find_field_bool(data,
+ "IssuerAltName-crit",
+ PR_TRUE),
+ SEC_OID_X509_ISSUER_ALT_NAME,
+ (EXTEN_VALUE_ENCODER)
+ CERT_EncodeAltNameExtension);
+ }
+ }
+ if (which != NULL) {
+ PORT_Free(which);
+ }
+ if (issuerCert != NULL) {
+ CERT_DestroyCertificate(issuerCert);
+ }
+#if 0
+ if (arena != NULL) {
+ PORT_ArenaRelease (arena, mark);
+ }
+#endif
+ return rv;
+}
+
+
+static SECStatus
+AddNameConstraints(void *extHandle,
+ Pair *data)
+{
+ PRBool autoIssuer = PR_FALSE;
+ PRArenaPool *arena = NULL;
+ CERTNameConstraints *constraints = NULL;
+ char *constraint = NULL;
+ SECStatus rv = SECSuccess;
+
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ error_allocate();
+ }
+ constraints = MakeNameConstraints(data, arena);
+ if (constraints != NULL) {
+ EncodeAndAddExtensionValue(arena, extHandle, constraints, PR_TRUE,
+ SEC_OID_X509_NAME_CONSTRAINTS,
+ (EXTEN_VALUE_ENCODER)
+ CERT_EncodeNameConstraintsExtension);
+ }
+ if (arena != NULL) {
+ PORT_ArenaRelease (arena, NULL);
+ }
+ return rv;
+}
+
+
+static SECStatus
+add_extensions(CERTCertificate *subjectCert,
+ Pair *data,
+ char *issuerNameStr,
+ CERTCertDBHandle *handle)
+{
+ void *extHandle;
+ SECStatus rv = SECSuccess;
+
+
+ extHandle = CERT_StartCertExtensions (subjectCert);
+ if (extHandle == NULL) {
+ error_out("ERROR: Unable to get certificates extension handle");
+ }
+ if (find_field_bool(data, "keyUsage", PR_TRUE)) {
+ rv = AddKeyUsage(extHandle, data);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Key Usage extension");
+ }
+ }
+
+ if( find_field_bool(data, "extKeyUsage", PR_TRUE) ) {
+ rv = AddExtKeyUsage(extHandle, data);
+ if( SECSuccess != rv ) {
+ error_out("ERROR: Unable to add Extended Key Usage extension");
+ }
+ }
+
+ if (find_field_bool(data, "basicConstraints", PR_TRUE)) {
+ rv = AddBasicConstraint(extHandle, data);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Basic Constraint extension");
+ }
+ }
+ if (find_field_bool(data, "subjectKeyIdentifier", PR_TRUE)) {
+ rv = AddSubKeyID(extHandle, data, subjectCert);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Subject Key Identifier Extension");
+ }
+ }
+ if (find_field_bool(data, "authorityKeyIdentifier", PR_TRUE)) {
+ rv = AddAuthKeyID (extHandle, data, issuerNameStr, handle);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Authority Key Identifier extension");
+ }
+ }
+ if (find_field_bool(data, "privKeyUsagePeriod", PR_TRUE)) {
+ rv = AddPrivKeyUsagePeriod (extHandle, data, subjectCert);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Private Key Usage Period extension");
+ }
+ }
+ if (find_field_bool(data, "SubAltName", PR_TRUE)) {
+ rv = AddAltName (extHandle, data, NULL, NULL, 0);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Subject Alternative Name extension");
+ }
+ }
+ if (find_field_bool(data, "IssuerAltName", PR_TRUE)) {
+ rv = AddAltName (extHandle, data, issuerNameStr, handle, 1);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Issuer Alternative Name Extension");
+ }
+ }
+ if (find_field_bool(data, "NameConstraints", PR_TRUE)) {
+ rv = AddNameConstraints(extHandle, data);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Name Constraints Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-cert-type", PR_TRUE)) {
+ rv = AddNscpCertType(extHandle, data);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape Certificate Type Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-base-url", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data, "netscape-base-url-text",
+ PR_TRUE),
+ find_field_bool(data,
+ "netscape-base-url-crit",
+ PR_TRUE),
+ SEC_OID_NS_CERT_EXT_BASE_URL);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape Base URL Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-revocation-url", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data,
+ "netscape-revocation-url-text",
+ PR_TRUE),
+ find_field_bool
+ (data, "netscape-revocation-url-crit",
+ PR_TRUE),
+ SEC_OID_NS_CERT_EXT_REVOCATION_URL);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape Revocation URL Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-ca-revocation-url", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data,
+ "netscape-ca-revocation-url-text",
+ PR_TRUE),
+ find_field_bool
+ (data, "netscape-ca-revocation-url-crit"
+ , PR_TRUE),
+ SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape CA Revocation URL Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-cert-renewal-url", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data,
+ "netscape-cert-renewal-url-text",
+ PR_TRUE),
+ find_field_bool
+ (data, "netscape-cert-renewal-url-crit",
+ PR_TRUE),
+ SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape Certificate Renewal URL Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-ca-policy-url", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data,
+ "netscape-ca-policy-url-text",
+ PR_TRUE),
+ find_field_bool
+ (data, "netscape-ca-policy-url-crit",
+ PR_TRUE),
+ SEC_OID_NS_CERT_EXT_CA_POLICY_URL);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape CA Policy URL Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-ssl-server-name", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data,
+ "netscape-ssl-server-name-text",
+ PR_TRUE),
+ find_field_bool
+ (data, "netscape-ssl-server-name-crit",
+ PR_TRUE),
+ SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape SSL Server Name Extension");
+ }
+ }
+ if (find_field_bool(data, "netscape-comment", PR_TRUE)) {
+ rv = add_IA5StringExtension(extHandle,
+ find_field(data, "netscape-comment-text",
+ PR_TRUE),
+ find_field_bool(data,
+ "netscape-comment-crit",
+ PR_TRUE),
+ SEC_OID_NS_CERT_EXT_COMMENT);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Unable to add Netscape Comment Extension");
+ }
+ }
+ CERT_FinishExtensions(extHandle);
+ return (rv);
+}
+
+
+
+char *
+return_dbpasswd(PK11SlotInfo *slot, PRBool retry, void *data)
+{
+ char *rv;
+
+ /* don't clobber our poor smart card */
+ if (retry == PR_TRUE) {
+ return NULL;
+ }
+ rv = PORT_Alloc(4);
+ PORT_Strcpy(rv, "foo");
+ return rv;
+}
+
+
+SECKEYPrivateKey *
+FindPrivateKeyFromNameStr(char *name,
+ CERTCertDBHandle *certHandle)
+{
+ SECKEYPrivateKey *key;
+ CERTCertificate *cert;
+ CERTCertificate *p11Cert;
+ SECStatus status = SECSuccess;
+
+
+ /* We don't presently have a PK11 function to find a cert by
+ ** subject name.
+ ** We do have a function to find a cert in the internal slot's
+ ** cert db by subject name, but it doesn't setup the slot info.
+ ** So, this HACK works, but should be replaced as soon as we
+ ** have a function to search for certs accross slots by subject name.
+ */
+ cert = CERT_FindCertByNameString(certHandle, name);
+ if (cert == NULL || cert->nickname == NULL) {
+ error_out("ERROR: Unable to retrieve issuers certificate");
+ }
+ p11Cert = PK11_FindCertFromNickname(cert->nickname, NULL);
+ if (p11Cert == NULL) {
+ error_out("ERROR: Unable to retrieve issuers certificate");
+ }
+ key = PK11_FindKeyByAnyCert(p11Cert, NULL);
+ return key;
+}
+
+static SECItem *
+SignCert(CERTCertificate *cert,
+ char *issuerNameStr,
+ Pair *data,
+ CERTCertDBHandle *handle,
+ int which_key)
+{
+ SECItem der;
+ SECItem *result = NULL;
+ SECKEYPrivateKey *caPrivateKey = NULL;
+ SECStatus rv;
+ PRArenaPool *arena;
+ SECOidTag algID;
+
+ if (which_key == 0) {
+ caPrivateKey = FindPrivateKeyFromNameStr(issuerNameStr, handle);
+ } else {
+ caPrivateKey = privkeys[which_key - 1];
+ }
+ if (caPrivateKey == NULL) {
+ error_out("ERROR: unable to retrieve issuers key");
+ }
+
+ arena = cert->arena;
+
+ switch(caPrivateKey->keyType) {
+ case rsaKey:
+ algID = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
+ break;
+ case dsaKey:
+ algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
+ break;
+ default:
+ error_out("ERROR: Unknown key type for issuer.");
+ goto done;
+ break;
+ }
+
+ rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Could not set signature algorithm id.");
+ }
+
+ if (find_field_bool(data,"ver-1", PR_TRUE)) {
+ *(cert->version.data) = 0;
+ cert->version.len = 1;
+ } else {
+ *(cert->version.data) = 2;
+ cert->version.len = 1;
+ }
+ der.data = NULL;
+ der.len = 0;
+ (void) SEC_ASN1EncodeItem (arena, &der, cert, CERT_CertificateTemplate);
+ if (der.data == NULL) {
+ error_out("ERROR: Could not encode certificate.\n");
+ }
+ rv = SEC_DerSignData (arena, &(cert->derCert), der.data, der.len, caPrivateKey,
+ algID);
+ if (rv != SECSuccess) {
+ error_out("ERROR: Could not sign encoded certificate data.\n");
+ }
+done:
+ SECKEY_DestroyPrivateKey(caPrivateKey);
+ return &(cert->derCert);
+}
+
+
+int
+main(int argc, char **argv)
+{
+ int length = 500;
+ int remaining = 500;
+ int n;
+ int fields = 3;
+ int i;
+ int serial;
+ int chainLen;
+ int which_key;
+ char *pos;
+#ifdef OFFLINE
+ char *form_output = "key=MIIBPTCBpzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7SLqjWBL9Wl11Vlg%0AaMqZCvcQOL%2FnvSqYPPRP0XZy9SoAeyWzQnBOiCm2t8H5mK7r2jnKdAQOmfhjaJil%0A3hNVu3SekHOXF6Ze7bkWa6%2FSGVcY%2FojkydxFSgY43nd1iydzPQDp8WWLL%2BpVpt%2B%2B%0ATRhFtVXbF0fQI03j9h3BoTgP2lkCAwEAARYDZm9vMA0GCSqGSIb3DQEBBAUAA4GB%0AAJ8UfRKJ0GtG%2B%2BufCC6tAfTzKrq3CTBHnom55EyXcsAsv6WbDqI%2F0rLAPkn2Xo1r%0AnNhtMxIuj441blMt%2Fa3AGLOy5zmC7Qawt8IytvQikQ1XTpTBCXevytrmLjCmlURr%0ANJryTM48WaMQHiMiJpbXCqVJC1d%2FpEWBtqvALzZaOOIy&subject=CN%3D%22test%22%26serial-auto%3Dtrue%26serial_value%3D%26ver-1%3Dtrue%26ver-3%3Dfalse%26caChoiceradio-SignWithDefaultkey%3Dtrue%26caChoiceradio-SignWithRandomChain%3Dfalse%26autoCAs%3D%26caChoiceradio-SignWithSpecifiedChain%3Dfalse%26manCAs%3D%26%24";
+#else
+ char *form_output;
+#endif
+ char *issuerNameStr;
+ char *certName;
+ char *DBdir = DB_DIRECTORY;
+ char *prefixs[10] = {"CA#1-", "CA#2-", "CA#3-",
+ "CA#4-", "CA#5-", "CA#6-",
+ "CA#7-", "CA#8-", "CA#9-", ""};
+ Pair *form_data;
+ CERTCertificate *cert;
+ CERTCertDBHandle *handle;
+ CERTCertificateRequest *certReq = NULL;
+ int warpmonths = 0;
+ SECItem *certDER;
+#ifdef FILEOUT
+ FILE *outfile;
+#endif
+ SECStatus status = SECSuccess;
+ extern char prefix[PREFIX_LEN];
+ SEC_PKCS7ContentInfo *certChain;
+ SECItem *encodedCertChain;
+ PRBool UChain = PR_FALSE;
+
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+
+#ifdef TEST
+ sleep(20);
+#endif
+ SECU_ConfigDirectory(DBdir);
+
+ PK11_SetPasswordFunc(return_dbpasswd);
+ status = NSS_InitReadWrite(DBdir);
+ if (status != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+ handle = CERT_GetDefaultCertDB();
+
+ prefix[0]= '\0';
+#if !defined(OFFLINE)
+ form_output = (char*) PORT_Alloc(length);
+ if (form_output == NULL) {
+ error_allocate();
+ }
+ pos = form_output;
+ while (feof(stdin) == 0 ) {
+ if (remaining <= 1) {
+ remaining += length;
+ length = length * 2;
+ form_output = PORT_Realloc(form_output, (length));
+ if (form_output == NULL) {
+ error_allocate();
+ }
+ pos = form_output + length - remaining;
+ }
+ n = fread(pos, 1, (size_t) (remaining - 1), stdin);
+ pos += n;
+ remaining -= n;
+ }
+ *pos = '&';
+ pos++;
+ length = pos - form_output;
+#else
+ length = PORT_Strlen(form_output);
+#endif
+#ifdef FILEOUT
+ printf("Content-type: text/plain\n\n");
+ fwrite(form_output, 1, (size_t)length, stdout);
+ printf("\n");
+#endif
+#ifdef FILEOUT
+ fwrite(form_output, 1, (size_t)length, stdout);
+ printf("\n");
+ fflush(stdout);
+#endif
+ form_data = make_datastruct(form_output, length);
+ status = clean_input(form_data);
+#if !defined(OFFLINE)
+ PORT_Free(form_output);
+#endif
+#ifdef FILEOUT
+ i = 0;
+ while(return_name(form_data, i) != NULL) {
+ printf("%s",return_name(form_data,i));
+ printf("=\n");
+ printf("%s",return_data(form_data,i));
+ printf("\n");
+ i++;
+ }
+ printf("I got that done, woo hoo\n");
+ fflush(stdout);
+#endif
+ issuerNameStr = PORT_Alloc(200);
+ if (find_field_bool(form_data, "caChoiceradio-SignWithSpecifiedChain",
+ PR_FALSE)) {
+ UChain = PR_TRUE;
+ chainLen = atoi(find_field(form_data, "manCAs", PR_FALSE));
+ PORT_Strcpy(prefix, prefixs[0]);
+ issuerNameStr = PORT_Strcpy(issuerNameStr,
+ "CN=Cert-O-Matic II, O=Cert-O-Matic II");
+ if (chainLen == 0) {
+ UChain = PR_FALSE;
+ }
+ } else {
+ if (find_field_bool(form_data, "caChoiceradio-SignWithRandomChain",
+ PR_FALSE)) {
+ PORT_Strcpy(prefix,prefixs[9]);
+ chainLen = atoi(find_field(form_data, "autoCAs", PR_FALSE));
+ if (chainLen < 1 || chainLen > 18) {
+ issuerNameStr = PORT_Strcpy(issuerNameStr,
+ "CN=CA18, O=Cert-O-Matic II");
+ }
+ issuerNameStr = PORT_Strcpy(issuerNameStr, "CN=CA");
+ issuerNameStr = PORT_Strcat(issuerNameStr,
+ find_field(form_data,"autoCAs", PR_FALSE));
+ issuerNameStr = PORT_Strcat(issuerNameStr,", O=Cert-O-Matic II");
+ } else {
+ issuerNameStr = PORT_Strcpy(issuerNameStr,
+ "CN=Cert-O-Matic II, O=Cert-O-Matic II");
+ }
+ chainLen = 0;
+ }
+
+ i = -1;
+ which_key = 0;
+ do {
+ extern SECStatus cert_GetKeyID(CERTCertificate *cert);
+ i++;
+ if (i != 0 && UChain) {
+ PORT_Strcpy(prefix, prefixs[i]);
+ }
+ /* find_field(form_data,"subject", PR_TRUE); */
+ certReq = makeCertReq(form_data, which_key);
+#ifdef OFFLINE
+ serial = 900;
+#else
+ serial = get_serial_number(form_data);
+#endif
+ cert = MakeV1Cert(handle, certReq, issuerNameStr, PR_FALSE,
+ serial, warpmonths, form_data);
+ if (certReq != NULL) {
+ CERT_DestroyCertificateRequest(certReq);
+ }
+ if (find_field_bool(form_data,"ver-3", PR_TRUE)) {
+ status = add_extensions(cert, form_data, issuerNameStr, handle);
+ if (status != SECSuccess) {
+ error_out("ERROR: Unable to add extensions");
+ }
+ }
+ status = cert_GetKeyID(cert);
+ if (status == SECFailure) {
+ error_out("ERROR: Unable to get Key ID.");
+ }
+ certDER = SignCert(cert, issuerNameStr, form_data, handle, which_key);
+ CERT_NewTempCertificate(handle, certDER, NULL, PR_FALSE, PR_TRUE);
+ issuerNameStr = find_field(form_data, "subject", PR_TRUE);
+ /* SECITEM_FreeItem(certDER, PR_TRUE); */
+ CERT_DestroyCertificate(cert);
+ if (i == (chainLen - 1)) {
+ i = 8;
+ }
+ ++which_key;
+ } while (i < 9 && UChain);
+
+
+
+#ifdef FILEOUT
+ outfile = fopen("../certout", "wb");
+#endif
+ certName = find_field(form_data, "subject", PR_FALSE);
+ cert = CERT_FindCertByNameString(handle, certName);
+ certChain = SEC_PKCS7CreateCertsOnly (cert, PR_TRUE, handle);
+ if (certChain == NULL) {
+ error_out("ERROR: No certificates in cert chain");
+ }
+ encodedCertChain = SEC_PKCS7EncodeItem (NULL, NULL, certChain, NULL, NULL,
+ NULL);
+ if (encodedCertChain) {
+#if !defined(FILEOUT)
+ printf("Content-type: application/x-x509-user-cert\r\n");
+ printf("Content-length: %d\r\n\r\n", encodedCertChain->len);
+ fwrite (encodedCertChain->data, 1, encodedCertChain->len, stdout);
+#else
+ fwrite (encodedCertChain->data, 1, encodedCertChain->len, outfile);
+#endif
+
+ } else {
+ error_out("Error: Unable to DER encode certificate");
+ }
+#ifdef FILEOUT
+ printf("\nI got here!\n");
+ fflush(outfile);
+ fclose(outfile);
+#endif
+ fflush(stdout);
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/security/nss/cmd/certcgi/index.html b/security/nss/cmd/certcgi/index.html
new file mode 100644
index 000000000..0bd79f3ce
--- /dev/null
+++ b/security/nss/cmd/certcgi/index.html
@@ -0,0 +1,956 @@
+<HTML> <!-- -*- Mode: Java; tab-width: 8 -*- -->
+<!--
+ - The contents of this file are subject to the Mozilla Public
+ - License Version 1.1 (the "License"); you may not use this file
+ - except in compliance with the License. You may obtain a copy of
+ - the License at http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS
+ - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ - implied. See the License for the specific language governing
+ - rights and limitations under the License.
+ -
+ - The Original Code is the Netscape security libraries.
+ -
+ - The Initial Developer of the Original Code is Netscape
+ - Communications Corporation. Portions created by Netscape are
+ - Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ - Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the
+ - terms of the GNU General Public License Version 2 or later (the
+ - "GPL"), in which case the provisions of the GPL are applicable
+ - instead of those above. If you wish to allow use of your
+ - version of this file only under the terms of the GPL and not to
+ - allow others to use your version of this file under the MPL,
+ - indicate your decision by deleting the provisions above and
+ - replace them with the notice and other provisions required by
+ - the GPL. If you do not delete the provisions above, a recipient
+ - may use your version of this file under either the MPL or the
+ - GPL.
+ -->
+<HEAD>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<SCRIPT LANGUAGE="JavaScript1.2">
+
+script_url = 'http://interzone.mcom.com/cgi-bin/certomatic/bin/certcgi.cgi'
+
+ext_page_ver1 =
+ make_page_intro('Version 1 extensions', "#FFFFFF") +
+ '<layer ID="ext1">' +
+ 'Version 1 X.509 certs do not support extensions' +
+ '</layer>' +
+ '</body></html>';
+
+cur_page = 1;
+
+num_ca = 0;
+
+index_list =
+ '0, your_certificate_index_label,' +
+ '0, netscape_extensions_index_label,' +
+ '0, standard_extensions_index_label,' +
+ '0, certifying_authorities_index_label';
+
+var main_page =
+ make_page_intro('Your Key', "#FFFFFF") +
+ '<layer ID="main" SRC="main.html">' +
+ '</layer>' +
+ '</body></html>' ;
+
+add_index_list = '';
+
+max_pages = 13;
+
+ver = 3
+
+ext_page_array = new Array(max_pages);
+
+index_label = 'Options';
+
+your_certificate_index_label = 'Your Certificate';
+
+netscape_extensions_index_label = 'Netscape X.509 Extensions';
+
+standard_extensions_index_label = 'Standard X.509 Extensions';
+
+certifying_authorities_index_label = 'Certifying Authorities';
+
+add_sub_alt_name_index_label = 'Add Subject Alternative Name';
+
+function setSubAltNameType(form)
+{
+ with(form)
+ {
+ if (SubAltNameRadio[0].checked)
+ {
+ return true;
+ }
+ if (SubAltNameRadio[3].checked || SubAltNameRadio[5].checked)
+ {
+ SubAltNameDataType.checked = true;
+ return true;
+ }
+ if (SubAltNameRadio[1].checked || SubAltNameRadio[2].checked ||
+ SubAltNameRadio[4].checked || SubAltNameRadio[6].checked ||
+ SubAltNameRadio[7].checked || SubAltNameRadio[8].checked)
+ {
+ SubAltNameDataType.checked = false;
+ return true;
+ }
+ }
+ return true;
+}
+
+function setIssuerAltNameType(form)
+{
+ with(form)
+ {
+ if (IssuerAltNameRadio[0].checked)
+ {
+ return true;
+ }
+ if (IssuerAltNameRadio[3].checked || IssuerAltNameRadio[5].checked)
+ {
+ IssuerAltNameDataType.checked = true;
+ return true;
+ }
+ if (IssuerAltNameRadio[1].checked || IssuerAltNameRadio[2].checked ||
+ IssuerAltNameRadio[4].checked || IssuerAltNameRadio[6].checked ||
+ IssuerAltNameRadio[7].checked || IssuerAltNameRadio[8].checked)
+ {
+ IssuerAltNameDataType.checked = false;
+ return true;
+ }
+ }
+ return true;
+}
+
+
+function setNameConstraintNameType(form)
+{
+ with(form)
+ {
+ if (NameConstraintRadio[0].checked)
+ {
+ return true;
+ }
+ if (NameConstraintRadio[3].checked || NameConstraintRadio[5].checked)
+ {
+ NameConstraintNameDataType.checked = true;
+ return true;
+ }
+ if (NameConstraintRadio[1].checked || NameConstraintRadio[2].checked ||
+ NameConstraintRadio[4].checked || NameConstraintRadio[6].checked ||
+ NameConstraintRadio[7].checked || NameConstraintRadio[8].checked)
+ {
+ NameConstraintNameDataType.checked = false;
+ return true;
+ }
+ }
+ return true;
+}
+
+
+function addSubAltName(form)
+{
+
+ with(form)
+ {
+ var len = SubAltNameSelect.length;
+ var value;
+ var i = 0;
+ while(!(i == (SubAltNameRadio.length - 1)) & !(SubAltNameRadio[i].checked == true))
+ {
+ i++;
+ }
+ if (i != 0)
+ {
+ value = SubAltNameText.value + " - " + (i + 1);
+ }
+ else
+ {
+ value = SubAltNameText.value + " - " + SubAltNameOtherNameOID.value + " - ";
+ if (SubAltNameDataType.checked)
+ {
+ value += "1 - ";
+ }
+ else
+ {
+ value += "0 - ";
+ }
+ value += (i + 1);
+ if (SubAltNameOtherNameOID.value == "")
+ {
+ alert("Other names must include an OID");
+ return false;
+ }
+ }
+
+ if ((SubAltNameText.value == "") | (SubAltNameRadio[i].checked != true))
+ {
+ alert("Alternative Names must include values for name and name type.");
+ }
+ else
+ {
+ SubAltNameSelect.options[len] = new Option(value, value);
+ }
+ }
+ return true;
+}
+
+function deleteSubAltName(form)
+{
+ with(form)
+ {
+ while (SubAltNameSelect.selectedIndex >= 0)
+ {
+ SubAltNameSelect[SubAltNameSelect.selectedIndex] = null;
+ }
+ }
+}
+
+function addIssuerAltName(form)
+{
+ with(form)
+ {
+ var len = IssuerAltNameSelect.length;
+ var value;
+ var i = 0;
+
+ while(!(i == (IssuerAltNameRadio.length -1)) & !(IssuerAltNameRadio[i].checked == true))
+ {
+ i++;
+ }
+ if (i != 0)
+ {
+ value = IssuerAltNameText.value + " - " + (i + 1);
+ }
+ else
+ {
+ value = IssuerAltNameText.value + " - " + IssuerAltNameOtherNameOID.value + " - ";
+ if (IssuerAltNameDataType.checked)
+ {
+ value += "1 - ";
+ }
+ else
+ {
+ value += "0 - ";
+ }
+ value += (i + 1);
+ if (IssuerAltNameOtherNameOID.value == "")
+ {
+ alert("Other names must include an OID");
+ return false;
+ }
+ }
+ if ((IssuerAltNameText.value == "") | (IssuerAltNameRadio[i].checked != true))
+ {
+ alert("Alternative Names must include values for name and name type.")
+ }
+ else
+ {
+ IssuerAltNameSelect.options[len] = new Option(value, value);
+ }
+ }
+ return true;
+}
+
+function deleteIssuerAltName(form)
+{
+ with(form)
+ {
+ while (IssuerAltNameSelect.selectedIndex >= 0)
+ {
+ IssuerAltNameSelect[IssuerAltNameSelect.selectedIndex] = null;
+ }
+ }
+}
+
+
+
+function addNameConstraint(form)
+{
+ with(form)
+ {
+ var len = NameConstraintSelect.length;
+ var value;
+ var i = 0;
+ var min = NameConstraintMin.value;
+ var max = NameConstraintMax.value;
+
+ while(!(i == (NameConstraintRadio.length - 1) ) & !(NameConstraintRadio[i].checked == true))
+ {
+ i++;
+ }
+ value = NameConstraintText.value + " - ";
+ if (i == 0)
+ {
+ value += NameConstraintOtherNameOID.value + " - ";
+ if (NameConstraintNameDataType.checked)
+ {
+ value += "1 - ";
+ }
+ else
+ {
+ value += "0 - ";
+ }
+ if (NameConstraintOtherNameOID.value == "")
+ {
+ alert("Other names must include an OID");
+ return false;
+ }
+ }
+ value += (i + 1) + " - ";
+ if (NameConstraintTypeRadio[0].checked == true)
+ {
+ value += "p - ";
+ }
+ else
+ {
+ value += "e - ";
+ }
+ value += min + " - " + max;
+ if ((min == "") | (NameConstraintText.value == "") | (NameConstraintRadio[i].checked != true))
+ {
+ alert("Name Constraints must include values for minimum, name, and name type.")
+ }
+ else
+ {
+ NameConstraintSelect.options[len] = new Option(value, value);
+ }
+ }
+ return true;
+}
+
+function deleteNameConstraint(form)
+{
+ with(form)
+ {
+ while (NameConstraintSelect.selectedIndex >= 0)
+ {
+ NameConstraintSelect[NameConstraintSelect.selectedIndex] = null;
+ }
+ }
+}
+
+
+function submit_it()
+{
+ save_cur_page(cur_page);
+
+ var array_string;
+ var subject = ext_page_array[0][22][0];
+ var serial = ext_page_array[0][10][0];
+ var ver1 = (ver == 1);
+ var ver3 = (ver == 3);
+ var serial_number = ext_page_array[0][12][0];
+ var notBefore = ext_page_array[0][20][0];
+ var notAfter = ext_page_array[0][21][0];
+ var manValidity = ext_page_array[0][19][0];
+
+ if (subject == "")
+ {
+ alert("The DN field must contain some data");
+ return false;
+ }
+ if (!serial & serial_number == "")
+ {
+ alert("No serial number specified");
+ return false;
+ }
+ if (ext_page_array[0][15][0])
+ {
+ var keygen = "<keygen name=\"key\" challenge=\"foo\">";
+ }
+ else
+ {
+ switch (ext_page_array[0][17][0]) {
+ case 2:
+ var keygen = "<keygen keytype=\"dsa\" pqg=\"MIGdAkEAjfKklEkidqo9JXWbsGhpy+rA2Dr7jQz3y7gyTw14guXQdi/FtyEOr8Lprawyq3qsSWk9+/g3JMLsBzbuMcgCkQIVAMdzIYxzfsjumTtPLe0w9I7azpFfAkEAYm0CeDnqChNBMWOlW0y1ACmdVSKVbO/LO/8Q85nOLC5xy53l+iS6v1jlt5UhklycxC6fb0ZLCIzFcq9T5teIAg==\" name=\"key\" challenge=\"foo\">";
+ break;
+ case 1:
+ var keygen = "<keygen keytype=\"dsa\" pqg=\"MIHaAmDCboVgX0+6pEeMlbwsasWDVBcJNHPKMzkq9kbCRK2U3k+tE15n+Dc2g3ZjDYr1um51e2iLC34/BwAAAAAAAAAAAAAAAAAAAAAAAAABbBhnlFN5Djmt0Mk8cdEBY5H8iPMCFMhUnFtbpjn3EyfH2DjVg3ALh7FtAmA2zWzhpeCwvOTjYnQorlXiv0WcnSiWmaC79CRYkFt5i+UEfRxwP1eNGJBVB1T+CPW6JGd4WhgsqtSf53pn5DEtv++O7lNfXyOhWhb3KaWHYIx8fuAXtioIWkWmpfEIVZA=\" name=\"key\" challenge=\"foo\">";
+ break;
+ case 0:
+ var keygen = "<keygen keytype=\"dsa\" pqg=\"MIIBHAKBgId8SiiWrcdua5zbsBhPkKfFcnHBG7T/bQla7c6OixGjjmSSuq2fJLvMKa579CaxHxLZzZZXIHmAk9poRgWl2GUUkCJ68XSum8OQzDPXPsofcEdeANjw3mIAAAAAAAAAAAAAAAAAAAAAAAAIE+MkW5hguLIQqWvEVi9dMpbNu6OZAhTIA+y3TgyiwA0D8pt686ofaL1IOQKBgAiZQC6UCXztr2iXxJrAC+51gN5oX/R9Thilln9RGegsWnHrdxUOpcm5vAWp1LU8TOXtujE8kqkm3UxIRhUWQORe9IxLANAXmZJqkw9FEVHkxj6Cy9detwT2MyBzSwS6avsf7aLisgHmI/IHSeapJsQ3NQa3rikb6zRiqIV+TVa6\" name=\"key\" challenge=\"foo\">";
+ break;
+ }
+ }
+ array_string = build_array_string();
+ hiddens = "<input type=\"hidden\" name=\"subject\" value=\'" + subject + "\'> \n" +
+ "<input type=\"hidden\" name=\"serial-auto\" value=\"" + serial + "\"> \n" +
+ "<input type=\"hidden\" name=\"serial_value\" value=\"" + serial_number + "\"> \n" +
+ "<input type=\"hidden\" name=\"ver-1\" value=\"" + ver1 + "\"> \n" +
+ "<input type=\"hidden\" name=\"ver-3\" value=\"" + ver3 + "\"> \n" +
+ "<input type=\"hidden\" name=\"notBefore\" value=\"" + notBefore + "\"> \n" +
+ "<input type=\"hidden\" name=\"notAfter\" value=\"" + notAfter + "\"> \n" +
+ "<input type=\"hidden\" name=\"manValidity\" value=\"" + manValidity + "\"> \n" +
+ array_string;
+
+ var good_submit_page =
+ '<html>' +
+ '<BODY TEXT="#000000" LINK="#000000" VLINK="#000000" ALINK="#FF0000" BGCOLOR="#FFFFFF">' +
+ '<form method="post" action="' + script_url + '">' +
+ 'Select size for your key:' + keygen + '</p>' +
+ '<input type="submit"></p>' +
+ hiddens +
+ '</form>\n' +
+ '</body>\n' +
+ '</html>\n';
+
+ window.frames.extensions.document.write(good_submit_page);
+ window.frames.extensions.document.close();
+ cur_page = max_pages + 1;
+ make_index(window);
+ return false;
+}
+
+
+
+function build_array_string()
+{
+ var j;
+ var array_string = '';
+ var pages;
+
+ if ((ext_page_array[3][4][0] > 0) && ext_page_array[3][3][0])
+ {
+ pages = 4 + parseInt(ext_page_array[3][4][0]);
+ }
+ else
+ {
+ pages = 4;
+ }
+ for (j = 1; j < pages; j++)
+ {
+ if ((j > 1 || (ver == 3)) &&
+ (ext_page_array[j].length > 1))
+ {
+ if (j < 4)
+ {
+ for (i = 0; i < ext_page_array[j].length; i++)
+ {
+ if (ext_page_array[j][i][3].indexOf("radio") == -1)
+ {
+ if (ext_page_array[j][i][3].indexOf("multiple") == -1)
+ {
+ array_string += '<input type=\"hidden\" name=\"' + ext_page_array[j][i][1] + '\" value=\'' + ext_page_array[j][i][0] + '\'> \n';
+ }
+ else
+ {
+ for (k = 0; k < ext_page_array[j][i][0].length; k++)
+ {
+ array_string += '<input type=\"hidden\" name=\"' + ext_page_array[j][i][1] + k + '\" value=\'' + ext_page_array[j][i][0][k] + '\'> \n';
+ }
+ }
+ }
+ else
+ {
+ array_string += '<input type=\"hidden\" name=\"' + ext_page_array[j][i][1] + '-' + ext_page_array[j][i][2] + '\" value=\'' + ext_page_array[j][i][0] + '\'> \n';
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < ext_page_array[j].length; i++)
+ {
+ if (ext_page_array[j][i][3].indexOf("radio") == -1)
+ {
+ if (ext_page_array[j][i][3].indexOf("multiple") == -1)
+ {
+ array_string += '<input type=\"hidden\" name=\"' + 'CA#' + (j - 3) + '-' + ext_page_array[j][i][1] + '\" value=\'' + ext_page_array[j][i][0] +'\'> \n';
+ }
+ else
+ {
+ for (k = 0; k < ext_page_array[j][i][0].length; k++)
+ {
+ array_string += '<input type=\"hidden\" name=\"' + 'CA#' + (j - 3) + '-' + ext_page_array[j][i][1] + k + '\" value=\'' + ext_page_array[j][i][0][k] + '\'> \n';
+ }
+ }
+ }
+ else
+ {
+ array_string += '<input type=\"hidden\" name=\"' + 'CA#' + (j - 3) + '-' + ext_page_array[j][i][1] + '-' + ext_page_array[j][i][2] + '\" value=\'' + ext_page_array[j][i][0] + '\'> \n';
+ }
+ }
+ }
+ }
+ }
+ return array_string;
+}
+
+
+
+function init_ext_page_array()
+{
+ for (i = 0; i < max_pages; i++)
+ {
+ ext_page_array[i] = '';
+ }
+}
+
+function ca_num_change(n,ca_form)
+{
+ with(ca_form)
+ {
+ n = parseInt(n,10);
+ if (caChoiceradio[2].checked)
+ {
+ if (n)
+ {
+ update_index(n);
+ }
+ else
+ {
+ update_index(0);
+ }
+ }
+ }
+}
+
+function choice_change(ca_form)
+{
+ with(ca_form)
+ {
+ if (caChoiceradio[2].checked)
+ {
+ ca_num_change(manCAs.value,ca_form);
+ }
+ else
+ {
+ update_index(0);
+ }
+ }
+}
+
+function update_index(n)
+{
+ var add_string = '';
+ for (var i = 0; i < n; i++)
+ {
+ var j = i + 1;
+ add_string = add_string + ',1, \'CA #' + j + '\'';
+ }
+ top.add_index_list = add_string;
+ num_ca = n;
+ make_index(window);
+}
+
+function set_ver1()
+// redraws the extensions page for version 1 certificates
+{
+ ver = 1
+ if (cur_page == 2 || cur_page == 3)
+ {
+ sa_switch_pane(window, cur_page, cur_page);
+ }
+}
+
+
+function set_ver3()
+// redraws the extensions page for version 3 certificates
+{
+ ver = 3
+ if (cur_page == 2)
+ {
+ sa_switch_pane(window, 0, 2);
+ }
+ else if (cur_page == 3)
+ {
+ sa_switch_pane(window, 0, 3);
+ }
+}
+
+function reset_subject(marker, value, form)
+// Updates the subject field from a subordinate field
+{
+ with(form)
+ {
+ var field_sep = '", ';
+ var begin_index = subject.value.indexOf(marker);
+ if (begin_index != 0 && subject.value[begin_index - 1] != ' ')
+ {
+ begin_index = subject.value.indexOf(marker, begin_index +1);
+ }
+ var end_index = subject.value.indexOf(field_sep, begin_index);
+ if (begin_index > -1) // is it a delete/change?
+ {
+ if (end_index == -1) // is it the last one (includes only one)?
+ {
+ if (value.length > 0) // do I have to change it?
+ {
+ if (begin_index == 0) // is is the only one?
+ {
+ subject.value = marker + '"' + value + '"';
+ }
+ else // it is the last of many
+ {
+ subject.value = subject.value.substring(0,begin_index) + marker + '"' + value + '"';
+ }
+ }
+ else // must be a delete
+ {
+ if (begin_index == 0) // is it the only one?
+ {
+ begin_index += 2;
+ }
+ subject.value = subject.value.substring(0,(begin_index - 2));
+ }
+ }
+ else // it is the first of many or a middle one
+ {
+ if (value.length >0) // do I have to change it?
+ {
+ subject.value = subject.value.substring(0,(begin_index + marker.length + 1)) + value + subject.value.substring(end_index,subject.length);
+ }
+ else // it is a delete
+ {
+ subject.value = subject.value.substring(0,begin_index) + subject.value.substring((end_index + 3),subject.length);
+ }
+ }
+ }
+ else // It is either an insert or a do nothing
+ {
+ if (value.length > 0) // is it an insert?
+ {
+ if (subject.value.length == 0) // is subject currently empty?
+ {
+ subject.value = marker + '"' + value + '"';
+ }
+ else
+ {
+ subject.value = subject.value + ', ' + marker + '"' + value + '"';
+ }
+ }
+ }
+ }
+}
+
+
+
+function reset_subjectFields(form)
+// updates all the subordinate fields from the subject field of a form
+// ************ move the strings to global variables, to make maintentance easier ****************
+{
+
+ update_subject_Field(form, 'CN=\"', form.name);
+ update_subject_Field(form, 'MAIL=\"', form.email);
+ update_subject_Field(form, 'O=\"', form.org);
+ update_subject_Field(form, 'C=\"', form.country);
+ update_subject_Field(form, ' L=\"', form.loc);
+ update_subject_Field(form, 'ST=\"', form.state);
+ update_subject_Field(form, 'E=\"', form.email);
+ update_subject_Field(form, 'OU=\"', form.org_unit);
+ update_subject_Field(form, 'UID=\"', form.uid);
+}
+
+function update_subject_Field(form, marker, update_field)
+//updates a single subordinate field from the subject field of a form
+// *************** need to deal with the two types of e-mail addresses **************
+{
+ with(form)
+ {
+ var field_sep = '", ';
+ var begin_index = subject.value.indexOf(marker) + marker.length;
+ var end_index = subject.value.indexOf(field_sep, begin_index);
+ if (end_index == -1)
+ {
+ end_index = subject.value.indexOf('"',begin_index);
+ }
+ if (begin_index != (-1 + marker.length) )
+ {
+ update_field.value = subject.value.substring(begin_index, end_index);
+ }
+ else
+ {
+ update_field.value = '';
+ }
+ }
+}
+
+
+function switch_mail(form)
+ // *************** I need to figure out if I want to delete the other type of e-mail address ************
+{
+ if (form.email_type[0].checked)
+ {
+ var del = 'E=';
+ var ins = 'MAIL=';
+ }
+ else
+ {
+ var del = 'MAIL=';
+ var ins = 'E=';
+ }
+ reset_subject(del, '', form);
+ reset_subject(ins, form.email.value, form);
+}
+
+function make_page_intro(title, bgcolor)
+{
+ var style = '<STYLE TYPE="text/css">BODY{' +
+ 'font-family: Geneva,MS Sans Serif,Arial,Lucida,Helvetica,sans-serif;' +
+ 'font-size: 10pt;' +
+ '}' +
+ 'TD{' +
+ 'font-family: Geneva,MS Sans Serif,Arial,Lucida,Helvetica,sans-serif;' +
+ 'font-size: 10pt;}' +
+ '</STYLE>';
+
+ if (bgcolor == null) { bgcolor = "#C0C0C0"; }
+ return '<HTML><HEAD>' +
+ '<TITLE>' + title + '</TITLE>' +
+ '</HEAD>' +
+ '<BODY TEXT="#000000" LINK="#000000" VLINK="#000000" ALINK="#FF0000" ' +
+ 'BGCOLOR="' + bgcolor + '">';
+}
+
+
+function make_index(window)
+{
+ with (window.frames.index)
+ {
+ eval ('index_string = make_index_page(cur_page, ' + index_list + add_index_list + ' )');
+ fool1 = make_page_intro(index_label, "#FFFFFF") +
+ index_string + '</BODY></HTML>';
+ document.write(fool1);
+ document.close();
+ }
+}
+
+
+function save_cur_page(page_number)
+{
+ var len;
+ var j = page_number - 1;
+ if (frames.extensions.document.layers.length != 0)
+ {
+ with (frames.extensions.document.layers[0].document)
+ {
+ if ((page_number != 2 && page_number != 3 && page_number <= max_pages) ||
+ ver == 3)
+ {
+ ext_page_array[j] = new Array(forms[0].elements.length);
+ for (i = 0; i < forms[0].elements.length; i++)
+ {
+ ext_page_array[j][i] = new Array(4);
+ switch (forms[0].elements[i].type)
+ {
+ case 'radio': case 'checkbox':
+ ext_page_array[j][i][0] = forms[0].elements[i].checked;
+ break;
+ case 'select-one':
+ ext_page_array[j][i][0] = forms[0].elements[i].selectedIndex;
+ break;
+ case 'select-multiple':
+ len = forms[0].elements[i].options.length;
+ ext_page_array[j][i][0] = new Array(len);
+ for(k = 0; k < len; k++)
+ {
+ ext_page_array[j][i][0][k] = forms[0].elements[i].options[k].value;
+ }
+ break;
+ default:
+ ext_page_array[j][i][0] = forms[0].elements[i].value;
+ }
+ ext_page_array[j][i][1] = forms[0].elements[i].name;
+ ext_page_array[j][i][2] = forms[0].elements[i].value;
+ ext_page_array[j][i][3] = forms[0].elements[i].type;
+ }
+ }
+ }
+ }
+}
+
+function reload_form(page_number)
+{
+ var j = page_number - 1;
+ with (frames.extensions.document.layers[0].document)
+ {
+ if (((page_number < 2 || page_number > 3) || ver == 3)
+ && page_number != 0 && (ext_page_array[j].length > 1))
+ {
+ for (i = 0; i < ext_page_array[j].length; i++)
+ {
+ switch (forms[0].elements[i].type)
+ {
+ case 'radio': case 'checkbox':
+ forms[0].elements[i].checked = ext_page_array[j][i][0];
+ break;
+ case 'select-one':
+ forms[0].elements[i].selectedIndex = ext_page_array[j][i][0];
+ break;
+ case 'select-multiple':
+ for (k = 0; k < ext_page_array[j][i][0].length; k++)
+ {
+ forms[0].elements[i].options[k] = new Option(ext_page_array[j][i][0][k],
+ ext_page_array[j][i][0][k]);
+ }
+ break;
+ default:
+ forms[0].elements[i].value = ext_page_array[j][i][0];
+ }
+ }
+ }
+ }
+}
+
+function sa_switch_pane(top_window, old_pane, new_pane)
+{
+ var ext_page_stnd =
+ make_page_intro(standard_extensions_index_label, "#FFFFFF") +
+ '<layer ID="ext" SRC="stnd_ext_form.html">' +
+ '</layer>' +
+ '</body></html>';
+
+ var ext_page_nscp =
+ make_page_intro(netscape_extensions_index_label, "#FFFFFF") +
+ '<layer ID="ext" SRC="nscp_ext_form.html">' +
+ '</layer>' +
+ '</body></html>';
+
+ var ext_page_ca =
+ make_page_intro(certifying_authorities_index_label, "#FFFFFF") +
+ '<layer ID="ext" SRC="ca.html">' +
+ '</layer>' +
+ '</body</html>';
+
+ var ext_page_ca_exp =
+ make_page_intro('Certifying Authority Details', "#FFFFFF") +
+ '<layer ID="ext" SRC="ca_form.html">' +
+ '</layer>' +
+ '</body></html>';
+
+
+ if (old_pane > 0 && cur_page <= max_pages)
+ {
+ save_cur_page(old_pane);
+ }
+ cur_page = new_pane;
+ make_index(top_window);
+ if (new_pane == 2 || new_pane == 3)
+ {
+ if (ver == 1)
+ {
+ frames.extensions.document.write(ext_page_ver1);
+ frames.extensions.document.close();
+ }
+ else
+ {
+ if (new_pane == 2)
+ {
+ frames.extensions.document.write(ext_page_nscp);
+ frames.extensions.document.close();
+ reload_form(new_pane);
+ }
+ else
+ {
+ frames.extensions.document.write(ext_page_stnd);
+ frames.extensions.document.close();
+ reload_form(new_pane);
+ }
+ }
+ }
+ else
+ {
+ if (new_pane == 4)
+ {
+ frames.extensions.document.write(ext_page_ca);
+ frames.extensions.document.close();
+ reload_form(new_pane);
+ }
+ else
+ {
+ if (new_pane == 1)
+ {
+ frames.extensions.document.write(main_page);
+ frames.extensions.document.close();
+ reload_form(new_pane);
+ }
+ else
+ {
+ frames.extensions.document.write(ext_page_ca_exp);
+ frames.extensions.document.close();
+ reload_form(new_pane);
+ }
+ }
+ }
+}
+
+function make_index_page(selected)
+{
+ var n_strings = ( make_index_page.arguments.length - 1 ) / 2;
+ var table_background;
+ var command;
+ var indent;
+ var label;
+ var ret_string = "";
+
+ ret_string += '<TABLE CELLSPACING=4>';
+ for ( var i = 1; i <= n_strings; i++ ) {
+ if ( i == selected ) {
+ table_background = 'BGCOLOR=#BBCCBB';
+ } else {
+ table_background = '';
+ }
+
+ indent = make_index_page.arguments[(i*2) - 1];
+ label = make_index_page.arguments[(i*2)];
+
+ if ( indent == 0 ) {
+ ret_string += ('<TR><TD COLSPAN=2 ' + table_background + '>');
+ } else {
+ ret_string += ('<TR><TD>&nbsp;&nbsp;</TD><TD ' + table_background + '>');
+ }
+
+ command = "'parent.sa_switch_pane(parent," + selected + "," + i + ")'";
+ ret_string += ('<A HREF="javascript:void setTimeout(' + command + ',0)">');
+ if ( indent == 0 ) { ret_string += "<B>"; }
+ ret_string += label;
+ if ( indent == 0 ) { ret_string += "</B>"; }
+ ret_string += '</A></TD></TR>';
+ }
+ if (selected == (max_pages + 1))
+ {
+ table_background = 'BGCOLOR=#BBCCBB';
+ } else {
+ table_background = '';
+ }
+ ret_string +=
+ '<TR><TD COLSPAN=2 ' + table_background +
+ '><b><A HREF="javascript:void setTimeout(\'top.submit_it()\', 0)">Finish</A></b>' +
+ '</TD></TR>' +
+ '<input type="submit"></form>' +
+ '</TABLE>';
+ return(ret_string);
+}
+
+
+function make_page(window)
+// Draws the initial page setup
+{
+ selected = cur_page
+ init_ext_page_array()
+
+ with (window.frames.extensions) {
+ document.write(main_page);
+ document.close();
+ }
+
+ make_index(window);
+
+}
+</script>
+
+</HEAD>
+<title>Cert-O-Matic</title>
+ <FRAMESET cols="150,*" BORDER=3 ONLOAD="make_page(window)">
+ <FRAME SRC="about:blank" NAME="index"
+ MARGINWIDTH=15 MARGINHEIGHT=10 BORDER=3>
+ <FRAME SRC="about:blank" NAME="extensions"
+ MARGINWIDTH=15 MARGINHEIGHT=10 BORDER=3>
+ </FRAMESET>
+</HTML>
diff --git a/security/nss/cmd/certcgi/main.html b/security/nss/cmd/certcgi/main.html
new file mode 100644
index 000000000..50e138aee
--- /dev/null
+++ b/security/nss/cmd/certcgi/main.html
@@ -0,0 +1,105 @@
+<HTML>
+<!--
+ - The contents of this file are subject to the Mozilla Public
+ - License Version 1.1 (the "License"); you may not use this file
+ - except in compliance with the License. You may obtain a copy of
+ - the License at http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS
+ - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ - implied. See the License for the specific language governing
+ - rights and limitations under the License.
+ -
+ - The Original Code is the Netscape security libraries.
+ -
+ - The Initial Developer of the Original Code is Netscape
+ - Communications Corporation. Portions created by Netscape are
+ - Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ - Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the
+ - terms of the GNU General Public License Version 2 or later (the
+ - "GPL"), in which case the provisions of the GPL are applicable
+ - instead of those above. If you wish to allow use of your
+ - version of this file only under the terms of the GPL and not to
+ - allow others to use your version of this file under the MPL,
+ - indicate your decision by deleting the provisions above and
+ - replace them with the notice and other provisions required by
+ - the GPL. If you do not delete the provisions above, a recipient
+ - may use your version of this file under either the MPL or the
+ - GPL.
+ -->
+<HEAD>
+ <TITLE>Main Layer for CertOMatic</TITLE>
+</HEAD>
+
+ <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi">
+ <table border=0 cellspacing=10 cellpadding=0>
+ <tr>
+ <td>
+ Common Name:</td><td> <input type="text" name="name" onChange="{window.top.reset_subject('CN=', value, form)}"></p>
+ </td>
+ <td></td><td></td>
+ <td>
+ Organization: </td><td> <input type="text" name="org" onChange="{window.top.reset_subject('O=', value, form)}"></p></td>
+ <tr>
+ <td>
+ <input type="radio" name="email_type" value="1" onClick="window.top.switch_mail(form)">MAIL=
+
+ <input type="radio" name="email_type" value="2" checked onClick="window.top.switch_mail(form)">E=
+ </td>
+ <td>
+ <input type="text" name="email" onChange="var temp;{if (email_type[0].checked) {temp = 'MAIL='} else {temp = 'E='}} ;{window.top.reset_subject(temp, value, form)}">
+ </td>
+ <td></td><td></td><td>
+ Organizational Unit: </td><td><input type="text" name="org_unit" onChange="{window.top.reset_subject('OU=', value, form)}"></p></td>
+ <tr>
+ <td>
+ UID= </td><td><input type="text" name="uid" onChange="{window.top.reset_subject('UID=', value, form)}"></p></td>
+ <td></td><td></td><td>
+ Locality: </td><td><input type="text" name="loc" onChange="{window.top.reset_subject('L=', value, form)}"></p></td>
+ <tr>
+ <td>
+ State or Province: </td><td><input type="text" name="state" onChange="{window.top.reset_subject('ST=', value, form)}"></p></td>
+ <td></td><td></td><td>
+ Country: </td><td><input type="text" size="2" name="country" onChange="{window.top.reset_subject('C=', value, form)}" maxlength="2"></p></td>
+ <tr>
+ <td COLSPAN=2>
+ Serial Number:
+ <DD><input type="radio" name="serial" value="auto" checked> Auto Generate
+ <DD><input type="radio" name="serial" value="input">
+ Use this hex value:&nbsp; <input type="text" name="serial_value" size="8" maxlength="8"></p>
+ </td>
+ <td></td> <td></td>
+ <td COLSPAN=2>
+ X.509 version:
+ <DD><input type="radio" name="ver" value="1" onClick="if (this.checked) {window.top.set_ver1();}"> Version 1
+ <DD><input type="radio" name="ver" value="3" checked onClick="if (this.checked) {window.top.set_ver3();}"> Version 3</P></td>
+ <tr>
+ <td COLSPAN=2>
+ Key Type:
+ <DD><input type="radio" name="keyType" value="rsa" checked> RSA
+ <DD><input type="radio" name="keyType" value="dsa"> DSA</p>
+ Intermediate CA Key Sizes:
+ <DD><select name="keysize">
+ <option>2048 (Very High Grade)
+ <option>1024 (High Grade)
+ <option>512 (Low Grade)
+ </select>
+ </td>
+ <td></td> <td></td>
+ <td COLSPAN=2>
+ Validity:
+ <DD><input type="radio" name="validity" value="auto" checked>
+ Generate Automatically
+ <DD><input type="radio" name="validity" value="man"> Use these values:
+ <DD>Not Before:&nbsp; <input type="text" size="15" maxlength="17" name="notBefore">
+ <DD>Not After:&nbsp;&nbsp;&nbsp; <input type="text" size="15" maxlength="17" name="notAfter">
+ <DD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ <FONT SIZE=-1><TT>YYMMDDhhmm[ss]{Z|+hhmm|-hhmm} </TT></FONT>
+ </table>
+ DN: <input type="text" name="subject" size="70" onChange="{window.top.reset_subjectFields(form)}"></P>
+ </form>
+</HTML>
diff --git a/security/nss/cmd/certcgi/manifest.mn b/security/nss/cmd/certcgi/manifest.mn
new file mode 100644
index 000000000..9d659f821
--- /dev/null
+++ b/security/nss/cmd/certcgi/manifest.mn
@@ -0,0 +1,50 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIREd.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = certcgi.c
+
+PROGRAM = certcgi
+
+USE_STATIC_LIBS = 1
+
diff --git a/security/nss/cmd/certcgi/nscp_ext_form.html b/security/nss/cmd/certcgi/nscp_ext_form.html
new file mode 100644
index 000000000..de939eecb
--- /dev/null
+++ b/security/nss/cmd/certcgi/nscp_ext_form.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<!--
+ - The contents of this file are subject to the Mozilla Public
+ - License Version 1.1 (the "License"); you may not use this file
+ - except in compliance with the License. You may obtain a copy of
+ - the License at http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS
+ - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ - implied. See the License for the specific language governing
+ - rights and limitations under the License.
+ -
+ - The Original Code is the Netscape security libraries.
+ -
+ - The Initial Developer of the Original Code is Netscape
+ - Communications Corporation. Portions created by Netscape are
+ - Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ - Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the
+ - terms of the GNU General Public License Version 2 or later (the
+ - "GPL"), in which case the provisions of the GPL are applicable
+ - instead of those above. If you wish to allow use of your
+ - version of this file only under the terms of the GPL and not to
+ - allow others to use your version of this file under the MPL,
+ - indicate your decision by deleting the provisions above and
+ - replace them with the notice and other provisions required by
+ - the GPL. If you do not delete the provisions above, a recipient
+ - may use your version of this file under either the MPL or the
+ - GPL.
+ -->
+
+ <body>
+ <table border=1 cellspacing=5 cellpadding=5>
+ <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi">
+ <tr>
+ <td>
+ <b>Netscape Certificate Type: </b></p>
+ Activate extension: <input type="checkbox" name="netscape-cert-type"></P>
+ Critical: <input type="checkbox" name="netscape-cert-type-crit">
+ <td>
+ <input type="checkbox" name="netscape-cert-type-ssl-client"> SSL Client</P>
+ <input type="checkbox" name="netscape-cert-type-ssl-server"> SSL Server</P>
+ <input type="checkbox" name="netscape-cert-type-smime"> S/MIME</P>
+ <input type="checkbox" name="netscape-cert-type-object-signing"> Object Signing</P>
+ <input type="checkbox" name="netscape-cert-type-reserved"> Reserved for future use (bit 4)</P>
+ <input type="checkbox" name="netscape-cert-type-ssl-ca"> SSL CA</P>
+ <input type="checkbox" name="netscape-cert-type-smime-ca"> S/MIME CA</P>
+ <input type="checkbox" name="netscape-cert-type-object-signing-ca"> Object Signing CA</P>
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Base URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-base-url"></P>
+ Critical: <input type="checkbox" name="netscape-base-url-crit">
+ <td>
+ <input type="text" name="netscape-base-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Revocation URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-revocation-url"></P>
+ Critical: <input type="checkbox" name="netscape-revocation-url-crit">
+ <td>
+ <input type="text" name="netscape-revocation-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape CA Revocation URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-ca-revocation-url"></P>
+ Critical: <input type="checkbox" name="netscape-ca-revocation-url-crit">
+ <td>
+ <input type="text" name="netscape-ca-revocation-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Certificate Renewal URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-cert-renewal-url"></P>
+ Critical: <input type="checkbox" name="netscape-cert-renewal-url-crit">
+ <td>
+ <input type="text" name="netscape-cert-renewal-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape CA Policy URL:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-ca-policy-url"></P>
+ Critical: <input type="checkbox" name="netscape-ca-policy-url-crit">
+ <td>
+ <input type="text" name="netscape-ca-policy-url-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape SSL Server Name:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-ssl-server-name"></P>
+ Critical: <input type="checkbox" name="netscape-ssl-server-name-crit">
+ <td>
+ <input type="text" name="netscape-ssl-server-name-text" size="50">
+ </tr>
+ <tr>
+ <td>
+ <b>Netscape Comment:</b></p>
+ Activate extension: <input type="checkbox" name="netscape-comment"></P>
+ Critical: <input type="checkbox" name="netscape-comment-crit">
+ <td>
+ <textarea name="netscape-comment-text" rows="5" cols="50"></textarea>
+ </tr>
+
+ </table>
+ </body>
+</html>
diff --git a/security/nss/cmd/certcgi/stnd_ext_form.html b/security/nss/cmd/certcgi/stnd_ext_form.html
new file mode 100644
index 000000000..ece9b2ff7
--- /dev/null
+++ b/security/nss/cmd/certcgi/stnd_ext_form.html
@@ -0,0 +1,247 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<!--
+ - The contents of this file are subject to the Mozilla Public
+ - License Version 1.1 (the "License"); you may not use this file
+ - except in compliance with the License. You may obtain a copy of
+ - the License at http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS
+ - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ - implied. See the License for the specific language governing
+ - rights and limitations under the License.
+ -
+ - The Original Code is the Netscape security libraries.
+ -
+ - The Initial Developer of the Original Code is Netscape
+ - Communications Corporation. Portions created by Netscape are
+ - Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ - Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the
+ - terms of the GNU General Public License Version 2 or later (the
+ - "GPL"), in which case the provisions of the GPL are applicable
+ - instead of those above. If you wish to allow use of your
+ - version of this file only under the terms of the GPL and not to
+ - allow others to use your version of this file under the MPL,
+ - indicate your decision by deleting the provisions above and
+ - replace them with the notice and other provisions required by
+ - the GPL. If you do not delete the provisions above, a recipient
+ - may use your version of this file under either the MPL or the
+ - GPL.
+ -->
+
+ <body>
+ <table border=1 cellspacing=5 cellpadding=5>
+ <form method="post" name="primary_form" action="http://interzone.mcom.com/burp.cgi">
+ <tr>
+ <td>
+ <b>Key Usage: </b></p>
+ Activate extension: <input type="checkbox" name="keyUsage"></P>
+ Critical: <input type="checkbox" name="keyUsage-crit">
+ <td>
+ <input type="checkbox" name="keyUsage-digitalSignature"> Digital Signature</P>
+ <input type="checkbox" name="keyUsage-nonRepudiation"> Non Repudiation</P>
+ <input type="checkbox" name="keyUsage-keyEncipherment"> Key Encipherment</P>
+ <input type="checkbox" name="keyUsage-dataEncipherment"> Data Encipherment</P>
+ <input type="checkbox" name="keyUsage-keyAgreement"> Key Agreement</P>
+ <input type="checkbox" name="keyUsage-keyCertSign"> Key Certificate Signing</P>
+ <input type="checkbox" name="keyUsage-cRLSign"> CRL Signing</P>
+ </tr>
+ <tr>
+ <td>
+ <b>Extended Key Usage: </b></p>
+ Activate extension: <input type="checkbox" name="extKeyUsage"></P>
+ Critical: <input type="checkbox" name="extKeyUsage-crit">
+ <td>
+ <input type="checkbox" name="extKeyUsage-serverAuth"> Server Auth</P>
+ <input type="checkbox" name="extKeyUsage-clientAuth"> Client Auth</P>
+ <input type="checkbox" name="extKeyUsage-codeSign"> Code Signing</P>
+ <input type="checkbox" name="extKeyUsage-emailProtect"> Email Protection</P>
+ <input type="checkbox" name="extKeyUsage-timeStamp"> Timestamp</P>
+ <input type="checkbox" name="extKeyUsage-ocspResponder"> OCSP Responder</P>
+ <input type="checkbox" name="extKeyUsage-NS-govtApproved"> Step-up</P>
+ </tr>
+ <tr>
+ <td>
+ <b>Basic Constraints:</b></p>
+ Activate extension: <input type="checkbox" name="basicConstraints"></P>
+ Critical: <input type="checkbox" name="basicConstraints-crit">
+ <td>
+ CA:</p>
+ <dd><input type=radio name="basicConstraints-cA-radio" value="CA"> True</p>
+ <dd><input type=radio name="basicConstraints-cA-radio" value="NotCA"> False</p>
+ <input type="checkbox" name="basicConstraints-pathLengthConstraint">
+ Include Path length: <input type="text" name="basicConstraints-pathLengthConstraint-text" size="2"></p>
+ </tr>
+ <tr>
+ <td>
+ <b>Authority Key Identifier:</b></p>
+ Activate extension: <input type="checkbox" name="authorityKeyIdentifier">
+ <td>
+ <input type="radio" name="authorityKeyIdentifier-radio" value="keyIdentifier"> Key Identider</p>
+ <input type="radio" name="authorityKeyIdentifier-radio" value="authorityCertIssuer"> Issuer Name and Serial number</p>
+ </tr>
+ <tr>
+ <td>
+ <b>Subject Key Identifier:</b></p>
+ Activate extension: <input type="checkbox" name="subjectKeyIdentifier">
+ <td>
+ Key Identifier:
+ <input type="text" name="subjectKeyIdentifier-text"></p>
+ This is an:<p>
+ <dd><dd><input type="radio" name="subjectKeyIdentifier-radio" value="ascii"> ascii text value<p>
+ <dd><dd><input type="radio" name="subjectKeyIdentifier-radio" value="hex"> hex value<p>
+ </tr>
+ <tr>
+ <td>
+ <b>Private Key Usage Period:</b></p>
+ Activate extension: <input type="checkbox" name="privKeyUsagePeriod"></p>
+ Critical: <input type="checkbox" name="privKeyUsagePeriod-crit">
+ <td>
+ Use:</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-radio" value="notBefore"> Not Before</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-radio" value="notAfter"> Not After</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-radio" value="both" > Both</p>
+ <b>Not to be used to sign before:</b></p>
+ <dd><input type="radio" name="privKeyUsagePeriod-notBefore-radio" value="auto"> Set to time of certificate issue</p>
+ <dd><input type="radio" name="privKeyUsagePeriod-notBefore-radio" value="manual"> Use This value</p>
+ <dd><dd>(YYYY/MM/DD HH:MM:SS):
+ <input type="text" name="privKeyUsagePeriod-notBefore-year" size="4" maxlength="4">/
+ <input type="text" name="privKeyUsagePeriod-notBefore-month" size="2" maxlength="2">/
+ <input type="text" name="privKeyUsagePeriod-notBefore-day" size="2" maxlength="2">
+ <input type="text" name="privKeyUsagePeriod-notBefore-hour" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notBefore-minute" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notBefore-second" size="2" maxlength="2"></p>
+ <b>Not to be used to sign after:</b></p>
+ <dd>(YYYY/MM/DD HH:MM:SS):
+ <input type="text" name="privKeyUsagePeriod-notAfter-year" size="4" maxlength="4">/
+ <input type="text" name="privKeyUsagePeriod-notAfter-month" size="2" maxlength="2">/
+ <input type="text" name="privKeyUsagePeriod-notAfter-day" size="2" maxlength="2">
+ <input type="text" name="privKeyUsagePeriod-notAfter-hour" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notAfter-minute" size="2" maxlength="2">:
+ <input type="text" name="privKeyUsagePeriod-notAfter-second" size="2" maxlength="2"></p>
+ </tr>
+ <tr>
+ <td>
+ <b>Subject Alternative Name:</b></p>
+ Activate extension: <input type="checkbox" name="SubAltName"></P>
+ Critical: <input type="checkbox" name="SubAltName-crit">
+ <td>
+ <table>
+ <tr>
+ <td>
+ General Names:</p>
+ <select name="SubAltNameSelect" multiple size="10">
+ </select></p></p>
+ <input type="button" name="SubAltName-add" value="Add" onClick="{parent.addSubAltName(this.form)}">
+ <input type="button" name="SubAltName-delete" value="Delete" onClick="parent.deleteSubAltName(this.form)">
+ </td><td>
+ <table><tr><td>
+ Name Type: </td></tr><tr><td>
+ <input type="radio" name="SubAltNameRadio" value="otherName" onClick="parent.setSubAltNameType(form)"> Other Name,
+ OID: <input type="text" name="SubAltNameOtherNameOID" size="6"> </td><td>
+ <input type="radio" name="SubAltNameRadio" value="rfc822Name" onClick="parent.setSubAltNameType(form)"> RFC 822 Name</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="dnsName" onClick="parent.setSubAltNameType(form)"> DNS Name </td><td>
+ <input type="radio" name="SubAltNameRadio" value="x400" onClick="parent.setSubAltNameType(form)"> X400 Address</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="directoryName" onClick="parent.setSubAltNameType(form)"> Directory Name</td><td>
+ <input type="radio" name="SubAltNameRadio" value="ediPartyName" onClick="parent.setSubAltNameType(form)"> EDI Party Name</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="URL" onClick="parent.setSubAltNameType(form)"> Uniform Resource Locator</td><td>
+ <input type="radio" name="SubAltNameRadio" value="ipAddress" onClick="parent.setSubAltNameType(form)"> IP Address</td></tr><td>
+ <input type="radio" name="SubAltNameRadio" value="regID"onClick="parent.setSubAltNameType(form)"> Registered ID</td><td>
+ <input type="radio" name="SubAltNameRadio" value="nscpNickname" onClick="parent.setSubAltNameType(form)"> Netscape Certificate Nickname</td><td></tr>
+ </table>
+ Name: <input type="text" name="SubAltNameText">
+ Binary Encoded: <input type="checkbox" name="SubAltNameDataType" value="binary" onClick="parent.setSubAltNameType(form)"></p>
+ </tr>
+ </table>
+ </tr>
+
+
+ <tr>
+ <td>
+ <b>Issuer Alternative Name:</b></p>
+ Activate extension: <input type="checkbox" name="IssuerAltName"></P>
+ Critical: <input type="checkbox" name="IssuerAltName-crit">
+ <td>
+ <input type="radio" name="IssuerAltNameSourceRadio" value="auto"> Use the Subject Alternative Name from the Issuers Certificate</p>
+ <input type="radio" name="IssuerAltNameSourceRadio" value="man"> Use this Name:
+ <table>
+ <tr>
+ <td>
+ General Names:</p>
+ <select name="IssuerAltNameSelect" multiple size="10">
+ </select></p></p>
+ <input type="button" name="IssuerAltName-add" value="Add" onClick="{parent.addIssuerAltName(this.form)}">
+ <input type="button" name="IssuerAltName-delete" value="Delete" onClick="parent.deleteIssuerAltName(this.form)">
+ </td><td>
+ <table><tr><td>
+ Name Type: </td></tr><tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="otherName" onClick="parent.setIssuerAltNameType(form)"> Other Name,
+ OID: <input type="text" name="IssuerAltNameOtherNameOID" size="6"> </td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="rfc822Name" onClick="parent.setIssuerAltNameType(form)"> RFC 822 Name</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="dnsName" onClick="parent.setIssuerAltNameType(form)"> DNS Name </td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="x400" onClick="parent.setIssuerAltNameType(form)"> X400 Address</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="directoryName" onClick="parent.setIssuerAltNameType(form)"> Directory Name</td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="ediPartyName" onClick="parent.setIssuerAltNameType(form)"> EDI Party Name</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="URL" onClick="parent.setIssuerAltNameType(form)"> Uniform Resource Locator</td><td>
+ <input type="radio" name="IssuerAltNameRadio" value="ipAddress" onClick="parent.setIssuerAltNameType(form)"> IP Address</td></tr><td>
+ <input type="radio" name="IssuerAltNameRadio" value="regID" onClick="parent.setIssuerAltNameType(form)"> Registered ID</td><td></tr>
+ </table>
+ Name: <input type="text" name="IssuerAltNameText">
+ Binary Encoded: <input type="checkbox" name="IssuerAltNameDataType" value="binary" onClick="parent.setIssuerAltNameType(form)"></p>
+ </tr>
+ </table>
+ </tr>
+
+ <tr>
+ <td>
+ <b>Name Constraints:</b></p>
+ Activate extension: <input type="checkbox" name="NameConstraints"></P>
+ <td>
+ <table>
+ <tr>
+ <td>
+ Name Constraints:</p>
+ <select name="NameConstraintSelect" multiple size="10">
+ </select></p></p>
+ <input type="button" name="NameConstraint-add" value="Add" onClick="{parent.addNameConstraint(this.form)}">
+ <input type="button" name="NameConstraint-delete" value="Delete" onClick="parent.deleteNameConstraint(this.form)">
+ </td><td>
+ <table><tr><td>
+ Name Type: </td></tr><tr><td>
+ <input type="radio" name="NameConstraintRadio" value="otherName" onClick="parent.setNameConstraintNameType(form)"> Other Name,
+ OID: <input type="text" name="NameConstraintOtherNameOID" size="6"> </td><td>
+ <input type="radio" name="NameConstraintRadio" value="rfc822Name" onClick="parent.setNameConstraintNameType(form)"> RFC 822 Name</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="dnsName" onClick="parent.setNameConstraintNameType(form)"> DNS Name </td><td>
+ <input type="radio" name="NameConstraintRadio" value="x400" onClick="parent.setNameConstraintNameType(form)"> X400 Address</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="directoryName" onClick="parent.setNameConstraintNameType(form)"> Directory Name</td><td>
+ <input type="radio" name="NameConstraintRadio" value="ediPartyName" onClick="parent.setNameConstraintNameType(form)"> EDI Party Name</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="URL" onClick="parent.setNameConstraintNameType(form)"> Uniform Resource Locator</td><td>
+ <input type="radio" name="NameConstraintRadio" value="ipAddress" onClick="parent.setNameConstraintNameType(form)"> IP Address</td></tr><td>
+ <input type="radio" name="NameConstraintRadio" value="regID" onClick="parent.setNameConstraintNameType(form)"> Registered ID</td><td></tr>
+ </table>
+ Name: <input type="text" name="NameConstraintText">
+ Binary Encoded: <input type="checkbox" name="NameConstraintNameDataType" value="binary" onClick="parent.setNameConstraintNameType(form)"></p>
+ Constraint type:<p>
+ <dd><input type="radio" name="NameConstraintTypeRadio" value="permited"> permited<p>
+ <dd><input type="radio" name="NameConstraintTypeRadio" value="excluded"> excluded<p>
+ Minimum: <input type="text" name="NameConstraintMin" size="8" maxlength="8"></p>
+ Maximum: <input type="text" name="NameConstraintMax" size="8" maxlength="8"></p>
+ </tr>
+ </table>
+ </tr>
+
+ </table>
+ </body>
+</html>
+
+
+
+
+
+
+
+
diff --git a/security/nss/cmd/certutil/Makefile b/security/nss/cmd/certutil/Makefile
new file mode 100644
index 000000000..8650a607d
--- /dev/null
+++ b/security/nss/cmd/certutil/Makefile
@@ -0,0 +1,76 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/certutil/certutil.c b/security/nss/cmd/certutil/certutil.c
new file mode 100644
index 000000000..0ef9710e2
--- /dev/null
+++ b/security/nss/cmd/certutil/certutil.c
@@ -0,0 +1,2885 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+** certutil.c
+**
+** utility for managing certificates and the cert database
+**
+*/
+#include <stdio.h>
+#include <string.h>
+
+#if defined(WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "nss.h"
+
+#define MIN_KEY_BITS 512
+#define MAX_KEY_BITS 2048
+#define DEFAULT_KEY_BITS 1024
+
+#define GEN_BREAK(e) rv=e; break;
+
+
+extern SECKEYPrivateKey *CERTUTIL_GeneratePrivateKey(KeyType keytype,
+ PK11SlotInfo *slot,
+ int rsasize,
+ int publicExponent,
+ char *noise,
+ SECKEYPublicKey **pubkeyp,
+ char *pqgFile,
+ secuPWData *pwdata);
+
+static char *progName;
+
+static CERTGeneralName *
+GetGeneralName (PRArenaPool *arena)
+{
+ CERTGeneralName *namesList = NULL;
+ CERTGeneralName *current;
+ CERTGeneralName *tail = NULL;
+ SECStatus rv = SECSuccess;
+ int intValue;
+ char buffer[512];
+ void *mark;
+
+ PORT_Assert (arena);
+ mark = PORT_ArenaMark (arena);
+ do {
+ puts ("\nSelect one of the following general name type: \n");
+ puts ("\t1 - instance of other name\n\t2 - rfc822Name\n\t3 - dnsName\n");
+ puts ("\t4 - x400Address\n\t5 - directoryName\n\t6 - ediPartyName\n");
+ puts ("\t7 - uniformResourceidentifier\n\t8 - ipAddress\n\t9 - registerID\n");
+ puts ("\tOther - omit\n\t\tChoice:");
+ scanf ("%d", &intValue);
+ if (intValue >= certOtherName || intValue <= certRegisterID) {
+ if (namesList == NULL) {
+ namesList = current = tail = (CERTGeneralName *) PORT_ArenaAlloc
+ (arena, sizeof (CERTGeneralName));
+ } else {
+ current = (CERTGeneralName *) PORT_ArenaAlloc(arena,
+ sizeof (CERTGeneralName));
+ }
+ if (current == NULL) {
+ GEN_BREAK (SECFailure);
+ }
+ } else {
+ break;
+ }
+ current->type = intValue;
+ puts ("\nEnter data:");
+ fflush (stdout);
+ gets (buffer);
+ switch (current->type) {
+ case certURI:
+ case certDNSName:
+ case certRFC822Name:
+ current->name.other.data = PORT_ArenaAlloc (arena, strlen (buffer));
+ if (current->name.other.data == NULL) {
+ GEN_BREAK (SECFailure);
+ }
+ PORT_Memcpy
+ (current->name.other.data, buffer, current->name.other.len = strlen(buffer));
+ break;
+
+ case certEDIPartyName:
+ case certIPAddress:
+ case certOtherName:
+ case certRegisterID:
+ case certX400Address: {
+
+ current->name.other.data = PORT_ArenaAlloc (arena, strlen (buffer) + 2);
+ if (current->name.other.data == NULL) {
+ GEN_BREAK (SECFailure);
+ }
+
+ PORT_Memcpy (current->name.other.data + 2, buffer, strlen (buffer));
+ /* This may not be accurate for all cases. For now, use this tag type */
+ current->name.other.data[0] = (char)(((current->type - 1) & 0x1f)| 0x80);
+ current->name.other.data[1] = (char)strlen (buffer);
+ current->name.other.len = strlen (buffer) + 2;
+ break;
+ }
+
+ case certDirectoryName: {
+ CERTName *directoryName = NULL;
+
+ directoryName = CERT_AsciiToName (buffer);
+ if (!directoryName) {
+ fprintf(stderr, "certutil: improperly formatted name: \"%s\"\n", buffer);
+ break;
+ }
+
+ rv = CERT_CopyName (arena, &current->name.directoryName, directoryName);
+ CERT_DestroyName (directoryName);
+
+ break;
+ }
+ }
+ if (rv != SECSuccess)
+ break;
+ current->l.next = &(namesList->l);
+ current->l.prev = &(tail->l);
+ tail->l.next = &(current->l);
+ tail = current;
+
+ }while (1);
+
+ if (rv != SECSuccess) {
+ PORT_SetError (rv);
+ PORT_ArenaRelease (arena, mark);
+ namesList = NULL;
+ }
+ return (namesList);
+}
+
+static SECStatus
+GetString(PRArenaPool *arena, char *prompt, SECItem *value)
+{
+ char buffer[251];
+
+ value->data = NULL;
+ value->len = 0;
+
+ puts (prompt);
+ gets (buffer);
+ if (strlen (buffer) > 0) {
+ value->data = PORT_ArenaAlloc (arena, strlen (buffer));
+ if (value->data == NULL) {
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ return (SECFailure);
+ }
+ PORT_Memcpy (value->data, buffer, value->len = strlen(buffer));
+ }
+ return (SECSuccess);
+}
+
+static CERTCertificateRequest *
+GetCertRequest(PRFileDesc *inFile, PRBool ascii)
+{
+ CERTCertificateRequest *certReq = NULL;
+ CERTSignedData signedData;
+ PRArenaPool *arena = NULL;
+ SECItem reqDER;
+ SECStatus rv;
+
+ reqDER.data = NULL;
+ do {
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ GEN_BREAK (SECFailure);
+ }
+
+ rv = SECU_ReadDERFromFile(&reqDER, inFile, ascii);
+ if (rv)
+ break;
+ certReq = (CERTCertificateRequest*) PORT_ArenaZAlloc
+ (arena, sizeof(CERTCertificateRequest));
+ if (!certReq)
+ break;
+ certReq->arena = arena;
+
+ /* Since cert request is a signed data, must decode to get the inner
+ data
+ */
+ PORT_Memset(&signedData, 0, sizeof(signedData));
+ rv = SEC_ASN1DecodeItem(arena, &signedData,
+ SEC_ASN1_GET(CERT_SignedDataTemplate), &reqDER);
+ if (rv)
+ break;
+
+ rv = SEC_ASN1DecodeItem(arena, certReq,
+ SEC_ASN1_GET(CERT_CertificateRequestTemplate), &signedData.data);
+ } while (0);
+
+ if (!rv) {
+ rv = CERT_VerifySignedDataWithPublicKeyInfo(&signedData,
+ &certReq->subjectPublicKeyInfo, NULL /* wincx */);
+ }
+
+ if (rv) {
+ PRErrorCode perr = PR_GetError();
+ fprintf(stderr, "%s: unable to decode DER cert request (%s)\n", progName,
+ SECU_Strerror(perr));
+ }
+ return (certReq);
+}
+
+static PRBool
+GetYesNo(char *prompt)
+{
+ char buf[3];
+
+ PR_Sync(PR_STDIN);
+ PR_Write(PR_STDOUT, prompt, strlen(prompt)+1);
+ PR_Read(PR_STDIN, buf, sizeof(buf));
+ return (buf[0] == 'y' || buf[0] == 'Y') ? PR_TRUE : PR_FALSE;
+#if 0
+ char charValue;
+
+ puts (prompt);
+ scanf ("%c", &charValue);
+ if (charValue != 'y' && charValue != 'Y')
+ return (0);
+ return (1);
+#endif
+}
+
+static SECStatus
+AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts,
+ PRFileDesc *inFile, PRBool ascii, PRBool emailcert, void *pwdata)
+{
+ CERTCertTrust *trust = NULL;
+ CERTCertificate *cert = NULL, *tempCert = NULL;
+ SECItem certDER;
+ SECStatus rv;
+
+ certDER.data = NULL;
+ do {
+ /* Read in the entire file specified with the -i argument */
+ rv = SECU_ReadDERFromFile(&certDER, inFile, ascii);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to read input file");
+ break;
+ }
+
+ /* Read in an ASCII cert and return a CERTCertificate */
+ cert = CERT_DecodeCertFromPackage((char *)certDER.data, certDER.len);
+ if (!cert) {
+ SECU_PrintError(progName, "could not obtain certificate from file");
+ GEN_BREAK(SECFailure);
+ }
+
+ /* Create a cert trust to pass to SEC_AddPermCertificate */
+ trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust));
+ if (!trust) {
+ SECU_PrintError(progName, "unable to allocate cert trust");
+ GEN_BREAK(SECFailure);
+ }
+
+ rv = CERT_DecodeTrustString(trust, trusts);
+ if (rv) {
+ SECU_PrintError(progName, "unable to decode trust string");
+ GEN_BREAK(SECFailure);
+ }
+
+ if (!PK11_IsFriendly(slot)) {
+ rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "could not authenticate to token or database");
+ GEN_BREAK(SECFailure);
+ }
+ }
+
+ rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "could not add certificate to token or database");
+ GEN_BREAK(SECFailure);
+ }
+
+ rv = CERT_ChangeCertTrust(handle, cert, trust);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "could not change trust on certificate");
+ GEN_BREAK(SECFailure);
+ }
+
+ if ( emailcert ) {
+ CERT_SaveSMimeProfile(cert, NULL, pwdata);
+ }
+
+ } while (0);
+
+ CERT_DestroyCertificate (cert);
+ PORT_Free(trust);
+ PORT_Free(certDER.data);
+
+ return rv;
+}
+
+/* This function belongs in libNSS somewhere. */
+static SECOidTag
+getSignatureOidTag(KeyType keyType, SECOidTag hashAlgTag)
+{
+ SECOidTag sigTag = SEC_OID_UNKNOWN;
+
+ switch (keyType) {
+ case rsaKey:
+ switch (hashAlgTag) {
+ case SEC_OID_MD2:
+ sigTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION; break;
+ case SEC_OID_UNKNOWN: /* default for RSA if not specified */
+ case SEC_OID_MD5:
+ sigTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; break;
+ case SEC_OID_SHA1:
+ sigTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; break;
+ case SEC_OID_SHA256:
+ sigTag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; break;
+ case SEC_OID_SHA384:
+ sigTag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; break;
+ case SEC_OID_SHA512:
+ sigTag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; break;
+ default:
+ break;
+ }
+ break;
+ case dsaKey:
+ switch (hashAlgTag) {
+ case SEC_OID_UNKNOWN: /* default for DSA if not specified */
+ case SEC_OID_SHA1:
+ sigTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return sigTag;
+}
+
+static SECStatus
+CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
+ SECOidTag hashAlgTag, CERTName *subject, char *phone, int ascii,
+ const char *emailAddrs, const char *dnsNames, PRFileDesc *outFile)
+{
+ CERTSubjectPublicKeyInfo *spki;
+ CERTCertificateRequest *cr;
+ SECItem *encoding;
+ SECOidTag signAlgTag;
+ SECItem result;
+ SECStatus rv;
+ PRArenaPool *arena;
+ PRInt32 numBytes;
+
+ /* Create info about public key */
+ spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
+ if (!spki) {
+ SECU_PrintError(progName, "unable to create subject public key");
+ return SECFailure;
+ }
+
+ /* Generate certificate request */
+ cr = CERT_CreateCertificateRequest(subject, spki, 0);
+ if (!cr) {
+ SECU_PrintError(progName, "unable to make certificate request");
+ return SECFailure;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( !arena ) {
+ SECU_PrintError(progName, "out of memory");
+ return SECFailure;
+ }
+
+ /* Der encode the request */
+ encoding = SEC_ASN1EncodeItem(arena, NULL, cr,
+ SEC_ASN1_GET(CERT_CertificateRequestTemplate));
+ if (encoding == NULL) {
+ SECU_PrintError(progName, "der encoding of request failed");
+ return SECFailure;
+ }
+
+ /* Sign the request */
+ signAlgTag = getSignatureOidTag(keyType, hashAlgTag);
+ if (signAlgTag == SEC_OID_UNKNOWN) {
+ SECU_PrintError(progName, "unknown Key or Hash type");
+ return SECFailure;
+ }
+ rv = SEC_DerSignData(arena, &result, encoding->data, encoding->len,
+ privk, signAlgTag);
+ if (rv) {
+ SECU_PrintError(progName, "signing of data failed");
+ return SECFailure;
+ }
+
+ /* Encode request in specified format */
+ if (ascii) {
+ char *obuf;
+ char *name, *email, *org, *state, *country;
+ SECItem *it;
+ int total;
+
+ it = &result;
+
+ obuf = BTOA_ConvertItemToAscii(it);
+ total = PL_strlen(obuf);
+
+ name = CERT_GetCommonName(subject);
+ if (!name) {
+ fprintf(stderr, "You must specify a common name\n");
+ return SECFailure;
+ }
+
+ if (!phone)
+ phone = strdup("(not specified)");
+
+ email = CERT_GetCertEmailAddress(subject);
+ if (!email)
+ email = strdup("(not specified)");
+
+ org = CERT_GetOrgName(subject);
+ if (!org)
+ org = strdup("(not specified)");
+
+ state = CERT_GetStateName(subject);
+ if (!state)
+ state = strdup("(not specified)");
+
+ country = CERT_GetCountryName(subject);
+ if (!country)
+ country = strdup("(not specified)");
+
+ PR_fprintf(outFile,
+ "\nCertificate request generated by Netscape certutil\n");
+ PR_fprintf(outFile, "Phone: %s\n\n", phone);
+ PR_fprintf(outFile, "Common Name: %s\n", name);
+ PR_fprintf(outFile, "Email: %s\n", email);
+ PR_fprintf(outFile, "Organization: %s\n", org);
+ PR_fprintf(outFile, "State: %s\n", state);
+ PR_fprintf(outFile, "Country: %s\n\n", country);
+
+ PR_fprintf(outFile, "%s\n", NS_CERTREQ_HEADER);
+ numBytes = PR_Write(outFile, obuf, total);
+ if (numBytes != total) {
+ SECU_PrintSystemError(progName, "write error");
+ return SECFailure;
+ }
+ PR_fprintf(outFile, "\n%s\n", NS_CERTREQ_TRAILER);
+ } else {
+ numBytes = PR_Write(outFile, result.data, result.len);
+ if (numBytes != (int)result.len) {
+ SECU_PrintSystemError(progName, "write error");
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+ChangeTrustAttributes(CERTCertDBHandle *handle, char *name, char *trusts)
+{
+ SECStatus rv;
+ CERTCertificate *cert;
+ CERTCertTrust *trust;
+
+ cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
+ if (!cert) {
+ SECU_PrintError(progName, "could not find certificate named \"%s\"",
+ name);
+ return SECFailure;
+ }
+
+ trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust));
+ if (!trust) {
+ SECU_PrintError(progName, "unable to allocate cert trust");
+ return SECFailure;
+ }
+
+ /* This function only decodes these characters: pPwcTCu, */
+ rv = CERT_DecodeTrustString(trust, trusts);
+ if (rv) {
+ SECU_PrintError(progName, "unable to decode trust string");
+ return SECFailure;
+ }
+
+ rv = CERT_ChangeCertTrust(handle, cert, trust);
+ if (rv) {
+ SECU_PrintError(progName, "unable to modify trust attributes");
+ return SECFailure;
+ }
+ CERT_DestroyCertificate(cert);
+
+ return SECSuccess;
+}
+
+static SECStatus
+printCertCB(CERTCertificate *cert, void *arg)
+{
+ SECStatus rv;
+ SECItem data;
+ CERTCertTrust *trust = (CERTCertTrust *)arg;
+
+ data.data = cert->derCert.data;
+ data.len = cert->derCert.len;
+
+ rv = SECU_PrintSignedData(stdout, &data, "Certificate", 0,
+ SECU_PrintCertificate);
+ if (rv) {
+ SECU_PrintError(progName, "problem printing certificate");
+ return(SECFailure);
+ }
+ if (trust) {
+ SECU_PrintTrustFlags(stdout, trust,
+ "Certificate Trust Flags", 1);
+ } else if (cert->trust) {
+ SECU_PrintTrustFlags(stdout, cert->trust,
+ "Certificate Trust Flags", 1);
+ }
+
+ printf("\n");
+
+ return(SECSuccess);
+}
+
+static SECStatus
+DumpChain(CERTCertDBHandle *handle, char *name)
+{
+ CERTCertificate *the_cert;
+ CERTCertificateList *chain;
+ int i, j;
+ the_cert = PK11_FindCertFromNickname(name, NULL);
+ if (!the_cert) {
+ SECU_PrintError(progName, "Could not find: %s\n", name);
+ return SECFailure;
+ }
+ chain = CERT_CertChainFromCert(the_cert, 0, PR_TRUE);
+ CERT_DestroyCertificate(the_cert);
+ if (!chain) {
+ SECU_PrintError(progName, "Could not obtain chain for: %s\n", name);
+ return SECFailure;
+ }
+ for (i=chain->len-1; i>=0; i--) {
+ CERTCertificate *c;
+ c = CERT_FindCertByDERCert(handle, &chain->certs[i]);
+ for (j=i; j<chain->len-1; j++) printf(" ");
+ printf("\"%s\" [%s]\n\n", c->nickname, c->subjectName);
+ CERT_DestroyCertificate(c);
+ }
+ CERT_DestroyCertificateList(chain);
+ return SECSuccess;
+}
+
+static SECStatus
+listCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot,
+ PRBool raw, PRBool ascii, PRFileDesc *outfile, void *pwarg)
+{
+ SECItem data;
+ PRInt32 numBytes;
+ SECStatus rv = SECFailure;
+ CERTCertList *certs;
+ CERTCertListNode *node;
+
+ /* List certs on a non-internal slot. */
+ if (!PK11_IsFriendly(slot) && PK11_NeedLogin(slot))
+ PK11_Authenticate(slot, PR_TRUE, pwarg);
+ if (name) {
+ CERTCertificate *the_cert;
+ the_cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
+ if (!the_cert) {
+ the_cert = PK11_FindCertFromNickname(name, NULL);
+ if (!the_cert) {
+ SECU_PrintError(progName, "Could not find: %s\n", name);
+ return SECFailure;
+ }
+ }
+ certs = CERT_CreateSubjectCertList(NULL, handle, &the_cert->derSubject,
+ PR_Now(), PR_FALSE);
+ CERT_DestroyCertificate(the_cert);
+
+ for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
+ node = CERT_LIST_NEXT(node)) {
+ the_cert = node->cert;
+ /* now get the subjectList that matches this cert */
+ data.data = the_cert->derCert.data;
+ data.len = the_cert->derCert.len;
+ if (ascii) {
+ PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER,
+ BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
+ rv = SECSuccess;
+ } else if (raw) {
+ numBytes = PR_Write(outfile, data.data, data.len);
+ if (numBytes != data.len) {
+ SECU_PrintSystemError(progName, "error writing raw cert");
+ rv = SECFailure;
+ }
+ rv = SECSuccess;
+ } else {
+ rv = printCertCB(the_cert, the_cert->trust);
+ }
+ if (rv != SECSuccess) {
+ break;
+ }
+ }
+ } else {
+
+ certs = PK11_ListCertsInSlot(slot);
+ if (certs) {
+ for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
+ node = CERT_LIST_NEXT(node)) {
+ SECU_PrintCertNickname(node->cert,stdout);
+ }
+ rv = SECSuccess;
+ }
+ }
+ CERT_DestroyCertList(certs);
+ if (rv) {
+ SECU_PrintError(progName, "problem printing certificate nicknames");
+ return SECFailure;
+ }
+
+ return SECSuccess; /* not rv ?? */
+}
+
+static SECStatus
+ListCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot,
+ PRBool raw, PRBool ascii, PRFileDesc *outfile, secuPWData *pwdata)
+{
+ SECStatus rv;
+
+ if (slot == NULL) {
+ CERTCertList *list;
+ CERTCertListNode *node;
+
+ list = PK11_ListCerts(PK11CertListUnique, pwdata);
+ for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
+ node = CERT_LIST_NEXT(node))
+ {
+ SECU_PrintCertNickname(node->cert, stdout);
+ }
+ CERT_DestroyCertList(list);
+ return SECSuccess;
+ } else {
+ rv = listCerts(handle,name,slot,raw,ascii,outfile,pwdata);
+ }
+ return rv;
+}
+
+static SECStatus
+DeleteCert(CERTCertDBHandle *handle, char *name)
+{
+ SECStatus rv;
+ CERTCertificate *cert;
+
+ cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
+ if (!cert) {
+ SECU_PrintError(progName, "could not find certificate named \"%s\"",
+ name);
+ return SECFailure;
+ }
+
+ rv = SEC_DeletePermCertificate(cert);
+ CERT_DestroyCertificate(cert);
+ if (rv) {
+ SECU_PrintError(progName, "unable to delete certificate");
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+static SECStatus
+ValidateCert(CERTCertDBHandle *handle, char *name, char *date,
+ char *certUsage, PRBool checkSig, PRBool logit, secuPWData *pwdata)
+{
+ SECStatus rv;
+ CERTCertificate *cert = NULL;
+ int64 timeBoundary;
+ SECCertificateUsage usage;
+ CERTVerifyLog reallog;
+ CERTVerifyLog *log = NULL;
+
+ switch (*certUsage) {
+ case 'C':
+ usage = certificateUsageSSLClient;
+ break;
+ case 'V':
+ usage = certificateUsageSSLServer;
+ break;
+ case 'S':
+ usage = certificateUsageEmailSigner;
+ break;
+ case 'R':
+ usage = certificateUsageEmailRecipient;
+ break;
+ default:
+ PORT_SetError (SEC_ERROR_INVALID_ARGS);
+ return (SECFailure);
+ }
+ do {
+ cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
+ if (!cert) {
+ SECU_PrintError(progName, "could not find certificate named \"%s\"",
+ name);
+ GEN_BREAK (SECFailure)
+ }
+
+ if (date != NULL) {
+ rv = DER_AsciiToTime(&timeBoundary, date);
+ if (rv) {
+ SECU_PrintError(progName, "invalid input date");
+ GEN_BREAK (SECFailure)
+ }
+ } else {
+ timeBoundary = PR_Now();
+ }
+
+ if ( logit ) {
+ log = &reallog;
+
+ log->count = 0;
+ log->head = NULL;
+ log->tail = NULL;
+ log->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( log->arena == NULL ) {
+ SECU_PrintError(progName, "out of memory");
+ GEN_BREAK (SECFailure)
+ }
+ }
+
+ rv = CERT_VerifyCertificate(handle, cert, checkSig, usage,
+ timeBoundary, pwdata, log, &usage);
+ if ( log ) {
+ if ( log->head == NULL ) {
+ fprintf(stdout, "%s: certificate is valid\n", progName);
+ GEN_BREAK (SECSuccess)
+ } else {
+ char *name;
+ CERTVerifyLogNode *node;
+
+ node = log->head;
+ while ( node ) {
+ if ( node->cert->nickname != NULL ) {
+ name = node->cert->nickname;
+ } else {
+ name = node->cert->subjectName;
+ }
+ fprintf(stderr, "%s : %s\n", name,
+ SECU_Strerror(node->error));
+ CERT_DestroyCertificate(node->cert);
+ node = node->next;
+ }
+ }
+ } else {
+ if (rv != SECSuccess) {
+ PRErrorCode perr = PORT_GetError();
+ fprintf(stdout, "%s: certificate is invalid: %s\n",
+ progName, SECU_Strerror(perr));
+ GEN_BREAK (SECFailure)
+ }
+ fprintf(stdout, "%s: certificate is valid\n", progName);
+ GEN_BREAK (SECSuccess)
+ }
+ } while (0);
+
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+
+ return (rv);
+}
+
+
+static SECStatus
+printKeyCB(SECKEYPublicKey *key, SECItem *data, void *arg)
+{
+ if (key->keyType == rsaKey) {
+ fprintf(stdout, "RSA Public-Key:\n");
+ SECU_PrintInteger(stdout, &key->u.rsa.modulus, "modulus", 1);
+ } else {
+ fprintf(stdout, "DSA Public-Key:\n");
+ SECU_PrintInteger(stdout, &key->u.dsa.publicValue, "publicValue", 1);
+ }
+ return SECSuccess;
+}
+
+/* callback for listing certs through pkcs11 */
+static SECStatus
+secu_PrintKey(FILE *out, int count, SECKEYPrivateKey *key)
+{
+ char *name;
+
+ name = PK11_GetPrivateKeyNickname(key);
+ if (name == NULL) {
+ /* should look up associated cert */
+ name = PORT_Strdup("< orphaned >");
+ }
+ fprintf(out, "<%d> %s\n", count, name);
+ PORT_Free(name);
+
+ return SECSuccess;
+}
+
+static SECStatus
+listKeys(PK11SlotInfo *slot, KeyType keyType, void *pwarg)
+{
+ SECKEYPrivateKeyList *list;
+ SECKEYPrivateKeyListNode *node;
+ int count;
+
+ if (PK11_NeedLogin(slot))
+ PK11_Authenticate(slot, PR_TRUE, pwarg);
+
+ list = PK11_ListPrivateKeysInSlot(slot);
+ if (list == NULL) {
+ SECU_PrintError(progName, "problem listing keys");
+ return SECFailure;
+ }
+ for (count=0, node=PRIVKEY_LIST_HEAD(list) ; !PRIVKEY_LIST_END(node,list);
+ node= PRIVKEY_LIST_NEXT(node),count++) {
+ secu_PrintKey(stdout, count, node->key);
+ }
+ SECKEY_DestroyPrivateKeyList(list);
+
+ if (count == 0) {
+ fprintf(stderr, "%s: no keys found\n", progName);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+ListKeys(PK11SlotInfo *slot, char *keyname, int index,
+ KeyType keyType, PRBool dopriv, secuPWData *pwdata)
+{
+ SECStatus rv = SECSuccess;
+
+ if (slot == NULL) {
+ PK11SlotList *list;
+ PK11SlotListElement *le;
+
+ list= PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,pwdata);
+ if (list) for (le = list->head; le; le = le->next) {
+ rv = listKeys(le->slot,keyType,pwdata);
+ }
+ } else {
+ rv = listKeys(slot,keyType,pwdata);
+ }
+ return rv;
+}
+
+static SECStatus
+DeleteKey(char *nickname, secuPWData *pwdata)
+{
+ SECStatus rv;
+ CERTCertificate *cert;
+ PK11SlotInfo *slot;
+
+ slot = PK11_GetInternalKeySlot();
+ if (PK11_NeedLogin(slot))
+ PK11_Authenticate(slot, PR_TRUE, pwdata);
+ cert = PK11_FindCertFromNickname(nickname, pwdata);
+ if (!cert) {
+ PK11_FreeSlot(slot);
+ return SECFailure;
+ }
+ rv = PK11_DeleteTokenCertAndKey(cert, pwdata);
+ if (rv != SECSuccess) {
+ SECU_PrintError("problem deleting private key \"%s\"\n", nickname);
+ }
+ CERT_DestroyCertificate(cert);
+ PK11_FreeSlot(slot);
+ return rv;
+}
+
+
+/*
+ * L i s t M o d u l e s
+ *
+ * Print a list of the PKCS11 modules that are
+ * available. This is useful for smartcard people to
+ * make sure they have the drivers loaded.
+ *
+ */
+static SECStatus
+ListModules(void)
+{
+ PK11SlotList *list;
+ PK11SlotListElement *le;
+
+ /* get them all! */
+ list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,NULL);
+ if (list == NULL) return SECFailure;
+
+ /* look at each slot*/
+ for (le = list->head ; le; le = le->next) {
+ printf ("\n");
+ printf (" slot: %s\n", PK11_GetSlotName(le->slot));
+ printf (" token: %s\n", PK11_GetTokenName(le->slot));
+ }
+ PK11_FreeSlotList(list);
+
+ return SECSuccess;
+}
+
+static void
+Usage(char *progName)
+{
+#define FPS fprintf(stderr,
+ FPS "Type %s -H for more detailed descriptions\n", progName);
+ FPS "Usage: %s -N [-d certdir] [-P dbprefix] [-f pwfile]\n", progName);
+ FPS "Usage: %s -T [-d certdir] [-P dbprefix] [-h token-name] [-f pwfile]\n", progName);
+ FPS "\t%s -A -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n",
+ progName);
+ FPS "\t%s -C [-c issuer-name | -x] -i cert-request-file -o cert-file\n"
+ "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
+ "\t\t [-f pwfile] [-d certdir] [-P dbprefix] [-1] [-2] [-3] [-4] [-5]\n"
+ "\t\t [-6] [-7 emailAddrs] [-8 dns-names]\n",
+ progName);
+ FPS "\t%s -D -n cert-name [-d certdir] [-P dbprefix]\n", progName);
+ FPS "\t%s -E -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n",
+ progName);
+ FPS "\t%s -G -n key-name [-h token-name] [-k rsa] [-g key-size] [-y exp]\n"
+ "\t\t [-f pwfile] [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
+ FPS "\t%s -G [-h token-name] -k dsa [-q pqgfile -g key-size] [-f pwfile]\n"
+ "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
+ FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|rsa|all]\n",
+ progName);
+ FPS "\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n");
+ FPS "\t%s -L [-n cert-name] [-X] [-d certdir] [-P dbprefix] [-r] [-a]\n", progName);
+ FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n",
+ progName);
+ FPS "\t%s -O -n cert-name [-X] [-d certdir] [-P dbprefix]\n", progName);
+ FPS "\t%s -R -s subj -o cert-request-file [-d certdir] [-P dbprefix] [-p phone] [-a]\n"
+ "\t\t [-y emailAddrs] [-k key-type] [-h token-name] [-f pwfile] [-g key-size]\n",
+ progName);
+ FPS "\t%s -V -n cert-name -u usage [-b time] [-e] \n"
+ "\t\t[-X] [-d certdir] [-P dbprefix]\n",
+ progName);
+ FPS "\t%s -S -n cert-name -s subj [-c issuer-name | -x] -t trustargs\n"
+ "\t\t [-k key-type] [-h token-name] [-g key-size]\n"
+ "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
+ "\t\t [-f pwfile] [-d certdir] [-P dbprefix]\n"
+ "\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n"
+ "\t\t [-8 dns-names]\n",
+ progName);
+ FPS "\t%s -U [-X] [-d certdir] [-P dbprefix]\n", progName);
+ exit(1);
+}
+
+static void LongUsage(char *progName)
+{
+
+ FPS "%-15s Add a certificate to the database (create if needed)\n",
+ "-A");
+ FPS "%-15s Add an Email certificate to the database (create if needed)\n",
+ "-E");
+ FPS "%-20s Specify the nickname of the certificate to add\n",
+ " -n cert-name");
+ FPS "%-20s Set the certificate trust attributes:\n",
+ " -t trustargs");
+ FPS "%-25s p \t valid peer\n", "");
+ FPS "%-25s P \t trusted peer (implies p)\n", "");
+ FPS "%-25s c \t valid CA\n", "");
+ FPS "%-25s T \t trusted CA to issue client certs (implies c)\n", "");
+ FPS "%-25s C \t trusted CA to issue server certs (implies c)\n", "");
+ FPS "%-25s u \t user cert\n", "");
+ FPS "%-25s w \t send warning\n", "");
+#ifdef DEBUG_NSSTEAM_ONLY
+ FPS "%-25s g \t make step-up cert\n", "");
+#endif /* DEBUG_NSSTEAM_ONLY */
+ FPS "%-20s Specify the password file\n",
+ " -f pwfile");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s The input certificate is encoded in ASCII (RFC1113)\n",
+ " -a");
+ FPS "%-20s Specify the certificate file (default is stdin)\n",
+ " -i input");
+ FPS "\n");
+
+ FPS "%-15s Create a new binary certificate from a BINARY cert request\n",
+ "-C");
+ FPS "%-20s The nickname of the issuer cert\n",
+ " -c issuer-name");
+ FPS "%-20s The BINARY certificate request file\n",
+ " -i cert-request ");
+ FPS "%-20s Output binary cert to this file (default is stdout)\n",
+ " -o output-cert");
+ FPS "%-20s Self sign\n",
+ " -x");
+ FPS "%-20s Cert serial number\n",
+ " -m serial-number");
+ FPS "%-20s Time Warp\n",
+ " -w warp-months");
+ FPS "%-20s Months valid (default is 3)\n",
+ " -v months-valid");
+ FPS "%-20s Specify the password file\n",
+ " -f pwfile");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s Create key usage extension\n",
+ " -1 ");
+ FPS "%-20s Create basic constraint extension\n",
+ " -2 ");
+ FPS "%-20s Create authority key ID extension\n",
+ " -3 ");
+ FPS "%-20s Create crl distribution point extension\n",
+ " -4 ");
+ FPS "%-20s Create netscape cert type extension\n",
+ " -5 ");
+ FPS "%-20s Create extended key usage extension\n",
+ " -6 ");
+ FPS "%-20s Create an email subject alt name extension\n",
+ " -7 ");
+ FPS "%-20s Create an dns subject alt name extension\n",
+ " -8 ");
+ FPS "\n");
+
+ FPS "%-15s Generate a new key pair\n",
+ "-G");
+ FPS "%-20s Name of token in which to generate key (default is internal)\n",
+ " -h token-name");
+ FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
+ " -k key-type");
+ FPS "%-20s Key size in bits, (min %d, max %d, default %d)\n",
+ " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
+ FPS "%-20s Set the public exponent value (3, 17, 65537) (rsa only)\n",
+ " -y exp");
+ FPS "%-20s Specify the password file\n",
+ " -f password-file");
+ FPS "%-20s Specify the noise file to be used\n",
+ " -z noisefile");
+ FPS "%-20s read PQG value from pqgfile (dsa only)\n",
+ " -q pqgfile");
+ FPS "%-20s Key database directory (default is ~/.netscape)\n",
+ " -d keydir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "\n");
+
+ FPS "%-15s Delete a certificate from the database\n",
+ "-D");
+ FPS "%-20s The nickname of the cert to delete\n",
+ " -n cert-name");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "\n");
+
+ FPS "%-15s List all modules\n", /*, or print out a single named module\n",*/
+ "-U");
+ FPS "%-20s Module database directory (default is '~/.netscape')\n",
+ " -d moddir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s force the database to open R/W\n",
+ " -X");
+ FPS "\n");
+
+ FPS "%-15s List all keys\n", /*, or print out a single named key\n",*/
+ "-K");
+ FPS "%-20s Name of token in which to look for keys (default is internal,"
+ " use \"all\" to list keys on all tokens)\n",
+ " -h token-name ");
+ FPS "%-20s Type of key pair to list (\"all\", \"dsa\", \"rsa\" (default))\n",
+ " -k key-type");
+ FPS "%-20s Specify the password file\n",
+ " -f password-file");
+ FPS "%-20s Key database directory (default is ~/.netscape)\n",
+ " -d keydir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s force the database to open R/W\n",
+ " -X");
+ FPS "\n");
+
+ FPS "%-15s List all certs, or print out a single named cert\n",
+ "-L");
+ FPS "%-20s Pretty print named cert (list all if unspecified)\n",
+ " -n cert-name");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s force the database to open R/W\n",
+ " -X");
+ FPS "%-20s For single cert, print binary DER encoding\n",
+ " -r");
+ FPS "%-20s For single cert, print ASCII encoding (RFC1113)\n",
+ " -a");
+ FPS "\n");
+
+ FPS "%-15s Modify trust attributes of certificate\n",
+ "-M");
+ FPS "%-20s The nickname of the cert to modify\n",
+ " -n cert-name");
+ FPS "%-20s Set the certificate trust attributes (see -A above)\n",
+ " -t trustargs");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "\n");
+
+ FPS "%-15s Create a new certificate database\n",
+ "-N");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "\n");
+ FPS "%-15s Reset the Key database or token\n",
+ "-T");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s Token to reset (default is internal)\n",
+ " -h token-name");
+ FPS "\n");
+
+ FPS "\n");
+ FPS "%-15s Print the chain of a certificate\n",
+ "-O");
+ FPS "%-20s The nickname of the cert to modify\n",
+ " -n cert-name");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s force the database to open R/W\n",
+ " -X");
+ FPS "\n");
+
+ FPS "%-15s Generate a certificate request (stdout)\n",
+ "-R");
+ FPS "%-20s Specify the subject name (using RFC1485)\n",
+ " -s subject");
+ FPS "%-20s Output the cert request to this file\n",
+ " -o output-req");
+ FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
+ " -k key-type");
+ FPS "%-20s Name of token in which to generate key (default is internal)\n",
+ " -h token-name");
+ FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
+ " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
+ FPS "%-20s Specify the password file\n",
+ " -f pwfile");
+ FPS "%-20s Key database directory (default is ~/.netscape)\n",
+ " -d keydir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
+ " -p phone");
+ FPS "%-20s Output the cert request in ASCII (RFC1113); default is binary\n",
+ " -a");
+ FPS "\n");
+
+ FPS "%-15s Validate a certificate\n",
+ "-V");
+ FPS "%-20s The nickname of the cert to Validate\n",
+ " -n cert-name");
+ FPS "%-20s validity time (\"YYMMDDHHMMSS[+HHMM|-HHMM|Z]\")\n",
+ " -b time");
+ FPS "%-20s Check certificate signature \n",
+ " -e ");
+ FPS "%-20s Specify certificate usage:\n", " -u certusage");
+ FPS "%-25s C \t SSL Client\n", "");
+ FPS "%-25s V \t SSL Server\n", "");
+ FPS "%-25s S \t Email signer\n", "");
+ FPS "%-25s R \t Email Recipient\n", "");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s force the database to open R/W\n",
+ " -X");
+ FPS "\n");
+
+ FPS "%-15s Make a certificate and add to database\n",
+ "-S");
+ FPS "%-20s Specify the nickname of the cert\n",
+ " -n key-name");
+ FPS "%-20s Specify the subject name (using RFC1485)\n",
+ " -s subject");
+ FPS "%-20s The nickname of the issuer cert\n",
+ " -c issuer-name");
+ FPS "%-20s Set the certificate trust attributes (see -A above)\n",
+ " -t trustargs");
+ FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
+ " -k key-type");
+ FPS "%-20s Name of token in which to generate key (default is internal)\n",
+ " -h token-name");
+ FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
+ " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
+ FPS "%-20s Self sign\n",
+ " -x");
+ FPS "%-20s Cert serial number\n",
+ " -m serial-number");
+ FPS "%-20s Time Warp\n",
+ " -w warp-months");
+ FPS "%-20s Months valid (default is 3)\n",
+ " -v months-valid");
+ FPS "%-20s Specify the password file\n",
+ " -f pwfile");
+ FPS "%-20s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-20s Cert & Key database prefix\n",
+ " -P dbprefix");
+ FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
+ " -p phone");
+ FPS "%-20s Create key usage extension\n",
+ " -1 ");
+ FPS "%-20s Create basic constraint extension\n",
+ " -2 ");
+ FPS "%-20s Create authority key ID extension\n",
+ " -3 ");
+ FPS "%-20s Create crl distribution point extension\n",
+ " -4 ");
+ FPS "%-20s Create netscape cert type extension\n",
+ " -5 ");
+ FPS "%-20s Create extended key usage extension\n",
+ " -6 ");
+ FPS "%-20s Create an email subject alt name extension\n",
+ " -7 ");
+ FPS "%-20s Create an dns subject alt name extension\n",
+ " -8 ");
+ FPS "\n");
+
+ exit(1);
+#undef FPS
+}
+
+
+static CERTCertificate *
+MakeV1Cert( CERTCertDBHandle * handle,
+ CERTCertificateRequest *req,
+ char * issuerNickName,
+ PRBool selfsign,
+ unsigned int serialNumber,
+ int warpmonths,
+ int validitylength)
+{
+ CERTCertificate *issuerCert = NULL;
+ CERTValidity *validity;
+ CERTCertificate *cert = NULL;
+ PRExplodedTime printableTime;
+ PRTime now, after;
+
+ if ( !selfsign ) {
+ issuerCert = CERT_FindCertByNicknameOrEmailAddr(handle, issuerNickName);
+ if (!issuerCert) {
+ SECU_PrintError(progName, "could not find certificate named \"%s\"",
+ issuerNickName);
+ return NULL;
+ }
+ }
+
+ now = PR_Now();
+ PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
+ if ( warpmonths ) {
+ printableTime.tm_month += warpmonths;
+ now = PR_ImplodeTime (&printableTime);
+ PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
+ }
+ printableTime.tm_month += validitylength;
+ printableTime.tm_month += 3;
+ after = PR_ImplodeTime (&printableTime);
+
+ /* note that the time is now in micro-second unit */
+ validity = CERT_CreateValidity (now, after);
+
+ cert = CERT_CreateCertificate(serialNumber,
+ (selfsign ? &req->subject
+ : &issuerCert->subject),
+ validity, req);
+
+ CERT_DestroyValidity(validity);
+ if ( issuerCert ) {
+ CERT_DestroyCertificate (issuerCert);
+ }
+
+ return(cert);
+}
+
+static SECStatus
+AddKeyUsage (void *extHandle)
+{
+ SECItem bitStringValue;
+ unsigned char keyUsage = 0x0;
+ char buffer[5];
+ int value;
+
+ while (1) {
+ fprintf(stdout, "%-25s 0 - Digital Signature\n", "");
+ fprintf(stdout, "%-25s 1 - Non-repudiation\n", "");
+ fprintf(stdout, "%-25s 2 - Key encipherment\n", "");
+ fprintf(stdout, "%-25s 3 - Data encipherment\n", "");
+ fprintf(stdout, "%-25s 4 - Key agreement\n", "");
+ fprintf(stdout, "%-25s 5 - Cert signing key\n", "");
+ fprintf(stdout, "%-25s 6 - CRL signing key\n", "");
+ fprintf(stdout, "%-25s Other to finish\n", "");
+ if (gets (buffer)) {
+ value = atoi (buffer);
+ if (value < 0 || value > 6)
+ break;
+ keyUsage |= (0x80 >> value);
+ }
+ else { /* gets() returns NULL on EOF or error */
+ break;
+ }
+ }
+
+ bitStringValue.data = &keyUsage;
+ bitStringValue.len = 1;
+ buffer[0] = 'n';
+ puts ("Is this a critical extension [y/n]? ");
+ gets (buffer);
+
+ return (CERT_EncodeAndAddBitStrExtension
+ (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
+ (buffer[0] == 'y' || buffer[0] == 'Y') ? PR_TRUE : PR_FALSE));
+
+}
+
+
+static CERTOidSequence *
+CreateOidSequence(void)
+{
+ CERTOidSequence *rv = (CERTOidSequence *)NULL;
+ PRArenaPool *arena = (PRArenaPool *)NULL;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if( (PRArenaPool *)NULL == arena ) {
+ goto loser;
+ }
+
+ rv = (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence));
+ if( (CERTOidSequence *)NULL == rv ) {
+ goto loser;
+ }
+
+ rv->oids = (SECItem **)PORT_ArenaZAlloc(arena, sizeof(SECItem *));
+ if( (SECItem **)NULL == rv->oids ) {
+ goto loser;
+ }
+
+ rv->arena = arena;
+ return rv;
+
+ loser:
+ if( (PRArenaPool *)NULL != arena ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return (CERTOidSequence *)NULL;
+}
+
+static void
+DestroyOidSequence(CERTOidSequence *os)
+{
+ if (os->arena) {
+ PORT_FreeArena(os->arena, PR_FALSE);
+ }
+}
+
+static SECStatus
+AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
+{
+ SECItem **oids;
+ PRUint32 count = 0;
+ SECOidData *od;
+
+ od = SECOID_FindOIDByTag(oidTag);
+ if( (SECOidData *)NULL == od ) {
+ return SECFailure;
+ }
+
+ for( oids = os->oids; (SECItem *)NULL != *oids; oids++ ) {
+ count++;
+ }
+
+ /* ArenaZRealloc */
+
+ {
+ PRUint32 i;
+
+ oids = (SECItem **)PORT_ArenaZAlloc(os->arena, sizeof(SECItem *) * (count+2));
+ if( (SECItem **)NULL == oids ) {
+ return SECFailure;
+ }
+
+ for( i = 0; i < count; i++ ) {
+ oids[i] = os->oids[i];
+ }
+
+ /* ArenaZFree(os->oids); */
+ }
+
+ os->oids = oids;
+ os->oids[count] = &od->oid;
+
+ return SECSuccess;
+}
+
+SEC_ASN1_MKSUB(SEC_ObjectIDTemplate);
+
+const SEC_ASN1Template CERT_OidSeqTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN,
+ offsetof(CERTOidSequence, oids),
+ SEC_ASN1_SUB(SEC_ObjectIDTemplate) }
+};
+
+
+static SECItem *
+EncodeOidSequence(CERTOidSequence *os)
+{
+ SECItem *rv;
+
+ rv = (SECItem *)PORT_ArenaZAlloc(os->arena, sizeof(SECItem));
+ if( (SECItem *)NULL == rv ) {
+ goto loser;
+ }
+
+ if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) {
+ goto loser;
+ }
+
+ return rv;
+
+ loser:
+ return (SECItem *)NULL;
+}
+
+static SECStatus
+AddExtKeyUsage (void *extHandle)
+{
+ char buffer[5];
+ int value;
+ CERTOidSequence *os;
+ SECStatus rv;
+ SECItem *item;
+
+ os = CreateOidSequence();
+ if( (CERTOidSequence *)NULL == os ) {
+ return SECFailure;
+ }
+
+ while (1) {
+ fprintf(stdout, "%-25s 0 - Server Auth\n", "");
+ fprintf(stdout, "%-25s 1 - Client Auth\n", "");
+ fprintf(stdout, "%-25s 2 - Code Signing\n", "");
+ fprintf(stdout, "%-25s 3 - Email Protection\n", "");
+ fprintf(stdout, "%-25s 4 - Timestamp\n", "");
+ fprintf(stdout, "%-25s 5 - OCSP Responder\n", "");
+#ifdef DEBUG_NSSTEAM_ONLY
+ fprintf(stdout, "%-25s 6 - Step-up\n", "");
+#endif /* DEBUG_NSSTEAM_ONLY */
+ fprintf(stdout, "%-25s Other to finish\n", "");
+
+ gets(buffer);
+ value = atoi(buffer);
+
+ switch( value ) {
+ case 0:
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
+ break;
+ case 1:
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
+ break;
+ case 2:
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
+ break;
+ case 3:
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
+ break;
+ case 4:
+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
+ break;
+ case 5:
+ rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
+ break;
+#ifdef DEBUG_NSSTEAM_ONLY
+ case 6:
+ rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
+ break;
+#endif /* DEBUG_NSSTEAM_ONLY */
+ default:
+ goto endloop;
+ }
+
+ if( SECSuccess != rv ) goto loser;
+ }
+
+ endloop:;
+ item = EncodeOidSequence(os);
+
+ buffer[0] = 'n';
+ puts ("Is this a critical extension [y/n]? ");
+ gets (buffer);
+
+ rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, item,
+ ((buffer[0] == 'y' || buffer[0] == 'Y')
+ ? PR_TRUE : PR_FALSE), PR_TRUE);
+ /*FALLTHROUGH*/
+ loser:
+ DestroyOidSequence(os);
+ return rv;
+}
+
+static SECStatus
+AddNscpCertType (void *extHandle)
+{
+ SECItem bitStringValue;
+ unsigned char keyUsage = 0x0;
+ char buffer[5];
+ int value;
+
+ while (1) {
+ fprintf(stdout, "%-25s 0 - SSL Client\n", "");
+ fprintf(stdout, "%-25s 1 - SSL Server\n", "");
+ fprintf(stdout, "%-25s 2 - S/MIME\n", "");
+ fprintf(stdout, "%-25s 3 - Object Signing\n", "");
+ fprintf(stdout, "%-25s 4 - Reserved for futuer use\n", "");
+ fprintf(stdout, "%-25s 5 - SSL CA\n", "");
+ fprintf(stdout, "%-25s 6 - S/MIME CA\n", "");
+ fprintf(stdout, "%-25s 7 - Object Signing CA\n", "");
+ fprintf(stdout, "%-25s Other to finish\n", "");
+ gets (buffer);
+ value = atoi (buffer);
+ if (value < 0 || value > 7)
+ break;
+ keyUsage |= (0x80 >> value);
+ }
+
+ bitStringValue.data = &keyUsage;
+ bitStringValue.len = 1;
+ buffer[0] = 'n';
+ puts ("Is this a critical extension [y/n]? ");
+ gets (buffer);
+
+ return (CERT_EncodeAndAddBitStrExtension
+ (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
+ (buffer[0] == 'y' || buffer[0] == 'Y') ? PR_TRUE : PR_FALSE));
+
+}
+
+static SECStatus
+AddSubjectAltNames(void *extHandle, const char *names, CERTGeneralNameType type)
+{
+ SECItem item = { 0, NULL, 0 };
+ CERTGeneralName *nameList = NULL;
+ CERTGeneralName *current = NULL;
+ PRCList *prev = NULL;
+ PRArenaPool *arena;
+ const char *cp;
+ char *tbuf;
+ SECStatus rv = SECSuccess;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ return SECFailure;
+ }
+
+ /*
+ * walk down the comma separated list of names. NOTE: there is
+ * no sanity checks to see if the email address look like email addresses.
+ */
+ for (cp=names; cp; cp = PORT_Strchr(cp,',')) {
+ int len;
+ char *end;
+
+ if (*cp == ',') {
+ cp++;
+ }
+ end = PORT_Strchr(cp,',');
+ len = end ? end-cp : PORT_Strlen(cp);
+ if (len <= 0) {
+ continue;
+ }
+ tbuf = PORT_ArenaAlloc(arena,len+1);
+ PORT_Memcpy(tbuf,cp,len);
+ tbuf[len] = 0;
+ current = (CERTGeneralName *) PORT_ZAlloc(sizeof(CERTGeneralName));
+ if (!current) {
+ rv = SECFailure;
+ break;
+ }
+ if (prev) {
+ current->l.prev = prev;
+ prev->next = &(current->l);
+ } else {
+ nameList = current;
+ }
+ current->type = type;
+ current->type = certRFC822Name;
+ current->name.other.data = (unsigned char *)tbuf;
+ current->name.other.len = PORT_Strlen(tbuf);
+ prev = &(current->l);
+ }
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ /* no email address */
+ if (!nameList) {
+ /*rv=SECSuccess; We know rv is SECSuccess because of the previous if*/
+ goto done;
+ }
+ nameList->l.prev = prev;
+ current->l.next = &(nameList->l);
+
+ CERT_EncodeAltNameExtension(arena, nameList, &item);
+ rv = CERT_AddExtension (extHandle, SEC_OID_X509_SUBJECT_ALT_NAME, &item,
+ PR_FALSE, PR_TRUE);
+done:
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+
+}
+
+static SECStatus
+AddEmailSubjectAlt(void *extHandle, const char *emailAddrs)
+{
+ return AddSubjectAltNames(extHandle, emailAddrs, certRFC822Name);
+}
+
+static SECStatus
+AddDNSSubjectAlt(void *extHandle, const char *dnsNames)
+{
+ return AddSubjectAltNames(extHandle, dnsNames, certDNSName);
+}
+
+
+typedef SECStatus (* EXTEN_VALUE_ENCODER)
+ (PRArenaPool *extHandle, void *value, SECItem *encodedValue);
+
+static SECStatus
+EncodeAndAddExtensionValue(
+ PRArenaPool * arena,
+ void * extHandle,
+ void * value,
+ PRBool criticality,
+ int extenType,
+ EXTEN_VALUE_ENCODER EncodeValueFn)
+{
+ SECItem encodedValue;
+ SECStatus rv;
+
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+ do {
+ rv = (*EncodeValueFn)(arena, value, &encodedValue);
+ if (rv != SECSuccess)
+ break;
+
+ rv = CERT_AddExtension
+ (extHandle, extenType, &encodedValue, criticality,PR_TRUE);
+ } while (0);
+
+ return (rv);
+}
+
+static SECStatus
+AddBasicConstraint(void *extHandle)
+{
+ CERTBasicConstraints basicConstraint;
+ SECItem encodedValue;
+ SECStatus rv;
+ char buffer[10];
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+ do {
+ basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
+ puts ("Is this a CA certificate [y/n]?");
+ gets (buffer);
+ basicConstraint.isCA = (buffer[0] == 'Y' || buffer[0] == 'y') ?
+ PR_TRUE : PR_FALSE;
+
+ puts ("Enter the path length constraint, enter to skip [<0 for unlimited path]:");
+ gets (buffer);
+ if (PORT_Strlen (buffer) > 0)
+ basicConstraint.pathLenConstraint = atoi (buffer);
+
+ rv = CERT_EncodeBasicConstraintValue (NULL, &basicConstraint, &encodedValue);
+ if (rv)
+ return (rv);
+
+ buffer[0] = 'n';
+ puts ("Is this a critical extension [y/n]? ");
+ gets (buffer);
+ rv = CERT_AddExtension
+ (extHandle, SEC_OID_X509_BASIC_CONSTRAINTS,
+ &encodedValue, (buffer[0] == 'y' || buffer[0] == 'Y') ?
+ PR_TRUE : PR_FALSE ,PR_TRUE);
+ } while (0);
+ PORT_Free (encodedValue.data);
+ return (rv);
+}
+
+static SECItem *
+SignCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool selfsign,
+ SECOidTag hashAlgTag,
+ SECKEYPrivateKey *privKey, char *issuerNickName, void *pwarg)
+{
+ SECItem der;
+ SECItem *result = NULL;
+ SECKEYPrivateKey *caPrivateKey = NULL;
+ SECStatus rv;
+ PRArenaPool *arena;
+ SECOidTag algID;
+ void *dummy;
+
+ if( !selfsign ) {
+ CERTCertificate *issuer = PK11_FindCertFromNickname(issuerNickName, pwarg);
+ if( (CERTCertificate *)NULL == issuer ) {
+ SECU_PrintError(progName, "unable to find issuer with nickname %s",
+ issuerNickName);
+ return (SECItem *)NULL;
+ }
+
+ privKey = caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg);
+ CERT_DestroyCertificate(issuer);
+ if (caPrivateKey == NULL) {
+ SECU_PrintError(progName, "unable to retrieve key %s", issuerNickName);
+ return NULL;
+ }
+ }
+
+ arena = cert->arena;
+
+ algID = getSignatureOidTag(privKey->keyType, hashAlgTag);
+ if (algID == SEC_OID_UNKNOWN) {
+ fprintf(stderr, "Unknown key or hash type for issuer.");
+ goto done;
+ }
+
+ rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "Could not set signature algorithm id.");
+ goto done;
+ }
+
+ /* we only deal with cert v3 here */
+ *(cert->version.data) = 2;
+ cert->version.len = 1;
+
+ der.len = 0;
+ der.data = NULL;
+ dummy = SEC_ASN1EncodeItem (arena, &der, cert,
+ SEC_ASN1_GET(CERT_CertificateTemplate));
+ if (!dummy) {
+ fprintf (stderr, "Could not encode certificate.\n");
+ goto done;
+ }
+
+ result = (SECItem *) PORT_ArenaZAlloc (arena, sizeof (SECItem));
+ if (result == NULL) {
+ fprintf (stderr, "Could not allocate item for certificate data.\n");
+ goto done;
+ }
+
+ rv = SEC_DerSignData(arena, result, der.data, der.len, privKey, algID);
+ if (rv != SECSuccess) {
+ fprintf (stderr, "Could not sign encoded certificate data.\n");
+ PORT_Free(result);
+ result = NULL;
+ goto done;
+ }
+ cert->derCert = *result;
+done:
+ if (caPrivateKey) {
+ SECKEY_DestroyPrivateKey(caPrivateKey);
+ }
+ return result;
+}
+
+static SECStatus
+AddAuthKeyID (void *extHandle)
+{
+ CERTAuthKeyID *authKeyID = NULL;
+ PRArenaPool *arena = NULL;
+ SECStatus rv = SECSuccess;
+ char buffer[512];
+
+ do {
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( !arena ) {
+ SECU_PrintError(progName, "out of memory");
+ GEN_BREAK (SECFailure);
+ }
+
+ if (GetYesNo ("Enter value for the authKeyID extension [y/n]?\n") == 0)
+ break;
+
+ authKeyID = PORT_ArenaZAlloc (arena, sizeof (CERTAuthKeyID));
+ if (authKeyID == NULL) {
+ GEN_BREAK (SECFailure);
+ }
+
+ rv = GetString (arena, "Enter value for the key identifier fields, enter to omit:",
+ &authKeyID->keyID);
+ if (rv != SECSuccess)
+ break;
+ authKeyID->authCertIssuer = GetGeneralName (arena);
+ if (authKeyID->authCertIssuer == NULL && SECFailure == PORT_GetError ())
+ break;
+
+
+ rv = GetString (arena, "Enter value for the authCertSerial field, enter to omit:",
+ &authKeyID->authCertSerialNumber);
+
+ buffer[0] = 'n';
+ puts ("Is this a critical extension [y/n]? ");
+ gets (buffer);
+
+ rv = EncodeAndAddExtensionValue
+ (arena, extHandle, authKeyID,
+ (buffer[0] == 'y' || buffer[0] == 'Y') ? PR_TRUE : PR_FALSE,
+ SEC_OID_X509_AUTH_KEY_ID,
+ (EXTEN_VALUE_ENCODER) CERT_EncodeAuthKeyID);
+ if (rv)
+ break;
+
+ } while (0);
+ if (arena)
+ PORT_FreeArena (arena, PR_FALSE);
+ return (rv);
+}
+
+static SECStatus
+AddCrlDistPoint(void *extHandle)
+{
+ PRArenaPool *arena = NULL;
+ CERTCrlDistributionPoints *crlDistPoints = NULL;
+ CRLDistributionPoint *current;
+ SECStatus rv = SECSuccess;
+ int count = 0, intValue;
+ char buffer[5];
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( !arena )
+ return (SECFailure);
+
+ do {
+ current = NULL;
+ current = PORT_ArenaZAlloc (arena, sizeof (*current));
+ if (current == NULL) {
+ GEN_BREAK (SECFailure);
+ }
+
+ /* Get the distributionPointName fields - this field is optional */
+ puts ("Enter the type of the distribution point name:\n");
+ puts ("\t1 - Full Name\n\t2 - Relative Name\n\tOther - omit\n\t\tChoice: ");
+ scanf ("%d", &intValue);
+ switch (intValue) {
+ case generalName:
+ current->distPointType = intValue;
+ current->distPoint.fullName = GetGeneralName (arena);
+ rv = PORT_GetError();
+ break;
+
+ case relativeDistinguishedName: {
+ CERTName *name;
+ char buffer[512];
+
+ current->distPointType = intValue;
+ puts ("Enter the relative name: ");
+ fflush (stdout);
+ gets (buffer);
+ /* For simplicity, use CERT_AsciiToName to converse from a string
+ to NAME, but we only interest in the first RDN */
+ name = CERT_AsciiToName (buffer);
+ if (!name) {
+ GEN_BREAK (SECFailure);
+ }
+ rv = CERT_CopyRDN (arena, &current->distPoint.relativeName, name->rdns[0]);
+ CERT_DestroyName (name);
+ break;
+ }
+ }
+ if (rv != SECSuccess)
+ break;
+
+ /* Get the reason flags */
+ puts ("\nSelect one of the following for the reason flags\n");
+ puts ("\t0 - unused\n\t1 - keyCompromise\n\t2 - caCompromise\n\t3 - affiliationChanged\n");
+ puts ("\t4 - superseded\n\t5 - cessationOfOperation\n\t6 - certificateHold\n");
+ puts ("\tother - omit\t\tChoice: ");
+
+ scanf ("%d", &intValue);
+ if (intValue >= 0 && intValue <8) {
+ current->reasons.data = PORT_ArenaAlloc (arena, sizeof(char));
+ if (current->reasons.data == NULL) {
+ GEN_BREAK (SECFailure);
+ }
+ *current->reasons.data = (char)(0x80 >> intValue);
+ current->reasons.len = 1;
+ }
+ puts ("Enter value for the CRL Issuer name:\n");
+ current->crlIssuer = GetGeneralName (arena);
+ if (current->crlIssuer == NULL && (rv = PORT_GetError()) == SECFailure)
+ break;
+
+ if (crlDistPoints == NULL) {
+ crlDistPoints = PORT_ArenaZAlloc (arena, sizeof (*crlDistPoints));
+ if (crlDistPoints == NULL) {
+ GEN_BREAK (SECFailure);
+ }
+ }
+
+ crlDistPoints->distPoints = PORT_ArenaGrow (arena,
+ crlDistPoints->distPoints,
+ sizeof (*crlDistPoints->distPoints) * count,
+ sizeof (*crlDistPoints->distPoints) *(count + 1));
+ if (crlDistPoints->distPoints == NULL) {
+ GEN_BREAK (SECFailure);
+ }
+
+ crlDistPoints->distPoints[count] = current;
+ ++count;
+ if (GetYesNo ("Enter more value for the CRL distribution point extension [y/n]\n") == 0) {
+ /* Add null to the end of the crlDistPoints to mark end of data */
+ crlDistPoints->distPoints = PORT_ArenaGrow(arena,
+ crlDistPoints->distPoints,
+ sizeof (*crlDistPoints->distPoints) * count,
+ sizeof (*crlDistPoints->distPoints) *(count + 1));
+ crlDistPoints->distPoints[count] = NULL;
+ break;
+ }
+
+
+ } while (1);
+
+ if (rv == SECSuccess) {
+ buffer[0] = 'n';
+ puts ("Is this a critical extension [y/n]? ");
+ gets (buffer);
+
+ rv = EncodeAndAddExtensionValue(arena, extHandle, crlDistPoints,
+ (buffer[0] == 'Y' || buffer[0] == 'y') ? PR_TRUE : PR_FALSE,
+ SEC_OID_X509_CRL_DIST_POINTS,
+ (EXTEN_VALUE_ENCODER) CERT_EncodeCRLDistributionPoints);
+ }
+ if (arena)
+ PORT_FreeArena (arena, PR_FALSE);
+ return (rv);
+}
+
+static SECStatus
+CreateCert(
+ CERTCertDBHandle *handle,
+ char * issuerNickName,
+ PRFileDesc *inFile,
+ PRFileDesc *outFile,
+ SECKEYPrivateKey *selfsignprivkey,
+ void *pwarg,
+ SECOidTag hashAlgTag,
+ unsigned int serialNumber,
+ int warpmonths,
+ int validitylength,
+ const char *emailAddrs,
+ const char *dnsNames,
+ PRBool ascii,
+ PRBool selfsign,
+ PRBool keyUsage,
+ PRBool extKeyUsage,
+ PRBool basicConstraint,
+ PRBool authKeyID,
+ PRBool crlDistPoints,
+ PRBool nscpCertType)
+{
+ void * extHandle;
+ SECItem * certDER;
+ PRArenaPool *arena = NULL;
+ CERTCertificate *subjectCert = NULL;
+ CERTCertificateRequest *certReq = NULL;
+ SECStatus rv = SECSuccess;
+ SECItem reqDER;
+
+ reqDER.data = NULL;
+ do {
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ GEN_BREAK (SECFailure);
+ }
+
+ /* Create a certrequest object from the input cert request der */
+ certReq = GetCertRequest(inFile, ascii);
+ if (certReq == NULL) {
+ GEN_BREAK (SECFailure)
+ }
+
+ subjectCert = MakeV1Cert (handle, certReq, issuerNickName, selfsign,
+ serialNumber, warpmonths, validitylength);
+ if (subjectCert == NULL) {
+ GEN_BREAK (SECFailure)
+ }
+
+ extHandle = CERT_StartCertExtensions (subjectCert);
+ if (extHandle == NULL) {
+ GEN_BREAK (SECFailure)
+ }
+
+ /* Add key usage extension */
+ if (keyUsage) {
+ rv = AddKeyUsage(extHandle);
+ if (rv)
+ break;
+ }
+
+ /* Add extended key usage extension */
+ if (extKeyUsage) {
+ rv = AddExtKeyUsage(extHandle);
+ if (rv)
+ break;
+ }
+
+ /* Add basic constraint extension */
+ if (basicConstraint) {
+ rv = AddBasicConstraint(extHandle);
+ if (rv)
+ break;
+ }
+
+ if (authKeyID) {
+ rv = AddAuthKeyID (extHandle);
+ if (rv)
+ break;
+ }
+
+
+ if (crlDistPoints) {
+ rv = AddCrlDistPoint (extHandle);
+ if (rv)
+ break;
+ }
+
+ if (nscpCertType) {
+ rv = AddNscpCertType(extHandle);
+ if (rv)
+ break;
+ }
+
+ if (emailAddrs != NULL) {
+ rv = AddEmailSubjectAlt(extHandle,emailAddrs);
+ if (rv)
+ break;
+ }
+
+ if (dnsNames != NULL) {
+ rv = AddDNSSubjectAlt(extHandle,dnsNames);
+ if (rv)
+ break;
+ }
+
+ CERT_FinishExtensions(extHandle);
+
+ certDER = SignCert(handle, subjectCert, selfsign, hashAlgTag,
+ selfsignprivkey, issuerNickName,pwarg);
+
+ if (certDER) {
+ if (ascii) {
+ PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CERT_HEADER,
+ BTOA_DataToAscii(certDER->data, certDER->len),
+ NS_CERT_TRAILER);
+ } else {
+ PR_Write(outFile, certDER->data, certDER->len);
+ }
+ }
+
+ } while (0);
+ CERT_DestroyCertificateRequest (certReq);
+ CERT_DestroyCertificate (subjectCert);
+ PORT_FreeArena (arena, PR_FALSE);
+ if (rv != SECSuccess) {
+ PRErrorCode perr = PR_GetError();
+ fprintf(stderr, "%s: unable to create cert (%s)\n", progName,
+ SECU_Strerror(perr));
+ }
+ return (rv);
+}
+
+/* Certutil commands */
+enum {
+ cmd_AddCert = 0,
+ cmd_CreateNewCert,
+ cmd_DeleteCert,
+ cmd_AddEmailCert,
+ cmd_DeleteKey,
+ cmd_GenKeyPair,
+ cmd_PrintHelp,
+ cmd_ListKeys,
+ cmd_ListCerts,
+ cmd_ModifyCertTrust,
+ cmd_NewDBs,
+ cmd_DumpChain,
+ cmd_CertReq,
+ cmd_CreateAndAddCert,
+ cmd_TokenReset,
+ cmd_ListModules,
+ cmd_CheckCertValidity,
+ cmd_ChangePassword,
+ cmd_Version
+};
+
+/* Certutil options */
+enum {
+ opt_SSOPass = 0,
+ opt_AddKeyUsageExt,
+ opt_AddBasicConstraintExt,
+ opt_AddAuthorityKeyIDExt,
+ opt_AddCRLDistPtsExt,
+ opt_AddNSCertTypeExt,
+ opt_AddExtKeyUsageExt,
+ opt_ExtendedEmailAddrs,
+ opt_ExtendedDNSNames,
+ opt_ASCIIForIO,
+ opt_ValidityTime,
+ opt_IssuerName,
+ opt_CertDir,
+ opt_VerifySig,
+ opt_PasswordFile,
+ opt_KeySize,
+ opt_TokenName,
+ opt_InputFile,
+ opt_KeyIndex,
+ opt_KeyType,
+ opt_DetailedInfo,
+ opt_SerialNumber,
+ opt_Nickname,
+ opt_OutputFile,
+ opt_PhoneNumber,
+ opt_DBPrefix,
+ opt_PQGFile,
+ opt_BinaryDER,
+ opt_Subject,
+ opt_Trust,
+ opt_Usage,
+ opt_Validity,
+ opt_OffsetMonths,
+ opt_SelfSign,
+ opt_RW,
+ opt_Exponent,
+ opt_NoiseFile,
+ opt_Hash
+};
+
+static secuCommandFlag certutil_commands[] =
+{
+ { /* cmd_AddCert */ 'A', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_CreateNewCert */ 'C', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_DeleteCert */ 'D', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_AddEmailCert */ 'E', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_DeleteKey */ 'F', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_GenKeyPair */ 'G', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_PrintHelp */ 'H', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ListKeys */ 'K', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ListCerts */ 'L', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ModifyCertTrust */ 'M', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_NewDBs */ 'N', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_DumpChain */ 'O', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_CertReq */ 'R', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_CreateAndAddCert */ 'S', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_TokenReset */ 'T', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ListModules */ 'U', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_CheckCertValidity */ 'V', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_ChangePassword */ 'W', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Version */ 'Y', PR_FALSE, 0, PR_FALSE }
+};
+
+static secuCommandFlag certutil_options[] =
+{
+ { /* opt_SSOPass */ '0', PR_TRUE, 0, PR_FALSE },
+ { /* opt_AddKeyUsageExt */ '1', PR_FALSE, 0, PR_FALSE },
+ { /* opt_AddBasicConstraintExt*/ '2', PR_FALSE, 0, PR_FALSE },
+ { /* opt_AddAuthorityKeyIDExt*/ '3', PR_FALSE, 0, PR_FALSE },
+ { /* opt_AddCRLDistPtsExt */ '4', PR_FALSE, 0, PR_FALSE },
+ { /* opt_AddNSCertTypeExt */ '5', PR_FALSE, 0, PR_FALSE },
+ { /* opt_AddExtKeyUsageExt */ '6', PR_FALSE, 0, PR_FALSE },
+ { /* opt_ExtendedEmailAddrs */ '7', PR_TRUE, 0, PR_FALSE },
+ { /* opt_ExtendedDNSNames */ '8', PR_TRUE, 0, PR_FALSE },
+ { /* opt_ASCIIForIO */ 'a', PR_FALSE, 0, PR_FALSE },
+ { /* opt_ValidityTime */ 'b', PR_TRUE, 0, PR_FALSE },
+ { /* opt_IssuerName */ 'c', PR_TRUE, 0, PR_FALSE },
+ { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_VerifySig */ 'e', PR_FALSE, 0, PR_FALSE },
+ { /* opt_PasswordFile */ 'f', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeySize */ 'g', PR_TRUE, 0, PR_FALSE },
+ { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE },
+ { /* opt_InputFile */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeyIndex */ 'j', PR_TRUE, 0, PR_FALSE },
+ { /* opt_KeyType */ 'k', PR_TRUE, 0, PR_FALSE },
+ { /* opt_DetailedInfo */ 'l', PR_FALSE, 0, PR_FALSE },
+ { /* opt_SerialNumber */ 'm', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OutputFile */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PhoneNumber */ 'p', PR_TRUE, 0, PR_FALSE },
+ { /* opt_DBPrefix */ 'P', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PQGFile */ 'q', PR_TRUE, 0, PR_FALSE },
+ { /* opt_BinaryDER */ 'r', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Subject */ 's', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Trust */ 't', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Usage */ 'u', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Validity */ 'v', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OffsetMonths */ 'w', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SelfSign */ 'x', PR_FALSE, 0, PR_FALSE },
+ { /* opt_RW */ 'X', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Exponent */ 'y', PR_TRUE, 0, PR_FALSE },
+ { /* opt_NoiseFile */ 'z', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Hash */ 'Z', PR_TRUE, 0, PR_FALSE }
+};
+
+int
+main(int argc, char **argv)
+{
+ CERTCertDBHandle *certHandle;
+ PK11SlotInfo *slot = NULL;
+ CERTName * subject = 0;
+ PRFileDesc *inFile = PR_STDIN;
+ PRFileDesc *outFile = 0;
+ char * certfile = "tempcert";
+ char * certreqfile = "tempcertreq";
+ char * slotname = "internal";
+ char * certPrefix = "";
+ KeyType keytype = rsaKey;
+ char * name = NULL;
+ SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
+ int keysize = DEFAULT_KEY_BITS;
+ int publicExponent = 0x010001;
+ unsigned int serialNumber = 0;
+ int warpmonths = 0;
+ int validitylength = 0;
+ int commandsEntered = 0;
+ char commandToRun = '\0';
+ secuPWData pwdata = { PW_NONE, 0 };
+ PRBool readOnly = PR_FALSE;
+
+ SECKEYPrivateKey *privkey = NULL;
+ SECKEYPublicKey *pubkey = NULL;
+
+ int i;
+ SECStatus rv;
+
+ secuCommand certutil;
+ certutil.numCommands = sizeof(certutil_commands) / sizeof(secuCommandFlag);
+ certutil.numOptions = sizeof(certutil_options) / sizeof(secuCommandFlag);
+ certutil.commands = certutil_commands;
+ certutil.options = certutil_options;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &certutil);
+
+ if (rv != SECSuccess)
+ Usage(progName);
+
+ if (certutil.commands[cmd_PrintHelp].activated)
+ LongUsage(progName);
+
+ if (certutil.options[opt_PasswordFile].arg) {
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = certutil.options[opt_PasswordFile].arg;
+ }
+
+ if (certutil.options[opt_CertDir].activated)
+ SECU_ConfigDirectory(certutil.options[opt_CertDir].arg);
+
+ if (certutil.options[opt_KeySize].activated) {
+ keysize = PORT_Atoi(certutil.options[opt_KeySize].arg);
+ if ((keysize < MIN_KEY_BITS) || (keysize > MAX_KEY_BITS)) {
+ PR_fprintf(PR_STDERR,
+ "%s -g: Keysize must be between %d and %d.\n",
+ MIN_KEY_BITS, MAX_KEY_BITS);
+ return 255;
+ }
+ }
+
+ /* -h specify token name */
+ if (certutil.options[opt_TokenName].activated) {
+ if (PL_strcmp(certutil.options[opt_TokenName].arg, "all") == 0)
+ slotname = NULL;
+ else
+ slotname = PL_strdup(certutil.options[opt_TokenName].arg);
+ }
+
+ /* -Z hash type */
+ if (certutil.options[opt_Hash].activated) {
+ char * arg = certutil.options[opt_Hash].arg;
+ if (!PL_strcmp(arg, "MD2")) {
+ hashAlgTag = SEC_OID_MD2;
+ } else if (!PL_strcmp(arg, "MD4")) {
+ hashAlgTag = SEC_OID_MD4;
+ } else if (!PL_strcmp(arg, "MD5")) {
+ hashAlgTag = SEC_OID_MD5;
+ } else if (!PL_strcmp(arg, "SHA1")) {
+ hashAlgTag = SEC_OID_SHA1;
+ } else if (!PL_strcmp(arg, "SHA256")) {
+ hashAlgTag = SEC_OID_SHA256;
+ } else if (!PL_strcmp(arg, "SHA384")) {
+ hashAlgTag = SEC_OID_SHA384;
+ } else if (!PL_strcmp(arg, "SHA512")) {
+ hashAlgTag = SEC_OID_SHA512;
+ } else {
+ PR_fprintf(PR_STDERR, "%s -Z: %s is not a recognized type.\n",
+ progName, arg);
+ return 255;
+ }
+ }
+
+ /* -k key type */
+ if (certutil.options[opt_KeyType].activated) {
+ char * arg = certutil.options[opt_KeyType].arg;
+ if (PL_strcmp(arg, "rsa") == 0) {
+ keytype = rsaKey;
+ } else if (PL_strcmp(arg, "dsa") == 0) {
+ keytype = dsaKey;
+ } else if (PL_strcmp(arg, "all") == 0) {
+ keytype = nullKey;
+ } else {
+ PR_fprintf(PR_STDERR, "%s -k: %s is not a recognized type.\n",
+ progName, arg);
+ return 255;
+ }
+ }
+
+ /* -m serial number */
+ if (certutil.options[opt_SerialNumber].activated) {
+ int sn = PORT_Atoi(certutil.options[opt_SerialNumber].arg);
+ if (sn < 0) {
+ PR_fprintf(PR_STDERR, "%s -m: %s is not a valid serial number.\n",
+ progName, certutil.options[opt_SerialNumber].arg);
+ return 255;
+ }
+ serialNumber = sn;
+ }
+
+ /* -P certdb name prefix */
+ if (certutil.options[opt_DBPrefix].activated)
+ certPrefix = strdup(certutil.options[opt_DBPrefix].arg);
+
+ /* -q PQG file */
+ if (certutil.options[opt_PQGFile].activated) {
+ if (keytype != dsaKey) {
+ PR_fprintf(PR_STDERR, "%s -q: PQG file is for DSA key (-k dsa).\n)",
+ progName);
+ return 255;
+ }
+ }
+
+ /* -s subject name */
+ if (certutil.options[opt_Subject].activated) {
+ subject = CERT_AsciiToName(certutil.options[opt_Subject].arg);
+ if (!subject) {
+ PR_fprintf(PR_STDERR, "%s -s: improperly formatted name: \"%s\"\n",
+ progName, certutil.options[opt_Subject].arg);
+ return 255;
+ }
+ }
+
+ /* -v validity period */
+ if (certutil.options[opt_Validity].activated) {
+ validitylength = PORT_Atoi(certutil.options[opt_Validity].arg);
+ if (validitylength < 0) {
+ PR_fprintf(PR_STDERR, "%s -v: incorrect validity period: \"%s\"\n",
+ progName, certutil.options[opt_Validity].arg);
+ return 255;
+ }
+ }
+
+ /* -w warp months */
+ if (certutil.options[opt_OffsetMonths].activated)
+ warpmonths = PORT_Atoi(certutil.options[opt_OffsetMonths].arg);
+
+ /* -y public exponent (for RSA) */
+ if (certutil.options[opt_Exponent].activated) {
+ publicExponent = PORT_Atoi(certutil.options[opt_Exponent].arg);
+ if ((publicExponent != 3) &&
+ (publicExponent != 17) &&
+ (publicExponent != 65537)) {
+ PR_fprintf(PR_STDERR, "%s -y: incorrect public exponent %d.",
+ progName, publicExponent);
+ PR_fprintf(PR_STDERR, "Must be 3, 17, or 65537.\n");
+ return 255;
+ }
+ }
+
+ /* Check number of commands entered. */
+ commandsEntered = 0;
+ for (i=0; i< certutil.numCommands; i++) {
+ if (certutil.commands[i].activated) {
+ commandToRun = certutil.commands[i].flag;
+ commandsEntered++;
+ }
+ if (commandsEntered > 1)
+ break;
+ }
+ if (commandsEntered > 1) {
+ PR_fprintf(PR_STDERR, "%s: only one command at a time!\n", progName);
+ PR_fprintf(PR_STDERR, "You entered: ");
+ for (i=0; i< certutil.numCommands; i++) {
+ if (certutil.commands[i].activated)
+ PR_fprintf(PR_STDERR, " -%c", certutil.commands[i].flag);
+ }
+ PR_fprintf(PR_STDERR, "\n");
+ return 255;
+ }
+ if (commandsEntered == 0) {
+ PR_fprintf(PR_STDERR, "%s: you must enter a command!\n", progName);
+ Usage(progName);
+ }
+
+ if (certutil.commands[cmd_ListCerts].activated ||
+ certutil.commands[cmd_PrintHelp].activated ||
+ certutil.commands[cmd_ListKeys].activated ||
+ certutil.commands[cmd_ListModules].activated ||
+ certutil.commands[cmd_CheckCertValidity].activated ||
+ certutil.commands[cmd_Version].activated ) {
+ readOnly = !certutil.options[opt_RW].activated;
+ }
+
+ /* -A, -D, -F, -M, -S, -V, and all require -n */
+ if ((certutil.commands[cmd_AddCert].activated ||
+ certutil.commands[cmd_DeleteCert].activated ||
+ certutil.commands[cmd_DeleteKey].activated ||
+ certutil.commands[cmd_ModifyCertTrust].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated ||
+ certutil.commands[cmd_CheckCertValidity].activated) &&
+ !certutil.options[opt_Nickname].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: nickname is required for this command (-n).\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* -A, -E, -M, -S require trust */
+ if ((certutil.commands[cmd_AddCert].activated ||
+ certutil.commands[cmd_AddEmailCert].activated ||
+ certutil.commands[cmd_ModifyCertTrust].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated) &&
+ !certutil.options[opt_Trust].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: trust is required for this command (-t).\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* if -L is given raw or ascii mode, it must be for only one cert. */
+ if (certutil.commands[cmd_ListCerts].activated &&
+ (certutil.options[opt_ASCIIForIO].activated ||
+ certutil.options[opt_BinaryDER].activated) &&
+ !certutil.options[opt_Nickname].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s: nickname is required to dump cert in raw or ascii mode.\n",
+ progName);
+ return 255;
+ }
+
+ /* -L can only be in (raw || ascii). */
+ if (certutil.commands[cmd_ListCerts].activated &&
+ certutil.options[opt_ASCIIForIO].activated &&
+ certutil.options[opt_BinaryDER].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s: cannot specify both -r and -a when dumping cert.\n",
+ progName);
+ return 255;
+ }
+
+ /* For now, deny -C -x combination */
+ if (certutil.commands[cmd_CreateNewCert].activated &&
+ certutil.options[opt_SelfSign].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s: self-signing a cert request is not supported.\n",
+ progName);
+ return 255;
+ }
+
+ /* If making a cert request, need a subject. */
+ if ((certutil.commands[cmd_CertReq].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated) &&
+ !certutil.options[opt_Subject].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: subject is required to create a cert request.\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* If making a cert, need a serial number. */
+ if ((certutil.commands[cmd_CreateNewCert].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated) &&
+ !certutil.options[opt_SerialNumber].activated) {
+ /* Make a default serial number from the current time. */
+ PRTime now = PR_Now();
+ LL_USHR(now, now, 19);
+ LL_L2UI(serialNumber, now);
+ }
+
+ /* Validation needs the usage to validate for. */
+ if (certutil.commands[cmd_CheckCertValidity].activated &&
+ !certutil.options[opt_Usage].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s -V: specify a usage to validate the cert for (-u).\n",
+ progName);
+ return 255;
+ }
+
+ /* To make a cert, need either a issuer or to self-sign it. */
+ if (certutil.commands[cmd_CreateAndAddCert].activated &&
+ !(certutil.options[opt_IssuerName].activated ||
+ certutil.options[opt_SelfSign].activated)) {
+ PR_fprintf(PR_STDERR,
+ "%s -S: must specify issuer (-c) or self-sign (-x).\n",
+ progName);
+ return 255;
+ }
+
+ /* Using slotname == NULL for listing keys and certs on all slots,
+ * but only that. */
+ if (!(certutil.commands[cmd_ListKeys].activated ||
+ certutil.commands[cmd_DumpChain].activated ||
+ certutil.commands[cmd_ListCerts].activated) && slotname == NULL) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: cannot use \"-h all\" for this command.\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* Using keytype == nullKey for list all key types, but only that. */
+ if (!certutil.commands[cmd_ListKeys].activated && keytype == nullKey) {
+ PR_fprintf(PR_STDERR,
+ "%s -%c: cannot use \"-k all\" for this command.\n",
+ progName, commandToRun);
+ return 255;
+ }
+
+ /* -S open outFile, temporary file for cert request. */
+ if (certutil.commands[cmd_CreateAndAddCert].activated) {
+ outFile = PR_Open(certreqfile, PR_RDWR | PR_CREATE_FILE, 00660);
+ if (!outFile) {
+ PR_fprintf(PR_STDERR,
+ "%s -o: unable to open \"%s\" for writing (%ld, %ld)\n",
+ progName, certreqfile,
+ PR_GetError(), PR_GetOSError());
+ return 255;
+ }
+ }
+
+ /* Open the input file. */
+ if (certutil.options[opt_InputFile].activated) {
+ inFile = PR_Open(certutil.options[opt_InputFile].arg, PR_RDONLY, 0);
+ if (!inFile) {
+ PR_fprintf(PR_STDERR,
+ "%s: unable to open \"%s\" for reading (%ld, %ld).\n",
+ progName, certutil.options[opt_InputFile].arg,
+ PR_GetError(), PR_GetOSError());
+ return 255;
+ }
+ }
+
+ /* Open the output file. */
+ if (certutil.options[opt_OutputFile].activated && !outFile) {
+ outFile = PR_Open(certutil.options[opt_OutputFile].arg,
+ PR_CREATE_FILE | PR_RDWR, 00660);
+ if (!outFile) {
+ PR_fprintf(PR_STDERR,
+ "%s: unable to open \"%s\" for writing (%ld, %ld).\n",
+ progName, certutil.options[opt_OutputFile].arg,
+ PR_GetError(), PR_GetOSError());
+ return 255;
+ }
+ }
+
+ name = SECU_GetOptionArg(&certutil, opt_Nickname);
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* Initialize NSPR and NSS. */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Initialize(SECU_ConfigDirectory(NULL), certPrefix, certPrefix,
+ "secmod.db", readOnly ? NSS_INIT_READONLY: 0);
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ rv = SECFailure;
+ goto shutdown;
+ }
+ certHandle = CERT_GetDefaultCertDB();
+
+ if (certutil.commands[cmd_Version].activated) {
+ int version = CERT_GetDBContentVersion(certHandle);
+ printf("Certificate database content version: %d\n", version);
+ }
+
+ if (PL_strcmp(slotname, "internal") == 0)
+ slot = PK11_GetInternalKeySlot();
+ else if (slotname != NULL)
+ slot = PK11_FindSlotByName(slotname);
+
+ /* If creating new database, initialize the password. */
+ if (certutil.commands[cmd_NewDBs].activated) {
+ SECU_ChangePW(slot, 0, certutil.options[opt_PasswordFile].arg);
+ }
+
+ /* The following 8 options are mutually exclusive with all others. */
+
+ /* List certs (-L) */
+ if (certutil.commands[cmd_ListCerts].activated) {
+ rv = ListCerts(certHandle, name, slot,
+ certutil.options[opt_BinaryDER].activated,
+ certutil.options[opt_ASCIIForIO].activated,
+ (outFile) ? outFile : PR_STDOUT, &pwdata);
+ goto shutdown;
+ }
+ if (certutil.commands[cmd_DumpChain].activated) {
+ rv = DumpChain(certHandle, name);
+ goto shutdown;
+ }
+ /* XXX needs work */
+ /* List keys (-K) */
+ if (certutil.commands[cmd_ListKeys].activated) {
+ rv = ListKeys(slot, name, 0 /*keyindex*/, keytype, PR_FALSE /*dopriv*/,
+ &pwdata);
+ goto shutdown;
+ }
+ /* List modules (-U) */
+ if (certutil.commands[cmd_ListModules].activated) {
+ rv = ListModules();
+ goto shutdown;
+ }
+ /* Delete cert (-D) */
+ if (certutil.commands[cmd_DeleteCert].activated) {
+ rv = DeleteCert(certHandle, name);
+ goto shutdown;
+ }
+ /* Delete key (-F) */
+ if (certutil.commands[cmd_DeleteKey].activated) {
+ rv = DeleteKey(name, &pwdata);
+ goto shutdown;
+ }
+ /* Modify trust attribute for cert (-M) */
+ if (certutil.commands[cmd_ModifyCertTrust].activated) {
+ rv = ChangeTrustAttributes(certHandle, name,
+ certutil.options[opt_Trust].arg);
+ goto shutdown;
+ }
+ /* Change key db password (-W) (future - change pw to slot?) */
+ if (certutil.commands[cmd_ChangePassword].activated) {
+ rv = SECU_ChangePW(slot, 0, certutil.options[opt_PasswordFile].arg);
+ goto shutdown;
+ }
+ /* Reset the a token */
+ if (certutil.commands[cmd_TokenReset].activated) {
+ char *sso_pass = "";
+
+ if (certutil.options[opt_SSOPass].activated) {
+ sso_pass = certutil.options[opt_SSOPass].arg;
+ }
+ rv = PK11_ResetToken(slot,sso_pass);
+
+ goto shutdown;
+ }
+ /* Check cert validity against current time (-V) */
+ if (certutil.commands[cmd_CheckCertValidity].activated) {
+ /* XXX temporary hack for fips - must log in to get priv key */
+ if (certutil.options[opt_VerifySig].activated) {
+ if (slot && PK11_NeedLogin(slot))
+ PK11_Authenticate(slot, PR_TRUE, &pwdata);
+ }
+ rv = ValidateCert(certHandle, name,
+ certutil.options[opt_ValidityTime].arg,
+ certutil.options[opt_Usage].arg,
+ certutil.options[opt_VerifySig].activated,
+ certutil.options[opt_DetailedInfo].activated,
+ &pwdata);
+ goto shutdown;
+ }
+
+ /*
+ * Key generation
+ */
+
+ /* These commands require keygen. */
+ if (certutil.commands[cmd_CertReq].activated ||
+ certutil.commands[cmd_CreateAndAddCert].activated ||
+ certutil.commands[cmd_GenKeyPair].activated) {
+ /* XXX Give it a nickname. */
+ privkey =
+ CERTUTIL_GeneratePrivateKey(keytype, slot, keysize,
+ publicExponent,
+ certutil.options[opt_NoiseFile].arg,
+ &pubkey,
+ certutil.options[opt_PQGFile].arg,
+ &pwdata);
+ if (privkey == NULL) {
+ SECU_PrintError(progName, "unable to generate key(s)\n");
+ rv = SECFailure;
+ goto shutdown;
+ }
+ privkey->wincx = &pwdata;
+ PORT_Assert(pubkey != NULL);
+
+ /* If all that was needed was keygen, exit. */
+ if (certutil.commands[cmd_GenKeyPair].activated) {
+ rv = SECSuccess;
+ goto shutdown;
+ }
+ }
+
+ /*
+ * Certificate request
+ */
+
+ /* Make a cert request (-R or -S). */
+ if (certutil.commands[cmd_CreateAndAddCert].activated ||
+ certutil.commands[cmd_CertReq].activated) {
+ rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
+ certutil.options[opt_PhoneNumber].arg,
+ certutil.options[opt_ASCIIForIO].activated,
+ certutil.options[opt_ExtendedEmailAddrs].arg,
+ certutil.options[opt_ExtendedDNSNames].arg,
+ outFile ? outFile : PR_STDOUT);
+ if (rv)
+ goto shutdown;
+ privkey->wincx = &pwdata;
+ }
+
+ /*
+ * Certificate creation
+ */
+
+ /* If making and adding a cert, load the cert request file
+ * and output the cert to another file.
+ */
+ if (certutil.commands[cmd_CreateAndAddCert].activated) {
+ PR_Close(outFile);
+ inFile = PR_Open(certreqfile, PR_RDONLY, 0);
+ if (!inFile) {
+ PR_fprintf(PR_STDERR, "Failed to open file \"%s\" (%ld, %ld).\n",
+ certreqfile, PR_GetError(), PR_GetOSError());
+ rv = SECFailure;
+ goto shutdown;
+ }
+ outFile = PR_Open(certfile, PR_RDWR | PR_CREATE_FILE, 00660);
+ if (!outFile) {
+ PR_fprintf(PR_STDERR, "Failed to open file \"%s\" (%ld, %ld).\n",
+ certfile, PR_GetError(), PR_GetOSError());
+ rv = SECFailure;
+ goto shutdown;
+ }
+ }
+
+ /* Create a certificate (-C or -S). */
+ if (certutil.commands[cmd_CreateAndAddCert].activated ||
+ certutil.commands[cmd_CreateNewCert].activated) {
+ rv = CreateCert(certHandle,
+ certutil.options[opt_IssuerName].arg,
+ inFile, outFile, privkey, &pwdata, hashAlgTag,
+ serialNumber, warpmonths, validitylength,
+ certutil.options[opt_ExtendedEmailAddrs].arg,
+ certutil.options[opt_ExtendedDNSNames].arg,
+ certutil.options[opt_ASCIIForIO].activated,
+ certutil.options[opt_SelfSign].activated,
+ certutil.options[opt_AddKeyUsageExt].activated,
+ certutil.options[opt_AddExtKeyUsageExt].activated,
+ certutil.options[opt_AddBasicConstraintExt].activated,
+ certutil.options[opt_AddAuthorityKeyIDExt].activated,
+ certutil.options[opt_AddCRLDistPtsExt].activated,
+ certutil.options[opt_AddNSCertTypeExt].activated);
+ if (rv)
+ goto shutdown;
+ }
+
+ /*
+ * Adding a cert to the database (or slot)
+ */
+
+ if (certutil.commands[cmd_CreateAndAddCert].activated) {
+ PORT_Assert(inFile != PR_STDIN);
+ PR_Close(inFile);
+ PR_Close(outFile);
+ inFile = PR_Open(certfile, PR_RDONLY, 0);
+ if (!inFile) {
+ PR_fprintf(PR_STDERR, "Failed to open file \"%s\" (%ld, %ld).\n",
+ certfile, PR_GetError(), PR_GetOSError());
+ rv = SECFailure;
+ goto shutdown;
+ }
+ }
+
+ if (certutil.commands[cmd_CreateAndAddCert].activated ||
+ certutil.commands[cmd_AddCert].activated ||
+ certutil.commands[cmd_AddEmailCert].activated) {
+ rv = AddCert(slot, certHandle, name,
+ certutil.options[opt_Trust].arg,
+ inFile,
+ certutil.options[opt_ASCIIForIO].activated,
+ certutil.commands[cmd_AddEmailCert].activated,&pwdata);
+ if (rv)
+ goto shutdown;
+ }
+
+ if (certutil.commands[cmd_CreateAndAddCert].activated) {
+ PORT_Assert(inFile != PR_STDIN);
+ PR_Close(inFile);
+ PR_Delete(certfile);
+ PR_Delete(certreqfile);
+ }
+
+shutdown:
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ if (privkey) {
+ SECKEY_DestroyPrivateKey(privkey);
+ }
+ if (pubkey) {
+ SECKEY_DestroyPublicKey(pubkey);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ if (rv == SECSuccess) {
+ return 0;
+ } else {
+ return 255;
+ }
+}
diff --git a/security/nss/cmd/certutil/keystuff.c b/security/nss/cmd/certutil/keystuff.c
new file mode 100644
index 000000000..317443a27
--- /dev/null
+++ b/security/nss/cmd/certutil/keystuff.c
@@ -0,0 +1,411 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#include <sys/time.h>
+#include <termios.h>
+#endif
+
+#if defined(XP_WIN) || defined (XP_PC)
+#include <time.h>
+#include <conio.h>
+#endif
+
+#if defined(__sun) && !defined(SVR4)
+extern int fclose(FILE*);
+extern int fprintf(FILE *, char *, ...);
+extern int isatty(int);
+extern char *sys_errlist[];
+#define strerror(errno) sys_errlist[errno]
+#endif
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+#include "pk11func.h"
+#include "secrng.h"
+#include "pqgutil.h"
+
+#define NUM_KEYSTROKES 120
+#define RAND_BUF_SIZE 60
+
+#define ERROR_BREAK rv = SECFailure;break;
+
+const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) },
+ { 0, }
+};
+
+/* returns 0 for success, -1 for failure (EOF encountered) */
+static int
+UpdateRNG(void)
+{
+ char * randbuf;
+ int fd, i, count;
+ int c;
+ int rv = 0;
+#ifdef XP_UNIX
+ cc_t orig_cc_min;
+ cc_t orig_cc_time;
+ tcflag_t orig_lflag;
+ struct termios tio;
+#endif
+
+#define FPS fprintf(stderr,
+ FPS "\n");
+ FPS "A random seed must be generated that will be used in the\n");
+ FPS "creation of your key. One of the easiest ways to create a\n");
+ FPS "random seed is to use the timing of keystrokes on a keyboard.\n");
+ FPS "\n");
+ FPS "To begin, type keys on the keyboard until this progress meter\n");
+ FPS "is full. DO NOT USE THE AUTOREPEAT FUNCTION ON YOUR KEYBOARD!\n");
+ FPS "\n");
+ FPS "\n");
+ FPS "Continue typing until the progress meter is full:\n\n");
+ FPS "| |\r");
+
+ /* turn off echo on stdin & return on 1 char instead of NL */
+ fd = fileno(stdin);
+
+#if defined(XP_UNIX) && !defined(VMS)
+ tcgetattr(fd, &tio);
+ orig_lflag = tio.c_lflag;
+ orig_cc_min = tio.c_cc[VMIN];
+ orig_cc_time = tio.c_cc[VTIME];
+ tio.c_lflag &= ~ECHO;
+ tio.c_lflag &= ~ICANON;
+ tio.c_cc[VMIN] = 1;
+ tio.c_cc[VTIME] = 0;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+#endif
+
+ /* Get random noise from keyboard strokes */
+ randbuf = (char *) PORT_Alloc(RAND_BUF_SIZE);
+ count = 0;
+ while (count < NUM_KEYSTROKES+1) {
+#ifdef VMS
+ c = GENERIC_GETCHAR_NOECHO();
+#elif XP_UNIX
+ c = getc(stdin);
+#else
+ c = getch();
+#endif
+ if (c == EOF) {
+ rv = -1;
+ break;
+ }
+ PK11_RandomUpdate(randbuf, sizeof(randbuf));
+ if (c != randbuf[0]) {
+ randbuf[0] = c;
+ FPS "\r|");
+ for (i=0; i<count/(NUM_KEYSTROKES/RAND_BUF_SIZE); i++) {
+ FPS "*");
+ }
+ if (count%(NUM_KEYSTROKES/RAND_BUF_SIZE) == 1)
+ FPS "/");
+ count++;
+ }
+ }
+ free(randbuf);
+
+ FPS "\n\n");
+ FPS "Finished. Press enter to continue: ");
+#if defined(VMS)
+ while((c = GENERIC_GETCHAR_NO_ECHO()) != '\r' && c != EOF)
+ ;
+#else
+ while ((c = getc(stdin)) != '\n' && c != EOF)
+ ;
+#endif
+ if (c == EOF)
+ rv = -1;
+ FPS "\n");
+
+#undef FPS
+
+#if defined(XP_UNIX) && !defined(VMS)
+ /* set back termio the way it was */
+ tio.c_lflag = orig_lflag;
+ tio.c_cc[VMIN] = orig_cc_min;
+ tio.c_cc[VTIME] = orig_cc_time;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+#endif
+ return rv;
+}
+
+
+static unsigned char P[] = { 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
+ 0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
+ 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
+ 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
+ 0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
+ 0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
+ 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
+ 0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
+ 0x91 };
+static unsigned char Q[] = { 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
+ 0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
+ 0x8e, 0xda, 0xce, 0x91, 0x5f };
+static unsigned char G[] = { 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
+ 0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
+ 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
+ 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
+ 0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
+ 0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
+ 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
+ 0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
+ 0x02 };
+
+static SECKEYPQGParams default_pqg_params = {
+ NULL,
+ { 0, P, sizeof(P) },
+ { 0, Q, sizeof(Q) },
+ { 0, G, sizeof(G) }
+};
+
+static SECKEYPQGParams *
+decode_pqg_params(char *str)
+{
+ char *buf;
+ unsigned int len;
+ PRArenaPool *arena;
+ SECKEYPQGParams *params;
+ SECStatus status;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL)
+ return NULL;
+
+ params = PORT_ArenaZAlloc(arena, sizeof(SECKEYPQGParams));
+ if (params == NULL)
+ goto loser;
+ params->arena = arena;
+
+ buf = (char *)ATOB_AsciiToData(str, &len);
+ if ((buf == NULL) || (len == 0))
+ goto loser;
+
+ status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, buf, len);
+ if (status != SECSuccess)
+ goto loser;
+
+ return params;
+
+loser:
+ if (arena != NULL)
+ PORT_FreeArena(arena, PR_FALSE);
+ return NULL;
+}
+
+void
+CERTUTIL_DestroyParamsPQG(SECKEYPQGParams *params)
+{
+ if (params->arena) {
+ PORT_FreeArena(params->arena, PR_FALSE);
+ }
+}
+
+static int
+pqg_prime_bits(char *str)
+{
+ SECKEYPQGParams *params = NULL;
+ int primeBits = 0, i;
+
+ params = decode_pqg_params(str);
+ if (params == NULL)
+ goto done; /* lose */
+
+ for (i = 0; params->prime.data[i] == 0; i++)
+ /* empty */;
+ primeBits = (params->prime.len - i) * 8;
+
+done:
+ if (params != NULL)
+ CERTUTIL_DestroyParamsPQG(params);
+ return primeBits;
+}
+
+static char *
+SECU_GetpqgString(char *filename)
+{
+ char phrase[400];
+ FILE *fh;
+ char *rv;
+
+ fh = fopen(filename,"r");
+ rv = fgets (phrase, sizeof(phrase), fh);
+
+ fclose(fh);
+ if (phrase[strlen(phrase)-1] == '\n')
+ phrase[strlen(phrase)-1] = '\0';
+ if (rv) {
+ return (char*) PORT_Strdup(phrase);
+ }
+ fprintf(stderr,"pqg file contain no data\n");
+ return NULL;
+}
+
+SECKEYPQGParams*
+getpqgfromfile(int keyBits, char *pqgFile)
+{
+ char *end, *str, *pqgString;
+ int primeBits;
+
+ pqgString = SECU_GetpqgString(pqgFile);
+ if (pqgString)
+ str = PORT_Strdup(pqgString);
+ else
+ return NULL;
+
+ do {
+ end = PORT_Strchr(str, ',');
+ if (end)
+ *end = '\0';
+ primeBits = pqg_prime_bits(str);
+ if (keyBits == primeBits)
+ goto found_match;
+ str = end + 1;
+ } while (end);
+
+ PORT_Free(pqgString);
+ PORT_Free(str);
+ return NULL;
+
+found_match:
+ PORT_Free(pqgString);
+ PORT_Free(str);
+ return decode_pqg_params(str);
+}
+
+void CERTUTIL_FileForRNG(char *noise)
+{
+ char buf[2048];
+ PRFileDesc *fd;
+ PRInt32 count;
+
+ fd = PR_OpenFile(noise,PR_RDONLY,0666);
+ if (!fd) return;
+
+ do {
+ count = PR_Read(fd,buf,sizeof(buf));
+ if (count > 0) {
+ PK11_RandomUpdate(buf,count);
+ }
+ } while (count > 0);
+
+ PR_Close(fd);
+
+}
+
+SECKEYPrivateKey *
+CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size,
+ int publicExponent, char *noise,
+ SECKEYPublicKey **pubkeyp, char *pqgFile,
+ secuPWData *pwdata)
+{
+ CK_MECHANISM_TYPE mechanism;
+ SECOidTag algtag;
+ PK11RSAGenParams rsaparams;
+ SECKEYPQGParams *dsaparams = NULL;
+ void *params;
+ PRArenaPool *dsaparena;
+
+ /*
+ * Do some random-number initialization.
+ */
+
+ if (noise) {
+ CERTUTIL_FileForRNG(noise);
+ } else {
+ int rv = UpdateRNG();
+ if (rv) {
+ PORT_SetError(PR_END_OF_FILE_ERROR);
+ return NULL;
+ }
+ }
+
+ switch (keytype) {
+ case rsaKey:
+ rsaparams.keySizeInBits = size;
+ rsaparams.pe = publicExponent;
+ mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
+ algtag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
+ params = &rsaparams;
+ break;
+ case dsaKey:
+ mechanism = CKM_DSA_KEY_PAIR_GEN;
+ algtag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
+ if (pqgFile) {
+ dsaparams = getpqgfromfile(size, pqgFile);
+ } else {
+ dsaparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (dsaparena == NULL) return NULL;
+ dsaparams = PORT_ArenaZAlloc(dsaparena, sizeof(SECKEYPQGParams));
+ if (dsaparams == NULL) return NULL;
+ dsaparams->arena = dsaparena;
+ SECITEM_AllocItem(dsaparena, &dsaparams->prime, sizeof P);
+ SECITEM_AllocItem(dsaparena, &dsaparams->subPrime, sizeof Q);
+ SECITEM_AllocItem(dsaparena, &dsaparams->base, sizeof G);
+ PORT_Memcpy(dsaparams->prime.data, P, dsaparams->prime.len);
+ PORT_Memcpy(dsaparams->subPrime.data, Q, dsaparams->subPrime.len);
+ PORT_Memcpy(dsaparams->base.data, G, dsaparams->base.len);
+ }
+ params = dsaparams;
+ break;
+ default:
+ return NULL;
+ }
+
+ if (slot == NULL)
+ return NULL;
+
+ if (PK11_Authenticate(slot, PR_TRUE, pwdata) != SECSuccess)
+ return NULL;
+
+ fprintf(stderr, "\n\n");
+ fprintf(stderr, "Generating key. This may take a few moments...\n\n");
+
+ return PK11_GenerateKeyPair(slot, mechanism, params, pubkeyp,
+ PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/,
+ pwdata /*wincx*/);
+}
diff --git a/security/nss/cmd/certutil/makefile.win b/security/nss/cmd/certutil/makefile.win
new file mode 100644
index 000000000..26cdc0651
--- /dev/null
+++ b/security/nss/cmd/certutil/makefile.win
@@ -0,0 +1,155 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+PROGRAM = certutil
+PROGRAM = $(OBJDIR)\$(PROGRAM).exe
+
+include <$(DEPTH)\config\config.mak>
+
+
+# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
+# rules.mak will append C_OBJS onto OBJS.
+# OBJS = $(CSRCS:.c=.obj)
+
+# include files are looked for in $LINCS and $INCS.
+# $LINCS is in manifest.mnw, computed from REQUIRES=
+INCS = $(INCS) \
+ -I$(DEPTH)/security/lib/cert \
+ -I../include \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+
+
+WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
+
+# these files are the content of libdbm
+DBM_LIB = \
+ $(WINFE)/DB.obj \
+ $(WINFE)/HASH.obj \
+ $(WINFE)/H_BIGKEY.obj \
+ $(WINFE)/H_PAGE.obj \
+ $(WINFE)/H_LOG2.obj \
+ $(WINFE)/H_FUNC.obj \
+ $(WINFE)/HASH_BUF.obj \
+ $(NULL)
+
+MOZ_LIBS = \
+ $(WINFE)/ALLXPSTR.obj \
+ $(WINFE)/XP_ERROR.obj \
+ $(WINFE)/XPASSERT.obj \
+ $(WINFE)/XP_REG.obj \
+ $(WINFE)/XP_TRACE.obj \
+ $(DBM_LIB) \
+ $(WINFE)/XP_STR.obj \
+ $(WINFE)/MKTEMP.obj \
+ $(NULL)
+
+SEC_LIBS = \
+ $(DIST)/lib/cert$(MOZ_BITS).lib \
+ $(DIST)/lib/crypto$(MOZ_BITS).lib \
+ $(DIST)/lib/hash$(MOZ_BITS).lib \
+ $(DIST)/lib/key$(MOZ_BITS).lib \
+ $(DIST)/lib/pkcs7$(MOZ_BITS).lib \
+ $(DIST)/lib/secmod$(MOZ_BITS).lib \
+ $(DIST)/lib/secutl$(MOZ_BITS).lib \
+ $(DIST)/lib/ssl$(MOZ_BITS).lib \
+ $(NULL)
+
+LLFLAGS = $(LLFLAGS) \
+ ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
+ $(SEC_LIBS) \
+ $(MOZ_LIBS) \
+ $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
+ $(LIBNSPR) \
+ $(NULL)
+
+
+# awt3240.lib # brpref32.lib # cert32.lib
+# crypto32.lib # dllcom.lib # editor32.lib
+# edpref32.lib # edtplug.lib # font.lib
+# hash32.lib # htmldg32.lib # img32.lib
+# javart32.lib # jbn3240.lib # jdb3240.lib
+# jmc.lib # jpeg3240.lib # jpw3240.lib
+# jrt3240.lib # js3240.lib # jsd3240.lib
+# key32.lib # libapplet32.lib # libnjs32.lib
+# libnsc32.lib # libreg32.lib # mm3240.lib
+# mnpref32.lib # netcst32.lib # nsdlg32.lib
+# nsldap32.lib # nsldaps32.lib # nsn32.lib
+# pkcs1232.lib # pkcs732.lib # pr3240.lib
+# prefui32.lib # prefuuid.lib # secmod32.lib
+# secnav32.lib # secutl32.lib # softup32.lib
+# sp3240.lib # ssl32.lib # uni3200.lib
+# unicvt32.lib # win32md.lib # winfont.lib
+# xppref32.lib # zlib32.lib
+
+include <$(DEPTH)\config\rules.mak>
+
+
+INSTALL = $(MAKE_INSTALL)
+
+objs: $(OBJS)
+
+$(PROGRAM)::
+ $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
+
+programs: $(PROGRAM)
+
+install:: $(TARGETS)
+ $(INSTALL) $(TARGETS) $(DIST)/bin
+
+# ALLXPSTR.obj XP_ALLOC.obj XP_HASH.obj XP_RGB.obj XP_WRAP.obj
+# CXPRINT.obj XP_C.cl XP_LIST.obj XP_SEC.obj netscape.exp
+# CXPRNDLG.obj XP_CNTXT.obj XP_MD5.obj XP_STR.obj xp.pch
+# EXPORT.obj XP_CORE.obj XP_MESG.obj XP_THRMO.obj xppref32.dll
+# XPASSERT.obj XP_ERROR.obj XP_RECT.obj XP_TIME.obj
+# XPLOCALE.obj XP_FILE.obj XP_REG.obj XP_TRACE.obj
+
+symbols:
+ @echo "CSRCS = $(CSRCS)"
+ @echo "INCS = $(INCS)"
+ @echo "OBJS = $(OBJS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "TARGETS = $(TARGETS)"
+ @echo "DIST = $(DIST)"
+ @echo "VERSION_NUMBER = $(VERSION_NUMBER)"
+ @echo "WINFE = $(WINFE)"
+ @echo "DBM_LIB = $(DBM_LIB)"
+ @echo "INSTALL = $(INSTALL)"
+
diff --git a/security/nss/cmd/certutil/manifest.mn b/security/nss/cmd/certutil/manifest.mn
new file mode 100644
index 000000000..9bf7af5b8
--- /dev/null
+++ b/security/nss/cmd/certutil/manifest.mn
@@ -0,0 +1,52 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ certutil.c \
+ keystuff.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = dbm seccmd
+
+PROGRAM = certutil
+
+#USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/checkcert/Makefile b/security/nss/cmd/checkcert/Makefile
new file mode 100644
index 000000000..573c12cac
--- /dev/null
+++ b/security/nss/cmd/checkcert/Makefile
@@ -0,0 +1,76 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/checkcert/checkcert.c b/security/nss/cmd/checkcert/checkcert.c
new file mode 100644
index 000000000..0cd5e61aa
--- /dev/null
+++ b/security/nss/cmd/checkcert/checkcert.c
@@ -0,0 +1,640 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "secutil.h"
+#include "plgetopt.h"
+#include "cert.h"
+#include "secoid.h"
+#include "cryptohi.h"
+
+/* maximum supported modulus length in bits (indicate problem if over this) */
+#define MAX_MODULUS (1024)
+
+
+static void Usage(char *progName)
+{
+ fprintf(stderr, "Usage: %s [aAvf] [certtocheck] [issuingcert]\n",
+ progName);
+ fprintf(stderr, "%-20s Cert to check is base64 encoded\n",
+ "-a");
+ fprintf(stderr, "%-20s Issuer's cert is base64 encoded\n",
+ "-A");
+ fprintf(stderr, "%-20s Verbose (indicate decoding progress etc.)\n",
+ "-v");
+ fprintf(stderr, "%-20s Force sanity checks even if pretty print fails.\n",
+ "-f");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ fprintf(stderr, "%-20s Specify the input type (no default)\n",
+ "-t type");
+ exit(-1);
+}
+
+
+/*
+ * Check integer field named fieldName, printing out results and
+ * returning the length of the integer in bits
+ */
+
+static
+int checkInteger(SECItem *intItem, char *fieldName, int verbose)
+{
+ int len, bitlen;
+ if (verbose) {
+ printf("Checking %s\n", fieldName);
+ }
+
+ len = intItem->len;
+
+ if (len && (intItem->data[0] & 0x80)) {
+ printf("PROBLEM: %s is NEGATIVE 2's-complement integer.\n",
+ fieldName);
+ }
+
+
+ /* calculate bit length and check for unnecessary leading zeros */
+ bitlen = len << 3;
+ if (len > 1 && intItem->data[0] == 0) {
+ /* leading zero byte(s) */
+ if (!(intItem->data[1] & 0x80)) {
+ printf("PROBLEM: %s has unneeded leading zeros. Violates DER.\n",
+ fieldName);
+ }
+ /* strip leading zeros in length calculation */
+ {
+ int i=0;
+ while (bitlen > 8 && intItem->data[i] == 0) {
+ bitlen -= 8;
+ i++;
+ }
+ }
+ }
+ return bitlen;
+}
+
+
+
+
+static
+void checkName(CERTName *n, char *fieldName, int verbose)
+{
+ char *v=0;
+ if (verbose) {
+ printf("Checking %s\n", fieldName);
+ }
+
+ v = CERT_GetCountryName(n);
+ if (!v) {
+ printf("PROBLEM: %s lacks Country Name (C)\n",
+ fieldName);
+ }
+ PORT_Free(v);
+
+ v = CERT_GetOrgName(n);
+ if (!v) {
+ printf("PROBLEM: %s lacks Organization Name (O)\n",
+ fieldName);
+ }
+ PORT_Free(v);
+
+ v = CERT_GetOrgUnitName(n);
+ if (!v) {
+ printf("WARNING: %s lacks Organization Unit Name (OU)\n",
+ fieldName);
+ }
+ PORT_Free(v);
+
+ v = CERT_GetCommonName(n);
+ if (!v) {
+ printf("PROBLEM: %s lacks Common Name (CN)\n",
+ fieldName);
+ }
+ PORT_Free(v);
+}
+
+
+
+
+/*
+ * Private version of verification that checks for agreement between
+ * signature algorithm oid (at the SignedData level) and oid in DigestInfo.
+ *
+ */
+
+
+/* Returns the tag for the hash algorithm in the given signature algorithm */
+ static
+ int hashAlg(int sigAlgTag) {
+ int rv;
+ switch(sigAlgTag) {
+ case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
+ rv = SEC_OID_MD2;
+ break;
+ case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
+ rv = SEC_OID_MD5;
+ break;
+ case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
+ rv = SEC_OID_SHA1;
+ break;
+ default:
+ rv = -1;
+ }
+ return rv;
+ }
+
+
+
+struct VFYContextStr {
+ int alg;
+ unsigned char digest[32];
+ void *hasher;
+ void (*begin)(void *);
+ void (*update)(void *, unsigned char*, unsigned);
+ SECStatus (*end)(void *, unsigned char*, unsigned int*, unsigned);
+ void (*destroy)(void *, PRBool);
+};
+
+
+static
+SECStatus
+OurVerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
+ SECItem *sig, SECAlgorithmID *sigAlgorithm)
+{
+ SECStatus rv;
+ VFYContext *cx;
+ SECOidData *sigAlgOid, *oiddata;
+ int sigAlgTag;
+ int hashAlgTag;
+ int showDigestOid=0;
+
+ cx = VFY_CreateContext(key, sig, SECOID_GetAlgorithmTag(sigAlgorithm),
+ NULL);
+ if (cx == NULL)
+ return SECFailure;
+
+ sigAlgOid = SECOID_FindOID(&sigAlgorithm->algorithm);
+ if (sigAlgOid == 0)
+ return SECFailure;
+ sigAlgTag = sigAlgOid->offset;
+
+ hashAlgTag = hashAlg(sigAlgTag);
+ if (hashAlgTag == -1) {
+ printf("PROBLEM: Unsupported Digest Algorithm in DigestInfo");
+ showDigestOid = 1;
+ } else if (hashAlgTag != cx->alg) {
+ printf("PROBLEM: Digest OID in DigestInfo is incompatible "
+ "with Signature Algorithm\n");
+ showDigestOid = 1;
+ }
+
+ if (showDigestOid) {
+ oiddata = SECOID_FindOIDByTag(cx->alg);
+ if ( oiddata ) {
+ printf("PROBLEM: (cont) Digest OID is %s\n", oiddata->desc);
+ } else {
+ SECU_PrintAsHex(stdout,
+ &oiddata->oid, "PROBLEM: UNKNOWN OID", 0);
+ }
+ }
+
+ rv = VFY_Begin(cx);
+ if (rv == SECSuccess) {
+ rv = VFY_Update(cx, buf, len);
+ if (rv == SECSuccess)
+ rv = VFY_End(cx);
+ }
+
+ VFY_DestroyContext(cx, PR_TRUE);
+ return rv;
+}
+
+
+
+static
+SECStatus
+OurVerifySignedData(CERTSignedData *sd, CERTCertificate *cert)
+{
+ SECItem sig;
+ SECKEYPublicKey *pubKey = 0;
+ SECStatus rv;
+
+ /* check the certificate's validity */
+ rv = CERT_CertTimesValid(cert);
+ if ( rv ) {
+ return(SECFailure);
+ }
+
+ /* get cert's public key */
+ pubKey = CERT_ExtractPublicKey(cert);
+ if ( !pubKey ) {
+ return(SECFailure);
+ }
+
+ /* check the signature */
+ sig = sd->signature;
+ DER_ConvertBitString(&sig);
+ rv = OurVerifyData(sd->data.data, sd->data.len, pubKey, &sig,
+ &sd->signatureAlgorithm);
+
+ SECKEY_DestroyPublicKey(pubKey);
+
+ if ( rv ) {
+ return(SECFailure);
+ }
+
+ return(SECSuccess);
+}
+
+
+
+
+static
+CERTCertificate *createEmptyCertificate(void)
+{
+ PRArenaPool *arena = 0;
+ CERTCertificate *c = 0;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if ( !arena ) {
+ return 0;
+ }
+
+
+ c = (CERTCertificate *) PORT_ArenaZAlloc(arena, sizeof(CERTCertificate));
+
+ if (c) {
+ c->referenceCount = 1;
+ c->arena = arena;
+ } else {
+ PORT_FreeArena(arena,PR_TRUE);
+ }
+
+ return c;
+}
+
+
+
+
+int main(int argc, char **argv)
+{
+ int rv, verbose=0, force=0;
+ int ascii=0, issuerAscii=0;
+ char *progName=0;
+ PRFileDesc *inFile=0, *issuerCertFile=0;
+ SECItem derCert, derIssuerCert;
+ PRArenaPool *arena=0;
+ CERTSignedData *signedData=0;
+ CERTCertificate *cert=0, *issuerCert=0;
+ SECKEYPublicKey *rsapubkey=0;
+ SECAlgorithmID md5WithRSAEncryption, md2WithRSAEncryption;
+ SECAlgorithmID sha1WithRSAEncryption, rsaEncryption;
+ SECItem spk;
+ int selfSigned=0;
+ int invalid=0;
+ char *inFileName = NULL, *issuerCertFileName = NULL;
+ PLOptState *optstate;
+ PLOptStatus status;
+
+ PORT_Memset(&md5WithRSAEncryption, 0, sizeof(md5WithRSAEncryption));
+ PORT_Memset(&md2WithRSAEncryption, 0, sizeof(md2WithRSAEncryption));
+ PORT_Memset(&sha1WithRSAEncryption, 0, sizeof(sha1WithRSAEncryption));
+ PORT_Memset(&rsaEncryption, 0, sizeof(rsaEncryption));
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "aAvf");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'v':
+ verbose = 1;
+ break;
+
+ case 'f':
+ force = 1;
+ break;
+
+ case 'a':
+ ascii = 1;
+ break;
+
+ case 'A':
+ issuerAscii = 1;
+ break;
+
+ case '\0':
+ if (!inFileName)
+ inFileName = PL_strdup(optstate->value);
+ else if (!issuerCertFileName)
+ issuerCertFileName = PL_strdup(optstate->value);
+ else
+ Usage(progName);
+ break;
+ }
+ }
+
+ if (!inFileName || !issuerCertFileName || status == PL_OPT_BAD) {
+ /* insufficient or excess args */
+ Usage(progName);
+ }
+
+ inFile = PR_Open(inFileName, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, inFileName);
+ exit(1);
+ }
+
+ issuerCertFile = PR_Open(issuerCertFileName, PR_RDONLY, 0);
+ if (!issuerCertFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, issuerCertFileName);
+ exit(1);
+ }
+
+ if (SECU_ReadDERFromFile(&derCert, inFile, ascii) != SECSuccess) {
+ printf("Couldn't read input certificate as DER binary or base64\n");
+ exit(1);
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == 0) {
+ fprintf(stderr,"%s: can't allocate scratch arena!", progName);
+ exit(1);
+ }
+
+ if (issuerCertFile) {
+ CERTSignedData *issuerCertSD=0;
+ if (SECU_ReadDERFromFile(&derIssuerCert, issuerCertFile, issuerAscii)
+ != SECSuccess) {
+ printf("Couldn't read issuer certificate as DER binary or base64.\n");
+ exit(1);
+ }
+ issuerCertSD = (CERTSignedData *) PORT_ArenaZAlloc(arena,
+ sizeof(CERTSignedData));
+ if (!issuerCertSD) {
+ fprintf(stderr,"%s: can't allocate issuer signed data!", progName);
+ exit(1);
+ }
+ rv = SEC_ASN1DecodeItem(arena, issuerCertSD,
+ SEC_ASN1_GET(CERT_SignedDataTemplate),
+ &derIssuerCert);
+ if (rv) {
+ fprintf(stderr, "%s: Issuer cert isn't X509 SIGNED Data?\n",
+ progName);
+ exit(1);
+ }
+ issuerCert = createEmptyCertificate();
+ if (!issuerCert) {
+ printf("%s: can't allocate space for issuer cert.", progName);
+ exit(1);
+ }
+ rv = SEC_ASN1DecodeItem(arena, issuerCert,
+ SEC_ASN1_GET(CERT_CertificateTemplate),
+ &issuerCertSD->data);
+ if (rv) {
+ printf("%s: Does not appear to be an X509 Certificate.\n",
+ progName);
+ exit(1);
+ }
+ }
+
+ signedData = (CERTSignedData *) PORT_ArenaZAlloc(arena,sizeof(CERTSignedData));
+ if (!signedData) {
+ fprintf(stderr,"%s: can't allocate signedData!", progName);
+ exit(1);
+ }
+
+ rv = SEC_ASN1DecodeItem(arena, signedData,
+ SEC_ASN1_GET(CERT_SignedDataTemplate),
+ &derCert);
+ if (rv) {
+ fprintf(stderr, "%s: Does not appear to be X509 SIGNED Data.\n",
+ progName);
+ exit(1);
+ }
+
+ if (verbose) {
+ printf("Decoded ok as X509 SIGNED data.\n");
+ }
+
+ cert = createEmptyCertificate();
+ if (!cert) {
+ fprintf(stderr, "%s: can't allocate cert", progName);
+ exit(1);
+ }
+
+ rv = SEC_ASN1DecodeItem(arena, cert,
+ SEC_ASN1_GET(CERT_CertificateTemplate),
+ &signedData->data);
+ if (rv) {
+ fprintf(stderr, "%s: Does not appear to be an X509 Certificate.\n",
+ progName);
+ exit(1);
+ }
+
+
+ if (verbose) {
+ printf("Decoded ok as an X509 certificate.\n");
+ }
+
+
+ rv = SECU_PrintSignedData(stdout, &derCert, "Certificate", 0,
+ SECU_PrintCertificate);
+
+ if (rv) {
+ fprintf(stderr, "%s: Unable to pretty print cert. Error: %d\n",
+ progName, PORT_GetError());
+ if (!force) {
+ exit(1);
+ }
+ }
+
+
+ /* Do various checks on the cert */
+
+ printf("\n");
+
+ /* Check algorithms */
+ SECOID_SetAlgorithmID(arena, &md5WithRSAEncryption,
+ SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, NULL);
+
+ SECOID_SetAlgorithmID(arena, &md2WithRSAEncryption,
+ SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION, NULL);
+
+ SECOID_SetAlgorithmID(arena, &sha1WithRSAEncryption,
+ SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, NULL);
+
+ SECOID_SetAlgorithmID(arena, &rsaEncryption,
+ SEC_OID_PKCS1_RSA_ENCRYPTION, NULL);
+
+ {
+ int isMD5RSA = (SECOID_CompareAlgorithmID(&cert->signature,
+ &md5WithRSAEncryption) == 0);
+ int isMD2RSA = (SECOID_CompareAlgorithmID(&cert->signature,
+ &md2WithRSAEncryption) == 0);
+ int isSHA1RSA = (SECOID_CompareAlgorithmID(&cert->signature,
+ &sha1WithRSAEncryption) == 0);
+
+ if (verbose) {
+ printf("\nDoing algorithm checks.\n");
+ }
+
+ if (!(isMD5RSA || isMD2RSA || isSHA1RSA)) {
+ printf("PROBLEM: Signature not PKCS1 MD5, MD2, or SHA1 + RSA.\n");
+ } else if (!isMD5RSA) {
+ printf("WARNING: Signature not PKCS1 MD5 with RSA Encryption\n");
+ }
+
+ if (SECOID_CompareAlgorithmID(&cert->signature,
+ &signedData->signatureAlgorithm)) {
+ printf("PROBLEM: Algorithm in sig and certInfo don't match.\n");
+ }
+ }
+
+ if (SECOID_CompareAlgorithmID(&cert->subjectPublicKeyInfo.algorithm,
+ &rsaEncryption)) {
+ printf("PROBLEM: Public key algorithm is not PKCS1 RSA Encryption.\n");
+ }
+
+ /* Check further public key properties */
+ spk = cert->subjectPublicKeyInfo.subjectPublicKey;
+ DER_ConvertBitString(&spk);
+
+ if (verbose) {
+ printf("\nsubjectPublicKey DER\n");
+ rv = DER_PrettyPrint(stdout, &spk, PR_FALSE);
+ printf("\n");
+ }
+
+ rsapubkey = (SECKEYPublicKey *)
+ PORT_ArenaZAlloc(arena,sizeof(SECKEYPublicKey));
+ if (!rsapubkey) {
+ fprintf(stderr, "%s: rsapubkey allocation failed.\n", progName);
+ exit(1);
+ }
+
+ rv = SEC_ASN1DecodeItem(arena, rsapubkey,
+ SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate), &spk);
+ if (rv) {
+ printf("PROBLEM: subjectPublicKey is not a DER PKCS1 RSAPublicKey.\n");
+ } else {
+ int mlen;
+ int pubexp;
+ if (verbose) {
+ printf("Decoded RSA Public Key ok. Doing key checks.\n");
+ }
+ PORT_Assert(rsapubkey->keyType == rsaKey); /* XXX RSA */
+ mlen = checkInteger(&rsapubkey->u.rsa.modulus, "Modulus", verbose);
+ printf("INFO: Public Key modulus length in bits: %d\n", mlen);
+ if (mlen > MAX_MODULUS) {
+ printf("PROBLEM: Modulus length exceeds %d bits.\n",
+ MAX_MODULUS);
+ }
+ if (mlen < 512) {
+ printf("WARNING: Short modulus.\n");
+ }
+ if (mlen != (1 << (ffs(mlen)-1))) {
+ printf("WARNING: Unusual modulus length (not a power of two).\n");
+ }
+ checkInteger(&rsapubkey->u.rsa.publicExponent, "Public Exponent",
+ verbose);
+ pubexp = DER_GetInteger(&rsapubkey->u.rsa.publicExponent);
+ if (pubexp != 17 && pubexp != 3 && pubexp != 65537) {
+ printf("WARNING: Public exponent not any of: 3, 17, 65537\n");
+ }
+ }
+
+
+ /* Name checks */
+ checkName(&cert->issuer, "Issuer Name", verbose);
+ checkName(&cert->subject, "Subject Name", verbose);
+
+ if (issuerCert) {
+ SECComparison c =
+ CERT_CompareName(&cert->issuer, &issuerCert->subject);
+ if (c) {
+ printf("PROBLEM: Issuer Name and Subject in Issuing Cert differ\n");
+ }
+ }
+
+ /* Check if self-signed */
+ selfSigned = (CERT_CompareName(&cert->issuer, &cert->subject) == 0);
+ if (selfSigned) {
+ printf("INFO: Certificate is self signed.\n");
+ } else {
+ printf("INFO: Certificate is NOT self-signed.\n");
+ }
+
+
+ /* Validity time check */
+ if (CERT_CertTimesValid(cert) == SECSuccess) {
+ printf("INFO: Inside validity period of certificate.\n");
+ } else {
+ printf("PROBLEM: Not in validity period of certificate.\n");
+ invalid = 1;
+ }
+
+ /* Signature check if self-signed */
+ if (selfSigned && !invalid) {
+ if (rsapubkey->u.rsa.modulus.len) {
+ SECStatus ver;
+ if (verbose) {
+ printf("Checking self signature.\n");
+ }
+ ver = OurVerifySignedData(signedData, cert);
+ if (ver != SECSuccess) {
+ printf("PROBLEM: Verification of self-signature failed!\n");
+ } else {
+ printf("INFO: Self-signature verifies ok.\n");
+ }
+ } else {
+ printf("INFO: Not checking signature due to key problems.\n");
+ }
+ } else if (!selfSigned && !invalid && issuerCert) {
+ SECStatus ver;
+ ver = OurVerifySignedData(signedData, issuerCert);
+ if (ver != SECSuccess) {
+ printf("PROBLEM: Verification of issuer's signature failed!\n");
+ } else {
+ printf("INFO: Issuer's signature verifies ok.\n");
+ }
+ } else {
+ printf("INFO: Not checking signature.\n");
+ }
+
+ return 0;
+}
+
+
+
diff --git a/security/nss/cmd/checkcert/makefile.win b/security/nss/cmd/checkcert/makefile.win
new file mode 100644
index 000000000..ff1fe62a7
--- /dev/null
+++ b/security/nss/cmd/checkcert/makefile.win
@@ -0,0 +1,130 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+#cannot define PROGRAM in manifest compatibly with NT and UNIX
+PROGRAM = checkcert
+PROGRAM = ./$(OBJDIR)/$(PROGRAM).exe
+include <$(DEPTH)\config\config.mak>
+
+# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
+# rules.mak will append C_OBJS onto OBJS.
+# OBJS = $(CSRCS:.c=.obj)
+
+# include files are looked for in $LINCS and $INCS.
+# $LINCS is in manifest.mnw, computed from REQUIRES=
+INCS = $(INCS) \
+ -I$(DEPTH)/security/lib/cert \
+ -I../include \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+ $(NULL)
+
+
+WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
+
+# these files are the content of libdbm
+DBM_LIB = \
+ $(WINFE)/DB.obj \
+ $(WINFE)/HASH.obj \
+ $(WINFE)/H_BIGKEY.obj \
+ $(WINFE)/H_PAGE.obj \
+ $(WINFE)/H_LOG2.obj \
+ $(WINFE)/H_FUNC.obj \
+ $(WINFE)/HASH_BUF.obj \
+ $(NULL)
+
+MOZ_LIBS = \
+ $(WINFE)/ALLXPSTR.obj \
+ $(WINFE)/XP_ERROR.obj \
+ $(WINFE)/XPASSERT.obj \
+ $(WINFE)/XP_REG.obj \
+ $(WINFE)/XP_TRACE.obj \
+ $(DBM_LIB) \
+ $(WINFE)/XP_STR.obj \
+ $(WINFE)/MKTEMP.obj \
+ $(NULL)
+
+SEC_LIBS = \
+ $(DIST)/lib/cert$(MOZ_BITS).lib \
+ $(DIST)/lib/crypto$(MOZ_BITS).lib \
+ $(DIST)/lib/hash$(MOZ_BITS).lib \
+ $(DIST)/lib/key$(MOZ_BITS).lib \
+ $(DIST)/lib/pkcs7$(MOZ_BITS).lib \
+ $(DIST)/lib/secmod$(MOZ_BITS).lib \
+ $(DIST)/lib/secutl$(MOZ_BITS).lib \
+ $(DIST)/lib/ssl$(MOZ_BITS).lib \
+ $(NULL)
+
+LLFLAGS = $(LLFLAGS) \
+ ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
+ $(SEC_LIBS) \
+ $(MOZ_LIBS) \
+ $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
+ $(LIBNSPR) \
+ $(NULL)
+
+
+include <$(DEPTH)\config\rules.mak>
+
+INSTALL = $(MAKE_INSTALL)
+
+objs: $(OBJS)
+
+$(PROGRAM)::
+ $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
+
+programs: $(PROGRAM)
+
+install:: $(TARGETS)
+ $(INSTALL) $(TARGETS) $(DIST)/bin
+
+
+symbols:
+ @echo "CSRCS = $(CSRCS)"
+ @echo "INCS = $(INCS)"
+ @echo "OBJS = $(OBJS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "TARGETS = $(TARGETS)"
+ @echo "DIST = $(DIST)"
+ @echo "VERSION_NUMBER = $(VERSION_NUMBER)"
+ @echo "WINFE = $(WINFE)"
+ @echo "DBM_LIB = $(DBM_LIB)"
+ @echo "INSTALL = $(INSTALL)"
+
diff --git a/security/nss/cmd/checkcert/manifest.mn b/security/nss/cmd/checkcert/manifest.mn
new file mode 100644
index 000000000..470c203ec
--- /dev/null
+++ b/security/nss/cmd/checkcert/manifest.mn
@@ -0,0 +1,47 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = checkcert.c
+
+PROGRAM = checkcert
diff --git a/security/nss/cmd/cmdlib/Makefile b/security/nss/cmd/cmdlib/Makefile
new file mode 100644
index 000000000..0769c80a3
--- /dev/null
+++ b/security/nss/cmd/cmdlib/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include config.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
diff --git a/security/nss/cmd/cmdlib/cmdline.c b/security/nss/cmd/cmdlib/cmdline.c
new file mode 100644
index 000000000..84ad35be3
--- /dev/null
+++ b/security/nss/cmd/cmdlib/cmdline.c
@@ -0,0 +1,474 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include <string.h>
+#include <ctype.h>
+
+#include "cmdutil.h"
+
+static int s_indent_size = 4;
+
+void
+CMD_SetIndentSize(int size)
+{
+ s_indent_size = size;
+}
+
+#if 0
+static void
+indent(PRFileDesc *out, int level)
+{
+ int i, j;
+ for (i=0; i<level; i++)
+ for (j=0; j<s_indent_size; j++)
+ PR_fprintf(out, " ");
+}
+#endif
+
+struct cmdPrintStateStr {
+ PRFileDesc *file;
+ int width;
+ int indent;
+ int linepos;
+};
+
+static void
+init_print_ps(cmdPrintState *ps, PRFileDesc *outfile, int width, int indent)
+{
+ ps->file = (outfile) ? outfile : PR_STDOUT;
+ ps->width = (width > 0) ? width : 80;
+ ps->indent = (indent > 0) ? indent : 0;
+ ps->linepos = 0;
+}
+
+static void
+print_ps_indent(cmdPrintState *ps)
+{
+ int j;
+ if (ps->linepos != 0) {
+ PR_fprintf(ps->file, "\n");
+ ps->linepos = 0;
+ }
+ for (j=0; j<=ps->indent; j++) PR_fprintf(ps->file, " ");
+ ps->linepos = ps->indent;
+}
+
+static void
+print_ps_to_indent(cmdPrintState *ps)
+{
+ if (ps->linepos > ps->indent)
+ PR_fprintf(ps->file, "\n");
+ while (ps->linepos <= ps->indent) {
+ PR_fprintf(ps->file, " ");
+ ps->linepos++;
+ }
+}
+
+static void
+nprintbuf(cmdPrintState *ps, char *buf, int start, int len)
+{
+ int j;
+ for (j=start; j<start + len; j++) {
+ if (buf[j] == '\n') {
+ PR_fprintf(ps->file, "\n");
+ ps->linepos = 0;
+ print_ps_indent(ps);
+ } else {
+ PR_fprintf(ps->file, "%c", buf[j]);
+ ps->linepos++;
+ }
+ }
+}
+
+static void
+nprintf(cmdPrintState *ps, char *msg, ...)
+{
+ char buf[256];
+ int i, len, grouplen;
+ PRBool openquote, openbracket, openparen, openangle, itsaword;
+ va_list args;
+ va_start(args, msg);
+ vsprintf(buf, msg, args);
+ len = strlen(buf);
+ /* print_ps_indent(ps); */
+ if (len < ps->width - ps->linepos) {
+ nprintbuf(ps, buf, 0, len + 1);
+ return;
+ }
+ /* group in this order: " [ ( < word > ) ] " */
+ i=0;
+ openquote=openbracket=openparen=openangle=itsaword=PR_FALSE;
+ while (i<len) {
+ grouplen = 0;
+ if (buf[i] == '\"') { openquote = PR_TRUE; grouplen = 1; }
+ else if (buf[i] == '[') { openbracket = PR_TRUE; grouplen = 1; }
+ else if (buf[i] == '(') { openparen = PR_TRUE; grouplen = 1; }
+ else if (buf[i] == '<') { openangle = PR_TRUE; grouplen = 1; }
+ else itsaword = PR_TRUE;
+ while (grouplen < len && buf[i+grouplen] != '\0' &&
+ ((openquote && buf[i+grouplen] != '\"') ||
+ (openbracket && buf[i+grouplen] != ']') ||
+ (openparen && buf[i+grouplen] != ')') ||
+ (openangle && buf[i+grouplen] != '>') ||
+ (itsaword && !isspace(buf[i+grouplen]))))
+ grouplen++;
+ grouplen++; /* grab the terminator (whitespace for word) */
+ if (!itsaword && isspace(buf[i+grouplen])) grouplen++;
+ if (grouplen < ps->width - ps->linepos) {
+ nprintbuf(ps, buf, i, grouplen);
+ } else if (grouplen < ps->width - ps->indent) {
+ print_ps_indent(ps);
+ nprintbuf(ps, buf, i, grouplen);
+ } else {
+ /* it's just too darn long. what to do? */
+ }
+ i += grouplen;
+ openquote=openbracket=openparen=openangle=itsaword=PR_FALSE;
+ }
+ va_end(args);
+}
+
+void
+CMD_PrintUsageString(cmdPrintState *ps, char *str)
+{
+ nprintf(ps, "%s", str);
+}
+
+/* void because it exits with Usage() if failure */
+static void
+command_line_okay(cmdCommand *cmd, char *progName)
+{
+ int i, c = -1;
+ /* user asked for help. hope somebody gives it to them. */
+ if (cmd->opt[0].on) return;
+ /* check that the command got all of its needed options */
+ for (i=0; i<cmd->ncmd; i++) {
+ if (cmd->cmd[i].on) {
+ if (c > 0) {
+ fprintf(stderr,
+ "%s: only one command can be given at a time.\n",
+ progName);
+ CMD_Usage(progName, cmd);
+ } else {
+ c = i;
+ }
+ }
+ }
+ if (cmd->cmd[c].argUse == CMDArgReq && cmd->cmd[c].arg == NULL) {
+ /* where's the arg when you need it... */
+ fprintf(stderr, "%s: command --%s requires an argument.\n",
+ progName, cmd->cmd[c].s);
+ fprintf(stderr, "type \"%s --%s --help\" for help.\n",
+ progName, cmd->cmd[c].s);
+ CMD_Usage(progName, cmd);
+ }
+ for (i=0; i<cmd->nopt; i++) {
+ if (cmd->cmd[c].req & CMDBIT(i)) {
+ /* command requires this option */
+ if (!cmd->opt[i].on) {
+ /* but it ain't there */
+ fprintf(stderr, "%s: command --%s requires option --%s.\n",
+ progName, cmd->cmd[c].s, cmd->opt[i].s);
+ } else {
+ /* okay, its there, but does it have an arg? */
+ if (cmd->opt[i].argUse == CMDArgReq && !cmd->opt[i].arg) {
+ fprintf(stderr, "%s: option --%s requires an argument.\n",
+ progName, cmd->opt[i].s);
+ }
+ }
+ } else if (cmd->cmd[c].opt & CMDBIT(i)) {
+ /* this option is optional */
+ if (cmd->opt[i].on) {
+ /* okay, its there, but does it have an arg? */
+ if (cmd->opt[i].argUse == CMDArgReq && !cmd->opt[i].arg) {
+ fprintf(stderr, "%s: option --%s requires an argument.\n",
+ progName, cmd->opt[i].s);
+ }
+ }
+ } else {
+ /* command knows nothing about it */
+ if (cmd->opt[i].on) {
+ /* so why the h--- is it on? */
+ fprintf(stderr, "%s: option --%s not used with command --%s.\n",
+ progName, cmd->opt[i].s, cmd->cmd[c].s);
+ }
+ }
+ }
+}
+
+static char *
+get_arg(char *curopt, char **nextopt, int argc, int *index)
+{
+ char *str;
+ if (curopt) {
+ str = curopt;
+ } else {
+ if (*index + 1 >= argc) return NULL;
+ /* not really an argument but another flag */
+ if (nextopt[*index+1][0] == '-') return NULL;
+ str = nextopt[++(*index)];
+ }
+ /* parse the option */
+ return strdup(str);
+}
+
+int
+CMD_ParseCommandLine(int argc, char **argv, char *progName, cmdCommand *cmd)
+{
+ int i, j, k;
+ int cmdToRun = -1;
+ char *flag;
+ i=1;
+ if (argc <= 1) return -2; /* gross hack for cmdless things like atob */
+ do {
+ flag = argv[i];
+ if (strlen(flag) < 2) /* huh? */
+ return -1;
+ if (flag[0] != '-')
+ return -1;
+ /* ignore everything after lone "--" (app-specific weirdness there) */
+ if (strcmp(flag, "--") == 0)
+ return cmdToRun;
+ /* single hyphen means short alias (single-char) */
+ if (flag[1] != '-') {
+ j=1;
+ /* collect a set of opts, ex. -abc */
+ while (flag[j] != '\0') {
+ PRBool found = PR_FALSE;
+ /* walk the command set looking for match */
+ for (k=0; k<cmd->ncmd; k++) {
+ if (flag[j] == cmd->cmd[k].c) {
+ /* done - only take one command at a time */
+ if (j > 1) return -1;
+ cmd->cmd[k].on = found = PR_TRUE;
+ cmdToRun = k;
+ if (cmd->cmd[k].argUse != CMDNoArg)
+ cmd->cmd[k].arg = get_arg(NULL, argv, argc, &i);
+ goto next_flag;
+ }
+ }
+ /* wasn't found in commands, try options */
+ for (k=0; k<cmd->nopt; k++) {
+ if (flag[j] == cmd->opt[k].c) {
+ /* collect this option and keep going */
+ cmd->opt[k].on = found = PR_TRUE;
+ if (flag[j+1] == '\0') {
+ if (cmd->opt[k].argUse != CMDNoArg)
+ cmd->opt[k].arg = get_arg(NULL, argv, argc, &i);
+ goto next_flag;
+ }
+ }
+ }
+ j++;
+ if (!found) return -1;
+ }
+ } else { /* long alias, ex. --list */
+ char *fl = NULL, *arg = NULL;
+ PRBool hyphened = PR_FALSE;
+ fl = &flag[2];
+ arg = strchr(fl, '=');
+ if (arg) {
+ *arg++ = '\0';
+ } else {
+ arg = strchr(fl, '-');
+ if (arg) {
+ hyphened = PR_TRUE; /* watch this, see below */
+ *arg++ = '\0';
+ }
+ }
+ for (k=0; k<cmd->ncmd; k++) {
+ if (strcmp(fl, cmd->cmd[k].s) == 0) {
+ cmd->cmd[k].on = PR_TRUE;
+ cmdToRun = k;
+ if (cmd->cmd[k].argUse != CMDNoArg || hyphened) {
+ cmd->cmd[k].arg = get_arg(arg, argv, argc, &i);
+ }
+ if (arg) arg[-1] = '=';
+ goto next_flag;
+ }
+ }
+ for (k=0; k<cmd->nopt; k++) {
+ if (strcmp(fl, cmd->opt[k].s) == 0) {
+ cmd->opt[k].on = PR_TRUE;
+ if (cmd->opt[k].argUse != CMDNoArg || hyphened) {
+ cmd->opt[k].arg = get_arg(arg, argv, argc, &i);
+ }
+ if (arg) arg[-1] = '=';
+ goto next_flag;
+ }
+ }
+ return -1;
+ }
+next_flag:
+ i++;
+ } while (i < argc);
+ command_line_okay(cmd, progName);
+ return cmdToRun;
+}
+
+void
+CMD_LongUsage(char *progName, cmdCommand *cmd, cmdUsageCallback usage)
+{
+ int i, j;
+ PRBool oneCommand = PR_FALSE;
+ cmdPrintState ps;
+ init_print_ps(&ps, PR_STDERR, 80, 0);
+ nprintf(&ps, "\n%s: ", progName);
+ /* prints app-specific header */
+ ps.indent = strlen(progName) + 4;
+ usage(&ps, 0, PR_FALSE, PR_TRUE, PR_FALSE);
+ for (i=0; i<cmd->ncmd; i++) if (cmd->cmd[i].on) oneCommand = PR_TRUE;
+ for (i=0; i<cmd->ncmd; i++) {
+ if ((oneCommand && cmd->cmd[i].on) || !oneCommand) {
+ ps.indent = 0;
+ print_ps_indent(&ps);
+ if (cmd->cmd[i].c != 0) {
+ nprintf(&ps, "-%c, ", cmd->cmd[i].c);
+ nprintf(&ps, "--%-16s ", cmd->cmd[i].s);
+ } else {
+ nprintf(&ps, "--%-20s ", cmd->cmd[i].s);
+ }
+ ps.indent += 20;
+ usage(&ps, i, PR_TRUE, PR_FALSE, PR_FALSE);
+ for (j=0; j<cmd->nopt; j++) {
+ if (cmd->cmd[i].req & CMDBIT(j)) {
+ ps.indent = 0;
+ print_ps_indent(&ps);
+ nprintf(&ps, "%3s* ", "");
+ if (cmd->opt[j].c != 0) {
+ nprintf(&ps, "-%c, ", cmd->opt[j].c);
+ nprintf(&ps, "--%-16s ", cmd->opt[j].s);
+ } else {
+ nprintf(&ps, "--%-20s ", cmd->opt[j].s);
+ }
+ ps.indent += 29;
+ usage(&ps, j, PR_FALSE, PR_FALSE, PR_FALSE);
+ }
+ }
+ for (j=0; j<cmd->nopt; j++) {
+ if (cmd->cmd[i].opt & CMDBIT(j)) {
+ ps.indent = 0;
+ print_ps_indent(&ps);
+ nprintf(&ps, "%5s", "");
+ if (cmd->opt[j].c != 0) {
+ nprintf(&ps, "-%c, ", cmd->opt[j].c);
+ nprintf(&ps, "--%-16s ", cmd->opt[j].s);
+ } else {
+ nprintf(&ps, "--%-20s ", cmd->opt[j].s);
+ }
+ ps.indent += 29;
+ usage(&ps, j, PR_FALSE, PR_FALSE, PR_FALSE);
+ }
+ }
+ }
+ nprintf(&ps, "\n");
+ }
+ ps.indent = 0;
+ nprintf(&ps, "\n* - required flag for command\n\n");
+ /* prints app-specific footer */
+ usage(&ps, 0, PR_FALSE, PR_FALSE, PR_TRUE);
+ /*nprintf(&ps, "\n\n");*/
+ exit(1);
+}
+
+void
+CMD_Usage(char *progName, cmdCommand *cmd)
+{
+ int i, j, inc;
+ PRBool first;
+ cmdPrintState ps;
+ init_print_ps(&ps, PR_STDERR, 80, 0);
+ nprintf(&ps, "%s", progName);
+ ps.indent = strlen(progName) + 1;
+ print_ps_to_indent(&ps);
+ for (i=0; i<cmd->ncmd; i++) {
+ if (cmd->cmd[i].c != 0) {
+ nprintf(&ps, "-%c", cmd->cmd[i].c);
+ inc = 4;
+ } else {
+ nprintf(&ps, "--%s", cmd->cmd[i].s);
+ inc = 4 + strlen(cmd->cmd[i].s);
+ }
+ first = PR_TRUE;
+ ps.indent += inc;
+ print_ps_to_indent(&ps);
+ for (j=0; j<cmd->nopt; j++) {
+ if (cmd->cmd[i].req & CMDBIT(j)) {
+ if (cmd->opt[j].c != 0 && cmd->opt[j].argUse == CMDNoArg) {
+ if (first) {
+ nprintf(&ps, "-");
+ first = !first;
+ }
+ nprintf(&ps, "%c", cmd->opt[j].c);
+ }
+ }
+ }
+ for (j=0; j<cmd->nopt; j++) {
+ if (cmd->cmd[i].req & CMDBIT(j)) {
+ if (cmd->opt[j].c != 0)
+ nprintf(&ps, "-%c ", cmd->opt[j].c);
+ else
+ nprintf(&ps, "--%s ", cmd->opt[j].s);
+ if (cmd->opt[j].argUse != CMDNoArg)
+ nprintf(&ps, "%s ", cmd->opt[j].s);
+ }
+ }
+ first = PR_TRUE;
+ for (j=0; j<cmd->nopt; j++) {
+ if (cmd->cmd[i].opt & CMDBIT(j)) {
+ if (cmd->opt[j].c != 0 && cmd->opt[j].argUse == CMDNoArg) {
+ if (first) {
+ nprintf(&ps, "[-");
+ first = !first;
+ }
+ nprintf(&ps, "%c", cmd->opt[j].c);
+ }
+ }
+ }
+ if (!first) nprintf(&ps, "] ");
+ for (j=0; j<cmd->nopt; j++) {
+ if (cmd->cmd[i].opt & CMDBIT(j) &&
+ cmd->opt[j].argUse != CMDNoArg) {
+ if (cmd->opt[j].c != 0)
+ nprintf(&ps, "[-%c %s] ", cmd->opt[j].c, cmd->opt[j].s);
+ else
+ nprintf(&ps, "[--%s %s] ", cmd->opt[j].s, cmd->opt[j].s);
+ }
+ }
+ ps.indent -= inc;
+ print_ps_indent(&ps);
+ }
+ ps.indent = 0;
+ nprintf(&ps, "\n");
+ exit(1);
+}
diff --git a/security/nss/cmd/cmdlib/cmdutil.h b/security/nss/cmd/cmdlib/cmdutil.h
new file mode 100644
index 000000000..69d3f2657
--- /dev/null
+++ b/security/nss/cmd/cmdlib/cmdutil.h
@@ -0,0 +1,115 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifndef _CMDUTIL_H_
+#define _CMDUTIL_H_
+
+#include <stdio.h>
+#include "nspr.h"
+#include "nssbase.h"
+
+typedef int
+(* CMD_PPFunc)(PRFileDesc *out, NSSItem *item, char *msg, int level);
+
+
+/*
+ * Command Line Parsing routines
+ *
+ * The attempt here is to provide common functionality for command line
+ * parsing across an array of tools. The tools should obey the historical
+ * rules of:
+ *
+ * (1) one command per line,
+ * (2) the command should be uppercase,
+ * (3) options should be lowercase,
+ * (4) a short usage statement is presented in case of error,
+ * (5) a long usage statement is given by -? or --help
+ */
+
+/* To aid in formatting usage output. XXX Uh, why exposed? */
+typedef struct cmdPrintStateStr cmdPrintState;
+
+typedef enum {
+ CMDArgReq = 0,
+ CMDArgOpt,
+ CMDNoArg
+} CMDArg;
+
+struct cmdCommandLineArgStr {
+ char c; /* one-character alias for flag */
+ char *s; /* string alias for flag */
+ CMDArg argUse; /* flag takes an argument */
+ char *arg; /* argument given for flag */
+ PRBool on; /* flag was issued at command-line */
+ int req; /* required arguments for commands */
+ int opt; /* optional arguments for commands */
+};
+
+struct cmdCommandLineOptStr {
+ char c; /* one-character alias for flag */
+ char *s; /* string alias for flag */
+ CMDArg argUse; /* flag takes an argument */
+ char *arg; /* argument given for flag */
+ PRBool on; /* flag was issued at command-line */
+};
+
+typedef struct cmdCommandLineArgStr cmdCommandLineArg;
+typedef struct cmdCommandLineOptStr cmdCommandLineOpt;
+
+struct cmdCommandStr {
+ int ncmd;
+ int nopt;
+ cmdCommandLineArg *cmd;
+ cmdCommandLineOpt *opt;
+};
+
+typedef struct cmdCommandStr cmdCommand;
+
+int
+CMD_ParseCommandLine(int argc, char **argv, char *progName, cmdCommand *cmd);
+
+typedef void
+(* cmdUsageCallback)(cmdPrintState *, int, PRBool, PRBool, PRBool);
+
+#define CMDBIT(n) (1<<n)
+
+void
+CMD_Usage(char *progName, cmdCommand *cmd);
+
+void
+CMD_LongUsage(char *progName, cmdCommand *cmd, cmdUsageCallback use);
+
+void
+CMD_PrintUsageString(cmdPrintState *ps, char *str);
+
+#endif /* _CMDUTIL_H_ */
diff --git a/security/nss/cmd/cmdlib/config.mk b/security/nss/cmd/cmdlib/config.mk
new file mode 100644
index 000000000..0a00dc61e
--- /dev/null
+++ b/security/nss/cmd/cmdlib/config.mk
@@ -0,0 +1,43 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#
+# Override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(LIBRARY)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+PROGRAM =
+
diff --git a/security/nss/cmd/cmdlib/manifest.mn b/security/nss/cmd/cmdlib/manifest.mn
new file mode 100644
index 000000000..d276bdb23
--- /dev/null
+++ b/security/nss/cmd/cmdlib/manifest.mn
@@ -0,0 +1,49 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+CORE_DEPTH = ../../..
+
+LIBRARY_NAME = cmdutil
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = seccmd
+
+DEFINES = -DNSPR20
+
+EXPORTS = cmdutil.h \
+ $(NULL)
+
+CSRCS = cmdline.c \
+ $(NULL)
+
+REQUIRES = nss nspr dbm
+
diff --git a/security/nss/cmd/crlutil/Makefile b/security/nss/cmd/crlutil/Makefile
new file mode 100644
index 000000000..573c12cac
--- /dev/null
+++ b/security/nss/cmd/crlutil/Makefile
@@ -0,0 +1,76 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/crlutil/crlutil.c b/security/nss/cmd/crlutil/crlutil.c
new file mode 100644
index 000000000..d41dadde7
--- /dev/null
+++ b/security/nss/cmd/crlutil/crlutil.c
@@ -0,0 +1,478 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+** certutil.c
+**
+** utility for managing certificates and the cert database
+**
+*/
+/* test only */
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "secutil.h"
+#include "cert.h"
+#include "certdb.h"
+#include "nss.h"
+#include "pk11func.h"
+
+#define SEC_CERT_DB_EXISTS 0
+#define SEC_CREATE_CERT_DB 1
+
+static char *progName;
+
+static CERTSignedCrl *FindCRL
+ (CERTCertDBHandle *certHandle, char *name, int type)
+{
+ CERTSignedCrl *crl = NULL;
+ CERTCertificate *cert = NULL;
+
+
+ cert = CERT_FindCertByNickname(certHandle, name);
+ if (!cert) {
+ SECU_PrintError(progName, "could not find certificate named %s", name);
+ return ((CERTSignedCrl *)NULL);
+ }
+
+ crl = SEC_FindCrlByName(certHandle, &cert->derSubject, type);
+ if (crl ==NULL)
+ SECU_PrintError
+ (progName, "could not find %s's CRL", name);
+ CERT_DestroyCertificate (cert);
+ return (crl);
+}
+
+static void DisplayCRL (CERTCertDBHandle *certHandle, char *nickName, int crlType)
+{
+ CERTCertificate *cert = NULL;
+ CERTSignedCrl *crl = NULL;
+
+ crl = FindCRL (certHandle, nickName, crlType);
+
+ if (crl) {
+ SECU_PrintCRLInfo (stdout, &crl->crl, "CRL Info:\n", 0);
+ SEC_DestroyCrl (crl);
+ }
+}
+
+static void ListCRLNames (CERTCertDBHandle *certHandle, int crlType, PRBool deletecrls)
+{
+ CERTCrlHeadNode *crlList = NULL;
+ CERTCrlNode *crlNode = NULL;
+ CERTName *name = NULL;
+ PRArenaPool *arena = NULL;
+ SECStatus rv;
+
+ do {
+ arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (arena == NULL) {
+ fprintf(stderr, "%s: fail to allocate memory\n", progName);
+ break;
+ }
+
+ name = PORT_ArenaZAlloc (arena, sizeof(*name));
+ if (name == NULL) {
+ fprintf(stderr, "%s: fail to allocate memory\n", progName);
+ break;
+ }
+ name->arena = arena;
+
+ rv = SEC_LookupCrls (certHandle, &crlList, crlType);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: fail to look up CRLs (%s)\n", progName,
+ SECU_Strerror(PORT_GetError()));
+ break;
+ }
+
+ /* just in case */
+ if (!crlList)
+ break;
+
+ crlNode = crlList->first;
+
+ fprintf (stdout, "\n");
+ fprintf (stdout, "\n%-40s %-5s\n\n", "CRL names", "CRL Type");
+ while (crlNode) {
+ char* asciiname = NULL;
+ name = &crlNode->crl->crl.name;
+ if (!name){
+ fprintf(stderr, "%s: fail to get the CRL issuer name (%s)\n", progName,
+ SECU_Strerror(PORT_GetError()));
+ break;
+ }
+
+ asciiname = CERT_NameToAscii(name);
+ fprintf (stdout, "\n%-40s %-5s\n", asciiname, "CRL");
+ if (asciiname) {
+ PORT_Free(asciiname);
+ }
+ if ( PR_TRUE == deletecrls) {
+ CERTSignedCrl* acrl = NULL;
+ SECItem* issuer = &crlNode->crl->crl.derName;
+ acrl = SEC_FindCrlByName(certHandle, issuer, crlType);
+ if (acrl)
+ {
+ SEC_DeletePermCRL(acrl);
+ }
+ }
+ crlNode = crlNode->next;
+ }
+
+ } while (0);
+ if (crlList)
+ PORT_FreeArena (crlList->arena, PR_FALSE);
+ PORT_FreeArena (arena, PR_FALSE);
+}
+
+static void ListCRL (CERTCertDBHandle *certHandle, char *nickName, int crlType)
+{
+ if (nickName == NULL)
+ ListCRLNames (certHandle, crlType, PR_FALSE);
+ else
+ DisplayCRL (certHandle, nickName, crlType);
+}
+
+
+
+static SECStatus DeleteCRL (CERTCertDBHandle *certHandle, char *name, int type)
+{
+ CERTSignedCrl *crl = NULL;
+ SECStatus rv = SECFailure;
+
+ crl = FindCRL (certHandle, name, type);
+ if (!crl) {
+ SECU_PrintError
+ (progName, "could not find the issuer %s's CRL", name);
+ return SECFailure;
+ }
+ rv = SEC_DeletePermCRL (crl);
+ if (rv != SECSuccess) {
+ SECU_PrintError
+ (progName, "fail to delete the issuer %s's CRL from the perm database (reason: %s)",
+ name, SECU_Strerror(PORT_GetError()));
+ return SECFailure;
+ }
+ return (rv);
+}
+
+SECStatus ImportCRL (CERTCertDBHandle *certHandle, char *url, int type,
+ PRFileDesc *inFile, PRInt32 importOptions, PRInt32 decodeOptions)
+{
+ CERTCertificate *cert = NULL;
+ CERTSignedCrl *crl = NULL;
+ SECItem crlDER;
+ PK11SlotInfo* slot = NULL;
+ int rv;
+ PRIntervalTime starttime, endtime, elapsed;
+ PRUint32 mins, secs, msecs;
+
+ crlDER.data = NULL;
+
+
+ /* Read in the entire file specified with the -f argument */
+ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to read input file");
+ return (SECFailure);
+ }
+
+ decodeOptions |= CRL_DECODE_DONT_COPY_DER;
+
+ slot = PK11_GetInternalKeySlot();
+
+ starttime = PR_IntervalNow();
+ crl = PK11_ImportCRL(slot, &crlDER, url, type,
+ NULL, importOptions, NULL, decodeOptions);
+ endtime = PR_IntervalNow();
+ elapsed = endtime - starttime;
+ mins = PR_IntervalToSeconds(elapsed) / 60;
+ secs = PR_IntervalToSeconds(elapsed) % 60;
+ msecs = PR_IntervalToMilliseconds(elapsed) % 1000;
+ printf("Elapsed : %2d:%2d.%3d\n", mins, secs, msecs);
+ if (!crl) {
+ const char *errString;
+
+ errString = SECU_Strerror(PORT_GetError());
+ if ( errString && PORT_Strlen (errString) == 0)
+ SECU_PrintError
+ (progName, "CRL is not imported (error: input CRL is not up to date.)");
+ else
+ SECU_PrintError
+ (progName, "unable to import CRL");
+ }
+ SEC_DestroyCrl (crl);
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ return (rv);
+}
+
+
+static void Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -L [-n nickname] [-d keydir] [-P dbprefix] [-t crlType]\n"
+ " %s -D -n nickname [-d keydir] [-P dbprefix]\n"
+ " %s -I -i crl -t crlType [-u url] [-d keydir] [-P dbprefix] [-B]\n"
+ " %s -E -t crlType [-d keydir] [-P dbprefix]\n"
+ " %s -T\n", progName, progName, progName, progName, progName);
+
+ fprintf (stderr, "%-15s List CRL\n", "-L");
+ fprintf(stderr, "%-20s Specify the nickname of the CA certificate\n",
+ "-n nickname");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+ fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
+ "-P dbprefix");
+
+ fprintf (stderr, "%-15s Delete a CRL from the cert database\n", "-D");
+ fprintf(stderr, "%-20s Specify the nickname for the CA certificate\n",
+ "-n nickname");
+ fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+ fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
+ "-P dbprefix");
+
+ fprintf (stderr, "%-15s Erase all CRLs of specified type from hte cert database\n", "-E");
+ fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+ fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
+ "-P dbprefix");
+
+ fprintf (stderr, "%-15s Import a CRL to the cert database\n", "-I");
+ fprintf(stderr, "%-20s Specify the file which contains the CRL to import\n",
+ "-i crl");
+ fprintf(stderr, "%-20s Specify the url.\n", "-u url");
+ fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+ fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n",
+ "-P dbprefix");
+#ifdef DEBUG
+ fprintf (stderr, "%-15s Test . Only for debugging purposes. See source code\n", "-T");
+#endif
+ fprintf(stderr, "%-20s CRL Types (default is SEC_CRL_TYPE):\n", " ");
+ fprintf(stderr, "%-20s \t 0 - SEC_KRL_TYPE\n", " ");
+ fprintf(stderr, "%-20s \t 1 - SEC_CRL_TYPE\n", " ");
+ fprintf(stderr, "\n%-20s Bypass CA certificate checks.\n", "-B");
+ fprintf(stderr, "\n%-20s Partial decode for faster operation.\n", "-p");
+ fprintf(stderr, "%-20s Repeat the operation.\n", "-r <iterations>");
+
+ exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+ SECItem privKeyDER;
+ CERTCertDBHandle *certHandle;
+ FILE *certFile;
+ PRFileDesc *inFile;
+ int listCRL;
+ int importCRL;
+ int deleteCRL;
+ int rv;
+ char *nickName;
+ char *url;
+ char *dbPrefix = "";
+ int crlType;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus secstatus;
+ PRBool bypassChecks = PR_FALSE;
+ PRInt32 decodeOptions = CRL_DECODE_DEFAULT_OPTIONS;
+ PRInt32 importOptions = CRL_IMPORT_DEFAULT_OPTIONS;
+ PRBool test = PR_FALSE;
+ PRBool erase = PR_FALSE;
+ PRInt32 i = 0;
+ PRInt32 iterations = 1;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ rv = 0;
+ deleteCRL = importCRL = listCRL = 0;
+ certFile = NULL;
+ inFile = NULL;
+ nickName = url = NULL;
+ privKeyDER.data = NULL;
+ certHandle = NULL;
+ crlType = SEC_CRL_TYPE;
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "BCDILP:d:i:n:pt:u:TEr:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'T':
+ test = PR_TRUE;
+ break;
+
+ case 'E':
+ erase = PR_TRUE;
+ break;
+
+ case 'B':
+ importOptions |= CRL_IMPORT_BYPASS_CHECKS;
+ break;
+
+ case 'C':
+ listCRL = 1;
+ break;
+
+ case 'D':
+ deleteCRL = 1;
+ break;
+
+ case 'I':
+ importCRL = 1;
+ break;
+
+ case 'L':
+ listCRL = 1;
+ break;
+
+ case 'P':
+ dbPrefix = strdup(optstate->value);
+ break;
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ PL_DestroyOptState(optstate);
+ return -1;
+ }
+ break;
+
+ case 'n':
+ nickName = strdup(optstate->value);
+ break;
+
+ case 'p':
+ decodeOptions |= CRL_DECODE_SKIP_ENTRIES;
+ break;
+
+ case 'r': {
+ const char* str = optstate->value;
+ if (str && atoi(str)>0)
+ iterations = atoi(str);
+ }
+ break;
+
+ case 't': {
+ char *type;
+
+ type = strdup(optstate->value);
+ crlType = atoi (type);
+ if (crlType != SEC_CRL_TYPE && crlType != SEC_KRL_TYPE) {
+ fprintf(stderr, "%s: invalid crl type\n", progName);
+ PL_DestroyOptState(optstate);
+ return -1;
+ }
+ break;
+
+ case 'u':
+ url = strdup(optstate->value);
+ break;
+ }
+ }
+ }
+ PL_DestroyOptState(optstate);
+
+ if (deleteCRL && !nickName) Usage (progName);
+ if (!(listCRL || deleteCRL || importCRL || test || erase)) Usage (progName);
+ if (importCRL && !inFile) Usage (progName);
+
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ secstatus = NSS_Initialize(SECU_ConfigDirectory(NULL), dbPrefix, dbPrefix,
+ "secmod.db", 0);
+ if (secstatus != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+
+ certHandle = CERT_GetDefaultCertDB();
+ if (certHandle == NULL) {
+ SECU_PrintError(progName, "unable to open the cert db");
+ /*ignoring return value of NSS_Shutdown() as code returns -1*/
+ (void) NSS_Shutdown();
+ return (-1);
+ }
+
+ for (i=0; i<iterations; i++) {
+ /* Read in the private key info */
+ if (deleteCRL)
+ DeleteCRL (certHandle, nickName, crlType);
+ else if (listCRL) {
+ ListCRL (certHandle, nickName, crlType);
+ }
+ else if (importCRL) {
+ rv = ImportCRL (certHandle, url, crlType, inFile, importOptions,
+ decodeOptions);
+ }
+ else if (erase) {
+ /* list and delete all CRLs */
+ ListCRLNames (certHandle, crlType, PR_TRUE);
+ }
+#ifdef DEBUG
+ else if (test) {
+ /* list and delete all CRLs */
+ ListCRLNames (certHandle, crlType, PR_TRUE);
+ /* list CRLs */
+ ListCRLNames (certHandle, crlType, PR_FALSE);
+ /* import CRL as a blob */
+ rv = ImportCRL (certHandle, url, crlType, inFile, importOptions,
+ decodeOptions);
+ /* list CRLs */
+ ListCRLNames (certHandle, crlType, PR_FALSE);
+ }
+#endif
+ }
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return (rv);
+}
diff --git a/security/nss/cmd/crlutil/makefile.win b/security/nss/cmd/crlutil/makefile.win
new file mode 100644
index 000000000..1f1b627ff
--- /dev/null
+++ b/security/nss/cmd/crlutil/makefile.win
@@ -0,0 +1,130 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+#cannot define PROGRAM in manifest compatibly with NT and UNIX
+PROGRAM = crlutil
+PROGRAM = ./$(OBJDIR)/$(PROGRAM).exe
+include <$(DEPTH)\config\config.mak>
+
+# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
+# rules.mak will append C_OBJS onto OBJS.
+# OBJS = $(CSRCS:.c=.obj)
+
+# include files are looked for in $LINCS and $INCS.
+# $LINCS is in manifest.mnw, computed from REQUIRES=
+INCS = $(INCS) \
+ -I$(DEPTH)/security/lib/cert \
+ -I../include \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+ $(NULL)
+
+
+WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
+
+# these files are the content of libdbm
+DBM_LIB = \
+ $(WINFE)/DB.obj \
+ $(WINFE)/HASH.obj \
+ $(WINFE)/H_BIGKEY.obj \
+ $(WINFE)/H_PAGE.obj \
+ $(WINFE)/H_LOG2.obj \
+ $(WINFE)/H_FUNC.obj \
+ $(WINFE)/HASH_BUF.obj \
+ $(NULL)
+
+MOZ_LIBS = \
+ $(WINFE)/ALLXPSTR.obj \
+ $(WINFE)/XP_ERROR.obj \
+ $(WINFE)/XPASSERT.obj \
+ $(WINFE)/XP_REG.obj \
+ $(WINFE)/XP_TRACE.obj \
+ $(DBM_LIB) \
+ $(WINFE)/XP_STR.obj \
+ $(WINFE)/MKTEMP.obj \
+ $(NULL)
+
+SEC_LIBS = \
+ $(DIST)/lib/cert$(MOZ_BITS).lib \
+ $(DIST)/lib/crypto$(MOZ_BITS).lib \
+ $(DIST)/lib/hash$(MOZ_BITS).lib \
+ $(DIST)/lib/key$(MOZ_BITS).lib \
+ $(DIST)/lib/pkcs7$(MOZ_BITS).lib \
+ $(DIST)/lib/secmod$(MOZ_BITS).lib \
+ $(DIST)/lib/secutl$(MOZ_BITS).lib \
+ $(DIST)/lib/ssl$(MOZ_BITS).lib \
+ $(NULL)
+
+LLFLAGS = $(LLFLAGS) \
+ ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
+ $(SEC_LIBS) \
+ $(MOZ_LIBS) \
+ $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
+ $(LIBNSPR) \
+ $(NULL)
+
+
+include <$(DEPTH)\config\rules.mak>
+
+INSTALL = $(MAKE_INSTALL)
+
+objs: $(OBJS)
+
+$(PROGRAM)::
+ $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
+
+programs: $(PROGRAM)
+
+install:: $(TARGETS)
+ $(INSTALL) $(TARGETS) $(DIST)/bin
+
+
+symbols:
+ @echo "CSRCS = $(CSRCS)"
+ @echo "INCS = $(INCS)"
+ @echo "OBJS = $(OBJS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "TARGETS = $(TARGETS)"
+ @echo "DIST = $(DIST)"
+ @echo "VERSION_NUMBER = $(VERSION_NUMBER)"
+ @echo "WINFE = $(WINFE)"
+ @echo "DBM_LIB = $(DBM_LIB)"
+ @echo "INSTALL = $(INSTALL)"
+
diff --git a/security/nss/cmd/crlutil/manifest.mn b/security/nss/cmd/crlutil/manifest.mn
new file mode 100644
index 000000000..169deb28a
--- /dev/null
+++ b/security/nss/cmd/crlutil/manifest.mn
@@ -0,0 +1,53 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = crlutil.c
+
+# this has to be different for NT and UNIX.
+# PROGRAM = ./$(OBJDIR)/crlutil.exe
+PROGRAM = crlutil
+
+#USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/crmf-cgi/Makefile b/security/nss/cmd/crmf-cgi/Makefile
new file mode 100644
index 000000000..23cb6f6b5
--- /dev/null
+++ b/security/nss/cmd/crmf-cgi/Makefile
@@ -0,0 +1,81 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+EXTRA_LIBS += $(DIST)/lib/crmf.lib
+else
+EXTRA_LIBS += $(DIST)/lib/libcrmf.$(LIB_SUFFIX)
+endif
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/crmf-cgi/config.mk b/security/nss/cmd/crmf-cgi/config.mk
new file mode 100644
index 000000000..bcbaa2804
--- /dev/null
+++ b/security/nss/cmd/crmf-cgi/config.mk
@@ -0,0 +1,44 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+
+#
+# Override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(PROGRAM)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+LIBRARY =
+
diff --git a/security/nss/cmd/crmf-cgi/crmfcgi.c b/security/nss/cmd/crmf-cgi/crmfcgi.c
new file mode 100644
index 000000000..72199cfd5
--- /dev/null
+++ b/security/nss/cmd/crmf-cgi/crmfcgi.c
@@ -0,0 +1,1124 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "seccomon.h"
+#include "nss.h"
+#include "key.h"
+#include "cert.h"
+#include "pk11func.h"
+#include "secmod.h"
+#include "cmmf.h"
+#include "crmf.h"
+#include "base64.h"
+#include "secasn1.h"
+#include "cryptohi.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define DEFAULT_ALLOC_SIZE 200
+#define DEFAULT_CGI_VARS 20
+
+typedef struct CGIVariableStr {
+ char *name;
+ char *value;
+} CGIVariable;
+
+typedef struct CGIVarTableStr {
+ CGIVariable **variables;
+ int numVars;
+ int numAlloc;
+} CGIVarTable;
+
+typedef struct CertResponseInfoStr {
+ CERTCertificate *cert;
+ long certReqID;
+} CertResponseInfo;
+
+typedef struct ChallengeCreationInfoStr {
+ long random;
+ SECKEYPublicKey *pubKey;
+} ChallengeCreationInfo;
+
+char *missingVar = NULL;
+
+/*
+ * Error values.
+ */
+typedef enum {
+ NO_ERROR = 0,
+ NSS_INIT_FAILED,
+ AUTH_FAILED,
+ REQ_CGI_VAR_NOT_PRESENT,
+ CRMF_REQ_NOT_PRESENT,
+ BAD_ASCII_FOR_REQ,
+ CGI_VAR_MISSING,
+ COULD_NOT_FIND_CA,
+ COULD_NOT_DECODE_REQS,
+ OUT_OF_MEMORY,
+ ERROR_RETRIEVING_REQUEST_MSG,
+ ERROR_RETRIEVING_CERT_REQUEST,
+ ERROR_RETRIEVING_SUBJECT_FROM_REQ,
+ ERROR_RETRIEVING_PUBLIC_KEY_FROM_REQ,
+ ERROR_CREATING_NEW_CERTIFICATE,
+ COULD_NOT_START_EXTENSIONS,
+ ERROR_RETRIEVING_EXT_FROM_REQ,
+ ERROR_ADDING_EXT_TO_CERT,
+ ERROR_ENDING_EXTENSIONS,
+ COULD_NOT_FIND_ISSUER_PRIVATE_KEY,
+ UNSUPPORTED_SIGN_OPERATION_FOR_ISSUER,
+ ERROR_SETTING_SIGN_ALG,
+ ERROR_ENCODING_NEW_CERT,
+ ERROR_SIGNING_NEW_CERT,
+ ERROR_CREATING_CERT_REP_CONTENT,
+ ERROR_CREATING_SINGLE_CERT_RESPONSE,
+ ERROR_SETTING_CERT_RESPONSES,
+ ERROR_CREATING_CA_LIST,
+ ERROR_ADDING_ISSUER_TO_CA_LIST,
+ ERROR_ENCODING_CERT_REP_CONTENT,
+ NO_POP_FOR_REQUEST,
+ UNSUPPORTED_POP,
+ ERROR_RETRIEVING_POP_SIGN_KEY,
+ ERROR_RETRIEVING_ALG_ID_FROM_SIGN_KEY,
+ ERROR_RETRIEVING_SIGNATURE_FROM_POP_SIGN_KEY,
+ DO_CHALLENGE_RESPONSE,
+ ERROR_RETRIEVING_PUB_KEY_FROM_NEW_CERT,
+ ERROR_ENCODING_CERT_REQ_FOR_POP,
+ ERROR_VERIFYING_SIGNATURE_POP,
+ ERROR_RETRIEVING_PUB_KEY_FOR_CHALL,
+ ERROR_CREATING_EMPTY_CHAL_CONTENT,
+ ERROR_EXTRACTING_GEN_NAME_FROM_ISSUER,
+ ERROR_SETTING_CHALLENGE,
+ ERROR_ENCODING_CHALL,
+ ERROR_CONVERTING_CHALL_TO_BASE64,
+ ERROR_CONVERTING_RESP_FROM_CHALL_TO_BIN,
+ ERROR_CREATING_KEY_RESP_FROM_DER,
+ ERROR_RETRIEVING_CLIENT_RESPONSE_TO_CHALLENGE,
+ ERROR_RETURNED_CHALL_NOT_VALUE_EXPECTED,
+ ERROR_GETTING_KEY_ENCIPHERMENT,
+ ERROR_NO_POP_FOR_PRIVKEY,
+ ERROR_UNSUPPORTED_POPOPRIVKEY_TYPE
+} ErrorCode;
+
+const char *
+CGITableFindValue(CGIVarTable *varTable, const char *key);
+
+void
+spitOutHeaders(void)
+{
+ printf("Content-type: text/html\n\n");
+}
+
+void
+dumpRequest(CGIVarTable *varTable)
+{
+ int i;
+ CGIVariable *var;
+
+ printf ("<table border=1 cellpadding=1 cellspacing=1 width=\"100%%\">\n");
+ printf ("<tr><td><b><center>Variable Name<center></b></td>"
+ "<td><b><center>Value</center></b></td></tr>\n");
+ for (i=0; i<varTable->numVars; i++) {
+ var = varTable->variables[i];
+ printf ("<tr><td><pre>%s</pre></td><td><pre>%s</pre></td></tr>\n",
+ var->name, var->value);
+ }
+ printf("</table>\n");
+}
+
+void
+echo_request(CGIVarTable *varTable)
+{
+ spitOutHeaders();
+ printf("<html><head><title>CGI Echo Page</title></head>\n"
+ "<body><h1>Got the following request</h1>\n");
+ dumpRequest(varTable);
+ printf("</body></html>");
+}
+
+void
+processVariable(CGIVariable *var)
+{
+ char *plusSign, *percentSign;
+
+ /*First look for all of the '+' and convert them to spaces */
+ plusSign = var->value;
+ while ((plusSign=strchr(plusSign, '+')) != NULL) {
+ *plusSign = ' ';
+ }
+ percentSign = var->value;
+ while ((percentSign=strchr(percentSign, '%')) != NULL) {
+ char string[3];
+ int value;
+
+ string[0] = percentSign[1];
+ string[1] = percentSign[2];
+ string[2] = '\0';
+
+ sscanf(string,"%x", &value);
+ *percentSign = (char)value;
+ memmove(&percentSign[1], &percentSign[3], 1+strlen(&percentSign[3]));
+ }
+}
+
+char *
+parseNextVariable(CGIVarTable *varTable, char *form_output)
+{
+ char *ampersand, *equal;
+ CGIVariable *var;
+
+ if (varTable->numVars == varTable->numAlloc) {
+ CGIVariable **newArr = realloc(varTable->variables,
+ (varTable->numAlloc + DEFAULT_CGI_VARS)*sizeof(CGIVariable*));
+ if (newArr == NULL) {
+ return NULL;
+ }
+ varTable->variables = newArr;
+ varTable->numAlloc += DEFAULT_CGI_VARS;
+ }
+ equal = strchr(form_output, '=');
+ if (equal == NULL) {
+ return NULL;
+ }
+ ampersand = strchr(equal, '&');
+ if (ampersand == NULL) {
+ return NULL;
+ }
+ equal[0] = '\0';
+ if (ampersand != NULL) {
+ ampersand[0] = '\0';
+ }
+ var = malloc(sizeof(CGIVariable));
+ var->name = form_output;
+ var->value = &equal[1];
+ varTable->variables[varTable->numVars] = var;
+ varTable->numVars++;
+ processVariable(var);
+ return (ampersand != NULL) ? &ampersand[1] : NULL;
+}
+
+void
+ParseInputVariables(CGIVarTable *varTable, char *form_output)
+{
+ varTable->variables = malloc(sizeof(CGIVariable*)*DEFAULT_CGI_VARS);
+ varTable->numVars = 0;
+ varTable->numAlloc = DEFAULT_CGI_VARS;
+ while (form_output && form_output[0] != '\0') {
+ form_output = parseNextVariable(varTable, form_output);
+ }
+}
+
+const char *
+CGITableFindValue(CGIVarTable *varTable, const char *key)
+{
+ const char *retVal = NULL;
+ int i;
+
+ for (i=0; i<varTable->numVars; i++) {
+ if (strcmp(varTable->variables[i]->name, key) == 0) {
+ retVal = varTable->variables[i]->value;
+ break;
+ }
+ }
+ return retVal;
+}
+
+char*
+passwordCallback(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ const char *passwd;
+ if (retry) {
+ return NULL;
+ }
+ passwd = CGITableFindValue((CGIVarTable*)arg, "dbPassword");
+ if (passwd == NULL) {
+ return NULL;
+ }
+ return PORT_Strdup(passwd);
+}
+
+ErrorCode
+initNSS(CGIVarTable *varTable)
+{
+ const char *nssDir;
+ PK11SlotInfo *keySlot;
+ SECStatus rv;
+
+ nssDir = CGITableFindValue(varTable,"NSSDirectory");
+ if (nssDir == NULL) {
+ missingVar = "NSSDirectory";
+ return REQ_CGI_VAR_NOT_PRESENT;
+ }
+ rv = NSS_Init(nssDir);
+ if (rv != SECSuccess) {
+ return NSS_INIT_FAILED;
+ }
+ PK11_SetPasswordFunc(passwordCallback);
+ keySlot = PK11_GetInternalKeySlot();
+ rv = PK11_Authenticate(keySlot, PR_FALSE, varTable);
+ PK11_FreeSlot(keySlot);
+ if (rv != SECSuccess) {
+ return AUTH_FAILED;
+ }
+ return NO_ERROR;
+}
+
+void
+dumpErrorMessage(ErrorCode errNum)
+{
+ spitOutHeaders();
+ printf("<html><head><title>Error</title></head><body><h1>Error processing "
+ "data</h1> Received the error %d<p>", errNum);
+ if (errNum == REQ_CGI_VAR_NOT_PRESENT) {
+ printf ("The missing variable is %s.", missingVar);
+ }
+ printf ("<i>More useful information here in the future.</i></body></html>");
+}
+
+ErrorCode
+initOldCertReq(CERTCertificateRequest *oldCertReq,
+ CERTName *subject, CERTSubjectPublicKeyInfo *spki)
+{
+ PRArenaPool *poolp;
+
+ poolp = oldCertReq->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SEC_ASN1EncodeInteger(poolp, &oldCertReq->version,
+ SEC_CERTIFICATE_VERSION_3);
+ CERT_CopyName(poolp, &oldCertReq->subject, subject);
+ SECKEY_CopySubjectPublicKeyInfo(poolp, &oldCertReq->subjectPublicKeyInfo,
+ spki);
+ oldCertReq->attributes = NULL;
+ return NO_ERROR;
+}
+
+ErrorCode
+addExtensions(CERTCertificate *newCert, CRMFCertRequest *certReq)
+{
+ int numExtensions, i;
+ void *extHandle;
+ ErrorCode rv = NO_ERROR;
+ CRMFCertExtension *ext;
+ SECStatus srv;
+
+ numExtensions = CRMF_CertRequestGetNumberOfExtensions(certReq);
+ if (numExtensions == 0) {
+ /* No extensions to add */
+ return NO_ERROR;
+ }
+ extHandle = CERT_StartCertExtensions(newCert);
+ if (extHandle == NULL) {
+ rv = COULD_NOT_START_EXTENSIONS;
+ goto loser;
+ }
+ for (i=0; i<numExtensions; i++) {
+ ext = CRMF_CertRequestGetExtensionAtIndex(certReq, i);
+ if (ext == NULL) {
+ rv = ERROR_RETRIEVING_EXT_FROM_REQ;
+ }
+ srv = CERT_AddExtension(extHandle, CRMF_CertExtensionGetOidTag(ext),
+ CRMF_CertExtensionGetValue(ext),
+ CRMF_CertExtensionGetIsCritical(ext), PR_FALSE);
+ if (srv != SECSuccess) {
+ rv = ERROR_ADDING_EXT_TO_CERT;
+ }
+ }
+ srv = CERT_FinishExtensions(extHandle);
+ if (srv != SECSuccess) {
+ rv = ERROR_ENDING_EXTENSIONS;
+ goto loser;
+ }
+ return NO_ERROR;
+ loser:
+ return rv;
+}
+
+void
+writeOutItem(const char *filePath, SECItem *der)
+{
+ PRFileDesc *outfile;
+
+ outfile = PR_Open (filePath,
+ PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ PR_Write(outfile, der->data, der->len);
+ PR_Close(outfile);
+
+}
+
+ErrorCode
+createNewCert(CERTCertificate**issuedCert,CERTCertificateRequest *oldCertReq,
+ CRMFCertReqMsg *currReq, CRMFCertRequest *certReq,
+ CERTCertificate *issuerCert, CGIVarTable *varTable)
+{
+ CERTCertificate *newCert = NULL;
+ CERTValidity *validity;
+ PRExplodedTime printableTime;
+ PRTime now, after;
+ ErrorCode rv=NO_ERROR;
+ SECKEYPrivateKey *issuerPrivKey;
+ SECItem derCert = { 0 };
+ SECOidTag signTag;
+ SECStatus srv;
+ long version;
+
+ now = PR_Now();
+ PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
+ printableTime.tm_month += 9;
+ after = PR_ImplodeTime(&printableTime);
+ validity = CERT_CreateValidity(now, after);
+ newCert = *issuedCert =
+ CERT_CreateCertificate(rand(), &(issuerCert->subject), validity,
+ oldCertReq);
+ if (newCert == NULL) {
+ rv = ERROR_CREATING_NEW_CERTIFICATE;
+ goto loser;
+ }
+ rv = addExtensions(newCert, certReq);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ issuerPrivKey = PK11_FindKeyByAnyCert(issuerCert, varTable);
+ if (issuerPrivKey == NULL) {
+ rv = COULD_NOT_FIND_ISSUER_PRIVATE_KEY;
+ }
+ switch(issuerPrivKey->keyType) {
+ case rsaKey:
+ signTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
+ break;
+ case dsaKey:
+ signTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
+ break;
+ default:
+ rv = UNSUPPORTED_SIGN_OPERATION_FOR_ISSUER;
+ goto loser;
+ }
+ srv = SECOID_SetAlgorithmID(newCert->arena, &newCert->signature,
+ signTag, 0);
+ if (srv != SECSuccess) {
+ rv = ERROR_SETTING_SIGN_ALG;
+ goto loser;
+ }
+ srv = CRMF_CertRequestGetCertTemplateVersion(certReq, &version);
+ if (srv != SECSuccess) {
+ /* No version included in the request */
+ *(newCert->version.data) = SEC_CERTIFICATE_VERSION_3;
+ } else {
+ SECITEM_FreeItem(&newCert->version, PR_FALSE);
+ SEC_ASN1EncodeInteger(newCert->arena, &newCert->version, version);
+ }
+ SEC_ASN1EncodeItem(newCert->arena, &derCert, newCert,
+ CERT_CertificateTemplate);
+ if (derCert.data == NULL) {
+ rv = ERROR_ENCODING_NEW_CERT;
+ goto loser;
+ }
+ srv = SEC_DerSignData(newCert->arena, &(newCert->derCert), derCert.data,
+ derCert.len, issuerPrivKey, signTag);
+ if (srv != SECSuccess) {
+ rv = ERROR_SIGNING_NEW_CERT;
+ goto loser;
+ }
+#ifdef WRITE_OUT_RESPONSE
+ writeOutItem("newcert.der", &newCert->derCert);
+#endif
+ return NO_ERROR;
+ loser:
+ *issuedCert = NULL;
+ if (newCert) {
+ CERT_DestroyCertificate(newCert);
+ }
+ return rv;
+
+}
+
+void
+formatCMMFResponse(char *nickname, char *base64Response)
+{
+ char *currLine, *nextLine;
+
+ printf("var retVal = crypto.importUserCertificates(\"%s\",\n", nickname);
+ currLine = base64Response;
+ while (1) {
+ nextLine = strchr(currLine, '\n');
+ if (nextLine == NULL) {
+ /* print out the last line here. */
+ printf ("\"%s\",\n", currLine);
+ break;
+ }
+ nextLine[0] = '\0';
+ printf("\"%s\\n\"+\n", currLine);
+ currLine = nextLine+1;
+ }
+ printf("true);\n"
+ "if(retVal == '') {\n"
+ "\tdocument.write(\"<h1>New Certificate Succesfully Imported.</h1>\");\n"
+ "} else {\n"
+ "\tdocument.write(\"<h2>Unable to import New Certificate</h2>\");\n"
+ "\tdocument.write(\"crypto.importUserCertificates returned <b>\");\n"
+ "\tdocument.write(retVal);\n"
+ "\tdocument.write(\"</b>\");\n"
+ "}\n");
+}
+
+void
+spitOutCMMFResponse(char *nickname, char *base64Response)
+{
+ spitOutHeaders();
+ printf("<html>\n<head>\n<title>CMMF Resonse Page</title>\n</head>\n\n"
+ "<body><h1>CMMF Response Page</h1>\n"
+ "<script language=\"JavaScript\">\n"
+ "<!--\n");
+ formatCMMFResponse(nickname, base64Response);
+ printf("// -->\n"
+ "</script>\n</body>\n</html>");
+}
+
+char*
+getNickname(CERTCertificate *cert)
+{
+ char *nickname;
+
+ if (cert->nickname != NULL) {
+ return cert->nickname;
+ }
+ nickname = CERT_GetCommonName(&cert->subject);
+ if (nickname != NULL) {
+ return nickname;
+ }
+ return CERT_NameToAscii(&cert->subject);
+}
+
+ErrorCode
+createCMMFResponse(CertResponseInfo *issuedCerts, int numCerts,
+ CERTCertificate *issuerCert, char **base64der)
+{
+ CMMFCertRepContent *certRepContent=NULL;
+ ErrorCode rv = NO_ERROR;
+ CMMFCertResponse **responses, *currResponse;
+ CERTCertList *caList;
+ int i;
+ SECStatus srv;
+ PRArenaPool *poolp;
+ SECItem *der;
+
+ certRepContent = CMMF_CreateCertRepContent();
+ if (certRepContent == NULL) {
+ rv = ERROR_CREATING_CERT_REP_CONTENT;
+ goto loser;
+ }
+ responses = PORT_NewArray(CMMFCertResponse*, numCerts);
+ if (responses == NULL) {
+ rv = OUT_OF_MEMORY;
+ goto loser;
+ }
+ for (i=0; i<numCerts;i++) {
+ responses[i] = currResponse =
+ CMMF_CreateCertResponse(issuedCerts[i].certReqID);
+ if (currResponse == NULL) {
+ rv = ERROR_CREATING_SINGLE_CERT_RESPONSE;
+ goto loser;
+ }
+ CMMF_CertResponseSetPKIStatusInfoStatus(currResponse, cmmfGranted);
+ CMMF_CertResponseSetCertificate(currResponse, issuedCerts[i].cert);
+ }
+ srv = CMMF_CertRepContentSetCertResponses(certRepContent, responses,
+ numCerts);
+ if (srv != SECSuccess) {
+ rv = ERROR_SETTING_CERT_RESPONSES;
+ goto loser;
+ }
+ caList = CERT_NewCertList();
+ if (caList == NULL) {
+ rv = ERROR_CREATING_CA_LIST;
+ goto loser;
+ }
+ srv = CERT_AddCertToListTail(caList, issuerCert);
+ if (srv != SECSuccess) {
+ rv = ERROR_ADDING_ISSUER_TO_CA_LIST;
+ goto loser;
+ }
+ srv = CMMF_CertRepContentSetCAPubs(certRepContent, caList);
+ CERT_DestroyCertList(caList);
+ poolp = PORT_NewArena(1024);
+ der = SEC_ASN1EncodeItem(poolp, NULL, certRepContent,
+ CMMFCertRepContentTemplate);
+ if (der == NULL) {
+ rv = ERROR_ENCODING_CERT_REP_CONTENT;
+ goto loser;
+ }
+#ifdef WRITE_OUT_RESPONSE
+ writeOutItem("CertRepContent.der", der);
+#endif
+ *base64der = BTOA_DataToAscii(der->data, der->len);
+ return NO_ERROR;
+ loser:
+ return rv;
+}
+
+ErrorCode
+issueCerts(CertResponseInfo *issuedCerts, int numCerts,
+ CERTCertificate *issuerCert)
+{
+ ErrorCode rv;
+ char *base64Response;
+
+ rv = createCMMFResponse(issuedCerts, numCerts, issuerCert, &base64Response);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ spitOutCMMFResponse(getNickname(issuedCerts[0].cert),base64Response);
+ return NO_ERROR;
+ loser:
+ return rv;
+}
+
+ErrorCode
+verifySignature(CGIVarTable *varTable, CRMFCertReqMsg *currReq,
+ CRMFCertRequest *certReq, CERTCertificate *newCert)
+{
+ SECStatus srv;
+ ErrorCode rv = NO_ERROR;
+ CRMFPOPOSigningKey *signKey = NULL;
+ SECAlgorithmID *algID = NULL;
+ SECItem *signature = NULL;
+ SECKEYPublicKey *pubKey = NULL;
+ SECItem *reqDER = NULL;
+
+ srv = CRMF_CertReqMsgGetPOPOSigningKey(currReq, &signKey);
+ if (srv != SECSuccess || signKey == NULL) {
+ rv = ERROR_RETRIEVING_POP_SIGN_KEY;
+ goto loser;
+ }
+ algID = CRMF_POPOSigningKeyGetAlgID(signKey);
+ if (algID == NULL) {
+ rv = ERROR_RETRIEVING_ALG_ID_FROM_SIGN_KEY;
+ goto loser;
+ }
+ signature = CRMF_POPOSigningKeyGetSignature(signKey);
+ if (signature == NULL) {
+ rv = ERROR_RETRIEVING_SIGNATURE_FROM_POP_SIGN_KEY;
+ goto loser;
+ }
+ /* Make the length the number of bytes instead of bits */
+ signature->len = (signature->len+7)/8;
+ pubKey = CERT_ExtractPublicKey(newCert);
+ if (pubKey == NULL) {
+ rv = ERROR_RETRIEVING_PUB_KEY_FROM_NEW_CERT;
+ goto loser;
+ }
+ reqDER = SEC_ASN1EncodeItem(NULL, NULL, certReq, CRMFCertRequestTemplate);
+ if (reqDER == NULL) {
+ rv = ERROR_ENCODING_CERT_REQ_FOR_POP;
+ goto loser;
+ }
+ srv = VFY_VerifyData(reqDER->data, reqDER->len, pubKey, signature,
+ SECOID_FindOIDTag(&algID->algorithm), varTable);
+ if (srv != SECSuccess) {
+ rv = ERROR_VERIFYING_SIGNATURE_POP;
+ goto loser;
+ }
+ /* Fall thru in successfull case. */
+ loser:
+ if (pubKey != NULL) {
+ SECKEY_DestroyPublicKey(pubKey);
+ }
+ if (reqDER != NULL) {
+ SECITEM_FreeItem(reqDER, PR_TRUE);
+ }
+ if (signature != NULL) {
+ SECITEM_FreeItem(signature, PR_TRUE);
+ }
+ if (algID != NULL) {
+ SECOID_DestroyAlgorithmID(algID, PR_TRUE);
+ }
+ if (signKey != NULL) {
+ CRMF_DestroyPOPOSigningKey(signKey);
+ }
+ return rv;
+}
+
+ErrorCode
+doChallengeResponse(CGIVarTable *varTable, CRMFCertReqMsg *currReq,
+ CRMFCertRequest *certReq, CERTCertificate *newCert,
+ ChallengeCreationInfo *challs, int *numChall)
+{
+ CRMFPOPOPrivKey *privKey = NULL;
+ CRMFPOPOPrivKeyChoice privKeyChoice;
+ SECStatus srv;
+ ErrorCode rv = NO_ERROR;
+
+ srv = CRMF_CertReqMsgGetPOPKeyEncipherment(currReq, &privKey);
+ if (srv != SECSuccess || privKey == NULL) {
+ rv = ERROR_GETTING_KEY_ENCIPHERMENT;
+ goto loser;
+ }
+ privKeyChoice = CRMF_POPOPrivKeyGetChoice(privKey);
+ CRMF_DestroyPOPOPrivKey(privKey);
+ switch (privKeyChoice) {
+ case crmfSubsequentMessage:
+ challs = &challs[*numChall];
+ challs->random = rand();
+ challs->pubKey = CERT_ExtractPublicKey(newCert);
+ if (challs->pubKey == NULL) {
+ rv = ERROR_RETRIEVING_PUB_KEY_FOR_CHALL;
+ goto loser;
+ }
+ (*numChall)++;
+ rv = DO_CHALLENGE_RESPONSE;
+ break;
+ case crmfThisMessage:
+ /* There'd better be a PKIArchiveControl in this message */
+ if (!CRMF_CertRequestIsControlPresent(certReq,
+ crmfPKIArchiveOptionsControl)) {
+ rv = ERROR_NO_POP_FOR_PRIVKEY;
+ goto loser;
+ }
+ break;
+ default:
+ rv = ERROR_UNSUPPORTED_POPOPRIVKEY_TYPE;
+ goto loser;
+ }
+loser:
+ return rv;
+}
+
+ErrorCode
+doProofOfPossession(CGIVarTable *varTable, CRMFCertReqMsg *currReq,
+ CRMFCertRequest *certReq, CERTCertificate *newCert,
+ ChallengeCreationInfo *challs, int *numChall)
+{
+ CRMFPOPChoice popChoice;
+ ErrorCode rv = NO_ERROR;
+
+ popChoice = CRMF_CertReqMsgGetPOPType(currReq);
+ if (popChoice == crmfNoPOPChoice) {
+ rv = NO_POP_FOR_REQUEST;
+ goto loser;
+ }
+ switch (popChoice) {
+ case crmfSignature:
+ rv = verifySignature(varTable, currReq, certReq, newCert);
+ break;
+ case crmfKeyEncipherment:
+ rv = doChallengeResponse(varTable, currReq, certReq, newCert,
+ challs, numChall);
+ break;
+ case crmfRAVerified:
+ case crmfKeyAgreement:
+ default:
+ rv = UNSUPPORTED_POP;
+ goto loser;
+ }
+ loser:
+ return rv;
+}
+
+void
+convertB64ToJS(char *base64)
+{
+ int i;
+
+ for (i=0; base64[i] != '\0'; i++) {
+ if (base64[i] == '\n') {
+ printf ("\\n");
+ }else {
+ printf ("%c", base64[i]);
+ }
+ }
+}
+
+void
+formatChallenge(char *chall64, char *certRepContentDER,
+ ChallengeCreationInfo *challInfo, int numChalls)
+{
+ printf ("function respondToChallenge() {\n"
+ " var chalForm = document.chalForm;\n\n"
+ " chalForm.CertRepContent.value = '");
+ convertB64ToJS(certRepContentDER);
+ printf ("';\n"
+ " chalForm.ChallResponse.value = crypto.popChallengeResponse('");
+ convertB64ToJS(chall64);
+ printf("');\n"
+ " chalForm.submit();\n"
+ "}\n");
+
+}
+
+void
+spitOutChallenge(char *chall64, char *certRepContentDER,
+ ChallengeCreationInfo *challInfo, int numChalls,
+ char *nickname)
+{
+ int i;
+
+ spitOutHeaders();
+ printf("<html>\n"
+ "<head>\n"
+ "<title>Challenge Page</title>\n"
+ "<script language=\"JavaScript\">\n"
+ "<!--\n");
+ /* The JavaScript function actually gets defined within
+ * this function call
+ */
+ formatChallenge(chall64, certRepContentDER, challInfo, numChalls);
+ printf("// -->\n"
+ "</script>\n"
+ "</head>\n"
+ "<body onLoad='respondToChallenge()'>\n"
+ "<h1>Cartman is now responding to the Challenge "
+ "presented by the CGI</h1>\n"
+ "<form action='crmfcgi' method='post' name='chalForm'>\n"
+ "<input type='hidden' name=CertRepContent value=''>\n"
+ "<input type='hidden' name=ChallResponse value=''>\n");
+ for (i=0;i<numChalls; i++) {
+ printf("<input type='hidden' name='chal%d' value='%d'>\n",
+ i+1, challInfo[i].random);
+ }
+ printf("<input type='hidden' name='nickname' value='%s'>\n", nickname);
+ printf("</form>\n</body>\n</html>");
+}
+
+ErrorCode
+issueChallenge(CertResponseInfo *issuedCerts, int numCerts,
+ ChallengeCreationInfo *challInfo, int numChalls,
+ CERTCertificate *issuer, CGIVarTable *varTable)
+{
+ ErrorCode rv = NO_ERROR;
+ CMMFPOPODecKeyChallContent *chalContent = NULL;
+ int i;
+ SECStatus srv;
+ PRArenaPool *poolp;
+ CERTGeneralName *genName;
+ SECItem *challDER = NULL;
+ char *chall64, *certRepContentDER;
+
+ rv = createCMMFResponse(issuedCerts, numCerts, issuer,
+ &certRepContentDER);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ chalContent = CMMF_CreatePOPODecKeyChallContent();
+ if (chalContent == NULL) {
+ rv = ERROR_CREATING_EMPTY_CHAL_CONTENT;
+ goto loser;
+ }
+ poolp = PORT_NewArena(1024);
+ if (poolp == NULL) {
+ rv = OUT_OF_MEMORY;
+ goto loser;
+ }
+ genName = CERT_GetCertificateNames(issuer, poolp);
+ if (genName == NULL) {
+ rv = ERROR_EXTRACTING_GEN_NAME_FROM_ISSUER;
+ goto loser;
+ }
+ for (i=0;i<numChalls;i++) {
+ srv = CMMF_POPODecKeyChallContentSetNextChallenge(chalContent,
+ challInfo[i].random,
+ genName,
+ challInfo[i].pubKey,
+ varTable);
+ SECKEY_DestroyPublicKey(challInfo[i].pubKey);
+ if (srv != SECSuccess) {
+ rv = ERROR_SETTING_CHALLENGE;
+ goto loser;
+ }
+ }
+ challDER = SEC_ASN1EncodeItem(NULL, NULL, chalContent,
+ CMMFPOPODecKeyChallContentTemplate);
+ if (challDER == NULL) {
+ rv = ERROR_ENCODING_CHALL;
+ goto loser;
+ }
+ chall64 = BTOA_DataToAscii(challDER->data, challDER->len);
+ SECITEM_FreeItem(challDER, PR_TRUE);
+ if (chall64 == NULL) {
+ rv = ERROR_CONVERTING_CHALL_TO_BASE64;
+ goto loser;
+ }
+ spitOutChallenge(chall64, certRepContentDER, challInfo, numChalls,
+ getNickname(issuedCerts[0].cert));
+ loser:
+ return rv;
+}
+
+
+ErrorCode
+processRequest(CGIVarTable *varTable)
+{
+ CERTCertDBHandle *certdb;
+ SECKEYKeyDBHandle *keydb;
+ CRMFCertReqMessages *certReqs = NULL;
+ const char *crmfReq;
+ const char *caNickname;
+ CERTCertificate *caCert = NULL;
+ CertResponseInfo *issuedCerts = NULL;
+ CERTSubjectPublicKeyInfo spki = { 0 };
+ ErrorCode rv=NO_ERROR;
+ PRBool doChallengeResponse = PR_FALSE;
+ SECItem der = { 0 };
+ SECStatus srv;
+ CERTCertificateRequest oldCertReq = { 0 };
+ CRMFCertReqMsg **reqMsgs = NULL,*currReq = NULL;
+ CRMFCertRequest **reqs = NULL, *certReq = NULL;
+ CERTName subject = { 0 };
+ int numReqs,i;
+ ChallengeCreationInfo *challInfo=NULL;
+ int numChalls = 0;
+
+ certdb = CERT_GetDefaultCertDB();
+ keydb = SECKEY_GetDefaultKeyDB();
+ crmfReq = CGITableFindValue(varTable, "CRMFRequest");
+ if (crmfReq == NULL) {
+ rv = CGI_VAR_MISSING;
+ missingVar = "CRMFRequest";
+ goto loser;
+ }
+ caNickname = CGITableFindValue(varTable, "CANickname");
+ if (caNickname == NULL) {
+ rv = CGI_VAR_MISSING;
+ missingVar = "CANickname";
+ goto loser;
+ }
+ caCert = CERT_FindCertByNickname(certdb, caNickname);
+ if (caCert == NULL) {
+ rv = COULD_NOT_FIND_CA;
+ goto loser;
+ }
+ srv = ATOB_ConvertAsciiToItem(&der, crmfReq);
+ if (srv != SECSuccess) {
+ rv = BAD_ASCII_FOR_REQ;
+ goto loser;
+ }
+ certReqs = CRMF_CreateCertReqMessagesFromDER(der.data, der.len);
+ SECITEM_FreeItem(&der, PR_FALSE);
+ if (certReqs == NULL) {
+ rv = COULD_NOT_DECODE_REQS;
+ goto loser;
+ }
+ numReqs = CRMF_CertReqMessagesGetNumMessages(certReqs);
+ issuedCerts = PORT_ZNewArray(CertResponseInfo, numReqs);
+ challInfo = PORT_ZNewArray(ChallengeCreationInfo, numReqs);
+ if (issuedCerts == NULL || challInfo == NULL) {
+ rv = OUT_OF_MEMORY;
+ goto loser;
+ }
+ reqMsgs = PORT_ZNewArray(CRMFCertReqMsg*, numReqs);
+ reqs = PORT_ZNewArray(CRMFCertRequest*, numReqs);
+ if (reqMsgs == NULL || reqs == NULL) {
+ rv = OUT_OF_MEMORY;
+ goto loser;
+ }
+ for (i=0; i<numReqs; i++) {
+ currReq = reqMsgs[i] =
+ CRMF_CertReqMessagesGetCertReqMsgAtIndex(certReqs, i);
+ if (currReq == NULL) {
+ rv = ERROR_RETRIEVING_REQUEST_MSG;
+ goto loser;
+ }
+ certReq = reqs[i] = CRMF_CertReqMsgGetCertRequest(currReq);
+ if (certReq == NULL) {
+ rv = ERROR_RETRIEVING_CERT_REQUEST;
+ goto loser;
+ }
+ srv = CRMF_CertRequestGetCertTemplateSubject(certReq, &subject);
+ if (srv != SECSuccess) {
+ rv = ERROR_RETRIEVING_SUBJECT_FROM_REQ;
+ goto loser;
+ }
+ srv = CRMF_CertRequestGetCertTemplatePublicKey(certReq, &spki);
+ if (srv != SECSuccess) {
+ rv = ERROR_RETRIEVING_PUBLIC_KEY_FROM_REQ;
+ goto loser;
+ }
+ rv = initOldCertReq(&oldCertReq, &subject, &spki);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ rv = createNewCert(&issuedCerts[i].cert, &oldCertReq, currReq, certReq,
+ caCert, varTable);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ rv = doProofOfPossession(varTable, currReq, certReq, issuedCerts[i].cert,
+ challInfo, &numChalls);
+ if (rv != NO_ERROR) {
+ if (rv == DO_CHALLENGE_RESPONSE) {
+ doChallengeResponse = PR_TRUE;
+ } else {
+ goto loser;
+ }
+ }
+ CRMF_CertReqMsgGetID(currReq, &issuedCerts[i].certReqID);
+ CRMF_DestroyCertReqMsg(currReq);
+ CRMF_DestroyCertRequest(certReq);
+ }
+ if (doChallengeResponse) {
+ rv = issueChallenge(issuedCerts, numReqs, challInfo, numChalls, caCert,
+ varTable);
+ } else {
+ rv = issueCerts(issuedCerts, numReqs, caCert);
+ }
+ loser:
+ if (certReqs != NULL) {
+ CRMF_DestroyCertReqMessages(certReqs);
+ }
+ return rv;
+}
+
+ErrorCode
+processChallengeResponse(CGIVarTable *varTable, const char *certRepContent)
+{
+ SECItem binDER = { 0 };
+ SECStatus srv;
+ ErrorCode rv = NO_ERROR;
+ const char *clientResponse;
+ const char *formChalValue;
+ const char *nickname;
+ CMMFPOPODecKeyRespContent *respContent = NULL;
+ int numResponses,i;
+ long curResponse, expectedResponse;
+ char cgiChalVar[10];
+#ifdef WRITE_OUT_RESPONSE
+ SECItem certRepBinDER = { 0 };
+
+ ATOB_ConvertAsciiToItem(&certRepBinDER, certRepContent);
+ writeOutItem("challCertRepContent.der", &certRepBinDER);
+ PORT_Free(certRepBinDER.data);
+#endif
+ clientResponse = CGITableFindValue(varTable, "ChallResponse");
+ if (clientResponse == NULL) {
+ rv = REQ_CGI_VAR_NOT_PRESENT;
+ missingVar = "ChallResponse";
+ goto loser;
+ }
+ srv = ATOB_ConvertAsciiToItem(&binDER, clientResponse);
+ if (srv != SECSuccess) {
+ rv = ERROR_CONVERTING_RESP_FROM_CHALL_TO_BIN;
+ goto loser;
+ }
+ respContent = CMMF_CreatePOPODecKeyRespContentFromDER(binDER.data,
+ binDER.len);
+ SECITEM_FreeItem(&binDER, PR_FALSE);
+ binDER.data = NULL;
+ if (respContent == NULL) {
+ rv = ERROR_CREATING_KEY_RESP_FROM_DER;
+ goto loser;
+ }
+ numResponses = CMMF_POPODecKeyRespContentGetNumResponses(respContent);
+ for (i=0;i<numResponses;i++){
+ srv = CMMF_POPODecKeyRespContentGetResponse(respContent,i,&curResponse);
+ if (srv != SECSuccess) {
+ rv = ERROR_RETRIEVING_CLIENT_RESPONSE_TO_CHALLENGE;
+ goto loser;
+ }
+ sprintf(cgiChalVar, "chal%d", i+1);
+ formChalValue = CGITableFindValue(varTable, cgiChalVar);
+ if (formChalValue == NULL) {
+ rv = REQ_CGI_VAR_NOT_PRESENT;
+ missingVar = strdup(cgiChalVar);
+ goto loser;
+ }
+ sscanf(formChalValue, "%ld", &expectedResponse);
+ if (expectedResponse != curResponse) {
+ rv = ERROR_RETURNED_CHALL_NOT_VALUE_EXPECTED;
+ goto loser;
+ }
+ }
+ nickname = CGITableFindValue(varTable, "nickname");
+ if (nickname == NULL) {
+ rv = REQ_CGI_VAR_NOT_PRESENT;
+ missingVar = "nickname";
+ goto loser;
+ }
+ spitOutCMMFResponse(nickname, certRepContent);
+ loser:
+ if (respContent != NULL) {
+ CMMF_DestroyPOPODecKeyRespContent(respContent);
+ }
+ return rv;
+}
+
+int
+main()
+{
+ char *form_output = NULL;
+ int form_output_len, form_output_used;
+ CGIVarTable varTable = { 0 };
+ ErrorCode errNum = 0;
+ char *certRepContent;
+
+#ifdef ATTACH_CGI
+ /* Put an ifinite loop in here so I can attach to
+ * the process after the process is spun off
+ */
+ { int stupid = 1;
+ while (stupid);
+ }
+#endif
+
+ form_output_used = 0;
+ srand(time(NULL));
+ while (feof(stdin) == 0) {
+ if (form_output == NULL) {
+ form_output = PORT_NewArray(char, DEFAULT_ALLOC_SIZE+1);
+ form_output_len = DEFAULT_ALLOC_SIZE;
+ } else if ((form_output_used + DEFAULT_ALLOC_SIZE) >= form_output_len) {
+ form_output_len += DEFAULT_ALLOC_SIZE;
+ form_output = PORT_Realloc(form_output, form_output_len+1);
+ }
+ form_output_used += fread(&form_output[form_output_used], sizeof(char),
+ DEFAULT_ALLOC_SIZE, stdin);
+ }
+ ParseInputVariables(&varTable, form_output);
+ certRepContent = CGITableFindValue(&varTable, "CertRepContent");
+ if (certRepContent == NULL) {
+ errNum = initNSS(&varTable);
+ if (errNum != 0) {
+ goto loser;
+ }
+ errNum = processRequest(&varTable);
+ } else {
+ errNum = processChallengeResponse(&varTable, certRepContent);
+ }
+ if (errNum != NO_ERROR) {
+ goto loser;
+ }
+ goto done;
+loser:
+ dumpErrorMessage(errNum);
+done:
+ free (form_output);
+ return 0;
+}
+
diff --git a/security/nss/cmd/crmf-cgi/crmfcgi.html b/security/nss/cmd/crmf-cgi/crmfcgi.html
new file mode 100644
index 000000000..e91923ece
--- /dev/null
+++ b/security/nss/cmd/crmf-cgi/crmfcgi.html
@@ -0,0 +1,165 @@
+<!--
+ - The contents of this file are subject to the Mozilla Public
+ - License Version 1.1 (the "License"); you may not use this file
+ - except in compliance with the License. You may obtain a copy of
+ - the License at http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS
+ - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ - implied. See the License for the specific language governing
+ - rights and limitations under the License.
+ -
+ - The Original Code is the Netscape security libraries.
+ -
+ - The Initial Developer of the Original Code is Netscape
+ - Communications Corporation. Portions created by Netscape are
+ - Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ - Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the
+ - terms of the GNU General Public License Version 2 or later (the
+ - "GPL"), in which case the provisions of the GPL are applicable
+ - instead of those above. If you wish to allow use of your
+ - version of this file only under the terms of the GPL and not to
+ - allow others to use your version of this file under the MPL,
+ - indicate your decision by deleting the provisions above and
+ - replace them with the notice and other provisions required by
+ - the GPL. If you do not delete the provisions above, a recipient
+ - may use your version of this file under either the MPL or the
+ - GPL.
+ -->
+
+<html>
+<head>
+<title>CRMF Test Page for PSM</title>
+<script language=javascript>
+var request;
+//This variable must be set to the first value
+//in the select field "testType" in the form.
+var keyGenType="SigningOnlyRSA";
+
+var requestedDN = "CN=Javi CA Shack ID, O=NSS";
+
+function setTestType() {
+ var testType = document.crmfForm.testType;
+
+ keyGenType = testType.options[testType.selectedIndex].value;
+}
+
+function setRequest() {
+ with (document.crmfForm) {
+ CRMFRequest.value = request.request;
+ submit();
+ }
+}
+
+function generateSignAndEncryptRSARequest() {
+ request = crypto.generateCRMFRequest(requestedDN,
+ null, null, null, "setRequest()",
+ crypto.algorithms.rsa.keyEx.keySizes[0],
+ null, "rsa-dual-use");
+}
+
+function generateSigningOnlyRSARequest() {
+ request = crypto.generateCRMFRequest(requestedDN,null,null,null,"setRequest()",
+ crypto.algorithms.rsa.signing.keySizes[0],
+ null, "rsa-sign");
+}
+
+function generateEncryptionOnlyRSARequest() {
+ request = crypto.generateCRMFRequest(requestedDN, null, null, null, "setRequest()",
+ crypto.algorithms.rsa.keyEx.keySizes[0],
+ null, "rsa-ex");
+}
+
+function generateDualRSAKeys() {
+ request = crypto.generateCRMFRequest(requestedDN, null, null, null, "setRequest()",
+ crypto.algorithms.rsa.keyEx.keySizes[0],
+ null, "rsa-ex",
+ crypto.algorithms.rsa.signing.keySizes[0],
+ null, "rsa-sign");
+}
+
+function generateDSAKey() {
+ request = crypto.generateCRMFRequest(requestedDN, null, null, null, "setRequest()",
+ crypto.algorithms.dsa.keySizes[0],
+ null, "dsa-sign-nonrepudiation");
+}
+
+function processForm(form) {
+ with (form) {
+ if (typeof(crypto.version) == "undefined") {
+ alert('You must be running PSM in order to use this page.');
+ return false;
+ }
+ if (NSSDirectory.value == "") {
+ alert('You must provide a path for NSS to use.');
+ return false;
+ }
+ if (dbPassword.value == "") {
+ alert('You must provide a password for the certificate database.');
+ return false;
+ }
+ if (CANickname.value == "") {
+ alert('You must provide a CA Nickname to use.');
+ return false;
+ }
+ //Now do the correct key generation.
+ if (keyGenType == "SignAndEncryptRSA") {
+ generateSignAndEncryptRSARequest();
+ } else if (keyGenType == "SigningOnlyRSA") {
+ generateSigningOnlyRSARequest();
+ } else if (keyGenType == "EncryptionOnlyRSA") {
+ generateEncryptionOnlyRSARequest();
+ } else if (keyGenType == "DualRSAKeys") {
+ generateDualRSAKeys();
+ } else if (keyGenType == "DSAKeyGen") {
+ generateDSAKey();
+ }
+ }
+ return true;
+}
+</script>
+</head>
+<body>
+<h1><center>CRMF Test page for PSM</center></h1>
+This page is designed to be used in combination with the executable
+produced by ns/security/cmd/crmf-cgi in a CGI environment. In order
+to successfully use this page, modify its action to post to a a server
+where you have installed the crmfcgi executable and you'll be able to
+test the functionality.
+<hr>
+<form name="crmfForm" method=post action="http://www.cgi-site.com/cgi-bin/crmfcgi">
+<h2>Certificate Database information</h2>
+First, enter all the information for the CGI to use for initializing
+NSS. The CGI will use the directory entered below as the directory
+where to look for the certificate and key databases.
+<pre>
+Path for NSS Config: <input size=40 type="text" name="NSSDirectory">
+</pre>
+Enter the password for the certificate database found in the direcotry
+above.
+<pre>
+Database Password: <input type="password" name="dbPassword" size=40>
+</pre>
+Now enter the nickname of the certificate to use for signing the
+certificate issued during this test.
+<pre>
+CA Nickname: <input size=40 type="text" name="CANickname">
+</pre>
+<h2>Now, figure out which type of key generation you want to test:</h2>
+<select name="testType" onChange="setTestType()">`
+<option value="SigningOnlyRSA">Signing Only-RSA
+<option value="EncryptionOnlyRSA">Encryption Only-RSA
+<option value="SignAndEncryptRSA">Sign and Encrypt Single Key -RSA
+<option value="DualRSAKeys">Dual Keys-RSA
+<option value="DSAKeyGen">DSA Key Gen
+</select>
+<input type="hidden" name=CRMFRequest value="">
+<hr>
+<input type="button" value="OK" onclick="processForm(document.crmfForm)">
+</form>
+</body>
+</html>
diff --git a/security/nss/cmd/crmf-cgi/manifest.mn b/security/nss/cmd/crmf-cgi/manifest.mn
new file mode 100644
index 000000000..3a3496327
--- /dev/null
+++ b/security/nss/cmd/crmf-cgi/manifest.mn
@@ -0,0 +1,61 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+MODULE = sectools
+
+EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ crmfcgi.c \
+ $(NULL)
+
+
+REQUIRES = nss dbm seccmd
+
+ifdef ATTACH_CGI
+DEFINES += -DATTACH_CGI
+endif
+
+ifdef WRITE_OUT_RESPONSE
+DEFINES += -DWRITE_OUT_RESPONSE
+endif
+
+PROGRAM = crmfcgi
+
+USE_STATIC_LIBS = 1
+
+INCLUDES =
+
+DEFINES = -DNSPR20
diff --git a/security/nss/cmd/crmftest/Makefile b/security/nss/cmd/crmftest/Makefile
new file mode 100644
index 000000000..5df669763
--- /dev/null
+++ b/security/nss/cmd/crmftest/Makefile
@@ -0,0 +1,99 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include config.mk
+
+ifeq ($(OS_TARGET)$(OS_RELEASE), AIX4.2)
+OS_LIBS += -lsvld
+endif
+
+ifeq ($(OS_TARGET)$(OS_RELEASE), SunOS5.6)
+OS_LIBS += -ldl -lxnet -lposix4 -lsocket -lnsl
+endif
+
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+EXTRA_LIBS += $(DIST)/lib/crmf.lib
+else
+EXTRA_LIBS += $(DIST)/lib/libcrmf.$(LIB_SUFFIX)
+endif
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+LDDIST = $(DIST)/lib
+
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+EXTRA_LIBS += $(LDDIST)/sectool.lib
+endif
+
+lame:
+ echo $(CPU_ARCH)
+
+include ../platrules.mk
diff --git a/security/nss/cmd/crmftest/config.mk b/security/nss/cmd/crmftest/config.mk
new file mode 100644
index 000000000..7343609f8
--- /dev/null
+++ b/security/nss/cmd/crmftest/config.mk
@@ -0,0 +1,43 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#
+# Override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(PROGRAM)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+LIBRARY =
+
diff --git a/security/nss/cmd/crmftest/manifest.mn b/security/nss/cmd/crmftest/manifest.mn
new file mode 100644
index 000000000..cd5275094
--- /dev/null
+++ b/security/nss/cmd/crmftest/manifest.mn
@@ -0,0 +1,53 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+DEPTH = .
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ testcrmf.c \
+ $(NULL)
+
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = dbm
+
+PROGRAM = crmftest
+
diff --git a/security/nss/cmd/crmftest/testcrmf.c b/security/nss/cmd/crmftest/testcrmf.c
new file mode 100644
index 000000000..e9bb08bdb
--- /dev/null
+++ b/security/nss/cmd/crmftest/testcrmf.c
@@ -0,0 +1,1533 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "crmf.h"
+#include "secrng.h"
+#include "secpkcs5.h"
+#include "pk11func.h"
+#include "pkcs11.h"
+#include "secmod.h"
+#include "secmodi.h"
+#include "key.h"
+#include "prio.h"
+#include "pqggen.h"
+#include "cmmf.h"
+#include "seccomon.h"
+#include "secmod.h"
+#include "prlock.h"
+#include "secmodi.h"
+#include "pkcs11.h"
+#include "pk11func.h"
+#include "secitem.h"
+#include "key.h"
+#include "rsa.h"
+#include "secpkcs5.h"
+#include "secasn1.h"
+#include "sechash.h"
+#include "cert.h"
+#include "secerr.h"
+#include <stdio.h>
+#include "prprf.h"
+#if !defined(XP_UNIX) && !defined(LINUX)
+extern int getopt(int, char **, char*);
+extern char *optarg;
+#endif
+#define MAX_KEY_LEN 512
+
+int64 notBefore;
+char *personalCert = NULL;
+char *recoveryEncrypter = NULL;
+char *caCertName = NULL;
+
+CERTCertDBHandle *db;
+SECKEYKeyDBHandle *keydb;
+
+void
+debug_test(SECItem *src, char *filePath)
+{
+ PRFileDesc *fileDesc;
+
+ fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ printf ("Could not cretae file %s.\n", filePath);
+ return;
+ }
+ PR_Write(fileDesc, src->data, src->len);
+
+}
+
+SECStatus
+get_serial_number(long *dest)
+{
+ RNGContext *rng;
+ SECStatus rv;
+
+ if (dest == NULL) {
+ return SECFailure;
+ }
+ rng = RNG_CreateContext();
+ if (rng == NULL) {
+ *dest = 0;
+ return SECFailure;
+ }
+ rv = RNG_GenerateRandomBytes(rng, (void*)dest, sizeof(long));
+ RNG_DestroyContext(rng, PR_TRUE);
+ return SECSuccess;
+}
+
+char *
+promptForPassword (PK11SlotInfo *slot, PRBool retry, void *cx)
+{
+ char passWord[80];
+ char *retPass = NULL;
+
+ if (retry) {
+ printf ("Incorrect password. Please re-enter the password.\n");
+ }
+ printf ("WARNING: Password will be echoed to the screen.\n");
+ printf ("Please enter the password for slot \"%s\":",
+ PK11_GetTokenName(slot));
+ scanf ("%s", passWord);
+ retPass = PORT_Strdup(passWord);
+ return retPass;
+}
+
+PK11RSAGenParams *
+GetRSAParams(void)
+{
+ PK11RSAGenParams *rsaParams;
+
+ rsaParams = PORT_ZNew(PK11RSAGenParams);
+
+ if (rsaParams == NULL)
+ return NULL;
+
+ rsaParams->keySizeInBits = MAX_KEY_LEN;
+ rsaParams->pe = 0x1001;
+
+ return rsaParams;
+
+}
+
+SECStatus
+SetSlotPassword(PK11SlotInfo *slot)
+{
+ char userPin[80];
+
+ printf ("Initialization of PIN's for your Database.\n");
+ printf ("------------------------------------------\n");
+ printf ("Please enter the PIN's for your Database.\n");
+ printf ("Warning: ALL PIN'S WILL BE ECHOED TO SCREEN!!!\n");
+ printf ("Now enter the PIN for the user: ");
+ scanf ("%s", userPin);
+ return PK11_InitPin (slot, NULL, userPin);
+}
+
+PQGParams*
+GetDSAParams(void)
+{
+ PQGParams *params = NULL;
+ PQGVerify *vfy = NULL;
+
+ SECStatus rv;
+
+ rv = PQG_ParamGen(0, &params, &vfy);
+ if (rv != SECSuccess) {
+ return NULL;
+ }
+ PQG_DestroyVerify(vfy);
+ return params;
+}
+
+CERTSubjectPublicKeyInfo *
+GetSubjectPubKeyInfo(SECKEYPrivateKey **destPrivKey,
+ SECKEYPublicKey **destPubKey) {
+ CERTSubjectPublicKeyInfo *spki = NULL;
+ SECKEYPrivateKey *privKey = NULL;
+ SECKEYPublicKey *pubKey = NULL;
+ PK11SlotInfo *keySlot = NULL;
+ PK11SlotInfo *cryptoSlot = NULL;
+ PK11RSAGenParams *rsaParams = NULL;
+ PQGParams *dsaParams = NULL;
+
+ keySlot = PK11_GetInternalKeySlot();
+ PK11_Authenticate(keySlot, PR_FALSE, NULL);
+ cryptoSlot = PK11_GetInternalSlot();
+ PK11_Authenticate(cryptoSlot, PR_FALSE, NULL);
+ PK11_FreeSlot(cryptoSlot);
+ rsaParams = GetRSAParams();
+ privKey = PK11_GenerateKeyPair(keySlot, CKM_RSA_PKCS_KEY_PAIR_GEN,
+ (void*)rsaParams, &pubKey, PR_FALSE,
+ PR_FALSE, NULL);
+/* dsaParams = GetDSAParams();
+ if (dsaParams == NULL) {
+ PK11_FreeSlot(keySlot);
+ return NULL;
+ }
+ privKey = PK11_GenerateKeyPair(keySlot, CKM_DSA_KEY_PAIR_GEN,
+ (void*)dsaParams, &pubKey, PR_FALSE,
+ PR_FALSE, NULL);*/
+ PK11_FreeSlot(keySlot);
+ if (privKey == NULL || pubKey == NULL) {
+ if (pubKey) {
+ SECKEY_DestroyPublicKey(pubKey);
+ }
+ if (privKey) {
+ SECKEY_DestroyPrivateKey(privKey);
+ }
+ return NULL;
+ }
+
+ spki = SECKEY_CreateSubjectPublicKeyInfo(pubKey);
+ *destPrivKey = privKey;
+ *destPubKey = pubKey;
+ return spki;
+}
+
+
+SECStatus
+InitPKCS11(void)
+{
+ PK11SlotInfo *cryptoSlot, *keySlot;
+
+ PK11_SetPasswordFunc(promptForPassword);
+
+ cryptoSlot = PK11_GetInternalSlot();
+ keySlot = PK11_GetInternalKeySlot();
+
+ if (PK11_NeedUserInit(cryptoSlot) && PK11_NeedLogin(cryptoSlot)) {
+ if (SetSlotPassword (cryptoSlot) != SECSuccess) {
+ printf ("Initializing the PIN's failed.\n");
+ return SECFailure;
+ }
+ }
+
+ if (PK11_NeedUserInit(keySlot) && PK11_NeedLogin(keySlot)) {
+ if (SetSlotPassword (keySlot) != SECSuccess) {
+ printf ("Initializing the PIN's failed.\n");
+ return SECFailure;
+ }
+ }
+
+ PK11_FreeSlot(cryptoSlot);
+ PK11_FreeSlot(keySlot);
+ return SECSuccess;
+}
+
+
+void
+WriteItOut (void *arg, const char *buf, unsigned long len)
+{
+ PRFileDesc *fileDesc = (PRFileDesc*)arg;
+
+ PR_Write(fileDesc, (void*)buf, len);
+}
+
+SECItem
+GetRandomBitString(void)
+{
+#define NUM_BITS 800
+#define BITS_IN_BYTE 8
+ SECItem bitString;
+ int numBytes = NUM_BITS/BITS_IN_BYTE;
+ unsigned char *bits = PORT_ZNewArray(unsigned char, numBytes);
+ RNGContext *rng;
+
+ rng = RNG_CreateContext();
+ RNG_GenerateRandomBytes(rng, (void*)bits, numBytes);
+ RNG_DestroyContext(rng, PR_TRUE);
+ bitString.data = bits;
+ bitString.len = NUM_BITS;
+ bitString.type = siBuffer;
+ return bitString;
+}
+
+CRMFCertExtCreationInfo*
+GetExtensions(void)
+{
+ CRMFCertExtCreationInfo *extInfo;
+ CRMFCertExtension *currExt;
+ CRMFCertExtension *extension;
+ SECItem data;
+ PRBool prFalse = PR_FALSE;
+ unsigned char keyUsage[4];
+
+ data.len = 4;
+ data.data = keyUsage;
+ keyUsage[0] = 0x03;
+ keyUsage[1] = 0x02;
+ keyUsage[2] = 0x07;
+ keyUsage[3] = KU_DIGITAL_SIGNATURE;
+ extension = CRMF_CreateCertExtension(SEC_OID_X509_KEY_USAGE,prFalse,
+ &data);
+ extInfo = PORT_ZNew(CRMFCertExtCreationInfo);
+ extInfo->numExtensions = 1;
+ extInfo->extensions = PORT_ZNewArray(CRMFCertExtension*, 1);
+ extInfo->extensions[0] = extension;
+ return extInfo;
+}
+
+void
+FreeExtInfo(CRMFCertExtCreationInfo *extInfo)
+{
+ int i;
+
+ for (i=0; i<extInfo->numExtensions; i++) {
+ CRMF_DestroyCertExtension(extInfo->extensions[i]);
+ }
+ PORT_Free(extInfo->extensions);
+ PORT_Free(extInfo);
+}
+
+int
+CreateCertRequest (CRMFCertRequest **inCertReq, SECKEYPrivateKey **privKey,
+ SECKEYPublicKey **pubKey)
+{
+ long serialNumber;
+ long version = 3;
+ char *issuerStr = PORT_Strdup ("CN=Javi's CA Shack, O=Information Systems");
+ char *subjectStr = PORT_Strdup ("CN=Javi's CA Shack ID, O=Engineering, "
+ "C=US");
+ CRMFCertRequest *certReq;
+ SECAlgorithmID * algID;
+ CERTName *issuer, *subject;
+ CRMFValidityCreationInfo validity;
+ CERTSubjectPublicKeyInfo *spki;
+ SECStatus rv;
+ SECOidTag tag, tag2;
+ SECItem issuerUID, subjectUID;
+ CRMFCertExtCreationInfo *extInfo;
+ CRMFEncryptedKey *encKey;
+ CERTCertificate *caCert;
+ CRMFPKIArchiveOptions *pkiArchOpt;
+
+ *inCertReq = NULL;
+ certReq = CRMF_CreateCertRequest(0x0ff02345);
+ if (certReq == NULL) {
+ printf ("Could not initialize a certificate request.\n");
+ return 1;
+ }
+ rv = CRMF_CertRequestSetTemplateField (certReq, crmfVersion, (void*)(&version));
+ if (rv != SECSuccess) {
+ printf("Could not add the version number to the "
+ "Certificate Request.\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 2;
+ }
+
+ if (get_serial_number(&serialNumber) != SECSuccess) {
+ printf ("Could not generate a serial number for cert request.\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 3;
+ }
+
+ rv = CRMF_CertRequestSetTemplateField (certReq, crmfSerialNumber,
+ (void*)(&serialNumber));
+ if (rv != SECSuccess) {
+ printf ("Could not add serial number to certificate template\n.");
+ CRMF_DestroyCertRequest(certReq);
+ return 4;
+ }
+
+ issuer = CERT_AsciiToName(issuerStr);
+ if (issuer == NULL) {
+ printf ("Could not create CERTName structure from %s.\n", issuerStr);
+ CRMF_DestroyCertRequest(certReq);
+ return 5;
+ }
+ rv = CRMF_CertRequestSetTemplateField (certReq, crmfIssuer, (void*) issuer);
+ PORT_Free(issuerStr);
+ CERT_DestroyName(issuer);
+ if (rv != SECSuccess) {
+ printf ("Could not add issuer to cert template\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 6;
+ }
+
+ subject = CERT_AsciiToName(subjectStr);
+ if (subject == NULL) {
+ printf ("Could not create CERTName structure from %s.\n", subjectStr);
+ CRMF_DestroyCertRequest(certReq);
+ return 7;
+ }
+ PORT_Free(subjectStr);
+ rv = CRMF_CertRequestSetTemplateField (certReq, crmfSubject, (void*)subject);
+ if (rv != SECSuccess) {
+ printf ("Could not add subject to cert template\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 8;
+ }
+ CERT_DestroyName(subject);
+
+ algID =
+ SEC_PKCS5CreateAlgorithmID (SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC,
+ NULL, 1);
+ if (algID == NULL) {
+ printf ("Couldn't create algorithm ID\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 9;
+ }
+ rv = CRMF_CertRequestSetTemplateField(certReq, crmfSigningAlg, (void*)algID);
+ SECOID_DestroyAlgorithmID(algID, PR_TRUE);
+ if (rv != SECSuccess) {
+ printf ("Could not add the signing algorithm to the cert template.\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 10;
+ }
+
+ validity.notBefore = &notBefore;
+ validity.notAfter = NULL;
+ notBefore = PR_Now();
+ rv = CRMF_CertRequestSetTemplateField(certReq, crmfValidity,(void*)(&validity));
+ if (rv != SECSuccess) {
+ printf ("Could not add validity to cert template\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 11;
+ }
+
+ spki = GetSubjectPubKeyInfo(privKey, pubKey);
+ if (spki == NULL) {
+ printf ("Could not create a Subject Public Key Info to add\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 12;
+ }
+ rv = CRMF_CertRequestSetTemplateField(certReq, crmfPublicKey, (void*)spki);
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ if (rv != SECSuccess) {
+ printf ("Could not add the public key to the template\n");
+ CRMF_DestroyCertRequest(certReq);
+ return 13;
+ }
+
+ caCert =
+ CERT_FindCertByNickname(CERT_GetDefaultCertDB(),
+ caCertName);
+ if (caCert == NULL) {
+ printf ("Could not find the certificate for %s\n", caCertName);
+ CRMF_DestroyCertRequest(certReq);
+ return 50;
+ }
+
+ issuerUID = GetRandomBitString();
+ subjectUID = GetRandomBitString();
+ CRMF_CertRequestSetTemplateField(certReq,crmfIssuerUID, (void*)&issuerUID);
+ CRMF_CertRequestSetTemplateField(certReq,crmfSubjectUID, (void*)&subjectUID);
+ PORT_Free(issuerUID.data);
+ PORT_Free(subjectUID.data);
+ extInfo = GetExtensions();
+ CRMF_CertRequestSetTemplateField(certReq, crmfExtension, (void*)extInfo);
+ FreeExtInfo(extInfo);
+ encKey = CRMF_CreateEncryptedKeyWithEncryptedValue(*privKey, caCert);
+ CERT_DestroyCertificate(caCert);
+ if (encKey == NULL) {
+ printf ("Could not create Encrypted Key with Encrypted Value.\n");
+ return 14;
+ }
+ pkiArchOpt = CRMF_CreatePKIArchiveOptions(crmfEncryptedPrivateKey, encKey);
+ CRMF_DestroyEncryptedKey(encKey);
+ if (pkiArchOpt == NULL) {
+ printf ("Could not create PKIArchiveOptions.\n");
+ return 15;
+ }
+ rv = CRMF_CertRequestSetPKIArchiveOptions(certReq, pkiArchOpt);
+ CRMF_DestroyPKIArchiveOptions(pkiArchOpt);
+ if (rv != SECSuccess) {
+ printf ("Could not add the PKIArchiveControl to Cert Request.\n");
+ return 16;
+ }
+ *inCertReq = certReq;
+ return 0;
+}
+
+int
+Encode (CRMFCertReqMsg *inCertReq,
+ CRMFCertReqMsg *secondReq, char *configdir)
+{
+#define PATH_LEN 150
+#define CRMF_FILE "CertReqMessages.der"
+ char filePath[PATH_LEN];
+ PRFileDesc *fileDesc;
+ SECStatus rv;
+ int irv = 0;
+ CRMFCertReqMsg *msgArr[3];
+ CRMFCertReqMsg *newMsg;
+
+ PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, CRMF_FILE);
+ fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ printf ("Could not open file %s\n", filePath);
+ irv = 14;
+ goto finish;
+ }
+/* rv = CRMF_EncodeCertReqMsg (inCertReq, WriteItOut, (void*)fileDesc);*/
+ msgArr[0] = inCertReq;
+ msgArr[1] = secondReq;
+ msgArr[2] = NULL;
+ rv = CRMF_EncodeCertReqMessages(msgArr, WriteItOut, (void*)fileDesc);
+ if (rv != SECSuccess) {
+ printf ("An error occurred while encoding.\n");
+ irv = 15;
+ goto finish;
+ }
+ finish:
+ PR_Close(fileDesc);
+ return irv;
+}
+
+int
+AddProofOfPossession(CRMFCertReqMsg *certReqMsg, SECKEYPrivateKey *privKey,
+ SECKEYPublicKey *pubKey, CRMFPOPChoice inPOPChoice)
+{
+
+ switch(inPOPChoice){
+ case crmfSignature:
+ CRMF_CertReqMsgSetSignaturePOP(certReqMsg, privKey, pubKey, NULL, NULL,
+ NULL);
+ break;
+ case crmfRAVerified:
+ CRMF_CertReqMsgSetRAVerifiedPOP(certReqMsg);
+ break;
+ case crmfKeyEncipherment:
+ CRMF_CertReqMsgSetKeyEnciphermentPOP(certReqMsg,
+ crmfSubsequentMessage,
+ crmfChallengeResp, NULL);
+ break;
+ case crmfKeyAgreement:
+ {
+ SECItem pendejo;
+ unsigned char lame[] = { 0xf0, 0x0f, 0xf0, 0x0f, 0xf0 };
+
+ pendejo.data = lame;
+ pendejo.len = 5;
+
+ CRMF_CertReqMsgSetKeyAgreementPOP(certReqMsg, crmfThisMessage,
+ crmfNoSubseqMess, &pendejo);
+ }
+ break;
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+#define BUFF_SIZE 150
+
+int
+Decode(char *configdir)
+{
+ char filePath[PATH_LEN];
+ unsigned char buffer[BUFF_SIZE];
+ char *asn1Buff;
+ PRFileDesc *fileDesc;
+ PRInt32 fileLen = 0;
+ PRInt32 bytesRead;
+ CRMFCertReqMsg *certReqMsg;
+ CRMFCertRequest *certReq;
+ CRMFGetValidity validity= {NULL, NULL};
+ CRMFCertReqMessages *certReqMsgs;
+ int numMsgs, i;
+ long lame;
+
+ PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, CRMF_FILE);
+ fileDesc = PR_Open(filePath, PR_RDONLY, 0644);
+ while (1) {
+ bytesRead = PR_Read(fileDesc, buffer, BUFF_SIZE);
+ if (bytesRead <= 0) break;
+ fileLen += bytesRead;
+ }
+ if (bytesRead < 0) {
+ printf ("Error while getting the length of the file %s\n", filePath);
+ return 200;
+ }
+
+ PR_Close(fileDesc);
+ fileDesc = PR_Open(filePath, PR_RDONLY, 0644);
+ asn1Buff = PORT_ZNewArray(char, fileLen);
+ bytesRead = PR_Read(fileDesc, asn1Buff, fileLen);
+ if (bytesRead != fileLen) {
+ printf ("Error while reading in the contents of %s\n", filePath);
+ return 201;
+ }
+ /*certReqMsg = CRMF_CreateCertReqMsgFromDER(asn1Buff, fileLen);
+ if (certReqMsg == NULL) {
+ printf ("Error while decoding the CertReqMsg\n");
+ return 202;
+ }
+ certReq = CRMF_CertReqMsgGetCertRequest(certReqMsg);
+*/
+ certReqMsgs = CRMF_CreateCertReqMessagesFromDER(asn1Buff, fileLen);
+ if (certReqMsgs == NULL) {
+ printf ("Error decoding CertReqMessages.\n");
+ return 202;
+ }
+ numMsgs = CRMF_CertReqMessagesGetNumMessages(certReqMsgs);
+ if (numMsgs <= 0) {
+ printf ("WARNING: The DER contained %d messages.\n", numMsgs);
+ }
+ for (i=0; i < numMsgs; i++) {
+ certReqMsg = CRMF_CertReqMessagesGetCertReqMsgAtIndex(certReqMsgs, i);
+ if (certReqMsg == NULL) {
+ printf ("ERROR: Could not access the message at index %d of %s\n",
+ i, filePath);
+ }
+ CRMF_CertReqMsgGetID(certReqMsg, &lame);
+ certReq = CRMF_CertReqMsgGetCertRequest(certReqMsg);
+ CRMF_CertRequestGetCertTemplateValidity(certReq, &validity);
+ CRMF_DestroyGetValidity(&validity);
+ CRMF_DestroyCertRequest(certReq);
+ CRMF_DestroyCertReqMsg(certReqMsg);
+ }
+ CRMF_DestroyCertReqMessages(certReqMsgs);
+ PORT_Free(asn1Buff);
+ return 0;
+}
+
+void
+GetBitsFromFile(char *filePath, SECItem *fileBits)
+{
+ PRFileDesc *fileDesc;
+ int bytesRead, fileLen=0;
+ char buffer[BUFF_SIZE], *asn1Buf;
+
+ fileDesc = PR_Open(filePath, PR_RDONLY, 0644);
+ while (1) {
+ bytesRead = PR_Read(fileDesc, buffer, BUFF_SIZE);
+ if (bytesRead <= 0) break;
+ fileLen += bytesRead;
+ }
+ if (bytesRead < 0) {
+ printf ("Error while getting the length of file %s.\n", filePath);
+ goto loser;
+ }
+ PR_Close(fileDesc);
+
+ fileDesc = PR_Open(filePath, PR_RDONLY, 0644);
+ asn1Buf = PORT_ZNewArray(char, fileLen);
+ if (asn1Buf == NULL) {
+ printf ("Out of memory in function GetBitsFromFile\n");
+ goto loser;
+ }
+ bytesRead = PR_Read(fileDesc, asn1Buf, fileLen);
+ if (bytesRead != fileLen) {
+ printf ("Error while reading the contents of %s\n", filePath);
+ goto loser;
+ }
+ fileBits->data = (unsigned char*)asn1Buf;
+ fileBits->len = fileLen;
+ return;
+ loser:
+ if (asn1Buf) {
+ PORT_Free(asn1Buf);
+ }
+ fileBits->data = NULL;
+ fileBits->len = 0;
+}
+
+int
+DecodeCMMFCertRepContent(char *derFile)
+{
+ int fileLen=0;
+ char *asn1Buf;
+ SECItem fileBits;
+ CMMFCertRepContent *certRepContent;
+
+
+ GetBitsFromFile(derFile, &fileBits);
+ if (fileBits.data == NULL) {
+ printf("Could not get bits from file %s\n", derFile);
+ return 304;
+ }
+ asn1Buf = (char*)fileBits.data;
+ fileLen = fileBits.len;
+ certRepContent = CMMF_CreateCertRepContentFromDER(db, asn1Buf, fileLen);
+ if (certRepContent == NULL) {
+ printf ("Error while decoding %s\n", derFile);
+ return 303;
+ }
+ CMMF_DestroyCertRepContent(certRepContent);
+ PORT_Free(asn1Buf);
+ return 0;
+}
+
+int
+DoCMMFStuff(char *configdir)
+{
+ CMMFCertResponse *certResp=NULL, *certResp2=NULL, *certResponses[3];
+ CMMFCertRepContent *certRepContent=NULL;
+ CERTCertificate *cert=NULL, *caCert=NULL;
+ CERTCertList *list=NULL;
+ PRFileDesc *fileDesc=NULL;
+ char filePath[PATH_LEN];
+ int rv = 0;
+ long random;
+ CMMFKeyRecRepContent *repContent=NULL;
+ SECKEYPrivateKey *privKey = NULL;
+ SECKEYPublicKey *caPubKey;
+ SECStatus srv;
+ SECItem fileBits;
+
+ certResp = CMMF_CreateCertResponse(0xff123);
+ CMMF_CertResponseSetPKIStatusInfoStatus(certResp, cmmfGranted);
+ cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), personalCert);
+ if (cert == NULL) {
+ printf ("Could not find the certificate for %s\n", personalCert);
+ rv = 416;
+ goto finish;
+ }
+ CMMF_CertResponseSetCertificate(certResp, cert);
+ certResp2 = CMMF_CreateCertResponse(0xff122);
+ CMMF_CertResponseSetPKIStatusInfoStatus(certResp2, cmmfGranted);
+ CMMF_CertResponseSetCertificate(certResp2, cert);
+
+ certResponses[0] = certResp;
+ certResponses[1] = NULL;
+ certResponses[2] = NULL;
+
+ certRepContent = CMMF_CreateCertRepContent();
+ CMMF_CertRepContentSetCertResponses(certRepContent, certResponses, 1);
+
+ list = CERT_GetCertChainFromCert(cert, PR_Now(), certUsageEmailSigner);
+ CMMF_CertRepContentSetCAPubs(certRepContent, list);
+
+ PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, "CertRepContent.der");
+ fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ printf ("Could not open file %s\n", filePath);
+ rv = 400;
+ goto finish;
+ }
+
+ srv = CMMF_EncodeCertRepContent(certRepContent, WriteItOut,
+ (void*)fileDesc);
+ PORT_Assert (srv == SECSuccess);
+ PR_Close(fileDesc);
+ rv = DecodeCMMFCertRepContent(filePath);
+ if (rv != 0) {
+ goto finish;
+ }
+ random = 0xa4e7;
+ caCert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(),
+ caCertName);
+ if (caCert == NULL) {
+ printf ("Could not get the certifcate for %s\n", caCertName);
+ rv = 411;
+ goto finish;
+ }
+ repContent = CMMF_CreateKeyRecRepContent();
+ if (repContent == NULL) {
+ printf ("Could not allocate a CMMFKeyRecRepContent structure\n");
+ rv = 407;
+ goto finish;
+ }
+ srv = CMMF_KeyRecRepContentSetPKIStatusInfoStatus(repContent,
+ cmmfGrantedWithMods);
+ if (srv != SECSuccess) {
+ printf ("Error trying to set PKIStatusInfo for "
+ "CMMFKeyRecRepContent.\n");
+ rv = 406;
+ goto finish;
+ }
+ srv = CMMF_KeyRecRepContentSetNewSignCert(repContent, cert);
+ if (srv != SECSuccess) {
+ printf ("Error trying to set the new signing certificate for "
+ "key recovery\n");
+ rv = 408;
+ goto finish;
+ }
+ srv = CMMF_KeyRecRepContentSetCACerts(repContent, list);
+ if (srv != SECSuccess) {
+ printf ("Errory trying to add the list of CA certs to the "
+ "CMMFKeyRecRepContent structure.\n");
+ rv = 409;
+ goto finish;
+ }
+ privKey = PK11_FindKeyByAnyCert(cert, NULL);
+ if (privKey == NULL) {
+ printf ("Could not get the private key associated with the\n"
+ "certificate %s\n", personalCert);
+ rv = 410;
+ goto finish;
+ }
+ caPubKey = CERT_ExtractPublicKey(caCert);
+ if (caPubKey == NULL) {
+ printf ("Could not extract the public from the "
+ "certificate for \n%s\n", caCertName);
+ rv = 412;
+ goto finish;
+ }
+ CERT_DestroyCertificate(caCert);
+ caCert = NULL;
+ srv = CMMF_KeyRecRepContentSetCertifiedKeyPair(repContent, cert, privKey,
+ caPubKey);
+ SECKEY_DestroyPrivateKey(privKey);
+ SECKEY_DestroyPublicKey(caPubKey);
+ if (srv != SECSuccess) {
+ printf ("Could not set the Certified Key Pair\n");
+ rv = 413;
+ goto finish;
+ }
+ PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir,
+ "KeyRecRepContent.der");
+ fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ printf ("Could not open file %s\n", filePath);
+ rv = 414;
+ goto finish;
+ }
+
+ srv = CMMF_EncodeKeyRecRepContent(repContent, WriteItOut,
+ (void*)fileDesc);
+ PORT_Assert (srv == SECSuccess);
+ PR_Close(fileDesc);
+ CMMF_DestroyKeyRecRepContent(repContent);
+ GetBitsFromFile(filePath, &fileBits);
+ repContent =
+ CMMF_CreateKeyRecRepContentFromDER(db, (const char *) fileBits.data,
+ fileBits.len);
+ if (repContent == NULL) {
+ printf ("ERROR: CMMF_CreateKeyRecRepContentFromDER failed on file:\n"
+ "\t%s\n", filePath);
+ rv = 415;
+ goto finish;
+ }
+ finish:
+ if (repContent) {
+ CMMF_DestroyKeyRecRepContent(repContent);
+ }
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+ if (list) {
+ CERT_DestroyCertList(list);
+ }
+ if (certResp) {
+ CMMF_DestroyCertResponse(certResp);
+ }
+ if (certResp2) {
+ CMMF_DestroyCertResponse(certResp2);
+ }
+ if (certRepContent) {
+ CMMF_DestroyCertRepContent(certRepContent);
+ }
+ return rv;
+}
+
+static CK_MECHANISM_TYPE
+mapWrapKeyType(KeyType keyType)
+{
+ switch (keyType) {
+ case rsaKey:
+ return CKM_RSA_PKCS;
+ default:
+ break;
+ }
+ return CKM_INVALID_MECHANISM;
+}
+
+#define KNOWN_MESSAGE_LENGTH 20 /*160 bits*/
+
+int
+DoKeyRecovery(char *configdir, SECKEYPrivateKey *privKey)
+{
+ SECKEYPublicKey *pubKey;
+ PK11SlotInfo *slot;
+ CK_OBJECT_HANDLE id;
+ CK_MECHANISM mech = { CKM_INVALID_MECHANISM, NULL, 0};
+ unsigned char *known_message = (unsigned char*)"Known Crypto Message";
+ unsigned char plaintext[KNOWN_MESSAGE_LENGTH];
+ char filePath[PATH_LEN];
+ CK_RV crv;
+ unsigned char *ciphertext;
+ CK_ULONG max_bytes_encrypted, bytes_encrypted;
+ unsigned char *text_compared;
+ CK_ULONG bytes_compared, bytes_decrypted;
+ SECKEYPrivateKey *unwrappedPrivKey, *caPrivKey;
+ CMMFKeyRecRepContent *keyRecRep;
+ SECStatus rv;
+ CERTCertificate *caCert, *myCert;
+ SECKEYPublicKey *caPubKey;
+ PRFileDesc *fileDesc;
+ SECItem fileBits, nickname;
+ CMMFCertifiedKeyPair *certKeyPair;
+
+ /*caCert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(),
+ caCertName);*/
+ myCert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), personalCert);
+ if (myCert == NULL) {
+ printf ("Could not find the certificate for %s\n", personalCert);
+ return 700;
+ }
+ caCert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(),
+ recoveryEncrypter);
+ if (caCert == NULL) {
+ printf ("Could not find the certificate for %s\n", recoveryEncrypter);
+ return 701;
+ }
+ caPubKey = CERT_ExtractPublicKey(caCert);
+ pubKey = SECKEY_ConvertToPublicKey(privKey);
+ max_bytes_encrypted = PK11_GetPrivateModulusLen(privKey);
+ slot = PK11_GetBestSlot(mapWrapKeyType(privKey->keyType), NULL);
+ id = PK11_ImportPublicKey(slot, pubKey, PR_FALSE);
+ switch(privKey->keyType) {
+ case rsaKey:
+ mech.mechanism = CKM_RSA_PKCS;
+ break;
+ case dsaKey:
+ mech.mechanism = CKM_DSA;
+ break;
+ case dhKey:
+ mech.mechanism = CKM_DH_PKCS_DERIVE;
+ break;
+ default:
+ printf ("Bad Key type in key recovery.\n");
+ return 512;
+
+ }
+ PK11_EnterSlotMonitor(slot);
+ crv = PK11_GETTAB(slot)->C_EncryptInit(slot->session, &mech, id);
+ if (crv != CKR_OK) {
+ PK11_ExitSlotMonitor(slot);
+ PK11_FreeSlot(slot);
+ printf ("C_EncryptInit failed in KeyRecovery\n");
+ return 500;
+ }
+ ciphertext = PORT_NewArray(unsigned char, max_bytes_encrypted);
+ if (ciphertext == NULL) {
+ PK11_ExitSlotMonitor(slot);
+ PK11_FreeSlot(slot);
+ printf ("Could not allocate memory for ciphertext.\n");
+ return 501;
+ }
+ bytes_encrypted = max_bytes_encrypted;
+ crv = PK11_GETTAB(slot)->C_Encrypt(slot->session,
+ known_message,
+ KNOWN_MESSAGE_LENGTH,
+ ciphertext,
+ &bytes_encrypted);
+ PK11_ExitSlotMonitor(slot);
+ PK11_FreeSlot(slot);
+ if (crv != CKR_OK) {
+ PORT_Free(ciphertext);
+ return 502;
+ }
+ /* Always use the smaller of these two values . . . */
+ bytes_compared = ( bytes_encrypted > KNOWN_MESSAGE_LENGTH )
+ ? KNOWN_MESSAGE_LENGTH
+ : bytes_encrypted;
+
+ /* If there was a failure, the plaintext */
+ /* goes at the end, therefore . . . */
+ text_compared = ( bytes_encrypted > KNOWN_MESSAGE_LENGTH )
+ ? (ciphertext + bytes_encrypted -
+ KNOWN_MESSAGE_LENGTH )
+ : ciphertext;
+
+ keyRecRep = CMMF_CreateKeyRecRepContent();
+ if (keyRecRep == NULL) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ printf ("Could not allocate a CMMFKeyRecRepContent structre.\n");
+ return 503;
+ }
+ rv = CMMF_KeyRecRepContentSetPKIStatusInfoStatus(keyRecRep,
+ cmmfGranted);
+ if (rv != SECSuccess) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ printf ("Could not set the status for the KeyRecRepContent\n");
+ return 504;
+ }
+ /* The myCert here should correspond to the certificate corresponding
+ * to the private key, but for this test any certificate will do.
+ */
+ rv = CMMF_KeyRecRepContentSetCertifiedKeyPair(keyRecRep, myCert,
+ privKey, caPubKey);
+ if (rv != SECSuccess) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ printf ("Could not set the Certified Key Pair\n");
+ return 505;
+ }
+ PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir,
+ "KeyRecRepContent.der");
+ fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ printf ("Could not open file %s\n", filePath);
+ return 506;
+ }
+ rv = CMMF_EncodeKeyRecRepContent(keyRecRep, WriteItOut, fileDesc);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ PR_Close(fileDesc);
+
+ if (rv != SECSuccess) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ printf ("Error while encoding CMMFKeyRecRepContent\n");
+ return 507;
+ }
+ GetBitsFromFile(filePath, &fileBits);
+ if (fileBits.data == NULL) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ printf ("Could not get the bits from file %s\n", filePath);
+ return 508;
+ }
+ keyRecRep =
+ CMMF_CreateKeyRecRepContentFromDER(db,(const char*)fileBits.data,
+ fileBits.len);
+ if (keyRecRep == NULL) {
+ printf ("Could not decode the KeyRecRepContent in file %s\n",
+ filePath);
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ return 509;
+ }
+ caPrivKey = PK11_FindKeyByAnyCert(caCert, NULL);
+ if (CMMF_KeyRecRepContentGetPKIStatusInfoStatus(keyRecRep) !=
+ cmmfGranted) {
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ printf ("A bad status came back with the "
+ "KeyRecRepContent structure\n");
+ return 510;
+ }
+#define NICKNAME "Key Recovery Test Key"
+ nickname.data = (unsigned char*)NICKNAME;
+ nickname.len = PORT_Strlen(NICKNAME);
+ certKeyPair = CMMF_KeyRecRepContentGetCertKeyAtIndex(keyRecRep, 0);
+ CMMF_DestroyKeyRecRepContent(keyRecRep);
+ rv = CMMF_CertifiedKeyPairUnwrapPrivKey(certKeyPair,
+ caPrivKey,
+ &nickname,
+ PK11_GetInternalKeySlot(),
+ db,
+ &unwrappedPrivKey, NULL);
+ CMMF_DestroyCertifiedKeyPair(certKeyPair);
+ if (rv != SECSuccess) {
+ printf ("Unwrapping the private key failed.\n");
+ return 511;
+ }
+ /*Now let's try to decrypt the ciphertext with the "recovered" key*/
+ PK11_EnterSlotMonitor(slot);
+ crv =
+ PK11_GETTAB(slot)->C_DecryptInit(unwrappedPrivKey->pkcs11Slot->session,
+ &mech,
+ unwrappedPrivKey->pkcs11ID);
+ if (crv != CKR_OK) {
+ PK11_ExitSlotMonitor(slot);
+ PORT_Free(ciphertext);
+ PK11_FreeSlot(slot);
+ printf ("Decrypting with the recovered key failed.\n");
+ return 513;
+ }
+ bytes_decrypted = KNOWN_MESSAGE_LENGTH;
+ crv = PK11_GETTAB(slot)->C_Decrypt(unwrappedPrivKey->pkcs11Slot->session,
+ ciphertext,
+ bytes_encrypted, plaintext,
+ &bytes_decrypted);
+ SECKEY_DestroyPrivateKey(unwrappedPrivKey);
+ PK11_ExitSlotMonitor(slot);
+ PORT_Free(ciphertext);
+ if (crv != CKR_OK) {
+ PK11_FreeSlot(slot);
+ printf ("Decrypting the ciphertext with recovered key failed.\n");
+ return 514;
+ }
+ if ((bytes_decrypted != KNOWN_MESSAGE_LENGTH) ||
+ (PORT_Memcmp(plaintext, known_message, KNOWN_MESSAGE_LENGTH) != 0)) {
+ PK11_FreeSlot(slot);
+ printf ("The recovered plaintext does not equal the known message:\n"
+ "\tKnown message: %s\n"
+ "\tRecovered plaintext: %s\n", known_message, plaintext);
+ return 515;
+ }
+ return 0;
+}
+
+int
+DoChallengeResponse(char *configdir, SECKEYPrivateKey *privKey,
+ SECKEYPublicKey *pubKey)
+{
+ CMMFPOPODecKeyChallContent *chalContent = NULL;
+ CMMFPOPODecKeyRespContent *respContent = NULL;
+ CERTCertificate *myCert = NULL;
+ CERTGeneralName *myGenName = NULL;
+ PRArenaPool *poolp = NULL;
+ SECItem DecKeyChallBits;
+ long *randomNums;
+ int numChallengesFound=0;
+ int numChallengesSet = 1,i;
+ long retrieved;
+ char filePath[PATH_LEN];
+ RNGContext *rng;
+ SECStatus rv;
+ PRFileDesc *fileDesc;
+ SECItem *publicValue, *keyID;
+ SECKEYPrivateKey *foundPrivKey;
+
+ chalContent = CMMF_CreatePOPODecKeyChallContent();
+ myCert = CERT_FindCertByNickname(db, personalCert);
+ if (myCert == NULL) {
+ printf ("Could not find the certificate for %s\n", personalCert);
+ return 900;
+ }
+ poolp = PORT_NewArena(1024);
+ if (poolp == NULL) {
+ printf("Could no allocate a new arena in DoChallengeResponse\n");
+ return 901;
+ }
+ myGenName = CERT_GetCertificateNames(myCert, poolp);
+ if (myGenName == NULL) {
+ printf ("Could not get the general names for %s certificate\n",
+ personalCert);
+ return 902;
+ }
+ randomNums = PORT_ArenaNewArray(poolp,long, numChallengesSet);
+ rng = RNG_CreateContext();
+ RNG_GenerateRandomBytes(rng, randomNums, numChallengesSet*sizeof(long));
+ for (i=0; i<numChallengesSet; i++) {
+ rv = CMMF_POPODecKeyChallContentSetNextChallenge(chalContent,
+ randomNums[i],
+ myGenName,
+ pubKey,
+ NULL);
+ }
+ RNG_DestroyContext(rng, PR_TRUE);
+ if (rv != SECSuccess) {
+ printf ("Could not set the challenge in DoChallengeResponse\n");
+ return 903;
+ }
+ PR_snprintf(filePath, PATH_LEN, "%s/POPODecKeyChallContent.der",
+ configdir);
+ fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ printf ("Could not open file %s\n", filePath);
+ return 904;
+ }
+ rv = CMMF_EncodePOPODecKeyChallContent(chalContent,WriteItOut,
+ (void*)fileDesc);
+ PR_Close(fileDesc);
+ CMMF_DestroyPOPODecKeyChallContent(chalContent);
+ if (rv != SECSuccess) {
+ printf ("Could not encode the POPODecKeyChallContent.\n");
+ return 905;
+ }
+ GetBitsFromFile(filePath, &DecKeyChallBits);
+ chalContent =
+ CMMF_CreatePOPODecKeyChallContentFromDER
+ ((const char*)DecKeyChallBits.data, DecKeyChallBits.len);
+ PORT_Free(DecKeyChallBits.data);
+ if (chalContent == NULL) {
+ printf ("Could not create the POPODecKeyChallContent from DER\n");
+ return 906;
+ }
+ numChallengesFound =
+ CMMF_POPODecKeyChallContentGetNumChallenges(chalContent);
+ if (numChallengesFound != numChallengesSet) {
+ printf ("Number of Challenges Found (%d) does not equal the number "
+ "set (%d)\n", numChallengesFound, numChallengesSet);
+ return 907;
+ }
+ for (i=0; i<numChallengesSet; i++) {
+ publicValue = CMMF_POPODecKeyChallContentGetPublicValue(chalContent, i);
+ if (publicValue == NULL) {
+ printf("Could not get the public value for challenge at index %d\n",
+ i);
+ return 908;
+ }
+ keyID = PK11_MakeIDFromPubKey(publicValue);
+ if (keyID == NULL) {
+ printf ("Could not make the keyID from the public value\n");
+ return 909;
+ }
+ foundPrivKey = PK11_FindKeyByKeyID(privKey->pkcs11Slot,keyID, NULL);
+ if (foundPrivKey == NULL) {
+ printf ("Could not find the private key corresponding to the public"
+ " value.\n");
+ return 910;
+ }
+ rv = CMMF_POPODecKeyChallContDecryptChallenge(chalContent, i,
+ foundPrivKey);
+ if (rv != SECSuccess) {
+ printf ("Could not decrypt the challenge at index %d\n", i);
+ return 911;
+ }
+ rv = CMMF_POPODecKeyChallContentGetRandomNumber(chalContent, i,
+ &retrieved);
+ if (rv != SECSuccess) {
+ printf ("Could not get the random number from the challenge at "
+ "index %d\n", i);
+ return 912;
+ }
+ if (retrieved != randomNums[i]) {
+ printf ("Retrieved the number (%d), expected (%d)\n", retrieved,
+ randomNums[i]);
+ return 913;
+ }
+ }
+ CMMF_DestroyPOPODecKeyChallContent(chalContent);
+ PR_snprintf(filePath, PATH_LEN, "%s/POPODecKeyRespContent.der",
+ configdir);
+ fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+ 0666);
+ if (fileDesc == NULL) {
+ printf ("Could not open file %s\n", filePath);
+ return 914;
+ }
+ rv = CMMF_EncodePOPODecKeyRespContent(randomNums, numChallengesSet,
+ WriteItOut, fileDesc);
+ PR_Close(fileDesc);
+ if (rv != 0) {
+ printf ("Could not encode the POPODecKeyRespContent\n");
+ return 915;
+ }
+ GetBitsFromFile(filePath, &DecKeyChallBits);
+ respContent =
+ CMMF_CreatePOPODecKeyRespContentFromDER((const char*)DecKeyChallBits.data,
+ DecKeyChallBits.len);
+ if (respContent == NULL) {
+ printf ("Could not decode the contents of the file %s\n", filePath);
+ return 916;
+ }
+ numChallengesFound =
+ CMMF_POPODecKeyRespContentGetNumResponses(respContent);
+ if (numChallengesFound != numChallengesSet) {
+ printf ("Number of responses found (%d) does not match the number "
+ "of challenges set (%d)\n",
+ numChallengesFound, numChallengesSet);
+ return 917;
+ }
+ for (i=0; i<numChallengesSet; i++) {
+ rv = CMMF_POPODecKeyRespContentGetResponse(respContent, i, &retrieved);
+ if (rv != SECSuccess) {
+ printf ("Could not retrieve the response at index %d\n", i);
+ return 918;
+ }
+ if (retrieved != randomNums[i]) {
+ printf ("Retrieved the number (%ld), expected (%ld)\n", retrieved,
+ randomNums[i]);
+ return 919;
+ }
+
+ }
+ CMMF_DestroyPOPODecKeyRespContent(respContent);
+ return 0;
+}
+
+char *
+certdb_name_cb(void *arg, int dbVersion)
+{
+ char *configdir = (char *)arg;
+ char *dbver;
+
+ switch (dbVersion) {
+ case 7:
+ dbver = "7";
+ break;
+ case 6:
+ dbver = "6";
+ break;
+ case 5:
+ dbver = "5";
+ break;
+ case 4:
+ default:
+ dbver = "";
+ break;
+ }
+ return PR_smprintf("%s/cert%s.db", configdir, dbver);
+}
+
+SECStatus
+OpenCertDB(char *configdir)
+{
+ CERTCertDBHandle *certdb;
+ SECStatus status = SECFailure;
+
+ certdb = PORT_ZNew(CERTCertDBHandle);
+ if (certdb == NULL) {
+ goto loser;
+ }
+ status = CERT_OpenCertDB(certdb, PR_TRUE, certdb_name_cb, configdir);
+ if (status == SECSuccess) {
+ CERT_SetDefaultCertDB(certdb);
+ db = certdb;
+ } else {
+ PORT_Free(certdb);
+ }
+ loser:
+ return status;
+}
+
+char *
+keydb_name_cb(void *arg, int dbVersion)
+{
+ char *configdir = (char*) arg;
+ char *dbver;
+
+ switch(dbVersion){
+ case 3:
+ dbver = "3";
+ break;
+ case 2:
+ default:
+ dbver = "";
+ break;
+ }
+ return PR_smprintf("%s/key%s.db", configdir, dbver);
+}
+
+SECStatus
+OpenKeyDB(char *configdir)
+{
+ SECKEYKeyDBHandle *keydb;
+
+ keydb = SECKEY_OpenKeyDB(PR_FALSE, keydb_name_cb, configdir);
+ if (keydb == NULL) {
+ return SECFailure;
+ }
+ SECKEY_SetDefaultKeyDB(keydb);
+ return SECSuccess;
+}
+
+SECStatus
+OpenSecModDB(char *configdir)
+{
+ char *secmodname = PR_smprintf("%d/secmod.db", configdir);
+ if (secmodname == NULL) {
+ return SECFailure;
+ }
+ SECMOD_init(secmodname);
+ return SECSuccess;
+}
+
+void
+CloseHCL(void)
+{
+ CERTCertDBHandle *certHandle;
+ SECKEYKeyDBHandle *keyHandle;
+
+ certHandle = CERT_GetDefaultCertDB();
+ if (certHandle) {
+ CERT_ClosePermCertDB(certHandle);
+ }
+ keyHandle = SECKEY_GetDefaultKeyDB();
+ if (keyHandle) {
+ SECKEY_CloseKeyDB(keyHandle);
+ }
+}
+
+SECStatus
+InitHCL(char *configdir)
+{
+ SECStatus status;
+ SECStatus rv = SECFailure;
+
+ RNG_RNGInit();
+ RNG_SystemInfoForRNG();
+
+ status = OpenCertDB(configdir);
+ if (status != SECSuccess) {
+ goto loser;
+ }
+
+ status = OpenKeyDB(configdir);
+ if (status != SECSuccess) {
+ goto loser;
+ }
+
+ status = OpenSecModDB(configdir);
+ if (status != SECSuccess) {
+ goto loser;
+ }
+
+ rv = SECSuccess;
+
+ loser:
+ if (rv != SECSuccess) {
+ CloseHCL();
+ }
+ return rv;
+}
+void
+Usage (void)
+{
+ printf ("Usage:\n"
+ "\tcrmftest -d [Database Directory] -p [Personal Cert]\n"
+ "\t -e [Encrypter] -s [CA Certificate]\n\n"
+ "Database Directory\n"
+ "\tThis is the directory where the key3.db, cert7.db, and\n"
+ "\tsecmod.db files are located. This is also the directory\n"
+ "\twhere the program will place CRMF/CMMF der files\n"
+ "Personal Cert\n"
+ "\tThis is the certificate that already exists in the cert\n"
+ "\tdatabase to use while encoding the response. The private\n"
+ "\tkey associated with the certificate must also exist in the\n"
+ "\tkey database.\n"
+ "Encrypter\n"
+ "\tThis is the certificate to use when encrypting the the \n"
+ "\tkey recovery response. The private key for this cert\n"
+ "\tmust also be present in the key database.\n"
+ "CA Certificate\n"
+ "\tThis is the nickname of the certificate to use as the\n"
+ "\tCA when doing all of the encoding.\n");
+}
+
+int
+main(int argc, char **argv)
+{
+ CRMFCertRequest *certReq, *certReq2;
+ CRMFCertReqMsg *certReqMsg;
+ CRMFCertReqMsg *secondMsg;
+ char *configdir;
+ int irv;
+ SECStatus rv;
+ SECKEYPrivateKey *privKey;
+ SECKEYPublicKey *pubKey;
+ int o;
+ PRBool hclInit = PR_FALSE, pArg = PR_FALSE, eArg = PR_FALSE,
+ sArg = PR_FALSE;
+
+ printf ("\ncrmftest v1.0\n");
+ while (-1 != (o = getopt(argc, argv, "d:p:e:s:"))) {
+ switch(o) {
+ case 'd':
+ configdir = PORT_Strdup(optarg);
+ rv = InitHCL(configdir);
+ if (rv != SECSuccess) {
+ printf ("InitHCL failed\n");
+ return 101;
+ }
+ hclInit = PR_TRUE;
+ break;
+ case 'p':
+ personalCert = PORT_Strdup(optarg);
+ if (personalCert == NULL) {
+ return 603;
+ }
+ pArg = PR_TRUE;
+ break;
+ case 'e':
+ recoveryEncrypter = PORT_Strdup(optarg);
+ if (recoveryEncrypter == NULL) {
+ return 602;
+ }
+ eArg = PR_TRUE;
+ break;
+ case 's':
+ caCertName = PORT_Strdup(optarg);
+ if (caCertName == NULL) {
+ return 604;
+ }
+ sArg = PR_TRUE;
+ break;
+ default:
+ Usage();
+ return 601;
+ }
+ }
+ if (!hclInit || !pArg || !eArg || !sArg) {
+ Usage();
+ return 600;
+ }
+
+ InitPKCS11();
+
+ irv = CreateCertRequest(&certReq, &privKey, &pubKey);
+ if (irv != 0 || certReq == NULL) {
+ goto loser;
+ }
+
+ certReqMsg = CRMF_CreateCertReqMsg();
+ secondMsg = CRMF_CreateCertReqMsg();
+ CRMF_CertReqMsgSetCertRequest(certReqMsg, certReq);
+ CRMF_CertReqMsgSetCertRequest(secondMsg, certReq);
+
+ irv = AddProofOfPossession(certReqMsg, privKey, pubKey, crmfSignature);
+ irv = AddProofOfPossession(secondMsg, privKey, pubKey, crmfKeyAgreement);
+ irv = Encode (certReqMsg, secondMsg, configdir);
+ if (irv != 0) {
+ goto loser;
+ }
+
+ rv = CRMF_DestroyCertRequest (certReq);
+ if (rv != SECSuccess) {
+ printf ("Error when destroy certificate request.\n");
+ irv = 100;
+ goto loser;
+ }
+
+ rv = CRMF_DestroyCertReqMsg(certReqMsg);
+ CRMF_DestroyCertReqMsg(secondMsg);
+
+ irv = Decode (configdir);
+ if (irv != 0) {
+ printf("Error while decoding\n");
+ goto loser;
+ }
+
+ if ((irv = DoCMMFStuff(configdir)) != 0) {
+ printf ("CMMF tests failed.\n");
+ goto loser;
+ }
+
+ if ((irv = DoKeyRecovery(configdir, privKey)) != 0) {
+ printf ("Error doing key recovery\n");
+ goto loser;
+ }
+
+ if ((irv = DoChallengeResponse(configdir, privKey, pubKey)) != 0) {
+ printf ("Error doing challenge-response\n");
+ goto loser;
+ }
+ printf ("Exiting successfully!!!\n\n");
+ irv = 0;
+
+ loser:
+ CloseHCL();
+ PORT_Free(configdir);
+ return irv;
+}
diff --git a/security/nss/cmd/dbck/Makefile b/security/nss/cmd/dbck/Makefile
new file mode 100644
index 000000000..7ca8f0630
--- /dev/null
+++ b/security/nss/cmd/dbck/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/dbck/dbck.c b/security/nss/cmd/dbck/dbck.c
new file mode 100644
index 000000000..a3f1b9d54
--- /dev/null
+++ b/security/nss/cmd/dbck/dbck.c
@@ -0,0 +1,1869 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+** dbck.c
+**
+** utility for fixing corrupt cert databases
+**
+*/
+#include <stdio.h>
+#include <string.h>
+
+#include "secutil.h"
+#include "cdbhdl.h"
+#include "certdb.h"
+#include "cert.h"
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+static char *progName;
+
+/* placeholders for pointer error types */
+static void *WrongEntry;
+static void *NoNickname;
+static void *NoSMime;
+
+enum {
+ GOBOTH = 0,
+ GORIGHT,
+ GOLEFT
+};
+
+typedef struct
+{
+ PRBool verbose;
+ PRBool dograph;
+ PRFileDesc *out;
+ PRFileDesc *graphfile;
+ int dbErrors[10];
+} dbDebugInfo;
+
+/*
+ * A list node for a cert db entry. The index is a unique identifier
+ * to use for creating generic maps of a db. This struct handles
+ * the cert, nickname, and smime db entry types, as all three have a
+ * single handle to a subject entry.
+ * This structure is pointed to by certDBEntryListNode->appData.
+ */
+typedef struct
+{
+ PRArenaPool *arena;
+ int index;
+ certDBEntryListNode *pSubject;
+} certDBEntryMap;
+
+/*
+ * Subject entry is special case, it has bidirectional handles. One
+ * subject entry can point to several certs (using the same DN), and
+ * a nickname and/or smime entry.
+ * This structure is pointed to by certDBEntryListNode->appData.
+ */
+typedef struct
+{
+ PRArenaPool *arena;
+ int index;
+ int numCerts;
+ certDBEntryListNode **pCerts;
+ certDBEntryListNode *pNickname;
+ certDBEntryListNode *pSMime;
+} certDBSubjectEntryMap;
+
+/*
+ * A map of a certdb.
+ */
+typedef struct
+{
+ int numCerts;
+ int numSubjects;
+ int numNicknames;
+ int numSMime;
+ certDBEntryListNode certs; /* pointer to head of cert list */
+ certDBEntryListNode subjects; /* pointer to head of subject list */
+ certDBEntryListNode nicknames; /* pointer to head of nickname list */
+ certDBEntryListNode smime; /* pointer to head of smime list */
+} certDBArray;
+
+/* Cast list to the base element, a certDBEntryListNode. */
+#define LISTNODE_CAST(node) \
+ ((certDBEntryListNode *)(node))
+
+static void
+Usage(char *progName)
+{
+#define FPS fprintf(stderr,
+ FPS "Type %s -H for more detailed descriptions\n", progName);
+ FPS "Usage: %s -D [-d certdir] [-i dbname] [-m] [-v [-f dumpfile]]\n",
+ progName);
+ FPS " %s -R -o newdbname [-d certdir] [-i dbname] [-aprsx] [-v [-f dumpfile]]\n",
+ progName);
+ exit(-1);
+}
+
+static void
+LongUsage(char *progName)
+{
+ FPS "%-15s Display this help message.\n",
+ "-H");
+ FPS "%-15s Dump analysis. No changes will be made to the database.\n",
+ "-D");
+ FPS "%-15s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-15s Input cert database name (default is cert7.db)\n",
+ " -i dbname");
+ FPS "%-15s Mail a graph of the database to certdb@netscape.com.\n",
+ " -m");
+ FPS "%-15s This will produce an index graph of your cert db and send\n",
+ "");
+ FPS "%-15s it to Netscape for analysis. Personal info will be removed.\n",
+ "");
+ FPS "%-15s Verbose mode. Dumps the entire contents of your cert7.db.\n",
+ " -v");
+ FPS "%-15s File to dump verbose output into.\n",
+ " -f dumpfile");
+ FPS "%-15s Repair the database. The program will look for broken\n",
+ "-R");
+ FPS "%-15s dependencies between subject entries and certificates,\n",
+ "");
+ FPS "%-15s between nickname entries and subjects, and between SMIME\n",
+ "");
+ FPS "%-15s profiles and subjects. Any duplicate entries will be\n",
+ "");
+ FPS "%-15s removed, any missing entries will be created.\n",
+ "");
+ FPS "%-15s File to store new database in (default is new_cert7.db)\n",
+ " -o newdbname");
+ FPS "%-15s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-15s Input cert database name (default is cert7.db)\n",
+ " -i dbname");
+ FPS "%-15s Prompt before removing any certificates.\n",
+ " -p");
+ FPS "%-15s Keep all possible certificates. Only remove certificates\n",
+ " -a");
+ FPS "%-15s which prevent creation of a consistent database. Thus any\n",
+ "");
+ FPS "%-15s expired or redundant entries will be kept.\n",
+ "");
+ FPS "%-15s Keep redundant nickname/email entries. It is possible\n",
+ " -r");
+ FPS "%-15s only one such entry will be usable.\n",
+ "");
+ FPS "%-15s Don't require an S/MIME profile in order to keep an S/MIME\n",
+ " -s");
+ FPS "%-15s cert. An empty profile will be created.\n",
+ "");
+ FPS "%-15s Keep expired certificates.\n",
+ " -x");
+ FPS "%-15s Verbose mode - report all activity while recovering db.\n",
+ " -v");
+ FPS "%-15s File to dump verbose output into.\n",
+ " -f dumpfile");
+ FPS "\n");
+ exit(-1);
+#undef FPS
+}
+
+/*******************************************************************
+ *
+ * Functions for dbck.
+ *
+ ******************************************************************/
+
+void
+printHexString(PRFileDesc *out, SECItem *hexval)
+{
+ int i;
+ for (i = 0; i < hexval->len; i++) {
+ if (i != hexval->len - 1) {
+ PR_fprintf(out, "%02x:", hexval->data[i]);
+ } else {
+ PR_fprintf(out, "%02x", hexval->data[i]);
+ }
+ }
+ PR_fprintf(out, "\n");
+}
+
+typedef enum {
+/* 0*/ NoSubjectForCert = 0,
+/* 1*/ SubjectHasNoKeyForCert,
+/* 2*/ NoNicknameOrSMimeForSubject,
+/* 3*/ WrongNicknameForSubject,
+/* 4*/ NoNicknameEntry,
+/* 5*/ WrongSMimeForSubject,
+/* 6*/ NoSMimeEntry,
+/* 7*/ NoSubjectForNickname,
+/* 8*/ NoSubjectForSMime,
+/* 9*/ NicknameAndSMimeEntry
+} dbErrorType;
+
+static char *dbErrorString[] = {
+/* 0*/ "<CERT ENTRY>\nDid not find a subject entry for this certificate.",
+/* 1*/ "<SUBJECT ENTRY>\nSubject has certKey which is not in db.",
+/* 2*/ "<SUBJECT ENTRY>\nSubject does not have a nickname or email address.",
+/* 3*/ "<SUBJECT ENTRY>\nUsing this subject's nickname, found a nickname entry for a different subject.",
+/* 4*/ "<SUBJECT ENTRY>\nDid not find a nickname entry for this subject.",
+/* 5*/ "<SUBJECT ENTRY>\nUsing this subject's email, found an S/MIME entry for a different subject.",
+/* 6*/ "<SUBJECT ENTRY>\nDid not find an S/MIME entry for this subject.",
+/* 7*/ "<NICKNAME ENTRY>\nDid not find a subject entry for this nickname.",
+/* 8*/ "<S/MIME ENTRY>\nDid not find a subject entry for this S/MIME profile.",
+};
+
+SECStatus
+dumpCertificate(CERTCertificate *cert, int num, PRFileDesc *outfile)
+{
+ int userCert = 0;
+ CERTCertTrust *trust = cert->trust;
+ userCert = (SEC_GET_TRUST_FLAGS(trust, trustSSL) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustEmail) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustObjectSigning) & CERTDB_USER);
+ if (num >= 0) {
+ PR_fprintf(outfile, "Certificate: %3d\n", num);
+ } else {
+ PR_fprintf(outfile, "Certificate:\n");
+ }
+ PR_fprintf(outfile, "----------------\n");
+ if (userCert)
+ PR_fprintf(outfile, "(User Cert)\n");
+ PR_fprintf(outfile, "## SUBJECT: %s\n", cert->subjectName);
+ PR_fprintf(outfile, "## ISSUER: %s\n", cert->issuerName);
+ PR_fprintf(outfile, "## SERIAL NUMBER: ");
+ printHexString(outfile, &cert->serialNumber);
+ { /* XXX should be separate function. */
+ int64 timeBefore, timeAfter;
+ PRExplodedTime beforePrintable, afterPrintable;
+ char *beforestr, *afterstr;
+ DER_UTCTimeToTime(&timeBefore, &cert->validity.notBefore);
+ DER_UTCTimeToTime(&timeAfter, &cert->validity.notAfter);
+ PR_ExplodeTime(timeBefore, PR_GMTParameters, &beforePrintable);
+ PR_ExplodeTime(timeAfter, PR_GMTParameters, &afterPrintable);
+ beforestr = PORT_Alloc(100);
+ afterstr = PORT_Alloc(100);
+ PR_FormatTime(beforestr, 100, "%a %b %d %H:%M:%S %Y", &beforePrintable);
+ PR_FormatTime(afterstr, 100, "%a %b %d %H:%M:%S %Y", &afterPrintable);
+ PR_fprintf(outfile, "## VALIDITY: %s to %s\n", beforestr, afterstr);
+ }
+ PR_fprintf(outfile, "\n");
+ return SECSuccess;
+}
+
+SECStatus
+dumpCertEntry(certDBEntryCert *entry, int num, PRFileDesc *outfile)
+{
+ CERTCertificate *cert;
+ cert = CERT_DecodeDERCertificate(&entry->derCert, PR_FALSE, NULL);
+ if (!cert) {
+ fprintf(stderr, "Failed to decode certificate.\n");
+ return SECFailure;
+ }
+ cert->trust = &entry->trust;
+ dumpCertificate(cert, num, outfile);
+ CERT_DestroyCertificate(cert);
+ return SECSuccess;
+}
+
+SECStatus
+dumpSubjectEntry(certDBEntrySubject *entry, int num, PRFileDesc *outfile)
+{
+ char *subjectName;
+ subjectName = CERT_DerNameToAscii(&entry->derSubject);
+ PR_fprintf(outfile, "Subject: %3d\n", num);
+ PR_fprintf(outfile, "------------\n");
+ PR_fprintf(outfile, "## %s\n", subjectName);
+ if (entry->nickname)
+ PR_fprintf(outfile, "## Subject nickname: %s\n", entry->nickname);
+ if (entry->emailAddr)
+ PR_fprintf(outfile, "## Subject email address: %s\n",
+ entry->emailAddr);
+ PR_fprintf(outfile, "## This subject has %d cert(s).\n", entry->ncerts);
+ PR_fprintf(outfile, "\n");
+ PORT_Free(subjectName);
+ return SECSuccess;
+}
+
+SECStatus
+dumpNicknameEntry(certDBEntryNickname *entry, int num, PRFileDesc *outfile)
+{
+ PR_fprintf(outfile, "Nickname: %3d\n", num);
+ PR_fprintf(outfile, "-------------\n");
+ PR_fprintf(outfile, "## \"%s\"\n\n", entry->nickname);
+ return SECSuccess;
+}
+
+SECStatus
+dumpSMimeEntry(certDBEntrySMime *entry, int num, PRFileDesc *outfile)
+{
+ PR_fprintf(outfile, "S/MIME Profile: %3d\n", num);
+ PR_fprintf(outfile, "-------------------\n");
+ PR_fprintf(outfile, "## \"%s\"\n", entry->emailAddr);
+ PR_fprintf(outfile, "## OPTIONS: ");
+ printHexString(outfile, &entry->smimeOptions);
+ PR_fprintf(outfile, "## TIMESTAMP: ");
+ printHexString(outfile, &entry->optionsDate);
+ PR_fprintf(outfile, "\n");
+ return SECSuccess;
+}
+
+SECStatus
+mapCertEntries(certDBArray *dbArray)
+{
+ certDBEntryCert *certEntry;
+ certDBEntrySubject *subjectEntry;
+ certDBEntryListNode *certNode, *subjNode;
+ certDBSubjectEntryMap *smap;
+ certDBEntryMap *map;
+ PRArenaPool *tmparena;
+ SECItem derSubject;
+ SECItem certKey;
+ PRCList *cElem, *sElem;
+ int i;
+
+ /* Arena for decoded entries */
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (tmparena == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return SECFailure;
+ }
+
+ /* Iterate over cert entries and map them to subject entries.
+ * NOTE: mapSubjectEntries must be called first to alloc memory
+ * for array of subject->cert map.
+ */
+ for (cElem = PR_LIST_HEAD(&dbArray->certs.link);
+ cElem != &dbArray->certs.link; cElem = PR_NEXT_LINK(cElem)) {
+ certNode = LISTNODE_CAST(cElem);
+ certEntry = (certDBEntryCert *)&certNode->entry;
+ map = (certDBEntryMap *)certNode->appData;
+ CERT_NameFromDERCert(&certEntry->derCert, &derSubject);
+ CERT_KeyFromDERCert(tmparena, &certEntry->derCert, &certKey);
+ /* Loop over found subjects for cert's DN. */
+ for (sElem = PR_LIST_HEAD(&dbArray->subjects.link);
+ sElem != &dbArray->subjects.link; sElem = PR_NEXT_LINK(sElem)) {
+ subjNode = LISTNODE_CAST(sElem);
+ subjectEntry = (certDBEntrySubject *)&subjNode->entry;
+ if (SECITEM_ItemsAreEqual(&derSubject, &subjectEntry->derSubject)) {
+ /* Found matching subject name, create link. */
+ map->pSubject = subjNode;
+ /* Make sure subject entry has cert's key. */
+ for (i=0; i<subjectEntry->ncerts; i++) {
+ if (SECITEM_ItemsAreEqual(&certKey,
+ &subjectEntry->certKeys[i])) {
+ /* Found matching cert key. */
+ smap = (certDBSubjectEntryMap *)subjNode->appData;
+ smap->pCerts[i] = certNode;
+ break;
+ }
+ }
+ }
+ }
+ }
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return SECSuccess;
+}
+
+SECStatus
+mapSubjectEntries(certDBArray *dbArray)
+{
+ certDBEntrySubject *subjectEntry;
+ certDBEntryNickname *nicknameEntry;
+ certDBEntrySMime *smimeEntry;
+ certDBEntryListNode *subjNode, *nickNode, *smimeNode;
+ certDBSubjectEntryMap *subjMap;
+ certDBEntryMap *nickMap, *smimeMap;
+ PRCList *sElem, *nElem, *mElem;
+
+ for (sElem = PR_LIST_HEAD(&dbArray->subjects.link);
+ sElem != &dbArray->subjects.link; sElem = PR_NEXT_LINK(sElem)) {
+ /* Iterate over subject entries and map subjects to nickname
+ * and smime entries. The cert<->subject map will be handled
+ * by a subsequent call to mapCertEntries.
+ */
+ subjNode = LISTNODE_CAST(sElem);
+ subjectEntry = (certDBEntrySubject *)&subjNode->entry;
+ subjMap = (certDBSubjectEntryMap *)subjNode->appData;
+ /* need to alloc memory here for array of matching certs. */
+ subjMap->pCerts = PORT_ArenaAlloc(subjMap->arena,
+ subjectEntry->ncerts*sizeof(int));
+ subjMap->numCerts = subjectEntry->ncerts;
+ if (subjectEntry->nickname) {
+ /* Subject should have a nickname entry, so create a link. */
+ for (nElem = PR_LIST_HEAD(&dbArray->nicknames.link);
+ nElem != &dbArray->nicknames.link;
+ nElem = PR_NEXT_LINK(nElem)) {
+ /* Look for subject's nickname in nickname entries. */
+ nickNode = LISTNODE_CAST(nElem);
+ nicknameEntry = (certDBEntryNickname *)&nickNode->entry;
+ nickMap = (certDBEntryMap *)nickNode->appData;
+ if (PL_strcmp(subjectEntry->nickname,
+ nicknameEntry->nickname) == 0) {
+ /* Found a nickname entry for subject's nickname. */
+ if (SECITEM_ItemsAreEqual(&subjectEntry->derSubject,
+ &nicknameEntry->subjectName)) {
+ /* Nickname and subject match. */
+ subjMap->pNickname = nickNode;
+ nickMap->pSubject = subjNode;
+ } else {
+ /* Nickname entry found is for diff. subject. */
+ subjMap->pNickname = WrongEntry;
+ }
+ }
+ }
+ } else {
+ subjMap->pNickname = NoNickname;
+ }
+ if (subjectEntry->emailAddr) {
+ /* Subject should have an smime entry, so create a link. */
+ for (mElem = PR_LIST_HEAD(&dbArray->smime.link);
+ mElem != &dbArray->smime.link; mElem = PR_NEXT_LINK(mElem)) {
+ /* Look for subject's email in S/MIME entries. */
+ smimeNode = LISTNODE_CAST(mElem);
+ smimeEntry = (certDBEntrySMime *)&smimeNode->entry;
+ smimeMap = (certDBEntryMap *)smimeNode->appData;
+ if (PL_strcmp(subjectEntry->emailAddr,
+ smimeEntry->emailAddr) == 0) {
+ /* Found a S/MIME entry for subject's email. */
+ if (SECITEM_ItemsAreEqual(&subjectEntry->derSubject,
+ &smimeEntry->subjectName)) {
+ /* S/MIME entry and subject match. */
+ subjMap->pSMime = smimeNode;
+ smimeMap->pSubject = subjNode;
+ } else {
+ /* S/MIME entry found is for diff. subject. */
+ subjMap->pSMime = WrongEntry;
+ }
+ }
+ }
+ } else {
+ subjMap->pSMime = NoSMime;
+ }
+ }
+ return SECSuccess;
+}
+
+void
+printnode(dbDebugInfo *info, const char *str, int num)
+{
+ if (!info->dograph)
+ return;
+ if (num < 0) {
+ PR_fprintf(info->graphfile, str);
+ } else {
+ PR_fprintf(info->graphfile, str, num);
+ }
+}
+
+PRBool
+map_handle_is_ok(dbDebugInfo *info, void *mapPtr, int indent)
+{
+ if (mapPtr == NULL) {
+ if (indent > 0)
+ printnode(info, " ", -1);
+ if (indent >= 0)
+ printnode(info, "******************* ", -1);
+ return PR_FALSE;
+ } else if (mapPtr == WrongEntry) {
+ if (indent > 0)
+ printnode(info, " ", -1);
+ if (indent >= 0)
+ printnode(info, "??????????????????? ", -1);
+ return PR_FALSE;
+ } else {
+ return PR_TRUE;
+ }
+}
+
+/* these call each other */
+void print_smime_graph(dbDebugInfo *info, certDBEntryMap *smimeMap,
+ int direction);
+void print_nickname_graph(dbDebugInfo *info, certDBEntryMap *nickMap,
+ int direction);
+void print_subject_graph(dbDebugInfo *info, certDBSubjectEntryMap *subjMap,
+ int direction, int optindex, int opttype);
+void print_cert_graph(dbDebugInfo *info, certDBEntryMap *certMap,
+ int direction);
+
+/* Given an smime entry, print its unique identifier. If GOLEFT is
+ * specified, print the cert<-subject<-smime map, else just print
+ * the smime entry.
+ */
+void
+print_smime_graph(dbDebugInfo *info, certDBEntryMap *smimeMap, int direction)
+{
+ certDBSubjectEntryMap *subjMap;
+ certDBEntryListNode *subjNode;
+ if (direction == GOLEFT) {
+ /* Need to output subject and cert first, see print_subject_graph */
+ subjNode = smimeMap->pSubject;
+ if (map_handle_is_ok(info, (void *)subjNode, 1)) {
+ subjMap = (certDBSubjectEntryMap *)subjNode->appData;
+ print_subject_graph(info, subjMap, GOLEFT,
+ smimeMap->index, certDBEntryTypeSMimeProfile);
+ } else {
+ printnode(info, "<---- S/MIME %5d ", smimeMap->index);
+ }
+ } else {
+ printnode(info, "S/MIME %5d ", smimeMap->index);
+ }
+}
+
+/* Given a nickname entry, print its unique identifier. If GOLEFT is
+ * specified, print the cert<-subject<-nickname map, else just print
+ * the nickname entry.
+ */
+void
+print_nickname_graph(dbDebugInfo *info, certDBEntryMap *nickMap, int direction)
+{
+ certDBSubjectEntryMap *subjMap;
+ certDBEntryListNode *subjNode;
+ if (direction == GOLEFT) {
+ /* Need to output subject and cert first, see print_subject_graph */
+ subjNode = nickMap->pSubject;
+ if (map_handle_is_ok(info, (void *)subjNode, 1)) {
+ subjMap = (certDBSubjectEntryMap *)subjNode->appData;
+ print_subject_graph(info, subjMap, GOLEFT,
+ nickMap->index, certDBEntryTypeNickname);
+ } else {
+ printnode(info, "<---- Nickname %5d ", nickMap->index);
+ }
+ } else {
+ printnode(info, "Nickname %5d ", nickMap->index);
+ }
+}
+
+/* Given a subject entry, if going right print the graph of the nickname|smime
+ * that it maps to (by its unique identifier); and if going left
+ * print the list of certs that it points to.
+ */
+void
+print_subject_graph(dbDebugInfo *info, certDBSubjectEntryMap *subjMap,
+ int direction, int optindex, int opttype)
+{
+ certDBEntryMap *map;
+ certDBEntryListNode *node;
+ int i;
+ /* The first line of output always contains the cert id, subject id,
+ * and nickname|smime id. Subsequent lines may contain additional
+ * cert id's for the subject if going left or both directions.
+ * Ex. of printing the graph for a subject entry:
+ * Cert 3 <- Subject 5 -> Nickname 32
+ * Cert 8 /
+ * Cert 9 /
+ * means subject 5 has 3 certs, 3, 8, and 9, and corresponds
+ * to nickname entry 32.
+ * To accomplish the above, it is required to dump the entire first
+ * line left-to-right, regardless of the input direction, and then
+ * finish up any remaining cert entries. Hence the code is uglier
+ * than one may expect.
+ */
+ if (direction == GOLEFT || direction == GOBOTH) {
+ /* In this case, nothing should be output until the first cert is
+ * located and output (cert 3 in the above example).
+ */
+ if (subjMap->numCerts == 0 || subjMap->pCerts == NULL)
+ /* XXX uh-oh */
+ return;
+ /* get the first cert and dump it. */
+ node = subjMap->pCerts[0];
+ if (map_handle_is_ok(info, (void *)node, 0)) {
+ map = (certDBEntryMap *)node->appData;
+ /* going left here stops. */
+ print_cert_graph(info, map, GOLEFT);
+ }
+ /* Now it is safe to output the subject id. */
+ if (direction == GOLEFT)
+ printnode(info, "Subject %5d <---- ", subjMap->index);
+ else /* direction == GOBOTH */
+ printnode(info, "Subject %5d ----> ", subjMap->index);
+ }
+ if (direction == GORIGHT || direction == GOBOTH) {
+ /* Okay, now output the nickname|smime for this subject. */
+ if (direction != GOBOTH) /* handled above */
+ printnode(info, "Subject %5d ----> ", subjMap->index);
+ if (subjMap->pNickname) {
+ node = subjMap->pNickname;
+ if (map_handle_is_ok(info, (void *)node, 0)) {
+ map = (certDBEntryMap *)node->appData;
+ /* going right here stops. */
+ print_nickname_graph(info, map, GORIGHT);
+ }
+ }
+ if (subjMap->pSMime) {
+ node = subjMap->pSMime;
+ if (map_handle_is_ok(info, (void *)node, 0)) {
+ map = (certDBEntryMap *)node->appData;
+ /* going right here stops. */
+ print_smime_graph(info, map, GORIGHT);
+ }
+ }
+ if (!subjMap->pNickname && !subjMap->pSMime) {
+ printnode(info, "******************* ", -1);
+ }
+ }
+ if (direction != GORIGHT) { /* going right has only one cert */
+ if (opttype == certDBEntryTypeNickname)
+ printnode(info, "Nickname %5d ", optindex);
+ else if (opttype == certDBEntryTypeSMimeProfile)
+ printnode(info, "S/MIME %5d ", optindex);
+ for (i=1 /* 1st one already done */; i<subjMap->numCerts; i++) {
+ printnode(info, "\n", -1); /* start a new line */
+ node = subjMap->pCerts[i];
+ if (map_handle_is_ok(info, (void *)node, 0)) {
+ map = (certDBEntryMap *)node->appData;
+ /* going left here stops. */
+ print_cert_graph(info, map, GOLEFT);
+ printnode(info, "/", -1);
+ }
+ }
+ }
+}
+
+/* Given a cert entry, print its unique identifer. If GORIGHT is specified,
+ * print the cert->subject->nickname|smime map, else just print
+ * the cert entry.
+ */
+void
+print_cert_graph(dbDebugInfo *info, certDBEntryMap *certMap, int direction)
+{
+ certDBSubjectEntryMap *subjMap;
+ certDBEntryListNode *subjNode;
+ if (direction == GOLEFT) {
+ printnode(info, "Cert %5d <---- ", certMap->index);
+ /* only want cert entry, terminate here. */
+ return;
+ }
+ /* Keep going right then. */
+ printnode(info, "Cert %5d ----> ", certMap->index);
+ subjNode = certMap->pSubject;
+ if (map_handle_is_ok(info, (void *)subjNode, 0)) {
+ subjMap = (certDBSubjectEntryMap *)subjNode->appData;
+ print_subject_graph(info, subjMap, GORIGHT, -1, -1);
+ }
+}
+
+SECStatus
+computeDBGraph(certDBArray *dbArray, dbDebugInfo *info)
+{
+ PRCList *cElem, *sElem, *nElem, *mElem;
+ certDBEntryListNode *node;
+ certDBEntryMap *map;
+ certDBSubjectEntryMap *subjMap;
+
+ /* Graph is of this form:
+ *
+ * certs:
+ * cert ---> subject ---> (nickname|smime)
+ *
+ * subjects:
+ * cert <--- subject ---> (nickname|smime)
+ *
+ * nicknames and smime:
+ * cert <--- subject <--- (nickname|smime)
+ */
+
+ /* Print cert graph. */
+ for (cElem = PR_LIST_HEAD(&dbArray->certs.link);
+ cElem != &dbArray->certs.link; cElem = PR_NEXT_LINK(cElem)) {
+ /* Print graph of everything to right of cert entry. */
+ node = LISTNODE_CAST(cElem);
+ map = (certDBEntryMap *)node->appData;
+ print_cert_graph(info, map, GORIGHT);
+ printnode(info, "\n", -1);
+ }
+ printnode(info, "\n", -1);
+
+ /* Print subject graph. */
+ for (sElem = PR_LIST_HEAD(&dbArray->subjects.link);
+ sElem != &dbArray->subjects.link; sElem = PR_NEXT_LINK(sElem)) {
+ /* Print graph of everything to both sides of subject entry. */
+ node = LISTNODE_CAST(sElem);
+ subjMap = (certDBSubjectEntryMap *)node->appData;
+ print_subject_graph(info, subjMap, GOBOTH, -1, -1);
+ printnode(info, "\n", -1);
+ }
+ printnode(info, "\n", -1);
+
+ /* Print nickname graph. */
+ for (nElem = PR_LIST_HEAD(&dbArray->nicknames.link);
+ nElem != &dbArray->nicknames.link; nElem = PR_NEXT_LINK(nElem)) {
+ /* Print graph of everything to left of nickname entry. */
+ node = LISTNODE_CAST(nElem);
+ map = (certDBEntryMap *)node->appData;
+ print_nickname_graph(info, map, GOLEFT);
+ printnode(info, "\n", -1);
+ }
+ printnode(info, "\n", -1);
+
+ /* Print smime graph. */
+ for (mElem = PR_LIST_HEAD(&dbArray->smime.link);
+ mElem != &dbArray->smime.link; mElem = PR_NEXT_LINK(mElem)) {
+ /* Print graph of everything to left of smime entry. */
+ node = LISTNODE_CAST(mElem);
+ if (node == NULL) break;
+ map = (certDBEntryMap *)node->appData;
+ print_smime_graph(info, map, GOLEFT);
+ printnode(info, "\n", -1);
+ }
+ printnode(info, "\n", -1);
+
+ return SECSuccess;
+}
+
+/*
+ * List the entries in the db, showing handles between entry types.
+ */
+void
+verboseOutput(certDBArray *dbArray, dbDebugInfo *info)
+{
+ int i, ref;
+ PRCList *elem;
+ certDBEntryListNode *node;
+ certDBEntryMap *map;
+ certDBSubjectEntryMap *smap;
+ certDBEntrySubject *subjectEntry;
+
+ /* List certs */
+ for (elem = PR_LIST_HEAD(&dbArray->certs.link);
+ elem != &dbArray->certs.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ map = (certDBEntryMap *)node->appData;
+ dumpCertEntry((certDBEntryCert*)&node->entry, map->index, info->out);
+ /* walk the cert handle to it's subject entry */
+ if (map_handle_is_ok(info, map->pSubject, -1)) {
+ smap = (certDBSubjectEntryMap *)map->pSubject->appData;
+ ref = smap->index;
+ PR_fprintf(info->out, "-->(subject %d)\n\n\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING SUBJECT ENTRY)\n\n\n");
+ }
+ }
+ /* List subjects */
+ for (elem = PR_LIST_HEAD(&dbArray->subjects.link);
+ elem != &dbArray->subjects.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ subjectEntry = (certDBEntrySubject *)&node->entry;
+ smap = (certDBSubjectEntryMap *)node->appData;
+ dumpSubjectEntry(subjectEntry, smap->index, info->out);
+ /* iterate over subject's certs */
+ for (i=0; i<smap->numCerts; i++) {
+ /* walk each subject handle to it's cert entries */
+ if (map_handle_is_ok(info, smap->pCerts[i], -1)) {
+ ref = ((certDBEntryMap *)smap->pCerts[i]->appData)->index;
+ PR_fprintf(info->out, "-->(%d. certificate %d)\n", i, ref);
+ } else {
+ PR_fprintf(info->out, "-->(%d. MISSING CERT ENTRY)\n", i);
+ }
+ }
+ if (subjectEntry->nickname) {
+ /* walk each subject handle to it's nickname entry */
+ if (map_handle_is_ok(info, smap->pNickname, -1)) {
+ ref = ((certDBEntryMap *)smap->pNickname->appData)->index;
+ PR_fprintf(info->out, "-->(nickname %d)\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING NICKNAME ENTRY)\n");
+ }
+ }
+ if (subjectEntry->emailAddr) {
+ /* walk each subject handle to it's smime entry */
+ if (map_handle_is_ok(info, smap->pSMime, -1)) {
+ ref = ((certDBEntryMap *)smap->pSMime->appData)->index;
+ PR_fprintf(info->out, "-->(s/mime %d)\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING S/MIME ENTRY)\n");
+ }
+ }
+ PR_fprintf(info->out, "\n\n");
+ }
+ for (elem = PR_LIST_HEAD(&dbArray->nicknames.link);
+ elem != &dbArray->nicknames.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ map = (certDBEntryMap *)node->appData;
+ dumpNicknameEntry((certDBEntryNickname*)&node->entry, map->index,
+ info->out);
+ if (map_handle_is_ok(info, map->pSubject, -1)) {
+ ref = ((certDBEntryMap *)map->pSubject->appData)->index;
+ PR_fprintf(info->out, "-->(subject %d)\n\n\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING SUBJECT ENTRY)\n\n\n");
+ }
+ }
+ for (elem = PR_LIST_HEAD(&dbArray->smime.link);
+ elem != &dbArray->smime.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ map = (certDBEntryMap *)node->appData;
+ dumpSMimeEntry((certDBEntrySMime*)&node->entry, map->index, info->out);
+ if (map_handle_is_ok(info, map->pSubject, -1)) {
+ ref = ((certDBEntryMap *)map->pSubject->appData)->index;
+ PR_fprintf(info->out, "-->(subject %d)\n\n\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING SUBJECT ENTRY)\n\n\n");
+ }
+ }
+ PR_fprintf(info->out, "\n\n");
+}
+
+char *errResult[] = {
+ "Certificate entries that had no subject entry.",
+ "Certificate entries that had no key in their subject entry.",
+ "Subject entries that had no nickname or email address.",
+ "Redundant nicknames (subjects with the same nickname).",
+ "Subject entries that had no nickname entry.",
+ "Redundant email addresses (subjects with the same email address).",
+ "Subject entries that had no S/MIME entry.",
+ "Nickname entries that had no subject entry.",
+ "S/MIME entries that had no subject entry.",
+};
+
+int
+fillDBEntryArray(CERTCertDBHandle *handle, certDBEntryType type,
+ certDBEntryListNode *list)
+{
+ PRCList *elem;
+ certDBEntryListNode *node;
+ certDBEntryMap *mnode;
+ certDBSubjectEntryMap *smnode;
+ PRArenaPool *arena;
+ int count = 0;
+ /* Initialize a dummy entry in the list. The list head will be the
+ * next element, so this element is skipped by for loops.
+ */
+ PR_INIT_CLIST((PRCList *)list);
+ /* Collect all of the cert db entries for this type into a list. */
+ SEC_TraverseDBEntries(handle, type, SEC_GetCertDBEntryList,
+ (PRCList *)list);
+ for (elem = PR_LIST_HEAD(&list->link);
+ elem != &list->link; elem = PR_NEXT_LINK(elem)) {
+ /* Iterate over the entries and ... */
+ node = (certDBEntryListNode *)elem;
+ if (type != certDBEntryTypeSubject) {
+ arena = PORT_NewArena(sizeof(*mnode));
+ mnode = (certDBEntryMap *)PORT_ArenaZAlloc(arena, sizeof(*mnode));
+ mnode->arena = arena;
+ /* ... assign a unique index number to each node, and ... */
+ mnode->index = count;
+ /* ... set the map pointer for the node. */
+ node->appData = (void *)mnode;
+ } else {
+ /* allocate some room for the cert pointers also */
+ arena = PORT_NewArena(sizeof(*smnode) + 20*sizeof(void *));
+ smnode = (certDBSubjectEntryMap *)
+ PORT_ArenaZAlloc(arena, sizeof(*smnode));
+ smnode->arena = arena;
+ smnode->index = count;
+ node->appData = (void *)smnode;
+ }
+ count++;
+ }
+ return count;
+}
+
+void
+freeDBEntryList(PRCList *list)
+{
+ PRCList *next, *elem;
+ certDBEntryListNode *node;
+ certDBEntryMap *map;
+
+ for (elem = PR_LIST_HEAD(list); elem != list;) {
+ next = PR_NEXT_LINK(elem);
+ node = (certDBEntryListNode *)elem;
+ map = (certDBEntryMap *)node->appData;
+ PR_REMOVE_LINK(&node->link);
+ PORT_FreeArena(map->arena, PR_TRUE);
+ PORT_FreeArena(node->entry.common.arena, PR_TRUE);
+ elem = next;
+ }
+}
+
+void
+DBCK_DebugDB(CERTCertDBHandle *handle, PRFileDesc *out, PRFileDesc *mailfile)
+{
+ int i, nCertsFound, nSubjFound, nErr;
+ int nCerts, nSubjects, nSubjCerts, nNicknames, nSMime;
+ PRCList *elem;
+ char c;
+ dbDebugInfo info;
+ certDBArray dbArray;
+
+ PORT_Memset(&dbArray, 0, sizeof(dbArray));
+ PORT_Memset(&info, 0, sizeof(info));
+ info.verbose = (out == NULL) ? PR_FALSE : PR_TRUE ;
+ info.dograph = (mailfile == NULL) ? PR_FALSE : PR_TRUE ;
+ info.out = (out) ? out : PR_STDOUT;
+ info.graphfile = mailfile;
+
+ /* Fill the array structure with cert/subject/nickname/smime entries. */
+ dbArray.numCerts = fillDBEntryArray(handle, certDBEntryTypeCert,
+ &dbArray.certs);
+ dbArray.numSubjects = fillDBEntryArray(handle, certDBEntryTypeSubject,
+ &dbArray.subjects);
+ dbArray.numNicknames = fillDBEntryArray(handle, certDBEntryTypeNickname,
+ &dbArray.nicknames);
+ dbArray.numSMime = fillDBEntryArray(handle, certDBEntryTypeSMimeProfile,
+ &dbArray.smime);
+
+ /* Compute the map between the database entries. */
+ mapSubjectEntries(&dbArray);
+ mapCertEntries(&dbArray);
+ computeDBGraph(&dbArray, &info);
+
+ /* Store the totals for later reference. */
+ nCerts = dbArray.numCerts;
+ nSubjects = dbArray.numSubjects;
+ nNicknames = dbArray.numNicknames;
+ nSMime = dbArray.numSMime;
+ nSubjCerts = 0;
+ for (elem = PR_LIST_HEAD(&dbArray.subjects.link);
+ elem != &dbArray.subjects.link; elem = PR_NEXT_LINK(elem)) {
+ certDBSubjectEntryMap *smap;
+ smap = (certDBSubjectEntryMap *)LISTNODE_CAST(elem)->appData;
+ nSubjCerts += smap->numCerts;
+ }
+
+ if (info.verbose) {
+ /* Dump the database contents. */
+ verboseOutput(&dbArray, &info);
+ }
+
+ freeDBEntryList(&dbArray.certs.link);
+ freeDBEntryList(&dbArray.subjects.link);
+ freeDBEntryList(&dbArray.nicknames.link);
+ freeDBEntryList(&dbArray.smime.link);
+
+ PR_fprintf(info.out, "\n");
+ PR_fprintf(info.out, "Database statistics:\n");
+ PR_fprintf(info.out, "N0: Found %4d Certificate entries.\n",
+ nCerts);
+ PR_fprintf(info.out, "N1: Found %4d Subject entries (unique DN's).\n",
+ nSubjects);
+ PR_fprintf(info.out, "N2: Found %4d Cert keys within Subject entries.\n",
+ nSubjCerts);
+ PR_fprintf(info.out, "N3: Found %4d Nickname entries.\n",
+ nNicknames);
+ PR_fprintf(info.out, "N4: Found %4d S/MIME entries.\n",
+ nSMime);
+ PR_fprintf(info.out, "\n");
+
+ nErr = 0;
+ for (i=0; i<sizeof(errResult)/sizeof(char*); i++) {
+ PR_fprintf(info.out, "E%d: Found %4d %s\n",
+ i, info.dbErrors[i], errResult[i]);
+ nErr += info.dbErrors[i];
+ }
+ PR_fprintf(info.out, "--------------\n Found %4d errors in database.\n",
+ nErr);
+
+ PR_fprintf(info.out, "\nCertificates:\n");
+ PR_fprintf(info.out, "N0 == N2 + E%d + E%d\n", NoSubjectForCert,
+ SubjectHasNoKeyForCert);
+ nCertsFound = nSubjCerts +
+ info.dbErrors[NoSubjectForCert] +
+ info.dbErrors[SubjectHasNoKeyForCert];
+ c = (nCertsFound == nCerts) ? '=' : '!';
+ PR_fprintf(info.out, "%d %c= %d + %d + %d\n", nCerts, c, nSubjCerts,
+ info.dbErrors[NoSubjectForCert],
+ info.dbErrors[SubjectHasNoKeyForCert]);
+ PR_fprintf(info.out, "\nSubjects:\n");
+ PR_fprintf(info.out, "N1 == N3 + N4 + E%d + E%d + E%d + E%d + E%d - E%d - E%d\n",
+ NoNicknameOrSMimeForSubject, WrongNicknameForSubject,
+ NoNicknameEntry, WrongSMimeForSubject, NoSMimeEntry,
+ NoSubjectForNickname, NoSubjectForSMime);
+ PR_fprintf(info.out, " - #(subjects with both nickname and S/MIME entries)\n");
+ nSubjFound = nNicknames + nSMime +
+ info.dbErrors[NoNicknameOrSMimeForSubject] +
+ info.dbErrors[WrongNicknameForSubject] +
+ info.dbErrors[NoNicknameEntry] +
+ info.dbErrors[WrongSMimeForSubject] +
+ info.dbErrors[NoSMimeEntry] -
+ info.dbErrors[NoSubjectForNickname] -
+ info.dbErrors[NoSubjectForSMime] -
+ info.dbErrors[NicknameAndSMimeEntry];
+ c = (nSubjFound == nSubjects) ? '=' : '!';
+ PR_fprintf(info.out, "%d %c= %d + %d + %d + %d + %d + %d + %d - %d - %d - %d\n",
+ nSubjects, c, nNicknames, nSMime,
+ info.dbErrors[NoNicknameOrSMimeForSubject],
+ info.dbErrors[WrongNicknameForSubject],
+ info.dbErrors[NoNicknameEntry],
+ info.dbErrors[WrongSMimeForSubject],
+ info.dbErrors[NoSMimeEntry],
+ info.dbErrors[NoSubjectForNickname],
+ info.dbErrors[NoSubjectForSMime],
+ info.dbErrors[NicknameAndSMimeEntry]);
+ PR_fprintf(info.out, "\n");
+}
+
+#ifdef DORECOVER
+enum {
+ dbInvalidCert = 0,
+ dbNoSMimeProfile,
+ dbOlderCert,
+ dbBadCertificate,
+ dbCertNotWrittenToDB
+};
+
+typedef struct dbRestoreInfoStr
+{
+ CERTCertDBHandle *handle;
+ PRBool verbose;
+ PRFileDesc *out;
+ int nCerts;
+ int nOldCerts;
+ int dbErrors[5];
+ PRBool removeType[3];
+ PRBool promptUser[3];
+} dbRestoreInfo;
+
+char *
+IsEmailCert(CERTCertificate *cert)
+{
+ char *email, *tmp1, *tmp2;
+ PRBool isCA;
+ int len;
+
+ if (!cert->subjectName) {
+ return NULL;
+ }
+
+ tmp1 = PORT_Strstr(cert->subjectName, "E=");
+ tmp2 = PORT_Strstr(cert->subjectName, "MAIL=");
+ /* XXX Nelson has cert for KTrilli which does not have either
+ * of above but is email cert (has cert->emailAddr).
+ */
+ if (!tmp1 && !tmp2 && !cert->emailAddr) {
+ return NULL;
+ }
+
+ /* Server or CA cert, not personal email. */
+ isCA = CERT_IsCACert(cert, NULL);
+ if (isCA)
+ return NULL;
+
+ /* XXX CERT_IsCACert advertises checking the key usage ext.,
+ but doesn't appear to. */
+ /* Check the key usage extension. */
+ if (cert->keyUsagePresent) {
+ /* Must at least be able to sign or encrypt (not neccesarily
+ * both if it is one of a dual cert).
+ */
+ if (!((cert->rawKeyUsage & KU_DIGITAL_SIGNATURE) ||
+ (cert->rawKeyUsage & KU_KEY_ENCIPHERMENT)))
+ return NULL;
+
+ /* CA cert, not personal email. */
+ if (cert->rawKeyUsage & (KU_KEY_CERT_SIGN | KU_CRL_SIGN))
+ return NULL;
+ }
+
+ if (cert->emailAddr) {
+ email = PORT_Strdup(cert->emailAddr);
+ } else {
+ if (tmp1)
+ tmp1 += 2; /* "E=" */
+ else
+ tmp1 = tmp2 + 5; /* "MAIL=" */
+ len = strcspn(tmp1, ", ");
+ email = (char*)PORT_Alloc(len+1);
+ PORT_Strncpy(email, tmp1, len);
+ email[len] = '\0';
+ }
+
+ return email;
+}
+
+SECStatus
+deleteit(CERTCertificate *cert, void *arg)
+{
+ return SEC_DeletePermCertificate(cert);
+}
+
+/* Different than DeleteCertificate - has the added bonus of removing
+ * all certs with the same DN.
+ */
+SECStatus
+deleteAllEntriesForCert(CERTCertDBHandle *handle, CERTCertificate *cert,
+ PRFileDesc *outfile)
+{
+#if 0
+ certDBEntrySubject *subjectEntry;
+ certDBEntryNickname *nicknameEntry;
+ certDBEntrySMime *smimeEntry;
+ int i;
+#endif
+
+ if (outfile) {
+ PR_fprintf(outfile, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n");
+ PR_fprintf(outfile, "Deleting redundant certificate:\n");
+ dumpCertificate(cert, -1, outfile);
+ }
+
+ CERT_TraverseCertsForSubject(handle, cert->subjectList, deleteit, NULL);
+#if 0
+ CERT_LockDB(handle);
+ subjectEntry = ReadDBSubjectEntry(handle, &cert->derSubject);
+ /* It had better be there, or created a bad db. */
+ PORT_Assert(subjectEntry);
+ for (i=0; i<subjectEntry->ncerts; i++) {
+ DeleteDBCertEntry(handle, &subjectEntry->certKeys[i]);
+ }
+ DeleteDBSubjectEntry(handle, &cert->derSubject);
+ if (subjectEntry->emailAddr) {
+ smimeEntry = ReadDBSMimeEntry(handle, subjectEntry->emailAddr);
+ if (smimeEntry) {
+ if (SECITEM_ItemsAreEqual(&subjectEntry->derSubject,
+ &smimeEntry->subjectName))
+ /* Only delete it if it's for this subject! */
+ DeleteDBSMimeEntry(handle, subjectEntry->emailAddr);
+ SEC_DestroyDBEntry((certDBEntry*)smimeEntry);
+ }
+ }
+ if (subjectEntry->nickname) {
+ nicknameEntry = ReadDBNicknameEntry(handle, subjectEntry->nickname);
+ if (nicknameEntry) {
+ if (SECITEM_ItemsAreEqual(&subjectEntry->derSubject,
+ &nicknameEntry->subjectName))
+ /* Only delete it if it's for this subject! */
+ DeleteDBNicknameEntry(handle, subjectEntry->nickname);
+ SEC_DestroyDBEntry((certDBEntry*)nicknameEntry);
+ }
+ }
+ SEC_DestroyDBEntry((certDBEntry*)subjectEntry);
+ CERT_UnlockDB(handle);
+#endif
+ return SECSuccess;
+}
+
+void
+getCertsToDelete(char *numlist, int len, int *certNums, int nCerts)
+{
+ int j, num;
+ char *numstr, *numend, *end;
+
+ numstr = numlist;
+ end = numstr + len - 1;
+ while (numstr != end) {
+ numend = strpbrk(numstr, ", \n");
+ *numend = '\0';
+ if (PORT_Strlen(numstr) == 0)
+ return;
+ num = PORT_Atoi(numstr);
+ if (numstr == numlist)
+ certNums[0] = num;
+ for (j=1; j<nCerts+1; j++) {
+ if (num == certNums[j]) {
+ certNums[j] = -1;
+ break;
+ }
+ }
+ if (numend == end)
+ break;
+ numstr = strpbrk(numend+1, "0123456789");
+ }
+}
+
+PRBool
+userSaysDeleteCert(CERTCertificate **certs, int nCerts,
+ int errtype, dbRestoreInfo *info, int *certNums)
+{
+ char response[32];
+ int32 nb;
+ int i;
+ /* User wants to remove cert without prompting. */
+ if (info->promptUser[errtype] == PR_FALSE)
+ return (info->removeType[errtype]);
+ switch (errtype) {
+ case dbInvalidCert:
+ PR_fprintf(PR_STDOUT, "******** Expired ********\n");
+ PR_fprintf(PR_STDOUT, "Cert has expired.\n\n");
+ dumpCertificate(certs[0], -1, PR_STDOUT);
+ PR_fprintf(PR_STDOUT,
+ "Keep it? (y/n - this one, Y/N - all expired certs) [n] ");
+ break;
+ case dbNoSMimeProfile:
+ PR_fprintf(PR_STDOUT, "******** No Profile ********\n");
+ PR_fprintf(PR_STDOUT, "S/MIME cert has no profile.\n\n");
+ dumpCertificate(certs[0], -1, PR_STDOUT);
+ PR_fprintf(PR_STDOUT,
+ "Keep it? (y/n - this one, Y/N - all S/MIME w/o profile) [n] ");
+ break;
+ case dbOlderCert:
+ PR_fprintf(PR_STDOUT, "******* Redundant nickname/email *******\n\n");
+ PR_fprintf(PR_STDOUT, "These certs have the same nickname/email:\n");
+ for (i=0; i<nCerts; i++)
+ dumpCertificate(certs[i], i, PR_STDOUT);
+ PR_fprintf(PR_STDOUT,
+ "Enter the certs you would like to keep from those listed above.\n");
+ PR_fprintf(PR_STDOUT,
+ "Use a comma-separated list of the cert numbers (ex. 0, 8, 12).\n");
+ PR_fprintf(PR_STDOUT,
+ "The first cert in the list will be the primary cert\n");
+ PR_fprintf(PR_STDOUT,
+ " accessed by the nickname/email handle.\n");
+ PR_fprintf(PR_STDOUT,
+ "List cert numbers to keep here, or hit enter\n");
+ PR_fprintf(PR_STDOUT,
+ " to always keep only the newest cert: ");
+ break;
+ default:
+ }
+ nb = PR_Read(PR_STDIN, response, sizeof(response));
+ PR_fprintf(PR_STDOUT, "\n\n");
+ if (errtype == dbOlderCert) {
+ if (!isdigit(response[0])) {
+ info->promptUser[errtype] = PR_FALSE;
+ info->removeType[errtype] = PR_TRUE;
+ return PR_TRUE;
+ }
+ getCertsToDelete(response, nb, certNums, nCerts);
+ return PR_TRUE;
+ }
+ /* User doesn't want to be prompted for this type anymore. */
+ if (response[0] == 'Y') {
+ info->promptUser[errtype] = PR_FALSE;
+ info->removeType[errtype] = PR_FALSE;
+ return PR_FALSE;
+ } else if (response[0] == 'N') {
+ info->promptUser[errtype] = PR_FALSE;
+ info->removeType[errtype] = PR_TRUE;
+ return PR_TRUE;
+ }
+ return (response[0] != 'y') ? PR_TRUE : PR_FALSE;
+}
+
+SECStatus
+addCertToDB(certDBEntryCert *certEntry, dbRestoreInfo *info,
+ CERTCertDBHandle *oldhandle)
+{
+ SECStatus rv = SECSuccess;
+ PRBool allowOverride;
+ PRBool userCert;
+ SECCertTimeValidity validity;
+ CERTCertificate *oldCert = NULL;
+ CERTCertificate *dbCert = NULL;
+ CERTCertificate *newCert = NULL;
+ CERTCertTrust *trust;
+ certDBEntrySMime *smimeEntry = NULL;
+ char *email = NULL;
+ char *nickname = NULL;
+ int nCertsForSubject = 1;
+
+ oldCert = CERT_DecodeDERCertificate(&certEntry->derCert, PR_FALSE,
+ certEntry->nickname);
+ if (!oldCert) {
+ info->dbErrors[dbBadCertificate]++;
+ SEC_DestroyDBEntry((certDBEntry*)certEntry);
+ return SECSuccess;
+ }
+
+ oldCert->dbEntry = certEntry;
+ oldCert->trust = &certEntry->trust;
+ oldCert->dbhandle = oldhandle;
+
+ trust = oldCert->trust;
+
+ info->nOldCerts++;
+
+ if (info->verbose)
+ PR_fprintf(info->out, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n");
+
+ if (oldCert->nickname)
+ nickname = PORT_Strdup(oldCert->nickname);
+
+ /* Always keep user certs. Skip ahead. */
+ /* XXX if someone sends themselves a signed message, it is possible
+ for their cert to be imported as an "other" cert, not a user cert.
+ this mucks with smime entries... */
+ userCert = (SEC_GET_TRUST_FLAGS(trust, trustSSL) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustEmail) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustObjectSigning) & CERTDB_USER);
+ if (userCert)
+ goto createcert;
+
+ /* If user chooses so, ignore expired certificates. */
+ allowOverride = (PRBool)((oldCert->keyUsage == certUsageSSLServer) ||
+ (oldCert->keyUsage == certUsageSSLServerWithStepUp));
+ validity = CERT_CheckCertValidTimes(oldCert, PR_Now(), allowOverride);
+ /* If cert expired and user wants to delete it, ignore it. */
+ if ((validity != secCertTimeValid) &&
+ userSaysDeleteCert(&oldCert, 1, dbInvalidCert, info, 0)) {
+ info->dbErrors[dbInvalidCert]++;
+ if (info->verbose) {
+ PR_fprintf(info->out, "Deleting expired certificate:\n");
+ dumpCertificate(oldCert, -1, info->out);
+ }
+ goto cleanup;
+ }
+
+ /* New database will already have default certs, don't attempt
+ to overwrite them. */
+ dbCert = CERT_FindCertByDERCert(info->handle, &oldCert->derCert);
+ if (dbCert) {
+ info->nCerts++;
+ if (info->verbose) {
+ PR_fprintf(info->out, "Added certificate to database:\n");
+ dumpCertificate(oldCert, -1, info->out);
+ }
+ goto cleanup;
+ }
+
+ /* Determine if cert is S/MIME and get its email if so. */
+ email = IsEmailCert(oldCert);
+
+ /*
+ XXX Just create empty profiles?
+ if (email) {
+ SECItem *profile = CERT_FindSMimeProfile(oldCert);
+ if (!profile &&
+ userSaysDeleteCert(&oldCert, 1, dbNoSMimeProfile, info, 0)) {
+ info->dbErrors[dbNoSMimeProfile]++;
+ if (info->verbose) {
+ PR_fprintf(info->out,
+ "Deleted cert missing S/MIME profile.\n");
+ dumpCertificate(oldCert, -1, info->out);
+ }
+ goto cleanup;
+ } else {
+ SECITEM_FreeItem(profile);
+ }
+ }
+ */
+
+createcert:
+
+ /* Sometimes happens... */
+ if (!nickname && userCert)
+ nickname = PORT_Strdup(oldCert->subjectName);
+
+ /* Create a new certificate, copy of the old one. */
+ newCert = CERT_NewTempCertificate(info->handle, &oldCert->derCert,
+ nickname, PR_FALSE, PR_TRUE);
+ if (!newCert) {
+ PR_fprintf(PR_STDERR, "Unable to create new certificate.\n");
+ dumpCertificate(oldCert, -1, PR_STDERR);
+ info->dbErrors[dbBadCertificate]++;
+ goto cleanup;
+ }
+
+ /* Add the cert to the new database. */
+ rv = CERT_AddTempCertToPerm(newCert, nickname, oldCert->trust);
+ if (rv) {
+ PR_fprintf(PR_STDERR, "Failed to write temp cert to perm database.\n");
+ dumpCertificate(oldCert, -1, PR_STDERR);
+ info->dbErrors[dbCertNotWrittenToDB]++;
+ goto cleanup;
+ }
+
+ if (info->verbose) {
+ PR_fprintf(info->out, "Added certificate to database:\n");
+ dumpCertificate(oldCert, -1, info->out);
+ }
+
+ /* If the cert is an S/MIME cert, and the first with it's subject,
+ * modify the subject entry to include the email address,
+ * CERT_AddTempCertToPerm does not do email addresses and S/MIME entries.
+ */
+ if (smimeEntry) { /*&& !userCert && nCertsForSubject == 1) { */
+#if 0
+ UpdateSubjectWithEmailAddr(newCert, email);
+#endif
+ SECItem emailProfile, profileTime;
+ rv = CERT_FindFullSMimeProfile(oldCert, &emailProfile, &profileTime);
+ /* calls UpdateSubjectWithEmailAddr */
+ if (rv == SECSuccess)
+ rv = CERT_SaveSMimeProfile(newCert, &emailProfile, &profileTime);
+ }
+
+ info->nCerts++;
+
+cleanup:
+
+ if (nickname)
+ PORT_Free(nickname);
+ if (email)
+ PORT_Free(email);
+ if (oldCert)
+ CERT_DestroyCertificate(oldCert);
+ if (dbCert)
+ CERT_DestroyCertificate(dbCert);
+ if (newCert)
+ CERT_DestroyCertificate(newCert);
+ if (smimeEntry)
+ SEC_DestroyDBEntry((certDBEntry*)smimeEntry);
+ return SECSuccess;
+}
+
+#if 0
+SECStatus
+copyDBEntry(SECItem *data, SECItem *key, certDBEntryType type, void *pdata)
+{
+ SECStatus rv;
+ CERTCertDBHandle *newdb = (CERTCertDBHandle *)pdata;
+ certDBEntryCommon common;
+ SECItem dbkey;
+
+ common.type = type;
+ common.version = CERT_DB_FILE_VERSION;
+ common.flags = data->data[2];
+ common.arena = NULL;
+
+ dbkey.len = key->len + SEC_DB_KEY_HEADER_LEN;
+ dbkey.data = (unsigned char *)PORT_Alloc(dbkey.len*sizeof(unsigned char));
+ PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], key->data, key->len);
+ dbkey.data[0] = type;
+
+ rv = WriteDBEntry(newdb, &common, &dbkey, data);
+
+ PORT_Free(dbkey.data);
+ return rv;
+}
+#endif
+
+int
+certIsOlder(CERTCertificate **cert1, CERTCertificate** cert2)
+{
+ return !CERT_IsNewer(*cert1, *cert2);
+}
+
+int
+findNewestSubjectForEmail(CERTCertDBHandle *handle, int subjectNum,
+ certDBArray *dbArray, dbRestoreInfo *info,
+ int *subjectWithSMime, int *smimeForSubject)
+{
+ int newestSubject;
+ int subjectsForEmail[50];
+ int i, j, ns, sNum;
+ certDBEntryListNode *subjects = &dbArray->subjects;
+ certDBEntryListNode *smime = &dbArray->smime;
+ certDBEntrySubject *subjectEntry1, *subjectEntry2;
+ certDBEntrySMime *smimeEntry;
+ CERTCertificate **certs;
+ CERTCertificate *cert;
+ CERTCertTrust *trust;
+ PRBool userCert;
+ int *certNums;
+
+ ns = 0;
+ subjectEntry1 = (certDBEntrySubject*)&subjects.entries[subjectNum];
+ subjectsForEmail[ns++] = subjectNum;
+
+ *subjectWithSMime = -1;
+ *smimeForSubject = -1;
+ newestSubject = subjectNum;
+
+ cert = CERT_FindCertByKey(handle, &subjectEntry1->certKeys[0]);
+ if (cert) {
+ trust = cert->trust;
+ userCert = (SEC_GET_TRUST_FLAGS(trust, trustSSL) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustEmail) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustObjectSigning) & CERTDB_USER);
+ CERT_DestroyCertificate(cert);
+ }
+
+ /* Loop over the remaining subjects. */
+ for (i=subjectNum+1; i<subjects.numEntries; i++) {
+ subjectEntry2 = (certDBEntrySubject*)&subjects.entries[i];
+ if (!subjectEntry2)
+ continue;
+ if (subjectEntry2->emailAddr &&
+ PORT_Strcmp(subjectEntry1->emailAddr,
+ subjectEntry2->emailAddr) == 0) {
+ /* Found a subject using the same email address. */
+ subjectsForEmail[ns++] = i;
+ }
+ }
+
+ /* Find the S/MIME entry for this email address. */
+ for (i=0; i<smime.numEntries; i++) {
+ smimeEntry = (certDBEntrySMime*)&smime.entries[i];
+ if (smimeEntry->common.arena == NULL)
+ continue;
+ if (PORT_Strcmp(subjectEntry1->emailAddr, smimeEntry->emailAddr) == 0) {
+ /* Find which of the subjects uses this S/MIME entry. */
+ for (j=0; j<ns && *subjectWithSMime < 0; j++) {
+ sNum = subjectsForEmail[j];
+ subjectEntry2 = (certDBEntrySubject*)&subjects.entries[sNum];
+ if (SECITEM_ItemsAreEqual(&smimeEntry->subjectName,
+ &subjectEntry2->derSubject)) {
+ /* Found the subject corresponding to the S/MIME entry. */
+ *subjectWithSMime = sNum;
+ *smimeForSubject = i;
+ }
+ }
+ SEC_DestroyDBEntry((certDBEntry*)smimeEntry);
+ PORT_Memset(smimeEntry, 0, sizeof(certDBEntry));
+ break;
+ }
+ }
+
+ if (ns <= 1)
+ return subjectNum;
+
+ if (userCert)
+ return *subjectWithSMime;
+
+ /* Now find which of the subjects has the newest cert. */
+ certs = (CERTCertificate**)PORT_Alloc(ns*sizeof(CERTCertificate*));
+ certNums = (int*)PORT_Alloc((ns+1)*sizeof(int));
+ certNums[0] = 0;
+ for (i=0; i<ns; i++) {
+ sNum = subjectsForEmail[i];
+ subjectEntry1 = (certDBEntrySubject*)&subjects.entries[sNum];
+ certs[i] = CERT_FindCertByKey(handle, &subjectEntry1->certKeys[0]);
+ certNums[i+1] = i;
+ }
+ /* Sort the array by validity. */
+ qsort(certs, ns, sizeof(CERTCertificate*),
+ (int (*)(const void *, const void *))certIsOlder);
+ newestSubject = -1;
+ for (i=0; i<ns; i++) {
+ sNum = subjectsForEmail[i];
+ subjectEntry1 = (certDBEntrySubject*)&subjects.entries[sNum];
+ if (SECITEM_ItemsAreEqual(&subjectEntry1->derSubject,
+ &certs[0]->derSubject))
+ newestSubject = sNum;
+ else
+ SEC_DestroyDBEntry((certDBEntry*)subjectEntry1);
+ }
+ if (info && userSaysDeleteCert(certs, ns, dbOlderCert, info, certNums)) {
+ for (i=1; i<ns+1; i++) {
+ if (certNums[i] >= 0 && certNums[i] != certNums[0]) {
+ deleteAllEntriesForCert(handle, certs[certNums[i]], info->out);
+ info->dbErrors[dbOlderCert]++;
+ }
+ }
+ }
+ CERT_DestroyCertArray(certs, ns);
+ return newestSubject;
+}
+
+CERTCertDBHandle *
+DBCK_ReconstructDBFromCerts(CERTCertDBHandle *oldhandle, char *newdbname,
+ PRFileDesc *outfile, PRBool removeExpired,
+ PRBool requireProfile, PRBool singleEntry,
+ PRBool promptUser)
+{
+ SECStatus rv;
+ dbRestoreInfo info;
+ certDBEntryContentVersion *oldContentVersion;
+ certDBArray dbArray;
+ int i;
+
+ PORT_Memset(&dbArray, 0, sizeof(dbArray));
+ PORT_Memset(&info, 0, sizeof(info));
+ info.verbose = (outfile) ? PR_TRUE : PR_FALSE;
+ info.out = (outfile) ? outfile : PR_STDOUT;
+ info.removeType[dbInvalidCert] = removeExpired;
+ info.removeType[dbNoSMimeProfile] = requireProfile;
+ info.removeType[dbOlderCert] = singleEntry;
+ info.promptUser[dbInvalidCert] = promptUser;
+ info.promptUser[dbNoSMimeProfile] = promptUser;
+ info.promptUser[dbOlderCert] = promptUser;
+
+ /* Allocate a handle to fill with CERT_OpenCertDB below. */
+ info.handle = (CERTCertDBHandle *)PORT_ZAlloc(sizeof(CERTCertDBHandle));
+ if (!info.handle) {
+ fprintf(stderr, "unable to get database handle");
+ return NULL;
+ }
+
+ /* Create a certdb with the most recent set of roots. */
+ rv = CERT_OpenCertDBFilename(info.handle, newdbname, PR_FALSE);
+
+ if (rv) {
+ fprintf(stderr, "could not open certificate database");
+ goto loser;
+ }
+
+ /* Create certificate, subject, nickname, and email records.
+ * mcom_db seems to have a sequential access bug. Though reads and writes
+ * should be allowed during traversal, they seem to screw up the sequence.
+ * So, stuff all the cert entries into an array, and loop over the array
+ * doing read/writes in the db.
+ */
+ fillDBEntryArray(oldhandle, certDBEntryTypeCert, &dbArray.certs);
+ for (elem = PR_LIST_HEAD(&dbArray->certs.link);
+ elem != &dbArray->certs.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ addCertToDB((certDBEntryCert*)&node->entry, &info, oldhandle);
+ /* entries get destroyed in addCertToDB */
+ }
+#if 0
+ rv = SEC_TraverseDBEntries(oldhandle, certDBEntryTypeSMimeProfile,
+ copyDBEntry, info.handle);
+#endif
+
+ /* Fix up the pointers between (nickname|S/MIME) --> (subject).
+ * Create S/MIME entries for S/MIME certs.
+ * Have the S/MIME entry point to the last-expiring cert using
+ * an email address.
+ */
+#if 0
+ CERT_RedoHandlesForSubjects(info.handle, singleEntry, &info);
+#endif
+
+ freeDBEntryList(&dbArray.certs.link);
+
+ /* Copy over the version record. */
+ /* XXX Already exists - and _must_ be correct... */
+ /*
+ versionEntry = ReadDBVersionEntry(oldhandle);
+ rv = WriteDBVersionEntry(info.handle, versionEntry);
+ */
+
+ /* Copy over the content version record. */
+ /* XXX Can probably get useful info from old content version?
+ * Was this db created before/after this tool? etc.
+ */
+#if 0
+ oldContentVersion = ReadDBContentVersionEntry(oldhandle);
+ CERT_SetDBContentVersion(oldContentVersion->contentVersion, info.handle);
+#endif
+
+#if 0
+ /* Copy over the CRL & KRL records. */
+ rv = SEC_TraverseDBEntries(oldhandle, certDBEntryTypeRevocation,
+ copyDBEntry, info.handle);
+ /* XXX Only one KRL, just do db->get? */
+ rv = SEC_TraverseDBEntries(oldhandle, certDBEntryTypeKeyRevocation,
+ copyDBEntry, info.handle);
+#endif
+
+ PR_fprintf(info.out, "Database had %d certificates.\n", info.nOldCerts);
+
+ PR_fprintf(info.out, "Reconstructed %d certificates.\n", info.nCerts);
+ PR_fprintf(info.out, "(ax) Rejected %d expired certificates.\n",
+ info.dbErrors[dbInvalidCert]);
+ PR_fprintf(info.out, "(as) Rejected %d S/MIME certificates missing a profile.\n",
+ info.dbErrors[dbNoSMimeProfile]);
+ PR_fprintf(info.out, "(ar) Rejected %d certificates for which a newer certificate was found.\n",
+ info.dbErrors[dbOlderCert]);
+ PR_fprintf(info.out, " Rejected %d corrupt certificates.\n",
+ info.dbErrors[dbBadCertificate]);
+ PR_fprintf(info.out, " Rejected %d certificates which did not write to the DB.\n",
+ info.dbErrors[dbCertNotWrittenToDB]);
+
+ if (rv)
+ goto loser;
+
+ return info.handle;
+
+loser:
+ if (info.handle)
+ PORT_Free(info.handle);
+ return NULL;
+}
+#endif /* DORECOVER */
+
+enum {
+ cmd_Debug = 0,
+ cmd_LongUsage,
+ cmd_Recover
+};
+
+enum {
+ opt_KeepAll = 0,
+ opt_CertDir,
+ opt_Dumpfile,
+ opt_InputDB,
+ opt_OutputDB,
+ opt_Mailfile,
+ opt_Prompt,
+ opt_KeepRedundant,
+ opt_KeepNoSMimeProfile,
+ opt_Verbose,
+ opt_KeepExpired
+};
+
+static secuCommandFlag dbck_commands[] =
+{
+ { /* cmd_Debug, */ 'D', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_LongUsage,*/ 'H', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Recover, */ 'R', PR_FALSE, 0, PR_FALSE }
+};
+
+static secuCommandFlag dbck_options[] =
+{
+ { /* opt_KeepAll, */ 'a', PR_FALSE, 0, PR_FALSE },
+ { /* opt_CertDir, */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Dumpfile, */ 'f', PR_TRUE, 0, PR_FALSE },
+ { /* opt_InputDB, */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OutputDB, */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Mailfile, */ 'm', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Prompt, */ 'p', PR_FALSE, 0, PR_FALSE },
+ { /* opt_KeepRedundant, */ 'r', PR_FALSE, 0, PR_FALSE },
+ { /* opt_KeepNoSMimeProfile,*/ 's', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Verbose, */ 'v', PR_FALSE, 0, PR_FALSE },
+ { /* opt_KeepExpired, */ 'x', PR_FALSE, 0, PR_FALSE }
+};
+
+int
+main(int argc, char **argv)
+{
+ CERTCertDBHandle *certHandle;
+
+ PRFileInfo fileInfo;
+ PRFileDesc *mailfile = NULL;
+ PRFileDesc *dumpfile = NULL;
+
+ char * pathname = 0;
+ char * fullname = 0;
+ char * newdbname = 0;
+
+ PRBool removeExpired, requireProfile, singleEntry;
+
+ SECStatus rv;
+
+ secuCommand dbck;
+ dbck.numCommands = sizeof(dbck_commands) / sizeof(secuCommandFlag);
+ dbck.numOptions = sizeof(dbck_options) / sizeof(secuCommandFlag);
+ dbck.commands = dbck_commands;
+ dbck.options = dbck_options;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &dbck);
+
+ if (rv != SECSuccess)
+ Usage(progName);
+
+ if (dbck.commands[cmd_LongUsage].activated)
+ LongUsage(progName);
+
+ if (!dbck.commands[cmd_Debug].activated &&
+ !dbck.commands[cmd_Recover].activated) {
+ PR_fprintf(PR_STDERR, "Please specify -D or -R.\n");
+ Usage(progName);
+ }
+
+ removeExpired = !(dbck.options[opt_KeepAll].activated ||
+ dbck.options[opt_KeepExpired].activated);
+
+ requireProfile = !(dbck.options[opt_KeepAll].activated ||
+ dbck.options[opt_KeepNoSMimeProfile].activated);
+
+ singleEntry = !(dbck.options[opt_KeepAll].activated ||
+ dbck.options[opt_KeepRedundant].activated);
+
+ if (dbck.options[opt_OutputDB].activated) {
+ newdbname = PL_strdup(dbck.options[opt_OutputDB].arg);
+ } else {
+ newdbname = PL_strdup("new_cert7.db");
+ }
+
+ /* Create a generic graph of the database. */
+ if (dbck.options[opt_Mailfile].activated) {
+ mailfile = PR_Open("./mailfile", PR_RDWR | PR_CREATE_FILE, 00660);
+ if (!mailfile) {
+ fprintf(stderr, "Unable to create mailfile.\n");
+ return -1;
+ }
+ }
+
+ /* Dump all debugging info while running. */
+ if (dbck.options[opt_Verbose].activated) {
+ if (dbck.options[opt_Dumpfile].activated) {
+ dumpfile = PR_Open(dbck.options[opt_Dumpfile].arg,
+ PR_RDWR | PR_CREATE_FILE, 00660);
+ }
+ if (!dumpfile) {
+ fprintf(stderr, "Unable to create dumpfile.\n");
+ return -1;
+ }
+ }
+
+ /* Set the cert database directory. */
+ if (dbck.options[opt_CertDir].activated) {
+ SECU_ConfigDirectory(dbck.options[opt_CertDir].arg);
+ }
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ SEC_Init();
+
+ certHandle = (CERTCertDBHandle *)PORT_ZAlloc(sizeof(CERTCertDBHandle));
+ if (!certHandle) {
+ SECU_PrintError(progName, "unable to get database handle");
+ return -1;
+ }
+
+ /* Open the possibly corrupt database. */
+ if (dbck.options[opt_InputDB].activated) {
+ pathname = SECU_ConfigDirectory(NULL);
+ fullname = PR_smprintf("%s/%s", pathname,
+ dbck.options[opt_InputDB].arg);
+ if (PR_GetFileInfo(fullname, &fileInfo) != PR_SUCCESS) {
+ fprintf(stderr, "Unable to read file \"%s\".\n", fullname);
+ return -1;
+ }
+ rv = CERT_OpenCertDBFilename(certHandle, fullname, PR_TRUE);
+ } else {
+ /* Use the default. */
+ fullname = SECU_CertDBNameCallback(NULL, CERT_DB_FILE_VERSION);
+ if (PR_GetFileInfo(fullname, &fileInfo) != PR_SUCCESS) {
+ fprintf(stderr, "Unable to read file \"%s\".\n", fullname);
+ return -1;
+ }
+ rv = CERT_OpenCertDB(certHandle, PR_TRUE,
+ SECU_CertDBNameCallback, NULL);
+ }
+
+ if (rv) {
+ SECU_PrintError(progName, "unable to open cert database");
+ return -1;
+ }
+
+ if (dbck.commands[cmd_Debug].activated) {
+ DBCK_DebugDB(certHandle, dumpfile, mailfile);
+ return 0;
+ }
+
+#ifdef DORECOVER
+ if (dbck.commands[cmd_Recover].activated) {
+ DBCK_ReconstructDBFromCerts(certHandle, newdbname,
+ dumpfile, removeExpired,
+ requireProfile, singleEntry,
+ dbck.options[opt_Prompt].activated);
+ return 0;
+ }
+#endif
+
+ if (mailfile)
+ PR_Close(mailfile);
+ if (dumpfile)
+ PR_Close(dumpfile);
+ if (certHandle) {
+ CERT_ClosePermCertDB(certHandle);
+ PORT_Free(certHandle);
+ }
+ return -1;
+}
diff --git a/security/nss/cmd/dbck/manifest.mn b/security/nss/cmd/dbck/manifest.mn
new file mode 100644
index 000000000..74e66c49e
--- /dev/null
+++ b/security/nss/cmd/dbck/manifest.mn
@@ -0,0 +1,49 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ dbck.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = dbm seccmd
+
+PROGRAM = dbck
diff --git a/security/nss/cmd/dbtest/Makefile b/security/nss/cmd/dbtest/Makefile
new file mode 100644
index 000000000..0ff13ae43
--- /dev/null
+++ b/security/nss/cmd/dbtest/Makefile
@@ -0,0 +1,88 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+ifdef XP_OS2_VACPP
+CFLAGS += -I../modutil
+endif
+
+ifeq (,$(filter-out WINNT WIN95 WIN16,$(OS_TARGET))) # omits WINCE
+ifndef BUILD_OPT
+ifndef NS_USE_GCC
+LDFLAGS += /subsystem:console /profile /debug /machine:I386 /incremental:no
+endif
+OS_CFLAGS += -D_CONSOLE
+endif
+endif
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#include ../platlibs.mk
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/dbtest/dbtest.c b/security/nss/cmd/dbtest/dbtest.c
new file mode 100644
index 000000000..39f659522
--- /dev/null
+++ b/security/nss/cmd/dbtest/dbtest.c
@@ -0,0 +1,181 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ * Sonja Mirtitsch Sun Microsystems
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+** dbtest.c
+**
+** QA test for cert and key databases, especially to open
+** database readonly (NSS_INIT_READONLY) and force initializations
+** even if the databases cannot be opened (NSS_INIT_FORCEOPEN)
+**
+*/
+#include <stdio.h>
+#include <string.h>
+
+#if defined(WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "certdb.h"
+#include "nss.h"
+#include "../modutil/modutil.h"
+
+#include "plgetopt.h"
+
+static char *progName;
+
+char *dbDir = NULL;
+
+static char *dbName[]={"secmod.db", "cert8.db", "key3.db"};
+static char* dbprefix = "";
+static char* secmodName = "secmod.db";
+PRBool verbose;
+
+
+static void Usage(const char *progName)
+{
+ printf("Usage: %s [-r] [-f] [-d dbdir ] \n",
+ progName);
+ printf("%-20s open database readonly (NSS_INIT_READONLY)\n", "-r");
+ printf("%-20s Continue to force initializations even if the\n", "-f");
+ printf("%-20s databases cannot be opened (NSS_INIT_FORCEOPEN)\n", " ");
+ printf("%-20s Directory with cert database (default is .\n",
+ "-d certdir");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ PLOptState *optstate;
+ PLOptStatus optstatus;
+
+ PRUint32 flags = 0;
+ PRBool useCommandLinePassword = PR_FALSE;
+ Error ret;
+ SECStatus rv;
+ char * dbString = NULL;
+ int i;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName+1 : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "rfd:h");
+
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'h':
+ default : Usage(progName); break;
+
+ case 'r': flags |= NSS_INIT_READONLY; break;
+
+ case 'f': flags |= NSS_INIT_FORCEOPEN; break;
+
+ case 'd':
+ dbDir = PORT_Strdup(optstate->value);
+ break;
+
+ }
+ }
+ if (optstatus == PL_OPT_BAD)
+ Usage(progName);
+
+ if (!dbDir) {
+ dbDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
+ }
+ dbDir = SECU_ConfigDirectory(dbDir);
+ PR_fprintf(PR_STDERR, "dbdir selected is %s\n\n", dbDir);
+
+ if( dbDir[0] == '\0') {
+ PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
+ ret= DIR_DOESNT_EXIST_ERR;
+ goto loser;
+ }
+
+
+ PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+ /* get the status of the directory and databases and output message */
+ if(PR_Access(dbDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
+ } else if(PR_Access(dbDir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dbDir);
+ } else {
+ if( !( flags & NSS_INIT_READONLY ) &&
+ PR_Access(dbDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dbDir);
+ }
+ for (i=0;i<3;i++) {
+ dbString=PR_smprintf("%s/%s",dbDir,dbName[i]);
+ PR_fprintf(PR_STDOUT, "database checked is %s\n",dbString);
+ if(PR_Access(dbString, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_DOESNT_EXIST_ERR],
+ dbString);
+ } else if(PR_Access(dbString, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
+ dbString);
+ } else if( !( flags & NSS_INIT_READONLY ) &&
+ PR_Access(dbString, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
+ dbString);
+ }
+ }
+ }
+
+ rv = NSS_Initialize(SECU_ConfigDirectory(dbDir), dbprefix, dbprefix,
+ secmodName, flags);
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ ret=NSS_INITIALIZE_FAILED_ERR;
+ } else {
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ ret=SUCCESS;
+ }
+
+loser:
+ return ret;
+}
+
diff --git a/security/nss/cmd/dbtest/makefile.win b/security/nss/cmd/dbtest/makefile.win
new file mode 100644
index 000000000..5a60fd0af
--- /dev/null
+++ b/security/nss/cmd/dbtest/makefile.win
@@ -0,0 +1,130 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+#cannot define PROGRAM in manifest compatibly with NT and UNIX
+PROGRAM = dbtest
+PROGRAM = ./$(OBJDIR)/$(PROGRAM).exe
+include <$(DEPTH)\config\config.mak>
+
+# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
+# rules.mak will append C_OBJS onto OBJS.
+# OBJS = $(CSRCS:.c=.obj)
+
+# include files are looked for in $LINCS and $INCS.
+# $LINCS is in manifest.mnw, computed from REQUIRES=
+INCS = $(INCS) \
+ -I$(DEPTH)/security/lib/cert \
+ -I../include \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+ $(NULL)
+
+
+WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
+
+# these files are the content of libdbm
+DBM_LIB = \
+ $(WINFE)/DB.obj \
+ $(WINFE)/HASH.obj \
+ $(WINFE)/H_BIGKEY.obj \
+ $(WINFE)/H_PAGE.obj \
+ $(WINFE)/H_LOG2.obj \
+ $(WINFE)/H_FUNC.obj \
+ $(WINFE)/HASH_BUF.obj \
+ $(NULL)
+
+MOZ_LIBS = \
+ $(WINFE)/ALLXPSTR.obj \
+ $(WINFE)/XP_ERROR.obj \
+ $(WINFE)/XPASSERT.obj \
+ $(WINFE)/XP_REG.obj \
+ $(WINFE)/XP_TRACE.obj \
+ $(DBM_LIB) \
+ $(WINFE)/XP_STR.obj \
+ $(WINFE)/MKTEMP.obj \
+ $(NULL)
+
+SEC_LIBS = \
+ $(DIST)/lib/cert$(MOZ_BITS).lib \
+ $(DIST)/lib/crypto$(MOZ_BITS).lib \
+ $(DIST)/lib/hash$(MOZ_BITS).lib \
+ $(DIST)/lib/key$(MOZ_BITS).lib \
+ $(DIST)/lib/pkcs7$(MOZ_BITS).lib \
+ $(DIST)/lib/secmod$(MOZ_BITS).lib \
+ $(DIST)/lib/secutl$(MOZ_BITS).lib \
+ $(DIST)/lib/ssl$(MOZ_BITS).lib \
+ $(NULL)
+
+LLFLAGS = $(LLFLAGS) \
+ ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
+ $(SEC_LIBS) \
+ $(MOZ_LIBS) \
+ $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
+ $(LIBNSPR) \
+ $(NULL)
+
+
+include <$(DEPTH)\config\rules.mak>
+
+INSTALL = $(MAKE_INSTALL)
+
+objs: $(OBJS)
+
+$(PROGRAM)::
+ $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
+
+programs: $(PROGRAM)
+
+install:: $(TARGETS)
+ $(INSTALL) $(TARGETS) $(DIST)/bin
+
+
+symbols:
+ @echo "CSRCS = $(CSRCS)"
+ @echo "INCS = $(INCS)"
+ @echo "OBJS = $(OBJS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "TARGETS = $(TARGETS)"
+ @echo "DIST = $(DIST)"
+ @echo "VERSION_NUMBER = $(VERSION_NUMBER)"
+ @echo "WINFE = $(WINFE)"
+ @echo "DBM_LIB = $(DBM_LIB)"
+ @echo "INSTALL = $(INSTALL)"
+
diff --git a/security/nss/cmd/dbtest/manifest.mn b/security/nss/cmd/dbtest/manifest.mn
new file mode 100644
index 000000000..0f6888088
--- /dev/null
+++ b/security/nss/cmd/dbtest/manifest.mn
@@ -0,0 +1,50 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+# DIRS =
+
+CSRCS = dbtest.c
+
+PROGRAM = dbtest
+
diff --git a/security/nss/cmd/derdump/Makefile b/security/nss/cmd/derdump/Makefile
new file mode 100644
index 000000000..573c12cac
--- /dev/null
+++ b/security/nss/cmd/derdump/Makefile
@@ -0,0 +1,76 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/derdump/derdump.c b/security/nss/cmd/derdump/derdump.c
new file mode 100644
index 000000000..603d5f772
--- /dev/null
+++ b/security/nss/cmd/derdump/derdump.c
@@ -0,0 +1,135 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "secutil.h"
+#include "nss.h"
+#include <errno.h>
+
+#if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
+#if !defined(WIN32)
+extern int fprintf(FILE *, char *, ...);
+#endif
+#endif
+#include "plgetopt.h"
+
+static void Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-r] [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s For formatted items, dump raw bytes as well\n",
+ "-r");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+ char *progName;
+ int option;
+ FILE *outFile;
+ PRFileDesc *inFile;
+ SECItem der;
+ SECStatus rv;
+ int16 xp_error;
+ PRBool raw = PR_FALSE;
+ PLOptState *optstate;
+ PLOptStatus status;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ /* Parse command line arguments */
+ inFile = 0;
+ outFile = 0;
+ optstate = PL_CreateOptState(argc, argv, "i:o:r");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'r':
+ raw = PR_TRUE;
+ break;
+
+ default:
+ Usage(progName);
+ break;
+ }
+ }
+ if (status == PL_OPT_BAD)
+ Usage(progName);
+
+ if (!inFile) inFile = PR_STDIN;
+ if (!outFile) outFile = stdout;
+
+ rv = NSS_NoDB_Init(NULL); /* XXX */
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+
+ rv = SECU_ReadDERFromFile(&der, inFile, PR_FALSE);
+ if (rv == SECSuccess) {
+ rv = DER_PrettyPrint(outFile, &der, raw);
+ if (rv == SECSuccess)
+ return 0;
+ }
+
+ xp_error = PORT_GetError();
+ if (xp_error) {
+ SECU_PrintError(progName, "error %d", xp_error);
+ }
+ if (errno) {
+ SECU_PrintSystemError(progName, "errno=%d", errno);
+ }
+ return 1;
+}
diff --git a/security/nss/cmd/derdump/makefile.win b/security/nss/cmd/derdump/makefile.win
new file mode 100644
index 000000000..9a9d4edef
--- /dev/null
+++ b/security/nss/cmd/derdump/makefile.win
@@ -0,0 +1,130 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+#cannot define PROGRAM in manifest compatibly with NT and UNIX
+PROGRAM = derdump
+PROGRAM = ./$(OBJDIR)/$(PROGRAM).exe
+include <$(DEPTH)\config\config.mak>
+
+# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
+# rules.mak will append C_OBJS onto OBJS.
+# OBJS = $(CSRCS:.c=.obj)
+
+# include files are looked for in $LINCS and $INCS.
+# $LINCS is in manifest.mnw, computed from REQUIRES=
+INCS = $(INCS) \
+ -I$(DEPTH)/security/lib/cert \
+ -I../include \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+ $(NULL)
+
+
+WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
+
+# these files are the content of libdbm
+DBM_LIB = \
+ $(WINFE)/DB.obj \
+ $(WINFE)/HASH.obj \
+ $(WINFE)/H_BIGKEY.obj \
+ $(WINFE)/H_PAGE.obj \
+ $(WINFE)/H_LOG2.obj \
+ $(WINFE)/H_FUNC.obj \
+ $(WINFE)/HASH_BUF.obj \
+ $(NULL)
+
+MOZ_LIBS = \
+ $(WINFE)/ALLXPSTR.obj \
+ $(WINFE)/XP_ERROR.obj \
+ $(WINFE)/XPASSERT.obj \
+ $(WINFE)/XP_REG.obj \
+ $(WINFE)/XP_TRACE.obj \
+ $(DBM_LIB) \
+ $(WINFE)/XP_STR.obj \
+ $(WINFE)/MKTEMP.obj \
+ $(NULL)
+
+SEC_LIBS = \
+ $(DIST)/lib/cert$(MOZ_BITS).lib \
+ $(DIST)/lib/crypto$(MOZ_BITS).lib \
+ $(DIST)/lib/hash$(MOZ_BITS).lib \
+ $(DIST)/lib/key$(MOZ_BITS).lib \
+ $(DIST)/lib/pkcs7$(MOZ_BITS).lib \
+ $(DIST)/lib/secmod$(MOZ_BITS).lib \
+ $(DIST)/lib/secutl$(MOZ_BITS).lib \
+ $(DIST)/lib/ssl$(MOZ_BITS).lib \
+ $(NULL)
+
+LLFLAGS = $(LLFLAGS) \
+ ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
+ $(SEC_LIBS) \
+ $(MOZ_LIBS) \
+ $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
+ $(LIBNSPR) \
+ $(NULL)
+
+
+include <$(DEPTH)\config\rules.mak>
+
+INSTALL = $(MAKE_INSTALL)
+
+objs: $(OBJS)
+
+$(PROGRAM)::
+ $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
+
+programs: $(PROGRAM)
+
+install:: $(TARGETS)
+ $(INSTALL) $(TARGETS) $(DIST)/bin
+
+
+symbols:
+ @echo "CSRCS = $(CSRCS)"
+ @echo "INCS = $(INCS)"
+ @echo "OBJS = $(OBJS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "TARGETS = $(TARGETS)"
+ @echo "DIST = $(DIST)"
+ @echo "VERSION_NUMBER = $(VERSION_NUMBER)"
+ @echo "WINFE = $(WINFE)"
+ @echo "DBM_LIB = $(DBM_LIB)"
+ @echo "INSTALL = $(INSTALL)"
+
diff --git a/security/nss/cmd/derdump/manifest.mn b/security/nss/cmd/derdump/manifest.mn
new file mode 100644
index 000000000..d9252cd0d
--- /dev/null
+++ b/security/nss/cmd/derdump/manifest.mn
@@ -0,0 +1,49 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = derdump.c
+
+PROGRAM = derdump
diff --git a/security/nss/cmd/digest/Makefile b/security/nss/cmd/digest/Makefile
new file mode 100644
index 000000000..573c12cac
--- /dev/null
+++ b/security/nss/cmd/digest/Makefile
@@ -0,0 +1,76 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/digest/digest.c b/security/nss/cmd/digest/digest.c
new file mode 100644
index 000000000..5405b1a3e
--- /dev/null
+++ b/security/nss/cmd/digest/digest.c
@@ -0,0 +1,254 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "secutil.h"
+#include "pk11func.h"
+#include "secoid.h"
+
+#if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
+#if !defined(WIN32)
+extern int fread(char *, size_t, size_t, FILE*);
+extern int fwrite(char *, size_t, size_t, FILE*);
+extern int fprintf(FILE *, char *, ...);
+#endif
+#endif
+
+#include "plgetopt.h"
+
+static SECOidData *
+HashTypeToOID(HASH_HashType hashtype)
+{
+ SECOidTag hashtag;
+
+ if (hashtype <= HASH_AlgNULL || hashtype >= HASH_AlgTOTAL)
+ return NULL;
+
+ switch (hashtype) {
+ case HASH_AlgMD2:
+ hashtag = SEC_OID_MD2;
+ break;
+ case HASH_AlgMD5:
+ hashtag = SEC_OID_MD5;
+ break;
+ case HASH_AlgSHA1:
+ hashtag = SEC_OID_SHA1;
+ break;
+ default:
+ fprintf(stderr, "A new hash type has been added to HASH_HashType.\n");
+ fprintf(stderr, "This program needs to be updated!\n");
+ return NULL;
+ }
+
+ return SECOID_FindOIDByTag(hashtag);
+}
+
+static SECOidData *
+HashNameToOID(const char *hashName)
+{
+ HASH_HashType htype;
+ SECOidData *hashOID;
+
+ for (htype = HASH_AlgNULL + 1; htype < HASH_AlgTOTAL; htype++) {
+ hashOID = HashTypeToOID(htype);
+ if (PORT_Strcasecmp(hashName, hashOID->desc) == 0)
+ break;
+ }
+
+ if (htype == HASH_AlgTOTAL)
+ return NULL;
+
+ return hashOID;
+}
+
+static void
+Usage(char *progName)
+{
+ HASH_HashType htype;
+
+ fprintf(stderr,
+ "Usage: %s -t type [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Specify the digest method (must be one of\n",
+ "-t type");
+ fprintf(stderr, "%-20s ", "");
+ for (htype = HASH_AlgNULL + 1; htype < HASH_AlgTOTAL; htype++) {
+ fprintf(stderr, HashTypeToOID(htype)->desc);
+ if (htype == (HASH_AlgTOTAL - 2))
+ fprintf(stderr, " or ");
+ else if (htype != (HASH_AlgTOTAL - 1))
+ fprintf(stderr, ", ");
+ }
+ fprintf(stderr, " (case ignored))\n");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+static int
+DigestFile(FILE *outFile, FILE *inFile, SECOidData *hashOID)
+{
+ int nb;
+ unsigned char ibuf[4096], digest[32];
+ PK11Context *hashcx;
+ unsigned int len;
+ SECStatus rv;
+
+ hashcx = PK11_CreateDigestContext(hashOID->offset);
+ if (hashcx == NULL) {
+ return -1;
+ }
+ PK11_DigestBegin(hashcx);
+
+
+ for (;;) {
+ if (feof(inFile)) break;
+ nb = fread(ibuf, 1, sizeof(ibuf), inFile);
+ if (nb != sizeof(ibuf)) {
+ if (nb == 0) {
+ if (ferror(inFile)) {
+ PORT_SetError(SEC_ERROR_IO);
+ PK11_DestroyContext(hashcx,PR_TRUE);
+ return -1;
+ }
+ /* eof */
+ break;
+ }
+ }
+ rv = PK11_DigestOp(hashcx, ibuf, nb);
+ if (rv != SECSuccess) {
+ PK11_DestroyContext(hashcx, PR_TRUE);
+ return -1;
+ }
+ }
+
+ rv = PK11_DigestFinal(hashcx, digest, &len, 32);
+ PK11_DestroyContext(hashcx, PR_TRUE);
+
+ if (rv != SECSuccess) return -1;
+
+ nb = fwrite(digest, 1, len, outFile);
+ if (nb != len) {
+ PORT_SetError(SEC_ERROR_IO);
+ return -1;
+ }
+
+ return 0;
+}
+
+#include "nss.h"
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ int opt;
+ FILE *inFile, *outFile;
+ char *hashName;
+ SECOidData *hashOID;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ inFile = NULL;
+ outFile = NULL;
+ hashName = NULL;
+
+ rv = NSS_Init("/tmp");
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: NSS_Init failed in directory %s\n",
+ progName, "/tmp");
+ return -1;
+ }
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "t:i:o:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'i':
+ inFile = fopen(optstate->value, "r");
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 't':
+ hashName = strdup(optstate->value);
+ break;
+ }
+ }
+
+ if (!hashName) Usage(progName);
+
+ if (!inFile) inFile = stdin;
+ if (!outFile) outFile = stdout;
+
+ hashOID = HashNameToOID(hashName);
+ if (hashOID == NULL) {
+ fprintf(stderr, "%s: invalid digest type\n", progName);
+ Usage(progName);
+ }
+
+ if (DigestFile(outFile, inFile, hashOID)) {
+ fprintf(stderr, "%s: problem digesting data (%s)\n",
+ progName, SECU_Strerror(PORT_GetError()));
+ return -1;
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/security/nss/cmd/digest/makefile.win b/security/nss/cmd/digest/makefile.win
new file mode 100644
index 000000000..e8ec27ca2
--- /dev/null
+++ b/security/nss/cmd/digest/makefile.win
@@ -0,0 +1,130 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+#cannot define PROGRAM in manifest compatibly with NT and UNIX
+PROGRAM = digest
+PROGRAM = ./$(OBJDIR)/$(PROGRAM).exe
+include <$(DEPTH)\config\config.mak>
+
+# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
+# rules.mak will append C_OBJS onto OBJS.
+# OBJS = $(CSRCS:.c=.obj)
+
+# include files are looked for in $LINCS and $INCS.
+# $LINCS is in manifest.mnw, computed from REQUIRES=
+INCS = $(INCS) \
+ -I$(DEPTH)/security/lib/cert \
+ -I../include \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+ $(NULL)
+
+
+WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
+
+# these files are the content of libdbm
+DBM_LIB = \
+ $(WINFE)/DB.obj \
+ $(WINFE)/HASH.obj \
+ $(WINFE)/H_BIGKEY.obj \
+ $(WINFE)/H_PAGE.obj \
+ $(WINFE)/H_LOG2.obj \
+ $(WINFE)/H_FUNC.obj \
+ $(WINFE)/HASH_BUF.obj \
+ $(NULL)
+
+MOZ_LIBS = \
+ $(WINFE)/ALLXPSTR.obj \
+ $(WINFE)/XP_ERROR.obj \
+ $(WINFE)/XPASSERT.obj \
+ $(WINFE)/XP_REG.obj \
+ $(WINFE)/XP_TRACE.obj \
+ $(DBM_LIB) \
+ $(WINFE)/XP_STR.obj \
+ $(WINFE)/MKTEMP.obj \
+ $(NULL)
+
+SEC_LIBS = \
+ $(DIST)/lib/cert$(MOZ_BITS).lib \
+ $(DIST)/lib/crypto$(MOZ_BITS).lib \
+ $(DIST)/lib/hash$(MOZ_BITS).lib \
+ $(DIST)/lib/key$(MOZ_BITS).lib \
+ $(DIST)/lib/pkcs7$(MOZ_BITS).lib \
+ $(DIST)/lib/secmod$(MOZ_BITS).lib \
+ $(DIST)/lib/secutl$(MOZ_BITS).lib \
+ $(DIST)/lib/ssl$(MOZ_BITS).lib \
+ $(NULL)
+
+LLFLAGS = $(LLFLAGS) \
+ ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
+ $(SEC_LIBS) \
+ $(MOZ_LIBS) \
+ $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
+ $(LIBNSPR) \
+ $(NULL)
+
+
+include <$(DEPTH)\config\rules.mak>
+
+INSTALL = $(MAKE_INSTALL)
+
+objs: $(OBJS)
+
+$(PROGRAM)::
+ $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
+
+programs: $(PROGRAM)
+
+install:: $(TARGETS)
+ $(INSTALL) $(TARGETS) $(DIST)/bin
+
+
+symbols:
+ @echo "CSRCS = $(CSRCS)"
+ @echo "INCS = $(INCS)"
+ @echo "OBJS = $(OBJS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "TARGETS = $(TARGETS)"
+ @echo "DIST = $(DIST)"
+ @echo "VERSION_NUMBER = $(VERSION_NUMBER)"
+ @echo "WINFE = $(WINFE)"
+ @echo "DBM_LIB = $(DBM_LIB)"
+ @echo "INSTALL = $(INSTALL)"
+
diff --git a/security/nss/cmd/digest/manifest.mn b/security/nss/cmd/digest/manifest.mn
new file mode 100644
index 000000000..c84152d01
--- /dev/null
+++ b/security/nss/cmd/digest/manifest.mn
@@ -0,0 +1,50 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = digest.c
+
+PROGRAM = digest
+
diff --git a/security/nss/cmd/ilock/Makefile b/security/nss/cmd/ilock/Makefile
new file mode 100644
index 000000000..4e39ffc3f
--- /dev/null
+++ b/security/nss/cmd/ilock/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/ilock/ilock.c b/security/nss/cmd/ilock/ilock.c
new file mode 100644
index 000000000..3e2390b8d
--- /dev/null
+++ b/security/nss/cmd/ilock/ilock.c
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+** File: ilock.c
+** Description: ilock.c is a unit test for nssilock. ilock.c
+** tests the basic operation of nssilock. It should not be
+** considered a complete test suite.
+**
+** To check that logging works, before running this test,
+** define the following environment variables:
+**
+**
+**
+**
+**
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <plgetopt.h>
+#include <nspr.h>
+#include <nssilock.h>
+
+
+/*
+** Test harness infrastructure
+*/
+PRLogModuleInfo *lm;
+PRLogModuleLevel msgLevel = PR_LOG_NONE;
+PRIntn debug = 0;
+PRUint32 failed_already = 0;
+/* end Test harness infrastructure */
+
+PRIntn optIterations = 1; /* default iterations */
+
+PRIntn main(PRIntn argc, char *argv[])
+{
+ PRIntn i;
+ {
+ /*
+ ** Get command line options
+ */
+ PLOptStatus os;
+ PLOptState *opt = PL_CreateOptState(argc, argv, "hdvi:");
+
+ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
+ {
+ if (PL_OPT_BAD == os) continue;
+ switch (opt->option)
+ {
+ case 'd': /* debug */
+ debug = 1;
+ msgLevel = PR_LOG_ERROR;
+ break;
+ case 'v': /* verbose mode */
+ msgLevel = PR_LOG_DEBUG;
+ break;
+ case 'i': /* number of iterations */
+ optIterations = atol( opt->value );
+ if ( 0 == optIterations ) optIterations = 1; /* coerce default on zero */
+ break;
+ default:
+ break;
+ }
+ }
+ PL_DestroyOptState(opt);
+ }
+
+ for ( i = 0 ; i < optIterations ; i++ ) {
+ /* First, test Lock */
+ {
+ PZLock *pl;
+ PZMonitor *pm;
+ PZCondVar *cv;
+ PRStatus rc;
+
+ pl = PZ_NewLock( nssILockOther );
+ if ( NULL == pl ) {
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+ PZ_Lock( pl );
+
+ rc = PZ_Unlock( pl );
+ if ( PR_FAILURE == rc ) {
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+ PZ_DestroyLock( pl );
+
+ /* now, test CVar */
+ /* re-create the lock we just destroyed */
+ pl = PZ_NewLock( nssILockOther );
+ if ( NULL == pl ) {
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+
+ cv = PZ_NewCondVar( pl );
+ if ( NULL == cv ) {
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+
+ PZ_Lock( pl );
+ rc = PZ_NotifyCondVar( cv );
+ if ( PR_FAILURE == rc ) {
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+
+ rc = PZ_NotifyAllCondVar( cv );
+ if ( PR_FAILURE == rc ) {
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+
+ rc = PZ_WaitCondVar( cv, PR_SecondsToInterval(1));
+ if ( PR_FAILURE == rc ) {
+ if ( PR_UNKNOWN_ERROR != PR_GetError()) {
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+ }
+ PZ_Unlock( pl );
+ PZ_DestroyCondVar( cv );
+
+ /* Now, test Monitor */
+ pm = PZ_NewMonitor( nssILockOther );
+ if ( NULL == pm ) {
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+
+ PZ_EnterMonitor( pm );
+
+ rc = PZ_Notify( pm );
+ if ( PR_FAILURE == rc ) {
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+ rc = PZ_NotifyAll( pm );
+ if ( PR_FAILURE == rc ) {
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+ rc = PZ_Wait( pm, PR_INTERVAL_NO_WAIT );
+ if ( PR_FAILURE == rc ) {
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+ rc = PZ_ExitMonitor( pm );
+ if ( PR_FAILURE == rc ) {
+ failed_already = PR_TRUE;
+ goto Finished;
+ }
+ PZ_DestroyMonitor( pm );
+ }
+ } /* --- end for() --- */
+
+
+Finished:
+ if (debug) printf("%s\n", (failed_already)? "FAIL" : "PASS");
+ return( (failed_already == PR_TRUE )? 1 : 0 );
+} /* main() */
+/* end ilock.c */
+
diff --git a/security/nss/cmd/ilock/manifest.mn b/security/nss/cmd/ilock/manifest.mn
new file mode 100644
index 000000000..4a8f7988c
--- /dev/null
+++ b/security/nss/cmd/ilock/manifest.mn
@@ -0,0 +1,44 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+CORE_DEPTH = ../../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = ilock.c
+
+PROGRAM = ilock
+# PROGRAM = ./$(OBJDIR)/ilock.exe
+
diff --git a/security/nss/cmd/include/secnew.h b/security/nss/cmd/include/secnew.h
new file mode 100644
index 000000000..eb4c30acd
--- /dev/null
+++ b/security/nss/cmd/include/secnew.h
@@ -0,0 +1,163 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#ifndef __secnew_h_
+#define __secnew_h_
+
+#include <stdio.h>
+
+typedef struct BERTemplateStr BERTemplate;
+typedef struct BERParseStr BERParse;
+typedef struct SECArbStr SECArb;
+
+/*
+ * An array of these structures define an encoding for an object using
+ * DER. The array is terminated with an entry where kind == 0.
+ */
+struct BERTemplateStr {
+ /* Kind of item to decode/encode */
+ unsigned long kind;
+
+ /*
+ * Offset from base of structure to SECItem that will hold
+ * decoded/encoded value.
+ */
+ unsigned short offset;
+
+ /*
+ * Used with DER_SET or DER_SEQUENCE. If not zero then points to a
+ * sub-template. The sub-template is filled in and completed before
+ * continuing on.
+ */
+ BERTemplate *sub;
+
+ /*
+ * Argument value, dependent on kind. Size of structure to allocate
+ * when kind==DER_POINTER For Context-Specific Implicit types its the
+ * underlying type to use.
+ */
+ unsigned long arg;
+};
+
+/*
+ * an arbitrary object
+ */
+struct SECArbStr {
+ unsigned long tag; /* NOTE: does not support high tag form */
+ unsigned long length; /* as reported in stream */
+ union {
+ SECItem item;
+ struct {
+ int numSubs;
+ SECArb **subs;
+ } cons;
+ } body;
+};
+
+/*
+ * Decode a piece of der encoded data.
+ * "dest" points to a structure that will be filled in with the
+ * decoding results.
+ * "t" is a template structure which defines the shape of the
+ * expected data.
+ * "src" is the ber encoded data.
+ */
+
+extern SECStatus BER_Decode(PRArenaPool * arena, void *dest, BERTemplate *t,
+ SECArb *arb);
+
+
+/*
+ * Encode a data structure into DER.
+ * "dest" will be filled in (and memory allocated) to hold the der
+ * encoded structure in "src"
+ * "t" is a template structure which defines the shape of the
+ * stored data
+ * "src" is a pointer to the structure that will be encoded
+ */
+
+extern SECStatus BER_Encode(PRArenaPool *arena, SECItem *dest, BERTemplate *t,
+ void *src);
+
+/*
+ * Client provided function that will get called with all the bytes
+ * passing through the parser
+ */
+typedef void (*BERFilterProc)(void *instance, unsigned char *buf, int length);
+
+/*
+ * Client provided function that can will be called after the tag and
+ * length information has been collected. It can be set up to be called
+ * either before or after the data has been colleced.
+ */
+typedef void (*BERNotifyProc)(
+ void *instance, SECArb *arb, int depth, PRBool before);
+
+extern BERParse *BER_ParseInit(PRArenaPool *arena, PRBool forceDER);
+extern SECArb *BER_ParseFini(BERParse *h);
+extern SECStatus BER_ParseSome(BERParse *h, unsigned char *buf, int len);
+
+extern void BER_SetFilter(BERParse *h, BERFilterProc proc, void *instance);
+extern void BER_SetLeafStorage(BERParse *h, PRBool keep);
+extern void BER_SetNotifyProc(BERParse *h, BERNotifyProc proc, void *instance,
+ PRBool beforeData);
+
+/*
+ * A BERUnparseProc is used as a callback to put the encoded SECArb tree
+ * tree to some stream. It returns PR_TRUE if the unparsing is to be
+ * aborted.
+ */
+typedef SECStatus (*BERUnparseProc)(
+ void *instance, unsigned char *data, int length, SECArb* arb);
+
+/*
+ * BER_Unparse walks the SECArb tree calling the BERUnparseProc with
+ * various pieces. It returns SECFailure if there was an error during that
+ * tree walk.
+ */
+extern SECStatus BER_Unparse(SECArb *arb, BERUnparseProc proc, void *instance);
+
+/*
+ * BER_ResolveLengths does a recursive walk through the tree generating
+ * non-zero entries for the length field of each node. It will fail if it
+ * discoveres a non-constructed node with a unknown length data field.
+ * Leaves are supposed to be of known length.
+ */
+extern SECStatus BER_ResolveLengths(SECArb *arb);
+
+/*
+ * BER_PRettyPrintArb will write an ASCII version of the tree to the FILE
+ * out.
+ */
+extern SECStatus BER_PrettyPrintArb(FILE *out, SECArb* a);
+
+#endif /* __secnew_h_ */
diff --git a/security/nss/cmd/keyutil/Makefile b/security/nss/cmd/keyutil/Makefile
new file mode 100644
index 000000000..a2ed814be
--- /dev/null
+++ b/security/nss/cmd/keyutil/Makefile
@@ -0,0 +1,73 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/keyutil/keyutil.c b/security/nss/cmd/keyutil/keyutil.c
new file mode 100644
index 000000000..65e6ad8b0
--- /dev/null
+++ b/security/nss/cmd/keyutil/keyutil.c
@@ -0,0 +1,340 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#include <sys/time.h>
+#include <termios.h>
+#endif
+
+#include "secopt.h"
+
+#if defined(XP_WIN)
+#include <time.h>
+#include <conio.h>
+#endif
+
+#if defined(__sun) && !defined(SVR4)
+extern int fclose(FILE*);
+extern int fprintf(FILE *, char *, ...);
+extern int getopt(int, char**, char*);
+extern int isatty(int);
+extern char *optarg;
+extern char *sys_errlist[];
+#define strerror(errno) sys_errlist[errno]
+#endif
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+static char *progName;
+
+static SECStatus
+ListKeys(SECKEYKeyDBHandle *handle, FILE *out)
+{
+ int rt;
+
+ rt = SECU_PrintKeyNames(handle, out);
+ if (rt) {
+ SECU_PrintError(progName, "unable to list nicknames");
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+DumpPublicKey(SECKEYKeyDBHandle *handle, char *nickname, FILE *out)
+{
+ SECKEYLowPrivateKey *privKey;
+ SECKEYLowPublicKey *publicKey;
+
+ /* check if key actually exists */
+ if (SECU_CheckKeyNameExists(handle, nickname) == PR_FALSE) {
+ SECU_PrintError(progName, "the key \"%s\" does not exist", nickname);
+ return SECFailure;
+ }
+
+ /* Read in key */
+ privKey = SECU_GetPrivateKey(handle, nickname);
+ if (!privKey) {
+ return SECFailure;
+ }
+
+ publicKey = SECKEY_LowConvertToPublicKey(privKey);
+
+ /* Output public key (in the clear) */
+ switch(publicKey->keyType) {
+ case rsaKey:
+ fprintf(out, "RSA Public-Key:\n");
+ SECU_PrintInteger(out, &publicKey->u.rsa.modulus, "modulus", 1);
+ SECU_PrintInteger(out, &publicKey->u.rsa.publicExponent,
+ "publicExponent", 1);
+ break;
+ case dsaKey:
+ fprintf(out, "DSA Public-Key:\n");
+ SECU_PrintInteger(out, &publicKey->u.dsa.params.prime, "prime", 1);
+ SECU_PrintInteger(out, &publicKey->u.dsa.params.subPrime,
+ "subPrime", 1);
+ SECU_PrintInteger(out, &publicKey->u.dsa.params.base, "base", 1);
+ SECU_PrintInteger(out, &publicKey->u.dsa.publicValue, "publicValue", 1);
+ break;
+ default:
+ fprintf(out, "unknown key type\n");
+ break;
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+DumpPrivateKey(SECKEYKeyDBHandle *handle, char *nickname, FILE *out)
+{
+ SECKEYLowPrivateKey *key;
+
+ /* check if key actually exists */
+ if (SECU_CheckKeyNameExists(handle, nickname) == PR_FALSE) {
+ SECU_PrintError(progName, "the key \"%s\" does not exist", nickname);
+ return SECFailure;
+ }
+
+ /* Read in key */
+ key = SECU_GetPrivateKey(handle, nickname);
+ if (!key) {
+ SECU_PrintError(progName, "error retrieving key");
+ return SECFailure;
+ }
+
+ switch(key->keyType) {
+ case rsaKey:
+ fprintf(out, "RSA Private-Key:\n");
+ SECU_PrintInteger(out, &key->u.rsa.modulus, "modulus", 1);
+ SECU_PrintInteger(out, &key->u.rsa.publicExponent, "publicExponent", 1);
+ SECU_PrintInteger(out, &key->u.rsa.privateExponent,
+ "privateExponent", 1);
+ SECU_PrintInteger(out, &key->u.rsa.prime1, "prime1", 1);
+ SECU_PrintInteger(out, &key->u.rsa.prime2, "prime2", 1);
+ SECU_PrintInteger(out, &key->u.rsa.exponent1, "exponent1", 1);
+ SECU_PrintInteger(out, &key->u.rsa.exponent2, "exponent2", 1);
+ SECU_PrintInteger(out, &key->u.rsa.coefficient, "coefficient", 1);
+ break;
+ case dsaKey:
+ fprintf(out, "DSA Private-Key:\n");
+ SECU_PrintInteger(out, &key->u.dsa.params.prime, "prime", 1);
+ SECU_PrintInteger(out, &key->u.dsa.params.subPrime, "subPrime", 1);
+ SECU_PrintInteger(out, &key->u.dsa.params.base, "base", 1);
+ SECU_PrintInteger(out, &key->u.dsa.publicValue, "publicValue", 1);
+ SECU_PrintInteger(out, &key->u.dsa.privateValue, "privateValue", 1);
+ break;
+ default:
+ fprintf(out, "unknown key type\n");
+ break;
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+ChangePassword(SECKEYKeyDBHandle *handle)
+{
+ SECStatus rv;
+
+ /* Write out database with a new password */
+ rv = SECU_ChangeKeyDBPassword(handle, NULL);
+ if (rv) {
+ SECU_PrintError(progName, "unable to change key password");
+ }
+ return rv;
+}
+
+static SECStatus
+DeletePrivateKey (SECKEYKeyDBHandle *keyHandle, char *nickName)
+{
+ SECStatus rv;
+
+ rv = SECU_DeleteKeyByName (keyHandle, nickName);
+ if (rv != SECSuccess)
+ fprintf(stderr, "%s: problem deleting private key (%s)\n",
+ progName, SECU_Strerror(PR_GetError()));
+ return (rv);
+
+}
+
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -p name [-d keydir]\n", progName);
+ fprintf(stderr,
+ " %s -P name [-d keydir]\n", progName);
+ fprintf(stderr,
+ " %s -D name [-d keydir]\n", progName);
+ fprintf(stderr,
+ " %s -l [-d keydir]\n", progName);
+ fprintf(stderr,
+ " %s -c [-d keydir]\n", progName);
+
+ fprintf(stderr, "%-20s Pretty print public key info for named key\n",
+ "-p nickname");
+ fprintf(stderr, "%-20s Pretty print private key info for named key\n",
+ "-P nickname");
+ fprintf(stderr, "%-20s Delete named private key from the key database\n",
+ "-D nickname");
+ fprintf(stderr, "%-20s List the nicknames for the keys in a database\n",
+ "-l");
+ fprintf(stderr, "%-20s Change the key database password\n",
+ "-c");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+
+ exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+ int o, changePassword, deleteKey, dumpPublicKey, dumpPrivateKey, list;
+ char *nickname;
+ SECStatus rv;
+ SECKEYKeyDBHandle *keyHandle;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ /* Parse command line arguments */
+ changePassword = deleteKey = dumpPublicKey = dumpPrivateKey = list = 0;
+ nickname = NULL;
+
+ while ((o = getopt(argc, argv, "ADP:cd:glp:")) != -1) {
+ switch (o) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'A':
+ fprintf(stderr, "%s: Can no longer add a key.", progName);
+ fprintf(stderr, " Use pkcs12 to import a key.\n\n");
+ Usage(progName);
+ break;
+
+ case 'D':
+ deleteKey = 1;
+ nickname = optarg;
+ break;
+
+ case 'P':
+ dumpPrivateKey = 1;
+ nickname = optarg;
+ break;
+
+ case 'c':
+ changePassword = 1;
+ break;
+
+ case 'd':
+ SECU_ConfigDirectory(optarg);
+ break;
+
+ case 'g':
+ fprintf(stderr, "%s: Can no longer generate a key.", progName);
+ fprintf(stderr, " Use certutil to generate a cert request.\n\n");
+ Usage(progName);
+ break;
+
+ case 'l':
+ list = 1;
+ break;
+
+ case 'p':
+ dumpPublicKey = 1;
+ nickname = optarg;
+ break;
+ }
+ }
+
+ if (dumpPublicKey+changePassword+dumpPrivateKey+list+deleteKey != 1)
+ Usage(progName);
+
+ if ((list || changePassword) && nickname)
+ Usage(progName);
+
+ if ((dumpPublicKey || dumpPrivateKey || deleteKey) && !nickname)
+ Usage(progName);
+
+
+ /* Call the libsec initialization routines */
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ SEC_Init();
+
+ /*
+ * XXX Note that the following opens the key database writable.
+ * If dumpPublicKey or dumpPrivateKey or list, though, we only want
+ * to open it read-only. There needs to be a better interface
+ * to the initialization routines so that we can specify which way
+ * to open it.
+ */
+ rv = SECU_PKCS11Init();
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "SECU_PKCS11Init failed");
+ return -1;
+ }
+
+ keyHandle = SECKEY_GetDefaultKeyDB();
+ if (keyHandle == NULL) {
+ SECU_PrintError(progName, "could not open key database");
+ return -1;
+ }
+
+ if (dumpPublicKey) {
+ rv = DumpPublicKey(keyHandle, nickname, stdout);
+ } else
+ if (changePassword) {
+ rv = ChangePassword(keyHandle);
+ } else
+ if (dumpPrivateKey) {
+ rv = DumpPrivateKey(keyHandle, nickname, stdout);
+ } else
+ if (list) {
+ rv = ListKeys(keyHandle, stdout);
+ } else
+ if (deleteKey) {
+ rv = DeletePrivateKey(keyHandle, nickname);
+ }
+
+
+ return rv ? -1 : 0;
+}
diff --git a/security/nss/cmd/keyutil/manifest.mn b/security/nss/cmd/keyutil/manifest.mn
new file mode 100644
index 000000000..e20a3d330
--- /dev/null
+++ b/security/nss/cmd/keyutil/manifest.mn
@@ -0,0 +1,50 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ keyutil.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+
+PROGRAM = keyutil
diff --git a/security/nss/cmd/lib/Makefile b/security/nss/cmd/lib/Makefile
new file mode 100644
index 000000000..217e25668
--- /dev/null
+++ b/security/nss/cmd/lib/Makefile
@@ -0,0 +1,76 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include config.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+$(OBJDIR)/secerror$(OBJ_SUFFIX): NSPRerrs.h SECerrs.h SSLerrs.h
+
diff --git a/security/nss/cmd/lib/NSPRerrs.h b/security/nss/cmd/lib/NSPRerrs.h
new file mode 100644
index 000000000..5e2cd793e
--- /dev/null
+++ b/security/nss/cmd/lib/NSPRerrs.h
@@ -0,0 +1,150 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+/* General NSPR 2.0 errors */
+/* Caller must #include "prerror.h" */
+
+ER2( PR_OUT_OF_MEMORY_ERROR, "Memory allocation attempt failed." )
+ER2( PR_BAD_DESCRIPTOR_ERROR, "Invalid file descriptor." )
+ER2( PR_WOULD_BLOCK_ERROR, "The operation would have blocked." )
+ER2( PR_ACCESS_FAULT_ERROR, "Invalid memory address argument." )
+ER2( PR_INVALID_METHOD_ERROR, "Invalid function for file type." )
+ER2( PR_ILLEGAL_ACCESS_ERROR, "Invalid memory address argument." )
+ER2( PR_UNKNOWN_ERROR, "Some unknown error has occurred." )
+ER2( PR_PENDING_INTERRUPT_ERROR,"Operation interrupted by another thread." )
+ER2( PR_NOT_IMPLEMENTED_ERROR, "function not implemented." )
+ER2( PR_IO_ERROR, "I/O function error." )
+ER2( PR_IO_TIMEOUT_ERROR, "I/O operation timed out." )
+ER2( PR_IO_PENDING_ERROR, "I/O operation on busy file descriptor." )
+ER2( PR_DIRECTORY_OPEN_ERROR, "The directory could not be opened." )
+ER2( PR_INVALID_ARGUMENT_ERROR, "Invalid function argument." )
+ER2( PR_ADDRESS_NOT_AVAILABLE_ERROR, "Network address not available (in use?)." )
+ER2( PR_ADDRESS_NOT_SUPPORTED_ERROR, "Network address type not supported." )
+ER2( PR_IS_CONNECTED_ERROR, "Already connected." )
+ER2( PR_BAD_ADDRESS_ERROR, "Network address is invalid." )
+ER2( PR_ADDRESS_IN_USE_ERROR, "Local Network address is in use." )
+ER2( PR_CONNECT_REFUSED_ERROR, "Connection refused by peer." )
+ER2( PR_NETWORK_UNREACHABLE_ERROR, "Network address is presently unreachable." )
+ER2( PR_CONNECT_TIMEOUT_ERROR, "Connection attempt timed out." )
+ER2( PR_NOT_CONNECTED_ERROR, "Network file descriptor is not connected." )
+ER2( PR_LOAD_LIBRARY_ERROR, "Failure to load dynamic library." )
+ER2( PR_UNLOAD_LIBRARY_ERROR, "Failure to unload dynamic library." )
+ER2( PR_FIND_SYMBOL_ERROR,
+"Symbol not found in any of the loaded dynamic libraries." )
+ER2( PR_INSUFFICIENT_RESOURCES_ERROR, "Insufficient system resources." )
+ER2( PR_DIRECTORY_LOOKUP_ERROR,
+"A directory lookup on a network address has failed." )
+ER2( PR_TPD_RANGE_ERROR,
+"Attempt to access a TPD key that is out of range." )
+ER2( PR_PROC_DESC_TABLE_FULL_ERROR, "Process open FD table is full." )
+ER2( PR_SYS_DESC_TABLE_FULL_ERROR, "System open FD table is full." )
+ER2( PR_NOT_SOCKET_ERROR,
+"Network operation attempted on non-network file descriptor." )
+ER2( PR_NOT_TCP_SOCKET_ERROR,
+"TCP-specific function attempted on a non-TCP file descriptor." )
+ER2( PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "TCP file descriptor is already bound." )
+ER2( PR_NO_ACCESS_RIGHTS_ERROR, "Access Denied." )
+ER2( PR_OPERATION_NOT_SUPPORTED_ERROR,
+"The requested operation is not supported by the platform." )
+ER2( PR_PROTOCOL_NOT_SUPPORTED_ERROR,
+"The host operating system does not support the protocol requested." )
+ER2( PR_REMOTE_FILE_ERROR, "Access to the remote file has been severed." )
+ER2( PR_BUFFER_OVERFLOW_ERROR,
+"The value requested is too large to be stored in the data buffer provided." )
+ER2( PR_CONNECT_RESET_ERROR, "TCP connection reset by peer." )
+ER2( PR_RANGE_ERROR, "Unused." )
+ER2( PR_DEADLOCK_ERROR, "The operation would have deadlocked." )
+ER2( PR_FILE_IS_LOCKED_ERROR, "The file is already locked." )
+ER2( PR_FILE_TOO_BIG_ERROR,
+"Write would result in file larger than the system allows." )
+ER2( PR_NO_DEVICE_SPACE_ERROR, "The device for storing the file is full." )
+ER2( PR_PIPE_ERROR, "Unused." )
+ER2( PR_NO_SEEK_DEVICE_ERROR, "Unused." )
+ER2( PR_IS_DIRECTORY_ERROR,
+"Cannot perform a normal file operation on a directory." )
+ER2( PR_LOOP_ERROR, "Symbolic link loop." )
+ER2( PR_NAME_TOO_LONG_ERROR, "File name is too long." )
+ER2( PR_FILE_NOT_FOUND_ERROR, "File not found." )
+ER2( PR_NOT_DIRECTORY_ERROR,
+"Cannot perform directory operation on a normal file." )
+ER2( PR_READ_ONLY_FILESYSTEM_ERROR,
+"Cannot write to a read-only file system." )
+ER2( PR_DIRECTORY_NOT_EMPTY_ERROR,
+"Cannot delete a directory that is not empty." )
+ER2( PR_FILESYSTEM_MOUNTED_ERROR,
+"Cannot delete or rename a file object while the file system is busy." )
+ER2( PR_NOT_SAME_DEVICE_ERROR,
+"Cannot rename a file to a file system on another device." )
+ER2( PR_DIRECTORY_CORRUPTED_ERROR,
+"The directory object in the file system is corrupted." )
+ER2( PR_FILE_EXISTS_ERROR,
+"Cannot create or rename a filename that already exists." )
+ER2( PR_MAX_DIRECTORY_ENTRIES_ERROR,
+"Directory is full. No additional filenames may be added." )
+ER2( PR_INVALID_DEVICE_STATE_ERROR,
+"The required device was in an invalid state." )
+ER2( PR_DEVICE_IS_LOCKED_ERROR, "The device is locked." )
+ER2( PR_NO_MORE_FILES_ERROR, "No more entries in the directory." )
+ER2( PR_END_OF_FILE_ERROR, "Encountered end of file." )
+ER2( PR_FILE_SEEK_ERROR, "Seek error." )
+ER2( PR_FILE_IS_BUSY_ERROR, "The file is busy." )
+ER2( PR_IN_PROGRESS_ERROR,
+"Operation is still in progress (probably a non-blocking connect)." )
+ER2( PR_ALREADY_INITIATED_ERROR,
+"Operation has already been initiated (probably a non-blocking connect)." )
+
+#ifdef PR_GROUP_EMPTY_ERROR
+ER2( PR_GROUP_EMPTY_ERROR, "The wait group is empty." )
+#endif
+
+#ifdef PR_INVALID_STATE_ERROR
+ER2( PR_INVALID_STATE_ERROR, "Object state improper for request." )
+#endif
+
+#ifdef PR_NETWORK_DOWN_ERROR
+ER2( PR_NETWORK_DOWN_ERROR, "Network is down." )
+#endif
+
+#ifdef PR_SOCKET_SHUTDOWN_ERROR
+ER2( PR_SOCKET_SHUTDOWN_ERROR, "The socket was previously shut down." )
+#endif
+
+#ifdef PR_CONNECT_ABORTED_ERROR
+ER2( PR_CONNECT_ABORTED_ERROR, "TCP Connection aborted." )
+#endif
+
+#ifdef PR_HOST_UNREACHABLE_ERROR
+ER2( PR_HOST_UNREACHABLE_ERROR, "Host is unreachable." )
+#endif
+
+/* always last */
+ER2( PR_MAX_ERROR, "Placeholder for the end of the list" )
diff --git a/security/nss/cmd/lib/SECerrs.h b/security/nss/cmd/lib/SECerrs.h
new file mode 100644
index 000000000..e566e3983
--- /dev/null
+++ b/security/nss/cmd/lib/SECerrs.h
@@ -0,0 +1,476 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/* General security error codes */
+/* Caller must #include "secerr.h" */
+
+ER3(SEC_ERROR_IO, SEC_ERROR_BASE + 0,
+"An I/O error occurred during security authorization.")
+
+ER3(SEC_ERROR_LIBRARY_FAILURE, SEC_ERROR_BASE + 1,
+"security library failure.")
+
+ER3(SEC_ERROR_BAD_DATA, SEC_ERROR_BASE + 2,
+"security library: received bad data.")
+
+ER3(SEC_ERROR_OUTPUT_LEN, SEC_ERROR_BASE + 3,
+"security library: output length error.")
+
+ER3(SEC_ERROR_INPUT_LEN, SEC_ERROR_BASE + 4,
+"security library has experienced an input length error.")
+
+ER3(SEC_ERROR_INVALID_ARGS, SEC_ERROR_BASE + 5,
+"security library: invalid arguments.")
+
+ER3(SEC_ERROR_INVALID_ALGORITHM, SEC_ERROR_BASE + 6,
+"security library: invalid algorithm.")
+
+ER3(SEC_ERROR_INVALID_AVA, SEC_ERROR_BASE + 7,
+"security library: invalid AVA.")
+
+ER3(SEC_ERROR_INVALID_TIME, SEC_ERROR_BASE + 8,
+"Improperly formatted time string.")
+
+ER3(SEC_ERROR_BAD_DER, SEC_ERROR_BASE + 9,
+"security library: improperly formatted DER-encoded message.")
+
+ER3(SEC_ERROR_BAD_SIGNATURE, SEC_ERROR_BASE + 10,
+"Peer's certificate has an invalid signature.")
+
+ER3(SEC_ERROR_EXPIRED_CERTIFICATE, SEC_ERROR_BASE + 11,
+"Peer's Certificate has expired.")
+
+ER3(SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_BASE + 12,
+"Peer's Certificate has been revoked.")
+
+ER3(SEC_ERROR_UNKNOWN_ISSUER, SEC_ERROR_BASE + 13,
+"Peer's Certificate issuer is not recognized.")
+
+ER3(SEC_ERROR_BAD_KEY, SEC_ERROR_BASE + 14,
+"Peer's public key is invalid.")
+
+ER3(SEC_ERROR_BAD_PASSWORD, SEC_ERROR_BASE + 15,
+"The security password entered is incorrect.")
+
+ER3(SEC_ERROR_RETRY_PASSWORD, SEC_ERROR_BASE + 16,
+"New password entered incorrectly. Please try again.")
+
+ER3(SEC_ERROR_NO_NODELOCK, SEC_ERROR_BASE + 17,
+"security library: no nodelock.")
+
+ER3(SEC_ERROR_BAD_DATABASE, SEC_ERROR_BASE + 18,
+"security library: bad database.")
+
+ER3(SEC_ERROR_NO_MEMORY, SEC_ERROR_BASE + 19,
+"security library: memory allocation failure.")
+
+ER3(SEC_ERROR_UNTRUSTED_ISSUER, SEC_ERROR_BASE + 20,
+"Peer's certificate issuer has been marked as not trusted by the user.")
+
+ER3(SEC_ERROR_UNTRUSTED_CERT, SEC_ERROR_BASE + 21,
+"Peer's certificate has been marked as not trusted by the user.")
+
+ER3(SEC_ERROR_DUPLICATE_CERT, (SEC_ERROR_BASE + 22),
+"Certificate already exists in your database.")
+
+ER3(SEC_ERROR_DUPLICATE_CERT_NAME, (SEC_ERROR_BASE + 23),
+"Downloaded certificate's name duplicates one already in your database.")
+
+ER3(SEC_ERROR_ADDING_CERT, (SEC_ERROR_BASE + 24),
+"Error adding certificate to database.")
+
+ER3(SEC_ERROR_FILING_KEY, (SEC_ERROR_BASE + 25),
+"Error refiling the key for this certificate.")
+
+ER3(SEC_ERROR_NO_KEY, (SEC_ERROR_BASE + 26),
+"The private key for this certificate cannot be found in key database")
+
+ER3(SEC_ERROR_CERT_VALID, (SEC_ERROR_BASE + 27),
+"This certificate is valid.")
+
+ER3(SEC_ERROR_CERT_NOT_VALID, (SEC_ERROR_BASE + 28),
+"This certificate is not valid.")
+
+ER3(SEC_ERROR_CERT_NO_RESPONSE, (SEC_ERROR_BASE + 29),
+"Cert Library: No Response")
+
+ER3(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, (SEC_ERROR_BASE + 30),
+"The certificate issuer's certificate has expired. Check your system date and time.")
+
+ER3(SEC_ERROR_CRL_EXPIRED, (SEC_ERROR_BASE + 31),
+"The CRL for the certificate's issuer has expired. Update it or check your system data and time.")
+
+ER3(SEC_ERROR_CRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 32),
+"The CRL for the certificate's issuer has an invalid signature.")
+
+ER3(SEC_ERROR_CRL_INVALID, (SEC_ERROR_BASE + 33),
+"New CRL has an invalid format.")
+
+ER3(SEC_ERROR_EXTENSION_VALUE_INVALID, (SEC_ERROR_BASE + 34),
+"Certificate extension value is invalid.")
+
+ER3(SEC_ERROR_EXTENSION_NOT_FOUND, (SEC_ERROR_BASE + 35),
+"Certificate extension not found.")
+
+ER3(SEC_ERROR_CA_CERT_INVALID, (SEC_ERROR_BASE + 36),
+"Issuer certificate is invalid.")
+
+ER3(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, (SEC_ERROR_BASE + 37),
+"Certificate path length constraint is invalid.")
+
+ER3(SEC_ERROR_CERT_USAGES_INVALID, (SEC_ERROR_BASE + 38),
+"Certificate usages field is invalid.")
+
+ER3(SEC_INTERNAL_ONLY, (SEC_ERROR_BASE + 39),
+"**Internal ONLY module**")
+
+ER3(SEC_ERROR_INVALID_KEY, (SEC_ERROR_BASE + 40),
+"The key does not support the requested operation.")
+
+ER3(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 41),
+"Certificate contains unknown critical extension.")
+
+ER3(SEC_ERROR_OLD_CRL, (SEC_ERROR_BASE + 42),
+"New CRL is not later than the current one.")
+
+ER3(SEC_ERROR_NO_EMAIL_CERT, (SEC_ERROR_BASE + 43),
+"Not encrypted or signed: you do not yet have an email certificate.")
+
+ER3(SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, (SEC_ERROR_BASE + 44),
+"Not encrypted: you do not have certificates for each of the recipients.")
+
+ER3(SEC_ERROR_NOT_A_RECIPIENT, (SEC_ERROR_BASE + 45),
+"Cannot decrypt: you are not a recipient, or matching certificate and \
+private key not found.")
+
+ER3(SEC_ERROR_PKCS7_KEYALG_MISMATCH, (SEC_ERROR_BASE + 46),
+"Cannot decrypt: key encryption algorithm does not match your certificate.")
+
+ER3(SEC_ERROR_PKCS7_BAD_SIGNATURE, (SEC_ERROR_BASE + 47),
+"Signature verification failed: no signer found, too many signers found, \
+or improper or corrupted data.")
+
+ER3(SEC_ERROR_UNSUPPORTED_KEYALG, (SEC_ERROR_BASE + 48),
+"Unsupported or unknown key algorithm.")
+
+ER3(SEC_ERROR_DECRYPTION_DISALLOWED, (SEC_ERROR_BASE + 49),
+"Cannot decrypt: encrypted using a disallowed algorithm or key size.")
+
+
+/* Fortezza Alerts */
+ER3(XP_SEC_FORTEZZA_BAD_CARD, (SEC_ERROR_BASE + 50),
+"Fortezza card has not been properly initialized. \
+Please remove it and return it to your issuer.")
+
+ER3(XP_SEC_FORTEZZA_NO_CARD, (SEC_ERROR_BASE + 51),
+"No Fortezza cards Found")
+
+ER3(XP_SEC_FORTEZZA_NONE_SELECTED, (SEC_ERROR_BASE + 52),
+"No Fortezza card selected")
+
+ER3(XP_SEC_FORTEZZA_MORE_INFO, (SEC_ERROR_BASE + 53),
+"Please select a personality to get more info on")
+
+ER3(XP_SEC_FORTEZZA_PERSON_NOT_FOUND, (SEC_ERROR_BASE + 54),
+"Personality not found")
+
+ER3(XP_SEC_FORTEZZA_NO_MORE_INFO, (SEC_ERROR_BASE + 55),
+"No more information on that Personality")
+
+ER3(XP_SEC_FORTEZZA_BAD_PIN, (SEC_ERROR_BASE + 56),
+"Invalid Pin")
+
+ER3(XP_SEC_FORTEZZA_PERSON_ERROR, (SEC_ERROR_BASE + 57),
+"Couldn't initialize Fortezza personalities.")
+/* end fortezza alerts. */
+
+ER3(SEC_ERROR_NO_KRL, (SEC_ERROR_BASE + 58),
+"No KRL for this site's certificate has been found.")
+
+ER3(SEC_ERROR_KRL_EXPIRED, (SEC_ERROR_BASE + 59),
+"The KRL for this site's certificate has expired.")
+
+ER3(SEC_ERROR_KRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 60),
+"The KRL for this site's certificate has an invalid signature.")
+
+ER3(SEC_ERROR_REVOKED_KEY, (SEC_ERROR_BASE + 61),
+"The key for this site's certificate has been revoked.")
+
+ER3(SEC_ERROR_KRL_INVALID, (SEC_ERROR_BASE + 62),
+"New KRL has an invalid format.")
+
+ER3(SEC_ERROR_NEED_RANDOM, (SEC_ERROR_BASE + 63),
+"security library: need random data.")
+
+ER3(SEC_ERROR_NO_MODULE, (SEC_ERROR_BASE + 64),
+"security library: no security module can perform the requested operation.")
+
+ER3(SEC_ERROR_NO_TOKEN, (SEC_ERROR_BASE + 65),
+"The security card or token does not exist, needs to be initialized, or has been removed.")
+
+ER3(SEC_ERROR_READ_ONLY, (SEC_ERROR_BASE + 66),
+"security library: read-only database.")
+
+ER3(SEC_ERROR_NO_SLOT_SELECTED, (SEC_ERROR_BASE + 67),
+"No slot or token was selected.")
+
+ER3(SEC_ERROR_CERT_NICKNAME_COLLISION, (SEC_ERROR_BASE + 68),
+"A certificate with the same nickname already exists.")
+
+ER3(SEC_ERROR_KEY_NICKNAME_COLLISION, (SEC_ERROR_BASE + 69),
+"A key with the same nickname already exists.")
+
+ER3(SEC_ERROR_SAFE_NOT_CREATED, (SEC_ERROR_BASE + 70),
+"error while creating safe object")
+
+ER3(SEC_ERROR_BAGGAGE_NOT_CREATED, (SEC_ERROR_BASE + 71),
+"error while creating baggage object")
+
+ER3(XP_JAVA_REMOVE_PRINCIPAL_ERROR, (SEC_ERROR_BASE + 72),
+"Couldn't remove the principal")
+
+ER3(XP_JAVA_DELETE_PRIVILEGE_ERROR, (SEC_ERROR_BASE + 73),
+"Couldn't delete the privilege")
+
+ER3(XP_JAVA_CERT_NOT_EXISTS_ERROR, (SEC_ERROR_BASE + 74),
+"This principal doesn't have a certificate")
+
+ER3(SEC_ERROR_BAD_EXPORT_ALGORITHM, (SEC_ERROR_BASE + 75),
+"Required algorithm is not allowed.")
+
+ER3(SEC_ERROR_EXPORTING_CERTIFICATES, (SEC_ERROR_BASE + 76),
+"Error attempting to export certificates.")
+
+ER3(SEC_ERROR_IMPORTING_CERTIFICATES, (SEC_ERROR_BASE + 77),
+"Error attempting to import certificates.")
+
+ER3(SEC_ERROR_PKCS12_DECODING_PFX, (SEC_ERROR_BASE + 78),
+"Unable to import. Decoding error. File not valid.")
+
+ER3(SEC_ERROR_PKCS12_INVALID_MAC, (SEC_ERROR_BASE + 79),
+"Unable to import. Invalid MAC. Incorrect password or corrupt file.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, (SEC_ERROR_BASE + 80),
+"Unable to import. MAC algorithm not supported.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE,(SEC_ERROR_BASE + 81),
+"Unable to import. Only password integrity and privacy modes supported.")
+
+ER3(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, (SEC_ERROR_BASE + 82),
+"Unable to import. File structure is corrupt.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, (SEC_ERROR_BASE + 83),
+"Unable to import. Encryption algorithm not supported.")
+
+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, (SEC_ERROR_BASE + 84),
+"Unable to import. File version not supported.")
+
+ER3(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT,(SEC_ERROR_BASE + 85),
+"Unable to import. Incorrect privacy password.")
+
+ER3(SEC_ERROR_PKCS12_CERT_COLLISION, (SEC_ERROR_BASE + 86),
+"Unable to import. Same nickname already exists in database.")
+
+ER3(SEC_ERROR_USER_CANCELLED, (SEC_ERROR_BASE + 87),
+"The user pressed cancel.")
+
+ER3(SEC_ERROR_PKCS12_DUPLICATE_DATA, (SEC_ERROR_BASE + 88),
+"Not imported, already in database.")
+
+ER3(SEC_ERROR_MESSAGE_SEND_ABORTED, (SEC_ERROR_BASE + 89),
+"Message not sent.")
+
+ER3(SEC_ERROR_INADEQUATE_KEY_USAGE, (SEC_ERROR_BASE + 90),
+"Certificate key usage inadequate for attempted operation.")
+
+ER3(SEC_ERROR_INADEQUATE_CERT_TYPE, (SEC_ERROR_BASE + 91),
+"Certificate type not approved for application.")
+
+ER3(SEC_ERROR_CERT_ADDR_MISMATCH, (SEC_ERROR_BASE + 92),
+"Address in signing certificate does not match address in message headers.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, (SEC_ERROR_BASE + 93),
+"Unable to import. Error attempting to import private key.")
+
+ER3(SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, (SEC_ERROR_BASE + 94),
+"Unable to import. Error attempting to import certificate chain.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, (SEC_ERROR_BASE + 95),
+"Unable to export. Unable to locate certificate or key by nickname.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, (SEC_ERROR_BASE + 96),
+"Unable to export. Private Key could not be located and exported.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_WRITE, (SEC_ERROR_BASE + 97),
+"Unable to export. Unable to write the export file.")
+
+ER3(SEC_ERROR_PKCS12_UNABLE_TO_READ, (SEC_ERROR_BASE + 98),
+"Unable to import. Unable to read the import file.")
+
+ER3(SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, (SEC_ERROR_BASE + 99),
+"Unable to export. Key database corrupt or deleted.")
+
+ER3(SEC_ERROR_KEYGEN_FAIL, (SEC_ERROR_BASE + 100),
+"Unable to generate public/private key pair.")
+
+ER3(SEC_ERROR_INVALID_PASSWORD, (SEC_ERROR_BASE + 101),
+"Password entered is invalid. Please pick a different one.")
+
+ER3(SEC_ERROR_RETRY_OLD_PASSWORD, (SEC_ERROR_BASE + 102),
+"Old password entered incorrectly. Please try again.")
+
+ER3(SEC_ERROR_BAD_NICKNAME, (SEC_ERROR_BASE + 103),
+"Certificate nickname already in use.")
+
+ER3(SEC_ERROR_NOT_FORTEZZA_ISSUER, (SEC_ERROR_BASE + 104),
+"Peer FORTEZZA chain has a non-FORTEZZA Certificate.")
+
+ER3(SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY, (SEC_ERROR_BASE + 105),
+"A sensitive key cannot be moved to the slot where it is needed.")
+
+ER3(SEC_ERROR_JS_INVALID_MODULE_NAME, (SEC_ERROR_BASE + 106),
+"Invalid module name.")
+
+ER3(SEC_ERROR_JS_INVALID_DLL, (SEC_ERROR_BASE + 107),
+"Invalid module path/filename")
+
+ER3(SEC_ERROR_JS_ADD_MOD_FAILURE, (SEC_ERROR_BASE + 108),
+"Unable to add module")
+
+ER3(SEC_ERROR_JS_DEL_MOD_FAILURE, (SEC_ERROR_BASE + 109),
+"Unable to delete module")
+
+ER3(SEC_ERROR_OLD_KRL, (SEC_ERROR_BASE + 110),
+"New KRL is not later than the current one.")
+
+ER3(SEC_ERROR_CKL_CONFLICT, (SEC_ERROR_BASE + 111),
+"New CKL has different issuer than current CKL. Delete current CKL.")
+
+ER3(SEC_ERROR_CERT_NOT_IN_NAME_SPACE, (SEC_ERROR_BASE + 112),
+"The Certifying Authority for this certificate is not permitted to issue a \
+certificate with this name.")
+
+ER3(SEC_ERROR_KRL_NOT_YET_VALID, (SEC_ERROR_BASE + 113),
+"The key revocation list for this certificate is not yet valid.")
+
+ER3(SEC_ERROR_CRL_NOT_YET_VALID, (SEC_ERROR_BASE + 114),
+"The certificate revocation list for this certificate is not yet valid.")
+
+ER3(SEC_ERROR_UNKNOWN_CERT, (SEC_ERROR_BASE + 115),
+"The requested certificate could not be found.")
+
+ER3(SEC_ERROR_UNKNOWN_SIGNER, (SEC_ERROR_BASE + 116),
+"The signer's certificate could not be found.")
+
+ER3(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, (SEC_ERROR_BASE + 117),
+"The location for the certificate status server has invalid format.")
+
+ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, (SEC_ERROR_BASE + 118),
+"The OCSP response cannot be fully decoded; it is of an unknown type.")
+
+ER3(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, (SEC_ERROR_BASE + 119),
+"The OCSP server returned unexpected/invalid HTTP data.")
+
+ER3(SEC_ERROR_OCSP_MALFORMED_REQUEST, (SEC_ERROR_BASE + 120),
+"The OCSP server found the request to be corrupted or improperly formed.")
+
+ER3(SEC_ERROR_OCSP_SERVER_ERROR, (SEC_ERROR_BASE + 121),
+"The OCSP server experienced an internal error.")
+
+ER3(SEC_ERROR_OCSP_TRY_SERVER_LATER, (SEC_ERROR_BASE + 122),
+"The OCSP server suggests trying again later.")
+
+ER3(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, (SEC_ERROR_BASE + 123),
+"The OCSP server requires a signature on this request.")
+
+ER3(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, (SEC_ERROR_BASE + 124),
+"The OCSP server has refused this request as unauthorized.")
+
+ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, (SEC_ERROR_BASE + 125),
+"The OCSP server returned an unrecognizable status.")
+
+ER3(SEC_ERROR_OCSP_UNKNOWN_CERT, (SEC_ERROR_BASE + 126),
+"The OCSP server has no status for the certificate.")
+
+ER3(SEC_ERROR_OCSP_NOT_ENABLED, (SEC_ERROR_BASE + 127),
+"You must enable OCSP before performing this operation.")
+
+ER3(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, (SEC_ERROR_BASE + 128),
+"You must set the OCSP default responder before performing this operation.")
+
+ER3(SEC_ERROR_OCSP_MALFORMED_RESPONSE, (SEC_ERROR_BASE + 129),
+"The response from the OCSP server was corrupted or improperly formed.")
+
+ER3(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, (SEC_ERROR_BASE + 130),
+"The signer of the OCSP response is not authorized to give status for \
+this certificate.")
+
+ER3(SEC_ERROR_OCSP_FUTURE_RESPONSE, (SEC_ERROR_BASE + 131),
+"The OCSP response is not yet valid (contains a date in the future).")
+
+ER3(SEC_ERROR_OCSP_OLD_RESPONSE, (SEC_ERROR_BASE + 132),
+"The OCSP response contains out-of-date information.")
+
+ER3(SEC_ERROR_DIGEST_NOT_FOUND, (SEC_ERROR_BASE + 133),
+"The CMS or PKCS #7 Digest was not found in signed message.")
+
+ER3(SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE, (SEC_ERROR_BASE + 134),
+"The CMS or PKCS #7 Message type is unsupported.")
+
+ER3(SEC_ERROR_MODULE_STUCK, (SEC_ERROR_BASE + 135),
+"PKCS #11 module could not be removed because it is still in use.")
+
+ER3(SEC_ERROR_BAD_TEMPLATE, (SEC_ERROR_BASE + 136),
+"Could not decode ASN.1 data. Specified template was invalid.")
+
+ER3(SEC_ERROR_CRL_NOT_FOUND, (SEC_ERROR_BASE + 137),
+"No matching CRL was found.")
+
+ER3(SEC_ERROR_REUSED_ISSUER_AND_SERIAL, (SEC_ERROR_BASE + 138),
+"You are attempting to import a cert with the same issuer/serial as \
+an existing cert, but that is not the same cert.")
+
+ER3(SEC_ERROR_BUSY, (SEC_ERROR_BASE + 139),
+"NSS could not shutdown. Objects are still in use.")
+
+ER3(SEC_ERROR_EXTRA_INPUT, (SEC_ERROR_BASE + 140),
+"DER-encoded message contained extra usused data.")
+
+ER3(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE, (SEC_ERROR_BASE + 141),
+"Unsupported elliptic curve.")
+
+ER3(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM, (SEC_ERROR_BASE + 142),
+"Unsupported elliptic curve point form.")
+
+ER3(SEC_ERROR_UNRECOGNIZED_OID, (SEC_ERROR_BASE + 143),
+"Unrecognized Object IDentifier.")
diff --git a/security/nss/cmd/lib/SSLerrs.h b/security/nss/cmd/lib/SSLerrs.h
new file mode 100644
index 000000000..06803b849
--- /dev/null
+++ b/security/nss/cmd/lib/SSLerrs.h
@@ -0,0 +1,366 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/* SSL-specific security error codes */
+/* caller must include "sslerr.h" */
+
+ER3(SSL_ERROR_EXPORT_ONLY_SERVER, SSL_ERROR_BASE + 0,
+"Unable to communicate securely. Peer does not support high-grade encryption.")
+
+ER3(SSL_ERROR_US_ONLY_SERVER, SSL_ERROR_BASE + 1,
+"Unable to communicate securely. Peer requires high-grade encryption which is not supported.")
+
+ER3(SSL_ERROR_NO_CYPHER_OVERLAP, SSL_ERROR_BASE + 2,
+"Cannot communicate securely with peer: no common encryption algorithm(s).")
+
+ER3(SSL_ERROR_NO_CERTIFICATE, SSL_ERROR_BASE + 3,
+"Unable to find the certificate or key necessary for authentication.")
+
+ER3(SSL_ERROR_BAD_CERTIFICATE, SSL_ERROR_BASE + 4,
+"Unable to communicate securely with peer: peers's certificate was rejected.")
+
+/* unused (SSL_ERROR_BASE + 5),*/
+
+ER3(SSL_ERROR_BAD_CLIENT, SSL_ERROR_BASE + 6,
+"The server has encountered bad data from the client.")
+
+ER3(SSL_ERROR_BAD_SERVER, SSL_ERROR_BASE + 7,
+"The client has encountered bad data from the server.")
+
+ER3(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE, SSL_ERROR_BASE + 8,
+"Unsupported certificate type.")
+
+ER3(SSL_ERROR_UNSUPPORTED_VERSION, SSL_ERROR_BASE + 9,
+"Peer using unsupported version of security protocol.")
+
+/* unused (SSL_ERROR_BASE + 10),*/
+
+ER3(SSL_ERROR_WRONG_CERTIFICATE, SSL_ERROR_BASE + 11,
+"Client authentication failed: private key in key database does not match public key in certificate database.")
+
+ER3(SSL_ERROR_BAD_CERT_DOMAIN, SSL_ERROR_BASE + 12,
+"Unable to communicate securely with peer: requested domain name does not match the server's certificate.")
+
+/* SSL_ERROR_POST_WARNING (SSL_ERROR_BASE + 13),
+ defined in sslerr.h
+*/
+
+ER3(SSL_ERROR_SSL2_DISABLED, (SSL_ERROR_BASE + 14),
+"Peer only supports SSL version 2, which is locally disabled.")
+
+
+ER3(SSL_ERROR_BAD_MAC_READ, (SSL_ERROR_BASE + 15),
+"SSL received a record with an incorrect Message Authentication Code.")
+
+ER3(SSL_ERROR_BAD_MAC_ALERT, (SSL_ERROR_BASE + 16),
+"SSL peer reports incorrect Message Authentication Code.")
+
+ER3(SSL_ERROR_BAD_CERT_ALERT, (SSL_ERROR_BASE + 17),
+"SSL peer cannot verify your certificate.")
+
+ER3(SSL_ERROR_REVOKED_CERT_ALERT, (SSL_ERROR_BASE + 18),
+"SSL peer rejected your certificate as revoked.")
+
+ER3(SSL_ERROR_EXPIRED_CERT_ALERT, (SSL_ERROR_BASE + 19),
+"SSL peer rejected your certificate as expired.")
+
+ER3(SSL_ERROR_SSL_DISABLED, (SSL_ERROR_BASE + 20),
+"Cannot connect: SSL is disabled.")
+
+ER3(SSL_ERROR_FORTEZZA_PQG, (SSL_ERROR_BASE + 21),
+"Cannot connect: SSL peer is in another FORTEZZA domain.")
+
+
+ER3(SSL_ERROR_UNKNOWN_CIPHER_SUITE , (SSL_ERROR_BASE + 22),
+"An unknown SSL cipher suite has been requested.")
+
+ER3(SSL_ERROR_NO_CIPHERS_SUPPORTED , (SSL_ERROR_BASE + 23),
+"No cipher suites are present and enabled in this program.")
+
+ER3(SSL_ERROR_BAD_BLOCK_PADDING , (SSL_ERROR_BASE + 24),
+"SSL received a record with bad block padding.")
+
+ER3(SSL_ERROR_RX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 25),
+"SSL received a record that exceeded the maximum permissible length.")
+
+ER3(SSL_ERROR_TX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 26),
+"SSL attempted to send a record that exceeded the maximum permissible length.")
+
+/*
+ * Received a malformed (too long or short or invalid content) SSL handshake.
+ */
+ER3(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST , (SSL_ERROR_BASE + 27),
+"SSL received a malformed Hello Request handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO , (SSL_ERROR_BASE + 28),
+"SSL received a malformed Client Hello handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_SERVER_HELLO , (SSL_ERROR_BASE + 29),
+"SSL received a malformed Server Hello handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CERTIFICATE , (SSL_ERROR_BASE + 30),
+"SSL received a malformed Certificate handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 31),
+"SSL received a malformed Server Key Exchange handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CERT_REQUEST , (SSL_ERROR_BASE + 32),
+"SSL received a malformed Certificate Request handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_HELLO_DONE , (SSL_ERROR_BASE + 33),
+"SSL received a malformed Server Hello Done handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CERT_VERIFY , (SSL_ERROR_BASE + 34),
+"SSL received a malformed Certificate Verify handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 35),
+"SSL received a malformed Client Key Exchange handshake message.")
+
+ER3(SSL_ERROR_RX_MALFORMED_FINISHED , (SSL_ERROR_BASE + 36),
+"SSL received a malformed Finished handshake message.")
+
+/*
+ * Received a malformed (too long or short) SSL record.
+ */
+ER3(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER , (SSL_ERROR_BASE + 37),
+"SSL received a malformed Change Cipher Spec record.")
+
+ER3(SSL_ERROR_RX_MALFORMED_ALERT , (SSL_ERROR_BASE + 38),
+"SSL received a malformed Alert record.")
+
+ER3(SSL_ERROR_RX_MALFORMED_HANDSHAKE , (SSL_ERROR_BASE + 39),
+"SSL received a malformed Handshake record.")
+
+ER3(SSL_ERROR_RX_MALFORMED_APPLICATION_DATA , (SSL_ERROR_BASE + 40),
+"SSL received a malformed Application Data record.")
+
+/*
+ * Received an SSL handshake that was inappropriate for the state we're in.
+ * E.g. Server received message from server, or wrong state in state machine.
+ */
+ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST , (SSL_ERROR_BASE + 41),
+"SSL received an unexpected Hello Request handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO , (SSL_ERROR_BASE + 42),
+"SSL received an unexpected Client Hello handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO , (SSL_ERROR_BASE + 43),
+"SSL received an unexpected Server Hello handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CERTIFICATE , (SSL_ERROR_BASE + 44),
+"SSL received an unexpected Certificate handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 45),
+"SSL received an unexpected Server Key Exchange handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST , (SSL_ERROR_BASE + 46),
+"SSL received an unexpected Certificate Request handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE , (SSL_ERROR_BASE + 47),
+"SSL received an unexpected Server Hello Done handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY , (SSL_ERROR_BASE + 48),
+"SSL received an unexpected Certificate Verify handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 49),
+"SSL received an unexpected Cllient Key Exchange handshake message.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_FINISHED , (SSL_ERROR_BASE + 50),
+"SSL received an unexpected Finished handshake message.")
+
+/*
+ * Received an SSL record that was inappropriate for the state we're in.
+ */
+ER3(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER , (SSL_ERROR_BASE + 51),
+"SSL received an unexpected Change Cipher Spec record.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 52),
+"SSL received an unexpected Alert record.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE , (SSL_ERROR_BASE + 53),
+"SSL received an unexpected Handshake record.")
+
+ER3(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA, (SSL_ERROR_BASE + 54),
+"SSL received an unexpected Application Data record.")
+
+/*
+ * Received record/message with unknown discriminant.
+ */
+ER3(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE , (SSL_ERROR_BASE + 55),
+"SSL received a record with an unknown content type.")
+
+ER3(SSL_ERROR_RX_UNKNOWN_HANDSHAKE , (SSL_ERROR_BASE + 56),
+"SSL received a handshake message with an unknown message type.")
+
+ER3(SSL_ERROR_RX_UNKNOWN_ALERT , (SSL_ERROR_BASE + 57),
+"SSL received an alert record with an unknown alert description.")
+
+/*
+ * Received an alert reporting what we did wrong. (more alerts above)
+ */
+ER3(SSL_ERROR_CLOSE_NOTIFY_ALERT , (SSL_ERROR_BASE + 58),
+"SSL peer has closed this connection.")
+
+ER3(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 59),
+"SSL peer was not expecting a handshake message it received.")
+
+ER3(SSL_ERROR_DECOMPRESSION_FAILURE_ALERT , (SSL_ERROR_BASE + 60),
+"SSL peer was unable to succesfully decompress an SSL record it received.")
+
+ER3(SSL_ERROR_HANDSHAKE_FAILURE_ALERT , (SSL_ERROR_BASE + 61),
+"SSL peer was unable to negotiate an acceptable set of security parameters.")
+
+ER3(SSL_ERROR_ILLEGAL_PARAMETER_ALERT , (SSL_ERROR_BASE + 62),
+"SSL peer rejected a handshake message for unacceptable content.")
+
+ER3(SSL_ERROR_UNSUPPORTED_CERT_ALERT , (SSL_ERROR_BASE + 63),
+"SSL peer does not support certificates of the type it received.")
+
+ER3(SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT , (SSL_ERROR_BASE + 64),
+"SSL peer had some unspecified issue with the certificate it received.")
+
+
+ER3(SSL_ERROR_GENERATE_RANDOM_FAILURE , (SSL_ERROR_BASE + 65),
+"SSL experienced a failure of its random number generator.")
+
+ER3(SSL_ERROR_SIGN_HASHES_FAILURE , (SSL_ERROR_BASE + 66),
+"Unable to digitally sign data required to verify your certificate.")
+
+ER3(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE , (SSL_ERROR_BASE + 67),
+"SSL was unable to extract the public key from the peer's certificate.")
+
+ER3(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 68),
+"Unspecified failure while processing SSL Server Key Exchange handshake.")
+
+ER3(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 69),
+"Unspecified failure while processing SSL Client Key Exchange handshake.")
+
+ER3(SSL_ERROR_ENCRYPTION_FAILURE , (SSL_ERROR_BASE + 70),
+"Bulk data encryption algorithm failed in selected cipher suite.")
+
+ER3(SSL_ERROR_DECRYPTION_FAILURE , (SSL_ERROR_BASE + 71),
+"Bulk data decryption algorithm failed in selected cipher suite.")
+
+ER3(SSL_ERROR_SOCKET_WRITE_FAILURE , (SSL_ERROR_BASE + 72),
+"Attempt to write encrypted data to underlying socket failed.")
+
+ER3(SSL_ERROR_MD5_DIGEST_FAILURE , (SSL_ERROR_BASE + 73),
+"MD5 digest function failed.")
+
+ER3(SSL_ERROR_SHA_DIGEST_FAILURE , (SSL_ERROR_BASE + 74),
+"SHA-1 digest function failed.")
+
+ER3(SSL_ERROR_MAC_COMPUTATION_FAILURE , (SSL_ERROR_BASE + 75),
+"MAC computation failed.")
+
+ER3(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE , (SSL_ERROR_BASE + 76),
+"Failure to create Symmetric Key context.")
+
+ER3(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE , (SSL_ERROR_BASE + 77),
+"Failure to unwrap the Symmetric key in Client Key Exchange message.")
+
+ER3(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED , (SSL_ERROR_BASE + 78),
+"SSL Server attempted to use domestic-grade public key with export cipher suite.")
+
+ER3(SSL_ERROR_IV_PARAM_FAILURE , (SSL_ERROR_BASE + 79),
+"PKCS11 code failed to translate an IV into a param.")
+
+ER3(SSL_ERROR_INIT_CIPHER_SUITE_FAILURE , (SSL_ERROR_BASE + 80),
+"Failed to initialize the selected cipher suite.")
+
+ER3(SSL_ERROR_SESSION_KEY_GEN_FAILURE , (SSL_ERROR_BASE + 81),
+"Client failed to generate session keys for SSL session.")
+
+ER3(SSL_ERROR_NO_SERVER_KEY_FOR_ALG , (SSL_ERROR_BASE + 82),
+"Server has no key for the attempted key exchange algorithm.")
+
+ER3(SSL_ERROR_TOKEN_INSERTION_REMOVAL , (SSL_ERROR_BASE + 83),
+"PKCS#11 token was inserted or removed while operation was in progress.")
+
+ER3(SSL_ERROR_TOKEN_SLOT_NOT_FOUND , (SSL_ERROR_BASE + 84),
+"No PKCS#11 token could be found to do a required operation.")
+
+ER3(SSL_ERROR_NO_COMPRESSION_OVERLAP , (SSL_ERROR_BASE + 85),
+"Cannot communicate securely with peer: no common compression algorithm(s).")
+
+ER3(SSL_ERROR_HANDSHAKE_NOT_COMPLETED , (SSL_ERROR_BASE + 86),
+"Cannot initiate another SSL handshake until current handshake is complete.")
+
+ER3(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE , (SSL_ERROR_BASE + 87),
+"Received incorrect handshakes hash values from peer.")
+
+ER3(SSL_ERROR_CERT_KEA_MISMATCH , (SSL_ERROR_BASE + 88),
+"The certificate provided cannot be used with the selected key exchange algorithm.")
+
+ER3(SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA , (SSL_ERROR_BASE + 89),
+"No certificate authority is trusted for SSL client authentication.")
+
+ER3(SSL_ERROR_SESSION_NOT_FOUND , (SSL_ERROR_BASE + 90),
+"Client's SSL session ID not found in server's session cache.")
+
+ER3(SSL_ERROR_DECRYPTION_FAILED_ALERT , (SSL_ERROR_BASE + 91),
+"Peer was unable to decrypt an SSL record it received.")
+
+ER3(SSL_ERROR_RECORD_OVERFLOW_ALERT , (SSL_ERROR_BASE + 92),
+"Peer received an SSL record that was longer than is permitted.")
+
+ER3(SSL_ERROR_UNKNOWN_CA_ALERT , (SSL_ERROR_BASE + 93),
+"Peer does not recognize and trust the CA that issued your certificate.")
+
+ER3(SSL_ERROR_ACCESS_DENIED_ALERT , (SSL_ERROR_BASE + 94),
+"Peer received a valid certificate, but access was denied.")
+
+ER3(SSL_ERROR_DECODE_ERROR_ALERT , (SSL_ERROR_BASE + 95),
+"Peer could not decode an SSL handshake message.")
+
+ER3(SSL_ERROR_DECRYPT_ERROR_ALERT , (SSL_ERROR_BASE + 96),
+"Peer reports failure of signature verification or key exchange.")
+
+ER3(SSL_ERROR_EXPORT_RESTRICTION_ALERT , (SSL_ERROR_BASE + 97),
+"Peer reports negotiation not in compliance with export regulations.")
+
+ER3(SSL_ERROR_PROTOCOL_VERSION_ALERT , (SSL_ERROR_BASE + 98),
+"Peer reports incompatible or unsupported protocol version.")
+
+ER3(SSL_ERROR_INSUFFICIENT_SECURITY_ALERT , (SSL_ERROR_BASE + 99),
+"Server requires ciphers more secure than those supported by client.")
+
+ER3(SSL_ERROR_INTERNAL_ERROR_ALERT , (SSL_ERROR_BASE + 100),
+"Peer reports it experienced an internal error.")
+
+ER3(SSL_ERROR_USER_CANCELED_ALERT , (SSL_ERROR_BASE + 101),
+"Peer user canceled handshake.")
+
+ER3(SSL_ERROR_NO_RENEGOTIATION_ALERT , (SSL_ERROR_BASE + 102),
+"Peer does not permit renegotiation of SSL security parameters.")
+
diff --git a/security/nss/cmd/lib/berparse.c b/security/nss/cmd/lib/berparse.c
new file mode 100644
index 000000000..c040ab2b1
--- /dev/null
+++ b/security/nss/cmd/lib/berparse.c
@@ -0,0 +1,404 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#include "secutil.h"
+
+typedef enum {
+ tagDone, lengthDone, leafDone, compositeDone,
+ notDone,
+ parseError, parseComplete
+} ParseState;
+
+typedef unsigned char Byte;
+typedef void (*ParseProc)(BERParse *h, unsigned char **buf, int *len);
+typedef struct {
+ SECArb arb;
+ int pos; /* length from global start to item start */
+ SECArb *parent;
+} ParseStackElem;
+
+struct BERParseStr {
+ PRArenaPool *his;
+ PRArenaPool *mine;
+ ParseProc proc;
+ int stackDepth;
+ ParseStackElem *stackPtr;
+ ParseStackElem *stack;
+ int pending; /* bytes remaining to complete this part */
+ int pos; /* running length of consumed characters */
+ ParseState state;
+ PRBool keepLeaves;
+ PRBool derOnly;
+ BERFilterProc filter;
+ void *filterArg;
+ BERNotifyProc before;
+ void *beforeArg;
+ BERNotifyProc after;
+ void *afterArg;
+};
+
+#define UNKNOWN -1
+
+static unsigned char NextChar(BERParse *h, unsigned char **buf, int *len)
+{
+ unsigned char c = *(*buf)++;
+ (*len)--;
+ h->pos++;
+ if (h->filter)
+ (*h->filter)(h->filterArg, &c, 1);
+ return c;
+}
+
+static void ParseTag(BERParse *h, unsigned char **buf, int *len)
+{
+ SECArb* arb = &(h->stackPtr->arb);
+ arb->tag = NextChar(h, buf, len);
+
+ PORT_Assert(h->state == notDone);
+
+ /*
+ * NOTE: This does not handle the high-tag-number form
+ */
+ if ((arb->tag & DER_HIGH_TAG_NUMBER) == DER_HIGH_TAG_NUMBER) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return;
+ }
+
+ h->pending = UNKNOWN;
+ arb->length = UNKNOWN;
+ if (arb->tag & DER_CONSTRUCTED) {
+ arb->body.cons.numSubs = 0;
+ arb->body.cons.subs = NULL;
+ } else {
+ arb->body.item.len = UNKNOWN;
+ arb->body.item.data = NULL;
+ }
+
+ h->state = tagDone;
+}
+
+static void ParseLength(BERParse *h, unsigned char **buf, int *len)
+{
+ Byte b;
+ SECArb *arb = &(h->stackPtr->arb);
+
+ PORT_Assert(h->state == notDone);
+
+ if (h->pending == UNKNOWN) {
+ b = NextChar(h, buf, len);
+ if ((b & 0x80) == 0) { /* short form */
+ arb->length = b;
+ /*
+ * if the tag and the length are both zero bytes, then this
+ * should be the marker showing end of list for the
+ * indefinite length composite
+ */
+ if (arb->length == 0 && arb->tag == 0)
+ h->state = compositeDone;
+ else
+ h->state = lengthDone;
+ return;
+ }
+
+ h->pending = b & 0x7f;
+ /* 0 implies this is an indefinite length */
+ if (h->pending > 4) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return;
+ }
+ arb->length = 0;
+ }
+
+ while ((*len > 0) && (h->pending > 0)) {
+ b = NextChar(h, buf, len);
+ arb->length = (arb->length << 8) + b;
+ h->pending--;
+ }
+ if (h->pending == 0) {
+ if (h->derOnly && (arb->length == 0))
+ h->state = parseError;
+ else
+ h->state = lengthDone;
+ }
+ return;
+}
+
+static void ParseLeaf(BERParse *h, unsigned char **buf, int *len)
+{
+ int count;
+ SECArb *arb = &(h->stackPtr->arb);
+
+ PORT_Assert(h->state == notDone);
+ PORT_Assert(h->pending >= 0);
+
+ if (*len < h->pending)
+ count = *len;
+ else
+ count = h->pending;
+
+ if (h->keepLeaves)
+ memcpy(arb->body.item.data + arb->body.item.len, *buf, count);
+ if (h->filter)
+ (*h->filter)(h->filterArg, *buf, count);
+ *buf += count;
+ *len -= count;
+ arb->body.item.len += count;
+ h->pending -= count;
+ h->pos += count;
+ if (h->pending == 0) {
+ h->state = leafDone;
+ }
+ return;
+}
+
+static void CreateArbNode(BERParse *h)
+{
+ SECArb *arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));
+
+ *arb = h->stackPtr->arb;
+
+ /*
+ * Special case closing the root
+ */
+ if (h->stackPtr == h->stack) {
+ PORT_Assert(arb->tag & DER_CONSTRUCTED);
+ h->state = parseComplete;
+ } else {
+ SECArb *parent = h->stackPtr->parent;
+ parent->body.cons.subs = DS_ArenaGrow(
+ h->his, parent->body.cons.subs,
+ (parent->body.cons.numSubs) * sizeof(SECArb*),
+ (parent->body.cons.numSubs + 1) * sizeof(SECArb*));
+ parent->body.cons.subs[parent->body.cons.numSubs] = arb;
+ parent->body.cons.numSubs++;
+ h->proc = ParseTag;
+ h->state = notDone;
+ h->pending = UNKNOWN;
+ }
+ if (h->after)
+ (*h->after)(h->afterArg, arb, h->stackPtr - h->stack, PR_FALSE);
+}
+
+SECStatus BER_ParseSome(BERParse *h, unsigned char *buf, int len)
+{
+ if (h->state == parseError) return PR_TRUE;
+
+ while (len) {
+ (*h->proc)(h, &buf, &len);
+ if (h->state == parseComplete) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return PR_TRUE;
+ }
+ if (h->state == parseError) return PR_TRUE;
+ PORT_Assert(h->state != parseComplete);
+
+ if (h->state <= compositeDone) {
+ if (h->proc == ParseTag) {
+ PORT_Assert(h->state == tagDone);
+ h->proc = ParseLength;
+ h->state = notDone;
+ } else if (h->proc == ParseLength) {
+ SECArb *arb = &(h->stackPtr->arb);
+ PORT_Assert(h->state == lengthDone || h->state == compositeDone);
+
+ if (h->before)
+ (*h->before)(h->beforeArg, arb,
+ h->stackPtr - h->stack, PR_TRUE);
+
+ /*
+ * Check to see if this is the end of an indefinite
+ * length composite
+ */
+ if (h->state == compositeDone) {
+ SECArb *parent = h->stackPtr->parent;
+ PORT_Assert(parent);
+ PORT_Assert(parent->tag & DER_CONSTRUCTED);
+ if (parent->length != 0) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return PR_TRUE;
+ }
+ /*
+ * NOTE: This does not check for an indefinite length
+ * composite being contained inside a definite length
+ * composite. It is not clear that is legal.
+ */
+ h->stackPtr--;
+ CreateArbNode(h);
+ } else {
+ h->stackPtr->pos = h->pos;
+
+
+ if (arb->tag & DER_CONSTRUCTED) {
+ SECArb *parent;
+ /*
+ * Make sure there is room on the stack before we
+ * stick anything else there.
+ */
+ PORT_Assert(h->stackPtr - h->stack < h->stackDepth);
+ if (h->stackPtr - h->stack == h->stackDepth - 1) {
+ int newDepth = h->stackDepth * 2;
+ h->stack = DS_ArenaGrow(h->mine, h->stack,
+ sizeof(ParseStackElem) * h->stackDepth,
+ sizeof(ParseStackElem) * newDepth);
+ h->stackPtr = h->stack + h->stackDepth + 1;
+ h->stackDepth = newDepth;
+ }
+ parent = &(h->stackPtr->arb);
+ h->stackPtr++;
+ h->stackPtr->parent = parent;
+ h->proc = ParseTag;
+ h->state = notDone;
+ h->pending = UNKNOWN;
+ } else {
+ if (arb->length < 0) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return PR_TRUE;
+ }
+ arb->body.item.len = 0;
+ if (arb->length > 0 && h->keepLeaves) {
+ arb->body.item.data =
+ PORT_ArenaAlloc(h->his, arb->length);
+ } else {
+ arb->body.item.data = NULL;
+ }
+ h->proc = ParseLeaf;
+ h->state = notDone;
+ h->pending = arb->length;
+ }
+ }
+ } else {
+ ParseStackElem *parent;
+ PORT_Assert(h->state = leafDone);
+ PORT_Assert(h->proc == ParseLeaf);
+
+ for (;;) {
+ CreateArbNode(h);
+ if (h->stackPtr == h->stack)
+ break;
+ parent = (h->stackPtr - 1);
+ PORT_Assert(parent->arb.tag & DER_CONSTRUCTED);
+ if (parent->arb.length == 0) /* need explicit end */
+ break;
+ if (parent->pos + parent->arb.length > h->pos)
+ break;
+ if (parent->pos + parent->arb.length < h->pos) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return PR_TRUE;
+ }
+ h->stackPtr = parent;
+ }
+ }
+
+ }
+ }
+ return PR_FALSE;
+}
+BERParse *BER_ParseInit(PRArenaPool *arena, PRBool derOnly)
+{
+ BERParse *h;
+ PRArenaPool *temp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (temp == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+ h = PORT_ArenaAlloc(temp, sizeof(BERParse));
+ if (h == NULL) {
+ PORT_FreeArena(temp, PR_FALSE);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+ h->his = arena;
+ h->mine = temp;
+ h->proc = ParseTag;
+ h->stackDepth = 20;
+ h->stack = PORT_ArenaZAlloc(h->mine,
+ sizeof(ParseStackElem) * h->stackDepth);
+ h->stackPtr = h->stack;
+ h->state = notDone;
+ h->pos = 0;
+ h->keepLeaves = PR_TRUE;
+ h->before = NULL;
+ h->after = NULL;
+ h->filter = NULL;
+ h->derOnly = derOnly;
+ return h;
+}
+
+SECArb *BER_ParseFini(BERParse *h)
+{
+ PRArenaPool *myArena = h->mine;
+ SECArb *arb;
+
+ if (h->state != parseComplete) {
+ arb = NULL;
+ } else {
+ arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));
+ *arb = h->stackPtr->arb;
+ }
+
+ PORT_FreeArena(myArena, PR_FALSE);
+
+ return arb;
+}
+
+
+void BER_SetFilter(BERParse *h, BERFilterProc proc, void *instance)
+{
+ h->filter = proc;
+ h->filterArg = instance;
+}
+
+void BER_SetLeafStorage(BERParse *h, PRBool keep)
+{
+ h->keepLeaves = keep;
+}
+
+void BER_SetNotifyProc(BERParse *h, BERNotifyProc proc, void *instance,
+ PRBool beforeData)
+{
+ if (beforeData) {
+ h->before = proc;
+ h->beforeArg = instance;
+ } else {
+ h->after = proc;
+ h->afterArg = instance;
+ }
+}
+
+
+
diff --git a/security/nss/cmd/lib/config.mk b/security/nss/cmd/lib/config.mk
new file mode 100644
index 000000000..0a00dc61e
--- /dev/null
+++ b/security/nss/cmd/lib/config.mk
@@ -0,0 +1,43 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#
+# Override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(LIBRARY)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+PROGRAM =
+
diff --git a/security/nss/cmd/lib/derprint.c b/security/nss/cmd/lib/derprint.c
new file mode 100644
index 000000000..7f699dec4
--- /dev/null
+++ b/security/nss/cmd/lib/derprint.c
@@ -0,0 +1,619 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#include "secutil.h"
+#include "secoid.h"
+
+#ifdef __sun
+extern int fprintf(FILE *strm, const char *format, .../* args */);
+extern int fflush(FILE *stream);
+#endif
+
+#define RIGHT_MARGIN 24
+/*#define RAW_BYTES 1 */
+
+static int prettyColumn = 0;
+
+static int
+getInteger256(unsigned char *data, unsigned int nb)
+{
+ int val;
+
+ switch (nb) {
+ case 1:
+ val = data[0];
+ break;
+ case 2:
+ val = (data[0] << 8) | data[1];
+ break;
+ case 3:
+ val = (data[0] << 16) | (data[1] << 8) | data[2];
+ break;
+ case 4:
+ val = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ return val;
+}
+
+static int
+prettyNewline(FILE *out)
+{
+ int rv;
+
+ if (prettyColumn != -1) {
+ rv = fprintf(out, "\n");
+ prettyColumn = -1;
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ }
+ return 0;
+}
+
+static int
+prettyIndent(FILE *out, unsigned level)
+{
+ unsigned int i;
+ int rv;
+
+ if (prettyColumn == -1) {
+ prettyColumn = level;
+ for (i = 0; i < level; i++) {
+ rv = fprintf(out, " ");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+prettyPrintByte(FILE *out, unsigned char item, unsigned int level)
+{
+ int rv;
+
+ rv = prettyIndent(out, level);
+ if (rv < 0)
+ return rv;
+
+ rv = fprintf(out, "%02x ", item);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ prettyColumn++;
+ if (prettyColumn >= RIGHT_MARGIN) {
+ return prettyNewline(out);
+ }
+
+ return 0;
+}
+
+static int
+prettyPrintLeaf(FILE *out, unsigned char *data,
+ unsigned int len, unsigned int lv)
+{
+ unsigned int i;
+ int rv;
+
+ for (i = 0; i < len; i++) {
+ rv = prettyPrintByte(out, *data++, lv);
+ if (rv < 0)
+ return rv;
+ }
+ return prettyNewline(out);
+}
+
+static int
+prettyPrintStringStart(FILE *out, unsigned char *str,
+ unsigned int len, unsigned int level)
+{
+#define BUF_SIZE 100
+ unsigned char buf[BUF_SIZE];
+ int rv;
+
+ if (len >= BUF_SIZE)
+ len = BUF_SIZE - 1;
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ rv = prettyIndent(out, level);
+ if (rv < 0)
+ return rv;
+
+ memcpy(buf, str, len);
+ buf[len] = '\000';
+
+ rv = fprintf(out, "\"%s\"", buf);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ return 0;
+#undef BUF_SIZE
+}
+
+static int
+prettyPrintString(FILE *out, unsigned char *str,
+ unsigned int len, unsigned int level, PRBool raw)
+{
+ int rv;
+
+ rv = prettyPrintStringStart(out, str, len, level);
+ if (rv < 0)
+ return rv;
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ if (raw) {
+ rv = prettyPrintLeaf(out, str, len, level);
+ if (rv < 0)
+ return rv;
+ }
+
+ return 0;
+}
+
+static int
+prettyPrintTime(FILE *out, unsigned char *str,
+ unsigned int len, unsigned int level, PRBool raw, PRBool utc)
+{
+ SECItem time_item;
+ int rv;
+
+ rv = prettyPrintStringStart(out, str, len, level);
+ if (rv < 0)
+ return rv;
+
+ time_item.data = str;
+ time_item.len = len;
+
+ rv = fprintf(out, " (");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ if (utc)
+ SECU_PrintUTCTime(out, &time_item, NULL, 0);
+ else
+ SECU_PrintGeneralizedTime(out, &time_item, NULL, 0);
+
+ rv = fprintf(out, ")");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ if (raw) {
+ rv = prettyPrintLeaf(out, str, len, level);
+ if (rv < 0)
+ return rv;
+ }
+
+ return 0;
+}
+
+static int
+prettyPrintObjectID(FILE *out, unsigned char *data,
+ unsigned int len, unsigned int level, PRBool raw)
+{
+ SECOidData *oiddata;
+ SECItem oiditem;
+ unsigned int i;
+ unsigned long val;
+ int rv;
+
+
+ /*
+ * First print the Object Id in numeric format
+ */
+
+ rv = prettyIndent(out, level);
+ if (rv < 0)
+ return rv;
+
+ val = data[0];
+ i = val % 40;
+ val = val / 40;
+ rv = fprintf(out, "%lu %u ", val, i);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ val = 0;
+ for (i = 1; i < len; ++i) {
+ unsigned long j;
+
+ j = data[i];
+ val = (val << 7) | (j & 0x7f);
+ if (j & 0x80)
+ continue;
+ rv = fprintf(out, "%lu ", val);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ val = 0;
+ }
+
+ /*
+ * Now try to look it up and print a symbolic version.
+ */
+ oiditem.data = data;
+ oiditem.len = len;
+ oiddata = SECOID_FindOID(&oiditem);
+ if (oiddata != NULL) {
+ i = PORT_Strlen(oiddata->desc);
+ if ((prettyColumn + 1 + (i / 3)) > RIGHT_MARGIN) {
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+ }
+
+ rv = prettyIndent(out, level);
+ if (rv < 0)
+ return rv;
+
+ rv = fprintf(out, "(%s)", oiddata->desc);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ }
+
+ /*
+ * Finally, on a new line, print the raw bytes (if requested).
+ */
+ if (raw) {
+ rv = prettyNewline(out);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ for (i = 0; i < len; i++) {
+ rv = prettyPrintByte(out, *data++, level);
+ if (rv < 0)
+ return rv;
+ }
+ }
+
+ return prettyNewline(out);
+}
+
+static char *prettyTagType [32] = {
+ "End of Contents",
+ "Boolean",
+ "Integer",
+ "Bit String",
+ "Octet String",
+ "NULL",
+ "Object Identifier",
+ "0x07",
+ "0x08",
+ "0x09",
+ "Enumerated",
+ "0x0B",
+ "UTF8 String",
+ "0x0D",
+ "0x0E",
+ "0x0F",
+ "Sequence",
+ "Set",
+ "0x12",
+ "Printable String",
+ "T61 String",
+ "0x15",
+ "IA5 String",
+ "UTC Time",
+ "Generalized Time",
+ "0x19",
+ "Visible String",
+ "0x1B",
+ "Universal String",
+ "0x1D",
+ "BMP String",
+ "High-Tag-Number"
+};
+
+static int
+prettyPrintTag(FILE *out, unsigned char *src, unsigned char *end,
+ unsigned char *codep, unsigned int level, PRBool raw)
+{
+ int rv;
+ unsigned char code, tagnum;
+
+ if (src >= end) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ code = *src;
+ tagnum = code & SEC_ASN1_TAGNUM_MASK;
+
+ /*
+ * NOTE: This code does not (yet) handle the high-tag-number form!
+ */
+ if (tagnum == SEC_ASN1_HIGH_TAG_NUMBER) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ if (raw)
+ rv = prettyPrintByte(out, code, level);
+ else
+ rv = prettyIndent(out, level);
+
+ if (rv < 0)
+ return rv;
+
+ if (code & SEC_ASN1_CONSTRUCTED) {
+ rv = fprintf(out, "C-");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ }
+
+ switch (code & SEC_ASN1_CLASS_MASK) {
+ case SEC_ASN1_UNIVERSAL:
+ rv = fprintf(out, "%s ", prettyTagType[tagnum]);
+ break;
+ case SEC_ASN1_APPLICATION:
+ rv = fprintf(out, "Application: %d ", tagnum);
+ break;
+ case SEC_ASN1_CONTEXT_SPECIFIC:
+ rv = fprintf(out, "[%d] ", tagnum);
+ break;
+ case SEC_ASN1_PRIVATE:
+ rv = fprintf(out, "Private: %d ", tagnum);
+ break;
+ }
+
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ *codep = code;
+
+ return 1;
+}
+
+static int
+prettyPrintLength(FILE *out, unsigned char *data, unsigned char *end,
+ int *lenp, PRBool *indefinitep, unsigned int lv, PRBool raw)
+{
+ unsigned char lbyte;
+ int lenLen;
+ int rv;
+
+ if (data >= end) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ rv = fprintf(out, " ");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ *indefinitep = PR_FALSE;
+
+ lbyte = *data++;
+ if (lbyte >= 0x80) {
+ /* Multibyte length */
+ unsigned nb = (unsigned) (lbyte & 0x7f);
+ if (nb > 4) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ if (nb > 0) {
+ int il;
+
+ if ((data + nb) > end) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ il = getInteger256(data, nb);
+ if (il < 0) return -1;
+ *lenp = (unsigned) il;
+ } else {
+ *lenp = 0;
+ *indefinitep = PR_TRUE;
+ }
+ lenLen = nb + 1;
+ if (raw) {
+ int i;
+
+ rv = prettyPrintByte(out, lbyte, lv);
+ if (rv < 0)
+ return rv;
+ for (i = 0; i < nb; i++) {
+ rv = prettyPrintByte(out, data[i], lv);
+ if (rv < 0)
+ return rv;
+ }
+ }
+ } else {
+ *lenp = lbyte;
+ lenLen = 1;
+ if (raw) {
+ rv = prettyPrintByte(out, lbyte, lv);
+ if (rv < 0)
+ return rv;
+ }
+ }
+ if (*indefinitep)
+ rv = fprintf(out, "(indefinite)\n");
+ else
+ rv = fprintf(out, "(%d)\n", *lenp);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ prettyColumn = -1;
+ return lenLen;
+}
+
+static int
+prettyPrintItem(FILE *out, unsigned char *data, unsigned char *end,
+ unsigned int lv, PRBool raw)
+{
+ int slen;
+ int lenLen;
+ unsigned char *orig = data;
+ int rv;
+
+ while (data < end) {
+ unsigned char code;
+ PRBool indefinite;
+
+ slen = prettyPrintTag(out, data, end, &code, lv, raw);
+ if (slen < 0)
+ return slen;
+ data += slen;
+
+ lenLen = prettyPrintLength(out, data, end, &slen, &indefinite, lv, raw);
+ if (lenLen < 0)
+ return lenLen;
+ data += lenLen;
+
+ /*
+ * Just quit now if slen more bytes puts us off the end.
+ */
+ if ((data + slen) > end) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ if (code & SEC_ASN1_CONSTRUCTED) {
+ if (slen > 0 || indefinite) {
+ slen = prettyPrintItem(out, data,
+ slen == 0 ? end : data + slen,
+ lv+1, raw);
+ if (slen < 0)
+ return slen;
+ data += slen;
+ }
+ } else if (code == 0) {
+ if (slen != 0 || lenLen != 1) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ break;
+ } else {
+ switch (code) {
+ case SEC_ASN1_PRINTABLE_STRING:
+ case SEC_ASN1_IA5_STRING:
+ case SEC_ASN1_VISIBLE_STRING:
+ rv = prettyPrintString(out, data, slen, lv+1, raw);
+ if (rv < 0)
+ return rv;
+ break;
+ case SEC_ASN1_UTC_TIME:
+ rv = prettyPrintTime(out, data, slen, lv+1, raw, PR_TRUE);
+ if (rv < 0)
+ return rv;
+ break;
+ case SEC_ASN1_GENERALIZED_TIME:
+ rv = prettyPrintTime(out, data, slen, lv+1, raw, PR_FALSE);
+ if (rv < 0)
+ return rv;
+ break;
+ case SEC_ASN1_OBJECT_ID:
+ rv = prettyPrintObjectID(out, data, slen, lv+1, raw);
+ if (rv < 0)
+ return rv;
+ break;
+ case SEC_ASN1_BOOLEAN: /* could do nicer job */
+ case SEC_ASN1_INTEGER: /* could do nicer job */
+ case SEC_ASN1_BIT_STRING: /* could do nicer job */
+ case SEC_ASN1_OCTET_STRING:
+ case SEC_ASN1_NULL:
+ case SEC_ASN1_ENUMERATED: /* could do nicer job, as INTEGER */
+ case SEC_ASN1_UTF8_STRING:
+ case SEC_ASN1_T61_STRING: /* print as printable string? */
+ case SEC_ASN1_UNIVERSAL_STRING:
+ case SEC_ASN1_BMP_STRING:
+ default:
+ rv = prettyPrintLeaf(out, data, slen, lv+1);
+ if (rv < 0)
+ return rv;
+ break;
+ }
+ data += slen;
+ }
+ }
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ return data - orig;
+}
+
+SECStatus
+DER_PrettyPrint(FILE *out, SECItem *it, PRBool raw)
+{
+ int rv;
+
+ prettyColumn = -1;
+
+ rv = prettyPrintItem(out, it->data, it->data + it->len, 0, raw);
+ if (rv < 0)
+ return SECFailure;
+ return SECSuccess;
+}
diff --git a/security/nss/cmd/lib/ffs.c b/security/nss/cmd/lib/ffs.c
new file mode 100644
index 000000000..3fce2c7c2
--- /dev/null
+++ b/security/nss/cmd/lib/ffs.c
@@ -0,0 +1,48 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#ifdef XP_PC
+
+int ffs( unsigned int i)
+{
+ int rv = 1;
+
+ if (!i) return 0;
+
+ while (!(i & 1)) {
+ i >>= 1;
+ ++rv;
+ }
+
+ return rv;
+}
+#endif
diff --git a/security/nss/cmd/lib/makefile.win b/security/nss/cmd/lib/makefile.win
new file mode 100644
index 000000000..92081a2f8
--- /dev/null
+++ b/security/nss/cmd/lib/makefile.win
@@ -0,0 +1,66 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+include <manifest.mn>
+
+include <$(DEPTH)\config\config.mak>
+
+# include files are aought in LINCS and INCS.
+# LINCS are generated from REQUIRES in manigest.mn
+INCS = $(INCS) \
+ -I..\include \
+ -I..\..\lib\cert \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)\dist\public\security \
+ -I$(DEPTH)\dist\public\nspr \
+ -I$(DEPTH)\cmd\winfe \
+ $(NULL)
+
+LCFLAGS = -DUSE_SSL -DEXPORT_VERSION
+
+PDBFILE = $(LIBNAME).pdb
+
+# work around a bug in rules.mak
+LIBRARY_SUFFIX = $(MOZ_BITS)
+
+include <$(DEPTH)\config\rules.mak>
+
+install:: $(LIBRARY)
+# $(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
+
+
+symbols::
+ @echo "LIBRARY_NAME is $(LIBRARY_NAME)"
+ @echo "LIBRARY is $(LIBRARY)"
diff --git a/security/nss/cmd/lib/manifest.mn b/security/nss/cmd/lib/manifest.mn
new file mode 100644
index 000000000..c68285252
--- /dev/null
+++ b/security/nss/cmd/lib/manifest.mn
@@ -0,0 +1,53 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+CORE_DEPTH = ../../..
+
+LIBRARY_NAME = sectool
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = seccmd
+
+DEFINES = -DNSPR20
+
+EXPORTS = secutil.h \
+ $(NULL)
+
+CSRCS = secutil.c \
+ secpwd.c \
+ derprint.c \
+ secerror.c \
+ ffs.c \
+ $(NULL)
+
+REQUIRES = nss nspr dbm
+
diff --git a/security/nss/cmd/lib/seccnames.c b/security/nss/cmd/lib/seccnames.c
new file mode 100644
index 000000000..a1857dc0e
--- /dev/null
+++ b/security/nss/cmd/lib/seccnames.c
@@ -0,0 +1,204 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+/*
+** secutil.c - various functions used by security stuff
+**
+*/
+
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+#include "prerror.h"
+#include "prprf.h"
+#include "plgetopt.h"
+
+#include "secutil.h"
+#include "secpkcs7.h"
+#include "secrng.h"
+#if !defined(_WIN32_WCE)
+#include <sys/stat.h>
+#endif
+#include <stdarg.h>
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+
+/* for SEC_TraverseNames */
+#include "cert.h"
+#include "certt.h"
+#include "certdb.h"
+
+typedef struct {
+ char * name;
+ CERTCertTrust trust;
+} certNameAndTrustEntry;
+
+typedef struct {
+ int numCerts;
+ certNameAndTrustEntry *nameAndTrustEntries;
+} certNameAndTrustList;
+
+SECStatus
+sec_CountCerts(CERTCertificate *cert, SECItem *unknown, void *arg)
+{
+ (*(int*)arg)++;
+ return SECSuccess;
+}
+
+SECStatus
+sec_CollectCertNamesAndTrust(CERTCertificate *cert, SECItem *unknown, void *arg)
+{
+ certNameAndTrustList *pCertNames = (certNameAndTrustList*)arg;
+ char *name;
+ int i;
+
+ i = pCertNames->numCerts;
+ name = cert->nickname ? cert->nickname : cert->emailAddr;
+
+ if (name)
+ pCertNames->nameAndTrustEntries[i].name = PORT_Strdup(name);
+ else
+ pCertNames->nameAndTrustEntries[i].name = PORT_Strdup("<unknown>");
+
+ PORT_Memcpy(&pCertNames->nameAndTrustEntries[i].trust, cert->trust, sizeof(*cert->trust));
+
+ pCertNames->numCerts++;
+
+ return SECSuccess;
+}
+
+
+static int
+sec_name_and_trust_compare_by_name(const void *p1, const void *p2)
+{
+ certNameAndTrustEntry *e1 = (certNameAndTrustEntry *)p1;
+ certNameAndTrustEntry *e2 = (certNameAndTrustEntry *)p2;
+ return PORT_Strcmp(e1->name, e2->name);
+}
+
+static int
+sec_combine_trust_flags(CERTCertTrust *trust)
+{
+ if (trust == NULL)
+ return 0;
+ return trust->sslFlags | trust->emailFlags | trust->objectSigningFlags;
+}
+
+static int
+sec_name_and_trust_compare_by_trust(const void *p1, const void *p2)
+{
+ certNameAndTrustEntry *e1 = (certNameAndTrustEntry *)p1;
+ certNameAndTrustEntry *e2 = (certNameAndTrustEntry *)p2;
+ int e1_is_ca, e2_is_ca;
+ int e1_is_user, e2_is_user;
+ int rv;
+
+ e1_is_ca = (sec_combine_trust_flags(&e1->trust) & CERTDB_VALID_CA) != 0;
+ e2_is_ca = (sec_combine_trust_flags(&e2->trust) & CERTDB_VALID_CA) != 0;
+ e1_is_user = (sec_combine_trust_flags(&e1->trust) & CERTDB_USER) != 0;
+ e2_is_user = (sec_combine_trust_flags(&e2->trust) & CERTDB_USER) != 0;
+
+ /* first, sort by user status, then CA status, */
+ /* then by actual comparison of CA flags, then by name */
+ if ((rv = (e2_is_user - e1_is_user)) == 0 && (rv = (e1_is_ca - e2_is_ca)) == 0)
+ if (e1_is_ca || (rv = memcmp(&e1->trust, &e2->trust, sizeof(CERTCertTrust))) == 0)
+ return PORT_Strcmp(e1->name, e2->name);
+ else
+ return rv;
+ else
+ return rv;
+}
+
+SECStatus
+SECU_PrintCertificateNames(CERTCertDBHandle *handle, PRFileDesc *out,
+ PRBool sortByName, PRBool sortByTrust)
+{
+ certNameAndTrustList certNames = { 0, NULL };
+ int numCerts, i;
+ SECStatus rv;
+ int (*comparefn)(const void *, const void *);
+ char trusts[30];
+
+ numCerts = 0;
+
+ rv = SEC_TraversePermCerts(handle, sec_CountCerts, &numCerts);
+ if (rv != SECSuccess)
+ return SECFailure;
+
+ certNames.nameAndTrustEntries =
+ (certNameAndTrustEntry *)PORT_Alloc(numCerts * sizeof(certNameAndTrustEntry));
+ if (certNames.nameAndTrustEntries == NULL)
+ return SECFailure;
+
+ rv = SEC_TraversePermCerts(handle, sec_CollectCertNamesAndTrust, &certNames);
+ if (rv != SECSuccess)
+ return SECFailure;
+
+ if (sortByName)
+ comparefn = sec_name_and_trust_compare_by_name;
+ else if (sortByTrust)
+ comparefn = sec_name_and_trust_compare_by_trust;
+ else
+ comparefn = NULL;
+
+ if (comparefn)
+ qsort(certNames.nameAndTrustEntries, certNames.numCerts,
+ sizeof(certNameAndTrustEntry), comparefn);
+
+ PR_fprintf(out, "\n%-60s %-5s\n\n", "Certificate Name", "Trust Attributes");
+ for (i = 0; i < certNames.numCerts; i++) {
+ PORT_Memset (trusts, 0, sizeof(trusts));
+ printflags(trusts, certNames.nameAndTrustEntries[i].trust.sslFlags);
+ PORT_Strcat(trusts, ",");
+ printflags(trusts, certNames.nameAndTrustEntries[i].trust.emailFlags);
+ PORT_Strcat(trusts, ",");
+ printflags(trusts, certNames.nameAndTrustEntries[i].trust.objectSigningFlags);
+ PR_fprintf(out, "%-60s %-5s\n",
+ certNames.nameAndTrustEntries[i].name, trusts);
+ }
+ PR_fprintf(out, "\n");
+ PR_fprintf(out, "p Valid peer\n");
+ PR_fprintf(out, "P Trusted peer (implies p)\n");
+ PR_fprintf(out, "c Valid CA\n");
+ PR_fprintf(out, "T Trusted CA to issue client certs (implies c)\n");
+ PR_fprintf(out, "C Trusted CA to certs(only server certs for ssl) (implies c)\n");
+ PR_fprintf(out, "u User cert\n");
+ PR_fprintf(out, "w Send warning\n");
+
+ for (i = 0; i < certNames.numCerts; i++)
+ PORT_Free(certNames.nameAndTrustEntries[i].name);
+ PORT_Free(certNames.nameAndTrustEntries);
+
+ return rv;
+}
diff --git a/security/nss/cmd/lib/secerror.c b/security/nss/cmd/lib/secerror.c
new file mode 100644
index 000000000..857704b79
--- /dev/null
+++ b/security/nss/cmd/lib/secerror.c
@@ -0,0 +1,107 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#include "nspr.h"
+
+struct tuple_str {
+ PRErrorCode errNum;
+ const char * errString;
+};
+
+typedef struct tuple_str tuple_str;
+
+#define ER2(a,b) {a, b},
+#define ER3(a,b,c) {a, c},
+
+#include "secerr.h"
+#include "sslerr.h"
+
+const tuple_str errStrings[] = {
+
+/* keep this list in asceding order of error numbers */
+#include "SSLerrs.h"
+#include "SECerrs.h"
+#include "NSPRerrs.h"
+
+};
+
+const PRInt32 numStrings = sizeof(errStrings) / sizeof(tuple_str);
+
+/* Returns a UTF-8 encoded constant error string for "errNum".
+ * Returns NULL of errNum is unknown.
+ */
+const char *
+SECU_Strerror(PRErrorCode errNum) {
+ PRInt32 low = 0;
+ PRInt32 high = numStrings - 1;
+ PRInt32 i;
+ PRErrorCode num;
+ static int initDone;
+
+ /* make sure table is in ascending order.
+ * binary search depends on it.
+ */
+ if (!initDone) {
+ PRErrorCode lastNum = ((PRInt32)0x80000000);
+ for (i = low; i <= high; ++i) {
+ num = errStrings[i].errNum;
+ if (num <= lastNum) {
+ fprintf(stderr,
+"sequence error in error strings at item %d\n"
+"error %d (%s)\n"
+"should come after \n"
+"error %d (%s)\n",
+ i, lastNum, errStrings[i-1].errString,
+ num, errStrings[i].errString);
+ }
+ lastNum = num;
+ }
+ initDone = 1;
+ }
+
+ /* Do binary search of table. */
+ while (low + 1 < high) {
+ i = (low + high) / 2;
+ num = errStrings[i].errNum;
+ if (errNum == num)
+ return errStrings[i].errString;
+ if (errNum < num)
+ high = i;
+ else
+ low = i;
+ }
+ if (errNum == errStrings[low].errNum)
+ return errStrings[low].errString;
+ if (errNum == errStrings[high].errNum)
+ return errStrings[high].errString;
+ return NULL;
+}
diff --git a/security/nss/cmd/lib/secpwd.c b/security/nss/cmd/lib/secpwd.c
new file mode 100644
index 000000000..9a505a720
--- /dev/null
+++ b/security/nss/cmd/lib/secpwd.c
@@ -0,0 +1,199 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#include "secutil.h"
+
+/*
+ * NOTE: The contents of this file are NOT used by the client.
+ * (They are part of the security library as a whole, but they are
+ * NOT USED BY THE CLIENT.) Do not change things on behalf of the
+ * client (like localizing strings), or add things that are only
+ * for the client (put them elsewhere).
+ */
+
+
+#ifdef XP_UNIX
+#include <termios.h>
+#include <unistd.h>
+#endif
+
+#if( defined(_WINDOWS) && !defined(_WIN32_WCE)) || defined(XP_OS2_VACPP)
+#include <conio.h>
+#include <io.h>
+#define QUIET_FGETS quiet_fgets
+static char * quiet_fgets (char *buf, int length, FILE *input);
+#else
+#define QUIET_FGETS fgets
+#endif
+
+static void echoOff(int fd)
+{
+#if defined(XP_UNIX) && !defined(VMS)
+ if (isatty(fd)) {
+ struct termios tio;
+ tcgetattr(fd, &tio);
+ tio.c_lflag &= ~ECHO;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+ }
+#endif
+}
+
+static void echoOn(int fd)
+{
+#if defined(XP_UNIX) && !defined(VMS)
+ if (isatty(fd)) {
+ struct termios tio;
+ tcgetattr(fd, &tio);
+ tio.c_lflag |= ECHO;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+ }
+#endif
+}
+
+char *SEC_GetPassword(FILE *input, FILE *output, char *prompt,
+ PRBool (*ok)(char *))
+{
+#if defined(_WINDOWS)
+ int isTTY = (input == stdin);
+#define echoOn(x)
+#define echoOff(x)
+#else
+ int infd = fileno(input);
+ int isTTY = isatty(infd);
+#endif
+ char phrase[200];
+
+ for (;;) {
+ /* Prompt for password */
+ if (isTTY) {
+ fprintf(output, "%s", prompt);
+ fflush (output);
+ echoOff(infd);
+ }
+
+ QUIET_FGETS ( phrase, sizeof(phrase), input);
+
+ if (isTTY) {
+ fprintf(output, "\n");
+ echoOn(infd);
+ }
+
+ /* stomp on newline */
+ phrase[PORT_Strlen(phrase)-1] = 0;
+
+ /* Validate password */
+ if (!(*ok)(phrase)) {
+ /* Not weird enough */
+ if (!isTTY) return 0;
+ fprintf(output, "Password must be at least 8 characters long with one or more\n");
+ fprintf(output, "non-alphabetic characters\n");
+ continue;
+ }
+ return (char*) PORT_Strdup(phrase);
+ }
+}
+
+
+
+PRBool SEC_CheckPassword(char *cp)
+{
+ int len;
+ char *end;
+
+ len = PORT_Strlen(cp);
+ if (len < 8) {
+ return PR_FALSE;
+ }
+ end = cp + len;
+ while (cp < end) {
+ unsigned char ch = *cp++;
+ if (!((ch >= 'A') && (ch <= 'Z')) &&
+ !((ch >= 'a') && (ch <= 'z'))) {
+ /* pass phrase has at least one non alphabetic in it */
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+PRBool SEC_BlindCheckPassword(char *cp)
+{
+ if (cp != NULL) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+/* Get a password from the input terminal, without echoing */
+
+#if defined(_WINDOWS) || defined(XP_OS2_VACPP)
+static char * quiet_fgets (char *buf, int length, FILE *input)
+ {
+ int c;
+ char *end = buf;
+
+ /* fflush (input); */
+ memset (buf, 0, length);
+
+#ifndef XP_OS2_VACPP
+ if (input != stdin) {
+ return fgets(buf,length,input);
+ }
+#else
+ if (!isatty(fileno(input))) {
+ return fgets(buf,length,input);
+ }
+#endif
+
+ while (1)
+ {
+#if defined (_WIN32_WCE)
+ c = getchar(); /* gets a character from stdin */
+#else
+ c = getch(); /* getch gets a character from the console */
+#endif
+ if (c == '\b')
+ {
+ if (end > buf)
+ end--;
+ }
+
+ else if (--length > 0)
+ *end++ = c;
+
+ if (!c || c == '\n' || c == '\r')
+ break;
+ }
+
+ return buf;
+ }
+#endif
diff --git a/security/nss/cmd/lib/secutil.c b/security/nss/cmd/lib/secutil.c
new file mode 100644
index 000000000..7e4570703
--- /dev/null
+++ b/security/nss/cmd/lib/secutil.c
@@ -0,0 +1,2622 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+/*
+** secutil.c - various functions used by security stuff
+**
+*/
+
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+#include "prerror.h"
+#include "prprf.h"
+#include "plgetopt.h"
+#include "prenv.h"
+
+#include "secutil.h"
+#include "secpkcs7.h"
+#include "secrng.h"
+#include <stdarg.h>
+#if !defined(_WIN32_WCE)
+#include <sys/stat.h>
+#include <errno.h>
+#endif
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+
+/* for SEC_TraverseNames */
+#include "cert.h"
+#include "certt.h"
+#include "certdb.h"
+
+/* #include "secmod.h" */
+#include "pk11func.h"
+#include "secoid.h"
+
+static char consoleName[] = {
+#ifdef XP_UNIX
+#ifdef VMS
+ "TT"
+#else
+ "/dev/tty"
+#endif
+#else
+#ifdef XP_OS2
+ "\\DEV\\CON"
+#else
+ "CON:"
+#endif
+#endif
+};
+
+char *
+SECU_GetString(int16 error_number)
+{
+
+ static char errString[80];
+ sprintf(errString, "Unknown error string (%d)", error_number);
+ return errString;
+}
+
+void
+SECU_PrintError(char *progName, char *msg, ...)
+{
+ va_list args;
+ PRErrorCode err = PORT_GetError();
+ const char * errString = SECU_Strerror(err);
+
+ va_start(args, msg);
+
+ fprintf(stderr, "%s: ", progName);
+ vfprintf(stderr, msg, args);
+ if (errString != NULL && PORT_Strlen(errString) > 0)
+ fprintf(stderr, ": %s\n", errString);
+ else
+ fprintf(stderr, ": error %d\n", (int)err);
+
+ va_end(args);
+}
+
+void
+SECU_PrintSystemError(char *progName, char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ fprintf(stderr, "%s: ", progName);
+ vfprintf(stderr, msg, args);
+#if defined(_WIN32_WCE)
+ fprintf(stderr, ": %d\n", PR_GetOSError());
+#else
+ fprintf(stderr, ": %s\n", strerror(errno));
+#endif
+ va_end(args);
+}
+
+static void
+secu_ClearPassword(char *p)
+{
+ if (p) {
+ PORT_Memset(p, 0, PORT_Strlen(p));
+ PORT_Free(p);
+ }
+}
+
+char *
+SECU_GetPasswordString(void *arg, char *prompt)
+{
+#ifndef _WINDOWS
+ char *p = NULL;
+ FILE *input, *output;
+
+ /* open terminal */
+ input = fopen(consoleName, "r");
+ if (input == NULL) {
+ fprintf(stderr, "Error opening input terminal for read\n");
+ return NULL;
+ }
+
+ output = fopen(consoleName, "w");
+ if (output == NULL) {
+ fprintf(stderr, "Error opening output terminal for write\n");
+ return NULL;
+ }
+
+ p = SEC_GetPassword (input, output, prompt, SEC_BlindCheckPassword);
+
+
+ fclose(input);
+ fclose(output);
+
+ return p;
+
+#else
+ /* Win32 version of above. opening the console may fail
+ on windows95, and certainly isn't necessary.. */
+
+ char *p = NULL;
+
+ p = SEC_GetPassword (stdin, stdout, prompt, SEC_BlindCheckPassword);
+ return p;
+
+#endif
+}
+
+
+/*
+ * p a s s w o r d _ h a r d c o d e
+ *
+ * A function to use the password passed in the -f(pwfile) argument
+ * of the command line.
+ * After use once, null it out otherwise PKCS11 calls us forever.?
+ *
+ */
+char *
+SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ unsigned char phrase[200];
+ PRFileDesc *fd;
+ PRInt32 nb;
+ char *pwFile = arg;
+ int i;
+
+ if (!pwFile)
+ return 0;
+
+ if (retry) {
+ return 0; /* no good retrying - the files contents will be the same */
+ }
+
+ fd = PR_Open(pwFile, PR_RDONLY, 0);
+ if (!fd) {
+ fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
+ return NULL;
+ }
+
+ nb = PR_Read(fd, phrase, sizeof(phrase));
+
+ PR_Close(fd);
+ /* handle the Windows EOL case */
+ i = 0;
+ while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb) i++;
+ phrase[i] = '\0';
+ if (nb == 0) {
+ fprintf(stderr,"password file contains no data\n");
+ return NULL;
+ }
+ return (char*) PORT_Strdup((char*)phrase);
+}
+
+char *
+SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char prompt[255];
+ secuPWData *pwdata = (secuPWData *)arg;
+ secuPWData pwnull = { PW_NONE, 0 };
+ char *pw;
+
+ if (pwdata == NULL)
+ pwdata = &pwnull;
+
+ if (retry && pwdata->source != PW_NONE) {
+ PR_fprintf(PR_STDERR, "incorrect password entered at command line.\n");
+ return NULL;
+ }
+
+ switch (pwdata->source) {
+ case PW_NONE:
+ sprintf(prompt, "Enter Password or Pin for \"%s\":",
+ PK11_GetTokenName(slot));
+ return SECU_GetPasswordString(NULL, prompt);
+ case PW_FROMFILE:
+ /* Instead of opening and closing the file every time, get the pw
+ * once, then keep it in memory (duh).
+ */
+ pw = SECU_FilePasswd(slot, retry, pwdata->data);
+ pwdata->source = PW_PLAINTEXT;
+ pwdata->data = PL_strdup(pw);
+ /* it's already been dup'ed */
+ return pw;
+ case PW_PLAINTEXT:
+ return PL_strdup(pwdata->data);
+ default:
+ break;
+ }
+
+ PR_fprintf(PR_STDERR, "Password check failed: No password found.\n");
+ return NULL;
+}
+
+char *
+secu_InitSlotPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *p0 = NULL;
+ char *p1 = NULL;
+ FILE *input, *output;
+ secuPWData *pwdata = arg;
+
+ if (pwdata->source == PW_FROMFILE) {
+ return SECU_FilePasswd(slot, retry, pwdata->data);
+ }
+ if (pwdata->source == PW_PLAINTEXT) {
+ return PL_strdup(pwdata->data);
+ }
+
+ /* PW_NONE - get it from tty */
+ /* open terminal */
+#ifdef _WINDOWS
+ input = stdin;
+#else
+ input = fopen(consoleName, "r");
+#endif
+ if (input == NULL) {
+ PR_fprintf(PR_STDERR, "Error opening input terminal for read\n");
+ return NULL;
+ }
+
+ /* we have no password, so initialize database with one */
+ PR_fprintf(PR_STDERR,
+ "Enter a password which will be used to encrypt your keys.\n"
+ "The password should be at least 8 characters long,\n"
+ "and should contain at least one non-alphabetic character.\n\n");
+
+ output = fopen(consoleName, "w");
+ if (output == NULL) {
+ PR_fprintf(PR_STDERR, "Error opening output terminal for write\n");
+ return NULL;
+ }
+
+
+ for (;;) {
+ if (p0)
+ PORT_Free(p0);
+ p0 = SEC_GetPassword(input, output, "Enter new password: ",
+ SEC_BlindCheckPassword);
+
+ if (p1)
+ PORT_Free(p1);
+ p1 = SEC_GetPassword(input, output, "Re-enter password: ",
+ SEC_BlindCheckPassword);
+ if (p0 && p1 && !PORT_Strcmp(p0, p1)) {
+ break;
+ }
+ PR_fprintf(PR_STDERR, "Passwords do not match. Try again.\n");
+ }
+
+ /* clear out the duplicate password string */
+ secu_ClearPassword(p1);
+
+ fclose(input);
+ fclose(output);
+
+ return p0;
+}
+
+SECStatus
+SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile)
+{
+ SECStatus rv;
+ secuPWData pwdata, newpwdata;
+ char *oldpw = NULL, *newpw = NULL;
+
+ if (passwd) {
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = passwd;
+ } else if (pwFile) {
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = pwFile;
+ } else {
+ pwdata.source = PW_NONE;
+ pwdata.data = NULL;
+ }
+
+ if (PK11_NeedUserInit(slot)) {
+ newpw = secu_InitSlotPassword(slot, PR_FALSE, &pwdata);
+ rv = PK11_InitPin(slot, (char*)NULL, newpw);
+ goto done;
+ }
+
+ for (;;) {
+ oldpw = SECU_GetModulePassword(slot, PR_FALSE, &pwdata);
+
+ if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
+ if (pwdata.source == PW_NONE) {
+ PR_fprintf(PR_STDERR, "Invalid password. Try again.\n");
+ } else {
+ PR_fprintf(PR_STDERR, "Invalid password.\n");
+ PORT_Memset(oldpw, 0, PL_strlen(oldpw));
+ PORT_Free(oldpw);
+ return SECFailure;
+ }
+ } else
+ break;
+
+ PORT_Free(oldpw);
+ }
+
+ newpwdata.source = PW_NONE;
+ newpwdata.data = NULL;
+
+ newpw = secu_InitSlotPassword(slot, PR_FALSE, &newpwdata);
+
+ if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
+ PR_fprintf(PR_STDERR, "Failed to change password.\n");
+ return SECFailure;
+ }
+
+ PORT_Memset(oldpw, 0, PL_strlen(oldpw));
+ PORT_Free(oldpw);
+
+ PR_fprintf(PR_STDOUT, "Password changed successfully.\n");
+
+done:
+ PORT_Memset(newpw, 0, PL_strlen(newpw));
+ PORT_Free(newpw);
+ return SECSuccess;
+}
+
+struct matchobj {
+ SECItem index;
+ char *nname;
+ PRBool found;
+};
+
+char *
+SECU_DefaultSSLDir(void)
+{
+ char *dir;
+ static char sslDir[1000];
+
+ dir = PR_GetEnv("SSL_DIR");
+ if (!dir)
+ return NULL;
+
+ sprintf(sslDir, "%s", dir);
+
+ if (sslDir[strlen(sslDir)-1] == '/')
+ sslDir[strlen(sslDir)-1] = 0;
+
+ return sslDir;
+}
+
+char *
+SECU_AppendFilenameToDir(char *dir, char *filename)
+{
+ static char path[1000];
+
+ if (dir[strlen(dir)-1] == '/')
+ sprintf(path, "%s%s", dir, filename);
+ else
+ sprintf(path, "%s/%s", dir, filename);
+ return path;
+}
+
+char *
+SECU_ConfigDirectory(const char* base)
+{
+ static PRBool initted = PR_FALSE;
+ const char *dir = ".netscape";
+ char *home;
+ static char buf[1000];
+
+ if (initted) return buf;
+
+
+ if (base == NULL || *base == 0) {
+ home = PR_GetEnv("HOME");
+ if (!home) home = "";
+
+ if (*home && home[strlen(home) - 1] == '/')
+ sprintf (buf, "%.900s%s", home, dir);
+ else
+ sprintf (buf, "%.900s/%s", home, dir);
+ } else {
+ sprintf(buf, "%.900s", base);
+ if (buf[strlen(buf) - 1] == '/')
+ buf[strlen(buf) - 1] = 0;
+ }
+
+
+ initted = PR_TRUE;
+ return buf;
+}
+
+/*Turn off SSL for now */
+/* This gets called by SSL when server wants our cert & key */
+int
+SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+ SECKEYPrivateKey *key;
+ CERTCertificate *cert;
+ int errsave;
+
+ if (arg == NULL) {
+ fprintf(stderr, "no key/cert name specified for client auth\n");
+ return -1;
+ }
+ cert = PK11_FindCertFromNickname(arg, NULL);
+ errsave = PORT_GetError();
+ if (!cert) {
+ if (errsave == SEC_ERROR_BAD_PASSWORD)
+ fprintf(stderr, "Bad password\n");
+ else if (errsave > 0)
+ fprintf(stderr, "Unable to read cert (error %d)\n", errsave);
+ else if (errsave == SEC_ERROR_BAD_DATABASE)
+ fprintf(stderr, "Unable to get cert from database (%d)\n", errsave);
+ else
+ fprintf(stderr, "SECKEY_FindKeyByName: internal error %d\n", errsave);
+ return -1;
+ }
+
+ key = PK11_FindKeyByAnyCert(arg,NULL);
+ if (!key) {
+ fprintf(stderr, "Unable to get key (%d)\n", PORT_GetError());
+ return -1;
+ }
+
+
+ *pRetCert = cert;
+ *pRetKey = key;
+
+ return 0;
+}
+
+SECStatus
+secu_StdinToItem(SECItem *dst)
+{
+ unsigned char buf[1000];
+ PRInt32 numBytes;
+ PRBool notDone = PR_TRUE;
+
+ dst->len = 0;
+ dst->data = NULL;
+
+ while (notDone) {
+ numBytes = PR_Read(PR_STDIN, buf, sizeof(buf));
+
+ if (numBytes < 0) {
+ PORT_SetError(PR_IO_ERROR);
+ return SECFailure;
+ }
+
+ if (numBytes == 0)
+ break;
+
+ if (buf[numBytes-1] == '\n') {
+ buf[numBytes-1] = '\0';
+ notDone = PR_FALSE;
+ }
+
+ if (dst->data) {
+ dst->data = (unsigned char*)PORT_Realloc(dst->data,
+ dst->len+numBytes);
+ PORT_Memcpy(dst->data+dst->len, buf, numBytes);
+ } else {
+ dst->data = (unsigned char*)PORT_Alloc(numBytes);
+ PORT_Memcpy(dst->data, buf, numBytes);
+ }
+ dst->len += numBytes;
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+SECU_FileToItem(SECItem *dst, PRFileDesc *src)
+{
+ PRFileInfo info;
+ PRInt32 numBytes;
+ PRStatus prStatus;
+
+ if (src == PR_STDIN)
+ return secu_StdinToItem(dst);
+
+ prStatus = PR_GetOpenFileInfo(src, &info);
+
+ if (prStatus != PR_SUCCESS) {
+ PORT_SetError(SEC_ERROR_IO);
+ return SECFailure;
+ }
+
+ /* XXX workaround for 3.1, not all utils zero dst before sending */
+ dst->data = 0;
+ if (!SECITEM_AllocItem(NULL, dst, info.size))
+ goto loser;
+
+ numBytes = PR_Read(src, dst->data, info.size);
+ if (numBytes != info.size) {
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
+ }
+
+ return SECSuccess;
+loser:
+ SECITEM_FreeItem(dst, PR_FALSE);
+ return SECFailure;
+}
+
+SECStatus
+SECU_TextFileToItem(SECItem *dst, PRFileDesc *src)
+{
+ PRFileInfo info;
+ PRInt32 numBytes;
+ PRStatus prStatus;
+ unsigned char *buf;
+
+ if (src == PR_STDIN)
+ return secu_StdinToItem(dst);
+
+ prStatus = PR_GetOpenFileInfo(src, &info);
+
+ if (prStatus != PR_SUCCESS) {
+ PORT_SetError(SEC_ERROR_IO);
+ return SECFailure;
+ }
+
+ buf = (unsigned char*)PORT_Alloc(info.size);
+ if (!buf)
+ return SECFailure;
+
+ numBytes = PR_Read(src, buf, info.size);
+ if (numBytes != info.size) {
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
+ }
+
+ if (buf[numBytes-1] == '\n') numBytes--;
+#ifdef _WINDOWS
+ if (buf[numBytes-1] == '\r') numBytes--;
+#endif
+
+ /* XXX workaround for 3.1, not all utils zero dst before sending */
+ dst->data = 0;
+ if (!SECITEM_AllocItem(NULL, dst, numBytes))
+ goto loser;
+
+ memcpy(dst->data, buf, numBytes);
+
+ PORT_Free(buf);
+ return SECSuccess;
+loser:
+ PORT_Free(buf);
+ return SECFailure;
+}
+
+SECStatus
+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii)
+{
+ SECStatus rv;
+ char *asc, *body, *trailer;
+ if (ascii) {
+ /* First convert ascii to binary */
+ SECItem filedata;
+
+ /* Read in ascii data */
+ rv = SECU_FileToItem(&filedata, inFile);
+ asc = (char *)filedata.data;
+ if (!asc) {
+ fprintf(stderr, "unable to read data from input file\n");
+ return SECFailure;
+ }
+
+ /* check for headers and trailers and remove them */
+ if ((body = strstr(asc, "-----BEGIN")) != NULL) {
+ body = PORT_Strchr(body, '\n') + 1;
+ trailer = strstr(body, "-----END");
+ if (trailer != NULL) {
+ *trailer = '\0';
+ } else {
+ fprintf(stderr, "input has header but no trailer\n");
+ return SECFailure;
+ }
+ } else {
+ body = asc;
+ }
+
+ /* Convert to binary */
+ rv = ATOB_ConvertAsciiToItem(der, body);
+ if (rv) {
+ fprintf(stderr, "error converting ascii to binary (%s)\n",
+ SECU_Strerror(PORT_GetError()));
+ return SECFailure;
+ }
+ PORT_Free(asc);
+ } else {
+ /* Read in binary der */
+ rv = SECU_FileToItem(der, inFile);
+ if (rv) {
+ fprintf(stderr, "error converting der (%s)\n",
+ SECU_Strerror(PORT_GetError()));
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+}
+
+#define INDENT_MULT 4
+void
+SECU_Indent(FILE *out, int level)
+{
+ int i;
+ for (i = 0; i < level; i++) {
+ fprintf(out, " ");
+ }
+}
+
+static void secu_Newline(FILE *out)
+{
+ fprintf(out, "\n");
+}
+
+void
+SECU_PrintAsHex(FILE *out, SECItem *data, const char *m, int level)
+{
+ unsigned i;
+ int column;
+ PRBool isString = PR_TRUE;
+
+ if ( m ) {
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ level++;
+ }
+
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ for (i = 0; i < data->len; i++) {
+ unsigned char val = data->data[i];
+
+ if (isString && val && !isprint(val)) {
+ isString = PR_FALSE;
+ }
+ if (i != data->len - 1) {
+ fprintf(out, "%02x:", data->data[i]);
+ column += 3;
+ } else {
+ fprintf(out, "%02x", data->data[i]);
+ column += 2;
+ break;
+ }
+ if (column > 76 || (i % 16 == 15)) {
+ secu_Newline(out);
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ }
+ }
+ if (isString) {
+ secu_Newline(out);
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ for (i = 0; i < data->len; i++) {
+ unsigned char val = data->data[i];
+
+ if (val) {
+ fprintf(out,"%c",val);
+ column++;
+ } else {
+ column = 77;
+ }
+ if (column > 76) {
+ secu_Newline(out);
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ }
+ }
+ }
+
+ level--;
+ if (column != level*INDENT_MULT) {
+ secu_Newline(out);
+ }
+}
+
+static const char *hex = "0123456789abcdef";
+
+static const char printable[257] = {
+ "................" /* 0x */
+ "................" /* 1x */
+ " !\"#$%&'()*+,-./" /* 2x */
+ "0123456789:;<=>?" /* 3x */
+ "@ABCDEFGHIJKLMNO" /* 4x */
+ "PQRSTUVWXYZ[\\]^_" /* 5x */
+ "`abcdefghijklmno" /* 6x */
+ "pqrstuvwxyz{|}~." /* 7x */
+ "................" /* 8x */
+ "................" /* 9x */
+ "................" /* ax */
+ "................" /* bx */
+ "................" /* cx */
+ "................" /* dx */
+ "................" /* ex */
+ "................" /* fx */
+};
+
+void
+SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len)
+{
+ const unsigned char *cp = (const unsigned char *)vp;
+ char buf[80];
+ char *bp;
+ char *ap;
+
+ fprintf(out, "%s [Len: %d]\n", msg, len);
+ memset(buf, ' ', sizeof buf);
+ bp = buf;
+ ap = buf + 50;
+ while (--len >= 0) {
+ unsigned char ch = *cp++;
+ *bp++ = hex[(ch >> 4) & 0xf];
+ *bp++ = hex[ch & 0xf];
+ *bp++ = ' ';
+ *ap++ = printable[ch];
+ if (ap - buf >= 66) {
+ *ap = 0;
+ fprintf(out, " %s\n", buf);
+ memset(buf, ' ', sizeof buf);
+ bp = buf;
+ ap = buf + 50;
+ }
+ }
+ if (bp > buf) {
+ *ap = 0;
+ fprintf(out, " %s\n", buf);
+ }
+}
+
+void
+SECU_PrintInteger(FILE *out, SECItem *i, char *m, int level)
+{
+ int iv;
+
+ if (!i || !i->len || !i->data) {
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: (null)\n", m);
+ } else {
+ fprintf(out, "(null)\n");
+ }
+ } else if (i->len > 4) {
+ SECU_PrintAsHex(out, i, m, level);
+ } else {
+ iv = DER_GetInteger(i);
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: %d (0x%x)\n", m, iv, iv);
+ } else {
+ fprintf(out, "%d (0x%x)\n", iv, iv);
+ }
+ }
+}
+
+void
+SECU_PrintString(FILE *out, SECItem *i, char *m, int level)
+{
+ char *string;
+ unsigned char *data = i->data;
+ int len = i->len;
+ int lenlen;
+ int tag;
+
+ string = PORT_ZAlloc(i->len+1);
+
+ tag = *data++; len--;
+ if (data[1] & 0x80) {
+ lenlen = data[1] & 0x1f;
+ } else {
+ lenlen = 1;
+ }
+ data += lenlen; len -= lenlen;
+ if (len <= 0) return;
+ PORT_Memcpy(string,data,len);
+
+ /* should check the validity of tag, and convert the string as necessary */
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: \"%s\"\n", m, string);
+ } else {
+ fprintf(out, "\"%s\"\n", string);
+ }
+}
+
+static void
+secu_PrintBoolean(FILE *out, SECItem *i, char *m, int level)
+{
+ int val = 0;
+
+ if ( i->data ) {
+ val = i->data[0];
+ }
+
+ if (m) {
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m); level++;
+ }
+ if ( val ) {
+ SECU_Indent(out, level); fprintf(out, "%s\n", "True");
+ } else {
+ SECU_Indent(out, level); fprintf(out, "%s\n", "False");
+ }
+}
+
+/*
+ * Format and print "time". If the tag message "m" is not NULL,
+ * do indent formatting based on "level" and add a newline afterward;
+ * otherwise just print the formatted time string only.
+ */
+static void
+secu_PrintTime(FILE *out, int64 time, char *m, int level)
+{
+ PRExplodedTime printableTime;
+ char *timeString;
+
+ /* Convert to local time */
+ PR_ExplodeTime(time, PR_GMTParameters, &printableTime);
+
+ timeString = PORT_Alloc(100);
+ if (timeString == NULL)
+ return;
+
+ if (m != NULL) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: ", m);
+ }
+
+ PR_FormatTime(timeString, 100, "%a %b %d %H:%M:%S %Y", &printableTime);
+ fprintf(out, timeString);
+
+ if (m != NULL)
+ fprintf(out, "\n");
+
+ PORT_Free(timeString);
+}
+
+/*
+ * Format and print the UTC Time "t". If the tag message "m" is not NULL,
+ * do indent formatting based on "level" and add a newline afterward;
+ * otherwise just print the formatted time string only.
+ */
+void
+SECU_PrintUTCTime(FILE *out, SECItem *t, char *m, int level)
+{
+ int64 time;
+ SECStatus rv;
+
+ rv = DER_UTCTimeToTime(&time, t);
+ if (rv != SECSuccess)
+ return;
+
+ secu_PrintTime(out, time, m, level);
+}
+
+/*
+ * Format and print the Generalized Time "t". If the tag message "m"
+ * is not NULL, * do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+void
+SECU_PrintGeneralizedTime(FILE *out, SECItem *t, char *m, int level)
+{
+ int64 time;
+ SECStatus rv;
+
+
+ rv = DER_GeneralizedTimeToTime(&time, t);
+ if (rv != SECSuccess)
+ return;
+
+ secu_PrintTime(out, time, m, level);
+}
+
+static void secu_PrintAny(FILE *out, SECItem *i, char *m, int level);
+
+void
+SECU_PrintSet(FILE *out, SECItem *t, char *m, int level)
+{
+ int type= t->data[0] & SEC_ASN1_TAGNUM_MASK;
+ int start;
+ unsigned char *bp;
+
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: ", m);
+ }
+
+ fprintf(out,"%s {\n", type == SEC_ASN1_SET ? "Set" : "Sequence"); /* } */
+
+ start = 2;
+ if (t->data[1] & 0x80) {
+ start += (t->data[1] & 0x7f);
+ }
+ for (bp=&t->data[start]; bp < &t->data[t->len]; ) {
+ SECItem tmp;
+ unsigned int i,len,lenlen;
+
+ if (bp[1] & 0x80) {
+ lenlen = bp[1] & 0x1f;
+ len = 0;
+ for (i=0; i < lenlen; i++) {
+ len = len * 255 + bp[2+i];
+ }
+ } else {
+ lenlen = 1;
+ len = bp[1];
+ }
+ tmp.len = len+lenlen+1;
+ if (tmp.len > &t->data[t->len] - bp) {
+ tmp.len = &t->data[t->len] - bp;
+ }
+ tmp.data = bp;
+ bp += tmp.len;
+ secu_PrintAny(out,&tmp,NULL,level+1);
+ }
+ /* { */SECU_Indent(out, level); fprintf(out, "}\n");
+}
+
+static void
+secu_PrintContextSpecific(FILE *out, SECItem *i, char *m, int level)
+{
+ int type= i->data[0] & SEC_ASN1_TAGNUM_MASK;
+ SECItem tmp;
+ int start;
+
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: ", m);
+ }
+
+ fprintf(out,"[%d]\n", type);
+ start = 2;
+ if (i->data[1] & 0x80) {
+ start = (i->data[1] & 0x7f) +1;
+ }
+ tmp.data = &i->data[start];
+ tmp.len = i->len -start;
+ SECU_PrintAsHex(out, &tmp, m, level+1);
+}
+
+static void
+secu_PrintOctetString(FILE *out, SECItem *i, char *m, int level)
+{
+ SECItem tmp;
+ int start;
+
+ start = 2;
+ if (i->data[1] & 0x80) {
+ start = (i->data[1] & 0x7f) +1;
+ }
+ tmp.data = &i->data[start];
+ tmp.len = i->len - start;
+ SECU_PrintAsHex(out, &tmp, m, level);
+}
+
+static void
+secu_PrintBitString(FILE *out, SECItem *i, char *m, int level)
+{
+ SECItem tmp;
+ int start;
+ int unused_bits;
+
+ start = 2;
+ if (i->data[1] & 0x80) {
+ start = (i->data[1] & 0x7f) + 1;
+ }
+ unused_bits = i->data[start++];
+ tmp.data = &i->data[start];
+ tmp.len = i->len - start;
+ SECU_PrintAsHex(out, &tmp, m, level);
+ if (unused_bits) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "(%d least significant bits unused)\n", unused_bits);
+ }
+}
+
+static void
+secu_PrintUniversal(FILE *out, SECItem *i, char *m, int level)
+{
+ switch (i->data[0] & SEC_ASN1_TAGNUM_MASK) {
+ case SEC_ASN1_INTEGER:
+ SECU_PrintInteger(out, i, m, level);
+ break;
+ case SEC_ASN1_OBJECT_ID:
+ SECU_PrintObjectID(out, i, m, level);
+ break;
+ case SEC_ASN1_BOOLEAN:
+ secu_PrintBoolean(out, i, m, level);
+ break;
+ case SEC_ASN1_UTF8_STRING:
+ case SEC_ASN1_PRINTABLE_STRING:
+ case SEC_ASN1_VISIBLE_STRING:
+ case SEC_ASN1_BMP_STRING:
+ case SEC_ASN1_IA5_STRING:
+ case SEC_ASN1_T61_STRING:
+ case SEC_ASN1_UNIVERSAL_STRING:
+ SECU_PrintString(out, i, m, level);
+ break;
+ case SEC_ASN1_GENERALIZED_TIME:
+ SECU_PrintGeneralizedTime(out, i, m, level);
+ break;
+ case SEC_ASN1_UTC_TIME:
+ SECU_PrintUTCTime(out, i, m, level);
+ break;
+ case SEC_ASN1_NULL:
+ SECU_Indent(out, level); fprintf(out, "%s: NULL\n", m);
+ break;
+ case SEC_ASN1_SET:
+ case SEC_ASN1_SEQUENCE:
+ SECU_PrintSet(out, i, m, level);
+ break;
+ case SEC_ASN1_OCTET_STRING:
+ secu_PrintOctetString(out, i, m, level);
+ break;
+ case SEC_ASN1_BIT_STRING:
+ secu_PrintBitString(out, i, m, level);
+ break;
+ default:
+ SECU_PrintAsHex(out, i, m, level);
+ break;
+ }
+}
+
+static void
+secu_PrintAny(FILE *out, SECItem *i, char *m, int level)
+{
+ if ( i && i->len && i->data ) {
+ switch (i->data[0] & SEC_ASN1_CLASS_MASK) {
+ case SEC_ASN1_CONTEXT_SPECIFIC:
+ secu_PrintContextSpecific(out, i, m, level);
+ break;
+ case SEC_ASN1_UNIVERSAL:
+ secu_PrintUniversal(out, i, m, level);
+ break;
+ default:
+ SECU_PrintAsHex(out, i, m, level);
+ break;
+ }
+ }
+}
+
+static int
+secu_PrintValidity(FILE *out, CERTValidity *v, char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintUTCTime(out, &v->notBefore, "Not Before", level+1);
+ SECU_PrintUTCTime(out, &v->notAfter, "Not After", level+1);
+ return 0;
+}
+
+void
+SECU_PrintObjectID(FILE *out, SECItem *oid, char *m, int level)
+{
+ const char *name;
+ SECOidData *oiddata;
+
+ oiddata = SECOID_FindOID(oid);
+ if (oiddata == NULL) {
+ SECU_PrintAsHex(out, oid, m, level);
+ return;
+ }
+ name = oiddata->desc;
+
+ SECU_Indent(out, level);
+ if (m != NULL)
+ fprintf(out, "%s: ", m);
+ fprintf(out, "%s\n", name);
+}
+
+void
+SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m, int level)
+{
+ SECU_PrintObjectID(out, &a->algorithm, m, level);
+
+ if (a->parameters.len == 0
+ || (a->parameters.len == 2
+ && PORT_Memcmp(a->parameters.data, "\005\000", 2) == 0)) {
+ /* No arguments or NULL argument */
+ } else {
+ /* Print args to algorithm */
+ SECU_PrintAsHex(out, &a->parameters, "Args", level+1);
+ }
+}
+
+static void
+secu_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m, int level)
+{
+ SECItem *value;
+ int i;
+ char om[100];
+
+ if (m) {
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ }
+
+ /*
+ * Should make this smarter; look at the type field and then decode
+ * and print the value(s) appropriately!
+ */
+ SECU_PrintObjectID(out, &(attr->type), "Type", level+1);
+ if (attr->values != NULL) {
+ i = 0;
+ while ((value = attr->values[i++]) != NULL) {
+ sprintf(om, "Value (%d)%s", i, attr->encoded ? " (encoded)" : "");
+ if (attr->encoded || attr->typeTag == NULL) {
+ SECU_PrintAsHex(out, value, om, level+1);
+ } else {
+ switch (attr->typeTag->offset) {
+ default:
+ SECU_PrintAsHex(out, value, om, level+1);
+ break;
+ case SEC_OID_PKCS9_CONTENT_TYPE:
+ SECU_PrintObjectID(out, value, om, level+1);
+ break;
+ case SEC_OID_PKCS9_SIGNING_TIME:
+ SECU_PrintUTCTime(out, value, om, level+1);
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void
+secu_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
+{
+#if 0 /*
+ * um, yeah, that might be nice, but if you look at the callers
+ * you will see that they do not *set* this, so this will not work!
+ * Instead, somebody needs to fix the callers to be smarter about
+ * public key stuff, if that is important.
+ */
+ PORT_Assert(pk->keyType == rsaKey);
+#endif
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &pk->u.rsa.modulus, "Modulus", level+1);
+ SECU_PrintInteger(out, &pk->u.rsa.publicExponent, "Exponent", level+1);
+}
+
+static void
+secu_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &pk->u.dsa.params.prime, "Prime", level+1);
+ SECU_PrintInteger(out, &pk->u.dsa.params.subPrime, "Subprime", level+1);
+ SECU_PrintInteger(out, &pk->u.dsa.params.base, "Base", level+1);
+ SECU_PrintInteger(out, &pk->u.dsa.publicValue, "PublicValue", level+1);
+}
+
+static int
+secu_PrintSubjectPublicKeyInfo(FILE *out, PRArenaPool *arena,
+ CERTSubjectPublicKeyInfo *i, char *msg, int level)
+{
+ SECKEYPublicKey *pk;
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", msg);
+ SECU_PrintAlgorithmID(out, &i->algorithm, "Public Key Algorithm", level+1);
+
+ pk = SECKEY_ExtractPublicKey(i);
+ if (pk) {
+ switch (pk->keyType) {
+ case rsaKey:
+ secu_PrintRSAPublicKey(out, pk, "RSA Public Key", level +1);
+ break;
+
+ case dsaKey:
+ secu_PrintDSAPublicKey(out, pk, "DSA Public Key", level +1);
+ break;
+
+ case dhKey:
+ case fortezzaKey:
+ case keaKey:
+ case ecKey:
+ fprintf(out, "unable to format this SPKI algorithm type\n");
+ break;
+ default:
+ fprintf(out, "unknown SPKI algorithm type\n");
+ break;
+ }
+ PORT_FreeArena(pk->arena, PR_FALSE);
+ } else {
+ SECU_PrintError("Error", "Parsing public key");
+ }
+
+ return 0;
+}
+
+static SECStatus
+secu_PrintX509InvalidDate(FILE *out, SECItem *value, char *msg, int level)
+{
+ SECItem decodedValue;
+ SECStatus rv;
+ int64 invalidTime;
+ char *formattedTime = NULL;
+
+ decodedValue.data = NULL;
+ rv = SEC_ASN1DecodeItem (NULL, &decodedValue,
+ SEC_ASN1_GET(SEC_GeneralizedTimeTemplate),
+ value);
+ if (rv == SECSuccess) {
+ rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
+ if (rv == SECSuccess) {
+ formattedTime = CERT_GenTime2FormattedAscii
+ (invalidTime, "%a %b %d %H:%M:%S %Y");
+ SECU_Indent(out, level +1);
+ fprintf (out, "%s: %s\n", msg, formattedTime);
+ PORT_Free (formattedTime);
+ }
+ }
+ PORT_Free (decodedValue.data);
+ return (rv);
+}
+
+static SECStatus
+PrintExtKeyUsageExten (FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTOidSequence *os;
+ SECItem **op;
+
+ SECU_Indent(out, level); fprintf(out, "Extended Key Usage Extension:\n");
+
+ os = CERT_DecodeOidSequence(value);
+ if( (CERTOidSequence *)NULL == os ) {
+ return SECFailure;
+ }
+
+ for( op = os->oids; *op; op++ ) {
+ SECOidData *od = SECOID_FindOID(*op);
+
+ if( (SECOidData *)NULL == od ) {
+ SECU_Indent(out, level+1);
+ SECU_PrintAsHex(out, *op, "Unknown:", level+2);
+ secu_Newline(out);
+ continue;
+ }
+
+ SECU_Indent(out, level+1);
+ if( od->desc ) fprintf(out, "%s", od->desc);
+ else SECU_PrintAsHex(out, &od->oid, "", level+2);
+
+ secu_Newline(out);
+ }
+
+ return SECSuccess;
+}
+
+char *
+itemToString(SECItem *item)
+{
+ char *string;
+
+ string = PORT_ZAlloc(item->len+1);
+ if (string == NULL) return NULL;
+ PORT_Memcpy(string,item->data,item->len);
+ string[item->len] = 0;
+ return string;
+}
+
+static SECStatus
+secu_PrintPolicyQualifier(FILE *out,CERTPolicyQualifier *policyQualifier,char *msg,int level)
+{
+ CERTUserNotice *userNotice;
+ SECItem **itemList = NULL;
+ char *string;
+
+ SECU_PrintObjectID(out, &policyQualifier->qualifierID ,
+ "Policy Qualifier Name", level);
+
+ switch (policyQualifier->oid) {
+ case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
+ userNotice = CERT_DecodeUserNotice(&policyQualifier->qualifierValue);
+ if (userNotice) {
+ if (userNotice->noticeReference.organization.len != 0) {
+ string=itemToString(&userNotice->noticeReference.organization);
+ itemList = userNotice->noticeReference.noticeNumbers;
+ while (*itemList) {
+ SECU_PrintInteger(out,*itemList,string,level+1);
+ itemList++;
+ }
+ PORT_Free(string);
+ }
+ if (userNotice->displayText.len != 0) {
+ SECU_PrintString(out,&userNotice->displayText,
+ "Display Text", level+1);
+ }
+ break;
+ }
+ /* fall through on error */
+ case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
+ default:
+ secu_PrintAny(out, &policyQualifier->qualifierValue, "Policy Qualifier Data", level+1);
+ break;
+ }
+
+ return SECSuccess;
+
+}
+
+static SECStatus
+secu_PrintPolicyInfo(FILE *out,CERTPolicyInfo *policyInfo,char *msg,int level)
+{
+ CERTPolicyQualifier **policyQualifiers;
+
+ policyQualifiers = policyInfo->policyQualifiers;
+ SECU_PrintObjectID(out, &policyInfo->policyID , "Policy Name", level);
+
+ while (*policyQualifiers != NULL) {
+ secu_PrintPolicyQualifier(out,*policyQualifiers,"",level+1);
+ policyQualifiers++;
+ }
+ return SECSuccess;
+
+}
+
+static SECStatus
+secu_PrintPolicy(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTCertificatePolicies *policies = NULL;
+ CERTPolicyInfo **policyInfos;
+
+ if (msg) {
+ SECU_Indent(out, level);
+ fprintf(out,"%s: \n",msg);
+ level++;
+ }
+ policies = CERT_DecodeCertificatePoliciesExtension(value);
+ if (policies == NULL) {
+ SECU_PrintAsHex(out, value, "Invalid Policy Data", level);
+ return SECFailure;
+ }
+
+ policyInfos = policies->policyInfos;
+ while (*policyInfos != NULL) {
+ secu_PrintPolicyInfo(out,*policyInfos,"",level);
+ policyInfos++;
+ }
+
+ CERT_DestroyCertificatePoliciesExtension(policies);
+ return SECSuccess;
+}
+
+char *nsTypeBits[] = {
+"SSL Client","SSL Server","S/MIME","Object Signing","Reserved","SSL CA","S/MIME CA","ObjectSigning CA" };
+
+static SECStatus
+secu_PrintBasicConstraints(FILE *out, SECItem *value, char *msg, int level) {
+ CERTBasicConstraints constraints;
+ SECStatus rv;
+
+ SECU_Indent(out, level);
+ if (msg) {
+ fprintf(out,"%s: ",msg);
+ }
+ rv = CERT_DecodeBasicConstraintValue(&constraints,value);
+ if (rv == SECSuccess && constraints.isCA) {
+ fprintf(out,"Is a CA with a maximum path length of %d.\n",
+ constraints.pathLenConstraint);
+ } else {
+ fprintf(out,"Is not a CA.\n");
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level) {
+ char NS_Type=0;
+ int len, i, found=0;
+
+ if (value->data[1] & 0x80) {
+ len = 3;
+ } else {
+ len = value->data[1];
+ }
+ if ((value->data[0] != SEC_ASN1_BIT_STRING) || (len < 2)) {
+ secu_PrintAny(out, value, "Data", level);
+ return SECSuccess;
+ }
+ NS_Type=value->data[3];
+
+
+ if (msg) {
+ SECU_Indent(out, level);
+ fprintf(out,"%s: ",msg);
+ } else {
+ SECU_Indent(out, level);
+ fprintf(out,"Netscape Certificate Type: ");
+ }
+ for (i=0; i < 8; i++) {
+ if ( (0x80 >> i) & NS_Type) {
+ fprintf(out,"%c%s",found?',':'<',nsTypeBits[i]);
+ found = 1;
+ }
+ }
+ if (found) { fprintf(out,">\n"); } else { fprintf(out,"none\n"); }
+ return SECSuccess;
+}
+
+void
+SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
+ char *msg, int level)
+{
+ SECOidTag oidTag;
+
+ if ( extensions ) {
+ SECU_Indent(out, level); fprintf(out, "%s:\n", msg);
+
+ while ( *extensions ) {
+ SECItem *tmpitem;
+ SECU_Indent(out, level+1); fprintf(out, "Name:\n");
+
+ tmpitem = &(*extensions)->id;
+ SECU_PrintObjectID(out, tmpitem, NULL, level+2);
+
+ tmpitem = &(*extensions)->critical;
+ if ( tmpitem->len ) {
+ secu_PrintBoolean(out, tmpitem, "Critical", level+1);
+ }
+
+ oidTag = SECOID_FindOIDTag (&((*extensions)->id));
+ tmpitem = &((*extensions)->value);
+
+ switch (oidTag) {
+ case SEC_OID_X509_INVALID_DATE:
+ case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
+ secu_PrintX509InvalidDate(out, tmpitem, "Date", level + 1);
+ break;
+ case SEC_OID_X509_CERTIFICATE_POLICIES:
+ secu_PrintPolicy(out, tmpitem, "Data", level +1);
+ break;
+ case SEC_OID_NS_CERT_EXT_BASE_URL:
+ case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
+ case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
+ case SEC_OID_NS_CERT_EXT_CA_CRL_URL:
+ case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
+ case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
+ case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
+ case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
+ case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
+ case SEC_OID_OCSP_RESPONDER:
+ SECU_PrintString(out,tmpitem, "URL", level+1);
+ break;
+ case SEC_OID_NS_CERT_EXT_COMMENT:
+ SECU_PrintString(out,tmpitem, "Comment", level+1);
+ break;
+ case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
+ SECU_PrintString(out,tmpitem, "ServerName", level+1);
+ break;
+ case SEC_OID_NS_CERT_EXT_CERT_TYPE:
+ secu_PrintNSCertType(out,tmpitem,"Data",level+1);
+ break;
+ case SEC_OID_X509_BASIC_CONSTRAINTS:
+ secu_PrintBasicConstraints(out,tmpitem,"Data",level+1);
+ break;
+
+ case SEC_OID_X509_SUBJECT_ALT_NAME:
+ case SEC_OID_X509_ISSUER_ALT_NAME:
+ /*
+ * We should add at least some of the more interesting cases
+ * here, but need to have subroutines to back them up.
+ */
+ case SEC_OID_NS_CERT_EXT_NETSCAPE_OK:
+ case SEC_OID_NS_CERT_EXT_ISSUER_LOGO:
+ case SEC_OID_NS_CERT_EXT_SUBJECT_LOGO:
+ case SEC_OID_NS_CERT_EXT_ENTITY_LOGO:
+ case SEC_OID_NS_CERT_EXT_USER_PICTURE:
+ case SEC_OID_NS_KEY_USAGE_GOVT_APPROVED:
+
+ /* x.509 v3 Extensions */
+ case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
+ case SEC_OID_X509_SUBJECT_KEY_ID:
+ case SEC_OID_X509_KEY_USAGE:
+ case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD:
+ case SEC_OID_X509_NAME_CONSTRAINTS:
+ case SEC_OID_X509_CRL_DIST_POINTS:
+ case SEC_OID_X509_POLICY_MAPPINGS:
+ case SEC_OID_X509_POLICY_CONSTRAINTS:
+ case SEC_OID_X509_AUTH_KEY_ID:
+ goto defualt;
+
+ case SEC_OID_X509_EXT_KEY_USAGE:
+ PrintExtKeyUsageExten(out, tmpitem, "", level+1);
+ break;
+
+ case SEC_OID_X509_AUTH_INFO_ACCESS:
+ case SEC_OID_X509_CRL_NUMBER:
+ case SEC_OID_X509_REASON_CODE:
+
+ /* PKIX OIDs */
+ case SEC_OID_PKIX_OCSP:
+ case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
+ case SEC_OID_PKIX_OCSP_NONCE:
+ case SEC_OID_PKIX_OCSP_CRL:
+ case SEC_OID_PKIX_OCSP_RESPONSE:
+ case SEC_OID_PKIX_OCSP_NO_CHECK:
+ case SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF:
+ case SEC_OID_PKIX_OCSP_SERVICE_LOCATOR:
+ case SEC_OID_PKIX_REGCTRL_REGTOKEN:
+ case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
+ case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
+ case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
+ case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
+ case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
+ case SEC_OID_PKIX_REGINFO_UTF8_PAIRS:
+ case SEC_OID_PKIX_REGINFO_CERT_REQUEST:
+ case SEC_OID_EXT_KEY_USAGE_SERVER_AUTH:
+ case SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH:
+ case SEC_OID_EXT_KEY_USAGE_CODE_SIGN:
+ case SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT:
+ case SEC_OID_EXT_KEY_USAGE_TIME_STAMP:
+
+ default:
+ defualt:
+ secu_PrintAny(out, tmpitem, "Data", level+1);
+ break;
+ }
+
+ secu_Newline(out);
+ extensions++;
+ }
+ }
+}
+
+
+void
+SECU_PrintName(FILE *out, CERTName *name, char *msg, int level)
+{
+ char *str;
+
+ SECU_Indent(out, level); fprintf(out, "%s: ", msg);
+
+ str = CERT_NameToAscii(name);
+ if (!str)
+ str = "!Invalid AVA!";
+ fprintf(out, str);
+
+ secu_Newline(out);
+}
+
+void
+printflags(char *trusts, unsigned int flags)
+{
+ if (flags & CERTDB_VALID_CA)
+ if (!(flags & CERTDB_TRUSTED_CA) &&
+ !(flags & CERTDB_TRUSTED_CLIENT_CA))
+ PORT_Strcat(trusts, "c");
+ if (flags & CERTDB_VALID_PEER)
+ if (!(flags & CERTDB_TRUSTED))
+ PORT_Strcat(trusts, "p");
+ if (flags & CERTDB_TRUSTED_CA)
+ PORT_Strcat(trusts, "C");
+ if (flags & CERTDB_TRUSTED_CLIENT_CA)
+ PORT_Strcat(trusts, "T");
+ if (flags & CERTDB_TRUSTED)
+ PORT_Strcat(trusts, "P");
+ if (flags & CERTDB_USER)
+ PORT_Strcat(trusts, "u");
+ if (flags & CERTDB_SEND_WARN)
+ PORT_Strcat(trusts, "w");
+ if (flags & CERTDB_INVISIBLE_CA)
+ PORT_Strcat(trusts, "I");
+ if (flags & CERTDB_GOVT_APPROVED_CA)
+ PORT_Strcat(trusts, "G");
+ return;
+}
+
+/* callback for listing certs through pkcs11 */
+SECStatus
+SECU_PrintCertNickname(CERTCertificate *cert, void *data)
+{
+ CERTCertTrust *trust;
+ FILE *out;
+ char trusts[30];
+ char *name;
+
+ PORT_Memset (trusts, 0, sizeof (trusts));
+ out = (FILE *)data;
+
+ name = cert->nickname;
+ if ( name == NULL ) {
+ name = cert->emailAddr;
+ }
+ if ( name == NULL ) {
+ name = "(NULL)";
+ }
+
+ trust = cert->trust;
+ if (trust) {
+ printflags(trusts, trust->sslFlags);
+ PORT_Strcat(trusts, ",");
+ printflags(trusts, trust->emailFlags);
+ PORT_Strcat(trusts, ",");
+ printflags(trusts, trust->objectSigningFlags);
+ } else {
+ PORT_Memcpy(trusts,",,",3);
+ }
+ fprintf(out, "%-60s %-5s\n", name, trusts);
+
+ return (SECSuccess);
+}
+
+int /* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
+SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m, int level)
+{
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCertificateRequest *cr;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ /* Decode certificate request */
+ cr = PORT_ArenaZNew(arena, CERTCertificateRequest);
+ if (!cr)
+ goto loser;
+ cr->arena = arena;
+ rv = SEC_QuickDERDecodeItem(arena, cr,
+ SEC_ASN1_GET(CERT_CertificateRequestTemplate), der);
+ if (rv)
+ goto loser;
+
+ /* Pretty print it out */
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &cr->version, "Version", level+1);
+ SECU_PrintName(out, &cr->subject, "Subject", level+1);
+ rv = secu_PrintSubjectPublicKeyInfo(out, arena, &cr->subjectPublicKeyInfo,
+ "Subject Public Key Info", level+1);
+ if (rv)
+ goto loser;
+ if (cr->attributes)
+ secu_PrintAny(out, cr->attributes[0], "Attributes", level+1);
+
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+int
+SECU_PrintCertificate(FILE *out, SECItem *der, char *m, int level)
+{
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCertificate *c;
+ int rv = SEC_ERROR_NO_MEMORY;
+ int iv;
+
+ if (!arena)
+ return rv;
+
+ /* Decode certificate */
+ c = PORT_ArenaZNew(arena, CERTCertificate);
+ if (!c)
+ goto loser;
+ c->arena = arena;
+ rv = SEC_ASN1DecodeItem(arena, c,
+ SEC_ASN1_GET(CERT_CertificateTemplate), der);
+ if (rv)
+ goto loser;
+
+ /* Pretty print it out */
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ iv = c->version.len ? DER_GetInteger(&c->version) : 0; /* version is optional */
+ SECU_Indent(out, level+1); fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
+
+ SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level+1);
+ SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level+1);
+ SECU_PrintName(out, &c->issuer, "Issuer", level+1);
+ secu_PrintValidity(out, &c->validity, "Validity", level+1);
+ SECU_PrintName(out, &c->subject, "Subject", level+1);
+ rv = secu_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo,
+ "Subject Public Key Info", level+1);
+ if (rv)
+ goto loser;
+ SECU_PrintExtensions(out, c->extensions, "Signed Extensions", level+1);
+ SECU_PrintFingerprints(out, &c->derCert, "Fingerprint", level);
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+int
+SECU_PrintPublicKey(FILE *out, SECItem *der, char *m, int level)
+{
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECKEYPublicKey key;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ PORT_Memset(&key, 0, sizeof(key));
+ rv = SEC_ASN1DecodeItem(arena, &key,
+ SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate), der);
+ if (!rv) {
+ /* Pretty print it out */
+ secu_PrintRSAPublicKey(out, &key, m, level);
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+#ifdef HAVE_EPV_TEMPLATE
+int
+SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level)
+{
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECKEYEncryptedPrivateKeyInfo key;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ PORT_Memset(&key, 0, sizeof(key));
+ rv = SEC_ASN1DecodeItem(arena, &key,
+ SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), der);
+ if (rv)
+ goto loser;
+
+ /* Pretty print it out */
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintAlgorithmID(out, &key.algorithm, "Encryption Algorithm",
+ level+1);
+ SECU_PrintAsHex(out, &key.encryptedData, "Encrypted Data", level+1);
+loser:
+ PORT_FreeArena(arena, PR_TRUE);
+ return rv;
+}
+#endif
+
+int
+SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
+{
+ unsigned char fingerprint[20];
+ char *fpStr = NULL;
+ SECItem fpItem;
+ /* print MD5 fingerprint */
+ memset(fingerprint, 0, sizeof fingerprint);
+ PK11_HashBuf(SEC_OID_MD5,fingerprint, derCert->data, derCert->len);
+ fpItem.data = fingerprint;
+ fpItem.len = MD5_LENGTH;
+ fpStr = CERT_Hexify(&fpItem, 1);
+ SECU_Indent(out, level); fprintf(out, "%s (MD5):\n", m);
+ SECU_Indent(out, level+1); fprintf(out, "%s\n", fpStr);
+ PORT_Free(fpStr);
+ fpStr = NULL;
+ /* print SHA1 fingerprint */
+ memset(fingerprint, 0, sizeof fingerprint);
+ PK11_HashBuf(SEC_OID_SHA1,fingerprint, derCert->data, derCert->len);
+ fpItem.data = fingerprint;
+ fpItem.len = SHA1_LENGTH;
+ fpStr = CERT_Hexify(&fpItem, 1);
+ SECU_Indent(out, level); fprintf(out, "%s (SHA1):\n", m);
+ SECU_Indent(out, level+1); fprintf(out, "%s\n", fpStr);
+ PORT_Free(fpStr);
+ fprintf(out, "\n");
+ return 0;
+}
+
+/*
+** PKCS7 Support
+*/
+
+/* forward declaration */
+static int
+secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *, int);
+
+/*
+** secu_PrintPKCS7EncContent
+** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
+*/
+static void
+secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
+ char *m, int level)
+{
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Content Type: %s\n",
+ (src->contentTypeTag != NULL) ? src->contentTypeTag->desc
+ : "Unknown");
+ SECU_PrintAlgorithmID(out, &(src->contentEncAlg),
+ "Content Encryption Algorithm", level+1);
+ SECU_PrintAsHex(out, &(src->encContent),
+ "Encrypted Content", level+1);
+}
+
+/*
+** secu_PrintRecipientInfo
+** Prints a PKCS7RecipientInfo type
+*/
+static void
+secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
+ int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(info->version), "Version", level + 1);
+
+ SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
+ level + 1);
+ SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "Serial Number", level + 1);
+
+ /* Parse and display encrypted key */
+ SECU_PrintAlgorithmID(out, &(info->keyEncAlg),
+ "Key Encryption Algorithm", level + 1);
+ SECU_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
+}
+
+/*
+** secu_PrintSignerInfo
+** Prints a PKCS7SingerInfo type
+*/
+static void
+secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m, int level)
+{
+ SEC_PKCS7Attribute *attr;
+ int iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(info->version), "Version", level + 1);
+
+ SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
+ level + 1);
+ SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "Serial Number", level + 1);
+
+ SECU_PrintAlgorithmID(out, &(info->digestAlg), "Digest Algorithm",
+ level + 1);
+
+ if (info->authAttr != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Authenticated Attributes:\n");
+ iv = 0;
+ while ((attr = info->authAttr[iv++]) != NULL) {
+ sprintf(om, "Attribute (%d)", iv);
+ secu_PrintAttribute(out, attr, om, level + 2);
+ }
+ }
+
+ /* Parse and display signature */
+ SECU_PrintAlgorithmID(out, &(info->digestEncAlg),
+ "Digest Encryption Algorithm", level + 1);
+ SECU_PrintAsHex(out, &(info->encDigest), "Encrypted Digest", level + 1);
+
+ if (info->unAuthAttr != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Unauthenticated Attributes:\n");
+ iv = 0;
+ while ((attr = info->unAuthAttr[iv++]) != NULL) {
+ sprintf(om, "Attribute (%x)", iv);
+ secu_PrintAttribute(out, attr, om, level + 2);
+ }
+ }
+}
+
+/* callers of this function must make sure that the CERTSignedCrl
+ from which they are extracting the CERTCrl has been fully-decoded.
+ Otherwise it will not have the entries even though the CRL may have
+ some */
+
+void
+SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level)
+{
+ CERTCrlEntry *entry;
+ int iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintAlgorithmID(out, &(crl->signatureAlg), "Signature Algorithm",
+ level + 1);
+ SECU_PrintName(out, &(crl->name), "Name", level + 1);
+ SECU_PrintUTCTime(out, &(crl->lastUpdate), "Last Update", level + 1);
+ SECU_PrintUTCTime(out, &(crl->nextUpdate), "Next Update", level + 1);
+
+ if (crl->entries != NULL) {
+ iv = 0;
+ while ((entry = crl->entries[iv++]) != NULL) {
+ sprintf(om, "Entry (%x):\n", iv);
+ SECU_Indent(out, level + 1); fprintf(out, om);
+ SECU_PrintInteger(out, &(entry->serialNumber), "Serial Number",
+ level + 2);
+ SECU_PrintUTCTime(out, &(entry->revocationDate), "Revocation Date",
+ level + 2);
+ SECU_PrintExtensions
+ (out, entry->extensions, "Signed CRL Entries Extensions", level + 1);
+ }
+ }
+ SECU_PrintExtensions
+ (out, crl->extensions, "Signed CRL Extension", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Signed
+** Pretty print a PKCS7 signed data type (up to version 1).
+*/
+static int
+secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
+ const char *m, int level)
+{
+ SECAlgorithmID *digAlg; /* digest algorithms */
+ SECItem *aCert; /* certificate */
+ CERTSignedCrl *aCrl; /* certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* signer information */
+ int rv, iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ SECU_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
+ sprintf(om, "Digest Algorithm (%x)", iv);
+ SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
+ }
+ }
+
+ /* Now for the content */
+ rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
+ "Content Information", level + 1);
+ if (rv != 0)
+ return rv;
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ SECU_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
+ iv = 0;
+ while ((aCert = src->rawCerts[iv++]) != NULL) {
+ sprintf(om, "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ SECU_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signed Revocation Lists:\n");
+ iv = 0;
+ while ((aCrl = src->crls[iv++]) != NULL) {
+ sprintf(om, "Signed Revocation List (%x)", iv);
+ SECU_Indent(out, level + 2); fprintf(out, "%s:\n", om);
+ SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "Signature Algorithm", level+3);
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
+ level+3);
+ SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
+ level + 3);
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signer Information List:\n");
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv++]) != NULL) {
+ sprintf(om, "Signer Information (%x)", iv);
+ secu_PrintSignerInfo(out, sigInfo, om, level + 2);
+ }
+ }
+
+ return 0;
+}
+
+/*
+** secu_PrintPKCS7Enveloped
+** Pretty print a PKCS7 enveloped data type (up to version 1).
+*/
+static void
+secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
+ const char *m, int level)
+{
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
+ int iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ sprintf(om, "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7SignedEnveloped
+** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
+*/
+static int
+secu_PrintPKCS7SignedAndEnveloped(FILE *out,
+ SEC_PKCS7SignedAndEnvelopedData *src,
+ const char *m, int level)
+{
+ SECAlgorithmID *digAlg; /* pointer for digest algorithms */
+ SECItem *aCert; /* pointer for certificate */
+ CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
+ int rv, iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ sprintf(om, "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ SECU_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
+ sprintf(om, "Digest Algorithm (%x)", iv);
+ SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ SECU_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
+ iv = 0;
+ while ((aCert = src->rawCerts[iv++]) != NULL) {
+ sprintf(om, "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ SECU_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signed Revocation Lists:\n");
+ iv = 0;
+ while ((aCrl = src->crls[iv++]) != NULL) {
+ sprintf(om, "Signed Revocation List (%x)", iv);
+ SECU_Indent(out, level + 2); fprintf(out, "%s:\n", om);
+ SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "Signature Algorithm", level+3);
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
+ level+3);
+ SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
+ level + 3);
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signer Information List:\n");
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv++]) != NULL) {
+ sprintf(om, "Signer Information (%x)", iv);
+ secu_PrintSignerInfo(out, sigInfo, om, level + 2);
+ }
+ }
+
+ return 0;
+}
+
+int
+SECU_PrintCrl (FILE *out, SECItem *der, char *m, int level)
+{
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCrl *c = NULL;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+ do {
+ /* Decode CRL */
+ c = PORT_ArenaZNew(arena, CERTCrl);
+ if (!c)
+ break;
+
+ rv = SEC_ASN1DecodeItem(arena, c, SEC_ASN1_GET(CERT_CrlTemplate), der);
+ if (rv != SECSuccess)
+ break;
+ SECU_PrintCRLInfo (out, c, m, level);
+ } while (0);
+ PORT_FreeArena (arena, PR_FALSE);
+ return rv;
+}
+
+
+/*
+** secu_PrintPKCS7Encrypted
+** Pretty print a PKCS7 encrypted data type (up to version 1).
+*/
+static void
+secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
+ const char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Digested
+** Pretty print a PKCS7 digested data type (up to version 1).
+*/
+static void
+secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
+ const char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ SECU_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm",
+ level + 1);
+ secu_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
+ level + 1);
+ SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
+}
+
+/*
+** secu_PrintPKCS7ContentInfo
+** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
+** appropriate function
+*/
+static int
+secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
+ char *m, int level)
+{
+ const char *desc;
+ SECOidTag kind;
+ int rv;
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ level++;
+
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ if (src->contentTypeTag == NULL) {
+ desc = "Unknown";
+ kind = SEC_OID_PKCS7_DATA;
+ } else {
+ desc = src->contentTypeTag->desc;
+ kind = src->contentTypeTag->offset;
+ }
+
+ if (src->content.data == NULL) {
+ SECU_Indent(out, level); fprintf(out, "%s:\n", desc);
+ level++;
+ SECU_Indent(out, level); fprintf(out, "<no content>\n");
+ return 0;
+ }
+
+ rv = 0;
+ switch (kind) {
+ case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
+ rv = secu_PrintPKCS7Signed(out, src->content.signedData, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
+ secu_PrintPKCS7Enveloped(out, src->content.envelopedData, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
+ rv = secu_PrintPKCS7SignedAndEnveloped(out,
+ src->content.signedAndEnvelopedData,
+ desc, level);
+ break;
+
+ case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
+ secu_PrintPKCS7Digested(out, src->content.digestedData, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
+ secu_PrintPKCS7Encrypted(out, src->content.encryptedData, desc, level);
+ break;
+
+ default:
+ SECU_PrintAsHex(out, src->content.data, desc, level);
+ break;
+ }
+
+ return rv;
+}
+
+/*
+** SECU_PrintPKCS7ContentInfo
+** Decode and print any major PKCS7 data type (up to version 1).
+*/
+int
+SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
+{
+ SEC_PKCS7ContentInfo *cinfo;
+ int rv;
+
+ cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (cinfo != NULL) {
+ /* Send it to recursive parsing and printing module */
+ rv = secu_PrintPKCS7ContentInfo(out, cinfo, m, level);
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ } else {
+ rv = -1;
+ }
+
+ return rv;
+}
+
+/*
+** End of PKCS7 functions
+*/
+
+void
+printFlags(FILE *out, unsigned int flags, int level)
+{
+ if ( flags & CERTDB_VALID_PEER ) {
+ SECU_Indent(out, level); fprintf(out, "Valid Peer\n");
+ }
+ if ( flags & CERTDB_TRUSTED ) {
+ SECU_Indent(out, level); fprintf(out, "Trusted\n");
+ }
+ if ( flags & CERTDB_SEND_WARN ) {
+ SECU_Indent(out, level); fprintf(out, "Warn When Sending\n");
+ }
+ if ( flags & CERTDB_VALID_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Valid CA\n");
+ }
+ if ( flags & CERTDB_TRUSTED_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Trusted CA\n");
+ }
+ if ( flags & CERTDB_NS_TRUSTED_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Netscape Trusted CA\n");
+ }
+ if ( flags & CERTDB_USER ) {
+ SECU_Indent(out, level); fprintf(out, "User\n");
+ }
+ if ( flags & CERTDB_TRUSTED_CLIENT_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Trusted Client CA\n");
+ }
+#ifdef DEBUG
+ if ( flags & CERTDB_GOVT_APPROVED_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Step-up\n");
+ }
+#endif /* DEBUG */
+}
+
+void
+SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_Indent(out, level+1); fprintf(out, "SSL Flags:\n");
+ printFlags(out, trust->sslFlags, level+2);
+ SECU_Indent(out, level+1); fprintf(out, "Email Flags:\n");
+ printFlags(out, trust->emailFlags, level+2);
+ SECU_Indent(out, level+1); fprintf(out, "Object Signing Flags:\n");
+ printFlags(out, trust->objectSigningFlags, level+2);
+}
+
+int SECU_PrintSignedData(FILE *out, SECItem *der, char *m,
+ int level, SECU_PPFunc inner)
+{
+ PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTSignedData *sd;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ /* Strip off the signature */
+ sd = PORT_ArenaZNew(arena, CERTSignedData);
+ if (!sd)
+ goto loser;
+
+ rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate),
+ der);
+ if (rv)
+ goto loser;
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ rv = (*inner)(out, &sd->data, "Data", level+1);
+ if (rv)
+ goto loser;
+
+ SECU_PrintAlgorithmID(out, &sd->signatureAlgorithm, "Signature Algorithm",
+ level+1);
+ DER_ConvertBitString(&sd->signature);
+ SECU_PrintAsHex(out, &sd->signature, "Signature", level+1);
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+
+}
+
+
+#ifdef AIX
+int _OS_SELECT (int nfds, void *readfds, void *writefds,
+ void *exceptfds, struct timeval *timeout) {
+ return select (nfds,readfds,writefds,exceptfds,timeout);
+}
+#endif
+
+SECItem *
+SECU_GetPBEPassword(void *arg)
+{
+ char *p = NULL;
+ SECItem *pwitem = NULL;
+
+ p = SECU_GetPasswordString(arg,"Password: ");
+
+ /* NOTE: This function is obviously unfinished. */
+
+ if ( pwitem == NULL ) {
+ fprintf(stderr, "Error hashing password\n");
+ return NULL;
+ }
+
+ return pwitem;
+}
+
+SECStatus
+SECU_ParseCommandLine(int argc, char **argv, char *progName, secuCommand *cmd)
+{
+ PRBool found;
+ PLOptState *optstate;
+ PLOptStatus status;
+ char *optstring;
+ int i, j;
+
+ optstring = (char *)malloc(cmd->numCommands + 2*cmd->numOptions);
+ j = 0;
+
+ for (i=0; i<cmd->numCommands; i++) {
+ optstring[j++] = cmd->commands[i].flag;
+ }
+ for (i=0; i<cmd->numOptions; i++) {
+ optstring[j++] = cmd->options[i].flag;
+ if (cmd->options[i].needsArg)
+ optstring[j++] = ':';
+ }
+ optstring[j] = '\0';
+ optstate = PL_CreateOptState(argc, argv, optstring);
+
+ /* Parse command line arguments */
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+
+ /* Wasn't really an option, just standalone arg. */
+ if (optstate->option == '\0')
+ continue;
+
+ found = PR_FALSE;
+
+ for (i=0; i<cmd->numCommands; i++) {
+ if (cmd->commands[i].flag == optstate->option) {
+ cmd->commands[i].activated = PR_TRUE;
+ if (optstate->value) {
+ cmd->commands[i].arg = (char *)optstate->value;
+ }
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ for (i=0; i<cmd->numOptions; i++) {
+ if (cmd->options[i].flag == optstate->option) {
+ cmd->options[i].activated = PR_TRUE;
+ if (optstate->value) {
+ cmd->options[i].arg = (char *)optstate->value;
+ }
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ return SECFailure;
+ }
+ if (status == PL_OPT_BAD)
+ return SECFailure;
+ return SECSuccess;
+}
+
+char *
+SECU_GetOptionArg(secuCommand *cmd, int optionNum)
+{
+ if (optionNum < 0 || optionNum >= cmd->numOptions)
+ return NULL;
+ if (cmd->options[optionNum].activated)
+ return PL_strdup(cmd->options[optionNum].arg);
+ else
+ return NULL;
+}
+
+static char SECUErrorBuf[64];
+
+char *
+SECU_ErrorStringRaw(int16 err)
+{
+ if (err == 0)
+ sprintf(SECUErrorBuf, "");
+ else if (err == SEC_ERROR_BAD_DATA)
+ sprintf(SECUErrorBuf, "Bad data");
+ else if (err == SEC_ERROR_BAD_DATABASE)
+ sprintf(SECUErrorBuf, "Problem with database");
+ else if (err == SEC_ERROR_BAD_DER)
+ sprintf(SECUErrorBuf, "Problem with DER");
+ else if (err == SEC_ERROR_BAD_KEY)
+ sprintf(SECUErrorBuf, "Problem with key");
+ else if (err == SEC_ERROR_BAD_PASSWORD)
+ sprintf(SECUErrorBuf, "Incorrect password");
+ else if (err == SEC_ERROR_BAD_SIGNATURE)
+ sprintf(SECUErrorBuf, "Bad signature");
+ else if (err == SEC_ERROR_EXPIRED_CERTIFICATE)
+ sprintf(SECUErrorBuf, "Expired certificate");
+ else if (err == SEC_ERROR_EXTENSION_VALUE_INVALID)
+ sprintf(SECUErrorBuf, "Invalid extension value");
+ else if (err == SEC_ERROR_INPUT_LEN)
+ sprintf(SECUErrorBuf, "Problem with input length");
+ else if (err == SEC_ERROR_INVALID_ALGORITHM)
+ sprintf(SECUErrorBuf, "Invalid algorithm");
+ else if (err == SEC_ERROR_INVALID_ARGS)
+ sprintf(SECUErrorBuf, "Invalid arguments");
+ else if (err == SEC_ERROR_INVALID_AVA)
+ sprintf(SECUErrorBuf, "Invalid AVA");
+ else if (err == SEC_ERROR_INVALID_TIME)
+ sprintf(SECUErrorBuf, "Invalid time");
+ else if (err == SEC_ERROR_IO)
+ sprintf(SECUErrorBuf, "Security I/O error");
+ else if (err == SEC_ERROR_LIBRARY_FAILURE)
+ sprintf(SECUErrorBuf, "Library failure");
+ else if (err == SEC_ERROR_NO_MEMORY)
+ sprintf(SECUErrorBuf, "Out of memory");
+ else if (err == SEC_ERROR_OLD_CRL)
+ sprintf(SECUErrorBuf, "CRL is older than the current one");
+ else if (err == SEC_ERROR_OUTPUT_LEN)
+ sprintf(SECUErrorBuf, "Problem with output length");
+ else if (err == SEC_ERROR_UNKNOWN_ISSUER)
+ sprintf(SECUErrorBuf, "Unknown issuer");
+ else if (err == SEC_ERROR_UNTRUSTED_CERT)
+ sprintf(SECUErrorBuf, "Untrusted certificate");
+ else if (err == SEC_ERROR_UNTRUSTED_ISSUER)
+ sprintf(SECUErrorBuf, "Untrusted issuer");
+ else if (err == SSL_ERROR_BAD_CERTIFICATE)
+ sprintf(SECUErrorBuf, "Bad certificate");
+ else if (err == SSL_ERROR_BAD_CLIENT)
+ sprintf(SECUErrorBuf, "Bad client");
+ else if (err == SSL_ERROR_BAD_SERVER)
+ sprintf(SECUErrorBuf, "Bad server");
+ else if (err == SSL_ERROR_EXPORT_ONLY_SERVER)
+ sprintf(SECUErrorBuf, "Export only server");
+ else if (err == SSL_ERROR_NO_CERTIFICATE)
+ sprintf(SECUErrorBuf, "No certificate");
+ else if (err == SSL_ERROR_NO_CYPHER_OVERLAP)
+ sprintf(SECUErrorBuf, "No cypher overlap");
+ else if (err == SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE)
+ sprintf(SECUErrorBuf, "Unsupported certificate type");
+ else if (err == SSL_ERROR_UNSUPPORTED_VERSION)
+ sprintf(SECUErrorBuf, "Unsupported version");
+ else if (err == SSL_ERROR_US_ONLY_SERVER)
+ sprintf(SECUErrorBuf, "U.S. only server");
+ else if (err == PR_IO_ERROR)
+ sprintf(SECUErrorBuf, "I/O error");
+
+ else if (err == SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE)
+ sprintf (SECUErrorBuf, "Expired Issuer Certificate");
+ else if (err == SEC_ERROR_REVOKED_CERTIFICATE)
+ sprintf (SECUErrorBuf, "Revoked certificate");
+ else if (err == SEC_ERROR_NO_KEY)
+ sprintf (SECUErrorBuf, "No private key in database for this cert");
+ else if (err == SEC_ERROR_CERT_NOT_VALID)
+ sprintf (SECUErrorBuf, "Certificate is not valid");
+ else if (err == SEC_ERROR_EXTENSION_NOT_FOUND)
+ sprintf (SECUErrorBuf, "Certificate extension was not found");
+ else if (err == SEC_ERROR_EXTENSION_VALUE_INVALID)
+ sprintf (SECUErrorBuf, "Certificate extension value invalid");
+ else if (err == SEC_ERROR_CA_CERT_INVALID)
+ sprintf (SECUErrorBuf, "Issuer certificate is invalid");
+ else if (err == SEC_ERROR_CERT_USAGES_INVALID)
+ sprintf (SECUErrorBuf, "Certificate usages is invalid");
+ else if (err == SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION)
+ sprintf (SECUErrorBuf, "Certificate has unknown critical extension");
+ else if (err == SEC_ERROR_PKCS7_BAD_SIGNATURE)
+ sprintf (SECUErrorBuf, "Bad PKCS7 signature");
+ else if (err == SEC_ERROR_INADEQUATE_KEY_USAGE)
+ sprintf (SECUErrorBuf, "Certificate not approved for this operation");
+ else if (err == SEC_ERROR_INADEQUATE_CERT_TYPE)
+ sprintf (SECUErrorBuf, "Certificate not approved for this operation");
+
+ return SECUErrorBuf;
+}
+
+char *
+SECU_ErrorString(int16 err)
+{
+ char *error_string;
+
+ *SECUErrorBuf = 0;
+ SECU_ErrorStringRaw (err);
+
+ if (*SECUErrorBuf == 0) {
+ error_string = SECU_GetString(err);
+ if (error_string == NULL || *error_string == '\0')
+ sprintf(SECUErrorBuf, "No error string found for %d.", err);
+ else
+ return error_string;
+ }
+
+ return SECUErrorBuf;
+}
+
+
+void
+SECU_PrintPRandOSError(char *progName)
+{
+ char buffer[513];
+ PRInt32 errLen = PR_GetErrorTextLength();
+ if (errLen > 0 && errLen < sizeof buffer) {
+ PR_GetErrorText(buffer);
+ }
+ SECU_PrintError(progName, "NSS_Initialize failed");
+ if (errLen > 0 && errLen < sizeof buffer) {
+ PR_fprintf(PR_STDERR, "\t%s\n", buffer);
+ }
+}
diff --git a/security/nss/cmd/lib/secutil.h b/security/nss/cmd/lib/secutil.h
new file mode 100644
index 000000000..69d9865d3
--- /dev/null
+++ b/security/nss/cmd/lib/secutil.h
@@ -0,0 +1,327 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#ifndef _SEC_UTIL_H_
+#define _SEC_UTIL_H_
+
+#include "seccomon.h"
+#include "secitem.h"
+#include "prerror.h"
+#include "base64.h"
+#include "key.h"
+#include "secpkcs7.h"
+#include "secasn1.h"
+#include "secder.h"
+#include <stdio.h>
+
+#define SEC_CT_PRIVATE_KEY "private-key"
+#define SEC_CT_PUBLIC_KEY "public-key"
+#define SEC_CT_CERTIFICATE "certificate"
+#define SEC_CT_CERTIFICATE_REQUEST "certificate-request"
+#define SEC_CT_PKCS7 "pkcs7"
+#define SEC_CT_CRL "crl"
+
+#define NS_CERTREQ_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----"
+#define NS_CERTREQ_TRAILER "-----END NEW CERTIFICATE REQUEST-----"
+
+#define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----"
+#define NS_CERT_TRAILER "-----END CERTIFICATE-----"
+
+/* From libsec/pcertdb.c --- it's not declared in sec.h */
+extern SECStatus SEC_AddPermCertificate(CERTCertDBHandle *handle,
+ SECItem *derCert, char *nickname, CERTCertTrust *trust);
+
+
+#ifdef SECUTIL_NEW
+typedef int (*SECU_PPFunc)(PRFileDesc *out, SECItem *item,
+ char *msg, int level);
+#else
+typedef int (*SECU_PPFunc)(FILE *out, SECItem *item, char *msg, int level);
+#endif
+
+typedef struct {
+ enum {
+ PW_NONE = 0,
+ PW_FROMFILE = 1,
+ PW_PLAINTEXT = 2
+ } source;
+ char *data;
+} secuPWData;
+
+/*
+** Change a password on a token, or initialize a token with a password
+** if it does not already have one.
+** Use passwd to send the password in plaintext, pwFile to specify a
+** file containing the password, or NULL for both to prompt the user.
+*/
+SECStatus SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile);
+
+/* These were stolen from the old sec.h... */
+/*
+** Check a password for legitimacy. Passwords must be at least 8
+** characters long and contain one non-alphabetic. Return DSTrue if the
+** password is ok, DSFalse otherwise.
+*/
+extern PRBool SEC_CheckPassword(char *password);
+
+/*
+** Blind check of a password. Complement to SEC_CheckPassword which
+** ignores length and content type, just retuning DSTrue is the password
+** exists, DSFalse if NULL
+*/
+extern PRBool SEC_BlindCheckPassword(char *password);
+
+/*
+** Get a password.
+** First prompt with "msg" on "out", then read the password from "in".
+** The password is then checked using "chkpw".
+*/
+extern char *SEC_GetPassword(FILE *in, FILE *out, char *msg,
+ PRBool (*chkpw)(char *));
+
+char *SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg);
+
+char *SECU_GetPasswordString(void *arg, char *prompt);
+
+/*
+** Write a dongle password.
+** Uses MD5 to hash constant system data (hostname, etc.), and then
+** creates RC4 key to encrypt a password "pw" into a file "fd".
+*/
+extern SECStatus SEC_WriteDongleFile(int fd, char *pw);
+
+/*
+** Get a dongle password.
+** Uses MD5 to hash constant system data (hostname, etc.), and then
+** creates RC4 key to decrypt and return a password from file "fd".
+*/
+extern char *SEC_ReadDongleFile(int fd);
+
+
+/* End stolen headers */
+
+/* Just sticks the two strings together with a / if needed */
+char *SECU_AppendFilenameToDir(char *dir, char *filename);
+
+/* Returns result of getenv("SSL_DIR") or NULL */
+extern char *SECU_DefaultSSLDir(void);
+
+/*
+** Should be called once during initialization to set the default
+** directory for looking for cert.db, key.db, and cert-nameidx.db files
+** Removes trailing '/' in 'base'
+** If 'base' is NULL, defaults to set to .netscape in home directory.
+*/
+extern char *SECU_ConfigDirectory(const char* base);
+
+/*
+** Basic callback function for SSL_GetClientAuthDataHook
+*/
+extern int
+SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey);
+
+/* print out an error message */
+extern void SECU_PrintError(char *progName, char *msg, ...);
+
+/* print out a system error message */
+extern void SECU_PrintSystemError(char *progName, char *msg, ...);
+
+/* Return informative error string */
+extern const char * SECU_Strerror(PRErrorCode errNum);
+
+/* Read the contents of a file into a SECItem */
+extern SECStatus SECU_FileToItem(SECItem *dst, PRFileDesc *src);
+extern SECStatus SECU_TextFileToItem(SECItem *dst, PRFileDesc *src);
+
+/* Read in a DER from a file, may be ascii */
+extern SECStatus
+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii);
+
+/* Indent based on "level" */
+extern void SECU_Indent(FILE *out, int level);
+
+/* Print integer value and hex */
+extern void SECU_PrintInteger(FILE *out, SECItem *i, char *m, int level);
+
+/* Print ObjectIdentifier symbolically */
+extern void SECU_PrintObjectID(FILE *out, SECItem *oid, char *m, int level);
+
+/* Print AlgorithmIdentifier symbolically */
+extern void SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m,
+ int level);
+
+/* Print SECItem as hex */
+extern void SECU_PrintAsHex(FILE *out, SECItem *i, const char *m, int level);
+
+/* dump a buffer in hex and ASCII */
+extern void SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len);
+
+/*
+ * Format and print the UTC Time "t". If the tag message "m" is not NULL,
+ * do indent formatting based on "level" and add a newline afterward;
+ * otherwise just print the formatted time string only.
+ */
+extern void SECU_PrintUTCTime(FILE *out, SECItem *t, char *m, int level);
+
+/*
+ * Format and print the Generalized Time "t". If the tag message "m"
+ * is not NULL, * do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+extern void SECU_PrintGeneralizedTime(FILE *out, SECItem *t, char *m,
+ int level);
+
+/* callback for listing certs through pkcs11 */
+extern SECStatus SECU_PrintCertNickname(CERTCertificate *cert, void *data);
+
+/* Dump all certificate nicknames in a database */
+extern SECStatus
+SECU_PrintCertificateNames(CERTCertDBHandle *handle, PRFileDesc* out,
+ PRBool sortByName, PRBool sortByTrust);
+
+/* See if nickname already in database. Return 1 true, 0 false, -1 error */
+int SECU_CheckCertNameExists(CERTCertDBHandle *handle, char *nickname);
+
+/* Dump contents of cert req */
+extern int SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m,
+ int level);
+
+/* Dump contents of certificate */
+extern int SECU_PrintCertificate(FILE *out, SECItem *der, char *m, int level);
+
+/* print trust flags on a cert */
+extern void SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, int level);
+
+/* Dump contents of public key */
+extern int SECU_PrintPublicKey(FILE *out, SECItem *der, char *m, int level);
+
+#ifdef HAVE_EPV_TEMPLATE
+/* Dump contents of private key */
+extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
+#endif
+
+/* Print the MD5 and SHA1 fingerprints of a cert */
+extern int SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m,
+ int level);
+
+/* Pretty-print any PKCS7 thing */
+extern int SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m,
+ int level);
+
+/* Init PKCS11 stuff */
+extern SECStatus SECU_PKCS11Init(PRBool readOnly);
+
+/* Dump contents of signed data */
+extern int SECU_PrintSignedData(FILE *out, SECItem *der, char *m, int level,
+ SECU_PPFunc inner);
+
+extern int SECU_PrintCrl(FILE *out, SECItem *der, char *m, int level);
+
+extern void
+SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level);
+
+extern void SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
+ char *msg, int level);
+
+extern void SECU_PrintName(FILE *out, CERTName *name, char *msg, int level);
+
+#ifdef SECU_GetPassword
+/* Convert a High public Key to a Low public Key */
+extern SECKEYLowPublicKey *SECU_ConvHighToLow(SECKEYPublicKey *pubHighKey);
+#endif
+
+extern SECItem *SECU_GetPBEPassword(void *arg);
+
+extern char *SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg);
+
+extern SECStatus DER_PrettyPrint(FILE *out, SECItem *it, PRBool raw);
+extern void SEC_Init(void);
+
+extern char *SECU_SECModDBName(void);
+
+extern void SECU_PrintPRandOSError(char *progName);
+
+/*
+ *
+ * Utilities for parsing security tools command lines
+ *
+ */
+
+/* A single command flag */
+typedef struct {
+ char flag;
+ PRBool needsArg;
+ char *arg;
+ PRBool activated;
+} secuCommandFlag;
+
+/* A full array of command/option flags */
+typedef struct
+{
+ int numCommands;
+ int numOptions;
+
+ secuCommandFlag *commands;
+ secuCommandFlag *options;
+} secuCommand;
+
+/* fill the "arg" and "activated" fields for each flag */
+SECStatus
+SECU_ParseCommandLine(int argc, char **argv, char *progName, secuCommand *cmd);
+char *
+SECU_GetOptionArg(secuCommand *cmd, int optionNum);
+
+/*
+ *
+ * Error messaging
+ *
+ */
+
+/* Return informative error string */
+char *SECU_ErrorString(int16 err);
+
+/* Return informative error string. Does not call XP_GetString */
+char *SECU_ErrorStringRaw(int16 err);
+
+void printflags(char *trusts, unsigned int flags);
+
+#ifndef XP_UNIX
+extern int ffs(unsigned int i);
+#endif
+
+#include "secerr.h"
+#include "sslerr.h"
+
+#endif /* _SEC_UTIL_H_ */
diff --git a/security/nss/cmd/makefile.inc b/security/nss/cmd/makefile.inc
new file mode 100644
index 000000000..029576e7c
--- /dev/null
+++ b/security/nss/cmd/makefile.inc
@@ -0,0 +1,84 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+INCLUDES += \
+ -I$(DEPTH)/security/lib/cert \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+ -I../include \
+ $(NULL)
+
+
+# For the time being, sec stuff is export only
+# US_FLAGS = -DEXPORT_VERSION -DUS_VERSION
+
+US_FLAGS = -DEXPORT_VERSION
+EXPORT_FLAGS = -DEXPORT_VERSION
+
+BASE_LIBS = \
+ $(DIST)/lib/libdbm.a \
+ $(DIST)/lib/libxp.a \
+ $(DIST)/lib/libnspr21.a \
+ $(NULL)
+
+
+#There is a circular dependancy in security/lib, and here is a gross fix
+SEC_LIBS = \
+ $(DIST)/lib/libsecnav.a \
+ $(DIST)/lib/libssl.a \
+ $(DIST)/lib/libpkcs7.a \
+ $(DIST)/lib/libcert.a \
+ $(DIST)/lib/libkey.a \
+ $(DIST)/lib/libsecmod.a \
+ $(DIST)/lib/libcrypto.a \
+ $(DIST)/lib/libsecutil.a \
+ $(DIST)/lib/libssl.a \
+ $(DIST)/lib/libpkcs7.a \
+ $(DIST)/lib/libcert.a \
+ $(DIST)/lib/libkey.a \
+ $(DIST)/lib/libsecmod.a \
+ $(DIST)/lib/libcrypto.a \
+ $(DIST)/lib/libsecutil.a \
+ $(DIST)/lib/libhash.a \
+ $(NULL)
+
+MYLIBDIR= ../lib/$(OBJDIR)
+MYLIB = $(MYLIBDIR)/libsectool.a
+
+US_LIBS = $(MYLIB) $(SEC_LIBS) $(BASE_LIBS) $(MYLIB) $(BASE_LIBS)
+EX_LIBS = $(MYLIB) $(SEC_LIBS) $(BASE_LIBS) $(MYLIB) $(BASE_LIBS)
+
+# this hack is necessary because rules.mk doesn't put anything like $(LIBS)
+# on the link command line (!?!?!?!)
+LDFLAGS += $(EX_LIBS)
+
diff --git a/security/nss/cmd/makefile.win b/security/nss/cmd/makefile.win
new file mode 100644
index 000000000..5e506590b
--- /dev/null
+++ b/security/nss/cmd/makefile.win
@@ -0,0 +1,48 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+include <$(DEPTH)\config\config.mak>
+
+include <$(DEPTH)\config\rules.mak>
+
+objs: $(OBJS)
+
+programs: $(PROGRAM)
+
+syms:
+ @echo "OBJS is $(OBJS)"
+ @echo "INCS is $(INCS)"
+
diff --git a/security/nss/cmd/makepqg/Makefile b/security/nss/cmd/makepqg/Makefile
new file mode 100644
index 000000000..36bf774fb
--- /dev/null
+++ b/security/nss/cmd/makepqg/Makefile
@@ -0,0 +1,77 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
+
diff --git a/security/nss/cmd/makepqg/makefile.win b/security/nss/cmd/makepqg/makefile.win
new file mode 100644
index 000000000..462448d73
--- /dev/null
+++ b/security/nss/cmd/makepqg/makefile.win
@@ -0,0 +1,156 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+PROGRAM = makepqg
+PROGRAM = $(OBJDIR)\$(PROGRAM).exe
+
+include <$(DEPTH)\config\config.mak>
+
+
+# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
+# rules.mak will append C_OBJS onto OBJS.
+# OBJS = $(CSRCS:.c=.obj)
+
+# include files are looked for in $LINCS and $INCS.
+# $LINCS is in manifest.mnw, computed from REQUIRES=
+INCS = $(INCS) \
+ -I$(DEPTH)/security/lib/cert \
+ -I$(DEPTH)/security/lib/crypto \
+ -I../include \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+
+
+WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
+
+# these files are the content of libdbm
+DBM_LIB = \
+ $(WINFE)/DB.obj \
+ $(WINFE)/HASH.obj \
+ $(WINFE)/H_BIGKEY.obj \
+ $(WINFE)/H_PAGE.obj \
+ $(WINFE)/H_LOG2.obj \
+ $(WINFE)/H_FUNC.obj \
+ $(WINFE)/HASH_BUF.obj \
+ $(NULL)
+
+MOZ_LIBS = \
+ $(WINFE)/ALLXPSTR.obj \
+ $(WINFE)/XP_ERROR.obj \
+ $(WINFE)/XPASSERT.obj \
+ $(WINFE)/XP_REG.obj \
+ $(WINFE)/XP_TRACE.obj \
+ $(DBM_LIB) \
+ $(WINFE)/XP_STR.obj \
+ $(WINFE)/MKTEMP.obj \
+ $(NULL)
+
+SEC_LIBS = \
+ $(DIST)/lib/cert$(MOZ_BITS).lib \
+ $(DIST)/lib/crypto$(MOZ_BITS).lib \
+ $(DIST)/lib/hash$(MOZ_BITS).lib \
+ $(DIST)/lib/key$(MOZ_BITS).lib \
+ $(DIST)/lib/pkcs7$(MOZ_BITS).lib \
+ $(DIST)/lib/secmod$(MOZ_BITS).lib \
+ $(DIST)/lib/secutl$(MOZ_BITS).lib \
+ $(DIST)/lib/ssl$(MOZ_BITS).lib \
+ $(NULL)
+
+LLFLAGS = $(LLFLAGS) \
+ ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
+ $(SEC_LIBS) \
+ $(MOZ_LIBS) \
+ $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
+ $(LIBNSPR) \
+ $(NULL)
+
+
+# awt3240.lib # brpref32.lib # cert32.lib
+# crypto32.lib # dllcom.lib # editor32.lib
+# edpref32.lib # edtplug.lib # font.lib
+# hash32.lib # htmldg32.lib # img32.lib
+# javart32.lib # jbn3240.lib # jdb3240.lib
+# jmc.lib # jpeg3240.lib # jpw3240.lib
+# jrt3240.lib # js3240.lib # jsd3240.lib
+# key32.lib # libapplet32.lib # libnjs32.lib
+# libnsc32.lib # libreg32.lib # mm3240.lib
+# mnpref32.lib # netcst32.lib # nsdlg32.lib
+# nsldap32.lib # nsldaps32.lib # nsn32.lib
+# pkcs1232.lib # pkcs732.lib # pr3240.lib
+# prefui32.lib # prefuuid.lib # secmod32.lib
+# secnav32.lib # secutl32.lib # softup32.lib
+# sp3240.lib # ssl32.lib # uni3200.lib
+# unicvt32.lib # win32md.lib # winfont.lib
+# xppref32.lib # zlib32.lib
+
+include <$(DEPTH)\config\rules.mak>
+
+
+INSTALL = $(MAKE_INSTALL)
+
+objs: $(OBJS)
+
+$(PROGRAM)::
+ $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
+
+programs: $(PROGRAM)
+
+install:: $(TARGETS)
+ $(INSTALL) $(TARGETS) $(DIST)/bin
+
+# ALLXPSTR.obj XP_ALLOC.obj XP_HASH.obj XP_RGB.obj XP_WRAP.obj
+# CXPRINT.obj XP_C.cl XP_LIST.obj XP_SEC.obj netscape.exp
+# CXPRNDLG.obj XP_CNTXT.obj XP_MD5.obj XP_STR.obj xp.pch
+# EXPORT.obj XP_CORE.obj XP_MESG.obj XP_THRMO.obj xppref32.dll
+# XPASSERT.obj XP_ERROR.obj XP_RECT.obj XP_TIME.obj
+# XPLOCALE.obj XP_FILE.obj XP_REG.obj XP_TRACE.obj
+
+symbols:
+ @echo "CSRCS = $(CSRCS)"
+ @echo "INCS = $(INCS)"
+ @echo "OBJS = $(OBJS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "TARGETS = $(TARGETS)"
+ @echo "DIST = $(DIST)"
+ @echo "VERSION_NUMBER = $(VERSION_NUMBER)"
+ @echo "WINFE = $(WINFE)"
+ @echo "DBM_LIB = $(DBM_LIB)"
+ @echo "INSTALL = $(INSTALL)"
+
diff --git a/security/nss/cmd/makepqg/makepqg.c b/security/nss/cmd/makepqg/makepqg.c
new file mode 100644
index 000000000..028ef7259
--- /dev/null
+++ b/security/nss/cmd/makepqg/makepqg.c
@@ -0,0 +1,290 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+#include "nss.h"
+#include "secutil.h"
+#include "secitem.h"
+#include "pk11func.h"
+#include "pk11pqg.h"
+#include "pqgutil.h"
+#include "secrng.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "plgetopt.h"
+
+#define BPB 8 /* bits per byte. */
+
+char *progName;
+
+
+const SEC_ASN1Template seckey_PQGParamsTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) },
+ { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) },
+ { 0, }
+};
+
+
+
+void
+Usage(void)
+{
+ fprintf(stderr, "Usage: %s\n", progName);
+ fprintf(stderr,
+"-a Output DER-encoded PQG params, BTOA encoded.\n"
+" -l prime-length Length of prime in bits (1024 is default)\n"
+" -o file Output to this file (default is stdout)\n"
+"-b Output DER-encoded PQG params in binary\n"
+" -l prime-length Length of prime in bits (1024 is default)\n"
+" -o file Output to this file (default is stdout)\n"
+"-r Output P, Q and G in ASCII hexadecimal. \n"
+" -l prime-length Length of prime in bits (1024 is default)\n"
+" -o file Output to this file (default is stdout)\n"
+"-g bits Generate SEED this many bits long.\n"
+);
+ exit(-1);
+
+}
+
+int
+outputPQGParams(PQGParams * pqgParams, PRBool output_binary, PRBool output_raw,
+ FILE * outFile)
+{
+ PRArenaPool * arena = NULL;
+ char * PQG;
+ SECItem encodedParams;
+
+ if (output_raw) {
+ SECItem item;
+
+ PK11_PQG_GetPrimeFromParams(pqgParams, &item);
+ SECU_PrintInteger(outFile, &item, "Prime", 1);
+ SECITEM_FreeItem(&item, PR_FALSE);
+
+ PK11_PQG_GetSubPrimeFromParams(pqgParams, &item);
+ SECU_PrintInteger(outFile, &item, "Subprime", 1);
+ SECITEM_FreeItem(&item, PR_FALSE);
+
+ PK11_PQG_GetBaseFromParams(pqgParams, &item);
+ SECU_PrintInteger(outFile, &item, "Base", 1);
+ SECITEM_FreeItem(&item, PR_FALSE);
+
+ fprintf(outFile, "\n");
+ return 0;
+ }
+
+ encodedParams.data = NULL;
+ encodedParams.len = 0;
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SEC_ASN1EncodeItem(arena, &encodedParams, pqgParams,
+ seckey_PQGParamsTemplate);
+ if (output_binary) {
+ fwrite(encodedParams.data, encodedParams.len, sizeof(char), outFile);
+ printf("\n");
+ return 0;
+ }
+
+ /* must be output ASCII */
+ PQG = BTOA_DataToAscii(encodedParams.data, encodedParams.len);
+
+ fprintf(outFile,"%s",PQG);
+ printf("\n");
+ return 0;
+}
+
+int
+outputPQGVerify(PQGVerify * pqgVerify, PRBool output_binary, PRBool output_raw,
+ FILE * outFile)
+{
+ if (output_raw) {
+ SECItem item;
+ unsigned int counter;
+
+ PK11_PQG_GetHFromVerify(pqgVerify, &item);
+ SECU_PrintInteger(outFile, &item, "h", 1);
+ SECITEM_FreeItem(&item, PR_FALSE);
+
+ PK11_PQG_GetSeedFromVerify(pqgVerify, &item);
+ SECU_PrintInteger(outFile, &item, "SEED", 1);
+ fprintf(outFile, " g: %d\n", item.len * BPB);
+ SECITEM_FreeItem(&item, PR_FALSE);
+
+ counter = PK11_PQG_GetCounterFromVerify(pqgVerify);
+ fprintf(outFile, " counter: %d\n", counter);
+ fprintf(outFile, "\n");
+ return 0;
+ }
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ FILE * outFile = NULL;
+ PQGParams * pqgParams = NULL;
+ PQGVerify * pqgVerify = NULL;
+ int keySizeInBits = 1024;
+ int j;
+ int o;
+ int g = 0;
+ SECStatus rv = 0;
+ SECStatus passed = 0;
+ PRBool output_ascii = PR_FALSE;
+ PRBool output_binary = PR_FALSE;
+ PRBool output_raw = PR_FALSE;
+ PLOptState *optstate;
+ PLOptStatus status;
+
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName+1 : argv[0];
+
+ /* Parse command line arguments */
+ optstate = PL_CreateOptState(argc, argv, "l:abro:g:" );
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+
+ case 'l':
+ keySizeInBits = atoi(optstate->value);
+ break;
+
+ case 'a':
+ output_ascii = PR_TRUE;
+ break;
+
+ case 'b':
+ output_binary = PR_TRUE;
+ break;
+
+ case 'r':
+ output_raw = PR_TRUE;
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "wb");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ rv = -1;
+ }
+ break;
+
+ case 'g':
+ g = atoi(optstate->value);
+ break;
+
+ default:
+ case '?':
+ Usage();
+ break;
+
+ }
+ }
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ /* exactly 1 of these options must be set. */
+ if (1 != ((output_ascii != PR_FALSE) +
+ (output_binary != PR_FALSE) +
+ (output_raw != PR_FALSE))) {
+ Usage();
+ }
+
+ j = PQG_PBITS_TO_INDEX(keySizeInBits);
+ if (j < 0) {
+ fprintf(stderr, "%s: Illegal prime length, \n"
+ "\tacceptable values are between 512 and 1024,\n"
+ "\tand divisible by 64\n", progName);
+ return -1;
+ }
+ if (g != 0 && (g < 160 || g >= 2048 || g % 8 != 0)) {
+ fprintf(stderr, "%s: Illegal g bits, \n"
+ "\tacceptable values are between 160 and 2040,\n"
+ "\tand divisible by 8\n", progName);
+ return -1;
+ }
+
+ if (outFile == NULL) {
+ outFile = stdout;
+ }
+
+
+ NSS_NoDB_Init(NULL);
+
+ if (g)
+ rv = PK11_PQG_ParamGenSeedLen((unsigned)j, (unsigned)(g/8),
+ &pqgParams, &pqgVerify);
+ else
+ rv = PK11_PQG_ParamGen((unsigned)j, &pqgParams, &pqgVerify);
+
+ if (rv != SECSuccess || pqgParams == NULL) {
+ fprintf(stderr, "%s: PQG parameter generation failed.\n", progName);
+ goto loser;
+ }
+ fprintf(stderr, "%s: PQG parameter generation completed.\n", progName);
+
+ o = outputPQGParams(pqgParams, output_binary, output_raw, outFile);
+ o = outputPQGVerify(pqgVerify, output_binary, output_raw, outFile);
+
+ rv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: PQG parameter verification aborted.\n", progName);
+ goto loser;
+ }
+ if (passed != SECSuccess) {
+ fprintf(stderr, "%s: PQG parameters failed verification.\n", progName);
+ goto loser;
+ }
+ fprintf(stderr, "%s: PQG parameters passed verification.\n", progName);
+
+ PK11_PQG_DestroyParams(pqgParams);
+ PK11_PQG_DestroyVerify(pqgVerify);
+ return 0;
+
+loser:
+ PK11_PQG_DestroyParams(pqgParams);
+ PK11_PQG_DestroyVerify(pqgVerify);
+ return 1;
+}
diff --git a/security/nss/cmd/makepqg/manifest.mn b/security/nss/cmd/makepqg/manifest.mn
new file mode 100644
index 000000000..328797094
--- /dev/null
+++ b/security/nss/cmd/makepqg/manifest.mn
@@ -0,0 +1,47 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+REQUIRES = nss seccmd dbm
+
+# DIRS =
+
+CSRCS = makepqg.c
+
+PROGRAM = makepqg
+
+#USE_STATIC_LIBS = 1
+
diff --git a/security/nss/cmd/makepqg/testit.ksh b/security/nss/cmd/makepqg/testit.ksh
new file mode 100644
index 000000000..98cb7fa9d
--- /dev/null
+++ b/security/nss/cmd/makepqg/testit.ksh
@@ -0,0 +1,41 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+COUNTER=75
+while [ $COUNTER -ge "1" ]
+do
+ COUNTER=$(eval expr $COUNTER - 1)
+ echo $COUNTER
+ */makepqg.exe -r -l 640 -g 160 || exit 1
+done
+
diff --git a/security/nss/cmd/manifest.mn b/security/nss/cmd/manifest.mn
new file mode 100644
index 000000000..13289a7d3
--- /dev/null
+++ b/security/nss/cmd/manifest.mn
@@ -0,0 +1,90 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+DEPTH = ../..
+# MODULE = seccmd
+
+REQUIRES = nss nspr libdbm
+
+DIRS = lib \
+ zlib \
+ atob \
+ bltest \
+ btoa \
+ certcgi \
+ certutil \
+ checkcert \
+ crlutil \
+ dbtest \
+ derdump \
+ digest \
+ makepqg \
+ ocspclnt \
+ oidcalc \
+ p7content \
+ p7env \
+ p7sign \
+ p7verify \
+ pk12util \
+ pp \
+ rngtest \
+ rsaperf \
+ sdrtest \
+ selfserv \
+ signtool \
+ signver \
+ shlibsign \
+ smimetools \
+ SSLsample \
+ ssltap \
+ strsclnt \
+ swfort \
+ tstclnt \
+ vfyserv \
+ modutil \
+ $(NULL)
+
+TEMPORARILY_DONT_BUILD = \
+ $(NULL)
+
+# rsaperf \
+#
+# needs to look at what needs to happen to make jar build in
+# the binary release environment.
+#
+# perror requires lib/strerror.c which requires the client code installed
+# to build (requires allxpstr.h)
+#
+DONT_BULD = jar \
+ perror \
+$(NULL)
diff --git a/security/nss/cmd/modutil/Makefile b/security/nss/cmd/modutil/Makefile
new file mode 100644
index 000000000..3d2bbb412
--- /dev/null
+++ b/security/nss/cmd/modutil/Makefile
@@ -0,0 +1,80 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
+#
+# Cancel the built-in implicit yacc and lex rules.
+#
+
+%.c: %.y
+%.c: %.l
diff --git a/security/nss/cmd/modutil/README b/security/nss/cmd/modutil/README
new file mode 100644
index 000000000..12d192c9f
--- /dev/null
+++ b/security/nss/cmd/modutil/README
@@ -0,0 +1,7 @@
+ CRYPTOGRAPHIC MODULE UTILITY (modutil)
+ VERSION 1.0
+ ===============================================
+
+The file specification.html documentats the software.
+
+The file pk11jar.html documents the PKCS #11 JAR format.
diff --git a/security/nss/cmd/modutil/config.mk b/security/nss/cmd/modutil/config.mk
new file mode 100644
index 000000000..9f0cdf1e4
--- /dev/null
+++ b/security/nss/cmd/modutil/config.mk
@@ -0,0 +1,77 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# Set the LDFLAGS value to encompass all normal link options, all #
+# library names, and all special system linking options #
+#######################################################################
+
+LDFLAGS = \
+ $(DYNAMIC_LIB_PATH) \
+ $(LDOPTS) \
+ $(LIBSECTOOLS) \
+ $(LIBSECMOD) \
+ $(LIBHASH) \
+ $(LIBCERT) \
+ $(LIBKEY) \
+ $(LIBCRYPTO) \
+ $(LIBSECUTIL) \
+ $(LIBDBM) \
+ $(LIBPLC3) \
+ $(LIBPLDS3) \
+ $(LIBPR3) \
+ $(DLLSYSTEM) \
+ $(LIBJAR) \
+ $(LIBZLIB) \
+ $(LIBPKCS7) \
+ $(LIBPLC3)
+
+# Strip out the symbols
+ifdef BUILD_OPT
+ ifneq (,$(filter-out WIN%,$(OS_TARGET)))
+ LDFLAGS += -s
+ endif
+endif
+
+#######################################################################
+# Adjust specific variables for all platforms #
+#######################################################################
+
+
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+ PACKAGE_FILES = license.txt README.TXT specification.html pk11jar.html modutil.exe
+else
+ PACKAGE_FILES = license.doc README specification.html pk11jar.html modutil
+endif
+
+ARCHIVE_NAME = modutil_$(OS_TARGET)$(OS_RELEASE)
diff --git a/security/nss/cmd/modutil/error.h b/security/nss/cmd/modutil/error.h
new file mode 100644
index 000000000..560e317db
--- /dev/null
+++ b/security/nss/cmd/modutil/error.h
@@ -0,0 +1,182 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifndef MODUTIL_ERROR_H
+#define MODUTIL_ERROR_H
+
+typedef enum {
+ NO_ERR=0,
+ INVALID_USAGE_ERR,
+ UNEXPECTED_ARG_ERR,
+ UNKNOWN_OPTION_ERR,
+ MULTIPLE_COMMAND_ERR,
+ OPTION_NEEDS_ARG_ERR,
+ DUPLICATE_OPTION_ERR,
+ MISSING_PARAM_ERR,
+ INVALID_FIPS_ARG,
+ NO_COMMAND_ERR,
+ NO_DBDIR_ERR,
+ FIPS_SWITCH_FAILED_ERR,
+ FIPS_ALREADY_ON_ERR,
+ FIPS_ALREADY_OFF_ERR,
+ FILE_ALREADY_EXISTS_ERR,
+ FILE_DOESNT_EXIST_ERR,
+ FILE_NOT_READABLE_ERR,
+ FILE_NOT_WRITEABLE_ERR,
+ DIR_DOESNT_EXIST_ERR,
+ DIR_NOT_READABLE_ERR,
+ DIR_NOT_WRITEABLE_ERR,
+ INVALID_CONSTANT_ERR,
+ ADD_MODULE_FAILED_ERR,
+ ADD_MODULE_FAILED_STATUS_ERR,
+ OUT_OF_MEM_ERR,
+ DELETE_INTERNAL_ERR,
+ DELETE_FAILED_ERR,
+ NO_LIST_LOCK_ERR,
+ NO_MODULE_LIST_ERR,
+ NO_SUCH_MODULE_ERR,
+ MOD_INFO_ERR,
+ SLOT_INFO_ERR,
+ TOKEN_INFO_ERR,
+ NO_SUCH_TOKEN_ERR,
+ CHANGEPW_FAILED_ERR,
+ BAD_PW_ERR,
+ DB_ACCESS_ERR,
+ AUTHENTICATION_FAILED_ERR,
+ NO_SUCH_SLOT_ERR,
+ ENABLE_FAILED_ERR,
+ UPDATE_MOD_FAILED_ERR,
+ DEFAULT_FAILED_ERR,
+ UNDEFAULT_FAILED_ERR,
+ STDIN_READ_ERR,
+ UNSPECIFIED_ERR,
+ NOCERTDB_MISUSE_ERR,
+ NSS_INITIALIZE_FAILED_ERR,
+
+ LAST_ERR /* must be last */
+} Error;
+#define SUCCESS NO_ERR
+
+/* !!! Should move this into its own .c and un-static it. */
+static char *errStrings[] = {
+ "Operation completed successfully.\n",
+ "ERROR: Invalid command line.\n",
+ "ERROR: Not expecting argument \"%s\".\n",
+ "ERROR: Unknown option: %s.\n",
+ "ERROR: %s: multiple commands are not allowed on the command line.\n",
+ "ERROR: %s: option needs an argument.\n",
+ "ERROR: %s: option cannot be given more than once.\n",
+ "ERROR: Command \"%s\" requires parameter \"%s\".\n",
+ "ERROR: Argument to -fips must be \"true\" or \"false\".\n",
+ "ERROR: No command was specified.\n",
+ "ERROR: Cannot determine database directory: use the -dbdir option.\n",
+ "ERROR: Unable to switch FIPS modes.\n",
+ "FIPS mode already enabled.\n",
+ "FIPS mode already disabled.\n",
+ "ERROR: File \"%s\" already exists.\n",
+ "ERROR: File \"%s\" does not exist.\n",
+ "ERROR: File \"%s\" is not readable.\n",
+ "ERROR: File \"%s\" is not writeable.\n",
+ "ERROR: Directory \"%s\" does not exist.\n",
+ "ERROR: Directory \"%s\" is not readable.\n",
+ "ERROR: Directory \"%s\" is not writeable.\n",
+ "\"%s\" is not a recognized value.\n",
+ "ERROR: Failed to add module \"%s\".\n",
+ "ERROR: Failed to add module \"%s\". Probable cause : \"%s\".\n",
+ "ERROR: Out of memory.\n",
+ "ERROR: Cannot delete internal module.\n",
+ "ERROR: Failed to delete module \"%s\".\n",
+ "ERROR: Unable to obtain lock on module list.\n",
+ "ERROR: Unable to obtain module list.\n",
+ "ERROR: Module \"%s\" not found in database.\n",
+ "ERROR: Unable to get information about module \"%s\".\n",
+ "ERROR: Unable to get information about slot \"%s\".\n",
+ "ERROR: Unable to get information about token \"%s\".\n",
+ "ERROR: Token \"%s\" not found.\n",
+ "ERROR: Unable to change password on token \"%s\".\n",
+ "ERROR: Incorrect password.\n",
+ "ERROR: Unable to access database \"%s\".\n",
+ "ERROR: Unable to authenticate to token \"%s\".\n",
+ "ERROR: Slot \"%s\" not found.\n",
+ "ERROR: Failed to %s slot \"%s\".\n",
+ "ERROR: Failed to update module \"%s\".\n",
+ "ERROR: Failed to change defaults.\n",
+ "ERROR: Failed to change default.\n",
+ "ERROR: Unable to read from standard input.\n",
+ "ERROR: Unknown error occurred.\n",
+ "ERROR: -nocertdb option can only be used with the -jar command.\n"
+ "ERROR: NSS_Initialize() failed.\n"
+};
+
+typedef enum {
+ FIPS_ENABLED_MSG=0,
+ FIPS_DISABLED_MSG,
+ USING_DBDIR_MSG,
+ CREATING_DB_MSG,
+ ADD_MODULE_SUCCESS_MSG,
+ DELETE_SUCCESS_MSG,
+ CHANGEPW_SUCCESS_MSG,
+ BAD_PW_MSG,
+ PW_MATCH_MSG,
+ DONE_MSG,
+ ENABLE_SUCCESS_MSG,
+ DEFAULT_SUCCESS_MSG,
+ UNDEFAULT_SUCCESS_MSG,
+ BROWSER_RUNNING_MSG,
+ ABORTING_MSG,
+
+ LAST_MSG /* must be last */
+} Message;
+
+static char *msgStrings[] = {
+ "FIPS mode enabled.\n",
+ "FIPS mode disabled.\n",
+ "Using database directory %s...\n",
+ "Creating \"%s\"...",
+ "Module \"%s\" added to database.\n",
+ "Module \"%s\" deleted from database.\n",
+ "Token \"%s\" password changed successfully.\n",
+ "Incorrect password, try again...\n",
+ "Passwords do not match, try again...\n",
+ "done.\n",
+ "Slot \"%s\" %s.\n",
+ "Successfully changed defaults.\n",
+ "Successfully changed defaults.\n",
+"\nWARNING: Performing this operation while the browser is running could cause"
+"\ncorruption of your security databases. If the browser is currently running,"
+"\nyou should exit browser before continuing this operation. Type "
+"\n'q <enter>' to abort, or <enter> to continue: ",
+ "\nAborting...\n"
+};
+
+#endif /* MODUTIL_ERROR_H */
diff --git a/security/nss/cmd/modutil/install-ds.c b/security/nss/cmd/modutil/install-ds.c
new file mode 100644
index 000000000..e6b90ded3
--- /dev/null
+++ b/security/nss/cmd/modutil/install-ds.c
@@ -0,0 +1,1541 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "install-ds.h"
+#include <prmem.h>
+#include <plstr.h>
+#include <prprf.h>
+#include <string.h>
+
+#define PORT_Strcasecmp PL_strcasecmp
+
+#define MODULE_FILE_STRING "ModuleFile"
+#define MODULE_NAME_STRING "ModuleName"
+#define MECH_FLAGS_STRING "DefaultMechanismFlags"
+#define CIPHER_FLAGS_STRING "DefaultCipherFlags"
+#define FILES_STRING "Files"
+#define FORWARD_COMPATIBLE_STRING "ForwardCompatible"
+#define PLATFORMS_STRING "Platforms"
+#define RELATIVE_DIR_STRING "RelativePath"
+#define ABSOLUTE_DIR_STRING "AbsolutePath"
+#define FILE_PERMISSIONS_STRING "FilePermissions"
+#define EQUIVALENT_PLATFORM_STRING "EquivalentPlatform"
+#define EXECUTABLE_STRING "Executable"
+
+#define DEFAULT_PERMISSIONS 0777
+
+#define PLATFORM_SEPARATOR_CHAR ':'
+
+/* Error codes */
+enum {
+ BOGUS_RELATIVE_DIR=0,
+ BOGUS_ABSOLUTE_DIR,
+ BOGUS_FILE_PERMISSIONS,
+ NO_RELATIVE_DIR,
+ NO_ABSOLUTE_DIR,
+ EMPTY_PLATFORM_STRING,
+ BOGUS_PLATFORM_STRING,
+ REPEAT_MODULE_FILE,
+ REPEAT_MODULE_NAME,
+ BOGUS_MODULE_FILE,
+ BOGUS_MODULE_NAME,
+ REPEAT_MECH,
+ BOGUS_MECH_FLAGS,
+ REPEAT_CIPHER,
+ BOGUS_CIPHER_FLAGS,
+ REPEAT_FILES,
+ REPEAT_EQUIV,
+ BOGUS_EQUIV,
+ EQUIV_TOO_MUCH_INFO,
+ NO_FILES,
+ NO_MODULE_FILE,
+ NO_MODULE_NAME,
+ NO_PLATFORMS,
+ EQUIV_LOOP,
+ UNKNOWN_MODULE_FILE
+};
+
+/* Indexed by the above error codes */
+static const char *errString[] = {
+ "%s: Invalid relative directory",
+ "%s: Invalid absolute directory",
+ "%s: Invalid file permissions",
+ "%s: No relative directory specified",
+ "%s: No absolute directory specified",
+ "Empty string given for platform name",
+ "%s: invalid platform string",
+ "More than one ModuleFile entry given for platform %s",
+ "More than one ModuleName entry given for platform %s",
+ "Invalid ModuleFile specification for platform %s",
+ "Invalid ModuleName specification for platform %s",
+ "More than one DefaultMechanismFlags entry given for platform %s",
+ "Invalid DefaultMechanismFlags specification for platform %s",
+ "More than one DefaultCipherFlags entry given for platform %s",
+ "Invalid DefaultCipherFlags entry given for platform %s",
+ "More than one Files entry given for platform %s",
+ "More than one EquivalentPlatform entry given for platform %s",
+ "Invalid EquivalentPlatform specification for platform %s",
+ "Module %s uses an EquivalentPlatform but also specifies its own"
+ " information",
+ "No Files specification in module %s",
+ "No ModuleFile specification in module %s",
+ "No ModuleName specification in module %s",
+ "No Platforms specification in installer script",
+ "Platform %s has an equivalency loop",
+ "Module file \"%s\" in platform \"%s\" does not exist"
+};
+
+static char* PR_Strdup(const char* str);
+
+#define PAD(x) {int i; for(i=0;i<x;i++) printf(" ");}
+#define PADINC 4
+
+Pk11Install_File*
+Pk11Install_File_new()
+{
+ Pk11Install_File* new_this;
+ new_this = (Pk11Install_File*)PR_Malloc(sizeof(Pk11Install_File));
+ Pk11Install_File_init(new_this);
+ return new_this;
+}
+
+void
+Pk11Install_File_init(Pk11Install_File* _this)
+{
+ _this->jarPath=NULL;
+ _this->relativePath=NULL;
+ _this->absolutePath=NULL;
+ _this->executable=PR_FALSE;
+ _this->permissions=0;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: ~Pk11Install_File
+// Class: Pk11Install_File
+// Notes: Destructor.
+*/
+void
+Pk11Install_File_delete(Pk11Install_File* _this)
+{
+ Pk11Install_File_Cleanup(_this);
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Cleanup
+// Class: Pk11Install_File
+*/
+void
+Pk11Install_File_Cleanup(Pk11Install_File* _this)
+{
+ if(_this->jarPath) {
+ PR_Free(_this->jarPath);
+ _this->jarPath = NULL;
+ }
+ if(_this->relativePath) {
+ PR_Free(_this->relativePath);
+ _this->relativePath = NULL;
+ }
+ if(_this->absolutePath) {
+ PR_Free(_this->absolutePath);
+ _this->absolutePath = NULL;
+ }
+
+ _this->permissions = 0;
+ _this->executable = PR_FALSE;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Generate
+// Class: Pk11Install_File
+// Notes: Creates a file data structure from a syntax tree.
+// Returns: NULL for success, otherwise an error message.
+*/
+char*
+Pk11Install_File_Generate(Pk11Install_File* _this,
+ const Pk11Install_Pair *pair)
+{
+ Pk11Install_ListIter *iter;
+ Pk11Install_Value *val;
+ Pk11Install_Pair *subpair;
+ Pk11Install_ListIter *subiter;
+ Pk11Install_Value *subval;
+ char* errStr;
+ char *endp;
+ PRBool gotPerms;
+
+ iter=NULL;
+ subiter=NULL;
+ errStr=NULL;
+ gotPerms=PR_FALSE;
+
+ /* Clear out old values */
+ Pk11Install_File_Cleanup(_this);
+
+ _this->jarPath = PR_Strdup(pair->key);
+
+ /* Go through all the pairs under this file heading */
+ iter = Pk11Install_ListIter_new(pair->list);
+ for( ; (val = iter->current); Pk11Install_ListIter_nextItem(iter)) {
+ if(val->type == PAIR_VALUE) {
+ subpair = val->pair;
+
+ /* Relative directory */
+ if(!PORT_Strcasecmp(subpair->key, RELATIVE_DIR_STRING)) {
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if(!subval || (subval->type != STRING_VALUE)){
+ errStr = PR_smprintf(errString[BOGUS_RELATIVE_DIR],
+ _this->jarPath);
+ goto loser;
+ }
+ _this->relativePath = PR_Strdup(subval->string);
+ Pk11Install_ListIter_delete(subiter);
+ subiter = NULL;
+
+ /* Absolute directory */
+ } else if( !PORT_Strcasecmp(subpair->key, ABSOLUTE_DIR_STRING)) {
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if(!subval || (subval->type != STRING_VALUE)){
+ errStr = PR_smprintf(errString[BOGUS_ABSOLUTE_DIR],
+ _this->jarPath);
+ goto loser;
+ }
+ _this->absolutePath = PR_Strdup(subval->string);
+ Pk11Install_ListIter_delete(subiter);
+ subiter = NULL;
+
+ /* file permissions */
+ } else if( !PORT_Strcasecmp(subpair->key,
+ FILE_PERMISSIONS_STRING)) {
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if(!subval || (subval->type != STRING_VALUE)){
+ errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
+ _this->jarPath);
+ goto loser;
+ }
+ _this->permissions = (int) strtol(subval->string, &endp, 8);
+ if(*endp != '\0' || subval->string == "\0") {
+ errStr = PR_smprintf(errString[BOGUS_FILE_PERMISSIONS],
+ _this->jarPath);
+ goto loser;
+ }
+ gotPerms = PR_TRUE;
+ Pk11Install_ListIter_delete(subiter);
+ subiter = NULL;
+ }
+ } else {
+ if(!PORT_Strcasecmp(val->string, EXECUTABLE_STRING)) {
+ _this->executable = PR_TRUE;
+ }
+ }
+ }
+
+ /* Default permission value */
+ if(!gotPerms) {
+ _this->permissions = DEFAULT_PERMISSIONS;
+ }
+
+ /* Make sure we got all the information */
+ if(!_this->relativePath && !_this->absolutePath) {
+ errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
+ goto loser;
+ }
+#if 0
+ if(!_this->relativePath ) {
+ errStr = PR_smprintf(errString[NO_RELATIVE_DIR], _this->jarPath);
+ goto loser;
+ }
+ if(!_this->absolutePath) {
+ errStr = PR_smprintf(errString[NO_ABSOLUTE_DIR], _this->jarPath);
+ goto loser;
+ }
+#endif
+
+loser:
+ if(iter) {
+ Pk11Install_ListIter_delete(iter);
+ PR_Free(iter);
+ }
+ if(subiter) {
+ Pk11Install_ListIter_delete(subiter);
+ PR_Free(subiter);
+ }
+ return errStr;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Print
+// Class: Pk11Install_File
+*/
+void
+Pk11Install_File_Print(Pk11Install_File* _this, int pad)
+{
+ PAD(pad); printf("jarPath: %s\n",
+ _this->jarPath ? _this->jarPath : "<NULL>");
+ PAD(pad); printf("relativePath: %s\n",
+ _this->relativePath ? _this->relativePath: "<NULL>");
+ PAD(pad); printf("absolutePath: %s\n",
+ _this->absolutePath ? _this->absolutePath: "<NULL>");
+ PAD(pad); printf("permissions: %o\n", _this->permissions);
+}
+
+Pk11Install_PlatformName*
+Pk11Install_PlatformName_new()
+{
+ Pk11Install_PlatformName* new_this;
+ new_this = (Pk11Install_PlatformName*)
+ PR_Malloc(sizeof(Pk11Install_PlatformName));
+ Pk11Install_PlatformName_init(new_this);
+ return new_this;
+}
+
+void
+Pk11Install_PlatformName_init(Pk11Install_PlatformName* _this)
+{
+ _this->OS = NULL;
+ _this->verString = NULL;
+ _this->numDigits = 0;
+ _this->arch = NULL;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: ~Pk11Install_PlatformName
+// Class: Pk11Install_PlatformName
+*/
+void
+Pk11Install_PlatformName_delete(Pk11Install_PlatformName* _this)
+{
+ Pk11Install_PlatformName_Cleanup(_this);
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Cleanup
+// Class: Pk11Install_PlatformName
+*/
+void
+Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName* _this)
+{
+ if(_this->OS) {
+ PR_Free(_this->OS);
+ _this->OS = NULL;
+ }
+ if(_this->verString) {
+ int i;
+ for (i=0; i<_this->numDigits; i++) {
+ PR_Free(_this->verString[i]);
+ }
+ PR_Free(_this->verString);
+ _this->verString = NULL;
+ }
+ if(_this->arch) {
+ PR_Free(_this->arch);
+ _this->arch = NULL;
+ }
+ _this->numDigits = 0;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Generate
+// Class: Pk11Install_PlatformName
+// Notes: Extracts the information from a platform string.
+*/
+char*
+Pk11Install_PlatformName_Generate(Pk11Install_PlatformName* _this,
+ const char *str)
+{
+ char *errStr;
+ char *copy;
+ char *end, *start; /* start and end of a section (OS, version, arch)*/
+ char *pend, *pstart; /* start and end of one portion of version*/
+ char *endp; /* used by strtol*/
+ int periods, i;
+
+ errStr=NULL;
+ copy=NULL;
+
+ if(!str) {
+ errStr = PR_smprintf(errString[EMPTY_PLATFORM_STRING]);
+ goto loser;
+ }
+ copy = PR_Strdup(str);
+
+ /*
+ // Get the OS
+ */
+ end = strchr(copy, PLATFORM_SEPARATOR_CHAR);
+ if(!end || end==copy) {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ *end = '\0';
+
+ _this->OS = PR_Strdup(copy);
+
+ /*
+ // Get the digits of the version of form: x.x.x (arbitrary number of digits)
+ */
+
+ start = end+1;
+ end = strchr(start, PLATFORM_SEPARATOR_CHAR);
+ if(!end) {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ *end = '\0';
+
+ if(end!=start) {
+ /* Find out how many periods*/
+ periods = 0;
+ pstart = start;
+ while( (pend=strchr(pstart, '.')) ) {
+ periods++;
+ pstart = pend+1;
+ }
+ _this->numDigits= 1+ periods;
+ _this->verString = (char**)PR_Malloc(sizeof(char*)*_this->numDigits);
+
+ pstart = start;
+ i = 0;
+ /* Get the digits before each period*/
+ while( (pend=strchr(pstart, '.')) ) {
+ if(pend == pstart) {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ *pend = '\0';
+ _this->verString[i] = PR_Strdup(pstart);
+ endp = pend;
+ if(endp==pstart || (*endp != '\0')) {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ pstart = pend+1;
+ i++;
+ }
+ /* Last digit comes after the last period*/
+ if(*pstart == '\0') {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ _this->verString[i] = PR_Strdup(pstart);
+ /*
+ if(endp==pstart || (*endp != '\0')) {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ */
+ } else {
+ _this->verString = NULL;
+ _this->numDigits = 0;
+ }
+
+ /*
+ // Get the architecture
+ */
+ start = end+1;
+ if( strchr(start, PLATFORM_SEPARATOR_CHAR) ) {
+ errStr = PR_smprintf(errString[BOGUS_PLATFORM_STRING], str);
+ goto loser;
+ }
+ _this->arch = PR_Strdup(start);
+
+ if(copy) {
+ PR_Free(copy);
+ }
+ return NULL;
+loser:
+ if(_this->OS) {
+ PR_Free(_this->OS);
+ _this->OS = NULL;
+ }
+ if(_this->verString) {
+ for (i=0; i<_this->numDigits; i++) {
+ PR_Free(_this->verString[i]);
+ }
+ PR_Free(_this->verString);
+ _this->verString = NULL;
+ }
+ _this->numDigits = 0;
+ if(_this->arch) {
+ PR_Free(_this->arch);
+ _this->arch = NULL;
+ }
+
+ return errStr;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: operator ==
+// Class: Pk11Install_PlatformName
+// Returns: PR_TRUE if the platform have the same OS, arch, and version
+*/
+PRBool
+Pk11Install_PlatformName_equal(Pk11Install_PlatformName* _this,
+ Pk11Install_PlatformName* cmp)
+{
+ int i;
+
+ if(!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
+ return PR_FALSE;
+ }
+
+ if( PORT_Strcasecmp(_this->OS, cmp->OS) ||
+ PORT_Strcasecmp(_this->arch, cmp->arch) ||
+ _this->numDigits != cmp->numDigits ) {
+ return PR_FALSE;
+ }
+
+ for(i=0; i < _this->numDigits; i++) {
+ if(PORT_Strcasecmp(_this->verString[i], cmp->verString[i])) {
+ return PR_FALSE;
+ }
+ }
+ return PR_TRUE;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: operator <=
+// Class: Pk11Install_PlatformName
+// Returns: PR_TRUE if the platform have the same OS and arch and a lower
+// or equal release.
+*/
+PRBool
+Pk11Install_PlatformName_lteq(Pk11Install_PlatformName* _this,
+ Pk11Install_PlatformName* cmp)
+{
+ return (Pk11Install_PlatformName_equal(_this,cmp) ||
+ Pk11Install_PlatformName_lt(_this,cmp)) ? PR_TRUE : PR_FALSE;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: operator <
+// Class: Pk11Install_PlatformName
+// Returns: PR_TRUE if the platform have the same OS and arch and a greater
+// release.
+*/
+PRBool
+Pk11Install_PlatformName_lt(Pk11Install_PlatformName* _this,
+ Pk11Install_PlatformName* cmp)
+{
+ int i, scmp;
+
+ if(!_this->OS || !_this->arch || !cmp->OS || !cmp->arch) {
+ return PR_FALSE;
+ }
+
+ if( PORT_Strcasecmp(_this->OS, cmp->OS) ) {
+ return PR_FALSE;
+ }
+ if( PORT_Strcasecmp(_this->arch, cmp->arch) ) {
+ return PR_FALSE;
+ }
+
+ for(i=0; (i < _this->numDigits) && (i < cmp->numDigits); i++) {
+ scmp = PORT_Strcasecmp(_this->verString[i], cmp->verString[i]);
+ if (scmp > 0) {
+ return PR_FALSE;
+ } else if (scmp < 0) {
+ return PR_TRUE;
+ }
+ }
+ /* All the digits they have in common are the same. */
+ if(_this->numDigits < cmp->numDigits) {
+ return PR_TRUE;
+ }
+
+ return PR_FALSE;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: GetString
+// Class: Pk11Install_PlatformName
+// Returns: String composed of OS, release, and architecture separated
+// by the separator char. Memory is allocated by this function
+// but is the responsibility of the caller to de-allocate.
+*/
+char*
+Pk11Install_PlatformName_GetString(Pk11Install_PlatformName* _this)
+{
+ char *ret;
+ char *ver;
+ char *OS_;
+ char *arch_;
+
+ OS_=NULL;
+ arch_=NULL;
+
+ OS_ = _this->OS ? _this->OS : "";
+ arch_ = _this->arch ? _this->arch : "";
+
+ ver = Pk11Install_PlatformName_GetVerString(_this);
+ ret = PR_smprintf("%s%c%s%c%s", OS_, PLATFORM_SEPARATOR_CHAR, ver,
+ PLATFORM_SEPARATOR_CHAR, arch_);
+
+ PR_Free(ver);
+
+ return ret;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: GetVerString
+// Class: Pk11Install_PlatformName
+// Returns: The version string for this platform, in the form x.x.x with an
+// arbitrary number of digits. Memory allocated by function,
+// must be de-allocated by caller.
+*/
+char*
+Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName* _this)
+{
+ char *tmp;
+ char *ret;
+ int i;
+ char buf[80];
+
+ tmp = (char*)PR_Malloc(80*_this->numDigits+1);
+ tmp[0] = '\0';
+
+ for(i=0; i < _this->numDigits-1; i++) {
+ sprintf(buf, "%s.", _this->verString[i]);
+ strcat(tmp, buf);
+ }
+ if(i < _this->numDigits) {
+ sprintf(buf, "%s", _this->verString[i]);
+ strcat(tmp, buf);
+ }
+
+ ret = PR_Strdup(tmp);
+ free(tmp);
+
+ return ret;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Print
+// Class: Pk11Install_PlatformName
+*/
+void
+Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad)
+{
+ PAD(pad); printf("OS: %s\n", _this->OS ? _this->OS : "<NULL>");
+ PAD(pad); printf("Digits: ");
+ if(_this->numDigits == 0) {
+ printf("None\n");
+ } else {
+ printf("%s\n", Pk11Install_PlatformName_GetVerString(_this));
+ }
+ PAD(pad); printf("arch: %s\n", _this->arch ? _this->arch : "<NULL>");
+}
+
+Pk11Install_Platform*
+Pk11Install_Platform_new()
+{
+ Pk11Install_Platform* new_this;
+ new_this = (Pk11Install_Platform*)PR_Malloc(sizeof(Pk11Install_Platform));
+ Pk11Install_Platform_init(new_this);
+ return new_this;
+}
+
+void
+Pk11Install_Platform_init(Pk11Install_Platform* _this)
+{
+ Pk11Install_PlatformName_init(&_this->name);
+ Pk11Install_PlatformName_init(&_this->equivName);
+ _this->equiv = NULL;
+ _this->usesEquiv = PR_FALSE;
+ _this->moduleFile = NULL;
+ _this->moduleName = NULL;
+ _this->modFile = -1;
+ _this->mechFlags = 0;
+ _this->cipherFlags = 0;
+ _this->files = NULL;
+ _this->numFiles = 0;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: ~Pk11Install_Platform
+// Class: Pk11Install_Platform
+*/
+void
+Pk11Install_Platform_delete(Pk11Install_Platform* _this)
+{
+ Pk11Install_Platform_Cleanup(_this);
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Cleanup
+// Class: Pk11Install_Platform
+*/
+void
+Pk11Install_Platform_Cleanup(Pk11Install_Platform* _this)
+{
+ int i;
+ if(_this->moduleFile) {
+ PR_Free(_this->moduleFile);
+ _this->moduleFile = NULL;
+ }
+ if(_this->moduleName) {
+ PR_Free(_this->moduleName);
+ _this->moduleName = NULL;
+ }
+ if(_this->files) {
+ for (i=0;i<_this->numFiles;i++) {
+ Pk11Install_File_delete(&_this->files[i]);
+ }
+ PR_Free(_this->files);
+ _this->files = NULL;
+ }
+ _this->equiv = NULL;
+ _this->usesEquiv = PR_FALSE;
+ _this->modFile = -1;
+ _this->numFiles = 0;
+ _this->mechFlags = _this->cipherFlags = 0;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Generate
+// Class: Pk11Install_Platform
+// Notes: Creates a platform data structure from a syntax tree.
+// Returns: NULL for success, otherwise an error message.
+*/
+char*
+Pk11Install_Platform_Generate(Pk11Install_Platform* _this,
+ const Pk11Install_Pair *pair)
+{
+ char* errStr;
+ char* endptr;
+ char* tmp;
+ int i;
+ Pk11Install_ListIter *iter;
+ Pk11Install_Value *val;
+ Pk11Install_Value *subval;
+ Pk11Install_Pair *subpair;
+ Pk11Install_ListIter *subiter;
+ PRBool gotModuleFile, gotModuleName, gotMech,
+ gotCipher, gotFiles, gotEquiv;
+
+ errStr=NULL;
+ iter=subiter=NULL;
+ val=subval=NULL;
+ subpair=NULL;
+ gotModuleFile=gotModuleName=gotMech=gotCipher=gotFiles=gotEquiv=PR_FALSE;
+ Pk11Install_Platform_Cleanup(_this);
+
+ errStr = Pk11Install_PlatformName_Generate(&_this->name,pair->key);
+ if(errStr) {
+ tmp = PR_smprintf("%s: %s", pair->key, errStr);
+ PR_smprintf_free(errStr);
+ errStr = tmp;
+ goto loser;
+ }
+
+ iter = Pk11Install_ListIter_new(pair->list);
+ for( ; (val=iter->current); Pk11Install_ListIter_nextItem(iter)) {
+ if(val->type==PAIR_VALUE) {
+ subpair = val->pair;
+
+ if( !PORT_Strcasecmp(subpair->key, MODULE_FILE_STRING)) {
+ if(gotModuleFile) {
+ errStr = PR_smprintf(errString[REPEAT_MODULE_FILE],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if(!subval || (subval->type != STRING_VALUE)) {
+ errStr = PR_smprintf(errString[BOGUS_MODULE_FILE],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ _this->moduleFile = PR_Strdup(subval->string);
+ Pk11Install_ListIter_delete(subiter);
+ PR_Free(subiter);
+ subiter = NULL;
+ gotModuleFile = PR_TRUE;
+ } else if(!PORT_Strcasecmp(subpair->key, MODULE_NAME_STRING)){
+ if(gotModuleName) {
+ errStr = PR_smprintf(errString[REPEAT_MODULE_NAME],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if(!subval || (subval->type != STRING_VALUE)) {
+ errStr = PR_smprintf(errString[BOGUS_MODULE_NAME],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ _this->moduleName = PR_Strdup(subval->string);
+ Pk11Install_ListIter_delete(subiter);
+ PR_Free(subiter);
+ subiter = NULL;
+ gotModuleName = PR_TRUE;
+ } else if(!PORT_Strcasecmp(subpair->key, MECH_FLAGS_STRING)) {
+ endptr=NULL;
+
+ if(gotMech) {
+ errStr = PR_smprintf(errString[REPEAT_MECH],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if(!subval || (subval->type != STRING_VALUE)) {
+ errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ _this->mechFlags = strtol(subval->string, &endptr, 0);
+ if(*endptr!='\0' || (endptr==subval->string) ) {
+ errStr = PR_smprintf(errString[BOGUS_MECH_FLAGS],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ Pk11Install_ListIter_delete(subiter);
+ PR_Free(subiter);
+ subiter=NULL;
+ gotMech = PR_TRUE;
+ } else if(!PORT_Strcasecmp(subpair->key,CIPHER_FLAGS_STRING)) {
+ endptr=NULL;
+
+ if(gotCipher) {
+ errStr = PR_smprintf(errString[REPEAT_CIPHER],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if(!subval || (subval->type != STRING_VALUE)) {
+ errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ _this->cipherFlags = strtol(subval->string, &endptr, 0);
+ if(*endptr!='\0' || (endptr==subval->string) ) {
+ errStr = PR_smprintf(errString[BOGUS_CIPHER_FLAGS],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ Pk11Install_ListIter_delete(subiter);
+ PR_Free(subiter);
+ subiter=NULL;
+ gotCipher = PR_TRUE;
+ } else if(!PORT_Strcasecmp(subpair->key, FILES_STRING)) {
+ if(gotFiles) {
+ errStr = PR_smprintf(errString[REPEAT_FILES],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ _this->numFiles = subpair->list->numPairs;
+ _this->files = (Pk11Install_File*)
+ PR_Malloc(sizeof(Pk11Install_File)*_this->numFiles);
+ for(i=0; i < _this->numFiles; i++,
+ Pk11Install_ListIter_nextItem(subiter)) {
+ Pk11Install_File_init(&_this->files[i]);
+ val = subiter->current;
+ if(val && (val->type==PAIR_VALUE)) {
+ errStr = Pk11Install_File_Generate(&_this->files[i],val->pair);
+ if(errStr) {
+ tmp = PR_smprintf("%s: %s",
+ Pk11Install_PlatformName_GetString(&_this->name),errStr);
+ PR_smprintf_free(errStr);
+ errStr = tmp;
+ goto loser;
+ }
+ }
+ }
+ gotFiles = PR_TRUE;
+ } else if(!PORT_Strcasecmp(subpair->key,
+ EQUIVALENT_PLATFORM_STRING)) {
+ if(gotEquiv) {
+ errStr = PR_smprintf(errString[REPEAT_EQUIV],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ subiter = Pk11Install_ListIter_new(subpair->list);
+ subval = subiter->current;
+ if(!subval || (subval->type != STRING_VALUE) ) {
+ errStr = PR_smprintf(errString[BOGUS_EQUIV],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ errStr = Pk11Install_PlatformName_Generate(&_this->equivName,
+ subval->string);
+ if(errStr) {
+ tmp = PR_smprintf("%s: %s",
+ Pk11Install_PlatformName_GetString(&_this->name), errStr);
+ tmp = PR_smprintf("%s: %s",
+ Pk11Install_PlatformName_GetString(&_this->name), errStr);
+ PR_smprintf_free(errStr);
+ errStr = tmp;
+ goto loser;
+ }
+ _this->usesEquiv = PR_TRUE;
+ }
+ }
+ }
+
+ /* Make sure we either have an EquivalentPlatform or all the other info */
+ if(_this->usesEquiv &&
+ (gotFiles || gotModuleFile || gotModuleName || gotMech || gotCipher)) {
+ errStr = PR_smprintf(errString[EQUIV_TOO_MUCH_INFO],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ if(!gotFiles && !_this->usesEquiv) {
+ errStr = PR_smprintf(errString[NO_FILES],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ if(!gotModuleFile && !_this->usesEquiv) {
+ errStr= PR_smprintf(errString[NO_MODULE_FILE],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ if(!gotModuleName && !_this->usesEquiv) {
+ errStr = PR_smprintf(errString[NO_MODULE_NAME],
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+
+ /* Point the modFile pointer to the correct file */
+ if(gotModuleFile) {
+ for(i=0; i < _this->numFiles; i++) {
+ if(!PORT_Strcasecmp(_this->moduleFile, _this->files[i].jarPath) ) {
+ _this->modFile = i;
+ break;
+ }
+ }
+ if(_this->modFile==-1) {
+ errStr = PR_smprintf(errString[UNKNOWN_MODULE_FILE],
+ _this->moduleFile,
+ Pk11Install_PlatformName_GetString(&_this->name));
+ goto loser;
+ }
+ }
+
+loser:
+ if(iter) {
+ PR_Free(iter);
+ }
+ if(subiter) {
+ PR_Free(subiter);
+ }
+ return errStr;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Print
+// Class: Pk11Install_Platform
+*/
+void
+Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad)
+{
+ int i;
+
+ PAD(pad); printf("Name:\n");
+ Pk11Install_PlatformName_Print(&_this->name,pad+PADINC);
+ PAD(pad); printf("equivName:\n");
+ Pk11Install_PlatformName_Print(&_this->equivName,pad+PADINC);
+ PAD(pad);
+ if(_this->usesEquiv) {
+ printf("Uses equiv, which points to:\n");
+ Pk11Install_Platform_Print(_this->equiv,pad+PADINC);
+ } else {
+ printf("Doesn't use equiv\n");
+ }
+ PAD(pad);
+ printf("Module File: %s\n", _this->moduleFile ? _this->moduleFile
+ : "<NULL>");
+ PAD(pad); printf("mechFlags: %lx\n", _this->mechFlags);
+ PAD(pad); printf("cipherFlags: %lx\n", _this->cipherFlags);
+ PAD(pad); printf("Files:\n");
+ for(i=0; i < _this->numFiles; i++) {
+ Pk11Install_File_Print(&_this->files[i],pad+PADINC);
+ PAD(pad); printf("--------------------\n");
+ }
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Pk11Install_Info
+// Class: Pk11Install_Info
+*/
+Pk11Install_Info*
+Pk11Install_Info_new()
+{
+ Pk11Install_Info* new_this;
+ new_this = (Pk11Install_Info*)PR_Malloc(sizeof(Pk11Install_Info));
+ Pk11Install_Info_init(new_this);
+ return new_this;
+}
+
+void
+Pk11Install_Info_init(Pk11Install_Info* _this)
+{
+ _this->platforms = NULL;
+ _this->numPlatforms = 0;
+ _this->forwardCompatible = NULL;
+ _this->numForwardCompatible = 0;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: ~Pk11Install_Info
+// Class: Pk11Install_Info
+*/
+void
+Pk11Install_Info_delete(Pk11Install_Info* _this)
+{
+ Pk11Install_Info_Cleanup(_this);
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Cleanup
+// Class: Pk11Install_Info
+*/
+void
+Pk11Install_Info_Cleanup(Pk11Install_Info* _this)
+{
+ int i;
+ if(_this->platforms) {
+ for (i=0;i<_this->numPlatforms;i++) {
+ Pk11Install_Platform_delete(&_this->platforms[i]);
+ }
+ PR_Free(&_this->platforms);
+ _this->platforms = NULL;
+ _this->numPlatforms = 0;
+ }
+
+ if(_this->forwardCompatible) {
+ for (i=0;i<_this->numForwardCompatible;i++) {
+ Pk11Install_PlatformName_delete(&_this->forwardCompatible[i]);
+ }
+ PR_Free(&_this->forwardCompatible);
+ _this->numForwardCompatible = 0;
+ }
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Generate
+// Class: Pk11Install_Info
+// Takes: Pk11Install_ValueList *list, the top-level list
+// resulting from parsing an installer file.
+// Returns: char*, NULL if successful, otherwise an error string.
+// Caller is responsible for freeing memory.
+*/
+char*
+Pk11Install_Info_Generate(Pk11Install_Info* _this,
+ const Pk11Install_ValueList *list)
+{
+ char *errStr;
+ Pk11Install_ListIter *iter;
+ Pk11Install_Value *val;
+ Pk11Install_Pair *pair;
+ Pk11Install_ListIter *subiter;
+ Pk11Install_Value *subval;
+ Pk11Install_Platform *first, *second;
+ int i, j;
+
+ errStr=NULL;
+ iter=subiter=NULL;
+ Pk11Install_Info_Cleanup(_this);
+
+ iter = Pk11Install_ListIter_new(list);
+ for( ; (val=iter->current); Pk11Install_ListIter_nextItem(iter)) {
+ if(val->type == PAIR_VALUE) {
+ pair = val->pair;
+
+ if(!PORT_Strcasecmp(pair->key, FORWARD_COMPATIBLE_STRING)) {
+ subiter = Pk11Install_ListIter_new(pair->list);
+ _this->numForwardCompatible = pair->list->numStrings;
+ _this->forwardCompatible = (Pk11Install_PlatformName*)
+ PR_Malloc(sizeof(Pk11Install_PlatformName)*
+ _this->numForwardCompatible);
+ for(i=0; i < _this->numForwardCompatible; i++,
+ Pk11Install_ListIter_nextItem(subiter)) {
+ subval = subiter->current;
+ if(subval->type == STRING_VALUE) {
+ errStr = Pk11Install_PlatformName_Generate(
+ &_this->forwardCompatible[i], subval->string);
+ if(errStr) {
+ goto loser;
+ }
+ }
+ }
+ Pk11Install_ListIter_delete(subiter);
+ PR_Free(subiter);
+ subiter = NULL;
+ } else if(!PORT_Strcasecmp(pair->key, PLATFORMS_STRING)) {
+ subiter = Pk11Install_ListIter_new(pair->list);
+ _this->numPlatforms = pair->list->numPairs;
+ _this->platforms = (Pk11Install_Platform*)
+ PR_Malloc(sizeof(Pk11Install_Platform)*
+ _this->numPlatforms);
+ for(i=0; i < _this->numPlatforms; i++,
+ Pk11Install_ListIter_nextItem(subiter)) {
+ Pk11Install_Platform_init(&_this->platforms[i]);
+ subval = subiter->current;
+ if(subval->type == PAIR_VALUE) {
+ errStr = Pk11Install_Platform_Generate(&_this->platforms[i],subval->pair);
+ if(errStr) {
+ goto loser;
+ }
+ }
+ }
+ Pk11Install_ListIter_delete(subiter);
+ PR_Free(subiter);
+ subiter = NULL;
+ }
+ }
+ }
+
+ if(_this->numPlatforms == 0) {
+ errStr = PR_smprintf(errString[NO_PLATFORMS]);
+ goto loser;
+ }
+
+/*
+ //
+ // Now process equivalent platforms
+ //
+
+ // First the naive pass
+*/
+ for(i=0; i < _this->numPlatforms; i++) {
+ if(_this->platforms[i].usesEquiv) {
+ _this->platforms[i].equiv = NULL;
+ for(j=0; j < _this->numPlatforms; j++) {
+ if (Pk11Install_PlatformName_equal(&_this->platforms[i].equivName,
+ &_this->platforms[j].name)) {
+ if(i==j) {
+ errStr = PR_smprintf(errString[EQUIV_LOOP],
+ Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
+ goto loser;
+ }
+ _this->platforms[i].equiv = &_this->platforms[j];
+ break;
+ }
+ }
+ if(_this->platforms[i].equiv == NULL) {
+ errStr = PR_smprintf(errString[BOGUS_EQUIV],
+ Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
+ goto loser;
+ }
+ }
+ }
+
+/*
+ // Now the intelligent pass, which will also detect loops.
+ // We will send two pointers through the linked list of equivalent
+ // platforms. Both start with the current node. "first" traverses
+ // two nodes for each iteration. "second" lags behind, only traversing
+ // one node per iteration. Eventually one of two things will happen:
+ // first will hit the end of the list (a platform that doesn't use
+ // an equivalency), or first will equal second if there is a loop.
+*/
+ for(i=0; i < _this->numPlatforms; i++) {
+ if(_this->platforms[i].usesEquiv) {
+ second = _this->platforms[i].equiv;
+ if(!second->usesEquiv) {
+ /* The first link is the terminal node */
+ continue;
+ }
+ first = second->equiv;
+ while(first->usesEquiv) {
+ if(first == second) {
+ errStr = PR_smprintf(errString[EQUIV_LOOP],
+ Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
+ goto loser;
+ }
+ first = first->equiv;
+ if(!first->usesEquiv) {
+ break;
+ }
+ if(first == second) {
+ errStr = PR_smprintf(errString[EQUIV_LOOP],
+ Pk11Install_PlatformName_GetString(&_this->platforms[i].name));
+ goto loser;
+ }
+ second = second->equiv;
+ first = first->equiv;
+ }
+ _this->platforms[i].equiv = first;
+ }
+ }
+
+loser:
+ if(iter) {
+ Pk11Install_ListIter_delete(iter);
+ PR_Free(iter);
+ iter = NULL;
+ }
+ if(subiter) {
+ Pk11Install_ListIter_delete(subiter);
+ PR_Free(subiter);
+ subiter = NULL;
+ }
+ return errStr;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: GetBestPlatform
+// Class: Pk11Install_Info
+// Takes: char *myPlatform, the platform we are currently running
+// on.
+*/
+Pk11Install_Platform*
+Pk11Install_Info_GetBestPlatform(Pk11Install_Info* _this, char *myPlatform)
+{
+ Pk11Install_PlatformName plat;
+ char *errStr;
+ int i, j;
+
+ errStr=NULL;
+
+ Pk11Install_PlatformName_init(&plat);
+ if( (errStr=Pk11Install_PlatformName_Generate(&plat, myPlatform)) ) {
+ PR_smprintf_free(errStr);
+ return NULL;
+ }
+
+ /* First try real platforms */
+ for(i=0; i < _this->numPlatforms; i++) {
+ if(Pk11Install_PlatformName_equal(&_this->platforms[i].name,&plat)) {
+ if(_this->platforms[i].equiv) {
+ return _this->platforms[i].equiv;
+ }
+ else {
+ return &_this->platforms[i];
+ }
+ }
+ }
+
+ /* Now try forward compatible platforms */
+ for(i=0; i < _this->numForwardCompatible; i++) {
+ if(Pk11Install_PlatformName_lteq(&_this->forwardCompatible[i],&plat)) {
+ break;
+ }
+ }
+ if(i == _this->numForwardCompatible) {
+ return NULL;
+ }
+
+ /* Got a forward compatible name, find the actual platform. */
+ for(j=0; j < _this->numPlatforms; j++) {
+ if(Pk11Install_PlatformName_equal(&_this->platforms[j].name,
+ &_this->forwardCompatible[i])) {
+ if(_this->platforms[j].equiv) {
+ return _this->platforms[j].equiv;
+ } else {
+ return &_this->platforms[j];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Method: Print
+// Class: Pk11Install_Info
+*/
+void
+Pk11Install_Info_Print(Pk11Install_Info* _this, int pad)
+{
+ int i;
+
+ PAD(pad); printf("Forward Compatible:\n");
+ for(i = 0; i < _this->numForwardCompatible; i++) {
+ Pk11Install_PlatformName_Print(&_this->forwardCompatible[i],pad+PADINC);
+ PAD(pad); printf("-------------------\n");
+ }
+ PAD(pad); printf("Platforms:\n");
+ for( i = 0; i < _this->numPlatforms; i++) {
+ Pk11Install_Platform_Print(&_this->platforms[i],pad+PADINC);
+ PAD(pad); printf("-------------------\n");
+ }
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+*/
+static char*
+PR_Strdup(const char* str)
+{
+ char *tmp;
+ tmp = (char*) PR_Malloc((unsigned int)(strlen(str)+1));
+ strcpy(tmp, str);
+ return tmp;
+}
+
+/* The global value list, the top of the tree */
+Pk11Install_ValueList* Pk11Install_valueList=NULL;
+
+/****************************************************************************/
+void
+Pk11Install_ValueList_AddItem(Pk11Install_ValueList* _this,
+ Pk11Install_Value *item)
+{
+ _this->numItems++;
+ if (item->type == STRING_VALUE) {
+ _this->numStrings++;
+ } else {
+ _this->numPairs++;
+ }
+ item->next = _this->head;
+ _this->head = item;
+}
+
+/****************************************************************************/
+Pk11Install_ListIter*
+Pk11Install_ListIter_new_default()
+{
+ Pk11Install_ListIter* new_this;
+ new_this = (Pk11Install_ListIter*)
+ PR_Malloc(sizeof(Pk11Install_ListIter));
+ Pk11Install_ListIter_init(new_this);
+ return new_this;
+}
+
+/****************************************************************************/
+void
+Pk11Install_ListIter_init(Pk11Install_ListIter* _this)
+{
+ _this->list = NULL;
+ _this->current = NULL;
+}
+
+/****************************************************************************/
+Pk11Install_ListIter*
+Pk11Install_ListIter_new(const Pk11Install_ValueList *_list)
+{
+ Pk11Install_ListIter* new_this;
+ new_this = (Pk11Install_ListIter*)
+ PR_Malloc(sizeof(Pk11Install_ListIter));
+ new_this->list = _list;
+ new_this->current = _list->head;
+ return new_this;
+}
+
+/****************************************************************************/
+void
+Pk11Install_ListIter_delete(Pk11Install_ListIter* _this)
+{
+ _this->list=NULL;
+ _this->current=NULL;
+}
+
+/****************************************************************************/
+void
+Pk11Install_ListIter_reset(Pk11Install_ListIter* _this)
+{
+ if(_this->list) {
+ _this->current = _this->list->head;
+ }
+}
+
+/*************************************************************************/
+Pk11Install_Value*
+Pk11Install_ListIter_nextItem(Pk11Install_ListIter* _this)
+{
+ if(_this->current) {
+ _this->current = _this->current->next;
+ }
+
+ return _this->current;
+}
+
+/****************************************************************************/
+Pk11Install_ValueList*
+Pk11Install_ValueList_new()
+{
+ Pk11Install_ValueList* new_this;
+ new_this = (Pk11Install_ValueList*)
+ PR_Malloc(sizeof(Pk11Install_ValueList));
+ new_this->numItems = 0;
+ new_this->numPairs = 0;
+ new_this->numStrings = 0;
+ new_this->head = NULL;
+ return new_this;
+}
+
+/****************************************************************************/
+void
+Pk11Install_ValueList_delete(Pk11Install_ValueList* _this)
+{
+
+ Pk11Install_Value *tmp;
+ Pk11Install_Value *list;
+ list = _this->head;
+
+ while(list != NULL) {
+ tmp = list;
+ list = list->next;
+ PR_Free(tmp);
+ }
+ PR_Free(_this);
+}
+
+/****************************************************************************/
+Pk11Install_Value*
+Pk11Install_Value_new_default()
+{
+ Pk11Install_Value* new_this;
+ new_this = (Pk11Install_Value*)PR_Malloc(sizeof(Pk11Install_Value));
+ new_this->type = STRING_VALUE;
+ new_this->string = NULL;
+ new_this->pair = NULL;
+ new_this->next = NULL;
+ return new_this;
+}
+
+/****************************************************************************/
+Pk11Install_Value*
+Pk11Install_Value_new(ValueType _type, Pk11Install_Pointer ptr)
+{
+ Pk11Install_Value* new_this;
+ new_this = Pk11Install_Value_new_default();
+ new_this->type = _type;
+ if(_type == STRING_VALUE) {
+ new_this->pair = NULL;
+ new_this->string = ptr.string;
+ } else {
+ new_this->string = NULL;
+ new_this->pair = ptr.pair;
+ }
+ return new_this;
+}
+
+/****************************************************************************/
+void
+Pk11Install_Value_delete(Pk11Install_Value* _this)
+{
+ if(_this->type == STRING_VALUE) {
+ PR_Free(_this->string);
+ } else {
+ PR_Free(_this->pair);
+ }
+}
+
+/****************************************************************************/
+Pk11Install_Pair*
+Pk11Install_Pair_new_default()
+{
+ return Pk11Install_Pair_new(NULL,NULL);
+}
+
+/****************************************************************************/
+Pk11Install_Pair*
+Pk11Install_Pair_new(char *_key, Pk11Install_ValueList *_list)
+{
+ Pk11Install_Pair* new_this;
+ new_this = (Pk11Install_Pair*)PR_Malloc(sizeof(Pk11Install_Pair));
+ new_this->key = _key;
+ new_this->list = _list;
+ return new_this;
+}
+
+/****************************************************************************/
+void
+Pk11Install_Pair_delete(Pk11Install_Pair* _this)
+{
+ PR_Free(_this->key);
+ Pk11Install_ValueList_delete(_this->list);
+ PR_Free(_this->list);
+}
+
+/*************************************************************************/
+void
+Pk11Install_Pair_Print(Pk11Install_Pair* _this, int pad)
+{
+ while (_this) {
+ /*PAD(pad); printf("**Pair\n");
+ PAD(pad); printf("***Key====\n");*/
+ PAD(pad); printf("%s {\n", _this->key);
+ /*PAD(pad); printf("====\n");*/
+ /*PAD(pad); printf("***ValueList\n");*/
+ Pk11Install_ValueList_Print(_this->list,pad+PADINC);
+ PAD(pad); printf("}\n");
+ }
+}
+
+/*************************************************************************/
+void
+Pk11Install_ValueList_Print(Pk11Install_ValueList* _this, int pad)
+{
+ Pk11Install_Value *v;
+
+ /*PAD(pad);printf("**Value List**\n");*/
+ for(v = _this->head; v != NULL; v=v->next) {
+ Pk11Install_Value_Print(v,pad);
+ }
+}
+
+/*************************************************************************/
+void
+Pk11Install_Value_Print(Pk11Install_Value* _this, int pad)
+{
+ /*PAD(pad); printf("**Value, type=%s\n",
+ type==STRING_VALUE ? "string" : "pair");*/
+ if(_this->type==STRING_VALUE) {
+ /*PAD(pad+PADINC); printf("====\n");*/
+ PAD(pad); printf("%s\n", _this->string);
+ /*PAD(pad+PADINC); printf("====\n");*/
+ } else {
+ Pk11Install_Pair_Print(_this->pair,pad+PADINC);
+ }
+}
diff --git a/security/nss/cmd/modutil/install-ds.h b/security/nss/cmd/modutil/install-ds.h
new file mode 100644
index 000000000..2311f0928
--- /dev/null
+++ b/security/nss/cmd/modutil/install-ds.h
@@ -0,0 +1,290 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifndef INSTALL_DS_H
+#define INSTALL_DS_H
+
+#include <stdio.h>
+#include <prio.h>
+#include <prmem.h>
+
+extern PRFileDesc *Pk11Install_FD;
+extern int Pk11Install_yylex();
+extern int Pk11Install_yylinenum;
+extern char *Pk11Install_yyerrstr;
+
+typedef enum { STRING_VALUE, PAIR_VALUE } ValueType;
+
+typedef struct Pk11Install_Pair_str Pk11Install_Pair;
+typedef union Pk11Install_Pointer_str Pk11Install_Pointer;
+typedef struct Pk11Install_Value_str Pk11Install_Value;
+typedef struct Pk11Install_ValueList_str Pk11Install_ValueList;
+typedef struct Pk11Install_ListIter_str Pk11Install_ListIter;
+typedef struct Pk11Install_File_str Pk11Install_File;
+typedef struct Pk11Install_PlatformName_str Pk11Install_PlatformName;
+typedef struct Pk11Install_Platform_str Pk11Install_Platform;
+typedef struct Pk11Install_Info_str Pk11Install_Info;
+
+extern Pk11Install_Pointer Pk11Install_yylval;
+extern Pk11Install_ValueList* Pk11Install_valueList;
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Pk11Install_Pair
+//////////////////////////////////////////////////////////////////////////
+*/
+
+struct Pk11Install_Pair_str {
+ char * key;
+ Pk11Install_ValueList *list;
+
+};
+
+Pk11Install_Pair*
+Pk11Install_Pair_new_default();
+Pk11Install_Pair*
+Pk11Install_Pair_new( char* _key, Pk11Install_ValueList* _list);
+void
+Pk11Install_Pair_delete(Pk11Install_Pair* _this);
+void
+Pk11Install_Pair_Print(Pk11Install_Pair* _this, int pad);
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Pk11Install_Pointer
+//////////////////////////////////////////////////////////////////////////
+*/
+union Pk11Install_Pointer_str {
+ Pk11Install_ValueList *list;
+ Pk11Install_Value *value;
+ Pk11Install_Pair *pair;
+ char *string;
+};
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Pk11Install_Value
+//////////////////////////////////////////////////////////////////////////
+*/
+struct Pk11Install_Value_str {
+
+ ValueType type;
+ char *string;
+ Pk11Install_Pair *pair;
+ struct Pk11Install_Value_str *next;
+};
+
+Pk11Install_Value*
+Pk11Install_Value_new_default();
+Pk11Install_Value*
+Pk11Install_Value_new(ValueType _type, Pk11Install_Pointer ptr);
+void
+Pk11Install_Value_delete(Pk11Install_Value* _this);
+void
+Pk11Install_Value_Print(Pk11Install_Value* _this, int pad);
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Pk11Install_ValueList
+//////////////////////////////////////////////////////////////////////////
+*/
+struct Pk11Install_ValueList_str {
+ int numItems;
+ int numPairs;
+ int numStrings;
+ Pk11Install_Value *head;
+};
+
+Pk11Install_ValueList*
+Pk11Install_ValueList_new();
+void
+Pk11Install_ValueList_delete(Pk11Install_ValueList* _this);
+void
+Pk11Install_ValueList_AddItem(Pk11Install_ValueList* _this,
+ Pk11Install_Value* item);
+void
+Pk11Install_ValueList_Print(Pk11Install_ValueList* _this, int pad);
+
+
+/*
+//////////////////////////////////////////////////////////////////////////
+// Pk11Install_ListIter
+//////////////////////////////////////////////////////////////////////////
+*/
+struct Pk11Install_ListIter_str {
+ const Pk11Install_ValueList *list;
+ Pk11Install_Value *current;
+};
+
+Pk11Install_ListIter*
+Pk11Install_ListIter_new_default();
+void
+Pk11Install_ListIter_init(Pk11Install_ListIter* _this);
+Pk11Install_ListIter*
+Pk11Install_ListIter_new(const Pk11Install_ValueList* _list);
+void
+Pk11Install_ListIter_delete(Pk11Install_ListIter* _this);
+void
+Pk11Install_ListIter_reset(Pk11Install_ListIter* _this);
+Pk11Install_Value*
+Pk11Install_ListIter_nextItem(Pk11Install_ListIter* _this);
+
+/************************************************************************
+ *
+ * Pk11Install_File
+ */
+struct Pk11Install_File_str {
+ char *jarPath;
+ char *relativePath;
+ char *absolutePath;
+ PRBool executable;
+ int permissions;
+};
+
+Pk11Install_File*
+Pk11Install_File_new();
+void
+Pk11Install_File_init(Pk11Install_File* _this);
+void
+Pk11Install_file_delete(Pk11Install_File* _this);
+/*// Parses a syntax tree to obtain all attributes.
+// Returns NULL for success, error message if parse error.*/
+char*
+Pk11Install_File_Generate(Pk11Install_File* _this,
+ const Pk11Install_Pair* pair);
+void
+Pk11Install_File_Print(Pk11Install_File* _this, int pad);
+void
+Pk11Install_File_Cleanup(Pk11Install_File* _this);
+
+/************************************************************************
+ *
+ * Pk11Install_PlatformName
+ */
+struct Pk11Install_PlatformName_str {
+ char *OS;
+ char **verString;
+ int numDigits;
+ char *arch;
+};
+
+Pk11Install_PlatformName*
+Pk11Install_PlatformName_new();
+void
+Pk11Install_PlatformName_init(Pk11Install_PlatformName* _this);
+void
+Pk11Install_PlatformName_delete(Pk11Install_PlatformName* _this);
+char*
+Pk11Install_PlatformName_Generate(Pk11Install_PlatformName* _this,
+ const char* str);
+char*
+Pk11Install_PlatformName_GetString(Pk11Install_PlatformName* _this);
+char*
+Pk11Install_PlatformName_GetVerString(Pk11Install_PlatformName* _this);
+void
+Pk11Install_PlatformName_Print(Pk11Install_PlatformName* _this, int pad);
+void
+Pk11Install_PlatformName_Cleanup(Pk11Install_PlatformName* _this);
+PRBool
+Pk11Install_PlatformName_equal(Pk11Install_PlatformName* _this,
+ Pk11Install_PlatformName* cmp);
+PRBool
+Pk11Install_PlatformName_lteq(Pk11Install_PlatformName* _this,
+ Pk11Install_PlatformName* cmp);
+PRBool
+Pk11Install_PlatformName_lt(Pk11Install_PlatformName* _this,
+ Pk11Install_PlatformName* cmp);
+
+/************************************************************************
+ *
+ * Pk11Install_Platform
+ */
+struct Pk11Install_Platform_str {
+ Pk11Install_PlatformName name;
+ Pk11Install_PlatformName equivName;
+ struct Pk11Install_Platform_str *equiv;
+ PRBool usesEquiv;
+ char *moduleFile;
+ char *moduleName;
+ int modFile;
+ unsigned long mechFlags;
+ unsigned long cipherFlags;
+ Pk11Install_File *files;
+ int numFiles;
+};
+
+Pk11Install_Platform*
+Pk11Install_Platform_new();
+void
+Pk11Install_Platform_init(Pk11Install_Platform* _this);
+void
+Pk11Install_Platform_delete(Pk11Install_Platform* _this);
+/*// Returns NULL for success, error message if parse error.*/
+char*
+Pk11Install_Platform_Generate(Pk11Install_Platform* _this,
+ const Pk11Install_Pair *pair);
+void
+Pk11Install_Platform_Print(Pk11Install_Platform* _this, int pad);
+void
+Pk11Install_Platform_Cleanup(Pk11Install_Platform* _this);
+
+/************************************************************************
+ *
+ * Pk11Install_Info
+ */
+struct Pk11Install_Info_str {
+ Pk11Install_Platform *platforms;
+ int numPlatforms;
+ Pk11Install_PlatformName *forwardCompatible;
+ int numForwardCompatible;
+};
+
+Pk11Install_Info*
+Pk11Install_Info_new();
+void
+Pk11Install_Info_init();
+void
+Pk11Install_Info_delete(Pk11Install_Info* _this);
+/*// Returns NULL for success, error message if parse error.*/
+char*
+Pk11Install_Info_Generate(Pk11Install_Info* _this,
+ const Pk11Install_ValueList *list);
+ /*// Returns NULL if there is no matching platform*/
+Pk11Install_Platform*
+Pk11Install_Info_GetBestPlatform(Pk11Install_Info* _this, char* myPlatform);
+void
+Pk11Install_Info_Print(Pk11Install_Info* _this, int pad);
+void
+Pk11Install_Info_Cleanup(Pk11Install_Info* _this);
+
+#endif /* INSTALL_DS_H */
diff --git a/security/nss/cmd/modutil/install.c b/security/nss/cmd/modutil/install.c
new file mode 100644
index 000000000..c6f55be01
--- /dev/null
+++ b/security/nss/cmd/modutil/install.c
@@ -0,0 +1,985 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "install.h"
+#include "install-ds.h"
+#include <prlock.h>
+#include <prio.h>
+#include <prmem.h>
+#include <prprf.h>
+#include <prsystem.h>
+#include <prproces.h>
+
+#ifdef XP_UNIX
+/* for chmod */
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+/*extern "C" {*/
+#include <jar.h>
+/*}*/
+
+extern /*"C"*/
+int Pk11Install_AddNewModule(char* moduleName, char* dllPath,
+ unsigned long defaultMechanismFlags,
+ unsigned long cipherEnableFlags);
+extern /*"C"*/
+short Pk11Install_UserVerifyJar(JAR *jar, PRFileDesc *out,
+ PRBool query);
+extern /*"C"*/
+const char* mySECU_ErrorString(int16);
+extern
+int Pk11Install_yyparse();
+
+#define INSTALL_METAINFO_TAG "Pkcs11_install_script"
+#define SCRIPT_TEMP_FILE "pkcs11inst.tmp"
+#define ROOT_MARKER "%root%"
+#define TEMP_MARKER "%temp%"
+#define PRINTF_ROOT_MARKER "%%root%%"
+#define TEMPORARY_DIRECTORY_NAME "pk11inst.dir"
+#define JAR_BASE_END (JAR_BASE+100)
+
+static PRLock* errorHandlerLock=NULL;
+static Pk11Install_ErrorHandler errorHandler=NULL;
+static char* PR_Strdup(const char* str);
+static int rm_dash_r (char *path);
+static int make_dirs(char *path, int file_perms);
+static int dir_perms(int perms);
+
+static Pk11Install_Error DoInstall(JAR *jar, const char *installDir,
+ const char* tempDir, Pk11Install_Platform *platform,
+ PRFileDesc *feedback, PRBool noverify);
+
+static char *errorString[]= {
+ "Operation was successful", /* PK11_INSTALL_NO_ERROR */
+ "Directory \"%s\" does not exist", /* PK11_INSTALL_DIR_DOESNT_EXIST */
+ "File \"%s\" does not exist", /* PK11_INSTALL_FILE_DOESNT_EXIST */
+ "File \"%s\" is not readable", /* PK11_INSTALL_FILE_NOT_READABLE */
+ "%s", /* PK11_INSTALL_ERROR_STRING */
+ "Error in JAR file %s: %s", /* PK11_INSTALL_JAR_ERROR */
+ "No Pkcs11_install_script specified in JAR metainfo file",
+ /* PK11_INSTALL_NO_INSTALLER_SCRIPT */
+ "Could not delete temporary file \"%s\"",
+ /*PK11_INSTALL_DELETE_TEMP_FILE */
+ "Could not open temporary file \"%s\"", /*PK11_INSTALL_OPEN_SCRIPT_FILE*/
+ "%s: %s", /* PK11_INSTALL_SCRIPT_PARSE */
+ "Error in script: %s",
+ "Unable to obtain system platform information",
+ "Installer script has no information about the current platform (%s)",
+ "Relative directory \"%s\" does not contain "PRINTF_ROOT_MARKER,
+ "Module File \"%s\" not found",
+ "Error occurred installing module \"%s\" into database",
+ "Error extracting \"%s\" from JAR file: %s",
+ "Directory \"%s\" is not writeable",
+ "Could not create directory \"%s\"",
+ "Could not remove directory \"%s\"",
+ "Unable to execute \"%s\"",
+ "Unable to wait for process \"%s\"",
+ "\"%s\" returned error code %d",
+ "User aborted operation",
+ "Unspecified error"
+};
+
+enum {
+ INSTALLED_FILE_MSG=0,
+ INSTALLED_MODULE_MSG,
+ INSTALLER_SCRIPT_NAME,
+ MY_PLATFORM_IS,
+ USING_PLATFORM,
+ PARSED_INSTALL_SCRIPT,
+ EXEC_FILE_MSG,
+ EXEC_SUCCESS,
+ INSTALLATION_COMPLETE_MSG,
+ USER_ABORT
+};
+
+static char *msgStrings[] = {
+ "Installed file %s to %s\n",
+ "Installed module \"%s\" into module database\n",
+ "Using installer script \"%s\"\n",
+ "Current platform is %s\n",
+ "Using installation parameters for platform %s\n",
+ "Successfully parsed installation script\n",
+ "Executing \"%s\"...\n",
+ "\"%s\" executed successfully\n",
+ "\nInstallation completed successfully\n",
+ "\nAborting...\n"
+};
+
+/**************************************************************************
+ * S t r i n g N o d e
+ */
+typedef struct StringNode_str {
+ char *str;
+ struct StringNode_str* next;
+} StringNode;
+
+StringNode* StringNode_new()
+{
+ StringNode* new_this;
+ new_this = (StringNode*)malloc(sizeof(StringNode));
+ new_this->str=NULL;
+ new_this->next=NULL;
+ return new_this;
+}
+
+void StringNode_delete(StringNode* s)
+{
+ if(s->str) {
+ PR_Free(s->str);
+ s->str=NULL;
+ }
+}
+
+/*************************************************************************
+ * S t r i n g L i s t
+ */
+typedef struct StringList_str {
+ StringNode* head;
+ StringNode* tail;
+} StringList;
+
+void StringList_new(StringList* list)
+{
+ list->head=NULL;
+ list->tail=NULL;
+}
+
+void StringList_delete(StringList* list)
+{
+ StringNode *tmp;
+ while(list->head) {
+ tmp = list->head;
+ list->head = list->head->next;
+ StringNode_delete(tmp);
+ }
+}
+
+void
+StringList_Append(StringList* list, char* str)
+{
+ if(!str) {
+ return;
+ }
+
+ if(!list->tail) {
+ /* This is the first element */
+ list->head = list->tail = StringNode_new();
+ } else {
+ list->tail->next = StringNode_new();
+ list->tail = list->tail->next;
+ }
+
+ list->tail->str = PR_Strdup(str);
+ list->tail->next = NULL; /* just to be sure */
+}
+
+/**************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ S e t E r r o r H a n d l e r
+ *
+ * Sets the error handler to be used by the library. Returns the current
+ * error handler function.
+ */
+Pk11Install_ErrorHandler
+Pk11Install_SetErrorHandler(Pk11Install_ErrorHandler handler)
+{
+ Pk11Install_ErrorHandler old;
+
+ if(!errorHandlerLock) {
+ errorHandlerLock = PR_NewLock();
+ }
+
+ PR_Lock(errorHandlerLock);
+
+ old = errorHandler;
+ errorHandler = handler;
+
+ PR_Unlock(errorHandlerLock);
+
+ return old;
+}
+
+/**************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ I n i t
+ *
+ * Does initialization that otherwise would be done on the fly. Only
+ * needs to be called by multithreaded apps, before they make any calls
+ * to this library.
+ */
+void
+Pk11Install_Init()
+{
+ if(!errorHandlerLock) {
+ errorHandlerLock = PR_NewLock();
+ }
+}
+
+/**************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ R e l e a s e
+ *
+ * Releases static data structures used by the library. Don't use the
+ * library after calling this, unless you call Pk11Install_Init()
+ * first. This function doesn't have to be called at all unless you're
+ * really anal about freeing memory before your program exits.
+ */
+void
+Pk11Install_Release()
+{
+ if(errorHandlerLock) {
+ PR_Free(errorHandlerLock);
+ errorHandlerLock = NULL;
+ }
+}
+
+/*************************************************************************
+ *
+ * e r r o r
+ *
+ * Takes an error code and its arguments, creates the error string,
+ * and sends the string to the handler function if it exists.
+ */
+
+#ifdef OSF1
+/* stdarg has already been pulled in from NSPR */
+#undef va_start
+#undef va_end
+#undef va_arg
+#include <varargs.h>
+#else
+#include <stdarg.h>
+#endif
+
+#ifdef OSF1
+static void
+error(long va_alist, ...)
+#else
+static void
+error(Pk11Install_Error errcode, ...)
+#endif
+{
+
+ va_list ap;
+ char *errstr;
+ Pk11Install_ErrorHandler handler;
+
+ if(!errorHandlerLock) {
+ errorHandlerLock = PR_NewLock();
+ }
+
+ PR_Lock(errorHandlerLock);
+
+ handler = errorHandler;
+
+ PR_Unlock(errorHandlerLock);
+
+ if(handler) {
+#ifdef OSF1
+ va_start(ap);
+ errstr = PR_vsmprintf(errorString[va_arg(ap, Pk11Install_Error)], ap);
+#else
+ va_start(ap, errcode);
+ errstr = PR_vsmprintf(errorString[errcode], ap);
+#endif
+ handler(errstr);
+ PR_smprintf_free(errstr);
+ va_end(ap);
+ }
+}
+
+/*************************************************************************
+ *
+ * j a r _ c a l l b a c k
+ */
+static int
+jar_callback(int status, JAR *foo, const char *bar, char *pathname,
+ char *errortext) {
+ char *string;
+
+ string = PR_smprintf("JAR error %d: %s in file %s\n", status, errortext,
+ pathname);
+ error(PK11_INSTALL_ERROR_STRING, string);
+ PR_smprintf_free(string);
+ return 0;
+}
+
+/*************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ D o I n s t a l l
+ *
+ * jarFile is the path of a JAR in the PKCS #11 module JAR format.
+ * installDir is the directory relative to which files will be
+ * installed.
+ */
+Pk11Install_Error
+Pk11Install_DoInstall(char *jarFile, const char *installDir,
+ const char *tempDir, PRFileDesc *feedback, short force, PRBool noverify)
+{
+ JAR *jar;
+ char *installer;
+ unsigned long installer_len;
+ int status;
+ Pk11Install_Error ret;
+ PRBool made_temp_file;
+ Pk11Install_Info installInfo;
+ Pk11Install_Platform *platform;
+ char* errMsg;
+ char sysname[SYS_INFO_BUFFER_LENGTH], release[SYS_INFO_BUFFER_LENGTH],
+ arch[SYS_INFO_BUFFER_LENGTH];
+ char *myPlatform;
+
+ jar=NULL;
+ ret = PK11_INSTALL_UNSPECIFIED;
+ made_temp_file=PR_FALSE;
+ errMsg=NULL;
+ Pk11Install_Info_init(&installInfo);
+
+ /*
+ printf("Inside DoInstall, jarFile=%s, installDir=%s, tempDir=%s\n",
+ jarFile, installDir, tempDir);
+ */
+
+ /*
+ * Check out jarFile and installDir for validity
+ */
+ if( PR_Access(installDir, PR_ACCESS_EXISTS) != PR_SUCCESS ) {
+ error(PK11_INSTALL_DIR_DOESNT_EXIST, installDir);
+ return PK11_INSTALL_DIR_DOESNT_EXIST;
+ }
+ if(!tempDir) {
+ tempDir = ".";
+ }
+ if( PR_Access(tempDir, PR_ACCESS_EXISTS) != PR_SUCCESS ) {
+ error(PK11_INSTALL_DIR_DOESNT_EXIST, tempDir);
+ return PK11_INSTALL_DIR_DOESNT_EXIST;
+ }
+ if( PR_Access(tempDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS ) {
+ error(PK11_INSTALL_DIR_NOT_WRITEABLE, tempDir);
+ return PK11_INSTALL_DIR_NOT_WRITEABLE;
+ }
+ if( (PR_Access(jarFile, PR_ACCESS_EXISTS) != PR_SUCCESS) ) {
+ error(PK11_INSTALL_FILE_DOESNT_EXIST, jarFile);
+ return PK11_INSTALL_FILE_DOESNT_EXIST;
+ }
+ if( PR_Access(jarFile, PR_ACCESS_READ_OK) != PR_SUCCESS ) {
+ error(PK11_INSTALL_FILE_NOT_READABLE, jarFile);
+ return PK11_INSTALL_FILE_NOT_READABLE;
+ }
+
+ /*
+ * Extract the JAR file
+ */
+ jar = JAR_new();
+ JAR_set_callback(JAR_CB_SIGNAL, jar, jar_callback);
+
+ if(noverify) {
+ status = JAR_pass_archive_unverified(jar, jarArchGuess, jarFile, "url");
+ } else {
+ status = JAR_pass_archive(jar, jarArchGuess, jarFile, "url");
+ }
+ if( (status < 0) || (jar->valid < 0) ) {
+ if (status >= JAR_BASE && status <= JAR_BASE_END) {
+ error(PK11_INSTALL_JAR_ERROR, jarFile, JAR_get_error(status));
+ } else {
+ error(PK11_INSTALL_JAR_ERROR, jarFile,
+ mySECU_ErrorString((int16) PORT_GetError()) );
+ }
+ ret=PK11_INSTALL_JAR_ERROR;
+ goto loser;
+ }
+ /*printf("passed the archive\n");*/
+
+ /*
+ * Show the user security information, allow them to abort or continue
+ */
+ if( Pk11Install_UserVerifyJar(jar, PR_STDOUT,
+ force?PR_FALSE:PR_TRUE) && !force) {
+ if(feedback) {
+ PR_fprintf(feedback, msgStrings[USER_ABORT]);
+ }
+ ret=PK11_INSTALL_USER_ABORT;
+ goto loser;
+ }
+
+ /*
+ * Get the name of the installation file
+ */
+ if( JAR_get_metainfo(jar, NULL, INSTALL_METAINFO_TAG, (void**)&installer,
+ (unsigned long*)&installer_len) ) {
+ error(PK11_INSTALL_NO_INSTALLER_SCRIPT);
+ ret=PK11_INSTALL_NO_INSTALLER_SCRIPT;
+ goto loser;
+ }
+ if(feedback) {
+ PR_fprintf(feedback, msgStrings[INSTALLER_SCRIPT_NAME], installer);
+ }
+
+ /*
+ * Extract the installation file
+ */
+ if( PR_Access(SCRIPT_TEMP_FILE, PR_ACCESS_EXISTS) == PR_SUCCESS) {
+ if( PR_Delete(SCRIPT_TEMP_FILE) != PR_SUCCESS) {
+ error(PK11_INSTALL_DELETE_TEMP_FILE, SCRIPT_TEMP_FILE);
+ ret=PK11_INSTALL_DELETE_TEMP_FILE;
+ goto loser;
+ }
+ }
+ if(noverify) {
+ status = JAR_extract(jar, installer, SCRIPT_TEMP_FILE);
+ } else {
+ status = JAR_verified_extract(jar, installer, SCRIPT_TEMP_FILE);
+ }
+ if(status) {
+ if (status >= JAR_BASE && status <= JAR_BASE_END) {
+ error(PK11_INSTALL_JAR_EXTRACT, installer, JAR_get_error(status));
+ } else {
+ error(PK11_INSTALL_JAR_EXTRACT, installer,
+ mySECU_ErrorString((int16) PORT_GetError()) );
+ }
+ ret = PK11_INSTALL_JAR_EXTRACT;
+ goto loser;
+ } else {
+ made_temp_file = PR_TRUE;
+ }
+
+ /*
+ * Parse the installation file into a syntax tree
+ */
+ Pk11Install_FD = PR_Open(SCRIPT_TEMP_FILE, PR_RDONLY, 0);
+ if(!Pk11Install_FD) {
+ error(PK11_INSTALL_OPEN_SCRIPT_FILE, SCRIPT_TEMP_FILE);
+ ret=PK11_INSTALL_OPEN_SCRIPT_FILE;
+ goto loser;
+ }
+ if(Pk11Install_yyparse()) {
+ error(PK11_INSTALL_SCRIPT_PARSE, installer,
+ Pk11Install_yyerrstr ? Pk11Install_yyerrstr : "");
+ ret=PK11_INSTALL_SCRIPT_PARSE;
+ goto loser;
+ }
+
+#if 0
+ /* for debugging */
+ Pk11Install_valueList->Print(0);
+#endif
+
+ /*
+ * From the syntax tree, build a semantic structure
+ */
+ errMsg = Pk11Install_Info_Generate(&installInfo,Pk11Install_valueList);
+ if(errMsg) {
+ error(PK11_INSTALL_SEMANTIC, errMsg);
+ ret=PK11_INSTALL_SEMANTIC;
+ goto loser;
+ }
+#if 0
+ installInfo.Print(0);
+#endif
+
+ if(feedback) {
+ PR_fprintf(feedback, msgStrings[PARSED_INSTALL_SCRIPT]);
+ }
+
+ /*
+ * Figure out which platform to use
+ */
+ {
+ sysname[0] = release[0] = arch[0] = '\0';
+
+ if( (PR_GetSystemInfo(PR_SI_SYSNAME, sysname, SYS_INFO_BUFFER_LENGTH)
+ != PR_SUCCESS) ||
+ (PR_GetSystemInfo(PR_SI_RELEASE, release, SYS_INFO_BUFFER_LENGTH)
+ != PR_SUCCESS) ||
+ (PR_GetSystemInfo(PR_SI_ARCHITECTURE, arch, SYS_INFO_BUFFER_LENGTH)
+ != PR_SUCCESS) ) {
+ error(PK11_INSTALL_SYSINFO);
+ ret=PK11_INSTALL_SYSINFO;
+ goto loser;
+ }
+ myPlatform = PR_smprintf("%s:%s:%s", sysname, release, arch);
+ platform = Pk11Install_Info_GetBestPlatform(&installInfo,myPlatform);
+ if(!platform) {
+ error(PK11_INSTALL_NO_PLATFORM, myPlatform);
+ PR_smprintf_free(myPlatform);
+ ret=PK11_INSTALL_NO_PLATFORM;
+ goto loser;
+ }
+ if(feedback) {
+ PR_fprintf(feedback, msgStrings[MY_PLATFORM_IS], myPlatform);
+ PR_fprintf(feedback, msgStrings[USING_PLATFORM],
+ Pk11Install_PlatformName_GetString(&platform->name));
+ }
+ PR_smprintf_free(myPlatform);
+ }
+
+ /* Run the install for that platform */
+ ret = DoInstall(jar, installDir, tempDir, platform, feedback, noverify);
+ if(ret) {
+ goto loser;
+ }
+
+ ret = PK11_INSTALL_SUCCESS;
+loser:
+ if(Pk11Install_valueList) {
+ Pk11Install_ValueList_delete(Pk11Install_valueList);
+ PR_Free(Pk11Install_valueList);
+ Pk11Install_valueList = NULL;
+ }
+ if(jar) {
+ JAR_destroy(jar);
+ }
+ if(made_temp_file) {
+ PR_Delete(SCRIPT_TEMP_FILE);
+ }
+ if(errMsg) {
+ PR_smprintf_free(errMsg);
+ }
+ return ret;
+}
+
+/*
+/////////////////////////////////////////////////////////////////////////
+// actually run the installation, copying files to and fro
+*/
+static Pk11Install_Error
+DoInstall(JAR *jar, const char *installDir, const char *tempDir,
+ Pk11Install_Platform *platform, PRFileDesc *feedback, PRBool noverify)
+{
+ Pk11Install_File *file;
+ Pk11Install_Error ret;
+ char *reldir;
+ char *dest;
+ char *modDest;
+ char *cp;
+ int i;
+ int status;
+ char *tempname, *temp;
+ StringList executables;
+ StringNode *execNode;
+ PRProcessAttr *attr;
+ PRProcess *proc;
+ char *argv[2];
+ char *envp[1];
+ int errcode;
+
+ ret=PK11_INSTALL_UNSPECIFIED;
+ reldir=NULL;
+ dest=NULL;
+ modDest=NULL;
+ tempname=NULL;
+
+ StringList_new(&executables);
+ /*
+ // Create Temporary directory
+ */
+ tempname = PR_smprintf("%s/%s", tempDir, TEMPORARY_DIRECTORY_NAME);
+ if( PR_Access(tempname, PR_ACCESS_EXISTS)==PR_SUCCESS ) {
+ /* Left over from previous run? Delete it. */
+ rm_dash_r(tempname);
+ }
+ if(PR_MkDir(tempname, 0700) != PR_SUCCESS) {
+ error(PK11_INSTALL_CREATE_DIR, tempname);
+ ret = PK11_INSTALL_CREATE_DIR;
+ goto loser;
+ }
+
+ /*
+ // Install all the files
+ */
+ for(i=0; i < platform->numFiles; i++) {
+ file = &platform->files[i];
+
+ if(file->relativePath) {
+ PRBool foundMarker = PR_FALSE;
+ reldir = PR_Strdup(file->relativePath);
+
+ /* Replace all the markers with the directories for which they stand */
+ while(1) {
+ if( (cp=PL_strcasestr(reldir, ROOT_MARKER)) ) {
+ /* Has a %root% marker */
+ *cp = '\0';
+ temp = PR_smprintf("%s%s%s", reldir, installDir,
+ cp+strlen(ROOT_MARKER));
+ PR_Free(reldir);
+ reldir = temp;
+ foundMarker = PR_TRUE;
+ } else if( (cp = PL_strcasestr(reldir, TEMP_MARKER)) ) {
+ /* Has a %temp% marker */
+ *cp = '\0';
+ temp = PR_smprintf("%s%s%s", reldir, tempname,
+ cp+strlen(TEMP_MARKER));
+ PR_Free(reldir);
+ reldir = temp;
+ foundMarker = PR_TRUE;
+ } else {
+ break;
+ }
+ }
+ if(!foundMarker) {
+ /* Has no markers...this isn't really a relative directory */
+ error(PK11_INSTALL_BOGUS_REL_DIR, file->relativePath);
+ ret = PK11_INSTALL_BOGUS_REL_DIR;
+ goto loser;
+ }
+ dest = reldir;
+ reldir = NULL;
+ } else if(file->absolutePath) {
+ dest = PR_Strdup(file->absolutePath);
+ }
+
+ /* Remember if this is the module file, we'll need to add it later */
+ if(i == platform->modFile) {
+ modDest = PR_Strdup(dest);
+ }
+
+ /* Remember is this is an executable, we'll need to run it later */
+ if(file->executable) {
+ StringList_Append(&executables,dest);
+ /*executables.Append(dest);*/
+ }
+
+ /* Make sure the directory we are targetting exists */
+ if( make_dirs(dest, file->permissions) ) {
+ ret=PK11_INSTALL_CREATE_DIR;
+ goto loser;
+ }
+
+ /* Actually extract the file onto the filesystem */
+ if(noverify) {
+ status = JAR_extract(jar, (char*)file->jarPath, dest);
+ } else {
+ status = JAR_verified_extract(jar, (char*)file->jarPath, dest);
+ }
+ if(status) {
+ if (status >= JAR_BASE && status <= JAR_BASE_END) {
+ error(PK11_INSTALL_JAR_EXTRACT, file->jarPath,
+ JAR_get_error(status));
+ } else {
+ error(PK11_INSTALL_JAR_EXTRACT, file->jarPath,
+ mySECU_ErrorString((int16) PORT_GetError()) );
+ }
+ ret=PK11_INSTALL_JAR_EXTRACT;
+ goto loser;
+ }
+ if(feedback) {
+ PR_fprintf(feedback, msgStrings[INSTALLED_FILE_MSG],
+ file->jarPath, dest);
+ }
+
+ /* no NSPR command to change permissions? */
+#ifdef XP_UNIX
+ chmod(dest, file->permissions);
+#endif
+
+ /* Memory clean-up tasks */
+ if(reldir) {
+ PR_Free(reldir);
+ reldir = NULL;
+ }
+ if(dest) {
+ PR_Free(dest);
+ dest = NULL;
+ }
+ }
+ /* Make sure we found the module file */
+ if(!modDest) {
+ /* Internal problem here, since every platform is supposed to have
+ a module file */
+ error(PK11_INSTALL_NO_MOD_FILE, platform->moduleName);
+ ret=PK11_INSTALL_NO_MOD_FILE;
+ goto loser;
+ }
+
+ /*
+ // Execute any executable files
+ */
+ {
+ argv[1] = NULL;
+ envp[0] = NULL;
+ for(execNode = executables.head; execNode; execNode = execNode->next) {
+ attr = PR_NewProcessAttr();
+ argv[0] = PR_Strdup(execNode->str);
+
+ /* Announce our intentions */
+ if(feedback) {
+ PR_fprintf(feedback, msgStrings[EXEC_FILE_MSG], execNode->str);
+ }
+
+ /* start the process */
+ if( !(proc=PR_CreateProcess(execNode->str, argv, envp, attr)) ) {
+ PR_Free(argv[0]);
+ PR_DestroyProcessAttr(attr);
+ error(PK11_INSTALL_EXEC_FILE, execNode->str);
+ ret=PK11_INSTALL_EXEC_FILE;
+ goto loser;
+ }
+
+ /* wait for it to finish */
+ if( PR_WaitProcess(proc, &errcode) != PR_SUCCESS) {
+ PR_Free(argv[0]);
+ PR_DestroyProcessAttr(attr);
+ error(PK11_INSTALL_WAIT_PROCESS, execNode->str);
+ ret=PK11_INSTALL_WAIT_PROCESS;
+ goto loser;
+ }
+
+ /* What happened? */
+ if(errcode) {
+ /* process returned an error */
+ error(PK11_INSTALL_PROC_ERROR, execNode->str, errcode);
+ } else if(feedback) {
+ /* process ran successfully */
+ PR_fprintf(feedback, msgStrings[EXEC_SUCCESS], execNode->str);
+ }
+
+ PR_Free(argv[0]);
+ PR_DestroyProcessAttr(attr);
+ }
+ }
+
+ /*
+ // Add the module
+ */
+ status = Pk11Install_AddNewModule((char*)platform->moduleName,
+ (char*)modDest, platform->mechFlags, platform->cipherFlags );
+
+ if(status != SECSuccess) {
+ error(PK11_INSTALL_ADD_MODULE, platform->moduleName);
+ ret=PK11_INSTALL_ADD_MODULE;
+ goto loser;
+ }
+ if(feedback) {
+ PR_fprintf(feedback, msgStrings[INSTALLED_MODULE_MSG],
+ platform->moduleName);
+ }
+
+ if(feedback) {
+ PR_fprintf(feedback, msgStrings[INSTALLATION_COMPLETE_MSG]);
+ }
+
+ ret = PK11_INSTALL_SUCCESS;
+
+loser:
+ if(reldir) {
+ PR_Free(reldir);
+ }
+ if(dest) {
+ PR_Free(dest);
+ }
+ if(modDest) {
+ PR_Free(modDest);
+ }
+ if(tempname) {
+ PRFileInfo info;
+ if(PR_GetFileInfo(tempname, &info) == PR_SUCCESS) {
+ if((info.type == PR_FILE_DIRECTORY)) {
+ /* Recursively remove temporary directory */
+ if(rm_dash_r(tempname)) {
+ error(PK11_INSTALL_REMOVE_DIR,
+ tempname);
+ ret=PK11_INSTALL_REMOVE_DIR;
+ }
+
+ }
+ }
+ PR_Free(tempname);
+ }
+ StringList_delete(&executables);
+ return ret;
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////
+*/
+static char*
+PR_Strdup(const char* str)
+{
+ char *tmp = (char*) PR_Malloc(strlen(str)+1);
+ strcpy(tmp, str);
+ return tmp;
+}
+
+/*
+ * r m _ d a s h _ r
+ *
+ * Remove a file, or a directory recursively.
+ *
+ */
+static int
+rm_dash_r (char *path)
+{
+ PRDir *dir;
+ PRDirEntry *entry;
+ PRFileInfo fileinfo;
+ char filename[240];
+
+ if(PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) {
+ /*fprintf(stderr, "Error: Unable to access %s\n", filename);*/
+ return -1;
+ }
+ if(fileinfo.type == PR_FILE_DIRECTORY) {
+
+ dir = PR_OpenDir(path);
+ if(!dir) {
+ return -1;
+ }
+
+ /* Recursively delete all entries in the directory */
+ while((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
+ sprintf(filename, "%s/%s", path, entry->name);
+ if(rm_dash_r(filename)) return -1;
+ }
+
+ if(PR_CloseDir(dir) != PR_SUCCESS) {
+ return -1;
+ }
+
+ /* Delete the directory itself */
+ if(PR_RmDir(path) != PR_SUCCESS) {
+ return -1;
+ }
+ } else {
+ if(PR_Delete(path) != PR_SUCCESS) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * m a k e _ d i r s
+ *
+ * Ensure that the directory portion of the path exists. This may require
+ * making the directory, and its parent, and its parent's parent, etc.
+ */
+static int
+make_dirs(char *path, int file_perms)
+{
+ char *Path;
+ char *start;
+ char *sep;
+ int ret = 0;
+ PRFileInfo info;
+
+ if(!path) {
+ return 0;
+ }
+
+ Path = PR_Strdup(path);
+ start = strpbrk(Path, "/\\");
+ if(!start) {
+ return 0;
+ }
+ start++; /* start right after first slash */
+
+ /* Each time through the loop add one more directory. */
+ while( (sep=strpbrk(start, "/\\")) ) {
+ *sep = '\0';
+
+ if( PR_GetFileInfo(Path, &info) != PR_SUCCESS) {
+ /* No such dir, we have to create it */
+ if( PR_MkDir(Path, dir_perms(file_perms)) != PR_SUCCESS) {
+ error(PK11_INSTALL_CREATE_DIR, Path);
+ ret = PK11_INSTALL_CREATE_DIR;
+ goto loser;
+ }
+ } else {
+ /* something exists by this name, make sure it's a directory */
+ if( info.type != PR_FILE_DIRECTORY ) {
+ error(PK11_INSTALL_CREATE_DIR, Path);
+ ret = PK11_INSTALL_CREATE_DIR;
+ goto loser;
+ }
+ }
+
+ /* If this is the lowest directory level, make sure it is writeable */
+ if(!strpbrk(sep+1, "/\\")) {
+ if( PR_Access(Path, PR_ACCESS_WRITE_OK)!=PR_SUCCESS) {
+ error(PK11_INSTALL_DIR_NOT_WRITEABLE, Path);
+ ret = PK11_INSTALL_DIR_NOT_WRITEABLE;
+ goto loser;
+ }
+ }
+
+ start = sep+1; /* start after the next slash */
+ *sep = '/';
+ }
+
+loser:
+ PR_Free(Path);
+ return ret;
+}
+
+/*************************************************************************
+ * d i r _ p e r m s
+ *
+ * Guesses the desired permissions on a directory based on the permissions
+ * of a file that will be stored in it. Give read, write, and
+ * execute to the owner (so we can create the file), read and
+ * execute to anyone who has read permissions on the file, and write
+ * to anyone who has write permissions on the file.
+ */
+static int
+dir_perms(int perms)
+{
+ int ret = 0;
+
+ /* owner */
+ ret |= 0700;
+
+ /* group */
+ if(perms & 0040) {
+ /* read on the file -> read and execute on the directory */
+ ret |= 0050;
+ }
+ if(perms & 0020) {
+ /* write on the file -> write on the directory */
+ ret |= 0020;
+ }
+
+ /* others */
+ if(perms & 0004) {
+ /* read on the file -> read and execute on the directory */
+ ret |= 0005;
+ }
+ if(perms & 0002) {
+ /* write on the file -> write on the directory */
+ ret |= 0002;
+ }
+
+ return ret;
+}
diff --git a/security/nss/cmd/modutil/install.h b/security/nss/cmd/modutil/install.h
new file mode 100644
index 000000000..3874ed77e
--- /dev/null
+++ b/security/nss/cmd/modutil/install.h
@@ -0,0 +1,130 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifndef PK11INSTALL_H
+#define PK11INSTALL_H
+
+#include <prio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*Pk11Install_ErrorHandler)(char *);
+
+typedef enum {
+ PK11_INSTALL_NO_ERROR=0,
+ PK11_INSTALL_DIR_DOESNT_EXIST,
+ PK11_INSTALL_FILE_DOESNT_EXIST,
+ PK11_INSTALL_FILE_NOT_READABLE,
+ PK11_INSTALL_ERROR_STRING,
+ PK11_INSTALL_JAR_ERROR,
+ PK11_INSTALL_NO_INSTALLER_SCRIPT,
+ PK11_INSTALL_DELETE_TEMP_FILE,
+ PK11_INSTALL_OPEN_SCRIPT_FILE,
+ PK11_INSTALL_SCRIPT_PARSE,
+ PK11_INSTALL_SEMANTIC,
+ PK11_INSTALL_SYSINFO,
+ PK11_INSTALL_NO_PLATFORM,
+ PK11_INSTALL_BOGUS_REL_DIR,
+ PK11_INSTALL_NO_MOD_FILE,
+ PK11_INSTALL_ADD_MODULE,
+ PK11_INSTALL_JAR_EXTRACT,
+ PK11_INSTALL_DIR_NOT_WRITEABLE,
+ PK11_INSTALL_CREATE_DIR,
+ PK11_INSTALL_REMOVE_DIR,
+ PK11_INSTALL_EXEC_FILE,
+ PK11_INSTALL_WAIT_PROCESS,
+ PK11_INSTALL_PROC_ERROR,
+ PK11_INSTALL_USER_ABORT,
+ PK11_INSTALL_UNSPECIFIED
+} Pk11Install_Error;
+#define PK11_INSTALL_SUCCESS PK11_INSTALL_NO_ERROR
+
+/**************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ I n i t
+ *
+ * Does initialization that otherwise would be done on the fly. Only
+ * needs to be called by multithreaded apps, before they make any calls
+ * to this library.
+ */
+void
+Pk11Install_Init();
+
+/**************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ S e t E r r o r H a n d l e r
+ *
+ * Sets the error handler to be used by the library. Returns the current
+ * error handler function.
+ */
+Pk11Install_ErrorHandler
+Pk11Install_SetErrorHandler(Pk11Install_ErrorHandler handler);
+
+
+/**************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ R e l e a s e
+ *
+ * Releases static data structures used by the library. Don't use the
+ * library after calling this, unless you call Pk11Install_Init()
+ * first. This function doesn't have to be called at all unless you're
+ * really anal about freeing memory before your program exits.
+ */
+void
+Pk11Install_Release();
+
+/*************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ D o I n s t a l l
+ *
+ * jarFile is the path of a JAR in the PKCS #11 module JAR format.
+ * installDir is the directory relative to which files will be
+ * installed.
+ * feedback is a file descriptor to which to write informative (not error)
+ * status messages: what files are being installed, what modules are being
+ * installed. If feedback==NULL, no messages will be displayed.
+ * If force != 0, interactive prompts will be suppressed.
+ * If noverify == PR_TRUE, signatures won't be checked on the JAR file.
+ */
+Pk11Install_Error
+Pk11Install_DoInstall(char *jarFile, const char *installDir,
+ const char *tempDir, PRFileDesc *feedback, short force,
+ PRBool noverify);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*PK11INSTALL_H*/
diff --git a/security/nss/cmd/modutil/installparse.c b/security/nss/cmd/modutil/installparse.c
new file mode 100644
index 000000000..16f81b6eb
--- /dev/null
+++ b/security/nss/cmd/modutil/installparse.c
@@ -0,0 +1,429 @@
+#ifndef lint
+char yysccsid[] = "@(#)yaccpar 1.4 (Berkeley) 02/25/90";
+#endif
+#line 37 "installparse.y"
+
+#define yyparse Pk11Install_yyparse
+#define yylex Pk11Install_yylex
+#define yyerror Pk11Install_yyerror
+#define yychar Pk11Install_yychar
+#define yyval Pk11Install_yyval
+#define yylval Pk11Install_yylval
+#define yydebug Pk11Install_yydebug
+#define yynerrs Pk11Install_yynerrs
+#define yyerrflag Pk11Install_yyerrflag
+#define yyss Pk11Install_yyss
+#define yyssp Pk11Install_yyssp
+#define yyvs Pk11Install_yyvs
+#define yyvsp Pk11Install_yyvsp
+#define yylhs Pk11Install_yylhs
+#define yylen Pk11Install_yylen
+#define yydefred Pk11Install_yydefred
+#define yydgoto Pk11Install_yydgoto
+#define yysindex Pk11Install_yysindex
+#define yyrindex Pk11Install_yyrindex
+#define yygindex Pk11Install_yygindex
+#define yytable Pk11Install_yytable
+#define yycheck Pk11Install_yycheck
+#define yyname Pk11Install_yyname
+#define yyrule Pk11Install_yyrule
+
+/* C Stuff */
+#include "install-ds.h"
+#include <prprf.h>
+
+#define YYSTYPE Pk11Install_Pointer
+extern char *Pk11Install_yytext;
+char *Pk11Install_yyerrstr=NULL;
+
+#line 40 "ytab.c"
+#define OPENBRACE 257
+#define CLOSEBRACE 258
+#define STRING 259
+#define YYERRCODE 256
+short yylhs[] = { -1,
+ 0, 1, 1, 2, 2, 3, 4,
+};
+short yylen[] = { 2,
+ 1, 2, 0, 1, 1, 4, 1,
+};
+short yydefred[] = { 0,
+ 0, 0, 1, 0, 4, 0, 2, 0, 0, 6,
+};
+short yydgoto[] = { 2,
+ 3, 4, 5, 6,
+};
+short yysindex[] = { -257,
+ 0, 0, 0, -257, 0, -252, 0, -257, -251, 0,
+};
+short yyrindex[] = { 6,
+ 1, 0, 0, 3, 0, 0, 0, -250, 0, 0,
+};
+short yygindex[] = { 0,
+ -4, 0, 0, 0,
+};
+#define YYTABLESIZE 261
+short yytable[] = { 7,
+ 5, 1, 3, 9, 8, 3, 10, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 7, 5, 5,
+ 3,
+};
+short yycheck[] = { 4,
+ 0, 259, 0, 8, 257, 0, 258, 258, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 257, 258, 259,
+ 258,
+};
+#define YYFINAL 2
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 259
+#if YYDEBUG
+char *yyname[] = {
+"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"OPENBRACE","CLOSEBRACE","STRING",
+};
+char *yyrule[] = {
+"$accept : toplist",
+"toplist : valuelist",
+"valuelist : value valuelist",
+"valuelist :",
+"value : key_value_pair",
+"value : STRING",
+"key_value_pair : key OPENBRACE valuelist CLOSEBRACE",
+"key : STRING",
+};
+#endif
+#ifndef YYSTYPE
+typedef int YYSTYPE;
+#endif
+#define yyclearin (yychar=(-1))
+#define yyerrok (yyerrflag=0)
+#ifndef YYSTACKSIZE
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 300
+#endif
+#endif
+int yydebug;
+int yynerrs;
+int yyerrflag;
+int yychar;
+short *yyssp;
+YYSTYPE *yyvsp;
+YYSTYPE yyval;
+YYSTYPE yylval;
+#define yystacksize YYSTACKSIZE
+short yyss[YYSTACKSIZE];
+YYSTYPE yyvs[YYSTACKSIZE];
+#line 118 "installparse.y"
+/*----------------------- Program Section --------------------------------*/
+
+/*************************************************************************/
+void
+Pk11Install_yyerror(char *message)
+{
+ char *tmp;
+ if(Pk11Install_yyerrstr) {
+ tmp=PR_smprintf("%sline %d: %s\n", Pk11Install_yyerrstr,
+ Pk11Install_yylinenum, message);
+ PR_smprintf_free(Pk11Install_yyerrstr);
+ } else {
+ tmp = PR_smprintf("line %d: %s\n", Pk11Install_yylinenum, message);
+ }
+ Pk11Install_yyerrstr=tmp;
+}
+#line 191 "ytab.c"
+#define YYABORT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+int
+yyparse()
+{
+ register int yym, yyn, yystate;
+#if YYDEBUG
+ register char *yys;
+ extern char *getenv();
+
+ if (yys = getenv("YYDEBUG"))
+ {
+ yyn = *yys;
+ if (yyn >= '0' && yyn <= '9')
+ yydebug = yyn - '0';
+ }
+#endif
+
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = (-1);
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+ *yyssp = yystate = 0;
+
+yyloop:
+ if (yyn = yydefred[yystate]) goto yyreduce;
+ if (yychar < 0)
+ {
+ if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("yydebug: state %d, reading %d (%s)\n", yystate,
+ yychar, yys);
+ }
+#endif
+ }
+ if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: state %d, shifting to state %d\n",
+ yystate, yytable[yyn]);
+#endif
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ yychar = (-1);
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+ yyn = yytable[yyn];
+ goto yyreduce;
+ }
+ if (yyerrflag) goto yyinrecovery;
+#ifdef lint
+ goto yynewerror;
+#endif
+yynewerror:
+ yyerror("syntax error");
+#ifdef lint
+ goto yyerrlab;
+#endif
+yyerrlab:
+ ++yynerrs;
+yyinrecovery:
+ if (yyerrflag < 3)
+ {
+ yyerrflag = 3;
+ for (;;)
+ {
+ if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: state %d, error recovery shifting\
+ to state %d\n", *yyssp, yytable[yyn]);
+#endif
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ goto yyloop;
+ }
+ else
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: error recovery discarding state %d\n",
+ *yyssp);
+#endif
+ if (yyssp <= yyss) goto yyabort;
+ --yyssp;
+ --yyvsp;
+ }
+ }
+ }
+ else
+ {
+ if (yychar == 0) goto yyabort;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("yydebug: state %d, error recovery discards token %d (%s)\n",
+ yystate, yychar, yys);
+ }
+#endif
+ yychar = (-1);
+ goto yyloop;
+ }
+yyreduce:
+#if YYDEBUG
+ if (yydebug)
+ printf("yydebug: state %d, reducing by rule %d (%s)\n",
+ yystate, yyn, yyrule[yyn]);
+#endif
+ yym = yylen[yyn];
+ yyval = yyvsp[1-yym];
+ switch (yyn)
+ {
+case 1:
+#line 84 "installparse.y"
+{
+ Pk11Install_valueList = yyvsp[0].list;
+}
+break;
+case 2:
+#line 89 "installparse.y"
+{
+ Pk11Install_ValueList_AddItem(yyvsp[0].list,yyvsp[-1].value);
+ yyval .list = yyvsp[0].list;
+}
+break;
+case 3:
+#line 94 "installparse.y"
+{
+ yyval .list = Pk11Install_ValueList_new();
+}
+break;
+case 4:
+#line 99 "installparse.y"
+{
+ yyval .value= Pk11Install_Value_new(PAIR_VALUE,yyvsp[0]);
+}
+break;
+case 5:
+#line 103 "installparse.y"
+{
+ yyval .value= Pk11Install_Value_new(STRING_VALUE, yyvsp[0]);
+}
+break;
+case 6:
+#line 108 "installparse.y"
+{
+ yyval .pair = Pk11Install_Pair_new(yyvsp[-3].string,yyvsp[-1].list);
+}
+break;
+case 7:
+#line 113 "installparse.y"
+{
+ yyval .string = yyvsp[0].string;
+}
+break;
+#line 374 "ytab.c"
+ }
+ yyssp -= yym;
+ yystate = *yyssp;
+ yyvsp -= yym;
+ yym = yylhs[yyn];
+ if (yystate == 0 && yym == 0)
+ {
+#ifdef YYDEBUG
+ if (yydebug)
+ printf("yydebug: after reduction, shifting from state 0 to\
+ state %d\n", YYFINAL);
+#endif
+ yystate = YYFINAL;
+ *++yyssp = YYFINAL;
+ *++yyvsp = yyval;
+ if (yychar < 0)
+ {
+ if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("yydebug: state %d, reading %d (%s)\n",
+ YYFINAL, yychar, yys);
+ }
+#endif
+ }
+ if (yychar == 0) goto yyaccept;
+ goto yyloop;
+ }
+ if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+ yystate = yytable[yyn];
+ else
+ yystate = yydgoto[yym];
+#ifdef YYDEBUG
+ if (yydebug)
+ printf("yydebug: after reduction, shifting from state %d \
+to state %d\n", *yyssp, yystate);
+#endif
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate;
+ *++yyvsp = yyval;
+ goto yyloop;
+yyoverflow:
+ yyerror("yacc stack overflow");
+yyabort:
+ return (1);
+yyaccept:
+ return (0);
+}
diff --git a/security/nss/cmd/modutil/installparse.h b/security/nss/cmd/modutil/installparse.h
new file mode 100644
index 000000000..75686d4fd
--- /dev/null
+++ b/security/nss/cmd/modutil/installparse.h
@@ -0,0 +1,3 @@
+#define OPENBRACE 257
+#define CLOSEBRACE 258
+#define STRING 259
diff --git a/security/nss/cmd/modutil/installparse.l b/security/nss/cmd/modutil/installparse.l
new file mode 100644
index 000000000..6befe16cb
--- /dev/null
+++ b/security/nss/cmd/modutil/installparse.l
@@ -0,0 +1,166 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+
+/* lex file for analyzing PKCS #11 Module installation instructions */
+
+/*----------------------------- Definitions ---------------------------*/
+%{
+#include <string.h>
+
+#include "install-ds.h" /* defines tokens and data structures */
+#include "installparse.h" /* produced by yacc -d */
+#include <prprf.h>
+static char *putSimpleString(char*); /* return copy of string */
+static char *putComplexString(char*); /* strip out quotes, deal with */
+ /* escaped characters */
+
+void Pk11Install_yyerror(char *);
+
+/* Overrides to use NSPR */
+#define malloc PR_Malloc
+#define realloc PR_Realloc
+#define free PR_Free
+
+int Pk11Install_yylinenum=1;
+static char *err;
+
+#define YY_NEVER_INTERACTIVE 1
+#define yyunput Pkcs11Install_yyunput
+
+/* This is the default YY_INPUT modified for NSPR */
+#define YY_INPUT(buf,result,max_size) \
+ if ( yy_current_buffer->yy_is_interactive ) { \
+ char c; \
+ int n; \
+ for ( n = 0; n < max_size && \
+ PR_Read(Pk11Install_FD, &c, 1)==1 && c != '\n'; ++n ) { \
+ buf[n] = c; \
+ } \
+ if ( c == '\n' ) { \
+ buf[n++] = c; \
+ } \
+ result = n; \
+ } else { \
+ result = PR_Read(Pk11Install_FD, buf, max_size); \
+ }
+
+%}
+
+/*** Regular expression definitions ***/
+/* simple_string has no whitespace, quotes, or braces */
+simple_string [^ \t\r\n\""{""}"]+
+
+/* complex_string is enclosed in quotes. Inside the quotes, quotes and
+ backslashes must be backslash-escaped. No newlines or carriage returns
+ are allowed inside the quotes. Otherwise, anything goes. */
+complex_string \"([^\"\\\r\n]|(\\\")|(\\\\))+\"
+
+/* Standard whitespace */
+whitespace [ \t\r]+
+
+other .
+
+/*---------------------------- Actions --------------------------------*/
+%%
+
+"{" return OPENBRACE;
+"}" return CLOSEBRACE;
+{simple_string} {Pk11Install_yylval.string =
+ putSimpleString(Pk11Install_yytext);
+ return STRING;}
+{complex_string} {Pk11Install_yylval.string =
+ putComplexString(Pk11Install_yytext);
+ return STRING;}
+
+"\n" Pk11Install_yylinenum++;
+
+{whitespace} ;
+
+{other} {err = PR_smprintf("Invalid lexeme: %s",Pk11Install_yytext);
+ Pk11Install_yyerror(err);
+ PR_smprintf_free(err);
+ return 1;
+ }
+
+%%
+/*------------------------ Program Section ----------------------------*/
+
+PRFileDesc *Pk11Install_FD=NULL;
+
+/*************************************************************************/
+/* dummy function required by lex */
+int Pk11Install_yywrap(void) { return 1;}
+
+/*************************************************************************/
+/* Return a copy of the given string */
+static char*
+putSimpleString(char *str)
+{
+ char *tmp = (char*) PR_Malloc(strlen(str)+1);
+ strcpy(tmp, str);
+ return tmp;
+}
+
+/*************************************************************************/
+/* Strip out quotes, replace escaped characters with what they stand for.
+ This function assumes that what is passed in is actually a complex
+ string, so error checking is lax. */
+static char*
+putComplexString(char *str)
+{
+ int size, i,j;
+ char *tmp;
+
+ if(!str) {
+ return NULL;
+ }
+ size = strlen(str);
+
+ /* Allocate the new space. This string will actually be too big,
+ since quotes and backslashes will be stripped out. But that's ok. */
+ tmp = (char*) PR_Malloc(size+1);
+
+ /* Copy it over */
+ for(i=0, j=0; i < size; i++) {
+ if(str[i]=='\"') {
+ continue; /* skip un-escaped quotes */
+ } else if(str[i]=='\\') {
+ ++i; /* escaped character. skip the backslash */
+ }
+ tmp[j++] = str[i];
+ }
+ tmp[j] = '\0';
+
+ return tmp;
+}
diff --git a/security/nss/cmd/modutil/installparse.y b/security/nss/cmd/modutil/installparse.y
new file mode 100644
index 000000000..6a32e25ab
--- /dev/null
+++ b/security/nss/cmd/modutil/installparse.y
@@ -0,0 +1,133 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/* yacc file for parsing PKCS #11 module installation instructions */
+/*------------------------ Definition Section ---------------------------*/
+
+%{
+#define yyparse Pk11Install_yyparse
+#define yylex Pk11Install_yylex
+#define yyerror Pk11Install_yyerror
+#define yychar Pk11Install_yychar
+#define yyval Pk11Install_yyval
+#define yylval Pk11Install_yylval
+#define yydebug Pk11Install_yydebug
+#define yynerrs Pk11Install_yynerrs
+#define yyerrflag Pk11Install_yyerrflag
+#define yyss Pk11Install_yyss
+#define yyssp Pk11Install_yyssp
+#define yyvs Pk11Install_yyvs
+#define yyvsp Pk11Install_yyvsp
+#define yylhs Pk11Install_yylhs
+#define yylen Pk11Install_yylen
+#define yydefred Pk11Install_yydefred
+#define yydgoto Pk11Install_yydgoto
+#define yysindex Pk11Install_yysindex
+#define yyrindex Pk11Install_yyrindex
+#define yygindex Pk11Install_yygindex
+#define yytable Pk11Install_yytable
+#define yycheck Pk11Install_yycheck
+#define yyname Pk11Install_yyname
+#define yyrule Pk11Install_yyrule
+
+/* C Stuff */
+#include "install-ds.h"
+#include <prprf.h>
+
+#define YYSTYPE Pk11Install_Pointer
+extern char *Pk11Install_yytext;
+char *Pk11Install_yyerrstr=NULL;
+
+%}
+
+/* Tokens */
+%token OPENBRACE
+%token CLOSEBRACE
+%token STRING
+%start toplist
+
+%%
+
+/*--------------------------- Productions -------------------------------*/
+
+toplist : valuelist
+{
+ Pk11Install_valueList = $1.list;
+}
+
+valuelist : value valuelist
+{
+ Pk11Install_ValueList_AddItem($2.list,$1.value);
+ $$.list = $2.list;
+}
+|
+{
+ $$.list = Pk11Install_ValueList_new();
+};
+
+value : key_value_pair
+{
+ $$.value= Pk11Install_Value_new(PAIR_VALUE,$1);
+}
+| STRING
+{
+ $$.value= Pk11Install_Value_new(STRING_VALUE, $1);
+};
+
+key_value_pair : key OPENBRACE valuelist CLOSEBRACE
+{
+ $$.pair = Pk11Install_Pair_new($1.string,$3.list);
+};
+
+key : STRING
+{
+ $$.string = $1.string;
+};
+
+%%
+/*----------------------- Program Section --------------------------------*/
+
+/*************************************************************************/
+void
+Pk11Install_yyerror(char *message)
+{
+ char *tmp;
+ if(Pk11Install_yyerrstr) {
+ tmp=PR_smprintf("%sline %d: %s\n", Pk11Install_yyerrstr,
+ Pk11Install_yylinenum, message);
+ PR_smprintf_free(Pk11Install_yyerrstr);
+ } else {
+ tmp = PR_smprintf("line %d: %s\n", Pk11Install_yylinenum, message);
+ }
+ Pk11Install_yyerrstr=tmp;
+}
diff --git a/security/nss/cmd/modutil/instsec.c b/security/nss/cmd/modutil/instsec.c
new file mode 100644
index 000000000..e6eaa384b
--- /dev/null
+++ b/security/nss/cmd/modutil/instsec.c
@@ -0,0 +1,178 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include <plarena.h>
+#include <prio.h>
+#include <prprf.h>
+#include <seccomon.h>
+#include <secmod.h>
+#include <jar.h>
+#include <secutil.h>
+
+/* These are installation functions that make calls to the security library.
+ * We don't want to include security include files in the C++ code too much.
+ */
+
+static char* PR_fgets(char *buf, int size, PRFileDesc *file);
+
+/***************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ A d d N e w M o d u l e
+ */
+int
+Pk11Install_AddNewModule(char* moduleName, char* dllPath,
+ unsigned long defaultMechanismFlags,
+ unsigned long cipherEnableFlags)
+{
+ return (SECMOD_AddNewModule(moduleName, dllPath,
+ SECMOD_PubMechFlagstoInternal(defaultMechanismFlags),
+ SECMOD_PubCipherFlagstoInternal(cipherEnableFlags))
+ == SECSuccess) ? 0 : -1;
+}
+
+/*************************************************************************
+ *
+ * P k 1 1 I n s t a l l _ U s e r V e r i f y J a r
+ *
+ * Gives the user feedback on the signatures of a JAR files, asks them
+ * whether they actually want to continue.
+ * Assumes the jar structure has already been created and is valid.
+ * Returns 0 if the user wants to continue the installation, nonzero
+ * if the user wishes to abort.
+ */
+short
+Pk11Install_UserVerifyJar(JAR *jar, PRFileDesc *out, PRBool query)
+{
+ JAR_Context *ctx;
+ JAR_Cert *fing;
+ JAR_Item *item;
+ char stdinbuf[80];
+ int count=0;
+
+ CERTCertificate *cert, *prev=NULL;
+
+ PR_fprintf(out, "\nThis installation JAR file was signed by:\n");
+
+ ctx = JAR_find(jar, NULL, jarTypeSign);
+
+ while(JAR_find_next(ctx, &item) >= 0 ) {
+ fing = (JAR_Cert*) item->data;
+ cert = fing->cert;
+ if(cert==prev) {
+ continue;
+ }
+
+ count++;
+ PR_fprintf(out, "----------------------------------------------\n");
+ if(cert) {
+ if(cert->nickname) {
+ PR_fprintf(out, "**NICKNAME**\n%s\n", cert->nickname);
+ }
+ if(cert->subjectName) {
+ PR_fprintf(out, "**SUBJECT NAME**\n%s\n", cert->subjectName); }
+ if(cert->issuerName) {
+ PR_fprintf(out, "**ISSUER NAME**\n%s\n", cert->issuerName);
+ }
+ } else {
+ PR_fprintf(out, "No matching certificate could be found.\n");
+ }
+ PR_fprintf(out, "----------------------------------------------\n\n");
+
+ prev=cert;
+ }
+
+ JAR_find_end(ctx);
+
+ if(count==0) {
+ PR_fprintf(out, "No signatures found: JAR FILE IS UNSIGNED.\n");
+ }
+
+ if(query) {
+ PR_fprintf(out,
+"Do you wish to continue this installation? (y/n) ");
+
+ if(PR_fgets(stdinbuf, 80, PR_STDIN) != NULL) {
+ char *response;
+
+ if( (response=strtok(stdinbuf, " \t\n\r")) ) {
+ if( !PL_strcasecmp(response, "y") ||
+ !PL_strcasecmp(response, "yes") ) {
+ return 0;
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+/**************************************************************************
+ *
+ * P R _ f g e t s
+ *
+ * fgets implemented with NSPR.
+ */
+static char*
+PR_fgets(char *buf, int size, PRFileDesc *file)
+{
+ int i;
+ int status;
+ char c;
+
+ i=0;
+ while(i < size-1) {
+ status = PR_Read(file, (void*) &c, 1);
+ if(status==-1) {
+ return NULL;
+ } else if(status==0) {
+ break;
+ }
+ buf[i++] = c;
+ if(c=='\n') {
+ break;
+ }
+ }
+ buf[i]='\0';
+
+ return buf;
+}
+
+/**************************************************************************
+ *
+ * m y S E C U _ E r r o r S t r i n g
+ *
+ */
+const char* mySECU_ErrorString(int16 errnum)
+{
+ return SECU_Strerror(errnum);
+}
diff --git a/security/nss/cmd/modutil/lex.Pk11Install_yy.c b/security/nss/cmd/modutil/lex.Pk11Install_yy.c
new file mode 100644
index 000000000..3943503db
--- /dev/null
+++ b/security/nss/cmd/modutil/lex.Pk11Install_yy.c
@@ -0,0 +1,1691 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#define yy_create_buffer Pk11Install_yy_create_buffer
+#define yy_delete_buffer Pk11Install_yy_delete_buffer
+#define yy_scan_buffer Pk11Install_yy_scan_buffer
+#define yy_scan_string Pk11Install_yy_scan_string
+#define yy_scan_bytes Pk11Install_yy_scan_bytes
+#define yy_flex_debug Pk11Install_yy_flex_debug
+#define yy_init_buffer Pk11Install_yy_init_buffer
+#define yy_flush_buffer Pk11Install_yy_flush_buffer
+#define yy_load_buffer_state Pk11Install_yy_load_buffer_state
+#define yy_switch_to_buffer Pk11Install_yy_switch_to_buffer
+#define yyin Pk11Install_yyin
+#define yyleng Pk11Install_yyleng
+#define yylex Pk11Install_yylex
+#define yyout Pk11Install_yyout
+#define yyrestart Pk11Install_yyrestart
+#define yytext Pk11Install_yytext
+#define yywrap Pk11Install_yywrap
+
+#line 20 "lex.Pk11Install_yy.c"
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header$
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+//#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator). This
+ * avoids problems with code like:
+ *
+ * if ( condition_holds )
+ * yyless( 5 );
+ * else
+ * do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+ };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext_ptr = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 8
+#define YY_END_OF_BUFFER 9
+static yyconst short int yy_accept[16] =
+ { 0,
+ 0, 0, 9, 3, 6, 5, 7, 1, 2, 3,
+ 6, 0, 0, 4, 0
+ } ;
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 5, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 6, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 7, 1, 8, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst int yy_meta[9] =
+ { 0,
+ 1, 2, 3, 4, 3, 1, 5, 5
+ } ;
+
+static yyconst short int yy_base[19] =
+ { 0,
+ 0, 0, 19, 0, 0, 21, 12, 21, 21, 0,
+ 0, 4, 6, 21, 21, 13, 11, 15
+ } ;
+
+static yyconst short int yy_def[19] =
+ { 0,
+ 15, 1, 15, 16, 17, 15, 18, 15, 15, 16,
+ 17, 18, 15, 15, 0, 15, 15, 15
+ } ;
+
+static yyconst short int yy_nxt[30] =
+ { 0,
+ 4, 5, 6, 5, 7, 4, 8, 9, 14, 13,
+ 12, 12, 11, 10, 11, 12, 12, 13, 15, 12,
+ 3, 15, 15, 15, 15, 15, 15, 15, 15
+ } ;
+
+static yyconst short int yy_chk[30] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 12, 12,
+ 13, 13, 17, 16, 17, 18, 18, 7, 3, 18,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "installparse.l"
+#define INITIAL 0
+/* lex file for analyzing PKCS #11 Module installation instructions */
+/*----------------------------- Definitions ---------------------------*/
+#line 5 "installparse.l"
+#include <string.h>
+
+#include "install-ds.h" /* defines tokens and data structures */
+#include "installparse.h" /* produced by yacc -d */
+#include <prprf.h>
+static char *putSimpleString(char*); /* return copy of string */
+static char *putComplexString(char*); /* strip out quotes, deal with */
+ /* escaped characters */
+
+void Pk11Install_yyerror(char *);
+
+/* Overrides to use NSPR */
+#define malloc PR_Malloc
+#define realloc PR_Realloc
+#define free PR_Free
+
+int Pk11Install_yylinenum=1;
+static char *err;
+
+#define YY_NEVER_INTERACTIVE 1
+#define yyunput Pkcs11Install_yyunput
+
+/* This is the default YY_INPUT modified for NSPR */
+#define YY_INPUT(buf,result,max_size) \
+ if ( yy_current_buffer->yy_is_interactive ) { \
+ char c; \
+ int n; \
+ for ( n = 0; n < max_size && \
+ PR_Read(Pk11Install_FD, &c, 1)==1 && c != '\n'; ++n ) { \
+ buf[n] = c; \
+ } \
+ if ( c == '\n' ) { \
+ buf[n++] = c; \
+ } \
+ result = n; \
+ } else { \
+ result = PR_Read(Pk11Install_FD, buf, max_size); \
+ }
+
+/*** Regular expression definitions ***/
+/* simple_string has no whitespace, quotes, or braces */
+/* complex_string is enclosed in quotes. Inside the quotes, quotes and
+ backslashes must be backslash-escaped. Otherwise, anything goes. */
+/* Standard whitespace */
+/*---------------------------- Actions --------------------------------*/
+#line 437 "lex.Pk11Install_yy.cpp"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines. This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( yy_current_buffer->yy_is_interactive ) \
+ { \
+ int c = '*', n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+ && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 60 "installparse.l"
+
+
+#line 591 "lex.Pk11Install_yy.cpp"
+
+ if ( yy_init )
+ {
+ yy_init = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yy_start )
+ yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! yy_current_buffer )
+ yy_current_buffer =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_load_buffer_state();
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 16 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 21 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+
+do_action: /* This label is used only to access EOF actions. */
+
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 62 "installparse.l"
+return OPENBRACE;
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 63 "installparse.l"
+return CLOSEBRACE;
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 64 "installparse.l"
+{Pk11Install_yylval.string =
+ putSimpleString(Pk11Install_yytext);
+ return STRING;}
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 67 "installparse.l"
+{Pk11Install_yylval.string =
+ putComplexString(Pk11Install_yytext);
+ return STRING;}
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 71 "installparse.l"
+Pk11Install_yylinenum++;
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 73 "installparse.l"
+;
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 75 "installparse.l"
+{err = PR_smprintf("Invalid lexeme: %s",Pk11Install_yytext);
+ Pk11Install_yyerror(err);
+ PR_smprintf_free(err);
+ return 1;
+ }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 81 "installparse.l"
+ECHO;
+ YY_BREAK
+#line 722 "lex.Pk11Install_yy.cpp"
+case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between yy_current_buffer and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yy_current_buffer->yy_input_file = yyin;
+ yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap() )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p =
+ yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+ {
+ register char *dest = yy_current_buffer->yy_ch_buf;
+ register char *source = yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( yy_current_buffer->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = yy_current_buffer;
+
+ int yy_c_buf_p_offset =
+ (int) (yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yy_flex_realloc( (void *) b->yy_ch_buf,
+ b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = yy_current_buffer->yy_buf_size -
+ number_to_move - 1;
+#endif
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
+
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ if ( yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+ return ret_val;
+ }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = yy_start;
+
+ for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 16 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+ }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+ {
+ register int yy_is_jam;
+ register char *yy_cp = yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 16 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 15);
+
+ return yy_is_jam ? 0 : yy_current_state;
+ }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+ {
+ register char *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yy_n_chars + 2;
+ register char *dest = &yy_current_buffer->yy_ch_buf[
+ yy_current_buffer->yy_buf_size + 2];
+ register char *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while ( source > yy_current_buffer->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ yy_current_buffer->yy_n_chars =
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+
+ yytext_ptr = yy_bp;
+ yy_hold_char = *yy_cp;
+ yy_c_buf_p = yy_cp;
+ }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+ {
+ int c;
+
+ *yy_c_buf_p = yy_hold_char;
+
+ if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* This was really a NUL. */
+ *yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yy_c_buf_p - yytext_ptr;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin );
+
+ /* fall through */
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+ return EOF;
+
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
+ *yy_c_buf_p = '\0'; /* preserve yytext */
+ yy_hold_char = *++yy_c_buf_p;
+
+
+ return c;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+ {
+ if ( ! yy_current_buffer )
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_init_buffer( yy_current_buffer, input_file );
+ yy_load_buffer_state();
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+ {
+ if ( yy_current_buffer == new_buffer )
+ return;
+
+ if ( yy_current_buffer )
+ {
+ /* Flush out information for old buffer. */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+ {
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+ }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+ {
+ if ( ! b )
+ return;
+
+ if ( b == yy_current_buffer )
+ yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yy_flex_free( (void *) b->yy_ch_buf );
+
+ yy_flex_free( (void *) b );
+ }
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+ {
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+ b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+ b->yy_is_interactive = 0;
+#else
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+ {
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == yy_current_buffer )
+ yy_load_buffer_state();
+ }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b );
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+ {
+ int len;
+ for ( len = 0; yy_str[len]; ++len )
+ ;
+
+ return yy_scan_bytes( yy_str, len );
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+ {
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *) yy_flex_alloc( n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < len; ++i )
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+ {
+ if ( yy_start_stack_ptr >= yy_start_stack_depth )
+ {
+ yy_size_t new_size;
+
+ yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yy_start_stack_depth * sizeof( int );
+
+ if ( ! yy_start_stack )
+ yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+ else
+ yy_start_stack = (int *) yy_flex_realloc(
+ (void *) yy_start_stack, new_size );
+
+ if ( ! yy_start_stack )
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack" );
+ }
+
+ yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+ }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+ {
+ if ( --yy_start_stack_ptr < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN(yy_start_stack[yy_start_stack_ptr]);
+ }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+ {
+ return yy_start_stack[yy_start_stack_ptr - 1];
+ }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+ {
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+ }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+ yy_c_buf_p = yytext + n; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+ } \
+ while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+ {
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+ }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+ {
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+ }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+ {
+ return (void *) malloc( size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+ {
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+ {
+ free( ptr );
+ }
+
+#if YY_MAIN
+int main()
+ {
+ yylex();
+ return 0;
+ }
+#endif
+#line 81 "installparse.l"
+
+/*------------------------ Program Section ----------------------------*/
+
+PRFileDesc *Pk11Install_FD=NULL;
+
+/*************************************************************************/
+/* dummy function required by lex */
+int Pk11Install_yywrap(void) { return 1;}
+
+/*************************************************************************/
+/* Return a copy of the given string */
+static char*
+putSimpleString(char *str)
+{
+ char *tmp = (char*) PR_Malloc(strlen(str)+1);
+ strcpy(tmp, str);
+ return tmp;
+}
+
+/*************************************************************************/
+/* Strip out quotes, replace escaped characters with what they stand for.
+ This function assumes that what is passed in is actually a complex
+ string, so error checking is lax. */
+static char*
+putComplexString(char *str)
+{
+ int size, i,j;
+ char *tmp;
+
+ if(!str) {
+ return NULL;
+ }
+ size = strlen(str);
+
+ /* Allocate the new space. This string will actually be too big,
+ since quotes and backslashes will be stripped out. But that's ok. */
+ tmp = (char*) PR_Malloc(size+1);
+
+ /* Copy it over */
+ for(i=0, j=0; i < size; i++) {
+ if(str[i]=='\"') {
+ continue; /* skip un-escaped quotes */
+ } else if(str[i]=='\\') {
+ ++i; /* escaped character. skip the backslash */
+ }
+ tmp[j++] = str[i];
+ }
+ tmp[j] = '\0';
+
+ return tmp;
+}
diff --git a/security/nss/cmd/modutil/manifest.mn b/security/nss/cmd/modutil/manifest.mn
new file mode 100644
index 000000000..b9ff7dc18
--- /dev/null
+++ b/security/nss/cmd/modutil/manifest.mn
@@ -0,0 +1,62 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+MODULE = sectools
+
+EXPORTS =
+
+CSRCS = modutil.c \
+ pk11.c \
+ instsec.c \
+ install.c \
+ installparse.c \
+ install-ds.c \
+ lex.Pk11Install_yy.c \
+ $(NULL)
+
+CPPSRCS =
+
+PROGRAM = modutil
+
+REQUIRES = seccmd nss dbm
+
+DEFINES = -DNSPR20
+
+# sigh
+#INCLUDES += -I$(CORE_DEPTH)/nss/lib/pk11wrap
+
+# USE_STATIC_LIBS = 1
+
+EXTRA_LIBS = $(JAR_LIBS)
diff --git a/security/nss/cmd/modutil/modutil.c b/security/nss/cmd/modutil/modutil.c
new file mode 100644
index 000000000..ba67ffa3c
--- /dev/null
+++ b/security/nss/cmd/modutil/modutil.c
@@ -0,0 +1,999 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "modutil.h"
+#include "install.h"
+#include <plstr.h>
+#include "secrng.h"
+#include "certdb.h" /* for CERT_DB_FILE_VERSION */
+#include "nss.h"
+
+static void install_error(char *message);
+static char* PR_fgets(char *buf, int size, PRFileDesc *file);
+static char *progName;
+
+
+/* This enum must be kept in sync with the commandNames list */
+typedef enum {
+ NO_COMMAND,
+ ADD_COMMAND,
+ CHANGEPW_COMMAND,
+ CREATE_COMMAND,
+ DEFAULT_COMMAND,
+ DELETE_COMMAND,
+ DISABLE_COMMAND,
+ ENABLE_COMMAND,
+ FIPS_COMMAND,
+ JAR_COMMAND,
+ LIST_COMMAND,
+ RAW_LIST_COMMAND,
+ RAW_ADD_COMMAND,
+ CHKFIPS_COMMAND,
+ UNDEFAULT_COMMAND
+} Command;
+
+/* This list must be kept in sync with the Command enum */
+static char *commandNames[] = {
+ "(no command)",
+ "-add",
+ "-changepw",
+ "-create",
+ "-default",
+ "-delete",
+ "-disable",
+ "-enable",
+ "-fips",
+ "-jar",
+ "-list",
+ "-rawlist",
+ "-rawadd",
+ "-chkfips",
+ "-undefault"
+};
+
+
+/* this enum must be kept in sync with the optionStrings list */
+typedef enum {
+ ADD_ARG=0,
+ RAW_ADD_ARG,
+ CHANGEPW_ARG,
+ CIPHERS_ARG,
+ CREATE_ARG,
+ DBDIR_ARG,
+ DBPREFIX_ARG,
+ DEFAULT_ARG,
+ DELETE_ARG,
+ DISABLE_ARG,
+ ENABLE_ARG,
+ FIPS_ARG,
+ FORCE_ARG,
+ JAR_ARG,
+ LIBFILE_ARG,
+ LIST_ARG,
+ RAW_LIST_ARG,
+ MECHANISMS_ARG,
+ NEWPWFILE_ARG,
+ PWFILE_ARG,
+ SLOT_ARG,
+ UNDEFAULT_ARG,
+ INSTALLDIR_ARG,
+ TEMPDIR_ARG,
+ SECMOD_ARG,
+ NOCERTDB_ARG,
+ STRING_ARG,
+ CHKFIPS_ARG,
+
+ NUM_ARGS /* must be last */
+} Arg;
+
+/* This list must be kept in sync with the Arg enum */
+static char *optionStrings[] = {
+ "-add",
+ "-rawadd",
+ "-changepw",
+ "-ciphers",
+ "-create",
+ "-dbdir",
+ "-dbprefix",
+ "-default",
+ "-delete",
+ "-disable",
+ "-enable",
+ "-fips",
+ "-force",
+ "-jar",
+ "-libfile",
+ "-list",
+ "-rawlist",
+ "-mechanisms",
+ "-newpwfile",
+ "-pwfile",
+ "-slot",
+ "-undefault",
+ "-installdir",
+ "-tempdir",
+ "-secmod",
+ "-nocertdb",
+ "-string",
+ "-chkfips",
+};
+
+/* Increment i if doing so would have i still be less than j. If you
+ are able to do this, return 0. Otherwise return 1. */
+#define TRY_INC(i,j) ( ((i+1)<j) ? (++i, 0) : 1 )
+
+/********************************************************************
+ *
+ * file-wide variables obtained from the command line
+ */
+static Command command = NO_COMMAND;
+static char* pwFile = NULL;
+static char* newpwFile = NULL;
+static char* moduleName = NULL;
+static char* moduleSpec = NULL;
+static char* slotName = NULL;
+static char* secmodName = NULL;
+static char* tokenName = NULL;
+static char* libFile = NULL;
+static char* dbdir = NULL;
+static char* dbprefix = "";
+static char* secmodString = NULL;
+static char* mechanisms = NULL;
+static char* ciphers = NULL;
+static char* fipsArg = NULL;
+static char* jarFile = NULL;
+static char* installDir = NULL;
+static char* tempDir = NULL;
+static short force = 0;
+static PRBool nocertdb = PR_FALSE;
+
+/*******************************************************************
+ *
+ * p a r s e _ a r g s
+ */
+static Error
+parse_args(int argc, char *argv[])
+{
+ int i;
+ char *arg;
+ int optionType;
+
+ /* Loop over all arguments */
+ for(i=1; i < argc; i++) {
+ arg = argv[i];
+
+ /* Make sure this is an option and not some floating argument */
+ if(arg[0] != '-') {
+ PR_fprintf(PR_STDERR, errStrings[UNEXPECTED_ARG_ERR], argv[i]);
+ return UNEXPECTED_ARG_ERR;
+ }
+
+ /* Find which option this is */
+ for(optionType=0; optionType < NUM_ARGS; optionType++) {
+ if(! strcmp(arg, optionStrings[optionType])) {
+ break;
+ }
+ }
+
+ /* Deal with this specific option */
+ switch(optionType) {
+ case NUM_ARGS:
+ default:
+ PR_fprintf(PR_STDERR, errStrings[UNKNOWN_OPTION_ERR], arg);
+ return UNKNOWN_OPTION_ERR;
+ break;
+ case ADD_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = ADD_COMMAND;
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ moduleName = argv[i];
+ break;
+ case CHANGEPW_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = CHANGEPW_COMMAND;
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ tokenName = argv[i];
+ break;
+ case CIPHERS_ARG:
+ if(ciphers != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ ciphers = argv[i];
+ break;
+ case CREATE_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = CREATE_COMMAND;
+ break;
+ case DBDIR_ARG:
+ if(dbdir != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ dbdir = argv[i];
+ break;
+ case DBPREFIX_ARG:
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ dbprefix = argv[i];
+ break;
+ case UNDEFAULT_ARG:
+ case DEFAULT_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ if(optionType == DEFAULT_ARG) {
+ command = DEFAULT_COMMAND;
+ } else {
+ command = UNDEFAULT_COMMAND;
+ }
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ moduleName = argv[i];
+ break;
+ case DELETE_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = DELETE_COMMAND;
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ moduleName = argv[i];
+ break;
+ case DISABLE_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = DISABLE_COMMAND;
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ moduleName = argv[i];
+ break;
+ case ENABLE_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = ENABLE_COMMAND;
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ moduleName = argv[i];
+ break;
+ case FIPS_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = FIPS_COMMAND;
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ fipsArg = argv[i];
+ break;
+ case CHKFIPS_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = CHKFIPS_COMMAND;
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ fipsArg = argv[i];
+ break;
+ case FORCE_ARG:
+ force = 1;
+ break;
+ case NOCERTDB_ARG:
+ nocertdb = PR_TRUE;
+ break;
+ case INSTALLDIR_ARG:
+ if(installDir != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ installDir = argv[i];
+ break;
+ case TEMPDIR_ARG:
+ if(tempDir != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ tempDir = argv[i];
+ break;
+ case JAR_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = JAR_COMMAND;
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ jarFile = argv[i];
+ break;
+ case LIBFILE_ARG:
+ if(libFile != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ libFile = argv[i];
+ break;
+ case LIST_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = LIST_COMMAND;
+ /* This option may or may not have an argument */
+ if( (i+1 < argc) && (argv[i+1][0] != '-') ) {
+ moduleName = argv[++i];
+ }
+ break;
+ case RAW_LIST_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = RAW_LIST_COMMAND;
+ /* This option may or may not have an argument */
+ if( (i+1 < argc) && (argv[i+1][0] != '-') ) {
+ moduleName = argv[++i];
+ }
+ break;
+ case RAW_ADD_ARG:
+ if(command != NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
+ return MULTIPLE_COMMAND_ERR;
+ }
+ command = RAW_ADD_COMMAND;
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ moduleSpec = argv[i];
+ break;
+ case MECHANISMS_ARG:
+ if(mechanisms != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ mechanisms = argv[i];
+ break;
+ case NEWPWFILE_ARG:
+ if(newpwFile != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ newpwFile = argv[i];
+ break;
+ case PWFILE_ARG:
+ if(pwFile != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ pwFile = argv[i];
+ break;
+ case SLOT_ARG:
+ if(slotName != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ slotName = argv[i];
+ break;
+ case SECMOD_ARG:
+ if(secmodName != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ secmodName = argv[i];
+ break;
+ case STRING_ARG:
+ if(secmodString != NULL) {
+ PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
+ return DUPLICATE_OPTION_ERR;
+ }
+ if(TRY_INC(i, argc)) {
+ PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
+ return OPTION_NEEDS_ARG_ERR;
+ }
+ secmodString = argv[i];
+ break;
+ }
+ }
+ return SUCCESS;
+}
+
+/************************************************************************
+ *
+ * v e r i f y _ p a r a m s
+ */
+static Error
+verify_params()
+{
+ switch(command) {
+ case ADD_COMMAND:
+ if(libFile == NULL) {
+ PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
+ commandNames[ADD_COMMAND], optionStrings[LIBFILE_ARG]);
+ return MISSING_PARAM_ERR;
+ }
+ break;
+ case CHANGEPW_COMMAND:
+ break;
+ case CREATE_COMMAND:
+ break;
+ case DELETE_COMMAND:
+ break;
+ case DISABLE_COMMAND:
+ break;
+ case ENABLE_COMMAND:
+ break;
+ case FIPS_COMMAND:
+ case CHKFIPS_COMMAND:
+ if(PL_strcasecmp(fipsArg, "true") &&
+ PL_strcasecmp(fipsArg, "false")) {
+ PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
+ return INVALID_FIPS_ARG;
+ }
+ break;
+ case JAR_COMMAND:
+ if(installDir == NULL) {
+ PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
+ commandNames[JAR_COMMAND], optionStrings[INSTALLDIR_ARG]);
+ return MISSING_PARAM_ERR;
+ }
+ break;
+ case LIST_COMMAND:
+ case RAW_LIST_COMMAND:
+ break;
+ case RAW_ADD_COMMAND:
+ break;
+ case UNDEFAULT_COMMAND:
+ case DEFAULT_COMMAND:
+ if(mechanisms == NULL) {
+ PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
+ commandNames[command], optionStrings[MECHANISMS_ARG]);
+ return MISSING_PARAM_ERR;
+ }
+ break;
+ default:
+ /* Ignore this here */
+ break;
+ }
+
+ return SUCCESS;
+}
+
+/********************************************************************
+ *
+ * i n i t _ c r y p t o
+ *
+ * Does crypto initialization that all commands will require.
+ * If -nocertdb option is specified, don't open key or cert db (we don't
+ * need them if we aren't going to be verifying signatures). This is
+ * because serverland doesn't always have cert and key database files
+ * available.
+ */
+static Error
+init_crypto(PRBool create, PRBool readOnly)
+{
+ char *dir;
+#ifdef notdef
+ char *moddbname=NULL, *keydbname, *certdbname;
+ PRBool free_moddbname = PR_FALSE;
+#endif
+ Error retval;
+ SECStatus rv;
+ PRUint32 flags = 0;
+
+ if (secmodName == NULL) {
+ secmodName = "secmod.db";
+ }
+
+ if(SECU_ConfigDirectory(dbdir)[0] == '\0') {
+ PR_fprintf(PR_STDERR, errStrings[NO_DBDIR_ERR]);
+ retval=NO_DBDIR_ERR;
+ goto loser;
+ }
+ dir = SECU_ConfigDirectory(NULL);
+
+ /* Make sure db directory exists and is readable */
+ if(PR_Access(dir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dir);
+ retval = DIR_DOESNT_EXIST_ERR;
+ goto loser;
+ } else if(PR_Access(dir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dir);
+ retval = DIR_NOT_READABLE_ERR;
+ goto loser;
+ }
+
+ /* Check for the proper permissions on databases */
+ if(create) {
+ /* Make sure dbs don't already exist, and the directory is
+ writeable */
+#ifdef notdef
+ if(PR_Access(moddbname, PR_ACCESS_EXISTS)==PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_ALREADY_EXISTS_ERR],
+ moddbname);
+ retval=FILE_ALREADY_EXISTS_ERR;
+ goto loser;
+ } else if(PR_Access(keydbname, PR_ACCESS_EXISTS)==PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_ALREADY_EXISTS_ERR], keydbname);
+ retval=FILE_ALREADY_EXISTS_ERR;
+ goto loser;
+ } else if(PR_Access(certdbname, PR_ACCESS_EXISTS)==PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_ALREADY_EXISTS_ERR],certdbname);
+ retval=FILE_ALREADY_EXISTS_ERR;
+ goto loser;
+ } else
+#endif
+ if(PR_Access(dir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dir);
+ retval=DIR_NOT_WRITEABLE_ERR;
+ goto loser;
+ }
+ } else {
+#ifdef notdef
+ /* Make sure dbs are readable and writeable */
+ if(PR_Access(moddbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+#ifndef XP_PC
+ /* in serverland, they always use secmod.db, even on UNIX. Try
+ this */
+ moddbname = PR_smprintf("%s/secmod.db", dir);
+ free_moddbname = PR_TRUE;
+ if(PR_Access(moddbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+#endif
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR], moddbname);
+ retval=FILE_NOT_READABLE_ERR;
+ goto loser;
+#ifndef XP_PC
+ }
+#endif
+ }
+ if(!nocertdb) { /* don't open cert and key db if -nocertdb */
+ if(PR_Access(keydbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
+ keydbname);
+ retval=FILE_NOT_READABLE_ERR;
+ goto loser;
+ }
+ if(PR_Access(certdbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
+ certdbname);
+ retval=FILE_NOT_READABLE_ERR;
+ goto loser;
+ }
+ }
+#endif
+
+ /* Check for write access if we'll be making changes */
+ if( !readOnly ) {
+#ifdef notdef
+ if(PR_Access(moddbname, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
+ moddbname);
+ retval=FILE_NOT_WRITEABLE_ERR;
+ goto loser;
+ }
+ if(!nocertdb) { /* don't open key and cert db if -nocertdb */
+ if(PR_Access(keydbname, PR_ACCESS_WRITE_OK)
+ != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
+ keydbname);
+ retval=FILE_NOT_WRITEABLE_ERR;
+ goto loser;
+ }
+ if(PR_Access(certdbname, PR_ACCESS_WRITE_OK)
+ != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
+ certdbname);
+ retval=FILE_NOT_WRITEABLE_ERR;
+ goto loser;
+ }
+ }
+#endif
+ }
+ PR_fprintf(PR_STDOUT, msgStrings[USING_DBDIR_MSG],
+ SECU_ConfigDirectory(NULL));
+ }
+
+ /* Open/create key database */
+ flags = 0;
+ if (readOnly) flags |= NSS_INIT_READONLY;
+ if (nocertdb) flags |= NSS_INIT_NOCERTDB;
+ rv = NSS_Initialize(SECU_ConfigDirectory(NULL), dbprefix, dbprefix,
+ secmodName, flags);
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ retval=NSS_INITIALIZE_FAILED_ERR;
+ goto loser;
+ }
+
+ retval=SUCCESS;
+loser:
+#ifdef notdef
+ if(free_moddbname) {
+ PR_Free(moddbname);
+ }
+#endif
+ return retval;
+}
+
+/*************************************************************************
+ *
+ * u s a g e
+ */
+static void
+usage()
+{
+ PR_fprintf(PR_STDOUT,
+"\nNetscape Cryptographic Module Utility\n"
+"Usage: modutil [command] [options]\n\n"
+" COMMANDS\n"
+"---------------------------------------------------------------------------\n"
+"-add MODULE_NAME Add the named module to the module database\n"
+" -libfile LIBRARY_FILE The name of the file (.so or .dll)\n"
+" containing the implementation of PKCS #11\n"
+" [-ciphers CIPHER_LIST] Enable the given ciphers on this module\n"
+" [-mechanisms MECHANISM_LIST] Make the module a default provider of the\n"
+" given mechanisms\n"
+" [-string CONFIG_STRING] Pass a configuration string to this module\n"
+"-changepw TOKEN Change the password on the named token\n"
+" [-pwfile FILE] The old password is in this file\n"
+" [-newpwfile FILE] The new password is in this file\n"
+"-create Create a new set of security databases\n"
+"-default MODULE Make the given module a default provider\n"
+" -mechanisms MECHANISM_LIST of the given mechanisms\n"
+" [-slot SLOT] limit change to only the given slot\n"
+"-delete MODULE Remove the named module from the module\n"
+" database\n"
+"-disable MODULE Disable the named module\n"
+" [-slot SLOT] Disable only the named slot on the module\n"
+"-enable MODULE Enable the named module\n"
+" [-slot SLOT] Enable only the named slot on the module\n"
+"-fips [ true | false ] If true, enable FIPS mode. If false,\n"
+" disable FIPS mode\n"
+"-force Do not run interactively\n"
+"-jar JARFILE Install a PKCS #11 module from the given\n"
+" JAR file in the PKCS #11 JAR format\n"
+" -installdir DIR Use DIR as the root directory of the\n"
+" installation\n"
+" [-tempdir DIR] Use DIR as the temporary installation\n"
+" directory. If not specified, the current\n"
+" directory is used\n"
+"-list [MODULE] Lists information about the specified module\n"
+" or about all modules if none is specified\n"
+"-chkfips [ true | false ] If true, verify FIPS mode. If false,\n"
+" verify not FIPS mode\n"
+"-undefault MODULE The given module is NOT a default provider\n"
+" -mechanisms MECHANISM_LIST of the listed mechanisms\n"
+" [-slot SLOT] limit change to only the given slot\n"
+"---------------------------------------------------------------------------\n"
+"\n"
+" OPTIONS\n"
+"---------------------------------------------------------------------------\n"
+"-dbdir DIR Directory DIR contains the security databases\n"
+"-dbprefix prefix Prefix for the security databases\n"
+"-nocertdb Do not load certificate or key databases. No\n"
+" verification will be performed on JAR files.\n"
+"-secmod secmodName Name of the security modules file\n"
+"---------------------------------------------------------------------------\n"
+"\n"
+"Mechanism lists are colon-separated. The following mechanisms are recognized:\n"
+"RSA, DSA, RC2, RC4, RC5, DES, DH, FORTEZZA, SHA1, MD5, MD2, SSL, TLS, RANDOM,\n"
+" FRIENDLY\n"
+"\n"
+"Cipher lists are colon-separated. The following ciphers are recognized:\n"
+"FORTEZZA\n"
+"\nQuestions or bug reports should be sent to modutil-support@netscape.com.\n"
+);
+
+}
+
+/*************************************************************************
+ *
+ * m a i n
+ */
+int
+main(int argc, char *argv[])
+{
+ int errcode = SUCCESS;
+ PRBool createdb, readOnly;
+#define STDINBUF_SIZE 80
+ char stdinbuf[STDINBUF_SIZE];
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+ if(parse_args(argc, argv) != SUCCESS) {
+ usage();
+ errcode = INVALID_USAGE_ERR;
+ goto loser;
+ }
+
+ if(verify_params() != SUCCESS) {
+ usage();
+ errcode = INVALID_USAGE_ERR;
+ goto loser;
+ }
+
+ if(command==NO_COMMAND) {
+ PR_fprintf(PR_STDERR, errStrings[NO_COMMAND_ERR]);
+ usage();
+ errcode = INVALID_USAGE_ERR;
+ goto loser;
+ }
+
+ if ((command == RAW_LIST_COMMAND) || (command == RAW_ADD_COMMAND)) {
+ if(!moduleName) {
+ char *readOnlyStr, *noCertDBStr, *sep;
+ if (!secmodName) secmodName="secmod.db";
+ if (!dbprefix) dbprefix = "";
+ sep = ((command == RAW_LIST_COMMAND) && nocertdb) ? "," : " ";
+ readOnlyStr = (command == RAW_LIST_COMMAND) ? "readOnly" : "" ;
+ noCertDBStr = nocertdb ? "noCertDB" : "";
+ SECU_ConfigDirectory(dbdir);
+
+ moduleName=PR_smprintf("name=\"NSS default Module DB\" parameters=\"configdir=%s certPrefix=%s keyPrefix=%s secmod=%s flags=%s%s%s\" NSS=\"flags=internal,moduleDB,moduleDBOnly,critical\"",
+ SECU_ConfigDirectory(NULL),dbprefix, dbprefix,
+ secmodName, readOnlyStr,sep, noCertDBStr);
+ }
+ if (command == RAW_LIST_COMMAND) {
+ errcode = RawListModule(moduleName);
+ } else {
+ PORT_Assert(moduleSpec);
+ errcode = RawAddModule(moduleName,moduleSpec);
+ }
+ goto loser;
+ }
+
+ /* Set up crypto stuff */
+ createdb = command==CREATE_COMMAND;
+ readOnly = ((command==LIST_COMMAND) || (command==CHKFIPS_COMMAND));
+
+ /* Make sure browser is not running if we're writing to a database */
+ /* Do this before initializing crypto */
+ if(!readOnly && !force) {
+ char *response;
+
+ PR_fprintf(PR_STDOUT, msgStrings[BROWSER_RUNNING_MSG]);
+ if( ! PR_fgets(stdinbuf, STDINBUF_SIZE, PR_STDIN)) {
+ PR_fprintf(PR_STDERR, errStrings[STDIN_READ_ERR]);
+ errcode = STDIN_READ_ERR;
+ goto loser;
+ }
+ if( (response=strtok(stdinbuf, " \r\n\t")) ) {
+ if(!PL_strcasecmp(response, "q")) {
+ PR_fprintf(PR_STDOUT, msgStrings[ABORTING_MSG]);
+ errcode = SUCCESS;
+ goto loser;
+ }
+ }
+ PR_fprintf(PR_STDOUT, "\n");
+ }
+
+ errcode = init_crypto(createdb, readOnly);
+ if( errcode != SUCCESS) {
+ goto loser;
+ }
+
+
+ /* Execute the command */
+ switch(command) {
+ case ADD_COMMAND:
+ errcode = AddModule(moduleName, libFile, ciphers, mechanisms, secmodString);
+ break;
+ case CHANGEPW_COMMAND:
+ errcode = ChangePW(tokenName, pwFile, newpwFile);
+ break;
+ case CREATE_COMMAND:
+ /* The work was already done in init_crypto() */
+ break;
+ case DEFAULT_COMMAND:
+ errcode = SetDefaultModule(moduleName, slotName, mechanisms);
+ break;
+ case DELETE_COMMAND:
+ errcode = DeleteModule(moduleName);
+ break;
+ case DISABLE_COMMAND:
+ errcode = EnableModule(moduleName, slotName, PR_FALSE);
+ break;
+ case ENABLE_COMMAND:
+ errcode = EnableModule(moduleName, slotName, PR_TRUE);
+ break;
+ case FIPS_COMMAND:
+ errcode = FipsMode(fipsArg);
+ break;
+ case CHKFIPS_COMMAND:
+ errcode = ChkFipsMode(fipsArg);
+ break;
+ case JAR_COMMAND:
+ Pk11Install_SetErrorHandler(install_error);
+ errcode = Pk11Install_DoInstall(jarFile, installDir, tempDir,
+ PR_STDOUT, force, nocertdb);
+ break;
+ case LIST_COMMAND:
+ if(moduleName) {
+ errcode = ListModule(moduleName);
+ } else {
+ errcode = ListModules();
+ }
+ break;
+ case UNDEFAULT_COMMAND:
+ errcode = UnsetDefaultModule(moduleName, slotName, mechanisms);
+ break;
+ default:
+ PR_fprintf(PR_STDERR, "This command is not supported yet.\n");
+ errcode = INVALID_USAGE_ERR;
+ break;
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+loser:
+ PR_Cleanup();
+ return errcode;
+}
+
+/************************************************************************
+ *
+ * i n s t a l l _ e r r o r
+ *
+ * Callback function to handle errors in PK11 JAR file installation.
+ */
+static void
+install_error(char *message)
+{
+ PR_fprintf(PR_STDERR, "Install error: %s\n", message);
+}
+
+/*************************************************************************
+ *
+ * o u t _ o f _ m e m o r y
+ */
+void
+out_of_memory(void)
+{
+ PR_fprintf(PR_STDERR, errStrings[OUT_OF_MEM_ERR]);
+ exit(OUT_OF_MEM_ERR);
+}
+
+
+/**************************************************************************
+ *
+ * P R _ f g e t s
+ *
+ * fgets implemented with NSPR.
+ */
+static char*
+PR_fgets(char *buf, int size, PRFileDesc *file)
+{
+ int i;
+ int status;
+ char c;
+
+ i=0;
+ while(i < size-1) {
+ status = PR_Read(file, (void*) &c, 1);
+ if(status==-1) {
+ return NULL;
+ } else if(status==0) {
+ break;
+ }
+ buf[i++] = c;
+ if(c=='\n') {
+ break;
+ }
+ }
+ buf[i]='\0';
+
+ return buf;
+}
diff --git a/security/nss/cmd/modutil/modutil.h b/security/nss/cmd/modutil/modutil.h
new file mode 100644
index 000000000..e6a0eeb13
--- /dev/null
+++ b/security/nss/cmd/modutil/modutil.h
@@ -0,0 +1,67 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifndef MODUTIL_H
+#define MODUTIL_H
+
+#include <stdio.h>
+#include <prio.h>
+#include <prprf.h>
+#include <prinit.h>
+#include <prmem.h>
+#include <plarena.h>
+#include <string.h>
+#include <seccomon.h>
+#include <secmod.h>
+#include <secutil.h>
+
+#include <prlock.h>
+
+#include "error.h"
+
+Error FipsMode(char *arg);
+Error ChkFipsMode(char *arg);
+Error AddModule(char *moduleName, char *libFile, char *ciphers,
+ char *mechanisms, char* modparms);
+Error DeleteModule(char *moduleName);
+Error ListModule(char *moduleName);
+Error ListModules();
+Error ChangePW(char *tokenName, char *pwFile, char *newpwFile);
+Error EnableModule(char *moduleName, char *slotName, PRBool enable);
+Error RawAddModule(char *dbmodulespec, char *modulespec);
+Error RawListModule(char *modulespec);
+Error SetDefaultModule(char *moduleName, char *slotName, char *mechanisms);
+Error UnsetDefaultModule(char *moduleName, char *slotName, char *mechanisms);
+void out_of_memory(void);
+
+#endif /*MODUTIL_H*/
diff --git a/security/nss/cmd/modutil/pk11.c b/security/nss/cmd/modutil/pk11.c
new file mode 100644
index 000000000..5a4041169
--- /dev/null
+++ b/security/nss/cmd/modutil/pk11.c
@@ -0,0 +1,919 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "modutil.h"
+/* #include "secmodti.h" */
+#include "pk11func.h"
+
+static PK11DefaultArrayEntry *pk11_DefaultArray = NULL;
+static int pk11_DefaultArraySize = 0;
+
+/*************************************************************************
+ *
+ * F i p s M o d e
+ * If arg=="true", enable FIPS mode on the internal module. If arg=="false",
+ * disable FIPS mode on the internal module.
+ */
+Error
+FipsMode(char *arg)
+{
+ char *internal_name;
+
+ if(!PORT_Strcasecmp(arg, "true")) {
+ if(!PK11_IsFIPS()) {
+ internal_name = PR_smprintf("%s",
+ SECMOD_GetInternalModule()->commonName);
+ if(SECMOD_DeleteInternalModule(internal_name) != SECSuccess) {
+ PR_fprintf(PR_STDERR, "%s\n", SECU_Strerror(PORT_GetError()));
+ PR_smprintf_free(internal_name);
+ PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
+ return FIPS_SWITCH_FAILED_ERR;
+ }
+ PR_smprintf_free(internal_name);
+ if (!PK11_IsFIPS()) {
+ PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
+ return FIPS_SWITCH_FAILED_ERR;
+ }
+ PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]);
+ } else {
+ PR_fprintf(PR_STDERR, errStrings[FIPS_ALREADY_ON_ERR]);
+ return FIPS_ALREADY_ON_ERR;
+ }
+ } else if(!PORT_Strcasecmp(arg, "false")) {
+ if(PK11_IsFIPS()) {
+ internal_name = PR_smprintf("%s",
+ SECMOD_GetInternalModule()->commonName);
+ if(SECMOD_DeleteInternalModule(internal_name) != SECSuccess) {
+ PR_fprintf(PR_STDERR, "%s\n", SECU_Strerror(PORT_GetError()));
+ PR_smprintf_free(internal_name);
+ PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
+ return FIPS_SWITCH_FAILED_ERR;
+ }
+ PR_smprintf_free(internal_name);
+ if (PK11_IsFIPS()) {
+ PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
+ return FIPS_SWITCH_FAILED_ERR;
+ }
+ PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]);
+ } else {
+ PR_fprintf(PR_STDERR, errStrings[FIPS_ALREADY_OFF_ERR]);
+ return FIPS_ALREADY_OFF_ERR;
+ }
+ } else {
+ PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
+ return INVALID_FIPS_ARG;
+ }
+
+ return SUCCESS;
+}
+
+/*************************************************************************
+ *
+ * C h k F i p s M o d e
+ * If arg=="true", verify FIPS mode is enabled on the internal module.
+ * If arg=="false", verify FIPS mode is disabled on the internal module.
+ */
+Error
+ChkFipsMode(char *arg)
+{
+ if(!PORT_Strcasecmp(arg, "true")) {
+ if (PK11_IsFIPS()) {
+ PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]);
+ } else {
+ PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]);
+ return FIPS_SWITCH_FAILED_ERR;
+ }
+
+ } else if(!PORT_Strcasecmp(arg, "false")) {
+ if(!PK11_IsFIPS()) {
+ PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]);
+ } else {
+ PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]);
+ return FIPS_SWITCH_FAILED_ERR;
+ }
+ } else {
+ PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
+ return INVALID_FIPS_ARG;
+ }
+
+ return SUCCESS;
+}
+
+/************************************************************************
+ * Cipher and Mechanism name-bitmask translation tables
+ */
+
+typedef struct {
+ char *name;
+ unsigned long mask;
+} MaskString;
+
+static MaskString mechanismStrings[] = {
+ {"RSA", PUBLIC_MECH_RSA_FLAG},
+ {"DSA", PUBLIC_MECH_DSA_FLAG},
+ {"RC2", PUBLIC_MECH_RC2_FLAG},
+ {"RC4", PUBLIC_MECH_RC4_FLAG},
+ {"RC5", PUBLIC_MECH_RC5_FLAG},
+ {"DES", PUBLIC_MECH_DES_FLAG},
+ {"DH", PUBLIC_MECH_DH_FLAG},
+ {"FORTEZZA", PUBLIC_MECH_FORTEZZA_FLAG},
+ {"SHA1", PUBLIC_MECH_SHA1_FLAG},
+ {"MD5", PUBLIC_MECH_MD5_FLAG},
+ {"MD2", PUBLIC_MECH_MD2_FLAG},
+ {"SSL", PUBLIC_MECH_SSL_FLAG},
+ {"TLS", PUBLIC_MECH_TLS_FLAG},
+ {"RANDOM", PUBLIC_MECH_RANDOM_FLAG},
+ {"FRIENDLY", PUBLIC_MECH_FRIENDLY_FLAG}
+};
+static int numMechanismStrings =
+ sizeof(mechanismStrings) / sizeof(mechanismStrings[0]);
+
+static MaskString cipherStrings[] = {
+ {"FORTEZZA", PUBLIC_CIPHER_FORTEZZA_FLAG}
+};
+static int numCipherStrings =
+ sizeof(cipherStrings) / sizeof(cipherStrings[0]);
+
+/* Maximum length of a colon-separated list of all the strings in an
+ * array. */
+#define MAX_STRING_LIST_LEN 240 /* or less */
+
+/************************************************************************
+ *
+ * g e t F l a g s F r o m S t r i n g
+ *
+ * Parses a mechanism list passed on the command line and converts it
+ * to an unsigned long bitmask.
+ * string is a colon-separated string of constants
+ * array is an array of MaskStrings.
+ * elements is the number of elements in array.
+ */
+static unsigned long
+getFlagsFromString(char *string, MaskString array[], int elements)
+{
+ unsigned long ret = 0;
+ short i = 0;
+ char *cp;
+ char *buf;
+ char *end;
+
+ if(!string || !string[0]) {
+ return ret;
+ }
+
+ /* Make a temporary copy of the string */
+ buf = PR_Malloc(strlen(string)+1);
+ if(!buf) {
+ out_of_memory();
+ }
+ strcpy(buf, string);
+
+ /* Look at each element of the list passed in */
+ for(cp=buf; cp && *cp; cp = (end ? end+1 : NULL) ) {
+ /* Look at the string up to the next colon */
+ end = strchr(cp, ':');
+ if(end) {
+ *end = '\0';
+ }
+
+ /* Find which element this is */
+ for(i=0; i < elements; i++) {
+ if( !PORT_Strcasecmp(cp, array[i].name) ) {
+ break;
+ }
+ }
+ if(i == elements) {
+ /* Skip a bogus string, but print a warning message */
+ PR_fprintf(PR_STDERR, errStrings[INVALID_CONSTANT_ERR], cp);
+ continue;
+ }
+ ret |= array[i].mask;
+ }
+
+ PR_Free(buf);
+ return ret;
+}
+
+/**********************************************************************
+ *
+ * g e t S t r i n g F r o m F l a g s
+ *
+ * The return string's memory is owned by this function. Copy it
+ * if you need it permanently or you want to change it.
+ */
+static char *
+getStringFromFlags(unsigned long flags, MaskString array[], int elements)
+{
+ static char buf[MAX_STRING_LIST_LEN];
+ int i;
+ int count=0;
+
+ buf[0] = '\0';
+ for(i=0; i<elements; i++) {
+ if( flags & array[i].mask ) {
+ ++count;
+ if(count!=1) {
+ strcat(buf, ":");
+ }
+ strcat(buf, array[i].name);
+ }
+ }
+ return buf;
+}
+
+/**********************************************************************
+ *
+ * A d d M o d u l e
+ *
+ * Add the named module, with the given library file, ciphers, and
+ * default mechanism flags
+ */
+Error
+AddModule(char *moduleName, char *libFile, char *cipherString,
+ char *mechanismString, char* modparms)
+{
+ unsigned long ciphers;
+ unsigned long mechanisms;
+ SECStatus status;
+
+ mechanisms =
+ getFlagsFromString(mechanismString, mechanismStrings,
+ numMechanismStrings);
+ ciphers =
+ getFlagsFromString(cipherString, cipherStrings, numCipherStrings);
+
+ status =
+ SECMOD_AddNewModuleEx(moduleName, libFile,
+ SECMOD_PubMechFlagstoInternal(mechanisms),
+ SECMOD_PubCipherFlagstoInternal(ciphers),
+ modparms, NULL );
+
+ if(status != SECSuccess) {
+ char* errtxt=NULL;
+ PRInt32 copied = 0;
+ if (PR_GetErrorTextLength()) {
+ errtxt = PR_Malloc(PR_GetErrorTextLength());
+ copied = PR_GetErrorText(errtxt);
+ }
+ if (copied && errtxt) {
+ PR_fprintf(PR_STDERR, errStrings[ADD_MODULE_FAILED_STATUS_ERR], moduleName, errtxt);
+ PR_Free(errtxt);
+ }
+ else {
+ PR_fprintf(PR_STDERR, errStrings[ADD_MODULE_FAILED_ERR], moduleName);
+ }
+ return ADD_MODULE_FAILED_ERR;
+ } else {
+ PR_fprintf(PR_STDOUT, msgStrings[ADD_MODULE_SUCCESS_MSG], moduleName);
+ return SUCCESS;
+ }
+}
+
+/***********************************************************************
+ *
+ * D e l e t e M o d u l e
+ *
+ * Deletes the named module from the database.
+ */
+Error
+DeleteModule(char *moduleName)
+{
+ SECStatus status;
+ int type;
+
+ status = SECMOD_DeleteModule(moduleName, &type);
+
+ if(status != SECSuccess) {
+ if(type == SECMOD_FIPS || type == SECMOD_INTERNAL) {
+ PR_fprintf(PR_STDERR, errStrings[DELETE_INTERNAL_ERR]);
+ return DELETE_INTERNAL_ERR;
+ } else {
+ PR_fprintf(PR_STDERR, errStrings[DELETE_FAILED_ERR], moduleName);
+ return DELETE_FAILED_ERR;
+ }
+ }
+
+ PR_fprintf(PR_STDOUT, msgStrings[DELETE_SUCCESS_MSG], moduleName);
+ return SUCCESS;
+}
+
+/************************************************************************
+ *
+ * R a w L i s t M o d u l e s
+ *
+ * Lists all the modules in the database, along with their slots and tokens.
+ */
+Error
+RawListModule(char *modulespec)
+{
+ SECMODModule *module;
+ char **moduleSpecList;
+
+ module = SECMOD_LoadModule(modulespec,NULL,PR_FALSE);
+ if (module == NULL) {
+ /* handle error */
+ return NO_SUCH_MODULE_ERR;
+ }
+
+ moduleSpecList = SECMOD_GetModuleSpecList(module);
+
+ for ( ;*moduleSpecList; moduleSpecList++) {
+ printf("%s\n",*moduleSpecList);
+ }
+
+ return SUCCESS;
+}
+
+Error
+RawAddModule(char *dbmodulespec, char *modulespec)
+{
+ SECMODModule *module;
+ SECMODModule *dbmodule;
+
+
+ dbmodule = SECMOD_LoadModule(dbmodulespec,NULL,PR_TRUE);
+ if (dbmodule == NULL) {
+ /* handle error */
+ return NO_SUCH_MODULE_ERR;
+ }
+
+ module = SECMOD_LoadModule(modulespec,dbmodule,PR_FALSE);
+ if (module == NULL) {
+ /* handle error */
+ return NO_SUCH_MODULE_ERR;
+ }
+
+ if( SECMOD_UpdateModule(module) != SECSuccess ) {
+ PR_fprintf(PR_STDERR, errStrings[UPDATE_MOD_FAILED_ERR], modulespec);
+ return UPDATE_MOD_FAILED_ERR;
+ }
+ return SUCCESS;
+}
+
+/************************************************************************
+ *
+ * L i s t M o d u l e s
+ *
+ * Lists all the modules in the database, along with their slots and tokens.
+ */
+Error
+ListModules()
+{
+ SECMODListLock *lock;
+ SECMODModuleList *list;
+ SECMODModuleList *mlp;
+ Error ret=UNSPECIFIED_ERR;
+ int count = 0, i;
+
+ lock = SECMOD_GetDefaultModuleListLock();
+ if(!lock) {
+ PR_fprintf(PR_STDERR, errStrings[NO_LIST_LOCK_ERR]);
+ return NO_LIST_LOCK_ERR;
+ }
+
+ SECMOD_GetReadLock(lock);
+
+ list = SECMOD_GetDefaultModuleList();
+ if(!list) {
+ PR_fprintf(PR_STDERR, errStrings[NO_MODULE_LIST_ERR]);
+ ret = NO_MODULE_LIST_ERR;
+ goto loser;
+ }
+
+ PR_fprintf(PR_STDOUT,
+ "\nListing of PKCS #11 Modules\n"
+ "-----------------------------------------------------------\n");
+
+ for(mlp=list; mlp != NULL; mlp = mlp->next) {
+ ++count;
+ if(count!=1) {
+ PR_fprintf(PR_STDOUT, "\n");
+ }
+
+ PR_fprintf(PR_STDOUT, "%3d. %s\n", count, mlp->module->commonName);
+
+ if(mlp->module->dllName) {
+ PR_fprintf(PR_STDOUT, "\tlibrary name: %s\n", mlp->module->dllName);
+ }
+
+ if(mlp->module->slotCount == 0) {
+ PR_fprintf(PR_STDOUT,
+ "\t slots: There are no slots attached to this module\n");
+ } else {
+ PR_fprintf(PR_STDOUT,
+ "\t slots: %d slot%s attached\n", mlp->module->slotCount,
+ (mlp->module->slotCount==1 ? "" : "s") );
+ }
+
+ if(mlp->module->loaded == 0) {
+ PR_fprintf(PR_STDOUT, "\tstatus: Not loaded\n");
+ } else {
+ PR_fprintf(PR_STDOUT, "\tstatus: loaded\n");
+ }
+
+ /* Print slot and token names */
+ for (i = 0; i < mlp->module->slotCount; i++) {
+ PK11SlotInfo *slot = mlp->module->slots[i];
+
+ PR_fprintf(PR_STDOUT, "\n");
+ PR_fprintf(PR_STDOUT, "\t slot: %s\n", PK11_GetSlotName(slot));
+ PR_fprintf(PR_STDOUT, "\ttoken: %s\n", PK11_GetTokenName(slot));
+ }
+ }
+
+ PR_fprintf(PR_STDOUT,
+ "-----------------------------------------------------------\n");
+
+ ret = SUCCESS;
+
+loser:
+ SECMOD_ReleaseReadLock(lock);
+ return ret;
+}
+
+/* Strings describing PK11DisableReasons */
+static char *disableReasonStr[] = {
+ "no reason",
+ "user disabled",
+ "could not initialize token",
+ "could not verify token",
+ "token not present"
+};
+static int numDisableReasonStr =
+ sizeof(disableReasonStr) / sizeof(disableReasonStr[0]);
+
+/***********************************************************************
+ *
+ * L i s t M o d u l e
+ *
+ * Lists detailed information about the named module.
+ */
+Error
+ListModule(char *moduleName)
+{
+ SECMODModule *module;
+ PK11SlotInfo *slot;
+ int slotnum;
+ CK_INFO modinfo;
+ CK_SLOT_INFO slotinfo;
+ CK_TOKEN_INFO tokeninfo;
+ char *ciphers, *mechanisms;
+ PK11DisableReasons reason;
+ Error rv = SUCCESS;
+
+ if(!moduleName) {
+ return SUCCESS;
+ }
+
+ module = SECMOD_FindModule(moduleName);
+ if(!module) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
+ return NO_SUCH_MODULE_ERR;
+ }
+
+ if(PK11_GetModInfo(module, &modinfo) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[MOD_INFO_ERR], moduleName);
+ return MOD_INFO_ERR;
+ }
+
+ /* Module info */
+ PR_fprintf(PR_STDOUT,
+ "\n-----------------------------------------------------------\n");
+ PR_fprintf(PR_STDOUT, "Name: %s\n", module->commonName);
+ if(module->internal || !module->dllName) {
+ PR_fprintf(PR_STDOUT, "Library file: **Internal ONLY module**\n");
+ } else {
+ PR_fprintf(PR_STDOUT, "Library file: %s\n", module->dllName);
+ }
+
+ PR_fprintf(PR_STDOUT, "Manufacturer: %.32s\n", modinfo.manufacturerID);
+ PR_fprintf(PR_STDOUT, "Description: %.32s\n", modinfo.libraryDescription);
+ PR_fprintf(PR_STDOUT, "PKCS #11 Version %d.%d\n",
+ modinfo.cryptokiVersion.major, modinfo.cryptokiVersion.minor);
+ PR_fprintf(PR_STDOUT, "Library Version: %d.%d\n",
+ modinfo.libraryVersion.major, modinfo.libraryVersion.minor);
+
+ /* Get cipher and mechanism flags */
+ ciphers = getStringFromFlags(module->ssl[0], cipherStrings,
+ numCipherStrings);
+ if(ciphers[0] == '\0') {
+ ciphers = "None";
+ }
+ PR_fprintf(PR_STDOUT, "Cipher Enable Flags: %s\n", ciphers);
+ mechanisms = NULL;
+ if(module->slotCount > 0) {
+ mechanisms = getStringFromFlags(
+ PK11_GetDefaultFlags(module->slots[0]),
+ mechanismStrings, numMechanismStrings);
+ }
+ if(mechanisms[0] =='\0') {
+ mechanisms = "None";
+ }
+ PR_fprintf(PR_STDOUT, "Default Mechanism Flags: %s\n", mechanisms);
+
+#define PAD " "
+
+ /* Loop over each slot */
+ for(slotnum=0; slotnum < module->slotCount; slotnum++) {
+ slot = module->slots[slotnum];
+ if(PK11_GetSlotInfo(slot, &slotinfo) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[SLOT_INFO_ERR],
+ PK11_GetSlotName(slot));
+ rv = SLOT_INFO_ERR;
+ continue;
+ }
+
+ /* Slot Info */
+ PR_fprintf(PR_STDOUT, "\n"PAD"Slot: %s\n", PK11_GetSlotName(slot));
+ mechanisms = getStringFromFlags(PK11_GetDefaultFlags(slot),
+ mechanismStrings, numMechanismStrings);
+ if(mechanisms[0] =='\0') {
+ mechanisms = "None";
+ }
+ PR_fprintf(PR_STDOUT, PAD"Slot Mechanism Flags: %s\n", mechanisms);
+ PR_fprintf(PR_STDOUT, PAD"Manufacturer: %.32s\n",
+ slotinfo.manufacturerID);
+ if (PK11_IsHW(slot)) {
+ PR_fprintf(PR_STDOUT, PAD"Type: Hardware\n");
+ } else {
+ PR_fprintf(PR_STDOUT, PAD"Type: Software\n");
+ }
+ PR_fprintf(PR_STDOUT, PAD"Version Number: %d.%d\n",
+ slotinfo.hardwareVersion.major, slotinfo.hardwareVersion.minor);
+ PR_fprintf(PR_STDOUT, PAD"Firmware Version: %d.%d\n",
+ slotinfo.firmwareVersion.major, slotinfo.firmwareVersion.minor);
+ if (PK11_IsDisabled(slot)) {
+ reason = PK11_GetDisabledReason(slot);
+ if(reason < numDisableReasonStr) {
+ PR_fprintf(PR_STDOUT, PAD"Status: DISABLED (%s)\n",
+ disableReasonStr[reason]);
+ } else {
+ PR_fprintf(PR_STDOUT, PAD"Status: DISABLED\n");
+ }
+ } else {
+ PR_fprintf(PR_STDOUT, PAD"Status: Enabled\n");
+ }
+
+ if(PK11_GetTokenInfo(slot, &tokeninfo) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[TOKEN_INFO_ERR],
+ PK11_GetTokenName(slot));
+ rv = TOKEN_INFO_ERR;
+ continue;
+ }
+
+ /* Token Info */
+ PR_fprintf(PR_STDOUT, PAD"Token Name: %.32s\n",
+ tokeninfo.label);
+ PR_fprintf(PR_STDOUT, PAD"Token Manufacturer: %.32s\n",
+ tokeninfo.manufacturerID);
+ PR_fprintf(PR_STDOUT, PAD"Token Model: %.16s\n", tokeninfo.model);
+ PR_fprintf(PR_STDOUT, PAD"Token Serial Number: %.16s\n",
+ tokeninfo.serialNumber);
+ PR_fprintf(PR_STDOUT, PAD"Token Version: %d.%d\n",
+ tokeninfo.hardwareVersion.major, tokeninfo.hardwareVersion.minor);
+ PR_fprintf(PR_STDOUT, PAD"Token Firmware Version: %d.%d\n",
+ tokeninfo.firmwareVersion.major, tokeninfo.firmwareVersion.minor);
+ if(tokeninfo.flags & CKF_WRITE_PROTECTED) {
+ PR_fprintf(PR_STDOUT, PAD"Access: Write Protected\n");
+ } else {
+ PR_fprintf(PR_STDOUT, PAD"Access: NOT Write Protected\n");
+ }
+ if(tokeninfo.flags & CKF_LOGIN_REQUIRED) {
+ PR_fprintf(PR_STDOUT, PAD"Login Type: Login required\n");
+ } else {
+ PR_fprintf(PR_STDOUT, PAD
+ "Login Type: Public (no login required)\n");
+ }
+ if(tokeninfo.flags & CKF_USER_PIN_INITIALIZED) {
+ PR_fprintf(PR_STDOUT, PAD"User Pin: Initialized\n");
+ } else {
+ PR_fprintf(PR_STDOUT, PAD"User Pin: NOT Initialized\n");
+ }
+ }
+ PR_fprintf(PR_STDOUT,
+ "\n-----------------------------------------------------------\n");
+ return rv;
+}
+
+/************************************************************************
+ *
+ * C h a n g e P W
+ */
+Error
+ChangePW(char *tokenName, char *pwFile, char *newpwFile)
+{
+ char *oldpw=NULL, *newpw=NULL, *newpw2=NULL;
+ PK11SlotInfo *slot;
+ Error ret=UNSPECIFIED_ERR;
+ PRBool matching;
+
+ slot = PK11_FindSlotByName(tokenName);
+ if(!slot) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_TOKEN_ERR], tokenName);
+ return NO_SUCH_TOKEN_ERR;
+ }
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* Get old password */
+ if(! PK11_NeedUserInit(slot)) {
+ if(pwFile) {
+ oldpw = SECU_FilePasswd(NULL, PR_FALSE, pwFile);
+ if(PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[BAD_PW_ERR]);
+ ret=BAD_PW_ERR;
+ goto loser;
+ }
+ } else {
+ for(matching=PR_FALSE; !matching; ) {
+ oldpw = SECU_GetPasswordString(NULL, "Enter old password: ");
+ if(PK11_CheckUserPassword(slot, oldpw) == SECSuccess) {
+ matching = PR_TRUE;
+ } else {
+ PR_fprintf(PR_STDOUT, msgStrings[BAD_PW_MSG]);
+ }
+ }
+ }
+ }
+
+ /* Get new password */
+ if(newpwFile) {
+ newpw = SECU_FilePasswd(NULL, PR_FALSE, newpwFile);
+ } else {
+ for(matching=PR_FALSE; !matching; ) {
+ newpw = SECU_GetPasswordString(NULL, "Enter new password: ");
+ newpw2 = SECU_GetPasswordString(NULL, "Re-enter new password: ");
+ if(strcmp(newpw, newpw2)) {
+ PR_fprintf(PR_STDOUT, msgStrings[PW_MATCH_MSG]);
+ } else {
+ matching = PR_TRUE;
+ }
+ }
+ }
+
+ /* Change the password */
+ if(PK11_NeedUserInit(slot)) {
+ if(PK11_InitPin(slot, NULL /*ssopw*/, newpw) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName);
+ ret = CHANGEPW_FAILED_ERR;
+ goto loser;
+ }
+ } else {
+ if(PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
+ PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName);
+ ret = CHANGEPW_FAILED_ERR;
+ goto loser;
+ }
+ }
+
+ PR_fprintf(PR_STDOUT, msgStrings[CHANGEPW_SUCCESS_MSG], tokenName);
+ ret = SUCCESS;
+
+loser:
+ if(oldpw) {
+ memset(oldpw, 0, strlen(oldpw));
+ PORT_Free(oldpw);
+ }
+ if(newpw) {
+ memset(newpw, 0, strlen(newpw));
+ PORT_Free(newpw);
+ }
+ if(newpw2) {
+ memset(newpw2, 0, strlen(newpw));
+ PORT_Free(newpw2);
+ }
+ return ret;
+}
+
+/***********************************************************************
+ *
+ * E n a b l e M o d u l e
+ *
+ * If enable==PR_TRUE, enables the module or slot.
+ * If enable==PR_FALSE, disables the module or slot.
+ * moduleName is the name of the module.
+ * slotName is the name of the slot. It is optional.
+ */
+Error
+EnableModule(char *moduleName, char *slotName, PRBool enable)
+{
+ int i;
+ SECMODModule *module;
+ PK11SlotInfo *slot = NULL;
+ PRBool found = PR_FALSE;
+
+ module = SECMOD_FindModule(moduleName);
+ if(!module) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
+ return NO_SUCH_MODULE_ERR;
+ }
+
+ for(i=0; i < module->slotCount; i++) {
+ slot = module->slots[i];
+ if(slotName && strcmp(PK11_GetSlotName(slot), slotName)) {
+ /* Not the right slot */
+ continue;
+ }
+ if(enable) {
+ if(! PK11_UserEnableSlot(slot)) {
+ PR_fprintf(PR_STDERR, errStrings[ENABLE_FAILED_ERR],
+ "enable", PK11_GetSlotName(slot));
+ return ENABLE_FAILED_ERR;
+ } else {
+ found = PR_TRUE;
+ PR_fprintf(PR_STDOUT, msgStrings[ENABLE_SUCCESS_MSG],
+ PK11_GetSlotName(slot), "enabled");
+ }
+ } else {
+ if(! PK11_UserDisableSlot(slot)) {
+ PR_fprintf(PR_STDERR, errStrings[ENABLE_FAILED_ERR],
+ "disable", PK11_GetSlotName(slot));
+ return ENABLE_FAILED_ERR;
+ } else {
+ found = PR_TRUE;
+ PR_fprintf(PR_STDOUT, msgStrings[ENABLE_SUCCESS_MSG],
+ PK11_GetSlotName(slot), "disabled");
+ }
+ }
+ }
+
+ if(slotName && !found) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName);
+ return NO_SUCH_SLOT_ERR;
+ }
+
+ /* Delete and re-add module to save changes */
+ if( SECMOD_UpdateModule(module) != SECSuccess ) {
+ PR_fprintf(PR_STDERR, errStrings[UPDATE_MOD_FAILED_ERR], moduleName);
+ return UPDATE_MOD_FAILED_ERR;
+ }
+
+ return SUCCESS;
+}
+
+/*************************************************************************
+ *
+ * S e t D e f a u l t M o d u l e
+ *
+ */
+Error
+SetDefaultModule(char *moduleName, char *slotName, char *mechanisms)
+{
+ SECMODModule *module;
+ PK11SlotInfo *slot;
+ int s, i;
+ unsigned long mechFlags = getFlagsFromString(mechanisms, mechanismStrings,
+ numMechanismStrings);
+ PRBool found = PR_FALSE;
+ Error errcode = UNSPECIFIED_ERR;
+
+ if (pk11_DefaultArray == NULL) {
+ pk11_DefaultArray = PK11_GetDefaultArray(&pk11_DefaultArraySize);
+ if (pk11_DefaultArray == NULL) {
+ /* should assert. This shouldn't happen */
+ goto loser;
+ }
+ }
+
+ mechFlags = SECMOD_PubMechFlagstoInternal(mechFlags);
+
+ module = SECMOD_FindModule(moduleName);
+ if(!module) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
+ errcode = NO_SUCH_MODULE_ERR;
+ goto loser;
+ }
+
+ /* Go through each slot */
+ for(s=0; s < module->slotCount; s++) {
+ slot = module->slots[s];
+
+ if ((slotName != NULL) &&
+ !((strcmp(PK11_GetSlotName(slot),slotName) == 0) ||
+ (strcmp(PK11_GetTokenName(slot),slotName) == 0)) ) {
+ /* we are only interested in changing the one slot */
+ continue;
+ }
+
+ found = PR_TRUE;
+
+ /* Go through each mechanism */
+ for(i=0; i < pk11_DefaultArraySize; i++) {
+ if(pk11_DefaultArray[i].flag & mechFlags) {
+ /* Enable this default mechanism */
+ PK11_UpdateSlotAttribute(slot, &(pk11_DefaultArray[i]),
+ PR_TRUE);
+ }
+ }
+ }
+ if (slotName && !found) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName);
+ errcode = NO_SUCH_SLOT_ERR;
+ goto loser;
+ }
+
+ /* Delete and re-add module to save changes */
+ if( SECMOD_UpdateModule(module) != SECSuccess ) {
+ PR_fprintf(PR_STDERR, errStrings[DEFAULT_FAILED_ERR],
+ moduleName);
+ errcode = DEFAULT_FAILED_ERR;
+ goto loser;
+ }
+
+ PR_fprintf(PR_STDOUT, msgStrings[DEFAULT_SUCCESS_MSG]);
+
+ errcode = SUCCESS;
+loser:
+ return errcode;
+}
+
+/************************************************************************
+ *
+ * U n s e t D e f a u l t M o d u l e
+ */
+Error
+UnsetDefaultModule(char *moduleName, char *slotName, char *mechanisms)
+{
+ SECMODModule * module;
+ PK11SlotInfo *slot;
+ int s, i;
+ unsigned long mechFlags = getFlagsFromString(mechanisms,
+ mechanismStrings, numMechanismStrings);
+ PRBool found = PR_FALSE;
+
+ if (pk11_DefaultArray == NULL) {
+ pk11_DefaultArray = PK11_GetDefaultArray(&pk11_DefaultArraySize);
+ if (pk11_DefaultArray == NULL) {
+ /* should assert. This shouldn't happen */
+ return UNSPECIFIED_ERR;
+ }
+ }
+
+ mechFlags = SECMOD_PubMechFlagstoInternal(mechFlags);
+
+ module = SECMOD_FindModule(moduleName);
+ if(!module) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
+ return NO_SUCH_MODULE_ERR;
+ }
+
+ for(s=0; s < module->slotCount; s++) {
+ slot = module->slots[s];
+ if ((slotName != NULL) &&
+ !((strcmp(PK11_GetSlotName(slot),slotName) == 0) ||
+ (strcmp(PK11_GetTokenName(slot),slotName) == 0)) ) {
+ /* we are only interested in changing the one slot */
+ continue;
+ }
+ for(i=0; i < pk11_DefaultArraySize ; i++) {
+ if(pk11_DefaultArray[i].flag & mechFlags) {
+ PK11_UpdateSlotAttribute(slot, &(pk11_DefaultArray[i]),
+ PR_FALSE);
+ }
+ }
+ }
+ if (slotName && !found) {
+ PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName);
+ return NO_SUCH_SLOT_ERR;
+ }
+
+ /* Delete and re-add module to save changes */
+ if( SECMOD_UpdateModule(module) != SECSuccess ) {
+ PR_fprintf(PR_STDERR, errStrings[UNDEFAULT_FAILED_ERR],
+ moduleName);
+ return UNDEFAULT_FAILED_ERR;
+ }
+
+ PR_fprintf(PR_STDOUT, msgStrings[UNDEFAULT_SUCCESS_MSG]);
+ return SUCCESS;
+}
diff --git a/security/nss/cmd/modutil/pk11jar.html b/security/nss/cmd/modutil/pk11jar.html
new file mode 100644
index 000000000..9440db014
--- /dev/null
+++ b/security/nss/cmd/modutil/pk11jar.html
@@ -0,0 +1,309 @@
+<html>
+<!--
+ - The contents of this file are subject to the Mozilla Public
+ - License Version 1.1 (the "License"); you may not use this file
+ - except in compliance with the License. You may obtain a copy of
+ - the License at http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS
+ - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ - implied. See the License for the specific language governing
+ - rights and limitations under the License.
+ -
+ - The Original Code is the Netscape security libraries.
+ -
+ - The Initial Developer of the Original Code is Netscape
+ - Communications Corporation. Portions created by Netscape are
+ - Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ - Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the
+ - terms of the GNU General Public License Version 2 or later (the
+ - "GPL"), in which case the provisions of the GPL are applicable
+ - instead of those above. If you wish to allow use of your
+ - version of this file only under the terms of the GPL and not to
+ - allow others to use your version of this file under the MPL,
+ - indicate your decision by deleting the provisions above and
+ - replace them with the notice and other provisions required by
+ - the GPL. If you do not delete the provisions above, a recipient
+ - may use your version of this file under either the MPL or the
+ - GPL.
+ -->
+<head>
+<title>PKCS #11 JAR Format</title>
+</head>
+<body bgcolor=white text=black link=blue vlink=purple alink=red>
+<center><h1>PKCS #11 JAR Format</h1></center>
+
+<p>PKCS #11 modules can be packaged into JAR files that support automatic
+installation onto the filesystem and into the security module database.
+The JAR file should contain:
+<ul>
+<li>All files that will be installed onto the target machine. This will
+include at least the PKCS #11 module library file (.DLL or .so), and
+may also include any other file that should be installed (such as
+documentation).
+<li>A script to perform the installation.
+</ul>
+The script can be in one of two forms. If the JAR file is to be
+run by Communicator (or any program that interprets Javascript), the
+instructions will be in the form of a SmartUpdate script.
+<a href="http://devedge/library/documentation/security/jmpkcs/">Documentation
+</a> on creating this script can be found on DevEdge.
+
+<p>If the
+JAR file is to be run by a server, modutil, or any other program that
+doesn't interpret Javascript, a special information file must be included
+in the format described in this document.
+
+<h2>Declaring the Script in the Manifest File</h2>
+The script can have any name, but it must be declared in the manifest file
+of the JAR archive. The metainfo tag for this is
+<code>Pkcs11_install_script</code>. Meta-information is put in the manifest
+file by putting it in a file which is passed to
+<a href="http://developer.netscape.com/software/index_frame.html?content=signedobj/jarpack.html#signtool1.3">Signtool</a>. For example,
+suppose the PKCS #11 installer script is in the file <code>pk11install</code>.
+In Signtool's metainfo file, you would have a line like this:
+<blockquote><pre>
++ Pkcs11_install_script: pk11install
+</pre></blockquote>
+
+<h2>Sample Script File</h2>
+<blockquote><pre>
+ForwardCompatible { IRIX:6.2:mips Solaris:5.5.1:sparc }
+Platforms {
+ WINNT::x86 {
+ ModuleName { "Fortezza Module" }
+ ModuleFile { win32/fort32.dll }
+ DefaultMechanismFlags{0x0001}
+ DefaultCipherFlags{0x0001}
+ Files {
+ win32/setup.exe {
+ Executable
+ RelativePath { %temp%/setup.exe }
+ }
+ win32/setup.hlp {
+ RelativePath { %temp%/setup.hlp }
+ }
+ win32/setup.cab {
+ RelativePath { %temp%/setup.cab }
+ }
+ }
+ }
+ WIN95::x86 {
+ EquivalentPlatform {WINNT::x86}
+ }
+ Solaris:5.5.1:sparc {
+ ModuleName { "Fortezza UNIX Module" }
+ ModuleFile { unix/fort.so }
+ DefaultMechanismFlags{0x0001}
+ CipherEnableFlags{0x0001}
+ Files {
+ unix/fort.so {
+ RelativePath{%root%/lib/fort.so}
+ AbsolutePath{/usr/local/netscape/lib/fort.so}
+ FilePermissions{555}
+ }
+ xplat/instr.html {
+ RelativePath{%root%/docs/inst.html}
+ AbsolutePath{/usr/local/netscape/docs/inst.html}
+ FilePermissions{555}
+ }
+ }
+ }
+ IRIX:6.2:mips {
+ EquivalentPlatform { Solaris:5.5.1:sparc }
+ }
+}
+</pre></blockquote>
+
+<hr>
+
+<h2>Script File Grammar</h2>
+<blockquote><pre>
+--> <i>valuelist</i>
+
+<i>valuelist</i> --> <i>value</i> <i>valuelist</i>
+<i> </i> <i>&lt;null&gt;</i>
+
+<i>value</i> --> <i>key_value_pair</i>
+<i> </i> <i>string</i>
+
+<i>key_value_pair</i> --> <i>key</i> { <i>valuelist</i> }
+
+<i>key</i> --> <i>string</i>
+
+<i>string</i> --> <i>simple_string</i>
+<i> </i> "<i>complex_string</i>"
+
+<i>simple_string</i> --> [^ \t\n\""{""}"]+ <font size=-1><i>(no whitespace, quotes, or braces)</i></font>
+
+<i>complex_string</i> --> ([^\"\\\r\n]|(\\\")|(\\\\))+ <font size=-1><i>(quotes and backslashes must be escaped with a backslash, no newlines or carriage returns are allowed in the string)</i></font>
+</pre></blockquote>
+Outside of complex strings, all whitespace (space, tab, newline) is considered
+equal and is used only to delimit tokens.
+
+<hr>
+
+<h2>Keys</h2>
+Keys are case-insensitive.
+<h3>Global Keys</h3>
+<dl>
+<dt><code>ForwardCompatible</code>
+<dd>Gives a list of platforms that are forward compatible. If the current
+platform cannot be found in the list of supported platforms, then the
+ForwardCompatible list will be checked for any platforms that have the same
+OS and architecture and an earlier version. If one is found, its
+attributes will be used for the current platform.
+<dt><code>Platforms</code> (<i>required</i>)
+<dd>Gives a list of platforms. Each entry in the list is itself a key-value
+pair:
+the key is the name of the platform, and the valuelist contains various
+attributes of the platform. The ModuleName, ModuleFile, and Files attributes
+must be specified, unless an EquivalentPlatform attribute is specified.
+The platform string is in the following
+format: <u><i>system name</i></u>:<u><i>os release</i></u>:<u><i>architecture</i></u>. The installer
+will obtain these values from NSPR. <u><i>os release</i></u> is an empty
+string on non-UNIX operating systems. The following system names and platforms
+are currently defined by NSPR:<code>
+<ul>
+<li>AIX (rs6000)
+<li>BSDI (x86)
+<li>FREEBSD (x86)
+<li>HPUX (hppa1.1)
+<li>IRIX (mips)
+<li>LINUX (ppc, alpha, x86)
+<li>MacOS (PowerPC) </code>(<i>Note: NSPR actually defines the OS as
+"</i><code>Mac OS</code><i>". The
+space makes the name unsuitable for being embedded in identifiers. Until
+NSPR changes, you will have to add some special code to deal with this case.
+</i>)<code>
+<li>NCR (x86)
+<li>NEC (mips)
+<li>OS2 (x86)
+<li>OSF (alpha)
+<li>ReliantUNIX (mips)
+<li>SCO (x86)
+<li>SOLARIS (sparc)
+<li>SONY (mips)
+<li>SUNOS (sparc)
+<li>UnixWare (x86)
+<li>WIN16 (x86)
+<li>WIN95 (x86)
+<li>WINNT (x86)
+</ul>
+</code>
+Examples of valid platform strings: <code>IRIX:6.2:mips, Solaris:5.5.1:sparc,
+Linux:2.0.32:x86, WIN95::x86</code>.
+</dl>
+
+<h3>Per-Platform Keys</h3>
+These keys only have meaning within the value list of an entry in
+the <code>Platforms</code> list.
+<dl>
+<dt><code>ModuleName</code> (<i>required</i>)
+<dd>Gives the common name for the module. This name will be used to
+reference the module from Communicator, modutil, servers, or any other
+program that uses the Netscape security module database.
+<dt><code>ModuleFile</code> (<i>required</i>)
+<dd>Names the PKCS #11 module file (DLL or .so) for this platform. The name
+is given as the relative path of the file within the JAR archive.
+<dt><code>Files</code> (<i>required</i>)
+<dd>Lists the files that should be installed for this module. Each entry
+in the file list is a key-value pair: the key is the path of the file in
+the JAR archive, and
+the valuelist contains attributes of the file. At least RelativePath and
+AbsoluteDir must be specified in this valuelist.
+<dt><code>DefaultMechanismFlags</code>
+<dd>This key-value pair specifies
+of which mechanisms this module will be a default provider. It is a bitstring
+specified in hexadecimal (0x) format. It is constructed as a bitwise OR
+of the following constants. If the <code>DefaultMechanismFlags</code>
+entry is omitted, the value will default to 0x0.
+<blockquote><pre>
+RSA: 0x0000 0001
+DSA: 0x0000 0002
+RC2: 0x0000 0004
+RC4: 0x0000 0008
+DES: 0x0000 0010
+DH: 0x0000 0020
+FORTEZZA: 0x0000 0040
+RC5: 0x0000 0080
+SHA1: 0x0000 0100
+MD5: 0x0000 0200
+MD2: 0x0000 0400
+RANDOM: 0x0800 0000
+FRIENDLY: 0x1000 0000
+OWN_PW_DEFAULTS: 0x2000 0000
+DISABLE: 0x4000 0000
+</pre></blockquote>
+<dt><code>CipherEnableFlags</code>
+<dd>This key-value pair specifies
+which SSL ciphers will be enabled. It is a bitstring specified in
+hexadecimal (0x) format. It is constructed as a bitwise OR of the following
+constants. If the <code>CipherEnableFlags</code> entry is omitted, the
+value will default to 0x0.
+<blockquote><pre>
+FORTEZZA: 0x0000 0001
+</pre></blockquote>
+<dt><code>EquivalentPlatform</code>
+<dd>Specifies that the attributes of the named platform should also be used
+for the current platform. Saves typing when there is more than one platform
+that uses the same settings.
+</dl>
+
+<h3>Per-File Keys</h3>
+These keys only have meaning within the valuelist of an entry in a
+<code>Files</code> list. At least one of <code>RelativePath</code> and
+<code>AbsolutePath</code> must be specified. If both are specified, the
+relative path will be tried first and the absolute path used only if no
+relative root directory is provided by the installer program.
+<dl>
+<dt><code>RelativePath</code>
+<dd>Specifies the destination directory of the file, relative to some directory
+decided at install-time. Two variables can be used in the relative
+path, "%root%" and "%temp%". "%root%" will be replaced at run-time with
+the directory relative to which files should be installed; for
+example, it may be the server's root directory or Communicator's root
+directory. "%temp%" is a directory that will be created at the beginning
+of the installation and destroyed at the end of the installation. Its purpose
+is to hold executable files (such as setup programs), or files that are
+used by these programs. For example, a Windows installation might consist
+of a <code>setup.exe</code> installation program, a help file, and a .cab file
+containing compressed information. All these files could be installed into the
+temporary directory. Files destined for the temporary directory are guaranteed
+to be in place before any executable file is run, and will not be deleted
+until all executable files have finished.
+<dt><code>AbsoluteDir</code>
+<dd>Specifies the destination directory of the file as an absolute path.
+This will only be used if the installer is unable to determine a
+relative directory.
+<dt><code>Executable</code>
+<dd>This string specifies that the file is to be executed during the
+course of the
+installation. Typically this would be used for a setup program provided
+by a module vendor, such as a self-extracting <code>setup.exe</code>.
+More than one file can be specified as executable, in which case they will
+be run in the order they are specified in the script file.
+<dt><code>FilePermissions</code>
+<dd>This string is interpreted as a string of octal digits, according to the
+standard UNIX format. It is a bitwise OR of the following constants:
+<blockquote><pre>
+user read: 400
+user write: 200
+user execute: 100
+group read: 040
+group write: 020
+group execute: 010
+other read: 004
+other write: 002
+other execute: 001
+</pre></blockquote>
+Some platforms may not understand these permissions. They will only be
+applied insofar as makes sense for the current platform. If this attribute
+is omitted, a default of 777 is assumed.
+
+</body>
+</html>
diff --git a/security/nss/cmd/modutil/rules.mk b/security/nss/cmd/modutil/rules.mk
new file mode 100644
index 000000000..b34662513
--- /dev/null
+++ b/security/nss/cmd/modutil/rules.mk
@@ -0,0 +1,54 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#
+# Some versions of yacc generate files that include platform-specific
+# system headers. For example, the yacc in Solaris 2.6 inserts
+# #include <values.h>
+# which does not exist on NT. For portability, always use Berkeley
+# yacc (such as the yacc in Linux) to generate files.
+#
+
+generate: installparse.c installparse.l
+
+installparse.c:
+ yacc -p Pk11Install_yy -d installparse.y
+ mv y.tab.c installparse.c
+ mv y.tab.h installparse.h
+
+installparse.l:
+ lex -olex.Pk11Install_yy.c -PPk11Install_yy installparse.l
+ @echo
+ @echo "**YOU MUST COMMENT OUT UNISTD.H FROM lex.Pk11Install_yy.cpp**"
+
+install.c: install-ds.h install.h
diff --git a/security/nss/cmd/modutil/specification.html b/security/nss/cmd/modutil/specification.html
new file mode 100644
index 000000000..48a1ab7cd
--- /dev/null
+++ b/security/nss/cmd/modutil/specification.html
@@ -0,0 +1,351 @@
+<html>
+<!--
+ - The contents of this file are subject to the Mozilla Public
+ - License Version 1.1 (the "License"); you may not use this file
+ - except in compliance with the License. You may obtain a copy of
+ - the License at http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS
+ - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ - implied. See the License for the specific language governing
+ - rights and limitations under the License.
+ -
+ - The Original Code is the Netscape security libraries.
+ -
+ - The Initial Developer of the Original Code is Netscape
+ - Communications Corporation. Portions created by Netscape are
+ - Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ - Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the
+ - terms of the GNU General Public License Version 2 or later (the
+ - "GPL"), in which case the provisions of the GPL are applicable
+ - instead of those above. If you wish to allow use of your
+ - version of this file only under the terms of the GPL and not to
+ - allow others to use your version of this file under the MPL,
+ - indicate your decision by deleting the provisions above and
+ - replace them with the notice and other provisions required by
+ - the GPL. If you do not delete the provisions above, a recipient
+ - may use your version of this file under either the MPL or the
+ - GPL.
+ -->
+<head>
+<title>Modutil Specification</title>
+</head>
+<body bgcolor=white fgcolor=black>
+<center><h1>PKCS #11 Module Management Utility
+<br><i>Specification</i></h1></center>
+
+<!---------------------------------------------------------------------->
+<!-------------------------- capabilities ------------------------------>
+<!---------------------------------------------------------------------->
+<h2>Capabilities</h2>
+<ul>
+<li>Add a PKCS #11 module, specifying a name and library file.
+(<a href="#add">-add</a>)
+<li>Add a PKCS #11 module from a server-formatted JAR file.
+(<a href="#jar">-jar</a>)
+<li>Change the password on or initialize a token.
+(<a href="#changepw">-changepw</a>)
+<li>Create databases (secmod[ule].db, key3.db, cert7.db) from scratch.
+(<a href="#create">-create</a>)
+<li>Switch to and from FIPS-140-1 compliant mode.
+(<a href="#fips">-fips</a>)
+<li>Delete a PKCS #11 module. (<a href="#delete">-delete</a>)
+<li>List installed PKCS #11 modules. (<a href="#list">-list</a>)
+<li>List detailed info on a particular module and its tokens, including
+whether needs login, is hardware, needs user init
+(<a href="#list">-list</a>)
+<li>Specify which modules should be the default provider of various
+cryptographic operations.(<a href="#default">-default</a>,
+<a href="#undefault">-undefault</a>)
+<li>Disable and enable slots, find out whether and why they are disabled.
+(<a href="#disable">-disable</a>, <a href="#enable">-enable</a>,
+<a href="#list">-list</a>)
+</ul>
+
+<hr>
+
+<!---------------------------------------------------------------------->
+<!-------------------------- Usage ------------------------------------->
+<!---------------------------------------------------------------------->
+<h2>Usage</h2>
+<code>modutil [<i>command</i>] [<i>options</i>]</code>
+<p>At most one command can be specified. With no arguments,
+<code>modutil</code> prints a usage message.
+<h3>Commands:</h3>
+<table border>
+<tr bgcolor="#cccccc">
+<th>Command</th><th>Description</th>
+</tr>
+
+<!---------------------------- -add ------------------------------>
+<tr>
+<td> <a name="add"></a>
+<code>-add <u><i>module name</i></u> -libfile <u><i>library file</i></u>
+ [-ciphers <u><i>cipher enable list</i></u>]
+ [-mechanisms <u><i>default mechanism list</i></u>]
+</code></td>
+<td>Adds a new module to the database with the given name.
+
+<p><u><i>library file</i></u> is the path of the DLL or other library file
+containing the module's implementation of the PKCS #11 interface.
+
+<p><u><i>cipher enable flags</i></u> is a colon-separated list of ciphers
+that will be enabled on this module. The list should be enclosed within quotes
+if necessary to prevent shell interpretation. The following ciphers are
+currently available:
+<ul>
+<li>FORTEZZA
+</ul>
+
+<p><u><i>default mechanism flags</i></u> is a colon-separated list of
+mechanisms for which this module should be the default provider. The
+list should be enclosed within quotes if necessary to prevent shell
+interpretation. <b>This
+list does not enable the mechanisms; it only specifies that this module
+will be a default provider for the listed mechanisms.</b> If more than
+one module claims to be a default provider for a given mechanism, it is
+undefined which will actually be chosen to provide that mechanism. The
+following mechanisms are currently available:
+<ul>
+<li>RSA
+<li>DSA
+<li>RC2
+<li>RC4
+<li>RC5
+<li>DES
+<li>DH
+<li>FORTEZZA
+<li>SHA1
+<li>MD5
+<li>MD2
+<li>RANDOM <i>(random number generation)</i>
+<li>FRIENDLY <i>(certificates are publicly-readable)</i>
+</ul>
+</td>
+</tr>
+
+<!-------------------------- -changepw ------------------------------------->
+<tr>
+<td><a name="changepw"></a><code>-changepw <u><i>token name</i></u>
+[-pwfile <u><i>old password file</i></u>]
+[-newpwfile <u><i>new password file</i></u>]</code></td>
+<td>Changes the password on the named token. If the token has not been
+initialized, this command will initialize the PIN.
+If a password file is given, the password will be read from that file;
+otherwise, the password will be obtained interactively.
+<b>Storing passwords in a file is much less secure than supplying them
+interactively.</b>
+<p>The password on the Netscape internal module cannot be changed if
+the <code>-nocertdb</code> option is specified.
+</td>
+</tr>
+
+<!-------------------------- -create ------------------------------------->
+<tr>
+<td><a name="create"></a><code>-create</code></td>
+<td>Creates a new secmod[ule].db, key3.db, and cert7.db in the directory
+specified with the
+<code>-dbdir</code> option, if one is specified. If no directory is
+specified, UNIX systems will use the user's .netscape directory, while other
+systems will return with an error message. If any of these databases already
+exist in the chosen directory, an error message is returned.
+<p>If used with <code>-nocertdb</code>, only secmod[ule].db will be created;
+cert7.db and key3.db will not be created.
+</td>
+</tr>
+
+<!------------------------------ -default -------------------------------->
+<tr>
+<td> <a name="default"></a> <code>-default <u><i>module name</i></u>
+-mechanisms <u><i>mechanism list</i></u></code>
+</td>
+<td>Specifies that the given module will be a default provider of the
+listed mechanisms. The mechanism list is the same as in the <code>-add</code>
+command.
+</td>
+</tr>
+
+<!-------------------------- -delete ------------------------------------->
+<tr>
+<td><a name="delete"></a><code>-delete <u><i>module name</i></u></code></td>
+<td>Deletes the named module from the database</td>
+</tr>
+
+<!-------------------------- -disable ------------------------------------->
+<tr>
+<td> <a name="disable"></a> <code>-disable <u><i>module name</i></u>
+[-slot <u><i>slot name</i></u>]</code></td>
+<td>Disables the named slot. If no slot is specified, all slots on
+the module are disabled.</td>
+</tr>
+
+<!-------------------------- -enable ------------------------------------->
+<tr>
+<td> <a name="enable"></a> <code>-enable <u><i>module name</i></u>
+[-slot <u><i>slot name</i></u>]</code></td>
+<td>Enables the named slot. If no slot is specified, all slots on
+the module are enabled.</td>
+</tr>
+
+<!-------------------------- -fips ------------------------------------->
+<tr>
+<td><a name="fips"></a><code>-fips [true | false]</code></td>
+<td>Enables or disables FIPS mode on the internal module. Passing
+<code>true</code> enables FIPS mode, passing <code>false</code> disables
+FIPS mode.</td>
+</tr>
+
+<!-------------------------- -force ------------------------------------->
+<tr>
+<td><a name="force"></a><code>-force</code></td>
+<td>Disables interactive prompts, so modutil can be run in a script.
+Should only be used by experts, since the prompts may relate to security
+or database integrity. Before using this option, test the command
+interactively once to see the warnings that are produced.</td>
+</tr>
+
+<!-------------------------- -jar ------------------------------------->
+<tr>
+<td><a name="jar"></a><code>-jar <u><i>JAR file</i></u>
+-installdir <u><i>root installation directory</i></u>
+[-tempdir <u><i>temporary directory</i></u>]</code></td>
+<td>Adds a new module from the given JAR file. The JAR file uses the
+server <a href="pk11jar.html">PKCS #11 JAR format</a> to describe the names of
+any files that need to be installed, the name of the module, mechanism flags,
+and cipher flags. The <u><i>root installation directory</i></u>
+is the directory relative to which files will be installed. This should be a
+ directory
+under which it would be natural to store dynamic library files, such as
+a server's root directory, or Communicator's root directory.
+The <u><i>temporary directory</i></u> is where temporary modutil files
+will be created in the course of the installation. If no temporary directory
+is specified, the current directory will be used.
+<p>If used with the <code>-nocertdb</code> option, the signatures on the JAR
+file will not be checked.</td>
+</tr>
+
+<!----------------------------- -list ------------------------------>
+<tr>
+<td><a name="list"></a><code>-list [<u><i>module name</i></u>]</code></td>
+<td>Without an argument, lists the PKCS #11 modules present in the module
+database.
+<blockquote>
+<pre>
+% <b>modutil -list</b>
+Using database directory /u/nicolson/.netscape...
+
+Listing of PKCS #11 Modules
+-----------------------------------------------------------
+ 1. Netscape Internal PKCS #11 Module
+ slots: 2 slots attached
+ status: loaded
+
+ slot: Communicator Internal Cryptographic Services Version 4.0
+ token: Communicator Generic Crypto Svcs
+
+ slot: Communicator User Private Key and Certificate Services
+ token: Communicator Certificate DB
+-----------------------------------------------------------
+</pre>
+</blockquote>
+<p>With an argument, provides a detailed description of the named module
+and its slots and tokens.
+<blockquote>
+<pre>
+% <b>modutil -list "Netscape Internal PKCS #11 Module"</b>
+Using database directory /u/nicolson/.netscape...
+
+-----------------------------------------------------------
+Name: Netscape Internal PKCS #11 Module
+Library file: **Internal ONLY module**
+Manufacturer: Netscape Communications Corp
+Description: Communicator Internal Crypto Svc
+PKCS #11 Version 2.0
+Library Version: 4.0
+Cipher Enable Flags: None
+Default Mechanism Flags: RSA:DSA:RC2:RC4:DES:SHA1:MD5:MD2
+
+ Slot: Communicator Internal Cryptographic Services Version 4.0
+ Manufacturer: Netscape Communications Corp
+ Type: Software
+ Version Number: 4.1
+ Firmware Version: 0.0
+ Status: Enabled
+ Token Name: Communicator Generic Crypto Svcs
+ Token Manufacturer: Netscape Communications Corp
+ Token Model: Libsec 4.0
+ Token Serial Number: 0000000000000000
+ Token Version: 4.0
+ Token Firmware Version: 0.0
+ Access: Write Protected
+ Login Type: Public (no login required)
+ User Pin: NOT Initialized
+
+ Slot: Communicator User Private Key and Certificate Services
+ Manufacturer: Netscape Communications Corp
+ Type: Software
+ Version Number: 3.0
+ Firmware Version: 0.0
+ Status: Enabled
+ Token Name: Communicator Certificate DB
+ Token Manufacturer: Netscape Communications Corp
+ Token Model: Libsec 4.0
+ Token Serial Number: 0000000000000000
+ Token Version: 7.0
+ Token Firmware Version: 0.0
+ Access: NOT Write Protected
+ Login Type: Login required
+ User Pin: Initialized
+
+-----------------------------------------------------------
+</pre>
+</blockquote>
+</td>
+</tr>
+
+<!------------------------------ Undefault ------------------------------->
+<tr>
+<td><a name="undefault"></a><code>-undefault <u><i>module name</i></u>
+-mechanisms <u><i>mechanism list</i></u></code></td>
+<td>Specifies that the given module will NOT be a default provider of
+the listed mechanisms. This command clears the default mechanism flags
+for the given module.</td>
+</tr>
+
+</table>
+
+<!------------------------------------------------------------------------>
+<!------------------------------ Options --------------------------------->
+<!------------------------------------------------------------------------>
+<h3>Options:</h3>
+<table border>
+<tr bgcolor="#cccccc"><th>Option</th><th>Description</th> </tr>
+
+<!------------------------------ -dbdir ---------------------------------->
+<tr>
+<td><code>-dbdir <u><i>directory</i></u></code></td>
+<td>Specifies which directory holds the module database. On UNIX systems,
+the user's netscape directory is the default. On other systems, there is
+no default, and this option must be used.</td>
+</tr>
+
+<!------------------------------ -dbdir ---------------------------------->
+<tr>
+<td><code>-nocertdb</code></td>
+<td>Do not open the certificate or key databases. This has several effects.
+With the <code>-create</code> command, this means that only a secmod.db file
+will be created; cert7.db and key3.db will not be created. With the
+<code>-jar</code> command, signatures on the JAR file will not be checked.
+With the <code>-changepw</code> command, the password on the Netscape internal
+module cannot be set or changed, since this password is stored in key3.db.
+</td>
+</tr>
+
+</table>
+
+</body>
+</html>
diff --git a/security/nss/cmd/ocspclnt/Makefile b/security/nss/cmd/ocspclnt/Makefile
new file mode 100644
index 000000000..490f738e5
--- /dev/null
+++ b/security/nss/cmd/ocspclnt/Makefile
@@ -0,0 +1,73 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
diff --git a/security/nss/cmd/ocspclnt/manifest.mn b/security/nss/cmd/ocspclnt/manifest.mn
new file mode 100644
index 000000000..68a84b8c7
--- /dev/null
+++ b/security/nss/cmd/ocspclnt/manifest.mn
@@ -0,0 +1,54 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ ocspclnt.c \
+ $(NULL)
+
+# headers for the MODULE (defined above) are implicitly required.
+REQUIRES = dbm seccmd
+
+# WINNT uses EXTRA_LIBS as the list of libs to link in.
+# Unix uses OS_LIBS for that purpose.
+# We can solve this via conditional makefile code, but
+# can't do this in manifest.mn because OS_ARCH isn't defined there.
+# So, look in the local Makefile for the defines for the list of libs.
+
+PROGRAM = ocspclnt
+
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/ocspclnt/ocspclnt.c b/security/nss/cmd/ocspclnt/ocspclnt.c
new file mode 100644
index 000000000..309d08538
--- /dev/null
+++ b/security/nss/cmd/ocspclnt/ocspclnt.c
@@ -0,0 +1,1221 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * Test program for client-side OCSP.
+ *
+ * $Id$
+ */
+
+#include "secutil.h"
+#include "nspr.h"
+#include "plgetopt.h"
+#include "nss.h"
+#include "cert.h"
+#include "ocsp.h"
+#include "xconst.h" /*
+ * XXX internal header file; needed to get at
+ * cert_DecodeAuthInfoAccessExtension -- would be
+ * nice to not need this, but that would require
+ * better/different APIs.
+ */
+
+#ifndef NO_PP /*
+ * Compile with this every once in a while to be
+ * sure that no dependencies on it get added
+ * outside of the pretty-printing routines.
+ */
+#include "ocspti.h" /* internals for pretty-printing routines *only* */
+#endif /* NO_PP */
+
+#define DEFAULT_DB_DIR "~/.netscape"
+
+
+static void
+synopsis (char *program_name)
+{
+ PRFileDesc *pr_stderr;
+
+ pr_stderr = PR_STDERR;
+ PR_fprintf (pr_stderr, "Usage:");
+ PR_fprintf (pr_stderr,
+ "\t%s -p [-d <dir>]\n",
+ program_name);
+ PR_fprintf (pr_stderr,
+ "\t%s -P [-d <dir>]\n",
+ program_name);
+ PR_fprintf (pr_stderr,
+ "\t%s -r <name> [-L] [-s <name>] [-d <dir>]\n",
+ program_name);
+ PR_fprintf (pr_stderr,
+ "\t%s -R <name> [-l <location>] [-s <name>] [-d <dir>]\n",
+ program_name);
+ PR_fprintf (pr_stderr,
+ "\t%s -S <name> [-l <location> -t <name>]\n",
+ program_name);
+ PR_fprintf (pr_stderr,
+ "\t\t [-s <name>] [-w <time>] [-d <dir>]\n");
+ PR_fprintf (pr_stderr,
+ "\t%s -V <name> -u <usage> [-l <location> -t <name>]\n",
+ program_name);
+ PR_fprintf (pr_stderr,
+ "\t\t [-s <name>] [-w <time>] [-d <dir>]\n");
+}
+
+
+static void
+short_usage (char *program_name)
+{
+ PR_fprintf (PR_STDERR,
+ "Type %s -H for more detailed descriptions\n",
+ program_name);
+ synopsis (program_name);
+}
+
+
+static void
+long_usage (char *program_name)
+{
+ PRFileDesc *pr_stderr;
+
+ pr_stderr = PR_STDERR;
+ synopsis (program_name);
+ PR_fprintf (pr_stderr, "\nCommands (must specify exactly one):\n");
+ PR_fprintf (pr_stderr,
+ " %-13s Pretty-print a binary request read from stdin\n",
+ "-p");
+ PR_fprintf (pr_stderr,
+ " %-13s Pretty-print a binary response read from stdin\n",
+ "-P");
+ PR_fprintf (pr_stderr,
+ " %-13s Create a request for cert \"nickname\" on stdout\n",
+ "-r nickname");
+ PR_fprintf (pr_stderr,
+ " %-13s Get response for cert \"nickname\", dump to stdout\n",
+ "-R nickname");
+ PR_fprintf (pr_stderr,
+ " %-13s Get status for cert \"nickname\"\n",
+ "-S nickname");
+ PR_fprintf (pr_stderr,
+ " %-13s Fully verify cert \"nickname\", w/ status check\n",
+ "-V nickname");
+ PR_fprintf (pr_stderr, "Options:\n");
+ PR_fprintf (pr_stderr,
+ " %-13s Add the service locator extension to the request\n",
+ "-L");
+ PR_fprintf (pr_stderr,
+ " %-13s Find security databases in \"dbdir\" (default %s)\n",
+ "-d dbdir", DEFAULT_DB_DIR);
+ PR_fprintf (pr_stderr,
+ " %-13s Use \"location\" as URL of responder\n",
+ "-l location");
+ PR_fprintf (pr_stderr,
+ " %-13s Trust cert \"nickname\" as response signer\n",
+ "-t nickname");
+ PR_fprintf (pr_stderr,
+ " %-13s Sign requests with cert \"nickname\"\n",
+ "-s nickname");
+ PR_fprintf (pr_stderr,
+ " %-13s Type of certificate usage for verification:\n",
+ "-u usage");
+ PR_fprintf (pr_stderr,
+ "%-17s c SSL Client\n", "");
+ PR_fprintf (pr_stderr,
+ "%-17s s SSL Server\n", "");
+ PR_fprintf (pr_stderr,
+ "%-17s e Email Recipient\n", "");
+ PR_fprintf (pr_stderr,
+ "%-17s E Email Signer\n", "");
+ PR_fprintf (pr_stderr,
+ "%-17s S Object Signer\n", "");
+ PR_fprintf (pr_stderr,
+ "%-17s C CA\n", "");
+ PR_fprintf (pr_stderr,
+ " %-13s Validity time (default current time), one of:\n",
+ "-w time");
+ PR_fprintf (pr_stderr,
+ "%-17s %-25s (GMT)\n", "", "YYMMDDhhmm[ss]Z");
+ PR_fprintf (pr_stderr,
+ "%-17s %-25s (later than GMT)\n", "", "YYMMDDhhmm[ss]+hhmm");
+ PR_fprintf (pr_stderr,
+ "%-17s %-25s (earlier than GMT)\n", "", "YYMMDDhhmm[ss]-hhmm");
+}
+
+
+/*
+ * XXX This is a generic function that would probably make a good
+ * replacement for SECU_DER_Read (which is not at all specific to DER,
+ * despite its name), but that requires fixing all of the tools...
+ * Still, it should be done, whenenver I/somebody has the time.
+ * (Also, consider whether this actually belongs in the security
+ * library itself, not just in the command library.)
+ *
+ * This function takes an open file (a PRFileDesc *) and reads the
+ * entire file into a SECItem. (Obviously, the file is intended to
+ * be small enough that such a thing is advisable.) Both the SECItem
+ * and the buffer it points to are allocated from the heap; the caller
+ * is expected to free them. ("SECITEM_FreeItem(item, PR_TRUE)")
+ */
+static SECItem *
+read_file_into_item (PRFileDesc *in_file, SECItemType si_type)
+{
+ PRStatus prv;
+ SECItem *item;
+ PRFileInfo file_info;
+ PRInt32 bytes_read;
+
+ prv = PR_GetOpenFileInfo (in_file, &file_info);
+ if (prv != PR_SUCCESS)
+ return NULL;
+
+ if (file_info.size == 0) {
+ /* XXX Need a better error; just grabbed this one for expediency. */
+ PORT_SetError (SEC_ERROR_INPUT_LEN);
+ return NULL;
+ }
+
+ if (file_info.size > 0xffff) { /* I think this is too big. */
+ PORT_SetError (SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+
+ item = PORT_Alloc (sizeof (SECItem));
+ if (item == NULL)
+ return NULL;
+
+ item->type = si_type;
+ item->len = (unsigned int) file_info.size;
+ item->data = PORT_Alloc ((size_t)item->len);
+ if (item->data == NULL)
+ goto loser;
+
+ bytes_read = PR_Read (in_file, item->data, (PRInt32) item->len);
+ if (bytes_read < 0) {
+ /* Something went wrong; error is already set for us. */
+ goto loser;
+ } else if (bytes_read == 0) {
+ /* Something went wrong; we read nothing. But no system/nspr error. */
+ /* XXX Need to set an error here. */
+ goto loser;
+ } else if (item->len != (unsigned int)bytes_read) {
+ /* Something went wrong; we read less (or more!?) than we expected. */
+ /* XXX Need to set an error here. */
+ goto loser;
+ }
+
+ return item;
+
+loser:
+ SECITEM_FreeItem (item, PR_TRUE);
+ return NULL;
+}
+
+
+/*
+ * Create a DER-encoded OCSP request (for the certificate whose nickname
+ * is "name") and dump it out.
+ */
+static SECStatus
+create_request (FILE *out_file, CERTCertDBHandle *handle, const char *cert_name,
+ PRBool add_service_locator, PRBool add_acceptable_responses)
+{
+ CERTCertificate *cert = NULL;
+ CERTCertList *certs = NULL;
+ CERTOCSPRequest *request = NULL;
+ int64 now = PR_Now();
+ SECItem *encoding = NULL;
+ SECStatus rv = SECFailure;
+
+ if (handle == NULL || cert_name == NULL)
+ goto loser;
+
+ cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) cert_name);
+ if (cert == NULL)
+ goto loser;
+
+ /*
+ * We need to create a list of one.
+ */
+ certs = CERT_NewCertList();
+ if (certs == NULL)
+ goto loser;
+
+ if (CERT_AddCertToListTail (certs, cert) != SECSuccess)
+ goto loser;
+
+ /*
+ * Now that cert is included in the list, we need to be careful
+ * that we do not try to destroy it twice. This will prevent that.
+ */
+ cert = NULL;
+
+ request = CERT_CreateOCSPRequest (certs, now, add_service_locator, NULL);
+ if (request == NULL)
+ goto loser;
+
+ if (add_acceptable_responses) {
+ rv = CERT_AddOCSPAcceptableResponses(request,
+ SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
+ if (rv != SECSuccess)
+ goto loser;
+ }
+
+ encoding = CERT_EncodeOCSPRequest (NULL, request, NULL);
+ if (encoding == NULL)
+ goto loser;
+
+ if (fwrite (encoding->data, encoding->len, 1, out_file) != 1)
+ goto loser;
+
+ rv = SECSuccess;
+
+loser:
+ if (encoding != NULL)
+ SECITEM_FreeItem(encoding, PR_TRUE);
+ if (request != NULL)
+ CERT_DestroyOCSPRequest(request);
+ if (certs != NULL)
+ CERT_DestroyCertList (certs);
+ if (cert != NULL)
+ CERT_DestroyCertificate (cert);
+
+ return rv;
+}
+
+
+/*
+ * Create a DER-encoded OCSP request (for the certificate whose nickname is
+ * "cert_name"), then get and dump a corresponding response. The responder
+ * location is either specified explicitly (as "responder_url") or found
+ * via the AuthorityInfoAccess URL in the cert.
+ */
+static SECStatus
+dump_response (FILE *out_file, CERTCertDBHandle *handle, const char *cert_name,
+ const char *responder_url)
+{
+ CERTCertificate *cert = NULL;
+ CERTCertList *certs = NULL;
+ char *loc = NULL;
+ int64 now = PR_Now();
+ SECItem *response = NULL;
+ SECStatus rv = SECFailure;
+ PRBool includeServiceLocator;
+
+ if (handle == NULL || cert_name == NULL)
+ goto loser;
+
+ cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) cert_name);
+ if (cert == NULL)
+ goto loser;
+
+ if (responder_url != NULL) {
+ loc = (char *) responder_url;
+ includeServiceLocator = PR_TRUE;
+ } else {
+ loc = CERT_GetOCSPAuthorityInfoAccessLocation (cert);
+ if (loc == NULL)
+ goto loser;
+ includeServiceLocator = PR_FALSE;
+ }
+
+ /*
+ * We need to create a list of one.
+ */
+ certs = CERT_NewCertList();
+ if (certs == NULL)
+ goto loser;
+
+ if (CERT_AddCertToListTail (certs, cert) != SECSuccess)
+ goto loser;
+
+ /*
+ * Now that cert is included in the list, we need to be careful
+ * that we do not try to destroy it twice. This will prevent that.
+ */
+ cert = NULL;
+
+ response = CERT_GetEncodedOCSPResponse (NULL, certs, loc, now,
+ includeServiceLocator,
+ NULL, NULL, NULL);
+ if (response == NULL)
+ goto loser;
+
+ if (fwrite (response->data, response->len, 1, out_file) != 1)
+ goto loser;
+
+ rv = SECSuccess;
+
+loser:
+ if (response != NULL)
+ SECITEM_FreeItem (response, PR_TRUE);
+ if (certs != NULL)
+ CERT_DestroyCertList (certs);
+ if (loc != NULL && loc != responder_url)
+ PORT_Free (loc);
+ if (cert != NULL)
+ CERT_DestroyCertificate (cert);
+
+ return rv;
+}
+
+
+/*
+ * Get the status for the specified certificate (whose nickname is "cert_name").
+ * Directly use the OCSP function rather than doing a full verification.
+ */
+static SECStatus
+get_cert_status (FILE *out_file, CERTCertDBHandle *handle,
+ const char *cert_name, int64 verify_time)
+{
+ CERTCertificate *cert = NULL;
+ SECStatus rv = SECFailure;
+
+ if (handle == NULL || cert_name == NULL)
+ goto loser;
+
+ cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) cert_name);
+ if (cert == NULL)
+ goto loser;
+
+ rv = CERT_CheckOCSPStatus (handle, cert, verify_time, NULL);
+
+ fprintf (out_file, "Check of certificate \"%s\" ", cert_name);
+ if (rv == SECSuccess) {
+ fprintf (out_file, "succeeded.\n");
+ } else {
+ const char *error_string = SECU_Strerror(PORT_GetError());
+ fprintf (out_file, "failed. Reason:\n");
+ if (error_string != NULL && PORT_Strlen(error_string) > 0)
+ fprintf (out_file, "%s\n", error_string);
+ else
+ fprintf (out_file, "Unknown\n");
+ }
+
+ rv = SECSuccess;
+
+loser:
+ if (cert != NULL)
+ CERT_DestroyCertificate (cert);
+
+ return rv;
+}
+
+
+/*
+ * Verify the specified certificate (whose nickname is "cert_name").
+ * OCSP is already turned on, so we just need to call the standard
+ * certificate verification API and let it do all the work.
+ */
+static SECStatus
+verify_cert (FILE *out_file, CERTCertDBHandle *handle, const char *cert_name,
+ SECCertUsage cert_usage, int64 verify_time)
+{
+ CERTCertificate *cert = NULL;
+ SECStatus rv = SECFailure;
+
+ if (handle == NULL || cert_name == NULL)
+ goto loser;
+
+ cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) cert_name);
+ if (cert == NULL)
+ goto loser;
+
+ rv = CERT_VerifyCert (handle, cert, PR_TRUE, cert_usage, verify_time,
+ NULL, NULL);
+
+ fprintf (out_file, "Verification of certificate \"%s\" ", cert_name);
+ if (rv == SECSuccess) {
+ fprintf (out_file, "succeeded.\n");
+ } else {
+ const char *error_string = SECU_Strerror(PORT_GetError());
+ fprintf (out_file, "failed. Reason:\n");
+ if (error_string != NULL && PORT_Strlen(error_string) > 0)
+ fprintf (out_file, "%s\n", error_string);
+ else
+ fprintf (out_file, "Unknown\n");
+ }
+
+ rv = SECSuccess;
+
+loser:
+ if (cert != NULL)
+ CERT_DestroyCertificate (cert);
+
+ return rv;
+}
+
+
+#ifdef NO_PP
+
+static SECStatus
+print_request (FILE *out_file, SECItem *data)
+{
+ fprintf (out_file, "Cannot pretty-print request compiled with NO_PP.\n");
+ return SECSuccess;
+}
+
+static SECStatus
+print_response (FILE *out_file, SECItem *data, CERTCertDBHandle *handle)
+{
+ fprintf (out_file, "Cannot pretty-print response compiled with NO_PP.\n");
+ return SECSuccess;
+}
+
+#else /* NO_PP */
+
+static void
+print_ocsp_version (FILE *out_file, SECItem *version, int level)
+{
+ if (version->len > 0) {
+ SECU_PrintInteger (out_file, version, "Version", level);
+ } else {
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "Version: DEFAULT\n");
+ }
+}
+
+
+static void
+print_ocsp_cert_id (FILE *out_file, CERTOCSPCertID *cert_id, int level)
+{
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "Cert ID:\n");
+ level++;
+
+ SECU_PrintAlgorithmID (out_file, &(cert_id->hashAlgorithm),
+ "Hash Algorithm", level);
+ SECU_PrintAsHex (out_file, &(cert_id->issuerNameHash),
+ "Issuer Name Hash", level);
+ SECU_PrintAsHex (out_file, &(cert_id->issuerKeyHash),
+ "Issuer Key Hash", level);
+ SECU_PrintInteger (out_file, &(cert_id->serialNumber),
+ "Serial Number", level);
+ /* XXX lookup the cert; if found, print something nice (nickname?) */
+}
+
+
+static void
+print_raw_certificates (FILE *out_file, SECItem **raw_certs, int level)
+{
+ SECItem *raw_cert;
+ int i = 0;
+ char cert_label[50];
+
+ SECU_Indent (out_file, level);
+
+ if (raw_certs == NULL) {
+ fprintf (out_file, "No Certificates.\n");
+ return;
+ }
+
+ fprintf (out_file, "Certificate List:\n");
+ while ((raw_cert = raw_certs[i++]) != NULL) {
+ sprintf (cert_label, "Certificate (%d)", i);
+ (void) SECU_PrintSignedData (out_file, raw_cert, cert_label, level + 1,
+ SECU_PrintCertificate);
+ }
+}
+
+
+static void
+print_ocsp_extensions (FILE *out_file, CERTCertExtension **extensions,
+ char *msg, int level)
+{
+ if (extensions) {
+ SECU_PrintExtensions (out_file, extensions, msg, level);
+ } else {
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "No %s\n", msg);
+ }
+}
+
+
+static void
+print_single_request (FILE *out_file, ocspSingleRequest *single, int level)
+{
+ print_ocsp_cert_id (out_file, single->reqCert, level);
+ print_ocsp_extensions (out_file, single->singleRequestExtensions,
+ "Single Request Extensions", level);
+}
+
+
+/*
+ * Decode the DER/BER-encoded item "data" as an OCSP request
+ * and pretty-print the subfields.
+ */
+static SECStatus
+print_request (FILE *out_file, SECItem *data)
+{
+ CERTOCSPRequest *request;
+ ocspTBSRequest *tbsRequest;
+ int level = 0;
+
+ PORT_Assert (out_file != NULL);
+ PORT_Assert (data != NULL);
+ if (out_file == NULL || data == NULL) {
+ PORT_SetError (SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ request = CERT_DecodeOCSPRequest (data);
+ if (request == NULL || request->tbsRequest == NULL)
+ return SECFailure;
+
+ tbsRequest = request->tbsRequest;
+
+ fprintf (out_file, "TBS Request:\n");
+ level++;
+
+ print_ocsp_version (out_file, &(tbsRequest->version), level);
+
+ /*
+ * XXX Probably should be an interface to get the signer name
+ * without looking inside the tbsRequest at all.
+ */
+ if (tbsRequest->requestorName != NULL) {
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "XXX print the requestorName\n");
+ } else {
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "No Requestor Name.\n");
+ }
+
+ if (tbsRequest->requestList != NULL) {
+ int i;
+
+ for (i = 0; tbsRequest->requestList[i] != NULL; i++) {
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "Request %d:\n", i);
+ print_single_request (out_file, tbsRequest->requestList[i],
+ level + 1);
+ }
+ } else {
+ fprintf (out_file, "Request list is empty.\n");
+ }
+
+ print_ocsp_extensions (out_file, tbsRequest->requestExtensions,
+ "Request Extensions", level);
+
+ if (request->optionalSignature != NULL) {
+ ocspSignature *whole_sig;
+ SECItem rawsig;
+
+ fprintf (out_file, "Signature:\n");
+
+ whole_sig = request->optionalSignature;
+ SECU_PrintAlgorithmID (out_file, &(whole_sig->signatureAlgorithm),
+ "Signature Algorithm", level);
+
+ rawsig = whole_sig->signature;
+ DER_ConvertBitString (&rawsig);
+ SECU_PrintAsHex (out_file, &rawsig, "Signature", level);
+
+ print_raw_certificates (out_file, whole_sig->derCerts, level);
+
+ fprintf (out_file, "XXX verify the sig and print result\n");
+ } else {
+ fprintf (out_file, "No Signature\n");
+ }
+
+ CERT_DestroyOCSPRequest (request);
+ return SECSuccess;
+}
+
+
+static void
+print_revoked_info (FILE *out_file, ocspRevokedInfo *revoked_info, int level)
+{
+ SECU_PrintGeneralizedTime (out_file, &(revoked_info->revocationTime),
+ "Revocation Time", level);
+
+ if (revoked_info->revocationReason != NULL) {
+ SECU_PrintAsHex (out_file, revoked_info->revocationReason,
+ "Revocation Reason", level);
+ } else {
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "No Revocation Reason.\n");
+ }
+}
+
+
+static void
+print_cert_status (FILE *out_file, ocspCertStatus *status, int level)
+{
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "Status: ");
+
+ switch (status->certStatusType) {
+ case ocspCertStatus_good:
+ fprintf (out_file, "Cert is good.\n");
+ break;
+ case ocspCertStatus_revoked:
+ fprintf (out_file, "Cert has been revoked.\n");
+ print_revoked_info (out_file, status->certStatusInfo.revokedInfo,
+ level + 1);
+ break;
+ case ocspCertStatus_unknown:
+ fprintf (out_file, "Cert is unknown to responder.\n");
+ break;
+ default:
+ fprintf (out_file, "Unrecognized status.\n");
+ break;
+ }
+}
+
+
+static void
+print_single_response (FILE *out_file, CERTOCSPSingleResponse *single,
+ int level)
+{
+ print_ocsp_cert_id (out_file, single->certID, level);
+
+ print_cert_status (out_file, single->certStatus, level);
+
+ SECU_PrintGeneralizedTime (out_file, &(single->thisUpdate),
+ "This Update", level);
+
+ if (single->nextUpdate != NULL) {
+ SECU_PrintGeneralizedTime (out_file, single->nextUpdate,
+ "Next Update", level);
+ } else {
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "No Next Update\n");
+ }
+
+ print_ocsp_extensions (out_file, single->singleExtensions,
+ "Single Response Extensions", level);
+}
+
+
+static void
+print_responder_id (FILE *out_file, ocspResponderID *responderID, int level)
+{
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "Responder ID ");
+
+ switch (responderID->responderIDType) {
+ case ocspResponderID_byName:
+ fprintf (out_file, "(byName):\n");
+ SECU_PrintName (out_file, &(responderID->responderIDValue.name),
+ "Name", level + 1);
+ break;
+ case ocspResponderID_byKey:
+ fprintf (out_file, "(byKey):\n");
+ SECU_PrintAsHex (out_file, &(responderID->responderIDValue.keyHash),
+ "Key Hash", level + 1);
+ break;
+ default:
+ fprintf (out_file, "Unrecognized Responder ID Type\n");
+ break;
+ }
+}
+
+
+static void
+print_response_data (FILE *out_file, ocspResponseData *responseData, int level)
+{
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "Response Data:\n");
+ level++;
+
+ print_ocsp_version (out_file, &(responseData->version), level);
+
+ print_responder_id (out_file, responseData->responderID, level);
+
+ SECU_PrintGeneralizedTime (out_file, &(responseData->producedAt),
+ "Produced At", level);
+
+ if (responseData->responses != NULL) {
+ int i;
+
+ for (i = 0; responseData->responses[i] != NULL; i++) {
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "Response %d:\n", i);
+ print_single_response (out_file, responseData->responses[i],
+ level + 1);
+ }
+ } else {
+ fprintf (out_file, "Response list is empty.\n");
+ }
+
+ print_ocsp_extensions (out_file, responseData->responseExtensions,
+ "Response Extensions", level);
+}
+
+
+static void
+print_basic_response (FILE *out_file, ocspBasicOCSPResponse *basic, int level)
+{
+ SECItem rawsig;
+
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "Basic OCSP Response:\n");
+ level++;
+
+ print_response_data (out_file, basic->tbsResponseData, level);
+
+ SECU_PrintAlgorithmID (out_file,
+ &(basic->responseSignature.signatureAlgorithm),
+ "Signature Algorithm", level);
+
+ rawsig = basic->responseSignature.signature;
+ DER_ConvertBitString (&rawsig);
+ SECU_PrintAsHex (out_file, &rawsig, "Signature", level);
+
+ print_raw_certificates (out_file, basic->responseSignature.derCerts, level);
+}
+
+
+/*
+ * Note this must match (exactly) the enumeration ocspResponseStatus.
+ */
+static char *responseStatusNames[] = {
+ "successful (Response has valid confirmations)",
+ "malformedRequest (Illegal confirmation request)",
+ "internalError (Internal error in issuer)",
+ "tryLater (Try again later)",
+ "unused ((4) is not used)",
+ "sigRequired (Must sign the request)",
+ "unauthorized (Request unauthorized)",
+ "other (Status value out of defined range)"
+};
+
+/*
+ * Decode the DER/BER-encoded item "data" as an OCSP response
+ * and pretty-print the subfields.
+ */
+static SECStatus
+print_response (FILE *out_file, SECItem *data, CERTCertDBHandle *handle)
+{
+ CERTOCSPResponse *response;
+ int level = 0;
+
+ PORT_Assert (out_file != NULL);
+ PORT_Assert (data != NULL);
+ if (out_file == NULL || data == NULL) {
+ PORT_SetError (SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ response = CERT_DecodeOCSPResponse (data);
+ if (response == NULL)
+ return SECFailure;
+
+ PORT_Assert (response->statusValue <= ocspResponse_other);
+ fprintf (out_file, "Response Status: %s\n",
+ responseStatusNames[response->statusValue]);
+
+ if (response->statusValue == ocspResponse_successful) {
+ ocspResponseBytes *responseBytes = response->responseBytes;
+ SECStatus sigStatus;
+ CERTCertificate *signerCert = NULL;
+
+ PORT_Assert (responseBytes != NULL);
+
+ level++;
+ fprintf (out_file, "Response Bytes:\n");
+ SECU_PrintObjectID (out_file, &(responseBytes->responseType),
+ "Response Type", level);
+ switch (response->responseBytes->responseTypeTag) {
+ case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
+ print_basic_response (out_file,
+ responseBytes->decodedResponse.basic,
+ level);
+ break;
+ default:
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "Unknown response syntax\n");
+ break;
+ }
+
+ sigStatus = CERT_VerifyOCSPResponseSignature (response, handle,
+ NULL, &signerCert, NULL);
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "Signature verification ");
+ if (sigStatus != SECSuccess) {
+ fprintf (out_file, "failed: %s\n", SECU_Strerror (PORT_GetError()));
+ } else {
+ fprintf (out_file, "succeeded.\n");
+ if (signerCert != NULL) {
+ SECU_PrintName (out_file, &signerCert->subject, "Signer",
+ level);
+ CERT_DestroyCertificate (signerCert);
+ } else {
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "No signer cert returned?\n");
+ }
+ }
+ } else {
+ SECU_Indent (out_file, level);
+ fprintf (out_file, "Unsuccessful response, no more information.\n");
+ }
+
+ CERT_DestroyOCSPResponse (response);
+ return SECSuccess;
+}
+
+#endif /* NO_PP */
+
+
+static SECStatus
+cert_usage_from_char (const char *cert_usage_str, SECCertUsage *cert_usage)
+{
+ PORT_Assert (cert_usage_str != NULL);
+ PORT_Assert (cert_usage != NULL);
+
+ if (PORT_Strlen (cert_usage_str) != 1)
+ return SECFailure;
+
+ switch (*cert_usage_str) {
+ case 'c':
+ *cert_usage = certUsageSSLClient;
+ break;
+ case 's':
+ *cert_usage = certUsageSSLServer;
+ break;
+ case 'e':
+ *cert_usage = certUsageEmailRecipient;
+ break;
+ case 'E':
+ *cert_usage = certUsageEmailSigner;
+ break;
+ case 'S':
+ *cert_usage = certUsageObjectSigner;
+ break;
+ case 'C':
+ *cert_usage = certUsageVerifyCA;
+ break;
+ default:
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int retval;
+ char *program_name;
+ PRFileDesc *in_file;
+ FILE *out_file; /* not PRFileDesc until SECU accepts it */
+ int crequest, dresponse;
+ int prequest, presponse;
+ int ccert, vcert;
+ const char *db_dir, *date_str, *cert_usage_str, *name;
+ const char *responder_name, *responder_url, *signer_name;
+ PRBool add_acceptable_responses, add_service_locator;
+ SECItem *data = NULL;
+ PLOptState *optstate;
+ SECStatus rv;
+ CERTCertDBHandle *handle = NULL;
+ SECCertUsage cert_usage;
+ int64 verify_time;
+
+ retval = -1; /* what we return/exit with on error */
+
+ program_name = PL_strrchr(argv[0], '/');
+ program_name = program_name ? (program_name + 1) : argv[0];
+
+ in_file = PR_STDIN;
+ out_file = stdout;
+
+ crequest = 0;
+ dresponse = 0;
+ prequest = 0;
+ presponse = 0;
+ ccert = 0;
+ vcert = 0;
+
+ db_dir = NULL;
+ date_str = NULL;
+ cert_usage_str = NULL;
+ name = NULL;
+ responder_name = NULL;
+ responder_url = NULL;
+ signer_name = NULL;
+
+ add_acceptable_responses = PR_FALSE;
+ add_service_locator = PR_FALSE;
+
+ optstate = PL_CreateOptState (argc, argv, "AHLPR:S:V:d:l:pr:s:t:u:w:");
+ if (optstate == NULL) {
+ SECU_PrintError (program_name, "PL_CreateOptState failed");
+ return retval;
+ }
+
+ while (PL_GetNextOpt (optstate) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ short_usage (program_name);
+ return retval;
+
+ case 'A':
+ add_acceptable_responses = PR_TRUE;
+ break;
+
+ case 'H':
+ long_usage (program_name);
+ return retval;
+
+ case 'L':
+ add_service_locator = PR_TRUE;
+ break;
+
+ case 'P':
+ presponse = 1;
+ break;
+
+ case 'R':
+ dresponse = 1;
+ name = optstate->value;
+ break;
+
+ case 'S':
+ ccert = 1;
+ name = optstate->value;
+ break;
+
+ case 'V':
+ vcert = 1;
+ name = optstate->value;
+ break;
+
+ case 'd':
+ db_dir = optstate->value;
+ break;
+
+ case 'l':
+ responder_url = optstate->value;
+ break;
+
+ case 'p':
+ prequest = 1;
+ break;
+
+ case 'r':
+ crequest = 1;
+ name = optstate->value;
+ break;
+
+ case 's':
+ signer_name = optstate->value;
+ break;
+
+ case 't':
+ responder_name = optstate->value;
+ break;
+
+ case 'u':
+ cert_usage_str = optstate->value;
+ break;
+
+ case 'w':
+ date_str = optstate->value;
+ break;
+ }
+ }
+
+ if ((crequest + dresponse + prequest + presponse + ccert + vcert) != 1) {
+ PR_fprintf (PR_STDERR, "%s: must specify exactly one command\n\n",
+ program_name);
+ short_usage (program_name);
+ return retval;
+ }
+
+ if (vcert) {
+ if (cert_usage_str == NULL) {
+ PR_fprintf (PR_STDERR, "%s: verification requires cert usage\n\n",
+ program_name);
+ short_usage (program_name);
+ return retval;
+ }
+
+ rv = cert_usage_from_char (cert_usage_str, &cert_usage);
+ if (rv != SECSuccess) {
+ PR_fprintf (PR_STDERR, "%s: invalid cert usage (\"%s\")\n\n",
+ program_name, cert_usage_str);
+ long_usage (program_name);
+ return retval;
+ }
+ }
+
+ if (ccert + vcert) {
+ if (responder_url != NULL || responder_name != NULL) {
+ /*
+ * To do a full status check, both the URL and the cert name
+ * of the responder must be specified if either one is.
+ */
+ if (responder_url == NULL || responder_name == NULL) {
+ if (responder_url == NULL)
+ PR_fprintf (PR_STDERR,
+ "%s: must also specify responder location\n\n",
+ program_name);
+ else
+ PR_fprintf (PR_STDERR,
+ "%s: must also specify responder name\n\n",
+ program_name);
+ short_usage (program_name);
+ return retval;
+ }
+ }
+
+ if (date_str != NULL) {
+ rv = DER_AsciiToTime (&verify_time, (char *) date_str);
+ if (rv != SECSuccess) {
+ SECU_PrintError (program_name, "error converting time string");
+ PR_fprintf (PR_STDERR, "\n");
+ long_usage (program_name);
+ return retval;
+ }
+ } else {
+ verify_time = PR_Now();
+ }
+ }
+
+ retval = -2; /* errors change from usage to runtime */
+
+ /*
+ * Initialize the NSPR and Security libraries.
+ */
+ PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ db_dir = SECU_ConfigDirectory (db_dir);
+ rv = NSS_Init (db_dir);
+ if (rv != SECSuccess) {
+ SECU_PrintError (program_name, "NSS_Init failed");
+ goto prdone;
+ }
+
+ if (prequest + presponse) {
+ data = read_file_into_item (in_file, siBuffer);
+ if (data == NULL) {
+ SECU_PrintError (program_name, "problem reading input");
+ goto nssdone;
+ }
+ }
+
+ if (crequest + dresponse + presponse + ccert + vcert) {
+ handle = CERT_GetDefaultCertDB();
+ if (handle == NULL) {
+ SECU_PrintError (program_name, "problem getting certdb handle");
+ goto nssdone;
+ }
+
+ /*
+ * It would be fine to do the enable for all of these commands,
+ * but this way we check that everything but an overall verify
+ * can be done without it. That is, that the individual pieces
+ * work on their own.
+ */
+ if (vcert) {
+ rv = CERT_EnableOCSPChecking (handle);
+ if (rv != SECSuccess) {
+ SECU_PrintError (program_name, "error enabling OCSP checking");
+ goto nssdone;
+ }
+ }
+
+ if ((ccert + vcert) && (responder_name != NULL)) {
+ rv = CERT_SetOCSPDefaultResponder (handle, responder_url,
+ responder_name);
+ if (rv != SECSuccess) {
+ SECU_PrintError (program_name,
+ "error setting default responder");
+ goto nssdone;
+ }
+
+ rv = CERT_EnableOCSPDefaultResponder (handle);
+ if (rv != SECSuccess) {
+ SECU_PrintError (program_name,
+ "error enabling default responder");
+ goto nssdone;
+ }
+ }
+ }
+
+#define NOTYET(opt) \
+ { \
+ PR_fprintf (PR_STDERR, "%s not yet working\n", opt); \
+ exit (-1); \
+ }
+
+ if (crequest) {
+ if (signer_name != NULL) {
+ NOTYET("-s");
+ }
+ rv = create_request (out_file, handle, name, add_service_locator,
+ add_acceptable_responses);
+ } else if (dresponse) {
+ if (signer_name != NULL) {
+ NOTYET("-s");
+ }
+ rv = dump_response (out_file, handle, name, responder_url);
+ } else if (prequest) {
+ rv = print_request (out_file, data);
+ } else if (presponse) {
+ rv = print_response (out_file, data, handle);
+ } else if (ccert) {
+ if (signer_name != NULL) {
+ NOTYET("-s");
+ }
+ rv = get_cert_status (out_file, handle, name, verify_time);
+ } else if (vcert) {
+ if (signer_name != NULL) {
+ NOTYET("-s");
+ }
+ rv = verify_cert (out_file, handle, name, cert_usage, verify_time);
+ }
+
+ if (rv != SECSuccess)
+ SECU_PrintError (program_name, "error performing requested operation");
+ else
+ retval = 0;
+
+nssdone:
+ if (data != NULL) {
+ SECITEM_FreeItem (data, PR_TRUE);
+ }
+
+ if (handle != NULL) {
+ (void) CERT_DisableOCSPChecking (handle);
+ }
+
+ if (NSS_Shutdown () != SECSuccess) {
+ exit(1);
+ }
+
+prdone:
+ PR_Cleanup ();
+ return retval;
+}
diff --git a/security/nss/cmd/oidcalc/Makefile b/security/nss/cmd/oidcalc/Makefile
new file mode 100644
index 000000000..689240abd
--- /dev/null
+++ b/security/nss/cmd/oidcalc/Makefile
@@ -0,0 +1,76 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/oidcalc/manifest.mn b/security/nss/cmd/oidcalc/manifest.mn
new file mode 100644
index 000000000..7e1c3fad6
--- /dev/null
+++ b/security/nss/cmd/oidcalc/manifest.mn
@@ -0,0 +1,47 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = oidcalc.c
+
+PROGRAM = oidcalc
diff --git a/security/nss/cmd/oidcalc/oidcalc.c b/security/nss/cmd/oidcalc/oidcalc.c
new file mode 100644
index 000000000..cadc425a4
--- /dev/null
+++ b/security/nss/cmd/oidcalc/oidcalc.c
@@ -0,0 +1,117 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main(int argc, char **argv)
+{
+ char *curstr;
+ char *nextstr;
+ unsigned int firstval;
+ unsigned int secondval;
+ unsigned int val;
+ unsigned char buf[5];
+ int count;
+
+ if ( argc != 2 ) {
+ fprintf(stderr, "wrong number of args\n");
+ exit(-1);
+ }
+
+ curstr = argv[1];
+
+ nextstr = strchr(curstr, '.');
+
+ if ( nextstr == NULL ) {
+ fprintf(stderr, "only one component\n");
+ exit(-1);
+ }
+
+ *nextstr = '\0';
+ firstval = atoi(curstr);
+
+ curstr = nextstr + 1;
+
+ nextstr = strchr(curstr, '.');
+
+ if ( nextstr ) {
+ *nextstr = '\0';
+ }
+
+ secondval = atoi(curstr);
+
+ if ( ( firstval < 0 ) || ( firstval > 2 ) ) {
+ fprintf(stderr, "first component out of range\n");
+ exit(-1);
+
+ }
+
+ if ( ( secondval < 0 ) || ( secondval > 39 ) ) {
+ fprintf(stderr, "second component out of range\n");
+ exit(-1);
+ }
+
+ printf("0x%x, ", ( firstval * 40 ) + secondval );
+ while ( nextstr ) {
+ curstr = nextstr + 1;
+
+ nextstr = strchr(curstr, '.');
+
+ if ( nextstr ) {
+ *nextstr = '\0';
+ }
+
+ memset(buf, 0, sizeof(buf));
+ val = atoi(curstr);
+ count = 0;
+ while ( val ) {
+ buf[count] = ( val & 0x7f );
+ val = val >> 7;
+ count++;
+ }
+
+ while ( count-- ) {
+ if ( count ) {
+ printf("0x%x, ", buf[count] | 0x80 );
+ } else {
+ printf("0x%x, ", buf[count] );
+ }
+ }
+ }
+ printf("\n");
+ return 0;
+}
+
diff --git a/security/nss/cmd/p7content/Makefile b/security/nss/cmd/p7content/Makefile
new file mode 100644
index 000000000..4e39ffc3f
--- /dev/null
+++ b/security/nss/cmd/p7content/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/p7content/manifest.mn b/security/nss/cmd/p7content/manifest.mn
new file mode 100644
index 000000000..3ebd21743
--- /dev/null
+++ b/security/nss/cmd/p7content/manifest.mn
@@ -0,0 +1,43 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+MODULE = nss
+
+CSRCS = p7content.c
+
+REQUIRES = seccmd
+
+PROGRAM = p7content
+
diff --git a/security/nss/cmd/p7content/p7content.c b/security/nss/cmd/p7content/p7content.c
new file mode 100644
index 000000000..8b5ad65ce
--- /dev/null
+++ b/security/nss/cmd/p7content/p7content.c
@@ -0,0 +1,271 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * p7content -- A command to display pkcs7 content.
+ *
+ * $Id$
+ */
+
+#include "nspr.h"
+#include "secutil.h"
+#include "plgetopt.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "nss.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
+extern int fwrite(char *, size_t, size_t, FILE*);
+extern int fprintf(FILE *, char *, ...);
+#endif
+
+
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-d dbdir] [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr,
+ "%-20s Key/Cert database directory (default is ~/.netscape)\n",
+ "-d dbdir");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+static PRBool saw_content;
+
+static void
+PrintBytes(void *arg, const char *buf, unsigned long len)
+{
+ FILE *out;
+
+ out = arg;
+ fwrite (buf, len, 1, out);
+
+ saw_content = PR_TRUE;
+}
+
+/*
+ * XXX Someday we may want to do real policy stuff here. This allows
+ * anything to be decrypted, which is okay for a test program but does
+ * not set an example of how a real client with a real policy would
+ * need to do it.
+ */
+static PRBool
+decryption_allowed(SECAlgorithmID *algid, PK11SymKey *key)
+{
+ return PR_TRUE;
+}
+
+int
+DecodeAndPrintFile(FILE *out, PRFileDesc *in, char *progName)
+{
+ SECItem derdata;
+ SEC_PKCS7ContentInfo *cinfo = NULL;
+ SEC_PKCS7DecoderContext *dcx;
+
+ if (SECU_ReadDERFromFile(&derdata, in, PR_FALSE)) {
+ SECU_PrintError(progName, "error converting der");
+ return -1;
+ }
+
+ fprintf(out,
+ "Content printed between bars (newline added before second bar):");
+ fprintf(out, "\n---------------------------------------------\n");
+
+ saw_content = PR_FALSE;
+ dcx = SEC_PKCS7DecoderStart(PrintBytes, out, NULL, NULL,
+ NULL, NULL, decryption_allowed);
+ if (dcx != NULL) {
+#if 0 /* Test that decoder works when data is really streaming in. */
+ {
+ unsigned long i;
+ for (i = 0; i < derdata.len; i++)
+ SEC_PKCS7DecoderUpdate(dcx, derdata.data + i, 1);
+ }
+#else
+ SEC_PKCS7DecoderUpdate(dcx, (char *)derdata.data, derdata.len);
+#endif
+ cinfo = SEC_PKCS7DecoderFinish(dcx);
+ }
+
+ fprintf(out, "\n---------------------------------------------\n");
+
+ if (cinfo == NULL)
+ return -1;
+
+ fprintf(out, "Content was%s encrypted.\n",
+ SEC_PKCS7ContentIsEncrypted(cinfo) ? "" : " not");
+
+ if (SEC_PKCS7ContentIsSigned(cinfo)) {
+ char *signer_cname, *signer_ename;
+ SECItem *signing_time;
+
+ if (saw_content) {
+ fprintf(out, "Signature is ");
+ PORT_SetError(0);
+ if (SEC_PKCS7VerifySignature(cinfo, certUsageEmailSigner, PR_FALSE))
+ fprintf(out, "valid.\n");
+ else
+ fprintf(out, "invalid (Reason: %s).\n",
+ SECU_Strerror(PORT_GetError()));
+ } else {
+ fprintf(out,
+ "Content is detached; signature cannot be verified.\n");
+ }
+
+ signer_cname = SEC_PKCS7GetSignerCommonName(cinfo);
+ if (signer_cname != NULL) {
+ fprintf(out, "The signer's common name is %s\n", signer_cname);
+ PORT_Free(signer_cname);
+ } else {
+ fprintf(out, "No signer common name.\n");
+ }
+
+ signer_ename = SEC_PKCS7GetSignerEmailAddress(cinfo);
+ if (signer_ename != NULL) {
+ fprintf(out, "The signer's email address is %s\n", signer_ename);
+ PORT_Free(signer_ename);
+ } else {
+ fprintf(out, "No signer email address.\n");
+ }
+
+ signing_time = SEC_PKCS7GetSigningTime(cinfo);
+ if (signing_time != NULL) {
+ SECU_PrintUTCTime(out, signing_time, "Signing time", 0);
+ } else {
+ fprintf(out, "No signing time included.\n");
+ }
+ } else {
+ fprintf(out, "Content was not signed.\n");
+ }
+
+ fprintf(out, "There were%s certs or crls included.\n",
+ SEC_PKCS7ContainsCertsOrCrls(cinfo) ? "" : " no");
+
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ return 0;
+}
+
+
+/*
+ * Print the contents of a PKCS7 message, indicating signatures, etc.
+ */
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *outFile;
+ PRFileDesc *inFile;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ inFile = NULL;
+ outFile = NULL;
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "d:i:o:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ default:
+ Usage(progName);
+ break;
+ }
+ }
+ if (status == PL_OPT_BAD)
+ Usage(progName);
+
+ if (!inFile) inFile = PR_STDIN;
+ if (!outFile) outFile = stdout;
+
+ /* Call the initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+
+ if (DecodeAndPrintFile(outFile, inFile, progName)) {
+ SECU_PrintError(progName, "problem decoding data");
+ return -1;
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/security/nss/cmd/p7env/Makefile b/security/nss/cmd/p7env/Makefile
new file mode 100644
index 000000000..4e39ffc3f
--- /dev/null
+++ b/security/nss/cmd/p7env/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/p7env/manifest.mn b/security/nss/cmd/p7env/manifest.mn
new file mode 100644
index 000000000..7d51282f9
--- /dev/null
+++ b/security/nss/cmd/p7env/manifest.mn
@@ -0,0 +1,43 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+MODULE = nss
+
+CSRCS = p7env.c
+
+REQUIRES = seccmd
+
+PROGRAM = p7env
+
diff --git a/security/nss/cmd/p7env/p7env.c b/security/nss/cmd/p7env/p7env.c
new file mode 100644
index 000000000..54d79fbfc
--- /dev/null
+++ b/security/nss/cmd/p7env/p7env.c
@@ -0,0 +1,273 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * p7env -- A command to create a pkcs7 enveloped data.
+ *
+ * $Id$
+ */
+
+#include "nspr.h"
+#include "secutil.h"
+#include "plgetopt.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "nss.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
+extern int fread(char *, size_t, size_t, FILE*);
+extern int fwrite(char *, size_t, size_t, FILE*);
+extern int fprintf(FILE *, char *, ...);
+#endif
+
+extern void SEC_Init(void); /* XXX */
+
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -r recipient [-d dbdir] [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Nickname of cert to use for encryption\n",
+ "-r recipient");
+ fprintf(stderr, "%-20s Cert database directory (default is ~/.netscape)\n",
+ "-d dbdir");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+struct recipient {
+ struct recipient *next;
+ char *nickname;
+ CERTCertificate *cert;
+};
+
+static void
+EncryptOut(void *arg, const char *buf, unsigned long len)
+{
+ FILE *out;
+
+ out = arg;
+ fwrite (buf, len, 1, out);
+}
+
+static int
+EncryptFile(FILE *outFile, FILE *inFile, struct recipient *recipients,
+ char *progName)
+{
+ SEC_PKCS7ContentInfo *cinfo;
+ SEC_PKCS7EncoderContext *ecx;
+ struct recipient *rcpt;
+ SECStatus rv;
+
+ if (outFile == NULL || inFile == NULL || recipients == NULL)
+ return -1;
+
+ /* XXX Need a better way to handle that certUsage stuff! */
+ /* XXX keysize? */
+ cinfo = SEC_PKCS7CreateEnvelopedData (recipients->cert,
+ certUsageEmailRecipient,
+ NULL, SEC_OID_DES_EDE3_CBC, 0,
+ NULL, NULL);
+ if (cinfo == NULL)
+ return -1;
+
+ for (rcpt = recipients->next; rcpt != NULL; rcpt = rcpt->next) {
+ rv = SEC_PKCS7AddRecipient (cinfo, rcpt->cert, certUsageEmailRecipient,
+ NULL);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error adding recipient \"%s\"",
+ rcpt->nickname);
+ return -1;
+ }
+ }
+
+ ecx = SEC_PKCS7EncoderStart (cinfo, EncryptOut, outFile, NULL);
+ if (ecx == NULL)
+ return -1;
+
+ for (;;) {
+ char ibuf[1024];
+ int nb;
+
+ if (feof(inFile))
+ break;
+ nb = fread(ibuf, 1, sizeof(ibuf), inFile);
+ if (nb == 0) {
+ if (ferror(inFile)) {
+ PORT_SetError(SEC_ERROR_IO);
+ rv = SECFailure;
+ }
+ break;
+ }
+ rv = SEC_PKCS7EncoderUpdate(ecx, ibuf, nb);
+ if (rv != SECSuccess)
+ break;
+ }
+
+ if (SEC_PKCS7EncoderFinish(ecx, NULL, NULL) != SECSuccess)
+ rv = SECFailure;
+
+ SEC_PKCS7DestroyContentInfo (cinfo);
+
+ if (rv != SECSuccess)
+ return -1;
+
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *inFile, *outFile;
+ char *certName;
+ CERTCertDBHandle *certHandle;
+ CERTCertificate *cert;
+ struct recipient *recipients, *rcpt;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ inFile = NULL;
+ outFile = NULL;
+ certName = NULL;
+ recipients = NULL;
+ rcpt = NULL;
+
+ /*
+ * Parse command line arguments
+ * XXX This needs to be enhanced to allow selection of algorithms
+ * and key sizes (or to look up algorithms and key sizes for each
+ * recipient in the magic database).
+ */
+ optstate = PL_CreateOptState(argc, argv, "d:i:o:r:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'i':
+ inFile = fopen(optstate->value, "r");
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'r':
+ if (rcpt == NULL) {
+ recipients = rcpt = PORT_Alloc (sizeof(struct recipient));
+ } else {
+ rcpt->next = PORT_Alloc (sizeof(struct recipient));
+ rcpt = rcpt->next;
+ }
+ if (rcpt == NULL) {
+ fprintf(stderr, "%s: unable to allocate recipient struct\n",
+ progName);
+ return -1;
+ }
+ rcpt->nickname = strdup(optstate->value);
+ rcpt->cert = NULL;
+ rcpt->next = NULL;
+ break;
+ }
+ }
+
+ if (!recipients) Usage(progName);
+
+ if (!inFile) inFile = stdin;
+ if (!outFile) outFile = stdout;
+
+ /* Call the libsec initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+
+ /* open cert database */
+ certHandle = CERT_GetDefaultCertDB();
+ if (certHandle == NULL) {
+ return -1;
+ }
+
+ /* find certs */
+ for (rcpt = recipients; rcpt != NULL; rcpt = rcpt->next) {
+ rcpt->cert = CERT_FindCertByNickname(certHandle, rcpt->nickname);
+ if (rcpt->cert == NULL) {
+ SECU_PrintError(progName,
+ "the cert for name \"%s\" not found in database",
+ rcpt->nickname);
+ return -1;
+ }
+ }
+
+ if (EncryptFile(outFile, inFile, recipients, progName)) {
+ SECU_PrintError(progName, "problem encrypting data");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/security/nss/cmd/p7sign/Makefile b/security/nss/cmd/p7sign/Makefile
new file mode 100644
index 000000000..4e39ffc3f
--- /dev/null
+++ b/security/nss/cmd/p7sign/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/p7sign/manifest.mn b/security/nss/cmd/p7sign/manifest.mn
new file mode 100644
index 000000000..d5134df48
--- /dev/null
+++ b/security/nss/cmd/p7sign/manifest.mn
@@ -0,0 +1,43 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+MODULE = nss
+
+CSRCS = p7sign.c
+
+REQUIRES = seccmd
+
+PROGRAM = p7sign
+
diff --git a/security/nss/cmd/p7sign/p7sign.c b/security/nss/cmd/p7sign/p7sign.c
new file mode 100644
index 000000000..09cbd8dcd
--- /dev/null
+++ b/security/nss/cmd/p7sign/p7sign.c
@@ -0,0 +1,292 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * p7sign -- A command to create a *detached* pkcs7 signature (over a given
+ * input file).
+ *
+ * $Id$
+ */
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "secutil.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "sechash.h" /* for HASH_GetHashObject() */
+#include "nss.h"
+#include "pk11func.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
+extern int fread(char *, size_t, size_t, FILE*);
+extern int fwrite(char *, size_t, size_t, FILE*);
+extern int fprintf(FILE *, char *, ...);
+#endif
+
+char* KeyDbPassword = 0;
+
+
+char* MyPK11PasswordFunc (PK11SlotInfo *slot, PRBool retry, void* arg)
+{
+ char *ret=0;
+
+ if (retry == PR_TRUE)
+ return NULL;
+ ret = PL_strdup (KeyDbPassword);
+ return ret;
+}
+
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -k keyname [-d keydir] [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Nickname of key to use for signature\n",
+ "-k keyname");
+ fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
+ "-d keydir");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ fprintf(stderr, "%-20s Encapsulate content in signature message\n",
+ "-e");
+ fprintf(stderr, "%-20s Password to the key databse\n", "-p");
+ exit(-1);
+}
+
+static void
+SignOut(void *arg, const char *buf, unsigned long len)
+{
+ FILE *out;
+
+ out = (FILE*) arg;
+ fwrite (buf, len, 1, out);
+}
+
+static int
+CreateDigest(SECItem *data, char *digestdata, unsigned int *len, unsigned int maxlen)
+{
+ const SECHashObject *hashObj;
+ void *hashcx;
+
+ /* XXX probably want to extend interface to allow other hash algorithms */
+ hashObj = HASH_GetHashObject(HASH_AlgSHA1);
+
+ hashcx = (* hashObj->create)();
+ if (hashcx == NULL)
+ return -1;
+
+ (* hashObj->begin)(hashcx);
+ (* hashObj->update)(hashcx, data->data, data->len);
+ (* hashObj->end)(hashcx, (unsigned char *)digestdata, len, maxlen);
+ (* hashObj->destroy)(hashcx, PR_TRUE);
+ return 0;
+}
+
+static int
+SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert,
+ PRBool encapsulated)
+{
+ int nb;
+ char digestdata[32];
+ unsigned int len;
+ SECItem digest, data2sign;
+ SEC_PKCS7ContentInfo *cinfo;
+ SECStatus rv;
+
+ if (outFile == NULL || inFile == NULL || cert == NULL)
+ return -1;
+
+ /* suck the file in */
+ if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE) != SECSuccess)
+ return -1;
+
+ if (!encapsulated) {
+ /* unfortunately, we must create the digest ourselves */
+ /* SEC_PKCS7CreateSignedData should have a flag to not include */
+ /* the content for non-encapsulated content at encode time, but */
+ /* should always compute the hash itself */
+ if (CreateDigest(&data2sign, digestdata, &len, 32) < 0)
+ return -1;
+ digest.data = (unsigned char *)digestdata;
+ digest.len = len;
+ }
+
+ /* XXX Need a better way to handle that usage stuff! */
+ cinfo = SEC_PKCS7CreateSignedData (cert, certUsageEmailSigner, NULL,
+ SEC_OID_SHA1,
+ encapsulated ? NULL : &digest,
+ NULL, NULL);
+ if (cinfo == NULL)
+ return -1;
+
+ if (encapsulated) {
+ SEC_PKCS7SetContent(cinfo, (char *)data2sign.data, data2sign.len);
+ }
+
+ rv = SEC_PKCS7IncludeCertChain (cinfo, NULL);
+ if (rv != SECSuccess) {
+ SEC_PKCS7DestroyContentInfo (cinfo);
+ return -1;
+ }
+
+ rv = SEC_PKCS7Encode (cinfo, SignOut, outFile, NULL,
+ NULL, NULL);
+
+ SEC_PKCS7DestroyContentInfo (cinfo);
+
+ if (rv != SECSuccess)
+ return -1;
+
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *outFile;
+ PRFileDesc *inFile;
+ char *keyName;
+ CERTCertDBHandle *certHandle;
+ CERTCertificate *cert;
+ PRBool encapsulated = PR_FALSE;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ inFile = NULL;
+ outFile = NULL;
+ keyName = NULL;
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "ed:k:i:o:p:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'e':
+ /* create a message with the signed content encapsulated */
+ encapsulated = PR_TRUE;
+ break;
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'k':
+ keyName = strdup(optstate->value);
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+ case 'p':
+ KeyDbPassword = strdup (optstate->value);
+ break;
+ }
+ }
+
+ if (!keyName) Usage(progName);
+
+ if (!inFile) inFile = PR_STDIN;
+ if (!outFile) outFile = stdout;
+
+ /* Call the initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+
+ PK11_SetPasswordFunc (MyPK11PasswordFunc);
+
+ /* open cert database */
+ certHandle = CERT_GetDefaultCertDB();
+ if (certHandle == NULL) {
+ return -1;
+ }
+
+ /* find cert */
+ cert = CERT_FindCertByNickname(certHandle, keyName);
+ if (cert == NULL) {
+ SECU_PrintError(progName,
+ "the corresponding cert for key \"%s\" does not exist",
+ keyName);
+ return -1;
+ }
+
+ if (SignFile(outFile, inFile, cert, encapsulated)) {
+ SECU_PrintError(progName, "problem signing data");
+ return -1;
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/security/nss/cmd/p7verify/Makefile b/security/nss/cmd/p7verify/Makefile
new file mode 100644
index 000000000..4e39ffc3f
--- /dev/null
+++ b/security/nss/cmd/p7verify/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/p7verify/manifest.mn b/security/nss/cmd/p7verify/manifest.mn
new file mode 100644
index 000000000..7e841c700
--- /dev/null
+++ b/security/nss/cmd/p7verify/manifest.mn
@@ -0,0 +1,43 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+MODULE = nss
+
+CSRCS = p7verify.c
+
+REQUIRES = seccmd
+
+PROGRAM = p7verify
+
diff --git a/security/nss/cmd/p7verify/p7verify.c b/security/nss/cmd/p7verify/p7verify.c
new file mode 100644
index 000000000..81815081b
--- /dev/null
+++ b/security/nss/cmd/p7verify/p7verify.c
@@ -0,0 +1,305 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * p7verify -- A command to do a verification of a *detached* pkcs7 signature.
+ *
+ * $Id$
+ */
+
+#include "nspr.h"
+#include "secutil.h"
+#include "plgetopt.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "secoid.h"
+#include "sechash.h" /* for HASH_GetHashObject() */
+#include "nss.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
+extern int fread(char *, size_t, size_t, FILE*);
+extern int fprintf(FILE *, char *, ...);
+#endif
+
+
+static HASH_HashType
+AlgorithmToHashType(SECAlgorithmID *digestAlgorithms)
+{
+
+ SECOidTag tag;
+
+ tag = SECOID_GetAlgorithmTag(digestAlgorithms);
+
+ switch (tag) {
+ case SEC_OID_MD2:
+ return HASH_AlgMD2;
+ case SEC_OID_MD5:
+ return HASH_AlgMD5;
+ case SEC_OID_SHA1:
+ return HASH_AlgSHA1;
+ default:
+ fprintf(stderr, "should never get here\n");
+ return HASH_AlgNULL;
+ }
+}
+
+static int
+DigestFile(unsigned char *digest, unsigned int *len, unsigned int maxLen,
+ FILE *inFile, HASH_HashType hashType)
+{
+ int nb;
+ unsigned char ibuf[4096];
+ const SECHashObject *hashObj;
+ void *hashcx;
+
+ hashObj = HASH_GetHashObject(hashType);
+
+ hashcx = (* hashObj->create)();
+ if (hashcx == NULL)
+ return -1;
+
+ (* hashObj->begin)(hashcx);
+
+ for (;;) {
+ if (feof(inFile)) break;
+ nb = fread(ibuf, 1, sizeof(ibuf), inFile);
+ if (nb != sizeof(ibuf)) {
+ if (nb == 0) {
+ if (ferror(inFile)) {
+ PORT_SetError(SEC_ERROR_IO);
+ (* hashObj->destroy)(hashcx, PR_TRUE);
+ return -1;
+ }
+ /* eof */
+ break;
+ }
+ }
+ (* hashObj->update)(hashcx, ibuf, nb);
+ }
+
+ (* hashObj->end)(hashcx, digest, len, maxLen);
+ (* hashObj->destroy)(hashcx, PR_TRUE);
+
+ return 0;
+}
+
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -c content -s signature [-d dbdir] [-u certusage]\n",
+ progName);
+ fprintf(stderr, "%-20s content file that was signed\n",
+ "-c content");
+ fprintf(stderr, "%-20s file containing signature for that content\n",
+ "-s signature");
+ fprintf(stderr,
+ "%-20s Key/Cert database directory (default is ~/.netscape)\n",
+ "-d dbdir");
+ fprintf(stderr, "%-20s Define the type of certificate usage (default is certUsageEmailSigner)\n",
+ "-u certusage");
+ fprintf(stderr, "%-25s 0 - certUsageSSLClient\n", " ");
+ fprintf(stderr, "%-25s 1 - certUsageSSLServer\n", " ");
+ fprintf(stderr, "%-25s 2 - certUsageSSLServerWithStepUp\n", " ");
+ fprintf(stderr, "%-25s 3 - certUsageSSLCA\n", " ");
+ fprintf(stderr, "%-25s 4 - certUsageEmailSigner\n", " ");
+ fprintf(stderr, "%-25s 5 - certUsageEmailRecipient\n", " ");
+ fprintf(stderr, "%-25s 6 - certUsageObjectSigner\n", " ");
+ fprintf(stderr, "%-25s 7 - certUsageUserCertImport\n", " ");
+ fprintf(stderr, "%-25s 8 - certUsageVerifyCA\n", " ");
+ fprintf(stderr, "%-25s 9 - certUsageProtectedObjectSigner\n", " ");
+ fprintf(stderr, "%-25s 10 - certUsageStatusResponder\n", " ");
+ fprintf(stderr, "%-25s 11 - certUsageAnyCA\n", " ");
+
+ exit(-1);
+}
+
+static int
+HashDecodeAndVerify(FILE *out, FILE *content, PRFileDesc *signature,
+ SECCertUsage usage, char *progName)
+{
+ SECItem derdata;
+ SEC_PKCS7ContentInfo *cinfo;
+ SEC_PKCS7SignedData *signedData;
+ HASH_HashType digestType;
+ SECItem digest;
+ unsigned char buffer[32];
+
+ if (SECU_ReadDERFromFile(&derdata, signature, PR_FALSE) != SECSuccess) {
+ SECU_PrintError(progName, "error reading signature file");
+ return -1;
+ }
+
+ cinfo = SEC_PKCS7DecodeItem(&derdata, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (cinfo == NULL)
+ return -1;
+
+ if (! SEC_PKCS7ContentIsSigned(cinfo)) {
+ fprintf (out, "Signature file is pkcs7 data, but not signed.\n");
+ return -1;
+ }
+
+ signedData = cinfo->content.signedData;
+
+ /* assume that there is only one digest algorithm for now */
+ digestType = AlgorithmToHashType(signedData->digestAlgorithms[0]);
+ if (digestType == HASH_AlgNULL) {
+ fprintf (out, "Invalid hash algorithmID\n");
+ return -1;
+ }
+
+ digest.data = buffer;
+ if (DigestFile (digest.data, &digest.len, 32, content, digestType)) {
+ SECU_PrintError (progName, "problem computing message digest");
+ return -1;
+ }
+
+ fprintf(out, "Signature is ");
+ if (SEC_PKCS7VerifyDetachedSignature (cinfo, usage, &digest, digestType,
+ PR_FALSE))
+ fprintf(out, "valid.\n");
+ else
+ fprintf(out, "invalid (Reason: %s).\n",
+ SECU_Strerror(PORT_GetError()));
+
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ return 0;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *contentFile, *outFile;
+ PRFileDesc *signatureFile;
+ SECCertUsage certUsage = certUsageEmailSigner;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ contentFile = NULL;
+ signatureFile = NULL;
+ outFile = NULL;
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "c:d:o:s:u:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'c':
+ contentFile = fopen(optstate->value, "r");
+ if (!contentFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 's':
+ signatureFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!signatureFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'u': {
+ int usageType;
+
+ usageType = atoi (strdup(optstate->value));
+ if (usageType < certUsageSSLClient || usageType > certUsageAnyCA)
+ return -1;
+ certUsage = (SECCertUsage)usageType;
+ break;
+ }
+
+ }
+ }
+
+ if (!contentFile) Usage (progName);
+ if (!signatureFile) Usage (progName);
+ if (!outFile) outFile = stdout;
+
+ /* Call the libsec initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+
+ if (HashDecodeAndVerify(outFile, contentFile, signatureFile,
+ certUsage, progName)) {
+ SECU_PrintError(progName, "problem decoding/verifying signature");
+ return -1;
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/security/nss/cmd/pk12util/Makefile b/security/nss/cmd/pk12util/Makefile
new file mode 100644
index 000000000..8650a607d
--- /dev/null
+++ b/security/nss/cmd/pk12util/Makefile
@@ -0,0 +1,76 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/pk12util/manifest.mn b/security/nss/cmd/pk12util/manifest.mn
new file mode 100644
index 000000000..40fd6d6ac
--- /dev/null
+++ b/security/nss/cmd/pk12util/manifest.mn
@@ -0,0 +1,51 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ pk12util.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = dbm seccmd
+
+PROGRAM = pk12util
+
+# USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/pk12util/pk12util.c b/security/nss/cmd/pk12util/pk12util.c
new file mode 100644
index 000000000..255c189d9
--- /dev/null
+++ b/security/nss/cmd/pk12util/pk12util.c
@@ -0,0 +1,867 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "nspr.h"
+#include "secutil.h"
+#include "pk11func.h"
+#include "pkcs12.h"
+#include "p12plcy.h"
+#include "pk12util.h"
+#include "nss.h"
+#include "secport.h"
+#include "certdb.h"
+
+#define PKCS12_IN_BUFFER_SIZE 200
+
+static char *progName;
+PRBool pk12_debugging = PR_FALSE;
+
+PRIntn pk12uErrno = 0;
+
+static void
+Usage(char *progName)
+{
+#define FPS PR_fprintf(PR_STDERR,
+ FPS "Usage: %s -i importfile [-d certdir] [-P dbprefix] [-h tokenname]\n",
+ progName);
+ FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n");
+ FPS "\t\t [-v]\n");
+ FPS "Usage: %s -o exportfile -n certname [-d certdir] [-P dbprefix]\n", progName);
+ FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n");
+ FPS "\t\t [-v]\n");
+ exit(PK12UERR_USAGE);
+}
+
+static PRBool
+p12u_OpenExportFile(p12uContext *p12cxt, PRBool fileRead)
+{
+ if(!p12cxt || !p12cxt->filename) {
+ return PR_FALSE;
+ }
+
+ if(fileRead) {
+ p12cxt->file = PR_Open(p12cxt->filename,
+ PR_RDONLY, 0400);
+ } else {
+ p12cxt->file = PR_Open(p12cxt->filename,
+ PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE,
+ 0600);
+ }
+
+ if(!p12cxt->file) {
+ p12cxt->error = PR_TRUE;
+ PR_SetError(SEC_ERROR_NO_MEMORY, 0);
+ return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+static void
+p12u_DestroyExportFileInfo(p12uContext **exp_ptr, PRBool removeFile)
+{
+ if(!exp_ptr || !(*exp_ptr)) {
+ return;
+ }
+
+ if((*exp_ptr)->file != NULL) {
+ PR_Close((*exp_ptr)->file);
+ }
+
+ if((*exp_ptr)->filename != NULL) {
+ if(removeFile) {
+ PR_Delete((*exp_ptr)->filename);
+ }
+ PR_Free((*exp_ptr)->filename);
+ }
+
+ PR_Free(*exp_ptr);
+ *exp_ptr = NULL;
+}
+
+static p12uContext *
+p12u_InitFile(PRBool fileImport, char *filename)
+{
+ p12uContext *p12cxt;
+ PRBool fileExist;
+
+ if(fileImport)
+ fileExist = PR_TRUE;
+ else
+ fileExist = PR_FALSE;
+
+ p12cxt = (p12uContext *)PORT_ZAlloc(sizeof(p12uContext));
+ if(!p12cxt) {
+ PR_SetError(SEC_ERROR_NO_MEMORY, 0);
+ return NULL;
+ }
+
+ p12cxt->error = PR_FALSE;
+ p12cxt->errorValue = 0;
+ p12cxt->filename = strdup(filename);
+
+ if(!p12u_OpenExportFile(p12cxt, fileImport)) {
+ PR_SetError(p12cxt->errorValue, 0);
+ p12u_DestroyExportFileInfo(&p12cxt, PR_FALSE);
+ return NULL;
+ }
+
+ return p12cxt;
+}
+
+SECItem *
+P12U_NicknameCollisionCallback(SECItem *old_nick, PRBool *cancel, void *wincx)
+{
+ char *nick = NULL;
+ SECItem *ret_nick = NULL;
+
+ if(cancel == NULL) {
+ pk12uErrno = PK12UERR_USER_CANCELLED;
+ return NULL;
+ }
+
+ if (!old_nick)
+ fprintf(stdout, "pk12util: no nickname for cert...not handled\n");
+
+ /* XXX not handled yet */
+ *cancel = PR_TRUE;
+ return NULL;
+
+#if 0
+ nick = strdup( DEFAULT_CERT_NICKNAME );
+
+ if(old_nick && !PORT_Strcmp((char *)old_nick->data, nick)) {
+ PORT_Free(nick);
+ return NULL;
+ }
+
+ ret_nick = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
+ if(ret_nick == NULL) {
+ PORT_Free(nick);
+ return NULL;
+ }
+
+ ret_nick->data = (unsigned char *)nick;
+ ret_nick->len = PORT_Strlen(nick);
+
+ return ret_nick;
+#endif
+}
+
+static SECStatus
+p12u_SwapUnicodeBytes(SECItem *uniItem)
+{
+ unsigned int i;
+ unsigned char a;
+ if((uniItem == NULL) || (uniItem->len % 2)) {
+ return SECFailure;
+ }
+ for(i = 0; i < uniItem->len; i += 2) {
+ a = uniItem->data[i];
+ uniItem->data[i] = uniItem->data[i+1];
+ uniItem->data[i+1] = a;
+ }
+ return SECSuccess;
+}
+
+static PRBool
+p12u_ucs2_ascii_conversion_function(PRBool toUnicode,
+ unsigned char *inBuf,
+ unsigned int inBufLen,
+ unsigned char *outBuf,
+ unsigned int maxOutBufLen,
+ unsigned int *outBufLen,
+ PRBool swapBytes)
+{
+ SECItem it = { 0 };
+ SECItem *dup = NULL;
+ PRBool ret;
+ /* If converting Unicode to ASCII, swap bytes before conversion
+ * as neccessary.
+ */
+ if (pk12_debugging) {
+ int i;
+ printf("Converted from:\n");
+ for (i=0; i<inBufLen; i++) {
+ printf("%2x ", inBuf[i]);
+ /*if (i%60 == 0) printf("\n");*/
+ }
+ printf("\n");
+ }
+ it.data = inBuf;
+ it.len = inBufLen;
+ dup = SECITEM_DupItem(&it);
+ if (!toUnicode && swapBytes) {
+ if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
+ SECITEM_ZfreeItem(dup, PR_TRUE);
+ return PR_FALSE;
+ }
+ }
+ /* Perform the conversion. */
+ ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len,
+ outBuf, maxOutBufLen, outBufLen);
+ if (dup)
+ SECITEM_ZfreeItem(dup, PR_TRUE);
+ /* If converting ASCII to Unicode, swap bytes before returning
+ * as neccessary.
+ */
+#if 0
+ if (toUnicode && swapBytes) {
+ it.data = outBuf;
+ it.len = *outBufLen;
+ dup = SECITEM_DupItem(&it);
+ if (p12u_SwapUnicodeBytes(dup) != SECSuccess) {
+ SECITEM_ZfreeItem(dup, PR_TRUE);
+ return PR_FALSE;
+ }
+ memcpy(outBuf, dup->data, *outBufLen);
+ SECITEM_ZfreeItem(dup, PR_TRUE);
+ }
+#endif
+ if (pk12_debugging) {
+ int i;
+ printf("Converted to:\n");
+ for (i=0; i<*outBufLen; i++) {
+ printf("%2x ", outBuf[i]);
+ /*if (i%60 == 0) printf("\n");*/
+ }
+ printf("\n");
+ }
+ return ret;
+}
+
+SECStatus
+P12U_UnicodeConversion(PRArenaPool *arena, SECItem *dest, SECItem *src,
+ PRBool toUnicode, PRBool swapBytes)
+{
+ unsigned int allocLen;
+ if(!dest || !src) {
+ return SECFailure;
+ }
+ allocLen = ((toUnicode) ? (src->len << 2) : src->len);
+ if(arena) {
+ dest->data = PORT_ArenaZAlloc(arena, allocLen);
+ } else {
+ dest->data = PORT_ZAlloc(allocLen);
+ }
+ if(PORT_UCS2_ASCIIConversion(toUnicode, src->data, src->len,
+ dest->data, allocLen, &dest->len,
+ swapBytes) == PR_FALSE) {
+ if(!arena) {
+ PORT_Free(dest->data);
+ }
+ dest->data = NULL;
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/*
+ *
+ */
+SECItem *
+P12U_GetP12FilePassword(PRBool confirmPw, secuPWData *p12FilePw)
+{
+ char *p0 = NULL, *p1 = NULL;
+ SECItem *pwItem = NULL;
+
+ if (p12FilePw == NULL || p12FilePw->source == PW_NONE) {
+ for (;;) {
+ p0 = SECU_GetPasswordString(NULL,
+ "Enter password for PKCS12 file: ");
+ if (!confirmPw)
+ break;
+ p1 = SECU_GetPasswordString(NULL, "Re-enter password: ");
+ if (PL_strcmp(p0, p1) == 0)
+ break;
+ }
+ } else if (p12FilePw->source == PW_FROMFILE) {
+ p0 = SECU_FilePasswd(NULL, PR_FALSE, p12FilePw->data);
+ } else { /* Plaintext */
+ p0 = p12FilePw->data;
+ }
+
+ pwItem = SECITEM_AllocItem(NULL, NULL, PL_strlen(p0) + 1);
+ memcpy(pwItem->data, p0, pwItem->len);
+
+ PORT_Memset(p0, 0, PL_strlen(p0));
+ PORT_Free(p0);
+
+ PORT_Memset(p1, 0, PL_strlen(p1));
+ PORT_Free(p1);
+
+ return pwItem;
+}
+
+SECStatus
+P12U_InitSlot(PK11SlotInfo *slot, secuPWData *slotPw)
+{
+ SECStatus rv;
+
+ /* New databases, initialize keydb password. */
+ if (PK11_NeedUserInit(slot)) {
+ rv = SECU_ChangePW(slot,
+ (slotPw->source == PW_PLAINTEXT) ? slotPw->data : 0,
+ (slotPw->source == PW_FROMFILE) ? slotPw->data : 0);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Failed to initialize slot \"%s\"",
+ PK11_GetSlotName(slot));
+ return SECFailure;
+ }
+ }
+
+ if (PK11_Authenticate(slot, PR_TRUE, slotPw) != SECSuccess) {
+ SECU_PrintError(progName,
+ "Failed to authenticate to PKCS11 slot");
+ PORT_SetError(SEC_ERROR_USER_CANCELLED);
+ pk12uErrno = PK12UERR_USER_CANCELLED;
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+/*
+ * given a filename for pkcs12 file, imports certs and keys
+ *
+ * Change: altitude
+ * I've changed this function so that it takes the keydb and pkcs12 file
+ * passwords from files. The "pwdKeyDB" and "pwdP12File"
+ * variables have been added for this purpose.
+ */
+PRIntn
+P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot,
+ secuPWData *slotPw, secuPWData *p12FilePw)
+{
+ p12uContext *p12cxt = NULL;
+ unsigned char inBuf[PKCS12_IN_BUFFER_SIZE];
+ SEC_PKCS12DecoderContext *p12dcx = NULL;
+ SECItem *pwitem = NULL, uniPwitem = { 0 };
+ SECItem p12file = { 0 };
+ SECStatus rv = SECFailure;
+ PRBool swapUnicode = PR_FALSE;
+ int error;
+
+#ifdef IS_LITTLE_ENDIAN
+ swapUnicode = PR_TRUE;
+#endif
+
+ rv = P12U_InitSlot(slot, slotPw);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "Failed to authenticate to \"%s\"",
+ PK11_GetSlotName(slot));
+ pk12uErrno = PK12UERR_PK11GETSLOT;
+ goto loser;
+ }
+
+ p12cxt = p12u_InitFile(PR_TRUE, in_file);
+ if(!p12cxt) {
+ SECU_PrintError(progName,"Initialization failed: %s", in_file);
+ pk12uErrno = PK12UERR_INIT_FILE;
+ goto loser;
+ }
+
+ /* get the password */
+ pwitem = P12U_GetP12FilePassword(PR_FALSE, p12FilePw);
+ if (!pwitem) {
+ pk12uErrno = PK12UERR_USER_CANCELLED;
+ goto loser;
+ }
+
+ if(P12U_UnicodeConversion(NULL, &uniPwitem, pwitem, PR_TRUE,
+ swapUnicode) != SECSuccess) {
+ SECU_PrintError(progName,"Unicode conversion failed");
+ pk12uErrno = PK12UERR_UNICODECONV;
+ goto loser;
+ }
+
+ /* init the decoder context */
+ p12dcx = SEC_PKCS12DecoderStart(&uniPwitem, slot, slotPw,
+ NULL, NULL, NULL, NULL, NULL);
+ if(!p12dcx) {
+ SECU_PrintError(progName,"PKCS12 decoder start failed");
+ pk12uErrno = PK12UERR_PK12DECODESTART;
+ goto loser;
+ }
+
+ /* decode the item */
+ rv = SECU_FileToItem(&p12file, p12cxt->file);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName,"Failed to read from import file");
+ goto loser;
+ }
+ rv = SEC_PKCS12DecoderUpdate(p12dcx, p12file.data, p12file.len);
+
+ if(rv != SECSuccess) {
+ error = PR_GetError();
+ if(error == SEC_ERROR_DECRYPTION_DISALLOWED) {
+ PR_SetError(error, 0);
+ goto loser;
+ }
+#ifdef EXTRA
+ /* unable to import as a new blob, it might be an old one */
+ if(p12u_TryToImportOldPDU(p12cxt, pwitem, slot, import_arg->nickCb,
+ import_arg->proto_win) != SECSuccess) {
+ goto loser;
+ }
+ goto tried_pdu_import;
+#endif /* EXTRA */
+ SECU_PrintError(progName,"PKCS12 decoding failed");
+ pk12uErrno = PK12UERR_DECODE;
+ }
+
+ rv = SECFailure;
+
+ /* does the blob authenticate properly? */
+ if(SEC_PKCS12DecoderVerify(p12dcx) != SECSuccess) {
+ SECU_PrintError(progName,"PKCS12 decode not verified");
+ pk12uErrno = PK12UERR_DECODEVERIFY;
+ goto loser;
+ }
+
+ /* make sure the bags are okey dokey -- nicknames correct, etc. */
+ if (SEC_PKCS12DecoderValidateBags(p12dcx, P12U_NicknameCollisionCallback)
+ != SECSuccess) {
+ if (PORT_GetError() == SEC_ERROR_PKCS12_DUPLICATE_DATA) {
+ pk12uErrno = PK12UERR_CERTALREADYEXISTS;
+ } else {
+ pk12uErrno = PK12UERR_DECODEVALIBAGS;
+ }
+ SECU_PrintError(progName,"PKCS12 decode validate bags failed");
+ goto loser;
+ }
+
+ /* stuff 'em in */
+ if(SEC_PKCS12DecoderImportBags(p12dcx) != SECSuccess) {
+ SECU_PrintError(progName,"PKCS12 decode import bags failed");
+ pk12uErrno = PK12UERR_DECODEIMPTBAGS;
+ goto loser;
+ }
+
+#if 0
+ /* important - to add the password hash into the key database */
+ rv = PK11_CheckUserPassword(slot, pw_string);
+ if( rv != SECSuccess ) {
+ SECU_PrintError(progName,"Failed to CheckUserPassword");
+ exit(-1);
+ }
+#endif
+
+ PR_Close(p12cxt->file);
+ p12cxt->file = NULL;
+ /* PK11_FreeSlot(slot); */
+
+ rv = SECSuccess;
+
+loser:
+ if (rv != SECSuccess) {
+ /* pk12u_report_failure */
+ } else {
+ /* pk12u_report_success ? */
+ }
+
+ if (p12dcx) {
+ SEC_PKCS12DecoderFinish(p12dcx);
+ }
+ p12u_DestroyExportFileInfo(&p12cxt, PR_FALSE);
+
+ if (uniPwitem.data) {
+ SECITEM_ZfreeItem(&uniPwitem, PR_FALSE);
+ }
+
+ if (pwitem) {
+ SECITEM_ZfreeItem(pwitem, PR_TRUE);
+ }
+
+
+ return rv;
+}
+
+static void
+p12u_DoPKCS12ExportErrors()
+{
+ int error_value;
+
+ error_value = PORT_GetError();
+ if ((error_value == SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY) ||
+ (error_value == SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME) ||
+ (error_value == SEC_ERROR_PKCS12_UNABLE_TO_WRITE)) {
+ fprintf(stderr, SECU_ErrorStringRaw((int16)error_value));
+ } else if(error_value == SEC_ERROR_USER_CANCELLED) {
+ ;
+ } else {
+ fprintf(stderr, SECU_ErrorStringRaw(SEC_ERROR_EXPORTING_CERTIFICATES));
+ }
+}
+
+static void
+p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
+{
+ p12uContext *p12cxt = arg;
+ int writeLen;
+
+ if(!p12cxt || (p12cxt->error == PR_TRUE)) {
+ return;
+ }
+
+ if(p12cxt->file == NULL) {
+ p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
+ p12cxt->error = PR_TRUE;
+ return;
+ }
+
+ writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (int32)len);
+
+ if(writeLen != (int)len) {
+ PR_Close(p12cxt->file);
+ PR_Free(p12cxt->filename);
+ p12cxt->filename = NULL;
+ p12cxt->file = NULL;
+ p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE;
+ p12cxt->error = PR_TRUE;
+ }
+}
+
+void
+P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
+ secuPWData *slotPw, secuPWData *p12FilePw)
+{
+ SEC_PKCS12ExportContext *p12ecx = NULL;
+ SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
+ SECItem *pwitem = NULL;
+ p12uContext *p12cxt = NULL;
+ CERTCertList* certlist = NULL;
+ CERTCertListNode* node = NULL;
+ PK11SlotInfo* slot = NULL;
+
+ if (P12U_InitSlot(inSlot, slotPw) != SECSuccess) {
+ SECU_PrintError(progName,"Failed to authenticate to \"%s\"",
+ PK11_GetSlotName(inSlot));
+ pk12uErrno = PK12UERR_PK11GETSLOT;
+ goto loser;
+ }
+ certlist = PK11_FindCertsFromNickname(nn, slotPw);
+ if(!certlist) {
+ SECU_PrintError(progName,"find user certs from nickname failed");
+ pk12uErrno = PK12UERR_FINDCERTBYNN;
+ return;
+ }
+
+ if ((SECSuccess != CERT_FilterCertListForUserCerts(certlist)) ||
+ CERT_LIST_EMPTY(certlist)) {
+ SECU_PrintError(progName,"no user certs from given nickname");
+ pk12uErrno = PK12UERR_FINDCERTBYNN;
+ goto loser;
+ }
+
+ /* Password to use for PKCS12 file. */
+ pwitem = P12U_GetP12FilePassword(PR_TRUE, p12FilePw);
+ if(!pwitem) {
+ goto loser;
+ }
+
+ p12cxt = p12u_InitFile(PR_FALSE, outfile);
+ if(!p12cxt) {
+ SECU_PrintError(progName,"Initialization failed: %s", outfile);
+ pk12uErrno = PK12UERR_INIT_FILE;
+ goto loser;
+ }
+
+ if (certlist) {
+ CERTCertificate* cert = NULL;
+ node = CERT_LIST_HEAD(certlist);
+ if (node) {
+ cert = node->cert;
+ }
+ if (cert) {
+ slot = cert->slot; /* use the slot from the first matching
+ certificate to create the context . This is for keygen */
+ }
+ }
+ if (!slot) {
+ SECU_PrintError(progName,"cert does not have a slot");
+ pk12uErrno = PK12UERR_FINDCERTBYNN;
+ goto loser;
+ }
+ p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, slotPw);
+ if(!p12ecx) {
+ SECU_PrintError(progName,"export context creation failed");
+ pk12uErrno = PK12UERR_EXPORTCXCREATE;
+ goto loser;
+ }
+
+ if(SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, SEC_OID_SHA1)
+ != SECSuccess) {
+ SECU_PrintError(progName,"PKCS12 add password integrity failed");
+ pk12uErrno = PK12UERR_PK12ADDPWDINTEG;
+ goto loser;
+ }
+
+ for (node = CERT_LIST_HEAD(certlist);!CERT_LIST_END(node,certlist);node=CERT_LIST_NEXT(node))
+ {
+ CERTCertificate* cert = node->cert;
+ if (!cert->slot) {
+ SECU_PrintError(progName,"cert does not have a slot");
+ pk12uErrno = PK12UERR_FINDCERTBYNN;
+ goto loser;
+ }
+
+ keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
+ if(/*!SEC_PKCS12IsEncryptionAllowed() || */ PK11_IsFIPS()) {
+ certSafe = keySafe;
+ } else {
+ certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
+ }
+
+ if(!certSafe || !keySafe) {
+ SECU_PrintError(progName,"key or cert safe creation failed");
+ pk12uErrno = PK12UERR_CERTKEYSAFE;
+ goto loser;
+ }
+
+ if(SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
+ CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
+ != SECSuccess) {
+ SECU_PrintError(progName,"add cert and key failed");
+ pk12uErrno = PK12UERR_ADDCERTKEY;
+ goto loser;
+ }
+ }
+
+ CERT_DestroyCertList(certlist);
+ certlist = NULL;
+
+ if(SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12cxt)
+ != SECSuccess) {
+ SECU_PrintError(progName,"PKCS12 encode failed");
+ pk12uErrno = PK12UERR_ENCODE;
+ goto loser;
+ }
+
+ p12u_DestroyExportFileInfo(&p12cxt, PR_FALSE);
+ SECITEM_ZfreeItem(pwitem, PR_TRUE);
+ fprintf(stdout, "%s: PKCS12 EXPORT SUCCESSFUL\n", progName);
+ SEC_PKCS12DestroyExportContext(p12ecx);
+
+ return;
+
+loser:
+ SEC_PKCS12DestroyExportContext(p12ecx);
+
+ if (certlist) {
+ CERT_DestroyCertList(certlist);
+ certlist = NULL;
+ }
+
+ if (slotPw)
+ PR_Free(slotPw->data);
+
+ if (p12FilePw)
+ PR_Free(p12FilePw->data);
+
+ p12u_DestroyExportFileInfo(&p12cxt, PR_TRUE);
+ if(pwitem) {
+ SECITEM_ZfreeItem(pwitem, PR_TRUE);
+ }
+ p12u_DoPKCS12ExportErrors();
+ return;
+}
+
+static void
+p12u_EnableAllCiphers()
+{
+ SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
+ SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
+ SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
+ SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
+ SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
+ SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
+ SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
+}
+
+static PRUintn
+P12U_Init(char *dir, char *dbprefix)
+{
+ SECStatus rv;
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_Initialize(dir,dbprefix,dbprefix,"secmod.db",0);
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ exit(-1);
+ }
+
+ /* setup unicode callback functions */
+ PORT_SetUCS2_ASCIIConversionFunction(p12u_ucs2_ascii_conversion_function);
+ /* use the defaults for UCS4-UTF8 and UCS2-UTF8 */
+
+ p12u_EnableAllCiphers();
+
+ return 0;
+}
+
+enum {
+ opt_CertDir = 0,
+ opt_TokenName,
+ opt_Import,
+ opt_SlotPWFile,
+ opt_SlotPW,
+ opt_Nickname,
+ opt_Export,
+ opt_P12FilePWFile,
+ opt_P12FilePW,
+ opt_DBPrefix,
+ opt_Debug
+};
+
+static secuCommandFlag pk12util_options[] =
+{
+ { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Import */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SlotPWFile */ 'k', PR_TRUE, 0, PR_FALSE },
+ { /* opt_SlotPW */ 'K', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Export */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_P12FilePWFile */ 'w', PR_TRUE, 0, PR_FALSE },
+ { /* opt_P12FilePW */ 'W', PR_TRUE, 0, PR_FALSE },
+ { /* opt_DBPrefix */ 'P', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Debug */ 'v', PR_FALSE, 0, PR_FALSE }
+};
+
+int
+main(int argc, char **argv)
+{
+ PRIntn ret = 0;
+ secuPWData slotPw = { PW_NONE, NULL };
+ secuPWData p12FilePw = { PW_NONE, NULL };
+ PK11SlotInfo *slot;
+ char *slotname = NULL;
+ char *import_file = NULL;
+ char *export_file = NULL;
+ char *dbprefix = "";
+ SECStatus rv;
+
+ secuCommand pk12util;
+ pk12util.numCommands = 0;
+ pk12util.commands = 0;
+ pk12util.numOptions = sizeof(pk12util_options) / sizeof(secuCommandFlag);
+ pk12util.options = pk12util_options;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &pk12util);
+
+ if (rv != SECSuccess)
+ Usage(progName);
+
+ pk12_debugging = pk12util.options[opt_Debug].activated;
+
+ if (pk12util.options[opt_Import].activated &&
+ pk12util.options[opt_Export].activated) {
+ Usage(progName);
+ }
+
+ if (pk12util.options[opt_Export].activated &&
+ !pk12util.options[opt_Nickname].activated) {
+ Usage(progName);
+ }
+
+ slotname = SECU_GetOptionArg(&pk12util, opt_TokenName);
+ import_file = SECU_GetOptionArg(&pk12util, opt_Import);
+ export_file = SECU_GetOptionArg(&pk12util, opt_Export);
+
+ if (pk12util.options[opt_P12FilePWFile].activated) {
+ p12FilePw.source = PW_FROMFILE;
+ p12FilePw.data = PL_strdup(pk12util.options[opt_P12FilePWFile].arg);
+ }
+
+ if (pk12util.options[opt_P12FilePW].activated) {
+ p12FilePw.source = PW_PLAINTEXT;
+ p12FilePw.data = PL_strdup(pk12util.options[opt_P12FilePW].arg);
+ }
+
+ if (pk12util.options[opt_SlotPWFile].activated) {
+ slotPw.source = PW_FROMFILE;
+ slotPw.data = PL_strdup(pk12util.options[opt_SlotPWFile].arg);
+ }
+
+ if (pk12util.options[opt_SlotPW].activated) {
+ slotPw.source = PW_PLAINTEXT;
+ slotPw.data = PL_strdup(pk12util.options[opt_SlotPW].arg);
+ }
+
+ if (pk12util.options[opt_CertDir].activated) {
+ SECU_ConfigDirectory(pk12util.options[opt_CertDir].arg);
+ }
+ if (pk12util.options[opt_DBPrefix].activated) {
+ dbprefix = pk12util.options[opt_DBPrefix].arg;
+ }
+ P12U_Init(SECU_ConfigDirectory(NULL),dbprefix);
+
+ if (!slotname || PL_strcmp(slotname, "internal") == 0)
+ slot = PK11_GetInternalKeySlot();
+ else
+ slot = PK11_FindSlotByName(slotname);
+
+ if (!slot) {
+ SECU_PrintError(progName,"Invalid slot \"%s\"", slotname);
+ pk12uErrno = PK12UERR_PK11GETSLOT;
+ goto done;
+ }
+
+ if (pk12util.options[opt_Import].activated) {
+
+ if ((ret = P12U_ImportPKCS12Object(import_file, slot, &slotPw,
+ &p12FilePw)) != 0)
+ goto done;
+
+ } else if (pk12util.options[opt_Export].activated) {
+ P12U_ExportPKCS12Object(pk12util.options[opt_Nickname].arg,
+ export_file, slot, &slotPw, &p12FilePw);
+ } else {
+ Usage(progName);
+ pk12uErrno = PK12UERR_USAGE;
+ }
+
+done:
+ if (slot) PK11_FreeSlot(slot);
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ exit(pk12uErrno);
+}
diff --git a/security/nss/cmd/pk12util/pk12util.h b/security/nss/cmd/pk12util/pk12util.h
new file mode 100644
index 000000000..8e456d98c
--- /dev/null
+++ b/security/nss/cmd/pk12util/pk12util.h
@@ -0,0 +1,69 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * ERROR codes in pk12util
+ * - should be organized better later
+ */
+#define PK12UERR_USER_CANCELLED 1
+#define PK12UERR_USAGE 2
+#define PK12UERR_CERTDB_OPEN 8
+#define PK12UERR_KEYDB_OPEN 9
+#define PK12UERR_INIT_FILE 10
+#define PK12UERR_UNICODECONV 11
+#define PK12UERR_TMPDIGCREATE 12
+#define PK12UERR_PK11GETSLOT 13
+#define PK12UERR_PK12DECODESTART 14
+#define PK12UERR_IMPORTFILEREAD 15
+#define PK12UERR_DECODE 16
+#define PK12UERR_DECODEVERIFY 17
+#define PK12UERR_DECODEVALIBAGS 18
+#define PK12UERR_DECODEIMPTBAGS 19
+#define PK12UERR_CERTALREADYEXISTS 20
+#define PK12UERR_PATCHDB 22
+#define PK12UERR_GETDEFCERTDB 23
+#define PK12UERR_FINDCERTBYNN 24
+#define PK12UERR_EXPORTCXCREATE 25
+#define PK12UERR_PK12ADDPWDINTEG 26
+#define PK12UERR_CERTKEYSAFE 27
+#define PK12UERR_ADDCERTKEY 28
+#define PK12UERR_ENCODE 29
+
+
+/* additions for importing and exporting PKCS 12 files */
+typedef struct p12uContextStr {
+ char *filename; /* name of file */
+ PRFileDesc *file; /* pointer to file */
+ PRBool error; /* error occurred? */
+ int errorValue; /* which error occurred? */
+} p12uContext;
diff --git a/security/nss/cmd/pkiutil/Makefile b/security/nss/cmd/pkiutil/Makefile
new file mode 100644
index 000000000..23afa3799
--- /dev/null
+++ b/security/nss/cmd/pkiutil/Makefile
@@ -0,0 +1,76 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/pkiutil/manifest.mn b/security/nss/cmd/pkiutil/manifest.mn
new file mode 100644
index 000000000..3f65c29ab
--- /dev/null
+++ b/security/nss/cmd/pkiutil/manifest.mn
@@ -0,0 +1,47 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ pkiutil.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = dbm seccmd
+
+PROGRAM = pkiutil
diff --git a/security/nss/cmd/pkiutil/pkiutil.c b/security/nss/cmd/pkiutil/pkiutil.c
new file mode 100644
index 000000000..f922debab
--- /dev/null
+++ b/security/nss/cmd/pkiutil/pkiutil.c
@@ -0,0 +1,373 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+#include "nss.h"
+#include "cmdutil.h"
+#include "nsspki.h"
+/* hmmm...*/
+#include "pki.h"
+
+#define PKIUTIL_VERSION_STRING "pkiutil version 0.1"
+
+char *progName = NULL;
+
+typedef struct {
+ PRBool raw;
+ PRBool ascii;
+ char *name;
+ PRFileDesc *file;
+} objOutputMode;
+
+typedef enum {
+ PKIUnknown = -1,
+ PKICertificate,
+ PKIPublicKey,
+ PKIPrivateKey,
+ PKIAny
+} PKIObjectType;
+
+static PKIObjectType
+get_object_class(char *type)
+{
+ if (strcmp(type, "certificate") == 0 || strcmp(type, "cert") == 0 ||
+ strcmp(type, "Certificate") == 0 || strcmp(type, "Cert") == 0) {
+ return PKICertificate;
+ } else if (strcmp(type, "public_key") == 0 ||
+ strcmp(type, "PublicKey") == 0) {
+ return PKIPublicKey;
+ } else if (strcmp(type, "private_key") == 0 ||
+ strcmp(type, "PrivateKey") == 0) {
+ return PKIPrivateKey;
+ } else if (strcmp(type, "all") == 0 || strcmp(type, "any") == 0) {
+ return PKIAny;
+ }
+ fprintf(stderr, "%s: \"%s\" is not a valid PKCS#11 object type.\n",
+ progName, type);
+ return PKIUnknown;
+}
+
+static PRStatus
+print_cert_callback(NSSCertificate *c, void *arg)
+{
+ int i;
+ NSSUTF8 *label;
+ NSSItem *id;
+ label = NSSCertificate_GetLabel(c);
+ printf("%s\n", label);
+ nss_ZFreeIf((void*)label);
+#if 0
+ id = NSSCertificate_GetID(c);
+ for (i=0; i<id->size; i++) {
+ printf("%c", ((char *)id->data)[i]);
+ }
+ printf("\n");
+#endif
+ return PR_SUCCESS;
+}
+
+/* pkiutil commands */
+enum {
+ cmd_Add = 0,
+ cmd_Dump,
+ cmd_List,
+ cmd_Version,
+ pkiutil_num_commands
+};
+
+/* pkiutil options */
+enum {
+ opt_Help = 0,
+ opt_Ascii,
+ opt_ProfileDir,
+ opt_TokenName,
+ opt_InputFile,
+ opt_Nickname,
+ opt_OutputFile,
+ opt_Binary,
+ opt_Trust,
+ opt_Type,
+ pkiutil_num_options
+};
+
+static cmdCommandLineArg pkiutil_commands[] =
+{
+ { /* cmd_Add */ 'A', "add", CMDNoArg, 0, PR_FALSE,
+ CMDBIT(opt_Nickname) | CMDBIT(opt_Trust),
+ CMDBIT(opt_Ascii) | CMDBIT(opt_ProfileDir)
+ | CMDBIT(opt_TokenName) | CMDBIT(opt_InputFile)
+ | CMDBIT(opt_Binary) | CMDBIT(opt_Type) },
+ { /* cmd_Dump */ 0 , "dump", CMDNoArg, 0, PR_FALSE,
+ CMDBIT(opt_Nickname),
+ CMDBIT(opt_Ascii) | CMDBIT(opt_ProfileDir)
+ | CMDBIT(opt_TokenName) | CMDBIT(opt_Binary)
+ | CMDBIT(opt_Type) },
+ { /* cmd_List */ 'L', "list", CMDNoArg, 0, PR_FALSE, 0,
+ CMDBIT(opt_Ascii) | CMDBIT(opt_ProfileDir)
+ | CMDBIT(opt_TokenName) | CMDBIT(opt_Binary)
+ | CMDBIT(opt_Nickname) | CMDBIT(opt_Type) },
+ { /* cmd_Version */ 'Y', "version", CMDNoArg, 0, PR_FALSE, 0, 0 }
+};
+
+static cmdCommandLineOpt pkiutil_options[] =
+{
+ { /* opt_Help */ '?', "help", CMDNoArg, 0, PR_FALSE },
+ { /* opt_Ascii */ 'a', "ascii", CMDNoArg, 0, PR_FALSE },
+ { /* opt_ProfileDir */ 'd', "dbdir", CMDArgReq, 0, PR_FALSE },
+ { /* opt_TokenName */ 'h', "token", CMDArgReq, 0, PR_FALSE },
+ { /* opt_InputFile */ 'i', "infile", CMDArgReq, 0, PR_FALSE },
+ { /* opt_Nickname */ 'n', "nickname", CMDArgReq, 0, PR_FALSE },
+ { /* opt_OutputFile */ 'o', "outfile", CMDArgReq, 0, PR_FALSE },
+ { /* opt_Binary */ 'r', "raw", CMDNoArg, 0, PR_FALSE },
+ { /* opt_Trust */ 't', "trust", CMDArgReq, 0, PR_FALSE },
+ { /* opt_Type */ 0 , "type", CMDArgReq, 0, PR_FALSE }
+};
+
+void pkiutil_usage(cmdPrintState *ps,
+ int num, PRBool cmd, PRBool header, PRBool footer)
+{
+#define pusg CMD_PrintUsageString
+ if (header) {
+ pusg(ps, "utility for managing PKCS#11 objects (certs and keys)\n");
+ } else if (footer) {
+ /*
+ printf("certificate trust can be:\n");
+ printf(" p - valid peer, P - trusted peer (implies p)\n");
+ printf(" c - valid CA\n");
+ printf(" T - trusted CA to issue client certs (implies c)\n");
+ printf(" C - trusted CA to issue server certs (implies c)\n");
+ printf(" u - user cert\n");
+ printf(" w - send warning\n");
+ */
+ } else if (cmd) {
+ switch(num) {
+ case cmd_Add:
+ pusg(ps, "Add an object to the token"); break;
+ case cmd_Dump:
+ pusg(ps, "Dump a single object"); break;
+ case cmd_List:
+ pusg(ps, "List objects on the token (-n for single object)"); break;
+ case cmd_Version:
+ pusg(ps, "Report version"); break;
+ default:
+ pusg(ps, "Unrecognized command"); break;
+ }
+ } else {
+ switch(num) {
+ case opt_Ascii:
+ pusg(ps, "Use ascii (base-64 encoded) mode for I/O"); break;
+ case opt_ProfileDir:
+ pusg(ps, "Directory containing security databases (def: \".\")");
+ break;
+ case opt_TokenName:
+ pusg(ps, "Name of PKCS#11 token to use (def: internal)"); break;
+ case opt_InputFile:
+ pusg(ps, "File for input (def: stdin)"); break;
+ case opt_Nickname:
+ pusg(ps, "Nickname of object"); break;
+ case opt_OutputFile:
+ pusg(ps, "File for output (def: stdout)"); break;
+ case opt_Binary:
+ pusg(ps, "Use raw (binary der-encoded) mode for I/O"); break;
+ case opt_Trust:
+ pusg(ps, "Trust level for certificate"); break;
+ case opt_Help: break;
+ default:
+ pusg(ps, "Unrecognized option");
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ PRFileDesc *infile = NULL;
+ PRFileDesc *outfile = NULL;
+ char *profiledir = "./";
+#if 0
+ secuPWData pwdata = { PW_NONE, 0 };
+#endif
+ int objclass = 3; /* ANY */
+ NSSTrustDomain *root_cert_td = NULL;
+ char *rootpath = NULL;
+ char builtin_name[]= "libnssckbi.so"; /* temporary hardcode */
+ PRStatus rv = PR_SUCCESS;
+
+ int cmdToRun;
+ cmdCommand pkiutil;
+ pkiutil.ncmd = pkiutil_num_commands;
+ pkiutil.nopt = pkiutil_num_options;
+ pkiutil.cmd = pkiutil_commands;
+ pkiutil.opt = pkiutil_options;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ cmdToRun = CMD_ParseCommandLine(argc, argv, progName, &pkiutil);
+
+#if 0
+ { int i, nc;
+ for (i=0; i<pkiutil.ncmd; i++)
+ printf("%s: %s <%s>\n", pkiutil.cmd[i].s,
+ (pkiutil.cmd[i].on) ? "on" : "off",
+ pkiutil.cmd[i].arg);
+ for (i=0; i<pkiutil.nopt; i++)
+ printf("%s: %s <%s>\n", pkiutil.opt[i].s,
+ (pkiutil.opt[i].on) ? "on" : "off",
+ pkiutil.opt[i].arg);
+ }
+#endif
+
+ if (pkiutil.opt[opt_Help].on)
+ CMD_LongUsage(progName, &pkiutil, pkiutil_usage);
+
+ if (cmdToRun < 0)
+ CMD_Usage(progName, &pkiutil);
+
+ /* -d */
+ if (pkiutil.opt[opt_ProfileDir].on) {
+ profiledir = strdup(pkiutil.opt[opt_ProfileDir].arg);
+ }
+
+ /* -i */
+ if (pkiutil.opt[opt_InputFile].on) {
+ char *fn = pkiutil.opt[opt_InputFile].arg;
+ infile = PR_Open(fn, PR_RDONLY, 0660);
+ } else {
+ infile = PR_STDIN;
+ }
+
+ /* -o */
+ if (pkiutil.opt[opt_OutputFile].on) {
+ char *fn = pkiutil.opt[opt_OutputFile].arg;
+ outfile = PR_Open(fn, PR_WRONLY | PR_CREATE_FILE, 0660);
+ } else {
+ outfile = PR_STDOUT;
+ }
+
+ /* --type can be found on many options */
+ if (pkiutil.opt[opt_Type].on)
+ objclass = get_object_class(pkiutil.opt[opt_Type].arg);
+ else if (cmdToRun == cmd_Dump && pkiutil.cmd[cmd_Dump].arg)
+ objclass = get_object_class(pkiutil.cmd[cmd_Dump].arg);
+ else if (cmdToRun == cmd_List && pkiutil.cmd[cmd_List].arg)
+ objclass = get_object_class(pkiutil.cmd[cmd_List].arg);
+ else if (cmdToRun == cmd_Add && pkiutil.cmd[cmd_Add].arg)
+ objclass = get_object_class(pkiutil.cmd[cmd_Add].arg);
+ if (objclass < 0)
+ goto done;
+
+ /* --print is an alias for --list --nickname */
+ if (cmdToRun == cmd_Dump) cmdToRun = cmd_List;
+
+ /* if list has raw | ascii must have -n. can't have both raw and ascii */
+ if (pkiutil.opt[opt_Binary].on || pkiutil.opt[opt_Ascii].on) {
+ if (cmdToRun == cmd_List && !pkiutil.opt[opt_Nickname].on) {
+ fprintf(stderr, "%s: specify a object to output with -n\n",
+ progName);
+ CMD_LongUsage(progName, &pkiutil, pkiutil_usage);
+ }
+ }
+
+ /* initialize */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ /* NSS_InitReadWrite(profiledir); */
+ NSS_NoDB_Init(NULL);
+
+ /* Display version info and exit */
+ if (cmdToRun == cmd_Version) {
+ printf("%s\nNSS Version %s\n", PKIUTIL_VERSION_STRING, NSS_VERSION);
+ goto done;
+ }
+
+ /* XXX okay - bootstrap stan by loading the root cert module for testing */
+ root_cert_td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL);
+ {
+ int rootpathlen = strlen(profiledir) + strlen(builtin_name) + 1;
+ rootpath = (char *)malloc(rootpathlen);
+ memcpy(rootpath, profiledir, strlen(profiledir));
+ memcpy(rootpath + strlen(profiledir),
+ builtin_name, strlen(builtin_name));
+ rootpath[rootpathlen - 1] = '\0';
+ }
+ NSSTrustDomain_LoadModule(root_cert_td, "Builtin Root Module", rootpath,
+ NULL, NULL);
+
+ printf("\n");
+ if (pkiutil.opt[opt_Nickname].on) {
+ int i;
+ NSSCertificate **certs;
+ NSSCertificate *cert;
+ certs = NSSTrustDomain_FindCertificatesByNickname(root_cert_td,
+ pkiutil.opt[opt_Nickname].arg, NULL, 0, NULL);
+ i = 0;
+ while ((cert = certs[i++]) != NULL) {
+ printf("Found cert:\n");
+ print_cert_callback(cert, NULL);
+ }
+ } else {
+ NSSTrustDomain_TraverseCertificates(root_cert_td, print_cert_callback, 0);
+ }
+
+ NSSTrustDomain_Destroy(root_cert_td);
+
+ /* List token objects */
+ if (cmdToRun == cmd_List) {
+#if 0
+ rv = list_token_objects(slot, objclass,
+ pkiutil.opt[opt_Nickname].arg,
+ pkiutil.opt[opt_Binary].on,
+ pkiutil.opt[opt_Ascii].on,
+ outfile, &pwdata);
+#endif
+ goto done;
+ }
+
+#if 0
+ /* Import an object into the token. */
+ if (cmdToRun == cmd_Add) {
+ rv = add_object_to_token(slot, object);
+ goto done;
+ }
+#endif
+
+done:
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return rv;
+}
diff --git a/security/nss/cmd/pkiutil/platlibs.mk b/security/nss/cmd/pkiutil/platlibs.mk
new file mode 100644
index 000000000..9a714f300
--- /dev/null
+++ b/security/nss/cmd/pkiutil/platlibs.mk
@@ -0,0 +1,53 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
+EXTRA_LIBS += \
+ $(DIST)/lib/libcmdutil.$(LIB_SUFFIX) \
+ $(NULL)
+
+ifeq ($(OS_ARCH), AIX)
+EXTRA_SHARED_LIBS += -brtl
+endif
+
+# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
+# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib/ \
+ -lnsspki3 \
+ -lnss3 \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+
diff --git a/security/nss/cmd/platlibs.mk b/security/nss/cmd/platlibs.mk
new file mode 100644
index 000000000..a160c3176
--- /dev/null
+++ b/security/nss/cmd/platlibs.mk
@@ -0,0 +1,219 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+
+ifdef USE_STATIC_LIBS
+
+# can't do this in manifest.mn because OS_ARCH isn't defined there.
+ifeq ($(OS_ARCH), WINNT)
+
+DEFINES += -DNSS_USE_STATIC_LIBS
+# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
+CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
+ifdef MOZILLA_SECURITY_BUILD
+ CRYPTOLIB=$(DIST)/lib/crypto.lib
+endif
+ifdef MOZILLA_BSAFE_BUILD
+ CRYPTOLIB+=$(DIST)/lib/bsafe$(BSAFEVER).lib
+ CRYPTOLIB+=$(DIST)/lib/freebl.lib
+endif
+
+EXTRA_LIBS += \
+ $(DIST)/lib/$(LIB_PREFIX)smime.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)ssl.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nss.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)ssl.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)sectool.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkcs12.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkcs7.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)certhi.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)cryptohi.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pk11wrap.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)certdb.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)softokn.$(LIB_SUFFIX) \
+ $(CRYPTOLIB) \
+ $(DIST)/lib/$(LIB_PREFIX)swfci.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nsspki.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nssdev.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nssb.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)dbm.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.$(LIB_SUFFIX) \
+ $(NULL)
+
+# $(PROGRAM) has NO explicit dependencies on $(OS_LIBS)
+#OS_LIBS += \
+ wsock32.lib \
+ winmm.lib \
+ $(NULL)
+
+JAR_LIBS = $(DIST)/lib/$(LIB_PREFIX)jar.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)zlib.$(LIB_SUFFIX) \
+ $(NULL)
+else
+
+# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
+CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
+ifdef MOZILLA_SECURITY_BUILD
+ CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)crypto.$(LIB_SUFFIX)
+endif
+ifdef MOZILLA_BSAFE_BUILD
+ CRYPTOLIB+=$(DIST)/lib/$(LIB_PREFIX)bsafe.$(LIB_SUFFIX)
+ CRYPTOLIB+=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX)
+endif
+EXTRA_LIBS += \
+ $(DIST)/lib/$(LIB_PREFIX)smime.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)ssl.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nss.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)ssl.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)sectool.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkcs12.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pkcs7.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)certhi.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pk11wrap.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)cryptohi.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)certhi.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nsspki.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)pk11wrap.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)softokn.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)certdb.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nsspki.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nssdev.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nssb.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)swfci.$(LIB_SUFFIX) \
+ $(CRYPTOLIB) \
+ $(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)dbm.$(LIB_SUFFIX) \
+ $(NULL)
+
+ifeq ($(OS_ARCH), AIX)
+EXTRA_SHARED_LIBS += -brtl
+endif
+
+# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
+# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
+ifdef XP_OS2_VACPP
+EXTRA_SHARED_LIBS += \
+ $(DIST)/lib/plc4.lib \
+ $(DIST)/lib/plds4.lib \
+ $(DIST)/lib/nspr4.lib \
+ $(NULL)
+else
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+endif
+endif
+
+JAR_LIBS = $(DIST)/lib/$(LIB_PREFIX)jar.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)zlib.$(LIB_SUFFIX) \
+ $(NULL)
+
+else # USE_STATIC_LIBS
+# can't do this in manifest.mn because OS_ARCH isn't defined there.
+ifeq ($(OS_ARCH), WINNT)
+
+# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
+EXTRA_LIBS += \
+ $(DIST)/lib/$(LIB_PREFIX)sectool.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(IMPORT_LIB_PREFIX)smime3$(IMPORT_LIB_SUFFIX) \
+ $(DIST)/lib/$(IMPORT_LIB_PREFIX)ssl3$(IMPORT_LIB_SUFFIX) \
+ $(DIST)/lib/$(IMPORT_LIB_PREFIX)nss3$(IMPORT_LIB_SUFFIX) \
+ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.$(LIB_SUFFIX) \
+ $(NULL)
+
+# $(PROGRAM) has NO explicit dependencies on $(OS_LIBS)
+#OS_LIBS += \
+ wsock32.lib \
+ winmm.lib \
+ $(NULL)
+
+JAR_LIBS = $(DIST)/lib/$(LIB_PREFIX)jar.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)zlib.$(LIB_SUFFIX) \
+ $(NULL)
+else
+
+# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS)
+EXTRA_LIBS += \
+ $(DIST)/lib/$(LIB_PREFIX)sectool.$(LIB_SUFFIX) \
+ $(NULL)
+
+ifeq ($(OS_ARCH), AIX)
+EXTRA_SHARED_LIBS += -brtl
+endif
+
+# If GNU ld is used, we must use the -rpath-link option to tell
+# the linker where to find libsoftokn3.so, an implicit dependency
+# of libnss3.so.
+ifeq (,$(filter-out BSD_OS FreeBSD Linux NetBSD, $(OS_ARCH)))
+EXTRA_SHARED_LIBS += -Wl,-rpath-link,$(DIST)/lib
+endif
+
+ifeq ($(OS_ARCH), SunOS)
+ifdef NS_USE_GCC
+ifdef GCC_USE_GNU_LD
+EXTRA_SHARED_LIBS += -Wl,-rpath-link,$(DIST)/lib
+endif
+endif
+endif
+
+ifeq ($(OS_ARCH), Darwin)
+EXTRA_SHARED_LIBS += -dylib_file @executable_path/libsoftokn3.dylib:$(DIST)/lib/libsoftokn3.dylib
+endif
+
+
+# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS)
+# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX.
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib \
+ -lssl3 \
+ -lsmime3 \
+ -lnss3 \
+ -lplc4 \
+ -lplds4 \
+ -lnspr4 \
+ $(NULL)
+
+JAR_LIBS = $(DIST)/lib/$(LIB_PREFIX)jar.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)zlib.$(LIB_SUFFIX) \
+ $(NULL)
+endif
+
+endif # USE_STATIC_LIBS
diff --git a/security/nss/cmd/platrules.mk b/security/nss/cmd/platrules.mk
new file mode 100644
index 000000000..3e5c19933
--- /dev/null
+++ b/security/nss/cmd/platrules.mk
@@ -0,0 +1,47 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+show:
+ @echo "DEFINES = ${DEFINES}"
+ @echo "EXTRA_LIBS = >$(EXTRA_LIBS)<"
+ @echo "IMPORT_LIBRARY = $(IMPORT_LIBRARY)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "OBJS = $(OBJS)"
+ @echo "OS_ARCH = $(OS_ARCH)"
+ @echo "PROGRAM = >$(PROGRAM)<"
+ @echo "PROGRAMS = $(PROGRAMS)"
+ @echo "SHARED_LIBRARY = $(SHARED_LIBRARY)"
+ @echo "TARGETS = >$(TARGETS)<"
+
+showplatform:
+ @echo $(PLATFORM)
diff --git a/security/nss/cmd/pp/Makefile b/security/nss/cmd/pp/Makefile
new file mode 100644
index 000000000..4e39ffc3f
--- /dev/null
+++ b/security/nss/cmd/pp/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/pp/manifest.mn b/security/nss/cmd/pp/manifest.mn
new file mode 100644
index 000000000..f43c9c625
--- /dev/null
+++ b/security/nss/cmd/pp/manifest.mn
@@ -0,0 +1,47 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = pp.c
+
+PROGRAM = pp
diff --git a/security/nss/cmd/pp/pp.c b/security/nss/cmd/pp/pp.c
new file mode 100644
index 000000000..157dec0af
--- /dev/null
+++ b/security/nss/cmd/pp/pp.c
@@ -0,0 +1,176 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * Pretty-print some well-known BER or DER encoded data (e.g. certificates,
+ * keys, pkcs7)
+ *
+ * $Id$
+ */
+
+#include "secutil.h"
+
+#if defined(__sun) && !defined(SVR4)
+extern int fprintf(FILE *, char *, ...);
+#endif
+
+#include "plgetopt.h"
+
+#include "pk11func.h"
+#include "nspr.h"
+#include "nss.h"
+
+static void Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s -t type [-a] [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Specify the input type (must be one of %s,\n",
+ "-t type", SEC_CT_PRIVATE_KEY);
+ fprintf(stderr, "%-20s %s, %s, %s,\n", "", SEC_CT_PUBLIC_KEY,
+ SEC_CT_CERTIFICATE, SEC_CT_CERTIFICATE_REQUEST);
+ fprintf(stderr, "%-20s %s or %s)\n", "", SEC_CT_PKCS7, SEC_CT_CRL);
+ fprintf(stderr, "%-20s Input is in ascii encoded form (RFC1113)\n",
+ "-a");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+ int rv, ascii;
+ char *progName;
+ FILE *outFile;
+ PRFileDesc *inFile;
+ SECItem der, data;
+ char *typeTag;
+ PLOptState *optstate;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ ascii = 0;
+ inFile = 0;
+ outFile = 0;
+ typeTag = 0;
+ optstate = PL_CreateOptState(argc, argv, "at:i:o:");
+ while ( PL_GetNextOpt(optstate) == PL_OPT_OK ) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'a':
+ ascii = 1;
+ break;
+
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 't':
+ typeTag = strdup(optstate->value);
+ break;
+ }
+ }
+
+ if (!typeTag) Usage(progName);
+
+ if (!inFile) inFile = PR_STDIN;
+ if (!outFile) outFile = stdout;
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_NoDB_Init(NULL);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: NSS_NoDB_Init failed\n", progName);
+ exit(1);
+ }
+
+ rv = SECU_ReadDERFromFile(&der, inFile, ascii);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: SECU_ReadDERFromFile failed\n", progName);
+ exit(1);
+ }
+
+ /* Data is untyped, using the specified type */
+ data.data = der.data;
+ data.len = der.len;
+
+ /* Pretty print it */
+ if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE) == 0) {
+ rv = SECU_PrintSignedData(outFile, &data, "Certificate", 0,
+ SECU_PrintCertificate);
+ } else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_REQUEST) == 0) {
+ rv = SECU_PrintSignedData(outFile, &data, "Certificate Request", 0,
+ SECU_PrintCertificateRequest);
+ } else if (PORT_Strcmp (typeTag, SEC_CT_CRL) == 0) {
+ rv = SECU_PrintSignedData (outFile, &data, "CRL", 0, SECU_PrintCrl);
+#ifdef HAVE_EPV_TEMPLATE
+ } else if (PORT_Strcmp(typeTag, SEC_CT_PRIVATE_KEY) == 0) {
+ rv = SECU_PrintPrivateKey(outFile, &data, "Private Key", 0);
+#endif
+ } else if (PORT_Strcmp(typeTag, SEC_CT_PUBLIC_KEY) == 0) {
+ rv = SECU_PrintPublicKey(outFile, &data, "Public Key", 0);
+ } else if (PORT_Strcmp(typeTag, SEC_CT_PKCS7) == 0) {
+ rv = SECU_PrintPKCS7ContentInfo(outFile, &data,
+ "PKCS #7 Content Info", 0);
+ } else {
+ fprintf(stderr, "%s: don't know how to print out '%s' files\n",
+ progName, typeTag);
+ return -1;
+ }
+
+ if (rv) {
+ fprintf(stderr, "%s: problem converting data (%s)\n",
+ progName, SECU_Strerror(PORT_GetError()));
+ return -1;
+ }
+ return 0;
+}
diff --git a/security/nss/cmd/rsaperf/Makefile b/security/nss/cmd/rsaperf/Makefile
new file mode 100644
index 000000000..35dc5f5da
--- /dev/null
+++ b/security/nss/cmd/rsaperf/Makefile
@@ -0,0 +1,84 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1998-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include ../platlibs.mk
+
+ifeq (,$(filter-out WINNT WIN95 WIN16,$(OS_TARGET))) #omits WINCE
+ifndef BUILD_OPT
+ifndef NS_USE_GCC
+LDFLAGS += /subsystem:console /profile /debug /machine:I386 /incremental:no
+endif
+OS_CFLAGS += -D_CONSOLE
+endif
+endif
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/rsaperf/defkey.c b/security/nss/cmd/rsaperf/defkey.c
new file mode 100644
index 000000000..3dd4fe36c
--- /dev/null
+++ b/security/nss/cmd/rsaperf/defkey.c
@@ -0,0 +1,202 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/* This key is the 1024-bit test key used for speed testing of RSA private
+** key ops.
+*/
+#include "seccomon.h"
+#include "secoidt.h"
+#include "lowkeyti.h"
+
+#undef CONST
+#define CONST
+
+static CONST unsigned char default_n[128] = {
+0xc2,0xae,0x96,0x89,0xaf,0xce,0xd0,0x7b,0x3b,0x35,0xfd,0x0f,0xb1,0xf4,0x7a,0xd1,
+0x3c,0x7d,0xb5,0x86,0xf2,0x68,0x36,0xc9,0x97,0xe6,0x82,0x94,0x86,0xaa,0x05,0x39,
+0xec,0x11,0x51,0xcc,0x5c,0xa1,0x59,0xba,0x29,0x18,0xf3,0x28,0xf1,0x9d,0xe3,0xae,
+0x96,0x5d,0x6d,0x87,0x73,0xf6,0xf6,0x1f,0xd0,0x2d,0xfb,0x2f,0x7a,0x13,0x7f,0xc8,
+0x0c,0x7a,0xe9,0x85,0xfb,0xce,0x74,0x86,0xf8,0xef,0x2f,0x85,0x37,0x73,0x0f,0x62,
+0x4e,0x93,0x17,0xb7,0x7e,0x84,0x9a,0x94,0x11,0x05,0xca,0x0d,0x31,0x4b,0x2a,0xc8,
+0xdf,0xfe,0xe9,0x0c,0x13,0xc7,0xf2,0xad,0x19,0x64,0x28,0x3c,0xb5,0x6a,0xc8,0x4b,
+0x79,0xea,0x7c,0xce,0x75,0x92,0x45,0x3e,0xa3,0x9d,0x64,0x6f,0x04,0x69,0x19,0x17
+};
+
+static CONST unsigned char default_e[3] = { 0x01,0x00,0x01 };
+
+static CONST unsigned char default_d[128] = {
+0x13,0xcb,0xbc,0xf2,0xf3,0x35,0x8c,0x6d,0x7b,0x6f,0xd9,0xf3,0xa6,0x9c,0xbd,0x80,
+0x59,0x2e,0x4f,0x2f,0x11,0xa7,0x17,0x2b,0x18,0x8f,0x0f,0xe8,0x1a,0x69,0x5f,0x6e,
+0xac,0x5a,0x76,0x7e,0xd9,0x4c,0x6e,0xdb,0x47,0x22,0x8a,0x57,0x37,0x7a,0x5e,0x94,
+0x7a,0x25,0xb5,0xe5,0x78,0x1d,0x3c,0x99,0xaf,0x89,0x7d,0x69,0x2e,0x78,0x9d,0x1d,
+0x84,0xc8,0xc1,0xd7,0x1a,0xb2,0x6d,0x2d,0x8a,0xd9,0xab,0x6b,0xce,0xae,0xb0,0xa0,
+0x58,0x55,0xad,0x5c,0x40,0x8a,0xd6,0x96,0x08,0x8a,0xe8,0x63,0xe6,0x3d,0x6c,0x20,
+0x49,0xc7,0xaf,0x0f,0x25,0x73,0xd3,0x69,0x43,0x3b,0xf2,0x32,0xf8,0x3d,0x5e,0xee,
+0x7a,0xca,0xd6,0x94,0x55,0xe5,0xbd,0x25,0x34,0x8d,0x63,0x40,0xb5,0x8a,0xc3,0x01
+};
+
+static CONST unsigned char default_p[64] = {
+0xf6,0x3c,0x3f,0x56,0x58,0x4f,0xb3,0x82,0x0c,0xf0,0x5b,0x42,0x36,0x1c,0x93,0xde,
+0x9b,0x32,0x01,0xb1,0x48,0xf8,0x00,0x57,0x9b,0xc1,0xbe,0x66,0xc2,0xbb,0xea,0x7c,
+0x75,0x29,0x2c,0x22,0xaa,0x7c,0xaf,0xbd,0x0d,0x3f,0xb0,0x64,0x97,0xf0,0x88,0x25,
+0xcb,0x8d,0xc7,0x19,0x0a,0x75,0x44,0xa4,0x5a,0xc3,0xb5,0xb9,0x85,0xea,0x27,0xa7
+};
+
+static CONST unsigned char default_q[64] = {
+0xca,0x66,0xfa,0x18,0x6a,0x46,0x36,0x1c,0x46,0xfe,0x47,0xe9,0x7e,0x52,0x83,0x8a,
+0xbb,0x72,0x13,0xcc,0x83,0x56,0x3d,0x64,0x22,0xdd,0xfa,0x7c,0x61,0x99,0xea,0xa4,
+0xb3,0x0e,0x8f,0x79,0x10,0xab,0xba,0x4a,0x73,0xd1,0x48,0x40,0x34,0x34,0xd3,0xd2,
+0x54,0x92,0xbe,0xf5,0xc8,0xc4,0x60,0x5f,0xd3,0xf7,0xce,0xbe,0x60,0x3e,0xb1,0x11
+};
+
+static CONST unsigned char default_dModP[64] = {
+0x8e,0x80,0xbf,0x87,0x11,0x04,0xcf,0x36,0x6c,0x96,0x8d,0xb9,0xfb,0xe6,0xfe,0x0c,
+0xce,0x74,0x5a,0x56,0x67,0x8c,0x5f,0x66,0x54,0x56,0x04,0x03,0x24,0x9f,0xec,0x4c,
+0xaa,0xe1,0x71,0x11,0x7e,0xe9,0x3a,0x2b,0x87,0x07,0x5c,0xe6,0x5a,0xa8,0x71,0xa2,
+0xad,0xf3,0x17,0x4e,0x7e,0xa6,0xef,0x5a,0xce,0xcc,0x84,0xd7,0x21,0x91,0x29,0xf1
+};
+
+static CONST unsigned char default_dModQ[64] = {
+0x87,0x60,0x1d,0x02,0xdb,0x82,0x1e,0x8b,0x07,0x48,0xe8,0x5c,0x59,0xeb,0x62,0xa4,
+0x15,0xff,0x95,0x12,0x82,0xfd,0xd9,0x8d,0xf2,0x6c,0x3a,0x2f,0x9b,0x30,0x51,0x6a,
+0xdb,0x80,0x6f,0xa1,0xef,0xee,0x8c,0x69,0x63,0xd1,0xa4,0xdb,0x9c,0x8f,0x80,0xe5,
+0xfb,0x3f,0x33,0x8e,0x3d,0x3c,0x6b,0xa1,0x6c,0xab,0x20,0x92,0xe0,0xd8,0xcd,0xa1
+};
+
+static CONST unsigned char default_qInvModP[64] = {
+0xce,0xcf,0x5a,0xad,0xc4,0x8c,0x44,0x91,0x3a,0xbc,0x7b,0xf8,0x80,0xf8,0x53,0xf5,
+0x12,0x84,0x8c,0x9c,0x6b,0x33,0x93,0x0d,0xa1,0x11,0xea,0xfa,0x4a,0xc1,0xeb,0x48,
+0xdc,0x44,0x86,0x93,0x1b,0x98,0xc7,0x82,0x22,0x68,0x30,0x44,0xd7,0x62,0x1b,0x90,
+0x54,0x07,0x4b,0x66,0xa7,0xc5,0x75,0x5a,0x72,0x77,0x92,0xdd,0x6c,0xf3,0x37,0xab
+};
+
+
+static struct NSSLOWKEYPrivateKeyStr rsaPriv;
+
+NSSLOWKEYPrivateKey *
+getDefaultRSAPrivateKey(void)
+{
+ if (rsaPriv.keyType != NSSLOWKEYRSAKey) {
+
+ /* leaving arena uninitialized. It isn't used in this test. */
+
+ rsaPriv.keyType = NSSLOWKEYRSAKey;
+
+ /* leaving arena uninitialized. It isn't used. */
+ /* leaving version uninitialized. It isn't used. */
+
+ rsaPriv.u.rsa.modulus.data = default_n;
+ rsaPriv.u.rsa.modulus.len = sizeof default_n;
+ rsaPriv.u.rsa.publicExponent.data = default_e;
+ rsaPriv.u.rsa.publicExponent.len = sizeof default_e;
+ rsaPriv.u.rsa.privateExponent.data = default_d;
+ rsaPriv.u.rsa.privateExponent.len = sizeof default_d;
+ rsaPriv.u.rsa.prime1.data = default_p;
+ rsaPriv.u.rsa.prime1.len = sizeof default_p;
+ rsaPriv.u.rsa.prime2.data = default_q;
+ rsaPriv.u.rsa.prime2.len = sizeof default_q;
+ rsaPriv.u.rsa.exponent1.data = default_dModP;
+ rsaPriv.u.rsa.exponent1.len = sizeof default_dModP;
+ rsaPriv.u.rsa.exponent2.data = default_dModQ;
+ rsaPriv.u.rsa.exponent2.len = sizeof default_dModQ;
+ rsaPriv.u.rsa.coefficient.data = default_qInvModP;
+ rsaPriv.u.rsa.coefficient.len = sizeof default_qInvModP;
+ }
+ return &rsaPriv;
+}
+
+static struct NSSLOWKEYPublicKeyStr rsaPub;
+
+NSSLOWKEYPublicKey *
+getDefaultRSAPublicKey(void)
+{
+ if (rsaPub.keyType != NSSLOWKEYRSAKey) {
+
+ rsaPub.keyType = NSSLOWKEYRSAKey;
+
+ rsaPub.u.rsa.modulus.data = default_n;
+ rsaPub.u.rsa.modulus.len = sizeof default_n;
+
+ rsaPub.u.rsa.publicExponent.data = default_e;
+ rsaPub.u.rsa.publicExponent.len = sizeof default_e;
+ }
+ return &rsaPub;
+}
+
+/* modPop = 536, privPop = 531, ex1Pop = 261, ex2Pop = 257
+ * After 46 tries, found this key:
+ * Version: 0 (0x0)
+ * Modulus:
+ * c2:ae:96:89:af:ce:d0:7b:3b:35:fd:0f:b1:f4:7a:d1:3c:7d:b5:
+ * 86:f2:68:36:c9:97:e6:82:94:86:aa:05:39:ec:11:51:cc:5c:a1:
+ * 59:ba:29:18:f3:28:f1:9d:e3:ae:96:5d:6d:87:73:f6:f6:1f:d0:
+ * 2d:fb:2f:7a:13:7f:c8:0c:7a:e9:85:fb:ce:74:86:f8:ef:2f:85:
+ * 37:73:0f:62:4e:93:17:b7:7e:84:9a:94:11:05:ca:0d:31:4b:2a:
+ * c8:df:fe:e9:0c:13:c7:f2:ad:19:64:28:3c:b5:6a:c8:4b:79:ea:
+ * 7c:ce:75:92:45:3e:a3:9d:64:6f:04:69:19:17
+ * Public Exponent: 65537 (0x10001)
+ * Private Exponent:
+ * 13:cb:bc:f2:f3:35:8c:6d:7b:6f:d9:f3:a6:9c:bd:80:59:2e:4f:
+ * 2f:11:a7:17:2b:18:8f:0f:e8:1a:69:5f:6e:ac:5a:76:7e:d9:4c:
+ * 6e:db:47:22:8a:57:37:7a:5e:94:7a:25:b5:e5:78:1d:3c:99:af:
+ * 89:7d:69:2e:78:9d:1d:84:c8:c1:d7:1a:b2:6d:2d:8a:d9:ab:6b:
+ * ce:ae:b0:a0:58:55:ad:5c:40:8a:d6:96:08:8a:e8:63:e6:3d:6c:
+ * 20:49:c7:af:0f:25:73:d3:69:43:3b:f2:32:f8:3d:5e:ee:7a:ca:
+ * d6:94:55:e5:bd:25:34:8d:63:40:b5:8a:c3:01
+ * Prime 1:
+ * f6:3c:3f:56:58:4f:b3:82:0c:f0:5b:42:36:1c:93:de:9b:32:01:
+ * b1:48:f8:00:57:9b:c1:be:66:c2:bb:ea:7c:75:29:2c:22:aa:7c:
+ * af:bd:0d:3f:b0:64:97:f0:88:25:cb:8d:c7:19:0a:75:44:a4:5a:
+ * c3:b5:b9:85:ea:27:a7
+ * Prime 2:
+ * ca:66:fa:18:6a:46:36:1c:46:fe:47:e9:7e:52:83:8a:bb:72:13:
+ * cc:83:56:3d:64:22:dd:fa:7c:61:99:ea:a4:b3:0e:8f:79:10:ab:
+ * ba:4a:73:d1:48:40:34:34:d3:d2:54:92:be:f5:c8:c4:60:5f:d3:
+ * f7:ce:be:60:3e:b1:11
+ * Exponent 1:
+ * 8e:80:bf:87:11:04:cf:36:6c:96:8d:b9:fb:e6:fe:0c:ce:74:5a:
+ * 56:67:8c:5f:66:54:56:04:03:24:9f:ec:4c:aa:e1:71:11:7e:e9:
+ * 3a:2b:87:07:5c:e6:5a:a8:71:a2:ad:f3:17:4e:7e:a6:ef:5a:ce:
+ * cc:84:d7:21:91:29:f1
+ * Exponent 2:
+ * 87:60:1d:02:db:82:1e:8b:07:48:e8:5c:59:eb:62:a4:15:ff:95:
+ * 12:82:fd:d9:8d:f2:6c:3a:2f:9b:30:51:6a:db:80:6f:a1:ef:ee:
+ * 8c:69:63:d1:a4:db:9c:8f:80:e5:fb:3f:33:8e:3d:3c:6b:a1:6c:
+ * ab:20:92:e0:d8:cd:a1
+ * Coefficient:
+ * ce:cf:5a:ad:c4:8c:44:91:3a:bc:7b:f8:80:f8:53:f5:12:84:8c:
+ * 9c:6b:33:93:0d:a1:11:ea:fa:4a:c1:eb:48:dc:44:86:93:1b:98:
+ * c7:82:22:68:30:44:d7:62:1b:90:54:07:4b:66:a7:c5:75:5a:72:
+ * 77:92:dd:6c:f3:37:ab
+ */
+
diff --git a/security/nss/cmd/rsaperf/manifest.mn b/security/nss/cmd/rsaperf/manifest.mn
new file mode 100644
index 000000000..802a63815
--- /dev/null
+++ b/security/nss/cmd/rsaperf/manifest.mn
@@ -0,0 +1,52 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1998-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+DEPTH = ../../..
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+REQUIRES = dbm seccmd
+
+# DIRS =
+
+CSRCS = rsaperf.c defkey.c
+
+PROGRAM = rsaperf
+
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/rsaperf/rsaperf.c b/security/nss/cmd/rsaperf/rsaperf.c
new file mode 100644
index 000000000..36927e718
--- /dev/null
+++ b/security/nss/cmd/rsaperf/rsaperf.c
@@ -0,0 +1,402 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "seccomon.h"
+#include "cert.h"
+#include "secutil.h"
+#include "nspr.h"
+#include "nss.h"
+#include "blapi.h"
+#include "plgetopt.h"
+#include "lowkeyi.h"
+
+
+#define MAX_RSA_MODULUS_BYTES (1024/8)
+#define DEFAULT_ITERS 10
+
+extern NSSLOWKEYPrivateKey * getDefaultRSAPrivateKey(void);
+extern NSSLOWKEYPublicKey * getDefaultRSAPublicKey(void);
+
+typedef struct TimingContextStr TimingContext;
+
+struct TimingContextStr {
+ int64 start;
+ int64 end;
+ int64 interval;
+
+ long days;
+ int hours;
+ int minutes;
+ int seconds;
+ int millisecs;
+};
+
+TimingContext *CreateTimingContext(void) {
+ return PR_Malloc(sizeof(TimingContext));
+}
+
+void DestroyTimingContext(TimingContext *ctx) {
+ PR_Free(ctx);
+}
+
+void TimingBegin(TimingContext *ctx) {
+ ctx->start = PR_Now();
+}
+
+static void timingUpdate(TimingContext *ctx) {
+ int64 tmp, remaining;
+ int64 L1000,L60,L24;
+
+ LL_I2L(L1000,1000);
+ LL_I2L(L60,60);
+ LL_I2L(L24,24);
+
+ LL_DIV(remaining, ctx->interval, L1000);
+ LL_MOD(tmp, remaining, L1000);
+ LL_L2I(ctx->millisecs, tmp);
+ LL_DIV(remaining, remaining, L1000);
+ LL_MOD(tmp, remaining, L60);
+ LL_L2I(ctx->seconds, tmp);
+ LL_DIV(remaining, remaining, L60);
+ LL_MOD(tmp, remaining, L60);
+ LL_L2I(ctx->minutes, tmp);
+ LL_DIV(remaining, remaining, L60);
+ LL_MOD(tmp, remaining, L24);
+ LL_L2I(ctx->hours, tmp);
+ LL_DIV(remaining, remaining, L24);
+ LL_L2I(ctx->days, remaining);
+}
+
+void TimingEnd(TimingContext *ctx) {
+ ctx->end = PR_Now();
+ LL_SUB(ctx->interval, ctx->end, ctx->start);
+ PORT_Assert(LL_GE_ZERO(ctx->interval));
+ timingUpdate(ctx);
+}
+
+void TimingDivide(TimingContext *ctx, int divisor) {
+ int64 tmp;
+
+ LL_I2L(tmp, divisor);
+ LL_DIV(ctx->interval, ctx->interval, tmp);
+
+ timingUpdate(ctx);
+}
+
+char *TimingGenerateString(TimingContext *ctx) {
+ char *buf = NULL;
+
+ if (ctx->days != 0) {
+ buf = PR_sprintf_append(buf, "%d days", ctx->days);
+ }
+ if (ctx->hours != 0) {
+ if (buf != NULL) buf = PR_sprintf_append(buf, ", ");
+ buf = PR_sprintf_append(buf, "%d hours", ctx->hours);
+ }
+ if (ctx->minutes != 0) {
+ if (buf != NULL) buf = PR_sprintf_append(buf, ", ");
+ buf = PR_sprintf_append(buf, "%d minutes", ctx->minutes);
+ }
+ if (buf != NULL) buf = PR_sprintf_append(buf, ", and ");
+ if (!buf && ctx->seconds == 0) {
+ int interval;
+ LL_L2I(interval, ctx->interval);
+ if (ctx->millisecs < 100)
+ buf = PR_sprintf_append(buf, "%d microseconds", interval);
+ else
+ buf = PR_sprintf_append(buf, "%d milliseconds", ctx->millisecs);
+ } else if (ctx->millisecs == 0) {
+ buf = PR_sprintf_append(buf, "%d seconds", ctx->seconds);
+ } else {
+ buf = PR_sprintf_append(buf, "%d.%03d seconds",
+ ctx->seconds, ctx->millisecs);
+ }
+ return buf;
+}
+
+void
+Usage(char *progName)
+{
+ fprintf(stderr, "Usage: %s [-d certdir] [-i iterations] [-s | -e]"
+ " -n nickname\n",
+ progName);
+ fprintf(stderr, "%-20s Cert database directory (default is ~/.netscape)\n",
+ "-d certdir");
+ fprintf(stderr, "%-20s How many operations to perform\n", "-i iterations");
+ fprintf(stderr, "%-20s Perform signing (private key) operations\n", "-s");
+ fprintf(stderr, "%-20s Perform encryption (public key) operations\n", "-e");
+ fprintf(stderr, "%-20s Nickname of certificate or key\n", "-n nickname");
+ exit(-1);
+}
+
+void
+printCount(int iterations)
+{
+
+}
+
+
+static void
+dumpBytes( unsigned char * b, int l)
+{
+ int i;
+ if (l <= 0)
+ return;
+ for (i = 0; i < l; ++i) {
+ if (i % 16 == 0)
+ printf("\t");
+ printf(" %02x", b[i]);
+ if (i % 16 == 15)
+ printf("\n");
+ }
+ if ((i % 16) != 0)
+ printf("\n");
+}
+
+static void
+dumpItem( SECItem * item, const char * description)
+{
+ if (item->len & 1 && item->data[0] == 0) {
+ printf("%s: (%d bytes)\n", description, item->len - 1);
+ dumpBytes(item->data + 1, item->len - 1);
+ } else {
+ printf("%s: (%d bytes)\n", description, item->len);
+ dumpBytes(item->data, item->len);
+ }
+}
+
+void
+printPrivKey(NSSLOWKEYPrivateKey * privKey)
+{
+ RSAPrivateKey *rsa = &privKey->u.rsa;
+
+ dumpItem( &rsa->modulus, "n");
+ dumpItem( &rsa->publicExponent, "e");
+ dumpItem( &rsa->privateExponent, "d");
+ dumpItem( &rsa->prime1, "P");
+ dumpItem( &rsa->prime2, "Q");
+ dumpItem( &rsa->exponent1, "d % (P-1)");
+ dumpItem( &rsa->exponent2, "d % (Q-1)");
+ dumpItem( &rsa->coefficient, "(Q ** -1) % P");
+ puts("");
+}
+
+void
+printFnCounts(long doPrint)
+{
+
+}
+
+typedef SECStatus (* RSAOp)(void * key,
+ unsigned char * output,
+ unsigned char * input);
+
+
+int
+main(int argc, char **argv)
+{
+ TimingContext * timeCtx;
+ SECKEYPublicKey * pubHighKey;
+ NSSLOWKEYPrivateKey * privKey;
+ NSSLOWKEYPublicKey * pubKey;
+ CERTCertificate * cert;
+ char * progName;
+ char * secDir = NULL;
+ char * nickname = NULL;
+ RSAOp fn;
+ void * rsaKey;
+ PLOptState * optstate;
+ PLOptStatus optstatus;
+ long iters = DEFAULT_ITERS;
+ int i;
+ PRBool doPriv = PR_FALSE;
+ PRBool doPub = PR_FALSE;
+ int rv;
+ CERTCertDBHandle * certdb;
+ unsigned char buf[1024];
+ unsigned char buf2[1024];
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName+1 : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "d:i:sen:");
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+ case 'd':
+ secDir = PORT_Strdup(optstate->value);
+ break;
+ case 'i':
+ iters = atol(optstate->value);
+ break;
+ case 's':
+ doPriv = PR_TRUE;
+ break;
+ case 'e':
+ doPub = PR_TRUE;
+ break;
+ case 'n':
+ nickname = PORT_Strdup(optstate->value);
+ break;
+ }
+ }
+ if (optstatus == PL_OPT_BAD)
+ Usage(progName);
+
+ if ((doPriv && doPub) || (nickname == NULL)) Usage(progName);
+
+ if (!doPriv && !doPub) doPriv = PR_TRUE;
+
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ secDir = SECU_ConfigDirectory(secDir);
+ if (strcmp(nickname, "none")) {
+ rv = NSS_Init(secDir);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "NSS_Init failed.\n");
+ exit(1);
+ }
+ certdb = CERT_GetDefaultCertDB();
+ } else {
+ rv = NSS_NoDB_Init(secDir);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "NSS_NoDB_Init failed.\n");
+ exit(1);
+ }
+ }
+#if defined(SECU_GetPassword)
+ if (doPub) {
+ if (!strcmp(nickname, "none")) {
+ pubKey = getDefaultRSAPublicKey();
+ } else {
+ cert = CERT_FindCertByNickname(certdb, nickname);
+ if (cert == NULL) {
+ fprintf(stderr,
+ "Can't find certificate by name \"%s\"\n", nickname);
+ exit(1);
+ }
+ pubHighKey = CERT_ExtractPublicKey(cert);
+ pubKey = SECU_ConvHighToLow(pubHighKey);
+ }
+ if (pubKey == NULL) {
+ fprintf(stderr, "Can't extract public key from certificate");
+ exit(1);
+ }
+ fn = (RSAOp)RSA_PublicKeyOp;
+ rsaKey = (void *)(&pubKey->u.rsa);
+ }
+
+ if (doPriv) {
+
+ if (!strcmp(nickname, "none")) {
+ privKey = getDefaultRSAPrivateKey();
+ } else {
+ cert = CERT_FindCertByNickname(certdb, nickname);
+ if (cert == NULL) {
+ fprintf(stderr,
+ "Can't find certificate by name \"%s\"\n", nickname);
+ exit(1);
+ }
+
+ privKey = SECKEY_FindKeyByCert(keydb, cert, SECU_GetPassword, NULL);
+ }
+ if (privKey == NULL) {
+ fprintf(stderr,
+ "Can't find private key by name \"%s\"\n", nickname);
+ exit(1);
+ }
+
+ fn = (RSAOp)RSA_PrivateKeyOp;
+ rsaKey = (void *)(&privKey->u.rsa);
+ }
+#else
+ if (doPub) {
+ pubKey = getDefaultRSAPublicKey();
+ fn = (RSAOp)RSA_PublicKeyOp;
+ rsaKey = (void *)(&pubKey->u.rsa);
+ }
+ if (doPriv) {
+ privKey = getDefaultRSAPrivateKey();
+ fn = (RSAOp)RSA_PrivateKeyOp;
+ rsaKey = (void *)(&privKey->u.rsa);
+ }
+#endif
+
+ memset(buf, 1, sizeof buf);
+ rv = fn(rsaKey, buf2, buf);
+ if (rv != SECSuccess) {
+ PRErrorCode errNum;
+ const char * errStr = NULL;
+
+ errNum = PR_GetError();
+ if (errNum)
+ errStr = SECU_Strerror(errNum);
+ else
+ errNum = rv;
+ if (!errStr)
+ errStr = "(null)";
+ fprintf(stderr, "Error in RSA operation: %d : %s\n", errNum, errStr);
+ exit(1);
+ }
+
+/* printf("START\n"); */
+
+ timeCtx = CreateTimingContext();
+ TimingBegin(timeCtx);
+ i = iters;
+ while (i--) {
+ rv = fn(rsaKey, buf2, buf);
+ if (rv != SECSuccess) {
+ PRErrorCode errNum = PR_GetError();
+ const char * errStr = SECU_Strerror(errNum);
+ fprintf(stderr, "Error in RSA operation: %d : %s\n",
+ errNum, errStr);
+ exit(1);
+ }
+ }
+ TimingEnd(timeCtx);
+ printf("%ld iterations in %s\n",
+ iters, TimingGenerateString(timeCtx));
+ TimingDivide(timeCtx, iters);
+ printf("one operation every %s\n", TimingGenerateString(timeCtx));
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/security/nss/cmd/samples/cert b/security/nss/cmd/samples/cert
new file mode 100644
index 000000000..3f8ec48df
--- /dev/null
+++ b/security/nss/cmd/samples/cert
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIIB7TCCAVYCAgMaMA0GCSqGSIb3DQEBBAUAMEcxCzAJBgNVBAYTAlVTMRAwDgYD
+VQQLEwdUZXN0IENBMSYwJAYDVQQKEx1OZXRzY2FwZSBDb21tdW5pY2F0aW9ucyBD
+b3JwLjAeFw05NTEyMDgwMjQwMjdaFw05NjAzMDcwMjQwMjdaMDgxFjAUBgNVBAMT
+DURhdmlkIGthcmx0b24xETAPBgNVBAoTCE5ldHNjYXBlMQswCQYDVQQGEwJVUzCB
+nTANBgkqhkiG9w0BAQEFAAOBiwAwgYcCgYEAltV2TH+QxqlgfUFk+UyiYAjByxrC
+dCSIa/FwRaPceLvE7ycD9L6AC4JA6k58E6ICsr/Y8TsXT4UmZhhLNc50VgSo8cGQ
+lajqIDvntq8M1uCXiVOnXmIAqoB6E8GiqW+9evOkgkumMksSwXiXAhMM7vJt3IU6
+b+FwdF5cRs0u1FUCAQMwDQYJKoZIhvcNAQEEBQADgYEAkFdr3ypcvI2+Xgwfp7+d
+YtN7w4UnQ7LR9FKmlnBauTVLmUtichn/O3WMT9cYTtZm5QQVRaE3qrGh0Nr6Ko1E
+nIHowd36TN45zkFraWoATfCV/f+P37WaADp20l2ryEY0Jpe4gnoeZ0+/ffoxyajC
+LZEJL6Dv2Ed83cebLjYxKsI=
+
+-----END CERTIFICATE-----
+
diff --git a/security/nss/cmd/samples/cert0 b/security/nss/cmd/samples/cert0
new file mode 100644
index 000000000..05cdc8553
--- /dev/null
+++ b/security/nss/cmd/samples/cert0
Binary files differ
diff --git a/security/nss/cmd/samples/cert1 b/security/nss/cmd/samples/cert1
new file mode 100644
index 000000000..38a7d299a
--- /dev/null
+++ b/security/nss/cmd/samples/cert1
Binary files differ
diff --git a/security/nss/cmd/samples/cert2 b/security/nss/cmd/samples/cert2
new file mode 100644
index 000000000..147c3eb9e
--- /dev/null
+++ b/security/nss/cmd/samples/cert2
Binary files differ
diff --git a/security/nss/cmd/samples/pkcs7.ber b/security/nss/cmd/samples/pkcs7.ber
new file mode 100644
index 000000000..6e3814c37
--- /dev/null
+++ b/security/nss/cmd/samples/pkcs7.ber
Binary files differ
diff --git a/security/nss/cmd/samples/pkcs7bday.ber b/security/nss/cmd/samples/pkcs7bday.ber
new file mode 100644
index 000000000..0ee6cfc13
--- /dev/null
+++ b/security/nss/cmd/samples/pkcs7bday.ber
Binary files differ
diff --git a/security/nss/cmd/samples/pkcs7cnet.ber b/security/nss/cmd/samples/pkcs7cnet.ber
new file mode 100644
index 000000000..df2bb2dd1
--- /dev/null
+++ b/security/nss/cmd/samples/pkcs7cnet.ber
Binary files differ
diff --git a/security/nss/cmd/samples/pkcs7news.ber b/security/nss/cmd/samples/pkcs7news.ber
new file mode 100644
index 000000000..c46a1786d
--- /dev/null
+++ b/security/nss/cmd/samples/pkcs7news.ber
Binary files differ
diff --git a/security/nss/cmd/samples/x509v3.der b/security/nss/cmd/samples/x509v3.der
new file mode 100644
index 000000000..1ada57c56
--- /dev/null
+++ b/security/nss/cmd/samples/x509v3.der
Binary files differ
diff --git a/security/nss/cmd/samples/x509v3.txt b/security/nss/cmd/samples/x509v3.txt
new file mode 100644
index 000000000..dde307697
--- /dev/null
+++ b/security/nss/cmd/samples/x509v3.txt
@@ -0,0 +1,10 @@
+MIIByzCCAXWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBLMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNVmVyaVNpZ24gSW5jLjEUMBIGA1UECxMLRW5naW5lZXJpbmcxDjAM
+BgNVBAMTBUphc29uMB4XDTk1MDgwODA3MDAwMFoXDTk2MDgwNzA3MDAwMFowSzEL
+MAkGA1UEBhMCVVMxFjAUBgNVBAoTDVZlcmlTaWduIEluYy4xFDASBgNVBAsTC0Vu
+Z2luZWVyaW5nMQ4wDAYDVQQDEwVKYXNvbjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC
+QQCvpXRU9t3NPFXvxJz2vuxX4zI55AA+xY1PsAEadhwWEMF2EnpG8woF4EGTwLdx
+xrw3Eirzu5RAAhqegCN1aPVBAgMBAAGjRDBCMBQGA2FiYwEB/wQKZXh0ZW5zaW9u
+MTAUBgNkZWYBAf8ECmV4dGVuc2lvbjIwFAYDZ2hpAQH/BApleHRlbnNpb24zMA0G
+CSqGSIb3DQEBBAUAA0EAawLNWFSYMtywAqkSYJb1gejljqi9QAtLZIM2ui+RCTP2
+jEjW5bp4oU1RX2iBSfU+MdEZx9DpMNjqBLrgOy1Djw==
diff --git a/security/nss/cmd/sdrtest/Makefile b/security/nss/cmd/sdrtest/Makefile
new file mode 100644
index 000000000..490f738e5
--- /dev/null
+++ b/security/nss/cmd/sdrtest/Makefile
@@ -0,0 +1,73 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
diff --git a/security/nss/cmd/sdrtest/manifest.mn b/security/nss/cmd/sdrtest/manifest.mn
new file mode 100644
index 000000000..a8a08fed0
--- /dev/null
+++ b/security/nss/cmd/sdrtest/manifest.mn
@@ -0,0 +1,54 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ sdrtest.c \
+ $(NULL)
+
+# headers for the MODULE (defined above) are implicitly required.
+REQUIRES = dbm seccmd
+
+# WINNT uses EXTRA_LIBS as the list of libs to link in.
+# Unix uses OS_LIBS for that purpose.
+# We can solve this via conditional makefile code, but
+# can't do this in manifest.mn because OS_ARCH isn't defined there.
+# So, look in the local Makefile for the defines for the list of libs.
+
+PROGRAM = sdrtest
+
+#USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/sdrtest/sdrtest.c b/security/nss/cmd/sdrtest/sdrtest.c
new file mode 100644
index 000000000..5bcdd4cde
--- /dev/null
+++ b/security/nss/cmd/sdrtest/sdrtest.c
@@ -0,0 +1,305 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * Test program for SDR (Secret Decoder Ring) functions.
+ *
+ * $Id$
+ */
+
+#include "nspr.h"
+#include "string.h"
+#include "nss.h"
+#include "secutil.h"
+#include "cert.h"
+#include "pk11func.h"
+
+#include "plgetopt.h"
+#include "pk11sdr.h"
+#include "secrng.h"
+
+#define DEFAULT_VALUE "Test"
+
+static void
+synopsis (char *program_name)
+{
+ PRFileDesc *pr_stderr;
+
+ pr_stderr = PR_STDERR;
+ PR_fprintf (pr_stderr, "Usage:");
+ PR_fprintf (pr_stderr,
+ "\t%s [-i <input-file>] [-o <output-file>] [-r <text>] [-d <dir>]\n",
+ program_name);
+}
+
+
+static void
+short_usage (char *program_name)
+{
+ PR_fprintf (PR_STDERR,
+ "Type %s -H for more detailed descriptions\n",
+ program_name);
+ synopsis (program_name);
+}
+
+
+static void
+long_usage (char *program_name)
+{
+ PRFileDesc *pr_stderr;
+
+ pr_stderr = PR_STDERR;
+ synopsis (program_name);
+ PR_fprintf (pr_stderr, "\nSecret Decoder Test:\n");
+ PR_fprintf (pr_stderr,
+ " %-13s Read encrypted data from \"file\"\n",
+ "-i file");
+ PR_fprintf (pr_stderr,
+ " %-13s Write newly generated encrypted data to \"file\"\n",
+ "-o file");
+ PR_fprintf (pr_stderr,
+ " %-13s Use \"text\" as the plaintext for encryption and verification\n",
+ "-t text");
+ PR_fprintf (pr_stderr,
+ " %-13s Find security databases in \"dbdir\"\n",
+ "-d dbdir");
+}
+
+int
+main (int argc, char **argv)
+{
+ int retval = 0; /* 0 - test succeeded. -1 - test failed */
+ SECStatus rv;
+ PLOptState *optstate;
+ char *program_name;
+ const char *input_file = NULL; /* read encrypted data from here (or create) */
+ const char *output_file = NULL; /* write new encrypted data here */
+ const char *value = DEFAULT_VALUE; /* Use this for plaintext */
+ SECItem data;
+ SECItem result;
+ SECItem text;
+ PRBool verbose = PR_FALSE;
+
+ result.data = 0;
+ text.data = 0; text.len = 0;
+
+ program_name = PL_strrchr(argv[0], '/');
+ program_name = program_name ? (program_name + 1) : argv[0];
+
+ optstate = PL_CreateOptState (argc, argv, "Hd:i:o:t:v");
+ if (optstate == NULL) {
+ SECU_PrintError (program_name, "PL_CreateOptState failed");
+ return -1;
+ }
+
+ while (PL_GetNextOpt (optstate) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ short_usage (program_name);
+ return retval;
+
+ case 'H':
+ long_usage (program_name);
+ return retval;
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'i':
+ input_file = optstate->value;
+ break;
+
+ case 'o':
+ output_file = optstate->value;
+ break;
+
+ case 't':
+ value = optstate->value;
+ break;
+
+ case 'v':
+ verbose = PR_TRUE;
+ break;
+ }
+ }
+
+ /*
+ * Initialize the Security libraries.
+ */
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ if (output_file) {
+ rv = NSS_InitReadWrite(SECU_ConfigDirectory(NULL));
+ } else {
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ }
+ if (rv != SECSuccess) {
+ retval = -1;
+ goto prdone;
+ }
+
+ /* Convert value into an item */
+ data.data = (unsigned char *)value;
+ data.len = strlen(value);
+
+ /* Get the encrypted result, either from the input file
+ * or from encrypting the plaintext value
+ */
+ if (input_file)
+ {
+ PRFileDesc *file /* = PR_OpenFile(input_file, 0) */;
+ PRFileInfo info;
+ PRStatus s;
+ PRInt32 count;
+
+ if (verbose) printf("Reading data from %s\n", input_file);
+
+ file = PR_Open(input_file, PR_RDONLY, 0);
+ if (!file) {
+ if (verbose) printf("Open of file failed\n");
+ retval = -1;
+ goto loser;
+ }
+
+ s = PR_GetOpenFileInfo(file, &info);
+ if (s != PR_SUCCESS) {
+ if (verbose) printf("File info operation failed\n");
+ retval = -1;
+ goto file_loser;
+ }
+
+ result.len = info.size;
+ result.data = (unsigned char *)malloc(result.len);
+ if (!result.data) {
+ if (verbose) printf("Allocation of buffer failed\n");
+ retval = -1;
+ goto file_loser;
+ }
+
+ count = PR_Read(file, result.data, result.len);
+ if (count != result.len) {
+ if (verbose) printf("Read failed\n");
+ retval = -1;
+ goto file_loser;
+ }
+
+file_loser:
+ PR_Close(file);
+ if (retval != 0) goto loser;
+ }
+ else
+ {
+ SECItem keyid = { 0, 0, 0 };
+ PK11SlotInfo *slot = NULL;
+
+ /* sigh, initialize the key database */
+ slot = PK11_GetInternalKeySlot();
+ if (slot && PK11_NeedUserInit(slot)) {
+ rv = SECU_ChangePW(slot, "", 0);
+ if (rv != SECSuccess) {
+ SECU_PrintError(program_name, "Failed to initialize slot \"%s\"",
+ PK11_GetSlotName(slot));
+ return SECFailure;
+ }
+ }
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+
+ rv = PK11SDR_Encrypt(&keyid, &data, &result, 0);
+ if (rv != SECSuccess) {
+ if (verbose) printf("Encrypt operation failed\n");
+ retval = -1;
+ goto loser;
+ }
+
+ if (verbose) printf("Encrypted result is %d bytes long\n", result.len);
+
+ /* -v printf("Result is %.*s\n", text.len, text.data); */
+ if (output_file)
+ {
+ PRFileDesc *file;
+ PRInt32 count;
+
+ if (verbose) printf("Writing result to %s\n", output_file);
+
+ /* Write to file */
+ file = PR_Open(output_file, PR_CREATE_FILE|PR_WRONLY, 0666);
+ if (!file) {
+ if (verbose) printf("Open of output file failed\n");
+ retval = -1;
+ goto loser;
+ }
+
+ count = PR_Write(file, result.data, result.len);
+
+ PR_Close(file);
+
+ if (count != result.len) {
+ if (verbose) printf("Write failed\n");
+ retval = -1;
+ goto loser;
+ }
+ }
+ }
+
+ /* Decrypt the value */
+ rv = PK11SDR_Decrypt(&result, &text, 0);
+ if (rv != SECSuccess) {
+ if (verbose) printf("Decrypt operation failed\n");
+ retval = -1;
+ goto loser;
+ }
+
+ if (verbose) printf("Decrypted result is %.*s\n", text.len, text.data);
+
+ /* Compare to required value */
+ if (text.len != data.len || memcmp(data.data, text.data, text.len) != 0)
+ {
+ if (verbose) printf("Comparison failed\n");
+ retval = -1;
+ goto loser;
+ }
+
+loser:
+ if (text.data) free(text.data);
+ if (result.data) free(result.data);
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+prdone:
+ PR_Cleanup ();
+ return retval;
+}
diff --git a/security/nss/cmd/selfserv/Makefile b/security/nss/cmd/selfserv/Makefile
new file mode 100644
index 000000000..f2a407990
--- /dev/null
+++ b/security/nss/cmd/selfserv/Makefile
@@ -0,0 +1,74 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/selfserv/makefile.win b/security/nss/cmd/selfserv/makefile.win
new file mode 100644
index 000000000..8fda0b906
--- /dev/null
+++ b/security/nss/cmd/selfserv/makefile.win
@@ -0,0 +1,136 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+#cannot define PROGRAM in manifest compatibly with NT and UNIX
+PROGRAM = selfserv
+PROGRAM = ./$(OBJDIR)/$(PROGRAM).exe
+include <$(DEPTH)\config\config.mak>
+
+# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
+# rules.mak will append C_OBJS onto OBJS.
+# OBJS = $(CSRCS:.c=.obj)
+
+# include files are looked for in $LINCS and $INCS.
+# $LINCS is in manifest.mnw, computed from REQUIRES=
+INCS = $(INCS) \
+ -I$(DEPTH)/security/lib/cert \
+ -I../include \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+ $(NULL)
+
+
+WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
+
+# these files are the content of libdbm
+DBM_LIB = \
+ $(WINFE)/DB.obj \
+ $(WINFE)/HASH.obj \
+ $(WINFE)/H_BIGKEY.obj \
+ $(WINFE)/H_PAGE.obj \
+ $(WINFE)/H_LOG2.obj \
+ $(WINFE)/H_FUNC.obj \
+ $(WINFE)/HASH_BUF.obj \
+ $(NULL)
+
+MOZ_LIBS = \
+ $(WINFE)/ALLXPSTR.obj \
+ $(WINFE)/XP_ERROR.obj \
+ $(WINFE)/XPASSERT.obj \
+ $(WINFE)/XP_REG.obj \
+ $(WINFE)/XP_TRACE.obj \
+ $(DBM_LIB) \
+ $(WINFE)/XP_STR.obj \
+ $(WINFE)/MKTEMP.obj \
+ $(NULL)
+
+IGNORE_ME2 = \
+ $(WINFE)/feutil.obj \
+ $(WINFE)/fenet.obj \
+ $(WINFE)/fegui.obj \
+ $(NULL)
+
+SEC_LIBS = \
+ $(DIST)/lib/cert$(MOZ_BITS).lib \
+ $(DIST)/lib/crypto$(MOZ_BITS).lib \
+ $(DIST)/lib/hash$(MOZ_BITS).lib \
+ $(DIST)/lib/key$(MOZ_BITS).lib \
+ $(DIST)/lib/pkcs7$(MOZ_BITS).lib \
+ $(DIST)/lib/secmod$(MOZ_BITS).lib \
+ $(DIST)/lib/secutl$(MOZ_BITS).lib \
+ $(DIST)/lib/ssl$(MOZ_BITS).lib \
+ $(NULL)
+
+LLFLAGS = $(LLFLAGS) \
+ $(SEC_LIBS) \
+ ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
+ $(MOZ_LIBS) \
+ $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
+ $(LIBNSPR) \
+ $(NULL)
+
+
+include <$(DEPTH)\config\rules.mak>
+
+INSTALL = $(MAKE_INSTALL)
+
+objs: $(OBJS)
+
+$(PROGRAM)::
+ $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
+
+programs: $(PROGRAM)
+
+install:: $(TARGETS)
+ $(INSTALL) $(TARGETS) $(DIST)/bin
+
+
+symbols:
+ @echo "CSRCS = $(CSRCS)"
+ @echo "INCS = $(INCS)"
+ @echo "OBJS = $(OBJS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "TARGETS = $(TARGETS)"
+ @echo "DIST = $(DIST)"
+ @echo "VERSION_NUMBER = $(VERSION_NUMBER)"
+ @echo "WINFE = $(WINFE)"
+ @echo "DBM_LIB = $(DBM_LIB)"
+ @echo "INSTALL = $(INSTALL)"
+
diff --git a/security/nss/cmd/selfserv/manifest.mn b/security/nss/cmd/selfserv/manifest.mn
new file mode 100644
index 000000000..e97085201
--- /dev/null
+++ b/security/nss/cmd/selfserv/manifest.mn
@@ -0,0 +1,48 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = selfserv.c
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+PROGRAM = selfserv
+
diff --git a/security/nss/cmd/selfserv/selfserv.c b/security/nss/cmd/selfserv/selfserv.c
new file mode 100644
index 000000000..41f1efe8b
--- /dev/null
+++ b/security/nss/cmd/selfserv/selfserv.c
@@ -0,0 +1,1752 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
+ * Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/* -r flag is interepreted as follows:
+ * 1 -r means request, not require, on initial handshake.
+ * 2 -r's mean request and require, on initial handshake.
+ * 3 -r's mean request, not require, on second handshake.
+ * 4 -r's mean request and require, on second handshake.
+ */
+#include <stdio.h>
+#include <string.h>
+
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#if defined(_WINDOWS)
+#include <process.h> /* for getpid() */
+#endif
+
+#ifdef XP_OS2_VACPP
+#include <Process.h> /* for getpid() */
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "prio.h"
+#include "prerror.h"
+#include "prnetdb.h"
+#include "prclist.h"
+#include "plgetopt.h"
+#include "pk11func.h"
+#include "secitem.h"
+#include "nss.h"
+#include "ssl.h"
+#include "sslproto.h"
+
+#ifndef PORT_Sprintf
+#define PORT_Sprintf sprintf
+#endif
+
+#ifndef PORT_Strstr
+#define PORT_Strstr strstr
+#endif
+
+#ifndef PORT_Malloc
+#define PORT_Malloc PR_Malloc
+#endif
+
+#define NUM_SID_CACHE_ENTRIES 1024
+
+static int handle_connection( PRFileDesc *, PRFileDesc *, int );
+
+static const char envVarName[] = { SSL_ENV_VAR_NAME };
+static const char inheritableSockName[] = { "SELFSERV_LISTEN_SOCKET" };
+
+static PRBool logStats = PR_FALSE;
+static int logPeriod = 30;
+static PRUint32 loggerOps = 0;
+
+const int ssl2CipherSuites[] = {
+ SSL_EN_RC4_128_WITH_MD5, /* A */
+ SSL_EN_RC4_128_EXPORT40_WITH_MD5, /* B */
+ SSL_EN_RC2_128_CBC_WITH_MD5, /* C */
+ SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */
+ SSL_EN_DES_64_CBC_WITH_MD5, /* E */
+ SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* F */
+#ifdef NSS_ENABLE_ECC
+ /* NOTE: Since no new SSL2 ciphersuites are being
+ * invented, and we've run out of lowercase letters
+ * for SSL3 ciphers, we use letters G and beyond
+ * for new SSL3 ciphers. A -1 indicates the cipher
+ * is not currently implemented.
+ */
+ -1, /* TLS_ECDH_ECDSA_WITH_NULL_SHA, * G */
+ -1, /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA, * H */
+ -1, /* TLS_ECDH_ECDSA_WITH_DES_CBC_SHA, * I */
+ -1, /* TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, * J */
+ -1, /* TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, * K */
+ -1, /* TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, * L */
+ -1, /* TLS_ECDH_RSA_WITH_NULL_SHA, * M */
+ -1, /* TLS_ECDH_RSA_WITH_RC4_128_SHA, * N */
+ -1, /* TLS_ECDH_RSA_WITH_DES_CBC_SHA, * O */
+ -1, /* TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, * P */
+ -1, /* TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, * Q */
+ -1, /* TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, * R */
+ -1, /* TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, * S */
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* T */
+#endif /* NSS_ENABLE_ECC */
+ 0
+};
+
+const int ssl3CipherSuites[] = {
+ SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* a */
+ SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, /* b */
+ SSL_RSA_WITH_RC4_128_MD5, /* c */
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
+ SSL_RSA_WITH_DES_CBC_SHA, /* e */
+ SSL_RSA_EXPORT_WITH_RC4_40_MD5, /* f */
+ SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* g */
+ SSL_FORTEZZA_DMS_WITH_NULL_SHA, /* h */
+ SSL_RSA_WITH_NULL_MD5, /* i */
+ SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, /* j */
+ SSL_RSA_FIPS_WITH_DES_CBC_SHA, /* k */
+ TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
+ TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, /* m */
+ SSL_RSA_WITH_RC4_128_SHA, /* n */
+ -1, /* TLS_DHE_DSS_WITH_RC4_128_SHA, * o */
+ -1, /* SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, * p */
+ -1, /* SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, * q */
+ -1, /* SSL_DHE_RSA_WITH_DES_CBC_SHA, * r */
+ -1, /* SSL_DHE_DSS_WITH_DES_CBC_SHA, * s */
+ -1, /* TLS_DHE_DSS_WITH_AES_128_CBC_SHA, * t */
+ -1, /* TLS_DHE_RSA_WITH_AES_128_CBC_SHA, * u */
+ TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
+ -1, /* TLS_DHE_DSS_WITH_AES_256_CBC_SHA, * w */
+ -1, /* TLS_DHE_RSA_WITH_AES_256_CBC_SHA, * x */
+ TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
+ SSL_RSA_WITH_NULL_SHA, /* z */
+ 0
+};
+
+/* data and structures for shutdown */
+static int stopping;
+
+static PRBool noDelay;
+static int requestCert;
+static int verbose;
+static SECItem bigBuf;
+
+static PRThread * acceptorThread;
+
+static PRLogModuleInfo *lm;
+
+/* Add custom password handler because SECU_GetModulePassword
+ * makes automation of this program next to impossible.
+ */
+
+char *
+ownPasswd(PK11SlotInfo *info, PRBool retry, void *arg)
+{
+ char * passwd = NULL;
+
+ if ( (!retry) && arg ) {
+ passwd = PL_strdup((char *)arg);
+ }
+
+ return passwd;
+}
+
+#define PRINTF if (verbose) printf
+#define FPRINTF if (verbose) fprintf
+#define FLUSH if (verbose) { fflush(stdout); fflush(stderr); }
+#define VLOG(arg) PR_LOG(lm,PR_LOG_DEBUG,arg)
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+
+"Usage: %s -n rsa_nickname -p port [-3DRTbmrvx] [-w password] [-t threads]\n"
+" [-i pid_file] [-c ciphers] [-d dbdir] [-f fortezza_nickname] \n"
+" [-L [seconds]] [-M maxProcs] [-l]\n"
+"-3 means disable SSL v3\n"
+"-D means disable Nagle delays in TCP\n"
+"-T means disable TLS\n"
+"-R means disable detection of rollback from TLS to SSL3\n"
+"-b means try binding to the port and exit\n"
+"-m means test the model-socket feature of SSL_ImportFD.\n"
+"-r flag is interepreted as follows:\n"
+" 1 -r means request, not require, cert on initial handshake.\n"
+" 2 -r's mean request and require, cert on initial handshake.\n"
+" 3 -r's mean request, not require, cert on second handshake.\n"
+" 4 -r's mean request and require, cert on second handshake.\n"
+"-v means verbose output\n"
+"-x means use export policy.\n"
+"-L seconds means log statistics every 'seconds' seconds (default=30).\n"
+"-M maxProcs tells how many processes to run in a multi-process server\n"
+"-t threads -- specify the number of threads to use for connections.\n"
+"-i pid_file file to write the process id of selfserve\n"
+"-c ciphers Letter(s) chosen from the following list\n"
+"-l means use local threads instead of global threads\n"
+"A SSL2 RC4 128 WITH MD5\n"
+"B SSL2 RC4 128 EXPORT40 WITH MD5\n"
+"C SSL2 RC2 128 CBC WITH MD5\n"
+"D SSL2 RC2 128 CBC EXPORT40 WITH MD5\n"
+"E SSL2 DES 64 CBC WITH MD5\n"
+"F SSL2 DES 192 EDE3 CBC WITH MD5\n"
+#ifdef NSS_ENABLE_ECC
+"T TLS ECDHE RSA WITH AES 128 CBC SHA\n"
+#endif /* NSS_ENABLE_ECC */
+"\n"
+"a SSL3 FORTEZZA DMS WITH FORTEZZA CBC SHA\n"
+"b SSL3 FORTEZZA DMS WITH RC4 128 SHA\n"
+"c SSL3 RSA WITH RC4 128 MD5\n"
+"d SSL3 RSA WITH 3DES EDE CBC SHA\n"
+"e SSL3 RSA WITH DES CBC SHA\n"
+"f SSL3 RSA EXPORT WITH RC4 40 MD5\n"
+"g SSL3 RSA EXPORT WITH RC2 CBC 40 MD5\n"
+"h SSL3 FORTEZZA DMS WITH NULL SHA\n"
+"i SSL3 RSA WITH NULL MD5\n"
+"j SSL3 RSA FIPS WITH 3DES EDE CBC SHA\n"
+"k SSL3 RSA FIPS WITH DES CBC SHA\n"
+"l SSL3 RSA EXPORT WITH DES CBC SHA\t(new)\n"
+"m SSL3 RSA EXPORT WITH RC4 56 SHA\t(new)\n"
+"n SSL3 RSA WITH RC4 128 SHA\n"
+"v SSL3 RSA WITH AES 128 CBC SHA\n"
+"y SSL3 RSA WITH AES 256 CBC SHA\n"
+"z SSL3 RSA WITH NULL SHA\n"
+ ,progName);
+}
+
+static const char *
+errWarn(char * funcString)
+{
+ PRErrorCode perr = PR_GetError();
+ const char * errString = SECU_Strerror(perr);
+
+ fprintf(stderr, "selfserv: %s returned error %d:\n%s\n",
+ funcString, perr, errString);
+ return errString;
+}
+
+static void
+errExit(char * funcString)
+{
+ errWarn(funcString);
+ exit(3);
+}
+
+
+/**************************************************************************
+**
+** Routines for disabling SSL ciphers.
+**
+**************************************************************************/
+
+void
+disableAllSSLCiphers(void)
+{
+ const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
+ int i = SSL_NumImplementedCiphers;
+ SECStatus rv;
+
+ /* disable all the SSL3 cipher suites */
+ while (--i >= 0) {
+ PRUint16 suite = cipherSuites[i];
+ rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
+ if (rv != SECSuccess) {
+ printf("SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n",
+ suite, i);
+ errWarn("SSL_CipherPrefSetDefault");
+ exit(2);
+ }
+ }
+}
+
+static SECStatus
+mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
+ PRBool isServer)
+{
+ SECStatus rv;
+ CERTCertificate * peerCert;
+
+ peerCert = SSL_PeerCertificate(fd);
+
+ PRINTF("selfserv: Subject: %s\nselfserv: Issuer : %s\n",
+ peerCert->subjectName, peerCert->issuerName);
+
+ rv = SSL_AuthCertificate(arg, fd, checkSig, isServer);
+
+ if (rv == SECSuccess) {
+ PRINTF("selfserv: -- SSL3: Certificate Validated.\n");
+ } else {
+ int err = PR_GetError();
+ FPRINTF(stderr, "selfserv: -- SSL3: Certificate Invalid, err %d.\n%s\n",
+ err, SECU_Strerror(err));
+ }
+ CERT_DestroyCertificate(peerCert);
+ FLUSH;
+ return rv;
+}
+
+void
+printSecurityInfo(PRFileDesc *fd)
+{
+ CERTCertificate * cert = NULL;
+ SSL3Statistics * ssl3stats = SSL_GetStatistics();
+ SECStatus result;
+ SSLChannelInfo channel;
+ SSLCipherSuiteInfo suite;
+
+ PRINTF(
+ "selfserv: %ld cache hits; %ld cache misses, %ld cache not reusable\n",
+ ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses,
+ ssl3stats->hch_sid_cache_not_ok);
+
+ result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
+ if (result == SECSuccess &&
+ channel.length == sizeof channel &&
+ channel.cipherSuite) {
+ result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
+ &suite, sizeof suite);
+ if (result == SECSuccess) {
+ FPRINTF(stderr,
+ "selfserv: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
+ channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
+ suite.effectiveKeyBits, suite.symCipherName,
+ suite.macBits, suite.macAlgorithmName);
+ FPRINTF(stderr,
+ "selfserv: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n",
+ channel.authKeyBits, suite.authAlgorithmName,
+ channel.keaKeyBits, suite.keaTypeName);
+ }
+ }
+ if (requestCert)
+ cert = SSL_PeerCertificate(fd);
+ else
+ cert = SSL_LocalCertificate(fd);
+ if (cert) {
+ char * ip = CERT_NameToAscii(&cert->issuer);
+ char * sp = CERT_NameToAscii(&cert->subject);
+ if (sp) {
+ FPRINTF(stderr, "selfserv: subject DN: %s\n", sp);
+ PR_Free(sp);
+ }
+ if (ip) {
+ FPRINTF(stderr, "selfserv: issuer DN: %s\n", ip);
+ PR_Free(ip);
+ }
+ CERT_DestroyCertificate(cert);
+ cert = NULL;
+ }
+ FLUSH;
+}
+
+static int MakeCertOK;
+
+static SECStatus
+myBadCertHandler( void *arg, PRFileDesc *fd)
+{
+ int err = PR_GetError();
+ if (!MakeCertOK)
+ fprintf(stderr,
+ "selfserv: -- SSL: Client Certificate Invalid, err %d.\n%s\n",
+ err, SECU_Strerror(err));
+ return (MakeCertOK ? SECSuccess : SECFailure);
+}
+
+/**************************************************************************
+** Begin thread management routines and data.
+**************************************************************************/
+#define MIN_THREADS 3
+#define DEFAULT_THREADS 8
+#define MAX_THREADS 128
+#define MAX_PROCS 25
+static int maxThreads = DEFAULT_THREADS;
+
+
+typedef struct jobStr {
+ PRCList link;
+ PRFileDesc *tcp_sock;
+ PRFileDesc *model_sock;
+ int requestCert;
+} JOB;
+
+static PZLock * qLock; /* this lock protects all data immediately below */
+static PZCondVar * jobQNotEmptyCv;
+static PZCondVar * freeListNotEmptyCv;
+static PZCondVar * threadCountChangeCv;
+static int threadCount;
+static PRCList jobQ;
+static PRCList freeJobs;
+static JOB *jobTable;
+
+SECStatus
+setupJobs(int maxJobs)
+{
+ int i;
+
+ jobTable = (JOB *)PR_Calloc(maxJobs, sizeof(JOB));
+ if (!jobTable)
+ return SECFailure;
+
+ PR_INIT_CLIST(&jobQ);
+ PR_INIT_CLIST(&freeJobs);
+
+ for (i = 0; i < maxJobs; ++i) {
+ JOB * pJob = jobTable + i;
+ PR_APPEND_LINK(&pJob->link, &freeJobs);
+ }
+ return SECSuccess;
+}
+
+typedef int startFn(PRFileDesc *a, PRFileDesc *b, int c);
+
+typedef enum { rs_idle = 0, rs_running = 1, rs_zombie = 2 } runState;
+
+typedef struct perThreadStr {
+ PRFileDesc *a;
+ PRFileDesc *b;
+ int c;
+ int rv;
+ startFn * startFunc;
+ PRThread * prThread;
+ runState state;
+} perThread;
+
+static perThread *threads;
+
+void
+thread_wrapper(void * arg)
+{
+ perThread * slot = (perThread *)arg;
+
+ slot->rv = (* slot->startFunc)(slot->a, slot->b, slot->c);
+
+ /* notify the thread exit handler. */
+ PZ_Lock(qLock);
+ slot->state = rs_zombie;
+ --threadCount;
+ PZ_NotifyAllCondVar(threadCountChangeCv);
+ PZ_Unlock(qLock);
+}
+
+int
+jobLoop(PRFileDesc *a, PRFileDesc *b, int c)
+{
+ PRCList * myLink = 0;
+ JOB * myJob;
+
+ PZ_Lock(qLock);
+ do {
+ myLink = 0;
+ while (PR_CLIST_IS_EMPTY(&jobQ) && !stopping) {
+ PZ_WaitCondVar(jobQNotEmptyCv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ if (!PR_CLIST_IS_EMPTY(&jobQ)) {
+ myLink = PR_LIST_HEAD(&jobQ);
+ PR_REMOVE_AND_INIT_LINK(myLink);
+ }
+ PZ_Unlock(qLock);
+ myJob = (JOB *)myLink;
+ /* myJob will be null when stopping is true and jobQ is empty */
+ if (!myJob)
+ break;
+ handle_connection( myJob->tcp_sock, myJob->model_sock,
+ myJob->requestCert);
+ PZ_Lock(qLock);
+ PR_APPEND_LINK(myLink, &freeJobs);
+ PZ_NotifyCondVar(freeListNotEmptyCv);
+ } while (PR_TRUE);
+ return 0;
+}
+
+
+SECStatus
+launch_threads(
+ startFn *startFunc,
+ PRFileDesc *a,
+ PRFileDesc *b,
+ int c,
+ PRBool local)
+{
+ int i;
+ SECStatus rv = SECSuccess;
+
+ /* create the thread management serialization structs */
+ qLock = PZ_NewLock(nssILockSelfServ);
+ jobQNotEmptyCv = PZ_NewCondVar(qLock);
+ freeListNotEmptyCv = PZ_NewCondVar(qLock);
+ threadCountChangeCv = PZ_NewCondVar(qLock);
+
+ /* allocate the array of thread slots */
+ threads = PR_Calloc(maxThreads, sizeof(perThread));
+ if ( NULL == threads ) {
+ fprintf(stderr, "Oh Drat! Can't allocate the perThread array\n");
+ return SECFailure;
+ }
+ /* 5 is a little extra, intended to keep the jobQ from underflowing.
+ ** That is, from going empty while not stopping and clients are still
+ ** trying to contact us.
+ */
+ rv = setupJobs(maxThreads + 5);
+ if (rv != SECSuccess)
+ return rv;
+
+ PZ_Lock(qLock);
+ for (i = 0; i < maxThreads; ++i) {
+ perThread * slot = threads + i;
+
+ slot->state = rs_running;
+ slot->a = a;
+ slot->b = b;
+ slot->c = c;
+ slot->startFunc = startFunc;
+ slot->prThread = PR_CreateThread(PR_USER_THREAD,
+ thread_wrapper, slot, PR_PRIORITY_NORMAL,
+ (PR_TRUE==local)?PR_LOCAL_THREAD:PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (slot->prThread == NULL) {
+ printf("selfserv: Failed to launch thread!\n");
+ slot->state = rs_idle;
+ rv = SECFailure;
+ break;
+ }
+
+ ++threadCount;
+ }
+ PZ_Unlock(qLock);
+
+ return rv;
+}
+
+#define DESTROY_CONDVAR(name) if (name) { \
+ PZ_DestroyCondVar(name); name = NULL; }
+#define DESTROY_LOCK(name) if (name) { \
+ PZ_DestroyLock(name); name = NULL; }
+
+
+void
+terminateWorkerThreads(void)
+{
+ VLOG(("selfserv: server_thead: waiting on stopping"));
+ PZ_Lock(qLock);
+ PZ_NotifyAllCondVar(jobQNotEmptyCv);
+ while (threadCount > 0) {
+ PZ_WaitCondVar(threadCountChangeCv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PZ_Unlock(qLock);
+
+ DESTROY_CONDVAR(jobQNotEmptyCv);
+ DESTROY_CONDVAR(freeListNotEmptyCv);
+ DESTROY_CONDVAR(threadCountChangeCv);
+
+ DESTROY_LOCK(qLock);
+ PR_Free(jobTable);
+ PR_Free(threads);
+}
+
+static void
+logger(void *arg)
+{
+ PRFloat64 seconds;
+ PRFloat64 opsPerSec;
+ PRIntervalTime period;
+ PRIntervalTime previousTime;
+ PRIntervalTime latestTime;
+ PRUint32 previousOps;
+ PRUint32 ops;
+ PRIntervalTime logPeriodTicks = PR_SecondsToInterval(logPeriod);
+ PRFloat64 secondsPerTick = 1.0 / (PRFloat64)PR_TicksPerSecond();
+
+ previousOps = loggerOps;
+ previousTime = PR_IntervalNow();
+
+ for (;;) {
+ PR_Sleep(logPeriodTicks);
+ latestTime = PR_IntervalNow();
+ ops = loggerOps;
+ period = latestTime - previousTime;
+ seconds = (PRFloat64) period*secondsPerTick;
+ opsPerSec = (ops - previousOps) / seconds;
+ printf("%.2f ops/second, %d threads\n", opsPerSec, threadCount);
+ fflush(stdout);
+ previousOps = ops;
+ previousTime = latestTime;
+ }
+}
+
+
+/**************************************************************************
+** End thread management routines.
+**************************************************************************/
+
+PRBool useModelSocket = PR_FALSE;
+PRBool disableSSL3 = PR_FALSE;
+PRBool disableTLS = PR_FALSE;
+PRBool disableRollBack = PR_FALSE;
+
+static const char stopCmd[] = { "GET /stop " };
+static const char getCmd[] = { "GET " };
+static const char EOFmsg[] = { "EOF\r\n\r\n\r\n" };
+static const char outHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: Generic Web Server\r\n"
+ "Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+};
+
+#ifdef FULL_DUPLEX_CAPABLE
+
+struct lockedVarsStr {
+ PZLock * lock;
+ int count;
+ int waiters;
+ PZCondVar * condVar;
+};
+
+typedef struct lockedVarsStr lockedVars;
+
+void
+lockedVars_Init( lockedVars * lv)
+{
+ lv->count = 0;
+ lv->waiters = 0;
+ lv->lock = PZ_NewLock(nssILockSelfServ);
+ lv->condVar = PZ_NewCondVar(lv->lock);
+}
+
+void
+lockedVars_Destroy( lockedVars * lv)
+{
+ PZ_DestroyCondVar(lv->condVar);
+ lv->condVar = NULL;
+
+ PZ_DestroyLock(lv->lock);
+ lv->lock = NULL;
+}
+
+void
+lockedVars_WaitForDone(lockedVars * lv)
+{
+ PZ_Lock(lv->lock);
+ while (lv->count > 0) {
+ PZ_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PZ_Unlock(lv->lock);
+}
+
+int /* returns count */
+lockedVars_AddToCount(lockedVars * lv, int addend)
+{
+ int rv;
+
+ PZ_Lock(lv->lock);
+ rv = lv->count += addend;
+ if (rv <= 0) {
+ PZ_NotifyCondVar(lv->condVar);
+ }
+ PZ_Unlock(lv->lock);
+ return rv;
+}
+
+int
+do_writes(
+ PRFileDesc * ssl_sock,
+ PRFileDesc * model_sock,
+ int requestCert
+ )
+{
+ int sent = 0;
+ int count = 0;
+ lockedVars * lv = (lockedVars *)model_sock;
+
+ VLOG(("selfserv: do_writes: starting"));
+ while (sent < bigBuf.len) {
+
+ count = PR_Write(ssl_sock, bigBuf.data + sent, bigBuf.len - sent);
+ if (count < 0) {
+ errWarn("PR_Write bigBuf");
+ break;
+ }
+ FPRINTF(stderr, "selfserv: PR_Write wrote %d bytes from bigBuf\n", count );
+ sent += count;
+ }
+ if (count >= 0) { /* last write didn't fail. */
+ PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND);
+ }
+
+ /* notify the reader that we're done. */
+ lockedVars_AddToCount(lv, -1);
+ FLUSH;
+ VLOG(("selfserv: do_writes: exiting"));
+ return (sent < bigBuf.len) ? SECFailure : SECSuccess;
+}
+
+static int
+handle_fdx_connection(
+ PRFileDesc * tcp_sock,
+ PRFileDesc * model_sock,
+ int requestCert
+ )
+{
+ PRFileDesc * ssl_sock = NULL;
+ SECStatus result;
+ int firstTime = 1;
+ lockedVars lv;
+ PRSocketOptionData opt;
+ char buf[10240];
+
+
+ VLOG(("selfserv: handle_fdx_connection: starting"));
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ PR_SetSocketOption(tcp_sock, &opt);
+
+ if (useModelSocket && model_sock) {
+ SECStatus rv;
+ ssl_sock = SSL_ImportFD(model_sock, tcp_sock);
+ if (!ssl_sock) {
+ errWarn("SSL_ImportFD with model");
+ goto cleanup;
+ }
+ rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 1);
+ if (rv != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ goto cleanup;
+ }
+ } else {
+ ssl_sock = tcp_sock;
+ }
+
+ lockedVars_Init(&lv);
+ lockedVars_AddToCount(&lv, 1);
+
+ /* Attempt to launch the writer thread. */
+ result = launch_thread(do_writes, ssl_sock, (PRFileDesc *)&lv,
+ requestCert);
+
+ if (result == SECSuccess)
+ do {
+ /* do reads here. */
+ int count;
+ count = PR_Read(ssl_sock, buf, sizeof buf);
+ if (count < 0) {
+ errWarn("FDX PR_Read");
+ break;
+ }
+ FPRINTF(stderr, "selfserv: FDX PR_Read read %d bytes.\n", count );
+ if (firstTime) {
+ firstTime = 0;
+ printSecurityInfo(ssl_sock);
+ }
+ } while (lockedVars_AddToCount(&lv, 0) > 0);
+
+ /* Wait for writer to finish */
+ lockedVars_WaitForDone(&lv);
+ lockedVars_Destroy(&lv);
+ FLUSH;
+
+cleanup:
+ if (ssl_sock)
+ PR_Close(ssl_sock);
+ else
+ PR_Close(tcp_sock);
+
+ VLOG(("selfserv: handle_fdx_connection: exiting"));
+ return SECSuccess;
+}
+
+#endif
+
+int
+handle_connection(
+ PRFileDesc *tcp_sock,
+ PRFileDesc *model_sock,
+ int requestCert
+ )
+{
+ PRFileDesc * ssl_sock = NULL;
+ PRFileDesc * local_file_fd = NULL;
+ char * post;
+ char * pBuf; /* unused space at end of buf */
+ const char * errString;
+ PRStatus status;
+ int bufRem; /* unused bytes at end of buf */
+ int bufDat; /* characters received in buf */
+ int newln = 0; /* # of consecutive newlns */
+ int firstTime = 1;
+ int reqLen;
+ int rv;
+ int numIOVs;
+ PRSocketOptionData opt;
+ PRIOVec iovs[16];
+ char msgBuf[160];
+ char buf[10240];
+ char fileName[513];
+
+ pBuf = buf;
+ bufRem = sizeof buf;
+ memset(buf, 0, sizeof buf);
+
+ VLOG(("selfserv: handle_connection: starting"));
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ PR_SetSocketOption(tcp_sock, &opt);
+
+ VLOG(("selfserv: handle_connection: starting\n"));
+ if (useModelSocket && model_sock) {
+ SECStatus rv;
+ ssl_sock = SSL_ImportFD(model_sock, tcp_sock);
+ if (!ssl_sock) {
+ errWarn("SSL_ImportFD with model");
+ goto cleanup;
+ }
+ rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 1);
+ if (rv != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ goto cleanup;
+ }
+ } else {
+ ssl_sock = tcp_sock;
+ }
+
+ if (noDelay) {
+ opt.option = PR_SockOpt_NoDelay;
+ opt.value.no_delay = PR_TRUE;
+ status = PR_SetSocketOption(ssl_sock, &opt);
+ if (status != PR_SUCCESS) {
+ errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)");
+ PR_Close(ssl_sock);
+ return SECFailure;
+ }
+ }
+
+ while (1) {
+ newln = 0;
+ reqLen = 0;
+ rv = PR_Read(ssl_sock, pBuf, bufRem);
+ if (rv == 0 ||
+ (rv < 0 && PR_END_OF_FILE_ERROR == PR_GetError())) {
+ if (verbose)
+ errWarn("HDX PR_Read hit EOF");
+ break;
+ }
+ if (rv < 0) {
+ errWarn("HDX PR_Read");
+ goto cleanup;
+ }
+ if (firstTime) {
+ firstTime = 0;
+ printSecurityInfo(ssl_sock);
+ }
+
+ pBuf += rv;
+ bufRem -= rv;
+ bufDat = pBuf - buf;
+ /* Parse the input, starting at the beginning of the buffer.
+ * Stop when we detect two consecutive \n's (or \r\n's)
+ * as this signifies the end of the GET or POST portion.
+ * The posted data follows.
+ */
+ while (reqLen < bufDat && newln < 2) {
+ int octet = buf[reqLen++];
+ if (octet == '\n') {
+ newln++;
+ } else if (octet != '\r') {
+ newln = 0;
+ }
+ }
+
+ /* came to the end of the buffer, or second newln
+ * If we didn't get an empty line (CRLFCRLF) then keep on reading.
+ */
+ if (newln < 2)
+ continue;
+
+ /* we're at the end of the HTTP request.
+ * If the request is a POST, then there will be one more
+ * line of data.
+ * This parsing is a hack, but ok for SSL test purposes.
+ */
+ post = PORT_Strstr(buf, "POST ");
+ if (!post || *post != 'P')
+ break;
+
+ /* It's a post, so look for the next and final CR/LF. */
+ /* We should parse content length here, but ... */
+ while (reqLen < bufDat && newln < 3) {
+ int octet = buf[reqLen++];
+ if (octet == '\n') {
+ newln++;
+ }
+ }
+ if (newln == 3)
+ break;
+ } /* read loop */
+
+ bufDat = pBuf - buf;
+ if (bufDat) do { /* just close if no data */
+ /* Have either (a) a complete get, (b) a complete post, (c) EOF */
+ if (reqLen > 0 && !strncmp(buf, getCmd, sizeof getCmd - 1)) {
+ char * fnBegin = buf + 4;
+ char * fnEnd;
+ PRFileInfo info;
+ /* try to open the file named.
+ * If succesful, then write it to the client.
+ */
+ fnEnd = strpbrk(fnBegin, " \r\n");
+ if (fnEnd) {
+ int fnLen = fnEnd - fnBegin;
+ if (fnLen < sizeof fileName) {
+ strncpy(fileName, fnBegin, fnLen);
+ fileName[fnLen] = 0; /* null terminate */
+ status = PR_GetFileInfo(fileName, &info);
+ if (status == PR_SUCCESS &&
+ info.type == PR_FILE_FILE &&
+ info.size >= 0 ) {
+ local_file_fd = PR_Open(fileName, PR_RDONLY, 0);
+ }
+ }
+ }
+ }
+ /* if user has requested client auth in a subsequent handshake,
+ * do it here.
+ */
+ if (requestCert > 2) { /* request cert was 3 or 4 */
+ CERTCertificate * cert = SSL_PeerCertificate(ssl_sock);
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ } else {
+ rv = SSL_OptionSet(ssl_sock, SSL_REQUEST_CERTIFICATE, 1);
+ if (rv < 0) {
+ errWarn("second SSL_OptionSet SSL_REQUEST_CERTIFICATE");
+ break;
+ }
+ rv = SSL_OptionSet(ssl_sock, SSL_REQUIRE_CERTIFICATE,
+ (requestCert == 4));
+ if (rv < 0) {
+ errWarn("second SSL_OptionSet SSL_REQUIRE_CERTIFICATE");
+ break;
+ }
+ rv = SSL_ReHandshake(ssl_sock, PR_TRUE);
+ if (rv != 0) {
+ errWarn("SSL_ReHandshake");
+ break;
+ }
+ rv = SSL_ForceHandshake(ssl_sock);
+ if (rv < 0) {
+ errWarn("SSL_ForceHandshake");
+ break;
+ }
+ }
+ }
+
+ numIOVs = 0;
+
+ iovs[numIOVs].iov_base = (char *)outHeader;
+ iovs[numIOVs].iov_len = (sizeof(outHeader)) - 1;
+ numIOVs++;
+
+ if (local_file_fd) {
+ PRInt32 bytes;
+ int errLen;
+ bytes = PR_TransmitFile(ssl_sock, local_file_fd, outHeader,
+ sizeof outHeader - 1,
+ PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytes >= 0) {
+ bytes -= sizeof outHeader - 1;
+ FPRINTF(stderr,
+ "selfserv: PR_TransmitFile wrote %d bytes from %s\n",
+ bytes, fileName);
+ break;
+ }
+ errString = errWarn("PR_TransmitFile");
+ errLen = PORT_Strlen(errString);
+ if (errLen > sizeof msgBuf - 1)
+ errLen = sizeof msgBuf - 1;
+ PORT_Memcpy(msgBuf, errString, errLen);
+ msgBuf[errLen] = 0;
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ } else if (reqLen <= 0) { /* hit eof */
+ PORT_Sprintf(msgBuf, "Get or Post incomplete after %d bytes.\r\n",
+ bufDat);
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ } else if (reqLen < bufDat) {
+ PORT_Sprintf(msgBuf, "Discarded %d characters.\r\n",
+ bufDat - reqLen);
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ }
+
+ if (reqLen > 0) {
+ if (verbose > 1)
+ fwrite(buf, 1, reqLen, stdout); /* display it */
+
+ iovs[numIOVs].iov_base = buf;
+ iovs[numIOVs].iov_len = reqLen;
+ numIOVs++;
+
+/* printSecurityInfo(ssl_sock); */
+ }
+
+ iovs[numIOVs].iov_base = (char *)EOFmsg;
+ iovs[numIOVs].iov_len = sizeof EOFmsg - 1;
+ numIOVs++;
+
+ rv = PR_Writev(ssl_sock, iovs, numIOVs, PR_INTERVAL_NO_TIMEOUT);
+ if (rv < 0) {
+ errWarn("PR_Writev");
+ break;
+ }
+ } while (0);
+
+cleanup:
+ PR_Close(ssl_sock);
+ if (local_file_fd)
+ PR_Close(local_file_fd);
+ VLOG(("selfserv: handle_connection: exiting\n"));
+
+ /* do a nice shutdown if asked. */
+ if (!strncmp(buf, stopCmd, sizeof stopCmd - 1)) {
+ stopping = 1;
+ VLOG(("selfserv: handle_connection: stop command"));
+ PR_Interrupt(acceptorThread);
+ PZ_TraceFlush();
+ }
+ VLOG(("selfserv: handle_connection: exiting"));
+ return SECSuccess; /* success */
+}
+
+SECStatus
+do_accepts(
+ PRFileDesc *listen_sock,
+ PRFileDesc *model_sock,
+ int requestCert
+ )
+{
+ PRNetAddr addr;
+ PRErrorCode perr;
+
+ VLOG(("selfserv: do_accepts: starting"));
+ PR_SetThreadPriority( PR_GetCurrentThread(), PR_PRIORITY_HIGH);
+
+ acceptorThread = PR_GetCurrentThread();
+ while (!stopping) {
+ PRFileDesc *tcp_sock;
+ PRCList *myLink;
+
+ FPRINTF(stderr, "\n\n\nselfserv: About to call accept.\n");
+ tcp_sock = PR_Accept(listen_sock, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (tcp_sock == NULL) {
+ perr = PR_GetError();
+ if ((perr != PR_CONNECT_RESET_ERROR &&
+ perr != PR_PENDING_INTERRUPT_ERROR) || verbose) {
+ errWarn("PR_Accept");
+ }
+ if (perr == PR_CONNECT_RESET_ERROR) {
+ FPRINTF(stderr,
+ "Ignoring PR_CONNECT_RESET_ERROR error - continue\n");
+ continue;
+ }
+ stopping = 1;
+ break;
+ }
+
+ VLOG(("selfserv: do_accept: Got connection\n"));
+
+ if (logStats) {
+ loggerOps++;
+ }
+
+ PZ_Lock(qLock);
+ while (PR_CLIST_IS_EMPTY(&freeJobs) && !stopping) {
+ PZ_WaitCondVar(freeListNotEmptyCv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ if (stopping) {
+ PZ_Unlock(qLock);
+ PR_Close(tcp_sock);
+ break;
+ }
+ myLink = PR_LIST_HEAD(&freeJobs);
+ PR_REMOVE_AND_INIT_LINK(myLink);
+ /* could release qLock here and reaquire it 7 lines below, but
+ ** why bother for 4 assignment statements?
+ */
+ {
+ JOB * myJob = (JOB *)myLink;
+ myJob->tcp_sock = tcp_sock;
+ myJob->model_sock = model_sock;
+ myJob->requestCert = requestCert;
+ }
+
+ PR_APPEND_LINK(myLink, &jobQ);
+ PZ_NotifyCondVar(jobQNotEmptyCv);
+ PZ_Unlock(qLock);
+ }
+
+ FPRINTF(stderr, "selfserv: Closing listen socket.\n");
+ VLOG(("selfserv: do_accepts: exiting"));
+ PR_Close(listen_sock);
+ return SECSuccess;
+}
+
+PRFileDesc *
+getBoundListenSocket(unsigned short port)
+{
+ PRFileDesc * listen_sock;
+ int listenQueueDepth = 5 + (2 * maxThreads);
+ PRStatus prStatus;
+ PRNetAddr addr;
+ PRSocketOptionData opt;
+
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_INADDR_ANY;
+ addr.inet.port = PR_htons(port);
+
+ listen_sock = PR_NewTCPSocket();
+ if (listen_sock == NULL) {
+ errExit("PR_NewTCPSocket");
+ }
+
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ prStatus = PR_SetSocketOption(listen_sock, &opt);
+ if (prStatus < 0) {
+ errExit("PR_SetSocketOption(PR_SockOpt_Nonblocking)");
+ }
+
+ opt.option=PR_SockOpt_Reuseaddr;
+ opt.value.reuse_addr = PR_TRUE;
+ prStatus = PR_SetSocketOption(listen_sock, &opt);
+ if (prStatus < 0) {
+ errExit("PR_SetSocketOption(PR_SockOpt_Reuseaddr)");
+ }
+
+ prStatus = PR_Bind(listen_sock, &addr);
+ if (prStatus < 0) {
+ errExit("PR_Bind");
+ }
+
+ prStatus = PR_Listen(listen_sock, listenQueueDepth);
+ if (prStatus < 0) {
+ errExit("PR_Listen");
+ }
+ return listen_sock;
+}
+
+void
+server_main(
+ PRFileDesc * listen_sock,
+ int requestCert,
+ SECKEYPrivateKey ** privKey,
+ CERTCertificate ** cert)
+{
+ PRFileDesc *model_sock = NULL;
+ int rv;
+ SSLKEAType kea;
+ SECStatus secStatus;
+
+ if (useModelSocket) {
+ model_sock = PR_NewTCPSocket();
+ if (model_sock == NULL) {
+ errExit("PR_NewTCPSocket on model socket");
+ }
+ model_sock = SSL_ImportFD(NULL, model_sock);
+ if (model_sock == NULL) {
+ errExit("SSL_ImportFD");
+ }
+ } else {
+ model_sock = listen_sock = SSL_ImportFD(NULL, listen_sock);
+ if (listen_sock == NULL) {
+ errExit("SSL_ImportFD");
+ }
+ }
+
+ /* do SSL configuration. */
+ /* all suites except RSA_NULL_MD5 are enabled by default */
+
+#if 0
+ /* This is supposed to be true by default.
+ ** Setting it explicitly should not be necessary.
+ ** Let's test and make sure that's true.
+ */
+ rv = SSL_OptionSet(model_sock, SSL_SECURITY, 1);
+ if (rv < 0) {
+ errExit("SSL_OptionSet SSL_SECURITY");
+ }
+#endif
+
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_SSL3, !disableSSL3);
+ if (rv != SECSuccess) {
+ errExit("error enabling SSLv3 ");
+ }
+
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_TLS, !disableTLS);
+ if (rv != SECSuccess) {
+ errExit("error enabling TLS ");
+ }
+
+ rv = SSL_OptionSet(model_sock, SSL_ROLLBACK_DETECTION, !disableRollBack);
+ if (rv != SECSuccess) {
+ errExit("error enabling RollBack detection ");
+ }
+
+ for (kea = kt_rsa; kea < kt_kea_size; kea++) {
+ if (cert[kea] != NULL) {
+ secStatus = SSL_ConfigSecureServer(model_sock,
+ cert[kea], privKey[kea], kea);
+ if (secStatus != SECSuccess)
+ errExit("SSL_ConfigSecureServer");
+ }
+ }
+
+ if (bigBuf.data) { /* doing FDX */
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1);
+ if (rv < 0) {
+ errExit("SSL_OptionSet SSL_ENABLE_FDX");
+ }
+ }
+
+ /* This cipher is not on by default. The Acceptance test
+ * would like it to be. Turn this cipher on.
+ */
+
+ secStatus = SSL_CipherPrefSetDefault( SSL_RSA_WITH_NULL_MD5, PR_TRUE);
+ if ( secStatus != SECSuccess ) {
+ errExit("SSL_CipherPrefSetDefault:SSL_RSA_WITH_NULL_MD5");
+ }
+
+
+ if (requestCert) {
+ SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate,
+ (void *)CERT_GetDefaultCertDB());
+ if (requestCert <= 2) {
+ rv = SSL_OptionSet(model_sock, SSL_REQUEST_CERTIFICATE, 1);
+ if (rv < 0) {
+ errExit("first SSL_OptionSet SSL_REQUEST_CERTIFICATE");
+ }
+ rv = SSL_OptionSet(model_sock, SSL_REQUIRE_CERTIFICATE,
+ (requestCert == 2));
+ if (rv < 0) {
+ errExit("first SSL_OptionSet SSL_REQUIRE_CERTIFICATE");
+ }
+ }
+ }
+
+ if (MakeCertOK)
+ SSL_BadCertHook(model_sock, myBadCertHandler, NULL);
+
+ /* end of ssl configuration. */
+
+
+ /* Now, do the accepting, here in the main thread. */
+ rv = do_accepts(listen_sock, model_sock, requestCert);
+
+ terminateWorkerThreads();
+
+ if (useModelSocket && model_sock) {
+ PR_Close(model_sock);
+ }
+
+}
+
+SECStatus
+readBigFile(const char * fileName)
+{
+ PRFileInfo info;
+ PRStatus status;
+ SECStatus rv = SECFailure;
+ int count;
+ int hdrLen;
+ PRFileDesc *local_file_fd = NULL;
+
+ status = PR_GetFileInfo(fileName, &info);
+
+ if (status == PR_SUCCESS &&
+ info.type == PR_FILE_FILE &&
+ info.size > 0 &&
+ NULL != (local_file_fd = PR_Open(fileName, PR_RDONLY, 0))) {
+
+ hdrLen = PORT_Strlen(outHeader);
+ bigBuf.len = hdrLen + info.size;
+ bigBuf.data = PORT_Malloc(bigBuf.len + 4095);
+ if (!bigBuf.data) {
+ errWarn("PORT_Malloc");
+ goto done;
+ }
+
+ PORT_Memcpy(bigBuf.data, outHeader, hdrLen);
+
+ count = PR_Read(local_file_fd, bigBuf.data + hdrLen, info.size);
+ if (count != info.size) {
+ errWarn("PR_Read local file");
+ goto done;
+ }
+ rv = SECSuccess;
+done:
+ PR_Close(local_file_fd);
+ }
+ return rv;
+}
+
+int numChildren;
+PRProcess * child[MAX_PROCS];
+
+PRProcess *
+haveAChild(int argc, char **argv, PRProcessAttr * attr)
+{
+ PRProcess * newProcess;
+
+ newProcess = PR_CreateProcess(argv[0], argv, NULL, attr);
+ if (!newProcess) {
+ errWarn("Can't create new process.");
+ } else {
+ child[numChildren++] = newProcess;
+ }
+ return newProcess;
+}
+
+void
+beAGoodParent(int argc, char **argv, int maxProcs, PRFileDesc * listen_sock)
+{
+ PRProcess * newProcess;
+ PRProcessAttr * attr;
+ int i;
+ PRInt32 exitCode;
+ PRStatus rv;
+
+ rv = PR_SetFDInheritable(listen_sock, PR_TRUE);
+ if (rv != PR_SUCCESS)
+ errExit("PR_SetFDInheritable");
+
+ attr = PR_NewProcessAttr();
+ if (!attr)
+ errExit("PR_NewProcessAttr");
+
+ rv = PR_ProcessAttrSetInheritableFD(attr, listen_sock, inheritableSockName);
+ if (rv != PR_SUCCESS)
+ errExit("PR_ProcessAttrSetInheritableFD");
+
+ for (i = 0; i < maxProcs; ++i) {
+ newProcess = haveAChild(argc, argv, attr);
+ if (!newProcess)
+ break;
+ }
+
+ rv = PR_SetFDInheritable(listen_sock, PR_FALSE);
+ if (rv != PR_SUCCESS)
+ errExit("PR_SetFDInheritable");
+
+ while (numChildren > 0) {
+ newProcess = child[numChildren - 1];
+ PR_WaitProcess(newProcess, &exitCode);
+ fprintf(stderr, "Child %d exited with exit code %x\n",
+ numChildren, exitCode);
+ numChildren--;
+ }
+ exit(0);
+}
+
+#ifdef DEBUG_nelsonb
+
+#if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
+#define SSL_GETPID getpid
+#elif defined(_WIN32_WCE)
+#define SSL_GETPID GetCurrentProcessId
+#elif defined(WIN32)
+extern int __cdecl _getpid(void);
+#define SSL_GETPID _getpid
+#else
+#define SSL_GETPID() 0
+#endif
+
+void
+WaitForDebugger(void)
+{
+
+ int waiting = 12;
+ int myPid = SSL_GETPID();
+ PRIntervalTime nrval = PR_SecondsToInterval(5);
+
+ while (waiting) {
+ printf("child %d is waiting to be debugged!\n", myPid);
+ PR_Sleep(nrval);
+ --waiting;
+ }
+}
+#endif
+
+int
+main(int argc, char **argv)
+{
+ char * progName = NULL;
+ char * nickName = NULL;
+ char * fNickName = NULL;
+ const char * fileName = NULL;
+ char * cipherString= NULL;
+ const char * dir = ".";
+ char * passwd = NULL;
+ const char * pidFile = NULL;
+ char * tmp;
+ char * envString;
+ PRFileDesc * listen_sock;
+ CERTCertificate * cert [kt_kea_size] = { NULL };
+ SECKEYPrivateKey * privKey[kt_kea_size] = { NULL };
+ int optionsFound = 0;
+ int maxProcs = 1;
+ unsigned short port = 0;
+ SECStatus rv;
+ PRStatus prStatus;
+ PRBool bindOnly = PR_FALSE;
+ PRBool useExportPolicy = PR_FALSE;
+ PRBool useLocalThreads = PR_FALSE;
+ PLOptState *optstate;
+ PLOptStatus status;
+ PRThread *loggerThread;
+ PRBool debugCache = PR_FALSE; /* bug 90518 */
+
+
+ tmp = strrchr(argv[0], '/');
+ tmp = tmp ? tmp + 1 : argv[0];
+ progName = strrchr(tmp, '\\');
+ progName = progName ? progName + 1 : tmp;
+
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ /* please keep this list of options in ASCII collating sequence.
+ ** numbers, then capital letters, then lower case, alphabetical.
+ */
+ optstate = PL_CreateOptState(argc, argv,
+ "2:3DL:M:RTbc:d:f:hi:lmn:op:rt:vw:xy");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ ++optionsFound;
+ switch(optstate->option) {
+ case '2': fileName = optstate->value; break;
+
+ case '3': disableSSL3 = PR_TRUE; break;
+
+ case 'D': noDelay = PR_TRUE; break;
+
+ case 'L':
+ logStats = PR_TRUE;
+ if (optstate->value == NULL) {
+ logPeriod = 30;
+ } else {
+ logPeriod = PORT_Atoi(optstate->value);
+ if (logPeriod <= 0) logPeriod = 30;
+ }
+ break;
+
+ case 'M':
+ maxProcs = PORT_Atoi(optstate->value);
+ if (maxProcs < 1) maxProcs = 1;
+ if (maxProcs > MAX_PROCS) maxProcs = MAX_PROCS;
+ break;
+
+ case 'R': disableRollBack = PR_TRUE; break;
+
+ case 'T': disableTLS = PR_TRUE; break;
+
+ case 'b': bindOnly = PR_TRUE; break;
+
+ case 'c': cipherString = strdup(optstate->value); break;
+
+ case 'd': dir = optstate->value; break;
+
+ case 'f': fNickName = strdup(optstate->value); break;
+
+ case 'h': Usage(progName); exit(0); break;
+
+ case 'i': pidFile = optstate->value; break;
+
+ case 'l': useLocalThreads = PR_TRUE; break;
+
+ case 'm': useModelSocket = PR_TRUE; break;
+
+ case 'n': nickName = strdup(optstate->value); break;
+
+ case 'o': MakeCertOK = 1; break;
+
+ case 'p': port = PORT_Atoi(optstate->value); break;
+
+ case 'r': ++requestCert; break;
+
+ case 't':
+ maxThreads = PORT_Atoi(optstate->value);
+ if ( maxThreads > MAX_THREADS ) maxThreads = MAX_THREADS;
+ if ( maxThreads < MIN_THREADS ) maxThreads = MIN_THREADS;
+ break;
+
+ case 'v': verbose++; break;
+
+ case 'w': passwd = strdup(optstate->value); break;
+
+ case 'x': useExportPolicy = PR_TRUE; break;
+
+ case 'y': debugCache = PR_TRUE; break;
+
+ default:
+ case '?':
+ fprintf(stderr, "Unrecognized or bad option specified.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(4);
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+ if (status == PL_OPT_BAD) {
+ fprintf(stderr, "Unrecognized or bad option specified.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(5);
+ }
+ if (!optionsFound) {
+ Usage(progName);
+ exit(51);
+ }
+
+ /* The -b (bindOnly) option is only used by the ssl.sh test
+ * script on Linux to determine whether a previous selfserv
+ * process has fully died and freed the port. (Bug 129701)
+ */
+ if (bindOnly) {
+ listen_sock = getBoundListenSocket(port);
+ if (!listen_sock) {
+ exit(1);
+ }
+ PR_Close(listen_sock);
+ exit(0);
+ }
+
+ if ((nickName == NULL) && (fNickName == NULL)) {
+ fprintf(stderr, "Required arg '-n' (rsa nickname) not supplied.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(6);
+ }
+
+ if (port == 0) {
+ fprintf(stderr, "Required argument 'port' must be non-zero value\n");
+ exit(7);
+ }
+
+ if (pidFile) {
+ FILE *tmpfile=fopen(pidFile,"w+");
+
+ if (tmpfile) {
+ fprintf(tmpfile,"%d",getpid());
+ fclose(tmpfile);
+ }
+ }
+
+ envString = getenv(envVarName);
+ tmp = getenv("TMP");
+ if (!tmp)
+ tmp = getenv("TMPDIR");
+ if (!tmp)
+ tmp = getenv("TEMP");
+ if (envString) {
+ /* we're one of the children in a multi-process server. */
+ listen_sock = PR_GetInheritedFD(inheritableSockName);
+ if (!listen_sock)
+ errExit("PR_GetInheritedFD");
+#ifndef WINNT
+ /* we can't do this on NT because it breaks NSPR and
+ PR_Accept will fail on the socket in the child process if
+ the socket state is change to non inheritable
+ It is however a security issue to leave it accessible,
+ but it is OK for a test server such as selfserv.
+ NSPR should fix it eventually . see bugzilla 101617
+ and 102077
+ */
+ prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE);
+ if (prStatus != PR_SUCCESS)
+ errExit("PR_SetFDInheritable");
+#endif
+#ifdef DEBUG_nelsonb
+ WaitForDebugger();
+#endif
+ rv = SSL_InheritMPServerSIDCache(envString);
+ if (rv != SECSuccess)
+ errExit("SSL_InheritMPServerSIDCache");
+ } else if (maxProcs > 1) {
+ /* we're going to be the parent in a multi-process server. */
+ listen_sock = getBoundListenSocket(port);
+ rv = SSL_ConfigMPServerSIDCache(NUM_SID_CACHE_ENTRIES, 0, 0, tmp);
+ if (rv != SECSuccess)
+ errExit("SSL_ConfigMPServerSIDCache");
+ beAGoodParent(argc, argv, maxProcs, listen_sock);
+ exit(99); /* should never get here */
+ } else {
+ /* we're an ordinary single process server. */
+ listen_sock = getBoundListenSocket(port);
+ prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE);
+ if (prStatus != PR_SUCCESS)
+ errExit("PR_SetFDInheritable");
+ rv = SSL_ConfigServerSessionIDCache(NUM_SID_CACHE_ENTRIES, 0, 0, tmp);
+ if (rv != SECSuccess)
+ errExit("SSL_ConfigServerSessionIDCache");
+ }
+
+ lm = PR_NewLogModule("TestCase");
+
+ if (fileName)
+ readBigFile(fileName);
+
+ /* set our password function */
+ PK11_SetPasswordFunc( passwd ? ownPasswd : SECU_GetModulePassword);
+
+ /* Call the libsec initialization routines */
+ rv = NSS_Init(dir);
+ if (rv != SECSuccess) {
+ fputs("NSS_Init failed.\n", stderr);
+ exit(8);
+ }
+
+ /* set the policy bits true for all the cipher suites. */
+ if (useExportPolicy)
+ NSS_SetExportPolicy();
+ else
+ NSS_SetDomesticPolicy();
+
+ /* all the SSL2 and SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ int ndx;
+
+ /* disable all the ciphers, then enable the ones we want. */
+ disableAllSSLCiphers();
+
+ while (0 != (ndx = *cipherString++)) {
+ const int *cptr;
+ int cipher;
+
+ if (! isalpha(ndx)) {
+ fprintf(stderr,
+ "Non-alphabetic char in cipher string (-c arg).\n");
+ exit(9);
+ }
+ cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
+ for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
+ /* do nothing */;
+ if (cipher) {
+ SECStatus status;
+ status = SSL_CipherPrefSetDefault(cipher, SSL_ALLOWED);
+ if (status != SECSuccess)
+ SECU_PrintError(progName, "SSL_CipherPrefSet()");
+ }
+ }
+ }
+
+ if (nickName) {
+ cert[kt_rsa] = PK11_FindCertFromNickname(nickName, passwd);
+ if (cert[kt_rsa] == NULL) {
+ fprintf(stderr, "selfserv: Can't find certificate %s\n", nickName);
+ exit(10);
+ }
+ privKey[kt_rsa] = PK11_FindKeyByAnyCert(cert[kt_rsa], passwd);
+ if (privKey[kt_rsa] == NULL) {
+ fprintf(stderr, "selfserv: Can't find Private Key for cert %s\n",
+ nickName);
+ exit(11);
+ }
+ }
+ if (fNickName) {
+ cert[kt_fortezza] = PK11_FindCertFromNickname(fNickName, NULL);
+ if (cert[kt_fortezza] == NULL) {
+ fprintf(stderr, "selfserv: Can't find certificate %s\n", fNickName);
+ exit(12);
+ }
+ privKey[kt_fortezza] = PK11_FindKeyByAnyCert(cert[kt_fortezza], NULL);
+ }
+
+ /* allocate the array of thread slots, and launch the worker threads. */
+ rv = launch_threads(&jobLoop, 0, 0, requestCert, useLocalThreads);
+
+ if (rv == SECSuccess && logStats) {
+ loggerThread = PR_CreateThread(PR_SYSTEM_THREAD,
+ logger, NULL, PR_PRIORITY_NORMAL,
+ useLocalThreads ? PR_LOCAL_THREAD:PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (loggerThread == NULL) {
+ fprintf(stderr, "selfserv: Failed to launch logger thread!\n");
+ rv = SECFailure;
+ }
+ }
+
+ if (rv == SECSuccess) {
+ server_main(listen_sock, requestCert, privKey, cert);
+ }
+
+ VLOG(("selfserv: server_thread: exiting"));
+
+ {
+ int i;
+ for (i=0; i<kt_kea_size; i++) {
+ if (cert[i]) {
+ CERT_DestroyCertificate(cert[i]);
+ }
+ if (privKey[i]) {
+ SECKEY_DestroyPrivateKey(privKey[i]);
+ }
+ }
+ }
+
+ if (debugCache) {
+ nss_DumpCertificateCacheInfo();
+ }
+
+ free(nickName);
+ free(passwd);
+
+ SSL_ShutdownServerSessionIDCache();
+
+ if (NSS_Shutdown() != SECSuccess) {
+ SECU_PrintError(progName, "NSS_Shutdown");
+ PR_Cleanup();
+ exit(1);
+ }
+ PR_Cleanup();
+ printf("selfserv: normal termination\n");
+ return 0;
+}
diff --git a/security/nss/cmd/shlibsign/Makefile b/security/nss/cmd/shlibsign/Makefile
new file mode 100644
index 000000000..11b458de9
--- /dev/null
+++ b/security/nss/cmd/shlibsign/Makefile
@@ -0,0 +1,110 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#
+# we really should have this driven from a list file made during the normal
+# NSS build prodecure.
+#
+ifndef USE_64
+ifeq ($(OS_TARGET), HP-UX)
+ ifneq ($(OS_TEST), ia64)
+ LOADABLE_FREEBL= 1
+ endif
+endif
+ifeq ($(OS_TARGET), SunOS)
+ ifeq ($(CPU_ARCH), sparc)
+ LOADABLE_FREEBL = 1
+ endif
+endif
+endif
+
+ifdef LOADABLE_FREEBL
+ CHECKFILES += freebl_pure32_3.chk freebl_hybrid_3.chk
+endif
+
+CHECKLOC=$(addprefix $(DIST)/lib/$(DLL_PREFIX), $(CHECKFILES))
+
+MD_LIB_RELEASE_FILES = $(CHECKLOC)
+ALL_TRASH += $(CHECKLOC)
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
+%.chk: %.$(DLL_SUFFIX)
+ifeq ($(OS_TARGET), OS2)
+ @cmd.exe /c sign.cmd $(DIST) $(OBJDIR) $(OS_TARGET) $<
+else
+ @sh ./sign.sh $(DIST) $(OBJDIR) $(OS_TARGET) $<
+endif
+
+libs install :: $(CHECKLOC)
+
diff --git a/security/nss/cmd/shlibsign/mangle/Makefile b/security/nss/cmd/shlibsign/mangle/Makefile
new file mode 100644
index 000000000..7948a4328
--- /dev/null
+++ b/security/nss/cmd/shlibsign/mangle/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../../platrules.mk
+
diff --git a/security/nss/cmd/shlibsign/mangle/mangle.c b/security/nss/cmd/shlibsign/mangle/mangle.c
new file mode 100644
index 000000000..7ff34b5e6
--- /dev/null
+++ b/security/nss/cmd/shlibsign/mangle/mangle.c
@@ -0,0 +1,166 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2003 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * Test program to mangle 1 bit in a binary
+ *
+ * $Id$
+ */
+
+#include "nspr.h"
+#include "plstr.h"
+#include "plgetopt.h"
+#include "prio.h"
+
+static PRFileDesc *pr_stderr;
+static void
+usage (char *program_name)
+{
+
+ PR_fprintf (pr_stderr, "Usage:");
+ PR_fprintf (pr_stderr, "%s -i shared_library_name -o byte_offset -b bit\n", program_name);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ /* buffers and locals */
+ PLOptState *optstate;
+ char *programName;
+ char cbuf;
+
+ /* parameter set variables */
+ const char *libFile = NULL;
+ int offset = -1;
+ int bitOffset = -1;
+
+ /* return values */
+ int retval = 2; /* 0 - test succeeded.
+ * 1 - illegal args
+ * 2 - function failed */
+ PRFileDesc *fd;
+ int bytesRead;
+ int bytesWritten;
+ int pos;
+
+ programName = PL_strrchr(argv[0], '/');
+ programName = programName ? (programName + 1) : argv[0];
+
+ pr_stderr = PR_STDERR;
+
+ optstate = PL_CreateOptState (argc, argv, "i:o:b:");
+ if (optstate == NULL) {
+ return 1;
+ }
+
+ while (PL_GetNextOpt (optstate) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'i':
+ libFile = optstate->value;
+ break;
+
+ case 'o':
+ offset = atoi(optstate->value);
+ break;
+
+ case 'b':
+ bitOffset = atoi(optstate->value);
+ break;
+ }
+ }
+
+ if (libFile == NULL) {
+ usage(programName);
+ return 1;
+ }
+ if ((bitOffset >= 8) || (bitOffset < 0)) {
+ usage(programName);
+ return 1;
+ }
+
+ if (offset < 0) {
+ usage(programName);
+ return 1;
+ }
+
+ /* open the target signature file */
+ fd = PR_OpenFile(libFile,PR_RDWR,0666);
+ if (fd == NULL ) {
+ /* lperror(libFile); */
+ PR_fprintf(pr_stderr,"Couldn't Open %s\n",libFile);
+ goto loser;
+ }
+
+ /* read the byte */
+ pos = PR_Seek(fd, offset, PR_SEEK_SET);
+ if (pos != offset) {
+ PR_fprintf(pr_stderr,"Seek for read on %s (to %d) failed\n", libFile, offset);
+ goto loser;
+ }
+ bytesRead = PR_Read(fd, &cbuf, 1);
+ if (bytesRead != 1) {
+ PR_fprintf(pr_stderr,"Read on %s (to %d) failed\n", libFile, offset);
+ goto loser;
+ }
+
+ PR_fprintf(pr_stderr,"Changing byte 0x%08x (%d): from %02x (%d) to ",
+ offset, offset, (unsigned char)cbuf, (unsigned char)cbuf);
+ /* change it */
+ cbuf ^= 1 << bitOffset;
+ PR_fprintf(pr_stderr,"%02x (%d)\n", (
+ unsigned char)cbuf, (unsigned char)cbuf);
+
+ /* write it back out */
+ pos = PR_Seek(fd, offset, PR_SEEK_SET);
+ if (pos != offset) {
+ PR_fprintf(pr_stderr,"Seek for write on %s (to %d) failed\n", libFile, offset);
+ goto loser;
+ }
+ bytesWritten = PR_Write(fd, &cbuf, 1);
+ if (bytesWritten != 1) {
+ PR_fprintf(pr_stderr,"Write on %s (to %d) failed\n", libFile, offset);
+ goto loser;
+ }
+
+ PR_Close(fd);
+ retval = 0;
+
+
+loser:
+
+ PR_Cleanup ();
+ return retval;
+}
+
+/*#DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" */
diff --git a/security/nss/cmd/shlibsign/mangle/manifest.mn b/security/nss/cmd/shlibsign/mangle/manifest.mn
new file mode 100644
index 000000000..d850921f0
--- /dev/null
+++ b/security/nss/cmd/shlibsign/mangle/manifest.mn
@@ -0,0 +1,52 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\"
+
+CSRCS = \
+ mangle.c \
+ $(NULL)
+
+
+# headers for the MODULE (defined above) are implicitly required.
+REQUIRES =
+
+PROGRAM = mangle
+
+USE_STATIC_LIBS = 1
+
diff --git a/security/nss/cmd/shlibsign/manifest.mn b/security/nss/cmd/shlibsign/manifest.mn
new file mode 100644
index 000000000..40cdeeff1
--- /dev/null
+++ b/security/nss/cmd/shlibsign/manifest.mn
@@ -0,0 +1,60 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\"
+
+CSRCS = \
+ shlibsign.c \
+ $(NULL)
+
+CHECKFILES = softokn3.chk
+
+# headers for the MODULE (defined above) are implicitly required.
+REQUIRES = dbm seccmd
+
+# WINNT uses EXTRA_LIBS as the list of libs to link in.
+# Unix uses OS_LIBS for that purpose.
+# We can solve this via conditional makefile code, but
+# can't do this in manifest.mn because OS_ARCH isn't defined there.
+# So, look in the local Makefile for the defines for the list of libs.
+
+PROGRAM = shlibsign
+
+DIRS = mangle
+
+#USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/shlibsign/shlibsign.c b/security/nss/cmd/shlibsign/shlibsign.c
new file mode 100644
index 000000000..6d4af89b4
--- /dev/null
+++ b/security/nss/cmd/shlibsign/shlibsign.c
@@ -0,0 +1,427 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * Test program for SDR (Secret Decoder Ring) functions.
+ *
+ * $Id$
+ */
+
+#ifdef XP_UNIX
+#define USES_LINKS 1
+#endif
+
+#include "nspr.h"
+#include <stdio.h>
+#include "nss.h"
+#include "secutil.h"
+#include "cert.h"
+#include "pk11func.h"
+
+#include "plgetopt.h"
+#include "pk11sdr.h"
+#include "secrng.h"
+#include "shsign.h"
+#include "pk11pqg.h"
+
+#ifdef USES_LINKS
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+static void
+usage (char *program_name)
+{
+ PRFileDesc *pr_stderr;
+
+ pr_stderr = PR_STDERR;
+ PR_fprintf (pr_stderr, "Usage:");
+ PR_fprintf (pr_stderr, "%s [-v] -i shared_library_name\n", program_name);
+}
+
+static char *
+mkoutput(const char *input)
+{
+ int in_len = PORT_Strlen(input);
+ char *output = PORT_Alloc(in_len+sizeof(SGN_SUFFIX));
+ int index = in_len + 1 - sizeof("."SHLIB_SUFFIX);
+
+ if ((index > 0) &&
+ (PORT_Strncmp(&input[index],
+ "."SHLIB_SUFFIX,sizeof("."SHLIB_SUFFIX)) == 0)) {
+ in_len = index;
+ }
+ PORT_Memcpy(output,input,in_len);
+ PORT_Memcpy(&output[in_len],SGN_SUFFIX,sizeof(SGN_SUFFIX));
+ return output;
+}
+
+
+static void
+lperror(const char *string)
+{
+ int errNum = PORT_GetError();
+ const char *error = SECU_Strerror(errNum);
+ fprintf(stderr,"%s: %s\n",string, error);
+}
+
+static void
+encodeInt(unsigned char *buf, int val)
+{
+ buf[3] = (val >> 0) & 0xff;
+ buf[2] = (val >> 8) & 0xff;
+ buf[1] = (val >> 16) & 0xff;
+ buf[0] = (val >> 24) & 0xff;
+ return;
+}
+
+static SECStatus
+writeItem(PRFileDesc *fd, SECItem *item, char *file)
+{
+ unsigned char buf[4];
+ int bytesWritten;
+
+ encodeInt(buf,item->len);
+ bytesWritten = PR_Write(fd,buf, 4);
+ if (bytesWritten != 4) {
+ lperror(file);
+ return SECFailure;
+ }
+ bytesWritten = PR_Write(fd, item->data, item->len);
+ if (bytesWritten != item->len) {
+ lperror(file);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int retval = 1; /* 0 - test succeeded. 1 - test failed */
+ SECStatus rv;
+ PLOptState *optstate;
+ char *program_name;
+ const char *input_file = NULL; /* read encrypted data from here (or create) */
+ char *output_file = NULL; /* write new encrypted data here */
+ PRBool verbose = PR_FALSE;
+ SECKEYPrivateKey *privk = NULL;
+ SECKEYPublicKey *pubk = NULL;
+ PK11SlotInfo *slot = NULL;
+ PRFileDesc *fd;
+ int bytesRead;
+ int bytesWritten;
+ unsigned char file_buf[512];
+ unsigned char hash_buf[SHA1_LENGTH];
+ unsigned char sign_buf[40]; /* DSA_LENGTH */
+ SECItem hash,sign;
+ PK11Context *hashcx = NULL;
+ int ks, count=0;
+ int keySize = 1024;
+ PQGParams *pqgParams = NULL;
+ PQGVerify *pqgVerify = NULL;
+#ifdef USES_LINKS
+ int ret;
+ struct stat stat_buf;
+ char link_buf[MAXPATHLEN+1];
+ char *link_file = NULL;
+#endif
+
+ hash.len = sizeof(hash_buf); hash.data = hash_buf;
+ sign.len = sizeof(sign_buf); sign.data = sign_buf;
+
+ program_name = PL_strrchr(argv[0], '/');
+ program_name = program_name ? (program_name + 1) : argv[0];
+
+ optstate = PL_CreateOptState (argc, argv, "d:i:o:v");
+ if (optstate == NULL) {
+ SECU_PrintError (program_name, "PL_CreateOptState failed");
+ return 1;
+ }
+
+ while (PL_GetNextOpt (optstate) == PL_OPT_OK) {
+ switch (optstate->option) {
+#ifdef notdef
+ case '?':
+ short_usage (program_name);
+ return 0;
+
+ case 'H':
+ long_usage (program_name);
+ return 0;
+#endif
+
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+
+ case 'i':
+ input_file = optstate->value;
+ break;
+
+ case 'o':
+ output_file = PORT_Strdup(optstate->value);
+ break;
+
+ case 'v':
+ verbose = PR_TRUE;
+ break;
+ }
+ }
+
+ if (input_file == NULL) {
+ usage(program_name);
+ return 1;
+ }
+
+ /*
+ * Initialize the Security libraries.
+ */
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ rv = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (rv != SECSuccess) {
+ rv = NSS_NoDB_Init("");
+ }
+ if (rv != SECSuccess) {
+ lperror("NSS_Init failed");
+ goto prdone;
+ }
+
+ /* Generate a DSA Key pair */
+ slot = PK11_GetBestSlot(CKM_DSA,NULL);
+ if (slot == NULL) {
+ lperror("CKM_DSA");
+ goto loser;
+
+ }
+ printf("Generating DSA Key Pair...."); fflush(stdout);
+ ks = PQG_PBITS_TO_INDEX(keySize);
+ rv = PK11_PQG_ParamGen(ks,&pqgParams, &pqgVerify);
+ if (rv != SECSuccess) {
+ lperror("Generating PQG Params");
+ goto loser;
+ }
+ privk = PK11_GenerateKeyPair(slot, CKM_DSA_KEY_PAIR_GEN, pqgParams, &pubk,
+ PR_FALSE, PR_TRUE, NULL);
+ if (privk == NULL) {
+ lperror("Generating DSA Key");
+ goto loser;
+ }
+
+ printf("done\n");
+
+ /* open the shared library */
+ fd = PR_OpenFile(input_file,PR_RDONLY,0);
+ if (fd == NULL ) {
+ lperror(input_file);
+ goto loser;
+ }
+#ifdef USES_LINKS
+ ret = lstat(input_file, &stat_buf);
+ if (ret < 0) {
+ perror(input_file);
+ goto loser;
+ }
+ if (S_ISLNK(stat_buf.st_mode)) {
+ char *dirpath,*dirend;
+ ret = readlink(input_file, link_buf, sizeof(link_buf) - 1);
+ if (ret < 0) {
+ perror(input_file);
+ goto loser;
+ }
+ link_buf[ret] = 0;
+ link_file = mkoutput(input_file);
+ /* get the dirname of input_file */
+ dirpath = PORT_Strdup(input_file);
+ dirend = PORT_Strrchr(dirpath, '/');
+ if (dirend) {
+ *dirend = '\0';
+ ret = chdir(dirpath);
+ if (ret < 0) {
+ perror(dirpath);
+ goto loser;
+ }
+ }
+ PORT_Free(dirpath);
+ input_file = link_buf;
+ /* get the basename of link_file */
+ dirend = PORT_Strrchr(link_file, '/');
+ if (dirend) {
+ link_file = dirend + 1;
+ }
+ }
+#endif
+ if (output_file == NULL) {
+ output_file = mkoutput(input_file);
+ }
+
+ hashcx = PK11_CreateDigestContext(SEC_OID_SHA1);
+ if (hashcx == NULL) {
+ lperror("SHA1 Digest Create");
+ goto loser;
+ }
+
+ /* hash the file */
+ while ((bytesRead = PR_Read(fd,file_buf,sizeof(file_buf))) > 0) {
+ PK11_DigestOp(hashcx,file_buf,bytesRead);
+ count += bytesRead;
+ }
+
+ PR_Close(fd);
+ fd = NULL;
+ if (bytesRead < 0) {
+ lperror(input_file);
+ goto loser;
+ }
+
+
+ PK11_DigestFinal(hashcx, hash.data, &hash.len, hash.len);
+
+ if (hash.len != SHA1_LENGTH) {
+ fprintf(stderr, "Digest length was not correct\n");
+ goto loser;
+ }
+
+ /* signe the hash */
+ rv = PK11_Sign(privk,&sign,&hash);
+ if (rv != SECSuccess) {
+ lperror("Signing");
+ goto loser;
+ }
+
+ if (verbose) {
+ int i,j;
+ fprintf(stderr,"Library File: %s %d bytes\n",input_file, count);
+ fprintf(stderr,"Check File: %s\n",output_file);
+#ifdef USES_LINKS
+ if (link_file) {
+ fprintf(stderr,"Link: %s\n",link_file);
+ }
+#endif
+ fprintf(stderr," hash: %d bytes\n", hash.len);
+#define STEP 10
+ for (i=0; i < hash.len; i += STEP) {
+ fprintf(stderr," ");
+ for (j=0; j < STEP && (i+j) < hash.len; j++) {
+ fprintf(stderr," %02x", hash.data[i+j]);
+ }
+ fprintf(stderr,"\n");
+ }
+ fprintf(stderr," signature: %d bytes\n", sign.len);
+ for (i=0; i < sign.len; i += STEP) {
+ fprintf(stderr," ");
+ for (j=0; j < STEP && (i+j) < sign.len; j++) {
+ fprintf(stderr," %02x", sign.data[i+j]);
+ }
+ fprintf(stderr,"\n");
+ }
+ }
+
+ /* open the target signature file */
+ fd = PR_OpenFile(output_file,PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,0666);
+ if (fd == NULL ) {
+ lperror(output_file);
+ goto loser;
+ }
+
+ /*
+ * we write the key out in a straight binary format because very
+ * low level libraries need to read an parse this file. Ideally we should
+ * just derEncode the public key (which would be pretty simple, and be
+ * more general), but then we'd need to link the ASN.1 decoder with the
+ * freebl libraries.
+ */
+
+ file_buf[0] = NSS_SIGN_CHK_MAGIC1;
+ file_buf[1] = NSS_SIGN_CHK_MAGIC2;
+ file_buf[2] = NSS_SIGN_CHK_MAJOR_VERSION;
+ file_buf[3] = NSS_SIGN_CHK_MINOR_VERSION;
+ encodeInt(&file_buf[4],12); /* offset to data start */
+ encodeInt(&file_buf[8],CKK_DSA);
+ bytesWritten = PR_Write(fd,file_buf, 12);
+ if (bytesWritten != 12) {
+ lperror(output_file);
+ goto loser;
+ }
+
+ rv = writeItem(fd,&pubk->u.dsa.params.prime,output_file);
+ if (rv != SECSuccess) goto loser;
+ rv = writeItem(fd,&pubk->u.dsa.params.subPrime,output_file);
+ if (rv != SECSuccess) goto loser;
+ rv = writeItem(fd,&pubk->u.dsa.params.base,output_file);
+ if (rv != SECSuccess) goto loser;
+ rv = writeItem(fd,&pubk->u.dsa.publicValue,output_file);
+ if (rv != SECSuccess) goto loser;
+ rv = writeItem(fd,&sign,output_file);
+ if (rv != SECSuccess) goto loser;
+
+ PR_Close(fd);
+
+#ifdef USES_LINKS
+ if (link_file) {
+ (void)unlink(link_file);
+ ret = symlink(output_file, link_file);
+ if (ret < 0) {
+ perror(link_file);
+ goto loser;
+ }
+ }
+#endif
+
+ retval = 0;
+
+loser:
+ if (hashcx) {
+ PK11_DestroyContext(hashcx, PR_TRUE);
+ }
+ if (privk) {
+ SECKEY_DestroyPrivateKey(privk);
+ }
+ if (pubk) {
+ SECKEY_DestroyPublicKey(pubk);
+ }
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+prdone:
+ PR_Cleanup ();
+ return retval;
+}
diff --git a/security/nss/cmd/shlibsign/sign.cmd b/security/nss/cmd/shlibsign/sign.cmd
new file mode 100644
index 000000000..612609de9
--- /dev/null
+++ b/security/nss/cmd/shlibsign/sign.cmd
@@ -0,0 +1,19 @@
+/* Equivalent to sign.sh for OS/2 */
+PARSE ARG dist objdir os_target therest
+dist=forwardtoback(dist);
+objdir=forwardtoback(objdir);
+'echo 'dist
+'echo 'objdir
+'set BEGINLIBPATH='dist'\lib;%BEGINLIBPATH%'
+'set LIBPATHSTRICT=T'
+objdir'\shlibsign -v -i 'therest
+exit
+
+forwardtoback: procedure
+ arg pathname
+ parse var pathname pathname'/'rest
+ do while (rest <> "")
+ pathname = pathname'\'rest
+ parse var pathname pathname'/'rest
+ end
+ return pathname
diff --git a/security/nss/cmd/shlibsign/sign.sh b/security/nss/cmd/shlibsign/sign.sh
new file mode 100644
index 000000000..9a5d79fc9
--- /dev/null
+++ b/security/nss/cmd/shlibsign/sign.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+case "${3}" in
+WIN*)
+ if echo "${PATH}" | grep -c \; >/dev/null; then
+ PATH=${PATH}\;${1}/bin\;${1}/lib
+ else
+ # ARG1 is ${1} with the drive letter escaped.
+ if echo "${1}" | grep -c : >/dev/null; then
+ ARG1=`(cd ${1}; pwd)`
+ else
+ ARG1=${1}
+ fi
+ PATH=${PATH}:${ARG1}/bin:${ARG1}/lib
+ fi
+ export PATH
+ echo ${2}/shlibsign -v -i ${4}
+ ${2}/shlibsign -v -i ${4}
+ ;;
+OpenVMS)
+ temp="tmp$$.tmp"
+ temp2="tmp$$.tmp2"
+ cd ${1}/lib
+ vmsdir=`dcl show default`
+ ls *.so > $temp
+ sed -e "s/\([^\.]*\)\.so/\$ define\/job \1 ${vmsdir}\1.so/" $temp > $temp2
+ echo '$ define/job getipnodebyname xxx' >> $temp2
+ echo '$ define/job vms_null_dl_name sys$share:decc$shr' >> $temp2
+ dcl @$temp2
+ echo ${2}/shlibsign -v -i ${4}
+ ${2}/shlibsign -v -i ${4}
+ sed -e "s/\([^\.]*\)\.so/\$ deass\/job \1/" $temp > $temp2
+ echo '$ deass/job getipnodebyname' >> $temp2
+ echo '$ deass/job vms_null_dl_name' >> $temp2
+ dcl @$temp2
+ rm $temp $temp2
+ ;;
+*)
+ LIBPATH=`(cd ${1}/lib; pwd)`:$LIBPATH
+ export LIBPATH
+ SHLIB_PATH=${1}/lib:$SHLIB_PATH
+ export SHLIB_PATH
+ LD_LIBRARY_PATH=${1}/lib:$LD_LIBRARY_PATH
+ export LD_LIBRARY_PATH
+ DYLD_LIBRARY_PATH=${1}/lib:$DYLD_LIBRARY_PATH
+ export DYLD_LIBRARY_PATH
+ LIBRARY_PATH=${1}/lib:$LIBRARY_PATH
+ export LIBRARY_PATH
+ echo ${2}/shlibsign -v -i ${4}
+ ${2}/shlibsign -v -i ${4}
+ ;;
+esac
diff --git a/security/nss/cmd/signtool/Makefile b/security/nss/cmd/signtool/Makefile
new file mode 100644
index 000000000..e4a3a6069
--- /dev/null
+++ b/security/nss/cmd/signtool/Makefile
@@ -0,0 +1,71 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/signtool/README b/security/nss/cmd/signtool/README
new file mode 100644
index 000000000..2bdb705c7
--- /dev/null
+++ b/security/nss/cmd/signtool/README
@@ -0,0 +1,119 @@
+ Signing Tool (signtool)
+ 1.3 Release Notes
+ ========================================
+
+Documentation is provided online at mozilla.org
+
+Problems or questions not covered by the online documentation can be
+discussed in the DevEdge Security Newsgroup.
+
+=== New Features in 1.3
+=======================
+
+The security library components have been upgraded to utilize NSS_2_7_1_RTM.
+This means that the maximum RSA keysize now supported should be 4096 bits.
+
+=== Zigbert 0.6 Support
+=======================
+This program was previously named Zigbert. The last version of zigbert
+was Zigbert 0.6. Because all the functionality of Zigbert is maintained in
+signtool 1.2, Zigbert is no longer supported. If you have problems
+using Zigbert, please upgrade to signtool 1.2.
+
+=== New Features in 1.2
+=======================
+
+Certificate Generation Improvements
+-----------------------------------
+Two new options have been added to control generation of self-signed object
+signing certificates with the -G option. The -s option takes the size (in bits)
+of the generated RSA private key. The -t option takes the name of the PKCS #11
+token on which to generate the keypair and install the certificate. Both
+options are optional. By default, the private key is 1024 bits and is generated
+on the internal software token.
+
+
+=== New Features in 1.1
+=======================
+
+File I/O
+--------
+Signtool can now read its options from a command file specified with the -f
+option on the command line. The format for the file is described in the
+documentation.
+Error messages and informational output can be redirected to an output file
+by supplying the "--outfile" option on the command line or the "outfile="
+option in the command file.
+
+New Options
+-----------
+"--norecurse" tells Signtool not to recurse into subdirectories when signing
+directories or parsing HTML with the -J option.
+"--leavearc" tells Signtool not to delete the temporary .arc directories
+produced by the -J option. This can aid debugging.
+"--verbosity" tells Signtool how much information to display. 0 is the
+default. -1 suppresses most messages, except for errors.
+
+=== Bug Fixes in 1.1
+====================
+
+-J option revamped
+------------------
+The -J option, which parses HTML files, extracts Java and Javascript code,
+and stores them in signed JAR files, has been re-implemented. Several bugs
+have been fixed:
+- CODEBASE attribute is no longer ignored
+- CLASS and SRC attributes can be be paths ("xxx/xxx/x.class") rather than
+ just filenames ("x.class").
+- LINK tags are handled correctly
+- various HTML parsing bugs fixed
+- error messages are more informative
+
+No Password on Key Database
+---------------------------
+If you had not yet set a Communicator password (which locks key3.db, the
+key database), signtool would fail with a cryptic error message whenever it
+attempted to verify the password. Now this condition is detected at the
+beginning of the program, and a more informative message is displayed.
+
+-x and -e Options
+-----------------
+Previously, only one of each of these options could be specified on the command
+line. Now arbitrarily many can be specified. For example, to sign only files
+with .class or .js extensions, the arguments "-eclass -ejs" could both be
+specified. To exclude the directories "subdir1" and "subdir2" from signing,
+the arguments "-x subdir1 -x subdir2" could both be specified.
+
+New Features in 1.0
+===================
+
+Creation of JAR files
+----------------------
+The -Z option causes signtool to output a JAR file formed by storing the
+signed archive in ZIP format. This eliminates the need to use a separate ZIP
+utility. The -c option specifies the compression level of the resulting
+JAR file.
+
+Generation of Object-Signing Certificates and Keys
+--------------------------------------------------
+The -G option will create a new, self-signed object-signing certificate
+which can be used for testing purposes. The generated certificate and
+associated public and private keys will be installed in the cert7.db and
+key3.db files in the directory specified with the -d option (unless the key
+is generated on an external token using the -t option). On Unix systems,
+if no directory is specified, the user's Netscape directory (~/.netscape)
+will be used. In addition, the certificate is output in X509 format to the
+files x509.raw and x509.cacert in the current directory. x509.cacert can
+be published on a web page and imported into browsers that visit that page.
+
+Extraction and Signing of JavaScript from HTML
+----------------------------------------------
+The -J option activates the same functionality provided by the signpages
+Perl script. It will parse a directory of html files, creating archives
+of the JavaScript called from the HTML. These archives are then signed and
+made into JAR files.
+
+Enhanced Smart Card Support
+---------------------------
+Certificates that reside on smart cards are displayed when using the -L and
+-l options.
diff --git a/security/nss/cmd/signtool/certgen.c b/security/nss/cmd/signtool/certgen.c
new file mode 100644
index 000000000..4687a7841
--- /dev/null
+++ b/security/nss/cmd/signtool/certgen.c
@@ -0,0 +1,713 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "signtool.h"
+
+#include "secoid.h"
+#include "cryptohi.h"
+#include "certdb.h"
+
+static char* GetSubjectFromUser(unsigned long serial);
+static CERTCertificate* GenerateSelfSignedObjectSigningCert(char *nickname,
+ CERTCertDBHandle *db, char *subject, unsigned long serial, int keysize,
+ char *token);
+static SECStatus ChangeTrustAttributes(CERTCertDBHandle *db,
+ CERTCertificate *cert, char *trusts);
+static SECStatus set_cert_type(CERTCertificate *cert, unsigned int type);
+static SECItem *sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk);
+static CERTCertificate* install_cert(CERTCertDBHandle *db, SECItem *derCert,
+ char *nickname);
+static SECStatus GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
+ SECKEYPrivateKey **privk, int keysize);
+static CERTCertificateRequest* make_cert_request(char *subject,
+ SECKEYPublicKey *pubk);
+static CERTCertificate * make_cert(CERTCertificateRequest *req,
+ unsigned long serial, CERTName *ca_subject);
+static void output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db);
+
+
+/***********************************************************************
+ *
+ * G e n e r a t e C e r t
+ *
+ * Runs the whole process of creating a new cert, getting info from the
+ * user, etc.
+ */
+int
+GenerateCert(char *nickname, int keysize, char *token)
+{
+ CERTCertDBHandle *db;
+ CERTCertificate *cert;
+ char *subject;
+ unsigned long serial;
+ char stdinbuf[160];
+
+ /* Print warning about having the browser open */
+ PR_fprintf(PR_STDOUT /*always go to console*/,
+"\nWARNING: Performing this operation while the browser is running could cause"
+"\ncorruption of your security databases. If the browser is currently running,"
+"\nyou should exit the browser before continuing this operation. Enter "
+"\n\"y\" to continue, or anything else to abort: ");
+ pr_fgets(stdinbuf, 160, PR_STDIN);
+ PR_fprintf(PR_STDOUT, "\n");
+ if(tolower(stdinbuf[0]) != 'y') {
+ PR_fprintf(errorFD, "Operation aborted at user's request.\n");
+ errorCount++;
+ return -1;
+ }
+
+ db = CERT_GetDefaultCertDB();
+ if(!db) {
+ FatalError("Unable to open certificate database");
+ }
+
+ if(PK11_FindCertFromNickname(nickname, NULL)) {
+ PR_fprintf(errorFD,
+"ERROR: Certificate with nickname \"%s\" already exists in database. You\n"
+"must choose a different nickname.\n", nickname);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ LL_L2UI(serial, PR_Now());
+
+ subject = GetSubjectFromUser(serial);
+
+ cert = GenerateSelfSignedObjectSigningCert(nickname, db, subject,
+ serial, keysize, token);
+
+ if(cert) {
+ output_ca_cert(cert, db);
+ CERT_DestroyCertificate(cert);
+ }
+
+ PORT_Free(subject);
+ return 0;
+}
+
+#undef VERBOSE_PROMPTS
+
+/*********************************************************************8
+ * G e t S u b j e c t F r o m U s e r
+ *
+ * Construct the subject information line for a certificate by querying
+ * the user on stdin.
+ */
+static char*
+GetSubjectFromUser(unsigned long serial)
+{
+ char buf[STDIN_BUF_SIZE];
+ char common_name_buf[STDIN_BUF_SIZE];
+ char *common_name, *state, *orgunit, *country, *org, *locality;
+ char *email, *uid;
+ char *subject;
+ char *cp;
+ int subjectlen=0;
+
+ common_name = state = orgunit = country = org = locality = email =
+ uid = subject = NULL;
+
+ /* Get subject information */
+ PR_fprintf(PR_STDOUT,
+"\nEnter certificate information. All fields are optional. Acceptable\n"
+"characters are numbers, letters, spaces, and apostrophes.\n");
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nCOMMON NAME\n"
+"Enter the full name you want to give your certificate. (Example: Test-Only\n"
+"Object Signing Certificate)\n"
+"-->");
+#else
+ PR_fprintf(PR_STDOUT, "certificate common name: ");
+#endif
+ fgets(buf, STDIN_BUF_SIZE, stdin);
+ cp = chop(buf);
+ if(*cp == '\0') {
+ sprintf(common_name_buf, "%s (%lu)", DEFAULT_COMMON_NAME, serial);
+ cp = common_name_buf;
+ }
+ common_name = PORT_ZAlloc(strlen(cp) + 6);
+ if(!common_name) {out_of_memory();}
+ sprintf(common_name, "CN=%s, ", cp);
+ subjectlen += strlen(common_name);
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nORGANIZATION NAME\n"
+"Enter the name of your organization. For example, this could be the name\n"
+"of your company.\n"
+"-->");
+#else
+ PR_fprintf(PR_STDOUT, "organization: ");
+#endif
+ fgets(buf, STDIN_BUF_SIZE, stdin);
+ cp = chop(buf);
+ if(*cp != '\0') {
+ org = PORT_ZAlloc(strlen(cp) + 5);
+ if(!org) {out_of_memory();}
+ sprintf(org, "O=%s, ", cp);
+ subjectlen += strlen(org);
+ }
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nORGANIZATION UNIT\n"
+"Enter the name of your organization unit. For example, this could be the\n"
+"name of your department.\n"
+"-->");
+#else
+ PR_fprintf(PR_STDOUT, "organization unit: ");
+#endif
+ fgets(buf, STDIN_BUF_SIZE, stdin);
+ cp = chop(buf);
+ if(*cp != '\0') {
+ orgunit = PORT_ZAlloc(strlen(cp)+6);
+ if(!orgunit) {out_of_memory();}
+ sprintf(orgunit, "OU=%s, ", cp);
+ subjectlen += strlen(orgunit);
+ }
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nSTATE\n"
+"Enter the name of your state or province.\n"
+"-->");
+#else
+ PR_fprintf(PR_STDOUT, "state or province: ");
+#endif
+ fgets(buf, STDIN_BUF_SIZE, stdin);
+ cp = chop(buf);
+ if(*cp != '\0') {
+ state = PORT_ZAlloc(strlen(cp)+6);
+ if(!state) {out_of_memory();}
+ sprintf(state, "ST=%s, ", cp);
+ subjectlen += strlen(state);
+ }
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nCOUNTRY\n"
+"Enter the 2-character abbreviation for the name of your country.\n"
+"-->");
+#else
+ PR_fprintf(PR_STDOUT, "country (must be exactly 2 characters): ");
+#endif
+ fgets(buf, STDIN_BUF_SIZE, stdin);
+ cp = chop(cp);
+ if(strlen(cp) != 2) {
+ *cp = '\0'; /* country code must be 2 chars */
+ }
+ if(*cp != '\0') {
+ country = PORT_ZAlloc(strlen(cp)+5);
+ if(!country) {out_of_memory();}
+ sprintf(country, "C=%s, ", cp);
+ subjectlen += strlen(country);
+ }
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nUSERNAME\n"
+"Enter your system username or UID\n"
+"-->");
+#else
+ PR_fprintf(PR_STDOUT, "username: ");
+#endif
+ fgets(buf, STDIN_BUF_SIZE, stdin);
+ cp = chop(buf);
+ if(*cp != '\0') {
+ uid = PORT_ZAlloc(strlen(cp)+7);
+ if(!uid) {out_of_memory();}
+ sprintf(uid, "UID=%s, ", cp);
+ subjectlen += strlen(uid);
+ }
+
+#ifdef VERBOSE_PROMPTS
+ PR_fprintf(PR_STDOUT, "\nEMAIL ADDRESS\n"
+"Enter your email address.\n"
+"-->");
+#else
+ PR_fprintf(PR_STDOUT, "email address: ");
+#endif
+ fgets(buf, STDIN_BUF_SIZE, stdin);
+ cp = chop(buf);
+ if(*cp != '\0') {
+ email = PORT_ZAlloc(strlen(cp)+5);
+ if(!email) {out_of_memory();}
+ sprintf(email, "E=%s,", cp);
+ subjectlen += strlen(email);
+ }
+
+ subjectlen++;
+
+ subject = PORT_ZAlloc(subjectlen);
+ if(!subject) {out_of_memory();}
+
+ sprintf(subject, "%s%s%s%s%s%s%s",
+ common_name ? common_name : "",
+ org ? org : "",
+ orgunit ? orgunit : "",
+ state ? state : "",
+ country ? country : "",
+ uid ? uid : "",
+ email ? email : ""
+ );
+ if( (strlen(subject) > 1) && (subject[strlen(subject)-1] == ' ') ) {
+ subject[strlen(subject)-2] = '\0';
+ }
+
+ PORT_Free(common_name);
+ PORT_Free(org);
+ PORT_Free(orgunit);
+ PORT_Free(state);
+ PORT_Free(country);
+ PORT_Free(uid);
+ PORT_Free(email);
+
+ return subject;
+}
+
+/**************************************************************************
+ *
+ * G e n e r a t e S e l f S i g n e d O b j e c t S i g n i n g C e r t
+ * *phew*^
+ *
+ */
+static CERTCertificate*
+GenerateSelfSignedObjectSigningCert(char *nickname, CERTCertDBHandle *db,
+ char *subject, unsigned long serial, int keysize, char *token)
+{
+ CERTCertificate *cert, *temp_cert;
+ SECItem *derCert;
+ CERTCertificateRequest *req;
+
+ PK11SlotInfo *slot = NULL;
+ SECKEYPrivateKey *privk = NULL;
+ SECKEYPublicKey *pubk = NULL;
+
+ if( token ) {
+ slot = PK11_FindSlotByName(token);
+ } else {
+ slot = PK11_GetInternalKeySlot();
+ }
+
+ if (slot == NULL) {
+ PR_fprintf(errorFD, "Can't find PKCS11 slot %s\n",
+ token ? token : "");
+ errorCount++;
+ exit (ERRX);
+ }
+
+ if( GenerateKeyPair(slot, &pubk, &privk, keysize) != SECSuccess) {
+ FatalError("Error generating keypair.");
+ }
+ req = make_cert_request (subject, pubk);
+ temp_cert = make_cert (req, serial, &req->subject);
+ if(set_cert_type(temp_cert,
+ NS_CERT_TYPE_OBJECT_SIGNING | NS_CERT_TYPE_OBJECT_SIGNING_CA)
+ != SECSuccess) {
+ FatalError("Unable to set cert type");
+ }
+
+ derCert = sign_cert (temp_cert, privk);
+ cert = install_cert(db, derCert, nickname);
+ if(ChangeTrustAttributes(db, cert, ",,uC") != SECSuccess) {
+ FatalError("Unable to change trust on generated certificate");
+ }
+
+ /* !!! Free memory ? !!! */
+ PK11_FreeSlot(slot);
+ SECKEY_DestroyPrivateKey(privk);
+ SECKEY_DestroyPublicKey(pubk);
+
+ return cert;
+}
+
+/**************************************************************************
+ *
+ * C h a n g e T r u s t A t t r i b u t e s
+ */
+static SECStatus
+ChangeTrustAttributes(CERTCertDBHandle *db, CERTCertificate *cert, char *trusts)
+{
+
+ CERTCertTrust *trust;
+
+ if(!db || !cert || !trusts) {
+ PR_fprintf(errorFD,"ChangeTrustAttributes got incomplete arguments.\n");
+ errorCount++;
+ return SECFailure;
+ }
+
+ trust = (CERTCertTrust*) PORT_ZAlloc(sizeof(CERTCertTrust));
+ if(!trust) {
+ PR_fprintf(errorFD, "ChangeTrustAttributes unable to allocate "
+ "CERTCertTrust\n");
+ errorCount++;
+ return SECFailure;
+ }
+
+ if( CERT_DecodeTrustString(trust, trusts) ) {
+ return SECFailure;
+ }
+
+ if( CERT_ChangeCertTrust(db, cert, trust) ) {
+ PR_fprintf(errorFD, "unable to modify trust attributes for cert %s\n",
+ cert->nickname ? cert->nickname : "");
+ errorCount++;
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+/*************************************************************************
+ *
+ * s e t _ c e r t _ t y p e
+ */
+static SECStatus
+set_cert_type(CERTCertificate *cert, unsigned int type)
+{
+ void *context;
+ SECStatus status = SECSuccess;
+ SECItem certType;
+ char ctype;
+
+ context = CERT_StartCertExtensions(cert);
+
+ certType.type = siBuffer;
+ certType.data = (unsigned char*) &ctype;
+ certType.len = 1;
+ ctype = (unsigned char)type;
+ if(CERT_EncodeAndAddBitStrExtension(context, SEC_OID_NS_CERT_EXT_CERT_TYPE,
+ &certType, PR_TRUE /*critical*/) != SECSuccess) {
+ status = SECFailure;
+ }
+
+ if(CERT_FinishExtensions(context) != SECSuccess) {
+ status = SECFailure;
+ }
+
+ return status;
+}
+
+/********************************************************************
+ *
+ * s i g n _ c e r t
+ */
+static SECItem *
+sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk)
+{
+ SECStatus rv;
+
+ SECItem der2;
+ SECItem *result2;
+
+ void *dummy;
+ SECOidTag alg = SEC_OID_UNKNOWN;
+
+ switch (privk->keyType)
+ {
+ case rsaKey:
+ alg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
+ break;
+
+ case dsaKey:
+ alg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
+ break;
+ default:
+ FatalError("Unknown key type");
+ }
+ PORT_Assert(alg != SEC_OID_UNKNOWN);
+
+ rv = SECOID_SetAlgorithmID (cert->arena, &cert->signature, alg, 0);
+
+ if (rv != SECSuccess)
+ {
+ PR_fprintf(errorFD, "%s: unable to set signature alg id\n", PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ der2.len = 0;
+ der2.data = NULL;
+
+ dummy = SEC_ASN1EncodeItem
+ (cert->arena, &der2, cert, CERT_CertificateTemplate);
+
+ if (rv != SECSuccess)
+ {
+ PR_fprintf(errorFD, "%s: error encoding cert\n", PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ result2 = (SECItem *) PORT_ArenaZAlloc (cert->arena, sizeof (SECItem));
+ if (result2 == NULL)
+ out_of_memory();
+
+ rv = SEC_DerSignData
+ (cert->arena, result2, der2.data, der2.len, privk, alg);
+
+ if (rv != SECSuccess)
+ {
+ PR_fprintf(errorFD, "can't sign encoded certificate data\n");
+ errorCount++;
+ exit (ERRX);
+ }
+ else if(verbosity >= 0) {
+ PR_fprintf(outputFD, "certificate has been signed\n");
+ }
+
+ cert->derCert = *result2;
+
+ return result2;
+}
+
+/*********************************************************************
+ *
+ * i n s t a l l _ c e r t
+ *
+ * Installs the cert in the permanent database.
+ */
+static CERTCertificate*
+install_cert(CERTCertDBHandle *db, SECItem *derCert, char *nickname)
+{
+ CERTCertificate *newcert;
+ PK11SlotInfo *newSlot;
+
+ newcert = CERT_DecodeDERCertificate(derCert, PR_TRUE, NULL);
+
+ if (newcert == NULL) {
+ PR_fprintf(errorFD, "%s: can't create new certificate\n", PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ newSlot = PK11_ImportCertForKey(newcert, nickname, NULL /*wincx*/);
+ if( newSlot == NULL ) {
+ PR_fprintf(errorFD, "Unable to install certificate\n");
+ errorCount++;
+ exit(ERRX);
+ }
+ PK11_FreeSlot(newSlot);
+
+ if(verbosity >= 0){
+ PR_fprintf(outputFD, "certificate \"%s\" added to database\n", nickname);
+ }
+
+ return newcert;
+}
+
+/******************************************************************
+ *
+ * G e n e r a t e K e y P a i r
+ */
+static SECStatus
+GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
+ SECKEYPrivateKey **privk, int keysize)
+{
+
+ PK11RSAGenParams rsaParams;
+
+ if( keysize == -1 ) {
+ rsaParams.keySizeInBits = DEFAULT_RSA_KEY_SIZE;
+ } else {
+ rsaParams.keySizeInBits = keysize;
+ }
+ rsaParams.pe = 0x10001;
+
+ if(PK11_Authenticate( slot, PR_FALSE /*loadCerts*/, NULL /*wincx*/)
+ != SECSuccess) {
+ SECU_PrintError(progName, "failure authenticating to key database.\n");
+ exit(ERRX);
+ }
+
+ *privk = PK11_GenerateKeyPair (slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams,
+ pubk, PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, NULL /*wincx*/ );
+
+ if (*privk != NULL && *pubk != NULL) {
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "generated public/private key pair\n");
+ }
+ } else {
+ SECU_PrintError(progName, "failure generating key pair\n");
+ exit (ERRX);
+ }
+
+ return SECSuccess;
+}
+
+/******************************************************************
+ *
+ * m a k e _ c e r t _ r e q u e s t
+ */
+static CERTCertificateRequest*
+make_cert_request(char *subject, SECKEYPublicKey *pubk)
+{
+ CERTName *subj;
+ CERTSubjectPublicKeyInfo *spki;
+
+ CERTCertificateRequest *req;
+
+ /* Create info about public key */
+ spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
+ if (!spki) {
+ SECU_PrintError(progName, "unable to create subject public key");
+ exit (ERRX);
+ }
+
+ subj = CERT_AsciiToName (subject);
+ if(subj == NULL) {
+ FatalError("Invalid data in certificate description");
+ }
+
+ /* Generate certificate request */
+ req = CERT_CreateCertificateRequest(subj, spki, 0);
+ if (!req) {
+ SECU_PrintError(progName, "unable to make certificate request");
+ exit (ERRX);
+ }
+
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "certificate request generated\n");
+ }
+
+ return req;
+}
+
+/******************************************************************
+ *
+ * m a k e _ c e r t
+ */
+static CERTCertificate *
+make_cert(CERTCertificateRequest *req, unsigned long serial,
+ CERTName *ca_subject)
+{
+ CERTCertificate *cert;
+
+ CERTValidity *validity = NULL;
+
+ PRTime now, after;
+ PRExplodedTime printableTime;
+
+ now = PR_Now();
+ PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
+
+ printableTime.tm_month += 3;
+ after = PR_ImplodeTime (&printableTime);
+
+ validity = CERT_CreateValidity (now, after);
+
+ if (validity == NULL)
+ {
+ PR_fprintf(errorFD, "%s: error creating certificate validity\n", PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ cert = CERT_CreateCertificate
+ (serial, ca_subject, validity, req);
+
+ if (cert == NULL)
+ {
+ /* should probably be more precise here */
+ PR_fprintf(errorFD, "%s: error while generating certificate\n", PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ return cert;
+ }
+
+/*************************************************************************
+ *
+ * o u t p u t _ c a _ c e r t
+ */
+static void
+output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db)
+ {
+ FILE *out;
+
+ SECItem *encodedCertChain;
+ SEC_PKCS7ContentInfo *certChain;
+ char *filename;
+
+ /* the raw */
+
+ filename = PORT_ZAlloc(strlen(DEFAULT_X509_BASENAME)+8);
+ if(!filename) out_of_memory();
+
+ sprintf(filename, "%s.raw", DEFAULT_X509_BASENAME);
+ if ((out = fopen (filename, "wb")) == NULL)
+ {
+ PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME, filename);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ certChain = SEC_PKCS7CreateCertsOnly (cert, PR_TRUE, db);
+ encodedCertChain
+ = SEC_PKCS7EncodeItem (NULL, NULL, certChain, NULL, NULL, NULL);
+ SEC_PKCS7DestroyContentInfo (certChain);
+
+ if (encodedCertChain)
+ {
+ fprintf(out, "Content-type: application/x-x509-ca-cert\n\n");
+ fwrite (encodedCertChain->data, 1, encodedCertChain->len, out);
+ SECITEM_FreeItem(encodedCertChain, PR_TRUE);
+ }
+ else {
+ PR_fprintf(errorFD, "%s: Can't DER encode this certificate\n", PROGRAM_NAME);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ fclose (out);
+
+ /* and the cooked */
+
+ sprintf(filename, "%s.cacert", DEFAULT_X509_BASENAME);
+ if ((out = fopen (filename, "wb")) == NULL)
+ {
+ PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME, filename);
+ errorCount++;
+ return;
+ }
+
+ fprintf (out, "%s\n%s\n%s\n",
+ NS_CERT_HEADER,
+ BTOA_DataToAscii (cert->derCert.data, cert->derCert.len),
+ NS_CERT_TRAILER);
+
+ fclose (out);
+
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "Exported certificate to %s.raw and %s.cacert.\n",
+ DEFAULT_X509_BASENAME, DEFAULT_X509_BASENAME);
+ }
+}
diff --git a/security/nss/cmd/signtool/javascript.c b/security/nss/cmd/signtool/javascript.c
new file mode 100644
index 000000000..142a9751a
--- /dev/null
+++ b/security/nss/cmd/signtool/javascript.c
@@ -0,0 +1,1790 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "signtool.h"
+#include <prmem.h>
+#include <prio.h>
+#include <prenv.h>
+
+static int javascript_fn(char *relpath, char *basedir, char *reldir,
+ char *filename, void *arg);
+static int extract_js (char *filename);
+static int copyinto (char *from, char *to);
+static PRStatus ensureExists (char *base, char *path);
+static int make_dirs(char *path, PRInt32 file_perms);
+
+static char *jartree = NULL;
+static int idOrdinal;
+static PRBool dumpParse=PR_FALSE;
+
+static char *event_handlers[] = {
+"onAbort",
+"onBlur",
+"onChange",
+"onClick",
+"onDblClick",
+"onDragDrop",
+"onError",
+"onFocus",
+"onKeyDown",
+"onKeyPress",
+"onKeyUp",
+"onLoad",
+"onMouseDown",
+"onMouseMove",
+"onMouseOut",
+"onMouseOver",
+"onMouseUp",
+"onMove",
+"onReset",
+"onResize",
+"onSelect",
+"onSubmit",
+"onUnload"
+};
+static int num_handlers = 23;
+
+/*
+ * I n l i n e J a v a S c r i p t
+ *
+ * Javascript signing. Instead of passing an archive to signtool,
+ * a directory containing html files is given. Archives are created
+ * from the archive= and src= tag attributes inside the html,
+ * as appropriate. Then the archives are signed.
+ *
+ */
+int
+InlineJavaScript(char *dir, PRBool recurse)
+{
+ jartree = dir;
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "\nGenerating inline signatures from HTML files in: %s\n", dir);
+ }
+ if(PR_GetEnv("SIGNTOOL_DUMP_PARSE")) {
+ dumpParse = PR_TRUE;
+ }
+
+ return foreach(dir, "", javascript_fn, recurse, PR_FALSE /*include dirs*/,
+ (void*)NULL);
+
+}
+
+/************************************************************************
+ *
+ * j a v a s c r i p t _ f n
+ */
+static int javascript_fn
+ (char *relpath, char *basedir, char *reldir, char *filename, void *arg)
+{
+ char fullname [FNSIZE];
+
+ /* only process inline scripts from .htm, .html, and .shtml*/
+
+ if(! (PL_strcaserstr(filename, ".htm") == filename + strlen(filename) -4) &&
+ ! (PL_strcaserstr(filename, ".html") == filename + strlen(filename) -5)&&
+ ! (PL_strcaserstr(filename, ".shtml") == filename + strlen(filename)-6)){
+ return 0;
+ }
+
+ /* don't process scripts that signtool has already
+ extracted (those that are inside .arc directories) */
+
+ if(PL_strcaserstr(filename, ".arc") == filename + strlen(filename) - 4)
+ return 0;
+
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "Processing HTML file: %s\n", relpath);
+ }
+
+ /* reset firstArchive at top of each HTML file */
+
+ /* skip directories that contain extracted scripts */
+
+ if(PL_strcaserstr(reldir, ".arc") == reldir + strlen(reldir) - 4)
+ return 0;
+
+ sprintf (fullname, "%s/%s", basedir, relpath);
+ return extract_js (fullname);
+}
+
+/*===========================================================================
+ =
+ = D A T A S T R U C T U R E S
+ =
+*/
+typedef enum {
+ TEXT_HTML_STATE=0,
+ SCRIPT_HTML_STATE
+} HTML_STATE ;
+
+typedef enum {
+ /* we start in the start state */
+ START_STATE,
+
+ /* We are looking for or reading in an attribute */
+ GET_ATT_STATE,
+
+ /* We're burning ws before finding an attribute */
+ PRE_ATT_WS_STATE,
+
+ /* We're burning ws after an attribute. Looking for an '='. */
+ POST_ATT_WS_STATE,
+
+ /* We're burning ws after an '=', waiting for a value */
+ PRE_VAL_WS_STATE,
+
+ /* We're reading in a value */
+ GET_VALUE_STATE,
+
+ /* We're reading in a value that's inside quotes */
+ GET_QUOTED_VAL_STATE,
+
+ /* We've encountered the closing '>' */
+ DONE_STATE,
+
+ /* Error state */
+ ERR_STATE
+} TAG_STATE ;
+
+typedef struct AVPair_Str {
+ char *attribute;
+ char *value;
+ unsigned int valueLine; /* the line that the value ends on */
+ struct AVPair_Str *next;
+} AVPair;
+
+typedef enum {
+ APPLET_TAG,
+ SCRIPT_TAG,
+ LINK_TAG,
+ STYLE_TAG,
+ COMMENT_TAG,
+ OTHER_TAG
+} TAG_TYPE ;
+
+typedef struct {
+ TAG_TYPE type;
+ AVPair *attList;
+ AVPair *attListTail;
+ char *text;
+} TagItem;
+
+typedef enum {
+ TAG_ITEM,
+ TEXT_ITEM
+} ITEM_TYPE ;
+
+typedef struct HTMLItem_Str{
+ unsigned int startLine;
+ unsigned int endLine;
+ ITEM_TYPE type;
+ union {
+ TagItem *tag;
+ char *text;
+ } item;
+ struct HTMLItem_Str *next;
+} HTMLItem;
+
+typedef struct {
+ PRFileDesc *fd;
+ PRInt32 curIndex;
+ PRBool IsEOF;
+#define FILE_BUFFER_BUFSIZE 512
+ char buf[FILE_BUFFER_BUFSIZE];
+ PRInt32 startOffset;
+ PRInt32 maxIndex;
+ unsigned int lineNum;
+} FileBuffer;
+
+/*===========================================================================
+ =
+ = F U N C T I O N S
+ =
+*/
+static HTMLItem* CreateTextItem(char *text, unsigned int startline,
+ unsigned int endline);
+static HTMLItem* CreateTagItem(TagItem* ti, unsigned int startline,
+ unsigned int endline);
+static TagItem* ProcessTag(FileBuffer* fb, char **errStr);
+static void DestroyHTMLItem(HTMLItem *item);
+static void DestroyTagItem(TagItem* ti);
+static TAG_TYPE GetTagType(char *att);
+static FileBuffer* FB_Create(PRFileDesc* fd);
+static int FB_GetChar(FileBuffer *fb);
+static PRInt32 FB_GetPointer(FileBuffer *fb);
+static PRInt32 FB_GetRange(FileBuffer *fb, PRInt32 start, PRInt32 end,
+ char **buf);
+static unsigned int FB_GetLineNum(FileBuffer *fb);
+static void FB_Destroy(FileBuffer *fb);
+static void PrintTagItem(PRFileDesc *fd, TagItem *ti);
+static void PrintHTMLStream(PRFileDesc *fd, HTMLItem *head);
+
+/************************************************************************
+ *
+ * C r e a t e T e x t I t e m
+ */
+static HTMLItem*
+CreateTextItem(char *text, unsigned int startline, unsigned int endline)
+{
+ HTMLItem *item;
+
+ item = PR_Malloc(sizeof(HTMLItem));
+ if(!item) {
+ return NULL;
+ }
+
+ item->type = TEXT_ITEM;
+ item->item.text = text;
+ item->next = NULL;
+ item->startLine = startline;
+ item->endLine = endline;
+
+ return item;
+}
+
+/************************************************************************
+ *
+ * C r e a t e T a g I t e m
+ */
+static HTMLItem*
+CreateTagItem(TagItem* ti, unsigned int startline, unsigned int endline)
+{
+ HTMLItem *item;
+
+ item = PR_Malloc(sizeof(HTMLItem));
+ if(!item) {
+ return NULL;
+ }
+
+ item->type = TAG_ITEM;
+ item->item.tag = ti;
+ item->next = NULL;
+ item->startLine = startline;
+ item->endLine = endline;
+
+ return item;
+}
+
+static PRBool
+isAttChar(char c)
+{
+ return (isalnum(c) || c=='/' || c=='-');
+}
+
+/************************************************************************
+ *
+ * P r o c e s s T a g
+ */
+static TagItem*
+ProcessTag(FileBuffer* fb, char **errStr)
+{
+ TAG_STATE state;
+ PRInt32 startText, startID, curPos;
+ PRBool firstAtt;
+ int curchar;
+ TagItem *ti=NULL;
+ AVPair *curPair=NULL;
+ char quotechar='\0';
+ unsigned int linenum;
+ unsigned int startline;
+
+ state = START_STATE;
+
+ startID = FB_GetPointer(fb);
+ startText = startID;
+ firstAtt = PR_TRUE;
+
+ ti = (TagItem*) PR_Malloc(sizeof(TagItem));
+ if(!ti) out_of_memory();
+ ti->type = OTHER_TAG;
+ ti->attList = NULL;
+ ti->attListTail = NULL;
+ ti->text = NULL;
+
+ startline = FB_GetLineNum(fb);
+
+ while(state != DONE_STATE && state != ERR_STATE) {
+ linenum = FB_GetLineNum(fb);
+ curchar = FB_GetChar(fb);
+ if(curchar == EOF) {
+ *errStr = PR_smprintf(
+ "line %d: Unexpected end-of-file while parsing tag starting at line %d.\n", linenum, startline);
+ state = ERR_STATE;
+ continue;
+ }
+
+ switch(state) {
+ case START_STATE:
+ if(curchar=='!') {
+ /*
+ * SGML tag or comment
+ * Here's the general rule for SGML tags. Everything from
+ * <! to > is the tag. Inside the tag, comments are
+ * delimited with --. So we are looking for the first '>'
+ * that is not commented out, that is, not inside a pair
+ * of --: <!DOCTYPE --this is a comment >(psyche!) -->
+ */
+
+ PRBool inComment = PR_FALSE;
+ short hyphenCount = 0; /* number of consecutive hyphens */
+
+ while(1) {
+ linenum = FB_GetLineNum(fb);
+ curchar = FB_GetChar(fb);
+ if(curchar == EOF) {
+ /* Uh oh, EOF inside comment */
+ *errStr = PR_smprintf(
+ "line %d: Unexpected end-of-file inside comment starting at line %d.\n",
+ linenum, startline);
+ state = ERR_STATE;
+ break;
+ }
+ if(curchar=='-') {
+ if(hyphenCount==1) {
+ /* This is a comment delimiter */
+ inComment = !inComment;
+ hyphenCount=0;
+ } else {
+ /* beginning of a comment delimiter? */
+ hyphenCount=1;
+ }
+ } else if(curchar=='>') {
+ if(!inComment) {
+ /* This is the end of the tag */
+ state = DONE_STATE;
+ break;
+ } else {
+ /* The > is inside a comment, so it's not
+ * really the end of the tag */
+ hyphenCount=0;
+ }
+ } else {
+ hyphenCount = 0;
+ }
+ }
+ ti->type = COMMENT_TAG;
+ break;
+ }
+ /* fall through */
+ case GET_ATT_STATE:
+ if(isspace(curchar) || curchar=='=' || curchar=='>') {
+ /* end of the current attribute */
+ curPos = FB_GetPointer(fb)-2;
+ if(curPos >= startID) {
+ /* We have an attribute */
+ curPair = (AVPair*)PR_Malloc(sizeof(AVPair));
+ if(!curPair) out_of_memory();
+ curPair->value = NULL;
+ curPair->next = NULL;
+ FB_GetRange(fb, startID, curPos, &curPair->attribute);
+
+ /* Stick this attribute on the list */
+ if(ti->attListTail) {
+ ti->attListTail->next = curPair;
+ ti->attListTail = curPair;
+ } else {
+ ti->attList = ti->attListTail = curPair;
+ }
+
+ /* If this is the first attribute, find the type of tag
+ * based on it. Also, start saving the text of the tag. */
+ if(firstAtt) {
+ ti->type = GetTagType(curPair->attribute);
+ startText = FB_GetPointer(fb)-1;
+ firstAtt = PR_FALSE;
+ }
+ } else {
+ if(curchar=='=') {
+ /* If we don't have any attribute but we do have an
+ * equal sign, that's an error */
+ *errStr = PR_smprintf("line %d: Malformed tag starting at line %d.\n", linenum, startline);
+ state = ERR_STATE;
+ break;
+ }
+ }
+
+ /* Compute next state */
+ if(curchar=='=') {
+ startID = FB_GetPointer(fb);
+ state = PRE_VAL_WS_STATE;
+ } else if(curchar=='>') {
+ state = DONE_STATE;
+ } else if(curPair) {
+ state = POST_ATT_WS_STATE;
+ } else {
+ state = PRE_ATT_WS_STATE;
+ }
+ } else if(isAttChar(curchar)) {
+ /* Just another char in the attribute. Do nothing */
+ state = GET_ATT_STATE;
+ } else {
+ /* bogus char */
+ *errStr= PR_smprintf("line %d: Bogus chararacter '%c' in tag.\n",
+ linenum, curchar);
+ state = ERR_STATE;
+ break;
+ }
+ break;
+ case PRE_ATT_WS_STATE:
+ if(curchar=='>') {
+ state = DONE_STATE;
+ } else if(isspace(curchar)) {
+ /* more whitespace, do nothing */
+ } else if(isAttChar(curchar)) {
+ /* starting another attribute */
+ startID = FB_GetPointer(fb)-1;
+ state = GET_ATT_STATE;
+ } else {
+ /* bogus char */
+ *errStr = PR_smprintf("line %d: Bogus character '%c' in tag.\n",
+ linenum, curchar);
+ state = ERR_STATE;
+ break;
+ }
+ break;
+ case POST_ATT_WS_STATE:
+ if(curchar=='>') {
+ state = DONE_STATE;
+ } else if(isspace(curchar)) {
+ /* more whitespace, do nothing */
+ } else if(isAttChar(curchar)) {
+ /* starting another attribute */
+ startID = FB_GetPointer(fb)-1;
+ state = GET_ATT_STATE;
+ } else if(curchar=='=') {
+ /* there was whitespace between the attribute and its equal
+ * sign, which means there's a value coming up */
+ state = PRE_VAL_WS_STATE;
+ } else {
+ /* bogus char */
+ *errStr = PR_smprintf("line %d: Bogus character '%c' in tag.\n",
+ linenum, curchar);
+ state = ERR_STATE;
+ break;
+ }
+ break;
+ case PRE_VAL_WS_STATE:
+ if(curchar=='>') {
+ /* premature end-of-tag (sounds like a personal problem). */
+ *errStr = PR_smprintf(
+ "line %d: End of tag while waiting for value.\n", linenum);
+ state = ERR_STATE;
+ break;
+ } else if(isspace(curchar)) {
+ /* more whitespace, do nothing */
+ break;
+ } else {
+ /* this must be some sort of value. Fall through
+ * to GET_VALUE_STATE */
+ startID=FB_GetPointer(fb)-1;
+ state = GET_VALUE_STATE;
+ }
+ /* Fall through if we didn't break on '>' or whitespace */
+ case GET_VALUE_STATE:
+ if(isspace(curchar) || curchar=='>') {
+ /* end of value */
+ curPos = FB_GetPointer(fb)-2;
+ if(curPos >= startID) {
+ /* Grab the value */
+ FB_GetRange(fb, startID, curPos, &curPair->value);
+ curPair->valueLine = linenum;
+ } else {
+ /* empty value, leave as NULL */
+ }
+ if(isspace(curchar)) {
+ state = PRE_ATT_WS_STATE;
+ } else {
+ state = DONE_STATE;
+ }
+ } else if(curchar=='\"' || curchar=='\'') {
+ /* quoted value. Start recording the value inside the quote*/
+ startID = FB_GetPointer(fb);
+ state = GET_QUOTED_VAL_STATE;
+ PORT_Assert(quotechar == '\0');
+ quotechar = curchar; /* look for matching quote type */
+ } else {
+ /* just more value */
+ }
+ break;
+ case GET_QUOTED_VAL_STATE:
+ PORT_Assert(quotechar != '\0');
+ if(curchar == quotechar) {
+ /* end of quoted value */
+ curPos = FB_GetPointer(fb)-2;
+ if(curPos >= startID) {
+ /* Grab the value */
+ FB_GetRange(fb, startID, curPos, &curPair->value);
+ curPair->valueLine = linenum;
+ } else {
+ /* empty value, leave it as NULL */
+ }
+ state = GET_ATT_STATE;
+ quotechar = '\0';
+ startID = FB_GetPointer(fb);
+ } else {
+ /* more quoted value, continue */
+ }
+ break;
+ case DONE_STATE:
+ case ERR_STATE:
+ default:
+ ; /* should never get here */
+ }
+ }
+
+ if(state == DONE_STATE) {
+ /* Get the text of the tag */
+ curPos = FB_GetPointer(fb)-1;
+ FB_GetRange(fb, startText, curPos, &ti->text);
+
+ /* Return the tag */
+ return ti;
+ }
+
+ /* Uh oh, an error. Kill the tag item*/
+ DestroyTagItem(ti);
+ return NULL;
+}
+
+/************************************************************************
+ *
+ * D e s t r o y H T M L I t e m
+ */
+static void
+DestroyHTMLItem(HTMLItem *item)
+{
+ if(item->type == TAG_ITEM) {
+ DestroyTagItem(item->item.tag);
+ } else {
+ if(item->item.text) {
+ PR_Free(item->item.text);
+ }
+ }
+}
+
+/************************************************************************
+ *
+ * D e s t r o y T a g I t e m
+ */
+static void
+DestroyTagItem(TagItem* ti)
+{
+ AVPair *temp;
+
+ if(ti->text) {
+ PR_Free(ti->text); ti->text = NULL;
+ }
+
+ while(ti->attList) {
+ temp = ti->attList;
+ ti->attList = ti->attList->next;
+
+ if(temp->attribute) {
+ PR_Free(temp->attribute); temp->attribute = NULL;
+ }
+ if(temp->value) {
+ PR_Free(temp->value); temp->value = NULL;
+ }
+ PR_Free(temp);
+ }
+
+ PR_Free(ti);
+}
+
+/************************************************************************
+ *
+ * G e t T a g T y p e
+ */
+static TAG_TYPE
+GetTagType(char *att)
+{
+ if(!PORT_Strcasecmp(att, "APPLET")) {
+ return APPLET_TAG;
+ }
+ if(!PORT_Strcasecmp(att, "SCRIPT")) {
+ return SCRIPT_TAG;
+ }
+ if(!PORT_Strcasecmp(att, "LINK")) {
+ return LINK_TAG;
+ }
+ if(!PORT_Strcasecmp(att, "STYLE")) {
+ return STYLE_TAG;
+ }
+ return OTHER_TAG;
+}
+
+/************************************************************************
+ *
+ * F B _ C r e a t e
+ */
+static FileBuffer*
+FB_Create(PRFileDesc* fd)
+{
+ FileBuffer *fb;
+ PRInt32 amountRead;
+ PRInt32 storedOffset;
+
+ fb = (FileBuffer*) PR_Malloc(sizeof(FileBuffer));
+ fb->fd = fd;
+ storedOffset = PR_Seek(fd, 0, PR_SEEK_CUR);
+ PR_Seek(fd, 0, PR_SEEK_SET);
+ fb->startOffset = 0;
+ amountRead = PR_Read(fd, fb->buf, FILE_BUFFER_BUFSIZE);
+ if(amountRead == -1) goto loser;
+ fb->maxIndex = amountRead-1;
+ fb->curIndex = 0;
+ fb->IsEOF = (fb->curIndex>fb->maxIndex) ? PR_TRUE : PR_FALSE;
+ fb->lineNum = 1;
+
+ PR_Seek(fd, storedOffset, PR_SEEK_SET);
+ return fb;
+loser:
+ PR_Seek(fd, storedOffset, PR_SEEK_SET);
+ PR_Free(fb);
+ return NULL;
+}
+
+/************************************************************************
+ *
+ * F B _ G e t C h a r
+ */
+static int
+FB_GetChar(FileBuffer *fb)
+{
+ PRInt32 storedOffset;
+ PRInt32 amountRead;
+ int retval=-1;
+
+ if(fb->IsEOF) {
+ return EOF;
+ }
+
+ storedOffset = PR_Seek(fb->fd, 0, PR_SEEK_CUR);
+
+ retval = fb->buf[fb->curIndex++];
+ if(retval=='\n') fb->lineNum++;
+
+ if(fb->curIndex > fb->maxIndex) {
+ /* We're at the end of the buffer. Try to get some new data from the
+ * file */
+ fb->startOffset += fb->maxIndex+1;
+ PR_Seek(fb->fd, fb->startOffset, PR_SEEK_SET);
+ amountRead = PR_Read(fb->fd, fb->buf, FILE_BUFFER_BUFSIZE);
+ if(amountRead==-1) goto loser;
+ fb->maxIndex = amountRead-1;
+ fb->curIndex = 0;
+ }
+
+ fb->IsEOF = (fb->curIndex > fb->maxIndex) ? PR_TRUE : PR_FALSE;
+
+loser:
+ PR_Seek(fb->fd, storedOffset, PR_SEEK_SET);
+ return retval;
+}
+
+/************************************************************************
+ *
+ * F B _ G e t L i n e N u m
+ *
+ */
+static unsigned int
+FB_GetLineNum(FileBuffer *fb)
+{
+ return fb->lineNum;
+}
+
+/************************************************************************
+ *
+ * F B _ G e t P o i n t e r
+ *
+ */
+static PRInt32
+FB_GetPointer(FileBuffer *fb)
+{
+ return fb->startOffset + fb->curIndex;
+}
+
+/************************************************************************
+ *
+ * F B _ G e t R a n g e
+ *
+ */
+static PRInt32
+FB_GetRange(FileBuffer *fb, PRInt32 start, PRInt32 end, char **buf)
+{
+ PRInt32 amountRead;
+ PRInt32 storedOffset;
+
+ *buf = PR_Malloc(end-start+2);
+ if(*buf == NULL) {
+ return 0;
+ }
+
+ storedOffset = PR_Seek(fb->fd, 0, PR_SEEK_CUR);
+ PR_Seek(fb->fd, start, PR_SEEK_SET);
+ amountRead = PR_Read(fb->fd, *buf, end-start+1);
+ PR_Seek(fb->fd, storedOffset, PR_SEEK_SET);
+ if(amountRead == -1) {
+ PR_Free(*buf);
+ *buf = NULL;
+ return 0;
+ }
+
+ (*buf)[end-start+1] = '\0';
+ return amountRead;
+}
+
+
+/************************************************************************
+ *
+ * F B _ D e s t r o y
+ *
+ */
+static void
+FB_Destroy(FileBuffer *fb)
+{
+ if(fb) {
+ PR_Free(fb);
+ }
+}
+
+/************************************************************************
+ *
+ * P r i n t T a g I t e m
+ *
+ */
+static void
+PrintTagItem(PRFileDesc *fd, TagItem *ti)
+{
+ AVPair *pair;
+
+ PR_fprintf(fd, "TAG:\n----\nType: ");
+ switch(ti->type) {
+ case APPLET_TAG:
+ PR_fprintf(fd, "applet\n");
+ break;
+ case SCRIPT_TAG:
+ PR_fprintf(fd, "script\n");
+ break;
+ case LINK_TAG:
+ PR_fprintf(fd, "link\n");
+ break;
+ case STYLE_TAG:
+ PR_fprintf(fd, "style\n");
+ break;
+ case COMMENT_TAG:
+ PR_fprintf(fd, "comment\n");
+ break;
+ case OTHER_TAG:
+ default:
+ PR_fprintf(fd, "other\n");
+ break;
+ }
+
+ PR_fprintf(fd, "Attributes:\n");
+ for(pair = ti->attList; pair; pair=pair->next) {
+ PR_fprintf(fd, "\t%s=%s\n", pair->attribute,
+ pair->value ? pair->value : "");
+ }
+ PR_fprintf(fd, "Text:%s\n", ti->text ? ti->text : "");
+
+ PR_fprintf(fd, "---End of tag---\n");
+}
+
+
+/************************************************************************
+ *
+ * P r i n t H T M L S t r e a m
+ *
+ */
+static void
+PrintHTMLStream(PRFileDesc *fd, HTMLItem *head)
+{
+ while(head) {
+ if(head->type==TAG_ITEM) {
+ PrintTagItem(fd, head->item.tag);
+ } else {
+ PR_fprintf(fd, "\nTEXT:\n-----\n%s\n-----\n\n", head->item.text);
+ }
+ head = head->next;
+ }
+}
+
+/************************************************************************
+ *
+ * S a v e I n l i n e S c r i p t
+ *
+ */
+static int
+SaveInlineScript(char *text, char *id, char *basedir, char *archiveDir)
+{
+ char *filename=NULL;
+ PRFileDesc *fd=NULL;
+ int retval = -1;
+ PRInt32 writeLen;
+ char *ilDir=NULL;
+
+ if(!text || !id || !archiveDir) {
+ return -1;
+ }
+
+ if(dumpParse) {
+ PR_fprintf(outputFD, "SaveInlineScript: text=%s, id=%s, \n"
+ "basedir=%s, archiveDir=%s\n",
+ text, id, basedir, archiveDir);
+ }
+
+ /* Make sure the archive directory is around */
+ if(ensureExists(basedir, archiveDir) != PR_SUCCESS) {
+ PR_fprintf(errorFD,
+ "ERROR: Unable to create archive directory %s.\n", archiveDir);
+ errorCount++;
+ return -1;
+ }
+
+ /* Make sure the inline script directory is around */
+ ilDir = PR_smprintf("%s/inlineScripts", archiveDir);
+ scriptdir = "inlineScripts";
+ if(ensureExists(basedir, ilDir) != PR_SUCCESS) {
+ PR_fprintf(errorFD,
+ "ERROR: Unable to create directory %s.\n", ilDir);
+ errorCount++;
+ return -1;
+ }
+
+ filename = PR_smprintf("%s/%s/%s", basedir, ilDir, id);
+
+ /* If the file already exists, give a warning, then blow it away */
+ if(PR_Access(filename, PR_ACCESS_EXISTS) == PR_SUCCESS) {
+ PR_fprintf(errorFD,
+ "warning: file \"%s\" already exists--will overwrite.\n",
+ filename);
+ warningCount++;
+ if(rm_dash_r(filename)) {
+ PR_fprintf(errorFD,
+ "ERROR: Unable to delete %s.\n", filename);
+ errorCount++;
+ goto finish;
+ }
+ }
+
+ /* Write text into file with name id */
+ fd = PR_Open(filename, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0777);
+ if(!fd) {
+ PR_fprintf(errorFD, "ERROR: Unable to create file \"%s\".\n",
+ filename);
+ errorCount++;
+ goto finish;
+ }
+ writeLen = strlen(text);
+ if( PR_Write(fd, text, writeLen) != writeLen) {
+ PR_fprintf(errorFD, "ERROR: Unable to write to file \"%s\".\n",
+ filename);
+ errorCount++;
+ goto finish;
+ }
+
+ retval = 0;
+finish:
+ if(filename) {
+ PR_smprintf_free(filename);
+ }
+ if(ilDir) {
+ PR_smprintf_free(ilDir);
+ }
+ if(fd) {
+ PR_Close(fd);
+ }
+ return retval;
+}
+
+/************************************************************************
+ *
+ * S a v e U n n a m a b l e S c r i p t
+ *
+ */
+static int
+SaveUnnamableScript(char *text, char *basedir, char *archiveDir,
+ char *HTMLfilename)
+{
+ char *id=NULL;
+ char *ext=NULL;
+ char *start=NULL;
+ int retval = -1;
+
+ if(!text || !archiveDir || !HTMLfilename) {
+ return -1;
+ }
+
+ if(dumpParse) {
+ PR_fprintf(outputFD, "SaveUnnamableScript: text=%s, basedir=%s,\n"
+ "archiveDir=%s, filename=%s\n", text, basedir, archiveDir,
+ HTMLfilename);
+ }
+
+ /* Construct the filename */
+ ext = PL_strrchr(HTMLfilename, '.');
+ if(ext) {
+ *ext = '\0';
+ }
+ for(start=HTMLfilename; strpbrk(start, "/\\");
+ start=strpbrk(start, "/\\")+1);
+ if(*start=='\0') start = HTMLfilename;
+ id = PR_smprintf("_%s%d", start, idOrdinal++);
+ if(ext) {
+ *ext = '.';
+ }
+
+ /* Now call SaveInlineScript to do the work */
+ retval = SaveInlineScript(text, id, basedir, archiveDir);
+
+ PR_Free(id);
+
+ return retval;
+}
+
+/************************************************************************
+ *
+ * S a v e S o u r c e
+ *
+ */
+static int
+SaveSource(char *src, char *codebase, char *basedir, char *archiveDir)
+{
+ char *from=NULL, *to=NULL;
+ int retval = -1;
+ char *arcDir=NULL;
+
+ if(!src || !archiveDir) {
+ return -1;
+ }
+
+ if(dumpParse) {
+ PR_fprintf(outputFD, "SaveSource: src=%s, codebase=%s, basedir=%s,\n"
+ "archiveDir=%s\n", src, codebase, basedir, archiveDir);
+ }
+
+ if(codebase) {
+ arcDir = PR_smprintf("%s/%s/%s/", basedir, codebase, archiveDir);
+ } else {
+ arcDir = PR_smprintf("%s/%s/", basedir, archiveDir);
+ }
+
+ if(codebase) {
+ from = PR_smprintf("%s/%s/%s", basedir, codebase, src);
+ to = PR_smprintf("%s%s", arcDir, src);
+ } else {
+ from = PR_smprintf("%s/%s", basedir, src);
+ to = PR_smprintf("%s%s", arcDir, src);
+ }
+
+ if(make_dirs(to, 0777)) {
+ PR_fprintf(errorFD,
+ "ERROR: Unable to create archive directory %s.\n", archiveDir);
+ errorCount++;
+ goto finish;
+ }
+
+ retval = copyinto(from, to);
+finish:
+ if(from) PR_Free(from);
+ if(to) PR_Free(to);
+ if(arcDir) PR_Free(arcDir);
+ return retval;
+}
+
+/************************************************************************
+ *
+ * T a g T y p e T o S t r i n g
+ *
+ */
+char *
+TagTypeToString(TAG_TYPE type)
+{
+ switch(type) {
+ case APPLET_TAG:
+ return "APPLET";
+ case SCRIPT_TAG:
+ return "SCRIPT";
+ case LINK_TAG:
+ return "LINK";
+ case STYLE_TAG:
+ return "STYLE";
+ default:
+ break;
+ }
+ return "unknown";
+}
+
+/************************************************************************
+ *
+ * e x t r a c t _ j s
+ *
+ */
+static int
+extract_js(char *filename)
+{
+ PRFileDesc *fd=NULL;
+ FileBuffer *fb=NULL;
+ HTML_STATE state;
+ int curchar;
+ HTMLItem *head = NULL;
+ HTMLItem *tail = NULL;
+ PRInt32 textStart;
+ PRInt32 curOffset;
+ TagItem *tagp=NULL;
+ char *text=NULL;
+ HTMLItem *curitem=NULL;
+ int retval = -1;
+ char *tagerr=NULL;
+ unsigned int linenum, startLine;
+ char *archiveDir=NULL, *firstArchiveDir=NULL;
+ HTMLItem *styleList, *styleListTail;
+ HTMLItem *entityList, *entityListTail;
+ char *basedir=NULL;
+
+ styleList = entityList = styleListTail = entityListTail = NULL;
+
+ /* Initialize the implicit ID counter for each file */
+ idOrdinal = 0;
+
+ /*
+ * First, parse the HTML into a stream of tags and text.
+ */
+
+ fd = PR_Open(filename, PR_RDONLY, 0);
+ if(!fd) {
+ PR_fprintf(errorFD, "Unable to open %s for reading.\n", filename);
+ errorCount++;
+ return -1;
+ }
+
+ /* Construct base directory of filename. */
+ {
+ char *cp;
+
+ basedir = PL_strdup(filename);
+
+ /* Remove trailing slashes */
+ while( (cp = PL_strprbrk(basedir, "/\\")) ==
+ (basedir + strlen(basedir) - 1)) {
+ *cp = '\0';
+ }
+
+ /* Now remove everything from the last slash (which will be followed
+ * by a filename) to the end */
+ cp = PL_strprbrk(basedir, "/\\");
+ if(cp) {
+ *cp = '\0';
+ }
+ }
+
+ state = TEXT_HTML_STATE;
+
+ fb = FB_Create(fd);
+
+ textStart=0;
+ startLine = 0;
+ while(linenum=FB_GetLineNum(fb), (curchar = FB_GetChar(fb)) != EOF) {
+ switch(state) {
+ case TEXT_HTML_STATE:
+ if(curchar == '<') {
+ /*
+ * Found a tag
+ */
+ /* Save the text so far to a new text item */
+ curOffset = FB_GetPointer(fb)-2;
+ if(curOffset >= textStart) {
+ if(FB_GetRange(fb, textStart, curOffset, &text) !=
+ curOffset-textStart+1) {
+ PR_fprintf(errorFD,
+ "Unable to read from %s.\n", filename);
+ errorCount++;
+ goto loser;
+ }
+ /* little fudge here. If the first character on a line
+ * is '<', meaning a new tag, the preceding text item
+ * actually ends on the previous line. In this case
+ * we will be saying that the text segment ends on the
+ * next line. I don't think this matters for text items. */
+ curitem = CreateTextItem(text, startLine, linenum);
+ text = NULL;
+ if(tail == NULL) {
+ head = tail = curitem;
+ } else {
+ tail->next = curitem;
+ tail = curitem;
+ }
+ }
+
+ /* Process the tag */
+ tagp = ProcessTag(fb, &tagerr);
+ if(!tagp) {
+ if(tagerr) {
+ PR_fprintf(errorFD, "Error in file %s: %s\n",
+ filename, tagerr);
+ errorCount++;
+ } else {
+ PR_fprintf(errorFD,
+ "Error in file %s, in tag starting at line %d\n",
+ filename, linenum);
+ errorCount++;
+ }
+ goto loser;
+ }
+ /* Add the tag to the list */
+ curitem = CreateTagItem(tagp, linenum, FB_GetLineNum(fb));
+ if(tail == NULL) {
+ head = tail = curitem;
+ } else {
+ tail->next = curitem;
+ tail = curitem;
+ }
+
+ /* What's the next state */
+ if(tagp->type == SCRIPT_TAG) {
+ state = SCRIPT_HTML_STATE;
+ }
+
+ /* Start recording text from the new offset */
+ textStart = FB_GetPointer(fb);
+ startLine = FB_GetLineNum(fb);
+ } else {
+ /* regular character. Next! */
+ }
+ break;
+ case SCRIPT_HTML_STATE:
+ if(curchar == '<') {
+ char *cp;
+ /*
+ * If this is a </script> tag, then we're at the end of the
+ * script. Otherwise, ignore
+ */
+ curOffset = FB_GetPointer(fb)-1;
+ cp = NULL;
+ if(FB_GetRange(fb, curOffset, curOffset+8, &cp) != 9) {
+ if(cp) { PR_Free(cp); cp = NULL; }
+ } else {
+ /* compare the strings */
+ if( !PORT_Strncasecmp(cp, "</script>", 9) ) {
+ /* This is the end of the script. Record the text. */
+ curOffset--;
+ if(curOffset >= textStart) {
+ if(FB_GetRange(fb, textStart, curOffset, &text) !=
+ curOffset-textStart+1) {
+ PR_fprintf(errorFD,
+ "Unable to read from %s.\n", filename);
+ errorCount++;
+ goto loser;
+ }
+ curitem = CreateTextItem(text, startLine, linenum);
+ text = NULL;
+ if(tail == NULL) {
+ head = tail = curitem;
+ } else {
+ tail->next = curitem;
+ tail = curitem;
+ }
+ }
+
+ /* Now parse the /script tag and put it on the list */
+ tagp = ProcessTag(fb, &tagerr);
+ if(!tagp) {
+ if(tagerr) {
+ PR_fprintf(errorFD,
+ "Error in file %s: %s\n", filename, tagerr);
+ } else {
+ PR_fprintf(errorFD,
+ "Error in file %s, in tag starting at"
+ " line %d\n", filename, linenum);
+ }
+ errorCount++;
+ goto loser;
+ }
+ curitem = CreateTagItem(tagp, linenum,
+ FB_GetLineNum(fb));
+ if(tail == NULL) {
+ head = tail = curitem;
+ } else {
+ tail->next = curitem;
+ tail = curitem;
+ }
+
+ /* go back to text state */
+ state = TEXT_HTML_STATE;
+
+ textStart = FB_GetPointer(fb);
+ startLine = FB_GetLineNum(fb);
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ /* End of the file. Wrap up any remaining text */
+ if(state == SCRIPT_HTML_STATE) {
+ if(tail && tail->type==TAG_ITEM) {
+ PR_fprintf(errorFD, "ERROR: <SCRIPT> tag at %s:%d is not followed "
+ "by a </SCRIPT> tag.\n", filename, tail->startLine);
+ } else {
+ PR_fprintf(errorFD, "ERROR: <SCRIPT> tag in file %s is not followed"
+ " by a </SCRIPT tag.\n", filename);
+ }
+ errorCount++;
+ goto loser;
+ }
+ curOffset = FB_GetPointer(fb)-1;
+ if(curOffset >= textStart) {
+ text = NULL;
+ if( FB_GetRange(fb, textStart, curOffset, &text) !=
+ curOffset-textStart+1) {
+ PR_fprintf(errorFD, "Unable to read from %s.\n", filename);
+ errorCount++;
+ goto loser;
+ }
+ curitem = CreateTextItem(text, startLine, linenum);
+ text = NULL;
+ if(tail == NULL) {
+ head = tail = curitem;
+ } else {
+ tail->next = curitem;
+ tail = curitem;
+ }
+ }
+
+ if(dumpParse) {
+ PrintHTMLStream(outputFD, head);
+ }
+
+
+
+
+ /*
+ * Now we have a stream of tags and text. Go through and deal with each.
+ */
+ for(curitem = head; curitem; curitem = curitem->next) {
+ TagItem *tagp=NULL;
+ AVPair *pairp=NULL;
+ char *src=NULL, *id=NULL, *codebase=NULL;
+ PRBool hasEventHandler=PR_FALSE;
+ int i;
+
+ /* Reset archive directory for each tag */
+ if(archiveDir) {
+ PR_Free(archiveDir); archiveDir = NULL;
+ }
+
+ /* We only analyze tags */
+ if(curitem->type != TAG_ITEM) {
+ continue;
+ }
+
+ tagp = curitem->item.tag;
+
+ /* go through the attributes to get information */
+ for(pairp=tagp->attList; pairp; pairp=pairp->next) {
+
+ /* ARCHIVE= */
+ if( !PL_strcasecmp(pairp->attribute, "archive")) {
+ if(archiveDir) {
+ /* Duplicate attribute. Print warning */
+ PR_fprintf(errorFD,
+ "warning: \"%s\" attribute overwrites previous attribute"
+ " in tag starting at %s:%d.\n",
+ pairp->attribute, filename, curitem->startLine);
+ warningCount++;
+ PR_Free(archiveDir);
+ }
+ archiveDir = PL_strdup(pairp->value);
+
+ /* Substiture ".arc" for ".jar" */
+ if( (PL_strlen(archiveDir)<4) ||
+ PL_strcasecmp((archiveDir+strlen(archiveDir)-4), ".jar")){
+ PR_fprintf(errorFD,
+ "warning: ARCHIVE attribute should end in \".jar\" in tag"
+ " starting on %s:%d.\n", filename, curitem->startLine);
+ warningCount++;
+ PR_Free(archiveDir);
+ archiveDir = PR_smprintf("%s.arc", archiveDir);
+ } else {
+ PL_strcpy(archiveDir+strlen(archiveDir)-4, ".arc");
+ }
+
+ /* Record the first archive. This will be used later if
+ * the archive is not specified */
+ if(firstArchiveDir == NULL) {
+ firstArchiveDir = PL_strdup(archiveDir);
+ }
+ }
+
+ /* CODEBASE= */
+ else if( !PL_strcasecmp(pairp->attribute, "codebase")) {
+ if(codebase) {
+ /* Duplicate attribute. Print warning */
+ PR_fprintf(errorFD,
+ "warning: \"%s\" attribute overwrites previous attribute"
+ " in tag staring at %s:%d.\n",
+ pairp->attribute, filename, curitem->startLine);
+ warningCount++;
+ }
+ codebase = pairp->value;
+ }
+
+ /* SRC= and HREF= */
+ else if( !PORT_Strcasecmp(pairp->attribute, "src") ||
+ !PORT_Strcasecmp(pairp->attribute, "href") ) {
+ if(src) {
+ /* Duplicate attribute. Print warning */
+ PR_fprintf(errorFD,
+ "warning: \"%s\" attribute overwrites previous attribute"
+ " in tag staring at %s:%d.\n",
+ pairp->attribute, filename, curitem->startLine);
+ warningCount++;
+ }
+ src = pairp->value;
+ }
+
+ /* CODE= */
+ else if(!PORT_Strcasecmp(pairp->attribute, "code") ) {
+ /*!!!XXX Change PORT to PL all over this code !!! */
+ if(src) {
+ /* Duplicate attribute. Print warning */
+ PR_fprintf(errorFD,
+ "warning: \"%s\" attribute overwrites previous attribute"
+ " ,in tag staring at %s:%d.\n",
+ pairp->attribute, filename, curitem->startLine);
+ warningCount++;
+ }
+ src = pairp->value;
+
+ /* Append a .class if one is not already present */
+ if( (PL_strlen(src)<6) ||
+ PL_strcasecmp( (src + PL_strlen(src) - 6), ".class") ) {
+ src = PR_smprintf("%s.class", src);
+ /* Put this string back into the data structure so it
+ * will be deallocated properly */
+ PR_Free(pairp->value);
+ pairp->value = src;
+ }
+ }
+
+ /* ID= */
+ else if (!PL_strcasecmp(pairp->attribute, "id") ) {
+ if(id) {
+ /* Duplicate attribute. Print warning */
+ PR_fprintf(errorFD,
+ "warning: \"%s\" attribute overwrites previous attribute"
+ " in tag staring at %s:%d.\n",
+ pairp->attribute, filename, curitem->startLine);
+ warningCount++;
+ }
+ id = pairp->value;
+ }
+
+ /* STYLE= */
+ /* style= attributes, along with JS entities, are stored into
+ * files with dynamically generated names. The filenames are
+ * based on the order in which the text is found in the file.
+ * All JS entities on all lines up to and including the line
+ * containing the end of the tag that has this style= attribute
+ * will be processed before this style=attribute. So we need
+ * to record the line that this _tag_ (not the attribute) ends on.
+ */
+ else if(!PL_strcasecmp(pairp->attribute, "style") && pairp->value) {
+ HTMLItem *styleItem;
+ /* Put this item on the style list */
+ styleItem = CreateTextItem(PL_strdup(pairp->value),
+ curitem->startLine, curitem->endLine);
+ if(styleListTail == NULL) {
+ styleList = styleListTail = styleItem;
+ } else {
+ styleListTail->next = styleItem;
+ styleListTail = styleItem;
+ }
+ }
+
+ /* Event handlers */
+ else {
+ for(i=0; i < num_handlers; i++) {
+ if(!PL_strcasecmp(event_handlers[i], pairp->attribute)) {
+ hasEventHandler = PR_TRUE;
+ break;
+ }
+ }
+ }
+
+ /* JS Entity */
+ {
+ char *entityStart, *entityEnd;
+ HTMLItem *entityItem;
+
+ /* go through each JavaScript entity ( &{...}; ) and store it
+ * in the entityList. The important thing is to record what
+ * line number it's on, so we can get it in the right order
+ * in relation to style= attributes.
+ * Apparently, these can't flow across lines, so the start and
+ * end line will be the same. That helps matters.
+ */
+ entityEnd = pairp->value;
+ while( entityEnd &&
+ (entityStart = PL_strstr(entityEnd, "&{")) != NULL) {
+ entityStart +=2; /* point at beginning of actual entity */
+ entityEnd = PL_strstr(entityStart, "}");
+ if(entityEnd) {
+ /* Put this item on the entity list */
+ *entityEnd = '\0';
+ entityItem = CreateTextItem(PL_strdup(entityStart),
+ pairp->valueLine, pairp->valueLine);
+ *entityEnd = '}';
+ if(entityListTail) {
+ entityListTail->next = entityItem;
+ entityListTail = entityItem;
+ } else {
+ entityList = entityListTail = entityItem;
+ }
+ }
+ }
+ }
+
+ }
+
+ /* If no archive was supplied, we use the first one of the file */
+ if(!archiveDir && firstArchiveDir) {
+ archiveDir = PL_strdup(firstArchiveDir);
+ }
+
+ /* If we have an event handler, we need to archive this tag */
+ if(hasEventHandler) {
+ if(!id) {
+ PR_fprintf(errorFD,
+ "warning: tag starting at %s:%d has event handler but"
+ " no ID attribute. The tag will not be signed.\n",
+ filename, curitem->startLine);
+ warningCount++;
+ } else if(!archiveDir) {
+ PR_fprintf(errorFD,
+ "warning: tag starting at %s:%d has event handler but"
+ " no ARCHIVE attribute. The tag will not be signed.\n",
+ filename, curitem->startLine);
+ warningCount++;
+ } else {
+ if(SaveInlineScript(tagp->text, id, basedir, archiveDir)) {
+ goto loser;
+ }
+ }
+ }
+
+ switch(tagp->type) {
+ case APPLET_TAG:
+ if(!src) {
+ PR_fprintf(errorFD,
+ "error: APPLET tag starting on %s:%d has no CODE "
+ "attribute.\n", filename, curitem->startLine);
+ errorCount++;
+ goto loser;
+ } else if(!archiveDir) {
+ PR_fprintf(errorFD,
+ "error: APPLET tag starting on %s:%d has no ARCHIVE "
+ "attribute.\n", filename, curitem->startLine);
+ errorCount++;
+ goto loser;
+ } else {
+ if(SaveSource(src, codebase, basedir, archiveDir)) {
+ goto loser;
+ }
+ }
+ break;
+ case SCRIPT_TAG:
+ case LINK_TAG:
+ case STYLE_TAG:
+ if(!archiveDir) {
+ PR_fprintf(errorFD,
+ "error: %s tag starting on %s:%d has no ARCHIVE "
+ "attribute.\n", TagTypeToString(tagp->type),
+ filename, curitem->startLine);
+ errorCount++;
+ goto loser;
+ } else if(src) {
+ if(SaveSource(src, codebase, basedir, archiveDir)) {
+ goto loser;
+ }
+ } else if(id) {
+ /* Save the next text item */
+ if(!curitem->next || (curitem->next->type != TEXT_ITEM)) {
+ PR_fprintf(errorFD,
+ "warning: %s tag starting on %s:%d is not followed"
+ " by script text.\n", TagTypeToString(tagp->type),
+ filename, curitem->startLine);
+ warningCount++;
+ /* just create empty file */
+ if(SaveInlineScript("", id, basedir, archiveDir)) {
+ goto loser;
+ }
+ } else {
+ curitem = curitem->next;
+ if(SaveInlineScript(curitem->item.text, id, basedir,
+ archiveDir)){
+ goto loser;
+ }
+ }
+ } else {
+ /* No src or id tag--warning */
+ PR_fprintf(errorFD,
+ "warning: %s tag starting on %s:%d has no SRC or"
+ " ID attributes. Will not sign.\n",
+ TagTypeToString(tagp->type), filename, curitem->startLine);
+ warningCount++;
+ }
+ break;
+ default:
+ /* do nothing for other tags */
+ break;
+ }
+
+ }
+
+ /* Now deal with all the unnamable scripts */
+ if(firstArchiveDir) {
+ HTMLItem *style, *entity;
+
+ /* Go through the lists of JS entities and style attributes. Do them
+ * in chronological order within a list. Pick the list with the lower
+ * endLine. In case of a tie, entities come first.
+ */
+ style = styleList; entity = entityList;
+ while(style || entity) {
+ if(!entity || (style && (style->endLine < entity->endLine))) {
+ /* Process style */
+ SaveUnnamableScript(style->item.text, basedir, firstArchiveDir,
+ filename);
+ style=style->next;
+ } else {
+ /* Process entity */
+ SaveUnnamableScript(entity->item.text, basedir, firstArchiveDir,
+ filename);
+ entity=entity->next;
+ }
+ }
+ }
+
+
+ retval = 0;
+loser:
+ /* Blow away the stream */
+ while(head) {
+ curitem = head;
+ head = head->next;
+ DestroyHTMLItem(curitem);
+ }
+ while(styleList) {
+ curitem = styleList;
+ styleList = styleList->next;
+ DestroyHTMLItem(curitem);
+ }
+ while(entityList) {
+ curitem = entityList;
+ entityList = entityList->next;
+ DestroyHTMLItem(curitem);
+ }
+ if(text) {
+ PR_Free(text); text=NULL;
+ }
+ if(fb) {
+ FB_Destroy(fb); fb=NULL;
+ }
+ if(fd) {
+ PR_Close(fd);
+ }
+ if(tagerr) {
+ PR_smprintf_free(tagerr); tagerr=NULL;
+ }
+ if(archiveDir) {
+ PR_Free(archiveDir); archiveDir=NULL;
+ }
+ if(firstArchiveDir) {
+ PR_Free(firstArchiveDir); firstArchiveDir=NULL;
+ }
+ return retval;
+}
+
+/**********************************************************************
+ *
+ * e n s u r e E x i s t s
+ *
+ * Check for existence of indicated directory. If it doesn't exist,
+ * it will be created.
+ * Returns PR_SUCCESS if the directory is present, PR_FAILURE otherwise.
+ */
+static PRStatus
+ensureExists (char *base, char *path)
+{
+ char fn [FNSIZE];
+ PRDir *dir;
+ sprintf (fn, "%s/%s", base, path);
+
+ /*PR_fprintf(outputFD, "Trying to open directory %s.\n", fn);*/
+
+ if( (dir=PR_OpenDir(fn)) ) {
+ PR_CloseDir(dir);
+ return PR_SUCCESS;
+ }
+ return PR_MkDir(fn, 0777);
+}
+
+/***************************************************************************
+ *
+ * m a k e _ d i r s
+ *
+ * Ensure that the directory portion of the path exists. This may require
+ * making the directory, and its parent, and its parent's parent, etc.
+ */
+static int
+make_dirs(char *path, int file_perms)
+{
+ char *Path;
+ char *start;
+ char *sep;
+ int ret = 0;
+ PRFileInfo info;
+
+ if(!path) {
+ return 0;
+ }
+
+ Path = PL_strdup(path);
+ start = strpbrk(Path, "/\\");
+ if(!start) {
+ return 0;
+ }
+ start++; /* start right after first slash */
+
+ /* Each time through the loop add one more directory. */
+ while( (sep=strpbrk(start, "/\\")) ) {
+ *sep = '\0';
+
+ if( PR_GetFileInfo(Path, &info) != PR_SUCCESS) {
+ /* No such dir, we have to create it */
+ if( PR_MkDir(Path, file_perms) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "ERROR: Unable to create directory %s.\n",
+ Path);
+ errorCount++;
+ ret = -1;
+ goto loser;
+ }
+ } else {
+ /* something exists by this name, make sure it's a directory */
+ if( info.type != PR_FILE_DIRECTORY ) {
+ PR_fprintf(errorFD, "ERROR: Unable to create directory %s.\n",
+ Path);
+ errorCount++;
+ ret = -1;
+ goto loser;
+ }
+ }
+
+ start = sep+1; /* start after the next slash */
+ *sep = '/';
+ }
+
+loser:
+ PR_Free(Path);
+ return ret;
+}
+
+/*
+ * c o p y i n t o
+ *
+ * Function to copy file "from" to path "to".
+ *
+ */
+static int
+copyinto (char *from, char *to)
+{
+ PRInt32 num;
+ char buf [BUFSIZ];
+ PRFileDesc *infp=NULL, *outfp=NULL;
+ int retval = -1;
+
+ if ((infp = PR_Open(from, PR_RDONLY, 0777)) == NULL) {
+ PR_fprintf(errorFD, "ERROR: Unable to open \"%s\" for reading.\n",
+ from);
+ errorCount++;
+ goto finish;
+ }
+
+ /* If to already exists, print a warning before deleting it */
+ if(PR_Access(to, PR_ACCESS_EXISTS) == PR_SUCCESS) {
+ PR_fprintf(errorFD, "warning: %s already exists--will overwrite\n",
+ to);
+ warningCount++;
+ if(rm_dash_r(to)) {
+ PR_fprintf(errorFD,
+ "ERROR: Unable to remove %s.\n", to);
+ errorCount++;
+ goto finish;
+ }
+ }
+
+ if ((outfp = PR_Open(to, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0777))
+ == NULL) {
+ char *errBuf=NULL;
+
+ errBuf = PR_Malloc(PR_GetErrorTextLength());
+ PR_fprintf(errorFD, "ERROR: Unable to open \"%s\" for writing.\n",
+ to);
+ if(PR_GetErrorText(errBuf)) {
+ PR_fprintf(errorFD, "Cause: %s\n", errBuf);
+ }
+ if(errBuf) {
+ PR_Free(errBuf);
+ }
+ errorCount++;
+ goto finish;
+ }
+
+ while( (num = PR_Read(infp, buf, BUFSIZ)) >0) {
+ if(PR_Write(outfp, buf, num) != num) {
+ PR_fprintf(errorFD, "ERROR: Error writing to %s.\n", to);
+ errorCount++;
+ goto finish;
+ }
+ }
+
+ retval = 0;
+finish:
+ if(infp) PR_Close(infp);
+ if(outfp) PR_Close(outfp);
+
+ return retval;
+}
diff --git a/security/nss/cmd/signtool/list.c b/security/nss/cmd/signtool/list.c
new file mode 100644
index 000000000..33ec93d93
--- /dev/null
+++ b/security/nss/cmd/signtool/list.c
@@ -0,0 +1,278 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "signtool.h"
+#include "pk11func.h"
+#include "certdb.h"
+
+static int num_trav_certs = 0;
+static SECStatus cert_trav_callback(CERTCertificate *cert, SECItem *k,
+ void *data);
+
+/*********************************************************************
+ *
+ * L i s t C e r t s
+ */
+int
+ListCerts(char *key, int list_certs)
+{
+ int failed = 0;
+ SECStatus rv;
+ char *ugly_list;
+ CERTCertDBHandle *db;
+
+ CERTCertificate *cert;
+ CERTVerifyLog errlog;
+
+ errlog.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if( errlog.arena == NULL) {
+ out_of_memory();
+ }
+ errlog.head = NULL;
+ errlog.tail = NULL;
+ errlog.count = 0;
+
+ ugly_list = PORT_ZAlloc (16);
+
+ if (ugly_list == NULL) {
+ out_of_memory();
+ }
+
+ *ugly_list = 0;
+
+ db= CERT_GetDefaultCertDB();
+
+ if (list_certs == 2) {
+ PR_fprintf(outputFD, "\nS Certificates\n");
+ PR_fprintf(outputFD, "- ------------\n");
+ } else {
+ PR_fprintf(outputFD, "\nObject signing certificates\n");
+ PR_fprintf(outputFD, "---------------------------------------\n");
+ }
+
+ num_trav_certs = 0;
+
+ /* Traverse non-internal DBs */
+ rv = PK11_TraverseSlotCerts(cert_trav_callback, (void*)&list_certs,
+ NULL /*wincx*/);
+
+ if (rv) {
+ PR_fprintf(outputFD, "**Traverse of non-internal DBs failed**\n");
+ return -1;
+ }
+
+ if (num_trav_certs == 0) {
+ PR_fprintf(outputFD,
+ "You don't appear to have any object signing certificates.\n");
+ }
+
+ if (list_certs == 2) {
+ PR_fprintf(outputFD, "- ------------\n");
+ } else {
+ PR_fprintf(outputFD, "---------------------------------------\n");
+ }
+
+ if (list_certs == 1) {
+ PR_fprintf(outputFD,
+ "For a list including CA's, use \"%s -L\"\n", PROGRAM_NAME);
+ }
+
+ if(list_certs == 2) {
+ PR_fprintf(outputFD,
+ "Certificates that can be used to sign objects have *'s to "
+ "their left.\n");
+ }
+
+ if (key) {
+ /* Do an analysis of the given cert */
+
+ cert = PK11_FindCertFromNickname(key, NULL /*wincx*/);
+
+ if (cert) {
+ PR_fprintf(outputFD,
+ "\nThe certificate with nickname \"%s\" was found:\n",
+ cert->nickname);
+ PR_fprintf(outputFD,
+ "\tsubject name: %s\n", cert->subjectName);
+ PR_fprintf(outputFD,
+ "\tissuer name: %s\n", cert->issuerName);
+
+ PR_fprintf(outputFD, "\n");
+
+ rv = CERT_CertTimesValid (cert);
+ if(rv != SECSuccess) {
+ PR_fprintf(outputFD, "**This certificate is expired**\n");
+ } else {
+ PR_fprintf(outputFD, "This certificate is not expired.\n");
+ }
+
+ rv = CERT_VerifyCert (db, cert, PR_TRUE,
+ certUsageObjectSigner, PR_Now(), NULL, &errlog);
+
+ if (rv != SECSuccess) {
+ failed = 1;
+ if(errlog.count > 0) {
+ PR_fprintf(outputFD,
+ "**Certificate validation failed for the "
+ "following reason(s):**\n");
+ } else {
+ PR_fprintf(outputFD, "**Certificate validation failed**");
+ }
+ } else {
+ PR_fprintf(outputFD, "This certificate is valid.\n");
+ }
+ displayVerifyLog(&errlog);
+
+
+ } else {
+ failed = 1;
+ PR_fprintf(outputFD,
+ "The certificate with nickname \"%s\" was NOT FOUND\n",
+ key);
+ }
+ }
+
+ if(errlog.arena != NULL) {
+ PORT_FreeArena(errlog.arena, PR_FALSE);
+ }
+
+ if (failed) {
+ return -1;
+ }
+ return 0;
+}
+
+/********************************************************************
+ *
+ * c e r t _ t r a v _ c a l l b a c k
+ */
+static SECStatus
+cert_trav_callback(CERTCertificate *cert, SECItem *k, void *data)
+{
+ int isSigningCert;
+ int list_certs = 1;
+
+ char *name, *issuerCN, *expires;
+ CERTCertificate *issuerCert = NULL;
+
+ if(data) {
+ list_certs = *((int*)data);
+ }
+
+ if (cert->nickname)
+ {
+ name = cert->nickname;
+
+ isSigningCert = cert->nsCertType & NS_CERT_TYPE_OBJECT_SIGNING;
+ issuerCert = CERT_FindCertIssuer (cert, PR_Now(), certUsageObjectSigner);
+ issuerCN = CERT_GetCommonName (&cert->issuer);
+
+ if (!isSigningCert && list_certs == 1)
+ return (SECSuccess);
+
+ /* Add this name or email to list */
+
+ if (name)
+ {
+ int rv;
+
+ num_trav_certs++;
+ if(list_certs == 2) {
+ PR_fprintf(outputFD, "%s ", isSigningCert ? "*" : " ");
+ }
+ PR_fprintf(outputFD, "%s\n", name);
+
+ if (list_certs == 1)
+ {
+ if(issuerCert == NULL) {
+ PR_fprintf(outputFD,
+ "\t++ Error ++ Unable to find issuer certificate\n");
+ return SECSuccess; /*function was a success even if cert is bogus*/
+ }
+ if (issuerCN == NULL)
+ PR_fprintf(outputFD, " Issued by: %s\n", issuerCert->nickname);
+ else
+ PR_fprintf(outputFD,
+ " Issued by: %s (%s)\n", issuerCert->nickname, issuerCN);
+
+ expires = DER_UTCDayToAscii (&cert->validity.notAfter);
+
+ if (expires)
+ PR_fprintf(outputFD, " Expires: %s\n", expires);
+
+ rv = CERT_CertTimesValid (cert);
+
+ if (rv != SECSuccess)
+ PR_fprintf(outputFD, " ++ Error ++ THIS CERTIFICATE IS EXPIRED\n");
+
+ if (rv == SECSuccess)
+ {
+ rv = CERT_VerifyCertNow (cert->dbhandle, cert,
+ PR_TRUE, certUsageObjectSigner, NULL);
+
+ if (rv != SECSuccess)
+ {
+ rv = PORT_GetError();
+ PR_fprintf(outputFD,
+ " ++ Error ++ THIS CERTIFICATE IS NOT VALID (%s)\n",
+ secErrorString(rv)); }
+ }
+
+ expires = DER_UTCDayToAscii (&issuerCert->validity.notAfter);
+ if (expires == NULL) expires = "(unknown)";
+
+ rv = CERT_CertTimesValid (issuerCert);
+
+ if (rv != SECSuccess)
+ PR_fprintf(outputFD,
+ " ++ Error ++ ISSUER CERT \"%s\" EXPIRED ON %s\n",
+ issuerCert->nickname, expires);
+
+ if (rv == SECSuccess)
+ {
+ rv = CERT_VerifyCertNow (issuerCert->dbhandle, issuerCert,
+ PR_TRUE, certUsageVerifyCA, NULL);
+ if (rv != SECSuccess)
+ {
+ rv = PORT_GetError();
+ PR_fprintf(outputFD,
+ " ++ Error ++ ISSUER CERT \"%s\" IS NOT VALID (%s)\n", issuerCert->nickname, secErrorString(rv));
+ }
+ }
+ }
+ }
+ }
+
+ return (SECSuccess);
+}
+
diff --git a/security/nss/cmd/signtool/manifest.mn b/security/nss/cmd/signtool/manifest.mn
new file mode 100644
index 000000000..448734056
--- /dev/null
+++ b/security/nss/cmd/signtool/manifest.mn
@@ -0,0 +1,57 @@
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+MODULE = nss
+
+EXPORTS =
+
+CSRCS = signtool.c \
+ certgen.c \
+ javascript.c \
+ list.c \
+ sign.c \
+ util.c \
+ verify.c \
+ zip.c \
+ $(NULL)
+
+PROGRAM = signtool
+
+REQUIRES = dbm seccmd
+
+DEFINES += -DNSPR20
+
+USE_STATIC_LIBS = 1
+
+EXTRA_LIBS = $(JAR_LIBS)
diff --git a/security/nss/cmd/signtool/sign.c b/security/nss/cmd/signtool/sign.c
new file mode 100644
index 000000000..59323c92d
--- /dev/null
+++ b/security/nss/cmd/signtool/sign.c
@@ -0,0 +1,861 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "signtool.h"
+#include "zip.h"
+#include "prmem.h"
+#include "blapi.h"
+#include "sechash.h" /* for HASH_GetHashObject() */
+
+static int create_pk7 (char *dir, char *keyName, int *keyType);
+static int jar_find_key_type (CERTCertificate *cert);
+static int manifesto (char *dirname, char *install_script, PRBool recurse);
+static int manifesto_fn(char *relpath, char *basedir, char *reldir,
+ char *filename, void *arg);
+static int sign_all_arc_fn(char *relpath, char *basedir, char *reldir,
+ char *filename, void *arg);
+static int add_meta (FILE *fp, char *name);
+static int SignFile (FILE *outFile, FILE *inFile, CERTCertificate *cert);
+static int generate_SF_file (char *manifile, char *who);
+static int calculate_MD5_range (FILE *fp, long r1, long r2, JAR_Digest *dig);
+static void SignOut (void *arg, const char *buf, unsigned long len);
+
+static char *metafile = NULL;
+static int optimize = 0;
+static FILE *mf;
+static ZIPfile *zipfile=NULL;
+
+/*
+ * S i g n A r c h i v e
+ *
+ * Sign an individual archive tree. A directory
+ * called META-INF is created underneath this.
+ *
+ */
+int
+SignArchive(char *tree, char *keyName, char *zip_file, int javascript,
+ char *meta_file, char *install_script, int _optimize, PRBool recurse)
+{
+ int status;
+ char tempfn [FNSIZE], fullfn [FNSIZE];
+ int keyType = rsaKey;
+
+ metafile = meta_file;
+ optimize = _optimize;
+
+ if(zip_file) {
+ zipfile = JzipOpen(zip_file, NULL /*no comment*/);
+ }
+
+ manifesto (tree, install_script, recurse);
+
+ if (keyName)
+ {
+ status = create_pk7 (tree, keyName, &keyType);
+ if (status < 0)
+ {
+ PR_fprintf(errorFD, "the tree \"%s\" was NOT SUCCESSFULLY SIGNED\n", tree);
+ errorCount++;
+ exit (ERRX);
+ }
+ }
+
+ /* mf to zip */
+
+ strcpy (tempfn, "META-INF/manifest.mf");
+ sprintf (fullfn, "%s/%s", tree, tempfn);
+ JzipAdd(fullfn, tempfn, zipfile, compression_level);
+
+ /* sf to zip */
+
+ sprintf (tempfn, "META-INF/%s.sf", base);
+ sprintf (fullfn, "%s/%s", tree, tempfn);
+ JzipAdd(fullfn, tempfn, zipfile, compression_level);
+
+ /* rsa/dsa to zip */
+
+ sprintf (tempfn, "META-INF/%s.%s", base, (keyType==dsaKey ? "dsa" : "rsa"));
+ sprintf (fullfn, "%s/%s", tree, tempfn);
+ JzipAdd(fullfn, tempfn, zipfile, compression_level);
+
+ JzipClose(zipfile);
+
+ if(verbosity >= 0) {
+ if (javascript) {
+ PR_fprintf(outputFD,"jarfile \"%s\" signed successfully\n",
+ zip_file);
+ } else {
+ PR_fprintf(outputFD, "tree \"%s\" signed successfully\n", tree);
+ }
+ }
+
+ return 0;
+}
+
+typedef struct {
+ char *keyName;
+ int javascript;
+ char *metafile;
+ char *install_script;
+ int optimize;
+} SignArcInfo;
+
+/*
+ * S i g n A l l A r c
+ *
+ * Javascript may generate multiple .arc directories, one
+ * for each jar archive needed. Sign them all.
+ *
+ */
+int
+SignAllArc(char *jartree, char *keyName, int javascript, char *metafile,
+ char *install_script, int optimize, PRBool recurse)
+{
+ SignArcInfo info;
+
+ info.keyName = keyName;
+ info.javascript = javascript;
+ info.metafile = metafile;
+ info.install_script = install_script;
+ info.optimize = optimize;
+
+ return foreach(jartree, "", sign_all_arc_fn, recurse,
+ PR_TRUE /*include dirs*/, (void*)&info);
+}
+
+static int
+sign_all_arc_fn(char *relpath, char *basedir, char *reldir, char *filename,
+ void *arg)
+{
+ char *zipfile=NULL;
+ char *arc=NULL, *archive=NULL;
+ int retval=0;
+ SignArcInfo *infop = (SignArcInfo*)arg;
+
+ /* Make sure there is one and only one ".arc" in the relative path,
+ * and that it is at the end of the path (don't sign .arcs within .arcs) */
+ if ( (PL_strcaserstr(relpath, ".arc") == relpath + strlen(relpath) - 4) &&
+ (PL_strcasestr(relpath, ".arc") == relpath + strlen(relpath) - 4) ) {
+
+ if(!infop) {
+ PR_fprintf(errorFD, "%s: Internal failure\n", PROGRAM_NAME);
+ errorCount++;
+ retval = -1;
+ goto finish;
+ }
+ archive = PR_smprintf("%s/%s", basedir, relpath);
+
+ zipfile = PL_strdup(archive);
+ arc = PORT_Strrchr (zipfile, '.');
+
+ if (arc == NULL) {
+ PR_fprintf(errorFD, "%s: Internal failure\n", PROGRAM_NAME);
+ errorCount++;
+ retval = -1;
+ goto finish;
+ }
+
+ PL_strcpy (arc, ".jar");
+
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "\nsigning: %s\n", zipfile);
+ }
+ retval = SignArchive(archive, infop->keyName, zipfile,
+ infop->javascript, infop->metafile, infop->install_script,
+ infop->optimize, PR_TRUE /* recurse */);
+ }
+finish:
+ if(archive) PR_Free(archive);
+ if(zipfile) PR_Free(zipfile);
+
+ return retval;
+}
+
+/*********************************************************************
+ *
+ * c r e a t e _ p k 7
+ */
+static int
+create_pk7 (char *dir, char *keyName, int *keyType)
+{
+ int status = 0;
+ char *file_ext;
+
+ CERTCertificate *cert;
+ CERTCertDBHandle *db;
+
+ FILE *in, *out;
+
+ char sf_file [FNSIZE];
+ char pk7_file [FNSIZE];
+
+
+ /* open cert database */
+ db = CERT_GetDefaultCertDB();
+
+ if (db == NULL)
+ return -1;
+
+
+ /* find cert */
+ /*cert = CERT_FindCertByNicknameOrEmailAddr(db, keyName);*/
+ cert = PK11_FindCertFromNickname(keyName, NULL /*wincx*/);
+
+ if (cert == NULL)
+ {
+ SECU_PrintError
+ (
+ PROGRAM_NAME,
+ "the cert \"%s\" does not exist in the database",
+ keyName
+ );
+ return -1;
+ }
+
+
+ /* determine the key type, which sets the extension for pkcs7 object */
+
+ *keyType = jar_find_key_type (cert);
+ file_ext = (*keyType == dsaKey) ? "dsa" : "rsa";
+
+ sprintf (sf_file, "%s/META-INF/%s.sf", dir, base);
+ sprintf (pk7_file, "%s/META-INF/%s.%s", dir, base, file_ext);
+
+ if ((in = fopen (sf_file, "rb")) == NULL)
+ {
+ PR_fprintf(errorFD, "%s: Can't open %s for reading\n", PROGRAM_NAME, sf_file);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ if ((out = fopen (pk7_file, "wb")) == NULL)
+ {
+ PR_fprintf(errorFD, "%s: Can't open %s for writing\n", PROGRAM_NAME, sf_file);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ status = SignFile (out, in, cert);
+
+ CERT_DestroyCertificate (cert);
+ fclose (in);
+ fclose (out);
+
+ if (status)
+ {
+ PR_fprintf(errorFD, "%s: PROBLEM signing data (%s)\n",
+ PROGRAM_NAME, SECU_ErrorString ((int16) PORT_GetError()));
+ errorCount++;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * j a r _ f i n d _ k e y _ t y p e
+ *
+ * Determine the key type for a given cert, which
+ * should be rsaKey or dsaKey. Any error return 0.
+ *
+ */
+static int
+jar_find_key_type (CERTCertificate *cert)
+{
+ PK11SlotInfo *slot = NULL;
+ SECKEYPrivateKey *privk = NULL;
+ KeyType keyType;
+
+ /* determine its type */
+ PK11_FindObjectForCert (cert, /*wincx*/ NULL, &slot);
+
+ if (slot == NULL)
+ {
+ PR_fprintf(errorFD, "warning - can't find slot for this cert\n");
+ warningCount++;
+ return 0;
+ }
+
+ privk = PK11_FindPrivateKeyFromCert (slot, cert, /*wincx*/ NULL);
+ PK11_FreeSlot (slot);
+
+ if (privk == NULL)
+ {
+ PR_fprintf(errorFD, "warning - can't find private key for this cert\n");
+ warningCount++;
+ return 0;
+ }
+
+ keyType = privk->keyType;
+ SECKEY_DestroyPrivateKey (privk);
+ return keyType;
+ }
+
+
+/*
+ * m a n i f e s t o
+ *
+ * Run once for every subdirectory in which a
+ * manifest is to be created -- usually exactly once.
+ *
+ */
+static int
+manifesto (char *dirname, char *install_script, PRBool recurse)
+{
+ char metadir [FNSIZE], sfname [FNSIZE];
+
+ /* Create the META-INF directory to hold signing info */
+
+ if (PR_Access (dirname, PR_ACCESS_READ_OK))
+ {
+ PR_fprintf(errorFD, "%s: unable to read your directory: %s\n", PROGRAM_NAME,
+ dirname);
+ errorCount++;
+ perror (dirname);
+ exit (ERRX);
+ }
+
+ if (PR_Access (dirname, PR_ACCESS_WRITE_OK)) {
+ PR_fprintf(errorFD, "%s: unable to write to your directory: %s\n",
+ PROGRAM_NAME, dirname);
+ errorCount++;
+ perror(dirname);
+ exit(ERRX);
+ }
+
+ sprintf (metadir, "%s/META-INF", dirname);
+
+ strcpy (sfname, metadir);
+
+ PR_MkDir (metadir, 0777);
+
+ strcat (metadir, "/");
+ strcat (metadir, MANIFEST);
+
+ if ((mf = fopen (metadir, "wb")) == NULL)
+ {
+ perror (MANIFEST);
+ PR_fprintf(errorFD, "%s: Probably, the directory you are trying to"
+
+ " sign has\n", PROGRAM_NAME);
+ PR_fprintf(errorFD, "%s: permissions problems or may not exist.\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "Generating %s file..\n", metadir);
+ }
+
+ fprintf(mf, "Manifest-Version: 1.0\n");
+ fprintf (mf, "Created-By: %s\n", CREATOR);
+ fprintf (mf, "Comments: %s\n", BREAKAGE);
+
+ if (scriptdir)
+ {
+ fprintf (mf, "Comments: --\n");
+ fprintf (mf, "Comments: --\n");
+ fprintf (mf, "Comments: -- This archive signs Javascripts which may not necessarily\n");
+ fprintf (mf, "Comments: -- be included in the physical jar file.\n");
+ fprintf (mf, "Comments: --\n");
+ fprintf (mf, "Comments: --\n");
+ }
+
+ if (install_script)
+ fprintf (mf, "Install-Script: %s\n", install_script);
+
+ if (metafile)
+ add_meta (mf, "+");
+
+ /* Loop through all files & subdirectories */
+ foreach (dirname, "", manifesto_fn, recurse, PR_FALSE /*include dirs */,
+ (void*)NULL);
+
+ fclose (mf);
+
+ strcat (sfname, "/");
+ strcat (sfname, base);
+ strcat (sfname, ".sf");
+
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "Generating %s.sf file..\n", base);
+ }
+ generate_SF_file (metadir, sfname);
+
+ return 0;
+}
+
+/*
+ * m a n i f e s t o _ f n
+ *
+ * Called by pointer from manifesto(), once for
+ * each file within the directory.
+ *
+ */
+static int manifesto_fn
+ (char *relpath, char *basedir, char *reldir, char *filename, void *arg)
+{
+ int use_js;
+
+ JAR_Digest dig;
+ char fullname [FNSIZE];
+
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "--> %s\n", relpath);
+ }
+
+ /* extension matching */
+ if(extensionsGiven) {
+ char *ext;
+
+ ext = PL_strrchr(relpath, '.');
+ if(!ext) {
+ return 0;
+ } else {
+ if(!PL_HashTableLookup(extensions, ext)) {
+ return 0;
+ }
+ }
+ }
+
+ sprintf (fullname, "%s/%s", basedir, relpath);
+
+ fprintf (mf, "\n");
+
+ use_js = 0;
+
+ if (scriptdir && !PORT_Strcmp (scriptdir, reldir))
+ use_js++;
+
+ /* sign non-.js files inside .arc directories
+ using the javascript magic */
+
+ if ( (PL_strcaserstr(filename, ".js") != filename + strlen(filename) - 3)
+ && (PL_strcaserstr(reldir, ".arc") == reldir + strlen(filename)-4))
+ use_js++;
+
+ if (use_js)
+ {
+ fprintf (mf, "Name: %s\n", filename);
+ fprintf (mf, "Magic: javascript\n");
+
+ if (optimize == 0)
+ fprintf (mf, "javascript.id: %s\n", filename);
+
+ if (metafile)
+ add_meta (mf, filename);
+ }
+ else
+ {
+ fprintf (mf, "Name: %s\n", relpath);
+ if (metafile)
+ add_meta (mf, relpath);
+ }
+
+ JAR_digest_file (fullname, &dig);
+
+
+ if (optimize == 0)
+ {
+ fprintf (mf, "Digest-Algorithms: MD5 SHA1\n");
+ fprintf (mf, "MD5-Digest: %s\n", BTOA_DataToAscii (dig.md5, MD5_LENGTH));
+ }
+
+ fprintf (mf, "SHA1-Digest: %s\n", BTOA_DataToAscii (dig.sha1, SHA1_LENGTH));
+
+ if(!use_js) {
+ JzipAdd(fullname, relpath, zipfile, compression_level);
+ }
+
+ return 0;
+}
+
+/*
+ * a d d _ m e t a
+ *
+ * Parse the metainfo file, and add any details
+ * necessary to the manifest file. In most cases you
+ * should be using the -i option (ie, for SmartUpdate).
+ *
+ */
+static int add_meta (FILE *fp, char *name)
+{
+ FILE *met;
+ char buf [BUFSIZ];
+
+ int place;
+ char *pattern, *meta;
+
+ int num = 0;
+
+ if ((met = fopen (metafile, "r")) != NULL)
+ {
+ while (fgets (buf, BUFSIZ, met))
+ {
+ char *s;
+
+ for (s = buf; *s && *s != '\n' && *s != '\r'; s++);
+ *s = 0;
+
+ if (*buf == 0)
+ continue;
+
+ pattern = buf;
+
+ /* skip to whitespace */
+ for (s = buf; *s && *s != ' ' && *s != '\t'; s++);
+
+ /* terminate pattern */
+ if (*s == ' ' || *s == '\t') *s++ = 0;
+
+ /* eat through whitespace */
+ while (*s == ' ' || *s == '\t') s++;
+
+ meta = s;
+
+ /* this will eventually be regexp matching */
+
+ place = 0;
+ if (!PORT_Strcmp (pattern, name))
+ place = 1;
+
+ if (place)
+ {
+ num++;
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "[%s] %s\n", name, meta);
+ }
+ fprintf (fp, "%s\n", meta);
+ }
+ }
+ fclose (met);
+ }
+ else
+ {
+ PR_fprintf(errorFD, "%s: can't open metafile: %s\n", PROGRAM_NAME, metafile);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ return num;
+}
+
+/**********************************************************************
+ *
+ * S i g n F i l e
+ */
+static int
+SignFile (FILE *outFile, FILE *inFile, CERTCertificate *cert)
+{
+ int nb;
+ char ibuf[4096], digestdata[32];
+ const SECHashObject *hashObj;
+ void *hashcx;
+ unsigned int len;
+
+ SECItem digest;
+ SEC_PKCS7ContentInfo *cinfo;
+ SECStatus rv;
+
+ if (outFile == NULL || inFile == NULL || cert == NULL)
+ return -1;
+
+ /* XXX probably want to extend interface to allow other hash algorithms */
+ hashObj = HASH_GetHashObject(HASH_AlgSHA1);
+
+ hashcx = (* hashObj->create)();
+ if (hashcx == NULL)
+ return -1;
+
+ (* hashObj->begin)(hashcx);
+
+ for (;;)
+ {
+ if (feof(inFile)) break;
+ nb = fread(ibuf, 1, sizeof(ibuf), inFile);
+ if (nb == 0)
+ {
+ if (ferror(inFile))
+ {
+ PORT_SetError(SEC_ERROR_IO);
+ (* hashObj->destroy)(hashcx, PR_TRUE);
+ return -1;
+ }
+ /* eof */
+ break;
+ }
+ (* hashObj->update)(hashcx, (unsigned char *) ibuf, nb);
+ }
+
+ (* hashObj->end)(hashcx, (unsigned char *) digestdata, &len, 32);
+ (* hashObj->destroy)(hashcx, PR_TRUE);
+
+ digest.data = (unsigned char *) digestdata;
+ digest.len = len;
+
+ cinfo = SEC_PKCS7CreateSignedData
+ (cert, certUsageObjectSigner, NULL,
+ SEC_OID_SHA1, &digest, NULL, NULL);
+
+ if (cinfo == NULL)
+ return -1;
+
+ rv = SEC_PKCS7IncludeCertChain (cinfo, NULL);
+ if (rv != SECSuccess)
+ {
+ SEC_PKCS7DestroyContentInfo (cinfo);
+ return -1;
+ }
+
+ if (no_time == 0)
+ {
+ rv = SEC_PKCS7AddSigningTime (cinfo);
+ if (rv != SECSuccess)
+ {
+ /* don't check error */
+ }
+ }
+
+ if(password) {
+ rv = SEC_PKCS7Encode(cinfo, SignOut, outFile, NULL,
+ (SECKEYGetPasswordKey) password_hardcode, NULL);
+ } else {
+ rv = SEC_PKCS7Encode(cinfo, SignOut, outFile, NULL, NULL,
+ NULL);
+ }
+
+
+ SEC_PKCS7DestroyContentInfo (cinfo);
+
+ if (rv != SECSuccess)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * g e n e r a t e _ S F _ f i l e
+ *
+ * From the supplied manifest file, calculates
+ * digests on the various sections, creating a .SF
+ * file in the process.
+ *
+ */
+static int generate_SF_file (char *manifile, char *who)
+{
+ FILE *sf;
+ FILE *mf;
+
+ long r1, r2, r3;
+
+ char whofile [FNSIZE];
+ char *buf, *name = NULL;
+
+ JAR_Digest dig;
+
+ int line = 0;
+
+ strcpy (whofile, who);
+
+ if ((mf = fopen (manifile, "rb")) == NULL)
+ {
+ perror (manifile);
+ exit (ERRX);
+ }
+
+ if ((sf = fopen (whofile, "wb")) == NULL)
+ {
+ perror (who);
+ exit (ERRX);
+ }
+
+ buf = (char *) PORT_ZAlloc (BUFSIZ);
+
+ if (buf)
+ name = (char *) PORT_ZAlloc (BUFSIZ);
+
+ if (buf == NULL || name == NULL)
+ out_of_memory();
+
+ fprintf (sf, "Signature-Version: 1.0\n");
+ fprintf (sf, "Created-By: %s\n", CREATOR);
+ fprintf (sf, "Comments: %s\n", BREAKAGE);
+
+ if (fgets (buf, BUFSIZ, mf) == NULL)
+ {
+ PR_fprintf(errorFD, "%s: empty manifest file!\n", PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ if (strncmp (buf, "Manifest-Version:", 17))
+ {
+ PR_fprintf(errorFD, "%s: not a manifest file!\n", PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ fseek (mf, 0L, SEEK_SET);
+
+ /* Process blocks of headers, and calculate their hashen */
+
+ while (1)
+ {
+ /* Beginning range */
+ r1 = ftell (mf);
+
+ if (fgets (name, BUFSIZ, mf) == NULL)
+ break;
+
+ line++;
+
+ if (r1 != 0 && strncmp (name, "Name:", 5))
+ {
+ PR_fprintf(errorFD, "warning: unexpected input in manifest file \"%s\" at line %d:\n", manifile, line);
+ PR_fprintf(errorFD, "%s\n", name);
+ warningCount++;
+ }
+
+ r2 = r1;
+ while (fgets (buf, BUFSIZ, mf))
+ {
+ if (*buf == 0 || *buf == '\n' || *buf == '\r')
+ break;
+
+ line++;
+
+ /* Ending range for hashing */
+ r2 = ftell (mf);
+ }
+
+ r3 = ftell (mf);
+
+ if (r1)
+ {
+ fprintf (sf, "\n");
+ fprintf (sf, "%s", name);
+ }
+
+ calculate_MD5_range (mf, r1, r2, &dig);
+
+ if (optimize == 0)
+ {
+ fprintf (sf, "Digest-Algorithms: MD5 SHA1\n");
+ fprintf (sf, "MD5-Digest: %s\n",
+ BTOA_DataToAscii (dig.md5, MD5_LENGTH));
+ }
+
+ fprintf (sf, "SHA1-Digest: %s\n",
+ BTOA_DataToAscii (dig.sha1, SHA1_LENGTH));
+
+ /* restore normalcy after changing offset position */
+ fseek (mf, r3, SEEK_SET);
+ }
+
+ PORT_Free (buf);
+ PORT_Free (name);
+
+ fclose (sf);
+ fclose (mf);
+
+ return 0;
+}
+
+/*
+ * c a l c u l a t e _ M D 5 _ r a n g e
+ *
+ * Calculate the MD5 digest on a range of bytes in
+ * the specified fopen'd file. Returns base64.
+ *
+ */
+static int
+calculate_MD5_range (FILE *fp, long r1, long r2, JAR_Digest *dig)
+{
+ int num;
+ int range;
+ unsigned char *buf;
+
+ MD5Context *md5 = 0;
+ SHA1Context *sha1 = 0;
+
+ unsigned int sha1_length, md5_length;
+
+ range = r2 - r1;
+
+ /* position to the beginning of range */
+ fseek (fp, r1, SEEK_SET);
+
+ buf = (unsigned char *) PORT_ZAlloc (range);
+ if (buf == NULL)
+ out_of_memory();
+
+ if ((num = fread (buf, 1, range, fp)) != range)
+ {
+ PR_fprintf(errorFD, "%s: expected %d bytes, got %d\n", PROGRAM_NAME,
+ range, num);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ md5 = MD5_NewContext();
+ sha1 = SHA1_NewContext();
+
+ if (md5 == NULL || sha1 == NULL)
+ {
+ PR_fprintf(errorFD, "%s: can't generate digest context\n", PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ MD5_Begin (md5);
+ SHA1_Begin (sha1);
+
+ MD5_Update (md5, buf, range);
+ SHA1_Update (sha1, buf, range);
+
+ MD5_End (md5, dig->md5, &md5_length, MD5_LENGTH);
+ SHA1_End (sha1, dig->sha1, &sha1_length, SHA1_LENGTH);
+
+ MD5_DestroyContext (md5, PR_TRUE);
+ SHA1_DestroyContext (sha1, PR_TRUE);
+
+ PORT_Free (buf);
+
+ return 0;
+}
+
+static void SignOut (void *arg, const char *buf, unsigned long len)
+{
+ fwrite (buf, len, 1, (FILE *) arg);
+}
diff --git a/security/nss/cmd/signtool/signtool.c b/security/nss/cmd/signtool/signtool.c
new file mode 100644
index 000000000..4e0236825
--- /dev/null
+++ b/security/nss/cmd/signtool/signtool.c
@@ -0,0 +1,1054 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * SIGNTOOL
+ *
+ * A command line tool to create manifest files
+ * from a directory hierarchy. It is assumed that
+ * the tree will be equivalent to what resides
+ * or will reside in an archive.
+ *
+ *
+ */
+
+#include "signtool.h"
+#include <prmem.h>
+#include <prio.h>
+
+/***********************************************************************
+ * Global Variable Definitions
+ */
+char *progName; /* argv[0] */
+
+/* password on command line. Use for build testing only */
+char *password = NULL;
+
+/* directories or files to exclude in descent */
+PLHashTable *excludeDirs = NULL;
+static PRBool exclusionsGiven = PR_FALSE;
+
+/* zatharus is the man who knows no time, dies tragic death */
+int no_time = 0;
+
+/* -b basename of .rsa, .sf files */
+char *base = DEFAULT_BASE_NAME;
+
+/* Only sign files with this extension */
+PLHashTable *extensions=NULL;
+PRBool extensionsGiven = PR_FALSE;
+
+char *scriptdir = NULL;
+
+int verbosity = 0;
+
+PRFileDesc *outputFD=NULL, *errorFD=NULL;
+
+int errorCount=0, warningCount=0;
+
+int compression_level=DEFAULT_COMPRESSION_LEVEL;
+PRBool compression_level_specified = PR_FALSE;
+
+/* Command-line arguments */
+static char *genkey = NULL;
+static char *verify = NULL;
+static char *zipfile = NULL;
+static char *cert_dir = NULL;
+static int javascript = 0;
+static char *jartree = NULL;
+static char *keyName = NULL;
+static char *metafile = NULL;
+static char *install_script = NULL;
+static int list_certs = 0;
+static int list_modules = 0;
+static int optimize = 0;
+static int enableOCSP = 0;
+static char *tell_who = NULL;
+static char *outfile = NULL;
+static char *cmdFile = NULL;
+static PRBool noRecurse = PR_FALSE;
+static PRBool leaveArc = PR_FALSE;
+static int keySize = -1;
+static char *token = NULL;
+
+typedef enum {
+ UNKNOWN_OPT,
+ QUESTION_OPT,
+ BASE_OPT,
+ COMPRESSION_OPT,
+ CERT_DIR_OPT,
+ EXTENSION_OPT,
+ INSTALL_SCRIPT_OPT,
+ SCRIPTDIR_OPT,
+ CERTNAME_OPT,
+ LIST_OBJSIGN_CERTS_OPT,
+ LIST_ALL_CERTS_OPT,
+ METAFILE_OPT,
+ OPTIMIZE_OPT,
+ ENABLE_OCSP_OPT,
+ PASSWORD_OPT,
+ VERIFY_OPT,
+ WHO_OPT,
+ EXCLUDE_OPT,
+ NO_TIME_OPT,
+ JAVASCRIPT_OPT,
+ ZIPFILE_OPT,
+ GENKEY_OPT,
+ MODULES_OPT,
+ NORECURSE_OPT,
+ SIGNDIR_OPT,
+ OUTFILE_OPT,
+ COMMAND_FILE_OPT,
+ LEAVE_ARC_OPT,
+ VERBOSITY_OPT,
+ KEYSIZE_OPT,
+ TOKEN_OPT
+} OPT_TYPE;
+
+typedef enum {
+ DUPLICATE_OPTION_ERR=0,
+ OPTION_NEEDS_ARG_ERR
+} Error;
+
+static char *errStrings[] = {
+"warning: %s option specified more than once. Only last specification will be used.\n",
+"ERROR: option \"%s\" requires an argument.\n"
+};
+
+
+static int ProcessOneOpt(OPT_TYPE type, char *arg);
+
+/*********************************************************************
+ *
+ * P r o c e s s C o m m a n d F i l e
+ */
+int
+ProcessCommandFile()
+{
+ PRFileDesc *fd;
+#define CMD_FILE_BUFSIZE 1024
+ char buf[CMD_FILE_BUFSIZE];
+ char *equals;
+ int linenum=0;
+ int retval=-1;
+ OPT_TYPE type;
+
+ fd = PR_Open(cmdFile, PR_RDONLY, 0777);
+ if(!fd) {
+ PR_fprintf(errorFD, "ERROR: Unable to open command file %s.\n");
+ errorCount++;
+ return -1;
+ }
+
+ while(pr_fgets(buf, CMD_FILE_BUFSIZE, fd), buf && *buf!='\0') {
+ char *eol;
+ linenum++;
+
+ /* Chop off final newline */
+ eol = PL_strchr(buf, '\r');
+ if(!eol) {
+ eol = PL_strchr(buf, '\n');
+ }
+ if(eol) *eol = '\0';
+
+ equals = PL_strchr(buf, '=');
+ if(!equals) {
+ continue;
+ }
+
+ *equals = '\0';
+ equals++;
+
+ /* Now buf points to the attribute, and equals points to the value. */
+
+ /* This is pretty straightforward, just deal with whatever attribute
+ * this is */
+ if(!PL_strcasecmp(buf, "basename")) {
+ type = BASE_OPT;
+ } else if(!PL_strcasecmp(buf, "compression")) {
+ type = COMPRESSION_OPT;
+ } else if(!PL_strcasecmp(buf, "certdir")) {
+ type = CERT_DIR_OPT;
+ } else if(!PL_strcasecmp(buf, "extension")) {
+ type = EXTENSION_OPT;
+ } else if(!PL_strcasecmp(buf, "generate")) {
+ type = GENKEY_OPT;
+ } else if(!PL_strcasecmp(buf, "installScript")) {
+ type = INSTALL_SCRIPT_OPT;
+ } else if(!PL_strcasecmp(buf, "javascriptdir")) {
+ type = SCRIPTDIR_OPT;
+ } else if(!PL_strcasecmp(buf, "htmldir")) {
+ type = JAVASCRIPT_OPT;
+ if(jartree) {
+ PR_fprintf(errorFD,
+ "warning: directory to be signed specified more than once."
+ " Only last specification will be used.\n");
+ warningCount++;
+ PR_Free(jartree); jartree=NULL;
+ }
+ jartree = PL_strdup(equals);
+ } else if(!PL_strcasecmp(buf, "certname")) {
+ type = CERTNAME_OPT;
+ } else if(!PL_strcasecmp(buf, "signdir")) {
+ type = SIGNDIR_OPT;
+ } else if(!PL_strcasecmp(buf, "list")) {
+ type = LIST_OBJSIGN_CERTS_OPT;
+ } else if(!PL_strcasecmp(buf, "listall")) {
+ type = LIST_ALL_CERTS_OPT;
+ } else if(!PL_strcasecmp(buf, "metafile")) {
+ type = METAFILE_OPT;
+ } else if(!PL_strcasecmp(buf, "modules")) {
+ type = MODULES_OPT;
+ } else if(!PL_strcasecmp(buf, "optimize")) {
+ type = OPTIMIZE_OPT;
+ } else if(!PL_strcasecmp(buf, "ocsp")) {
+ type = ENABLE_OCSP_OPT;
+ } else if(!PL_strcasecmp(buf, "password")) {
+ type = PASSWORD_OPT;
+ } else if(!PL_strcasecmp(buf, "verify")) {
+ type = VERIFY_OPT;
+ } else if(!PL_strcasecmp(buf, "who")) {
+ type = WHO_OPT;
+ } else if(!PL_strcasecmp(buf, "exclude")) {
+ type = EXCLUDE_OPT;
+ } else if(!PL_strcasecmp(buf, "notime")) {
+ type = NO_TIME_OPT;
+ } else if(!PL_strcasecmp(buf, "jarfile")) {
+ type = ZIPFILE_OPT;
+ } else if(!PL_strcasecmp(buf, "outfile")) {
+ type = OUTFILE_OPT;
+ } else if(!PL_strcasecmp(buf, "leavearc")) {
+ type = LEAVE_ARC_OPT;
+ } else if(!PL_strcasecmp(buf, "verbosity")) {
+ type = VERBOSITY_OPT;
+ } else if(!PL_strcasecmp(buf, "keysize")) {
+ type = KEYSIZE_OPT;
+ } else if(!PL_strcasecmp(buf, "token")) {
+ type = TOKEN_OPT;
+ } else {
+ PR_fprintf(errorFD,
+ "warning: unknown attribute \"%s\" in command file, line %d.\n",
+ buf, linenum);
+ warningCount++;
+ type = UNKNOWN_OPT;
+ }
+
+ /* Process the option, whatever it is */
+ if(type != UNKNOWN_OPT) {
+ if(ProcessOneOpt(type, equals)==-1) {
+ goto finish;
+ }
+ }
+ }
+
+ retval = 0;
+
+finish:
+ PR_Close(fd);
+ return retval;
+}
+
+/*********************************************************************
+ *
+ * p a r s e _ a r g s
+ */
+static int
+parse_args(int argc, char *argv[])
+{
+ char *opt;
+ char *arg;
+ int needsInc = 0;
+ int i;
+ OPT_TYPE type;
+
+ /* Loop over all arguments */
+ for(i=1; i < argc; i++) {
+ opt = argv[i];
+ arg = NULL;
+
+ if(opt[0] == '-') {
+ if(opt[1] == '-') {
+ /* word option */
+ if(i < argc-1) {
+ needsInc = 1;
+ arg = argv[i+1];
+ } else {
+ arg = NULL;
+ }
+
+ if( !PL_strcasecmp(opt+2, "norecurse")) {
+ type = NORECURSE_OPT;
+ } else if( !PL_strcasecmp(opt+2, "leavearc")) {
+ type = LEAVE_ARC_OPT;
+ } else if( !PL_strcasecmp(opt+2, "verbosity")) {
+ type = VERBOSITY_OPT;
+ } else if( !PL_strcasecmp(opt+2, "outfile")) {
+ type = OUTFILE_OPT;
+ } else if( !PL_strcasecmp(opt+2, "keysize")) {
+ type = KEYSIZE_OPT;
+ } else if( !PL_strcasecmp(opt+2, "token")) {
+ type = TOKEN_OPT;
+ } else {
+ PR_fprintf(errorFD, "warning: unknown option: %s\n", opt);
+ warningCount++;
+ type = UNKNOWN_OPT;
+ }
+ } else {
+ /* char option */
+ if(opt[2]!='\0') {
+ arg = opt+2;
+ } else if(i < argc-1) {
+ needsInc = 1;
+ arg = argv[i+1];
+ } else {
+ arg = NULL;
+ }
+
+ switch(opt[1]) {
+ case '?':
+ type = QUESTION_OPT;
+ break;
+ case 'b':
+ type = BASE_OPT;
+ break;
+ case 'c':
+ type = COMPRESSION_OPT;
+ break;
+ case 'd':
+ type = CERT_DIR_OPT;
+ break;
+ case 'e':
+ type = EXTENSION_OPT;
+ break;
+ case 'f':
+ type = COMMAND_FILE_OPT;
+ break;
+ case 'i':
+ type = INSTALL_SCRIPT_OPT;
+ break;
+ case 'j':
+ type = SCRIPTDIR_OPT;
+ break;
+ case 'k':
+ type = CERTNAME_OPT;
+ break;
+ case 'l':
+ type = LIST_OBJSIGN_CERTS_OPT;
+ break;
+ case 'L':
+ type = LIST_ALL_CERTS_OPT;
+ break;
+ case 'm':
+ type = METAFILE_OPT;
+ break;
+ case 'o':
+ type = OPTIMIZE_OPT;
+ break;
+ case 'O':
+ type = ENABLE_OCSP_OPT;
+ break;
+ case 'p':
+ type = PASSWORD_OPT;
+ break;
+ case 'v':
+ type = VERIFY_OPT;
+ break;
+ case 'w':
+ type = WHO_OPT;
+ break;
+ case 'x':
+ type = EXCLUDE_OPT;
+ break;
+ case 'z':
+ type = NO_TIME_OPT;
+ break;
+ case 'J':
+ type = JAVASCRIPT_OPT;
+ break;
+ case 'Z':
+ type = ZIPFILE_OPT;
+ break;
+ case 'G':
+ type = GENKEY_OPT;
+ break;
+ case 'M':
+ type = MODULES_OPT;
+ break;
+ case 's':
+ type = KEYSIZE_OPT;
+ break;
+ case 't':
+ type = TOKEN_OPT;
+ break;
+ default:
+ type = UNKNOWN_OPT;
+ PR_fprintf(errorFD, "warning: unrecognized option: -%c.\n",
+ opt[1]);
+ warningCount++;
+ break;
+ }
+ }
+ } else {
+ type = UNKNOWN_OPT;
+ if(i == argc-1) {
+ if(jartree) {
+ PR_fprintf(errorFD,
+ "warning: directory to be signed specified more than once."
+ " Only last specification will be used.\n");
+ warningCount++;
+ PR_Free(jartree); jartree = NULL;
+ }
+ jartree = PL_strdup(opt);
+ } else {
+ PR_fprintf(errorFD, "warning: unrecognized option: %s\n", opt);
+ warningCount++;
+ }
+ }
+
+ if(type != UNKNOWN_OPT) {
+ short ateArg;
+
+ ateArg = ProcessOneOpt(type, arg);
+ if(ateArg==-1) {
+ /* error */
+ return -1;
+ } else if(ateArg && needsInc) {
+ i++;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*********************************************************************
+ *
+ * P r o c e s s O n e O p t
+ *
+ * Since options can come from different places (command file, word options,
+ * char options), this is a central function that is called to deal with
+ * them no matter where they come from.
+ *
+ * type is the type of option.
+ * arg is the argument to the option, possibly NULL.
+ * Returns 1 if the argument was eaten, 0 if it wasn't, and -1 for error.
+ */
+static int
+ProcessOneOpt(OPT_TYPE type, char *arg)
+{
+ int ate=0;
+
+ switch(type) {
+ case QUESTION_OPT:
+ usage();
+ break;
+ case BASE_OPT:
+ if(base) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-b");
+ warningCount++;
+ PR_Free(base); base=NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-b");
+ errorCount++;
+ goto loser;
+ }
+ base = PL_strdup(arg);
+ ate = 1;
+ break;
+ case COMPRESSION_OPT:
+ if(compression_level_specified) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-c");
+ warningCount++;
+ }
+ if( !arg ) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-c");
+ errorCount++;
+ goto loser;
+ }
+ compression_level = atoi(arg);
+ compression_level_specified = PR_TRUE;
+ ate = 1;
+ break;
+ case CERT_DIR_OPT:
+ if(cert_dir) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-d");
+ warningCount++;
+ PR_Free(cert_dir); cert_dir = NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-d");
+ errorCount++;
+ goto loser;
+ }
+ cert_dir = PL_strdup(arg);
+ ate = 1;
+ break;
+ case EXTENSION_OPT:
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "extension (-e)");
+ errorCount++;
+ goto loser;
+ }
+ PL_HashTableAdd(extensions, arg, arg);
+ extensionsGiven = PR_TRUE;
+ ate = 1;
+ break;
+ case INSTALL_SCRIPT_OPT:
+ if(install_script) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "installScript (-i)");
+ warningCount++;
+ PR_Free(install_script); install_script = NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "installScript (-i)");
+ errorCount++;
+ goto loser;
+ }
+ install_script = PL_strdup(arg);
+ ate = 1;
+ break;
+ case SCRIPTDIR_OPT:
+ if(scriptdir) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "javascriptdir (-j)");
+ warningCount++;
+ PR_Free(scriptdir); scriptdir = NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "javascriptdir (-j)");
+ errorCount++;
+ goto loser;
+ }
+ scriptdir = PL_strdup(arg);
+ ate = 1;
+ break;
+ case CERTNAME_OPT:
+ if(keyName) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "keyName (-k)");
+ warningCount++;
+ PR_Free(keyName); keyName = NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "keyName (-k)");
+ errorCount++;
+ goto loser;
+ }
+ keyName = PL_strdup(arg);
+ ate = 1;
+ break;
+ case LIST_OBJSIGN_CERTS_OPT:
+ case LIST_ALL_CERTS_OPT:
+ if(list_certs != 0) {
+ PR_fprintf(errorFD,
+ "warning: only one of -l and -L may be specified.\n");
+ warningCount++;
+ }
+ list_certs = (type==LIST_OBJSIGN_CERTS_OPT ? 1 : 2);
+ break;
+ case METAFILE_OPT:
+ if(metafile) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "metafile (-m)");
+ warningCount++;
+ PR_Free(metafile); metafile = NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "metafile (-m)");
+ errorCount++;
+ goto loser;
+ }
+ metafile = PL_strdup(arg);
+ ate = 1;
+ break;
+ case OPTIMIZE_OPT:
+ optimize = 1;
+ break;
+ case ENABLE_OCSP_OPT:
+ enableOCSP = 1;
+ break;
+ case PASSWORD_OPT:
+ if(password) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "password (-p)");
+ warningCount++;
+ PR_Free(password); password= NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "password (-p)");
+ errorCount++;
+ goto loser;
+ }
+ password = PL_strdup(arg);
+ ate = 1;
+ break;
+ case VERIFY_OPT:
+ if(verify) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "verify (-v)");
+ warningCount++;
+ PR_Free(verify); verify = NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "verify (-v)");
+ errorCount++;
+ goto loser;
+ }
+ verify = PL_strdup(arg);
+ ate = 1;
+ break;
+ case WHO_OPT:
+ if(tell_who) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "who (-v)");
+ warningCount++;
+ PR_Free(tell_who); tell_who = NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "who (-w)");
+ errorCount++;
+ goto loser;
+ }
+ tell_who = PL_strdup(arg);
+ ate = 1;
+ break;
+ case EXCLUDE_OPT:
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "exclude (-x)");
+ errorCount++;
+ goto loser;
+ }
+ PL_HashTableAdd(excludeDirs, arg, arg);
+ exclusionsGiven = PR_TRUE;
+ ate = 1;
+ break;
+ case NO_TIME_OPT:
+ no_time = 1;
+ break;
+ case JAVASCRIPT_OPT:
+ javascript++;
+ break;
+ case ZIPFILE_OPT:
+ if(zipfile) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "jarfile (-Z)");
+ warningCount++;
+ PR_Free(zipfile); zipfile = NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "jarfile (-Z)");
+ errorCount++;
+ goto loser;
+ }
+ zipfile = PL_strdup(arg);
+ ate = 1;
+ break;
+ case GENKEY_OPT:
+ if(genkey) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "generate (-G)");
+ warningCount++;
+ PR_Free(zipfile); zipfile = NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "generate (-G)");
+ errorCount++;
+ goto loser;
+ }
+ genkey = PL_strdup(arg);
+ ate = 1;
+ break;
+ case MODULES_OPT:
+ list_modules++;
+ break;
+ case SIGNDIR_OPT:
+ if(jartree) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "signdir");
+ warningCount++;
+ PR_Free(jartree); jartree = NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "signdir");
+ errorCount++;
+ goto loser;
+ }
+ jartree = PL_strdup(arg);
+ ate = 1;
+ break;
+ case OUTFILE_OPT:
+ if(outfile) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR],
+ "outfile");
+ warningCount++;
+ PR_Free(outfile); outfile = NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "outfile");
+ errorCount++;
+ goto loser;
+ }
+ outfile = PL_strdup(arg);
+ ate = 1;
+ break;
+ case COMMAND_FILE_OPT:
+ if(cmdFile) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-f");
+ warningCount++;
+ PR_Free(cmdFile); cmdFile = NULL;
+ }
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-f");
+ errorCount++;
+ goto loser;
+ }
+ cmdFile = PL_strdup(arg);
+ ate = 1;
+ break;
+ case NORECURSE_OPT:
+ noRecurse = PR_TRUE;
+ break;
+ case LEAVE_ARC_OPT:
+ leaveArc = PR_TRUE;
+ break;
+ case VERBOSITY_OPT:
+ if(!arg) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR],
+ "--verbosity");
+ errorCount++;
+ goto loser;
+ }
+ verbosity = atoi(arg);
+ ate = 1;
+ break;
+ case KEYSIZE_OPT:
+ if( keySize != -1 ) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-s");
+ warningCount++;
+ }
+ keySize = atoi(arg);
+ ate = 1;
+ if( keySize < 1 || keySize > MAX_RSA_KEY_SIZE ) {
+ PR_fprintf(errorFD, "Invalid key size: %d.\n", keySize);
+ errorCount++;
+ goto loser;
+ }
+ break;
+ case TOKEN_OPT:
+ if( token ) {
+ PR_fprintf(errorFD, errStrings[DUPLICATE_OPTION_ERR], "-t");
+ PR_Free(token); token = NULL;
+ }
+ if( ! arg ) {
+ PR_fprintf(errorFD, errStrings[OPTION_NEEDS_ARG_ERR], "-t");
+ errorCount++;
+ goto loser;
+ }
+ token = PL_strdup(arg);
+ ate = 1;
+ break;
+ default:
+ PR_fprintf(errorFD, "warning: unknown option\n");
+ warningCount++;
+ break;
+ }
+
+ return ate;
+loser:
+ return -1;
+}
+
+
+/*********************************************************************
+ *
+ * m a i n
+ */
+int
+main(int argc, char *argv[])
+{
+ PRBool readOnly;
+ int retval=0;
+
+ outputFD = PR_STDOUT;
+ errorFD = PR_STDERR;
+
+ progName = argv[0];
+
+ if (argc < 2)
+ {
+ usage();
+ }
+
+ excludeDirs = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
+ PL_CompareStrings, NULL, NULL);
+ extensions = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
+ PL_CompareStrings, NULL, NULL);
+
+ if(parse_args(argc, argv)) {
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* Parse the command file if one was given */
+ if(cmdFile) {
+ if(ProcessCommandFile()) {
+ retval = -1;
+ goto cleanup;
+ }
+ }
+
+ /* Set up output redirection */
+ if(outfile) {
+ if(PR_Access(outfile, PR_ACCESS_EXISTS)==PR_SUCCESS) {
+ /* delete the file if it is already present */
+ PR_fprintf(errorFD,
+ "warning: %s already exists and will be overwritten.\n",
+ outfile);
+ warningCount++;
+ if(PR_Delete(outfile) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "ERROR: unable to delete %s.\n", outfile);
+ errorCount++;
+ exit(ERRX);
+ }
+ }
+ outputFD = PR_Open(outfile,
+ PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0777);
+ if(!outputFD) {
+ PR_fprintf(errorFD, "ERROR: Unable to create %s.\n", outfile);
+ errorCount++;
+ exit(ERRX);
+ }
+ errorFD = outputFD;
+ }
+
+ /* This seems to be a fairly common user error */
+
+ if (verify && list_certs > 0)
+ {
+ PR_fprintf (errorFD, "%s: Can't use -l and -v at the same time\n",
+ PROGRAM_NAME);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* -J assumes -Z now */
+
+ if (javascript && zipfile)
+ {
+ PR_fprintf (errorFD, "%s: Can't use -J and -Z at the same time\n",
+ PROGRAM_NAME);
+ PR_fprintf (errorFD, "%s: -J option will create the jar files for you\n",
+ PROGRAM_NAME);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* Less common mixing of -L with various options */
+
+ if (list_certs > 0 &&
+ (tell_who || zipfile || javascript ||
+ scriptdir || extensionsGiven || exclusionsGiven || install_script)) {
+ PR_fprintf(errorFD, "%s: Can't use -l or -L with that option\n",
+ PROGRAM_NAME);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+
+ if (!cert_dir)
+ cert_dir = get_default_cert_dir();
+
+ VerifyCertDir(cert_dir, keyName);
+
+
+ if( compression_level < MIN_COMPRESSION_LEVEL ||
+ compression_level > MAX_COMPRESSION_LEVEL) {
+ PR_fprintf(errorFD, "Compression level must be between %d and %d.\n",
+ MIN_COMPRESSION_LEVEL, MAX_COMPRESSION_LEVEL);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ if(jartree && !keyName) {
+ PR_fprintf(errorFD, "You must specify a key with which to sign.\n");
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ readOnly = (genkey == NULL); /* only key generation requires write */
+ if(InitCrypto(cert_dir, readOnly)) {
+ PR_fprintf(errorFD, "ERROR: Cryptographic initialization failed.\n");
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ if (enableOCSP) {
+ SECStatus rv = CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
+ if (rv != SECSuccess) {
+ PR_fprintf(errorFD, "ERROR: Attempt to enable OCSP Checking failed.\n");
+ errorCount++;
+ retval = -1;
+ }
+ }
+
+ if (verify)
+ {
+ if (VerifyJar(verify))
+ {
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+ }
+ else if (list_certs)
+ {
+ if (ListCerts(keyName, list_certs))
+ {
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+ }
+ else if (list_modules)
+ {
+ JarListModules();
+ }
+ else if (genkey)
+ {
+ if (GenerateCert(genkey, keySize, token))
+ {
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+ }
+ else if (tell_who)
+ {
+ if (JarWho(tell_who))
+ {
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+ }
+ else if (javascript && jartree)
+ {
+ /* make sure directory exists */
+ PRDir *dir;
+ dir = PR_OpenDir(jartree);
+ if(!dir) {
+ PR_fprintf(errorFD, "ERROR: unable to open directory %s.\n", jartree);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ } else {
+ PR_CloseDir(dir);
+ }
+
+ /* undo junk from prior runs of signtool*/
+ if(RemoveAllArc(jartree)) {
+ PR_fprintf(errorFD, "Error removing archive directories under %s\n", jartree);
+ errorCount++;
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* traverse all the htm|html files in the directory */
+ if(InlineJavaScript(jartree, !noRecurse)) {
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* sign any resultant .arc directories created in above step */
+ if(SignAllArc(jartree, keyName, javascript, metafile, install_script,
+ optimize, !noRecurse)) {
+ retval = -1;
+ goto cleanup;
+ }
+
+ if(!leaveArc) {
+ RemoveAllArc(jartree);
+ }
+
+ if(errorCount>0 || warningCount>0) {
+ PR_fprintf(outputFD, "%d error%s, %d warning%s.\n", errorCount,
+ errorCount==1?"":"s", warningCount, warningCount==1?"":"s");
+ } else {
+ PR_fprintf(outputFD, "Directory %s signed successfully.\n", jartree);
+ }
+ } else if (jartree)
+ {
+ SignArchive(jartree, keyName, zipfile, javascript, metafile,
+ install_script, optimize, !noRecurse);
+ }
+ else
+ usage();
+
+cleanup:
+ if(extensions) {
+ PL_HashTableDestroy(extensions); extensions = NULL;
+ }
+ if(excludeDirs) {
+ PL_HashTableDestroy(excludeDirs); excludeDirs = NULL;
+ }
+ if(outputFD != PR_STDOUT) {
+ PR_Close(outputFD);
+ }
+ rm_dash_r(TMP_OUTPUT);
+ if (retval == 0) {
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ }
+ return retval;
+}
+
diff --git a/security/nss/cmd/signtool/signtool.h b/security/nss/cmd/signtool/signtool.h
new file mode 100644
index 000000000..5c6ad0284
--- /dev/null
+++ b/security/nss/cmd/signtool/signtool.h
@@ -0,0 +1,140 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifndef SIGNTOOL_H
+#define SIGNTOOL_H
+
+#define DJN_TEST
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "prprf.h"
+#include "prio.h"
+#include "secutil.h"
+#include "ocsp.h"
+#include "jar.h"
+#include "jarfile.h"
+#include "secpkcs7.h"
+#include "pk11func.h"
+#include "secmod.h"
+#include "plhash.h"
+
+#ifdef _UNIX
+#include <unistd.h>
+#endif
+
+/**********************************************************************
+ * General Defines
+ */
+#define JAR_BASE_END JAR_BASE + 100
+#define ERRX (-1) /* the exit code used on failure */
+#define FNSIZE 256 /* the maximum length for filenames */
+#define MAX_RSA_KEY_SIZE 4096
+#define DEFAULT_RSA_KEY_SIZE 1024
+#define MANIFEST "manifest.mf"
+#define DEFAULT_X509_BASENAME "x509"
+#define DEFAULT_COMMON_NAME "Signtool 1.3 Testing Certificate"
+#define CREATOR "Signtool (signtool 1.3)"
+#define BREAKAGE "PLEASE DO NOT EDIT THIS FILE. YOU WILL BREAK IT."
+#define MIN_COMPRESSION_LEVEL (-1)
+#define MAX_COMPRESSION_LEVEL 9
+#define DEFAULT_COMPRESSION_LEVEL (-1) /* zlib understands this to be default*/
+#define STDIN_BUF_SIZE 160
+#define PROGRAM_NAME "signtool"
+#define LONG_PROGRAM_NAME "Signing Tool"
+#define DEFAULT_BASE_NAME "zigbert"
+#define VERSION "1.3"
+#define TMP_OUTPUT "signtool.tmp"
+
+
+/***************************************************************
+ * Main Task Functions
+ */
+int GenerateCert(char *nickname, int keysize, char *token);
+int ListCerts(char *key, int list_certs);
+int VerifyJar(char *filename);
+int SignArchive(char *tree, char *keyName, char *zip_file, int javascript,
+ char *meta_file, char *install_script, int _optimize, PRBool recurse);
+int SignAllArc(char *jartree, char *keyName, int javascript, char *metafile,
+ char *install_script, int optimize, PRBool recurse);
+int InlineJavaScript(char *dir, PRBool recurse);
+int JarWho(char *filename);
+void JarListModules(void);
+
+/**************************************************************
+ * Utility Functions
+ */
+CERTCertDBHandle *OpenCertDB (PRBool readOnly);
+
+int RemoveAllArc(char *tree);
+void VerifyCertDir(char *dir, char *keyName);
+int InitCrypto(char *cert_dir, PRBool readOnly);
+int foreach (char *dirname, char *prefix,
+ int (*fn)(char *filename, char *dirname, char *basedir,char *base,void*arg),
+ PRBool recurse, PRBool includeDirs, void *arg);
+void print_error (int i);
+void give_help (int status);
+const char* secErrorString(long code);
+void displayVerifyLog(CERTVerifyLog *log);
+void usage (void);
+char* chop(char*);
+void out_of_memory(void);
+void FatalError(char *msg);
+char* get_default_cert_dir(void);
+SECItem *password_hardcode(void *arg, void *handle);
+char* pk11_password_hardcode(PK11SlotInfo *slot, PRBool retry, void *arg);
+int rm_dash_r(char *path);
+char* pr_fgets(char *buf, int size, PRFileDesc *file);
+
+
+/*****************************************************************
+ * Global Variables (*gag*)
+ */
+extern char *password; /* the password passed in on the command line */
+extern PLHashTable *excludeDirs; /* directory entry to skip while recursing */
+extern int no_time;
+extern char *base; /* basename of ".rsa" and ".sf" files */
+extern long *mozilla_event_queue;
+extern char *progName; /* argv[0] */
+extern PLHashTable *extensions;/* only sign files with this extension */
+extern PRBool extensionsGiven;
+extern char *scriptdir;
+extern int compression_level;
+extern PRFileDesc *outputFD, *errorFD;
+extern int verbosity;
+extern int errorCount;
+extern int warningCount;
+
+#endif /* SIGNTOOL_H */
diff --git a/security/nss/cmd/signtool/util.c b/security/nss/cmd/signtool/util.c
new file mode 100644
index 000000000..c1b401e33
--- /dev/null
+++ b/security/nss/cmd/signtool/util.c
@@ -0,0 +1,990 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "signtool.h"
+#include "prio.h"
+#include "prmem.h"
+#include "nss.h"
+
+static int is_dir (char *filename);
+
+/***********************************************************
+ * Nasty hackish function definitions
+ */
+
+long *mozilla_event_queue = 0;
+
+#ifndef XP_WIN
+char *XP_GetString (int i)
+{
+ return SECU_ErrorStringRaw ((int16) i);
+}
+#endif
+
+void FE_SetPasswordEnabled()
+{
+}
+
+void /*MWContext*/ *FE_GetInitContext (void)
+{
+ return 0;
+}
+
+void /*MWContext*/ *XP_FindSomeContext()
+{
+ /* No windows context in command tools */
+ return NULL;
+}
+
+void ET_moz_CallFunction()
+{
+}
+
+
+/*
+ * R e m o v e A l l A r c
+ *
+ * Remove .arc directories that are lingering
+ * from a previous run of signtool.
+ *
+ */
+int
+RemoveAllArc(char *tree)
+{
+ PRDir *dir;
+ PRDirEntry *entry;
+ char *archive=NULL;
+ int retval = 0;
+
+ dir = PR_OpenDir (tree);
+ if (!dir) return -1;
+
+ for (entry = PR_ReadDir (dir,0); entry; entry = PR_ReadDir (dir,0)) {
+
+ if(entry->name[0] == '.') {
+ continue;
+ }
+
+ if(archive) PR_Free(archive);
+ archive = PR_smprintf("%s/%s", tree, entry->name);
+
+ if (PL_strcaserstr (entry->name, ".arc")
+ == (entry->name + strlen(entry->name) - 4) ) {
+
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "removing: %s\n", archive);
+ }
+
+ if(rm_dash_r(archive)) {
+ PR_fprintf(errorFD, "Error removing %s\n", archive);
+ errorCount++;
+ retval = -1;
+ goto finish;
+ }
+ } else if(is_dir(archive)) {
+ if(RemoveAllArc(archive)) {
+ retval = -1;
+ goto finish;
+ }
+ }
+ }
+
+finish:
+ PR_CloseDir (dir);
+ if(archive) PR_Free(archive);
+
+ return retval;
+}
+
+/*
+ * r m _ d a s h _ r
+ *
+ * Remove a file, or a directory recursively.
+ *
+ */
+int rm_dash_r (char *path)
+{
+ PRDir *dir;
+ PRDirEntry *entry;
+ PRFileInfo fileinfo;
+ char filename[FNSIZE];
+
+ if(PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) {
+ /*fprintf(stderr, "Error: Unable to access %s\n", filename);*/
+ return -1;
+ }
+ if(fileinfo.type == PR_FILE_DIRECTORY) {
+
+ dir = PR_OpenDir(path);
+ if(!dir) {
+ PR_fprintf(errorFD, "Error: Unable to open directory %s.\n", path);
+ errorCount++;
+ return -1;
+ }
+
+ /* Recursively delete all entries in the directory */
+ while((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
+ sprintf(filename, "%s/%s", path, entry->name);
+ if(rm_dash_r(filename)) return -1;
+ }
+
+ if(PR_CloseDir(dir) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "Error: Could not close %s.\n", path);
+ errorCount++;
+ return -1;
+ }
+
+ /* Delete the directory itself */
+ if(PR_RmDir(path) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
+ errorCount++;
+ return -1;
+ }
+ } else {
+ if(PR_Delete(path) != PR_SUCCESS) {
+ PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
+ errorCount++;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * u s a g e
+ *
+ * Print some useful help information
+ *
+ */
+void
+usage (void)
+{
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%s %s - a signing tool for jar files\n", LONG_PROGRAM_NAME, VERSION);
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "Usage: %s [options] directory-tree \n\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, " -b\"basename\"\t\tbasename of .sf, .rsa files for signing\n");
+ PR_fprintf(outputFD, " -c#\t\t\t\tCompression level, 0-9, 0=none\n");
+ PR_fprintf(outputFD, " -d\"certificate directory\"\tcontains cert*.db and key*.db\n");
+ PR_fprintf(outputFD, " -e\".ext\"\t\t\tsign only files with this extension\n");
+ PR_fprintf(outputFD, " -f\"filename\"\t\t\tread commands from file\n");
+ PR_fprintf(outputFD, " -G\"nickname\"\t\tcreate object-signing cert with this nickname\n");
+ PR_fprintf(outputFD, " -i\"installer script\"\tassign installer javascript\n");
+ PR_fprintf(outputFD, " -j\"javascript directory\"\tsign javascript files in this subtree\n");
+ PR_fprintf(outputFD, " -J\t\t\t\tdirectory contains HTML files. Javascript will\n"
+ "\t\t\t\tbe extracted and signed.\n");
+ PR_fprintf(outputFD, " -k\"cert nickname\"\t\tsign with this certificate\n");
+ PR_fprintf(outputFD, " --leavearc\t\t\tdo not delete .arc directories created\n"
+ "\t\t\t\tby -J option\n");
+ PR_fprintf(outputFD, " -m\"metafile\"\t\tinclude custom meta-information\n");
+ PR_fprintf(outputFD, " --norecurse\t\t\tdo not operate on subdirectories\n");
+ PR_fprintf(outputFD, " -o\t\t\t\toptimize - omit optional headers\n");
+ PR_fprintf(outputFD, " -O\t\t\t\tenableOCSP - enable OCSP checking\n");
+ PR_fprintf(outputFD, " --outfile \"filename\"\tredirect output to file\n");
+ PR_fprintf(outputFD, " -p\"password\"\t\tfor password on command line (insecure)\n");
+ PR_fprintf(outputFD, " -s keysize\t\t\tkeysize in bits of generated cert\n");
+ PR_fprintf(outputFD, " -t token\t\t\tname of token on which to generate cert\n");
+ PR_fprintf(outputFD, " --verbosity #\t\tSet amount of debugging information to generate.\n"
+ "\t\t\t\tLower number means less output, 0 is default.\n");
+ PR_fprintf(outputFD, " -x\"name\"\t\t\tdirectory or filename to exclude\n");
+ PR_fprintf(outputFD, " -z\t\t\t\tomit signing time from signature\n");
+ PR_fprintf(outputFD, " -Z\"jarfile\"\t\t\tcreate JAR file with the given name.\n"
+ "\t\t\t\t(Default compression level is 6.)\n");
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%s -l\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, " lists the signing certificates in your database\n");
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%s -L\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, " lists all certificates in your database, marks object-signing certificates\n");
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%s -M\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, " lists the PKCS #11 modules available to %s\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%s -v file.jar\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, " show the contents of the specified jar file\n");
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%s -w file.jar\n", PROGRAM_NAME);
+ PR_fprintf(outputFD, " if valid, tries to tell you who signed the jar file\n");
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "For more details, visit\n");
+ PR_fprintf(outputFD,
+" http://developer.netscape.com/library/documentation/signedobj/signtool/\n");
+
+ exit (ERRX);
+}
+
+/*
+ * p r i n t _ e r r o r
+ *
+ * For the undocumented -E function. If an older version
+ * of communicator gives you a numeric error, we can see what
+ * really happened without doing hex math.
+ *
+ */
+
+void
+print_error (int err)
+{
+ PR_fprintf(errorFD, "Error %d: %s\n", err, JAR_get_error (err));
+ errorCount++;
+ give_help (err);
+}
+
+/*
+ * o u t _ o f _ m e m o r y
+ *
+ * Out of memory, exit Signtool.
+ *
+ */
+void
+out_of_memory (void)
+{
+ PR_fprintf(errorFD, "%s: out of memory\n", PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+}
+
+/*
+ * V e r i f y C e r t D i r
+ *
+ * Validate that the specified directory
+ * contains a certificate database
+ *
+ */
+void
+VerifyCertDir(char *dir, char *keyName)
+{
+ char fn [FNSIZE];
+
+ /* don't try verifying if we don't have a local directory */
+ if (strncmp(dir,"multiaccess:",sizeof("multiaccess:")-1) == 0) {
+ return;
+ }
+
+ /* This code is really broken because it makes underlying assumptions about
+ * how the NSS profile directory is laid out, but these names can change
+ * from release to release. */
+ sprintf (fn, "%s/cert8.db", dir);
+
+ if (PR_Access (fn, PR_ACCESS_EXISTS))
+ {
+ PR_fprintf(errorFD, "%s: No certificate database in \"%s\"\n", PROGRAM_NAME,
+ dir);
+ PR_fprintf(errorFD, "%s: Check the -d arguments that you gave\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "using certificate directory: %s\n", dir);
+ }
+
+ if (keyName == NULL)
+ return;
+
+ /* if the user gave the -k key argument, verify that
+ a key database already exists */
+
+ sprintf (fn, "%s/key3.db", dir);
+
+ if (PR_Access (fn, PR_ACCESS_EXISTS))
+ {
+ PR_fprintf(errorFD, "%s: No private key database in \"%s\"\n", PROGRAM_NAME,
+ dir);
+ PR_fprintf(errorFD, "%s: Check the -d arguments that you gave\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+}
+
+/*
+ * f o r e a c h
+ *
+ * A recursive function to loop through all names in
+ * the specified directory, as well as all subdirectories.
+ *
+ * FIX: Need to see if all platforms allow multiple
+ * opendir's to be called.
+ *
+ */
+
+int
+foreach(char *dirname, char *prefix,
+ int (*fn)(char *relpath, char *basedir, char *reldir, char *filename,
+ void* arg),
+ PRBool recurse, PRBool includeDirs, void *arg) {
+ char newdir [FNSIZE];
+ int retval = 0;
+
+ PRDir *dir;
+ PRDirEntry *entry;
+
+ strcpy (newdir, dirname);
+ if (*prefix) {
+ strcat (newdir, "/");
+ strcat (newdir, prefix);
+ }
+
+ dir = PR_OpenDir (newdir);
+ if (!dir) return -1;
+
+ for (entry = PR_ReadDir (dir,0); entry; entry = PR_ReadDir (dir,0)) {
+ if ( strcmp(entry->name, ".")==0 ||
+ strcmp(entry->name, "..")==0 )
+ {
+ /* no infinite recursion, please */
+ continue;
+ }
+
+ /* can't sign self */
+ if (!strcmp (entry->name, "META-INF"))
+ continue;
+
+ /* -x option */
+ if (PL_HashTableLookup(excludeDirs, entry->name))
+ continue;
+
+ strcpy (newdir, dirname);
+ if (*dirname)
+ strcat (newdir, "/");
+
+ if (*prefix) {
+ strcat (newdir, prefix);
+ strcat (newdir, "/");
+ }
+ strcat (newdir, entry->name);
+
+ if(!is_dir(newdir) || includeDirs) {
+ char newpath [FNSIZE];
+
+ strcpy (newpath, prefix);
+ if (*newpath)
+ strcat (newpath, "/");
+ strcat (newpath, entry->name);
+
+ if( (*fn) (newpath, dirname, prefix, (char *) entry->name, arg)) {
+ retval = -1;
+ break;
+ }
+ }
+
+ if (is_dir (newdir)) {
+ if(recurse) {
+ char newprefix [FNSIZE];
+
+ strcpy (newprefix, prefix);
+ if (*newprefix) {
+ strcat (newprefix, "/");
+ }
+ strcat (newprefix, entry->name);
+
+ if(foreach (dirname, newprefix, fn, recurse, includeDirs,arg)) {
+ retval = -1;
+ break;
+ }
+ }
+ }
+
+ }
+
+ PR_CloseDir (dir);
+
+ return retval;
+}
+
+/*
+ * i s _ d i r
+ *
+ * Return 1 if file is a directory.
+ * Wonder if this runs on a mac, trust not.
+ *
+ */
+static int is_dir (char *filename)
+{
+ PRFileInfo finfo;
+
+ if( PR_GetFileInfo(filename, &finfo) != PR_SUCCESS ) {
+ printf("Unable to get information about %s\n", filename);
+ return 0;
+ }
+
+ return ( finfo.type == PR_FILE_DIRECTORY );
+}
+
+/*
+ * p a s s w o r d _ h a r d c o d e
+ *
+ * A function to use the password passed in the -p(password) argument
+ * of the command line. This is only to be used for build & testing purposes,
+ * as it's extraordinarily insecure.
+ *
+ * After use once, null it out otherwise PKCS11 calls us forever.
+ *
+ */
+SECItem *
+password_hardcode(void *arg, void *handle)
+{
+ SECItem *pw = NULL;
+ if (password) {
+ pw = SECITEM_AllocItem(NULL, NULL, PL_strlen(password));
+ pw->data = (unsigned char *)PL_strdup(password);
+ password = NULL;
+ }
+ return pw;
+}
+
+char *
+pk11_password_hardcode(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *pw;
+ if (retry) {
+ return NULL; /* the password is incorrect, fail */
+ }
+ pw = password ? PORT_Strdup (password) : NULL;
+ /* XXX don't do this, or FIPS won't work */
+ /*password = NULL;*/
+ return pw;
+}
+
+/************************************************************************
+ *
+ * c e r t D B N a m e C a l l b a c k
+ */
+static char *
+certDBNameCallback(void *arg, int dbVersion)
+{
+ char *fnarg;
+ char *dir;
+ char *filename;
+
+ dir = SECU_ConfigDirectory (NULL);
+
+ switch ( dbVersion ) {
+ case 7:
+ fnarg = "7";
+ break;
+ case 6:
+ fnarg = "6";
+ break;
+ case 5:
+ fnarg = "5";
+ break;
+ case 4:
+ default:
+ fnarg = "";
+ break;
+ }
+ filename = PR_smprintf("%s/cert%s.db", dir, fnarg);
+ return(filename);
+}
+
+/***************************************************************
+ *
+ * s e c E r r o r S t r i n g
+ *
+ * Returns an error string corresponding to the given error code.
+ * Doesn't cover all errors; returns a default for many.
+ * Returned string is only valid until the next call of this function.
+ */
+const char*
+secErrorString(long code)
+{
+ static char errstring[80]; /* dynamically constructed error string */
+ char *c; /* the returned string */
+
+ switch(code) {
+ case SEC_ERROR_IO: c = "io error";
+ break;
+ case SEC_ERROR_LIBRARY_FAILURE: c = "security library failure";
+ break;
+ case SEC_ERROR_BAD_DATA: c = "bad data";
+ break;
+ case SEC_ERROR_OUTPUT_LEN: c = "output length";
+ break;
+ case SEC_ERROR_INPUT_LEN: c = "input length";
+ break;
+ case SEC_ERROR_INVALID_ARGS: c = "invalid args";
+ break;
+ case SEC_ERROR_EXPIRED_CERTIFICATE: c = "expired certificate";
+ break;
+ case SEC_ERROR_REVOKED_CERTIFICATE: c = "revoked certificate";
+ break;
+ case SEC_ERROR_INADEQUATE_KEY_USAGE: c = "inadequate key usage";
+ break;
+ case SEC_ERROR_INADEQUATE_CERT_TYPE: c = "inadequate certificate type";
+ break;
+ case SEC_ERROR_UNTRUSTED_CERT: c = "untrusted cert";
+ break;
+ case SEC_ERROR_NO_KRL: c = "no key revocation list";
+ break;
+ case SEC_ERROR_KRL_BAD_SIGNATURE: c = "key revocation list: bad signature";
+ break;
+ case SEC_ERROR_KRL_EXPIRED: c = "key revocation list expired";
+ break;
+ case SEC_ERROR_REVOKED_KEY: c = "revoked key";
+ break;
+ case SEC_ERROR_CRL_BAD_SIGNATURE:
+ c = "certificate revocation list: bad signature";
+ break;
+ case SEC_ERROR_CRL_EXPIRED: c = "certificate revocation list expired";
+ break;
+ case SEC_ERROR_CRL_NOT_YET_VALID:
+ c = "certificate revocation list not yet valid";
+ break;
+ case SEC_ERROR_UNKNOWN_ISSUER: c = "unknown issuer";
+ break;
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: c = "expired issuer certificate";
+ break;
+ case SEC_ERROR_BAD_SIGNATURE: c = "bad signature";
+ break;
+ case SEC_ERROR_BAD_KEY: c = "bad key";
+ break;
+ case SEC_ERROR_NOT_FORTEZZA_ISSUER: c = "not fortezza issuer";
+ break;
+ case SEC_ERROR_CA_CERT_INVALID:
+ c = "Certificate Authority certificate invalid";
+ break;
+ case SEC_ERROR_EXTENSION_NOT_FOUND: c = "extension not found";
+ break;
+ case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: c = "certificate not in name space";
+ break;
+ case SEC_ERROR_UNTRUSTED_ISSUER: c = "untrusted issuer";
+ break;
+ default:
+ sprintf(errstring, "security error %ld", code);
+ c = errstring;
+ break;
+ }
+
+ return c;
+}
+
+/***************************************************************
+ *
+ * d i s p l a y V e r i f y L o g
+ *
+ * Prints the log of a cert verification.
+ */
+void
+displayVerifyLog(CERTVerifyLog *log)
+{
+ CERTVerifyLogNode *node;
+ CERTCertificate *cert;
+ char *name;
+
+ if( !log || (log->count <= 0) ) {
+ return;
+ }
+
+ for(node = log->head; node != NULL; node = node->next) {
+
+ if( !(cert = node->cert) ) {
+ continue;
+ }
+
+ /* Get a name for this cert */
+ if(cert->nickname != NULL) {
+ name = cert->nickname;
+ } else if(cert->emailAddr != NULL) {
+ name = cert->emailAddr;
+ } else {
+ name = cert->subjectName;
+ }
+
+ printf( "%s%s:\n",
+ name,
+ (node->depth > 0) ? " [Certificate Authority]" : ""
+ );
+
+ printf("\t%s\n", secErrorString(node->error));
+
+ }
+}
+/*
+ * J a r L i s t M o d u l e s
+ *
+ * Print a list of the PKCS11 modules that are
+ * available. This is useful for smartcard people to
+ * make sure they have the drivers loaded.
+ *
+ */
+void
+JarListModules(void)
+{
+ int i;
+ int count = 0;
+
+ SECMODModuleList *modules = NULL;
+ static SECMODListLock *moduleLock = NULL;
+
+ SECMODModuleList *mlp;
+
+ modules = SECMOD_GetDefaultModuleList();
+
+ if (modules == NULL)
+ {
+ PR_fprintf(errorFD, "%s: Can't get module list\n", PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ if ((moduleLock = SECMOD_NewListLock()) == NULL)
+ {
+ /* this is the wrong text */
+ PR_fprintf(errorFD, "%s: unable to acquire lock on module list\n",
+ PROGRAM_NAME);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ SECMOD_GetReadLock (moduleLock);
+
+ PR_fprintf(outputFD, "\nListing of PKCS11 modules\n");
+ PR_fprintf(outputFD, "-----------------------------------------------\n");
+
+ for (mlp = modules; mlp != NULL; mlp = mlp->next)
+ {
+ count++;
+ PR_fprintf(outputFD, "%3d. %s\n", count, mlp->module->commonName);
+
+ if (mlp->module->internal)
+ PR_fprintf(outputFD, " (this module is internally loaded)\n");
+ else
+ PR_fprintf(outputFD, " (this is an external module)\n");
+
+ if (mlp->module->dllName)
+ PR_fprintf(outputFD, " DLL name: %s\n", mlp->module->dllName);
+
+ if (mlp->module->slotCount == 0)
+ PR_fprintf(outputFD, " slots: There are no slots attached to this module\n");
+ else
+ PR_fprintf(outputFD, " slots: %d slots attached\n", mlp->module->slotCount);
+
+ if (mlp->module->loaded == 0)
+ PR_fprintf(outputFD, " status: Not loaded\n");
+ else
+ PR_fprintf(outputFD, " status: loaded\n");
+
+ for (i = 0; i < mlp->module->slotCount; i++)
+ {
+ PK11SlotInfo *slot = mlp->module->slots[i];
+
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, " slot: %s\n", PK11_GetSlotName(slot));
+ PR_fprintf(outputFD, " token: %s\n", PK11_GetTokenName(slot));
+ }
+ }
+
+ PR_fprintf(outputFD, "-----------------------------------------------\n");
+
+ if (count == 0)
+ PR_fprintf(outputFD,
+ "Warning: no modules were found (should have at least one)\n");
+
+ SECMOD_ReleaseReadLock (moduleLock);
+}
+
+/**********************************************************************
+ * c h o p
+ *
+ * Eliminates leading and trailing whitespace. Returns a pointer to the
+ * beginning of non-whitespace, or an empty string if it's all whitespace.
+ */
+char*
+chop(char *str)
+{
+ char *start, *end;
+
+ if(str) {
+ start = str;
+
+ /* Nip leading whitespace */
+ while(isspace(*start)) {
+ start++;
+ }
+
+ /* Nip trailing whitespace */
+ if(*start) {
+ end = start + strlen(start) - 1;
+ while(isspace(*end) && end > start) {
+ end--;
+ }
+ *(end+1) = '\0';
+ }
+
+ return start;
+ } else {
+ return NULL;
+ }
+}
+
+/***********************************************************************
+ *
+ * F a t a l E r r o r
+ *
+ * Outputs an error message and bails out of the program.
+ */
+void
+FatalError(char *msg)
+{
+ if(!msg) msg = "";
+
+ PR_fprintf(errorFD, "FATAL ERROR: %s\n", msg);
+ errorCount++;
+ exit(ERRX);
+}
+
+/*************************************************************************
+ *
+ * I n i t C r y p t o
+ */
+int
+InitCrypto(char *cert_dir, PRBool readOnly)
+{
+ SECStatus rv;
+ static int prior = 0;
+ PK11SlotInfo *slotinfo;
+
+ CERTCertDBHandle *db;
+
+ if (prior == 0) {
+ /* some functions such as OpenKeyDB expect this path to be
+ * implicitly set prior to calling */
+ if (readOnly) {
+ rv = NSS_Init(cert_dir);
+ } else {
+ rv = NSS_InitReadWrite(cert_dir);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(PROGRAM_NAME);
+ exit(-1);
+ }
+
+ SECU_ConfigDirectory (cert_dir);
+
+ /* Been there done that */
+ prior++;
+
+ if(password) {
+ PK11_SetPasswordFunc(pk11_password_hardcode);
+ }
+
+ /* Must login to FIPS before you do anything else */
+ if(PK11_IsFIPS()) {
+ slotinfo = PK11_GetInternalSlot();
+ if(!slotinfo) {
+ fprintf(stderr, "%s: Unable to get PKCS #11 Internal Slot."
+ "\n", PROGRAM_NAME);
+ return -1;
+ }
+ if(PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
+ NULL /*wincx*/) != SECSuccess) {
+ fprintf(stderr, "%s: Unable to authenticate to %s.\n",
+ PROGRAM_NAME, PK11_GetSlotName(slotinfo));
+ PK11_FreeSlot(slotinfo);
+ return -1;
+ }
+ PK11_FreeSlot(slotinfo);
+ }
+
+ /* Make sure there is a password set on the internal key slot */
+ slotinfo = PK11_GetInternalKeySlot();
+ if(!slotinfo) {
+ fprintf(stderr, "%s: Unable to get PKCS #11 Internal Key Slot."
+ "\n", PROGRAM_NAME);
+ return -1;
+ }
+ if(PK11_NeedUserInit(slotinfo)) {
+ PR_fprintf(errorFD,
+"\nWARNING: No password set on internal key database. Most operations will fail."
+"\nYou must use Communicator to create a password.\n");
+ warningCount++;
+ }
+
+ /* Make sure we can authenticate to the key slot in FIPS mode */
+ if(PK11_IsFIPS()) {
+ if(PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
+ NULL /*wincx*/) != SECSuccess) {
+ fprintf(stderr, "%s: Unable to authenticate to %s.\n",
+ PROGRAM_NAME, PK11_GetSlotName(slotinfo));
+ PK11_FreeSlot(slotinfo);
+ return -1;
+ }
+ }
+ PK11_FreeSlot(slotinfo);
+ }
+
+ return 0;
+}
+
+/* Windows foolishness is now in the secutil lib */
+
+/*****************************************************************
+ * g e t _ d e f a u l t _ c e r t _ d i r
+ *
+ * Attempt to locate a certificate directory.
+ * Failing that, complain that the user needs to
+ * use the -d(irectory) parameter.
+ *
+ */
+char *get_default_cert_dir (void)
+{
+ char *home;
+
+ char *cd = NULL;
+ static char db [FNSIZE];
+
+#ifdef XP_UNIX
+ home = getenv ("HOME");
+
+ if (home && *home)
+ {
+ sprintf (db, "%s/.netscape", home);
+ cd = db;
+ }
+#endif
+
+#ifdef XP_PC
+ FILE *fp;
+
+ /* first check the environment override */
+
+ home = getenv ("JAR_HOME");
+
+ if (home && *home)
+ {
+ sprintf (db, "%s/cert7.db", home);
+
+ if ((fp = fopen (db, "r")) != NULL)
+ {
+ fclose (fp);
+ cd = home;
+ }
+ }
+
+ /* try the old navigator directory */
+
+ if (cd == NULL)
+ {
+ home = "c:/Program Files/Netscape/Navigator";
+
+ sprintf (db, "%s/cert7.db", home);
+
+ if ((fp = fopen (db, "r")) != NULL)
+ {
+ fclose (fp);
+ cd = home;
+ }
+ }
+
+ /* Try the current directory, I wonder if this
+ is really a good idea. Remember, Windows only.. */
+
+ if (cd == NULL)
+ {
+ home = ".";
+
+ sprintf (db, "%s/cert7.db", home);
+
+ if ((fp = fopen (db, "r")) != NULL)
+ {
+ fclose (fp);
+ cd = home;
+ }
+ }
+
+#endif
+
+ if (!cd)
+ {
+ PR_fprintf(errorFD,
+ "You must specify the location of your certificate directory\n");
+ PR_fprintf(errorFD,
+ "with the -d option. Example: -d ~/.netscape in many cases with Unix.\n");
+ errorCount++;
+ exit (ERRX);
+ }
+
+ return cd;
+}
+
+/************************************************************************
+ * g i v e _ h e l p
+ */
+void give_help (int status)
+{
+ if (status == SEC_ERROR_UNKNOWN_ISSUER)
+ {
+ PR_fprintf(errorFD,
+ "The Certificate Authority (CA) for this certificate\n");
+ PR_fprintf(errorFD,
+ "does not appear to be in your database. You should contact\n");
+ PR_fprintf(errorFD,
+ "the organization which issued this certificate to obtain\n");
+ PR_fprintf(errorFD, "a copy of its CA Certificate.\n");
+ }
+}
+
+/**************************************************************************
+ *
+ * p r _ f g e t s
+ *
+ * fgets implemented with NSPR.
+ */
+char*
+pr_fgets(char *buf, int size, PRFileDesc *file)
+{
+ int i;
+ int status;
+ char c;
+
+ i=0;
+ while(i < size-1) {
+ status = PR_Read(file, (void*) &c, 1);
+ if(status==-1) {
+ return NULL;
+ } else if(status==0) {
+ break;
+ }
+ buf[i++] = c;
+ if(c=='\n') {
+ break;
+ }
+ }
+ buf[i]='\0';
+
+ return buf;
+}
+
diff --git a/security/nss/cmd/signtool/verify.c b/security/nss/cmd/signtool/verify.c
new file mode 100644
index 000000000..fd80ef737
--- /dev/null
+++ b/security/nss/cmd/signtool/verify.c
@@ -0,0 +1,382 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "signtool.h"
+
+
+static int jar_cb(int status, JAR *jar, const char *metafile,
+ char *pathname, char *errortext);
+static int verify_global (JAR *jar);
+
+/*************************************************************************
+ *
+ * V e r i f y J a r
+ */
+int
+VerifyJar(char *filename)
+{
+ FILE *fp;
+
+ int ret;
+ int status;
+ int failed = 0;
+ char *err;
+
+ JAR *jar;
+ JAR_Context *ctx;
+
+ JAR_Item *it;
+
+ jar = JAR_new();
+
+ if ((fp = fopen (filename, "r")) == NULL)
+ {
+ perror (filename);
+ exit (ERRX);
+ }
+ else
+ fclose (fp);
+
+ JAR_set_callback (JAR_CB_SIGNAL, jar, jar_cb);
+
+
+ status = JAR_pass_archive (jar, jarArchGuess, filename, "some-url");
+
+ if (status < 0 || jar->valid < 0)
+ {
+ failed = 1;
+ PR_fprintf(outputFD, "\nNOTE -- \"%s\" archive DID NOT PASS crypto verification.\n", filename);
+ if (status < 0)
+ {
+ char *errtext;
+
+ if (status >= JAR_BASE && status <= JAR_BASE_END)
+ {
+ errtext = JAR_get_error (status);
+ }
+ else
+ {
+ errtext = SECU_ErrorString ((int16) PORT_GetError());
+ }
+
+ PR_fprintf(outputFD, " (reported reason: %s)\n\n", errtext);
+
+ /* corrupt files should not have their contents listed */
+
+ if (status == JAR_ERR_CORRUPT)
+ return -1;
+ }
+ PR_fprintf(outputFD,
+ "entries shown below will have their digests checked only.\n");
+ jar->valid = 0;
+ }
+ else
+ PR_fprintf(outputFD,
+ "archive \"%s\" has passed crypto verification.\n", filename);
+
+ if (verify_global (jar))
+ failed = 1;
+
+ PR_fprintf(outputFD, "\n");
+ PR_fprintf(outputFD, "%16s %s\n", "status", "path");
+ PR_fprintf(outputFD, "%16s %s\n", "------------", "-------------------");
+
+ ctx = JAR_find (jar, NULL, jarTypeMF);
+
+ while (JAR_find_next (ctx, &it) >= 0)
+ {
+ if (it && it->pathname)
+ {
+ rm_dash_r(TMP_OUTPUT);
+ ret = JAR_verified_extract (jar, it->pathname, TMP_OUTPUT);
+ /* if (ret < 0) printf ("error %d on %s\n", ret, it->pathname); */
+ if (ret < 0) failed = 1;
+
+ if (ret == JAR_ERR_PNF)
+ err = "NOT PRESENT";
+ else if (ret == JAR_ERR_HASH)
+ err = "HASH FAILED";
+ else
+ err = "NOT VERIFIED";
+
+ PR_fprintf(outputFD, "%16s %s\n",
+ ret >= 0 ? "verified" : err, it->pathname);
+
+ if (ret != 0 && ret != JAR_ERR_PNF && ret != JAR_ERR_HASH)
+ PR_fprintf(outputFD, " (reason: %s)\n", JAR_get_error (ret));
+ }
+ }
+
+ JAR_find_end (ctx);
+
+ if (status < 0 || jar->valid < 0)
+ {
+ failed = 1;
+ PR_fprintf(outputFD,
+ "\nNOTE -- \"%s\" archive DID NOT PASS crypto verification.\n", filename);
+ give_help (status);
+ }
+
+ JAR_destroy (jar);
+
+ if (failed)
+ return -1;
+ return 0;
+}
+
+/***************************************************************************
+ *
+ * v e r i f y _ g l o b a l
+ */
+static int
+verify_global (JAR *jar)
+{
+ FILE *fp;
+ JAR_Context *ctx;
+
+ char *ext;
+
+ JAR_Item *it;
+ JAR_Digest *globaldig;
+
+ unsigned int sha1_length, md5_length;
+
+ char buf [BUFSIZ];
+
+ unsigned char *md5_digest, *sha1_digest;
+
+ int retval = 0;
+
+ ctx = JAR_find (jar, "*", jarTypePhy);
+
+ while (JAR_find_next (ctx, &it) >= 0) {
+ if (!PORT_Strncmp (it->pathname, "META-INF", 8)) {
+ for (ext = it->pathname; *ext; ext++);
+ while (ext > it->pathname && *ext != '.') ext--;
+
+ if(verbosity >= 0) {
+ if (!PORT_Strcasecmp (ext, ".rsa")) {
+ PR_fprintf(outputFD, "found a RSA signature file: %s\n",
+ it->pathname);
+ }
+
+ if(!PORT_Strcasecmp (ext, ".dsa")) {
+ PR_fprintf(outputFD, "found a DSA signature file: %s\n",
+ it->pathname);
+ }
+
+ if (!PORT_Strcasecmp (ext, ".mf")) {
+ PR_fprintf(outputFD,
+ "found a MF master manifest file: %s\n", it->pathname);
+ }
+ }
+
+ if (!PORT_Strcasecmp (ext, ".sf")) {
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD,
+ "found a SF signature manifest file: %s\n", it->pathname);
+ }
+
+ rm_dash_r(TMP_OUTPUT);
+ if (JAR_extract (jar, it->pathname, TMP_OUTPUT) < 0) {
+ PR_fprintf(errorFD, "%s: error extracting %s\n", PROGRAM_NAME,
+ it->pathname);
+ errorCount++;
+ retval = -1;
+ continue;
+ }
+
+ md5_digest = NULL;
+ sha1_digest = NULL;
+
+ if ((fp = fopen (TMP_OUTPUT, "rb")) != NULL) {
+ while (fgets (buf, BUFSIZ, fp)) {
+ char *s;
+
+ if (*buf == 0 || *buf == '\n' || *buf == '\r') break;
+
+ for (s = buf; *s && *s != '\n' && *s != '\r'; s++);
+ *s = 0;
+
+ if (!PORT_Strncmp (buf, "MD5-Digest: ", 12)) {
+ md5_digest = ATOB_AsciiToData (buf + 12, &md5_length);
+ }
+
+ if (!PORT_Strncmp (buf, "SHA1-Digest: ", 13)) {
+ sha1_digest = ATOB_AsciiToData (buf + 13, &sha1_length);
+ }
+
+ if (!PORT_Strncmp (buf, "SHA-Digest: ", 12)) {
+ sha1_digest = ATOB_AsciiToData (buf + 12, &sha1_length);
+ }
+ }
+
+ globaldig = jar->globalmeta;
+
+ if (globaldig && md5_digest) {
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD,
+ " md5 digest on global metainfo: %s\n",
+ PORT_Memcmp (md5_digest, globaldig->md5, MD5_LENGTH) ?
+ "no match" : "match");
+ }
+ }
+
+ if (globaldig && sha1_digest) {
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD,
+ " sha digest on global metainfo: %s\n",
+ PORT_Memcmp(sha1_digest, globaldig->sha1,
+ SHA1_LENGTH) ? "no match" : "match");
+ }
+ }
+
+ if (globaldig == NULL) {
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD,
+ "global metadigest is not available, strange.\n");
+ }
+ }
+
+ fclose (fp);
+ }
+ }
+ }
+ }
+
+ JAR_find_end (ctx);
+
+ return retval;
+}
+
+/************************************************************************
+ *
+ * J a r W h o
+ */
+int
+JarWho(char *filename)
+ {
+ FILE *fp;
+
+ JAR *jar;
+ JAR_Context *ctx;
+
+ int status;
+ int retval = 0;
+
+ JAR_Item *it;
+ JAR_Cert *fing;
+
+ CERTCertificate *cert, *prev = NULL;
+
+ jar = JAR_new();
+
+ if ((fp = fopen (filename, "r")) == NULL)
+ {
+ perror (filename);
+ exit (ERRX);
+ }
+ else
+ fclose (fp);
+
+ status = JAR_pass_archive (jar, jarArchGuess, filename, "some-url");
+
+ if (status < 0 || jar->valid < 0)
+ {
+ PR_fprintf(outputFD,
+ "NOTE -- \"%s\" archive DID NOT PASS crypto verification.\n", filename);
+ retval = -1;
+ if (jar->valid < 0 || status != -1)
+ {
+ char *errtext;
+
+ if (status >= JAR_BASE && status <= JAR_BASE_END)
+ {
+ errtext = JAR_get_error (status);
+ }
+ else
+ {
+ errtext = SECU_ErrorString ((int16) PORT_GetError());
+ }
+
+ PR_fprintf(outputFD, " (reported reason: %s)\n\n", errtext);
+ }
+ }
+
+ PR_fprintf(outputFD, "\nSigner information:\n\n");
+
+ ctx = JAR_find (jar, NULL, jarTypeSign);
+
+ while (JAR_find_next (ctx, &it) >= 0)
+ {
+ fing = (JAR_Cert *) it->data;
+ cert = fing->cert;
+
+ if (cert)
+ {
+ if (prev == cert)
+ break;
+
+ if (cert->nickname)
+ PR_fprintf(outputFD, "nickname: %s\n", cert->nickname);
+ if (cert->subjectName)
+ PR_fprintf(outputFD, "subject name: %s\n", cert->subjectName);
+ if (cert->issuerName)
+ PR_fprintf(outputFD, "issuer name: %s\n", cert->issuerName);
+ }
+ else
+ {
+ PR_fprintf(outputFD, "no certificate could be found\n");
+ retval = -1;
+ }
+
+ prev = cert;
+ }
+
+ JAR_find_end (ctx);
+
+ JAR_destroy (jar);
+ return retval;
+}
+
+/************************************************************************
+ * j a r _ c b
+ */
+static int jar_cb(int status, JAR *jar, const char *metafile,
+ char *pathname, char *errortext)
+{
+ PR_fprintf(errorFD, "error %d: %s IN FILE %s\n", status, errortext, pathname);
+ errorCount++;
+ return 0;
+}
+
diff --git a/security/nss/cmd/signtool/zip.c b/security/nss/cmd/signtool/zip.c
new file mode 100644
index 000000000..62e885137
--- /dev/null
+++ b/security/nss/cmd/signtool/zip.c
@@ -0,0 +1,678 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "signtool.h"
+#include "zip.h"
+#include "zlib.h"
+#include "prmem.h"
+
+static void inttox (int in, char *out);
+static void longtox (long in, char *out);
+
+/****************************************************************
+ *
+ * J z i p O p e n
+ *
+ * Opens a new ZIP file and creates a new ZIPfile structure to
+ * control the process of installing files into a zip.
+ */
+ZIPfile*
+JzipOpen(char *filename, char *comment)
+{
+ ZIPfile *zipfile;
+ PRExplodedTime prtime;
+
+ zipfile = PORT_ZAlloc(sizeof(ZIPfile));
+ if(!zipfile) out_of_memory();
+
+ /* Construct time and date */
+ PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &prtime);
+ zipfile->date = ((prtime.tm_year-1980) << 9) |
+ ((prtime.tm_month+1) << 5) |
+ prtime.tm_mday;
+ zipfile->time = (prtime.tm_hour<<11) |
+ (prtime.tm_min<<5) |
+ (prtime.tm_sec&0x3f);
+
+ if (filename &&
+ (zipfile->fp = PR_Open(filename,
+ PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0777)) == NULL) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "%s: can't open output jar, %s.%s\n", PROGRAM_NAME,
+ filename, nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit (ERRX);
+ }
+
+ zipfile->list = NULL;
+ if(filename) {
+ zipfile->filename = PORT_ZAlloc(strlen(filename)+1);
+ if(!zipfile->filename) out_of_memory();
+ PORT_Strcpy(zipfile->filename, filename);
+ }
+ if(comment) {
+ zipfile->comment = PORT_ZAlloc(strlen(comment)+1);
+ if(!zipfile->comment) out_of_memory();
+ PORT_Strcpy(zipfile->comment, comment);
+ }
+
+ return zipfile;
+}
+
+static
+void*
+my_alloc_func(void* opaque, uInt items, uInt size)
+{
+ return PORT_Alloc(items*size);
+}
+
+static
+void
+my_free_func(void* opaque, void* address)
+{
+ PORT_Free(address);
+}
+
+static
+void
+handle_zerror(int err, char *msg)
+{
+ if(!msg) {
+ msg = "";
+ }
+
+ errorCount++; /* unless Z_OK...see below */
+
+ switch(err) {
+ case Z_OK:
+ PR_fprintf(errorFD, "No error: %s\n", msg);
+ errorCount--; /* this was incremented above */
+ break;
+ case Z_MEM_ERROR:
+ PR_fprintf(errorFD, "Deflation ran out of memory: %s\n", msg);
+ break;
+ case Z_STREAM_ERROR:
+ PR_fprintf(errorFD, "Invalid compression level: %s\n", msg);
+ break;
+ case Z_VERSION_ERROR:
+ PR_fprintf(errorFD, "Incompatible compression library version: %s\n", msg);
+ break;
+ case Z_DATA_ERROR:
+ PR_fprintf(errorFD, "Compression data error: %s\n", msg);
+ break;
+ default:
+ PR_fprintf(errorFD, "Unknown error in compression library: %s\n", msg);
+ break;
+ }
+}
+
+
+/****************************************************************
+ *
+ * J z i p A d d
+ *
+ * Adds a new file into a ZIP file. The ZIP file must have already
+ * been opened with JzipOpen.
+ */
+int
+JzipAdd(char *fullname, char *filename, ZIPfile *zipfile, int compression_level)
+{
+ ZIPentry *entry;
+ PRFileDesc *readfp;
+ PRFileDesc *zipfp;
+ int num;
+ Bytef inbuf[BUFSIZ], outbuf[BUFSIZ];
+ unsigned long crc;
+ z_stream zstream;
+ int err;
+ unsigned long local_size_pos;
+ int deflate_percent;
+
+
+ if( !fullname || !filename || !zipfile) {
+ return -1;
+ }
+
+ zipfp = zipfile->fp;
+
+
+ if( (readfp = PR_Open(fullname, PR_RDONLY, 0777)) == NULL) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "%s: %s\n", fullname, nsprErr ? nsprErr : "");
+ errorCount++;
+ if(nsprErr) PR_Free(nsprErr);
+ exit(ERRX);
+ }
+
+ /*
+ * Make sure the input file is not the output file.
+ * Add a few bytes to the end of the JAR file and see if the input file
+ * twitches
+ */
+ {
+ PRInt32 endOfJar;
+ PRInt32 inputSize;
+ PRBool isSame;
+
+ inputSize = PR_Available(readfp);
+
+ endOfJar = PR_Seek(zipfp, 0L, PR_SEEK_CUR);
+
+ if(PR_Write(zipfp, "abcde", 5) < 5) {
+ char *nsprErr;
+
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing to zip file: %s\n",
+ nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ isSame = (PR_Available(readfp) != inputSize);
+
+ PR_Seek(zipfp, endOfJar, PR_SEEK_SET);
+
+ if(isSame) {
+ /* It's the same file! Forget it! */
+ PR_Close(readfp);
+ return 0;
+ }
+ }
+
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "adding %s to %s...", fullname, zipfile->filename);
+ }
+
+ entry = PORT_ZAlloc(sizeof(ZIPentry));
+ if(!entry) out_of_memory();
+
+ entry->filename = PORT_Strdup(filename);
+ entry->comment = NULL;
+
+ /* Set up local file header */
+ longtox(LSIG, entry->local.signature);
+ inttox(strlen(filename), entry->local.filename_len);
+ inttox(zipfile->time, entry->local.time);
+ inttox(zipfile->date, entry->local.date);
+ inttox(Z_DEFLATED, entry->local.method);
+
+ /* Set up central directory entry */
+ longtox(CSIG, entry->central.signature);
+ inttox(strlen(filename), entry->central.filename_len);
+ if(entry->comment) {
+ inttox(strlen(entry->comment), entry->central.commentfield_len);
+ }
+ longtox(PR_Seek(zipfile->fp, 0, PR_SEEK_CUR),
+ entry->central.localhdr_offset);
+ inttox(zipfile->time, entry->central.time);
+ inttox(zipfile->date, entry->central.date);
+ inttox(Z_DEFLATED, entry->central.method);
+
+ /* Compute crc. Too bad we have to process the whole file to do this*/
+ crc = crc32(0L, NULL, 0);
+ while( (num = PR_Read(readfp, inbuf, BUFSIZ)) > 0) {
+ crc = crc32(crc, inbuf, num);
+ }
+ PR_Seek(readfp, 0L, PR_SEEK_SET);
+
+ /* Store CRC */
+ longtox(crc, entry->local.crc32);
+ longtox(crc, entry->central.crc32);
+
+ /* Stick this entry onto the end of the list */
+ entry->next = NULL;
+ if( zipfile->list == NULL ) {
+ /* First entry */
+ zipfile->list = entry;
+ } else {
+ ZIPentry *pe;
+
+ pe = zipfile->list;
+ while(pe->next != NULL) {
+ pe = pe->next;
+ }
+ pe->next = entry;
+ }
+
+ /*
+ * Start writing stuff out
+ */
+
+ local_size_pos = PR_Seek(zipfp, 0, PR_SEEK_CUR) + 18;
+ /* File header */
+ if(PR_Write(zipfp, &entry->local, sizeof(struct ZipLocal))
+ < sizeof(struct ZipLocal)) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ /* File Name */
+ if( PR_Write(zipfp, filename, strlen(filename)) < strlen(filename)) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ /*
+ * File data
+ */
+ /* Initialize zstream */
+ zstream.zalloc = my_alloc_func;
+ zstream.zfree = my_free_func;
+ zstream.opaque = NULL;
+ zstream.next_in = inbuf;
+ zstream.avail_in = BUFSIZ;
+ zstream.next_out = outbuf;
+ zstream.avail_out = BUFSIZ;
+ /* Setting the windowBits to -MAX_WBITS is an undocumented feature of
+ * zlib (see deflate.c in zlib). It is the same thing that Java does
+ * when you specify the nowrap option for deflation in java.util.zip.
+ * It causes zlib to leave out its headers and footers, which don't
+ * work in PKZIP files.
+ */
+ err = deflateInit2(&zstream, compression_level, Z_DEFLATED,
+ -MAX_WBITS, 8 /*default*/, Z_DEFAULT_STRATEGY);
+ if(err != Z_OK) {
+ handle_zerror(err, zstream.msg);
+ exit(ERRX);
+ }
+
+ while( (zstream.avail_in = PR_Read(readfp, inbuf, BUFSIZ)) > 0) {
+ zstream.next_in = inbuf;
+ /* Process this chunk of data */
+ while(zstream.avail_in > 0) {
+ err = deflate(&zstream, Z_NO_FLUSH);
+ if(err != Z_OK) {
+ handle_zerror(err, zstream.msg);
+ exit(ERRX);
+ }
+ if(zstream.avail_out <= 0) {
+ if( PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ zstream.next_out = outbuf;
+ zstream.avail_out = BUFSIZ;
+ }
+ }
+ }
+
+ /* Now flush everything */
+ while(1) {
+ err = deflate(&zstream, Z_FINISH);
+ if(err == Z_STREAM_END) {
+ break;
+ } else if(err == Z_OK) {
+ /* output buffer full, repeat */
+ } else {
+ handle_zerror(err, zstream.msg);
+ exit(ERRX);
+ }
+ if( PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ zstream.avail_out = BUFSIZ;
+ zstream.next_out = outbuf;
+ }
+
+ /* If there's any output left, write it out. */
+ if(zstream.next_out != outbuf) {
+ if( PR_Write(zipfp, outbuf, zstream.next_out-outbuf) <
+ zstream.next_out-outbuf) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ zstream.avail_out = BUFSIZ;
+ zstream.next_out = outbuf;
+ }
+
+ /* Now that we know the compressed size, write this to the headers */
+ longtox(zstream.total_in, entry->local.orglen);
+ longtox(zstream.total_out, entry->local.size);
+ if(PR_Seek(zipfp, local_size_pos, PR_SEEK_SET) == -1) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Accessing zip file: %s\n", nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ if( PR_Write(zipfp, entry->local.size, 8) != 8) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ if(PR_Seek(zipfp, 0L, PR_SEEK_END) == -1) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Accessing zip file: %s\n", nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ longtox(zstream.total_in, entry->central.orglen);
+ longtox(zstream.total_out, entry->central.size);
+
+ /* Close out the deflation operation */
+ err = deflateEnd(&zstream);
+ if(err != Z_OK) {
+ handle_zerror(err, zstream.msg);
+ exit(ERRX);
+ }
+
+ PR_Close(readfp);
+
+ if((zstream.total_in > zstream.total_out) && (zstream.total_in > 0)) {
+ deflate_percent = (int) ( (zstream.total_in-zstream.total_out)*100 /
+ zstream.total_in );
+ } else {
+ deflate_percent = 0;
+ }
+ if(verbosity >= 0) {
+ PR_fprintf(outputFD, "(deflated %d%%)\n", deflate_percent);
+ }
+
+ return 0;
+}
+
+/********************************************************************
+ * J z i p C l o s e
+ *
+ * Finishes the ZipFile. ALSO DELETES THE ZIPFILE STRUCTURE PASSED IN!!
+ */
+int
+JzipClose(ZIPfile *zipfile)
+{
+ ZIPentry *pe, *dead;
+ PRFileDesc *zipfp;
+ struct ZipEnd zipend;
+ unsigned int entrycount = 0;
+
+ if(!zipfile) {
+ return -1;
+ }
+
+ if(!zipfile->filename) {
+ /* bogus */
+ return 0;
+ }
+
+ zipfp = zipfile->fp;
+ zipfile->central_start = PR_Seek(zipfp, 0L, PR_SEEK_CUR);
+
+ /* Write out all the central directories */
+ pe = zipfile->list;
+ while(pe) {
+ entrycount++;
+
+ /* Write central directory info */
+ if( PR_Write(zipfp, &pe->central, sizeof(struct ZipCentral))
+ < sizeof(struct ZipCentral)) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ /* Write filename */
+ if( PR_Write(zipfp, pe->filename, strlen(pe->filename))
+ < strlen(pe->filename)) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ /* Write file comment */
+ if(pe->comment) {
+ if( PR_Write(zipfp, pe->comment, strlen(pe->comment))
+ < strlen(pe->comment)) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ }
+
+ /* Delete the structure */
+ dead = pe;
+ pe = pe->next;
+ if(dead->filename) {
+ PORT_Free(dead->filename);
+ }
+ if(dead->comment) {
+ PORT_Free(dead->comment);
+ }
+ PORT_Free(dead);
+ }
+ zipfile->central_end = PR_Seek(zipfile->fp, 0L, PR_SEEK_CUR);
+
+ /* Create the ZipEnd structure */
+ PORT_Memset(&zipend, 0, sizeof(zipend));
+ longtox(ESIG, zipend.signature);
+ inttox(entrycount, zipend.total_entries_disk);
+ inttox(entrycount, zipend.total_entries_archive);
+ longtox(zipfile->central_end-zipfile->central_start,
+ zipend.central_dir_size);
+ longtox(zipfile->central_start, zipend.offset_central_dir);
+ if(zipfile->comment) {
+ inttox(strlen(zipfile->comment), zipend.commentfield_len);
+ }
+
+ /* Write out ZipEnd xtructure */
+ if( PR_Write(zipfp, &zipend, sizeof(zipend)) < sizeof(zipend)) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+
+ /* Write out Zipfile comment */
+ if(zipfile->comment) {
+ if( PR_Write(zipfp, zipfile->comment, strlen(zipfile->comment))
+ < strlen(zipfile->comment)) {
+ char *nsprErr;
+ if(PR_GetErrorTextLength()) {
+ nsprErr = PR_Malloc(PR_GetErrorTextLength());
+ PR_GetErrorText(nsprErr);
+ } else {
+ nsprErr = NULL;
+ }
+ PR_fprintf(errorFD, "Writing zip data: %s\n",
+ nsprErr ? nsprErr : "");
+ if(nsprErr) PR_Free(nsprErr);
+ errorCount++;
+ exit(ERRX);
+ }
+ }
+
+ PR_Close(zipfp);
+
+ /* Free the memory of the zipfile structure */
+ if(zipfile->filename) {
+ PORT_Free(zipfile->filename);
+ }
+ if(zipfile->comment) {
+ PORT_Free(zipfile->comment);
+ }
+ PORT_Free(zipfile);
+
+ return 0;
+}
+
+/**********************************************
+ * i n t t o x
+ *
+ * Converts a two byte ugly endianed integer
+ * to our platform's integer.
+ *
+ */
+
+static void inttox (int in, char *out)
+{
+ out [0] = (in & 0xFF);
+ out [1] = (in & 0xFF00) >> 8;
+}
+
+/*********************************************
+ * l o n g t o x
+ *
+ * Converts a four byte ugly endianed integer
+ * to our platform's integer.
+ *
+ */
+
+static void longtox (long in, char *out)
+{
+ out [0] = (in & 0xFF);
+ out [1] = (in & 0xFF00) >> 8;
+ out [2] = (in & 0xFF0000) >> 16;
+ out [3] = (in & 0xFF000000) >> 24;
+}
+
diff --git a/security/nss/cmd/signtool/zip.h b/security/nss/cmd/signtool/zip.h
new file mode 100644
index 000000000..08512f3c4
--- /dev/null
+++ b/security/nss/cmd/signtool/zip.h
@@ -0,0 +1,100 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/* zip.h
+ * Structures and functions for creating ZIP archives.
+ */
+#ifndef ZIP_H
+#define ZIP_H
+
+/* For general information on ZIP formats, you can look at jarfile.h
+ * in ns/security/lib/jar. Or look it up on the web...
+ */
+
+/* One entry in a ZIPfile. This corresponds to one file in the archive.
+ * We have to save this information because first all the files go into
+ * the archive with local headers; then at the end of the file we have to
+ * put the central directory entries for each file.
+ */
+typedef struct ZIPentry_s {
+ struct ZipLocal local; /* local header info */
+ struct ZipCentral central; /* central directory info */
+ char *filename; /* name of file */
+ char *comment; /* comment for this file -- optional */
+
+ struct ZIPentry_s *next;
+} ZIPentry;
+
+/* This structure contains the necessary data for putting a ZIP file
+ * together. Has some overall information and a list of ZIPentrys.
+ */
+typedef struct ZIPfile_s {
+ char *filename; /* ZIP file name */
+ char *comment; /* ZIP file comment -- may be NULL */
+ PRFileDesc *fp; /* ZIP file pointer */
+ ZIPentry *list; /* one entry for each file in the archive */
+ unsigned int time; /* the GMT time of creation, in DOS format */
+ unsigned int date; /* the GMT date of creation, in DOS format */
+ unsigned long central_start; /* starting offset of central directory */
+ unsigned long central_end; /*index right after the last byte of central*/
+} ZIPfile;
+
+
+/* Open a new ZIP file. Takes the name of the zip file and an optional
+ * comment to be included in the file. Returns a new ZIPfile structure
+ * which is used by JzipAdd and JzipClose
+ */
+ZIPfile* JzipOpen(char *filename, char *comment);
+
+/* Add a file to a ZIP archive. Fullname is the path relative to the
+ * current directory. Filename is what the name will be stored as in the
+ * archive, and thus what it will be restored as. zipfile is a structure
+ * returned from a previous call to JzipOpen.
+ *
+ * Non-zero return code means error (although usually the function will
+ * call exit() rather than return an error--gotta fix this).
+ */
+int JzipAdd(char *fullname, char *filename, ZIPfile *zipfile,
+ int compression_level);
+
+/* Finalize a ZIP archive. Adds all the footer information to the end of
+ * the file and closes it. Also DELETES THE ZIPFILE STRUCTURE that was
+ * passed in. So you never have to allocate or free a ZIPfile yourself.
+ *
+ * Non-zero return code means error (although usually the function will
+ * call exit() rather than return an error--gotta fix this).
+ */
+int JzipClose (ZIPfile *zipfile);
+
+
+#endif /* ZIP_H */
diff --git a/security/nss/cmd/signver/Makefile b/security/nss/cmd/signver/Makefile
new file mode 100644
index 000000000..e4a3a6069
--- /dev/null
+++ b/security/nss/cmd/signver/Makefile
@@ -0,0 +1,71 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/signver/examples/1/form.pl b/security/nss/cmd/signver/examples/1/form.pl
new file mode 100755
index 000000000..2034bf728
--- /dev/null
+++ b/security/nss/cmd/signver/examples/1/form.pl
@@ -0,0 +1,50 @@
+#! /usr/bin/perl
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+
+print "Content-type: text/html\n\n";
+print "<B>Server Name:</B> ", $ENV{'SERVER_NAME'}, "<BR>", "\n";
+print "<B>Server Port:</B> ", $ENV{'SERVER_PORT'}, "<BR>", "\n";
+print "<B>Server Software:</B> ", $ENV{'SERVER_SOFTWARE'}, "<BR>", "\n";
+print "<B>Server Protocol:</B> ", $ENV{'SERVER_PROTOCOL'}, "<BR>", "\n";
+print "<B>CGI Revision:</B> ", $ENV{'GATEWAY_INTERFACE'}, "<BR>", "\n";
+print "<B>Browser:</B> ", $ENV{'HTTP_USER_AGENT'}, "<BR>", "\n";
+print "<B>Remote Address:</B> ", $ENV{'REMOTE_ADDR'}, "<BR>", "\n";
+print "<B>Remote Host:</B> ", $ENV{'REMOTE_HOST'}, "<BR>", "\n";
+print "<B>Remote User:</B> ", $ENV{'REMOTE_USER'}, "<BR>", "\n";
+print "You typed:\n";
+
+while( $_ = <STDIN>) {
+ print "$_";
+}
+
diff --git a/security/nss/cmd/signver/examples/1/signedForm.html b/security/nss/cmd/signver/examples/1/signedForm.html
new file mode 100644
index 000000000..1444a1775
--- /dev/null
+++ b/security/nss/cmd/signver/examples/1/signedForm.html
@@ -0,0 +1,84 @@
+<html>
+<!--
+ - The contents of this file are subject to the Mozilla Public
+ - License Version 1.1 (the "License"); you may not use this file
+ - except in compliance with the License. You may obtain a copy of
+ - the License at http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS
+ - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ - implied. See the License for the specific language governing
+ - rights and limitations under the License.
+ -
+ - The Original Code is the Netscape security libraries.
+ -
+ - The Initial Developer of the Original Code is Netscape
+ - Communications Corporation. Portions created by Netscape are
+ - Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ - Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the
+ - terms of the GNU General Public License Version 2 or later (the
+ - "GPL"), in which case the provisions of the GPL are applicable
+ - instead of those above. If you wish to allow use of your
+ - version of this file only under the terms of the GPL and not to
+ - allow others to use your version of this file under the MPL,
+ - indicate your decision by deleting the provisions above and
+ - replace them with the notice and other provisions required by
+ - the GPL. If you do not delete the provisions above, a recipient
+ - may use your version of this file under either the MPL or the
+ - GPL.
+ -->
+<head>
+<title>Form to sign</title>
+<script language="javascript">
+<!--
+function submitSigned(form){
+ var signature = "";
+ var dataToSign = "";
+ var i;
+
+ form.action='signedForm.pl';
+ for (i = 0; i < form.length; i++)
+ if (form.elements[i].type == "text")
+ dataToSign += form.elements[i].value;
+
+ // alert("Data to sign:\n" + dataToSign);
+ signature = crypto.signText(dataToSign, "ask");
+ /* alert("You cannot see this alert");
+ alert("Data signature:\n" + signature); */
+
+ if (signature != "error:userCancel") {
+ for (i = 0; i < form.length; i++) {
+ if (form.elements[i].type == "hidden") {
+ if (form.elements[i].name == "dataToSign")
+ form.elements[i].value = dataToSign;
+ if (form.elements[i].name == "dataSignature")
+ form.elements[i].value = signature;
+ }
+ }
+ form.submit();
+ }
+}
+//-->
+</script>
+</head>
+
+<body>
+<form method=post Action="form.pl">
+<input type=hidden size=30 name=dataSignature>
+<input type=hidden size=30 name=dataToSign>
+<input type=text size=30 name=p>
+<BR>
+<input type=text size=30 name=q>
+<BR>
+<input type=text size=30 name=r>
+<BR>
+<input type=submit value="Submit Data">
+<input type=button value="Sign and Submit Data" onclick=submitSigned(this.form)>
+<input type=reset value=Reset>
+</form>
+</body>
+</html>
diff --git a/security/nss/cmd/signver/examples/1/signedForm.nt.html b/security/nss/cmd/signver/examples/1/signedForm.nt.html
new file mode 100644
index 000000000..5487739ce
--- /dev/null
+++ b/security/nss/cmd/signver/examples/1/signedForm.nt.html
@@ -0,0 +1,84 @@
+<html>
+<!--
+ - The contents of this file are subject to the Mozilla Public
+ - License Version 1.1 (the "License"); you may not use this file
+ - except in compliance with the License. You may obtain a copy of
+ - the License at http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS
+ - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ - implied. See the License for the specific language governing
+ - rights and limitations under the License.
+ -
+ - The Original Code is the Netscape security libraries.
+ -
+ - The Initial Developer of the Original Code is Netscape
+ - Communications Corporation. Portions created by Netscape are
+ - Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ - Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the
+ - terms of the GNU General Public License Version 2 or later (the
+ - "GPL"), in which case the provisions of the GPL are applicable
+ - instead of those above. If you wish to allow use of your
+ - version of this file only under the terms of the GPL and not to
+ - allow others to use your version of this file under the MPL,
+ - indicate your decision by deleting the provisions above and
+ - replace them with the notice and other provisions required by
+ - the GPL. If you do not delete the provisions above, a recipient
+ - may use your version of this file under either the MPL or the
+ - GPL.
+ -->
+<head>
+<title>Form to sign</title>
+<script language="javascript">
+<!--
+function submitSigned(form){
+ var signature = "";
+ var dataToSign = "";
+ var i;
+
+ form.action='cgi-bin/signedForm.pl';
+ for (i = 0; i < form.length; i++)
+ if (form.elements[i].type == "text")
+ dataToSign += form.elements[i].value;
+
+ // alert("Data to sign:\n" + dataToSign);
+ signature = crypto.signText(dataToSign, "ask");
+ /* alert("You cannot see this alert");
+ alert("Data signature:\n" + signature); */
+
+ if (signature != "error:userCancel") {
+ for (i = 0; i < form.length; i++) {
+ if (form.elements[i].type == "hidden") {
+ if (form.elements[i].name == "dataToSign")
+ form.elements[i].value = dataToSign;
+ if (form.elements[i].name == "dataSignature")
+ form.elements[i].value = signature;
+ }
+ }
+ form.submit();
+ }
+}
+//-->
+</script>
+</head>
+
+<body>
+<form method=post Action="cgi-bin/form.pl">
+<input type=hidden size=30 name=dataSignature>
+<input type=hidden size=30 name=dataToSign>
+<input type=text size=30 name=p>
+<BR>
+<input type=text size=30 name=q>
+<BR>
+<input type=text size=30 name=r>
+<BR>
+<input type=submit value="Submit Data">
+<input type=button value="Sign and Submit Data" onclick=submitSigned(this.form)>
+<input type=reset value=Reset>
+</form>
+</body>
+</html>
diff --git a/security/nss/cmd/signver/examples/1/signedForm.pl b/security/nss/cmd/signver/examples/1/signedForm.pl
new file mode 100755
index 000000000..3c2cd0ed3
--- /dev/null
+++ b/security/nss/cmd/signver/examples/1/signedForm.pl
@@ -0,0 +1,88 @@
+#! /usr/bin/perl
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+
+
+sub decode {
+ read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
+ @pairs = split(/&/, $buffer);
+ foreach $pair (@pairs)
+ {
+ ($name, $value) = split(/=/, $pair);
+ $value =~tr/+/ /;
+ $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
+ $FORM{$name} = $value;
+# print "name=$name value=$value<BR>\n";
+ }
+}
+
+print "Content-type: text/html\n\n";
+
+&decode();
+
+$dataSignature = $FORM{'dataSignature'};
+$dataToSign = $FORM{'dataToSign'};
+
+unlink("signature");
+open(FILE1,">signature") || die("Cannot open file for writing\n");
+
+print FILE1 "$dataSignature";
+
+close(FILE1);
+
+
+unlink("data");
+open(FILE2,">data") || die("Cannot open file for writing\n");
+
+print FILE2 "$dataToSign";
+
+close(FILE2);
+
+
+print "<BR><B>Signed Data:</B><BR>", "$dataToSign", "<BR>";
+
+print "<BR><b>Verification Info:</b><BR>";
+
+$verInfo = `./signver -D . -s signature -d data -v`;
+print "<font color=red><b>$verInfo</b></font><BR>";
+
+print "<BR><B>Signature Data:</B><BR>", "$dataSignature", "<BR>";
+
+print "<BR><b>Signature Info:</b><BR>";
+
+foreach $line (`./signver -s signature -A`) {
+ print "$line<BR>\n";
+}
+
+print "<b>End of Info</b><BR>";
+
diff --git a/security/nss/cmd/signver/manifest.mn b/security/nss/cmd/signver/manifest.mn
new file mode 100644
index 000000000..9efdaad29
--- /dev/null
+++ b/security/nss/cmd/signver/manifest.mn
@@ -0,0 +1,54 @@
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+MODULE = nss
+
+CSRCS = signver.c \
+ pk7print.c \
+ $(NULL)
+
+REQUIRES = dbm seccmd
+
+PROGRAM = signver
+
+PACKAGE_FILES = README.txt signedForm.html signedForm.pl form.pl
+ifeq ($(subst /,_,$(shell uname -s)),WINNT)
+PACKAGE_FILES += signedForm.nt.pl signver.exe
+else
+PACKAGE_FILES += signver
+endif
+
+ARCHIVE_NAME = signver
+
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/signver/pk7print.c b/security/nss/cmd/signver/pk7print.c
new file mode 100644
index 000000000..94d8e8f36
--- /dev/null
+++ b/security/nss/cmd/signver/pk7print.c
@@ -0,0 +1,922 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+** secutil.c - various functions used by security stuff
+**
+*/
+
+/* pkcs #7 -related functions */
+
+
+#include "secutil.h"
+#include "secpkcs7.h"
+#include "secoid.h"
+#include <sys/stat.h>
+#include <stdarg.h>
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+
+/* for SEC_TraverseNames */
+#include "cert.h"
+#include "prtypes.h"
+#include "prtime.h"
+
+#include "prlong.h"
+#include "secmod.h"
+#include "pk11func.h"
+#include "prerror.h"
+
+
+
+
+/*
+** PKCS7 Support
+*/
+
+/* forward declaration */
+int
+sv_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *);
+
+
+void
+sv_PrintAsHex(FILE *out, SECItem *data, char *m)
+{
+ unsigned i;
+
+ if (m) fprintf(out, m);
+
+ for (i = 0; i < data->len; i++) {
+ if (i < data->len - 1) {
+ fprintf(out, "%02x:", data->data[i]);
+ } else {
+ fprintf(out, "%02x\n", data->data[i]);
+ break;
+ }
+ }
+}
+
+void
+sv_PrintInteger(FILE *out, SECItem *i, char *m)
+{
+ int iv;
+
+ if (i->len > 4) {
+ sv_PrintAsHex(out, i, m);
+ } else {
+ iv = DER_GetInteger(i);
+ fprintf(out, "%s%d (0x%x)\n", m, iv, iv);
+ }
+}
+
+
+int
+sv_PrintUTCTime(FILE *out, SECItem *t, char *m)
+{
+ PRExplodedTime printableTime;
+ int64 time;
+ char *timeString;
+ int rv;
+
+ rv = DER_UTCTimeToTime(&time, t);
+ if (rv) return rv;
+
+ /* Converse to local time */
+ PR_ExplodeTime(time, PR_GMTParameters, &printableTime);
+
+ timeString = (char *)PORT_Alloc(100);
+
+ if ( timeString ) {
+ PR_FormatTime( timeString, 100, "%a %b %d %H:%M:%S %Y", &printableTime );
+ fprintf(out, "%s%s\n", m, timeString);
+ PORT_Free(timeString);
+ return 0;
+ }
+ return SECFailure;
+}
+
+
+int
+sv_PrintValidity(FILE *out, CERTValidity *v, char *m)
+{
+ int rv;
+
+ fprintf(out, m);
+ rv = sv_PrintUTCTime(out, &v->notBefore, "notBefore=");
+ if (rv) return rv;
+ fprintf(out, m);
+ sv_PrintUTCTime(out, &v->notAfter, "notAfter=");
+ return rv;
+}
+
+void
+sv_PrintObjectID(FILE *out, SECItem *oid, char *m)
+{
+ const char *name;
+ SECOidData *oiddata;
+
+ oiddata = SECOID_FindOID(oid);
+ if (oiddata == NULL) {
+ sv_PrintAsHex(out, oid, m);
+ return;
+ }
+ name = oiddata->desc;
+
+ if (m != NULL)
+ fprintf(out, "%s", m);
+ fprintf(out, "%s\n", name);
+}
+
+void
+sv_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m)
+{
+ sv_PrintObjectID(out, &a->algorithm, m);
+
+ if ((a->parameters.len != 2) ||
+ (PORT_Memcmp(a->parameters.data, "\005\000", 2) != 0)) {
+ /* Print args to algorithm */
+ sv_PrintAsHex(out, &a->parameters, "Args=");
+ }
+}
+
+void
+sv_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m)
+{
+ SECItem *value;
+ int i;
+ char om[100];
+
+ fprintf(out, m);
+
+ /*
+ * XXX Make this smarter; look at the type field and then decode
+ * and print the value(s) appropriately!
+ */
+ sv_PrintObjectID(out, &(attr->type), "type=");
+ if (attr->values != NULL) {
+ i = 0;
+ while ((value = attr->values[i]) != NULL) {
+ sprintf(om, "%svalue[%d]=%s", m, i++, attr->encoded ? "(encoded)" : "");
+ if (attr->encoded || attr->typeTag == NULL) {
+ sv_PrintAsHex(out, value, om);
+ } else {
+ switch (attr->typeTag->offset) {
+ default:
+ sv_PrintAsHex(out, value, om);
+ break;
+ case SEC_OID_PKCS9_CONTENT_TYPE:
+ sv_PrintObjectID(out, value, om);
+ break;
+ case SEC_OID_PKCS9_SIGNING_TIME:
+ sv_PrintUTCTime(out, value, om);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void
+sv_PrintName(FILE *out, CERTName *name, char *msg)
+{
+ char *str;
+
+ str = CERT_NameToAscii(name);
+ fprintf(out, "%s%s\n", msg, str);
+}
+
+
+#if 0
+/*
+** secu_PrintPKCS7EncContent
+** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
+*/
+void
+secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
+ char *m, int level)
+{
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ secu_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ secu_Indent(out, level + 1);
+ fprintf(out, "Content Type: %s\n",
+ (src->contentTypeTag != NULL) ? src->contentTypeTag->desc
+ : "Unknown");
+ sv_PrintAlgorithmID(out, &(src->contentEncAlg),
+ "Content Encryption Algorithm");
+ sv_PrintAsHex(out, &(src->encContent),
+ "Encrypted Content", level+1);
+}
+
+/*
+** secu_PrintRecipientInfo
+** Prints a PKCS7RecipientInfo type
+*/
+void
+secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
+ int level)
+{
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(info->version), "Version");
+
+ sv_PrintName(out, &(info->issuerAndSN->issuer), "Issuer");
+ sv_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "Serial Number");
+
+ /* Parse and display encrypted key */
+ sv_PrintAlgorithmID(out, &(info->keyEncAlg),
+ "Key Encryption Algorithm");
+ sv_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
+}
+#endif
+
+/*
+** secu_PrintSignerInfo
+** Prints a PKCS7SingerInfo type
+*/
+void
+sv_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m)
+{
+ SEC_PKCS7Attribute *attr;
+ int iv;
+
+ fprintf(out, m);
+ sv_PrintInteger(out, &(info->version), "version=");
+
+ fprintf(out, m);
+ sv_PrintName(out, &(info->issuerAndSN->issuer), "issuerName=");
+ fprintf(out, m);
+ sv_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "serialNumber=");
+
+ fprintf(out, m);
+ sv_PrintAlgorithmID(out, &(info->digestAlg), "digestAlgorithm=");
+
+ if (info->authAttr != NULL) {
+ char mm[120];
+
+ iv = 0;
+ while (info->authAttr[iv] != NULL) iv++;
+ fprintf(out, "%sauthenticatedAttributes=%d\n", m, iv);
+ iv = 0;
+ while ((attr = info->authAttr[iv]) != NULL) {
+ sprintf(mm, "%sattribute[%d].", m, iv++);
+ sv_PrintAttribute(out, attr, mm);
+ }
+ }
+
+ /* Parse and display signature */
+ fprintf(out, m);
+ sv_PrintAlgorithmID(out, &(info->digestEncAlg), "digestEncryptionAlgorithm=");
+ fprintf(out, m);
+ sv_PrintAsHex(out, &(info->encDigest), "encryptedDigest=");
+
+ if (info->unAuthAttr != NULL) {
+ char mm[120];
+
+ iv = 0;
+ while (info->unAuthAttr[iv] != NULL) iv++;
+ fprintf(out, "%sunauthenticatedAttributes=%d\n", m, iv);
+ iv = 0;
+ while ((attr = info->unAuthAttr[iv]) != NULL) {
+ sprintf(mm, "%sattribute[%d].", m, iv++);
+ sv_PrintAttribute(out, attr, mm);
+ }
+ }
+}
+
+void
+sv_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m)
+{
+ fprintf(out, m);
+ sv_PrintInteger(out, &pk->u.rsa.modulus, "modulus=");
+ fprintf(out, m);
+ sv_PrintInteger(out, &pk->u.rsa.publicExponent, "exponent=");
+}
+
+void
+sv_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m)
+{
+ fprintf(out, m);
+ sv_PrintInteger(out, &pk->u.dsa.params.prime, "prime=");
+ fprintf(out, m);
+ sv_PrintInteger(out, &pk->u.dsa.params.subPrime, "subprime=");
+ fprintf(out, m);
+ sv_PrintInteger(out, &pk->u.dsa.params.base, "base=");
+ fprintf(out, m);
+ sv_PrintInteger(out, &pk->u.dsa.publicValue, "publicValue=");
+}
+
+int
+sv_PrintSubjectPublicKeyInfo(FILE *out, PRArenaPool *arena,
+ CERTSubjectPublicKeyInfo *i, char *msg)
+{
+ SECKEYPublicKey *pk;
+ int rv;
+ char mm[200];
+
+ sprintf(mm, "%s.publicKeyAlgorithm=", msg);
+ sv_PrintAlgorithmID(out, &i->algorithm, mm);
+
+ pk = (SECKEYPublicKey*) PORT_ZAlloc(sizeof(SECKEYPublicKey));
+ if (!pk) return PORT_GetError();
+
+ DER_ConvertBitString(&i->subjectPublicKey);
+ switch(SECOID_FindOIDTag(&i->algorithm.algorithm)) {
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ rv = SEC_ASN1DecodeItem(arena, pk, SECKEY_RSAPublicKeyTemplate,
+ &i->subjectPublicKey);
+ if (rv) return rv;
+ sprintf(mm, "%s.rsaPublicKey.", msg);
+ sv_PrintRSAPublicKey(out, pk, mm);
+ break;
+ case SEC_OID_ANSIX9_DSA_SIGNATURE:
+ rv = SEC_ASN1DecodeItem(arena, pk, SECKEY_DSAPublicKeyTemplate,
+ &i->subjectPublicKey);
+ if (rv) return rv;
+ sprintf(mm, "%s.dsaPublicKey.", msg);
+ sv_PrintDSAPublicKey(out, pk, mm);
+ break;
+ default:
+ fprintf(out, "%s=bad SPKI algorithm type\n", msg);
+ return 0;
+ }
+
+ return 0;
+}
+
+SECStatus
+sv_PrintInvalidDateExten (FILE *out, SECItem *value, char *msg)
+{
+ SECItem decodedValue;
+ SECStatus rv;
+ int64 invalidTime;
+ char *formattedTime = NULL;
+
+ decodedValue.data = NULL;
+ rv = SEC_ASN1DecodeItem (NULL, &decodedValue, SEC_GeneralizedTimeTemplate,
+ value);
+ if (rv == SECSuccess) {
+ rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
+ if (rv == SECSuccess) {
+ formattedTime = CERT_GenTime2FormattedAscii(invalidTime, "%a %b %d %H:%M:%S %Y");
+ fprintf (out, "%s: %s\n", msg, formattedTime);
+ PORT_Free (formattedTime);
+ }
+ }
+ PORT_Free (decodedValue.data);
+
+ return (rv);
+}
+
+int
+sv_PrintExtensions(FILE *out, CERTCertExtension **extensions, char *msg)
+{
+ SECOidTag oidTag;
+
+ if (extensions) {
+
+ while ( *extensions ) {
+ SECItem *tmpitem;
+
+ fprintf(out, "%sname=", msg);
+
+ tmpitem = &(*extensions)->id;
+ sv_PrintObjectID(out, tmpitem, NULL);
+
+ tmpitem = &(*extensions)->critical;
+ if ( tmpitem->len )
+ fprintf(out, "%scritical=%s\n", msg,
+ (tmpitem->data && tmpitem->data[0])? "True": "False");
+
+ oidTag = SECOID_FindOIDTag (&((*extensions)->id));
+
+ fprintf(out, msg);
+ tmpitem = &((*extensions)->value);
+ if (oidTag == SEC_OID_X509_INVALID_DATE)
+ sv_PrintInvalidDateExten (out, tmpitem,"invalidExt");
+ else
+ sv_PrintAsHex(out,tmpitem, "data=");
+
+ /*fprintf(out, "\n");*/
+ extensions++;
+ }
+ }
+
+ return 0;
+}
+
+/* callers of this function must make sure that the CERTSignedCrl
+ from which they are extracting the CERTCrl has been fully-decoded.
+ Otherwise it will not have the entries even though the CRL may have
+ some */
+void
+sv_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m)
+{
+ CERTCrlEntry *entry;
+ int iv;
+ char om[100];
+
+ fprintf(out, m);
+ sv_PrintAlgorithmID(out, &(crl->signatureAlg), "signatureAlgorithm=");
+ fprintf(out, m);
+ sv_PrintName(out, &(crl->name), "name=");
+ fprintf(out, m);
+ sv_PrintUTCTime(out, &(crl->lastUpdate), "lastUpdate=");
+ fprintf(out, m);
+ sv_PrintUTCTime(out, &(crl->nextUpdate), "nextUpdate=");
+
+ if (crl->entries != NULL) {
+ iv = 0;
+ while ((entry = crl->entries[iv]) != NULL) {
+ fprintf(out, "%sentry[%d].", m, iv);
+ sv_PrintInteger(out, &(entry->serialNumber), "serialNumber=");
+ fprintf(out, "%sentry[%d].", m, iv);
+ sv_PrintUTCTime(out, &(entry->revocationDate), "revocationDate=");
+ sprintf(om, "%sentry[%d].signedCRLEntriesExtensions.", m, iv++);
+ sv_PrintExtensions(out, entry->extensions, om);
+ }
+ }
+ sprintf(om, "%ssignedCRLEntriesExtensions.", m);
+ sv_PrintExtensions(out, crl->extensions, om);
+}
+
+
+int
+sv_PrintCertificate(FILE *out, SECItem *der, char *m, int level)
+{
+ PRArenaPool *arena = NULL;
+ CERTCertificate *c;
+ int rv;
+ int iv;
+ char mm[200];
+
+ /* Decode certificate */
+ c = (CERTCertificate*) PORT_ZAlloc(sizeof(CERTCertificate));
+ if (!c) return PORT_GetError();
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) return SEC_ERROR_NO_MEMORY;
+
+ rv = SEC_ASN1DecodeItem(arena, c, CERT_CertificateTemplate, der);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+
+ /* Pretty print it out */
+ iv = DER_GetInteger(&c->version);
+ fprintf(out, "%sversion=%d (0x%x)\n", m, iv + 1, iv);
+ sprintf(mm, "%sserialNumber=", m);
+ sv_PrintInteger(out, &c->serialNumber, mm);
+ sprintf(mm, "%ssignatureAlgorithm=", m);
+ sv_PrintAlgorithmID(out, &c->signature, mm);
+ sprintf(mm, "%sissuerName=", m);
+ sv_PrintName(out, &c->issuer, mm);
+ sprintf(mm, "%svalidity.", m);
+ sv_PrintValidity(out, &c->validity, mm);
+ sprintf(mm, "%ssubject=", m);
+ sv_PrintName(out, &c->subject, mm);
+ sprintf(mm, "%ssubjectPublicKeyInfo", m);
+ rv = sv_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo, mm);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+ sprintf(mm, "%ssignedExtensions.", m);
+ sv_PrintExtensions(out, c->extensions, mm);
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return 0;
+}
+
+int
+sv_PrintSignedData(FILE *out, SECItem *der, char *m, SECU_PPFunc inner)
+{
+ PRArenaPool *arena = NULL;
+ CERTSignedData *sd;
+ int rv;
+
+ /* Strip off the signature */
+ sd = (CERTSignedData*) PORT_ZAlloc(sizeof(CERTSignedData));
+ if (!sd) return PORT_GetError();
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) return SEC_ERROR_NO_MEMORY;
+
+ rv = SEC_ASN1DecodeItem(arena, sd, CERT_SignedDataTemplate, der);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+
+/* fprintf(out, "%s:\n", m); */
+ PORT_Strcat(m, "data.");
+
+ rv = (*inner)(out, &sd->data, m, 0);
+ if (rv) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+ }
+
+ m[PORT_Strlen(m) - 5] = 0;
+ fprintf(out, m);
+ sv_PrintAlgorithmID(out, &sd->signatureAlgorithm, "signatureAlgorithm=");
+ DER_ConvertBitString(&sd->signature);
+ fprintf(out, m);
+ sv_PrintAsHex(out, &sd->signature, "signature=");
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return 0;
+
+}
+
+
+/*
+** secu_PrintPKCS7Signed
+** Pretty print a PKCS7 signed data type (up to version 1).
+*/
+int
+sv_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src)
+{
+ SECAlgorithmID *digAlg; /* digest algorithms */
+ SECItem *aCert; /* certificate */
+ CERTSignedCrl *aCrl; /* certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* signer information */
+ int rv, iv;
+ char om[120];
+
+ sv_PrintInteger(out, &(src->version), "pkcs7.version=");
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ iv = 0;
+ while (src->digestAlgorithms[iv] != NULL)
+ iv++;
+ fprintf(out, "pkcs7.digestAlgorithmListLength=%d\n", iv);
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv]) != NULL) {
+ sprintf(om, "pkcs7.digestAlgorithm[%d]=", iv++);
+ sv_PrintAlgorithmID(out, digAlg, om);
+ }
+ }
+
+ /* Now for the content */
+ rv = sv_PrintPKCS7ContentInfo(out, &(src->contentInfo),
+ "pkcs7.contentInformation=");
+ if (rv != 0) return rv;
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ iv = 0;
+ while (src->rawCerts[iv] != NULL)
+ iv++;
+ fprintf(out, "pkcs7.certificateListLength=%d\n", iv);
+
+ iv = 0;
+ while ((aCert = src->rawCerts[iv]) != NULL) {
+ sprintf(om, "certificate[%d].", iv++);
+ rv = sv_PrintSignedData(out, aCert, om, sv_PrintCertificate);
+ if (rv) return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ iv = 0;
+ while (src->crls[iv] != NULL) iv++;
+ fprintf(out, "pkcs7.signedRevocationLists=%d\n", iv);
+ iv = 0;
+ while ((aCrl = src->crls[iv]) != NULL) {
+ sprintf(om, "signedRevocationList[%d].", iv);
+ fprintf(out, om);
+ sv_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "signatureAlgorithm=");
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ fprintf(out, om);
+ sv_PrintAsHex(out, &aCrl->signatureWrap.signature, "signature=");
+ sprintf(om, "certificateRevocationList[%d].", iv);
+ sv_PrintCRLInfo(out, &aCrl->crl, om);
+ iv++;
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ iv = 0;
+ while (src->signerInfos[iv] != NULL)
+ iv++;
+ fprintf(out, "pkcs7.signerInformationListLength=%d\n", iv);
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv]) != NULL) {
+ sprintf(om, "signerInformation[%d].", iv++);
+ sv_PrintSignerInfo(out, sigInfo, om);
+ }
+ }
+
+ return 0;
+}
+
+#if 0
+/*
+** secu_PrintPKCS7Enveloped
+** Pretty print a PKCS7 enveloped data type (up to version 1).
+*/
+void
+secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
+ char *m, int level)
+{
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
+ int iv;
+ char om[100];
+
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ secu_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ sprintf(om, "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7SignedEnveloped
+** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
+*/
+int
+secu_PrintPKCS7SignedAndEnveloped(FILE *out,
+ SEC_PKCS7SignedAndEnvelopedData *src,
+ char *m, int level)
+{
+ SECAlgorithmID *digAlg; /* pointer for digest algorithms */
+ SECItem *aCert; /* pointer for certificate */
+ CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
+ int rv, iv;
+ char om[100];
+
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ secu_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ sprintf(om, "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ secu_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
+ sprintf(om, "Digest Algorithm (%x)", iv);
+ sv_PrintAlgorithmID(out, digAlg, om);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ secu_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
+ iv = 0;
+ while ((aCert = src->rawCerts[iv++]) != NULL) {
+ sprintf(om, "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ SECU_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ secu_Indent(out, level + 1);
+ fprintf(out, "Signed Revocation Lists:\n");
+ iv = 0;
+ while ((aCrl = src->crls[iv++]) != NULL) {
+ sprintf(om, "Signed Revocation List (%x)", iv);
+ secu_Indent(out, level + 2); fprintf(out, "%s:\n", om);
+ sv_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "Signature Algorithm");
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ sv_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
+ level+3);
+ SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
+ level + 3);
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ secu_Indent(out, level + 1);
+ fprintf(out, "Signer Information List:\n");
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv++]) != NULL) {
+ sprintf(om, "Signer Information (%x)", iv);
+ secu_PrintSignerInfo(out, sigInfo, om, level + 2);
+ }
+ }
+
+ return 0;
+}
+
+PR_IMPLEMENT(int)
+SECU_PrintCrl (FILE *out, SECItem *der, char *m, int level)
+{
+ PRArenaPool *arena = NULL;
+ CERTCrl *c = NULL;
+ int rv;
+
+ do {
+ /* Decode CRL */
+ c = (CERTCrl*) PORT_ZAlloc(sizeof(CERTCrl));
+ if (!c) {
+ rv = PORT_GetError();
+ break;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ rv = SEC_ERROR_NO_MEMORY;
+ break;
+ }
+
+ rv = SEC_ASN1DecodeItem(arena, c, CERT_CrlTemplate, der);
+ if (rv != SECSuccess)
+ break;
+ SECU_PrintCRLInfo (out, c, m, level);
+ } while (0);
+ PORT_FreeArena (arena, PR_FALSE);
+ PORT_Free (c);
+ return (rv);
+}
+
+/*
+** secu_PrintPKCS7Encrypted
+** Pretty print a PKCS7 encrypted data type (up to version 1).
+*/
+void
+secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
+ char *m, int level)
+{
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Digested
+** Pretty print a PKCS7 digested data type (up to version 1).
+*/
+void
+sv_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src)
+{
+ secu_Indent(out, level); fprintf(out, "%s:\n", m);
+ sv_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ sv_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm");
+ sv_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
+ level + 1);
+ sv_PrintAsHex(out, &src->digest, "Digest", level + 1);
+}
+
+#endif
+
+/*
+** secu_PrintPKCS7ContentInfo
+** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
+** appropriate function
+*/
+int
+sv_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src, char *m)
+{
+ const char *desc;
+ SECOidTag kind;
+ int rv;
+
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ if (src->contentTypeTag == NULL) {
+ desc = "Unknown";
+ kind = SEC_OID_PKCS7_DATA;
+ } else {
+ desc = src->contentTypeTag->desc;
+ kind = src->contentTypeTag->offset;
+ }
+
+ fprintf(out, "%s%s\n", m, desc);
+
+ if (src->content.data == NULL) {
+ fprintf(out, "pkcs7.data=<no content>\n");
+ return 0;
+ }
+
+ rv = 0;
+ switch (kind) {
+ case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
+ rv = sv_PrintPKCS7Signed(out, src->content.signedData);
+ break;
+
+ case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
+ fprintf(out, "pkcs7EnvelopedData=<unsupported>\n");
+ /*sv_PrintPKCS7Enveloped(out, src->content.envelopedData);*/
+ break;
+
+ case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
+ fprintf(out, "pkcs7SignedEnvelopedData=<unsupported>\n");
+ /*rv = sv_PrintPKCS7SignedAndEnveloped(out,
+ src->content.signedAndEnvelopedData);*/
+ break;
+
+ case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
+ fprintf(out, "pkcs7DigestedData=<unsupported>\n");
+ /*sv_PrintPKCS7Digested(out, src->content.digestedData);*/
+ break;
+
+ case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
+ fprintf(out, "pkcs7EncryptedData=<unsupported>\n");
+ /*sv_PrintPKCS7Encrypted(out, src->content.encryptedData);*/
+ break;
+
+ default:
+ fprintf(out, "pkcs7UnknownData=<unsupported>\n");
+ /*sv_PrintAsHex(out, src->content.data);*/
+ break;
+ }
+
+ return rv;
+}
+
+
+int
+SV_PrintPKCS7ContentInfo(FILE *out, SECItem *der)
+{
+ SEC_PKCS7ContentInfo *cinfo;
+ int rv = -1;
+
+ cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ if (cinfo != NULL) {
+ rv = sv_PrintPKCS7ContentInfo(out, cinfo, "pkcs7.contentInfo=");
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ }
+
+ return rv;
+}
+/*
+** End of PKCS7 functions
+*/
diff --git a/security/nss/cmd/signver/signver.c b/security/nss/cmd/signver/signver.c
new file mode 100644
index 000000000..ca56bc862
--- /dev/null
+++ b/security/nss/cmd/signver/signver.c
@@ -0,0 +1,455 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "secutil.h"
+#include "secmod.h"
+#include "cert.h"
+#include "secoid.h"
+#include "nss.h"
+
+/* NSPR 2.0 header files */
+#include "prinit.h"
+#include "prprf.h"
+#include "prsystem.h"
+#include "prmem.h"
+/* Portable layer header files */
+#include "plstr.h"
+#include "sechash.h" /* for HASH_GetHashObject() */
+
+static int debugInfo = 0;
+
+static char *usageInfo[] = {
+ "Options:",
+ " -a signature file is ASCII",
+ " -d certdir directory containing cert database",
+ " -i dataFileName input file name containing data,",
+ " leave filename blank to use stdin",
+ " -s signatureFileName input file name containing signature,",
+ " leave filename blank to use stdin",
+ " -o outputFileName output file name, default stdout",
+ " -A display all information from pkcs #7",
+ " -C display all information from all certs",
+ " -C -n display number of certificates",
+ " -C -n certNum display all information from the certNum",
+ " certificate in pkcs #7 signed object",
+ " -C -n certNum f1 ... fN display information about specified",
+ " fields from the certNum certificate in",
+ " the pkcs #7 signed object",
+ " -S display signer information list",
+ " -S -n display number of signer information blocks",
+ " -S -n signerNum display all information from the signerNum",
+ " signer information block in pkcs #7",
+ " -S -n signerNum f1 ... fN display information about specified",
+ " fields from the signerNum signer",
+ " information block in pkcs #7 object",
+ " -V verify the signed object and display result",
+ " -V -v verify the signed object and display",
+ " result and reason for failure",
+ "Version 2.0"
+};
+static int nUsageInfo = sizeof(usageInfo)/sizeof(char *);
+
+extern int SV_PrintPKCS7ContentInfo(FILE *, SECItem *);
+
+static void Usage(char *progName, FILE *outFile)
+{
+ int i;
+ fprintf(outFile, "Usage: %s options\n", progName);
+ for (i = 0; i < nUsageInfo; i++)
+ fprintf(outFile, "%s\n", usageInfo[i]);
+ exit(-1);
+}
+
+static HASH_HashType
+AlgorithmToHashType(SECAlgorithmID *digestAlgorithms)
+{
+ SECOidTag tag;
+
+ tag = SECOID_GetAlgorithmTag(digestAlgorithms);
+
+ switch (tag) {
+ case SEC_OID_MD2:
+ if (debugInfo) PR_fprintf(PR_STDERR, "Hash algorithm: HASH_AlgMD2 SEC_OID_MD2\n");
+ return HASH_AlgMD2;
+ case SEC_OID_MD5:
+ if (debugInfo) PR_fprintf(PR_STDERR, "Hash algorithm: HASH_AlgMD5 SEC_OID_MD5\n");
+ return HASH_AlgMD5;
+ case SEC_OID_SHA1:
+ if (debugInfo) PR_fprintf(PR_STDERR, "Hash algorithm: HASH_AlgSHA1 SEC_OID_SHA1\n");
+ return HASH_AlgSHA1;
+ default:
+ if (debugInfo) PR_fprintf(PR_STDERR, "should never get here\n");
+ return HASH_AlgNULL;
+ }
+}
+
+
+static int
+DigestData (unsigned char *digest, unsigned char *data,
+ unsigned int *len, unsigned int maxLen,
+ HASH_HashType hashType)
+{
+ const SECHashObject *hashObj;
+ void *hashcx;
+
+ hashObj = HASH_GetHashObject(hashType);
+ hashcx = (* hashObj->create)();
+ if (hashcx == NULL)
+ return -1;
+
+ (* hashObj->begin)(hashcx);
+ (* hashObj->update)(hashcx, data, PORT_Strlen((char *)data));
+ (* hashObj->end)(hashcx, digest, len, maxLen);
+ (* hashObj->destroy)(hashcx, PR_TRUE);
+
+ return 0;
+}
+
+enum {
+ cmd_DisplayAllPCKS7Info = 0,
+ cmd_DisplayCertInfo,
+ cmd_DisplaySignerInfo,
+ cmd_VerifySignedObj
+};
+
+enum {
+ opt_ASCII,
+ opt_CertDir,
+ opt_InputDataFile,
+ opt_ItemNumber,
+ opt_OutputFile,
+ opt_InputSigFile,
+ opt_TypeTag,
+ opt_PrintWhyFailure
+};
+
+static secuCommandFlag signver_commands[] =
+{
+ { /* cmd_DisplayAllPCKS7Info*/ 'A', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_DisplayCertInfo */ 'C', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_DisplaySignerInfo */ 'S', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_VerifySignedObj */ 'V', PR_FALSE, 0, PR_FALSE }
+};
+
+static secuCommandFlag signver_options[] =
+{
+ { /* opt_ASCII */ 'a', PR_FALSE, 0, PR_FALSE },
+ { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_InputDataFile */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_ItemNumber */ 'n', PR_FALSE, 0, PR_FALSE },
+ { /* opt_OutputFile */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_InputSigFile */ 's', PR_TRUE, 0, PR_FALSE },
+ { /* opt_TypeTag */ 't', PR_TRUE, 0, PR_FALSE },
+ { /* opt_PrintWhyFailure */ 'v', PR_FALSE, 0, PR_FALSE }
+};
+
+int main(int argc, char **argv)
+{
+ PRExplodedTime explodedCurrent;
+ SECItem der, data;
+ char *progName;
+ int rv;
+ PRFileDesc *dataFile = 0;
+ PRFileDesc *signFile = 0;
+ FILE *outFile = stdout;
+ char *typeTag = 0;
+ PRBool displayAllCerts = PR_FALSE;
+ PRBool displayAllSigners = PR_FALSE;
+ PRFileInfo info;
+ PRInt32 nb;
+ SECStatus secstatus;
+
+ secuCommand signver;
+ signver.numCommands = sizeof(signver_commands) /sizeof(secuCommandFlag);
+ signver.numOptions = sizeof(signver_options) / sizeof(secuCommandFlag);
+ signver.commands = signver_commands;
+ signver.options = signver_options;
+
+#ifdef XP_PC
+ progName = strrchr(argv[0], '\\');
+#else
+ progName = strrchr(argv[0], '/');
+#endif
+ progName = progName ? progName+1 : argv[0];
+
+ /*_asm int 3*/
+
+ PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &explodedCurrent);
+#if 0
+ if (explodedCurrent.tm_year >= 1998
+ && explodedCurrent.tm_month >= 5 /* months past tm_year (0-11, Jan = 0) */
+ && explodedCurrent.tm_mday >= 1) {
+ PR_fprintf(PR_STDERR, "%s: expired\n", progName);
+ return -1;
+ }
+#endif
+
+ SECU_ParseCommandLine(argc, argv, progName, &signver);
+
+ /* Set the certdb directory (default is ~/.{browser}) */
+ SECU_ConfigDirectory(signver.options[opt_CertDir].arg);
+
+ /* Set the certificate type. */
+ typeTag = SECU_GetOptionArg(&signver, opt_TypeTag);
+
+ /* -i and -s without filenames */
+ if (signver.options[opt_InputDataFile].activated &&
+ signver.options[opt_InputSigFile].activated &&
+ !signver.options[opt_InputDataFile].arg &&
+ !signver.options[opt_InputSigFile].arg)
+ PR_fprintf(PR_STDERR,
+ "%s: Only data or signature file can use stdin (not both).\n",
+ progName);
+
+ /* Open the input data file (no arg == use stdin). */
+ if (signver.options[opt_InputDataFile].activated) {
+ if (signver.options[opt_InputDataFile].arg)
+ dataFile = PR_Open(signver.options[opt_InputDataFile].arg,
+ PR_RDONLY, 0);
+ else
+ dataFile = PR_STDIN;
+ if (!dataFile) {
+ PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading.\n",
+ progName, signver.options[opt_InputDataFile].arg);
+ return -1;
+ }
+ }
+
+ /* Open the input signature file (no arg == use stdin). */
+ if (signver.options[opt_InputSigFile].activated) {
+ if (signver.options[opt_InputSigFile].arg)
+ signFile = PR_Open(signver.options[opt_InputSigFile].arg,
+ PR_RDONLY, 0);
+ else
+ signFile = PR_STDIN;
+ if (!signFile) {
+ PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading.\n",
+ progName, signver.options[opt_InputSigFile].arg);
+ return -1;
+ }
+ }
+
+#if 0
+ if (!typeTag) ascii = 1;
+#endif
+
+ /* Open|Create the output file. */
+ if (signver.options[opt_OutputFile].activated) {
+ outFile = fopen(signver.options[opt_OutputFile].arg, "w");
+ /*
+ outFile = PR_Open(signver.options[opt_OutputFile].arg,
+ PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 00660);
+ */
+ if (!outFile) {
+ PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for writing.\n",
+ progName, signver.options[opt_OutputFile].arg);
+ return -1;
+ }
+ }
+
+ if (signver.commands[cmd_DisplayCertInfo].activated &&
+ !signver.options[opt_ItemNumber].arg)
+ displayAllCerts = PR_TRUE;
+
+ if (signver.commands[cmd_DisplaySignerInfo].activated &&
+ !signver.options[opt_ItemNumber].arg)
+ displayAllSigners = PR_TRUE;
+
+#if 0
+ case 'W':
+ debugInfo = 1;
+ break;
+#endif
+
+ if (!signFile && !dataFile && !typeTag)
+ Usage(progName, outFile);
+
+ if (!signFile && !dataFile &&
+ signver.commands[cmd_VerifySignedObj].activated) {
+ PR_fprintf(PR_STDERR,
+ "%s: unable to read all data from standard input\n",
+ progName);
+ return -1;
+ }
+
+ PR_SetError(0, 0); /* PR_Init("pp", 1, 1, 0);*/
+ secstatus = NSS_Init(SECU_ConfigDirectory(NULL));
+ if (secstatus != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+
+ rv = SECU_ReadDERFromFile(&der, signFile,
+ signver.options[opt_ASCII].activated);
+
+ /* Data is untyped, using the specified type */
+ data.data = der.data;
+ data.len = der.len;
+
+
+ /* Signature Verification */
+ if (!signver.options[opt_TypeTag].activated) {
+ if (signver.commands[cmd_VerifySignedObj].activated) {
+ SEC_PKCS7ContentInfo *cinfo;
+
+ cinfo = SEC_PKCS7DecodeItem(&data, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ if (cinfo != NULL) {
+#if 0
+ if (debugInfo) {
+ PR_fprintf(PR_STDERR, "Content %s encrypted.\n",
+ SEC_PKCS7ContentIsEncrypted(cinfo) ? "was" : "was not");
+
+ PR_fprintf(PR_STDERR, "Content %s signed.\n",
+ SEC_PKCS7ContentIsSigned(cinfo) ? "was" : "was not");
+ }
+#endif
+
+ if (SEC_PKCS7ContentIsSigned(cinfo)) {
+ SEC_PKCS7SignedData *signedData;
+ HASH_HashType digestType;
+ SECItem digest, data;
+ unsigned char *dataToVerify, digestBuffer[32];
+
+ signedData = cinfo->content.signedData;
+
+ /* assume that there is only one digest algorithm for now */
+ digestType =
+ AlgorithmToHashType(signedData->digestAlgorithms[0]);
+ if (digestType == HASH_AlgNULL) {
+ PR_fprintf(PR_STDERR, "Invalid hash algorithmID\n");
+ return (-1);
+ }
+ rv = SECU_FileToItem(&data, dataFile);
+ dataToVerify = data.data;
+ if (dataToVerify) {
+ /*certUsageObjectSigner;*/
+ SECCertUsage usage = certUsageEmailSigner;
+
+
+#if 0
+ if (debugInfo)
+ PR_fprintf(PR_STDERR, "dataToVerify=%s\n",
+ dataToVerify);
+#endif
+ digest.data = digestBuffer;
+ if (DigestData (digest.data, dataToVerify,
+ &digest.len, 32, digestType)) {
+ PR_fprintf(PR_STDERR, "Fail to compute message digest for verification. Reason: %s\n",
+ SECU_ErrorString((int16)PORT_GetError()));
+ return (-1);
+ }
+#if 0
+ if (debugInfo) {
+ PR_fprintf(PR_STDERR, "Data Digest=:");
+ for (i = 0; i < digest.len; i++)
+ PR_fprintf(PR_STDERR, "%02x:", digest.data[i]);
+ PR_fprintf(PR_STDERR, "\n");
+ }
+#endif
+
+
+ if (signver.commands[cmd_VerifySignedObj].activated)
+ fprintf(outFile, "signatureValid=");
+ PORT_SetError(0);
+ if (SEC_PKCS7VerifyDetachedSignature (cinfo, usage,
+ &digest, digestType, PR_FALSE)) {
+ if (signver.commands[cmd_VerifySignedObj].activated)
+ fprintf(outFile, "yes");
+ } else {
+ if (signver.commands[cmd_VerifySignedObj].activated){
+ fprintf(outFile, "no");
+ if (signver.options[opt_PrintWhyFailure].activated)
+ fprintf(outFile, ":%s", SECU_ErrorString((int16)PORT_GetError()));
+ }
+ }
+ if (signver.commands[cmd_VerifySignedObj].activated)
+ fprintf(outFile, "\n");
+
+ SECITEM_FreeItem(&data, PR_FALSE);
+ } else {
+ PR_fprintf(PR_STDERR, "Cannot read data\n");
+ return (-1);
+ }
+ }
+
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ } else
+ PR_fprintf(PR_STDERR, "Unable to decode PKCS7 data\n");
+ }
+
+ if (signver.commands[cmd_DisplayAllPCKS7Info].activated)
+ SV_PrintPKCS7ContentInfo(outFile, &data);
+
+ if (displayAllCerts)
+ PR_fprintf(PR_STDERR, "-C option is not implemented in this version\n");
+
+ if (displayAllSigners)
+ PR_fprintf(PR_STDERR, "-S option is not implemented in this version\n");
+
+ /* Pretty print it */
+ } else if (PL_strcmp(typeTag, SEC_CT_CERTIFICATE) == 0) {
+ rv = SECU_PrintSignedData(outFile, &data, "Certificate", 0,
+ SECU_PrintCertificate);
+ } else if (PL_strcmp(typeTag, SEC_CT_CERTIFICATE_REQUEST) == 0) {
+ rv = SECU_PrintSignedData(outFile, &data, "Certificate Request", 0,
+ SECU_PrintCertificateRequest);
+ } else if (PL_strcmp (typeTag, SEC_CT_CRL) == 0) {
+ rv = SECU_PrintSignedData (outFile, &data, "CRL", 0, SECU_PrintCrl);
+#ifdef HAVE_EPK_TEMPLATE
+ } else if (PL_strcmp(typeTag, SEC_CT_PRIVATE_KEY) == 0) {
+ rv = SECU_PrintPrivateKey(outFile, &data, "Private Key", 0);
+#endif
+ } else if (PL_strcmp(typeTag, SEC_CT_PUBLIC_KEY) == 0) {
+ rv = SECU_PrintPublicKey(outFile, &data, "Public Key", 0);
+ } else if (PL_strcmp(typeTag, SEC_CT_PKCS7) == 0) {
+ rv = SECU_PrintPKCS7ContentInfo(outFile, &data,
+ "PKCS #7 Content Info", 0);
+ } else {
+ PR_fprintf(PR_STDERR, "%s: don't know how to print out '%s' files\n",
+ progName, typeTag);
+ return -1;
+ }
+
+ if (rv) {
+ PR_fprintf(PR_STDERR, "%s: problem converting data (%s)\n",
+ progName, SECU_ErrorString((int16)PORT_GetError()));
+ return -1;
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/security/nss/cmd/smimetools/Makefile b/security/nss/cmd/smimetools/Makefile
new file mode 100644
index 000000000..9e3263d43
--- /dev/null
+++ b/security/nss/cmd/smimetools/Makefile
@@ -0,0 +1,73 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include rules.mk
+
+include ../platrules.mk
diff --git a/security/nss/cmd/smimetools/cmsutil.c b/security/nss/cmd/smimetools/cmsutil.c
new file mode 100644
index 000000000..3af802431
--- /dev/null
+++ b/security/nss/cmd/smimetools/cmsutil.c
@@ -0,0 +1,1450 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * cmsutil -- A command to work with CMS data
+ *
+ * $Id$
+ */
+
+#include "nspr.h"
+#include "secutil.h"
+#include "plgetopt.h"
+#include "secpkcs7.h"
+#include "cert.h"
+#include "certdb.h"
+#include "secoid.h"
+#include "cms.h"
+#include "nss.h"
+#include "smime.h"
+#include "pk11func.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#if defined(_WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+extern void SEC_Init(void); /* XXX */
+char *progName = NULL;
+static int cms_verbose = 0;
+
+/* XXX stolen from cmsarray.c
+ * nss_CMSArray_Count - count number of elements in array
+ */
+int
+nss_CMSArray_Count(void **array)
+{
+ int n = 0;
+ if (array == NULL)
+ return 0;
+ while (*array++ != NULL)
+ n++;
+ return n;
+}
+
+static SECStatus
+DigestFile(PLArenaPool *poolp, SECItem ***digests, SECItem *input,
+ SECAlgorithmID **algids)
+{
+ NSSCMSDigestContext *digcx;
+
+ digcx = NSS_CMSDigestContext_StartMultiple(algids);
+ if (digcx == NULL)
+ return SECFailure;
+
+ NSS_CMSDigestContext_Update(digcx, input->data, input->len);
+
+ return NSS_CMSDigestContext_FinishMultiple(digcx, poolp, digests);
+}
+
+
+static void
+Usage(char *progName)
+{
+ fprintf(stderr,
+"Usage: %s [-D|-S|-E] [<options>] [-d dbdir] [-u certusage]\n",
+ progName);
+ fprintf(stderr,
+" -D decode a CMS message\n"
+" -c content use this detached content\n"
+" -n suppress output of content\n"
+" -h num generate email headers with info about CMS message\n"
+" -S create a CMS signed message\n"
+" -G include a signing time attribute\n"
+" -H hash use hash (default:SHA1)\n"
+" -N nick use certificate named \"nick\" for signing\n"
+" -P include a SMIMECapabilities attribute\n"
+" -T do not include content in CMS message\n"
+" -Y nick include a EncryptionKeyPreference attribute with cert\n"
+" (use \"NONE\" to omit)\n"
+" -E create a CMS enveloped message (NYI)\n"
+" -r id,... create envelope for these recipients,\n"
+" where id can be a certificate nickname or email address\n"
+" -d dbdir key/cert database directory (default: ~/.netscape)\n"
+" -i infile use infile as source of data (default: stdin)\n"
+" -o outfile use outfile as destination of data (default: stdout)\n"
+" -p password use password as key db password (default: prompt)\n"
+" -u certusage set type of certificate usage (default: certUsageEmailSigner)\n"
+" -v print debugging information\n"
+"\nCert usage codes:\n");
+ fprintf(stderr, "%-25s 0 - certUsageSSLClient\n", " ");
+ fprintf(stderr, "%-25s 1 - certUsageSSLServer\n", " ");
+ fprintf(stderr, "%-25s 2 - certUsageSSLServerWithStepUp\n", " ");
+ fprintf(stderr, "%-25s 3 - certUsageSSLCA\n", " ");
+ fprintf(stderr, "%-25s 4 - certUsageEmailSigner\n", " ");
+ fprintf(stderr, "%-25s 5 - certUsageEmailRecipient\n", " ");
+ fprintf(stderr, "%-25s 6 - certUsageObjectSigner\n", " ");
+ fprintf(stderr, "%-25s 7 - certUsageUserCertImport\n", " ");
+ fprintf(stderr, "%-25s 8 - certUsageVerifyCA\n", " ");
+ fprintf(stderr, "%-25s 9 - certUsageProtectedObjectSigner\n", " ");
+ fprintf(stderr, "%-25s 10 - certUsageStatusResponder\n", " ");
+ fprintf(stderr, "%-25s 11 - certUsageAnyCA\n", " ");
+
+ exit(-1);
+}
+
+struct optionsStr {
+ char *password;
+ SECCertUsage certUsage;
+ CERTCertDBHandle *certHandle;
+};
+
+struct decodeOptionsStr {
+ struct optionsStr *options;
+ PRFileDesc *contentFile;
+ int headerLevel;
+ PRBool suppressContent;
+ NSSCMSGetDecryptKeyCallback dkcb;
+ PK11SymKey *bulkkey;
+};
+
+struct signOptionsStr {
+ struct optionsStr *options;
+ char *nickname;
+ char *encryptionKeyPreferenceNick;
+ PRBool signingTime;
+ PRBool smimeProfile;
+ PRBool detached;
+ SECOidTag hashAlgTag;
+};
+
+struct envelopeOptionsStr {
+ struct optionsStr *options;
+ char **recipients;
+};
+
+struct certsonlyOptionsStr {
+ struct optionsStr *options;
+ char **recipients;
+};
+
+struct encryptOptionsStr {
+ struct optionsStr *options;
+ char **recipients;
+ NSSCMSMessage *envmsg;
+ SECItem *input;
+ FILE *outfile;
+ PRFileDesc *envFile;
+ PK11SymKey *bulkkey;
+ SECOidTag bulkalgtag;
+ int keysize;
+};
+
+static NSSCMSMessage *
+decode(FILE *out, SECItem *output, SECItem *input,
+ const struct decodeOptionsStr *decodeOptions)
+{
+ NSSCMSDecoderContext *dcx;
+ NSSCMSMessage *cmsg;
+ NSSCMSContentInfo *cinfo;
+ NSSCMSSignedData *sigd = NULL;
+ NSSCMSEnvelopedData *envd;
+ NSSCMSEncryptedData *encd;
+ SECAlgorithmID **digestalgs;
+ int nlevels, i, nsigners, j;
+ char *signercn;
+ NSSCMSSignerInfo *si;
+ SECOidTag typetag;
+ SECItem **digests;
+ PLArenaPool *poolp;
+ PK11PasswordFunc pwcb;
+ void *pwcb_arg;
+ SECItem *item, sitem = { 0, 0, 0 };
+ secuPWData pwdata = { PW_NONE, 0 };
+
+ if (decodeOptions->options->password)
+ {
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = decodeOptions->options->password;
+ }
+ pwcb = SECU_GetModulePassword;
+ pwcb_arg = (void *)&pwdata;
+
+ if (decodeOptions->contentFile) {
+ /* detached content: grab content file */
+ SECU_FileToItem(&sitem, decodeOptions->contentFile);
+ }
+
+ dcx = NSS_CMSDecoder_Start(NULL,
+ NULL, NULL, /* content callback */
+ pwcb, pwcb_arg, /* password callback */
+ decodeOptions->dkcb, /* decrypt key callback */
+ decodeOptions->bulkkey);
+ (void)NSS_CMSDecoder_Update(dcx, (char *)input->data, input->len);
+ cmsg = NSS_CMSDecoder_Finish(dcx);
+ if (cmsg == NULL) {
+ fprintf(stderr, "%s: failed to decode message.\n", progName);
+ return NULL;
+ }
+
+ if (decodeOptions->headerLevel >= 0) {
+ /*fprintf(out, "SMIME: ", decodeOptions->headerLevel, i);*/
+ fprintf(out, "SMIME: ");
+ }
+
+ nlevels = NSS_CMSMessage_ContentLevelCount(cmsg);
+ for (i = 0; i < nlevels; i++) {
+ cinfo = NSS_CMSMessage_ContentLevel(cmsg, i);
+ typetag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
+
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "\tlevel=%d.%d; ", decodeOptions->headerLevel, nlevels - i);
+
+ switch (typetag) {
+ case SEC_OID_PKCS7_SIGNED_DATA:
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "type=signedData; ");
+ sigd = (NSSCMSSignedData *)NSS_CMSContentInfo_GetContent(cinfo);
+ if (sigd == NULL) {
+ SECU_PrintError(progName,
+ "problem finding signedData component");
+ goto loser;
+ }
+
+ /* if we have a content file, but no digests for this signedData */
+ if (decodeOptions->contentFile != NULL && !NSS_CMSSignedData_HasDigests(sigd)) {
+ if ((poolp = PORT_NewArena(1024)) == NULL) {
+ fprintf(stderr, "cmsutil: Out of memory.\n");
+ goto loser;
+ }
+ digestalgs = NSS_CMSSignedData_GetDigestAlgs(sigd);
+ if (DigestFile (poolp, &digests, &sitem, digestalgs)
+ != SECSuccess) {
+ SECU_PrintError(progName,
+ "problem computing message digest");
+ goto loser;
+ }
+ if (NSS_CMSSignedData_SetDigests(sigd, digestalgs, digests) != SECSuccess) {
+
+ SECU_PrintError(progName,
+ "problem setting message digests");
+ goto loser;
+ }
+ PORT_FreeArena(poolp, PR_FALSE);
+ }
+
+ /* import the certificates */
+ if (NSS_CMSSignedData_ImportCerts(sigd,
+ decodeOptions->options->certHandle,
+ decodeOptions->options->certUsage,
+ PR_FALSE)
+ != SECSuccess) {
+ SECU_PrintError(progName, "cert import failed");
+ goto loser;
+ }
+
+ /* find out about signers */
+ nsigners = NSS_CMSSignedData_SignerInfoCount(sigd);
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "nsigners=%d; ", nsigners);
+ if (nsigners == 0) {
+ /* must be a cert transport message */
+ SECStatus rv;
+ /* XXX workaround for bug #54014 */
+ NSS_CMSSignedData_ImportCerts(sigd,
+ decodeOptions->options->certHandle,
+ decodeOptions->options->certUsage,
+ PR_TRUE);
+ rv = NSS_CMSSignedData_VerifyCertsOnly(sigd,
+ decodeOptions->options->certHandle,
+ decodeOptions->options->certUsage);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "cmsutil: Verify certs-only failed!\n");
+ goto loser;
+ }
+ return cmsg;
+ }
+
+ /* still no digests? */
+ if (!NSS_CMSSignedData_HasDigests(sigd)) {
+ SECU_PrintError(progName, "no message digests");
+ goto loser;
+ }
+
+ for (j = 0; j < nsigners; j++) {
+ si = NSS_CMSSignedData_GetSignerInfo(sigd, j);
+ signercn = NSS_CMSSignerInfo_GetSignerCommonName(si);
+ if (signercn == NULL)
+ signercn = "";
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "\n\t\tsigner%d.id=\"%s\"; ", j, signercn);
+ (void)NSS_CMSSignedData_VerifySignerInfo(sigd, j,
+ decodeOptions->options->certHandle,
+ decodeOptions->options->certUsage);
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "signer%d.status=%s; ", j,
+ NSS_CMSUtil_VerificationStatusToString(
+ NSS_CMSSignerInfo_GetVerificationStatus(si)));
+ /* XXX what do we do if we don't print headers? */
+ }
+ break;
+ case SEC_OID_PKCS7_ENVELOPED_DATA:
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "type=envelopedData; ");
+ envd = (NSSCMSEnvelopedData *)NSS_CMSContentInfo_GetContent(cinfo);
+ break;
+ case SEC_OID_PKCS7_ENCRYPTED_DATA:
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "type=encryptedData; ");
+ encd = (NSSCMSEncryptedData *)NSS_CMSContentInfo_GetContent(cinfo);
+ break;
+ case SEC_OID_PKCS7_DATA:
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "type=data; ");
+ break;
+ default:
+ break;
+ }
+ if (decodeOptions->headerLevel >= 0)
+ fprintf(out, "\n");
+ }
+
+ if (!decodeOptions->suppressContent) {
+ item = decodeOptions->contentFile ? &sitem :
+ NSS_CMSMessage_GetContent(cmsg);
+ SECITEM_CopyItem(NULL, output, item);
+ }
+
+ return cmsg;
+loser:
+ if (cmsg)
+ NSS_CMSMessage_Destroy(cmsg);
+ return NULL;
+}
+
+/* example of a callback function to use with encoder */
+/*
+static void
+writeout(void *arg, const char *buf, unsigned long len)
+{
+ FILE *f = (FILE *)arg;
+
+ if (f != NULL && buf != NULL)
+ (void)fwrite(buf, len, 1, f);
+}
+*/
+
+static NSSCMSMessage *
+signed_data(struct signOptionsStr *signOptions)
+{
+ NSSCMSMessage *cmsg = NULL;
+ NSSCMSContentInfo *cinfo;
+ NSSCMSSignedData *sigd;
+ NSSCMSSignerInfo *signerinfo;
+ CERTCertificate *cert= NULL, *ekpcert = NULL;
+
+ if (cms_verbose) {
+ fprintf(stderr, "Input to signed_data:\n");
+ if (signOptions->options->password)
+ fprintf(stderr, "password [%s]\n", signOptions->options->password);
+ else
+ fprintf(stderr, "password [NULL]\n");
+ fprintf(stderr, "certUsage [%d]\n", signOptions->options->certUsage);
+ if (signOptions->options->certHandle)
+ fprintf(stderr, "certdb [%p]\n", signOptions->options->certHandle);
+ else
+ fprintf(stderr, "certdb [NULL]\n");
+ if (signOptions->nickname)
+ fprintf(stderr, "nickname [%s]\n", signOptions->nickname);
+ else
+ fprintf(stderr, "nickname [NULL]\n");
+ }
+ if (signOptions->nickname == NULL) {
+ fprintf(stderr,
+ "ERROR: please indicate the nickname of a certificate to sign with.\n");
+ return NULL;
+ }
+ if ((cert = CERT_FindUserCertByUsage(signOptions->options->certHandle,
+ signOptions->nickname,
+ signOptions->options->certUsage,
+ PR_FALSE,
+ NULL)) == NULL) {
+ SECU_PrintError(progName,
+ "the corresponding cert for key \"%s\" does not exist",
+ signOptions->nickname);
+ return NULL;
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "Found certificate for %s\n", signOptions->nickname);
+ }
+ /*
+ * create the message object
+ */
+ cmsg = NSS_CMSMessage_Create(NULL); /* create a message on its own pool */
+ if (cmsg == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS message.\n");
+ return NULL;
+ }
+ /*
+ * build chain of objects: message->signedData->data
+ */
+ if ((sigd = NSS_CMSSignedData_Create(cmsg)) == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS signedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
+ if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd)
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS signedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSSignedData_GetContentInfo(sigd);
+ /* we're always passing data in and detaching optionally */
+ if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL,
+ signOptions->detached)
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS data object.\n");
+ goto loser;
+ }
+ /*
+ * create & attach signer information
+ */
+ signerinfo = NSS_CMSSignerInfo_Create(cmsg, cert, signOptions->hashAlgTag);
+ if (signerinfo == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS signerInfo object.\n");
+ goto loser;
+ }
+ if (cms_verbose) {
+ fprintf(stderr,
+ "Created CMS message, added signed data w/ signerinfo\n");
+ }
+ /* we want the cert chain included for this one */
+ if (NSS_CMSSignerInfo_IncludeCerts(signerinfo, NSSCMSCM_CertChain,
+ signOptions->options->certUsage)
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot find cert chain.\n");
+ goto loser;
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "imported certificate\n");
+ }
+ if (signOptions->signingTime) {
+ if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now())
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add signingTime attribute.\n");
+ goto loser;
+ }
+ }
+ if (signOptions->smimeProfile) {
+ if (NSS_CMSSignerInfo_AddSMIMECaps(signerinfo) != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add SMIMECaps attribute.\n");
+ goto loser;
+ }
+ }
+
+ if (!signOptions->encryptionKeyPreferenceNick) {
+ /* check signing cert for fitness as encryption cert */
+ SECStatus FitForEncrypt = CERT_CheckCertUsage(cert,
+ certUsageEmailRecipient);
+
+ if (SECSuccess == FitForEncrypt) {
+ /* if yes, add signing cert as EncryptionKeyPreference */
+ if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, cert,
+ signOptions->options->certHandle)
+ != SECSuccess) {
+ fprintf(stderr,
+ "ERROR: cannot add default SMIMEEncKeyPrefs attribute.\n");
+ goto loser;
+ }
+ if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, cert,
+ signOptions->options->certHandle)
+ != SECSuccess) {
+ fprintf(stderr,
+ "ERROR: cannot add default MS SMIMEEncKeyPrefs attribute.\n");
+ goto loser;
+ }
+ } else {
+ /* this is a dual-key cert case, we need to look for the encryption
+ certificate under the same nickname as the signing cert */
+ /* get the cert, add it to the message */
+ if ((ekpcert = CERT_FindUserCertByUsage(
+ signOptions->options->certHandle,
+ signOptions->nickname,
+ certUsageEmailRecipient,
+ PR_FALSE,
+ NULL)) == NULL) {
+ SECU_PrintError(progName,
+ "the corresponding cert for key \"%s\" does not exist",
+ signOptions->encryptionKeyPreferenceNick);
+ goto loser;
+ }
+ if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, ekpcert,
+ signOptions->options->certHandle)
+ != SECSuccess) {
+ fprintf(stderr,
+ "ERROR: cannot add SMIMEEncKeyPrefs attribute.\n");
+ goto loser;
+ }
+ if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, ekpcert,
+ signOptions->options->certHandle)
+ != SECSuccess) {
+ fprintf(stderr,
+ "ERROR: cannot add MS SMIMEEncKeyPrefs attribute.\n");
+ goto loser;
+ }
+ if (NSS_CMSSignedData_AddCertificate(sigd, ekpcert) != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add encryption certificate.\n");
+ goto loser;
+ }
+ }
+ } else if (PL_strcmp(signOptions->encryptionKeyPreferenceNick, "NONE") == 0) {
+ /* No action */
+ } else {
+ /* get the cert, add it to the message */
+ if ((ekpcert = CERT_FindUserCertByUsage(
+ signOptions->options->certHandle,
+ signOptions->encryptionKeyPreferenceNick,
+ certUsageEmailRecipient, PR_FALSE, NULL))
+ == NULL) {
+ SECU_PrintError(progName,
+ "the corresponding cert for key \"%s\" does not exist",
+ signOptions->encryptionKeyPreferenceNick);
+ goto loser;
+ }
+ if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, ekpcert,
+ signOptions->options->certHandle)
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add SMIMEEncKeyPrefs attribute.\n");
+ goto loser;
+ }
+ if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, ekpcert,
+ signOptions->options->certHandle)
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add MS SMIMEEncKeyPrefs attribute.\n");
+ goto loser;
+ }
+ if (NSS_CMSSignedData_AddCertificate(sigd, ekpcert) != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add encryption certificate.\n");
+ goto loser;
+ }
+ }
+
+ if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add CMS signerInfo object.\n");
+ goto loser;
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "created signed-data message\n");
+ }
+ if (ekpcert) {
+ CERT_DestroyCertificate(ekpcert);
+ }
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+ return cmsg;
+loser:
+ if (ekpcert) {
+ CERT_DestroyCertificate(ekpcert);
+ }
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ }
+ NSS_CMSMessage_Destroy(cmsg);
+ return NULL;
+}
+
+static NSSCMSMessage *
+enveloped_data(struct envelopeOptionsStr *envelopeOptions)
+{
+ NSSCMSMessage *cmsg = NULL;
+ NSSCMSContentInfo *cinfo;
+ NSSCMSEnvelopedData *envd;
+ NSSCMSRecipientInfo *recipientinfo;
+ CERTCertificate **recipientcerts = NULL;
+ CERTCertDBHandle *dbhandle;
+ PLArenaPool *tmppoolp = NULL;
+ SECOidTag bulkalgtag;
+ int keysize, i = 0;
+ int cnt;
+ dbhandle = envelopeOptions->options->certHandle;
+ /* count the recipients */
+ if ((cnt = nss_CMSArray_Count((void **)envelopeOptions->recipients)) == 0) {
+ fprintf(stderr, "ERROR: please name at least one recipient.\n");
+ goto loser;
+ }
+ if ((tmppoolp = PORT_NewArena (1024)) == NULL) {
+ fprintf(stderr, "ERROR: out of memory.\n");
+ goto loser;
+ }
+ /* XXX find the recipient's certs by email address or nickname */
+ if ((recipientcerts =
+ (CERTCertificate **)PORT_ArenaZAlloc(tmppoolp,
+ (cnt+1)*sizeof(CERTCertificate*)))
+ == NULL) {
+ fprintf(stderr, "ERROR: out of memory.\n");
+ goto loser;
+ }
+ for (i=0; envelopeOptions->recipients[i] != NULL; i++) {
+ if ((recipientcerts[i] =
+ CERT_FindCertByNicknameOrEmailAddr(dbhandle,
+ envelopeOptions->recipients[i]))
+ == NULL) {
+ SECU_PrintError(progName, "cannot find certificate for \"%s\"",
+ envelopeOptions->recipients[i]);
+ i=0;
+ goto loser;
+ }
+ }
+ recipientcerts[i] = NULL;
+ i=0;
+ /* find a nice bulk algorithm */
+ if (NSS_SMIMEUtil_FindBulkAlgForRecipients(recipientcerts, &bulkalgtag,
+ &keysize) != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot find common bulk algorithm.\n");
+ goto loser;
+ }
+ /*
+ * create the message object
+ */
+ cmsg = NSS_CMSMessage_Create(NULL); /* create a message on its own pool */
+ if (cmsg == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS message.\n");
+ goto loser;
+ }
+ /*
+ * build chain of objects: message->envelopedData->data
+ */
+ if ((envd = NSS_CMSEnvelopedData_Create(cmsg, bulkalgtag, keysize))
+ == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS envelopedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
+ if (NSS_CMSContentInfo_SetContent_EnvelopedData(cmsg, cinfo, envd)
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS envelopedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSEnvelopedData_GetContentInfo(envd);
+ /* we're always passing data in, so the content is NULL */
+ if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE)
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS data object.\n");
+ goto loser;
+ }
+ /*
+ * create & attach recipient information
+ */
+ for (i = 0; recipientcerts[i] != NULL; i++) {
+ if ((recipientinfo = NSS_CMSRecipientInfo_Create(cmsg,
+ recipientcerts[i]))
+ == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS recipientInfo object.\n");
+ goto loser;
+ }
+ if (NSS_CMSEnvelopedData_AddRecipient(envd, recipientinfo)
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot add CMS recipientInfo object.\n");
+ goto loser;
+ }
+ CERT_DestroyCertificate(recipientcerts[i]);
+ }
+ if (tmppoolp)
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ return cmsg;
+loser:
+ if (recipientcerts) {
+ for (; recipientcerts[i] != NULL; i++) {
+ CERT_DestroyCertificate(recipientcerts[i]);
+ }
+ }
+ if (cmsg)
+ NSS_CMSMessage_Destroy(cmsg);
+ if (tmppoolp)
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ return NULL;
+}
+
+PK11SymKey *dkcb(void *arg, SECAlgorithmID *algid)
+{
+ return (PK11SymKey*)arg;
+}
+
+static SECStatus
+get_enc_params(struct encryptOptionsStr *encryptOptions)
+{
+ struct envelopeOptionsStr envelopeOptions;
+ SECStatus rv = SECFailure;
+ NSSCMSMessage *env_cmsg;
+ NSSCMSContentInfo *cinfo;
+ int i, nlevels;
+ /*
+ * construct an enveloped data message to obtain bulk keys
+ */
+ if (encryptOptions->envmsg) {
+ env_cmsg = encryptOptions->envmsg; /* get it from an old message */
+ } else {
+ SECItem dummyOut = { 0, 0, 0 };
+ SECItem dummyIn = { 0, 0, 0 };
+ char str[] = "Hello!";
+ PLArenaPool *tmparena = PORT_NewArena(1024);
+ dummyIn.data = (unsigned char *)str;
+ dummyIn.len = strlen(str);
+ envelopeOptions.options = encryptOptions->options;
+ envelopeOptions.recipients = encryptOptions->recipients;
+ env_cmsg = enveloped_data(&envelopeOptions);
+ NSS_CMSDEREncode(env_cmsg, &dummyIn, &dummyOut, tmparena);
+ PR_Write(encryptOptions->envFile, dummyOut.data, dummyOut.len);
+ PORT_FreeArena(tmparena, PR_FALSE);
+ }
+ /*
+ * get the content info for the enveloped data
+ */
+ nlevels = NSS_CMSMessage_ContentLevelCount(env_cmsg);
+ for (i = 0; i < nlevels; i++) {
+ SECOidTag typetag;
+ cinfo = NSS_CMSMessage_ContentLevel(env_cmsg, i);
+ typetag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
+ if (typetag == SEC_OID_PKCS7_DATA) {
+ /*
+ * get the symmetric key
+ */
+ encryptOptions->bulkalgtag = NSS_CMSContentInfo_GetContentEncAlgTag(cinfo);
+ encryptOptions->keysize = NSS_CMSContentInfo_GetBulkKeySize(cinfo);
+ encryptOptions->bulkkey = NSS_CMSContentInfo_GetBulkKey(cinfo);
+ rv = SECSuccess;
+ break;
+ }
+ }
+ if (i == nlevels) {
+ fprintf(stderr, "%s: could not retrieve enveloped data.", progName);
+ }
+ if (env_cmsg)
+ NSS_CMSMessage_Destroy(env_cmsg);
+ return rv;
+}
+
+static NSSCMSMessage *
+encrypted_data(struct encryptOptionsStr *encryptOptions)
+{
+ SECStatus rv = SECFailure;
+ NSSCMSMessage *cmsg = NULL;
+ NSSCMSContentInfo *cinfo;
+ NSSCMSEncryptedData *encd;
+ NSSCMSEncoderContext *ecx = NULL;
+ PLArenaPool *tmppoolp = NULL;
+ SECItem derOut = { 0, 0, 0 };
+ /* arena for output */
+ tmppoolp = PORT_NewArena(1024);
+ if (!tmppoolp) {
+ fprintf(stderr, "%s: out of memory.\n", progName);
+ return NULL;
+ }
+ /*
+ * create the message object
+ */
+ cmsg = NSS_CMSMessage_Create(NULL);
+ if (cmsg == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS message.\n");
+ goto loser;
+ }
+ /*
+ * build chain of objects: message->encryptedData->data
+ */
+ if ((encd = NSS_CMSEncryptedData_Create(cmsg, encryptOptions->bulkalgtag,
+ encryptOptions->keysize))
+ == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS encryptedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
+ if (NSS_CMSContentInfo_SetContent_EncryptedData(cmsg, cinfo, encd)
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS encryptedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSEncryptedData_GetContentInfo(encd);
+ /* we're always passing data in, so the content is NULL */
+ if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE)
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS data object.\n");
+ goto loser;
+ }
+ ecx = NSS_CMSEncoder_Start(cmsg, NULL, NULL, &derOut, tmppoolp, NULL, NULL,
+ dkcb, encryptOptions->bulkkey, NULL, NULL);
+ if (!ecx) {
+ fprintf(stderr, "%s: cannot create encoder context.\n", progName);
+ goto loser;
+ }
+ rv = NSS_CMSEncoder_Update(ecx, (char *)encryptOptions->input->data,
+ encryptOptions->input->len);
+ if (rv) {
+ fprintf(stderr, "%s: failed to add data to encoder.\n", progName);
+ goto loser;
+ }
+ rv = NSS_CMSEncoder_Finish(ecx);
+ if (rv) {
+ fprintf(stderr, "%s: failed to encrypt data.\n", progName);
+ goto loser;
+ }
+ fwrite(derOut.data, derOut.len, 1, encryptOptions->outfile);
+ /*
+ if (bulkkey)
+ PK11_FreeSymKey(bulkkey);
+ */
+ if (tmppoolp)
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ return cmsg;
+loser:
+ /*
+ if (bulkkey)
+ PK11_FreeSymKey(bulkkey);
+ */
+ if (tmppoolp)
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ if (cmsg)
+ NSS_CMSMessage_Destroy(cmsg);
+ return NULL;
+}
+
+static NSSCMSMessage *
+signed_data_certsonly(struct certsonlyOptionsStr *certsonlyOptions)
+{
+ NSSCMSMessage *cmsg = NULL;
+ NSSCMSContentInfo *cinfo;
+ NSSCMSSignedData *sigd;
+ CERTCertificate **certs = NULL;
+ CERTCertDBHandle *dbhandle;
+ PLArenaPool *tmppoolp = NULL;
+ int i = 0, cnt;
+ dbhandle = certsonlyOptions->options->certHandle;
+ if ((cnt = nss_CMSArray_Count((void**)certsonlyOptions->recipients)) == 0) {
+ fprintf(stderr,
+ "ERROR: please indicate the nickname of a certificate to sign with.\n");
+ goto loser;
+ }
+ if ((tmppoolp = PORT_NewArena (1024)) == NULL) {
+ fprintf(stderr, "ERROR: out of memory.\n");
+ goto loser;
+ }
+ if ((certs =
+ (CERTCertificate **)PORT_ArenaZAlloc(tmppoolp,
+ (cnt+1)*sizeof(CERTCertificate*)))
+ == NULL) {
+ fprintf(stderr, "ERROR: out of memory.\n");
+ goto loser;
+ }
+ for (i=0; certsonlyOptions->recipients[i] != NULL; i++) {
+ if ((certs[i] =
+ CERT_FindCertByNicknameOrEmailAddr(dbhandle,
+ certsonlyOptions->recipients[i]))
+ == NULL) {
+ SECU_PrintError(progName, "cannot find certificate for \"%s\"",
+ certsonlyOptions->recipients[i]);
+ i=0;
+ goto loser;
+ }
+ }
+ certs[i] = NULL;
+ i=0;
+ /*
+ * create the message object
+ */
+ cmsg = NSS_CMSMessage_Create(NULL);
+ if (cmsg == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS message.\n");
+ goto loser;
+ }
+ /*
+ * build chain of objects: message->signedData->data
+ */
+ if ((sigd = NSS_CMSSignedData_CreateCertsOnly(cmsg, certs[0], PR_TRUE))
+ == NULL) {
+ fprintf(stderr, "ERROR: cannot create CMS signedData object.\n");
+ goto loser;
+ }
+ CERT_DestroyCertificate(certs[0]);
+ for (i=1; i<cnt; i++) {
+ if (NSS_CMSSignedData_AddCertChain(sigd, certs[i])) {
+ fprintf(stderr, "ERROR: cannot add cert chain for \"%s\".\n",
+ certsonlyOptions->recipients[i]);
+ goto loser;
+ }
+ CERT_DestroyCertificate(certs[i]);
+ }
+ cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
+ if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd)
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS signedData object.\n");
+ goto loser;
+ }
+ cinfo = NSS_CMSSignedData_GetContentInfo(sigd);
+ if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE)
+ != SECSuccess) {
+ fprintf(stderr, "ERROR: cannot attach CMS data object.\n");
+ goto loser;
+ }
+ if (tmppoolp)
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ return cmsg;
+loser:
+ if (certs) {
+ for (; i<cnt; i++) {
+ CERT_DestroyCertificate(certs[i]);
+ }
+ }
+ if (cmsg)
+ NSS_CMSMessage_Destroy(cmsg);
+ if (tmppoolp)
+ PORT_FreeArena(tmppoolp, PR_FALSE);
+ return NULL;
+}
+
+typedef enum { UNKNOWN, DECODE, SIGN, ENCRYPT, ENVELOPE, CERTSONLY } Mode;
+
+int
+main(int argc, char **argv)
+{
+ FILE *outFile;
+ NSSCMSMessage *cmsg = NULL;
+ PRFileDesc *inFile;
+ PLOptState *optstate;
+ PLOptStatus status;
+ Mode mode = UNKNOWN;
+ PK11PasswordFunc pwcb;
+ void *pwcb_arg;
+ struct decodeOptionsStr decodeOptions = { 0 };
+ struct signOptionsStr signOptions = { 0 };
+ struct envelopeOptionsStr envelopeOptions = { 0 };
+ struct certsonlyOptionsStr certsonlyOptions = { 0 };
+ struct encryptOptionsStr encryptOptions = { 0 };
+ struct optionsStr options = { 0 };
+ int exitstatus;
+ static char *ptrarray[128] = { 0 };
+ int nrecipients = 0;
+ char *str, *tok;
+ char *envFileName;
+ SECItem input = { 0, 0, 0};
+ SECItem output = { 0, 0, 0};
+ SECItem dummy = { 0, 0, 0 };
+ SECItem envmsg = { 0, 0, 0 };
+ SECStatus rv;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName+1 : argv[0];
+
+ inFile = PR_STDIN;
+ outFile = stdout;
+ envFileName = NULL;
+ mode = UNKNOWN;
+ decodeOptions.contentFile = NULL;
+ decodeOptions.suppressContent = PR_FALSE;
+ decodeOptions.headerLevel = -1;
+ options.certUsage = certUsageEmailSigner;
+ options.password = NULL;
+ signOptions.nickname = NULL;
+ signOptions.detached = PR_FALSE;
+ signOptions.signingTime = PR_FALSE;
+ signOptions.smimeProfile = PR_FALSE;
+ signOptions.encryptionKeyPreferenceNick = NULL;
+ signOptions.hashAlgTag = SEC_OID_SHA1;
+ envelopeOptions.recipients = NULL;
+ encryptOptions.recipients = NULL;
+ encryptOptions.envmsg = NULL;
+ encryptOptions.envFile = NULL;
+ encryptOptions.bulkalgtag = SEC_OID_UNKNOWN;
+ encryptOptions.bulkkey = NULL;
+ encryptOptions.keysize = -1;
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv,
+ "CDEGH:N:OPSTY:c:d:e:h:i:no:p:r:s:u:v");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'C':
+ mode = ENCRYPT;
+ break;
+ case 'D':
+ mode = DECODE;
+ break;
+ case 'E':
+ mode = ENVELOPE;
+ break;
+ case 'G':
+ if (mode != SIGN) {
+ fprintf(stderr,
+ "%s: option -G only supported with option -S.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ signOptions.signingTime = PR_TRUE;
+ break;
+ case 'H':
+ if (mode != SIGN) {
+ fprintf(stderr,
+ "%s: option -n only supported with option -D.\n",
+ "%s: option -H only supported with option -S.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ decodeOptions.suppressContent = PR_TRUE;
+ if (!strcmp(optstate->value, "MD2"))
+ signOptions.hashAlgTag = SEC_OID_MD2;
+ else if (!strcmp(optstate->value, "MD4"))
+ signOptions.hashAlgTag = SEC_OID_MD4;
+ else if (!strcmp(optstate->value, "MD5"))
+ signOptions.hashAlgTag = SEC_OID_MD5;
+ else if (!strcmp(optstate->value, "SHA1"))
+ signOptions.hashAlgTag = SEC_OID_SHA1;
+ else if (!strcmp(optstate->value, "SHA256"))
+ signOptions.hashAlgTag = SEC_OID_SHA256;
+ else if (!strcmp(optstate->value, "SHA384"))
+ signOptions.hashAlgTag = SEC_OID_SHA384;
+ else if (!strcmp(optstate->value, "SHA512"))
+ signOptions.hashAlgTag = SEC_OID_SHA512;
+ else {
+ fprintf(stderr,
+ "%s: -H requires one of MD2,MD4,MD5,SHA1,SHA256,SHA384,SHA512\n",
+ progName);
+ exit(1);
+ }
+ break;
+ case 'N':
+ if (mode != SIGN) {
+ fprintf(stderr,
+ "%s: option -N only supported with option -S.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ signOptions.nickname = strdup(optstate->value);
+ break;
+ case 'O':
+ mode = CERTSONLY;
+ break;
+ case 'P':
+ if (mode != SIGN) {
+ fprintf(stderr,
+ "%s: option -P only supported with option -S.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ signOptions.smimeProfile = PR_TRUE;
+ break;
+ case 'S':
+ mode = SIGN;
+ break;
+ case 'T':
+ if (mode != SIGN) {
+ fprintf(stderr,
+ "%s: option -T only supported with option -S.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ signOptions.detached = PR_TRUE;
+ break;
+ case 'Y':
+ if (mode != SIGN) {
+ fprintf(stderr,
+ "%s: option -Y only supported with option -S.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ signOptions.encryptionKeyPreferenceNick = strdup(optstate->value);
+ break;
+
+ case 'c':
+ if (mode != DECODE) {
+ fprintf(stderr,
+ "%s: option -c only supported with option -D.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ if ((decodeOptions.contentFile =
+ PR_Open(optstate->value, PR_RDONLY, 006600)) == NULL) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading.\n",
+ progName, optstate->value);
+ exit(1);
+ }
+ break;
+ case 'd':
+ SECU_ConfigDirectory(optstate->value);
+ break;
+ case 'e':
+ envFileName = strdup(optstate->value);
+ encryptOptions.envFile = PR_Open(envFileName, PR_RDONLY, 00660);
+ break;
+
+ case 'h':
+ if (mode != DECODE) {
+ fprintf(stderr,
+ "%s: option -h only supported with option -D.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ decodeOptions.headerLevel = atoi(optstate->value);
+ if (decodeOptions.headerLevel < 0) {
+ fprintf(stderr, "option -h cannot have a negative value.\n");
+ exit(1);
+ }
+ break;
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 00660);
+ if (inFile == NULL) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ exit(1);
+ }
+ break;
+
+ case 'n':
+ if (mode != DECODE) {
+ fprintf(stderr,
+ "%s: option -n only supported with option -D.\n",
+ progName);
+ Usage(progName);
+ exit(1);
+ }
+ decodeOptions.suppressContent = PR_TRUE;
+ break;
+ case 'o':
+ outFile = fopen(optstate->value, "wb");
+ if (outFile == NULL) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ exit(1);
+ }
+ break;
+ case 'p':
+ if (!optstate->value) {
+ fprintf(stderr, "%s: option -p must have a value.\n", progName);
+ Usage(progName);
+ exit(1);
+ }
+
+ options.password = strdup(optstate->value);
+ break;
+
+ case 'r':
+ if (!optstate->value) {
+ fprintf(stderr, "%s: option -r must have a value.\n", progName);
+ Usage(progName);
+ exit(1);
+ }
+ envelopeOptions.recipients = ptrarray;
+ str = (char *)optstate->value;
+ do {
+ tok = strchr(str, ',');
+ if (tok) *tok = '\0';
+ envelopeOptions.recipients[nrecipients++] = strdup(str);
+ if (tok) str = tok + 1;
+ } while (tok);
+ envelopeOptions.recipients[nrecipients] = NULL;
+ encryptOptions.recipients = envelopeOptions.recipients;
+ certsonlyOptions.recipients = envelopeOptions.recipients;
+ break;
+
+ case 'u': {
+ int usageType;
+
+ usageType = atoi (strdup(optstate->value));
+ if (usageType < certUsageSSLClient || usageType > certUsageAnyCA)
+ return -1;
+ options.certUsage = (SECCertUsage)usageType;
+ break;
+ }
+ case 'v':
+ cms_verbose = 1;
+ break;
+
+ }
+ }
+ if (status == PL_OPT_BAD)
+ Usage(progName);
+ PL_DestroyOptState(optstate);
+
+ if (mode == UNKNOWN)
+ Usage(progName);
+
+ if (mode != CERTSONLY)
+ SECU_FileToItem(&input, inFile);
+ if (inFile != PR_STDIN)
+ PR_Close(inFile);
+ if (cms_verbose) {
+ fprintf(stderr, "received commands\n");
+ }
+
+ /* Call the libsec initialization routines */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_InitReadWrite(SECU_ConfigDirectory(NULL));
+ if (SECSuccess != rv) {
+ SECU_PrintError(progName, "NSS_Init failed");
+ exit(1);
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "NSS has been initialized.\n");
+ }
+ options.certHandle = CERT_GetDefaultCertDB();
+ if (!options.certHandle) {
+ SECU_PrintError(progName, "No default cert DB");
+ exit(1);
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "Got default certdb\n");
+ }
+
+#if defined(_WIN32)
+ if (outFile == stdout) {
+ /* If we're going to write binary data to stdout, we must put stdout
+ ** into O_BINARY mode or else outgoing \n's will become \r\n's.
+ */
+ int smrv = _setmode(_fileno(stdout), _O_BINARY);
+ if (smrv == -1) {
+ fprintf(stderr,
+ "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
+ progName);
+ return smrv;
+ }
+ }
+#endif
+
+ exitstatus = 0;
+ switch (mode) {
+ case DECODE:
+ decodeOptions.options = &options;
+ if (encryptOptions.envFile) {
+ /* Decoding encrypted-data, so get the bulkkey from an
+ * enveloped-data message.
+ */
+ SECU_FileToItem(&envmsg, encryptOptions.envFile);
+ decodeOptions.options = &options;
+ encryptOptions.envmsg = decode(NULL, &dummy, &envmsg,
+ &decodeOptions);
+ if (!encryptOptions.envmsg) {
+ SECU_PrintError(progName, "problem decoding env msg");
+ exitstatus = 1;
+ break;
+ }
+ rv = get_enc_params(&encryptOptions);
+ decodeOptions.dkcb = dkcb;
+ decodeOptions.bulkkey = encryptOptions.bulkkey;
+ }
+ cmsg = decode(outFile, &output, &input, &decodeOptions);
+ if (!cmsg) {
+ SECU_PrintError(progName, "problem decoding");
+ exitstatus = 1;
+ }
+ fwrite(output.data, output.len, 1, outFile);
+ break;
+ case SIGN:
+ signOptions.options = &options;
+ cmsg = signed_data(&signOptions);
+ if (!cmsg) {
+ SECU_PrintError(progName, "problem signing");
+ exitstatus = 1;
+ }
+ break;
+ case ENCRYPT:
+ if (!envFileName) {
+ fprintf(stderr, "%s: you must specify an envelope file with -e.\n",
+ progName);
+ exit(1);
+ }
+ encryptOptions.options = &options;
+ encryptOptions.input = &input;
+ encryptOptions.outfile = outFile;
+ if (!encryptOptions.envFile) {
+ encryptOptions.envFile = PR_Open(envFileName,
+ PR_WRONLY|PR_CREATE_FILE, 00660);
+ if (!encryptOptions.envFile) {
+ fprintf(stderr, "%s: failed to create file %s.\n", progName,
+ envFileName);
+ exit(1);
+ }
+ } else {
+ SECU_FileToItem(&envmsg, encryptOptions.envFile);
+ decodeOptions.options = &options;
+ encryptOptions.envmsg = decode(NULL, &dummy, &envmsg,
+ &decodeOptions);
+ if (encryptOptions.envmsg == NULL) {
+ SECU_PrintError(progName, "problem decrypting env msg");
+ exitstatus = 1;
+ break;
+ }
+ }
+ /* decode an enveloped-data message to get the bulkkey (create
+ * a new one if neccessary)
+ */
+ rv = get_enc_params(&encryptOptions);
+ /* create the encrypted-data message */
+ cmsg = encrypted_data(&encryptOptions);
+ if (!cmsg) {
+ SECU_PrintError(progName, "problem encrypting");
+ exitstatus = 1;
+ }
+ if (encryptOptions.bulkkey) {
+ PK11_FreeSymKey(encryptOptions.bulkkey);
+ encryptOptions.bulkkey = NULL;
+ }
+ break;
+ case ENVELOPE:
+ envelopeOptions.options = &options;
+ cmsg = enveloped_data(&envelopeOptions);
+ if (!cmsg) {
+ SECU_PrintError(progName, "problem enveloping");
+ exitstatus = 1;
+ }
+ break;
+ case CERTSONLY:
+ certsonlyOptions.options = &options;
+ cmsg = signed_data_certsonly(&certsonlyOptions);
+ if (!cmsg) {
+ SECU_PrintError(progName, "problem with certs-only");
+ exitstatus = 1;
+ }
+ break;
+ default:
+ fprintf(stderr, "One of options -D, -S or -E must be set.\n");
+ Usage(progName);
+ exitstatus = 1;
+ }
+ if ( (mode == SIGN || mode == ENVELOPE || mode == CERTSONLY)
+ && (!exitstatus) ) {
+ PLArenaPool *arena = PORT_NewArena(1024);
+ NSSCMSEncoderContext *ecx;
+ SECItem output = { 0, 0, 0 };
+ secuPWData pwdata = { PW_NONE, 0 };
+
+ if (!arena) {
+ fprintf(stderr, "%s: out of memory.\n", progName);
+ exit(1);
+ }
+
+ if (options.password)
+ {
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = options.password;
+ }
+ pwcb = SECU_GetModulePassword;
+ pwcb_arg = (void *)&pwdata;
+
+ if (cms_verbose) {
+ fprintf(stderr, "cmsg [%p]\n", cmsg);
+ fprintf(stderr, "arena [%p]\n", arena);
+ if (pwcb_arg)
+ fprintf(stderr, "password [%s]\n", (char *)pwcb_arg);
+ else
+ fprintf(stderr, "password [NULL]\n");
+ }
+ ecx = NSS_CMSEncoder_Start(cmsg,
+ NULL, NULL, /* DER output callback */
+ &output, arena, /* destination storage */
+ pwcb, pwcb_arg, /* password callback */
+ NULL, NULL, /* decrypt key callback */
+ NULL, NULL ); /* detached digests */
+ if (!ecx) {
+ fprintf(stderr, "%s: cannot create encoder context.\n", progName);
+ exit(1);
+ }
+ if (cms_verbose) {
+ fprintf(stderr, "input len [%d]\n", input.len);
+ { unsigned int j;
+ for(j=0;j<input.len;j++)
+ fprintf(stderr, "%2x%c", input.data[j], (j>0&&j%35==0)?'\n':' ');
+ }
+ }
+ if (input.len > 0) { /* skip if certs-only (or other zero content) */
+ rv = NSS_CMSEncoder_Update(ecx, (char *)input.data, input.len);
+ if (rv) {
+ fprintf(stderr,
+ "%s: failed to add data to encoder.\n", progName);
+ exit(1);
+ }
+ }
+ rv = NSS_CMSEncoder_Finish(ecx);
+ if (rv) {
+ SECU_PrintError(progName, "failed to encode data");
+ exit(1);
+ }
+
+ if (cms_verbose) {
+ fprintf(stderr, "encoding passed\n");
+ }
+ /*PR_Write(output.data, output.len);*/
+ fwrite(output.data, output.len, 1, outFile);
+ if (cms_verbose) {
+ fprintf(stderr, "wrote to file\n");
+ }
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ if (cmsg)
+ NSS_CMSMessage_Destroy(cmsg);
+ if (outFile != stdout)
+ fclose(outFile);
+
+ if (decodeOptions.contentFile)
+ PR_Close(decodeOptions.contentFile);
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ exit(exitstatus);
+}
diff --git a/security/nss/cmd/smimetools/manifest.mn b/security/nss/cmd/smimetools/manifest.mn
new file mode 100644
index 000000000..552cfec7d
--- /dev/null
+++ b/security/nss/cmd/smimetools/manifest.mn
@@ -0,0 +1,45 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+MODULE = nss
+
+CSRCS = cmsutil.c
+
+MYLIB = $(DIST)/lib/libsmime.a
+
+REQUIRES = seccmd dbm
+
+PROGRAM = cmsutil
+SCRIPTS = smime
diff --git a/security/nss/cmd/smimetools/rules.mk b/security/nss/cmd/smimetools/rules.mk
new file mode 100644
index 000000000..51e0baaed
--- /dev/null
+++ b/security/nss/cmd/smimetools/rules.mk
@@ -0,0 +1,37 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+# $Id$
+#
+
+install::
+ $(INSTALL) -m 755 $(SCRIPTS) $(SOURCE_BIN_DIR)
diff --git a/security/nss/cmd/smimetools/smime b/security/nss/cmd/smimetools/smime
new file mode 100755
index 000000000..d23a912ed
--- /dev/null
+++ b/security/nss/cmd/smimetools/smime
@@ -0,0 +1,576 @@
+#!/usr/local/bin/perl
+
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+
+#
+# smime.pl - frontend for S/MIME message generation and parsing
+#
+# $Id$
+#
+
+use Getopt::Std;
+
+@boundarychars = ( "0" .. "9", "A" .. "F" );
+
+# path to cmsutil
+$cmsutilpath = "cmsutil";
+
+#
+# Thanks to Gisle Aas <gisle@aas.no> for the base64 functions
+# originally taken from MIME-Base64-2.11 at www.cpan.org
+#
+sub encode_base64($)
+{
+ my $res = "";
+ pos($_[0]) = 0; # ensure start at the beginning
+ while ($_[0] =~ /(.{1,45})/gs) {
+ $res .= substr(pack('u', $1), 1); # get rid of length byte after packing
+ chop($res);
+ }
+ $res =~ tr|` -_|AA-Za-z0-9+/|;
+ # fix padding at the end
+ my $padding = (3 - length($_[0]) % 3) % 3;
+ $res =~ s/.{$padding}$/'=' x $padding/e if $padding;
+ # break encoded string into lines of no more than 76 characters each
+ $res =~ s/(.{1,76})/$1\n/g;
+ $res;
+}
+
+sub decode_base64($)
+{
+ local($^W) = 0; # unpack("u",...) gives bogus warning in 5.00[123]
+
+ my $str = shift;
+ my $res = "";
+
+ $str =~ tr|A-Za-z0-9+=/||cd; # remove non-base64 chars
+ if (length($str) % 4) {
+ require Carp;
+ Carp::carp("Length of base64 data not a multiple of 4")
+ }
+ $str =~ s/=+$//; # remove padding
+ $str =~ tr|A-Za-z0-9+/| -_|; # convert to uuencoded format
+ while ($str =~ /(.{1,60})/gs) {
+ my $len = chr(32 + length($1)*3/4); # compute length byte
+ $res .= unpack("u", $len . $1 ); # uudecode
+ }
+ $res;
+}
+
+#
+# parse headers into a hash
+#
+# %headers = parseheaders($headertext);
+#
+sub parseheaders($)
+{
+ my ($headerdata) = @_;
+ my $hdr;
+ my %hdrhash;
+ my $hdrname;
+ my $hdrvalue;
+ my @hdrvalues;
+ my $subhdrname;
+ my $subhdrvalue;
+
+ # the expression in split() correctly handles continuation lines
+ foreach $hdr (split(/\n(?=\S)/, $headerdata)) {
+ $hdr =~ s/\r*\n\s+/ /g; # collapse continuation lines
+ ($hdrname, $hdrvalue) = $hdr =~ m/^(\S+):\s+(.*)$/;
+
+ # ignore non-headers (or should we die horribly?)
+ next unless (defined($hdrname));
+ $hdrname =~ tr/A-Z/a-z/; # lowercase the header name
+ @hdrvalues = split(/\s*;\s*/, $hdrvalue); # split header values (XXXX quoting)
+
+ # there is guaranteed to be at least one value
+ $hdrvalue = shift @hdrvalues;
+ if ($hdrvalue =~ /^\s*\"(.*)\"\s*$/) { # strip quotes if there
+ $hdrvalue = $1;
+ }
+
+ $hdrhash{$hdrname}{MAIN} = $hdrvalue;
+ # print "XXX $hdrname = $hdrvalue\n";
+
+ # deal with additional name-value pairs
+ foreach $hdrvalue (@hdrvalues) {
+ ($subhdrname, $subhdrvalue) = $hdrvalue =~ m/^(\S+)\s*=\s*(.*)$/;
+ # ignore non-name-value pairs (or should we die?)
+ next unless (defined($subhdrname));
+ $subhdrname =~ tr/A-Z/a-z/;
+ if ($subhdrvalue =~ /^\s*\"(.*)\"\s*$/) { # strip quotes if there
+ $subhdrvalue = $1;
+ }
+ $hdrhash{$hdrname}{$subhdrname} = $subhdrvalue;
+ }
+
+ }
+ return %hdrhash;
+}
+
+#
+# encryptentity($entity, $options) - encrypt an S/MIME entity,
+# creating a new application/pkcs7-smime entity
+#
+# entity - string containing entire S/MIME entity to encrypt
+# options - options for cmsutil
+#
+# this will generate and return a new application/pkcs7-smime entity containing
+# the enveloped input entity.
+#
+sub encryptentity($$)
+{
+ my ($entity, $cmsutiloptions) = @_;
+ my $out = "";
+ my $boundary;
+
+ $tmpencfile = "/tmp/encryptentity.$$";
+
+ #
+ # generate a random boundary string
+ #
+ $boundary = "------------ms" . join("", @boundarychars[map{rand @boundarychars }( 1 .. 24 )]);
+
+ #
+ # tell cmsutil to generate a enveloped CMS message using our data
+ #
+ open(CMS, "|$cmsutilpath -E $cmsutiloptions -o $tmpencfile") or die "ERROR: cannot pipe to cmsutil";
+ print CMS $entity;
+ unless (close(CMS)) {
+ print STDERR "ERROR: encryption failed.\n";
+ unlink($tmpsigfile);
+ exit 1;
+ }
+
+ $out = "Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m\n";
+ $out .= "Content-Transfer-Encoding: base64\n";
+ $out .= "Content-Disposition: attachment; filename=smime.p7m\n";
+ $out .= "\n"; # end of entity header
+
+ open (ENC, $tmpencfile) or die "ERROR: cannot find newly generated encrypted content";
+ local($/) = undef; # slurp whole file
+ $out .= encode_base64(<ENC>), "\n"; # entity body is base64-encoded CMS message
+ close(ENC);
+
+ unlink($tmpencfile);
+
+ $out;
+}
+
+#
+# signentity($entity, $options) - sign an S/MIME entity
+#
+# entity - string containing entire S/MIME entity to sign
+# options - options for cmsutil
+#
+# this will generate and return a new multipart/signed entity consisting
+# of the canonicalized original content, plus a signature block.
+#
+sub signentity($$)
+{
+ my ($entity, $cmsutiloptions) = @_;
+ my $out = "";
+ my $boundary;
+
+ $tmpsigfile = "/tmp/signentity.$$";
+
+ #
+ # generate a random boundary string
+ #
+ $boundary = "------------ms" . join("", @boundarychars[map{rand @boundarychars }( 1 .. 24 )]);
+
+ #
+ # tell cmsutil to generate a signed CMS message using the canonicalized data
+ # The signedData has detached content (-T) and includes a signing time attribute (-G)
+ #
+ # if we do not provide a password on the command line, here's where we would be asked for it
+ #
+ open(CMS, "|$cmsutilpath -S -T -G $cmsutiloptions -o $tmpsigfile") or die "ERROR: cannot pipe to cmsutil";
+ print CMS $entity;
+ unless (close(CMS)) {
+ print STDERR "ERROR: signature generation failed.\n";
+ unlink($tmpsigfile);
+ exit 1;
+ }
+
+ open (SIG, $tmpsigfile) or die "ERROR: cannot find newly generated signature";
+
+ #
+ # construct a new multipart/signed MIME entity consisting of the original content and
+ # the signature
+ #
+ # (we assume that cmsutil generates a SHA1 digest)
+ $out .= "Content-Type: multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha1; boundary=\"${boundary}\"\n";
+ $out .= "\n"; # end of entity header
+ $out .= "This is a cryptographically signed message in MIME format.\n"; # explanatory comment
+ $out .= "\n--${boundary}\n";
+ $out .= $entity;
+ $out .= "\n--${boundary}\n";
+ $out .= "Content-Type: application/pkcs7-signature; name=smime.p7s\n";
+ $out .= "Content-Transfer-Encoding: base64\n";
+ $out .= "Content-Disposition: attachment; filename=smime.p7s\n";
+ $out .= "Content-Description: S/MIME Cryptographic Signature\n";
+ $out .= "\n"; # end of signature subentity header
+
+ local($/) = undef; # slurp whole file
+ $out .= encode_base64(<SIG>); # append base64-encoded signature
+ $out .= "\n--${boundary}--\n";
+
+ close(SIG);
+ unlink($tmpsigfile);
+
+ $out;
+}
+
+sub usage {
+ print STDERR "usage: smime [options]\n";
+ print STDERR " options:\n";
+ print STDERR " -S nick generate signed message, use certificate named \"nick\"\n";
+ print STDERR " -p passwd use \"passwd\" as security module password\n";
+ print STDERR " -E rec1[,rec2...] generate encrypted message for recipients\n";
+ print STDERR " -D decode a S/MIME message\n";
+ print STDERR " -p passwd use \"passwd\" as security module password\n";
+ print STDERR " (required for decrypting only)\n";
+ print STDERR " -C pathname set pathname of \"cmsutil\"\n";
+ print STDERR " -d directory set directory containing certificate db\n";
+ print STDERR " (default: ~/.netscape)\n";
+ print STDERR "\nWith -S or -E, smime will take a regular RFC822 message or MIME entity\n";
+ print STDERR "on stdin and generate a signed or encrypted S/MIME message with the same\n";
+ print STDERR "headers and content from it. The output can be used as input to a MTA.\n";
+ print STDERR "-D causes smime to strip off all S/MIME layers if possible and output\n";
+ print STDERR "the \"inner\" message.\n";
+}
+
+#
+# start of main procedures
+#
+
+#
+# process command line options
+#
+unless (getopts('S:E:p:d:C:D')) {
+ usage();
+ exit 1;
+}
+
+unless (defined($opt_S) or defined($opt_E) or defined($opt_D)) {
+ print STDERR "ERROR: -S and/or -E, or -D must be specified.\n";
+ usage();
+ exit 1;
+}
+
+$signopts = "";
+$encryptopts = "";
+$decodeopts = "";
+
+# pass -d option along
+if (defined($opt_d)) {
+ $signopts .= "-d \"$opt_d\" ";
+ $encryptopts .= "-d \"$opt_d\" ";
+ $decodeopts .= "-d \"$opt_d\" ";
+}
+
+if (defined($opt_S)) {
+ $signopts .= "-N \"$opt_S\" ";
+}
+
+if (defined($opt_p)) {
+ $signopts .= "-p \"$opt_p\" ";
+ $decodeopts .= "-p \"$opt_p\" ";
+}
+
+if (defined($opt_E)) {
+ @recipients = split(",", $opt_E);
+ $encryptopts .= "-r ";
+ $encryptopts .= join (" -r ", @recipients);
+}
+
+if (defined($opt_C)) {
+ $cmsutilpath = $opt_C;
+}
+
+#
+# split headers into mime entity headers and RFC822 headers
+# The RFC822 headers are preserved and stay on the outer layer of the message
+#
+$rfc822headers = "";
+$mimeheaders = "";
+$mimebody = "";
+$skippedheaders = "";
+while (<STDIN>) {
+ last if (/^$/);
+ if (/^content-\S+: /i) {
+ $lastref = \$mimeheaders;
+ } elsif (/^mime-version: /i) {
+ $lastref = \$skippedheaders; # skip it
+ } elsif (/^\s/) {
+ ;
+ } else {
+ $lastref = \$rfc822headers;
+ }
+ $$lastref .= $_;
+}
+
+#
+# if there are no MIME entity headers, generate some default ones
+#
+if ($mimeheaders eq "") {
+ $mimeheaders .= "Content-Type: text/plain; charset=us-ascii\n";
+ $mimeheaders .= "Content-Transfer-Encoding: 7bit\n";
+}
+
+#
+# slurp in the entity body
+#
+$saveRS = $/;
+$/ = undef;
+$mimebody = <STDIN>;
+$/ = $saveRS;
+chomp($mimebody);
+
+if (defined $opt_D) {
+ #
+ # decode
+ #
+ # possible options would be:
+ # - strip off only one layer
+ # - strip off outer signature (if present)
+ # - just print information about the structure of the message
+ # - strip n layers, then dump DER of CMS message
+
+ $layercounter = 1;
+
+ while (1) {
+ %hdrhash = parseheaders($mimeheaders);
+ unless (exists($hdrhash{"content-type"}{MAIN})) {
+ print STDERR "ERROR: no content type header found in MIME entity\n";
+ last; # no content-type - we're done
+ }
+
+ $contenttype = $hdrhash{"content-type"}{MAIN};
+ if ($contenttype eq "application/pkcs7-mime") {
+ #
+ # opaque-signed or enveloped message
+ #
+ unless (exists($hdrhash{"content-type"}{"smime-type"})) {
+ print STDERR "ERROR: no smime-type attribute in application/pkcs7-smime entity.\n";
+ last;
+ }
+ $smimetype = $hdrhash{"content-type"}{"smime-type"};
+ if ($smimetype eq "signed-data" or $smimetype eq "enveloped-data") {
+ # it's verification or decryption time!
+
+ # can handle only base64 encoding for now
+ # all other encodings are treated as binary (8bit)
+ if ($hdrhash{"content-transfer-encoding"}{MAIN} eq "base64") {
+ $mimebody = decode_base64($mimebody);
+ }
+
+ # if we need to dump the DER, we would do it right here
+
+ # now write the DER
+ $tmpderfile = "/tmp/der.$$";
+ open(TMP, ">$tmpderfile") or die "ERROR: cannot write signature data to temporary file";
+ print TMP $mimebody;
+ unless (close(TMP)) {
+ print STDERR "ERROR: writing signature data to temporary file.\n";
+ unlink($tmpderfile);
+ exit 1;
+ }
+
+ $mimeheaders = "";
+ open(TMP, "$cmsutilpath -D $decodeopts -h $layercounter -i $tmpderfile |") or die "ERROR: cannot open pipe to cmsutil";
+ $layercounter++;
+ while (<TMP>) {
+ last if (/^\r?$/); # empty lines mark end of header
+ if (/^SMIME: /) { # add all SMIME info to the rfc822 hdrs
+ $lastref = \$rfc822headers;
+ } elsif (/^\s/) {
+ ; # continuation lines go to the last dest
+ } else {
+ $lastref = \$mimeheaders; # all other headers are mime headers
+ }
+ $$lastref .= $_;
+ }
+ # slurp in rest of the data to $mimebody
+ $saveRS = $/; $/ = undef; $mimebody = <TMP>; $/ = $saveRS;
+ close(TMP);
+
+ unlink($tmpderfile);
+
+ } else {
+ print STDERR "ERROR: unknown smime-type \"$smimetype\" in application/pkcs7-smime entity.\n";
+ last;
+ }
+ } elsif ($contenttype eq "multipart/signed") {
+ #
+ # clear signed message
+ #
+ unless (exists($hdrhash{"content-type"}{"protocol"})) {
+ print STDERR "ERROR: content type has no protocol attribute in multipart/signed entity.\n";
+ last;
+ }
+ if ($hdrhash{"content-type"}{"protocol"} ne "application/pkcs7-signature") {
+ # we cannot handle this guy
+ print STDERR "ERROR: unknown protocol \"", $hdrhash{"content-type"}{"protocol"},
+ "\" in multipart/signed entity.\n";
+ last;
+ }
+ unless (exists($hdrhash{"content-type"}{"boundary"})) {
+ print STDERR "ERROR: no boundary attribute in multipart/signed entity.\n";
+ last;
+ }
+ $boundary = $hdrhash{"content-type"}{"boundary"};
+
+ # split $mimebody along \n--$boundary\n - gets you four parts
+ # first (0), any comments the sending agent might have put in
+ # second (1), the message itself
+ # third (2), the signature as a mime entity
+ # fourth (3), trailing data (there shouldn't be any)
+
+ @multiparts = split(/\r?\n--$boundary(?:--)?\r?\n/, $mimebody);
+
+ #
+ # parse the signature headers
+ ($submimeheaders, $submimebody) = split(/^$/m, $multiparts[2]);
+ %sighdrhash = parseheaders($submimeheaders);
+ unless (exists($sighdrhash{"content-type"}{MAIN})) {
+ print STDERR "ERROR: signature entity has no content type.\n";
+ last;
+ }
+ if ($sighdrhash{"content-type"}{MAIN} ne "application/pkcs7-signature") {
+ # we cannot handle this guy
+ print STDERR "ERROR: unknown content type \"", $sighdrhash{"content-type"}{MAIN},
+ "\" in signature entity.\n";
+ last;
+ }
+ if ($sighdrhash{"content-transfer-encoding"}{MAIN} eq "base64") {
+ $submimebody = decode_base64($submimebody);
+ }
+
+ # we would dump the DER at this point
+
+ $tmpsigfile = "/tmp/sig.$$";
+ open(TMP, ">$tmpsigfile") or die "ERROR: cannot write signature data to temporary file";
+ print TMP $submimebody;
+ unless (close(TMP)) {
+ print STDERR "ERROR: writing signature data to temporary file.\n";
+ unlink($tmpsigfile);
+ exit 1;
+ }
+
+ $tmpmsgfile = "/tmp/msg.$$";
+ open(TMP, ">$tmpmsgfile") or die "ERROR: cannot write message data to temporary file";
+ print TMP $multiparts[1];
+ unless (close(TMP)) {
+ print STDERR "ERROR: writing message data to temporary file.\n";
+ unlink($tmpsigfile);
+ unlink($tmpmsgfile);
+ exit 1;
+ }
+
+ $mimeheaders = "";
+ open(TMP, "$cmsutilpath -D $decodeopts -h $layercounter -c $tmpmsgfile -i $tmpsigfile |") or die "ERROR: cannot open pipe to cmsutil";
+ $layercounter++;
+ while (<TMP>) {
+ last if (/^\r?$/);
+ if (/^SMIME: /) {
+ $lastref = \$rfc822headers;
+ } elsif (/^\s/) {
+ ;
+ } else {
+ $lastref = \$mimeheaders;
+ }
+ $$lastref .= $_;
+ }
+ $saveRS = $/; $/ = undef; $mimebody = <TMP>; $/ = $saveRS;
+ close(TMP);
+ unlink($tmpsigfile);
+ unlink($tmpmsgfile);
+
+ } else {
+
+ # not a content type we know - we're done
+ last;
+
+ }
+ }
+
+ # so now we have the S/MIME parsing information in rfc822headers
+ # and the first mime entity we could not handle in mimeheaders and mimebody.
+ # dump 'em out and we're done.
+ print $rfc822headers;
+ print $mimeheaders . "\n" . $mimebody;
+
+} else {
+
+ #
+ # encode (which is much easier than decode)
+ #
+
+ $mimeentity = $mimeheaders . "\n" . $mimebody;
+
+ #
+ # canonicalize inner entity (rudimentary yet)
+ # convert single LFs to CRLF
+ # if no Content-Transfer-Encoding header present:
+ # if 8 bit chars present, use Content-Transfer-Encoding: quoted-printable
+ # otherwise, use Content-Transfer-Encoding: 7bit
+ #
+ $mimeentity =~ s/\r*\n/\r\n/mg;
+
+ #
+ # now do the wrapping
+ # we sign first, then encrypt because that's what Communicator needs
+ #
+ if (defined($opt_S)) {
+ $mimeentity = signentity($mimeentity, $signopts);
+ }
+
+ if (defined($opt_E)) {
+ $mimeentity = encryptentity($mimeentity, $encryptopts);
+ }
+
+ #
+ # XXX sign again to do triple wrapping (RFC2634)
+ #
+
+ #
+ # now write out the RFC822 headers
+ # followed by the final $mimeentity
+ #
+ print $rfc822headers;
+ print "MIME-Version: 1.0 (NSS SMIME - http://www.mozilla.org/projects/security)\n"; # set up the flag
+ print $mimeentity;
+}
+
+exit 0;
diff --git a/security/nss/cmd/sslstrength/Makefile b/security/nss/cmd/sslstrength/Makefile
new file mode 100644
index 000000000..8a0332d89
--- /dev/null
+++ b/security/nss/cmd/sslstrength/Makefile
@@ -0,0 +1,82 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+ifeq (,$(filter-out WINNT WIN95 WIN16,$(OS_TARGET))) # omits WINCE
+ifndef BUILD_OPT
+LDFLAGS += /subsystem:console /profile /debug /machine:I386 /incremental:no
+OS_CFLAGS += -D_CONSOLE
+endif
+endif
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#include ../platlibs.mk
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/sslstrength/manifest.mn b/security/nss/cmd/sslstrength/manifest.mn
new file mode 100644
index 000000000..8b7cb7b0d
--- /dev/null
+++ b/security/nss/cmd/sslstrength/manifest.mn
@@ -0,0 +1,50 @@
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+MODULE = nss
+
+EXPORTS =
+
+CSRCS = sslstrength.c \
+ $(NULL)
+
+PROGRAM = sslstrength
+
+REQUIRES = dbm seccmd
+
+DEFINES += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\"
+
+PACKAGE_FILES = sslstrength
+
+ARCHIVE_NAME = sslstrength
diff --git a/security/nss/cmd/sslstrength/sslstr.cgi b/security/nss/cmd/sslstrength/sslstr.cgi
new file mode 100644
index 000000000..ab6a1bff9
--- /dev/null
+++ b/security/nss/cmd/sslstrength/sslstr.cgi
@@ -0,0 +1,296 @@
+#!/usr/bin/perl
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+
+use CGI qw(:standard);
+
+
+
+# Replace this will the full path to the sslstrength executable.
+$sslstrength = "./sslstrength";
+
+
+# Replace this with the name of this CGI.
+
+$sslcgi = "sslstr.cgi";
+
+
+$query = new CGI;
+
+print header;
+
+print "<HTML><HEAD>
+<SCRIPT language='javascript'>
+
+function doexport(form) {
+ form.ssl2ciphers.options[0].selected=0;
+ form.ssl2ciphers.options[1].selected=0;
+ form.ssl2ciphers.options[2].selected=0;
+ form.ssl2ciphers.options[3].selected=0;
+ form.ssl2ciphers.options[4].selected=1;
+ form.ssl2ciphers.options[5].selected=1;
+
+ form.ssl3ciphers.options[0].selected=1;
+ form.ssl3ciphers.options[1].selected=1;
+ form.ssl3ciphers.options[2].selected=0;
+ form.ssl3ciphers.options[3].selected=1;
+ form.ssl3ciphers.options[4].selected=1;
+ form.ssl3ciphers.options[5].selected=1;
+ form.ssl3ciphers.options[6].selected=0;
+ form.ssl3ciphers.options[7].selected=0;
+
+
+}
+
+function dodomestic(form) {
+ form.ssl2ciphers.options[0].selected=1;
+ form.ssl2ciphers.options[1].selected=1;
+ form.ssl2ciphers.options[2].selected=1;
+ form.ssl2ciphers.options[3].selected=1;
+ form.ssl2ciphers.options[4].selected=1;
+ form.ssl2ciphers.options[5].selected=1;
+
+ form.ssl3ciphers.options[0].selected=1;
+ form.ssl3ciphers.options[1].selected=1;
+ form.ssl3ciphers.options[2].selected=1;
+ form.ssl3ciphers.options[3].selected=1;
+ form.ssl3ciphers.options[4].selected=1;
+ form.ssl3ciphers.options[5].selected=1;
+ form.ssl3ciphers.options[6].selected=1;
+ form.ssl3ciphers.options[7].selected=1;
+
+}
+
+function doclearssl2(form) {
+ form.ssl2ciphers.options[0].selected=0;
+ form.ssl2ciphers.options[1].selected=0;
+ form.ssl2ciphers.options[2].selected=0;
+ form.ssl2ciphers.options[3].selected=0;
+ form.ssl2ciphers.options[4].selected=0;
+ form.ssl2ciphers.options[5].selected=0;
+}
+
+
+function doclearssl3(form) {
+ form.ssl3ciphers.options[0].selected=0;
+ form.ssl3ciphers.options[1].selected=0;
+ form.ssl3ciphers.options[2].selected=0;
+ form.ssl3ciphers.options[3].selected=0;
+ form.ssl3ciphers.options[4].selected=0;
+ form.ssl3ciphers.options[5].selected=0;
+ form.ssl3ciphers.options[6].selected=0;
+ form.ssl3ciphers.options[7].selected=0;
+
+}
+
+function dohost(form,hostname) {
+ form.host.value=hostname;
+ }
+
+
+
+</SCRIPT>
+<TITLE>\n";
+print "SSLStrength\n";
+print "</TITLE></HEAD>\n";
+
+print "<h1>SSLStrength</h1>\n";
+
+if ($query->param('dotest')) {
+ print "Output from sslstrength: \n";
+ print "<pre>\n";
+
+ $cs = "";
+
+ @ssl2ciphers = $query->param('ssl2ciphers');
+ for $cipher (@ssl2ciphers) {
+ if ($cipher eq "SSL_EN_RC2_128_WITH_MD5") { $cs .= "a"; }
+ if ($cipher eq "SSL_EN_RC2_128_CBC_WITH_MD5") { $cs .= "b"; }
+ if ($cipher eq "SSL_EN_DES_192_EDE3_CBC_WITH_MD5") { $cs .= "c"; }
+ if ($cipher eq "SSL_EN_DES_64_CBC_WITH_MD5") { $cs .= "d"; }
+ if ($cipher eq "SSL_EN_RC4_128_EXPORT40_WITH_MD5") { $cs .= "e"; }
+ if ($cipher eq "SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5") { $cs .= "f"; }
+ }
+
+ @ssl3ciphers = $query->param('ssl3ciphers');
+ for $cipher (@ssl3ciphers) {
+ if ($cipher eq "SSL_RSA_WITH_RC4_128_MD5") { $cs .= "i"; }
+ if ($cipher eq "SSL_RSA_WITH_3DES_EDE_CBC_SHA") { $cs .= "j"; }
+ if ($cipher eq "SSL_RSA_WITH_DES_CBC_SHA") { $cs .= "k"; }
+ if ($cipher eq "SSL_RSA_EXPORT_WITH_RC4_40_MD5") { $cs .= "l"; }
+ if ($cipher eq "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5") { $cs .= "m"; }
+ if ($cipher eq "SSL_RSA_WITH_NULL_MD5") { $cs .= "o"; }
+ if ($cipher eq "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA") { $cs .= "p"; }
+ if ($cipher eq "SSL_RSA_FIPS_WITH_DES_CBC_SHA") { $cs .= "q"; }
+ }
+
+ $hs = $query->param('host');
+ if ($hs eq "") {
+ print "</pre>You must specify a host to connect to.<br><br>\n";
+ exit(0);
+ }
+
+ $ps = $query->param('policy');
+
+ $cmdstring = "$sslstrength $hs policy=$ps ciphers=$cs";
+
+ print "running sslstrength:\n";
+ print "$cmdstring\n";
+
+ $r = open(SSLS, "$cmdstring |");
+ if ($r == 0) {
+ print "<pre>There was a problem starting $cmdstring<br><br>\n";
+ exit(0);
+ }
+ while (<SSLS>) {
+ print "$_";
+ }
+ close(SSLS);
+
+
+ print "</pre>\n";
+
+}
+
+else {
+print "<FORM method=post action=$sslcgi>\n";
+print "<hr>
+<h2>Host Name</h2>
+<TABLE BORDER=0 CELLPADDING=20>
+<TR>
+<TD>
+Type hostname here:<br>
+<input type=text name=host size=30>&nbsp;<br><br>
+<TD>
+ <b>Or click these buttons to test some well-known servers</b><br>
+ <TABLE BORDER=0>
+ <TR>
+ <TD>
+ Export servers:
+ <TD>
+ <input type=button value='F-Tech' onclick=dohost(this.form,'strongbox.ftech.net')>
+ </TR>
+ <TR>
+ <TD>
+ Domestic servers:
+ <TD>
+ <input type=button value='Wells Fargo' onclick=dohost(this.form,'banking.wellsfargo.com')>
+ </TR>
+ <TR>
+ <TD>
+ Step-Up Servers
+ <TD>
+ <input type=button value='Barclaycard' onclick=dohost(this.form,'enigma.barclaycard.co.uk')>
+ <input type=button value='BBVnet' onclick=dohost(this.form,'www.bbvnet.com')>&nbsp;
+ <input type=button value='BHIF' onclick=dohost(this.form,'empresas.bhif.cl')>&nbsp;
+ </TR>
+ </TABLE>
+</TR>
+</TABLE>
+<br>
+<hr>
+<br>
+<h2>Encryption policy</h2>
+<input type=radio name=policy VALUE=export onclick=doexport(this.form)>&nbsp;
+Export<br>
+<input type=radio name=policy VALUE=domestic CHECKED onclick=dodomestic(this.form)>&nbsp;
+Domestic<br>
+<br>
+<hr>
+<br>
+<h2>Cipher Selection</h2>
+(use ctrl to multi-select)<br>
+<table>
+<tr>
+<td>SSL 2 Ciphers
+<td>
+<SELECT NAME=ssl2ciphers SIZE=6 MULTIPLE align=bottom>
+<OPTION SELECTED>SSL_EN_RC4_128_WITH_MD5
+<OPTION SELECTED>SSL_EN_RC2_128_CBC_WITH_MD5
+<OPTION SELECTED>SSL_EN_DES_192_EDE3_CBC_WITH_MD5
+<OPTION SELECTED>SSL_EN_DES_64_CBC_WITH_MD5
+<OPTION SELECTED>SSL_EN_RC4_128_EXPORT40_WITH_MD5
+<OPTION SELECTED>SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5
+</SELECT>
+<input type=button Value='Clear all' onclick = 'doclearssl2(this.form)'>
+</tr>
+<tr>
+<td>SSL3 Ciphers
+<td>
+<SELECT NAME=ssl3ciphers SIZE=8 MULTIPLE>
+<OPTION SELECTED>SSL_RSA_WITH_RC4_128_MD5
+<OPTION SELECTED>SSL_RSA_WITH_3DES_EDE_CBC_SHA
+<OPTION SELECTED>SSL_RSA_WITH_DES_CBC_SHA
+<OPTION SELECTED>SSL_RSA_EXPORT_WITH_RC4_40_MD5
+<OPTION SELECTED>SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
+<OPTION SELECTED>SSL_RSA_WITH_NULL_MD5
+<OPTION SELECTED>SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
+<OPTION SELECTED>SSL_RSA_FIPS_WITH_DES_CBC_SHA
+</SELECT>
+<input type=button value='Clear all' onclick = 'doclearssl3(this.form)'>
+
+<TD>
+<input type=submit name=dotest value='Run SSLStrength'>
+</tr>
+</table>
+<input type=hidden name=dotest>
+<br>
+<br>
+</form>
+\n";
+
+}
+
+
+exit(0);
+
+
+__END__
+
+ id CipherName Domestic Export
+ a SSL_EN_RC4_128_WITH_MD5 (ssl2) Yes No
+ b SSL_EN_RC2_128_CBC_WITH_MD5 (ssl2) Yes No
+ c SSL_EN_DES_192_EDE3_CBC_WITH_MD5 (ssl2) Yes No
+ d SSL_EN_DES_64_CBC_WITH_MD5 (ssl2) Yes No
+ e SSL_EN_RC4_128_EXPORT40_WITH_MD5 (ssl2) Yes Yes
+ f SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5 (ssl2) Yes Yes
+ i SSL_RSA_WITH_RC4_128_MD5 (ssl3) Yes Step-up only
+ j SSL_RSA_WITH_3DES_EDE_CBC_SHA (ssl3) Yes Step-up only
+ k SSL_RSA_WITH_DES_CBC_SHA (ssl3) Yes No
+ l SSL_RSA_EXPORT_WITH_RC4_40_MD5 (ssl3) Yes Yes
+ m SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 (ssl3) Yes Yes
+ o SSL_RSA_WITH_NULL_MD5 (ssl3) Yes Yes
+
+
+
diff --git a/security/nss/cmd/sslstrength/sslstrength.c b/security/nss/cmd/sslstrength/sslstrength.c
new file mode 100644
index 000000000..7e8604ed0
--- /dev/null
+++ b/security/nss/cmd/sslstrength/sslstrength.c
@@ -0,0 +1,622 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifdef SSLTELNET
+#include <termios.h>
+#endif
+
+/* Portable layer header files */
+#include "prinit.h"
+#include "prprf.h"
+#include "prsystem.h"
+#include "prmem.h"
+#include "plstr.h"
+#include "prnetdb.h"
+#include "prinrval.h"
+
+#include "secutil.h"
+
+/* Security library files */
+#include "cert.h"
+#include "ssl.h"
+#include "sslproto.h"
+#include "secmod.h"
+#include "nss.h"
+
+/* define this if you want telnet capability! */
+
+/* #define SSLTELNET 1 */
+
+PRInt32 debug;
+
+#ifdef DEBUG_stevep
+#define dbmsg(x) if (verbose) PR_fprintf(PR_STDOUT,x);
+#else
+#define dbmsg(x) ;
+#endif
+
+
+/* Set SSL Policy to Domestic (strong=1) or Export (strong=0) */
+
+#define ALLOW(x) SSL_CipherPolicySet(x,SSL_ALLOWED); SSL_CipherPrefSetDefault(x,1);
+#define DISALLOW(x) SSL_CipherPolicySet(x,SSL_NOT_ALLOWED); SSL_CipherPrefSetDefault(x,0);
+#define MAYBEALLOW(x) SSL_CipherPolicySet(x,SSL_RESTRICTED); SSL_CipherPrefSetDefault(x,1);
+
+struct CipherPolicy {
+ char number;
+ long id;
+ char *name;
+ PRInt32 pref;
+ PRInt32 domestic;
+ PRInt32 export;
+};
+
+struct CipherPolicy ciphers[] = {
+ { 'a',SSL_EN_RC4_128_WITH_MD5, "SSL_EN_RC4_128_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
+ { 'b',SSL_EN_RC2_128_CBC_WITH_MD5, "SSL_EN_RC2_128_CBC_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
+ { 'c',SSL_EN_DES_192_EDE3_CBC_WITH_MD5, "SSL_EN_DES_192_EDE3_CBC_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
+ { 'd',SSL_EN_DES_64_CBC_WITH_MD5, "SSL_EN_DES_64_CBC_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
+ { 'e',SSL_EN_RC4_128_EXPORT40_WITH_MD5, "SSL_EN_RC4_128_EXPORT40_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_ALLOWED },
+ { 'f',SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, "SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5 (ssl2)",1, SSL_ALLOWED,SSL_ALLOWED },
+#ifdef FORTEZZA
+ { 'g',SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA",1,SSL_ALLOWED,SSL_NOT_ALLOWED },
+ { 'h',SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, "SSL_FORTEZZA_DMS_WITH_RC4_128_SHA",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
+#endif
+ { 'i',SSL_RSA_WITH_RC4_128_MD5, "SSL_RSA_WITH_RC4_128_MD5 (ssl3)",1, SSL_ALLOWED,SSL_RESTRICTED },
+ { 'j',SSL_RSA_WITH_3DES_EDE_CBC_SHA, "SSL_RSA_WITH_3DES_EDE_CBC_SHA (ssl3)",1, SSL_ALLOWED,SSL_RESTRICTED },
+ { 'k',SSL_RSA_WITH_DES_CBC_SHA, "SSL_RSA_WITH_DES_CBC_SHA (ssl3)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
+ { 'l',SSL_RSA_EXPORT_WITH_RC4_40_MD5, "SSL_RSA_EXPORT_WITH_RC4_40_MD5 (ssl3)",1, SSL_ALLOWED,SSL_ALLOWED },
+ { 'm',SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 (ssl3)",1, SSL_ALLOWED,SSL_ALLOWED },
+#ifdef FORTEZZA
+ { 'n',SSL_FORTEZZA_DMS_WITH_NULL_SHA, "SSL_FORTEZZA_DMS_WITH_NULL_SHA",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
+#endif
+ { 'o',SSL_RSA_WITH_NULL_MD5, "SSL_RSA_WITH_NULL_MD5 (ssl3)",1, SSL_ALLOWED,SSL_ALLOWED },
+ { 'p',SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA (ssl3)",1, SSL_ALLOWED,SSL_NOT_ALLOWED },
+ { 'q',SSL_RSA_FIPS_WITH_DES_CBC_SHA, "SSL_RSA_FIPS_WITH_DES_CBC_SHA (ssl3)",1, SSL_ALLOWED,SSL_NOT_ALLOWED }
+
+};
+
+void PrintErrString(char *progName,char *msg) {
+
+ PRErrorCode e = PORT_GetError();
+ char *s=NULL;
+
+
+ if ((e >= PR_NSPR_ERROR_BASE) && (e < PR_MAX_ERROR)) {
+
+ if (e == PR_DIRECTORY_LOOKUP_ERROR)
+ s = PL_strdup("Hostname Lookup Failed");
+ else if (e == PR_NETWORK_UNREACHABLE_ERROR)
+ s = PL_strdup("Network Unreachable");
+ else if (e == PR_CONNECT_TIMEOUT_ERROR)
+ s = PL_strdup("Connection Timed Out");
+ else s = PR_smprintf("%d",e);
+
+ if (!s) return;
+ }
+ else {
+ s = PL_strdup(SECU_ErrorString(e));
+ }
+
+ PR_fprintf(PR_STDOUT,"%s: ",progName);
+ if (s) {
+ if (*s)
+ PR_fprintf(PR_STDOUT, "%s\n", s);
+ else
+ PR_fprintf(PR_STDOUT, "\n");
+
+ PR_Free(s);
+ }
+
+}
+
+void PrintCiphers(int onlyenabled) {
+ int ciphercount,i;
+
+ if (onlyenabled) {
+ PR_fprintf(PR_STDOUT,"Your Cipher preference:\n");
+ }
+
+ ciphercount = sizeof(ciphers)/sizeof(struct CipherPolicy);
+ PR_fprintf(PR_STDOUT,
+ " %s %-45s %-12s %-12s\n","id","CipherName","Domestic","Export");
+
+ for (i=0;i<ciphercount;i++) {
+ if ( (onlyenabled ==0) || ((onlyenabled==1)&&(ciphers[i].pref))) {
+ PR_fprintf(PR_STDOUT,
+ " %c %-45s %-12s %-12s\n",ciphers[i].number,ciphers[i].name,
+ (ciphers[i].domestic==SSL_ALLOWED)?"Yes":
+ ( (ciphers[i].domestic==SSL_NOT_ALLOWED)?"No":"Step-up only"),
+ (ciphers[i].export==SSL_ALLOWED)?"Yes":
+ ( (ciphers[i].export==SSL_NOT_ALLOWED)?"No":"Step-up only"));
+ }
+ }
+}
+
+
+void SetPolicy(char *c,int policy) { /* policy==1 : domestic, policy==0, export */
+ int i,j,cpolicy;
+ /* first, enable all relevant ciphers according to policy */
+ for (j=0;j<(sizeof(ciphers)/sizeof(struct CipherPolicy));j++) {
+ SSL_CipherPolicySet(ciphers[j].id,policy?ciphers[j].domestic:ciphers[j].export);
+ SSL_CipherPrefSetDefault(ciphers[j].id, PR_FALSE);
+ ciphers[j].pref =0;
+ }
+
+
+ for (i=0;i<(int)PL_strlen(c);i++) {
+ for (j=0;j<(sizeof(ciphers)/sizeof(struct CipherPolicy));j++) {
+ if (ciphers[j].number == c[i]) {
+ cpolicy = policy?ciphers[j].domestic:ciphers[j].export;
+ if (cpolicy == SSL_NOT_ALLOWED) {
+ PR_fprintf(PR_STDOUT, "You're trying to enable a cipher (%c:%s) outside of your policy. ignored\n",
+ c[i],ciphers[j].name);
+ }
+ else {
+ ciphers[j].pref=1;
+ SSL_CipherPrefSetDefault(ciphers[j].id, PR_TRUE);
+ }
+ }
+ }
+ }
+}
+
+
+int MyAuthCertificateHook(void *arg, PRFileDesc *fd, PRBool checksig, PRBool isserver) {
+ return SECSuccess;
+}
+
+
+void Usage() {
+#ifdef SSLTELNET
+ PR_fprintf(PR_STDOUT,"SSLTelnet ");
+#else
+ PR_fprintf(PR_STDOUT,"SSLStrength (No telnet functionality) ");
+#endif
+ PR_fprintf(PR_STDOUT,"Version 1.5\n");
+
+ PR_fprintf(PR_STDOUT,"Usage:\n sslstrength hostname[:port] [ciphers=xyz] [certdir=x] [debug] [verbose] "
+#ifdef SSLTELNET
+"[telnet]|[servertype]|[querystring=<string>] "
+#endif
+"[policy=export|domestic]\n sslstrength ciphers\n");
+}
+
+
+PRInt32 debug = 0;
+PRInt32 verbose = 0;
+
+PRInt32 main(PRInt32 argc,char **argv, char **envp)
+{
+
+
+ /* defaults for command line arguments */
+ char *hostnamearg=NULL;
+ char *portnumarg=NULL;
+ char *sslversionarg=NULL;
+ char *keylenarg=NULL;
+ char *certdir=NULL;
+ char *hostname;
+ char *nickname=NULL;
+ char *progname=NULL;
+ /* struct sockaddr_in addr; */
+ PRNetAddr addr;
+
+ int ss_on;
+ char *ss_cipher;
+ int ss_keysize;
+ int ss_secretsize;
+ char *ss_issuer;
+ char *ss_subject;
+ int policy=1;
+ char *set_ssl_policy=NULL;
+ int print_ciphers=0;
+
+ char buf[10];
+ char netdbbuf[PR_NETDB_BUF_SIZE];
+ PRHostEnt hp;
+ PRStatus r;
+ PRNetAddr na;
+ SECStatus rv;
+ int portnum=443; /* default https: port */
+ PRFileDesc *s,*fd;
+
+ CERTCertDBHandle *handle;
+ CERTCertificate *c;
+ PRInt32 i;
+#ifdef SSLTELNET
+ struct termios tmp_tc;
+ char cb;
+ int prev_lflag,prev_oflag,prev_iflag;
+ int t_fin,t_fout;
+ int servertype=0, telnet=0;
+ char *querystring=NULL;
+#endif
+
+ debug = 0;
+
+ progname = (char *)PL_strrchr(argv[0], '/');
+ progname = progname ? progname+1 : argv[0];
+
+ /* Read in command line args */
+ if (argc == 1) {
+ Usage();
+ return(0);
+ }
+
+ if (! PL_strcmp("ciphers",argv[1])) {
+ PrintCiphers(0);
+ exit(0);
+ }
+
+ hostname = argv[1];
+
+ if (!PL_strcmp(hostname , "usage") || !PL_strcmp(hostname, "-help") ) {
+ Usage();
+ exit(0);
+ }
+
+ if ((portnumarg = PL_strchr(hostname,':'))) {
+ *portnumarg = 0;
+ portnumarg = &portnumarg[1];
+ }
+
+ if (portnumarg) {
+ if (*portnumarg == 0) {
+ PR_fprintf(PR_STDOUT,"malformed port number supplied\n");
+ return(1);
+ }
+ portnum = atoi(portnumarg);
+ }
+
+ for (i = 2 ; i < argc; i++)
+ {
+ if (!PL_strncmp(argv[i] , "sslversion=",11) )
+ sslversionarg=&(argv[i][11]);
+ else if (!PL_strncmp(argv[i], "certdir=",8) )
+ certdir = &(argv[i][8]);
+ else if (!PL_strncmp(argv[i], "ciphers=",8) )
+ {
+ set_ssl_policy=&(argv[i][8]);
+ }
+ else if (!PL_strncmp(argv[i], "policy=",7) ) {
+ if (!PL_strcmp(&(argv[i][7]),"domestic")) policy=1;
+ else if (!PL_strcmp(&(argv[i][7]),"export")) policy=0;
+ else {
+ PR_fprintf(PR_STDOUT,"sslstrength: invalid argument. policy must be one of (domestic,export)\n");
+ }
+ }
+ else if (!PL_strcmp(argv[i] , "debug") )
+ debug = 1;
+#ifdef SSLTELNET
+ else if (!PL_strcmp(argv[i] , "telnet") )
+ telnet = 1;
+ else if (!PL_strcmp(argv[i] , "servertype") )
+ servertype = 1;
+ else if (!PL_strncmp(argv[i] , "querystring=",11) )
+ querystring = &argv[i][12];
+#endif
+ else if (!PL_strcmp(argv[i] , "verbose") )
+ verbose = 1;
+ }
+
+#ifdef SSLTELNET
+ if (telnet && (servertype || querystring)) {
+ PR_fprintf(PR_STDOUT,"You can't use telnet and (server or querystring) options at the same time\n");
+ exit(1);
+ }
+#endif
+
+ PR_fprintf(PR_STDOUT,"Using %s policy\n",policy?"domestic":"export");
+
+ /* allow you to set env var SSLDIR to set the cert directory */
+ if (! certdir) certdir = SECU_DefaultSSLDir();
+
+ /* if we don't have one still, initialize with no databases */
+ if (!certdir) {
+ rv = NSS_NoDB_Init(NULL);
+
+ (void) SECMOD_AddNewModule("Builtins", DLL_PREFIX"nssckbi."DLL_SUFFIX,0,0);
+ } else {
+ rv = NSS_Init(certdir);
+ SECU_ConfigDirectory(certdir);
+ }
+
+ /* Lookup host */
+ r = PR_GetHostByName(hostname,netdbbuf,PR_NETDB_BUF_SIZE,&hp);
+
+ if (r) {
+ PrintErrString(progname,"Host Name lookup failed");
+ return(1);
+ }
+
+ /* should the third field really be 0? */
+
+ PR_EnumerateHostEnt(0,&hp,0,&na);
+ PR_InitializeNetAddr(PR_IpAddrNull,portnum,&na);
+
+ PR_fprintf(PR_STDOUT,"Connecting to %s:%d\n",hostname, portnum);
+
+ /* Create socket */
+
+ fd = PR_NewTCPSocket();
+ if (fd == NULL) {
+ PrintErrString(progname, "error creating socket");
+ return -1;
+ }
+
+ s = SSL_ImportFD(NULL,fd);
+ if (s == NULL) {
+ PrintErrString(progname, "error creating socket");
+ return -1;
+ }
+
+ dbmsg("10: About to enable security\n");
+
+ rv = SSL_OptionSet(s, SSL_SECURITY, PR_TRUE);
+ if (rv < 0) {
+ PrintErrString(progname, "error enabling socket");
+ return -1;
+ }
+
+ if (set_ssl_policy) {
+ SetPolicy(set_ssl_policy,policy);
+ }
+ else {
+ PR_fprintf(PR_STDOUT,"Using all ciphersuites usually found in client\n");
+ if (policy) {
+ SetPolicy("abcdefghijklmnopqrst",policy);
+ }
+ else {
+ SetPolicy("efghijlmo",policy);
+ }
+ }
+
+ PrintCiphers(1);
+
+ rv = SSL_OptionSet(s, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
+ if (rv < 0) {
+ PrintErrString(progname, "error enabling client handshake");
+ return -1;
+ }
+
+ dbmsg("30: About to set AuthCertificateHook\n");
+
+
+ SSL_AuthCertificateHook(s, MyAuthCertificateHook, (void *)handle);
+ /* SSL_AuthCertificateHook(s, SSL_AuthCertificate, (void *)handle); */
+ /* SSL_GetClientAuthDataHook(s, GetClientAuthDataHook, (void *)nickname);*/
+
+
+ dbmsg("40: About to SSLConnect\n");
+
+ /* Try to connect to the server */
+ /* now SSL_Connect takes new arguments. */
+
+
+ r = PR_Connect(s, &na, PR_TicksPerSecond()*5);
+ if (r < 0) {
+ PrintErrString(progname, "unable to connect");
+ return -1;
+ }
+
+ rv = SSL_ForceHandshake(s);
+
+ if (rv) {
+ PrintErrString(progname,"SSL Handshake failed. ");
+ exit(1);
+ }
+
+ rv = SSL_SecurityStatus(s, &ss_on, &ss_cipher,
+ &ss_keysize, &ss_secretsize,
+ &ss_issuer, &ss_subject);
+
+
+ dbmsg("60: done with security status, about to print\n");
+
+ c = SSL_PeerCertificate(s);
+ if (!c) PR_fprintf(PR_STDOUT,"Couldn't retrieve peers Certificate\n");
+ PR_fprintf(PR_STDOUT,"SSL Connection Status\n",rv);
+
+ PR_fprintf(PR_STDOUT," Cipher: %s\n",ss_cipher);
+ PR_fprintf(PR_STDOUT," Key Size: %d\n",ss_keysize);
+ PR_fprintf(PR_STDOUT," Secret Key Size: %d\n",ss_secretsize);
+ PR_fprintf(PR_STDOUT," Issuer: %s\n",ss_issuer);
+ PR_fprintf(PR_STDOUT," Subject: %s\n",ss_subject);
+
+ PR_fprintf(PR_STDOUT," Valid: from %s to %s\n",
+ c==NULL?"???":DER_UTCDayToAscii(&c->validity.notBefore),
+ c==NULL?"???":DER_UTCDayToAscii(&c->validity.notAfter));
+
+#ifdef SSLTELNET
+
+
+
+
+ if (servertype || querystring) {
+ char buffer[1024];
+ char ch;
+ char qs[] = "HEAD / HTTP/1.0";
+
+
+
+
+ if (!querystring) querystring = qs;
+ PR_fprintf(PR_STDOUT,"\nServer query mode\n>>Sending:\n%s\n",querystring);
+
+ PR_fprintf(PR_STDOUT,"\n*** Server said:\n");
+ ch = querystring[PL_strlen(querystring)-1];
+ if (ch == '"' || ch == '\'') {
+ PR_fprintf(PR_STDOUT,"Warning: I'm not smart enough to cope with quotes mid-string like that\n");
+ }
+
+ rv = PR_Write(s,querystring,PL_strlen(querystring));
+ if ((rv < 1) ) {
+ PR_fprintf(PR_STDOUT,"Oh dear - couldn't send servertype query\n");
+ goto closedown;
+ }
+
+ rv = PR_Write(s,"\r\n\r\n",4);
+ rv = PR_Read(s,buffer,1024);
+ if ((rv < 1) ) {
+ PR_fprintf(PR_STDOUT,"Oh dear - couldn't read server repsonse\n");
+ goto closedown;
+ }
+ PR_Write(PR_STDOUT,buffer,rv);
+ }
+
+
+ if (telnet) {
+
+ PR_fprintf(PR_STDOUT,"---------------------------\n"
+ "telnet mode. CTRL-C to exit\n"
+ "---------------------------\n");
+
+
+
+ /* fudge terminal attributes */
+ t_fin = PR_FileDesc2NativeHandle(PR_STDIN);
+ t_fout = PR_FileDesc2NativeHandle(PR_STDOUT);
+
+ tcgetattr(t_fin,&tmp_tc);
+ prev_lflag = tmp_tc.c_lflag;
+ prev_oflag = tmp_tc.c_oflag;
+ prev_iflag = tmp_tc.c_iflag;
+ tmp_tc.c_lflag &= ~ECHO;
+ /* tmp_tc.c_oflag &= ~ONLCR; */
+ tmp_tc.c_lflag &= ~ICANON;
+ tmp_tc.c_iflag &= ~ICRNL;
+ tmp_tc.c_cflag |= CS8;
+ tmp_tc.c_cc[VMIN] = 1;
+ tmp_tc.c_cc[VTIME] = 0;
+
+ tcsetattr(t_fin, TCSANOW, &tmp_tc);
+ /* ioctl(tin, FIONBIO, (char *)&onoff);
+ ioctl(tout, FIONBIO, (char *)&onoff);*/
+
+
+ {
+ PRPollDesc pds[2];
+ char buffer[1024];
+ int amt,amtwritten;
+ char *x;
+
+ /* STDIN */
+ pds[0].fd = PR_STDIN;
+ pds[0].in_flags = PR_POLL_READ;
+ pds[1].fd = s;
+ pds[1].in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
+
+ while (1) {
+ int nfds;
+
+ nfds = PR_Poll(pds,2,PR_SecondsToInterval(2));
+ if (nfds == 0) continue;
+
+ /** read input from keyboard*/
+ /* note: this is very inefficient if reading from a file */
+
+ if (pds[0].out_flags & PR_POLL_READ) {
+ amt = PR_Read(PR_STDIN,&buffer,1);
+ /* PR_fprintf(PR_STDOUT,"fd[0]:%d=%d\r\n",amt,buffer[0]); */
+ if (amt == 0) {
+ PR_fprintf(PR_STDOUT,"\n");
+ goto loser;
+ }
+
+ if (buffer[0] == '\r') {
+ buffer[0] = '\r';
+ buffer[1] = '\n';
+ amt = 2;
+ }
+ rv = PR_Write(PR_STDOUT,buffer,amt);
+
+
+ rv = PR_Write(s,buffer,amt);
+ if (rv == -1) {
+ PR_fprintf(PR_STDOUT,"Error writing to socket: %d\n",PR_GetError());
+ }
+ }
+
+ /***/
+
+
+ /***/
+ if (pds[1].out_flags & PR_POLL_EXCEPT) {
+ PR_fprintf(PR_STDOUT,"\r\nServer closed connection\r\n");
+ goto loser;
+ }
+ if (pds[1].out_flags & PR_POLL_READ) {
+ amt = PR_Read(s,&buffer,1024);
+
+ if (amt == 0) {
+ PR_fprintf(PR_STDOUT,"\r\nServer closed connection\r\n");
+ goto loser;
+ }
+ rv = PR_Write(PR_STDOUT,buffer,amt);
+ }
+ /***/
+
+ }
+ }
+ loser:
+
+ /* set terminal back to normal */
+ tcgetattr(t_fin,&tmp_tc);
+
+ tmp_tc.c_lflag = prev_lflag;
+ tmp_tc.c_oflag = prev_oflag;
+ tmp_tc.c_iflag = prev_iflag;
+ tcsetattr(t_fin, TCSANOW, &tmp_tc);
+
+ /* ioctl(tin, FIONBIO, (char *)&onoff);
+ ioctl(tout, FIONBIO, (char *)&onoff); */
+ }
+
+#endif
+ /* SSLTELNET */
+
+ closedown:
+
+ PR_Close(s);
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return(0);
+
+} /* main */
+
+/*EOF*/
+
diff --git a/security/nss/cmd/sslstrength/sslwrap b/security/nss/cmd/sslstrength/sslwrap
new file mode 100755
index 000000000..e6955dc92
--- /dev/null
+++ b/security/nss/cmd/sslstrength/sslwrap
@@ -0,0 +1,181 @@
+#!/usr/bin/perl
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+
+@profiles = (
+# "host:port" "policy" "ciphers" "exp-cipher" "expkeysize"
+
+ [ "cfu:443", "export", "efijlmo", "RC4-40", "40" ],
+ [ "hbombsgi:448", "export", "efijlmo", "RC4-40", "40" ],
+ [ "hbombsgi:448", "domestic", "abcdefijklmo", "RC4", "128" ],
+ [ "gandalf:5666", "domestic", "abcdefijklmo", "RC4", "128" ],
+ [ "gandalf:5666", "export", "efijlmo", "RC4", "128" ],
+ [ "gandalf:5666", "domestic", "j", "3DES-EDE-CBC", "168" ],
+ [ "gandalf:5666", "domestic", "k", "DES-CBC", "56" ],
+ [ "gandalf:5666", "export", "l", "RC4-40", "40" ],
+ [ "gandalf:5666", "export", "efijlmo", "RC4", "128" ],
+ [ "hbombcfu:443", "export", "efijlmo", "RC4", "128" ],
+
+ );
+
+$file = &filename;
+
+open(HTML, ">$file.htm") || die"Cannot open html output file\n";
+
+$mutversion = "";
+$platform = $ARGV[0];
+
+
+print HTML
+"<HTML><HEAD>
+<TITLE>ssl/sslstrength: Version: $mutversion Platform: $platform Run date mm/dd/yy</TITLE></HEAD><BODY>\n";
+
+print HTML
+"<TABLE BORDER=1><TR>
+<TD><B>Test Case Number</B></TD>
+<TD><B>Program</B></TD>
+<TD><B>Description of Test Case</B></TD>
+<TD><B>Start date/time<B></TD>
+<TD><B>End date/time<B></TD>
+<TD><B>PASS/FAIL</B></TD>
+</TR>\n";
+
+$countpass =0;
+$countfail =0;
+
+
+$testnum =0;
+for $profile (@profiles) {
+ $testnum ++;
+ ($host, $policy, $ciphers, $expcipher, $expkeysize) = @$profile;
+
+ $cmd = "./sslstrength $host policy=$policy ciphers=$ciphers";
+
+ $starttime = &datestring." ".&timestring;
+ print STDERR "$cmd\n";
+ open(PIPE, "$cmd|") || die "Cannot start sslstrength\n";
+
+ $cipher = "";
+ $keysize = "";
+ while (<PIPE>) {
+ chop;
+ if (/^ Cipher: *(.*)/) {
+ $cipher = $1;
+ }
+ if (/^ Secret Key Size: (.*)/) {
+ $keysize = $1;
+ }
+ }
+ close(PIPE);
+ $endtime = &datestring." ".&timestring;
+
+ if (( $? != 0) || ($cipher ne $expcipher) || ($keysize ne $expkeysize)) {
+ $countfail ++;
+ $passed =0;
+ }
+ else {
+ $countpass ++;
+ $passed =1;
+ }
+
+print HTML
+"<TR>
+<TD><B>$testnum</B></TD>
+<TD></TD>
+<TD>$cmd</TD>
+<TD>$starttime</TD>
+<TD>$endtime</TD>
+<TD><B>".($passed ? "PASS" : "<FONT COLOR=red>FAIL: return code =
+c=$cipher, ec=$expcipher, s=$keysize, es=$expkeysize.</FONT>")."
+</B></TD>
+</TR>\n";
+
+}
+
+print HTML "</table>\n";
+
+close(HTML);
+
+open (SUM, ">$file.sum") ||die "couldn't open summary file for writing\n";
+
+print SUM <<EOM;
+[Status]
+mut=SSL
+mutversion=1.0
+platform=$platform
+pass=$countpass
+fail=$countfail
+knownFail=0
+malformed=0
+EOM
+
+ close(SUM);
+
+
+
+sub timestring
+{
+
+ my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
+ my $string;
+
+ $string = sprintf "%2d:%02d:%02d",$hour, $min, $sec;
+ return $string;
+}
+
+sub datestring
+{
+
+ my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
+ my $string;
+
+ $string = sprintf "%d/%d/%2d",$mon+1, $mday+1, $year;
+ return $string;
+}
+
+sub filename
+{
+
+ my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
+ my $string;
+
+ $string = sprintf "%04d%02d%02d",$year+1900, $mon+1, $mday;
+ return $string;
+}
+
+
+
+
+
+
diff --git a/security/nss/cmd/ssltap/Makefile b/security/nss/cmd/ssltap/Makefile
new file mode 100644
index 000000000..f6d8cc93e
--- /dev/null
+++ b/security/nss/cmd/ssltap/Makefile
@@ -0,0 +1,79 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+# Since ssltap doesn't use any of NSS, we'll skip NSS's link libs,
+# and just link with NSPR.
+#
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
+-include ../platrules.mk
+
diff --git a/security/nss/cmd/ssltap/config.mk b/security/nss/cmd/ssltap/config.mk
new file mode 100644
index 000000000..23b15fbd5
--- /dev/null
+++ b/security/nss/cmd/ssltap/config.mk
@@ -0,0 +1,52 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# Set the LDFLAGS value to encompass all normal link options, all #
+# library names, and all special system linking options #
+#######################################################################
+
+LDFLAGS = \
+ $(DYNAMIC_LIB_PATH) \
+ $(LDOPTS) \
+ $(LIBPLC) \
+ $(LIBPR) \
+ $(DLLSYSTEM)
+
+#######################################################################
+# Adjust specific variables for all platforms #
+#######################################################################
+
+OS_CFLAGS += -DNSPR20=1
+
+
diff --git a/security/nss/cmd/ssltap/manifest.mn b/security/nss/cmd/ssltap/manifest.mn
new file mode 100644
index 000000000..adfd2bd03
--- /dev/null
+++ b/security/nss/cmd/ssltap/manifest.mn
@@ -0,0 +1,51 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+EXPORTS =
+
+CSRCS = ssltap.c \
+ $(NULL)
+
+PROGRAM = ssltap
+
+REQUIRES = seccmd dbm
+
+PACKAGE_FILES = ssltap-manual.html licence.doc ssltap.exe
+
+ARCHIVE_NAME = ssltap
+
diff --git a/security/nss/cmd/ssltap/ssltap-manual.html b/security/nss/cmd/ssltap/ssltap-manual.html
new file mode 100644
index 000000000..28c9e17ee
--- /dev/null
+++ b/security/nss/cmd/ssltap/ssltap-manual.html
@@ -0,0 +1,199 @@
+<HTML>
+<!--
+ - The contents of this file are subject to the Mozilla Public
+ - License Version 1.1 (the "License"); you may not use this file
+ - except in compliance with the License. You may obtain a copy of
+ - the License at http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS
+ - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ - implied. See the License for the specific language governing
+ - rights and limitations under the License.
+ -
+ - The Original Code is the Netscape security libraries.
+ -
+ - The Initial Developer of the Original Code is Netscape
+ - Communications Corporation. Portions created by Netscape are
+ - Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ - Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the
+ - terms of the GNU General Public License Version 2 or later (the
+ - "GPL"), in which case the provisions of the GPL are applicable
+ - instead of those above. If you wish to allow use of your
+ - version of this file only under the terms of the GPL and not to
+ - allow others to use your version of this file under the MPL,
+ - indicate your decision by deleting the provisions above and
+ - replace them with the notice and other provisions required by
+ - the GPL. If you do not delete the provisions above, a recipient
+ - may use your version of this file under either the MPL or the
+ - GPL.
+ -->
+<HEAD>
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+ <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (WinNT; U) [Netscape]">
+ <META NAME="Author" CONTENT="Steve Parkinson">
+ <TITLE>SSLTap - manual</TITLE>
+</HEAD>
+<BODY>
+
+<H1>
+SSLTap Manual page</H1>
+
+<H3>
+Summary</H3>
+A command-line proxy which is SSL-aware. It snoops on TCP connections,
+and displays the data going by, including SSL records and handshaking&nbsp;
+if the connection is SSL.
+<H3>
+Synopsis</H3>
+<TT>ssltap [-vhfsxl] [-p port] hostname:port</TT>
+
+<P><TT>&nbsp;&nbsp; -v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [prints version string]</TT>
+<BR><TT>&nbsp;&nbsp; -h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [outputs hex instead
+of ASCII]</TT>
+<BR><TT>&nbsp;&nbsp; -f&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [turn on Fancy HTML
+coloring]</TT>
+<BR><TT>&nbsp;&nbsp; -s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [turn on SSL decoding]</TT>
+<BR><TT>&nbsp;&nbsp; -x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [turn on extra SSL
+hex dumps]</TT>
+<BR><TT>&nbsp;&nbsp; -p port [specify rendezvous port (default 1924)]</TT>
+<BR><TT>&nbsp;&nbsp; -l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [loop - continue
+to wait for more connections]</TT>
+<H3>
+Description</H3>
+SSLTap opens a socket on a rendezvous port, and waits for an incoming connection
+(client side). Once this connection arrives, SSLTap makes another connection
+to hostname:port (server side). It passes any data sent by the client to
+the server, and vice versa. However, SSLTap will also display the data
+to the console. It can do this for plain HTTP connections, or any TCP protocol.
+However, SSLTap can also work with SSL streams, as detailed below.
+
+<P>Let's assume your development machine is called 'intercept'. The simplest
+usage of SSLTap is to run the command <TT>'ssltap www.netscape.com:80'</TT>
+on intercept. The program will wait for an incoming connection on port
+1924. Next you would want to go to your browser, and enter the URL http://intercept:1924.
+The page retrieved by the browser will actually be gotten from the server
+at www.netscape.com, but will go via SSLTap.
+
+<P>Data sent from the client to the server is surrounded by a '--> [ ]'
+symbol, and data sent from the server to the client, a '&lt;---[&nbsp;
+]' symbol.
+
+<P>You'll notice that the page retrieved with this example looks incomplete.
+This is because SSLTap by default closes down after the first connection
+is complete, so the browser is not able to load images. To make the SSLTap
+continue to accept connections, switch on looping mode with the -l option.
+
+<P>You can change the default rendezvous port to something else with the
+-p option.
+
+<P>The remaining options change the way the output is produced.
+
+<P>The -f option prints 'fancy' output - in colored HTML. Data sent from
+the client to the server is in blue. The server's reply is in red. This
+is designed so you can load the output up into a browser. When used with
+looping mode, the different connections are separated with horizontal lines.
+
+<P>-x will turn on HEX printing. Instead of being output as ascii, the
+data is shown as Hex, like this:
+<UL><TT>&lt;-- [</TT>
+<BR><TT>&nbsp;&nbsp; 0: 56 d5 16 3e&nbsp; a1 6b b1 4a&nbsp; 8f 67 c4 d7&nbsp;
+21 2f 6f dd&nbsp; | V..>.k.J.g..!/o.</TT>
+<BR><TT>&nbsp; 10: bb 22 c4 75&nbsp; 8c f4 ce 28&nbsp; 16 a6 20 aa&nbsp;
+fb 9a 59 a1&nbsp; | .".u...(.. ...Y.</TT>
+<BR><TT>&nbsp; 20: 51 91 14 d2&nbsp; fc 9f a7 ea&nbsp; 4d 9c f7 3a&nbsp;
+9d 83 62 4a&nbsp; | Q.......M..:..bJ</TT>
+<BR><TT>]</TT>
+<BR>&nbsp;</UL>
+
+<H4>
+SSL Parse mode</H4>
+The following options deal with SSL connections.
+<UL>-s will turn on SSL parsing. (SSLTap doesn't automatically detect SSL
+sessions.)
+<BR>-x will turn on extra SSL hexdumps. Mostly, if SSL can decode the data,
+it doesn't display the hex.</UL>
+The following SSL3 Data structures are parsed: Handshake, ClientHello,
+ServerHello, CertificateChain, Certificate. In addition, SSL2 ClientHello,
+ServerHello, ClientMasterKey are also partly parsed. NO DECRYPTION IS PERFORMED
+ON THE DATA. SSLTAP CANNOT DECRYPT the data.
+
+<P>If a certificate chain is detected, DER-encoded certificates will be
+saved into files in the current directory called 'cert.0x' where x is the
+sequence number of the certificate.
+<BR>&nbsp;
+<H3>
+Operation Hints</H3>
+Often, you'll find that the server certificate does not get transferred,
+or other parts of the handshake do not happen. This is because the browser
+is taking advantage of session-id-reuse (using the handshake results from
+a previous session). If you restart the browser, it'll clear the session
+id cache.
+
+<P>If you run the ssltap on a different machine that the ssl server you're
+trying to connect to, the browser will complain that the host name you're
+trying to connect to is different to the certificate, but it will still
+let you connect, after showing you a dialog.
+<H3>
+Bugs</H3>
+Please contact <A HREF="mailto:ssltap-support@netscape.com">ssltap-support@netscape.com</A>
+for bug reports.
+<H3>
+History</H3>
+2.1 - First public release (March 1998)
+<BR>&nbsp;
+<H3>
+Other</H3>
+For reference, here is a table of some well-known port numbers:
+<BR>&nbsp;
+<TABLE BORDER=2 >
+<TR>
+<TD>HTTP</TD>
+
+<TD>80</TD>
+</TR>
+
+<TR>
+<TD>SMTP</TD>
+
+<TD>25</TD>
+</TR>
+
+<TR>
+<TD>HTTPS</TD>
+
+<TD>443</TD>
+</TR>
+
+<TR>
+<TD>FTP</TD>
+
+<TD>21</TD>
+</TR>
+
+<TR>
+<TD>IMAPS</TD>
+
+<TD>993</TD>
+</TR>
+
+<TR>
+<TD>NNTP</TD>
+
+<TD>119</TD>
+</TR>
+
+<TR>
+<TD>NNTPS</TD>
+
+<TD>563</TD>
+</TR>
+</TABLE>
+&nbsp;
+
+<P>&nbsp;
+</BODY>
+</HTML>
diff --git a/security/nss/cmd/ssltap/ssltap.c b/security/nss/cmd/ssltap/ssltap.c
new file mode 100644
index 000000000..daca2949f
--- /dev/null
+++ b/security/nss/cmd/ssltap/ssltap.c
@@ -0,0 +1,1334 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+ * ssltap.c
+ *
+ * Version 1.0 : Frederick Roeber : 11 June 1997
+ * Version 2.0 : Steve Parkinson : 13 November 1997
+ * Version 3.0 : Nelson Bolyard : 22 July 1998
+ * Version 3.1 : Nelson Bolyard : 24 May 1999
+ *
+ * changes in version 2.0:
+ * Uses NSPR20
+ * Shows structure of SSL negotiation, if enabled.
+ *
+ * This "proxies" a socket connection (like a socks tunnel), but displays the
+ * data is it flies by.
+ *
+ * In the code, the 'client' socket is the one on the client side of the
+ * proxy, and the server socket is on the server side.
+ *
+ */
+
+#include "nspr.h"
+#include "plstr.h"
+#include "secutil.h"
+#include <memory.h> /* for memcpy, etc. */
+#include <string.h>
+#include <time.h>
+
+#include "plgetopt.h"
+
+#define VERSIONSTRING "$Revision$ ($Date$) $Author$"
+
+
+struct _DataBufferList;
+struct _DataBuffer;
+
+typedef struct _DataBufferList {
+ struct _DataBuffer *first,*last;
+ int size;
+ int isEncrypted;
+} DataBufferList;
+
+typedef struct _DataBuffer {
+ unsigned char *buffer;
+ int length;
+ int offset; /* offset of first good byte */
+ struct _DataBuffer *next;
+} DataBuffer;
+
+
+DataBufferList
+ clientstream = {NULL, NULL, 0, 0},
+ serverstream = {NULL, NULL, 0, 0};
+
+struct sslhandshake {
+ PRUint8 type;
+ PRUint32 length;
+};
+
+typedef struct _SSLRecord {
+ PRUint8 type;
+ PRUint8 ver_maj,ver_min;
+
+ PRUint8 length[2];
+} SSLRecord;
+
+typedef struct _ClientHelloV2 {
+ PRUint8 length[2];
+ PRUint8 type;
+ PRUint8 version[2];
+ PRUint8 cslength[2];
+ PRUint8 sidlength[2];
+ PRUint8 rndlength[2];
+ PRUint8 csuites[1];
+} ClientHelloV2;
+
+typedef struct _ServerHelloV2 {
+ PRUint8 length[2];
+ PRUint8 type;
+ PRUint8 sidhit;
+ PRUint8 certtype;
+ PRUint8 version[2];
+ PRUint8 certlength[2];
+ PRUint8 cslength[2];
+ PRUint8 cidlength[2];
+} ServerHelloV2;
+
+typedef struct _ClientMasterKeyV2 {
+ PRUint8 length[2];
+ PRUint8 type;
+
+ PRUint8 cipherkind[3];
+ PRUint8 clearkey[2];
+ PRUint8 secretkey[2];
+
+} ClientMasterKeyV2;
+
+
+
+#define TAPBUFSIZ 16384
+
+#define DEFPORT 1924
+#include <ctype.h>
+
+int hexparse=0;
+int sslparse=0;
+int sslhexparse=0;
+int looparound=0;
+int fancy=0;
+int isV2Session=0;
+
+#define GET_SHORT(x) ((PRUint16)(((PRUint16)((PRUint8*)x)[0]) << 8) + ((PRUint16)((PRUint8*)x)[1]))
+#define GET_24(x) ((PRUint32) ( \
+ (((PRUint32)((PRUint8*)x)[0]) << 16) \
+ + \
+ (((PRUint32)((PRUint8*)x)[1]) << 8) \
+ + \
+ (((PRUint32)((PRUint8*)x)[2]) << 0) \
+ ) )
+
+void print_hex(int amt, unsigned char *buf);
+void read_stream_bytes(unsigned char *d, DataBufferList *db, int length);
+
+void myhalt(int dblsize,int collectedsize) {
+
+ while(1) ;
+
+}
+
+const char *get_error_text(int error) {
+ switch (error) {
+ case PR_IO_TIMEOUT_ERROR:
+ return "Timeout";
+ break;
+ case PR_CONNECT_REFUSED_ERROR:
+ return "Connection refused";
+ break;
+ case PR_NETWORK_UNREACHABLE_ERROR:
+ return "Network unreachable";
+ break;
+ case PR_BAD_ADDRESS_ERROR:
+ return "Bad address";
+ break;
+ case PR_CONNECT_RESET_ERROR:
+ return "Connection reset";
+ break;
+ case PR_PIPE_ERROR:
+ return "Pipe error";
+ break;
+ }
+
+ return "";
+}
+
+
+
+
+
+void check_integrity(DataBufferList *dbl) {
+ DataBuffer *db;
+ int i;
+
+ db = dbl->first;
+ i =0;
+ while (db) {
+ i+= db->length - db->offset;
+ db = db->next;
+ }
+ if (i != dbl->size) {
+ myhalt(dbl->size,i);
+ }
+}
+
+/* Free's the DataBuffer at the head of the list and returns the pointer
+ * to the new head of the list.
+ */
+DataBuffer *
+free_head(DataBufferList *dbl)
+{
+ DataBuffer *db = dbl->first;
+ PR_ASSERT(db->offset >= db->length);
+ if (db->offset >= db->length) {
+ dbl->first = db->next;
+ if (dbl->first == NULL) {
+ dbl->last = NULL;
+ }
+ PR_Free(db->buffer);
+ PR_Free(db);
+ db = dbl->first;
+ }
+ return db;
+}
+
+void
+read_stream_bytes(unsigned char *d, DataBufferList *dbl, int length) {
+ int copied = 0;
+ DataBuffer *db = dbl->first;
+
+ if (!db) {
+ PR_fprintf(PR_STDERR,"assert failed - dbl->first is null\n");
+ exit(8);
+ }
+ while (length) {
+ int toCopy;
+ /* find the number of bytes to copy from the head buffer */
+ /* if there's too many in this buffer, then only copy 'length' */
+ toCopy = PR_MIN(db->length - db->offset, length);
+
+ memcpy(d + copied, db->buffer + db->offset, toCopy);
+ copied += toCopy;
+ db->offset += toCopy;
+ length -= toCopy;
+ dbl->size -= toCopy;
+
+ /* if we emptied the head buffer */
+ if (db->offset >= db->length) {
+ db = free_head(dbl);
+ }
+ }
+
+ check_integrity(dbl);
+
+}
+
+void
+flush_stream(DataBufferList *dbl)
+{
+ DataBuffer *db = dbl->first;
+ check_integrity(dbl);
+ while (db) {
+ db->offset = db->length;
+ db = free_head(dbl);
+ }
+ dbl->size = 0;
+ check_integrity(dbl);
+}
+
+
+const char * V2CipherString(int cs_int) {
+ char *cs_str;
+ cs_str = NULL;
+ switch (cs_int) {
+
+ case 0x010080: cs_str = "SSL2/RSA/RC4-128/MD5"; break;
+ case 0x020080: cs_str = "SSL2/RSA/RC4-40/MD5"; break;
+ case 0x030080: cs_str = "SSL2/RSA/RC2CBC128/MD5"; break;
+ case 0x040080: cs_str = "SSL2/RSA/RC2CBC40/MD5"; break;
+ case 0x050080: cs_str = "SSL2/RSA/IDEA128CBC/MD5"; break;
+ case 0x060040: cs_str = "SSL2/RSA/DES56-CBC/MD5"; break;
+ case 0x0700C0: cs_str = "SSL2/RSA/3DES192EDE-CBC/MD5"; break;
+
+ case 0x000001: cs_str = "SSL3/RSA/NULL/MD5"; break;
+ case 0x000002: cs_str = "SSL3/RSA/NULL/SHA"; break;
+ case 0x000003: cs_str = "SSL3/RSA/RC4-40/MD5"; break;
+ case 0x000004: cs_str = "SSL3/RSA/RC4-128/MD5"; break;
+ case 0x000005: cs_str = "SSL3/RSA/RC4-128/SHA"; break;
+ case 0x000006: cs_str = "SSL3/RSA/RC2CBC40/MD5"; break;
+ case 0x000007: cs_str = "SSL3/RSA/IDEA128CBC/SHA"; break;
+ case 0x000008: cs_str = "SSL3/RSA/DES40-CBC/SHA"; break;
+ case 0x000009: cs_str = "SSL3/RSA/DES56-CBC/SHA"; break;
+ case 0x00000A: cs_str = "SSL3/RSA/3DES192EDE-CBC/SHA"; break;
+
+ case 0x00000B: cs_str = "SSL3/DH-DSS/DES40-CBC/SHA"; break;
+ case 0x00000C: cs_str = "SSL3/DH_DSS/DES56-CBC/SHA"; break;
+ case 0x00000D: cs_str = "SSL3/DH-DSS/DES192EDE3CBC/SHA"; break;
+ case 0x00000E: cs_str = "SSL3/DH-RSA/DES40-CBC/SHA"; break;
+ case 0x00000F: cs_str = "SSL3/DH_RSA/DES56-CBC/SHA"; break;
+ case 0x000010: cs_str = "SSL3/DH-RSA/3DES192EDE-CBC/SHA"; break;
+
+ case 0x000011: cs_str = "SSL3/DHE-DSS/DES40-CBC/SHA"; break;
+ case 0x000012: cs_str = "SSL3/DHE_DSS/DES56-CBC/SHA"; break;
+ case 0x000013: cs_str = "SSL3/DHE-DSS/DES192EDE3CBC/SHA"; break;
+ case 0x000014: cs_str = "SSL3/DHE-RSA/DES40-CBC/SHA"; break;
+ case 0x000015: cs_str = "SSL3/DHE_RSA/DES56-CBC/SHA"; break;
+ case 0x000016: cs_str = "SSL3/DHE-RSA/3DES192EDE-CBC/SHA"; break;
+
+ case 0x000017: cs_str = "SSL3/DH-anon/RC4-40/MD5"; break;
+ case 0x000018: cs_str = "SSL3/DH-anon/RC4-128/MD5"; break;
+ case 0x000019: cs_str = "SSL3/DH-anon/DES40-CBC/SHA"; break;
+ case 0x00001A: cs_str = "SSL3/DH-anon/DES56-CBC/SHA"; break;
+ case 0x00001B: cs_str = "SSL3/DH-anon/3DES192EDE-CBC/SHA"; break;
+
+ case 0x00001C: cs_str = "SSL3/FORTEZZA-DMS/NULL/SHA"; break;
+ case 0x00001D: cs_str = "SSL3/FORTEZZA-DMS/FORTEZZA-CBC/SHA"; break;
+ case 0x00001E: cs_str = "SSL3/FORTEZZA-DMS/RC4-128/SHA"; break;
+
+ case 0x000062: cs_str = "TLS/RSA_EXPORT1024/DES56_CBC/SHA"; break;
+ case 0x000064: cs_str = "TLS/RSA_EXPORT1024/RC4-56/SHA"; break;
+ case 0x000063: cs_str = "TLS/DHE-DSS_EXPORT1024/DES56-CBC/SHA"; break;
+ case 0x000065: cs_str = "TLS/DHE-DSS_EXPORT1024/RC4-56/SHA"; break;
+ case 0x000066: cs_str = "TLS/DHE-DSS/RC4-128/SHA"; break;
+
+ case 0x00ffe1: cs_str = "SSL3/RSA-FIPS/DES56-CBC/SHA"; break;
+ case 0x00ffe0: cs_str = "SSL3/RSA-FIPS/3DES192EDE-CBC/SHA"; break;
+
+ /* the string literal is broken up to avoid trigraphs */
+ default: cs_str = "????" "/????????" "/?????????" "/???"; break;
+ }
+
+ return cs_str;
+}
+
+void partial_packet(int thispacket, int size, int needed)
+{
+ PR_fprintf(PR_STDOUT,"(%u bytes", thispacket);
+ if (thispacket < needed) {
+ PR_fprintf(PR_STDOUT,", making %u", size);
+ }
+ PR_fprintf(PR_STDOUT," of %u", needed);
+ if (size > needed) {
+ PR_fprintf(PR_STDOUT,", with %u left over", size - needed);
+ }
+ PR_fprintf(PR_STDOUT,")\n");
+}
+
+char * get_time_string(void)
+{
+ char *cp;
+ char *eol;
+ time_t tt;
+
+ time(&tt);
+ cp = ctime(&tt);
+ eol = strchr(cp, '\n');
+ if (eol)
+ *eol = 0;
+ return cp;
+}
+
+void print_sslv2(DataBufferList *s, unsigned char *tbuf, unsigned int alloclen)
+{
+ ClientHelloV2 *chv2;
+ ServerHelloV2 *shv2;
+ unsigned char *pos;
+ unsigned int p;
+ unsigned int q;
+ PRUint32 len;
+
+ chv2 = (ClientHelloV2 *)tbuf;
+ shv2 = (ServerHelloV2 *)tbuf;
+ if (s->isEncrypted) {
+ PR_fprintf(PR_STDOUT," [ssl2] Encrypted {...}\n");
+ return;
+ }
+ PR_fprintf(PR_STDOUT," [%s]", get_time_string() );
+ switch(chv2->type) {
+ case 1:
+ PR_fprintf(PR_STDOUT," [ssl2] ClientHelloV2 {\n");
+ PR_fprintf(PR_STDOUT," version = {0x%02x, 0x%02x}\n",
+ (PRUint32)chv2->version[0],(PRUint32)chv2->version[1]);
+ PR_fprintf(PR_STDOUT," cipher-specs-length = %d (0x%02x)\n",
+ (PRUint32)(GET_SHORT((chv2->cslength))),
+ (PRUint32)(GET_SHORT((chv2->cslength))));
+ PR_fprintf(PR_STDOUT," sid-length = %d (0x%02x)\n",
+ (PRUint32)(GET_SHORT((chv2->sidlength))),
+ (PRUint32)(GET_SHORT((chv2->sidlength))));
+ PR_fprintf(PR_STDOUT," challenge-length = %d (0x%02x)\n",
+ (PRUint32)(GET_SHORT((chv2->rndlength))),
+ (PRUint32)(GET_SHORT((chv2->rndlength))));
+ PR_fprintf(PR_STDOUT," cipher-suites = { \n");
+ for (p=0;p<GET_SHORT((chv2->cslength));p+=3) {
+ const char *cs_str=NULL;
+ PRUint32 cs_int=0;
+ cs_int = GET_24((&chv2->csuites[p]));
+ cs_str = V2CipherString(cs_int);
+
+ PR_fprintf(PR_STDOUT," (0x%06x) %s\n",
+ cs_int, cs_str);
+ }
+ q = p;
+ PR_fprintf(PR_STDOUT," }\n");
+ if (chv2->sidlength) {
+ PR_fprintf(PR_STDOUT," session-id = { ");
+ for (p=0;p<GET_SHORT((chv2->sidlength));p+=2) {
+ PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q]))));
+ }
+ }
+ q += p;
+ PR_fprintf(PR_STDOUT,"}\n");
+ if (chv2->rndlength) {
+ PR_fprintf(PR_STDOUT," challenge = { ");
+ for (p=0;p<GET_SHORT((chv2->rndlength));p+=2) {
+ PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q]))));
+ }
+ PR_fprintf(PR_STDOUT,"}\n");
+ }
+ PR_fprintf(PR_STDOUT,"}\n");
+ break;
+ /* end of V2 CLientHello Parsing */
+
+ case 2: /* Client Master Key */
+ {
+ const char *cs_str=NULL;
+ PRUint32 cs_int=0;
+ ClientMasterKeyV2 *cmkv2;
+ cmkv2 = (ClientMasterKeyV2 *)chv2;
+ isV2Session = 1;
+
+ PR_fprintf(PR_STDOUT," [ssl2] ClientMasterKeyV2 { \n");
+
+ cs_int = GET_24(&cmkv2->cipherkind[0]);
+ cs_str = V2CipherString(cs_int);
+ PR_fprintf(PR_STDOUT," cipher-spec-chosen = (0x%06x) %s\n",
+ cs_int, cs_str);
+
+ PR_fprintf(PR_STDOUT," clear-portion = %d bits\n",
+ 8*(PRUint32)(GET_SHORT((cmkv2->clearkey))));
+
+ PR_fprintf(PR_STDOUT," }\n");
+ clientstream.isEncrypted = 1;
+ serverstream.isEncrypted = 1;
+ }
+ break;
+
+
+ case 3:
+ PR_fprintf(PR_STDOUT," [ssl2] Client Finished V2 {...}\n");
+ isV2Session = 1;
+ break;
+
+
+ case 4: /* V2 Server Hello */
+ isV2Session = 1;
+
+ PR_fprintf(PR_STDOUT," [ssl2] ServerHelloV2 {\n");
+ PR_fprintf(PR_STDOUT," sid hit = {0x%02x}\n",
+ (PRUintn)shv2->sidhit);
+ PR_fprintf(PR_STDOUT," version = {0x%02x, 0x%02x}\n",
+ (PRUint32)shv2->version[0],(PRUint32)shv2->version[1]);
+ PR_fprintf(PR_STDOUT," cipher-specs-length = %d (0x%02x)\n",
+ (PRUint32)(GET_SHORT((shv2->cslength))),
+ (PRUint32)(GET_SHORT((shv2->cslength))));
+ PR_fprintf(PR_STDOUT," sid-length = %d (0x%02x)\n",
+ (PRUint32)(GET_SHORT((shv2->cidlength))),
+ (PRUint32)(GET_SHORT((shv2->cidlength))));
+
+ pos = (unsigned char *)shv2;
+ pos += 2; /* skip length header */
+ pos += 11; /* position pointer to Certificate data area */
+ q = GET_SHORT(&shv2->certlength);
+ if (q >alloclen) {
+ goto eosh;
+ }
+ pos += q; /* skip certificate */
+
+ PR_fprintf(PR_STDOUT," cipher-suites = { ");
+ len = GET_SHORT((shv2->cslength));
+ for (p = 0; p < len; p += 3) {
+ const char *cs_str=NULL;
+ PRUint32 cs_int=0;
+ cs_int = GET_24((pos+p));
+ cs_str = V2CipherString(cs_int);
+ PR_fprintf(PR_STDOUT,"\n ");
+ PR_fprintf(PR_STDOUT,"(0x%06x) %s", cs_int, cs_str);
+ }
+ pos += len;
+ PR_fprintf(PR_STDOUT," }\n"); /* End of cipher suites */
+ len = (PRUint32)GET_SHORT((shv2->cidlength));
+ if (len) {
+ PR_fprintf(PR_STDOUT," connection-id = { ");
+ for (p = 0; p < len; p += 2) {
+ PR_fprintf(PR_STDOUT,"0x%04x ", (PRUint32)(GET_SHORT((pos + p))));
+ }
+ PR_fprintf(PR_STDOUT," }\n"); /* End of connection id */
+ }
+eosh:
+ PR_fprintf(PR_STDOUT,"\n }\n"); /* end of ServerHelloV2 */
+ if (shv2->sidhit) {
+ clientstream.isEncrypted = 1;
+ serverstream.isEncrypted = 1;
+ }
+ break;
+
+ case 5:
+ PR_fprintf(PR_STDOUT," [ssl2] Server Verify V2 {...}\n");
+ isV2Session = 1;
+ break;
+
+ case 6:
+ PR_fprintf(PR_STDOUT," [ssl2] Server Finished V2 {...}\n");
+ isV2Session = 1;
+ break;
+
+ case 7:
+ PR_fprintf(PR_STDOUT," [ssl2] Request Certificate V2 {...}\n");
+ isV2Session = 1;
+ break;
+
+ case 8:
+ PR_fprintf(PR_STDOUT," [ssl2] Client Certificate V2 {...}\n");
+ isV2Session = 1;
+ break;
+
+ default:
+ PR_fprintf(PR_STDOUT," [ssl2] UnknownType 0x%02x {...}\n",
+ (PRUint32)chv2->type);
+ break;
+ }
+}
+
+
+
+
+
+
+void print_ssl3_handshake(unsigned char *tbuf,
+ unsigned int alloclen,
+ SSLRecord * sr)
+{
+ struct sslhandshake sslh;
+ unsigned char * hsdata;
+ int offset=0;
+
+ PR_fprintf(PR_STDOUT," handshake {\n");
+
+ while (offset < alloclen) {
+ sslh.type = tbuf[offset];
+ sslh.length = GET_24(tbuf+offset+1);
+ hsdata= &tbuf[offset+4];
+
+ if (sslhexparse) print_hex(4,tbuf+offset);
+
+ PR_fprintf(PR_STDOUT," type = %d (",sslh.type);
+ switch(sslh.type) {
+ case 0: PR_fprintf(PR_STDOUT,"hello_request)\n"); break;
+ case 1: PR_fprintf(PR_STDOUT,"client_hello)\n"); break;
+ case 2: PR_fprintf(PR_STDOUT,"server_hello)\n"); break;
+ case 11: PR_fprintf(PR_STDOUT,"certificate)\n"); break;
+ case 12: PR_fprintf(PR_STDOUT,"server_key_exchange)\n"); break;
+ case 13: PR_fprintf(PR_STDOUT,"certificate_request)\n"); break;
+ case 14: PR_fprintf(PR_STDOUT,"server_hello_done)\n"); break;
+ case 15: PR_fprintf(PR_STDOUT,"certificate_verify)\n"); break;
+ case 16: PR_fprintf(PR_STDOUT,"client_key_exchange)\n"); break;
+ case 20: PR_fprintf(PR_STDOUT,"finished)\n"); break;
+ default: PR_fprintf(PR_STDOUT,"unknown)\n");
+ }
+
+ PR_fprintf(PR_STDOUT," length = %d (0x%06x)\n",sslh.length,sslh.length);
+ switch (sslh.type) {
+
+ case 1: /* client hello */
+ switch (sr->ver_maj) {
+ case 2: /* ssl version 2 */
+ PR_fprintf(PR_STDOUT," ClientHelloV2 {...}\n");
+ break;
+ case 3: /* ssl version 3 */
+ {
+ int sidlength,pos,csuitelength,w;
+ PR_fprintf(PR_STDOUT," ClientHelloV3 {\n");
+ PR_fprintf(PR_STDOUT," client_version = {%d, %d}\n",
+ (PRUint8)hsdata[0],(PRUint8)hsdata[1]);
+ PR_fprintf(PR_STDOUT," random = {...}\n");
+ if (sslhexparse) print_hex(32,&hsdata[2]);
+ PR_fprintf(PR_STDOUT," session ID = {\n");
+ sidlength = (int)hsdata[2+32];
+ PR_fprintf(PR_STDOUT," length = %d\n",sidlength);
+ PR_fprintf(PR_STDOUT," contents = {..}\n");
+ if (sslhexparse) print_hex(sidlength,&hsdata[2+32+1]);
+ PR_fprintf(PR_STDOUT," }\n");
+ pos = 2+32+1+sidlength;
+ csuitelength = GET_SHORT((hsdata+pos));
+ PR_fprintf(PR_STDOUT," cipher_suites[%d] = { \n",
+ csuitelength/2);
+ if (csuitelength%1) {
+ PR_fprintf(PR_STDOUT,
+ "*error in protocol - csuitelength shouldn't be odd*\n");
+ }
+
+ for (w=0; w<csuitelength; w+=2) {
+ const char *cs_str=NULL;
+ PRUint32 cs_int=0;
+ cs_int = GET_SHORT((hsdata+pos+2+w));
+ cs_str = V2CipherString(cs_int);
+
+ PR_fprintf(PR_STDOUT,
+ " (0x%04x) %s\n", cs_int, cs_str);
+ }
+
+ /* for (w=0;w<csuitelength;w+=2) {
+ PR_fprintf(PR_STDOUT,"0x%04x ",GET_SHORT((hsdata+pos+2+w)));
+ } */
+
+ PR_fprintf(PR_STDOUT,"\n }\n");
+ PR_fprintf(PR_STDOUT," }\n");
+
+
+
+ } /* end of ssl version 3 */
+ break;
+ default:
+ PR_fprintf(PR_STDOUT," ClientHelloUndefinedVersion{}\n");
+ } /* end of switch sr->ver_maj */
+ break;
+
+ case 2: /* server hello */
+ {
+ int sidlength, pos;
+ const char *cs_str=NULL;
+ PRUint32 cs_int=0;
+ PR_fprintf(PR_STDOUT," ServerHello {\n");
+ PR_fprintf(PR_STDOUT," server_version = {%d, %d}\n",
+ (PRUint8)hsdata[0],(PRUint8)hsdata[1]);
+ PR_fprintf(PR_STDOUT," random = {...}\n");
+ if (sslhexparse) print_hex(32,&hsdata[2]);
+ PR_fprintf(PR_STDOUT," session ID = {\n");
+ sidlength = (int)hsdata[2+32];
+ PR_fprintf(PR_STDOUT," length = %d\n",sidlength);
+ PR_fprintf(PR_STDOUT," contents = {..}\n");
+ if (sslhexparse) print_hex(sidlength,&hsdata[2+32+1]);
+ PR_fprintf(PR_STDOUT," }\n");
+ pos = 2+32+1+sidlength;
+ cs_int = GET_SHORT((hsdata+pos));
+ cs_str = V2CipherString(cs_int);
+ PR_fprintf(PR_STDOUT," cipher_suite = (0x%04x) %s\n",
+ cs_int, cs_str);
+ PR_fprintf(PR_STDOUT," }\n");
+ }
+ break;
+
+
+
+ case 11: /* certificate */
+ {
+ PRFileDesc *cfd;
+ int pos;
+ int certslength;
+ int certlength;
+ int certbytesread = 0;
+ static int certFileNumber;
+ char certFileName[20];
+
+ PR_fprintf(PR_STDOUT," CertificateChain {\n");
+ certslength = GET_24(hsdata);
+ PR_fprintf(PR_STDOUT," chainlength = %d (0x%04x)\n",
+ certslength,certslength);
+ pos = 3;
+ while (certbytesread < certslength) {
+ certlength = GET_24((hsdata+pos));
+ pos += 3;
+ PR_fprintf(PR_STDOUT," Certificate {\n");
+ PR_fprintf(PR_STDOUT," size = %d (0x%04x)\n",
+ certlength,certlength);
+
+ PR_snprintf(certFileName, sizeof certFileName, "cert.%03d",
+ ++certFileNumber);
+ cfd = PR_Open(certFileName, PR_WRONLY|PR_CREATE_FILE, 0664);
+ if (!cfd) {
+ PR_fprintf(PR_STDOUT,
+ " data = { couldn't save file '%s' }\n",
+ certFileName);
+ } else {
+ PR_Write(cfd, (hsdata+pos), certlength);
+ PR_fprintf(PR_STDOUT,
+ " data = { saved in file '%s' }\n",
+ certFileName);
+ PR_Close(cfd);
+ }
+
+ PR_fprintf(PR_STDOUT," }\n");
+ pos += certlength;
+ certbytesread += certlength+3;
+ }
+ PR_fprintf(PR_STDOUT," }\n");
+ }
+ break;
+
+ case 13: /* certificate request */
+ if (sslhexparse) {
+ PR_fprintf(PR_STDOUT," CertificateRequest {\n");
+ print_hex(sslh.length, hsdata);
+ PR_fprintf(PR_STDOUT," }\n");
+ }
+ break;
+
+ case 16: /* client key exchange */
+ {
+ PR_fprintf(PR_STDOUT," ClientKeyExchange {\n");
+ PR_fprintf(PR_STDOUT," message = {...}\n");
+ PR_fprintf(PR_STDOUT," }\n");
+ }
+ break;
+
+ } /* end of switch sslh.type */
+ offset += sslh.length + 4; /* +4 because of length (3 bytes) and type (1 byte) */
+ } /* while */
+ PR_fprintf(PR_STDOUT," }\n");
+}
+
+
+void print_ssl(DataBufferList *s, int length, unsigned char *buffer)
+{
+ /* -------------------------------------------------------- */
+ /* first, create a new buffer object for this piece of data. */
+
+ DataBuffer *db;
+ int i,l;
+
+ if (s->size == 0 && length > 0 && buffer[0] >= 32 && buffer[0] < 128) {
+ /* Not an SSL record, treat entire buffer as plaintext */
+ PR_Write(PR_STDOUT,buffer,length);
+ return;
+ }
+
+
+ check_integrity(s);
+
+ i = 0;
+ l = length;
+
+ db = PR_NEW(struct _DataBuffer);
+
+ db->buffer = (unsigned char*)PR_Malloc(length);
+ db->length = length;
+ db->offset = 0;
+ memcpy(db->buffer, buffer, length);
+ db->next = NULL;
+
+ /* now, add it to the stream */
+
+ if (s->last != NULL) s->last->next = db;
+ s->last = db;
+ s->size += length;
+ if (s->first == NULL) s->first = db;
+
+ check_integrity(s);
+
+ /*------------------------------------------------------- */
+ /* now we look at the stream to see if we have enough data to
+ decode */
+
+ while (s->size > 0 ) {
+ unsigned char *tbuf = NULL;
+
+ SSLRecord sr;
+ unsigned alloclen;
+ unsigned recordsize;
+
+ check_integrity(s);
+
+ if ( s->first == NULL) {
+ PR_fprintf(PR_STDOUT,"ERROR: s->first is null\n");
+ exit(9);
+ }
+
+ /* in the case of an SSL 2 client-hello (which is all ssltap supports) */
+ /* will have the high-bit set, whereas an SSL 3 client-hello will not */
+ /* SSL2 can also send records that begin with the high bit clear.
+ * This code will incorrectly handle them. XXX
+ */
+ if (isV2Session || s->first->buffer[s->first->offset] & 0x80) {
+ /* it's an SSL 2 packet */
+ unsigned char lenbuf[3];
+
+ /* first, we check if there's enough data for it to be an SSL2-type
+ * record. What a pain.*/
+ if (s->size < sizeof lenbuf) {
+ partial_packet(length, s->size, sizeof lenbuf);
+ return;
+ }
+
+ /* read the first two bytes off the stream. */
+ read_stream_bytes(lenbuf, s, sizeof(lenbuf));
+ alloclen = ((unsigned int)(lenbuf[0] & 0x7f) << 8) + lenbuf[1] +
+ ((lenbuf[0] & 0x80) ? 2 : 3);
+ PR_fprintf(PR_STDOUT, "alloclen = %u bytes\n", alloclen);
+
+ /* put 'em back on the head of the stream. */
+ db = PR_NEW(struct _DataBuffer);
+
+ db->length = sizeof lenbuf;
+ db->buffer = (unsigned char*) PR_Malloc(db->length);
+ db->offset = 0;
+ memcpy(db->buffer, lenbuf, sizeof lenbuf);
+
+ db->next = s->first;
+ s->first = db;
+ if (s->last == NULL)
+ s->last = db;
+ s->size += db->length;
+
+ /* if there wasn't enough, go back for more. */
+ if (s->size < alloclen) {
+ check_integrity(s);
+ partial_packet(length, s->size, alloclen);
+ return;
+ }
+ partial_packet(length, s->size, alloclen);
+
+ /* read in the whole record. */
+ tbuf = PR_Malloc(alloclen);
+ read_stream_bytes(tbuf, s, alloclen);
+
+ print_sslv2(s, tbuf, alloclen);
+ PR_FREEIF(tbuf);
+ check_integrity(s);
+
+ continue;
+ }
+
+ /***********************************************************/
+ /* It's SSL v3 */
+ /***********************************************************/
+ check_integrity(s);
+
+ if (s->size < sizeof(SSLRecord)) {
+ partial_packet(length, s->size, sizeof(SSLRecord));
+ return;
+ }
+
+ read_stream_bytes((unsigned char *)&sr, s, sizeof sr);
+
+ /* we have read the stream bytes. Look at the length of
+ the ssl record. If we don't have enough data to satisfy this
+ request, then put the bytes we just took back at the head
+ of the queue */
+ recordsize = GET_SHORT(sr.length);
+
+ if (recordsize > s->size) {
+ db = PR_NEW(struct _DataBuffer);
+
+ db->length = sizeof sr;
+ db->buffer = (unsigned char*) PR_Malloc(db->length);
+ db->offset = 0;
+ memcpy(db->buffer, &sr, sizeof sr);
+ db->next = s->first;
+
+ /* now, add it back on to the head of the stream */
+
+ s->first = db;
+ if (s->last == NULL)
+ s->last = db;
+ s->size += db->length;
+
+ check_integrity(s);
+ partial_packet(length, s->size, recordsize);
+ return;
+ }
+ partial_packet(length, s->size, recordsize);
+
+
+ PR_fprintf(PR_STDOUT,"SSLRecord { [%s]\n", get_time_string() );
+ if (sslhexparse) {
+ print_hex(5,(unsigned char*)&sr);
+ }
+
+ check_integrity(s);
+
+ PR_fprintf(PR_STDOUT," type = %d (",sr.type);
+ switch(sr.type) {
+ case 20 :
+ PR_fprintf(PR_STDOUT,"change_cipher_spec)\n");
+ break;
+ case 21 :
+ PR_fprintf(PR_STDOUT,"alert)\n");
+ break;
+ case 22 :
+ PR_fprintf(PR_STDOUT,"handshake)\n");
+ break;
+ case 23 :
+ PR_fprintf(PR_STDOUT,"application_data)\n");
+ break;
+ default:
+ PR_fprintf(PR_STDOUT,"unknown)\n");
+ break;
+ }
+ PR_fprintf(PR_STDOUT," version = { %d,%d }\n",
+ (PRUint32)sr.ver_maj,(PRUint32)sr.ver_min);
+ PR_fprintf(PR_STDOUT," length = %d (0x%x)\n",
+ (PRUint32)GET_SHORT(sr.length), (PRUint32)GET_SHORT(sr.length));
+
+
+ alloclen = recordsize;
+ PR_ASSERT(s->size >= alloclen);
+ if (s->size >= alloclen) {
+ tbuf = (unsigned char*) PR_Malloc(alloclen);
+ read_stream_bytes(tbuf, s, alloclen);
+
+ if (s->isEncrypted) {
+ PR_fprintf(PR_STDOUT," < encrypted >\n");
+ } else
+
+ switch(sr.type) {
+ case 20 : /* change_cipher_spec */
+ if (sslhexparse) print_hex(alloclen,tbuf);
+ s->isEncrypted = 1; /* mark to say we can only dump hex form now on */
+ break;
+
+ case 21 : /* alert */
+ switch(tbuf[0]) {
+ case 1: PR_fprintf(PR_STDOUT, " warning: "); break;
+ case 2: PR_fprintf(PR_STDOUT, " fatal: "); break;
+ default: PR_fprintf(PR_STDOUT, " unknown level %d: ", tbuf[0]); break;
+ }
+
+ switch(tbuf[1]) {
+ case 0: PR_fprintf(PR_STDOUT, "close notify\n"); break;
+ case 10: PR_fprintf(PR_STDOUT, "unexpected message\n"); break;
+ case 20: PR_fprintf(PR_STDOUT, "bad record mac\n"); break;
+ case 21: PR_fprintf(PR_STDOUT, "decryption failed\n"); break;
+ case 22: PR_fprintf(PR_STDOUT, "record overflow\n"); break;
+ case 30: PR_fprintf(PR_STDOUT, "decompression failure\n"); break;
+ case 40: PR_fprintf(PR_STDOUT, "handshake failure\n"); break;
+ case 41: PR_fprintf(PR_STDOUT, "no certificate\n"); break;
+ case 42: PR_fprintf(PR_STDOUT, "bad certificate\n"); break;
+ case 43: PR_fprintf(PR_STDOUT, "unsupported certificate\n"); break;
+ case 44: PR_fprintf(PR_STDOUT, "certificate revoked\n"); break;
+ case 45: PR_fprintf(PR_STDOUT, "certificate expired\n"); break;
+ case 46: PR_fprintf(PR_STDOUT, "certificate unknown\n"); break;
+ case 47: PR_fprintf(PR_STDOUT, "illegal parameter\n"); break;
+ case 48: PR_fprintf(PR_STDOUT, "unknown CA\n"); break;
+ case 49: PR_fprintf(PR_STDOUT, "access denied\n"); break;
+ case 50: PR_fprintf(PR_STDOUT, "decode error\n"); break;
+ case 51: PR_fprintf(PR_STDOUT, "decrypt error\n"); break;
+ case 60: PR_fprintf(PR_STDOUT, "export restriction\n"); break;
+ case 70: PR_fprintf(PR_STDOUT, "protocol version\n"); break;
+ case 71: PR_fprintf(PR_STDOUT, "insufficient security\n"); break;
+ case 80: PR_fprintf(PR_STDOUT, "internal error\n"); break;
+ case 90: PR_fprintf(PR_STDOUT, "user canceled\n"); break;
+ case 100: PR_fprintf(PR_STDOUT, "no renegotiation\n"); break;
+ default: PR_fprintf(PR_STDOUT, "unknown error %d\n", tbuf[1]); break;
+ }
+
+ if (sslhexparse) print_hex(alloclen,tbuf);
+ break;
+
+ case 22 : /* handshake */
+ print_ssl3_handshake( tbuf, alloclen, &sr );
+ break;
+
+ case 23 : /* application data */
+ default:
+ print_hex(alloclen,tbuf);
+ break;
+ }
+ }
+ PR_fprintf(PR_STDOUT,"}\n");
+ PR_FREEIF(tbuf);
+ check_integrity(s);
+ }
+}
+
+void print_hex(int amt, unsigned char *buf) {
+ int i,j,k;
+ char *string = (char*)PR_Malloc(5000);
+ char t[20];
+
+
+ for(i=0;i<amt;i++) {
+ t[1] =0;
+
+ if (i%16 ==0) { /* if we are at the beginning of a line */
+ PR_fprintf(PR_STDOUT,"%4x:",i); /* print the line number */
+ strcpy(string,"");
+ }
+
+ if (i%4 == 0) {
+ PR_fprintf(PR_STDOUT," ");
+ }
+
+ t[0] = buf[i];
+
+ if (!isprint(t[0])) {
+ t[0] = '.';
+ }
+ if (fancy) {
+ switch (t[0]) {
+ case '<':
+ strcpy(t,"&lt;");
+ break;
+ case '>':
+ strcpy(t,"&gt;");
+ break;
+ case '&':
+ strcpy(t,"&amp;");
+ break;
+ }
+ }
+ strcat(string,t);
+
+ PR_fprintf(PR_STDOUT,"%02x ",(PRUint8) buf[i]);
+
+ /* if we've reached the end of the line - add the string */
+ if (i%16 == 15) PR_fprintf(PR_STDOUT," | %s\n",string);
+ }
+ /* we reached the end of the buffer,*/
+ /* do we have buffer left over? */
+ j = i%16;
+ if (j > 0) {
+ for (k=0;k<(16-j);k++) PR_fprintf(PR_STDOUT," ");
+ PR_fprintf(PR_STDOUT," |%s\n",string);
+ }
+ PR_Free(string);
+}
+
+void Usage(void) {
+ PR_fprintf(PR_STDERR, "SSLTAP (C) 1997, 1998 Netscape Communications Corporation.\n");
+ PR_fprintf(PR_STDERR, "Usage: ssltap [-vhfsxl] [-p port] hostname:port\n");
+ PR_fprintf(PR_STDERR, " -v [prints version string]\n");
+ PR_fprintf(PR_STDERR, " -h [outputs hex instead of ASCII]\n");
+ PR_fprintf(PR_STDERR, " -f [turn on Fancy HTML coloring]\n");
+ PR_fprintf(PR_STDERR, " -s [turn on SSL decoding]\n");
+ PR_fprintf(PR_STDERR, " -x [turn on extra SSL hex dumps]\n");
+ PR_fprintf(PR_STDERR, " -p port [specify rendezvous port (default 1924)]\n");
+ PR_fprintf(PR_STDERR, " -l [loop - continue to wait for more connections]\n");
+
+
+}
+
+void
+showErr(const char * msg) {
+ PRErrorCode err = PR_GetError();
+ const char * errString;
+
+ if (err == PR_UNKNOWN_ERROR)
+ err = PR_CONNECT_RESET_ERROR; /* bug in NSPR. */
+ errString = SECU_Strerror(err);
+
+ if (!errString)
+ errString = "(no text available)";
+ PR_fprintf(PR_STDERR, "Error %d: %s: %s", err, errString, msg);
+}
+
+int main(int argc, char *argv[])
+{
+ char *hostname=NULL;
+ PRUint16 rendport=DEFPORT,port;
+ PRHostEnt hp;
+ PRStatus r;
+ PRNetAddr na_client,na_server,na_rend;
+ PRFileDesc *s_server,*s_client,*s_rend; /*rendezvous */
+ char netdbbuf[PR_NETDB_BUF_SIZE];
+ int c_count=0;
+ PLOptState *optstate;
+ PLOptStatus status;
+
+ optstate = PL_CreateOptState(argc,argv,"fvxhslp:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'f':
+ fancy++;
+ break;
+ case 'h':
+ hexparse++;
+ break;
+ case 'v':
+ PR_fprintf(PR_STDOUT,"Version: %s\n",VERSIONSTRING);
+ break;
+ case 's':
+ sslparse++;
+ break;
+ case 'x':
+ sslhexparse++;
+ break;
+ case 'l':
+ looparound++;
+ break;
+ case 'p':
+ rendport = atoi(optstate->value);
+ break;
+ case '\0':
+ hostname = PL_strdup(optstate->value);
+ }
+ }
+ if (status == PL_OPT_BAD)
+ Usage();
+
+ if (fancy) {
+ if (!hexparse && !sslparse) {
+ PR_fprintf(PR_STDERR,
+"Note: use of -f without -s or -h not recommended, \n"
+"as the output looks a little strange. It may be useful, however\n");
+ }
+ }
+
+ if(! hostname ) Usage(), exit(2);
+
+ {
+ char *colon = (char *)strchr(hostname, ':');
+ if (!colon) {
+ PR_fprintf(PR_STDERR,
+ "You must specify the host AND port you wish to connect to\n");
+ Usage(), exit(3);
+ }
+ port = atoi(&colon[1]);
+ *colon = '\0';
+
+ if (port == 0) {
+ PR_fprintf(PR_STDERR, "Port must be a nonzero number.\n");
+ exit(4);
+ }
+ }
+
+ /* find the 'server' IP address so we don't have to look it up later */
+
+ if (fancy) {
+ PR_fprintf(PR_STDOUT,"<HTML><HEAD><TITLE>SSLTAP output</TITLE></HEAD>\n");
+ PR_fprintf(PR_STDOUT,"<BODY><PRE>\n");
+ }
+ PR_fprintf(PR_STDERR,"Looking up \"%s\"...\n", hostname);
+ r = PR_GetHostByName(hostname,netdbbuf,PR_NETDB_BUF_SIZE,&hp);
+ if (r) {
+ showErr("Host Name lookup failed\n");
+ exit(5);
+ }
+
+ PR_EnumerateHostEnt(0,&hp,0,&na_server);
+ PR_InitializeNetAddr(PR_IpAddrNull,port,&na_server);
+ /* set up the port which the client will connect to */
+
+ r = PR_InitializeNetAddr(PR_IpAddrAny,rendport,&na_rend);
+ if (r == PR_FAILURE) {
+ PR_fprintf(PR_STDERR,
+ "PR_InitializeNetAddr(,%d,) failed with error %d\n",PR_GetError());
+ exit(0);
+ }
+
+
+ s_rend = PR_NewTCPSocket();
+ if (!s_rend) {
+ showErr("Couldn't create socket\n");
+ exit(6);
+ }
+
+ if (PR_Bind(s_rend, &na_rend )) {
+ PR_fprintf(PR_STDERR,"Couldn't bind to port %d (error %d)\n",rendport, PR_GetError());
+ exit(-1);
+ }
+
+ if ( PR_Listen(s_rend, 5)) {
+ showErr("Couldn't listen\n");
+ exit(-1);
+ }
+
+ PR_fprintf(PR_STDERR,"Proxy socket ready and listening\n");
+ do { /* accept one connection and process it. */
+ PRPollDesc pds[2];
+
+ s_client = PR_Accept(s_rend,&na_client,PR_SecondsToInterval(3600));
+ if (s_client == NULL) {
+ showErr("accept timed out\n");
+ exit(7);
+ }
+
+ s_server = PR_NewTCPSocket();
+ if (s_server == NULL) {
+ showErr("couldn't open new socket to connect to server \n");
+ exit(8);
+ }
+
+ r = PR_Connect(s_server,&na_server,PR_SecondsToInterval(5));
+
+ if ( r == PR_FAILURE )
+ {
+ showErr("Couldn't connect\n");
+ return -1;
+ }
+
+ if (looparound) {
+ if (fancy) PR_fprintf(PR_STDOUT,"<p><HR><H2>");
+ PR_fprintf(PR_STDOUT,"Connection #%d [%s]\n", c_count+1,
+ get_time_string());
+ if (fancy) PR_fprintf(PR_STDOUT,"</H2>");
+ }
+
+
+ PR_fprintf(PR_STDOUT,"Connected to %s:%d\n", hostname, port);
+
+#define PD_C 0
+#define PD_S 1
+
+ pds[PD_C].fd = s_client;
+ pds[PD_S].fd = s_server;
+ pds[PD_C].in_flags = PR_POLL_READ;
+ pds[PD_S].in_flags = PR_POLL_READ;
+
+ /* make sure the new connections don't start out encrypted. */
+ clientstream.isEncrypted = 0;
+ serverstream.isEncrypted = 0;
+ isV2Session = 0;
+
+ while( (pds[PD_C].in_flags & PR_POLL_READ) != 0 ||
+ (pds[PD_S].in_flags & PR_POLL_READ) != 0 )
+ { /* Handle all messages on the connection */
+ PRInt32 amt;
+ PRInt32 wrote;
+ unsigned char buffer[ TAPBUFSIZ ];
+
+ amt = PR_Poll(pds,2,PR_INTERVAL_NO_TIMEOUT);
+ if (amt <= 0) {
+ if (amt)
+ showErr( "PR_Poll failed.\n");
+ else
+ showErr( "PR_Poll timed out.\n");
+ break;
+ }
+
+ if (pds[PD_C].out_flags & PR_POLL_EXCEPT) {
+ showErr( "Exception on client-side socket.\n");
+ break;
+ }
+
+ if (pds[PD_S].out_flags & PR_POLL_EXCEPT) {
+ showErr( "Exception on server-side socket.\n");
+ break;
+ }
+
+
+/* read data, copy it to stdout, and write to other socket */
+
+ if ((pds[PD_C].in_flags & PR_POLL_READ) != 0 &&
+ (pds[PD_C].out_flags & PR_POLL_READ) != 0 ) {
+
+ amt = PR_Read(s_client, buffer, sizeof(buffer));
+
+ if ( amt < 0) {
+ showErr( "Client socket read failed.\n");
+ break;
+ }
+
+ if( amt == 0 ) {
+ PR_fprintf(PR_STDOUT, "Read EOF on Client socket. [%s]\n",
+ get_time_string() );
+ pds[PD_C].in_flags &= ~PR_POLL_READ;
+ PR_Shutdown(s_server, PR_SHUTDOWN_SEND);
+ continue;
+ }
+
+ PR_fprintf(PR_STDOUT,"--> [\n");
+ if (fancy) PR_fprintf(PR_STDOUT,"<font color=blue>");
+
+ if (hexparse) print_hex(amt, buffer);
+ if (sslparse) print_ssl(&clientstream,amt,buffer);
+ if (!hexparse && !sslparse) PR_Write(PR_STDOUT,buffer,amt);
+ if (fancy) PR_fprintf(PR_STDOUT,"</font>");
+ PR_fprintf(PR_STDOUT,"]\n");
+
+ wrote = PR_Write(s_server, buffer, amt);
+ if (wrote != amt ) {
+ if (wrote < 0) {
+ showErr("Write to server socket failed.\n");
+ break;
+ } else {
+ PR_fprintf(PR_STDERR, "Short write to server socket!\n");
+ }
+ }
+ } /* end of read from client socket. */
+
+/* read data, copy it to stdout, and write to other socket */
+ if ((pds[PD_S].in_flags & PR_POLL_READ) != 0 &&
+ (pds[PD_S].out_flags & PR_POLL_READ) != 0 ) {
+
+ amt = PR_Read(s_server, buffer, sizeof(buffer));
+
+ if ( amt < 0) {
+ showErr( "error on server-side socket.\n");
+ break;
+ }
+
+ if( amt == 0 ) {
+ PR_fprintf(PR_STDOUT, "Read EOF on Server socket. [%s]\n",
+ get_time_string() );
+ pds[PD_S].in_flags &= ~PR_POLL_READ;
+ PR_Shutdown(s_client, PR_SHUTDOWN_SEND);
+ continue;
+ }
+
+ PR_fprintf(PR_STDOUT,"<-- [\n");
+ if (fancy) PR_fprintf(PR_STDOUT,"<font color=red>");
+ if (hexparse) print_hex(amt, (unsigned char *)buffer);
+ if (sslparse) print_ssl(&serverstream,amt,(unsigned char *)buffer);
+ if (!hexparse && !sslparse) PR_Write(PR_STDOUT,buffer,amt);
+ if (fancy) PR_fprintf(PR_STDOUT,"</font>");
+ PR_fprintf(PR_STDOUT,"]\n");
+
+
+ wrote = PR_Write(s_client, buffer, amt);
+ if (wrote != amt ) {
+ if (wrote < 0) {
+ showErr("Write to client socket failed.\n");
+ break;
+ } else {
+ PR_fprintf(PR_STDERR, "Short write to client socket!\n");
+ }
+ }
+
+ } /* end of read from server socket. */
+
+/* Loop, handle next message. */
+
+ } /* handle messages during a connection loop */
+ PR_Close(s_client);
+ PR_Close(s_server);
+ flush_stream(&clientstream);
+ flush_stream(&serverstream);
+
+ c_count++;
+ PR_fprintf(PR_STDERR,"Connection %d Complete [%s]\n", c_count,
+ get_time_string() );
+ } while (looparound); /* accept connection and process it. */
+ PR_Close(s_rend);
+ return 0;
+}
diff --git a/security/nss/cmd/strsclnt/Makefile b/security/nss/cmd/strsclnt/Makefile
new file mode 100644
index 000000000..4e39ffc3f
--- /dev/null
+++ b/security/nss/cmd/strsclnt/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/strsclnt/manifest.mn b/security/nss/cmd/strsclnt/manifest.mn
new file mode 100644
index 000000000..e54345f6d
--- /dev/null
+++ b/security/nss/cmd/strsclnt/manifest.mn
@@ -0,0 +1,47 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+CORE_DEPTH = ../../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = strsclnt.c
+
+# the MODULE above is always implicitly REQUIREd
+REQUIRES = seccmd dbm
+
+PROGRAM = strsclnt
+# PROGRAM = ./$(OBJDIR)/strsclnt.exe
+
diff --git a/security/nss/cmd/strsclnt/strsclnt.c b/security/nss/cmd/strsclnt/strsclnt.c
new file mode 100644
index 000000000..ae20c02bb
--- /dev/null
+++ b/security/nss/cmd/strsclnt/strsclnt.c
@@ -0,0 +1,1175 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#include <stdio.h>
+#include <string.h>
+
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#if !defined(_WIN32_WCE)
+#include <errno.h>
+#include <fcntl.h>
+#endif
+#include <stdarg.h>
+
+#include "plgetopt.h"
+
+#include "nspr.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "prerror.h"
+
+#include "pk11func.h"
+#include "secitem.h"
+#include "sslproto.h"
+#include "nss.h"
+#include "ssl.h"
+
+#ifndef PORT_Sprintf
+#define PORT_Sprintf sprintf
+#endif
+
+#ifndef PORT_Strstr
+#define PORT_Strstr strstr
+#endif
+
+#ifndef PORT_Malloc
+#define PORT_Malloc PR_Malloc
+#endif
+
+#define RD_BUF_SIZE (60 * 1024)
+
+/* Include these cipher suite arrays to re-use tstclnt's
+ * cipher selection code.
+ */
+
+int ssl2CipherSuites[] = {
+ SSL_EN_RC4_128_WITH_MD5, /* A */
+ SSL_EN_RC4_128_EXPORT40_WITH_MD5, /* B */
+ SSL_EN_RC2_128_CBC_WITH_MD5, /* C */
+ SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */
+ SSL_EN_DES_64_CBC_WITH_MD5, /* E */
+ SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* F */
+#ifdef NSS_ENABLE_ECC
+ /* NOTE: Since no new SSL2 ciphersuites are being
+ * invented, and we've run out of lowercase letters
+ * for SSL3 ciphers, we use letters G and beyond
+ * for new SSL3 ciphers.
+ */
+ TLS_ECDH_ECDSA_WITH_NULL_SHA, /* G */
+ TLS_ECDH_ECDSA_WITH_RC4_128_SHA, /* H */
+ TLS_ECDH_ECDSA_WITH_DES_CBC_SHA, /* I */
+ TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* J */
+ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, /* K */
+ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, /* L */
+ TLS_ECDH_RSA_WITH_NULL_SHA, /* M */
+ TLS_ECDH_RSA_WITH_RC4_128_SHA, /* N */
+ TLS_ECDH_RSA_WITH_DES_CBC_SHA, /* O */
+ TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, /* P */
+ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, /* Q */
+ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, /* R */
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* S */
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* T */
+#endif /* NSS_ENABLE_ECC */
+ 0
+};
+
+int ssl3CipherSuites[] = {
+ SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* a */
+ SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, /* b */
+ SSL_RSA_WITH_RC4_128_MD5, /* c */
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
+ SSL_RSA_WITH_DES_CBC_SHA, /* e */
+ SSL_RSA_EXPORT_WITH_RC4_40_MD5, /* f */
+ SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* g */
+ SSL_FORTEZZA_DMS_WITH_NULL_SHA, /* h */
+ SSL_RSA_WITH_NULL_MD5, /* i */
+ SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, /* j */
+ SSL_RSA_FIPS_WITH_DES_CBC_SHA, /* k */
+ TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
+ TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, /* m */
+ SSL_RSA_WITH_RC4_128_SHA, /* n */
+ TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
+ SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
+ SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
+ SSL_DHE_RSA_WITH_DES_CBC_SHA, /* r */
+ SSL_DHE_DSS_WITH_DES_CBC_SHA, /* s */
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */
+ TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */
+ TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
+ 0
+};
+
+/* This global string is so that client main can see
+ * which ciphers to use.
+ */
+
+static const char *cipherString;
+
+static int certsTested;
+static int MakeCertOK;
+static int NoReuse;
+static PRBool NoDelay;
+static PRBool QuitOnTimeout = PR_FALSE;
+
+static SSL3Statistics * ssl3stats;
+
+static int failed_already = 0;
+
+
+char * ownPasswd( PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *passwd = NULL;
+
+ if ( (!retry) && arg ) {
+ passwd = PL_strdup((char *)arg);
+ }
+
+ return passwd;
+}
+
+int stopping;
+int verbose;
+SECItem bigBuf;
+
+#define PRINTF if (verbose) printf
+#define FPRINTF if (verbose) fprintf
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-n rsa_nickname] [-p port] [-d dbdir] [-c connections]\n"
+ " [-DNvq] [-f fortezza_nickname] [-2 filename]\n"
+ " [-w dbpasswd] [-C cipher(s)] [-t threads] hostname\n"
+ " where -v means verbose\n"
+ " -D means no TCP delays\n"
+ " -q means quit when server gone (timeout rather than retry forever)\n"
+ " -N means no session reuse\n",
+ progName);
+ exit(1);
+}
+
+
+static void
+errWarn(char * funcString)
+{
+ PRErrorCode perr = PR_GetError();
+ const char * errString = SECU_Strerror(perr);
+
+ fprintf(stderr, "strsclnt: %s returned error %d:\n%s\n",
+ funcString, perr, errString);
+}
+
+static void
+errExit(char * funcString)
+{
+ errWarn(funcString);
+ exit(1);
+}
+
+/**************************************************************************
+**
+** Routines for disabling SSL ciphers.
+**
+**************************************************************************/
+
+void
+disableAllSSLCiphers(void)
+{
+ const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
+ int i = SSL_NumImplementedCiphers;
+ SECStatus rv;
+
+ /* disable all the SSL3 cipher suites */
+ while (--i >= 0) {
+ PRUint16 suite = cipherSuites[i];
+ rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
+ if (rv != SECSuccess) {
+ printf("SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n",
+ suite, i);
+ errWarn("SSL_CipherPrefSetDefault");
+ exit(2);
+ }
+ }
+}
+
+/* This invokes the "default" AuthCert handler in libssl.
+** The only reason to use this one is that it prints out info as it goes.
+*/
+static SECStatus
+mySSLAuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig,
+ PRBool isServer)
+{
+ SECStatus rv;
+ CERTCertificate * peerCert;
+
+ peerCert = SSL_PeerCertificate(fd);
+
+ PRINTF("strsclnt: Subject: %s\nstrsclnt: Issuer : %s\n",
+ peerCert->subjectName, peerCert->issuerName);
+ /* invoke the "default" AuthCert handler. */
+ rv = SSL_AuthCertificate(arg, fd, checkSig, isServer);
+
+ ++certsTested;
+ if (rv == SECSuccess) {
+ fputs("strsclnt: -- SSL: Server Certificate Validated.\n", stderr);
+ }
+ CERT_DestroyCertificate(peerCert);
+ /* error, if any, will be displayed by the Bad Cert Handler. */
+ return rv;
+}
+
+static SECStatus
+myBadCertHandler( void *arg, PRFileDesc *fd)
+{
+ int err = PR_GetError();
+ if (!MakeCertOK)
+ fprintf(stderr,
+ "strsclnt: -- SSL: Server Certificate Invalid, err %d.\n%s\n",
+ err, SECU_Strerror(err));
+ return (MakeCertOK ? SECSuccess : SECFailure);
+}
+
+void
+printSecurityInfo(PRFileDesc *fd)
+{
+ CERTCertificate * cert = NULL;
+ SSL3Statistics * ssl3stats = SSL_GetStatistics();
+ SECStatus result;
+ SSLChannelInfo channel;
+ SSLCipherSuiteInfo suite;
+
+ static int only_once;
+
+ if (only_once && verbose < 2)
+ return;
+ only_once = 1;
+
+ result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
+ if (result == SECSuccess &&
+ channel.length == sizeof channel &&
+ channel.cipherSuite) {
+ result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
+ &suite, sizeof suite);
+ if (result == SECSuccess) {
+ FPRINTF(stderr,
+ "strsclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
+ channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
+ suite.effectiveKeyBits, suite.symCipherName,
+ suite.macBits, suite.macAlgorithmName);
+ FPRINTF(stderr,
+ "strsclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n",
+ channel.authKeyBits, suite.authAlgorithmName,
+ channel.keaKeyBits, suite.keaTypeName);
+ }
+ }
+
+ cert = SSL_LocalCertificate(fd);
+ if (!cert)
+ cert = SSL_PeerCertificate(fd);
+
+ if (verbose && cert) {
+ char * ip = CERT_NameToAscii(&cert->issuer);
+ char * sp = CERT_NameToAscii(&cert->subject);
+ if (sp) {
+ fprintf(stderr, "strsclnt: subject DN: %s\n", sp);
+ PR_Free(sp);
+ }
+ if (ip) {
+ fprintf(stderr, "strsclnt: issuer DN: %s\n", ip);
+ PR_Free(ip);
+ }
+ }
+ if (cert) {
+ CERT_DestroyCertificate(cert);
+ cert = NULL;
+ }
+ fprintf(stderr,
+ "strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n",
+ ssl3stats->hsh_sid_cache_hits,
+ ssl3stats->hsh_sid_cache_misses,
+ ssl3stats->hsh_sid_cache_not_ok);
+
+}
+
+/**************************************************************************
+** Begin thread management routines and data.
+**************************************************************************/
+
+#define MAX_THREADS 128
+
+typedef int startFn(void *a, void *b, int c);
+
+PRLock * threadLock;
+PRCondVar * threadStartQ;
+PRCondVar * threadEndQ;
+
+int numUsed;
+int numRunning;
+PRInt32 numConnected;
+int max_threads = 8; /* default much less than max. */
+
+typedef enum { rs_idle = 0, rs_running = 1, rs_zombie = 2 } runState;
+
+typedef struct perThreadStr {
+ void * a;
+ void * b;
+ int c;
+ int rv;
+ startFn * startFunc;
+ PRThread * prThread;
+ PRBool inUse;
+ runState running;
+} perThread;
+
+perThread threads[MAX_THREADS];
+
+void
+thread_wrapper(void * arg)
+{
+ perThread * slot = (perThread *)arg;
+
+ /* wait for parent to finish launching us before proceeding. */
+ PR_Lock(threadLock);
+ PR_Unlock(threadLock);
+
+ slot->rv = (* slot->startFunc)(slot->a, slot->b, slot->c);
+
+ /* Handle cleanup of thread here. */
+ PRINTF("strsclnt: Thread in slot %d returned %d\n",
+ slot - threads, slot->rv);
+
+ PR_Lock(threadLock);
+ slot->running = rs_idle;
+ --numRunning;
+
+ /* notify the thread launcher. */
+ PR_NotifyCondVar(threadStartQ);
+
+ PR_Unlock(threadLock);
+}
+
+SECStatus
+launch_thread(
+ startFn * startFunc,
+ void * a,
+ void * b,
+ int c)
+{
+ perThread * slot;
+ int i;
+
+ if (!threadStartQ) {
+ threadLock = PR_NewLock();
+ threadStartQ = PR_NewCondVar(threadLock);
+ threadEndQ = PR_NewCondVar(threadLock);
+ }
+ PR_Lock(threadLock);
+ while (numRunning >= max_threads) {
+ PR_WaitCondVar(threadStartQ, PR_INTERVAL_NO_TIMEOUT);
+ }
+ for (i = 0; i < numUsed; ++i) {
+ if (threads[i].running == rs_idle)
+ break;
+ }
+ if (i >= numUsed) {
+ if (i >= MAX_THREADS) {
+ /* something's really wrong here. */
+ PORT_Assert(i < MAX_THREADS);
+ PR_Unlock(threadLock);
+ return SECFailure;
+ }
+ ++numUsed;
+ PORT_Assert(numUsed == i + 1);
+ }
+
+ slot = threads + i;
+ slot->a = a;
+ slot->b = b;
+ slot->c = c;
+
+ slot->startFunc = startFunc;
+
+ slot->prThread = PR_CreateThread(PR_USER_THREAD,
+ thread_wrapper, slot,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (slot->prThread == NULL) {
+ PR_Unlock(threadLock);
+ printf("strsclnt: Failed to launch thread!\n");
+ return SECFailure;
+ }
+
+ slot->inUse = 1;
+ slot->running = 1;
+ ++numRunning;
+ PR_Unlock(threadLock);
+ PRINTF("strsclnt: Launched thread in slot %d \n", i);
+
+ return SECSuccess;
+}
+
+/* Wait until numRunning == 0 */
+int
+reap_threads(void)
+{
+ perThread * slot;
+ int i;
+
+ if (!threadLock)
+ return 0;
+ PR_Lock(threadLock);
+ while (numRunning > 0) {
+ PR_WaitCondVar(threadStartQ, PR_INTERVAL_NO_TIMEOUT);
+ }
+
+ /* Safety Sam sez: make sure count is right. */
+ for (i = 0; i < numUsed; ++i) {
+ slot = threads + i;
+ if (slot->running != rs_idle) {
+ FPRINTF(stderr, "strsclnt: Thread in slot %d is in state %d!\n",
+ i, slot->running);
+ }
+ }
+ PR_Unlock(threadLock);
+ return 0;
+}
+
+void
+destroy_thread_data(void)
+{
+ PORT_Memset(threads, 0, sizeof threads);
+
+ if (threadEndQ) {
+ PR_DestroyCondVar(threadEndQ);
+ threadEndQ = NULL;
+ }
+ if (threadStartQ) {
+ PR_DestroyCondVar(threadStartQ);
+ threadStartQ = NULL;
+ }
+ if (threadLock) {
+ PR_DestroyLock(threadLock);
+ threadLock = NULL;
+ }
+}
+
+/**************************************************************************
+** End thread management routines.
+**************************************************************************/
+
+PRBool useModelSocket = PR_TRUE;
+
+static const char stopCmd[] = { "GET /stop " };
+static const char outHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: Netscape-Enterprise/2.0a\r\n"
+ "Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+};
+
+struct lockedVarsStr {
+ PRLock * lock;
+ int count;
+ int waiters;
+ PRCondVar * condVar;
+};
+
+typedef struct lockedVarsStr lockedVars;
+
+void
+lockedVars_Init( lockedVars * lv)
+{
+ lv->count = 0;
+ lv->waiters = 0;
+ lv->lock = PR_NewLock();
+ lv->condVar = PR_NewCondVar(lv->lock);
+}
+
+void
+lockedVars_Destroy( lockedVars * lv)
+{
+ PR_DestroyCondVar(lv->condVar);
+ lv->condVar = NULL;
+
+ PR_DestroyLock(lv->lock);
+ lv->lock = NULL;
+}
+
+void
+lockedVars_WaitForDone(lockedVars * lv)
+{
+ PR_Lock(lv->lock);
+ while (lv->count > 0) {
+ PR_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(lv->lock);
+}
+
+int /* returns count */
+lockedVars_AddToCount(lockedVars * lv, int addend)
+{
+ int rv;
+
+ PR_Lock(lv->lock);
+ rv = lv->count += addend;
+ if (rv <= 0) {
+ PR_NotifyCondVar(lv->condVar);
+ }
+ PR_Unlock(lv->lock);
+ return rv;
+}
+
+int
+do_writes(
+ void * a,
+ void * b,
+ int c)
+{
+ PRFileDesc * ssl_sock = (PRFileDesc *)a;
+ lockedVars * lv = (lockedVars *)b;
+ int sent = 0;
+ int count = 0;
+
+ while (sent < bigBuf.len) {
+
+ count = PR_Write(ssl_sock, bigBuf.data + sent, bigBuf.len - sent);
+ if (count < 0) {
+ errWarn("PR_Write bigBuf");
+ break;
+ }
+ FPRINTF(stderr, "strsclnt: PR_Write wrote %d bytes from bigBuf\n",
+ count );
+ sent += count;
+ }
+ if (count >= 0) { /* last write didn't fail. */
+ PR_Shutdown(ssl_sock, PR_SHUTDOWN_SEND);
+ }
+
+ /* notify the reader that we're done. */
+ lockedVars_AddToCount(lv, -1);
+ return (sent < bigBuf.len) ? SECFailure : SECSuccess;
+}
+
+int
+handle_fdx_connection( PRFileDesc * ssl_sock, int connection)
+{
+ SECStatus result;
+ int firstTime = 1;
+ int countRead = 0;
+ lockedVars lv;
+ char *buf;
+
+
+ lockedVars_Init(&lv);
+ lockedVars_AddToCount(&lv, 1);
+
+ /* Attempt to launch the writer thread. */
+ result = launch_thread(do_writes, ssl_sock, &lv, connection);
+
+ if (result != SECSuccess)
+ goto cleanup;
+
+ buf = PR_Malloc(RD_BUF_SIZE);
+
+ if (buf) {
+ do {
+ /* do reads here. */
+ PRInt32 count;
+
+ count = PR_Read(ssl_sock, buf, RD_BUF_SIZE);
+ if (count < 0) {
+ errWarn("PR_Read");
+ break;
+ }
+ countRead += count;
+ FPRINTF(stderr,
+ "strsclnt: connection %d read %d bytes (%d total).\n",
+ connection, count, countRead );
+ if (firstTime) {
+ firstTime = 0;
+ printSecurityInfo(ssl_sock);
+ }
+ } while (lockedVars_AddToCount(&lv, 0) > 0);
+ PR_Free(buf);
+ buf = 0;
+ }
+
+ /* Wait for writer to finish */
+ lockedVars_WaitForDone(&lv);
+ lockedVars_Destroy(&lv);
+
+ FPRINTF(stderr,
+ "strsclnt: connection %d read %d bytes total. -----------------------\n",
+ connection, countRead);
+
+cleanup:
+ /* Caller closes the socket. */
+
+ return SECSuccess;
+}
+
+const char request[] = {"GET /abc HTTP/1.0\r\n\r\n" };
+
+SECStatus
+handle_connection( PRFileDesc *ssl_sock, int connection)
+{
+ int countRead = 0;
+ PRInt32 rv;
+ char *buf;
+
+ buf = PR_Malloc(RD_BUF_SIZE);
+ if (!buf)
+ return SECFailure;
+
+ /* compose the http request here. */
+
+ rv = PR_Write(ssl_sock, request, strlen(request));
+ if (rv <= 0) {
+ errWarn("PR_Write");
+ PR_Free(buf);
+ buf = 0;
+ failed_already = 1;
+ return SECFailure;
+ }
+ printSecurityInfo(ssl_sock);
+
+ /* read until EOF */
+ while (1) {
+ rv = PR_Read(ssl_sock, buf, RD_BUF_SIZE);
+ if (rv == 0) {
+ break; /* EOF */
+ }
+ if (rv < 0) {
+ errWarn("PR_Read");
+ break;
+ }
+
+ countRead += rv;
+ FPRINTF(stderr, "strsclnt: connection %d read %d bytes (%d total).\n",
+ connection, rv, countRead );
+ }
+ PR_Free(buf);
+ buf = 0;
+
+ /* Caller closes the socket. */
+
+ FPRINTF(stderr,
+ "strsclnt: connection %d read %d bytes total. -----------------------\n",
+ connection, countRead);
+
+ return SECSuccess; /* success */
+}
+
+/* one copy of this function is launched in a separate thread for each
+** connection to be made.
+*/
+int
+do_connects(
+ void * a,
+ void * b,
+ int connection)
+{
+ PRNetAddr * addr = (PRNetAddr *) a;
+ PRFileDesc * model_sock = (PRFileDesc *) b;
+ PRFileDesc * ssl_sock = 0;
+ PRFileDesc * tcp_sock = 0;
+ PRStatus prStatus;
+ PRUint32 sleepInterval = 50; /* milliseconds */
+ SECStatus result;
+ int rv = SECSuccess;
+ PRSocketOptionData opt;
+
+retry:
+
+ tcp_sock = PR_NewTCPSocket();
+ if (tcp_sock == NULL) {
+ errExit("PR_NewTCPSocket");
+ }
+
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ prStatus = PR_SetSocketOption(tcp_sock, &opt);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_SetSocketOption(PR_SockOpt_Nonblocking, PR_FALSE)");
+ PR_Close(tcp_sock);
+ return SECSuccess;
+ }
+
+ if (NoDelay) {
+ opt.option = PR_SockOpt_NoDelay;
+ opt.value.no_delay = PR_TRUE;
+ prStatus = PR_SetSocketOption(tcp_sock, &opt);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)");
+ PR_Close(tcp_sock);
+ return SECSuccess;
+ }
+ }
+
+ prStatus = PR_Connect(tcp_sock, addr, PR_INTERVAL_NO_TIMEOUT);
+ if (prStatus != PR_SUCCESS) {
+ PRErrorCode err = PR_GetError();
+ if ((err == PR_CONNECT_REFUSED_ERROR) ||
+ (err == PR_CONNECT_RESET_ERROR) ) {
+ int connections = numConnected;
+
+ PR_Close(tcp_sock);
+ if (connections > 2 && max_threads >= connections) {
+ max_threads = connections - 1;
+ fprintf(stderr,"max_threads set down to %d\n", max_threads);
+ }
+ if (QuitOnTimeout && sleepInterval > 40000) {
+ fprintf(stderr,
+ "strsclnt: Client timed out waiting for connection to server.\n");
+ exit(1);
+ }
+ PR_Sleep(PR_MillisecondsToInterval(sleepInterval));
+ sleepInterval <<= 1;
+ goto retry;
+ }
+ errWarn("PR_Connect");
+ rv = SECFailure;
+ goto done;
+ }
+
+ ssl_sock = SSL_ImportFD(model_sock, tcp_sock);
+ /* XXX if this import fails, close tcp_sock and return. */
+ if (!ssl_sock) {
+ PR_Close(tcp_sock);
+ return SECSuccess;
+ }
+
+ rv = SSL_ResetHandshake(ssl_sock, /* asServer */ 0);
+ if (rv != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ goto done;
+ }
+
+ PR_AtomicIncrement(&numConnected);
+
+ if (bigBuf.data != NULL) {
+ result = handle_fdx_connection( ssl_sock, connection);
+ } else {
+ result = handle_connection( ssl_sock, connection);
+ }
+
+ PR_AtomicDecrement(&numConnected);
+
+done:
+ if (ssl_sock) {
+ PR_Close(ssl_sock);
+ } else if (tcp_sock) {
+ PR_Close(tcp_sock);
+ }
+ return SECSuccess;
+}
+
+/* Returns IP address for hostname as PRUint32 in Host Byte Order.
+** Since the value returned is an integer (not a string of bytes),
+** it is inherently in Host Byte Order.
+*/
+PRUint32
+getIPAddress(const char * hostName)
+{
+ const unsigned char *p;
+ PRStatus prStatus;
+ PRUint32 rv;
+ PRHostEnt prHostEnt;
+ char scratch[PR_NETDB_BUF_SIZE];
+
+ prStatus = PR_GetHostByName(hostName, scratch, sizeof scratch, &prHostEnt);
+ if (prStatus != PR_SUCCESS)
+ errExit("PR_GetHostByName");
+
+#undef h_addr
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+
+ p = (const unsigned char *)(prHostEnt.h_addr); /* in Network Byte order */
+ FPRINTF(stderr, "strsclnt: %s -> %d.%d.%d.%d\n", hostName,
+ p[0], p[1], p[2], p[3]);
+ rv = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ return rv;
+}
+
+void
+client_main(
+ unsigned short port,
+ int connections,
+ SECKEYPrivateKey ** privKey,
+ CERTCertificate ** cert,
+ const char * hostName,
+ char * nickName)
+{
+ PRFileDesc *model_sock = NULL;
+ int i;
+ int rv;
+ PRUint32 ipAddress; /* in host byte order */
+ PRNetAddr addr;
+
+ /* Assemble NetAddr struct for connections. */
+ ipAddress = getIPAddress(hostName);
+
+ addr.inet.family = PR_AF_INET;
+ addr.inet.port = PR_htons(port);
+ addr.inet.ip = PR_htonl(ipAddress);
+
+ /* all suites except RSA_NULL_MD5 are enabled by Domestic Policy */
+ NSS_SetDomesticPolicy();
+
+ /* all the SSL2 and SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ int ndx;
+
+ /* disable all the ciphers, then enable the ones we want. */
+ disableAllSSLCiphers();
+
+ while (0 != (ndx = *cipherString++)) {
+ int *cptr;
+ int cipher;
+
+ if (! isalpha(ndx))
+ Usage("strsclnt");
+ cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
+ for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
+ /* do nothing */;
+ if (cipher) {
+ SECStatus rv;
+ rv = SSL_CipherPrefSetDefault(cipher, PR_TRUE);
+ if (rv != SECSuccess) {
+ fprintf(stderr,
+ "strsclnt: SSL_CipherPrefSetDefault failed with value 0x%04x\n",
+ cipher);
+ exit(1);
+ }
+ }
+ }
+ }
+
+ /* configure model SSL socket. */
+
+ model_sock = PR_NewTCPSocket();
+ if (model_sock == NULL) {
+ errExit("PR_NewTCPSocket on model socket");
+ }
+
+ model_sock = SSL_ImportFD(NULL, model_sock);
+ if (model_sock == NULL) {
+ errExit("SSL_ImportFD");
+ }
+
+ /* do SSL configuration. */
+
+ rv = SSL_OptionSet(model_sock, SSL_SECURITY, 1);
+ if (rv < 0) {
+ errExit("SSL_OptionSet SSL_SECURITY");
+ }
+
+ if (bigBuf.data) { /* doing FDX */
+ rv = SSL_OptionSet(model_sock, SSL_ENABLE_FDX, 1);
+ if (rv < 0) {
+ errExit("SSL_OptionSet SSL_ENABLE_FDX");
+ }
+ }
+
+ if (NoReuse) {
+ rv = SSL_OptionSet(model_sock, SSL_NO_CACHE, 1);
+ if (rv < 0) {
+ errExit("SSL_OptionSet SSL_NO_CACHE");
+ }
+ }
+
+ SSL_SetURL(model_sock, hostName);
+
+ SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate,
+ (void *)CERT_GetDefaultCertDB());
+
+ SSL_BadCertHook(model_sock, myBadCertHandler, NULL);
+
+ SSL_GetClientAuthDataHook(model_sock, NSS_GetClientAuthData, nickName);
+
+ /* I'm not going to set the HandshakeCallback function. */
+
+ /* end of ssl configuration. */
+
+ i = 1;
+ if (!NoReuse) {
+ rv = launch_thread(do_connects, &addr, model_sock, i);
+ --connections;
+ ++i;
+ /* wait for the first connection to terminate, then launch the rest. */
+ reap_threads();
+ }
+ if (connections > 0) {
+ /* Start up the connections */
+ do {
+ rv = launch_thread(do_connects, &addr, model_sock, i);
+ ++i;
+ } while (--connections > 0);
+ reap_threads();
+ }
+ destroy_thread_data();
+
+ PR_Close(model_sock);
+
+}
+
+SECStatus
+readBigFile(const char * fileName)
+{
+ PRFileInfo info;
+ PRStatus status;
+ SECStatus rv = SECFailure;
+ int count;
+ int hdrLen;
+ PRFileDesc *local_file_fd = NULL;
+
+ status = PR_GetFileInfo(fileName, &info);
+
+ if (status == PR_SUCCESS &&
+ info.type == PR_FILE_FILE &&
+ info.size > 0 &&
+ NULL != (local_file_fd = PR_Open(fileName, PR_RDONLY, 0))) {
+
+ hdrLen = PORT_Strlen(outHeader);
+ bigBuf.len = hdrLen + info.size;
+ bigBuf.data = PORT_Malloc(bigBuf.len + 4095);
+ if (!bigBuf.data) {
+ errWarn("PORT_Malloc");
+ goto done;
+ }
+
+ PORT_Memcpy(bigBuf.data, outHeader, hdrLen);
+
+ count = PR_Read(local_file_fd, bigBuf.data + hdrLen, info.size);
+ if (count != info.size) {
+ errWarn("PR_Read local file");
+ goto done;
+ }
+ rv = SECSuccess;
+done:
+ PR_Close(local_file_fd);
+ }
+ return rv;
+}
+
+int
+main(int argc, char **argv)
+{
+ const char * dir = ".";
+ char * fNickName = NULL;
+ const char * fileName = NULL;
+ char * hostName = NULL;
+ char * nickName = NULL;
+ char * progName = NULL;
+ char * tmp = NULL;
+ char * passwd = NULL;
+ CERTCertificate * cert [kt_kea_size] = { NULL };
+ SECKEYPrivateKey * privKey[kt_kea_size] = { NULL };
+ int connections = 1;
+ int exitVal;
+ int tmpInt;
+ unsigned short port = 443;
+ SECStatus rv;
+ PLOptState * optstate;
+ PLOptStatus status;
+
+ /* Call the NSPR initialization routines */
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ tmp = strrchr(argv[0], '/');
+ tmp = tmp ? tmp + 1 : argv[0];
+ progName = strrchr(tmp, '\\');
+ progName = progName ? progName + 1 : tmp;
+
+
+ optstate = PL_CreateOptState(argc, argv, "2:C:DNc:d:f:n:op:t:vqw:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch(optstate->option) {
+
+ case '2': fileName = optstate->value; break;
+
+ case 'C': cipherString = optstate->value; break;
+
+ case 'D': NoDelay = PR_TRUE; break;
+
+ case 'N': NoReuse = 1; break;
+
+ case 'c': connections = PORT_Atoi(optstate->value); break;
+
+ case 'd': dir = optstate->value; break;
+
+ case 'f': fNickName = PL_strdup(optstate->value); break;
+
+ case 'n': nickName = PL_strdup(optstate->value); break;
+
+ case 'o': MakeCertOK = 1; break;
+
+ case 'p': port = PORT_Atoi(optstate->value); break;
+
+ case 'q': QuitOnTimeout = PR_TRUE; break;
+
+ case 't':
+ tmpInt = PORT_Atoi(optstate->value);
+ if (tmpInt > 0 && tmpInt < MAX_THREADS)
+ max_threads = tmpInt;
+ break;
+
+ case 'v': verbose++; break;
+
+ case 'w': passwd = PL_strdup(optstate->value); break;
+
+ case 0: /* positional parameter */
+ if (hostName) {
+ Usage(progName);
+ }
+ hostName = PL_strdup(optstate->value);
+ break;
+
+ default:
+ case '?':
+ Usage(progName);
+ break;
+
+ }
+ }
+ if (!hostName || status == PL_OPT_BAD)
+ Usage(progName);
+
+ if (port == 0)
+ Usage(progName);
+
+ if (fileName)
+ readBigFile(fileName);
+
+ /* set our password function */
+ if ( passwd ) {
+ PK11_SetPasswordFunc(ownPasswd);
+ } else {
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+ }
+
+ /* Call the libsec initialization routines */
+ rv = NSS_Init(dir);
+ if (rv != SECSuccess) {
+ fputs("NSS_Init failed.\n", stderr);
+ exit(1);
+ }
+ ssl3stats = SSL_GetStatistics();
+
+ if (nickName && strcmp(nickName, "none")) {
+
+ cert[kt_rsa] = PK11_FindCertFromNickname(nickName, passwd);
+ if (cert[kt_rsa] == NULL) {
+ fprintf(stderr, "strsclnt: Can't find certificate %s\n", nickName);
+ exit(1);
+ }
+
+ privKey[kt_rsa] = PK11_FindKeyByAnyCert(cert[kt_rsa], passwd);
+ if (privKey[kt_rsa] == NULL) {
+ fprintf(stderr, "strsclnt: Can't find Private Key for cert %s\n",
+ nickName);
+ exit(1);
+ }
+
+ }
+ if (fNickName) {
+ cert[kt_fortezza] = PK11_FindCertFromNickname(fNickName, passwd);
+ if (cert[kt_fortezza] == NULL) {
+ fprintf(stderr, "strsclnt: Can't find certificate %s\n", fNickName);
+ exit(1);
+ }
+
+ privKey[kt_fortezza] = PK11_FindKeyByAnyCert(cert[kt_fortezza], passwd);
+ if (privKey[kt_fortezza] == NULL) {
+ fprintf(stderr, "strsclnt: Can't find Private Key for cert %s\n",
+ fNickName);
+ exit(1);
+ }
+ }
+
+ client_main(port, connections, privKey, cert, hostName, nickName);
+
+ /* clean up */
+ if (cert[kt_rsa]) {
+ CERT_DestroyCertificate(cert[kt_rsa]);
+ }
+ if (cert[kt_fortezza]) {
+ CERT_DestroyCertificate(cert[kt_fortezza]);
+ }
+ if (privKey[kt_rsa]) {
+ SECKEY_DestroyPrivateKey(privKey[kt_rsa]);
+ }
+ if (privKey[kt_fortezza]) {
+ SECKEY_DestroyPrivateKey(privKey[kt_fortezza]);
+ }
+
+ /* some final stats. */
+ if (ssl3stats->hsh_sid_cache_hits + ssl3stats->hsh_sid_cache_misses +
+ ssl3stats->hsh_sid_cache_not_ok == 0) {
+ /* presumably we were testing SSL2. */
+ printf("strsclnt: %d server certificates tested.\n", certsTested);
+ } else {
+ printf(
+ "strsclnt: %ld cache hits; %ld cache misses, %ld cache not reusable\n",
+ ssl3stats->hsh_sid_cache_hits,
+ ssl3stats->hsh_sid_cache_misses,
+ ssl3stats->hsh_sid_cache_not_ok);
+ }
+
+ if (!NoReuse)
+ exitVal = (ssl3stats->hsh_sid_cache_misses > 1) ||
+ (ssl3stats->hsh_sid_cache_not_ok != 0) ||
+ (certsTested > 1);
+ else
+ exitVal = (ssl3stats->hsh_sid_cache_misses != connections) ||
+ (certsTested != connections);
+
+ exitVal = ( exitVal || failed_already );
+ SSL_ClearSessionCache();
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ PR_Cleanup();
+ return exitVal;
+}
+
diff --git a/security/nss/cmd/swfort/Makefile b/security/nss/cmd/swfort/Makefile
new file mode 100644
index 000000000..a5b4350a6
--- /dev/null
+++ b/security/nss/cmd/swfort/Makefile
@@ -0,0 +1,108 @@
+#! gmake
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+
+CORE_DEPTH = ../../..
+
+include manifest.mn
+include $(CORE_DEPTH)/coreconf/config.mk
+
+# $(NULL)
+
+
+INCLUDES += \
+ -I$(DIST)/../public/security \
+ -I$(DIST)/../private/security \
+ -I$(DEPTH)/security/lib/cert \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+ -I./include \
+ $(NULL)
+
+
+# For the time being, sec stuff is export only
+# US_FLAGS = -DEXPORT_VERSION -DUS_VERSION
+
+US_FLAGS = -DEXPORT_VERSION
+EXPORT_FLAGS = -DEXPORT_VERSION
+
+BASE_LIBS = \
+ $(DIST)/lib/libdbm.$(LIB_SUFFIX) \
+ $(DIST)/lib/libxp.$(LIB_SUFFIX) \
+ $(DIST)/lib/libnspr.$(LIB_SUFFIX) \
+ $(NULL)
+
+# $(DIST)/lib/libpurenspr.$(LIB_SUFFIX) \
+
+#There are a circular dependancies in security/lib, and we deal with it by
+# double linking some libraries
+SEC_LIBS = \
+ $(DIST)/lib/libsecnav.$(LIB_SUFFIX) \
+ $(DIST)/lib/libssl.$(LIB_SUFFIX) \
+ $(DIST)/lib/libpkcs7.$(LIB_SUFFIX) \
+ $(DIST)/lib/libcert.$(LIB_SUFFIX) \
+ $(DIST)/lib/libkey.$(LIB_SUFFIX) \
+ $(DIST)/lib/libsecmod.$(LIB_SUFFIX) \
+ $(DIST)/lib/libcrypto.$(LIB_SUFFIX) \
+ $(DIST)/lib/libsecutil.$(LIB_SUFFIX) \
+ $(DIST)/lib/libssl.$(LIB_SUFFIX) \
+ $(DIST)/lib/libpkcs7.$(LIB_SUFFIX) \
+ $(DIST)/lib/libcert.$(LIB_SUFFIX) \
+ $(DIST)/lib/libkey.$(LIB_SUFFIX) \
+ $(DIST)/lib/libsecmod.$(LIB_SUFFIX) \
+ $(DIST)/lib/libcrypto.$(LIB_SUFFIX) \
+ $(DIST)/lib/libsecutil.$(LIB_SUFFIX) \
+ $(DIST)/lib/libhash.$(LIB_SUFFIX) \
+ $(NULL)
+
+MYLIB = lib/$(OBJDIR)/libsectool.$(LIB_SUFFIX)
+
+US_LIBS = $(MYLIB) $(SEC_LIBS) $(BASE_LIBS) $(MYLIB) $(BASE_LIBS)
+EX_LIBS = $(MYLIB) $(SEC_LIBS) $(BASE_LIBS) $(MYLIB) $(BASE_LIBS)
+
+REQUIRES = libxp nspr security
+
+CSRCS = $(EXEC_SRCS) $(BI_SRCS)
+
+OBJS = $(CSRCS:.c=.o) $(BI_SRCS:.c=-us.o) $(BI_SRCS:.c=-ex.o)
+
+PROGS = $(addprefix $(OBJDIR)/, $(EXEC_SRCS:.c=$(BIN_SUFFIX)))
+US_PROGS = $(addprefix $(OBJDIR)/, $(BI_SRCS:.c=-us$(BIN_SUFFIX)))
+EX_PROGS = $(addprefix $(OBJDIR)/, $(BI_SRCS:.c=-ex$(BIN_SUFFIX)))
+
+
+NON_DIRS = $(PROGS) $(US_PROGS) $(EX_PROGS)
+TARGETS = $(NON_DIRS)
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+symbols::
+ @echo "TARGETS = $(TARGETS)"
diff --git a/security/nss/cmd/swfort/instinit/Makefile b/security/nss/cmd/swfort/instinit/Makefile
new file mode 100644
index 000000000..f912d54cd
--- /dev/null
+++ b/security/nss/cmd/swfort/instinit/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../../platrules.mk
diff --git a/security/nss/cmd/swfort/instinit/instinit.c b/security/nss/cmd/swfort/instinit/instinit.c
new file mode 100644
index 000000000..8b8b86c81
--- /dev/null
+++ b/security/nss/cmd/swfort/instinit/instinit.c
@@ -0,0 +1,421 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#include <stdio.h>
+
+#include "prio.h"
+#include "seccomon.h"
+#include "swforti.h"
+#include "cert.h"
+#include "pk11func.h"
+#include "nss.h"
+#include "secutil.h"
+
+#define CERTDB_VALID_CA (1<<3)
+#define CERTDB_TRUSTED_CA (1<<4) /* trusted for issuing server certs */
+
+void secmod_GetInternalModule(SECMODModule *module);
+void sec_SetCheckKRLState(int i);
+
+#define STEP 16
+void
+printItem(SECItem *key) {
+ int i;
+ unsigned char *block;
+ int len;
+ for (block=key->data,len=key->len; len > 0; len -= STEP,block += STEP) {
+ for(i=0; i < STEP && i < len; i++) printf(" %02x ",block[i]);
+ printf("\n");
+ }
+ printf("\n");
+}
+
+void
+dump(unsigned char *block, int len) {
+ int i;
+ for (; len > 0; len -= STEP,block += STEP) {
+ for(i=0; i < STEP && i < len; i++) printf(" %02x ",block[i]);
+ printf("\n");
+ }
+ printf("\n");
+}
+
+
+/*
+ * We need to move this to security/cmd .. so we can use the password
+ * prompting infrastructure.
+ */
+char *GetUserInput(char * prompt)
+{
+ char phrase[200];
+
+ fprintf(stderr, "%s", prompt);
+ fflush (stderr);
+
+ fgets ((char*) phrase, sizeof(phrase), stdin);
+
+ /* stomp on newline */
+ phrase[PORT_Strlen((char*)phrase)-1] = 0;
+
+ /* Validate password */
+ return (char*) PORT_Strdup((char*)phrase);
+}
+
+void ClearPass(char *pass) {
+ PORT_Memset(pass,0,strlen(pass));
+ PORT_Free(pass);
+}
+
+char *
+formatDERIssuer(FORTSWFile *file,SECItem *derIssuer)
+{
+ CERTName name;
+ SECStatus rv;
+
+ PORT_Memset(&name,0,sizeof(name));;
+ rv = SEC_ASN1DecodeItem(file->arena,&name,CERT_NameTemplate,derIssuer);
+ if (rv != SECSuccess) {
+ return NULL;
+ }
+ return CERT_NameToAscii(&name);
+}
+
+#define NETSCAPE_INIT_FILE "nsswft.swf"
+
+char *getDefaultTarget(void)
+{
+ char *fname = NULL;
+ char *home = NULL;
+ static char unix_home[512];
+
+ /* first try to get it from the environment */
+ fname = getenv("SW_FORTEZZA_FILE");
+ if (fname != NULL) {
+ return PORT_Strdup(fname);
+ }
+
+#ifdef XP_UNIX
+ home = getenv("HOME");
+ if (home) {
+ strncpy(unix_home,home, sizeof(unix_home)-sizeof("/.netscape/"NETSCAPE_INIT_FILE));
+ strcat(unix_home,"/.netscape/"NETSCAPE_INIT_FILE);
+ return unix_home;
+ }
+#endif
+#ifdef XP_WIN
+ home = getenv("windir");
+ if (home) {
+ strncpy(unix_home,home, sizeof(unix_home)-sizeof("\\"NETSCAPE_INIT_FILE));
+ strcat(unix_home,"\\"NETSCAPE_INIT_FILE);
+ return unix_home;
+ }
+#endif
+ return (NETSCAPE_INIT_FILE);
+}
+
+void
+usage(char *prog) {
+ fprintf(stderr,"usage: %s [-v][-f][-t transport_pass][-u user_pass][-o output_file] source_file\n",prog);
+ exit(1);
+}
+
+int main(int argc, char ** argv)
+{
+
+ FORTSignedSWFile * swfile;
+ int size;
+ SECItem file;
+ char *progname = *argv++;
+ char *filename = NULL;
+ char *outname = NULL;
+ char *cp;
+ int verbose = 0;
+ int force = 0;
+ CERTCertDBHandle *certhandle = NULL;
+ CERTCertificate *cert;
+ CERTCertTrust *trust;
+ char * pass;
+ SECStatus rv;
+ int i;
+ int64 now; /* XXXX */
+ char *issuer;
+ char *transport_pass = NULL;
+ char *user_pass = NULL;
+ SECItem *outItem = NULL;
+ PRFileDesc *fd;
+ PRFileInfo info;
+ PRStatus prv;
+
+
+
+
+ /* put better argument parsing here */
+ while ((cp = *argv++) != NULL) {
+ if (*cp == '-') {
+ while (*++cp) {
+ switch (*cp) {
+ /* verbose mode */
+ case 'v':
+ verbose++;
+ break;
+ /* explicitly set the target */
+ case 'o':
+ outname = *argv++;
+ break;
+ case 'f':
+ /* skip errors in signatures without prompts */
+ force++;
+ break;
+ case 't':
+ /* provide password on command line */
+ transport_pass = *argv++;
+ break;
+ case 'u':
+ /* provide user password on command line */
+ user_pass = *argv++;
+ break;
+ default:
+ usage(progname);
+ break;
+ }
+ }
+ } else if (filename) {
+ usage(progname);
+ } else {
+ filename = cp;
+ }
+ }
+
+ if (filename == NULL) usage(progname);
+ if (outname == NULL) outname = getDefaultTarget();
+
+
+ now = PR_Now();
+ /* read the file in */
+ fd = PR_Open(filename,PR_RDONLY,0);
+ if (fd == NULL) {
+ fprintf(stderr,"%s: couldn't open file \"%s\".\n",progname,filename);
+ exit(1);
+ }
+
+ prv = PR_GetOpenFileInfo(fd,&info);
+ if (prv != PR_SUCCESS) {
+ fprintf(stderr,"%s: couldn't get info on file \"%s\".\n",
+ progname,filename);
+ exit(1);
+ }
+
+ size = info.size;
+
+ file.data = malloc(size);
+ file.len = size;
+
+ file.len = PR_Read(fd,file.data,file.len);
+ if (file.len < 0) {
+ fprintf(stderr,"%s: couldn't read file \"%s\".\n",progname, filename);
+ exit(1);
+ }
+
+ PR_Close(fd);
+
+ /* Parse the file */
+ swfile = FORT_GetSWFile(&file);
+ if (swfile == NULL) {
+ fprintf(stderr,
+ "%s: File \"%s\" not a valid FORTEZZA initialization file.\n",
+ progname,filename);
+ exit(1);
+ }
+
+ issuer = formatDERIssuer(&swfile->file,&swfile->file.derIssuer);
+ if (issuer == NULL) {
+ issuer = "<Invalid Issuer DER>";
+ }
+
+ if (verbose) {
+ printf("Processing file %s ....\n",filename);
+ printf(" Version %ld\n",DER_GetInteger(&swfile->file.version));
+ printf(" Issuer: %s\n",issuer);
+ printf(" Serial Number: ");
+ for (i=0; i < (int)swfile->file.serialID.len; i++) {
+ printf(" %02x",swfile->file.serialID.data[i]);
+ }
+ printf("\n");
+ }
+
+
+ /* Check the Initalization phrase and save Kinit */
+ if (!transport_pass) {
+ pass = SECU_GetPasswordString(NULL,"Enter the Initialization Memphrase:");
+ transport_pass = pass;
+ }
+ rv = FORT_CheckInitPhrase(swfile,transport_pass);
+ if (rv != SECSuccess) {
+ fprintf(stderr,
+ "%s: Invalid Initialization Memphrase for file \"%s\".\n",
+ progname,filename);
+ exit(1);
+ }
+
+ /* Check the user or init phrase and save Ks, use Kinit to unwrap the
+ * remaining data. */
+ if (!user_pass) {
+ pass = SECU_GetPasswordString(NULL,"Enter the User Memphrase or the User PIN:");
+ user_pass = pass;
+ }
+ rv = FORT_CheckUserPhrase(swfile,user_pass);
+ if (rv != SECSuccess) {
+ fprintf(stderr,"%s: Invalid User Memphrase or PIN for file \"%s\".\n",
+ progname,filename);
+ exit(1);
+ }
+
+ NSS_NoDB_Init(NULL);
+ sec_SetCheckKRLState(1);
+ certhandle = CERT_GetDefaultCertDB();
+
+ /* now dump the certs into the temparary data base */
+ for (i=0; swfile->file.slotEntries[i]; i++) {
+ int trusted = 0;
+ SECItem *derCert = FORT_GetDERCert(swfile,
+ swfile->file.slotEntries[i]->certIndex);
+
+ if (derCert == NULL) {
+ if (verbose) {
+ printf(" Cert %02d: %s \"%s\" \n",
+ swfile->file.slotEntries[i]->certIndex,
+ "untrusted", "Couldn't decrypt Cert");
+ }
+ continue;
+ }
+ cert = CERT_NewTempCertificate(certhandle, derCert, NULL,
+ PR_FALSE, PR_TRUE);
+ if (cert == NULL) {
+ if (verbose) {
+ printf(" Cert %02d: %s \"%s\" \n",
+ swfile->file.slotEntries[i]->certIndex,
+ "untrusted", "Couldn't decode Cert");
+ }
+ continue;
+ }
+ if (swfile->file.slotEntries[i]->trusted.data[0]) {
+ /* Add TRUST */
+ trust = PORT_ArenaAlloc(cert->arena,sizeof(CERTCertTrust));
+ if (trust != NULL) {
+ trust->sslFlags = CERTDB_VALID_CA|CERTDB_TRUSTED_CA;
+ trust->emailFlags = CERTDB_VALID_CA|CERTDB_TRUSTED_CA;
+ trust->objectSigningFlags = CERTDB_VALID_CA|CERTDB_TRUSTED_CA;
+ cert->trust = trust;
+ trusted++;
+ }
+ }
+ if (verbose) {
+ printf(" Cert %02d: %s \"%s\" \n",
+ swfile->file.slotEntries[i]->certIndex,
+ trusted?" trusted ":"untrusted",
+ CERT_NameToAscii(&cert->subject));
+ }
+ }
+
+ fflush(stdout);
+
+
+ cert = CERT_FindCertByName(certhandle,&swfile->file.derIssuer);
+ if (cert == NULL) {
+ fprintf(stderr,"%s: Couldn't find signer certificate \"%s\".\n",
+ progname,issuer);
+ rv = SECFailure;
+ goto noverify;
+ }
+ rv = CERT_VerifySignedData(&swfile->signatureWrap,cert, now, NULL);
+ if (rv != SECSuccess) {
+ fprintf(stderr,
+ "%s: Couldn't verify the signature on file \"%s\" with certificate \"%s\".\n",
+ progname,filename,issuer);
+ goto noverify;
+ }
+ rv = CERT_VerifyCert(certhandle, cert, PR_TRUE, certUsageSSLServer,
+ now ,NULL,NULL);
+ /* not an normal cert, see if it's a CA? */
+ if (rv != SECSuccess) {
+ rv = CERT_VerifyCert(certhandle, cert, PR_TRUE, certUsageAnyCA,
+ now ,NULL,NULL);
+ }
+ if (rv != SECSuccess) {
+ fprintf(stderr,"%s: Couldn't verify the signer certificate \"%s\".\n",
+ progname,issuer);
+ goto noverify;
+ }
+
+noverify:
+ if (rv != SECSuccess) {
+ if (!force) {
+ pass = GetUserInput(
+ "Signature verify failed, continue without verification? ");
+ if (!(pass && ((*pass == 'Y') || (*pass == 'y')))) {
+ exit(1);
+ }
+ }
+ }
+
+
+ /* now write out the modified init file for future use */
+ outItem = FORT_PutSWFile(swfile);
+ if (outItem == NULL) {
+ fprintf(stderr,"%s: Couldn't format target init file.\n",
+ progname);
+ goto noverify;
+ }
+
+ if (verbose) {
+ printf("writing modified file out to \"%s\".\n",outname);
+ }
+
+ /* now write it out */
+ fd = PR_Open(outname,PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,0700);
+ if (fd == NULL) {
+ fprintf(stderr,"%s: couldn't open file \"%s\".\n",progname,outname);
+ exit(1);
+ }
+
+ file.len = PR_Write(fd,outItem->data,outItem->len);
+ if (file.len < 0) {
+ fprintf(stderr,"%s: couldn't read file \"%s\".\n",progname, filename);
+ exit(1);
+ }
+
+ PR_Close(fd);
+
+ exit(0);
+ return (0);
+}
+
diff --git a/security/nss/cmd/swfort/instinit/manifest.mn b/security/nss/cmd/swfort/instinit/manifest.mn
new file mode 100644
index 000000000..8380f4246
--- /dev/null
+++ b/security/nss/cmd/swfort/instinit/manifest.mn
@@ -0,0 +1,46 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+CORE_DEPTH = ../../../..
+
+DEFINES += -DNSPR20
+
+MODULE = nss
+
+CSRCS = instinit.c
+
+REQUIRES = nspr dbm seccmd
+
+PROGRAM = instinit
+# PROGRAM = ./$(OBJDIR)/selfserv.exe
+
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/swfort/manifest.mn b/security/nss/cmd/swfort/manifest.mn
new file mode 100644
index 000000000..aaacd83e8
--- /dev/null
+++ b/security/nss/cmd/swfort/manifest.mn
@@ -0,0 +1,38 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+CORE_DEPTH = ../../..
+
+REQUIRES = nss seccmd dbm
+
+
+DIRS = instinit newuser
diff --git a/security/nss/cmd/swfort/newuser/Makefile b/security/nss/cmd/swfort/newuser/Makefile
new file mode 100644
index 000000000..f0a47a0a3
--- /dev/null
+++ b/security/nss/cmd/swfort/newuser/Makefile
@@ -0,0 +1,83 @@
+#! gmake
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+ctmp := $(shell $(MAKE) -C ../../../lib/fortcrypt --no-print-directory cilib_name)
+ifeq ($(ctmp), $(patsubst /%,/,$(ctmp)))
+ CILIB := ../../../lib/fortcrypt/$(ctmp)
+else
+ CILIB := $(ctmp)
+endif
+
+EXTRA_LIBS += $(CILIB)
+
+include ../../platlibs.mk
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../../platrules.mk
+
diff --git a/security/nss/cmd/swfort/newuser/manifest.mn b/security/nss/cmd/swfort/newuser/manifest.mn
new file mode 100644
index 000000000..4554c69ef
--- /dev/null
+++ b/security/nss/cmd/swfort/newuser/manifest.mn
@@ -0,0 +1,45 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+CORE_DEPTH = ../../../..
+
+DEFINES += -DNSPR20
+
+MODULE = nss
+
+CSRCS = newuser.c mktst.c
+
+REQUIRES = nspr dbm seccmd
+
+PROGRAM = newuser
+
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/swfort/newuser/mktst.c b/security/nss/cmd/swfort/newuser/mktst.c
new file mode 100644
index 000000000..6e111d3dd
--- /dev/null
+++ b/security/nss/cmd/swfort/newuser/mktst.c
@@ -0,0 +1,254 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#include <stdio.h>
+
+#include "prio.h"
+#include "swforti.h"
+#include "maci.h"
+#include "secder.h"
+#include "blapi.h"
+
+void
+printkey(char *s, unsigned char *block) {
+ int i;
+ printf("%s \n 0x",s);
+ for(i=0; i < 10; i++) printf("%02x",block[i]);
+ printf("\n");
+}
+
+void
+printblock(char *s, unsigned char *block) {
+ int i;
+ printf("%s \n 0x",s);
+ for(i=0; i < 8; i++) printf("%02x",block[i]);
+ printf("\n 0x");
+ for(i=8; i < 16; i++) printf("%02x",block[i]);
+ printf("\n");
+}
+
+
+static char *leafbits="THIS IS NOT LEAF";
+
+static void
+encryptCertEntry(fortProtectedData *pdata,FORTSkipjackKeyPtr Ks,
+ unsigned char *data,int len)
+{
+ unsigned char *dataout;
+ int enc_len;
+ /* XXX Make length */
+ pdata->dataIV.data = PORT_ZAlloc(24);
+ pdata->dataIV.len = 24;
+ PORT_Memcpy(pdata->dataIV.data,leafbits,SKIPJACK_LEAF_SIZE);
+ fort_GenerateRandom(&pdata->dataIV.data[SKIPJACK_LEAF_SIZE],
+ SKIPJACK_BLOCK_SIZE);
+ enc_len = (len + (SKIPJACK_BLOCK_SIZE-1)) & ~(SKIPJACK_BLOCK_SIZE-1);
+ dataout = pdata->dataEncryptedWithKs.data = PORT_ZAlloc(enc_len);
+ pdata->dataEncryptedWithKs.len = enc_len;
+ fort_skipjackEncrypt(Ks,&pdata->dataIV.data[SKIPJACK_LEAF_SIZE],
+ enc_len, data,dataout);
+ if (len > 255) {
+ pdata->length.data = PORT_ZAlloc(2);
+ pdata->length.data[0] = (len >> 8) & 0xff;
+ pdata->length.data[1] = len & 0xff;
+ pdata->length.len = 2;
+ } else {
+ pdata->length.data = PORT_ZAlloc(1);
+ pdata->length.data[0] = len & 0xff;
+ pdata->length.len = 1;
+ }
+
+}
+
+unsigned char issuer[30] = { 0 };
+
+void
+makeCertSlot(fortSlotEntry *entry,int index,char *label,SECItem *cert,
+ FORTSkipjackKeyPtr Ks, unsigned char *xKEA, unsigned char *xDSA,
+ unsigned char *pubKey, int pubKeyLen, unsigned char *p, unsigned char *q,
+ unsigned char *g)
+{
+ unsigned char *key; /* private key */
+
+ entry->trusted.data = PORT_Alloc(1);
+ *entry->trusted.data = index == 0 ? 1 : 0;
+ entry->trusted.len = 1;
+ entry->certificateIndex.data = PORT_Alloc(1);
+ *entry->certificateIndex.data = index;
+ entry->certificateIndex.len = 1;
+ entry->certIndex = index;
+ encryptCertEntry(&entry->certificateLabel,Ks,
+ (unsigned char *)label, strlen(label));
+ encryptCertEntry(&entry->certificateData,Ks, cert->data, cert->len);
+ if (xKEA) {
+ entry->exchangeKeyInformation = PORT_ZNew(fortKeyInformation);
+ entry->exchangeKeyInformation->keyFlags.data = PORT_ZAlloc(1);
+ entry->exchangeKeyInformation->keyFlags.data[0] = 1;
+ entry->exchangeKeyInformation->keyFlags.len = 1;
+ key = PORT_Alloc(24);
+ fort_skipjackWrap(Ks,24,xKEA,key);
+ entry->exchangeKeyInformation->privateKeyWrappedWithKs.data = key;
+ entry->exchangeKeyInformation->privateKeyWrappedWithKs.len = 24;
+ entry->exchangeKeyInformation->derPublicKey.data = pubKey;
+ entry->exchangeKeyInformation->derPublicKey.len = pubKeyLen;
+ entry->exchangeKeyInformation->p.data = p;
+ entry->exchangeKeyInformation->p.len = 128;
+ entry->exchangeKeyInformation->q.data = q;
+ entry->exchangeKeyInformation->q.len = 20;
+ entry->exchangeKeyInformation->g.data = g;
+ entry->exchangeKeyInformation->g.len = 128;
+
+ entry->signatureKeyInformation = PORT_ZNew(fortKeyInformation);
+ entry->signatureKeyInformation->keyFlags.data = PORT_ZAlloc(1);
+ entry->signatureKeyInformation->keyFlags.data[0] = 1;
+ entry->signatureKeyInformation->keyFlags.len = 1;
+ key = PORT_Alloc(24);
+ fort_skipjackWrap(Ks,24,xDSA,key);
+ entry->signatureKeyInformation->privateKeyWrappedWithKs.data = key;
+ entry->signatureKeyInformation->privateKeyWrappedWithKs.len = 24;
+ entry->signatureKeyInformation->derPublicKey.data = pubKey;
+ entry->signatureKeyInformation->derPublicKey.len = pubKeyLen;
+ entry->signatureKeyInformation->p.data = p;
+ entry->signatureKeyInformation->p.len = 128;
+ entry->signatureKeyInformation->q.data = q;
+ entry->signatureKeyInformation->q.len = 20;
+ entry->signatureKeyInformation->g.data = g;
+ entry->signatureKeyInformation->g.len = 128;
+ } else {
+ entry->exchangeKeyInformation = NULL;
+ entry->signatureKeyInformation = NULL;
+ }
+
+ return;
+}
+
+
+void
+makeProtectedPhrase(FORTSWFile *file, fortProtectedPhrase *prot_phrase,
+ FORTSkipjackKeyPtr Ks, FORTSkipjackKeyPtr Kinit, char *phrase)
+{
+ SHA1Context *sha;
+ unsigned char hashout[SHA1_LENGTH];
+ FORTSkipjackKey Kfek;
+ unsigned int len;
+ unsigned char cw[4];
+ unsigned char enc_version[2];
+ unsigned char *data = NULL;
+ int keySize;
+ int i,version;
+ char tmp_data[13];
+
+ if (strlen(phrase) < 12) {
+ PORT_Memset(tmp_data, ' ', sizeof(tmp_data));
+ PORT_Memcpy(tmp_data,phrase,strlen(phrase));
+ tmp_data[12] = 0;
+ phrase = tmp_data;
+ }
+
+ /* now calculate the PBE key for fortezza */
+ sha = SHA1_NewContext();
+ SHA1_Begin(sha);
+ version = DER_GetUInteger(&file->version);
+ enc_version[0] = (version >> 8) & 0xff;
+ enc_version[1] = version & 0xff;
+ SHA1_Update(sha,enc_version,sizeof(enc_version));
+ SHA1_Update(sha,file->derIssuer.data, file->derIssuer.len);
+ SHA1_Update(sha,file->serialID.data, file->serialID.len);
+ SHA1_Update(sha,(unsigned char *)phrase,strlen(phrase));
+ SHA1_End(sha,hashout,&len,SHA1_LENGTH);
+ PORT_Memcpy(Kfek,hashout,sizeof(FORTSkipjackKey));
+
+ keySize = sizeof(CI_KEY);
+ if (Kinit) keySize = SKIPJACK_BLOCK_SIZE*2;
+ data = PORT_ZAlloc(keySize);
+ prot_phrase->wrappedKValue.data = data;
+ prot_phrase->wrappedKValue.len = keySize;
+ fort_skipjackWrap(Kfek,sizeof(CI_KEY),Ks,data);
+
+ /* first, decrypt the hashed/Encrypted Memphrase */
+ data = (unsigned char *) PORT_ZAlloc(SHA1_LENGTH+sizeof(cw));
+
+ /* now build the hash for comparisons */
+ SHA1_Begin(sha);
+ SHA1_Update(sha,(unsigned char *)phrase,strlen(phrase));
+ SHA1_End(sha,hashout,&len,SHA1_LENGTH);
+ SHA1_DestroyContext(sha,PR_TRUE);
+
+
+ /* now calcuate the checkword and compare it */
+ cw[0] = cw[1] = cw[2] = cw[3] = 0;
+ for (i=0; i <5 ; i++) {
+ cw[0] = cw[0] ^ hashout[i*4];
+ cw[1] = cw[1] ^ hashout[i*4+1];
+ cw[2] = cw[2] ^ hashout[i*4+2];
+ cw[3] = cw[3] ^ hashout[i*4+3];
+ }
+
+ PORT_Memcpy(data,hashout,len);
+ PORT_Memcpy(data+len,cw,sizeof(cw));
+
+ prot_phrase->memPhraseIV.data = PORT_ZAlloc(24);
+ prot_phrase->memPhraseIV.len = 24;
+ PORT_Memcpy(prot_phrase->memPhraseIV.data,leafbits,SKIPJACK_LEAF_SIZE);
+ fort_GenerateRandom(&prot_phrase->memPhraseIV.data[SKIPJACK_LEAF_SIZE],
+ SKIPJACK_BLOCK_SIZE);
+ prot_phrase->kValueIV.data = PORT_ZAlloc(24);
+ prot_phrase->kValueIV.len = 24;
+ PORT_Memcpy(prot_phrase->kValueIV.data,leafbits,SKIPJACK_LEAF_SIZE);
+ fort_GenerateRandom(&prot_phrase->kValueIV.data[SKIPJACK_LEAF_SIZE],
+ SKIPJACK_BLOCK_SIZE);
+ fort_skipjackEncrypt(Ks,&prot_phrase->memPhraseIV.data[SKIPJACK_LEAF_SIZE],
+ len+sizeof(cw), data,data);
+
+ prot_phrase->hashedEncryptedMemPhrase.data = data;
+ prot_phrase->hashedEncryptedMemPhrase.len = len+sizeof(cw);
+
+ if (Kinit) {
+ fort_skipjackEncrypt(Kinit,
+ &prot_phrase->kValueIV.data[SKIPJACK_LEAF_SIZE],
+ prot_phrase->wrappedKValue.len,
+ prot_phrase->wrappedKValue.data,
+ prot_phrase->wrappedKValue.data );
+ }
+
+ return;
+}
+
+
+void
+fill_in(SECItem *item,unsigned char *data, int len)
+{
+ item->data = PORT_Alloc(len);
+ PORT_Memcpy(item->data,data,len);
+ item->len = len;
+}
+
diff --git a/security/nss/cmd/swfort/newuser/newuser.c b/security/nss/cmd/swfort/newuser/newuser.c
new file mode 100644
index 000000000..33b6b853a
--- /dev/null
+++ b/security/nss/cmd/swfort/newuser/newuser.c
@@ -0,0 +1,1133 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#ifdef XP_UNIX
+#include <unistd.h>
+#endif
+#include "cryptint.h"
+#include "blapi.h" /* program calls low level functions directly!*/
+#include "pk11func.h"
+#include "secmod.h"
+/*#include "secmodi.h"*/
+#include "cert.h"
+#include "key.h"
+#include "nss.h"
+#include "swforti.h"
+#include "secutil.h"
+#include "secrng.h"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#define MAX_PERSONALITIES 50
+typedef struct {
+ int index;
+ CI_CERT_STR label;
+ CERTCertificate *cert;
+} certlist;
+
+typedef struct {
+ int card;
+ int index;
+ CI_CERT_STR label;
+ certlist valid[MAX_PERSONALITIES];
+ int count;
+} Cert;
+
+
+#define EMAIL_OID_LEN 9
+#define EMAIL_OID 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01
+unsigned char emailAVA[127] = {
+ 0x31, 6+EMAIL_OID_LEN, /* Set */
+ 0x30, 4+EMAIL_OID_LEN, /* Sequence */
+ 0x06, EMAIL_OID_LEN, EMAIL_OID,
+ 0x13, 0, /* printable String */
+};
+#define EMAIL_DATA_START 8+EMAIL_OID_LEN
+
+int emailOffset[] = { 1, 3, EMAIL_DATA_START-1 };
+int offsetCount = sizeof(emailOffset)/sizeof(emailOffset[0]);
+
+unsigned char hash[20] = { 'H', 'a', 's', 'h', ' ', 'F', 'a', 'i', 'l', 'e',
+ 'd', ' ', '*', '*', '*', '*', '*', '*', '*', '*' };
+unsigned char sig[40] = { 'H', 'a', 's', 'h', ' ', 'F', 'a', 'i', 'l', 'e',
+ 'd', ' ', '*', '*', '*', '*', '*', '*', '*', '*',
+ '>', '>', '>', ' ', 'N', 'o', 't', ' ', 'S', 'i',
+ 'g', 'n', 'd', ' ', '<', '<', '<', ' ', ' ', ' ' };
+
+
+/*void *malloc(int); */
+
+unsigned char *data_start(unsigned char *buf, int length, int *data_length)
+{
+ unsigned char tag;
+ int used_length= 0;
+
+ tag = buf[used_length++];
+
+ /* blow out when we come to the end */
+ if (tag == 0) {
+ return NULL;
+ }
+
+ *data_length = buf[used_length++];
+
+ if (*data_length&0x80) {
+ int len_count = *data_length & 0x7f;
+
+ *data_length = 0;
+
+ while (len_count-- > 0) {
+ *data_length = (*data_length << 8) | buf[used_length++];
+ }
+ }
+
+ if (*data_length > (length-used_length) ) {
+ *data_length = length-used_length;
+ return NULL;
+ }
+
+ return (buf + used_length);
+}
+
+unsigned char *
+GetAbove(unsigned char *cert,int cert_length,int *above_len)
+{
+ unsigned char *buf = cert;
+ int buf_length = cert_length;
+ unsigned char *tmp;
+ int len;
+
+ *above_len = 0;
+
+ /* optional serial number */
+ if ((buf[0] & 0xa0) == 0xa0) {
+ tmp = data_start(buf,buf_length,&len);
+ if (tmp == NULL) return NULL;
+ buf_length -= (tmp-buf) + len;
+ buf = tmp + len;
+ }
+ /* serial number */
+ tmp = data_start(buf,buf_length,&len);
+ if (tmp == NULL) return NULL;
+ buf_length -= (tmp-buf) + len;
+ buf = tmp + len;
+ /* skip the OID */
+ tmp = data_start(buf,buf_length,&len);
+ if (tmp == NULL) return NULL;
+ buf_length -= (tmp-buf) + len;
+ buf = tmp + len;
+ /* issuer */
+ tmp = data_start(buf,buf_length,&len);
+ if (tmp == NULL) return NULL;
+ buf_length -= (tmp-buf) + len;
+ buf = tmp + len;
+ /* skip the date */
+ tmp = data_start(buf,buf_length,&len);
+ if (tmp == NULL) return NULL;
+ buf_length -= (tmp-buf) + len;
+ buf = tmp + len;
+
+ *above_len = buf - cert;
+ return cert;
+}
+
+unsigned char *
+GetSubject(unsigned char *cert,int cert_length,int *subj_len) {
+ unsigned char *buf = cert;
+ int buf_length = cert_length;
+ unsigned char *tmp;
+ int len;
+
+ *subj_len = 0;
+
+ /* optional serial number */
+ if ((buf[0] & 0xa0) == 0xa0) {
+ tmp = data_start(buf,buf_length,&len);
+ if (tmp == NULL) return NULL;
+ buf_length -= (tmp-buf) + len;
+ buf = tmp + len;
+ }
+ /* serial number */
+ tmp = data_start(buf,buf_length,&len);
+ if (tmp == NULL) return NULL;
+ buf_length -= (tmp-buf) + len;
+ buf = tmp + len;
+ /* skip the OID */
+ tmp = data_start(buf,buf_length,&len);
+ if (tmp == NULL) return NULL;
+ buf_length -= (tmp-buf) + len;
+ buf = tmp + len;
+ /* issuer */
+ tmp = data_start(buf,buf_length,&len);
+ if (tmp == NULL) return NULL;
+ buf_length -= (tmp-buf) + len;
+ buf = tmp + len;
+ /* skip the date */
+ tmp = data_start(buf,buf_length,&len);
+ if (tmp == NULL) return NULL;
+ buf_length -= (tmp-buf) + len;
+ buf = tmp + len;
+
+ return data_start(buf,buf_length,subj_len);
+}
+
+unsigned char *
+GetBelow(unsigned char *cert,int cert_length,int *below_len) {
+ unsigned char *subj;
+ int subj_len;
+ unsigned char *below;
+
+ *below_len = 0;
+
+ subj = GetSubject(cert,cert_length,&subj_len);
+
+ below = subj + subj_len;
+ *below_len = cert_length - (below - cert);
+ return below;
+}
+
+unsigned char *
+GetSignature(unsigned char *sig,int sig_length,int *subj_len) {
+ unsigned char *buf = sig;
+ int buf_length = sig_length;
+ unsigned char *tmp;
+ int len;
+
+ *subj_len = 0;
+
+ /* signature oid */
+ tmp = data_start(buf,buf_length,&len);
+ if (tmp == NULL) return NULL;
+ buf_length -= (tmp-buf) + len;
+ buf = tmp + len;
+ /* signature data */
+ tmp = data_start(buf,buf_length,&len);
+ if (tmp == NULL) return NULL;
+
+ *subj_len = len -1;
+ return tmp+1;
+}
+
+int DER_Sequence(unsigned char *buf, int length) {
+ int next = 0;
+
+ buf[next++] = 0x30;
+ if (length < 0x80) {
+ buf[next++] = length;
+ } else {
+ buf[next++] = 0x82;
+ buf[next++] = (length >> 8) & 0xff;
+ buf[next++] = length & 0xff;
+ }
+ return next;
+}
+
+static
+int Cert_length(unsigned char *buf, int length) {
+ unsigned char tag;
+ int used_length= 0;
+ int data_length;
+
+ tag = buf[used_length++];
+
+ /* blow out when we come to the end */
+ if (tag == 0) {
+ return 0;
+ }
+
+ data_length = buf[used_length++];
+
+ if (data_length&0x80) {
+ int len_count = data_length & 0x7f;
+
+ data_length = 0;
+
+ while (len_count-- > 0) {
+ data_length = (data_length << 8) | buf[used_length++];
+ }
+ }
+
+ if (data_length > (length-used_length) ) {
+ return length;
+ }
+
+ return (data_length + used_length);
+}
+
+int
+InitCard(int card, char *inpass) {
+ int cirv;
+ char buf[50];
+ char *pass;
+
+ cirv = CI_Open( 0 /* flags */, card);
+ if (cirv != CI_OK) return cirv;
+
+ if (inpass == NULL) {
+ sprintf(buf,"Enter PIN for card in socket %d: ",card);
+ pass = SECU_GetPasswordString(NULL, buf);
+
+ if (pass == NULL) {
+ CI_Close(CI_POWER_DOWN_FLAG,card);
+ return CI_FAIL;
+ }
+ } else pass=inpass;
+
+ cirv = CI_CheckPIN(CI_USER_PIN,(unsigned char *)pass);
+ if (cirv != CI_OK) {
+ CI_Close(CI_POWER_DOWN_FLAG,card);
+ }
+ return cirv;
+}
+
+int
+isUser(CI_PERSON *person) {
+ return 1;
+}
+
+int
+isCA(CI_PERSON *person) {
+ return 0;
+}
+
+int FoundCert(int card, char *name, Cert *cert) {
+ CI_PERSON personalities[MAX_PERSONALITIES];
+ CI_PERSON *person;
+ int cirv;
+ int i;
+ int user_len = strlen(name);
+
+ PORT_Memset(personalities, 0, sizeof(CI_PERSON)*MAX_PERSONALITIES);
+
+ cirv = CI_GetPersonalityList(MAX_PERSONALITIES,personalities);
+ if (cirv != CI_OK) return 0;
+
+
+ cert->count = 1;
+ cert->valid[0].index = 0;
+ memcpy(cert->valid[0].label,"RRXX0000Root PAA Certificate ",
+ sizeof(cert->valid[0].label));
+ cert->valid[0].cert = NULL;
+ for (i=0; i < MAX_PERSONALITIES; i++) {
+ person = &personalities[i];
+ if ( (PORT_Memcmp(person->CertLabel,"RRXX",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"RTXX",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"LAXX",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"INKS",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"INKX",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"ONKS",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"ONKX",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"KEAK",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"3IKX",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"DSA1",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"DSAI",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"DSAO",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"3IXS",4) == 0) ||
+ (PORT_Memcmp(person->CertLabel,"3OXS",4) == 0) ){
+ int index;
+
+ cert->valid[cert->count].cert = NULL;
+ memcpy(cert->valid[cert->count].label,
+ person->CertLabel,sizeof(person->CertLabel));
+ for (index = sizeof(person->CertLabel)-1;
+ cert->valid[cert->count].label[index] == ' '; index--) {
+ cert->valid[cert->count].label[index] = 0;
+ }
+ cert->valid[cert->count++].index = person->CertificateIndex;
+ }
+ }
+ for (i=0; i < MAX_PERSONALITIES; i++) {
+ person = &personalities[i];
+ if (strncmp((char *)&person->CertLabel[8],name,user_len) == 0) {
+ cert->card = card;
+ cert->index = person->CertificateIndex;
+ memcpy(&cert->label,person->CertLabel,sizeof(person->CertLabel));
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void
+Terminate(char *mess, int cirv, int card1, int card2)
+{
+ fprintf(stderr,"FAIL: %s error %d\n",mess,cirv);
+ if (card1 != -1) CI_Close(CI_POWER_DOWN_FLAG,card1);
+ if (card2 != -1) CI_Close(CI_POWER_DOWN_FLAG,card2);
+ CI_Terminate();
+ exit(1);
+}
+
+void
+usage(char *prog)
+{
+ fprintf(stderr,"usage: %s [-e email][-t transport][-u userpin][-U userpass][-s ssopin][-S ssopass][-o outfile] common_name ca_label\n",prog);
+ exit(1);
+}
+
+#define CERT_SIZE 2048
+
+
+/* version and oid */
+unsigned char header[] = {
+ /* Cert OID */
+ 0x02, 0x10,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x0b, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x02, 0x01, 0x01, 0x13 };
+
+#define KEY_START 21
+#define KMID_OFFSET 4
+#define KEA_OFFSET 15
+#define DSA_OFFSET 148
+unsigned char key[] = {
+ /* Sequence(Constructed): 293 bytes (0x125) */
+ 0x30, 0x82, 0x01, 0x25,
+ /*Sequence(Constructed): 11 bytes (0xb) */
+ 0x30, 0x0b,
+ /* ObjectId(Universal): 9 bytes (0x9) */
+ 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x02, 0x01, 0x01, 0x14,
+ /* BitString(Universal): 276 bytes (0x114) */
+ 0x03, 0x82, 0x01, 0x14,
+ 0x00, 0x00, 0x01, 0xef, 0x04, 0x01, 0x00, 0x01,
+ 0x00, 0x00, 0x69, 0x60, 0x70, 0x00, 0x80, 0x02,
+ 0x2e, 0x46, 0xb9, 0xcb, 0x22, 0x72, 0x0b, 0x1c,
+ 0xe6, 0x25, 0x20, 0x16, 0x86, 0x05, 0x8e, 0x2b,
+ 0x98, 0xd1, 0x46, 0x3d, 0x00, 0xb8, 0x69, 0xe1,
+ 0x1a, 0x42, 0x7d, 0x7d, 0xb5, 0xbf, 0x9f, 0x26,
+ 0xd3, 0x2c, 0xb1, 0x73, 0x01, 0xb6, 0xb2, 0x6f,
+ 0x7b, 0xa5, 0x54, 0x85, 0x60, 0x77, 0x81, 0x8a,
+ 0x87, 0x86, 0xe0, 0x2d, 0xbf, 0xdb, 0x28, 0xe8,
+ 0xfa, 0x20, 0x35, 0xb4, 0xc0, 0x94, 0x10, 0x8e,
+ 0x1c, 0x58, 0xaa, 0x02, 0x60, 0x97, 0xf5, 0xb3,
+ 0x2f, 0xf8, 0x99, 0x29, 0x28, 0x73, 0x47, 0x36,
+ 0xdd, 0x1d, 0x78, 0x95, 0xeb, 0xb8, 0xec, 0x45,
+ 0x96, 0x69, 0x6f, 0x54, 0xc8, 0x1f, 0x2d, 0x3a,
+ 0xd9, 0x0e, 0x8e, 0xaa, 0x59, 0x11, 0x8c, 0x3b,
+ 0x8d, 0xa4, 0xed, 0xf2, 0x7d, 0xdc, 0x42, 0xaa,
+ 0xa4, 0xd2, 0x1c, 0xb9, 0x87, 0xd0, 0xd9, 0x3d,
+ 0x8e, 0x89, 0xbb, 0x06, 0x54, 0xcf, 0x32, 0x00,
+ 0x02, 0x00, 0x00, 0x80, 0x0b, 0x80, 0x6c, 0x0f,
+ 0x71, 0xd1, 0xa1, 0xa9, 0x26, 0xb4, 0xf1, 0xcd,
+ 0x6a, 0x7a, 0x09, 0xaa, 0x58, 0x28, 0xd7, 0x35,
+ 0x74, 0x8e, 0x7c, 0x83, 0xcb, 0xfe, 0x00, 0x3b,
+ 0x62, 0x00, 0xfb, 0x90, 0x37, 0xcd, 0x93, 0xcf,
+ 0xf3, 0xe4, 0x6d, 0x8d, 0xdd, 0xb8, 0x53, 0xe0,
+ 0x5c, 0xda, 0x1a, 0x7e, 0x56, 0x03, 0x95, 0x03,
+ 0x2f, 0x74, 0x86, 0xb1, 0xa0, 0xbb, 0x05, 0x91,
+ 0xe4, 0x76, 0x83, 0xe6, 0x62, 0xf9, 0x12, 0x64,
+ 0x5a, 0x62, 0xd8, 0x94, 0x04, 0x1f, 0x83, 0x02,
+ 0x2e, 0xc5, 0xa7, 0x17, 0x46, 0x46, 0x21, 0x96,
+ 0xc3, 0xa9, 0x8e, 0x92, 0x18, 0xd1, 0x52, 0x08,
+ 0x1d, 0xff, 0x8e, 0x24, 0xdb, 0x6c, 0xd8, 0xfe,
+ 0x80, 0x93, 0xe1, 0xa5, 0x4a, 0x0a, 0x37, 0x24,
+ 0x18, 0x07, 0xbe, 0x0f, 0xaf, 0x73, 0xea, 0x50,
+ 0x64, 0xa1, 0xb3, 0x77, 0xe5, 0x41, 0x02, 0x82,
+ 0x39, 0xb9, 0xe3, 0x94
+};
+
+unsigned char valitity[] = {
+ 0x30, 0x1e,
+ 0x17, 0x0d,
+ '2','0','0','0','0','1','0','1','0','0','0','0','Z',
+ 0x17, 0x0d,
+ '2','0','0','5','1','2','0','1','0','0','0','0','Z'
+};
+
+
+unsigned char cnam_oid[] = { 0x06, 0x03, 0x55, 0x04, 0x03 };
+
+unsigned char signature[] = {
+ /* the OID */
+ 0x30, 0x0b, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x02, 0x01, 0x01, 0x13,
+ /* signature wrap */
+ 0x03, 0x29, 0x00,
+ /* 40 byte dsa signature */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+unsigned char fortezza_oid [] = {
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x02, 0x01, 0x01, 0x13
+};
+
+unsigned char software_ou[] = {
+ 0x31, 26, 0x30, 24,
+ 0x06, 0x03, 0x55, 0x04, 0x0b,
+ 0x13, 17,
+ 'S','o','f','t','w',
+ 'a','r','e',' ','F',
+ 'O','R','T','E','Z','Z','A'
+};
+
+
+char letterarray[] = {
+ 'a','b','c','d','e','f','g','h','i','j','k','l','m','n',
+ 'o','p','q','r','s','t','u','v','w','x','y','z' };
+
+char constarray[] = {
+ 'b','c','d','f','g','h','j','k','l','m','n',
+ 'p','q','r','s','t','v','w','x','y','z' };
+
+char vowelarray[] = {
+ 'a','e','i','o','u','y' };
+
+char digitarray[] = {
+ '0','1','2','3','4','5','6','7','8','9' };
+
+unsigned long
+getRandom(unsigned long max) {
+ unsigned short data;
+ unsigned long result;
+
+ fort_GenerateRandom((unsigned char *)&data,sizeof(data));
+
+ result = (unsigned long)data * max;
+ result = result >> 16;
+ return result;
+}
+
+
+char getLetter(void)
+{
+ return letterarray[getRandom(sizeof(letterarray))];
+}
+char getVowel(void)
+{
+ return vowelarray[getRandom(sizeof(vowelarray))];
+}
+char getDigit(void)
+{
+ return digitarray[getRandom(sizeof(digitarray))];
+}
+
+char getConst(void)
+{
+ return constarray[getRandom(sizeof(constarray))];
+}
+
+char *getPinPhrase(void)
+{
+ char * pass = PORT_ZAlloc(5);
+
+ pass[0] = getDigit();
+ pass[1] = getDigit();
+ pass[2] = getDigit();
+ pass[3] = getDigit();
+
+ return pass;
+}
+
+char *getPassPhrase(void)
+{
+ char * pass = PORT_ZAlloc(13);
+
+ pass[0] = getConst()+'A'-'a';
+ pass[1] = getVowel();
+ pass[2] = getConst();
+ pass[3] = getVowel();
+ pass[4] = getConst();
+ pass[5] = getVowel();
+ pass[6] = getConst();
+ pass[7] = getDigit();
+ pass[8] = getDigit();
+ pass[9] = getDigit();
+ pass[10] = getDigit();
+ pass[11] = getLetter()+'A'-'a';
+
+ return pass;
+}
+
+extern void
+makeCertSlot(fortSlotEntry * entry,
+ int index,
+ char * label,
+ SECItem * cert,
+ FORTSkipjackKeyPtr Ks,
+ unsigned char *xKEA,
+ unsigned char *xDSA,
+ unsigned char *pubKey,
+ int pubKeyLen,
+ unsigned char *p,
+ unsigned char *q,
+ unsigned char *g);
+
+extern void
+makeProtectedPhrase(FORTSWFile * file,
+ fortProtectedPhrase *prot_phrase,
+ FORTSkipjackKeyPtr Ks,
+ FORTSkipjackKeyPtr Kinit,
+ char * phrase);
+
+extern void
+fill_in(SECItem *item, unsigned char *data, int len);
+
+char *userLabel = "INKS0002 ";
+int main(int argc, char **argv)
+{
+ char *progname = *argv++;
+ char *commonName = NULL;
+ char *caname = NULL;
+ char *email = NULL;
+ char *outname = NULL;
+ char *cp;
+ int arg_count = 0;
+ Cert caCert;
+ SECItem userCert;
+ int cirv,i;
+ int cards, start;
+ unsigned char *subject;
+ int subject_len;
+ int signature_len = sizeof(signature);
+ int newSubject_len, newCertBody_len, len;
+ int cname1_len, cname_len, pstring_len;
+ int valitity_len = sizeof(valitity);
+ unsigned char origCert[CERT_SIZE];
+ unsigned char newSubject[CERT_SIZE];
+ unsigned char newCertBody[CERT_SIZE];
+ unsigned char newCert[CERT_SIZE];
+ unsigned char pstring[CERT_SIZE];
+ unsigned char cname1[CERT_SIZE];
+ unsigned char cname[CERT_SIZE];
+ CERTCertificate *myCACert = NULL;
+ CERTCertificate *cert;
+ CERTCertDBHandle *certhandle;
+ SECStatus rv;
+ unsigned char serial[16];
+ SECKEYPublicKey *pubKey;
+ DSAPrivateKey *keaPrivKey;
+ DSAPrivateKey *dsaPrivKey;
+ CI_RANDOM randomVal;
+ PQGParams *params;
+ int pca_index = -1;
+ unsigned char *p,*q,*g;
+ FORTSkipjackKey Ks;
+ FORTSkipjackKey Kinit;
+ FORTSWFile *file;
+ FORTSignedSWFile *signed_file;
+ FORTSignedSWFile *signed_file2;
+ unsigned char random[20];
+ unsigned char vers;
+ unsigned char *data;
+ char *transportPin=NULL;
+ char *ssoMemPhrase=NULL;
+ char *userMemPhrase=NULL;
+ char *ssoPin=NULL;
+ char *userPin=NULL;
+ char *pass=NULL;
+ SECItem *outItem;
+ int email_len = 0;
+ int emailAVA_len = 0;
+
+
+ /* put better argument parsing here */
+ while ((cp = *argv++) != NULL) {
+ if (*cp == '-') {
+ while (*++cp) {
+ switch (*cp) {
+ /* verbose mode */
+ case 'e':
+ email = *argv++;
+ break;
+ /* explicitly set the target */
+ case 'o':
+ outname = *argv++;
+ break;
+ case 't':
+ /* provide password on command line */
+ transportPin = *argv++;
+ break;
+ case 'u':
+ /* provide user password on command line */
+ userPin = *argv++;
+ break;
+ case 'U':
+ /* provide user password on command line */
+ userMemPhrase = *argv++;
+ break;
+ case 's':
+ /* provide user password on command line */
+ ssoPin = *argv++;
+ break;
+ case 'S':
+ /* provide user password on command line */
+ ssoMemPhrase = *argv++;
+ break;
+ case 'p':
+ /* provide card password on command line */
+ pass = *argv++;
+ break;
+ case 'd':
+ transportPin="test1234567890";
+ ssoMemPhrase="sso1234567890";
+ userMemPhrase="user1234567890";
+ ssoPin="9999";
+ userPin="0000";
+ break;
+ default:
+ usage(progname);
+ break;
+ }
+ }
+ } else switch (arg_count++) {
+ case 0:
+ commonName = cp;
+ break;
+ case 1:
+ caname = cp;
+ break;
+ default:
+ usage(progname);
+ }
+ }
+
+ if (outname == NULL) outname = "swfort.sfi";
+ if (caname == NULL) usage(progname);
+
+
+
+ caCert.card = -1;
+ memset(newCert,0,CERT_SIZE);
+
+ if (commonName == NULL) usage(progname);
+
+
+ cirv = CI_Initialize(&cards);
+
+ start = 0;
+ for (i=0; i < cards; i++) {
+ cirv = InitCard(i+1,pass);
+ if (cirv == CI_OK) {
+ if (FoundCert(i+1,caname,&caCert)) {
+ break;
+ }
+ }
+ }
+
+ if (caCert.card == -1) {
+ fprintf(stderr,
+ "WARNING: Couldn't find Signing CA...new cert will not be signed\n");
+ }
+
+
+ /*
+ * initialize enough security to deal with certificates.
+ */
+ NSS_NoDB_Init(NULL);
+ certhandle = CERT_GetDefaultCertDB();
+ if (certhandle == NULL) {
+ Terminate("Couldn't build temparary Cert Database",
+ 1, -1, caCert.card);
+ exit(1);
+ }
+
+ CI_GenerateRandom(random);
+ RNG_RandomUpdate(random,sizeof(random));
+ CI_GenerateRandom(random);
+ RNG_RandomUpdate(random,sizeof(random));
+
+
+ if (transportPin == NULL) transportPin = getPassPhrase();
+ if (ssoMemPhrase == NULL) ssoMemPhrase = getPassPhrase();
+ if (userMemPhrase == NULL) userMemPhrase = getPassPhrase();
+ if (ssoPin == NULL) ssoPin = getPinPhrase();
+ if (userPin == NULL) userPin = getPinPhrase();
+
+
+
+ /* now dump the certs into the temparary data base */
+ for (i=0; i < caCert.count; i++) {
+ int trusted = 0;
+ SECItem derCert;
+
+ cirv = CI_Select(caCert.card);
+ if (cirv != CI_OK) {
+ Terminate("Couldn't select on CA card",cirv,
+ -1, caCert.card);
+ }
+ cirv = CI_GetCertificate(caCert.valid[i].index,origCert);
+ if (cirv != CI_OK) {
+ continue;
+ }
+ derCert.data = origCert;
+ derCert.len = Cert_length(origCert, sizeof(origCert));
+ cert =
+ (CERTCertificate *)CERT_NewTempCertificate(certhandle,&derCert, NULL,
+ PR_FALSE, PR_TRUE);
+ caCert.valid[i].cert = cert;
+ if (cert == NULL) continue;
+ if (caCert.valid[i].index == caCert.index) myCACert=cert;
+ if (caCert.valid[i].index == atoi((char *)&caCert.label[4]))
+ pca_index = i;
+ }
+
+ if (myCACert == NULL) {
+ Terminate("Couldn't find CA's Certificate", 1, -1, caCert.card);
+ exit(1);
+ }
+
+
+ /*
+ * OK now build the user cert.
+ */
+ /* first get the serial number and KMID */
+ cirv = CI_GenerateRandom(randomVal);
+ memcpy(&header[2],randomVal,sizeof(serial));
+ memcpy(serial,randomVal,sizeof(serial));
+ memcpy(&key[KEY_START+KMID_OFFSET],randomVal+sizeof(serial),7);
+ /* KMID */
+
+ /* now generate the keys */
+ pubKey = CERT_ExtractPublicKey(myCACert);
+ if (pubKey == NULL) {
+ Terminate("Couldn't extract CA's public key",
+ 1, -1, caCert.card);
+ exit(1);
+ }
+
+
+ switch (pubKey->keyType) {
+ case fortezzaKey:
+ params = (PQGParams *)&pubKey->u.fortezza.params;
+ break;
+ case dsaKey:
+ params = (PQGParams *)&pubKey->u.dsa.params;
+ break;
+ default:
+ Terminate("Certificate is not a fortezza or DSA Cert",
+ 1, -1, caCert.card);
+ exit(1);
+ }
+
+ rv = DSA_NewKey(params,&keaPrivKey);
+ if (rv != SECSuccess) {
+ Terminate("Couldn't Generate KEA key",
+ PORT_GetError(), -1, caCert.card);
+ exit(1);
+ }
+ rv = DSA_NewKey(params,&dsaPrivKey);
+ if (rv != SECSuccess) {
+ Terminate("Couldn't Generate DSA key",
+ PORT_GetError(), -1, caCert.card);
+ exit(1);
+ }
+
+ if (keaPrivKey->publicValue.len == 129)
+ keaPrivKey->publicValue.data++;
+ if (dsaPrivKey->publicValue.len == 129)
+ dsaPrivKey->publicValue.data++;
+ if (keaPrivKey->privateValue.len == 21)
+ keaPrivKey->privateValue.data++;
+ if (dsaPrivKey->privateValue.len == 21)
+ dsaPrivKey->privateValue.data++;
+
+ /* save the parameters */
+ p = params->prime.data;
+ if (params->prime.len == 129) p++;
+ q = params->subPrime.data;
+ if (params->subPrime.len == 21) q++;
+ g = params->base.data;
+ if (params->base.len == 129) g++;
+
+ memcpy(&key[KEY_START+KEA_OFFSET],
+ keaPrivKey->publicValue.data,
+ keaPrivKey->publicValue.len);
+ memcpy(&key[KEY_START+DSA_OFFSET],
+ dsaPrivKey->publicValue.data,
+ dsaPrivKey->publicValue.len);
+
+ /* build the der subject */
+ subject = data_start(myCACert->derSubject.data,myCACert->derSubject.len,
+ &subject_len);
+
+ /* build the new Common name AVA */
+ len = DER_Sequence(pstring,strlen(commonName));
+ memcpy(pstring+len,commonName,strlen(commonName));
+ len += strlen(commonName);
+ pstring_len = len;
+ pstring[0] = 0x13;
+
+ len = DER_Sequence(cname1,sizeof(cnam_oid)+pstring_len);
+ memcpy(cname1+len,cnam_oid,sizeof(cnam_oid)); len += sizeof(cnam_oid);
+ memcpy(cname1+len,pstring,pstring_len); len += pstring_len;
+ cname1_len = len;
+
+ len = DER_Sequence(cname, cname1_len);
+ memcpy(cname+len,cname1,cname1_len); len += cname1_len;
+ cname_len = len;
+ cname[0] = 0x31; /* make it a set rather than a sequence */
+
+ if (email) {
+ email_len = strlen(email);
+ emailAVA_len = EMAIL_DATA_START + email_len;
+ }
+
+ /* now assemble it */
+ len = DER_Sequence(newSubject,subject_len + sizeof(software_ou) +
+ cname_len + emailAVA_len);
+ memcpy(newSubject+len,subject,subject_len);
+
+ for (i=0; i < subject_len; i++) {
+ if (memcmp(newSubject+len+i,cnam_oid,sizeof(cnam_oid)) == 0) {
+ newSubject[i+len+4] = 0x0b; /* change CN to OU */
+ break;
+ }
+ }
+ len += subject_len;
+ memcpy(newSubject+len,software_ou,sizeof(software_ou));
+ len += sizeof(software_ou);
+ memcpy(newSubject+len,cname,cname_len); len += cname_len;
+ newSubject_len = len;
+
+ /*
+ * build the email AVA
+ */
+ if (email) {
+ memcpy(&emailAVA[EMAIL_DATA_START],email,email_len);
+ for (i=0; i < offsetCount; i++) {
+ emailAVA[emailOffset[i]] += email_len;
+ }
+ memcpy(newSubject+len,emailAVA,emailAVA_len);
+ newSubject_len += emailAVA_len;
+ }
+
+
+ /*
+ * Assemble the Cert
+ */
+
+ len = DER_Sequence(newCertBody,sizeof(header)+newSubject_len+
+ valitity_len+myCACert->derSubject.len+sizeof(key));
+ memcpy(newCertBody+len,header,sizeof(header));len += sizeof(header);
+ memcpy(newCertBody+len,myCACert->derSubject.data,
+ myCACert->derSubject.len);len += myCACert->derSubject.len;
+ memcpy(newCertBody+len,valitity,valitity_len);len += valitity_len;
+ memcpy(newCertBody+len,newSubject,newSubject_len);
+ len += newSubject_len;
+ memcpy(newCertBody+len,key,sizeof(key));len += sizeof(key);
+ newCertBody_len = len;
+
+
+ /*
+ * generate the hash
+ */
+ cirv = CI_InitializeHash();
+ if (cirv == CI_OK) {
+ int hash_left = newCertBody_len & 63;
+ int hash_len = newCertBody_len - hash_left;
+ cirv = CI_Hash(hash_len,newCertBody);
+ if (cirv == CI_OK) {
+ cirv = CI_GetHash(hash_left,newCertBody+hash_len,hash);
+ }
+ }
+
+ /*
+ * now sign the hash
+ */
+ if ((cirv == CI_OK) && (caCert.card != -1)) {
+ cirv = CI_Select(caCert.card);
+ if (cirv == CI_OK) {
+ cirv = CI_SetPersonality(caCert.index);
+ if (cirv == CI_OK) {
+ cirv = CI_Sign(hash,sig);
+ }
+ }
+ } else cirv = -1;
+
+ if (cirv != CI_OK) {
+ memcpy(sig,hash,sizeof(hash));
+ }
+
+ /*
+ * load in new signature
+ */
+ {
+ int sig_len;
+ unsigned char *sig_start =
+ GetSignature(signature,signature_len,&sig_len);
+ memcpy(sig_start,sig,sizeof(sig));
+ }
+
+ /*
+ * now do the final wrap
+ */
+ len = DER_Sequence(newCert,newCertBody_len+signature_len);
+ memcpy(newCert+len,newCertBody,newCertBody_len); len += newCertBody_len;
+ memcpy(newCert+len, signature, signature_len); len +=signature_len;
+ userCert.data = newCert;
+ userCert.len = len;
+
+
+ /* OK, we now have our cert, let's go build our software file */
+ signed_file = PORT_ZNew(FORTSignedSWFile);
+ file = &signed_file->file;
+
+ signed_file->signatureWrap.signature.data = PORT_ZAlloc(40);
+ signed_file->signatureWrap.signature.len = 40;
+ signed_file->signatureWrap.signatureAlgorithm.algorithm.data =
+ fortezza_oid;
+ signed_file->signatureWrap.signatureAlgorithm.algorithm.len =
+ sizeof(fortezza_oid);
+
+ vers = 1;
+ fill_in(&file->version,&vers,1);
+ file->derIssuer.data = myCACert->derSubject.data;
+ file->derIssuer.len = myCACert->derSubject.len;
+ file->serialID.data = serial;
+ file->serialID.len =sizeof(serial);
+ /* generate out Ks value */
+ fort_GenerateRandom(Ks,sizeof(Ks));
+ makeProtectedPhrase(file,&file->initMemPhrase,Kinit,NULL,transportPin);
+ makeProtectedPhrase(file,&file->ssoMemPhrase,Ks,Kinit,ssoMemPhrase);
+ makeProtectedPhrase(file,&file->ssoPinPhrase,Ks,Kinit,ssoPin);
+ makeProtectedPhrase(file,&file->userMemPhrase,Ks,Kinit,userMemPhrase);
+ makeProtectedPhrase(file,&file->userPinPhrase,Ks,Kinit,userPin);
+ file->wrappedRandomSeed.data = PORT_ZAlloc(12);
+ file->wrappedRandomSeed.len = 12;
+ cirv = fort_GenerateRandom(file->wrappedRandomSeed.data,10);
+ if (cirv != CI_OK) {
+ Terminate("Couldn't get Random Seed",
+ cirv, -1, caCert.card);
+ }
+ fort_skipjackWrap(Ks,12,file->wrappedRandomSeed.data,
+ file->wrappedRandomSeed.data);
+ file->slotEntries = PORT_ZAlloc(sizeof(fortSlotEntry *)*5);
+ /* paa */
+ file->slotEntries[0] = PORT_ZNew(fortSlotEntry);
+ makeCertSlot(file->slotEntries[0],0,
+ (char *)caCert.valid[0].label,
+ &caCert.valid[0].cert->derCert,
+ Ks,NULL,NULL,NULL,0,p,q,g);
+ /* pca */
+ file->slotEntries[1] = PORT_ZNew(fortSlotEntry);
+ makeCertSlot(file->slotEntries[1],1,
+ (char *)caCert.valid[pca_index].label,
+ &caCert.valid[pca_index].cert->derCert,
+ Ks,NULL,NULL,NULL,0,p,q,g);
+ /* ca */
+ file->slotEntries[2] = PORT_ZNew(fortSlotEntry);
+ /* make sure the caCert lable points to our new pca slot location */
+ caCert.label[4] = '0';
+ caCert.label[5] = '0';
+ caCert.label[6] = '0';
+ caCert.label[7] = '1';
+ makeCertSlot(file->slotEntries[2],2,(char *)caCert.label,
+ &myCACert->derCert,Ks,NULL,NULL,NULL,0,p,q,g);
+ /* user */
+ file->slotEntries[3] = PORT_ZNew(fortSlotEntry);
+ strncpy(&userLabel[8],commonName,sizeof(CI_PERSON)-8);
+ makeCertSlot(file->slotEntries[3],3,userLabel,&userCert,Ks,
+ keaPrivKey->privateValue.data,
+ dsaPrivKey->privateValue.data,
+ key, sizeof(key), p, q, g);
+ file->slotEntries[4] = 0;
+
+ /* encode the file so we can sign it */
+ outItem = FORT_PutSWFile(signed_file);
+
+ /* get the der encoded data to sign */
+ signed_file2 = FORT_GetSWFile(outItem);
+
+ /* now sign it */
+ len = signed_file2->signatureWrap.data.len;
+ data = signed_file2->signatureWrap.data.data;
+ /*
+ * generate the hash
+ */
+ cirv = CI_InitializeHash();
+ if (cirv == CI_OK) {
+ int hash_left = len & 63;
+ int hash_len = len - hash_left;
+ cirv = CI_Hash(hash_len,data);
+ if (cirv == CI_OK) {
+ cirv = CI_GetHash(hash_left,data+hash_len,hash);
+ }
+ }
+
+ /*
+ * now sign the hash
+ */
+ if ((cirv == CI_OK) && (caCert.card != -1)) {
+ cirv = CI_Select(caCert.card);
+ if (cirv == CI_OK) {
+ cirv = CI_SetPersonality(caCert.index);
+ if (cirv == CI_OK) {
+ cirv = CI_Sign(hash,sig);
+ }
+ }
+ } else cirv = -1;
+
+ if (cirv != CI_OK) {
+ memcpy(sig,hash,sizeof(hash));
+ }
+ memcpy( signed_file->signatureWrap.signature.data,sig,sizeof(sig));
+ signed_file->signatureWrap.signature.len = sizeof(sig)*8;
+
+
+ /* encode it for the last time */
+ outItem = FORT_PutSWFile(signed_file);
+
+
+ /*
+ * write it out to the .sfi file
+ */
+ {
+ int fd = open(outname,O_WRONLY|O_CREAT|O_BINARY,0777);
+
+ write(fd,outItem->data,outItem->len);
+ close(fd);
+ }
+ CI_Close(CI_POWER_DOWN_FLAG,caCert.card);
+ CI_Terminate();
+
+ printf("Wrote %s to file %s.\n",commonName,outname);
+ printf("Initialization Memphrase: %s\n",transportPin);
+ printf("SSO Memphrase: %s\n",ssoMemPhrase);
+ printf("User Memphrase: %s\n",userMemPhrase);
+ printf("SSO pin: %s\n",ssoPin);
+ printf("User pin: %s\n",userPin);
+
+ return 0;
+}
+
diff --git a/security/nss/cmd/tests/Makefile b/security/nss/cmd/tests/Makefile
new file mode 100644
index 000000000..da66e20df
--- /dev/null
+++ b/security/nss/cmd/tests/Makefile
@@ -0,0 +1,73 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
diff --git a/security/nss/cmd/tests/manifest.mn b/security/nss/cmd/tests/manifest.mn
new file mode 100644
index 000000000..878effc3c
--- /dev/null
+++ b/security/nss/cmd/tests/manifest.mn
@@ -0,0 +1,49 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = remtest.c
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+PROGRAMS = $(CSRCS:.c=)
+
+TARGETS = $(PROGRAMS)
+
+#NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/tests/remtest.c b/security/nss/cmd/tests/remtest.c
new file mode 100644
index 000000000..b17bc0f8b
--- /dev/null
+++ b/security/nss/cmd/tests/remtest.c
@@ -0,0 +1,162 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+**
+** Sample client side test program that uses SSL and libsec
+**
+*/
+
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#else
+#include "ctype.h" /* for isalpha() */
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "nss.h"
+#include "pk11func.h"
+#include "plgetopt.h"
+
+void
+Usage(char *progName)
+{
+ fprintf(stderr,"usage: %s [-d profiledir] -t tokenName [-r]\n", progName);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ char * certDir = NULL;
+ PLOptState *optstate;
+ PLOptStatus optstatus;
+ SECStatus rv;
+ char * tokenName = NULL;
+ PRBool cont=PR_TRUE;
+ PK11TokenEvent event = PK11TokenPresentEvent;
+ PK11TokenStatus status;
+ char *progName;
+ PK11SlotInfo *slot;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName+1 : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "rd:t:");
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+
+ case 'd':
+ certDir = strdup(optstate->value);
+ certDir = SECU_ConfigDirectory(certDir);
+ break;
+ case 't':
+ tokenName = strdup(optstate->value);
+ break;
+ case 'r':
+ event = PK11TokenRemovedOrChangedEvent;
+ break;
+ }
+ }
+ if (optstatus == PL_OPT_BAD)
+ Usage(progName);
+
+ if (tokenName == NULL) {
+ Usage(progName);
+ }
+
+ if (!certDir) {
+ certDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
+ certDir = SECU_ConfigDirectory(certDir); /* call even if it's NULL */
+ }
+
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ /* open the cert DB, the key DB, and the secmod DB. */
+ rv = NSS_Init(certDir);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to open cert database");
+ return 1;
+ }
+
+ printf("Looking up tokenNamed: <%s>\n",tokenName);
+ slot = PK11_FindSlotByName(tokenName);
+ if (slot == NULL) {
+ SECU_PrintError(progName, "unable to find token");
+ return 1;
+ }
+
+ do {
+ status =
+ PK11_WaitForTokenEvent(slot,event,PR_INTERVAL_NO_TIMEOUT, 0, 0);
+
+ switch (status) {
+ case PK11TokenNotRemovable:
+ cont = PR_FALSE;
+ printf("%s Token Not Removable\n",tokenName);
+ break;
+ case PK11TokenChanged:
+ event = PK11TokenRemovedOrChangedEvent;
+ printf("%s Token Changed\n", tokenName);
+ break;
+ case PK11TokenRemoved:
+ event = PK11TokenPresentEvent;
+ printf("%s Token Removed\n", tokenName);
+ break;
+ case PK11TokenPresent:
+ event = PK11TokenRemovedOrChangedEvent;
+ printf("%s Token Present\n", tokenName);
+ break;
+ }
+ } while (cont);
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ PR_Cleanup();
+ return 0;
+}
diff --git a/security/nss/cmd/tstclnt/Makefile b/security/nss/cmd/tstclnt/Makefile
new file mode 100644
index 000000000..b31a4fdc8
--- /dev/null
+++ b/security/nss/cmd/tstclnt/Makefile
@@ -0,0 +1,84 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+ifeq (,$(filter-out WINNT WIN95 WIN16,$(OS_TARGET))) # omits WINCE
+ifndef BUILD_OPT
+ifndef NS_USE_GCC
+LDFLAGS += /subsystem:console /profile /debug /machine:I386 /incremental:no
+endif
+OS_CFLAGS += -D_CONSOLE
+endif
+endif
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#include ../platlibs.mk
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/tstclnt/makefile.win b/security/nss/cmd/tstclnt/makefile.win
new file mode 100644
index 000000000..6cf6c12cf
--- /dev/null
+++ b/security/nss/cmd/tstclnt/makefile.win
@@ -0,0 +1,130 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+#cannot define PROGRAM in manifest compatibly with NT and UNIX
+PROGRAM = tstclnt
+PROGRAM = ./$(OBJDIR)/$(PROGRAM).exe
+include <$(DEPTH)\config\config.mak>
+
+# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
+# rules.mak will append C_OBJS onto OBJS.
+# OBJS = $(CSRCS:.c=.obj)
+
+# include files are looked for in $LINCS and $INCS.
+# $LINCS is in manifest.mnw, computed from REQUIRES=
+INCS = $(INCS) \
+ -I$(DEPTH)/security/lib/cert \
+ -I../include \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+ $(NULL)
+
+
+WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
+
+# these files are the content of libdbm
+DBM_LIB = \
+ $(WINFE)/DB.obj \
+ $(WINFE)/HASH.obj \
+ $(WINFE)/H_BIGKEY.obj \
+ $(WINFE)/H_PAGE.obj \
+ $(WINFE)/H_LOG2.obj \
+ $(WINFE)/H_FUNC.obj \
+ $(WINFE)/HASH_BUF.obj \
+ $(NULL)
+
+MOZ_LIBS = \
+ $(WINFE)/ALLXPSTR.obj \
+ $(WINFE)/XP_ERROR.obj \
+ $(WINFE)/XPASSERT.obj \
+ $(WINFE)/XP_REG.obj \
+ $(WINFE)/XP_TRACE.obj \
+ $(DBM_LIB) \
+ $(WINFE)/XP_STR.obj \
+ $(WINFE)/MKTEMP.obj \
+ $(NULL)
+
+SEC_LIBS = \
+ $(DIST)/lib/cert$(MOZ_BITS).lib \
+ $(DIST)/lib/crypto$(MOZ_BITS).lib \
+ $(DIST)/lib/hash$(MOZ_BITS).lib \
+ $(DIST)/lib/key$(MOZ_BITS).lib \
+ $(DIST)/lib/pkcs7$(MOZ_BITS).lib \
+ $(DIST)/lib/secmod$(MOZ_BITS).lib \
+ $(DIST)/lib/secutl$(MOZ_BITS).lib \
+ $(DIST)/lib/ssl$(MOZ_BITS).lib \
+ $(NULL)
+
+LLFLAGS = $(LLFLAGS) \
+ ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
+ $(SEC_LIBS) \
+ $(MOZ_LIBS) \
+ $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
+ $(LIBNSPR) \
+ $(NULL)
+
+
+include <$(DEPTH)\config\rules.mak>
+
+INSTALL = $(MAKE_INSTALL)
+
+objs: $(OBJS)
+
+$(PROGRAM)::
+ $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
+
+programs: $(PROGRAM)
+
+install:: $(TARGETS)
+ $(INSTALL) $(TARGETS) $(DIST)/bin
+
+
+symbols:
+ @echo "CSRCS = $(CSRCS)"
+ @echo "INCS = $(INCS)"
+ @echo "OBJS = $(OBJS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "TARGETS = $(TARGETS)"
+ @echo "DIST = $(DIST)"
+ @echo "VERSION_NUMBER = $(VERSION_NUMBER)"
+ @echo "WINFE = $(WINFE)"
+ @echo "DBM_LIB = $(DBM_LIB)"
+ @echo "INSTALL = $(INSTALL)"
+
diff --git a/security/nss/cmd/tstclnt/manifest.mn b/security/nss/cmd/tstclnt/manifest.mn
new file mode 100644
index 000000000..8762227e4
--- /dev/null
+++ b/security/nss/cmd/tstclnt/manifest.mn
@@ -0,0 +1,50 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+# DIRS =
+
+CSRCS = tstclnt.c
+
+PROGRAM = tstclnt
+
diff --git a/security/nss/cmd/tstclnt/tstclnt.c b/security/nss/cmd/tstclnt/tstclnt.c
new file mode 100644
index 000000000..84f08f3a6
--- /dev/null
+++ b/security/nss/cmd/tstclnt/tstclnt.c
@@ -0,0 +1,779 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
+ * Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+**
+** Sample client side test program that uses SSL and libsec
+**
+*/
+
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#else
+#include "ctype.h" /* for isalpha() */
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "nss.h"
+#include "ssl.h"
+#include "sslproto.h"
+#include "pk11func.h"
+#include "plgetopt.h"
+
+#define PRINTF if (verbose) printf
+#define FPRINTF if (verbose) fprintf
+
+#define MAX_WAIT_FOR_SERVER 600
+#define WAIT_INTERVAL 100
+
+int ssl2CipherSuites[] = {
+ SSL_EN_RC4_128_WITH_MD5, /* A */
+ SSL_EN_RC4_128_EXPORT40_WITH_MD5, /* B */
+ SSL_EN_RC2_128_CBC_WITH_MD5, /* C */
+ SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */
+ SSL_EN_DES_64_CBC_WITH_MD5, /* E */
+ SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* F */
+#ifdef NSS_ENABLE_ECC
+ /* NOTE: Since no new SSL2 ciphersuites are being
+ * invented, and we've run out of lowercase letters
+ * for SSL3 ciphers, we use letters G and beyond
+ * for new SSL3 ciphers.
+ */
+ TLS_ECDH_ECDSA_WITH_NULL_SHA, /* G */
+ TLS_ECDH_ECDSA_WITH_RC4_128_SHA, /* H */
+ TLS_ECDH_ECDSA_WITH_DES_CBC_SHA, /* I */
+ TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* J */
+ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, /* K */
+ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, /* L */
+ TLS_ECDH_RSA_WITH_NULL_SHA, /* M */
+ TLS_ECDH_RSA_WITH_RC4_128_SHA, /* N */
+ TLS_ECDH_RSA_WITH_DES_CBC_SHA, /* O */
+ TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, /* P */
+ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, /* Q */
+ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, /* R */
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* S */
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* T */
+#endif /* NSS_ENABLE_ECC */
+ 0
+};
+
+int ssl3CipherSuites[] = {
+ SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* a */
+ SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, /* b */
+ SSL_RSA_WITH_RC4_128_MD5, /* c */
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
+ SSL_RSA_WITH_DES_CBC_SHA, /* e */
+ SSL_RSA_EXPORT_WITH_RC4_40_MD5, /* f */
+ SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* g */
+ SSL_FORTEZZA_DMS_WITH_NULL_SHA, /* h */
+ SSL_RSA_WITH_NULL_MD5, /* i */
+ SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, /* j */
+ SSL_RSA_FIPS_WITH_DES_CBC_SHA, /* k */
+ TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
+ TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, /* m */
+ SSL_RSA_WITH_RC4_128_SHA, /* n */
+ TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
+ SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
+ SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
+ SSL_DHE_RSA_WITH_DES_CBC_SHA, /* r */
+ SSL_DHE_DSS_WITH_DES_CBC_SHA, /* s */
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */
+ TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */
+ TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
+ SSL_RSA_WITH_NULL_SHA, /* z */
+ 0
+};
+
+unsigned long __cmp_umuls;
+PRBool verbose;
+
+static char *progName;
+
+/* This exists only for the automated test suite. It allows us to
+ * pass in a password on the command line.
+ */
+
+char *password = NULL;
+
+char * ownPasswd( PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *passwd = NULL;
+ if ( (!retry) && arg ) {
+ passwd = PL_strdup((char *)arg);
+ }
+ return passwd;
+}
+
+void printSecurityInfo(PRFileDesc *fd)
+{
+ CERTCertificate * cert;
+ SSL3Statistics * ssl3stats = SSL_GetStatistics();
+ SECStatus result;
+ SSLChannelInfo channel;
+ SSLCipherSuiteInfo suite;
+
+ result = SSL_GetChannelInfo(fd, &channel, sizeof channel);
+ if (result == SECSuccess &&
+ channel.length == sizeof channel &&
+ channel.cipherSuite) {
+ result = SSL_GetCipherSuiteInfo(channel.cipherSuite,
+ &suite, sizeof suite);
+ if (result == SECSuccess) {
+ FPRINTF(stderr,
+ "tstclnt: SSL version %d.%d using %d-bit %s with %d-bit %s MAC\n",
+ channel.protocolVersion >> 8, channel.protocolVersion & 0xff,
+ suite.effectiveKeyBits, suite.symCipherName,
+ suite.macBits, suite.macAlgorithmName);
+ FPRINTF(stderr,
+ "tstclnt: Server Auth: %d-bit %s, Key Exchange: %d-bit %s\n",
+ channel.authKeyBits, suite.authAlgorithmName,
+ channel.keaKeyBits, suite.keaTypeName);
+ }
+ }
+ cert = SSL_RevealCert(fd);
+ if (cert) {
+ char * ip = CERT_NameToAscii(&cert->issuer);
+ char * sp = CERT_NameToAscii(&cert->subject);
+ if (sp) {
+ fprintf(stderr, "subject DN: %s\n", sp);
+ PR_Free(sp);
+ }
+ if (ip) {
+ fprintf(stderr, "issuer DN: %s\n", ip);
+ PR_Free(ip);
+ }
+ CERT_DestroyCertificate(cert);
+ cert = NULL;
+ }
+ fprintf(stderr,
+ "%ld cache hits; %ld cache misses, %ld cache not reusable\n",
+ ssl3stats->hsh_sid_cache_hits, ssl3stats->hsh_sid_cache_misses,
+ ssl3stats->hsh_sid_cache_not_ok);
+
+}
+
+void
+handshakeCallback(PRFileDesc *fd, void *client_data)
+{
+ printSecurityInfo(fd);
+}
+
+static void Usage(const char *progName)
+{
+ printf(
+"Usage: %s -h host [-p port] [-d certdir] [-n nickname] [-23Tovx] \n"
+" [-c ciphers] [-w passwd] [-q]\n", progName);
+ printf("%-20s Hostname to connect with\n", "-h host");
+ printf("%-20s Port number for SSL server\n", "-p port");
+ printf("%-20s Directory with cert database (default is ~/.netscape)\n",
+ "-d certdir");
+ printf("%-20s Nickname of key and cert for client auth\n", "-n nickname");
+ printf("%-20s Disable SSL v2.\n", "-2");
+ printf("%-20s Disable SSL v3.\n", "-3");
+ printf("%-20s Disable TLS (SSL v3.1).\n", "-T");
+ printf("%-20s Override bad server cert. Make it OK.\n", "-o");
+ printf("%-20s Verbose progress reporting.\n", "-v");
+ printf("%-20s Use export policy.\n", "-x");
+ printf("%-20s Ping the server and then exit.\n", "-q");
+ printf("%-20s Letter(s) chosen from the following list\n", "-c ciphers");
+ printf(
+"A SSL2 RC4 128 WITH MD5\n"
+"B SSL2 RC4 128 EXPORT40 WITH MD5\n"
+"C SSL2 RC2 128 CBC WITH MD5\n"
+"D SSL2 RC2 128 CBC EXPORT40 WITH MD5\n"
+"E SSL2 DES 64 CBC WITH MD5\n"
+"F SSL2 DES 192 EDE3 CBC WITH MD5\n"
+#ifdef NSS_ENABLE_ECC
+"G TLS ECDH ECDSA WITH NULL SHA\n"
+"H TLS ECDH ECDSA WITH RC4 128 CBC SHA\n"
+"I TLS ECDH ECDSA WITH DES CBC SHA\n"
+"J TLS ECDH ECDSA WITH 3DES EDE CBC SHA\n"
+"K TLS ECDH ECDSA WITH AES 128 CBC SHA\n"
+"L TLS ECDH ECDSA WITH AES 256 CBC SHA\n"
+"M TLS ECDH RSA WITH NULL SHA\n"
+"N TLS ECDH RSA WITH RC4 128 CBC SHA\n"
+"O TLS ECDH RSA WITH DES CBC SHA\n"
+"P TLS ECDH RSA WITH 3DES EDE CBC SHA\n"
+"Q TLS ECDH RSA WITH AES 128 CBC SHA\n"
+"R TLS ECDH RSA WITH AES 256 CBC SHA\n"
+"S TLS ECDHE ECDSA WITH AES 128 CBC SHA\n"
+"T TLS ECDHE RSA WITH AES 128 CBC SHA\n"
+#endif /* NSS_ENABLE_ECC */
+"\n"
+"a SSL3 FORTEZZA DMS WITH FORTEZZA CBC SHA\n"
+"b SSL3 FORTEZZA DMS WITH RC4 128 SHA\n"
+"c SSL3 RSA WITH RC4 128 MD5\n"
+"d SSL3 RSA WITH 3DES EDE CBC SHA\n"
+"e SSL3 RSA WITH DES CBC SHA\n"
+"f SSL3 RSA EXPORT WITH RC4 40 MD5\n"
+"g SSL3 RSA EXPORT WITH RC2 CBC 40 MD5\n"
+"h SSL3 FORTEZZA DMS WITH NULL SHA\n"
+"i SSL3 RSA WITH NULL MD5\n"
+"j SSL3 RSA FIPS WITH 3DES EDE CBC SHA\n"
+"k SSL3 RSA FIPS WITH DES CBC SHA\n"
+"l SSL3 RSA EXPORT WITH DES CBC SHA\t(new)\n"
+"m SSL3 RSA EXPORT WITH RC4 56 SHA\t(new)\n"
+"n SSL3 RSA WITH RC4 128 SHA\n"
+"o SSL3 DHE DSS WITH RC4 128 SHA\n"
+"p SSL3 DHE RSA WITH 3DES EDE CBC SHA\n"
+"q SSL3 DHE DSS WITH 3DES EDE CBC SHA\n"
+"r SSL3 DHE RSA WITH DES CBC SHA\n"
+"s SSL3 DHE DSS WITH DES CBC SHA\n"
+"t SSL3 DHE DSS WITH AES 128 CBC SHA\n"
+"u SSL3 DHE RSA WITH AES 128 CBC SHA\n"
+"v SSL3 RSA WITH AES 128 CBC SHA\n"
+"w SSL3 DHE DSS WITH AES 256 CBC SHA\n"
+"x SSL3 DHE RSA WITH AES 256 CBC SHA\n"
+"y SSL3 RSA WITH AES 256 CBC SHA\n"
+"z SSL3 RSA WITH NULL SHA\n"
+ );
+ exit(1);
+}
+
+void
+milliPause(PRUint32 milli)
+{
+ PRIntervalTime ticks = PR_MillisecondsToInterval(milli);
+ PR_Sleep(ticks);
+}
+
+void
+disableAllSSLCiphers(void)
+{
+ const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
+ int i = SSL_NumImplementedCiphers;
+ SECStatus rv;
+
+ /* disable all the SSL3 cipher suites */
+ while (--i >= 0) {
+ PRUint16 suite = cipherSuites[i];
+ rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
+ if (rv != SECSuccess) {
+ PRErrorCode err = PR_GetError();
+ printf("SSL_CipherPrefSet didn't like value 0x%04x (i = %d): %s\n",
+ suite, i, SECU_Strerror(err));
+ exit(2);
+ }
+ }
+}
+
+/*
+ * Callback is called when incoming certificate is not valid.
+ * Returns SECSuccess to accept the cert anyway, SECFailure to reject.
+ */
+static SECStatus
+ownBadCertHandler(void * arg, PRFileDesc * socket)
+{
+ PRErrorCode err = PR_GetError();
+ /* can log invalid cert here */
+ printf("Bad server certificate: %d, %s\n", err, SECU_Strerror(err));
+ return SECSuccess; /* override, say it's OK. */
+}
+
+int main(int argc, char **argv)
+{
+ PRFileDesc * s;
+ PRFileDesc * std_out;
+ CERTCertDBHandle * handle;
+ char * host = NULL;
+ char * port = "443";
+ char * certDir = NULL;
+ char * nickname = NULL;
+ char * cipherString = NULL;
+ int multiplier = 0;
+ SECStatus rv;
+ PRStatus status;
+ PRInt32 filesReady;
+ PRInt32 ip;
+ int npds;
+ int override = 0;
+ int disableSSL2 = 0;
+ int disableSSL3 = 0;
+ int disableTLS = 0;
+ int useExportPolicy = 0;
+ int file_read = 0;
+ PRSocketOptionData opt;
+ PRNetAddr addr;
+ PRHostEnt hp;
+ PRPollDesc pollset[2];
+ char buf[PR_NETDB_BUF_SIZE];
+ PRBool useCommandLinePassword = PR_FALSE;
+ PRBool pingServerFirst = PR_FALSE;
+ int error=0;
+ PLOptState *optstate;
+ PLOptStatus optstatus;
+ PRStatus prStatus;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName+1 : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "23Tfc:h:p:d:m:n:oqvw:x");
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ default : Usage(progName); break;
+
+ case '2': disableSSL2 = 1; break;
+
+ case '3': disableSSL3 = 1; break;
+
+ case 'T': disableTLS = 1; break;
+
+ case 'c': cipherString = strdup(optstate->value); break;
+
+ case 'h': host = strdup(optstate->value); break;
+#ifdef _WINDOWS
+ case 'f': file_read = 1; break;
+#else
+ case 'f': break;
+#endif
+
+ case 'd':
+ certDir = strdup(optstate->value);
+ certDir = SECU_ConfigDirectory(certDir);
+ break;
+
+ case 'm':
+ multiplier = atoi(optstate->value);
+ if (multiplier < 0)
+ multiplier = 0;
+ break;
+
+ case 'n': nickname = strdup(optstate->value); break;
+
+ case 'o': override = 1; break;
+
+ case 'p': port = strdup(optstate->value); break;
+
+ case 'q': pingServerFirst = PR_TRUE; break;
+
+ case 'v': verbose++; break;
+
+ case 'w':
+ password = PORT_Strdup(optstate->value);
+ useCommandLinePassword = PR_TRUE;
+ break;
+
+ case 'x': useExportPolicy = 1; break;
+ }
+ }
+ if (optstatus == PL_OPT_BAD)
+ Usage(progName);
+
+ if (!host || !port) Usage(progName);
+
+ if (!certDir) {
+ certDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
+ certDir = SECU_ConfigDirectory(certDir); /* call even if it's NULL */
+ }
+
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ /* set our password function */
+ if ( useCommandLinePassword ) {
+ PK11_SetPasswordFunc(ownPasswd);
+ } else {
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+ }
+
+ /* open the cert DB, the key DB, and the secmod DB. */
+ rv = NSS_Init(certDir);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "unable to open cert database");
+#if 0
+ rv = CERT_OpenVolatileCertDB(handle);
+ CERT_SetDefaultCertDB(handle);
+#else
+ return 1;
+#endif
+ }
+ handle = CERT_GetDefaultCertDB();
+
+ /* set the policy bits true for all the cipher suites. */
+ if (useExportPolicy)
+ NSS_SetExportPolicy();
+ else
+ NSS_SetDomesticPolicy();
+
+ /* all the SSL2 and SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ /* disable all the ciphers, then enable the ones we want. */
+ disableAllSSLCiphers();
+ }
+
+ /* Lookup host */
+ status = PR_GetHostByName(host, buf, sizeof(buf), &hp);
+ if (status != PR_SUCCESS) {
+ SECU_PrintError(progName, "error looking up host");
+ return 1;
+ }
+ if (PR_EnumerateHostEnt(0, &hp, atoi(port), &addr) == -1) {
+ SECU_PrintError(progName, "error looking up host address");
+ return 1;
+ }
+
+ ip = PR_ntohl(addr.inet.ip);
+ PRINTF("%s: connecting to %s:%d (address=%d.%d.%d.%d)\n",
+ progName, host, PR_ntohs(addr.inet.port),
+ (ip >> 24) & 0xff,
+ (ip >> 16) & 0xff,
+ (ip >> 8) & 0xff,
+ (ip >> 0) & 0xff);
+
+ if (pingServerFirst) {
+ int iter = 0;
+ PRErrorCode err;
+ do {
+ s = PR_NewTCPSocket();
+ if (s == NULL) {
+ SECU_PrintError(progName, "Failed to create a TCP socket");
+ }
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ prStatus = PR_SetSocketOption(s, &opt);
+ if (prStatus != PR_SUCCESS) {
+ PR_Close(s);
+ SECU_PrintError(progName,
+ "Failed to set blocking socket option");
+ return 1;
+ }
+ prStatus = PR_Connect(s, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (prStatus == PR_SUCCESS) {
+ PR_Shutdown(s, PR_SHUTDOWN_BOTH);
+ PR_Close(s);
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ PR_Cleanup();
+ return 0;
+ }
+ err = PR_GetError();
+ if ((err != PR_CONNECT_REFUSED_ERROR) &&
+ (err != PR_CONNECT_RESET_ERROR)) {
+ SECU_PrintError(progName, "TCP Connection failed");
+ return 1;
+ }
+ PR_Close(s);
+ PR_Sleep(PR_MillisecondsToInterval(WAIT_INTERVAL));
+ } while (++iter < MAX_WAIT_FOR_SERVER);
+ SECU_PrintError(progName,
+ "Client timed out while waiting for connection to server");
+ return 1;
+ }
+
+ /* Create socket */
+ s = PR_NewTCPSocket();
+ if (s == NULL) {
+ SECU_PrintError(progName, "error creating socket");
+ return 1;
+ }
+
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_TRUE;
+ PR_SetSocketOption(s, &opt);
+ /*PR_SetSocketOption(PR_GetSpecialFD(PR_StandardInput), &opt);*/
+
+ s = SSL_ImportFD(NULL, s);
+ if (s == NULL) {
+ SECU_PrintError(progName, "error importing socket");
+ return 1;
+ }
+
+ rv = SSL_OptionSet(s, SSL_SECURITY, 1);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling socket");
+ return 1;
+ }
+
+ rv = SSL_OptionSet(s, SSL_HANDSHAKE_AS_CLIENT, 1);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling client handshake");
+ return 1;
+ }
+
+ /* all the SSL2 and SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ int ndx;
+
+ while (0 != (ndx = *cipherString++)) {
+ int *cptr;
+ int cipher;
+
+ if (! isalpha(ndx))
+ Usage(progName);
+ cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
+ for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
+ /* do nothing */;
+ if (cipher) {
+ SECStatus status;
+ status = SSL_CipherPrefSet(s, cipher, SSL_ALLOWED);
+ if (status != SECSuccess)
+ SECU_PrintError(progName, "SSL_CipherPrefSet()");
+ }
+ }
+ }
+
+ rv = SSL_OptionSet(s, SSL_ENABLE_SSL2, !disableSSL2);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling SSLv2 ");
+ return 1;
+ }
+
+ rv = SSL_OptionSet(s, SSL_ENABLE_SSL3, !disableSSL3);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling SSLv3 ");
+ return 1;
+ }
+
+ rv = SSL_OptionSet(s, SSL_ENABLE_TLS, !disableTLS);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error enabling TLS ");
+ return 1;
+ }
+
+ /* disable ssl2 and ssl2-compatible client hellos. */
+ rv = SSL_OptionSet(s, SSL_V2_COMPATIBLE_HELLO, !disableSSL2);
+ if (rv != SECSuccess) {
+ SECU_PrintError(progName, "error disabling v2 compatibility");
+ return 1;
+ }
+
+ if (useCommandLinePassword) {
+ SSL_SetPKCS11PinArg(s, password);
+ }
+
+ SSL_AuthCertificateHook(s, SSL_AuthCertificate, (void *)handle);
+ if (override) {
+ SSL_BadCertHook(s, ownBadCertHandler, NULL);
+ }
+ SSL_GetClientAuthDataHook(s, NSS_GetClientAuthData, (void *)nickname);
+ SSL_HandshakeCallback(s, handshakeCallback, NULL);
+ SSL_SetURL(s, host);
+
+ /* Try to connect to the server */
+ status = PR_Connect(s, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (status != PR_SUCCESS) {
+ if (PR_GetError() == PR_IN_PROGRESS_ERROR) {
+ if (verbose)
+ SECU_PrintError(progName, "connect");
+ milliPause(50 * multiplier);
+ pollset[0].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ pollset[0].out_flags = 0;
+ pollset[0].fd = s;
+ while(1) {
+ PRINTF("%s: about to call PR_Poll for connect completion!\n", progName);
+ filesReady = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
+ if (filesReady < 0) {
+ SECU_PrintError(progName, "unable to connect (poll)");
+ return 1;
+ }
+ PRINTF("%s: PR_Poll returned 0x%02x for socket out_flags.\n",
+ progName, pollset[0].out_flags);
+ if (filesReady == 0) { /* shouldn't happen! */
+ PRINTF("%s: PR_Poll returned zero!\n", progName);
+ return 1;
+ }
+ /* Must milliPause between PR_Poll and PR_GetConnectStatus,
+ * Or else winsock gets mighty confused.
+ * Sleep(0);
+ */
+ milliPause(1);
+ status = PR_GetConnectStatus(pollset);
+ if (status == PR_SUCCESS) {
+ break;
+ }
+ if (PR_GetError() != PR_IN_PROGRESS_ERROR) {
+ SECU_PrintError(progName, "unable to connect (poll)");
+ return 1;
+ }
+ SECU_PrintError(progName, "poll");
+ milliPause(50 * multiplier);
+ }
+ } else {
+ SECU_PrintError(progName, "unable to connect");
+ return 1;
+ }
+ }
+
+ pollset[0].fd = s;
+ pollset[0].in_flags = PR_POLL_READ;
+ pollset[1].fd = PR_GetSpecialFD(PR_StandardInput);
+ pollset[1].in_flags = PR_POLL_READ;
+ npds = 2;
+ std_out = PR_GetSpecialFD(PR_StandardOutput);
+
+
+ if (file_read) {
+ pollset[1].out_flags = PR_POLL_READ;
+ npds=1;
+ }
+
+ /*
+ ** Select on stdin and on the socket. Write data from stdin to
+ ** socket, read data from socket and write to stdout.
+ */
+ PRINTF("%s: ready...\n", progName);
+
+ while (pollset[0].in_flags || pollset[1].in_flags) {
+ char buf[4000]; /* buffer for stdin */
+ int nb; /* num bytes read from stdin. */
+
+ pollset[0].out_flags = 0;
+ if (!file_read) {
+ pollset[1].out_flags = 0;
+ }
+
+ PRINTF("%s: about to call PR_Poll !\n", progName);
+ if (pollset[1].in_flags && file_read) {
+ filesReady = PR_Poll(pollset, npds, PR_INTERVAL_NO_WAIT);
+ filesReady++;
+ } else {
+ filesReady = PR_Poll(pollset, npds, PR_INTERVAL_NO_TIMEOUT);
+ }
+ if (filesReady < 0) {
+ SECU_PrintError(progName, "select failed");
+ error=1;
+ goto done;
+ }
+ if (filesReady == 0) { /* shouldn't happen! */
+ PRINTF("%s: PR_Poll returned zero!\n", progName);
+ return 1;
+ }
+ PRINTF("%s: PR_Poll returned!\n", progName);
+ if (pollset[1].in_flags) {
+ PRINTF("%s: PR_Poll returned 0x%02x for stdin out_flags.\n",
+ progName, pollset[1].out_flags);
+#ifndef _WINDOWS
+ }
+ if (pollset[1].out_flags & PR_POLL_READ) {
+#endif
+ /* Read from stdin and write to socket */
+ nb = PR_Read(pollset[1].fd, buf, sizeof(buf));
+ PRINTF("%s: stdin read %d bytes\n", progName, nb);
+ if (nb < 0) {
+ if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ SECU_PrintError(progName, "read from stdin failed");
+ error=1;
+ break;
+ }
+ } else if (nb == 0) {
+ pollset[1].in_flags = 0;
+ } else {
+ char * bufp = buf;
+ PRINTF("%s: Writing %d bytes to server\n", progName, nb);
+ do {
+ PRInt32 cc = PR_Write(s, bufp, nb);
+ if (cc < 0) {
+ PRErrorCode err = PR_GetError();
+ if (err != PR_WOULD_BLOCK_ERROR) {
+ SECU_PrintError(progName,
+ "write to SSL socket failed");
+ error=254;
+ goto done;
+ }
+ cc = 0;
+ }
+ bufp += cc;
+ nb -= cc;
+ if (nb <= 0)
+ break;
+ pollset[0].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ pollset[0].out_flags = 0;
+ PRINTF("%s: about to call PR_Poll on writable socket !\n", progName);
+ cc = PR_Poll(pollset, 1, PR_INTERVAL_NO_TIMEOUT);
+ PRINTF("%s: PR_Poll returned with writable socket !\n", progName);
+ } while (1);
+ pollset[0].in_flags = PR_POLL_READ;
+ }
+ }
+
+ if (pollset[0].in_flags) {
+ PRINTF("%s: PR_Poll returned 0x%02x for socket out_flags.\n",
+ progName, pollset[0].out_flags);
+ }
+ if ( (pollset[0].out_flags & PR_POLL_READ)
+ || (pollset[0].out_flags & PR_POLL_ERR)
+#ifdef PR_POLL_HUP
+ || (pollset[0].out_flags & PR_POLL_HUP)
+#endif
+ ) {
+ /* Read from socket and write to stdout */
+ nb = PR_Read(pollset[0].fd, buf, sizeof(buf));
+ PRINTF("%s: Read from server %d bytes\n", progName, nb);
+ if (nb < 0) {
+ if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
+ SECU_PrintError(progName, "read from socket failed");
+ error=1;
+ goto done;
+ }
+ } else if (nb == 0) {
+ /* EOF from socket... bye bye */
+ pollset[0].in_flags = 0;
+ } else {
+ PR_Write(std_out, buf, nb);
+ puts("\n\n");
+ }
+ }
+ milliPause(50 * multiplier);
+ }
+
+ done:
+ PR_Close(s);
+ SSL_ClearSessionCache();
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ PR_Cleanup();
+ return error;
+}
diff --git a/security/nss/cmd/ttformat/Makefile b/security/nss/cmd/ttformat/Makefile
new file mode 100644
index 000000000..f2a407990
--- /dev/null
+++ b/security/nss/cmd/ttformat/Makefile
@@ -0,0 +1,74 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+include ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/ttformat/manifest.mn b/security/nss/cmd/ttformat/manifest.mn
new file mode 100644
index 000000000..c63d5b052
--- /dev/null
+++ b/security/nss/cmd/ttformat/manifest.mn
@@ -0,0 +1,48 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = ttformat.c
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+PROGRAM = ttformat
+
diff --git a/security/nss/cmd/ttformat/nClient b/security/nss/cmd/ttformat/nClient
new file mode 100755
index 000000000..aab8402bd
--- /dev/null
+++ b/security/nss/cmd/ttformat/nClient
@@ -0,0 +1,49 @@
+# /bin/ksh
+#
+# nClient -- run the nss test strsclnt for performance testing
+#
+# syntax: nClient [options]
+#
+# where: options are:
+# any valid command line option for strsclnt
+# Note that some options are set by this script!
+#
+# Description:
+# nClient runs the nss test program "strsclnt" for purposes of
+# gathering performance data.
+#
+# some shell variables are set at the top of the script
+# you may have to change these, depending on the host you
+# are running on and other "stuff". caveat emptor.
+#
+# You will have to tinker with this script to get it to
+# run for you.
+#
+# See also: nServ
+#
+# --- begin nClient -------------------------------------------------------
+baseDir=/home/lorenzo/nss-raw/mozilla
+#
+# shell variables for running strsclnt
+#
+export HOST=`hostname -s`
+export DOMSUF=red.iplanet.com
+serverHost=dbldog
+nssDB=${baseDir}/tests_results/security/${HOST}.1/client
+nssHost=${HOST}.red.iplanet.com
+pushd ${baseDir}/security/nss/tests/common
+objDir=`gmake objdir_name`
+popd
+#
+#
+nssOptions="-p 12944 ${serverHost}.red.iplanet.com"
+export LD_LIBRARY_PATH=${baseDir}/dist/${objDir}/lib
+clientProg=${baseDir}/security/nss/cmd/strsclnt/${objDir}/strsclnt
+#
+# do the test
+#
+nssCommand="${clientProg} -d ${nssDB} ${nssOptions}"
+echo $nssCommand $*
+${nssCommand} $* &
+#
+# --- end nClient --------------------------------------------------------
diff --git a/security/nss/cmd/ttformat/nServ b/security/nss/cmd/ttformat/nServ
new file mode 100755
index 000000000..ddf51b0e8
--- /dev/null
+++ b/security/nss/cmd/ttformat/nServ
@@ -0,0 +1,49 @@
+# /bin/ksh
+#
+# nServ -- run the nss test selfserv for performance testing
+#
+# syntax: nServ [options]
+#
+# where: options are:
+# Valid arguments to the selfserv program
+# Note that this script sets some options
+#
+# Description:
+# nServ runs the nss test program "selfserv" for purposes of
+# gathering performance data.
+#
+# some shell variables are set at the top of the script
+# you may have to change these, depending on the host you
+# are running on and other "stuff". caveat emptor.
+#
+# See also: nClinet
+#
+# --- begin nServ -------------------------------------------------------
+#
+baseDir=/home/lorenzo/nss-server/mozilla
+#
+# shell variables for running selfserv
+#
+export HOST=`hostname -s`
+export DOMSUF=red.iplanet.com
+nssDB=${baseDir}/tests_results/security/${HOST}.1/server
+nssHost=${HOST}.red.iplanet.com
+nssOptions="-p 12944 -w nss"
+pushd ${baseDir}/security/nss/tests/common
+objDir=`gmake objdir_name`
+popd
+export LD_LIBRARY_PATH=${baseDir}/dist/${objDir}/lib
+#
+# shell variables for capturing instrumentation data
+#
+export NSPR_LOG_MODULES=TestCase:6
+export NSPR_LOG_FILE=xxxLogfile
+#
+# do the test
+#
+nssCommand="${baseDir}/dist/${objDir}/bin/selfserv -d ${nssDB} -n ${nssHost} ${nssOptions}"
+echo $nssCommand
+${nssCommand} $* &
+# xxgdb ${baseDir}/dist/${objDir}/bin/selfserv
+#
+# --- end nServ -------------------------------------------------------
diff --git a/security/nss/cmd/ttformat/redux.pl b/security/nss/cmd/ttformat/redux.pl
new file mode 100755
index 000000000..ccc13c24a
--- /dev/null
+++ b/security/nss/cmd/ttformat/redux.pl
@@ -0,0 +1,77 @@
+#
+# redux.pl -- general nss trace data extraction
+#
+# syntax: redux.pl
+#
+# redux.pl reads a file of formatted trace table records from stdin
+# The trace records are formatted by nssilock.c
+# redux.pl parses the lines and accumulates data in a hash
+# When finished with stdin, redux.pl traverses the hash and emits
+# the accumulated data.
+#
+# Operation:
+# read stdin, accumulate in a hash by file, line, type.
+# traverse the hash, reporting data.
+#
+# raw data format:
+# thredid op ltype callTime heldTime lock line file
+#
+# Notes:
+# After running redux.pl, sort the report on column 4 in decending sequence
+# to see where the lock contention is.
+#
+#
+# -----------------------------------------------------------------------
+use Getopt::Std;
+
+getopts("h") || die "redux.pl: unrecognized command option";
+
+
+# -----------------------------------------------------------------------
+# read stdin to exhaustion
+while ( <STDIN> ) {
+ $recordCount++;
+# next if ($recordCount < 36000 ); # skip initialization records
+ chomp;
+ ($thredid, $op, $ltype, $callTime, $heldTime, $lock, $line, $file) = split;
+
+# select out un-interesting lines
+# next if (( $callTime < $opt_c ) && ( $heldTime < $opt_h ));
+# print $_, "\n";
+
+# count general stats
+ $interesting++;
+
+# format the key
+ $hashKey = $file ." ". $line ." ". $ltype;
+
+# Update the data in the hash entry
+ $theData = $theHash{$hashKey}; # read it if it already exists
+ ( $hCount, $hcallTime, $hheldTime, $hcallMax, $hheldMax ) = split(/\s+/, $theData );
+ $hCount++;
+ $hcallTime += $callTime;
+ $hheldTime += $heldTime;
+ $hcallMax = ( $hcallMax > $callTime )? $hcallMax : $callTime;
+ $hheldMax = ( $hheldMax > $heldTime )? $hheldMax : $heldTime;
+
+# Write theData back to the hash
+ $theData = $hCount." ".$hcallTime." ".$hheldTime." ".$hcallMax." ".$hheldMax;
+ $theHash{$hashKey} = $theData;
+} # end while()
+
+# -----------------------------------------------------------------------
+# traverse theHash
+ printf("%-16s %6s %-16s %8s %8s %8s %8s %8s\n",
+ "File","line","ltype","hits","calltim","heldtim","callmax","heldmax" );
+while (($hashKey,$theData) = each(%theHash)) {
+ $hashElements++;
+ ($file, $line, $ltype) = split(/\s+/, $hashKey );
+ ( $hCount, $hcallTime, $hheldTime, $hcallMax, $hheldMax ) = split(/\s+/, $theData );
+ printf("%-16s %6d %-16s %8d %8d %8d %8d %8d\n",
+ $file, $line, $ltype, $hCount, $hcallTime, $hheldTime, $hcallMax, $hheldMax );
+} # end while()
+
+# -----------------------------------------------------------------------
+# dump global statistics
+printf ("Record count: %d\n", $recordCount );
+printf("Interesting: %d, HashElements: %d\n", $interesting, $hashElements);
diff --git a/security/nss/cmd/ttformat/reduxhwm.pl b/security/nss/cmd/ttformat/reduxhwm.pl
new file mode 100644
index 000000000..f442ff4e4
--- /dev/null
+++ b/security/nss/cmd/ttformat/reduxhwm.pl
@@ -0,0 +1,33 @@
+#
+# reduxhwm.pl -- analyze highwatermark data in xxxLogfile
+#
+# example interesting line in xxxLogfile
+# 1026[8154da0]: selfserv: Launched thread in slot 37, highWaterMark: 63
+#
+#
+#
+while ( <STDIN> ) {
+ chomp;
+ ($proc, $who, $launched, $thread, $in, $slotx, $slot, $hwm, $highwatermark) = split;
+ if ( $launched == "Launched" ) {
+ next if ( $slot == 0 );
+ $notInteresting++;
+ if ( $hwmMax < $highwatermark ){
+ $hwmMax = $highwatermark;
+ }
+ $hwmArray[$slot] += 1;
+ $interesting++;
+ }
+} # end while()
+
+printf ("Interesteing: %d\n", $interesting );
+printf ("Not Interesting: %d\n", $notInteresting - $interesting );
+
+foreach $element (@hwmArray) {
+ $percent = 100*($element / $interesting);
+ $percentTotal += $percent;
+ printf("Slot %2d: %d hits, %2.2f percent, %2.2f total percent\n", $i, $element, $percent, $percentTotal );
+ $i++;
+}
+printf("Sum of percentages: %3.2f\n", $percentTotal );
+# --- end ---
diff --git a/security/nss/cmd/ttformat/ttformat.c b/security/nss/cmd/ttformat/ttformat.c
new file mode 100644
index 000000000..7fcf04f86
--- /dev/null
+++ b/security/nss/cmd/ttformat/ttformat.c
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/*
+** File: ttformat.c
+** Description: ttformat.c reads the file "xxxTTLog". xxxTTLog
+** contains fixed length binary data written by nssilock.
+** ttformat formats the data to a human readable form (printf)
+** usable for visual scanning and for processing via a perl script.
+** Output is written to stdout
+**
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <nssilock.h>
+
+/*
+** struct maps enum nssILockType to character representation
+*/
+struct {
+ nssILockType ltype;
+ char *name;
+} ltypeNameT[] = {
+ { nssILockArena, "Arena" },
+ { nssILockSession, "Session" },
+ { nssILockObject, "Object" },
+ { nssILockRefLock, "RefLock" },
+ { nssILockCert, "Cert", },
+ { nssILockCertDB, "CertDB" },
+ { nssILockDBM, "DBM" },
+ { nssILockCache, "Cache" },
+ { nssILockSSL, "SSL" },
+ { nssILockList, "List" },
+ { nssILockSlot, "Slot" },
+ { nssILockFreelist, "Freelist" },
+ { nssILockOID, "OID" },
+ { nssILockAttribute, "Attribute" },
+ { nssILockPK11cxt, "PK11Context" },
+ { nssILockRWLock, "RWLock" },
+ { nssILockOther, "Other" },
+ { nssILockSelfServ, "SelfServ" }
+}; /* end ltypeNameT */
+
+/*
+** struct maps enum nssILockOp to character representation
+*/
+struct {
+ nssILockOp op;
+ char *name;
+} opNameT[] = {
+ { FlushTT, "FlushTT" },
+ { NewLock, "NewLock" },
+ { Lock, "Lock" },
+ { Unlock, "Unlock" },
+ { DestroyLock, "DestroyLock" },
+ { NewCondVar, "NewCondVar" },
+ { WaitCondVar, "WaitCondVar" },
+ { NotifyCondVar, "NotifyCondVar" },
+ { NotifyAllCondVar, "NotifyAllCondVar" },
+ { DestroyCondVar, "DestroyCondVar" },
+ { NewMonitor, "NewMonitor" },
+ { EnterMonitor, "EnterMonitor" },
+ { ExitMonitor, "ExitMonitor" },
+ { Notify, "Notify" },
+ { NotifyAll, "NotifyAll" },
+ { Wait, "Wait" },
+ { DestroyMonitor, "DestroyMonitor" }
+}; /* end opNameT */
+
+
+int main(int argc, char *argv[])
+{
+ FILE *filea;
+ struct pzTrace_s inBuf;
+ char *opName;
+ char *ltypeName;
+ int rCount = 0;
+ int oCount = 0;
+
+ filea = fopen( "xxxTTLog", "r" );
+ if ( NULL == filea ) {
+ fprintf( stderr, "ttformat: Oh drat! Can't open 'xxxTTLog'\n" );
+ exit(1);
+ }
+
+ while(1 == (fread( &inBuf, sizeof(inBuf), 1 , filea ))) {
+ ++rCount;
+ if ( inBuf.op > DestroyMonitor ) continue;
+ if ( inBuf.op < FlushTT ) continue;
+
+ opName = opNameT[inBuf.op].name;
+ ltypeName = ltypeNameT[inBuf.ltype].name;
+
+ ++oCount;
+ printf("%8d %18s %18s %6d %6d %12p %6d %20s\n",
+ inBuf.threadID, opName, ltypeName, inBuf.callTime, inBuf.heldTime,
+ inBuf.lock, inBuf.line, inBuf.file );
+ } /* end while() */
+
+ fprintf( stderr, "Read: %d, Wrote: %d\n", rCount, oCount );
+ return 0;
+} /* main() */
+/* end ttformat.c */
diff --git a/security/nss/cmd/vfychain/Makefile b/security/nss/cmd/vfychain/Makefile
new file mode 100644
index 000000000..8a0332d89
--- /dev/null
+++ b/security/nss/cmd/vfychain/Makefile
@@ -0,0 +1,82 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+ifeq (,$(filter-out WINNT WIN95 WIN16,$(OS_TARGET))) # omits WINCE
+ifndef BUILD_OPT
+LDFLAGS += /subsystem:console /profile /debug /machine:I386 /incremental:no
+OS_CFLAGS += -D_CONSOLE
+endif
+endif
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#include ../platlibs.mk
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/vfychain/manifest.mn b/security/nss/cmd/vfychain/manifest.mn
new file mode 100644
index 000000000..1cdcc4de8
--- /dev/null
+++ b/security/nss/cmd/vfychain/manifest.mn
@@ -0,0 +1,51 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd
+
+# DIRS =
+
+CSRCS = vfychain.c
+DEFINES += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\"
+
+PROGRAM = vfychain
+
diff --git a/security/nss/cmd/vfychain/vfychain.c b/security/nss/cmd/vfychain/vfychain.c
new file mode 100644
index 000000000..91189ed19
--- /dev/null
+++ b/security/nss/cmd/vfychain/vfychain.c
@@ -0,0 +1,438 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/****************************************************************************
+ * Read in a cert chain from one or more files, and verify the chain for
+ * some usage.
+ * *
+ * This code was modified from other code also kept in the NSS directory.
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "prerror.h"
+
+#include "nssrenam.h"
+#include "pk11func.h"
+#include "seccomon.h"
+#include "secutil.h"
+#include "secmod.h"
+#include "secitem.h"
+#include "cert.h"
+
+
+/* #include <stdlib.h> */
+/* #include <errno.h> */
+/* #include <fcntl.h> */
+/* #include <stdarg.h> */
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "prio.h"
+#include "nss.h"
+
+/* #include "vfyutil.h" */
+
+#define RD_BUF_SIZE (60 * 1024)
+
+int verbose;
+
+char *password = NULL;
+
+/* Function: char * myPasswd()
+ *
+ * Purpose: This function is our custom password handler that is called by
+ * SSL when retreiving private certs and keys from the database. Returns a
+ * pointer to a string that with a password for the database. Password pointer
+ * should point to dynamically allocated memory that will be freed later.
+ */
+char *
+myPasswd(PK11SlotInfo *info, PRBool retry, void *arg)
+{
+ char * passwd = NULL;
+
+ if ( (!retry) && arg ) {
+ passwd = PORT_Strdup((char *)arg);
+ }
+ return passwd;
+}
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-d dbdir] certfile [certfile ...]\n",
+ progName);
+ exit(1);
+}
+
+/**************************************************************************
+**
+** Error and information routines.
+**
+**************************************************************************/
+
+void
+errWarn(char *function)
+{
+ PRErrorCode errorNumber = PR_GetError();
+ const char * errorString = SECU_Strerror(errorNumber);
+
+ fprintf(stderr, "Error in function %s: %d\n - %s\n",
+ function, errorNumber, errorString);
+}
+
+void
+exitErr(char *function)
+{
+ errWarn(function);
+ /* Exit gracefully. */
+ /* ignoring return value of NSS_Shutdown as code exits with 1 anyway*/
+ (void) NSS_Shutdown();
+ PR_Cleanup();
+ exit(1);
+}
+
+static char *
+bestCertName(CERTCertificate *cert) {
+ if (cert->nickname) {
+ return cert->nickname;
+ }
+ if (cert->emailAddr) {
+ return cert->emailAddr;
+ }
+ return cert->subjectName;
+}
+
+void
+printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig,
+ SECCertUsage certUsage, void *pinArg)
+{
+ CERTVerifyLog log;
+ CERTVerifyLogNode *node = NULL;
+ unsigned int depth = (unsigned int)-1;
+ unsigned int flags = 0;
+ char * errstr = NULL;
+ PRErrorCode err = PORT_GetError();
+
+ log.arena = PORT_NewArena(512);
+ log.head = log.tail = NULL;
+ log.count = 0;
+ CERT_VerifyCert(handle, cert, checksig, certUsage,
+ PR_Now(), pinArg, &log);
+
+ if (log.count > 0) {
+ fprintf(outfile,"PROBLEM WITH THE CERT CHAIN:\n");
+ for (node = log.head; node; node = node->next) {
+ if (depth != node->depth) {
+ depth = node->depth;
+ fprintf(outfile,"CERT %d. %s %s:\n", depth,
+ bestCertName(node->cert),
+ depth ? "[Certificate Authority]": "");
+ if (verbose) {
+ const char * emailAddr;
+ emailAddr = CERT_GetFirstEmailAddress(node->cert);
+ if (emailAddr) {
+ fprintf(outfile,"Email Address(es): ");
+ do {
+ fprintf(outfile, "%s\n", emailAddr);
+ emailAddr = CERT_GetNextEmailAddress(node->cert,
+ emailAddr);
+ } while (emailAddr);
+ }
+ }
+ }
+ fprintf(outfile," ERROR %d: %s\n", node->error,
+ SECU_Strerror(node->error));
+ errstr = NULL;
+ switch (node->error) {
+ case SEC_ERROR_INADEQUATE_KEY_USAGE:
+ flags = (unsigned int)node->arg;
+ switch (flags) {
+ case KU_DIGITAL_SIGNATURE:
+ errstr = "Cert cannot sign.";
+ break;
+ case KU_KEY_ENCIPHERMENT:
+ errstr = "Cert cannot encrypt.";
+ break;
+ case KU_KEY_CERT_SIGN:
+ errstr = "Cert cannot sign other certs.";
+ break;
+ default:
+ errstr = "[unknown usage].";
+ break;
+ }
+ case SEC_ERROR_INADEQUATE_CERT_TYPE:
+ flags = (unsigned int)node->arg;
+ switch (flags) {
+ case NS_CERT_TYPE_SSL_CLIENT:
+ case NS_CERT_TYPE_SSL_SERVER:
+ errstr = "Cert cannot be used for SSL.";
+ break;
+ case NS_CERT_TYPE_SSL_CA:
+ errstr = "Cert cannot be used as an SSL CA.";
+ break;
+ case NS_CERT_TYPE_EMAIL:
+ errstr = "Cert cannot be used for SMIME.";
+ break;
+ case NS_CERT_TYPE_EMAIL_CA:
+ errstr = "Cert cannot be used as an SMIME CA.";
+ break;
+ case NS_CERT_TYPE_OBJECT_SIGNING:
+ errstr = "Cert cannot be used for object signing.";
+ break;
+ case NS_CERT_TYPE_OBJECT_SIGNING_CA:
+ errstr = "Cert cannot be used as an object signing CA.";
+ break;
+ default:
+ errstr = "[unknown usage].";
+ break;
+ }
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ case SEC_ERROR_UNTRUSTED_ISSUER:
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ errstr = node->cert->issuerName;
+ break;
+ default:
+ break;
+ }
+ if (errstr) {
+ fprintf(stderr," %s\n",errstr);
+ }
+ CERT_DestroyCertificate(node->cert);
+ }
+ }
+ PORT_SetError(err); /* restore original error code */
+}
+
+typedef struct certMemStr {
+ struct certMemStr * next;
+ CERTCertificate * cert;
+} certMem;
+
+certMem * theCerts;
+
+void
+rememberCert(CERTCertificate * cert)
+{
+ certMem * newCertMem = PORT_ZNew(certMem);
+ if (newCertMem) {
+ newCertMem->next = theCerts;
+ newCertMem->cert = cert;
+ theCerts = newCertMem;
+ }
+}
+
+void
+forgetCerts(void)
+{
+ certMem * oldCertMem;
+ while (oldCertMem = theCerts) {
+ theCerts = oldCertMem->next;
+ CERT_DestroyCertificate(oldCertMem->cert);
+ PORT_Free(oldCertMem);
+ }
+ theCerts = NULL;
+}
+
+
+CERTCertificate *
+readCertFile(const char * fileName, PRBool isAscii)
+{
+ unsigned char * pb;
+ CERTCertificate * cert = NULL;
+ CERTCertDBHandle *defaultDB = NULL;
+ PRFileDesc* fd;
+ PRInt32 cc = -1;
+ PRInt32 total;
+ PRInt32 remaining;
+ SECItem item;
+ static unsigned char certBuf[RD_BUF_SIZE];
+
+ fd = PR_Open(fileName, PR_RDONLY, 0777);
+ if (!fd) {
+ PRIntn err = PR_GetError();
+ fprintf(stderr, "open of %s failed, %d = %s\n",
+ fileName, err, SECU_Strerror(err));
+ return cert;
+ }
+ /* read until EOF or buffer is full */
+ pb = certBuf;
+ while (0 < (remaining = (sizeof certBuf) - (pb - certBuf))) {
+ cc = PR_Read(fd, pb, remaining);
+ if (cc == 0)
+ break;
+ if (cc < 0) {
+ PRIntn err = PR_GetError();
+ fprintf(stderr, "read of %s failed, %d = %s\n",
+ fileName, err, SECU_Strerror(err));
+ break;
+ }
+ /* cc > 0 */
+ pb += cc;
+ }
+ PR_Close(fd);
+ if (cc < 0)
+ return cert;
+ if (!remaining || cc > 0) { /* file was too big. */
+ fprintf(stderr, "cert file %s was too big.\n");
+ return cert;
+ }
+ total = pb - certBuf;
+ if (!total) { /* file was empty */
+ fprintf(stderr, "cert file %s was empty.\n");
+ return cert;
+ }
+ if (isAscii) {
+ /* convert from Base64 to binary here ... someday */
+ }
+ item.type = siBuffer;
+ item.data = certBuf;
+ item.len = total;
+ defaultDB = CERT_GetDefaultCertDB();
+ cert = CERT_NewTempCertificate(defaultDB, &item,
+ NULL /* nickname */,
+ PR_FALSE /* isPerm */,
+ PR_TRUE /* copyDER */);
+ if (!cert) {
+ PRIntn err = PR_GetError();
+ fprintf(stderr, "couldn't import %s, %d = %s\n",
+ fileName, err, SECU_Strerror(err));
+ }
+ return cert;
+}
+
+int
+main(int argc, char *argv[], char *envp[])
+{
+ char * certDir = NULL;
+ char * progName = NULL;
+ char * cipherString = NULL;
+ CERTCertificate * cert;
+ CERTCertificate * firstCert = NULL;
+ CERTCertDBHandle * defaultDB = NULL;
+ PRBool isAscii = PR_FALSE;
+ SECStatus secStatus;
+ SECCertUsage certUsage = certUsageSSLServer;
+ PLOptState * optstate;
+ PLOptStatus status;
+
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ progName = PL_strdup(argv[0]);
+
+ optstate = PL_CreateOptState(argc, argv, "ad:ru:w:v");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch(optstate->option) {
+ case 0 : /* positional parameter */ goto breakout;
+ case 'a' : isAscii = PR_TRUE; break;
+ case 'd' : certDir = PL_strdup(optstate->value); break;
+ case 'r' : isAscii = PR_FALSE; break;
+ case 'u' : certUsage = (SECCertUsage)PORT_Atoi(optstate->value); break;
+ case 'w' : password = PL_strdup(optstate->value); break;
+ case 'v' : verbose++; break;
+ default : Usage(progName); break;
+ }
+ }
+breakout:
+ if (status != PL_OPT_OK)
+ Usage(progName);
+
+ /* Set our password function callback. */
+ PK11_SetPasswordFunc(myPasswd);
+
+ /* Initialize the NSS libraries. */
+ if (certDir) {
+ secStatus = NSS_Init(certDir);
+ } else {
+ secStatus = NSS_NoDB_Init(NULL);
+
+ /* load the builtins */
+ SECMOD_AddNewModule("Builtins", DLL_PREFIX"nssckbi."DLL_SUFFIX, 0, 0);
+ }
+ if (secStatus != SECSuccess) {
+ exitErr("NSS_Init");
+ }
+
+
+ while (status == PL_OPT_OK) {
+ switch(optstate->option) {
+ default : Usage(progName); break;
+ case 'a' : isAscii = PR_TRUE; break;
+ case 'r' : isAscii = PR_FALSE; break;
+ case 0 : /* positional parameter */
+ cert = readCertFile(optstate->value, isAscii);
+ if (!cert)
+ goto punt;
+ rememberCert(cert);
+ if (!firstCert)
+ firstCert = cert;
+ break;
+ }
+ status = PL_GetNextOpt(optstate);
+ }
+ if (status == PL_OPT_BAD || !firstCert)
+ Usage(progName);
+
+ /* NOW, verify the cert chain. */
+ defaultDB = CERT_GetDefaultCertDB();
+ secStatus = CERT_VerifyCert(defaultDB, firstCert,
+ PR_TRUE /* check sig */,
+ certUsage,
+ PR_Now(),
+ NULL, /* wincx */
+ NULL); /* error log */
+
+ if (secStatus != SECSuccess) {
+ PRIntn err = PR_GetError();
+ fprintf(stderr, "Chain is bad, %d = %s\n", err, SECU_Strerror(err));
+ printCertProblems(stderr, defaultDB, firstCert,
+ PR_TRUE, certUsage, NULL);
+ } else {
+ fprintf(stderr, "Chain is good!\n");
+ }
+
+punt:
+ forgetCerts();
+ if (NSS_Shutdown != SECSuccess) {
+ exit(1);
+ }
+ PR_Cleanup();
+ return 0;
+}
diff --git a/security/nss/cmd/vfyserv/Makefile b/security/nss/cmd/vfyserv/Makefile
new file mode 100644
index 000000000..b31a4fdc8
--- /dev/null
+++ b/security/nss/cmd/vfyserv/Makefile
@@ -0,0 +1,84 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+ifeq (,$(filter-out WINNT WIN95 WIN16,$(OS_TARGET))) # omits WINCE
+ifndef BUILD_OPT
+ifndef NS_USE_GCC
+LDFLAGS += /subsystem:console /profile /debug /machine:I386 /incremental:no
+endif
+OS_CFLAGS += -D_CONSOLE
+endif
+endif
+
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#include ../platlibs.mk
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/security/nss/cmd/vfyserv/makefile.win b/security/nss/cmd/vfyserv/makefile.win
new file mode 100644
index 000000000..6cf6c12cf
--- /dev/null
+++ b/security/nss/cmd/vfyserv/makefile.win
@@ -0,0 +1,130 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+VERBOSE = 1
+include <manifest.mn>
+
+#cannot define PROGRAM in manifest compatibly with NT and UNIX
+PROGRAM = tstclnt
+PROGRAM = ./$(OBJDIR)/$(PROGRAM).exe
+include <$(DEPTH)\config\config.mak>
+
+# let manifest generate C_OBJS, it will prepend ./$(OBJDIR)/
+# rules.mak will append C_OBJS onto OBJS.
+# OBJS = $(CSRCS:.c=.obj)
+
+# include files are looked for in $LINCS and $INCS.
+# $LINCS is in manifest.mnw, computed from REQUIRES=
+INCS = $(INCS) \
+ -I$(DEPTH)/security/lib/cert \
+ -I../include \
+ $(NULL)
+
+IGNORE_ME = \
+ -I$(DEPTH)/security/lib/key \
+ -I$(DEPTH)/security/lib/util \
+ $(NULL)
+
+
+WINFE = $(DEPTH)/cmd/winfe/mkfiles$(MOZ_BITS)/x86Dbg
+
+# these files are the content of libdbm
+DBM_LIB = \
+ $(WINFE)/DB.obj \
+ $(WINFE)/HASH.obj \
+ $(WINFE)/H_BIGKEY.obj \
+ $(WINFE)/H_PAGE.obj \
+ $(WINFE)/H_LOG2.obj \
+ $(WINFE)/H_FUNC.obj \
+ $(WINFE)/HASH_BUF.obj \
+ $(NULL)
+
+MOZ_LIBS = \
+ $(WINFE)/ALLXPSTR.obj \
+ $(WINFE)/XP_ERROR.obj \
+ $(WINFE)/XPASSERT.obj \
+ $(WINFE)/XP_REG.obj \
+ $(WINFE)/XP_TRACE.obj \
+ $(DBM_LIB) \
+ $(WINFE)/XP_STR.obj \
+ $(WINFE)/MKTEMP.obj \
+ $(NULL)
+
+SEC_LIBS = \
+ $(DIST)/lib/cert$(MOZ_BITS).lib \
+ $(DIST)/lib/crypto$(MOZ_BITS).lib \
+ $(DIST)/lib/hash$(MOZ_BITS).lib \
+ $(DIST)/lib/key$(MOZ_BITS).lib \
+ $(DIST)/lib/pkcs7$(MOZ_BITS).lib \
+ $(DIST)/lib/secmod$(MOZ_BITS).lib \
+ $(DIST)/lib/secutl$(MOZ_BITS).lib \
+ $(DIST)/lib/ssl$(MOZ_BITS).lib \
+ $(NULL)
+
+LLFLAGS = $(LLFLAGS) \
+ ../lib/$(OBJDIR)/sectool$(MOZ_BITS).lib \
+ $(SEC_LIBS) \
+ $(MOZ_LIBS) \
+ $(DEPTH)/nspr/src/$(OBJDIR)/getopt.obj \
+ $(LIBNSPR) \
+ $(NULL)
+
+
+include <$(DEPTH)\config\rules.mak>
+
+INSTALL = $(MAKE_INSTALL)
+
+objs: $(OBJS)
+
+$(PROGRAM)::
+ $(INSTALL) $(DIST)/bin/pr3240.dll ./$(OBJDIR)
+
+programs: $(PROGRAM)
+
+install:: $(TARGETS)
+ $(INSTALL) $(TARGETS) $(DIST)/bin
+
+
+symbols:
+ @echo "CSRCS = $(CSRCS)"
+ @echo "INCS = $(INCS)"
+ @echo "OBJS = $(OBJS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "TARGETS = $(TARGETS)"
+ @echo "DIST = $(DIST)"
+ @echo "VERSION_NUMBER = $(VERSION_NUMBER)"
+ @echo "WINFE = $(WINFE)"
+ @echo "DBM_LIB = $(DBM_LIB)"
+ @echo "INSTALL = $(INSTALL)"
+
diff --git a/security/nss/cmd/vfyserv/manifest.mn b/security/nss/cmd/vfyserv/manifest.mn
new file mode 100644
index 000000000..ccbca1d75
--- /dev/null
+++ b/security/nss/cmd/vfyserv/manifest.mn
@@ -0,0 +1,51 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+# DIRS =
+
+CSRCS = vfyserv.c vfyutil.c
+DEFINES += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\"
+
+PROGRAM = vfyserv
+
diff --git a/security/nss/cmd/vfyserv/vfyserv.c b/security/nss/cmd/vfyserv/vfyserv.c
new file mode 100644
index 000000000..288319dcd
--- /dev/null
+++ b/security/nss/cmd/vfyserv/vfyserv.c
@@ -0,0 +1,458 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+/****************************************************************************
+ * SSL client program that tests a server for proper operation of SSL2, *
+ * SSL3, and TLS. Test propder certificate installation. *
+ * *
+ * This code was modified from the SSLSample code also kept in the NSS *
+ * directory. *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(XP_UNIX)
+#include <unistd.h>
+#endif
+
+#include "prerror.h"
+
+#include "pk11func.h"
+#include "secmod.h"
+#include "secitem.h"
+
+
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "nspr.h"
+#include "plgetopt.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "nss.h"
+
+#include "vfyserv.h"
+
+#define RD_BUF_SIZE (60 * 1024)
+
+extern int ssl2CipherSuites[];
+extern int ssl3CipherSuites[];
+
+GlobalThreadMgr threadMGR;
+char *certNickname = NULL;
+char *hostName = NULL;
+char *password = NULL;
+unsigned short port = 0;
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-p port] [-c connections] [-C cipher(s)] hostname\n",
+ progName);
+ exit(1);
+}
+
+PRFileDesc *
+setupSSLSocket(PRNetAddr *addr)
+{
+ PRFileDesc *tcpSocket;
+ PRFileDesc *sslSocket;
+ PRSocketOptionData socketOption;
+ PRStatus prStatus;
+ SECStatus secStatus;
+
+
+ tcpSocket = PR_NewTCPSocket();
+ if (tcpSocket == NULL) {
+ errWarn("PR_NewTCPSocket");
+ }
+
+ /* Make the socket blocking. */
+ socketOption.option = PR_SockOpt_Nonblocking;
+ socketOption.value.non_blocking = PR_FALSE;
+
+ prStatus = PR_SetSocketOption(tcpSocket, &socketOption);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_SetSocketOption");
+ goto loser;
+ }
+
+
+ /* Import the socket into the SSL layer. */
+ sslSocket = SSL_ImportFD(NULL, tcpSocket);
+ if (!sslSocket) {
+ errWarn("SSL_ImportFD");
+ goto loser;
+ }
+
+ /* Set configuration options. */
+ secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, PR_TRUE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_OptionSet:SSL_SECURITY");
+ goto loser;
+ }
+
+ secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT");
+ goto loser;
+ }
+
+ /* Set SSL callback routines. */
+ secStatus = SSL_GetClientAuthDataHook(sslSocket,
+ (SSLGetClientAuthData)myGetClientAuthData,
+ (void *)certNickname);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_GetClientAuthDataHook");
+ goto loser;
+ }
+
+ secStatus = SSL_AuthCertificateHook(sslSocket,
+ (SSLAuthCertificate)myAuthCertificate,
+ (void *)CERT_GetDefaultCertDB());
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_AuthCertificateHook");
+ goto loser;
+ }
+
+ secStatus = SSL_BadCertHook(sslSocket,
+ (SSLBadCertHandler)myBadCertHandler, NULL);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_BadCertHook");
+ goto loser;
+ }
+
+ secStatus = SSL_HandshakeCallback(sslSocket,
+ (SSLHandshakeCallback)myHandshakeCallback,
+ NULL);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_HandshakeCallback");
+ goto loser;
+ }
+
+ return sslSocket;
+
+loser:
+
+ PR_Close(tcpSocket);
+ return NULL;
+}
+
+
+const char requestString[] = {"GET /testfile HTTP/1.0\r\n\r\n" };
+
+SECStatus
+handle_connection(PRFileDesc *sslSocket, int connection)
+{
+ int countRead = 0;
+ PRInt32 numBytes;
+ char *readBuffer;
+
+ readBuffer = PORT_Alloc(RD_BUF_SIZE);
+ if (!readBuffer) {
+ exitErr("PORT_Alloc");
+ }
+
+ /* compose the http request here. */
+
+ numBytes = PR_Write(sslSocket, requestString, strlen(requestString));
+ if (numBytes <= 0) {
+ errWarn("PR_Write");
+ PR_Free(readBuffer);
+ readBuffer = NULL;
+ return SECFailure;
+ }
+
+ /* read until EOF */
+ while (PR_TRUE) {
+ numBytes = PR_Read(sslSocket, readBuffer, RD_BUF_SIZE);
+ if (numBytes == 0) {
+ break; /* EOF */
+ }
+ if (numBytes < 0) {
+ errWarn("PR_Read");
+ break;
+ }
+ countRead += numBytes;
+ }
+
+ printSecurityInfo(stderr, sslSocket);
+
+ PR_Free(readBuffer);
+ readBuffer = NULL;
+
+ /* Caller closes the socket. */
+
+ fprintf(stderr,
+ "***** Connection %d read %d bytes total.\n",
+ connection, countRead);
+
+ return SECSuccess; /* success */
+}
+
+#define BYTE(n,i) (((i)>>((n)*8))&0xff)
+
+/* one copy of this function is launched in a separate thread for each
+** connection to be made.
+*/
+SECStatus
+do_connects(void *a, int connection)
+{
+ PRNetAddr *addr = (PRNetAddr *)a;
+ PRFileDesc *sslSocket;
+ PRHostEnt hostEntry;
+ char buffer[PR_NETDB_BUF_SIZE];
+ PRStatus prStatus;
+ PRIntn hostenum;
+ PRInt32 ip;
+ SECStatus secStatus;
+
+ /* Set up SSL secure socket. */
+ sslSocket = setupSSLSocket(addr);
+ if (sslSocket == NULL) {
+ errWarn("setupSSLSocket");
+ return SECFailure;
+ }
+
+ secStatus = SSL_SetPKCS11PinArg(sslSocket, password);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_SetPKCS11PinArg");
+ return secStatus;
+ }
+
+ secStatus = SSL_SetURL(sslSocket, hostName);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_SetURL");
+ return secStatus;
+ }
+
+ /* Prepare and setup network connection. */
+ prStatus = PR_GetHostByName(hostName, buffer, sizeof(buffer), &hostEntry);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_GetHostByName");
+ return SECFailure;
+ }
+
+ hostenum = PR_EnumerateHostEnt(0, &hostEntry, port, addr);
+ if (hostenum == -1) {
+ errWarn("PR_EnumerateHostEnt");
+ return SECFailure;
+ }
+
+ ip = PR_ntohl(addr->inet.ip);
+ fprintf(stderr,
+ "Connecting to host %s (addr %d.%d.%d.%d) on port %d\n",
+ hostName, BYTE(3,ip), BYTE(2,ip), BYTE(1,ip),
+ BYTE(0,ip), PR_ntohs(addr->inet.port));
+
+ prStatus = PR_Connect(sslSocket, addr, PR_INTERVAL_NO_TIMEOUT);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_Connect");
+ return SECFailure;
+ }
+
+ /* Established SSL connection, ready to send data. */
+#if 0
+ secStatus = SSL_ForceHandshake(sslSocket);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_ForceHandshake");
+ return secStatus;
+ }
+#endif
+
+ secStatus = SSL_ResetHandshake(sslSocket, /* asServer */ PR_FALSE);
+ if (secStatus != SECSuccess) {
+ errWarn("SSL_ResetHandshake");
+ prStatus = PR_Close(sslSocket);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_Close");
+ }
+ return secStatus;
+ }
+
+ secStatus = handle_connection(sslSocket, connection);
+ if (secStatus != SECSuccess) {
+ /* error already printed out in handle_connection */
+ /* errWarn("handle_connection"); */
+ prStatus = PR_Close(sslSocket);
+ if (prStatus != PR_SUCCESS) {
+ errWarn("PR_Close");
+ }
+ return secStatus;
+ }
+
+ PR_Close(sslSocket);
+ return SECSuccess;
+}
+
+void
+client_main(unsigned short port,
+ int connections,
+ const char * hostName)
+{
+ int i;
+ SECStatus secStatus;
+ PRStatus prStatus;
+ PRInt32 rv;
+ PRNetAddr addr;
+ PRHostEnt hostEntry;
+ char buffer[256];
+
+ /* Setup network connection. */
+ prStatus = PR_GetHostByName(hostName, buffer, 256, &hostEntry);
+ if (prStatus != PR_SUCCESS) {
+ exitErr("PR_GetHostByName");
+ }
+
+ rv = PR_EnumerateHostEnt(0, &hostEntry, port, &addr);
+ if (rv < 0) {
+ exitErr("PR_EnumerateHostEnt");
+ }
+
+ secStatus = launch_thread(&threadMGR, do_connects, &addr, 1);
+ if (secStatus != SECSuccess) {
+ exitErr("launch_thread");
+ }
+
+ if (connections > 1) {
+ /* wait for the first connection to terminate, then launch the rest. */
+ reap_threads(&threadMGR);
+ /* Start up the connections */
+ for (i = 2; i <= connections; ++i) {
+ secStatus = launch_thread(&threadMGR, do_connects, &addr, i);
+ if (secStatus != SECSuccess) {
+ errWarn("launch_thread");
+ }
+ }
+ }
+
+ reap_threads(&threadMGR);
+ destroy_thread_data(&threadMGR);
+}
+
+int
+main(int argc, char **argv)
+{
+ char * certDir = NULL;
+ char * progName = NULL;
+ int connections = 1;
+ char * cipherString = NULL;
+ SECStatus secStatus;
+ PLOptState * optstate;
+ PLOptStatus status;
+
+ /* Call the NSPR initialization routines */
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ progName = PORT_Strdup(argv[0]);
+
+ hostName = NULL;
+ optstate = PL_CreateOptState(argc, argv, "C:c:d:n:p:w:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch(optstate->option) {
+ case 'C' : cipherString = PL_strdup(optstate->value); break;
+ case 'c' : connections = PORT_Atoi(optstate->value); break;
+ case 'd' : certDir = PL_strdup(optstate->value); break;
+ case 'p' : port = PORT_Atoi(optstate->value); break;
+ case 'w' : password = PL_strdup(optstate->value); break;
+ case '\0': hostName = PL_strdup(optstate->value); break;
+ default : Usage(progName);
+ }
+ }
+
+ if (port == 0) {
+ port = 443;
+ }
+
+ if (port == 0 || hostName == NULL)
+ Usage(progName);
+
+ /* Set our password function callback. */
+ PK11_SetPasswordFunc(myPasswd);
+
+ /* Initialize the NSS libraries. */
+ if (certDir) {
+ secStatus = NSS_Init(certDir);
+ } else {
+ secStatus = NSS_NoDB_Init(NULL);
+
+ /* load the builtins */
+ SECMOD_AddNewModule("Builtins",
+ DLL_PREFIX"nssckbi."DLL_SUFFIX, 0, 0);
+ }
+ if (secStatus != SECSuccess) {
+ exitErr("NSS_Init");
+ }
+
+ /* All cipher suites except RSA_NULL_MD5 are enabled by
+ * Domestic Policy. */
+ NSS_SetDomesticPolicy();
+ SSL_CipherPrefSetDefault(SSL_RSA_WITH_NULL_MD5, PR_TRUE);
+
+ /* all the SSL2 and SSL3 cipher suites are enabled by default. */
+ if (cipherString) {
+ int ndx;
+
+ /* disable all the ciphers, then enable the ones we want. */
+ disableAllSSLCiphers();
+
+ while (0 != (ndx = *cipherString++)) {
+ int *cptr;
+ int cipher;
+
+ if (! isalpha(ndx))
+ Usage(progName);
+ cptr = islower(ndx) ? ssl3CipherSuites : ssl2CipherSuites;
+ for (ndx &= 0x1f; (cipher = *cptr++) != 0 && --ndx > 0; )
+ /* do nothing */;
+ if (cipher) {
+ SSL_CipherPrefSetDefault(cipher, PR_TRUE);
+ }
+ }
+ }
+
+ client_main(port, connections, hostName);
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ PR_Cleanup();
+ PORT_Free(progName);
+ return 0;
+}
+
diff --git a/security/nss/cmd/vfyserv/vfyserv.h b/security/nss/cmd/vfyserv/vfyserv.h
new file mode 100644
index 000000000..e23b5e779
--- /dev/null
+++ b/security/nss/cmd/vfyserv/vfyserv.h
@@ -0,0 +1,182 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#ifndef SSLSAMPLE_H
+#define SSLSAMPLE_H
+
+/* Generic header files */
+
+#include <stdio.h>
+#include <string.h>
+
+/* NSPR header files */
+
+#include "nspr.h"
+#include "prerror.h"
+#include "prnetdb.h"
+
+/* NSS header files */
+
+#include "pk11func.h"
+#include "secitem.h"
+#include "ssl.h"
+#include "certt.h"
+#include "nss.h"
+#include "secrng.h"
+#include "secder.h"
+#include "key.h"
+#include "sslproto.h"
+
+/* Custom header files */
+
+/*
+#include "sslerror.h"
+*/
+
+#define BUFFER_SIZE 10240
+
+/* Declare SSL cipher suites. */
+
+extern int cipherSuites[];
+extern int ssl2CipherSuites[];
+extern int ssl3CipherSuites[];
+
+/* Data buffer read from a socket. */
+typedef struct DataBufferStr {
+ char data[BUFFER_SIZE];
+ int index;
+ int remaining;
+ int dataStart;
+ int dataEnd;
+} DataBuffer;
+
+/* SSL callback routines. */
+
+char * myPasswd(PK11SlotInfo *info, PRBool retry, void *arg);
+
+SECStatus myAuthCertificate(void *arg, PRFileDesc *socket,
+ PRBool checksig, PRBool isServer);
+
+SECStatus myBadCertHandler(void *arg, PRFileDesc *socket);
+
+SECStatus myHandshakeCallback(PRFileDesc *socket, void *arg);
+
+SECStatus myGetClientAuthData(void *arg, PRFileDesc *socket,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey);
+
+/* Disable all v2/v3 SSL ciphers. */
+
+void disableAllSSLCiphers(void);
+
+
+/* Error and information utilities. */
+
+void errWarn(char *function);
+
+void exitErr(char *function);
+
+void printSecurityInfo(FILE *outfile, PRFileDesc *fd);
+
+void printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig,
+ SECCertUsage certUsage, void *pinArg);
+
+/* Some simple thread management routines. */
+
+#define MAX_THREADS 32
+
+typedef SECStatus startFn(void *a, int b);
+
+typedef enum { rs_idle = 0, rs_running = 1, rs_zombie = 2 } runState;
+
+typedef struct perThreadStr {
+ PRFileDesc *a;
+ int b;
+ int rv;
+ startFn *startFunc;
+ PRThread *prThread;
+ PRBool inUse;
+ runState running;
+} perThread;
+
+typedef struct GlobalThreadMgrStr {
+ PRLock *threadLock;
+ PRCondVar *threadStartQ;
+ PRCondVar *threadEndQ;
+ perThread threads[MAX_THREADS];
+ int index;
+ int numUsed;
+ int numRunning;
+} GlobalThreadMgr;
+
+void thread_wrapper(void * arg);
+
+SECStatus launch_thread(GlobalThreadMgr *threadMGR,
+ startFn *startFunc, void *a, int b);
+
+SECStatus reap_threads(GlobalThreadMgr *threadMGR);
+
+void destroy_thread_data(GlobalThreadMgr *threadMGR);
+
+/* Management of locked variables. */
+
+struct lockedVarsStr {
+ PRLock * lock;
+ int count;
+ int waiters;
+ PRCondVar * condVar;
+};
+
+typedef struct lockedVarsStr lockedVars;
+
+void lockedVars_Init(lockedVars *lv);
+
+void lockedVars_Destroy(lockedVars *lv);
+
+void lockedVars_WaitForDone(lockedVars *lv);
+
+int lockedVars_AddToCount(lockedVars *lv, int addend);
+
+/* Buffer stuff. */
+
+static const char stopCmd[] = { "GET /stop " };
+static const char defaultHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: SSL sample server\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+};
+
+#endif
diff --git a/security/nss/cmd/vfyserv/vfyutil.c b/security/nss/cmd/vfyserv/vfyutil.c
new file mode 100644
index 000000000..10e393458
--- /dev/null
+++ b/security/nss/cmd/vfyserv/vfyutil.c
@@ -0,0 +1,714 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "vfyserv.h"
+#include "secerr.h"
+#include "sslerr.h"
+#include "nspr.h"
+#include "secutil.h"
+
+/* Declare SSL cipher suites. */
+
+int ssl2CipherSuites[] = {
+ SSL_EN_RC4_128_WITH_MD5, /* A */
+ SSL_EN_RC4_128_EXPORT40_WITH_MD5, /* B */
+ SSL_EN_RC2_128_CBC_WITH_MD5, /* C */
+ SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, /* D */
+ SSL_EN_DES_64_CBC_WITH_MD5, /* E */
+ SSL_EN_DES_192_EDE3_CBC_WITH_MD5, /* F */
+ 0
+};
+
+int ssl3CipherSuites[] = {
+ SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* a */
+ SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, /* b */
+ SSL_RSA_WITH_RC4_128_MD5, /* c */
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA, /* d */
+ SSL_RSA_WITH_DES_CBC_SHA, /* e */
+ SSL_RSA_EXPORT_WITH_RC4_40_MD5, /* f */
+ SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* g */
+ SSL_FORTEZZA_DMS_WITH_NULL_SHA, /* h */
+ SSL_RSA_WITH_NULL_MD5, /* i */
+ SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, /* j */
+ SSL_RSA_FIPS_WITH_DES_CBC_SHA, /* k */
+ TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, /* l */
+ TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, /* m */
+ SSL_RSA_WITH_RC4_128_SHA, /* n */
+ TLS_DHE_DSS_WITH_RC4_128_SHA, /* o */
+ SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* p */
+ SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* q */
+ SSL_DHE_RSA_WITH_DES_CBC_SHA, /* r */
+ SSL_DHE_DSS_WITH_DES_CBC_SHA, /* s */
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* t */
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* u */
+ TLS_RSA_WITH_AES_128_CBC_SHA, /* v */
+ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* w */
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* x */
+ TLS_RSA_WITH_AES_256_CBC_SHA, /* y */
+ SSL_RSA_WITH_NULL_SHA, /* z */
+ 0
+};
+
+/**************************************************************************
+**
+** SSL callback routines.
+**
+**************************************************************************/
+
+/* Function: char * myPasswd()
+ *
+ * Purpose: This function is our custom password handler that is called by
+ * SSL when retreiving private certs and keys from the database. Returns a
+ * pointer to a string that with a password for the database. Password pointer
+ * should point to dynamically allocated memory that will be freed later.
+ */
+char *
+myPasswd(PK11SlotInfo *info, PRBool retry, void *arg)
+{
+ char * passwd = NULL;
+
+ if ( (!retry) && arg ) {
+ passwd = PORT_Strdup((char *)arg);
+ }
+ return passwd;
+}
+
+/* Function: SECStatus myAuthCertificate()
+ *
+ * Purpose: This function is our custom certificate authentication handler.
+ *
+ * Note: This implementation is essentially the same as the default
+ * SSL_AuthCertificate().
+ */
+SECStatus
+myAuthCertificate(void *arg, PRFileDesc *socket,
+ PRBool checksig, PRBool isServer)
+{
+
+ SECCertUsage certUsage;
+ CERTCertificate * cert;
+ void * pinArg;
+ char * hostName;
+ SECStatus secStatus;
+
+ if (!arg || !socket) {
+ errWarn("myAuthCertificate");
+ return SECFailure;
+ }
+
+ /* Define how the cert is being used based upon the isServer flag. */
+
+ certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
+
+ cert = SSL_PeerCertificate(socket);
+
+ pinArg = SSL_RevealPinArg(socket);
+
+ secStatus = CERT_VerifyCertNow((CERTCertDBHandle *)arg,
+ cert,
+ checksig,
+ certUsage,
+ pinArg);
+
+ /* If this is a server, we're finished. */
+ if (isServer || secStatus != SECSuccess) {
+ printCertProblems(stderr, (CERTCertDBHandle *)arg, cert,
+ checksig, certUsage, pinArg);
+ CERT_DestroyCertificate(cert);
+ return secStatus;
+ }
+
+ /* Certificate is OK. Since this is the client side of an SSL
+ * connection, we need to verify that the name field in the cert
+ * matches the desired hostname. This is our defense against
+ * man-in-the-middle attacks.
+ */
+
+ /* SSL_RevealURL returns a hostName, not an URL. */
+ hostName = SSL_RevealURL(socket);
+
+ if (hostName && hostName[0]) {
+ secStatus = CERT_VerifyCertName(cert, hostName);
+ } else {
+ PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0);
+ secStatus = SECFailure;
+ }
+
+ if (hostName)
+ PR_Free(hostName);
+
+ CERT_DestroyCertificate(cert);
+ return secStatus;
+}
+
+/* Function: SECStatus myBadCertHandler()
+ *
+ * Purpose: This callback is called when the incoming certificate is not
+ * valid. We define a certain set of parameters that still cause the
+ * certificate to be "valid" for this session, and return SECSuccess to cause
+ * the server to continue processing the request when any of these conditions
+ * are met. Otherwise, SECFailure is return and the server rejects the
+ * request.
+ */
+SECStatus
+myBadCertHandler(void *arg, PRFileDesc *socket)
+{
+
+ SECStatus secStatus = SECFailure;
+ PRErrorCode err;
+
+ /* log invalid cert here */
+
+ if (!arg) {
+ return secStatus;
+ }
+
+ *(PRErrorCode *)arg = err = PORT_GetError();
+
+ /* If any of the cases in the switch are met, then we will proceed */
+ /* with the processing of the request anyway. Otherwise, the default */
+ /* case will be reached and we will reject the request. */
+
+ switch (err) {
+ case SEC_ERROR_INVALID_AVA:
+ case SEC_ERROR_INVALID_TIME:
+ case SEC_ERROR_BAD_SIGNATURE:
+ case SEC_ERROR_EXPIRED_CERTIFICATE:
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ case SEC_ERROR_UNTRUSTED_CERT:
+ case SEC_ERROR_CERT_VALID:
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ case SEC_ERROR_CRL_EXPIRED:
+ case SEC_ERROR_CRL_BAD_SIGNATURE:
+ case SEC_ERROR_EXTENSION_VALUE_INVALID:
+ case SEC_ERROR_CA_CERT_INVALID:
+ case SEC_ERROR_CERT_USAGES_INVALID:
+ case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:
+ secStatus = SECSuccess;
+ break;
+ default:
+ secStatus = SECFailure;
+ break;
+ }
+
+ fprintf(stderr, "Bad certificate: %d, %s\n", err, SECU_Strerror(err));
+
+ return secStatus;
+}
+
+/* Function: SECStatus ownGetClientAuthData()
+ *
+ * Purpose: This callback is used by SSL to pull client certificate
+ * information upon server request.
+ */
+SECStatus
+myGetClientAuthData(void *arg,
+ PRFileDesc *socket,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+
+ CERTCertificate * cert;
+ SECKEYPrivateKey * privKey;
+ char * chosenNickName = (char *)arg;
+ void * proto_win = NULL;
+ SECStatus secStatus = SECFailure;
+
+ proto_win = SSL_RevealPinArg(socket);
+
+ if (chosenNickName) {
+ cert = PK11_FindCertFromNickname(chosenNickName, proto_win);
+ if (cert) {
+ privKey = PK11_FindKeyByAnyCert(cert, proto_win);
+ if (privKey) {
+ secStatus = SECSuccess;
+ } else {
+ CERT_DestroyCertificate(cert);
+ }
+ }
+ } else { /* no nickname given, automatically find the right cert */
+ CERTCertNicknames *names;
+ int i;
+
+ names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
+ SEC_CERT_NICKNAMES_USER, proto_win);
+
+ if (names != NULL) {
+ for(i = 0; i < names->numnicknames; i++ ) {
+
+ cert = PK11_FindCertFromNickname(names->nicknames[i],
+ proto_win);
+ if (!cert) {
+ continue;
+ }
+
+ /* Only check unexpired certs */
+ if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE)
+ != secCertTimeValid ) {
+ CERT_DestroyCertificate(cert);
+ continue;
+ }
+
+ secStatus = NSS_CmpCertChainWCANames(cert, caNames);
+ if (secStatus == SECSuccess) {
+ privKey = PK11_FindKeyByAnyCert(cert, proto_win);
+ if (privKey) {
+ break;
+ }
+ secStatus = SECFailure;
+ break;
+ }
+ CERT_FreeNicknames(names);
+ } /* for loop */
+ }
+ }
+
+ if (secStatus == SECSuccess) {
+ *pRetCert = cert;
+ *pRetKey = privKey;
+ }
+
+ return secStatus;
+}
+
+/* Function: SECStatus myHandshakeCallback()
+ *
+ * Purpose: Called by SSL to inform application that the handshake is
+ * complete. This function is mostly used on the server side of an SSL
+ * connection, although it is provided for a client as well.
+ * Useful when a non-blocking SSL_ReHandshake or SSL_ResetHandshake
+ * is used to initiate a handshake.
+ *
+ * A typical scenario would be:
+ *
+ * 1. Server accepts an SSL connection from the client without client auth.
+ * 2. Client sends a request.
+ * 3. Server determines that to service request it needs to authenticate the
+ * client and initiates another handshake requesting client auth.
+ * 4. While handshake is in progress, server can do other work or spin waiting
+ * for the handshake to complete.
+ * 5. Server is notified that handshake has been successfully completed by
+ * the custom handshake callback function and it can service the client's
+ * request.
+ *
+ * Note: This function is not implemented in this sample, as we are using
+ * blocking sockets.
+ */
+SECStatus
+myHandshakeCallback(PRFileDesc *socket, void *arg)
+{
+ fprintf(stderr,"Handshake Complete: SERVER CONFIGURED CORRECTLY\n");
+ return SECSuccess;
+}
+
+
+/**************************************************************************
+**
+** Routines for disabling SSL ciphers.
+**
+**************************************************************************/
+
+void
+disableAllSSLCiphers(void)
+{
+ const PRUint16 *cipherSuites = SSL_ImplementedCiphers;
+ int i = SSL_NumImplementedCiphers;
+ SECStatus rv;
+
+ /* disable all the SSL3 cipher suites */
+ while (--i >= 0) {
+ PRUint16 suite = cipherSuites[i];
+ rv = SSL_CipherPrefSetDefault(suite, PR_FALSE);
+ if (rv != SECSuccess) {
+ fprintf(stderr,
+ "SSL_CipherPrefSetDefault didn't like value 0x%04x (i = %d)\n",
+ suite, i);
+ errWarn("SSL_CipherPrefSetDefault");
+ exit(2);
+ }
+ }
+}
+
+/**************************************************************************
+**
+** Error and information routines.
+**
+**************************************************************************/
+
+void
+errWarn(char *function)
+{
+ PRErrorCode errorNumber = PR_GetError();
+ const char * errorString = SECU_Strerror(errorNumber);
+
+ fprintf(stderr, "Error in function %s: %d\n - %s\n",
+ function, errorNumber, errorString);
+}
+
+void
+exitErr(char *function)
+{
+ errWarn(function);
+ /* Exit gracefully. */
+ /* ignoring return value of NSS_Shutdown as code exits with 1 anyway*/
+ (void) NSS_Shutdown();
+ PR_Cleanup();
+ exit(1);
+}
+
+void
+printSecurityInfo(FILE *outfile, PRFileDesc *fd)
+{
+ char * cp; /* bulk cipher name */
+ char * ip; /* cert issuer DN */
+ char * sp; /* cert subject DN */
+ int op; /* High, Low, Off */
+ int kp0; /* total key bits */
+ int kp1; /* secret key bits */
+ int result;
+ SSL3Statistics * ssl3stats = SSL_GetStatistics();
+
+ if (!outfile) {
+ outfile = stdout;
+ }
+
+ result = SSL_SecurityStatus(fd, &op, &cp, &kp0, &kp1, &ip, &sp);
+ if (result != SECSuccess)
+ return;
+ fprintf(outfile,
+ " bulk cipher %s, %d secret key bits, %d key bits, status: %d\n"
+ " subject DN:\n %s\n"
+ " issuer DN:\n %s\n", cp, kp1, kp0, op, sp, ip);
+ PR_Free(cp);
+ PR_Free(ip);
+ PR_Free(sp);
+
+ fprintf(outfile,
+ " %ld cache hits; %ld cache misses, %ld cache not reusable\n",
+ ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses,
+ ssl3stats->hch_sid_cache_not_ok);
+
+}
+
+
+/**************************************************************************
+** Begin thread management routines and data.
+**************************************************************************/
+
+void
+thread_wrapper(void * arg)
+{
+ GlobalThreadMgr *threadMGR = (GlobalThreadMgr *)arg;
+ perThread *slot = &threadMGR->threads[threadMGR->index];
+
+ /* wait for parent to finish launching us before proceeding. */
+ PR_Lock(threadMGR->threadLock);
+ PR_Unlock(threadMGR->threadLock);
+
+ slot->rv = (* slot->startFunc)(slot->a, slot->b);
+
+ PR_Lock(threadMGR->threadLock);
+ slot->running = rs_zombie;
+
+ /* notify the thread exit handler. */
+ PR_NotifyCondVar(threadMGR->threadEndQ);
+
+ PR_Unlock(threadMGR->threadLock);
+}
+
+SECStatus
+launch_thread(GlobalThreadMgr *threadMGR,
+ startFn *startFunc,
+ void *a,
+ int b)
+{
+ perThread *slot;
+ int i;
+
+ if (!threadMGR->threadStartQ) {
+ threadMGR->threadLock = PR_NewLock();
+ threadMGR->threadStartQ = PR_NewCondVar(threadMGR->threadLock);
+ threadMGR->threadEndQ = PR_NewCondVar(threadMGR->threadLock);
+ }
+ PR_Lock(threadMGR->threadLock);
+ while (threadMGR->numRunning >= MAX_THREADS) {
+ PR_WaitCondVar(threadMGR->threadStartQ, PR_INTERVAL_NO_TIMEOUT);
+ }
+ for (i = 0; i < threadMGR->numUsed; ++i) {
+ slot = &threadMGR->threads[i];
+ if (slot->running == rs_idle)
+ break;
+ }
+ if (i >= threadMGR->numUsed) {
+ if (i >= MAX_THREADS) {
+ /* something's really wrong here. */
+ PORT_Assert(i < MAX_THREADS);
+ PR_Unlock(threadMGR->threadLock);
+ return SECFailure;
+ }
+ ++(threadMGR->numUsed);
+ PORT_Assert(threadMGR->numUsed == i + 1);
+ slot = &threadMGR->threads[i];
+ }
+
+ slot->a = a;
+ slot->b = b;
+ slot->startFunc = startFunc;
+
+ threadMGR->index = i;
+
+ slot->prThread = PR_CreateThread(PR_USER_THREAD,
+ thread_wrapper, threadMGR,
+ PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD, 0);
+
+ if (slot->prThread == NULL) {
+ PR_Unlock(threadMGR->threadLock);
+ printf("Failed to launch thread!\n");
+ return SECFailure;
+ }
+
+ slot->inUse = 1;
+ slot->running = 1;
+ ++(threadMGR->numRunning);
+ PR_Unlock(threadMGR->threadLock);
+
+ return SECSuccess;
+}
+
+SECStatus
+reap_threads(GlobalThreadMgr *threadMGR)
+{
+ perThread * slot;
+ int i;
+
+ if (!threadMGR->threadLock)
+ return SECSuccess;
+ PR_Lock(threadMGR->threadLock);
+ while (threadMGR->numRunning > 0) {
+ PR_WaitCondVar(threadMGR->threadEndQ, PR_INTERVAL_NO_TIMEOUT);
+ for (i = 0; i < threadMGR->numUsed; ++i) {
+ slot = &threadMGR->threads[i];
+ if (slot->running == rs_zombie) {
+ /* Handle cleanup of thread here. */
+
+ /* Now make sure the thread has ended OK. */
+ PR_JoinThread(slot->prThread);
+ slot->running = rs_idle;
+ --threadMGR->numRunning;
+
+ /* notify the thread launcher. */
+ PR_NotifyCondVar(threadMGR->threadStartQ);
+ }
+ }
+ }
+
+ /* Safety Sam sez: make sure count is right. */
+ for (i = 0; i < threadMGR->numUsed; ++i) {
+ slot = &threadMGR->threads[i];
+ if (slot->running != rs_idle) {
+ fprintf(stderr, "Thread in slot %d is in state %d!\n",
+ i, slot->running);
+ }
+ }
+ PR_Unlock(threadMGR->threadLock);
+ return SECSuccess;
+}
+
+void
+destroy_thread_data(GlobalThreadMgr *threadMGR)
+{
+ PORT_Memset(threadMGR->threads, 0, sizeof(threadMGR->threads));
+
+ if (threadMGR->threadEndQ) {
+ PR_DestroyCondVar(threadMGR->threadEndQ);
+ threadMGR->threadEndQ = NULL;
+ }
+ if (threadMGR->threadStartQ) {
+ PR_DestroyCondVar(threadMGR->threadStartQ);
+ threadMGR->threadStartQ = NULL;
+ }
+ if (threadMGR->threadLock) {
+ PR_DestroyLock(threadMGR->threadLock);
+ threadMGR->threadLock = NULL;
+ }
+}
+
+/**************************************************************************
+** End thread management routines.
+**************************************************************************/
+
+void
+lockedVars_Init( lockedVars * lv)
+{
+ lv->count = 0;
+ lv->waiters = 0;
+ lv->lock = PR_NewLock();
+ lv->condVar = PR_NewCondVar(lv->lock);
+}
+
+void
+lockedVars_Destroy( lockedVars * lv)
+{
+ PR_DestroyCondVar(lv->condVar);
+ lv->condVar = NULL;
+
+ PR_DestroyLock(lv->lock);
+ lv->lock = NULL;
+}
+
+void
+lockedVars_WaitForDone(lockedVars * lv)
+{
+ PR_Lock(lv->lock);
+ while (lv->count > 0) {
+ PR_WaitCondVar(lv->condVar, PR_INTERVAL_NO_TIMEOUT);
+ }
+ PR_Unlock(lv->lock);
+}
+
+int /* returns count */
+lockedVars_AddToCount(lockedVars * lv, int addend)
+{
+ int rv;
+
+ PR_Lock(lv->lock);
+ rv = lv->count += addend;
+ if (rv <= 0) {
+ PR_NotifyCondVar(lv->condVar);
+ }
+ PR_Unlock(lv->lock);
+ return rv;
+}
+
+static char *
+bestCertName(CERTCertificate *cert) {
+ if (cert->nickname) {
+ return cert->nickname;
+ }
+ if (cert->emailAddr) {
+ return cert->emailAddr;
+ }
+ return cert->subjectName;
+}
+
+void
+printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig,
+ SECCertUsage certUsage, void *pinArg)
+{
+ CERTVerifyLog log;
+ CERTVerifyLogNode *node = NULL;
+ unsigned int depth = (unsigned int)-1;
+ unsigned int flags = 0;
+ char * errstr = NULL;
+ PRErrorCode err = PORT_GetError();
+
+ log.arena = PORT_NewArena(512);
+ log.head = log.tail = NULL;
+ log.count = 0;
+ CERT_VerifyCert(handle, cert, checksig, certUsage,
+ PR_Now(), pinArg, &log);
+
+ if (log.count > 0) {
+ fprintf(outfile,"PROBLEM WITH THE CERT CHAIN:\n");
+ for (node = log.head; node; node = node->next) {
+ if (depth != node->depth) {
+ depth = node->depth;
+ fprintf(outfile,"CERT %d. %s %s:\n", depth,
+ bestCertName(node->cert),
+ depth ? "[Certificate Authority]": "");
+ }
+ fprintf(outfile," ERROR %d: %s\n", node->error,
+ SECU_Strerror(node->error));
+ errstr = NULL;
+ switch (node->error) {
+ case SEC_ERROR_INADEQUATE_KEY_USAGE:
+ flags = (unsigned int)node->arg;
+ switch (flags) {
+ case KU_DIGITAL_SIGNATURE:
+ errstr = "Cert cannot sign.";
+ break;
+ case KU_KEY_ENCIPHERMENT:
+ errstr = "Cert cannot encrypt.";
+ break;
+ case KU_KEY_CERT_SIGN:
+ errstr = "Cert cannot sign other certs.";
+ break;
+ default:
+ errstr = "[unknown usage].";
+ break;
+ }
+ case SEC_ERROR_INADEQUATE_CERT_TYPE:
+ flags = (unsigned int)node->arg;
+ switch (flags) {
+ case NS_CERT_TYPE_SSL_CLIENT:
+ case NS_CERT_TYPE_SSL_SERVER:
+ errstr = "Cert cannot be used for SSL.";
+ break;
+ case NS_CERT_TYPE_SSL_CA:
+ errstr = "Cert cannot be used as an SSL CA.";
+ break;
+ case NS_CERT_TYPE_EMAIL:
+ errstr = "Cert cannot be used for SMIME.";
+ break;
+ case NS_CERT_TYPE_EMAIL_CA:
+ errstr = "Cert cannot be used as an SMIME CA.";
+ break;
+ case NS_CERT_TYPE_OBJECT_SIGNING:
+ errstr = "Cert cannot be used for object signing.";
+ break;
+ case NS_CERT_TYPE_OBJECT_SIGNING_CA:
+ errstr = "Cert cannot be used as an object signing CA.";
+ break;
+ default:
+ errstr = "[unknown usage].";
+ break;
+ }
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ case SEC_ERROR_UNTRUSTED_ISSUER:
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ errstr = node->cert->issuerName;
+ break;
+ default:
+ break;
+ }
+ if (errstr) {
+ fprintf(stderr," %s\n",errstr);
+ }
+ CERT_DestroyCertificate(node->cert);
+ }
+ }
+ PR_SetError(err, 0); /* restore original error code */
+}
diff --git a/security/nss/cmd/zlib/Makefile b/security/nss/cmd/zlib/Makefile
new file mode 100644
index 000000000..fa46e6763
--- /dev/null
+++ b/security/nss/cmd/zlib/Makefile
@@ -0,0 +1,75 @@
+#! gmake
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include config.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
diff --git a/security/nss/cmd/zlib/README b/security/nss/cmd/zlib/README
new file mode 100644
index 000000000..28adc90b2
--- /dev/null
+++ b/security/nss/cmd/zlib/README
@@ -0,0 +1,99 @@
+zlib 1.0.4 is a general purpose data compression library. All the code
+is reentrant (thread safe). The data format used by the zlib library
+is described by RFCs (Request for Comments) 1950 to 1952 in the files
+ftp://ds.internic.net/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate
+format) and rfc1952.txt (gzip format). These documents are also available in
+other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
+
+All functions of the compression library are documented in the file
+zlib.h. A usage example of the library is given in the file example.c
+which also tests that the library is working correctly. Another
+example is given in the file minigzip.c. The compression library itself
+is composed of all source files except example.c and minigzip.c.
+
+To compile all files and run the test program, follow the instructions
+given at the top of Makefile. In short "make test; make install"
+should work for most machines. For MSDOS, use one of the special
+makefiles such as Makefile.msc; for VMS, use Make_vms.com or descrip.mms.
+
+Questions about zlib should be sent to <zlib@quest.jpl.nasa.gov> or,
+if this fails, to the addresses given below in the Copyright section.
+The zlib home page is http://quest.jpl.nasa.gov/zlib/
+
+The changes made in version 1.0.4 are documented in the file ChangeLog.
+The main changes since 1.0.3 are:
+
+- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
+ bit, so the decompressor could decompress all the correct data but went
+ on to attempt decompressing extra garbage data. This affected minigzip too.
+- zlibVersion and gzerror return const char* (needed for DLL)
+- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
+
+
+A Perl interface to zlib written by Paul Marquess <pmarquess@bfsec.bt.co.uk>
+is in the CPAN (Comprehensive Perl Archive Network) sites, such as:
+ftp://ftp.cis.ufl.edu/pub/perl/CPAN/modules/by-module/Compress/Compress-Zlib*
+
+
+Notes for some targets:
+
+- For Turbo C the small model is supported only with reduced performance to
+ avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
+
+- For 64-bit Iris, deflate.c must be compiled without any optimization.
+ With -O, one libpng test fails. The test works in 32 bit mode (with
+ the -32 compiler flag). The compiler bug has been reported to SGI.
+
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1
+ it works when compiled with cc.
+
+- zlib doesn't work on HP-UX 9.05 with one cc compiler (the one not
+ accepting the -O option). It works with the other cc compiler.
+
+- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc
+ and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL
+ For help on building a zlib DLL, contact Alessandro Iacopetti
+ <iaco@email.alessandria.alpcom.it> http://lisa.unial.it/iaco ,
+ or contact Brad Clarke <bclarke@cyberus.ca>.
+
+- gzdopen is not supported on RISCOS
+
+
+Acknowledgments:
+
+ The deflate format used by zlib was defined by Phil Katz. The deflate
+ and zlib specifications were written by Peter Deutsch. Thanks to all the
+ people who reported problems and suggested various improvements in zlib;
+ they are too numerous to cite here.
+
+Copyright notice:
+
+ (C) 1995-1996 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ gzip@prep.ai.mit.edu madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not*
+receiving lengthy legal documents to sign. The sources are provided
+for free but without warranty of any kind. The library has been
+entirely written by Jean-loup Gailly and Mark Adler; it does not
+include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include
+in the file ChangeLog history information documenting your changes.
diff --git a/security/nss/cmd/zlib/adler32.c b/security/nss/cmd/zlib/adler32.c
new file mode 100644
index 000000000..9f4afd63c
--- /dev/null
+++ b/security/nss/cmd/zlib/adler32.c
@@ -0,0 +1,48 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+/* $Id$ */
+
+#include "zlib.h"
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+PR_PUBLIC_API(uLong) adler32(adler, buf, len)
+ uLong adler;
+ const Bytef *buf;
+ uInt len;
+{
+ unsigned long s1 = adler & 0xffff;
+ unsigned long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ if (buf == Z_NULL) return 1L;
+
+ while (len > 0) {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16) {
+ DO16(buf);
+ buf += 16;
+ k -= 16;
+ }
+ if (k != 0) do {
+ s1 += *buf++;
+ s2 += s1;
+ } while (--k);
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+}
diff --git a/security/nss/cmd/zlib/compress.c b/security/nss/cmd/zlib/compress.c
new file mode 100644
index 000000000..3e1cc7c09
--- /dev/null
+++ b/security/nss/cmd/zlib/compress.c
@@ -0,0 +1,57 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+/* $Id$ */
+
+#include "zlib.h"
+
+/* ===========================================================================
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least 0.1% larger than
+ sourceLen plus 8 bytes. Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+PR_PUBLIC_API(int) compress (dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
+ if (err != Z_OK) return err;
+
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = deflateEnd(&stream);
+ return err;
+}
diff --git a/security/nss/cmd/zlib/config.mk b/security/nss/cmd/zlib/config.mk
new file mode 100644
index 000000000..a1c67fdb4
--- /dev/null
+++ b/security/nss/cmd/zlib/config.mk
@@ -0,0 +1,70 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+#
+# Currently, override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(LIBRARY)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+PROGRAM =
+
+#######################################################################
+# Set the LDFLAGS value to encompass all normal link options, all #
+# library names, and all special system linking options #
+#######################################################################
+
+SECTOOLS_LIBS = $(LDOPTS) $(LIBSSL) $(LIBPKCS7) $(LIBCERT) $(LIBKEY) \
+ $(LIBSECMOD) $(LIBCRYPTO) $(LIBSECUTIL) $(LIBSECMOD) $(LIBSSL) \
+ $(LIBPKCS7) $(LIBCERT) $(LIBKEY) $(LIBCRYPTO) $(LIBSECUTIL) \
+ $(LIBHASH) $(LIBDBM) $(DLLPLC) $(DLLPLDS) $(DLLPR) $(DLLSYSTEM)
+
+ifeq ($(OS_TARGET),AIX)
+ OS_LIBS += $(SECTOOLS_LIBS)
+endif
+
+ifeq ($(OS_TARGET),NCR)
+ OS_LIBS += $(SECTOOLS_LIBS)
+endif
+
+ifeq ($(OS_TARGET),SCO_SV)
+ OS_LIBS += $(SECTOOLS_LIBS)
+endif
+
+LDFLAGS += $(SECTOOLS_LIBS)
+
+
+
+
diff --git a/security/nss/cmd/zlib/crc32.c b/security/nss/cmd/zlib/crc32.c
new file mode 100644
index 000000000..398871cf8
--- /dev/null
+++ b/security/nss/cmd/zlib/crc32.c
@@ -0,0 +1,162 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+/* $Id$ */
+
+#include "zlib.h"
+
+#define local static
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local int crc_table_empty = 1;
+local uLongf crc_table[256];
+local void make_crc_table OF((void));
+
+/*
+ Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+ x (which is shifting right by one and adding x^32 mod p if the bit shifted
+ out is a one). We start with the highest power (least significant bit) of
+ q and repeat for all eight bits of q.
+
+ The table is simply the CRC of all possible eight bit values. This is all
+ the information needed to generate CRC's on data a byte at a time for all
+ combinations of CRC register values and incoming bytes.
+*/
+local void make_crc_table()
+{
+ uLong c;
+ int n, k;
+ uLong poly; /* polynomial exclusive-or pattern */
+ /* terms of polynomial defining this crc (except x^32): */
+ static Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+ /* make exclusive-or pattern from polynomial (0xedb88320L) */
+ poly = 0L;
+ for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
+ poly |= 1L << (31 - p[n]);
+
+ for (n = 0; n < 256; n++)
+ {
+ c = (uLong)n;
+ for (k = 0; k < 8; k++)
+ c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+ crc_table[n] = c;
+ }
+ crc_table_empty = 0;
+}
+#else
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+local uLongf crc_table[256] = {
+ 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+ 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+ 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+ 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+ 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+ 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+ 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+ 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+ 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+ 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+ 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+ 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+ 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+ 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+ 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+ 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+ 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+ 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+ 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+ 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+ 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+ 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+ 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+ 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+ 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+ 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+ 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+ 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+ 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+ 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+ 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+ 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+ 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+ 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+ 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+ 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+ 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+ 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+ 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+ 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+ 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+ 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+ 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+ 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+ 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+ 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+ 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+ 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+ 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+ 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+ 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+ 0x2d02ef8dL
+};
+#endif
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+uLongf *get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty) make_crc_table();
+#endif
+ return (uLongf *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
+#define DO2(buf) DO1(buf); DO1(buf);
+#define DO4(buf) DO2(buf); DO2(buf);
+#define DO8(buf) DO4(buf); DO4(buf);
+
+/* ========================================================================= */
+PR_PUBLIC_API(uLong) crc32(crc, buf, len)
+ uLong crc;
+ const Bytef *buf;
+ uInt len;
+{
+ if (buf == Z_NULL) return 0L;
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif
+ crc = crc ^ 0xffffffffUL;
+ while (len >= 8)
+ {
+ DO8(buf);
+ len -= 8;
+ }
+ if (len) do {
+ DO1(buf);
+ } while (--len);
+ return crc ^ 0xffffffffUL;
+}
diff --git a/security/nss/cmd/zlib/deflate.c b/security/nss/cmd/zlib/deflate.c
new file mode 100644
index 000000000..f748ce156
--- /dev/null
+++ b/security/nss/cmd/zlib/deflate.c
@@ -0,0 +1,1209 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* $Id$ */
+
+#include "deflate.h"
+
+char deflate_copyright[] = " deflate 1.0.4 Copyright 1995-1996 Jean-loup Gailly ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ * Function prototypes.
+ */
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast OF((deflate_state *s, int flush));
+local block_state deflate_slow OF((deflate_state *s, int flush));
+local void lm_init OF((deflate_state *s));
+local uInt longest_match OF((deflate_state *s, IPos cur_match));
+local void putShortMSB OF((deflate_state *s, uInt b));
+local void flush_pending OF((z_streamp strm));
+local int read_buf OF((z_streamp strm, charf *buf, unsigned size));
+#ifdef ASMV
+ void match_init OF((void)); /* asm code initialization */
+#endif
+
+#ifdef DEBUG_NEVER
+local void check_match OF((deflate_state *s, IPos start, IPos match,
+ int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+local config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive
+ * input characters, so that a running hash key can be computed from the
+ * previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * IN assertion: all calls to to INSERT_STRING are made with consecutive
+ * input characters and the first MIN_MATCH bytes of str are valid
+ * (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ s->head[s->hash_size-1] = NIL; \
+ zmemzero((charf *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+PR_PUBLIC_API(int) deflateInit_(strm, level, version, stream_size)
+ z_streamp strm;
+ int level;
+ const char *version;
+ int stream_size;
+{
+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+PR_PUBLIC_API(int) deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+ version, stream_size)
+ z_streamp strm;
+ int level;
+ int method;
+ int windowBits;
+ int memLevel;
+ int strategy;
+ const char *version;
+ int stream_size;
+{
+ deflate_state *s;
+ int noheader = 0;
+
+ ushf *overlay;
+ /* We overlay pending_buf and d_buf+l_buf. This works since the average
+ * output size for (length,distance) codes is <= 24 bits.
+ */
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->msg = Z_NULL;
+ if (strm->zalloc == Z_NULL) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == Z_NULL) strm->zfree = zcfree;
+
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+
+ if (windowBits < 0) { /* undocumented feature: suppress zlib header */
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+ return Z_STREAM_ERROR;
+ }
+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+ if (s == Z_NULL) return Z_MEM_ERROR;
+ strm->state = (struct internal_state FAR *)s;
+ s->strm = strm;
+
+ s->noheader = noheader;
+ s->w_bits = windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+ s->pending_buf = (uchf *) overlay;
+
+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+ s->pending_buf == Z_NULL) {
+ strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+ deflateEnd (strm);
+ return Z_MEM_ERROR;
+ }
+ s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return deflateReset(strm);
+}
+
+/* ========================================================================= */
+PR_PUBLIC_API(int) deflateSetDictionary (strm, dictionary, dictLength)
+ z_streamp strm;
+ const Bytef *dictionary;
+ uInt dictLength;
+{
+ deflate_state *s;
+ uInt length = dictLength;
+ uInt n;
+ IPos hash_head = 0;
+
+ if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+ strm->state->status != INIT_STATE) return Z_STREAM_ERROR;
+
+ s = strm->state;
+ strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+ if (length < MIN_MATCH) return Z_OK;
+ if (length > MAX_DIST(s)) {
+ length = MAX_DIST(s);
+ dictionary += dictLength - length;
+ }
+ zmemcpy((charf *)s->window, dictionary, length);
+ s->strstart = length;
+ s->block_start = (long)length;
+
+ /* Insert all strings in the hash table (except for the last two bytes).
+ * s->lookahead stays null, so s->ins_h will be recomputed at the next
+ * call of fill_window.
+ */
+ s->ins_h = s->window[0];
+ UPDATE_HASH(s, s->ins_h, s->window[1]);
+ for (n = 0; n <= length - MIN_MATCH; n++) {
+ INSERT_STRING(s, n, hash_head);
+ }
+ if (hash_head) hash_head = 0; /* to make compiler happy */
+ return Z_OK;
+}
+
+/* ========================================================================= */
+PR_PUBLIC_API(int) deflateReset (strm)
+ z_streamp strm;
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->noheader < 0) {
+ s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */
+ }
+ s->status = s->noheader ? BUSY_STATE : INIT_STATE;
+ strm->adler = 1;
+ s->last_flush = Z_NO_FLUSH;
+
+ _tr_init(s);
+ lm_init(s);
+
+ return Z_OK;
+}
+
+/* ========================================================================= */
+PR_PUBLIC_API(int) deflateParams(strm, level, strategy)
+ z_streamp strm;
+ int level;
+ int strategy;
+{
+ deflate_state *s;
+ compress_func func;
+ int err = Z_OK;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+
+ if (level == Z_DEFAULT_COMPRESSION) {
+ level = 6;
+ }
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if (func != configuration_table[level].func && strm->total_in != 0) {
+ /* Flush the last buffer: */
+ err = deflate(strm, Z_PARTIAL_FLUSH);
+ }
+ if (s->level != level) {
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return err;
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+ deflate_state *s;
+ uInt b;
+{
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+ z_streamp strm;
+{
+ unsigned len = strm->state->pending;
+
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ zmemcpy(strm->next_out, strm->state->pending_out, len);
+ strm->next_out += len;
+ strm->state->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ strm->state->pending -= len;
+ if (strm->state->pending == 0) {
+ strm->state->pending_out = strm->state->pending_buf;
+ }
+}
+
+/* ========================================================================= */
+PR_PUBLIC_API(int) deflate (strm, flush)
+ z_streamp strm;
+ int flush;
+{
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ flush > Z_FINISH || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ s->strm = strm; /* just in case */
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Write the zlib header */
+ if (s->status == INIT_STATE) {
+
+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+ uInt level_flags = (s->level-1) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ s->status = BUSY_STATE;
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = 1L;
+ }
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && flush <= old_flush &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = (*(configuration_table[s->level].func))(s, flush);
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+ Assert(strm->avail_out > 0, "bug2");
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->noheader) return Z_STREAM_END;
+
+ /* Write the zlib trailer (adler32) */
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ s->noheader = -1; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+PR_PUBLIC_API(int) deflateEnd (strm)
+ z_streamp strm;
+{
+ int status;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, strm->state->pending_buf);
+ TRY_FREE(strm, strm->state->head);
+ TRY_FREE(strm, strm->state->prev);
+ TRY_FREE(strm, strm->state->window);
+
+ status = strm->state->status;
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* ========================================================================= */
+PR_PUBLIC_API(int) deflateCopy (dest, source)
+ z_streamp dest;
+ z_streamp source;
+{
+ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+ return Z_STREAM_ERROR;
+ }
+ *dest = *source;
+ return Z_STREAM_ERROR; /* to be implemented */
+#if 0
+ dest->state = (struct internal_state FAR *)
+ (*dest->zalloc)(1, sizeof(deflate_state));
+ if (dest->state == Z_NULL) return Z_MEM_ERROR;
+
+ *(dest->state) = *(source->state);
+ return Z_OK;
+#endif
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+ z_streamp strm;
+ charf *buf;
+ unsigned size;
+{
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ if (!strm->state->noheader) {
+ strm->adler = adler32(strm->adler, strm->next_in, len);
+ }
+ zmemcpy(buf, strm->next_in, len);
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+ deflate_state *s;
+{
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+#ifdef ASMV
+ match_init(); /* initialize the asm code */
+#endif
+}
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Posf *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ushf*)scan;
+ register ush scan_end = *(ushf*)(scan+best_len-1);
+#else
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len-1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2:
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ushf*)(match+best_len-1) != scan_end ||
+ *(ushf*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window+strstart+257 */
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend-scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len-1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ushf*)(scan+best_len-1);
+#else
+ scan_end1 = scan[best_len-1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return best_len;
+ return s->lookahead;
+}
+#endif /* ASMV */
+
+#ifdef DEBUG_NEVER
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+ deflate_state *s;
+ IPos start, match;
+ int length;
+{
+ /* check that the match is indeed a match */
+ if (zmemcmp((charf *)s->window + match,
+ (charf *)s->window + start, length) != EQUAL) {
+#if 0
+ fprintf(stderr, " start %u, match %u, length %d\n",
+ start, match, length);
+#endif
+ do {
+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+ } while (--length != 0);
+ z_error("invalid match");
+ }
+ if (verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start-match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+local void fill_window(s)
+ deflate_state *s;
+{
+ register unsigned n, m;
+ register Posf *p;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if strstart == 0
+ * and lookahead == 1 (input done one byte at time)
+ */
+ more--;
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ } else if (s->strstart >= wsize+MAX_DIST(s)) {
+
+ zmemcpy((charf *)s->window, (charf *)s->window+wsize,
+ (unsigned)wsize);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+
+ s->block_start -= (long) wsize;
+
+ /* Slide the hash table (could be avoided with 32 bit values
+ at the expense of memory usage):
+ */
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ } while (--n);
+
+ n = wsize;
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) return;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, (charf *)s->window + s->strstart + s->lookahead,
+ more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead >= MIN_MATCH) {
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+ _tr_flush_block(s, (s->block_start >= 0L ? \
+ (charf *)&s->window[(unsigned)s->block_start] : \
+ (charf *)Z_NULL), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (eof)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+ FLUSH_BLOCK_ONLY(s, eof); \
+ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying.
+ */
+local block_state deflate_stored(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ for (;;) {
+ /* Fill the window as much as possible: */
+ if (s->lookahead <= 1) {
+
+ Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+ s->block_start >= (long)s->w_size, "slide too late");
+
+ fill_window(s);
+ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+ Assert(s->block_start >= 0L, "block gone");
+
+ s->strstart += s->lookahead;
+ s->lookahead = 0;
+
+ /* Stored blocks are limited to 0xffff bytes: */
+ if (s->strstart == 0 || s->strstart > 0xfffe) {
+ /* strstart == 0 is possible when wraparound on 16-bit machine */
+ s->lookahead = s->strstart - 0xffff;
+ s->strstart = 0xffff;
+ }
+
+ /* Emit a stored block if it is large enough: */
+ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+ FLUSH_BLOCK(s, 0);
+ }
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head = NIL; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ if (s->strategy != Z_HUFFMAN_ONLY) {
+ s->match_length = longest_match (s, hash_head);
+ }
+ /* longest_match() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ bflush = _tr_tally(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in hash table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ bflush = _tr_tally (s, 0, s->window[s->strstart]);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head = NIL; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ if (s->strategy != Z_HUFFMAN_ONLY) {
+ s->match_length = longest_match (s, hash_head);
+ }
+ /* longest_match() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
+ (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR))) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+ bflush = _tr_tally(s, s->strstart -1 - s->prev_match,
+ s->prev_length - MIN_MATCH);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length-1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ if (_tr_tally (s, 0, s->window[s->strstart-1])) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally (s, 0, s->window[s->strstart-1]);
+ s->match_available = 0;
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
diff --git a/security/nss/cmd/zlib/deflate.h b/security/nss/cmd/zlib/deflate.h
new file mode 100644
index 000000000..410b21984
--- /dev/null
+++ b/security/nss/cmd/zlib/deflate.h
@@ -0,0 +1,275 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-1996 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* $Id$ */
+
+#ifndef _DEFLATE_H
+#define _DEFLATE_H
+
+#include "zutil.h"
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE 42
+#define BUSY_STATE 113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ int pending; /* nb of bytes in the pending buffer */
+ int noheader; /* suppress zlib header and adler32 */
+ Byte data_type; /* UNKNOWN, BINARY or ASCII */
+ Byte method; /* STORED (for zip only) or DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to supress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *l_buf; /* buffer for literals or lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt last_lit; /* running index in l_buf */
+
+ ushf *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ ulg compressed_len; /* total bit length of compressed file */
+ uInt matches; /* number of string matches in current block */
+ int last_eob_len; /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+ ulg bits_sent; /* bit length of the compressed data */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+ /* in trees.c */
+void _tr_init OF((deflate_state *s));
+int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+ulg _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+void _tr_align OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+#endif
diff --git a/security/nss/cmd/zlib/example.c b/security/nss/cmd/zlib/example.c
new file mode 100644
index 000000000..7c9176094
--- /dev/null
+++ b/security/nss/cmd/zlib/example.c
@@ -0,0 +1,503 @@
+/* example.c -- usage example of the zlib compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id$ */
+
+#include <stdio.h>
+#include "zlib.h"
+
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#else
+ extern void exit OF((int));
+#endif
+
+#define CHECK_ERR(err, msg) { \
+ if (err != Z_OK) { \
+ fprintf(stderr, "%s error: %d\n", msg, err); \
+ exit(1); \
+ } \
+}
+
+const char hello[] = "hello, hello!";
+/* "hello world" would be more standard, but the repeated "hello"
+ * stresses the compression code better, sorry...
+ */
+
+const char dictionary[] = "hello";
+uLong dictId; /* Adler32 value of the dictionary */
+
+void test_compress OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_gzio OF((const char *out, const char *in,
+ Byte *uncompr, int uncomprLen));
+void test_deflate OF((Byte *compr, uLong comprLen));
+void test_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_large_deflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_large_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_flush OF((Byte *compr, uLong comprLen));
+void test_sync OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_dict_deflate OF((Byte *compr, uLong comprLen));
+void test_dict_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+int main OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Test compress() and uncompress()
+ */
+void test_compress(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ uLong len = strlen(hello)+1;
+
+ err = compress(compr, &comprLen, (const Bytef*)hello, len);
+ CHECK_ERR(err, "compress");
+
+ strcpy((char*)uncompr, "garbage");
+
+ err = uncompress(uncompr, &uncomprLen, compr, comprLen);
+ CHECK_ERR(err, "uncompress");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad uncompress\n");
+ } else {
+ printf("uncompress(): %s\n", uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test read/write of .gz files
+ */
+void test_gzio(out, in, uncompr, uncomprLen)
+ const char *out; /* output file */
+ const char *in; /* input file */
+ Byte *uncompr;
+ int uncomprLen;
+{
+ int err;
+ int len = strlen(hello)+1;
+ gzFile file;
+
+ file = gzopen(out, "wb");
+ if (file == NULL) {
+ fprintf(stderr, "gzopen error\n");
+ exit(1);
+ }
+
+ if (gzwrite(file, (const voidp)hello, (unsigned)len) != len) {
+ fprintf(stderr, "gzwrite err: %s\n", gzerror(file, &err));
+ }
+ gzclose(file);
+
+ file = gzopen(in, "rb");
+ if (file == NULL) {
+ fprintf(stderr, "gzopen error\n");
+ }
+ strcpy((char*)uncompr, "garbage");
+
+ uncomprLen = gzread(file, uncompr, (unsigned)uncomprLen);
+ if (uncomprLen != len) {
+ fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
+ }
+ gzclose(file);
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad gzread\n");
+ } else {
+ printf("gzread(): %s\n", uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with small buffers
+ */
+void test_deflate(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+ int len = strlen(hello)+1;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.next_out = compr;
+
+ while (c_stream.total_in != (uLong)len && c_stream.total_out < comprLen) {
+ c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+ }
+ /* Finish the stream, still forcing small buffers: */
+ for (;;) {
+ c_stream.avail_out = 1;
+ err = deflate(&c_stream, Z_FINISH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "deflate");
+ }
+
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with small buffers
+ */
+void test_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_in = compr;
+ d_stream.next_out = uncompr;
+
+ while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
+ d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "inflate");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad inflate\n");
+ } else {
+ printf("inflate(): %s\n", uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with large buffers and dynamic change of compression level
+ */
+void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_SPEED);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_out = compr;
+ c_stream.avail_out = (uInt)comprLen;
+
+ /* At this point, uncompr is still mostly zeroes, so it should compress
+ * very well:
+ */
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (uInt)uncomprLen;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+ if (c_stream.avail_in != 0) {
+ fprintf(stderr, "deflate not greedy\n");
+ }
+
+ /* Feed in already compressed data and switch to no compression: */
+ deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+ c_stream.next_in = compr;
+ c_stream.avail_in = (uInt)comprLen/2;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ /* Switch back to compressing mode: */
+ deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (uInt)uncomprLen;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate should report Z_STREAM_END\n");
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with large buffers
+ */
+void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (uInt)comprLen;
+
+ for (;;) {
+ d_stream.next_out = uncompr; /* discard the output */
+ d_stream.avail_out = (uInt)uncomprLen;
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "large inflate");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
+ fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
+ } else {
+ printf("large_inflate(): OK\n");
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with full flush
+ */
+void test_flush(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+ int len = strlen(hello)+1;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.next_out = compr;
+ c_stream.avail_in = 3;
+ c_stream.avail_out = (uInt)comprLen;
+ err = deflate(&c_stream, Z_FULL_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ compr[3]++; /* force an error in first compressed block */
+ c_stream.avail_in = len - 3;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ CHECK_ERR(err, "deflate");
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflateSync()
+ */
+void test_sync(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_in = compr;
+ d_stream.next_out = uncompr;
+ d_stream.avail_in = 2; /* just read the zlib header */
+ d_stream.avail_out = (uInt)uncomprLen;
+
+ inflate(&d_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "inflate");
+
+ d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */
+ err = inflateSync(&d_stream); /* but skip the damaged part */
+ CHECK_ERR(err, "inflateSync");
+
+ err = inflate(&d_stream, Z_FINISH);
+ if (err != Z_DATA_ERROR) {
+ fprintf(stderr, "inflate should report DATA_ERROR\n");
+ /* Because of incorrect adler32 */
+ }
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ printf("after inflateSync(): hel%s\n", uncompr);
+}
+
+/* ===========================================================================
+ * Test deflate() with preset dictionary
+ */
+void test_dict_deflate(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ err = deflateSetDictionary(&c_stream,
+ (const Bytef*)dictionary, sizeof(dictionary));
+ CHECK_ERR(err, "deflateSetDictionary");
+
+ dictId = c_stream.adler;
+ c_stream.next_out = compr;
+ c_stream.avail_out = (uInt)comprLen;
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.avail_in = (uInt)strlen(hello)+1;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate should report Z_STREAM_END\n");
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with a preset dictionary
+ */
+void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (uInt)comprLen;
+
+ d_stream.next_out = uncompr;
+ d_stream.avail_out = (uInt)uncomprLen;
+
+ for (;;) {
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ if (err == Z_NEED_DICT) {
+ if (d_stream.adler != dictId) {
+ fprintf(stderr, "unexpected dictionary");
+ exit(1);
+ }
+ err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
+ sizeof(dictionary));
+ }
+ CHECK_ERR(err, "inflate with dict");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad inflate with dict\n");
+ } else {
+ printf("inflate with dictionary: %s\n", uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Usage: example [output.gz [input.gz]]
+ */
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ Byte *compr, *uncompr;
+ uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
+ uLong uncomprLen = comprLen;
+
+ if (zlibVersion()[0] != ZLIB_VERSION[0]) {
+ fprintf(stderr, "incompatible zlib version\n");
+ exit(1);
+
+ } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
+ fprintf(stderr, "warning: different zlib version\n");
+ }
+
+ compr = (Byte*)calloc((uInt)comprLen, 1);
+ uncompr = (Byte*)calloc((uInt)uncomprLen, 1);
+ /* compr and uncompr are cleared to avoid reading uninitialized
+ * data and to ensure that uncompr compresses well.
+ */
+ if (compr == Z_NULL || uncompr == Z_NULL) {
+ printf("out of memory\n");
+ exit(1);
+ }
+
+ test_compress(compr, comprLen, uncompr, uncomprLen);
+
+ test_gzio((argc > 1 ? argv[1] : "foo.gz"),
+ (argc > 2 ? argv[2] : "foo.gz"),
+ uncompr, (int)uncomprLen);
+
+ test_deflate(compr, comprLen);
+ test_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+ test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ test_flush(compr, comprLen);
+ test_sync(compr, comprLen, uncompr, uncomprLen);
+
+ test_dict_deflate(compr, comprLen);
+ test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ exit(0);
+ return 0; /* to avoid warning */
+}
diff --git a/security/nss/cmd/zlib/gzio.c b/security/nss/cmd/zlib/gzio.c
new file mode 100644
index 000000000..c52d30d30
--- /dev/null
+++ b/security/nss/cmd/zlib/gzio.c
@@ -0,0 +1,537 @@
+/* gzio.c -- IO on .gz files
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+
+/* $Id$ */
+
+#include <stdio.h>
+
+#include "zutil.h"
+
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+#define Z_BUFSIZE 4096
+
+#define ALLOC(size) malloc(size)
+#define TRYFREE(p) {if (p) free(p);}
+
+static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+
+typedef struct gz_stream {
+ z_stream stream;
+ int z_err; /* error code for last stream operation */
+ int z_eof; /* set if end of input file */
+ FILE *file; /* .gz file */
+ Byte *inbuf; /* input buffer */
+ Byte *outbuf; /* output buffer */
+ uLong crc; /* crc32 of uncompressed data */
+ char *msg; /* error message */
+ char *path; /* path name for debugging only */
+ int transparent; /* 1 if input file is not a .gz file */
+ char mode; /* 'w' or 'r' */
+} gz_stream;
+
+
+local gzFile gz_open OF((const char *path, const char *mode, int fd));
+local int get_byte OF((gz_stream *s));
+local void check_header OF((gz_stream *s));
+local int destroy OF((gz_stream *s));
+local void putLong OF((FILE *file, uLong x));
+local uLong getLong OF((gz_stream *s));
+
+/* ===========================================================================
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb"). The file is given either by file descriptor
+ or path name (if fd == -1).
+ gz_open return NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR).
+*/
+local gzFile gz_open (path, mode, fd)
+ const char *path;
+ const char *mode;
+ int fd;
+{
+ int err;
+ int level = Z_DEFAULT_COMPRESSION; /* compression level */
+ char *p = (char*)mode;
+ gz_stream *s;
+ char fmode[80]; /* copy of mode, without the compression level */
+ char *m = fmode;
+
+ if (!path || !mode) return Z_NULL;
+
+ s = (gz_stream *)ALLOC(sizeof(gz_stream));
+ if (!s) return Z_NULL;
+
+ s->stream.zalloc = (alloc_func)0;
+ s->stream.zfree = (free_func)0;
+ s->stream.opaque = (voidpf)0;
+ s->stream.next_in = s->inbuf = Z_NULL;
+ s->stream.next_out = s->outbuf = Z_NULL;
+ s->stream.avail_in = s->stream.avail_out = 0;
+ s->file = NULL;
+ s->z_err = Z_OK;
+ s->z_eof = 0;
+ s->crc = crc32(0L, Z_NULL, 0);
+ s->msg = NULL;
+ s->transparent = 0;
+
+ s->path = (char*)ALLOC(strlen(path)+1);
+ if (s->path == NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ strcpy(s->path, path); /* do this early for debugging */
+
+ s->mode = '\0';
+ do {
+ if (*p == 'r') s->mode = 'r';
+ if (*p == 'w' || *p == 'a') s->mode = 'w';
+ if (*p >= '0' && *p <= '9') {
+ level = *p - '0';
+ } else {
+ *m++ = *p; /* copy the mode */
+ }
+ } while (*p++ && m != fmode + sizeof(fmode));
+ if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
+
+ if (s->mode == 'w') {
+ err = deflateInit2(&(s->stream), level,
+ Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0);
+ /* windowBits is passed < 0 to suppress zlib header */
+
+ s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+
+ if (err != Z_OK || s->outbuf == Z_NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ } else {
+ err = inflateInit2(&(s->stream), -MAX_WBITS);
+ s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
+
+ if (err != Z_OK || s->inbuf == Z_NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ }
+ s->stream.avail_out = Z_BUFSIZE;
+
+ errno = 0;
+ s->file = fd < 0 ? FOPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
+
+ if (s->file == NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ if (s->mode == 'w') {
+ /* Write a very simple .gz header:
+ */
+ fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
+ Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
+ } else {
+ check_header(s); /* skip the .gz header */
+ }
+ return (gzFile)s;
+}
+
+/* ===========================================================================
+ Opens a gzip (.gz) file for reading or writing.
+*/
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern gzFile) gzopen (const char *path, const char *mode)
+#else
+extern gzFile EXPORT gzopen OF((const char *path, const char *mode))
+#endif
+{
+ return gz_open (path, mode, -1);
+}
+
+/* ===========================================================================
+ Associate a gzFile with the file descriptor fd. fd is not dup'ed here
+ to mimic the behavio(u)r of fdopen.
+*/
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern gzFile) gzdopen (int fd, const char *mode)
+#else
+extern gzFile EXPORT gzdopen OF((int fd, const char *mode))
+#endif
+{
+ char name[20];
+
+ if (fd < 0) return (gzFile)Z_NULL;
+ sprintf(name, "<fd:%d>", fd); /* for debugging */
+
+ return gz_open (name, mode, fd);
+}
+
+/* ===========================================================================
+ Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+ for end of file.
+ IN assertion: the stream s has been sucessfully opened for reading.
+*/
+local int get_byte(s)
+ gz_stream *s;
+{
+ if (s->z_eof) return EOF;
+ if (s->stream.avail_in == 0) {
+ errno = 0;
+ s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ if (s->stream.avail_in == 0) {
+ s->z_eof = 1;
+ if (ferror(s->file)) s->z_err = Z_ERRNO;
+ return EOF;
+ }
+ s->stream.next_in = s->inbuf;
+ }
+ s->stream.avail_in--;
+ return *(s->stream.next_in)++;
+}
+
+/* ===========================================================================
+ Check the gzip header of a gz_stream opened for reading. Set the stream
+ mode to transparent if the gzip magic header is not present; set s->err
+ to Z_DATA_ERROR if the magic header is present but the rest of the header
+ is incorrect.
+ IN assertion: the stream s has already been created sucessfully;
+ s->stream.avail_in is zero for the first time, but may be non-zero
+ for concatenated .gz files.
+*/
+local void check_header(s)
+ gz_stream *s;
+{
+ int method; /* method byte */
+ int flags; /* flags byte */
+ uInt len;
+ int c;
+
+ /* Check the gzip magic header */
+ for (len = 0; len < 2; len++) {
+ c = get_byte(s);
+ if (c != gz_magic[len]) {
+ s->transparent = 1;
+ if (c != EOF) s->stream.avail_in++, s->stream.next_in--;
+ s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
+ return;
+ }
+ }
+ method = get_byte(s);
+ flags = get_byte(s);
+ if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+ s->z_err = Z_DATA_ERROR;
+ return;
+ }
+
+ /* Discard time, xflags and OS code: */
+ for (len = 0; len < 6; len++) (void)get_byte(s);
+
+ if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+ len = (uInt)get_byte(s);
+ len += ((uInt)get_byte(s))<<8;
+ /* len is garbage if EOF but the loop below will quit anyway */
+ while (len-- != 0 && get_byte(s) != EOF) ;
+ }
+ if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+ while ((c = get_byte(s)) != 0 && c != EOF) ;
+ }
+ if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
+ while ((c = get_byte(s)) != 0 && c != EOF) ;
+ }
+ if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
+ for (len = 0; len < 2; len++) (void)get_byte(s);
+ }
+ s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
+}
+
+ /* ===========================================================================
+ * Cleanup then free the given gz_stream. Return a zlib error code.
+ Try freeing in the reverse order of allocations.
+ */
+local int destroy (s)
+ gz_stream *s;
+{
+ int err = Z_OK;
+
+ if (!s) return Z_STREAM_ERROR;
+
+ TRYFREE(s->msg);
+
+ if (s->stream.state != NULL) {
+ if (s->mode == 'w') {
+ err = deflateEnd(&(s->stream));
+ } else if (s->mode == 'r') {
+ err = inflateEnd(&(s->stream));
+ }
+ }
+ if (s->file != NULL && fclose(s->file)) {
+ err = Z_ERRNO;
+ }
+ if (s->z_err < 0) err = s->z_err;
+
+ TRYFREE(s->inbuf);
+ TRYFREE(s->outbuf);
+ TRYFREE(s->path);
+ TRYFREE(s);
+ return err;
+}
+
+/* ===========================================================================
+ Reads the given number of uncompressed bytes from the compressed file.
+ gzread returns the number of bytes actually read (0 for end of file).
+*/
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) gzread (gzFile file, voidp buf, unsigned len)
+#else
+extern int EXPORT gzread OF((gzFile file, voidp buf, unsigned len))
+#endif
+{
+ gz_stream *s = (gz_stream*)file;
+ Bytef *start = buf; /* starting point for crc computation */
+ Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
+
+ if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
+
+ if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
+ if (s->z_err == Z_STREAM_END) return 0; /* EOF */
+
+ s->stream.next_out = next_out = buf;
+ s->stream.avail_out = len;
+
+ while (s->stream.avail_out != 0) {
+
+ if (s->transparent) {
+ /* Copy first the lookahead bytes: */
+ uInt n = s->stream.avail_in;
+ if (n > s->stream.avail_out) n = s->stream.avail_out;
+ if (n > 0) {
+ zmemcpy(s->stream.next_out, s->stream.next_in, n);
+ next_out += n;
+ s->stream.next_out = next_out;
+ s->stream.next_in += n;
+ s->stream.avail_out -= n;
+ s->stream.avail_in -= n;
+ }
+ if (s->stream.avail_out > 0) {
+ s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
+ s->file);
+ }
+ return (int)(len - s->stream.avail_out);
+ }
+ if (s->stream.avail_in == 0 && !s->z_eof) {
+
+ errno = 0;
+ s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ if (s->stream.avail_in == 0) {
+ s->z_eof = 1;
+ if (ferror(s->file)) {
+ s->z_err = Z_ERRNO;
+ break;
+ }
+ }
+ s->stream.next_in = s->inbuf;
+ }
+ s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
+
+ if (s->z_err == Z_STREAM_END) {
+ /* Check CRC and original size */
+ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+ start = s->stream.next_out;
+
+ if (getLong(s) != s->crc || getLong(s) != s->stream.total_out) {
+ s->z_err = Z_DATA_ERROR;
+ } else {
+ /* Check for concatenated .gz files: */
+ check_header(s);
+ if (s->z_err == Z_OK) {
+ inflateReset(&(s->stream));
+ s->crc = crc32(0L, Z_NULL, 0);
+ }
+ }
+ }
+ if (s->z_err != Z_OK || s->z_eof) break;
+ }
+ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+
+ return (int)(len - s->stream.avail_out);
+}
+
+/* ===========================================================================
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of bytes actually written (0 in case of error).
+*/
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) gzwrite (gzFile file, const voidp buf, unsigned len)
+#else
+extern int EXPORT gzwrite OF((gzFile file, const voidp buf, unsigned len))
+#endif
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+ s->stream.next_in = buf;
+ s->stream.avail_in = len;
+
+ while (s->stream.avail_in != 0) {
+
+ if (s->stream.avail_out == 0) {
+
+ s->stream.next_out = s->outbuf;
+ if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+ s->z_err = Z_ERRNO;
+ break;
+ }
+ s->stream.avail_out = Z_BUFSIZE;
+ }
+ s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
+ if (s->z_err != Z_OK) break;
+ }
+ s->crc = crc32(s->crc, buf, len);
+
+ return (int)(len - s->stream.avail_in);
+}
+
+/* ===========================================================================
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) gzflush (gzFile file, int flush)
+#else
+extern int EXPORT gzflush OF((gzFile file, int flush))
+#endif
+{
+ uInt len;
+ int done = 0;
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+ s->stream.avail_in = 0; /* should be zero already anyway */
+
+ for (;;) {
+ len = Z_BUFSIZE - s->stream.avail_out;
+
+ if (len != 0) {
+ if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
+ s->z_err = Z_ERRNO;
+ return Z_ERRNO;
+ }
+ s->stream.next_out = s->outbuf;
+ s->stream.avail_out = Z_BUFSIZE;
+ }
+ if (done) break;
+ s->z_err = deflate(&(s->stream), flush);
+
+ /* deflate has finished flushing only when it hasn't used up
+ * all the available space in the output buffer:
+ */
+ done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
+
+ if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
+ }
+ fflush(s->file);
+ return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+
+/* ===========================================================================
+ Outputs a long in LSB order to the given file
+*/
+local void putLong (file, x)
+ FILE *file;
+ uLong x;
+{
+ int n;
+ for (n = 0; n < 4; n++) {
+ fputc((int)(x & 0xff), file);
+ x >>= 8;
+ }
+}
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets
+*/
+local uLong getLong (s)
+ gz_stream *s;
+{
+ uLong x = (uLong)get_byte(s);
+ int c;
+
+ x += ((uLong)get_byte(s))<<8;
+ x += ((uLong)get_byte(s))<<16;
+ c = get_byte(s);
+ if (c == EOF) s->z_err = Z_DATA_ERROR;
+ x += ((uLong)c)<<24;
+ return x;
+}
+
+/* ===========================================================================
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state.
+*/
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) gzclose (gzFile file)
+#else
+extern int EXPORT gzclose OF((gzFile file))
+#endif
+{
+ int err;
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL) return Z_STREAM_ERROR;
+
+ if (s->mode == 'w') {
+ err = gzflush (file, Z_FINISH);
+ if (err != Z_OK) return destroy(file);
+
+ putLong (s->file, s->crc);
+ putLong (s->file, s->stream.total_in);
+
+ }
+ return destroy(file);
+}
+
+/* ===========================================================================
+ Returns the error message for the last error which occured on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occured in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern const char *) gzerror (gzFile file, int *errnum)
+#else
+extern const char * EXPORT gzerror OF((gzFile file, int *errnum))
+#endif
+{
+ char *m;
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL) {
+ *errnum = Z_STREAM_ERROR;
+ return (const char*)ERR_MSG(Z_STREAM_ERROR);
+ }
+ *errnum = s->z_err;
+ if (*errnum == Z_OK) return (const char*)"";
+
+ m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
+
+ if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
+
+ TRYFREE(s->msg);
+ s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
+ strcpy(s->msg, s->path);
+ strcat(s->msg, ": ");
+ strcat(s->msg, m);
+ return (const char*)s->msg;
+}
diff --git a/security/nss/cmd/zlib/infblock.c b/security/nss/cmd/zlib/infblock.c
new file mode 100644
index 000000000..8eddbafed
--- /dev/null
+++ b/security/nss/cmd/zlib/infblock.c
@@ -0,0 +1,406 @@
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local uInt border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarily, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+
+void inflate_blocks_reset(s, z, c)
+inflate_blocks_statef *s;
+z_streamp z;
+uLongf *c;
+{
+ if (s->checkfn != Z_NULL)
+ *c = s->check;
+ if (s->mode == BTREE || s->mode == DTREE)
+ ZFREE(z, s->sub.trees.blens);
+ if (s->mode == CODES)
+ {
+ inflate_codes_free(s->sub.decode.codes, z);
+ inflate_trees_free(s->sub.decode.td, z);
+ inflate_trees_free(s->sub.decode.tl, z);
+ }
+ s->mode = TYPE;
+ s->bitk = 0;
+ s->bitb = 0;
+ s->read = s->write = s->window;
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(0L, Z_NULL, 0);
+ Trace((stderr, "inflate: blocks reset\n"));
+}
+
+
+inflate_blocks_statef *inflate_blocks_new(z, c, w)
+z_streamp z;
+check_func c;
+uInt w;
+{
+ inflate_blocks_statef *s;
+
+ if ((s = (inflate_blocks_statef *)ZALLOC
+ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+ return s;
+ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+ {
+ ZFREE(z, s);
+ return Z_NULL;
+ }
+ s->end = s->window + w;
+ s->checkfn = c;
+ s->mode = TYPE;
+ Trace((stderr, "inflate: blocks allocated\n"));
+ inflate_blocks_reset(s, z, &s->check);
+ return s;
+}
+
+
+#ifdef DEBUG
+ extern uInt inflate_hufts;
+#endif
+int inflate_blocks(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+ uInt t; /* temporary storage */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input based on current state */
+ while (1) switch (s->mode)
+ {
+ case TYPE:
+ NEEDBITS(3)
+ t = (uInt)b & 7;
+ s->last = t & 1;
+ switch (t >> 1)
+ {
+ case 0: /* stored */
+ Trace((stderr, "inflate: stored block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ t = k & 7; /* go to byte boundary */
+ DUMPBITS(t)
+ s->mode = LENS; /* get length of stored block */
+ break;
+ case 1: /* fixed */
+ Trace((stderr, "inflate: fixed codes block%s\n",
+ s->last ? " (last)" : ""));
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+
+ inflate_trees_fixed(&bl, &bd, &tl, &td);
+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+ if (s->sub.decode.codes == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.decode.tl = Z_NULL; /* don't try to free these */
+ s->sub.decode.td = Z_NULL;
+ }
+ DUMPBITS(3)
+ s->mode = CODES;
+ break;
+ case 2: /* dynamic */
+ Trace((stderr, "inflate: dynamic codes block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ s->mode = TABLE;
+ break;
+ case 3: /* illegal */
+ DUMPBITS(3)
+ s->mode = BAD;
+ z->msg = (char*)"invalid block type";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ break;
+ case LENS:
+ NEEDBITS(32)
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ s->mode = BAD;
+ z->msg = (char*)"invalid stored block lengths";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ s->sub.left = (uInt)b & 0xffff;
+ b = k = 0; /* dump bits */
+ Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
+ s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
+ break;
+ case STORED:
+ if (n == 0)
+ LEAVE
+ NEEDOUT
+ t = s->sub.left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ zmemcpy(q, p, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((s->sub.left -= t) != 0)
+ break;
+ Tracev((stderr, "inflate: stored end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ s->mode = s->last ? DRY : TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14)
+ s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ s->mode = BAD;
+ z->msg = (char*)"too many length or distance symbols";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+#endif
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (t < 19)
+ t = 19;
+ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ DUMPBITS(14)
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ s->mode = BTREE;
+ case BTREE:
+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+ {
+ NEEDBITS(3)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+ DUMPBITS(3)
+ }
+ while (s->sub.trees.index < 19)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+ s->sub.trees.bb = 7;
+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+ &s->sub.trees.tb, z);
+ if (t != Z_OK)
+ {
+ ZFREE(z, s->sub.trees.blens);
+ r = t;
+ if (r == Z_DATA_ERROR)
+ s->mode = BAD;
+ LEAVE
+ }
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: bits tree ok\n"));
+ s->mode = DTREE;
+ case DTREE:
+ while (t = s->sub.trees.table,
+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+ {
+ inflate_huft *h;
+ uInt i, j, c;
+
+ t = s->sub.trees.bb;
+ NEEDBITS(t)
+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+ t = h->word.what.Bits;
+ c = h->more.Base;
+ if (c < 16)
+ {
+ DUMPBITS(t)
+ s->sub.trees.blens[s->sub.trees.index++] = c;
+ }
+ else /* c == 16..18 */
+ {
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+ NEEDBITS(t + i)
+ DUMPBITS(t)
+ j += (uInt)b & inflate_mask[i];
+ DUMPBITS(i)
+ i = s->sub.trees.index;
+ t = s->sub.trees.table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ inflate_trees_free(s->sub.trees.tb, z);
+ ZFREE(z, s->sub.trees.blens);
+ s->mode = BAD;
+ z->msg = (char*)"invalid bit length repeat";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+ do {
+ s->sub.trees.blens[i++] = c;
+ } while (--j);
+ s->sub.trees.index = i;
+ }
+ }
+ inflate_trees_free(s->sub.trees.tb, z);
+ s->sub.trees.tb = Z_NULL;
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+ inflate_codes_statef *c;
+
+ bl = 9; /* must be <= 9 for lookahead assumptions */
+ bd = 6; /* must be <= 9 for lookahead assumptions */
+ t = s->sub.trees.table;
+#ifdef DEBUG
+ inflate_hufts = 0;
+#endif
+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+ s->sub.trees.blens, &bl, &bd, &tl, &td, z);
+ ZFREE(z, s->sub.trees.blens);
+ if (t != Z_OK)
+ {
+ if (t == (uInt)Z_DATA_ERROR)
+ s->mode = BAD;
+ r = t;
+ LEAVE
+ }
+ Tracev((stderr, "inflate: trees ok, %d * %d bytes used\n",
+ inflate_hufts, sizeof(inflate_huft)));
+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+ {
+ inflate_trees_free(td, z);
+ inflate_trees_free(tl, z);
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.decode.codes = c;
+ s->sub.decode.tl = tl;
+ s->sub.decode.td = td;
+ }
+ s->mode = CODES;
+ case CODES:
+ UPDATE
+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+ return inflate_flush(s, z, r);
+ r = Z_OK;
+ inflate_codes_free(s->sub.decode.codes, z);
+ inflate_trees_free(s->sub.decode.td, z);
+ inflate_trees_free(s->sub.decode.tl, z);
+ LOAD
+ Tracev((stderr, "inflate: codes end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ if (!s->last)
+ {
+ s->mode = TYPE;
+ break;
+ }
+ if (k > 7) /* return unused byte, if any */
+ {
+ Assert(k < 16, "inflate_codes grabbed too many bytes")
+ k -= 8;
+ n++;
+ p--; /* can always return one */
+ }
+ s->mode = DRY;
+ case DRY:
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ s->mode = DONE;
+ case DONE:
+ r = Z_STREAM_END;
+ LEAVE
+ case BAD:
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+}
+
+
+int inflate_blocks_free(s, z, c)
+inflate_blocks_statef *s;
+z_streamp z;
+uLongf *c;
+{
+ inflate_blocks_reset(s, z, c);
+ ZFREE(z, s->window);
+ ZFREE(z, s);
+ Trace((stderr, "inflate: blocks freed\n"));
+ return Z_OK;
+}
+
+
+void inflate_set_dictionary(s, d, n)
+inflate_blocks_statef *s;
+const Bytef *d;
+uInt n;
+{
+ zmemcpy((charf *)s->window, d, n);
+ s->read = s->write = s->window + n;
+}
diff --git a/security/nss/cmd/zlib/infblock.h b/security/nss/cmd/zlib/infblock.h
new file mode 100644
index 000000000..3ecd50cd3
--- /dev/null
+++ b/security/nss/cmd/zlib/infblock.h
@@ -0,0 +1,37 @@
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+extern inflate_blocks_statef * inflate_blocks_new OF((
+ z_streamp z,
+ check_func c, /* check function */
+ uInt w)); /* window size */
+
+extern int inflate_blocks OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int)); /* initial return code */
+
+extern void inflate_blocks_reset OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ uLongf *)); /* check value on output */
+
+extern int inflate_blocks_free OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ uLongf *)); /* check value on output */
+
+extern void inflate_set_dictionary OF((
+ inflate_blocks_statef *s,
+ const Bytef *d, /* dictionary */
+ uInt n)); /* dictionary length */
diff --git a/security/nss/cmd/zlib/infcodes.c b/security/nss/cmd/zlib/infcodes.c
new file mode 100644
index 000000000..3ae3818a1
--- /dev/null
+++ b/security/nss/cmd/zlib/infcodes.c
@@ -0,0 +1,247 @@
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+ /* mode */
+ enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ START, /* x: set up for LEN */
+ LEN, /* i: get length/literal/eob next */
+ LENEXT, /* i: getting length extra (have base) */
+ DIST, /* i: get distance next */
+ DISTEXT, /* i: getting distance extra */
+ COPY, /* o: copying bytes in window, waiting for space */
+ LIT, /* o: got literal, waiting for output space */
+ WASH, /* o: got eob, possibly still output waiting */
+ END, /* x: got eob and all data flushed */
+ BADCODE} /* x: got error */
+ mode; /* current inflate_codes mode */
+
+ /* mode dependent information */
+ uInt len;
+ union {
+ struct {
+ inflate_huft *tree; /* pointer into tree */
+ uInt need; /* bits needed */
+ } code; /* if LEN or DIST, where in tree */
+ uInt lit; /* if LIT, literal */
+ struct {
+ uInt get; /* bits to get for extra */
+ uInt dist; /* distance back to copy from */
+ } copy; /* if EXT or COPY, where and how much */
+ } sub; /* submode */
+
+ /* mode independent information */
+ Byte lbits; /* ltree bits decoded per branch */
+ Byte dbits; /* dtree bits decoder per branch */
+ inflate_huft *ltree; /* literal/length/eob tree */
+ inflate_huft *dtree; /* distance tree */
+
+};
+
+
+inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+z_streamp z;
+{
+ inflate_codes_statef *c;
+
+ if ((c = (inflate_codes_statef *)
+ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+ {
+ c->mode = START;
+ c->lbits = (Byte)bl;
+ c->dbits = (Byte)bd;
+ c->ltree = tl;
+ c->dtree = td;
+ Tracev((stderr, "inflate: codes new\n"));
+ }
+ return c;
+}
+
+
+int inflate_codes(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+ uInt j; /* temporary storage */
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ Bytef *f; /* pointer to copy strings from */
+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input and output based on current state */
+ while (1) switch (c->mode)
+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ case START: /* x: set up for LEN */
+#ifndef SLOW
+ if (m >= 258 && n >= 10)
+ {
+ UPDATE
+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+ LOAD
+ if (r != Z_OK)
+ {
+ c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+ break;
+ }
+ }
+#endif /* !SLOW */
+ c->sub.code.need = c->lbits;
+ c->sub.code.tree = c->ltree;
+ c->mode = LEN;
+ case LEN: /* i: get length/literal/eob next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e == 0) /* literal */
+ {
+ c->sub.lit = t->base;
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", t->base));
+ c->mode = LIT;
+ break;
+ }
+ if (e & 16) /* length */
+ {
+ c->sub.copy.get = e & 15;
+ c->len = t->base;
+ c->mode = LENEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t->next;
+ break;
+ }
+ if (e & 32) /* end of block */
+ {
+ Tracevv((stderr, "inflate: end of block\n"));
+ c->mode = WASH;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = (char*)"invalid literal/length code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case LENEXT: /* i: getting length extra (have base) */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->len += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ c->sub.code.need = c->dbits;
+ c->sub.code.tree = c->dtree;
+ Tracevv((stderr, "inflate: length %u\n", c->len));
+ c->mode = DIST;
+ case DIST: /* i: get distance next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e & 16) /* distance */
+ {
+ c->sub.copy.get = e & 15;
+ c->sub.copy.dist = t->base;
+ c->mode = DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t->next;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = (char*)"invalid distance code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case DISTEXT: /* i: getting distance extra */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->sub.copy.dist += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
+ c->mode = COPY;
+ case COPY: /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+ f = (uInt)(q - s->window) < c->sub.copy.dist ?
+ s->end - (c->sub.copy.dist - (q - s->window)) :
+ q - c->sub.copy.dist;
+#else
+ f = q - c->sub.copy.dist;
+ if ((uInt)(q - s->window) < c->sub.copy.dist)
+ f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
+#endif
+ while (c->len)
+ {
+ NEEDOUT
+ OUTBYTE(*f++)
+ if (f == s->end)
+ f = s->window;
+ c->len--;
+ }
+ c->mode = START;
+ break;
+ case LIT: /* o: got literal, waiting for output space */
+ NEEDOUT
+ OUTBYTE(c->sub.lit)
+ c->mode = START;
+ break;
+ case WASH: /* o: got eob, possibly more output */
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ c->mode = END;
+ case END:
+ r = Z_STREAM_END;
+ LEAVE
+ case BADCODE: /* x: got error */
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+}
+
+
+void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_streamp z;
+{
+ ZFREE(z, c);
+ Tracev((stderr, "inflate: codes free\n"));
+}
diff --git a/security/nss/cmd/zlib/infcodes.h b/security/nss/cmd/zlib/infcodes.h
new file mode 100644
index 000000000..c2c38df2c
--- /dev/null
+++ b/security/nss/cmd/zlib/infcodes.h
@@ -0,0 +1,27 @@
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+extern inflate_codes_statef *inflate_codes_new OF((
+ uInt, uInt,
+ inflate_huft *, inflate_huft *,
+ z_streamp ));
+
+extern int inflate_codes OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int));
+
+extern void inflate_codes_free OF((
+ inflate_codes_statef *,
+ z_streamp ));
+
diff --git a/security/nss/cmd/zlib/inffast.c b/security/nss/cmd/zlib/inffast.c
new file mode 100644
index 000000000..86eee4a29
--- /dev/null
+++ b/security/nss/cmd/zlib/inffast.c
@@ -0,0 +1,168 @@
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
+
+/* Called with number of bytes left to write in window at least 258
+ (the maximum string length) and number of input bytes available
+ at least ten. The ten bytes are six bytes for the longest length/
+ distance pair plus four bytes for overloading the bit buffer. */
+
+int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+inflate_blocks_statef *s;
+z_streamp z;
+{
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ uInt ml; /* mask for literal/length tree */
+ uInt md; /* mask for distance tree */
+ uInt c; /* bytes to copy */
+ uInt d; /* distance back to copy from */
+ Bytef *r; /* copy source pointer */
+
+ /* load input, output, bit values */
+ LOAD
+
+ /* initialize masks */
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ /* do until not enough input or output space for fast loop */
+ do { /* assume called with m >= 258 && n >= 10 */
+ /* get literal/length code */
+ GRABBITS(20) /* max bits for literal/length code */
+ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+ {
+ DUMPBITS(t->bits)
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: * literal '%c'\n" :
+ "inflate: * literal 0x%02x\n", t->base));
+ *q++ = (Byte)t->base;
+ m--;
+ continue;
+ }
+ do {
+ DUMPBITS(t->bits)
+ if (e & 16)
+ {
+ /* get extra bits for length */
+ e &= 15;
+ c = t->base + ((uInt)b & inflate_mask[e]);
+ DUMPBITS(e)
+ Tracevv((stderr, "inflate: * length %u\n", c));
+
+ /* decode distance base of block to copy */
+ GRABBITS(15); /* max bits for distance code */
+ e = (t = td + ((uInt)b & md))->exop;
+ do {
+ DUMPBITS(t->bits)
+ if (e & 16)
+ {
+ /* get extra bits to add to distance base */
+ e &= 15;
+ GRABBITS(e) /* get extra bits (up to 13) */
+ d = t->base + ((uInt)b & inflate_mask[e]);
+ DUMPBITS(e)
+ Tracevv((stderr, "inflate: * distance %u\n", d));
+
+ /* do the copy */
+ m -= c;
+ if ((uInt)(q - s->window) >= d) /* offset before dest */
+ { /* just copy */
+ r = q - d;
+ *q++ = *r++; c--; /* minimum count is three, */
+ *q++ = *r++; c--; /* so unroll loop a little */
+ }
+ else /* else offset after destination */
+ {
+ e = d - (uInt)(q - s->window); /* bytes from offset to end */
+ r = s->end - e; /* pointer to offset */
+ if (c > e) /* if source crosses, */
+ {
+ c -= e; /* copy to end of window */
+ do {
+ *q++ = *r++;
+ } while (--e);
+ r = s->window; /* copy rest from start of window */
+ }
+ }
+ do { /* copy all or what's left */
+ *q++ = *r++;
+ } while (--c);
+ break;
+ }
+ else if ((e & 64) == 0)
+ e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
+ else
+ {
+ z->msg = (char*)"invalid distance code";
+ UNGRAB
+ UPDATE
+ return Z_DATA_ERROR;
+ }
+ } while (1);
+ break;
+ }
+ if ((e & 64) == 0)
+ {
+ if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
+ {
+ DUMPBITS(t->bits)
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: * literal '%c'\n" :
+ "inflate: * literal 0x%02x\n", t->base));
+ *q++ = (Byte)t->base;
+ m--;
+ break;
+ }
+ }
+ else if (e & 32)
+ {
+ Tracevv((stderr, "inflate: * end of block\n"));
+ UNGRAB
+ UPDATE
+ return Z_STREAM_END;
+ }
+ else
+ {
+ z->msg = (char*)"invalid literal/length code";
+ UNGRAB
+ UPDATE
+ return Z_DATA_ERROR;
+ }
+ } while (1);
+ } while (m >= 258 && n >= 10);
+
+ /* not enough input or output--restore pointers and return */
+ UNGRAB
+ UPDATE
+ return Z_OK;
+}
diff --git a/security/nss/cmd/zlib/inffast.h b/security/nss/cmd/zlib/inffast.h
new file mode 100644
index 000000000..8cc644efb
--- /dev/null
+++ b/security/nss/cmd/zlib/inffast.h
@@ -0,0 +1,17 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+extern int inflate_fast OF((
+ uInt,
+ uInt,
+ inflate_huft *,
+ inflate_huft *,
+ inflate_blocks_statef *,
+ z_streamp ));
diff --git a/security/nss/cmd/zlib/inffixed.h b/security/nss/cmd/zlib/inffixed.h
new file mode 100644
index 000000000..77f7e7631
--- /dev/null
+++ b/security/nss/cmd/zlib/inffixed.h
@@ -0,0 +1,151 @@
+/* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by the maketree.c program
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+local uInt fixed_bl = 9;
+local uInt fixed_bd = 5;
+local inflate_huft fixed_tl[] = {
+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
+ };
+local inflate_huft fixed_td[] = {
+ {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
+ {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
+ {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
+ {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
+ {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
+ {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
+ {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
+ {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
+ };
diff --git a/security/nss/cmd/zlib/inflate.c b/security/nss/cmd/zlib/inflate.c
new file mode 100644
index 000000000..8cd0c141c
--- /dev/null
+++ b/security/nss/cmd/zlib/inflate.c
@@ -0,0 +1,346 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+
+#include "zutil.h"
+#include "infblock.h"
+
+struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
+
+/* inflate private state */
+struct internal_state {
+
+ /* mode */
+ enum {
+ METHOD, /* waiting for method byte */
+ FLAG, /* waiting for flag byte */
+ DICT4, /* four dictionary check bytes to go */
+ DICT3, /* three dictionary check bytes to go */
+ DICT2, /* two dictionary check bytes to go */
+ DICT1, /* one dictionary check byte to go */
+ DICT0, /* waiting for inflateSetDictionary */
+ BLOCKS, /* decompressing blocks */
+ CHECK4, /* four check bytes to go */
+ CHECK3, /* three check bytes to go */
+ CHECK2, /* two check bytes to go */
+ CHECK1, /* one check byte to go */
+ DONE, /* finished check, done */
+ BAD} /* got an error--stay here */
+ mode; /* current inflate mode */
+
+ /* mode dependent information */
+ union {
+ uInt method; /* if FLAGS, method byte */
+ struct {
+ uLong was; /* computed check value */
+ uLong need; /* stream check value */
+ } check; /* if CHECK, check values to compare */
+ uInt marker; /* if BAD, inflateSync's marker bytes count */
+ } sub; /* submode */
+
+ /* mode independent information */
+ int nowrap; /* flag for no wrapper */
+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */
+ inflate_blocks_statef
+ *blocks; /* current inflate_blocks state */
+
+};
+
+
+PR_PUBLIC_API(int) inflateReset(z)
+z_streamp z;
+{
+ uLong c;
+
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->total_in = z->total_out = 0;
+ z->msg = Z_NULL;
+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+ inflate_blocks_reset(z->state->blocks, z, &c);
+ Trace((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+
+PR_PUBLIC_API(int) inflateEnd(z)
+z_streamp z;
+{
+ uLong c;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->blocks != Z_NULL)
+ inflate_blocks_free(z->state->blocks, z, &c);
+ ZFREE(z, z->state);
+ z->state = Z_NULL;
+ Trace((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+
+PR_PUBLIC_API(int) inflateInit2_(z, w, version, stream_size)
+z_streamp z;
+int w;
+const char *version;
+int stream_size;
+{
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != sizeof(z_stream))
+ return Z_VERSION_ERROR;
+
+ /* initialize state */
+ if (z == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->msg = Z_NULL;
+ if (z->zalloc == Z_NULL)
+ {
+ z->zalloc = zcalloc;
+ z->opaque = (voidpf)0;
+ }
+ if (z->zfree == Z_NULL) z->zfree = zcfree;
+ if ((z->state = (struct internal_state FAR *)
+ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+ return Z_MEM_ERROR;
+ z->state->blocks = Z_NULL;
+
+ /* handle undocumented nowrap option (no zlib header or check) */
+ z->state->nowrap = 0;
+ if (w < 0)
+ {
+ w = - w;
+ z->state->nowrap = 1;
+ }
+
+ /* set window size */
+ if (w < 8 || w > 15)
+ {
+ inflateEnd(z);
+ return Z_STREAM_ERROR;
+ }
+ z->state->wbits = (uInt)w;
+
+ /* create inflate_blocks state */
+ if ((z->state->blocks =
+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+ == Z_NULL)
+ {
+ inflateEnd(z);
+ return Z_MEM_ERROR;
+ }
+ Trace((stderr, "inflate: allocated\n"));
+
+ /* reset state */
+ inflateReset(z);
+ return Z_OK;
+}
+
+
+PR_PUBLIC_API(int) inflateInit_(z, version, stream_size)
+z_streamp z;
+const char *version;
+int stream_size;
+{
+ return inflateInit2_(z, DEF_WBITS, version, stream_size);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)return r;r=Z_OK;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+PR_PUBLIC_API(int) inflate(z, f)
+z_streamp z;
+int f;
+{
+ int r;
+ uInt b;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL || f < 0)
+ return Z_STREAM_ERROR;
+ r = Z_BUF_ERROR;
+ while (1) switch (z->state->mode)
+ {
+ case METHOD:
+ NEEDBYTE
+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"unknown compression method";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"invalid window size";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ z->state->mode = FLAG;
+ case FLAG:
+ NEEDBYTE
+ b = NEXTBYTE;
+ if (((z->state->sub.method << 8) + b) % 31)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"incorrect header check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Trace((stderr, "inflate: zlib header ok\n"));
+ if (!(b & PRESET_DICT))
+ {
+ z->state->mode = BLOCKS;
+ break;
+ }
+ z->state->mode = DICT4;
+ case DICT4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = DICT3;
+ case DICT3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = DICT2;
+ case DICT2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = DICT1;
+ case DICT1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+ z->adler = z->state->sub.check.need;
+ z->state->mode = DICT0;
+ return Z_NEED_DICT;
+ case DICT0:
+ z->state->mode = BAD;
+ z->msg = (char*)"need dictionary";
+ z->state->sub.marker = 0; /* can try inflateSync */
+ return Z_STREAM_ERROR;
+ case BLOCKS:
+ r = inflate_blocks(z->state->blocks, z, r);
+ if (r == Z_DATA_ERROR)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0; /* can try inflateSync */
+ break;
+ }
+ if (r != Z_STREAM_END)
+ return r;
+ r = Z_OK;
+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+ if (z->state->nowrap)
+ {
+ z->state->mode = DONE;
+ break;
+ }
+ z->state->mode = CHECK4;
+ case CHECK4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = CHECK3;
+ case CHECK3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = CHECK2;
+ case CHECK2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = CHECK1;
+ case CHECK1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+
+ if (z->state->sub.check.was != z->state->sub.check.need)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"incorrect data check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Trace((stderr, "inflate: zlib check ok\n"));
+ z->state->mode = DONE;
+ case DONE:
+ return Z_STREAM_END;
+ case BAD:
+ return Z_DATA_ERROR;
+ default:
+ return Z_STREAM_ERROR;
+ }
+}
+
+
+PR_PUBLIC_API(int) inflateSetDictionary(z, dictionary, dictLength)
+z_streamp z;
+const Bytef *dictionary;
+uInt dictLength;
+{
+ uInt length = dictLength;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
+ return Z_STREAM_ERROR;
+
+ if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
+ z->adler = 1L;
+
+ if (length >= ((uInt)1<<z->state->wbits))
+ {
+ length = (1<<z->state->wbits)-1;
+ dictionary += dictLength - length;
+ }
+ inflate_set_dictionary(z->state->blocks, dictionary, length);
+ z->state->mode = BLOCKS;
+ return Z_OK;
+}
+
+
+PR_PUBLIC_API(int) inflateSync(z)
+z_streamp z;
+{
+ uInt n; /* number of bytes to look at */
+ Bytef *p; /* pointer to bytes */
+ uInt m; /* number of marker bytes found in a row */
+ uLong r, w; /* temporaries to save total_in and total_out */
+
+ /* set up */
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->mode != BAD)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0;
+ }
+ if ((n = z->avail_in) == 0)
+ return Z_BUF_ERROR;
+ p = z->next_in;
+ m = z->state->sub.marker;
+
+ /* search */
+ while (n && m < 4)
+ {
+ if (*p == (Byte)(m < 2 ? 0 : 0xff))
+ m++;
+ else if (*p)
+ m = 0;
+ else
+ m = 4 - m;
+ p++, n--;
+ }
+
+ /* restore */
+ z->total_in += p - z->next_in;
+ z->next_in = p;
+ z->avail_in = n;
+ z->state->sub.marker = m;
+
+ /* return no joy or set up to restart on a new block */
+ if (m != 4)
+ return Z_DATA_ERROR;
+ r = z->total_in; w = z->total_out;
+ inflateReset(z);
+ z->total_in = r; z->total_out = w;
+ z->state->mode = BLOCKS;
+ return Z_OK;
+}
diff --git a/security/nss/cmd/zlib/inftrees.c b/security/nss/cmd/zlib/inftrees.c
new file mode 100644
index 000000000..91dc00375
--- /dev/null
+++ b/security/nss/cmd/zlib/inftrees.c
@@ -0,0 +1,479 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+char inflate_copyright[] = " inflate 1.0.4 Copyright 1995-1996 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+ uIntf *, /* code lengths in bits */
+ uInt, /* number of codes */
+ uInt, /* number of "simple" codes */
+ uIntf *, /* list of base values for non-simple codes */
+ uIntf *, /* list of extra bits for non-simple codes */
+ inflate_huft * FAR*,/* result: starting table */
+ uIntf *, /* maximum lookup bits (returns actual) */
+ z_streamp )); /* for zalloc function */
+
+local voidpf falloc OF((
+ voidpf, /* opaque pointer (not used) */
+ uInt, /* number of items */
+ uInt)); /* size of item */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* see note #13 above about 258 */
+local uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
+local uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+local uInt cpdext[30] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15 /* maximum bit length of any code */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+#ifdef DEBUG
+ uInt inflate_hufts;
+#endif
+
+local int huft_build(b, n, s, d, e, t, m, zs)
+uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
+uInt n; /* number of codes (assumed <= N_MAX) */
+uInt s; /* number of simple-valued codes (0..s-1) */
+uIntf *d; /* list of base values for non-simple codes */
+uIntf *e; /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t; /* result: starting table */
+uIntf *m; /* maximum lookup bits, returns actual */
+z_streamp zs; /* for zalloc function */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ if the given code set is incomplete (the tables are still built in this
+ case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ set of lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+ uInt a; /* counter for codes of length k */
+ uInt c[BMAX+1]; /* bit length count table */
+ uInt f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register uInt i; /* counter, current code */
+ register uInt j; /* counter */
+ register int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ register uIntf *p; /* pointer into c[], b[], or v[] */
+ inflate_huft *q; /* points to current table */
+ struct inflate_huft_s r; /* table entry for structure assignment */
+ inflate_huft *u[BMAX]; /* table stack */
+ uInt v[N_MAX]; /* values in order of bit length */
+ register int w; /* bits before this table == (l * h) */
+ uInt x[BMAX+1]; /* bit offsets, then code stack */
+ uIntf *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ uInt z; /* number of entries in current table */
+
+
+ /* Generate counts for each bit length */
+ p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+ C4 /* clear c[]--assume BMAX+1 is 16 */
+ p = b; i = n;
+ do {
+ c[*p++]++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (inflate_huft *)Z_NULL;
+ *m = 0;
+ return Z_OK;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ l = *m;
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((uInt)l < j)
+ l = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((uInt)l > i)
+ l = i;
+ *m = l;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return Z_DATA_ERROR;
+ if ((y -= c[i]) < 0)
+ return Z_DATA_ERROR;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+ n = x[g]; /* set n to length of v */
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = -l; /* bits decoded == (l * h) */
+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
+ q = (inflate_huft *)Z_NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l)
+ {
+ h++;
+ w += l; /* previous table always l bits */
+
+ /* compute minimum size table less than or equal to l bits */
+ z = g - w;
+ z = z > (uInt)l ? l : z; /* table size upper limit */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ if (j < z)
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ z = 1 << j; /* table entries for j-bit table */
+
+ /* allocate and link in new table */
+ if ((q = (inflate_huft *)ZALLOC
+ (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
+ {
+ if (h)
+ inflate_trees_free(u[0], zs);
+ return Z_MEM_ERROR; /* not enough memory */
+ }
+#ifdef DEBUG
+ inflate_hufts += z + 1;
+#endif
+ *t = q + 1; /* link to list for huft_free() */
+ *(t = &(q->next)) = Z_NULL;
+ u[h] = ++q; /* table starts after link */
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.bits = (Byte)l; /* bits to dump before this table */
+ r.exop = (Byte)j; /* bits in this table */
+ r.next = q; /* pointer to this table */
+ j = i >> (w - l); /* (get around Turbo C bug) */
+ u[h-1][j] = r; /* connect to last table */
+ }
+ }
+
+ /* set up table entry in r */
+ r.bits = (Byte)(k - w);
+ if (p >= v + n)
+ r.exop = 128 + 64; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
+ r.base = *p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
+ r.base = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ while ((i & ((1 << w) - 1)) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ }
+ }
+ }
+
+
+ /* Return Z_BUF_ERROR if we were given an incomplete table */
+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+int inflate_trees_bits(c, bb, tb, z)
+uIntf *c; /* 19 code lengths */
+uIntf *bb; /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+z_streamp z; /* for zfree function */
+{
+ int r;
+
+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+ else if (r == Z_BUF_ERROR || *bb == 0)
+ {
+ inflate_trees_free(*tb, z);
+ z->msg = (char*)"incomplete dynamic bit lengths tree";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+}
+
+
+int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
+uInt nl; /* number of literal/length codes */
+uInt nd; /* number of distance codes */
+uIntf *c; /* that many (total) code lengths */
+uIntf *bl; /* literal desired/actual bit depth */
+uIntf *bd; /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+z_streamp z; /* for zfree function */
+{
+ int r;
+
+ /* build literal/length tree */
+ r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z);
+ if (r != Z_OK || *bl == 0)
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed literal/length tree";
+ else if (r != Z_MEM_ERROR)
+ {
+ inflate_trees_free(*tl, z);
+ z->msg = (char*)"incomplete literal/length tree";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+ }
+
+ /* build distance tree */
+ r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z);
+ if (r != Z_OK || (*bd == 0 && nl > 257))
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed literal/length tree";
+ else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+ r = Z_OK;
+ }
+#else
+ inflate_trees_free(*td, z);
+ z->msg = (char*)"incomplete distance tree";
+ r = Z_DATA_ERROR;
+ }
+ else if (r != Z_MEM_ERROR)
+ {
+ z->msg = (char*)"empty distance tree with lengths";
+ r = Z_DATA_ERROR;
+ }
+ inflate_trees_free(*tl, z);
+ return r;
+#endif
+ }
+
+ /* done */
+ return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+local int fixed_built = 0;
+#define FIXEDH 530 /* number of hufts used by fixed tables */
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+
+
+local voidpf falloc(q, n, s)
+voidpf q; /* opaque pointer */
+uInt n; /* number of items */
+uInt s; /* size of item */
+{
+ Assert(s == sizeof(inflate_huft) && n <= *(intf *)q,
+ "inflate_trees falloc overflow");
+ *(intf *)q -= n+s-s; /* s-s to avoid warning */
+ return (voidpf)(fixed_mem + *(intf *)q);
+}
+
+
+int inflate_trees_fixed(bl, bd, tl, td)
+uIntf *bl; /* literal desired/actual bit depth */
+uIntf *bd; /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+{
+ /* build fixed tables if not already (multiple overlapped executions ok) */
+ if (!fixed_built)
+ {
+ int k; /* temporary variable */
+ unsigned c[288]; /* length list for huft_build */
+ z_stream z; /* for falloc function */
+ int f = FIXEDH; /* number of hufts left in fixed_mem */
+
+ /* set up fake z_stream for memory routines */
+ z.zalloc = falloc;
+ z.zfree = Z_NULL;
+ z.opaque = (voidpf)&f;
+
+ /* literal table */
+ for (k = 0; k < 144; k++)
+ c[k] = 8;
+ for (; k < 256; k++)
+ c[k] = 9;
+ for (; k < 280; k++)
+ c[k] = 7;
+ for (; k < 288; k++)
+ c[k] = 8;
+ fixed_bl = 7;
+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
+
+ /* distance table */
+ for (k = 0; k < 30; k++)
+ c[k] = 5;
+ fixed_bd = 5;
+ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
+
+ /* done */
+ Assert(f == 0, "invalid build of fixed tables");
+ fixed_built = 1;
+ }
+ *bl = fixed_bl;
+ *bd = fixed_bd;
+ *tl = fixed_tl;
+ *td = fixed_td;
+ return Z_OK;
+}
+
+
+int inflate_trees_free(t, z)
+inflate_huft *t; /* table to free */
+z_streamp z; /* for zfree function */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+ list of the tables it made, with the links in a dummy first entry of
+ each table. */
+{
+ register inflate_huft *p, *q, *r;
+
+ /* Reverse linked list */
+ p = Z_NULL;
+ q = t;
+ while (q != Z_NULL)
+ {
+ r = (q - 1)->next;
+ (q - 1)->next = p;
+ p = q;
+ q = r;
+ }
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ while (p != Z_NULL)
+ {
+ q = (--p)->next;
+ ZFREE(z,p);
+ p = q;
+ }
+ return Z_OK;
+}
diff --git a/security/nss/cmd/zlib/inftrees.h b/security/nss/cmd/zlib/inftrees.h
new file mode 100644
index 000000000..b06613ddd
--- /dev/null
+++ b/security/nss/cmd/zlib/inftrees.h
@@ -0,0 +1,59 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+ union {
+ struct {
+ Byte Exop; /* number of extra bits or operation */
+ Byte Bits; /* number of bits in this code or subcode */
+ } what;
+ Bytef *pad; /* pad structure to a power of 2 (4 bytes for */
+ } word; /* 16-bit, 8 bytes for 32-bit machines) */
+ union {
+ uInt Base; /* literal, length base, or distance base */
+ inflate_huft *Next; /* pointer to next level of table */
+ } more;
+};
+
+#ifdef DEBUG
+ extern uInt inflate_hufts;
+#endif
+
+extern int inflate_trees_bits OF((
+ uIntf *, /* 19 code lengths */
+ uIntf *, /* bits tree desired/actual depth */
+ inflate_huft * FAR *, /* bits tree result */
+ z_streamp )); /* for zalloc, zfree functions */
+
+extern int inflate_trees_dynamic OF((
+ uInt, /* number of literal/length codes */
+ uInt, /* number of distance codes */
+ uIntf *, /* that many (total) code lengths */
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *, /* distance tree result */
+ z_streamp )); /* for zalloc, zfree functions */
+
+extern int inflate_trees_fixed OF((
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *)); /* distance tree result */
+
+extern int inflate_trees_free OF((
+ inflate_huft *, /* tables to free */
+ z_streamp )); /* for zfree function */
+
diff --git a/security/nss/cmd/zlib/infutil.c b/security/nss/cmd/zlib/infutil.c
new file mode 100644
index 000000000..eb21199c3
--- /dev/null
+++ b/security/nss/cmd/zlib/infutil.c
@@ -0,0 +1,87 @@
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* And'ing with mask[n] masks the lower n bits */
+uInt inflate_mask[17] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* copy as much as possible from the sliding window to the output area */
+int inflate_flush(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+ uInt n;
+ Bytef *p;
+ Bytef *q;
+
+ /* local copies of source and destination pointers */
+ p = z->next_out;
+ q = s->read;
+
+ /* compute number of bytes to copy as far as end of window */
+ n = (uInt)((q <= s->write ? s->write : s->end) - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy as far as end of window */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+
+ /* see if more to copy at beginning of window */
+ if (q == s->end)
+ {
+ /* wrap pointers */
+ q = s->window;
+ if (s->write == s->end)
+ s->write = s->window;
+
+ /* compute bytes to copy */
+ n = (uInt)(s->write - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+ }
+
+ /* update pointers */
+ z->next_out = p;
+ s->read = q;
+
+ /* done */
+ return r;
+}
diff --git a/security/nss/cmd/zlib/infutil.h b/security/nss/cmd/zlib/infutil.h
new file mode 100644
index 000000000..702cd290c
--- /dev/null
+++ b/security/nss/cmd/zlib/infutil.h
@@ -0,0 +1,99 @@
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFUTIL_H
+#define _INFUTIL_H
+
+typedef enum {
+ TYPE, /* get type bits (3, including end bit) */
+ LENS, /* get lengths for stored */
+ STORED, /* processing stored block */
+ TABLE, /* get table lengths */
+ BTREE, /* get bit lengths tree for a dynamic block */
+ DTREE, /* get length, distance trees for a dynamic block */
+ CODES, /* processing fixed or dynamic block */
+ DRY, /* output remaining window bytes */
+ DONE, /* finished last block, done */
+ BAD} /* got a data error--stuck here */
+inflate_block_mode;
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+ /* mode */
+ inflate_block_mode mode; /* current inflate_block mode */
+
+ /* mode dependent information */
+ union {
+ uInt left; /* if STORED, bytes left to copy */
+ struct {
+ uInt table; /* table lengths (14 bits) */
+ uInt index; /* index into blens (or border) */
+ uIntf *blens; /* bit lengths of codes */
+ uInt bb; /* bit length tree depth */
+ inflate_huft *tb; /* bit length decoding tree */
+ } trees; /* if DTREE, decoding info for trees */
+ struct {
+ inflate_huft *tl;
+ inflate_huft *td; /* trees to free */
+ inflate_codes_statef
+ *codes;
+ } decode; /* if CODES, current state */
+ } sub; /* submode */
+ uInt last; /* true if this block is the last block */
+
+ /* mode independent information */
+ uInt bitk; /* bits in bit buffer */
+ uLong bitb; /* bit buffer */
+ Bytef *window; /* sliding window */
+ Bytef *end; /* one byte after sliding window */
+ Bytef *read; /* window read pointer */
+ Bytef *write; /* window write pointer */
+ check_func checkfn; /* check function */
+ uLong check; /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/* update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/* get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/* output bytes */
+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/* load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
+extern uInt inflate_mask[17];
+
+/* copy as much as possible from the sliding window to the output area */
+extern int inflate_flush OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int));
+
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+#endif
diff --git a/security/nss/cmd/zlib/makefile.win b/security/nss/cmd/zlib/makefile.win
new file mode 100644
index 000000000..0f87b40b8
--- /dev/null
+++ b/security/nss/cmd/zlib/makefile.win
@@ -0,0 +1,91 @@
+NODEPEND=1
+IGNORE_MANIFEST = 1
+
+#//------------------------------------------------------------------------
+#//
+# New build system where zip dll is build indepenant of java stubs.
+#//
+#//------------------------------------------------------------------------
+MODULE = zlib
+EXPORTS = \
+ zlib.h \
+ zconf.h \
+ $(NULL)
+
+
+#//------------------------------------------------------------------------
+#//
+#// Specify the depth of the current directory relative to the
+#// root of NS
+#//
+#//------------------------------------------------------------------------
+DEPTH= ..\..\..\
+
+MAKE_OBJ_TYPE=DLL
+#//------------------------------------------------------------------------
+#//
+#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...)
+#//
+#//------------------------------------------------------------------------
+DLLNAME=$(ZIPDLL)
+PDBFILE=$(MOD_ZIP).pdb
+MAPFILE=$(MOD_ZIP).map
+!if "$(MOZ_BITS)" == "16"
+DEFFILE=zip16.def
+!endif
+#RESFILE=zip.res
+
+#//------------------------------------------------------------------------
+#//
+#// Define the files necessary to build the target (ie. OBJS)
+#//
+#//------------------------------------------------------------------------
+OBJS= \
+ .\$(OBJDIR)\adler32.obj \
+ .\$(OBJDIR)\compress.obj \
+ .\$(OBJDIR)\crc32.obj \
+ .\$(OBJDIR)\deflate.obj \
+ .\$(OBJDIR)\gzio.obj \
+ .\$(OBJDIR)\infblock.obj \
+ .\$(OBJDIR)\infcodes.obj \
+ .\$(OBJDIR)\inffast.obj \
+ .\$(OBJDIR)\inflate.obj \
+ .\$(OBJDIR)\inftrees.obj \
+ .\$(OBJDIR)\infutil.obj \
+ .\$(OBJDIR)\trees.obj \
+ .\$(OBJDIR)\uncompr.obj \
+ .\$(OBJDIR)\zutil.obj \
+ $(NULL)
+
+#//------------------------------------------------------------------------
+#//
+#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...)
+#// (these must be defined before the common makefiles are included)
+#//
+#//------------------------------------------------------------------------
+
+DLL=.\$(OBJDIR)\$(DLLNAME)
+MAPFILE= $(MOD_ZIP).map
+
+
+#//------------------------------------------------------------------------
+#//
+#// Define any local options for the make tools
+#// (ie. LCFLAGS, LLFLAGS, LLIBS, LINCS)
+#//
+#//------------------------------------------------------------------------
+LLIBS=$(LLIBS) $(LIBNSPR)
+LINCS=$(LINCS) -I. -I_gen
+# clobber and clobber_all will remove the following garbage:
+GARBAGE = $(GARBAGE) _gen
+
+#//------------------------------------------------------------------------
+#//
+#// Include the common makefile rules
+#//
+#//------------------------------------------------------------------------
+include <$(DEPTH)/sun-java/config/rules.mak>
+
+export:: $(DLL)
+ $(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME) $(DIST)\bin
+ $(MAKE_INSTALL) .\$(OBJDIR)\$(MOD_ZIP).lib $(DIST)\lib
diff --git a/security/nss/cmd/zlib/maketree.c b/security/nss/cmd/zlib/maketree.c
new file mode 100644
index 000000000..a16d4b146
--- /dev/null
+++ b/security/nss/cmd/zlib/maketree.c
@@ -0,0 +1,85 @@
+/* maketree.c -- make inffixed.h table for decoding fixed codes
+ * Copyright (C) 1995-2002 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* This program is included in the distribution for completeness.
+ You do not need to compile or run this program since inffixed.h
+ is already included in the distribution. To use this program
+ you need to compile zlib with BUILDFIXED defined and then compile
+ and link this program with the zlib library. Then the output of
+ this program can be piped to inffixed.h. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "zutil.h"
+#include "inftrees.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* generate initialization table for an inflate_huft structure array */
+void maketree(uInt b, inflate_huft *t)
+{
+ int i, e;
+
+ i = 0;
+ while (1)
+ {
+ e = t[i].exop;
+ if (e && (e & (16+64)) == 0) /* table pointer */
+ {
+ fprintf(stderr, "maketree: cannot initialize sub-tables!\n");
+ exit(1);
+ }
+ if (i % 4 == 0)
+ printf("\n ");
+ printf(" {{{%u,%u}},%u}", t[i].exop, t[i].bits, t[i].base);
+ if (++i == (1<<b))
+ break;
+ putchar(',');
+ }
+ puts("");
+}
+
+/* create the fixed tables in C initialization syntax */
+void main(void)
+{
+ int r;
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+ z_stream z;
+
+ z.zalloc = zcalloc;
+ z.opaque = (voidpf)0;
+ z.zfree = zcfree;
+ r = inflate_trees_fixed(&bl, &bd, &tl, &td, &z);
+ if (r)
+ {
+ fprintf(stderr, "inflate_trees_fixed error %d\n", r);
+ return;
+ }
+ puts("/* inffixed.h -- table for decoding fixed codes");
+ puts(" * Generated automatically by the maketree.c program");
+ puts(" */");
+ puts("");
+ puts("/* WARNING: this file should *not* be used by applications. It is");
+ puts(" part of the implementation of the compression library and is");
+ puts(" subject to change. Applications should only use zlib.h.");
+ puts(" */");
+ puts("");
+ printf("local uInt fixed_bl = %d;\n", bl);
+ printf("local uInt fixed_bd = %d;\n", bd);
+ printf("local inflate_huft fixed_tl[] = {");
+ maketree(bl, tl);
+ puts(" };");
+ printf("local inflate_huft fixed_td[] = {");
+ maketree(bd, td);
+ puts(" };");
+}
diff --git a/security/nss/cmd/zlib/manifest.mn b/security/nss/cmd/zlib/manifest.mn
new file mode 100644
index 000000000..13460377c
--- /dev/null
+++ b/security/nss/cmd/zlib/manifest.mn
@@ -0,0 +1,60 @@
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Netscape security libraries.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 1994-2000 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the
+# terms of the GNU General Public License Version 2 or later (the
+# "GPL"), in which case the provisions of the GPL are applicable
+# instead of those above. If you wish to allow use of your
+# version of this file only under the terms of the GPL and not to
+# allow others to use your version of this file under the MPL,
+# indicate your decision by deleting the provisions above and
+# replace them with the notice and other provisions required by
+# the GPL. If you do not delete the provisions above, a recipient
+# may use your version of this file under either the MPL or the
+# GPL.
+#
+
+CORE_DEPTH = ../../..
+
+MODULE = seccmd
+
+EXPORTS = zlib.h zconf.h
+
+CSRCS = adler32.c \
+ crc32.c \
+ compress.c \
+ uncompr.c \
+ deflate.c \
+ trees.c \
+ zutil.c \
+ inflate.c \
+ infblock.c \
+ inftrees.c \
+ infcodes.c \
+ infutil.c \
+ inffast.c \
+ $(NULL)
+
+LIBRARY_NAME = zlib
+
+# REQUIRES = nss
+
+DEFINES = -DNSPR20=1 -DMOZILLA_CLIENT=1
+
diff --git a/security/nss/cmd/zlib/minigzip.c b/security/nss/cmd/zlib/minigzip.c
new file mode 100644
index 000000000..60a48a12d
--- /dev/null
+++ b/security/nss/cmd/zlib/minigzip.c
@@ -0,0 +1,246 @@
+/* minigzip.c -- simulate gzip using the zlib compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * minigzip is a minimal implementation of the gzip utility. This is
+ * only an example of using zlib and isn't meant to replace the
+ * full-featured gzip. No attempt is made to deal with file systems
+ * limiting names to 14 or 8+3 characters, etc... Error checking is
+ * very limited. So use minigzip only for testing; use gzip for the
+ * real thing. On MSDOS, use only on file names without extension
+ * or in pipe mode.
+ */
+
+/* $Id$ */
+
+#include <stdio.h>
+#include "zlib.h"
+
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#else
+ extern void exit OF((int));
+#endif
+
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32)
+# include <fcntl.h>
+# include <io.h>
+# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+# define SET_BINARY_MODE(file)
+#endif
+
+#ifdef VMS
+# define unlink delete
+# define GZ_SUFFIX "-gz"
+#endif
+#ifdef RISCOS
+# define unlink remove
+# define GZ_SUFFIX "-gz"
+# define fileno(file) file->__file
+#endif
+
+#ifndef GZ_SUFFIX
+# define GZ_SUFFIX ".gz"
+#endif
+#define SUFFIX_LEN sizeof(GZ_SUFFIX)
+
+extern int unlink OF((const char *));
+
+#define BUFLEN 4096
+#define MAX_NAME_LEN 1024
+
+#define local static
+/* For MSDOS and other systems with limitation on stack size. For Unix,
+ #define local
+ works also.
+ */
+
+char *prog;
+
+void error OF((const char *msg));
+void gz_compress OF((FILE *in, gzFile out));
+void gz_uncompress OF((gzFile in, FILE *out));
+void file_compress OF((char *file));
+void file_uncompress OF((char *file));
+int main OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Display error message and exit
+ */
+void error(msg)
+ const char *msg;
+{
+ fprintf(stderr, "%s: %s\n", prog, msg);
+ exit(1);
+}
+
+/* ===========================================================================
+ * Compress input to output then close both files.
+ */
+void gz_compress(in, out)
+ FILE *in;
+ gzFile out;
+{
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+ for (;;) {
+ len = fread(buf, 1, sizeof(buf), in);
+ if (ferror(in)) {
+ perror("fread");
+ exit(1);
+ }
+ if (len == 0) break;
+
+ if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
+ }
+ fclose(in);
+ if (gzclose(out) != Z_OK) error("failed gzclose");
+}
+
+/* ===========================================================================
+ * Uncompress input to output then close both files.
+ */
+void gz_uncompress(in, out)
+ gzFile in;
+ FILE *out;
+{
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+ for (;;) {
+ len = gzread(in, buf, sizeof(buf));
+ if (len < 0) error (gzerror(in, &err));
+ if (len == 0) break;
+
+ if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
+ error("failed fwrite");
+ }
+ }
+ if (fclose(out)) error("failed fclose");
+
+ if (gzclose(in) != Z_OK) error("failed gzclose");
+}
+
+
+/* ===========================================================================
+ * Compress the given file: create a corresponding .gz file and remove the
+ * original.
+ */
+void file_compress(file)
+ char *file;
+{
+ local char outfile[MAX_NAME_LEN];
+ FILE *in;
+ gzFile out;
+
+ strcpy(outfile, file);
+ strcat(outfile, GZ_SUFFIX);
+
+ in = fopen(file, "rb");
+ if (in == NULL) {
+ perror(file);
+ exit(1);
+ }
+ out = gzopen(outfile, "wb"); /* use "wb9" for maximal compression */
+ if (out == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
+ exit(1);
+ }
+ gz_compress(in, out);
+
+ unlink(file);
+}
+
+
+/* ===========================================================================
+ * Uncompress the given file and remove the original.
+ */
+void file_uncompress(file)
+ char *file;
+{
+ local char buf[MAX_NAME_LEN];
+ char *infile, *outfile;
+ FILE *out;
+ gzFile in;
+ int len = strlen(file);
+
+ strcpy(buf, file);
+
+ if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
+ infile = file;
+ outfile = buf;
+ outfile[len-3] = '\0';
+ } else {
+ outfile = file;
+ infile = buf;
+ strcat(infile, GZ_SUFFIX);
+ }
+ in = gzopen(infile, "rb");
+ if (in == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
+ exit(1);
+ }
+ out = fopen(outfile, "wb");
+ if (out == NULL) {
+ perror(file);
+ exit(1);
+ }
+
+ gz_uncompress(in, out);
+
+ unlink(infile);
+}
+
+
+/* ===========================================================================
+ * Usage: minigzip [-d] [files...]
+ */
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int uncompr = 0;
+ gzFile file;
+
+ prog = argv[0];
+ argc--, argv++;
+
+ if (argc > 0) {
+ uncompr = (strcmp(*argv, "-d") == 0);
+ if (uncompr) {
+ argc--, argv++;
+ }
+ }
+ if (argc == 0) {
+ SET_BINARY_MODE(stdin);
+ SET_BINARY_MODE(stdout);
+ if (uncompr) {
+ file = gzdopen(fileno(stdin), "rb");
+ if (file == NULL) error("can't gzdopen stdin");
+ gz_uncompress(file, stdout);
+ } else {
+ file = gzdopen(fileno(stdout), "wb"); /* "wb9" for max compr. */
+ if (file == NULL) error("can't gzdopen stdout");
+ gz_compress(stdin, file);
+ }
+ } else {
+ do {
+ if (uncompr) {
+ file_uncompress(*argv);
+ } else {
+ file_compress(*argv);
+ }
+ } while (argv++, --argc);
+ }
+ exit(0);
+ return 0; /* to avoid warning */
+}
diff --git a/security/nss/cmd/zlib/netscape_mods.doc b/security/nss/cmd/zlib/netscape_mods.doc
new file mode 100644
index 000000000..c8a72d159
--- /dev/null
+++ b/security/nss/cmd/zlib/netscape_mods.doc
@@ -0,0 +1,43 @@
+
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * The contents of this file are subject to the Netscape Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+Netscape Modifications to Zlib source -
+
+
+Changes were made to the following files to
+create a zlib dll:
+
+ adler32.c
+ compress.c
+ crc32.c
+ deflate.c
+ gzio.c
+ inflate.c
+ uncompr.c
+ zutil.c
+
+
+Various changes for cross platform builds
+are clearly marked through out the source.
+
+
diff --git a/security/nss/cmd/zlib/trees.c b/security/nss/cmd/zlib/trees.c
new file mode 100644
index 000000000..84623d992
--- /dev/null
+++ b/security/nss/cmd/zlib/trees.c
@@ -0,0 +1,1143 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-1996 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* $Id$ */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+# include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+local int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+local uch dist_code[512];
+/* distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+local uch length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+struct static_tree_desc_s {
+ ct_data *static_tree; /* static tree or NULL */
+ intf *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+local static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+local static_tree_desc static_bl_desc =
+{(ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block OF((deflate_state *s));
+local void pqdownheap OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen OF((deflate_state *s, tree_desc *desc));
+local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree OF((deflate_state *s, tree_desc *desc));
+local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local int build_bl_tree OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+ int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+ ct_data *dtree));
+local void set_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup OF((deflate_state *s));
+local void bi_flush OF((deflate_state *s));
+local void copy_block OF((deflate_state *s, charf *buf, unsigned len,
+ int header));
+
+#ifndef DEBUG_NEVER
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+# define send_code(s, c, tree) \
+ { if (verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+#define d_code(dist) \
+ ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. dist_code[256] and dist_code[257] are never
+ * used.
+ */
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+ deflate_state *s;
+ int value; /* value to send */
+ int length; /* number of bits */
+{
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (value << s->bi_valid);
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += length - Buf_size;
+ } else {
+ s->bi_buf |= value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = value;\
+ s->bi_buf |= (val << s->bi_valid);\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* DEBUG */
+
+
+#ifndef MAX
+#define MAX(a,b) (a >= b ? a : b)
+#endif
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables. In a multi-threaded environment,
+ * this function may be called by two threads concurrently, but this is
+ * harmless since both invocations do exactly the same thing.
+ */
+local void tr_static_init()
+{
+ static int static_init_done = 0;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ length_code[length-1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+}
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void _tr_init(s)
+ deflate_state *s;
+{
+ tr_static_init();
+
+ s->compressed_len = 0L;
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+ deflate_state *s;
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+ deflate_state *s;
+ ct_data *tree; /* the tree to restore */
+ int k; /* node to move down */
+{
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ ct_data *stree = desc->stat_desc->static_tree;
+ intf *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n-base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (bits + xbits);
+ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if (tree[m].Len != (unsigned) bits) {
+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((long)bits - (long)tree[m].Len)
+ *(long)tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+ ct_data *tree; /* the tree to decorate */
+ int max_code; /* largest code with non zero frequency */
+ ushf *bl_count; /* number of codes at each bit length */
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ ush code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+ deflate_state *s;
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*(max_blindex+1) + 5+5+4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+ deflate_state *s;
+ int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes-1, 5);
+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void _tr_stored_block(s, buf, stored_len, eof)
+ deflate_state *s;
+ charf *buf; /* input block */
+ ulg stored_len; /* length of input block */
+ int eof; /* true if this is the last block for a file */
+{
+ send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+
+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void _tr_align(s)
+ deflate_state *s;
+{
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+ bi_flush(s);
+ /* Of the 10 bits for the empty block, we have already sent
+ * (10 - bi_valid) bits. The lookahead for the last real code (before
+ * the EOB of the previous block) was thus at least one plus the length
+ * of the EOB plus what we have just sent of the empty static block.
+ */
+ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+ s->compressed_len += 10L;
+ bi_flush(s);
+ }
+ s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file. This function
+ * returns the total compressed length for the file so far.
+ */
+ulg _tr_flush_block(s, buf, stored_len, eof)
+ deflate_state *s;
+ charf *buf; /* input block, or NULL if too old */
+ ulg stored_len; /* length of input block */
+ int eof; /* true if this is the last block for a file */
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is ascii or binary */
+ if (s->data_type == Z_UNKNOWN) set_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute first the block length in bytes*/
+ opt_lenb = (s->opt_len+3+7)>>3;
+ static_lenb = (s->static_len+3+7)>>3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->last_lit));
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+ /* If compression failed and this is the first and last block,
+ * and if the .zip file can be seeked (to rewrite the local header),
+ * the whole file is transformed into a stored file:
+ */
+#ifdef STORED_FILE_OK
+# ifdef FORCE_STORED_FILE
+ if (eof && s->compressed_len == 0L) { /* force stored file */
+# else
+ if (stored_len <= opt_lenb && eof && s->compressed_len==0L && seekable()) {
+# endif
+ /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
+ if (buf == (charf*)0) error ("block vanished");
+
+ copy_block(buf, (unsigned)stored_len, 0); /* without header */
+ s->compressed_len = stored_len << 3;
+ s->method = STORED;
+ } else
+#endif /* STORED_FILE_OK */
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, eof);
+
+#ifdef FORCE_STATIC
+ } else if (static_lenb >= 0) { /* force static trees */
+#else
+ } else if (static_lenb == opt_lenb) {
+#endif
+ send_bits(s, (STATIC_TREES<<1)+eof, 3);
+ compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+ s->compressed_len += 3 + s->static_len;
+ } else {
+ send_bits(s, (DYN_TREES<<1)+eof, 3);
+ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+ max_blindex+1);
+ compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+ s->compressed_len += 3 + s->opt_len;
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ init_block(s);
+
+ if (eof) {
+ bi_windup(s);
+ s->compressed_len += 7; /* align on byte boundary */
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+ s->compressed_len-7*eof));
+
+ return s->compressed_len >> 3;
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int _tr_tally (s, dist, lc)
+ deflate_state *s;
+ unsigned dist; /* distance of matched string */
+ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+ s->d_buf[s->last_lit] = (ush)dist;
+ s->l_buf[s->last_lit++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s->dyn_ltree[length_code[lc]+LITERALS+1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+
+ /* Try to guess if it is profitable to stop the current block here */
+ if (s->level > 2 && (s->last_lit & 0xfff) == 0) {
+ /* Compute an upper bound for the compressed length */
+ ulg out_length = (ulg)s->last_lit*8L;
+ ulg in_length = (ulg)((long)s->strstart - s->block_start);
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (ulg)s->dyn_dtree[dcode].Freq *
+ (5L+extra_dbits[dcode]);
+ }
+ out_length >>= 3;
+ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+ s->last_lit, in_length, out_length,
+ 100L - out_length*100L/in_length));
+ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+ }
+ return (s->last_lit == s->lit_bufsize-1);
+ /* We avoid equality with lit_bufsize because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+ deflate_state *s;
+ ct_data *ltree; /* literal tree */
+ ct_data *dtree; /* distance tree */
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned lx = 0; /* running index in l_buf */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->last_lit != 0) do {
+ dist = s->d_buf[lx];
+ lc = s->l_buf[lx++];
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = length_code[lc];
+ send_code(s, code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+ Assert((uInt)s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow");
+
+ } while (lx < s->last_lit);
+
+ send_code(s, END_BLOCK, ltree);
+ s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Set the data type to ASCII or BINARY, using a crude approximation:
+ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ * IN assertion: the fields freq of dyn_ltree are set and the total of all
+ * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ */
+local void set_data_type(s)
+ deflate_state *s;
+{
+ int n = 0;
+ unsigned ascii_freq = 0;
+ unsigned bin_freq = 0;
+ while (n < 7) bin_freq += s->dyn_ltree[n++].Freq;
+ while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq;
+ while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq;
+ s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII);
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+ unsigned code; /* the value to invert */
+ int len; /* its bit length */
+{
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+ deflate_state *s;
+{
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+ deflate_state *s;
+{
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef DEBUG
+ s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(s, buf, len, header)
+ deflate_state *s;
+ charf *buf; /* the input data */
+ unsigned len; /* its length */
+ int header; /* true if block header must be written */
+{
+ bi_windup(s); /* align on byte boundary */
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+
+ if (header) {
+ put_short(s, (ush)len);
+ put_short(s, (ush)~len);
+#ifdef DEBUG
+ s->bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG
+ s->bits_sent += (ulg)len<<3;
+#endif
+ while (len--) {
+ put_byte(s, *buf++);
+ }
+}
diff --git a/security/nss/cmd/zlib/trees.h b/security/nss/cmd/zlib/trees.h
new file mode 100644
index 000000000..72facf900
--- /dev/null
+++ b/security/nss/cmd/zlib/trees.h
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch _dist_code[DIST_CODE_LEN] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+};
+
diff --git a/security/nss/cmd/zlib/uncompr.c b/security/nss/cmd/zlib/uncompr.c
new file mode 100644
index 000000000..5e5a83247
--- /dev/null
+++ b/security/nss/cmd/zlib/uncompr.c
@@ -0,0 +1,58 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+/* $Id$ */
+
+#include "zlib.h"
+
+/* ===========================================================================
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+PR_PUBLIC_API(int) uncompress (dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+
+ err = inflateInit(&stream);
+ if (err != Z_OK) return err;
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ return err;
+ }
+ *destLen = stream.total_out;
+
+ err = inflateEnd(&stream);
+ return err;
+}
diff --git a/security/nss/cmd/zlib/zconf.h b/security/nss/cmd/zlib/zconf.h
new file mode 100644
index 000000000..096a448b4
--- /dev/null
+++ b/security/nss/cmd/zlib/zconf.h
@@ -0,0 +1,190 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+/* $Id$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateReset z_inflateReset
+# define compress z_compress
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+# define WIN32
+#endif
+#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
+# ifndef __32BIT__
+# define __32BIT__
+# endif
+#endif
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#if defined(MSDOS) && !defined(__32BIT__)
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32) || defined(XP_OS2)) && !defined(STDC)
+# define STDC
+#endif
+#if (defined(__STDC__) || defined(__cplusplus)) && !defined(STDC)
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ 1 << (windowBits+2) + 1 << (memLevel+9)
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR __far
+# else
+# define FAR far
+# endif
+#endif
+#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
+# ifndef __32BIT__
+# define SMALL_MEDIUM
+# define FAR __far
+# endif
+#endif
+#ifndef FAR
+# define FAR
+#endif
+
+typedef unsigned char Byte; /* 8 bits */
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#if defined(__BORLANDC__) && defined(SMALL_MEDIUM)
+ /* Borland C/C++ ignores FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#ifdef MOZILLA_CLIENT
+#include "prtypes.h"
+#else
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if (defined(_WINDOWS) || defined(WINDOWS)) && defined(ZLIB_DLL)
+# include <windows.h>
+# define EXPORT WINAPI
+#else
+# define EXPORT
+#endif
+
+/* #define PR_PUBLIC_API(type) type */
+
+#endif /* MOZILLA_CLIENT */
+
+#endif /* _ZCONF_H */
diff --git a/security/nss/cmd/zlib/zip16.def b/security/nss/cmd/zlib/zip16.def
new file mode 100644
index 000000000..664eeab09
--- /dev/null
+++ b/security/nss/cmd/zlib/zip16.def
@@ -0,0 +1,24 @@
+LIBRARY zip1640.DLL
+EXETYPE WINDOWS
+PROTMODE
+
+DESCRIPTION '16-bit Zip DLL'
+
+STUB 'WINSTUB.EXE'
+
+CODE LOADONCALL MOVEABLE DISCARDABLE
+DATA PRELOAD MOVEABLE SINGLE
+
+HEAPSIZE 8192
+
+EXPORTS
+
+IMPORTS
+ _malloc = nspr3.2
+ _realloc = nspr3.3
+ _calloc = nspr3.4
+ _free = nspr3.5
+ _getenv = nspr3.9
+ _printf = nspr3.11
+ _sscanf = nspr3.33
+
diff --git a/security/nss/cmd/zlib/zlib.h b/security/nss/cmd/zlib/zlib.h
new file mode 100644
index 000000000..b216f00a3
--- /dev/null
+++ b/security/nss/cmd/zlib/zlib.h
@@ -0,0 +1,892 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.0.4, Jul 24th, 1996.
+
+ Copyright (C) 1995-1996 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ gzip@prep.ai.mit.edu madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+/* This file was modified since it was taken from the zlib distribution */
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "zconf.h"
+
+#define ZLIB_VERSION "1.0.4"
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms may be added later and will have the same
+ stream interface.
+
+ For compression the application must provide the output buffer and
+ may optionally provide the input buffer for optimization. For decompression,
+ the application must provide the input buffer and may optionally provide
+ the output buffer for optimization.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The library does not install any signal handler. It is recommended to
+ add at least a handler for SIGSEGV when decompressing; the library checks
+ the consistency of the input data whenever possible but may go nuts
+ for some forms of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: ascii or binary */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern const char *) zlibVersion (void);
+#else
+extern const char * EXPORT zlibVersion OF((void));
+#endif
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+extern int EXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflate (z_streamp strm, int flush);
+#else
+extern int EXPORT deflate OF((z_streamp strm, int flush));
+#endif
+/*
+ Performs one or both of the following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ If the parameter flush is set to Z_PARTIAL_FLUSH, the current compression
+ block is terminated and flushed to the output buffer so that the
+ decompressor can get all input data available so far. For method 9, a future
+ variant on method 8, the current block will be flushed but not terminated.
+ Z_SYNC_FLUSH has the same effect as partial flush except that the compressed
+ output is byte aligned (the compressor can clear its internal bit buffer)
+ and the current block is always terminated; this can be useful if the
+ compressor has to be restarted from scratch after an interruption (in which
+ case the internal state of the compressor may be lost).
+ If flush is set to Z_FULL_FLUSH, the compression block is terminated, a
+ special marker is output and the compression dictionary is discarded; this
+ is useful to allow the decompressor to synchronize if one compressed block
+ has been damaged (see inflateSync below). Flushing degrades compression and
+ so should be used only when necessary. Using Z_FULL_FLUSH too often can
+ seriously degrade the compression. If deflate returns with avail_out == 0,
+ this function must be called again with the same value of the flush
+ parameter and more output space (updated avail_out), until the flush is
+ complete (deflate returns with non-zero avail_out).
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ 0.1% larger than avail_in plus 12 bytes. If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() may update data_type if it can make a good guess about
+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible.
+*/
+
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflateEnd (z_streamp strm);
+#else
+extern int EXPORT deflateEnd OF((z_streamp strm));
+#endif
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+extern int EXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller. If
+ zalloc and zfree are set to Z_NULL, inflateInit updates them to use default
+ allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_VERSION_ERROR if the zlib library version is incompatible
+ with the version assumed by the caller. msg is set to null if there is no
+ error message. inflateInit does not perform any decompression: this will be
+ done by inflate().
+*/
+
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) inflate (z_streamp strm, int flush);
+#else
+extern int EXPORT inflate OF((z_streamp strm, int flush));
+#endif
+/*
+ Performs one or both of the following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ If the parameter flush is set to Z_PARTIAL_FLUSH, inflate flushes as much
+ output as possible to the output buffer. The flushing behavior of inflate is
+ not specified for values of the flush parameter other than Z_PARTIAL_FLUSH
+ and Z_FINISH, but the current implementation actually flushes as much output
+ as possible anyway.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster routine
+ may be used for the single inflate() call.
+
+ inflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if the end of the
+ compressed data has been reached and all uncompressed output has been
+ produced, Z_NEED_DICT if a preset dictionary is needed at this point (see
+ inflateSetDictionary below), Z_DATA_ERROR if the input data was corrupted,
+ Z_STREAM_ERROR if the stream structure was inconsistent (for example if
+ next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in
+ the output buffer when Z_FINISH is used. In the Z_DATA_ERROR case, the
+ application may then call inflateSync to look for a good compression block.
+ In the Z_NEED_DICT case, strm->adler is set to the Adler32 value of the
+ dictionary chosen by the compressor.
+*/
+
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) inflateEnd (z_streamp strm);
+#else
+extern int EXPORT inflateEnd OF((z_streamp strm));
+#endif
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+extern int EXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library. (Method 9 will allow a 64K history buffer and
+ partial block flushes.)
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library (the value 16 will be allowed for method 9). Larger
+ values of this parameter result in better compression at the expense of
+ memory usage. The default value is 15 if deflateInit is used instead.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match). Filtered data consists mostly of small values with a
+ somewhat random distribution. In this case, the compression algorithm is
+ tuned to compress them better. The effect of Z_FILTERED is to force more
+ Huffman coding and less string matching; it is somewhat intermediate
+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+ the compression ratio but not the correctness of the compressed output even
+ if it is not set appropriately.
+
+ If next_in is not null, the library will use this buffer to hold also
+ some history information; the buffer must either hold the entire input
+ data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in
+ is null, the library will allocate its own history buffer (and leave next_in
+ null). next_out need not be provided here but must be provided by the
+ application for the next call of deflate().
+
+ If the history buffer is provided by the application, next_in must
+ must never be changed by the application since the compressor maintains
+ information inside this buffer from call to call; the application
+ must provide more input only by increasing avail_in. next_in is always
+ reset by the library in this case.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
+ not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
+ an invalid method). msg is set to null if there is no error message.
+ deflateInit2 does not perform any compression: this will be done by
+ deflate().
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflateSetDictionary (z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength);
+#else
+extern int EXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+#endif
+/*
+ Initializes the compression dictionary (history buffer) from the given
+ byte sequence without producing any compressed output. This function must
+ be called immediately after deflateInit or deflateInit2, before any call
+ of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and
+ can be predicted with good accuracy; the data can then be compressed better
+ than with the default empty dictionary. In this version of the library,
+ only the last 32K bytes of the dictionary are used.
+ Upon return of this function, strm->adler is set to the Adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.)
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state
+ is inconsistent (for example if deflate has already been called for this
+ stream). deflateSetDictionary does not perform any compression: this will
+ be done by deflate().
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflateCopy (z_streamp dest, z_streamp source);
+#else
+extern int EXPORT deflateCopy OF((z_streamp dest, z_streamp source));
+#endif
+/*
+ Sets the destination stream as a complete copy of the source stream. If
+ the source stream is using an application-supplied history buffer, a new
+ buffer is allocated for the destination stream. The compressed output
+ buffer is always application-supplied. It's the responsibility of the
+ application to provide the correct values of next_out and avail_out for the
+ next call of deflate.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflateReset (z_streamp strm);
+#else
+extern int EXPORT deflateReset OF((z_streamp strm));
+#endif
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflateParams (z_streamp strm, int level, int strategy);
+#else
+extern int EXPORT deflateParams OF((z_streamp strm, int level, int strategy));
+#endif
+/*
+ Dynamically update the compression level and compression strategy.
+ This can be used to switch between compression and straight copy of
+ the input data, or to switch to a different kind of input data requiring
+ a different strategy. If the compression level is changed, the input
+ available so far is compressed with the old level (and may be flushed);
+ the new level will take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+/*
+extern int EXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with more compression options. The
+ fields next_out, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library (the value 16 will be allowed soon). The
+ default value is 15 if inflateInit is used instead. If a compressed stream
+ with a larger window size is given as input, inflate() will return with
+ the error code Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ If next_out is not null, the library will use this buffer for the history
+ buffer; the buffer must either be large enough to hold the entire output
+ data, or have at least 1<<windowBits bytes. If next_out is null, the
+ library will allocate its own buffer (and leave next_out null). next_in
+ need not be provided here but must be provided by the application for the
+ next call of inflate().
+
+ If the history buffer is provided by the application, next_out must
+ never be changed by the application since the decompressor maintains
+ history information inside this buffer from call to call; the application
+ can only reset next_out to the beginning of the history buffer when
+ avail_out is zero and all output has been consumed.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
+ not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
+ windowBits < 8). msg is set to null if there is no error message.
+ inflateInit2 does not perform any decompression: this will be done by
+ inflate().
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) inflateSetDictionary (z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength);
+#else
+extern int EXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+#endif
+/*
+ Initializes the decompression dictionary (history buffer) from the given
+ uncompressed byte sequence. This function must be called immediately after
+ a call of inflate if this call returned Z_NEED_DICT. The dictionary chosen
+ by the compressor can be determined from the Adler32 value returned by this
+ call of inflate. The compressor and decompressor must use exactly the same
+ dictionary (see deflateSetDictionary).
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) inflateSync (z_streamp strm);
+#else
+extern int EXPORT inflateSync OF((z_streamp strm));
+#endif
+/*
+ Skips invalid compressed data until the special marker (see deflate()
+ above) can be found, or until all available input is skipped. No output
+ is provided.
+
+ inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no marker has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) inflateReset (z_streamp strm);
+#else
+extern int EXPORT inflateReset OF((z_streamp strm));
+#endif
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level, window size,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) compress (Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen);
+#else
+extern int EXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+#endif
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least 0.1% larger than
+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) uncompress (Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen);
+#else
+extern int EXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+#endif
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+typedef voidp gzFile;
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern gzFile) gzopen (const char *path, const char *mode);
+#else
+extern gzFile EXPORT gzopen OF((const char *path, const char *mode));
+#endif
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9"). gzopen can be used to read a file which is not in gzip format;
+ in this case gzread will directly read from the file without decompression.
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR).
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern gzFile) gzdopen (int fd, const char *mode);
+#else
+extern gzFile EXPORT gzdopen OF((int fd, const char *mode));
+#endif
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) gzread (gzFile file, voidp buf, unsigned len);
+#else
+extern int EXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+#endif
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) gzwrite (gzFile file, const voidp buf, unsigned len);
+#else
+extern int EXPORT gzwrite OF((gzFile file, const voidp buf, unsigned len));
+#endif
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) gzflush (gzFile file, int flush);
+#else
+extern int EXPORT gzflush OF((gzFile file, int flush));
+#endif
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) gzclose (gzFile file);
+#else
+extern int EXPORT gzclose OF((gzFile file));
+#endif
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern const char *) gzerror (gzFile file, int *errnum);
+#else
+extern const char * EXPORT gzerror OF((gzFile file, int *errnum));
+#endif
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern uLong) adler32 (uLong adler, const Bytef *buf, uInt len);
+#else
+extern uLong EXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+#endif
+
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern uLong) crc32 (uLong crc, const Bytef *buf, uInt len);
+#else
+extern uLong EXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+#endif
+/*
+ Update a running crc with the bytes buf[0..len-1] and return the updated
+ crc. If buf is NULL, this function returns the required initial value
+ for the crc. Pre- and post-conditioning (one's complement) is performed
+ within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+#ifdef MOZILLA_CLIENT
+PR_PUBLIC_API(extern int) deflateInit_ (z_streamp strm, int level, const char *version,
+ int stream_size);
+PR_PUBLIC_API(extern int) inflateInit_ (z_streamp strm, const char *version,
+ int stream_size);
+PR_PUBLIC_API(extern int) deflateInit2_ (z_streamp strm, int level, int method,
+ int windowBits, int memLevel, int strategy,
+ const char *version, int stream_size);
+PR_PUBLIC_API(extern int) inflateInit2_ (z_streamp strm, int windowBits,
+ const char *version, int stream_size);
+#else
+extern int EXPORT deflateInit_ OF((z_streamp strm, int level, const char *version,
+ int stream_size));
+extern int EXPORT inflateInit_ OF((z_streamp strm, const char *version,
+ int stream_size));
+extern int EXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel, int strategy,
+ const char *version, int stream_size));
+extern int EXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+#endif /* MOZILLA_CLIENT */
+
+
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+uLongf *get_crc_table OF((void)); /* can be used by asm versions of crc32() */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
diff --git a/security/nss/cmd/zlib/zutil.c b/security/nss/cmd/zlib/zutil.c
new file mode 100644
index 000000000..afca3ed0c
--- /dev/null
+++ b/security/nss/cmd/zlib/zutil.c
@@ -0,0 +1,215 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+/* $Id$ */
+
+#include <stdio.h>
+
+#include "zutil.h"
+
+#ifdef MOZILLA_CLIENT
+#include "prtypes.h"
+#include "prlog.h"
+#endif
+
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+#ifndef STDC
+extern void exit OF((int));
+#endif
+
+const char *z_errmsg[10] = {
+"need dictionary", /* Z_NEED_DICT 2 */
+"stream end", /* Z_STREAM_END 1 */
+"", /* Z_OK 0 */
+"file error", /* Z_ERRNO (-1) */
+"stream error", /* Z_STREAM_ERROR (-2) */
+"data error", /* Z_DATA_ERROR (-3) */
+"insufficient memory", /* Z_MEM_ERROR (-4) */
+"buffer error", /* Z_BUF_ERROR (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+PR_PUBLIC_API(const char *) zlibVersion()
+{
+ return ZLIB_VERSION;
+}
+
+#if defined(DEBUG) && defined(MOZILLA_CLIENT)
+void z_error (m)
+ char *m;
+{
+ PR_ASSERT(0);
+}
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+ Bytef* dest;
+ Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+ Bytef* s1;
+ Bytef* s2;
+ uInt len;
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void zmemzero(dest, len)
+ Bytef* dest;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+#ifdef __TURBOC__
+#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
+/* Small and medium model in Turbo C are for now limited to near allocation
+ * with reduced MAX_WBITS and MAX_MEM_LEVEL
+ */
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf = opaque; /* just to make some compilers happy */
+ ulg bsize = (ulg)items*size;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ int n;
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ ptr = opaque; /* just to make some compilers happy */
+ Assert(0, "zcfree: ptr not found");
+}
+#endif
+#endif /* __TURBOC__ */
+
+
+#if defined(M_I86) && !defined(__32BIT__)
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER < 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ return _halloc((long)items, size);
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ _hfree(ptr);
+}
+
+#endif /* MSC */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (opaque, items, size)
+ voidpf opaque;
+ unsigned items;
+ unsigned size;
+{
+ if (opaque) items += size - size; /* make compiler happy */
+ return (voidpf)calloc(items, size);
+}
+
+void zcfree (opaque, ptr)
+ voidpf opaque;
+ voidpf ptr;
+{
+ free(ptr);
+ if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/security/nss/cmd/zlib/zutil.h b/security/nss/cmd/zlib/zutil.h
new file mode 100644
index 000000000..6918260cf
--- /dev/null
+++ b/security/nss/cmd/zlib/zutil.h
@@ -0,0 +1,211 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+/* This file was modified since it was taken from the zlib distribution */
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* $Id$ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#if defined(_WIN32_WCE)
+#elif defined(MSDOS)||defined(VMS)||defined(CRAY)||defined(WIN32)||defined(RISCOS)
+# include <stddef.h>
+# include <errno.h>
+#else
+ extern int errno;
+#endif
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#ifdef MSDOS
+# define OS_CODE 0x00
+# ifdef __TURBOC__
+# include <alloc.h>
+# else /* MSC or DJGPP */
+# include <malloc.h>
+# endif
+#endif
+
+#ifdef OS2
+# define OS_CODE 0x06
+#endif
+
+#ifdef WIN32 /* Window 95 & Windows NT */
+# define OS_CODE 0x0b
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 0x02
+# define FOPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 0x01
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 0x05
+#endif
+
+#ifdef MACOS
+# define OS_CODE 0x07
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define OS_CODE 0x0F
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+ /* Common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef FOPEN
+# define FOPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#ifdef HAVE_STRERROR
+#ifndef MOZILLA_CLIENT
+ extern char *strerror OF((int));
+#endif
+# define zstrerror(errnum) strerror(errnum)
+#else
+# define zstrerror(errnum) ""
+#endif
+
+#if defined(pyr)
+# define NO_MEMCPY
+#endif
+#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(_MSC_VER)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ extern void zmemcpy OF((Bytef* dest, Bytef* source, uInt len));
+ extern int zmemcmp OF((Bytef* s1, Bytef* s2, uInt len));
+ extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG_ZLIB
+# include <stdio.h>
+# ifndef verbose
+# define verbose 0
+# endif
+ extern void z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) fprintf x
+# define Tracev(x) {if (verbose) fprintf x ;}
+# define Tracevv(x) {if (verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+# include <stdio.h>
+# ifndef verbose
+# define verbose 0
+# endif
+ extern void z_error OF((char *m));
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+typedef uLong (*check_func) OF((uLong check, const Bytef *buf, uInt len));
+
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void zcfree OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* _Z_UTIL_H */