diff -ur emacs-21.0.102.orig/src/process.c emacs-21.0.102/src/process.c
--- emacs-21.0.102.orig/src/process.c	Thu Mar 15 16:55:00 2001
+++ emacs-21.0.102/src/process.c	Tue May  1 01:14:03 2001
@@ -1736,6 +1736,1814 @@
 
 #ifdef HAVE_SOCKETS
 
+
+#include "private/pprio.h"
+#include "prio.h"
+#include "ssl.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);
+
+#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 */
+
+/* SSL-specific security error codes  */
+
+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.")
+
+/* General security error codes  */
+
+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.")
+
+/* General NSPR 2.0 errors */
+
+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" )
+
+};
+
+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 = 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;
+}
+
+/* Declare SSL cipher suites. */
+
+int cipherSuites[] = {
+	SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA,
+	SSL_FORTEZZA_DMS_WITH_RC4_128_SHA,
+	SSL_RSA_WITH_RC4_128_MD5,
+	SSL_RSA_WITH_3DES_EDE_CBC_SHA,
+	SSL_RSA_WITH_DES_CBC_SHA,
+	SSL_RSA_EXPORT_WITH_RC4_40_MD5,
+	SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
+	SSL_FORTEZZA_DMS_WITH_NULL_SHA,
+	SSL_RSA_WITH_NULL_MD5,
+	0
+};
+
+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) {
+		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);
+
+	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) {
+      puts("would fail here /jas");
+      /* return secStatus; */
+      return SECSuccess;
+    }
+
+    *(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. */
+	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;
+}
+
+
+DEFUN ("ssl-init", Fssl_init, Sssl_init,
+       1, 1, 0,
+  "Initialize SSL library.")
+   (dbpath)
+     Lisp_Object dbpath;
+{
+  SECStatus   secStatus;
+
+  if (! NILP (dbpath))
+    CHECK_STRING (dbpath, 0);
+
+  /* Initialize the NSS libraries. */
+  secStatus = NSS_Init(XSTRING(dbpath)->data);
+  if (secStatus != SECSuccess) {
+    puts("NSS_Init");
+    return Qnil;
+  }
+
+  return Qt;
+}
+
+
+
+/* XXX: replace with ssl-set-policy that take symbol argument with
+   policy /sj */
+DEFUN ("ssl-set-policy-domestic", Fssl_set_policy_domestic,
+       Sssl_set_policy_domestic,
+       0, 0, 0,
+       "Set Domestic encryption policy.")
+     ()
+{
+  SECStatus   secStatus;
+
+  secStatus = NSS_SetDomesticPolicy();
+  if (secStatus != SECSuccess) {
+    puts("NSS_setdomesticpolicy");
+    return Qnil;
+  }
+
+  return Qt;
+}
+
+
+/* XXX what about the ssl network stream?  can we close the ssl connection
+   without closing the tcp connection? /sj */
+DEFUN ("ssl-done", Fssl_done, Sssl_done,
+       0, 0, 0,
+   "Destruct SSL library.")
+     ()
+{
+  NSS_Shutdown();
+
+  return Qt;
+}
+
+/* XXX: how can we store these in the process structure? /sj */
+PRFileDesc *prin = NULL, *prout = NULL;
+PRFileDesc *sslin = NULL, *sslout = NULL;
+
+DEFUN ("ssl-start", Fssl_start, Sssl_start,
+       1, 1, 0,
+       "Setup SSL on a existing network stream.")
+   (process)
+     Lisp_Object process;
+{
+  int outch, inch;
+  SECStatus   secStatus;
+
+  /* XXX not here /sj */
+  SSL_CipherPrefSetDefault(SSL_RSA_WITH_NULL_MD5, PR_TRUE);
+
+  if (! NILP (process))
+    CHECK_PROCESS (process, 0);
+  
+  inch = XPROCESS (process)->infd;
+  outch = XPROCESS (process)->outfd;
+
+  /* Import the socket into the NSPR layer. */
+  prin = PR_ImportTCPSocket(inch);
+  if (prin == NULL) {
+    printf("can't import socket\n");
+    return Qnil;
+  }
+
+  /* Import the socket into the NSPR layer. */
+  prout = PR_ImportTCPSocket(outch);
+  if (prout == NULL) {
+    printf("can't import socket 2\n");
+    return Qnil;
+  }
+
+  /* Import the socket into the SSL layer. */
+  sslin = SSL_ImportFD(NULL, prin);
+  if (sslin == NULL) {
+    printf("can't ssl socket");
+    return Qnil;
+  }
+
+  /* Import the socket into the SSL layer. */
+  sslout = SSL_ImportFD(NULL, prout);
+  if (sslout == NULL) {
+    errWarn("can't ssl socket 2");
+    return Qnil;
+  }
+
+  /* Set configuration options. XXX not here? /sj */
+  secStatus = SSL_OptionSet(sslin, SSL_SECURITY, PR_TRUE);
+  if (secStatus != SECSuccess) {
+    errWarn("SSL_OptionSet:SSL_SECURITY");
+    return Qnil;
+  }
+
+  /* We're a client. XXX emacs doesn't support servers, does it? /sj */
+  secStatus = SSL_OptionSet(sslin, 
+			    SSL_HANDSHAKE_AS_CLIENT, PR_TRUE);
+  if (secStatus != SECSuccess) {
+    errWarn("SSL_OptionSet:SSL_HANDSHAKE_AS_CLIENT");
+    return Qnil;
+  }
+  
+  /* Set SSL callback routines. XXX: not here /sj */
+  secStatus = SSL_GetClientAuthDataHook(sslin,
+					(SSLGetClientAuthData)
+					myGetClientAuthData,
+					(void *)"certNickname");
+  if (secStatus != SECSuccess) {
+    errWarn("SSL_GetClientAuthDataHook");
+    return Qnil;
+  }
+  secStatus = SSL_AuthCertificateHook(sslin,
+				      (SSLAuthCertificate)myAuthCertificate,
+				      (void *)CERT_GetDefaultCertDB());
+  if (secStatus != SECSuccess) {
+    errWarn("SSL_AuthCertificateHook");
+    return Qnil;
+  }
+  secStatus = SSL_BadCertHook(sslin, 
+			      (SSLBadCertHandler)myBadCertHandler, NULL);
+  if (secStatus != SECSuccess) {
+    errWarn("SSL_BadCertHook");
+    return Qnil;
+  }
+  secStatus = SSL_HandshakeCallback(sslin, 
+				    (SSLHandshakeCallback)myHandshakeCallback,
+				    NULL);
+  if (secStatus != SECSuccess) {
+    errWarn("SSL_HandshakeCallback");
+    return Qnil;
+  }
+
+  /* Set certdb password. XXX: not here /sj */
+  secStatus = SSL_SetPKCS11PinArg(sslin, "password");
+  if (secStatus != SECSuccess) {
+    errWarn("SSL_SetPKCS11PinArg");
+    return Qnil;
+  }
+
+  /* Set SSL end-point hostname */
+  secStatus = SSL_SetURL(sslin, "www.pdc.kth.se");
+  if (secStatus != SECSuccess) {
+    errWarn("SSL_SetURL");
+    return Qnil;
+  }
+
+  /* Start SSL handshake.*/
+  secStatus = SSL_ResetHandshake(sslin,
+				 /* asServer */ PR_FALSE);
+  if (secStatus != SECSuccess) {
+    errWarn("can't reset handshake");
+    return Qnil;
+  }
+  secStatus = SSL_ForceHandshake(sslin);
+  if (secStatus != SECSuccess) {
+    errWarn("can't force handshake");
+    return Qnil;
+  }
+
+  printSecurityInfo(sslin);
+
+  /* XXX This should be called when process.c shuts down. How? /sj 
+  PR_Cleanup();*/
+
+  return Qt;
+}
+
+
+
 /* open a TCP network connection to a given HOST/SERVICE.  Treated
    exactly like a normal process when reading and writing.  Only
    differences are in status display and process deletion.  A network
@@ -4594,6 +6402,12 @@
     }
   bzero (proc_decode_coding_system, sizeof proc_decode_coding_system);
   bzero (proc_encode_coding_system, sizeof proc_encode_coding_system);
+
+  /* Call the NSPR initialization routines */
+  PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+  /* Set our password function callback. */
+  PK11_SetPasswordFunc(myPasswd);
 }
 
 void
