blob: 00740d09236fe8347888950d743a34896562d5ce [file] [log] [blame]
#! /bin/bash
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
########################################################################
#
# mozilla/security/nss/tests/dbtest/dbtest.sh
#
# Certificate generating and handeling for NSS QA, can be included
# multiple times from all.sh and the individual scripts
#
# needs to work on all Unix and Windows platforms
#
# included from (don't expect this to be up to date)
# --------------------------------------------------
# all.sh
# ssl.sh
# smime.sh
# tools.sh
#
# special strings
# ---------------
# FIXME ... known problems, search for this string
# NOTE .... unexpected behavior
#
# FIXME - Netscape - NSS
########################################################################
############################## dbtest_init ###############################
# local shell function to initialize this script
########################################################################
dbtest_init()
{
SCRIPTNAME="dbtests.sh"
if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for
CLEANUP="${SCRIPTNAME}" # cleaning this script will do it
fi
if [ -z "${INIT_SOURCED}" ] ; then
cd ../common
. ./init.sh
fi
if [ ! -r $CERT_LOG_FILE ]; then # we need certificates here
cd ../cert
. ./cert.sh
fi
SCRIPTNAME="dbtests.sh"
RONLY_DIR=${HOSTDIR}/ronlydir
EMPTY_DIR=${HOSTDIR}/emptydir
CONFLICT_DIR=${HOSTDIR}/conflictdir
THREAD_DIR=${HOSTDIR}/threadir
html_head "CERT and Key DB Tests"
}
############################## dbtest_cleanup ############################
# local shell function to finish this script (no exit since it might be
# sourced)
########################################################################
dbtest_cleanup()
{
html "</TABLE><BR>"
cd ${QADIR}
chmod a+rw $RONLY_DIR
. common/cleanup.sh
}
Echo()
{
echo
echo "---------------------------------------------------------------"
echo "| $*"
echo "---------------------------------------------------------------"
}
dbtest_main()
{
cd ${HOSTDIR}
Echo "test opening the database read/write in a nonexisting directory"
${BINDIR}/certutil -L -X -d ./non_existent_dir
ret=$?
if [ $ret -ne 255 ]; then
html_failed "Certutil succeeded in a nonexisting directory $ret"
else
html_passed "Certutil didn't work in a nonexisting dir $ret"
fi
${BINDIR}/dbtest -r -d ./non_existent_dir
ret=$?
if [ $ret -ne 46 ]; then
html_failed "Dbtest readonly succeeded in a nonexisting directory $ret"
else
html_passed "Dbtest readonly didn't work in a nonexisting dir $ret"
fi
Echo "test force opening the database in a nonexisting directory"
${BINDIR}/dbtest -f -d ./non_existent_dir
ret=$?
if [ $ret -ne 0 ]; then
html_failed "Dbtest force failed in a nonexisting directory $ret"
else
html_passed "Dbtest force succeeded in a nonexisting dir $ret"
fi
Echo "test opening the database readonly in an empty directory"
mkdir $EMPTY_DIR
${BINDIR}/tstclnt -h ${HOST} -d $EMPTY_DIR
ret=$?
if [ $ret -ne 1 ]; then
html_failed "Tstclnt succeded in an empty directory $ret"
else
html_passed "Tstclnt didn't work in an empty dir $ret"
fi
${BINDIR}/dbtest -r -d $EMPTY_DIR
ret=$?
if [ $ret -ne 46 ]; then
html_failed "Dbtest readonly succeeded in an empty directory $ret"
else
html_passed "Dbtest readonly didn't work in an empty dir $ret"
fi
rm -rf $EMPTY_DIR/* 2>/dev/null
${BINDIR}/dbtest -i -d $EMPTY_DIR
ret=$?
if [ $ret -ne 0 ]; then
html_failed "Dbtest logout after empty DB Init loses key $ret"
else
html_passed "Dbtest logout after empty DB Init has key"
fi
rm -rf $EMPTY_DIR/* 2>/dev/null
${BINDIR}/dbtest -i -p pass -d $EMPTY_DIR
ret=$?
if [ $ret -ne 0 ]; then
html_failed "Dbtest password DB Init loses needlogin state $ret"
else
html_passed "Dbtest password DB Init maintains needlogin state"
fi
rm -rf $EMPTY_DIR/* 2>/dev/null
${BINDIR}/certutil -D -n xxxx -d $EMPTY_DIR #created DB
ret=$?
if [ $ret -ne 255 ]; then
html_failed "Certutil succeeded in deleting a cert in an empty directory $ret"
else
html_passed "Certutil didn't work in an empty dir $ret"
fi
rm -rf $EMPTY_DIR/* 2>/dev/null
Echo "test force opening the database readonly in a empty directory"
${BINDIR}/dbtest -r -f -d $EMPTY_DIR
ret=$?
if [ $ret -ne 0 ]; then
html_failed "Dbtest force readonly failed in an empty directory $ret"
else
html_passed "Dbtest force readonly succeeded in an empty dir $ret"
fi
Echo "test opening the database r/w in a readonly directory"
mkdir $RONLY_DIR
cp -r ${CLIENTDIR}/* $RONLY_DIR
chmod -w $RONLY_DIR $RONLY_DIR/*
# On Mac OS X 10.1, if we do a "chmod -w" on files in an
# NFS-mounted directory, it takes several seconds for the
# first open to see the files are readonly, but subsequent
# opens immediately see the files are readonly. As a
# workaround we open the files once first. (Bug 185074)
if [ "${OS_ARCH}" = "Darwin" ]; then
cat $RONLY_DIR/* > /dev/null
fi
# skipping the next two tests when user is root,
# otherwise they would fail due to rooty powers
if [ $UID -ne 0 ]; then
${BINDIR}/dbtest -d $RONLY_DIR
ret=$?
if [ $ret -ne 46 ]; then
html_failed "Dbtest r/w succeeded in a readonly directory $ret"
else
html_passed "Dbtest r/w didn't work in an readonly dir $ret"
fi
else
html_passed "Skipping Dbtest r/w in a readonly dir because user is root"
fi
if [ $UID -ne 0 ]; then
${BINDIR}/certutil -D -n "TestUser" -d .
ret=$?
if [ $ret -ne 255 ]; then
html_failed "Certutil succeeded in deleting a cert in a readonly directory $ret"
else
html_passed "Certutil didn't work in an readonly dir $ret"
fi
else
html_passed "Skipping Certutil delete cert in a readonly directory test because user is root"
fi
Echo "test opening the database ronly in a readonly directory"
${BINDIR}/dbtest -d $RONLY_DIR -r
ret=$?
if [ $ret -ne 0 ]; then
html_failed "Dbtest readonly failed in a readonly directory $ret"
else
html_passed "Dbtest readonly succeeded in a readonly dir $ret"
fi
Echo "test force opening the database r/w in a readonly directory"
${BINDIR}/dbtest -d $RONLY_DIR -f
ret=$?
if [ $ret -ne 0 ]; then
html_failed "Dbtest force failed in a readonly directory $ret"
else
html_passed "Dbtest force succeeded in a readonly dir $ret"
fi
Echo "ls -l $RONLY_DIR"
ls -ld $RONLY_DIR $RONLY_DIR/*
mkdir ${CONFLICT_DIR}
Echo "test creating a new cert with a conflicting nickname"
cd ${CONFLICT_DIR}
pwd
${BINDIR}/certutil -N -d ${CONFLICT_DIR} -f ${R_PWFILE}
ret=$?
if [ $ret -ne 0 ]; then
html_failed "Nicknane conflict test failed, couldn't create database $ret"
else
${BINDIR}/certutil -A -n alice -t ,, -i ${R_ALICEDIR}/Alice.cert -d ${CONFLICT_DIR}
ret=$?
if [ $ret -ne 0 ]; then
html_failed "Nicknane conflict test failed, couldn't import alice cert $ret"
else
${BINDIR}/certutil -A -n alice -t ,, -i ${R_BOBDIR}/Bob.cert -d ${CONFLICT_DIR}
ret=$?
if [ $ret -eq 0 ]; then
html_failed "Nicknane conflict test failed, could import conflict nickname $ret"
else
html_passed "Nicknane conflict test, could not import conflict nickname $ret"
fi
fi
fi
Echo "test importing an old cert to a conflicting nickname"
# first, import the certificate
${BINDIR}/certutil -A -n bob -t ,, -i ${R_BOBDIR}/Bob.cert -d ${CONFLICT_DIR}
# now import with a different nickname
${BINDIR}/certutil -A -n alice -t ,, -i ${R_BOBDIR}/Bob.cert -d ${CONFLICT_DIR}
# the old one should still be there...
${BINDIR}/certutil -L -n bob -d ${CONFLICT_DIR}
ret=$?
if [ $ret -ne 0 ]; then
html_failed "Nickname conflict test-setting nickname conflict incorrectly worked"
else
html_passed "Nickname conflict test-setting nickname conflict was correctly rejected"
fi
# import a token private key and make sure the corresponding public key is
# created
${BINDIR}/pk11importtest -d ${CONFLICT_DIR} -f ${R_PWFILE}
ret=$?
if [ $ret -ne 0 ]; then
html_failed "Importing Token Private Key does not create the corrresponding Public Key"
else
html_passed "Importing Token Private Key correctly creates the corrresponding Public Key"
fi
#
# If we are testing an sqlite db, make sure we detect corrupted attributes.
# This test only runs if 1) we have sqlite3 (the command line sqlite diagnostic
# tool) and 2) we are using the sql database (rather than the dbm).
#
which sqlite3
ret=$?
KEYDB=${CONFLICT_DIR}/key4.db
# make sure sql database is bing used.
if [ ! -f ${KEYDB} ]; then
Echo "skipping key corruption test: requires sql database"
# make sure sqlite3 is installed.
elif [ $ret -ne 0 ]; then
Echo "skipping key corruption test: sqlite3 command not installed"
else
# we are going to mangle this key database in multiple tests, save a copy
# so that we can restore it later.
cp ${KEYDB} ${KEYDB}.save
# dump the keys in the log for diagnostic purposes
${BINDIR}/certutil -K -d ${CONFLICT_DIR} -f ${R_PWFILE}
# fetch the rsa and ec key ids
rsa_id=$(${BINDIR}/certutil -K -d ${CONFLICT_DIR} -f ${R_PWFILE} | grep rsa | awk '{ print $4}')
ec_id=$(${BINDIR}/certutil -K -d ${CONFLICT_DIR} -f ${R_PWFILE} | grep ' ec ' | awk '{ print $4}')
# now loop through all the private attributes and mangle them one at a time
for i in 120 122 123 124 125 126 127 128 011
do
Echo "testing if key corruption is detected in attribute $i"
cp ${KEYDB}.save ${KEYDB} # restore the saved keydb
# find all the hmacs for this key attribute and mangle each entry
sqlite3 ${KEYDB} ".dump metadata" | sed -e "/sig_key_.*_00000$i/{s/.*VALUES('\\(.*\\)',X'\\(.*\\)',NULL.*/\\1 \\2/;p;};d" | while read sig data
do
# mangle the last byte of the hmac
# The following increments the last nibble by 1 with both F and f
# mapping to 0. This mangles both upper and lower case results, so
# it will work on the mac.
last=$((${#data}-1))
newbyte=$(echo "${data:${last}}" | tr A-Fa-f0-9 B-F0b-f0-9a)
mangle=${data::${last}}${newbyte}
echo " amending ${sig} from ${data} to ${mangle}"
# write the mangled entry, inserting with a key matching an existing
# entry will overwrite the existing entry with the same key (${sig})
sqlite3 ${KEYDB} "BEGIN TRANSACTION; INSERT INTO metaData VALUES('${sig}',X'${mangle}',NULL); COMMIT"
done
# pick the key based on the attribute we are mangling,
# only CKA_VALUE (0x011) is not an RSA attribute, so we choose
# ec for 0x011 and rsa for all the rest. We could use the dsa
# key here, both CKA_VALUE attributes will be modifed in the loop above, but
# ec is more common than dsa these days.
if [ "$i" = "011" ]; then
key_id=$ec_id
else
key_id=$rsa_id
fi
# now try to use the mangled key (try to create a cert request with the key).
echo "${BINDIR}/certutil -R -k ${key_id} -s 'CN=BadTest, E=bad@mozilla.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US' -d ${CONFLICT_DIR} -f ${R_PWFILE} -a"
${BINDIR}/certutil -R -k ${key_id} -s 'CN=BadTest, E=bad@mozilla.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US' -d ${CONFLICT_DIR} -f ${R_PWFILE} -a
ret=$?
if [ ${ret} -eq 0 ]; then
html_failed "Key attribute $i corruption not detected"
else
html_passed "Corrupted key attribute $i correctly disabled key"
fi
done
cp ${KEYDB}.save ${KEYDB} # restore the saved keydb
fi
if [ "${NSS_DEFAULT_DB_TYPE}" = "sql" ] ; then
LOOPS=${NSS_SDB_THREAD_LOOPS-7}
THREADS=${NSS_SDB_THREAD_THREADS-30}
mkdir -p ${THREAD_DIR}
Echo "testing for thread starvation while creating keys"
${BINDIR}/certutil -N -d ${THREAD_DIR} --empty-password
${BINDIR}/sdbthreadtst -l ${LOOPS} -t ${THREADS} -d ${THREAD_DIR}
ret=$?
case "$ret" in
"0")
html_passed "Successfully completed ${LOOPS} loops in ${THREADS} threads without failure."
;;
"2")
html_failed "sdbthreadtst failed for some environment reason (like lack of memory)"
;;
"1")
html_failed "sdbthreadtst failed do to starvation using ${LOOPS} loops and ${THREADS} threads."
;;
*)
html_failed "sdbthreadtst failed with an unrecognized error code."
esac
fi
}
################## main #################################################
dbtest_init
dbtest_main 2>&1
dbtest_cleanup