@@ -4681,6 +6495,10 @@
 /*  defsubr (&Sprocess_connection); */
   defsubr (&Sset_process_coding_system);
   defsubr (&Sprocess_coding_system);
+  defsubr (&Sssl_start);
+  defsubr (&Sssl_init);
+  defsubr (&Sssl_done);
+  defsubr (&Sssl_set_policy_domestic);
 }
 
 
diff -ur emacs-21.0.102.orig/src/process.h emacs-21.0.102/src/process.h
--- emacs-21.0.102.orig/src/process.h	Wed Apr 29 23:47:23 1998
+++ emacs-21.0.102/src/process.h	Tue May  1 01:02:37 2001
@@ -19,6 +19,11 @@
 Boston, MA 02111-1307, USA.  */
 
 
+/* XXX: how can we store these in the process structure? /sj */
+#include "nspr.h"
+extern PRFileDesc *prin, *prout;
+extern PRFileDesc *sslin, *sslout;
+
 /* This structure records information about a subprocess
    or network connection.
 
diff -ur emacs-21.0.102.orig/src/sysdep.c emacs-21.0.102/src/sysdep.c
--- emacs-21.0.102.orig/src/sysdep.c	Thu Apr  5 16:42:04 2001
+++ emacs-21.0.102/src/sysdep.c	Tue May  1 00:52:49 2001
@@ -3276,9 +3276,16 @@
      unsigned int nbyte;
 {
   register int rtnval;
-  
-  while ((rtnval = read (fildes, buf, nbyte)) == -1
-	 && (errno == EINTR));
+
+  if (sslin) {
+    puts("secure read");
+    while ((rtnval = PR_Read (sslin, buf, nbyte)) == -1
+	   && (errno == EINTR));
+  }
+  else
+    while ((rtnval = read (fildes, buf, nbyte)) == -1
+	   && (errno == EINTR));
+
   return (rtnval);
 }
 
@@ -3294,7 +3301,12 @@
 
   while (nbyte > 0)
     {
-      rtnval = write (fildes, buf, nbyte);
+      if (sslin) {
+	puts("secure write");
+	rtnval = PR_Write (sslin, buf, nbyte);
+      }
+      else
+	rtnval = write (fildes, buf, nbyte);
 
       if (rtnval == -1)
 	{

