diff -ur --new-file emacs-21.0.102.orig/lisp/net/ssl.el emacs-21.0.102/lisp/net/ssl.el
--- emacs-21.0.102.orig/lisp/net/ssl.el	Thu Jan  1 01:00:00 1970
+++ emacs-21.0.102/lisp/net/ssl.el	Sun May  6 00:56:04 2001
@@ -0,0 +1,43 @@
+;; Simple test:
+;;
+;; (setq jas (open-ssl-stream "ssl" (current-buffer) "www.pdc.kth.se" 443))
+;; (process-send-string jas "GET /\r\n\r\n")
+
+(defvar ssl-rsa-with-null-md5 ?\x0001)
+(defvar ssl-security 1)
+(defvar ssl-handshake-as-client 5)
+
+(defvar ssl-certdb-path "~/.netscape")
+
+(defun ssl-simple-badcerthook (arg)
+  (message (format "Simple badcerthook %s" arg))
+  t)
+
+(defun open-ssl-stream (name buffer host service)
+  "Open a SSL connection for a service to a host.
+Returns a subprocess-object to represent the connection.
+Input and output work as for subprocesses; `delete-process' closes it.
+Args are NAME BUFFER HOST SERVICE.
+NAME is name for process.  It is modified if necessary to make it unique.
+BUFFER is the buffer (or buffer-name) to associate with the process.
+ Process output goes at end of that buffer, unless you specify
+ an output stream or filter function to handle the output.
+ BUFFER may be also nil, meaning that this process is not associated
+ with any buffer
+Third arg is name of the host to connect to, or its IP address.
+Fourth arg SERVICE is name of the service desired, or an integer
+specifying a port number to connect to."
+  (let ((proc (open-network-stream name buffer host service)))
+    (nss-init (expand-file-name ssl-certdb-path))
+    (nss-setdomesticpolicy)
+    (ssl-cipherprefsetdefault ssl-rsa-with-null-md5 t)
+    (ssl-importfd nil proc)
+    (ssl-optionset proc ssl-security t)
+    (ssl-optionset proc ssl-handshake-as-client t)
+    (ssl-badcerthook proc 'ssl-simple-badcerthook 42)
+    (ssl-seturl proc host)
+    (ssl-resethandshake proc nil)
+    (ssl-forcehandshake proc)
+    proc))
+
+(provide 'ssl)
diff -ur --new-file emacs-21.0.102.orig/src/nss-stuff.c emacs-21.0.102/src/nss-stuff.c
--- emacs-21.0.102.orig/src/nss-stuff.c	Thu Jan  1 01:00:00 1970
+++ emacs-21.0.102/src/nss-stuff.c	Sat May  5 22:50:44 2001
@@ -0,0 +1,1562 @@
+
+#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 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;
+}
diff -ur --new-file 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	Sun May  6 00:50:03 2001
@@ -1736,6 +1736,313 @@
 
 #ifdef HAVE_SOCKETS
 
+#include "nss-stuff.c"
+
+DEFUN ("nss-init", Fnss_init, Snss_init,
+       1, 1, 0,
+       "Initialize the Network Security Services.\n\
+nss-init opens the certN.db, keyN.db, and secmod.db files (where N is\n\
+a numeric digit) in CONFIGDIR (e.g. \"~/.netscape\"). nss-init is not\n\
+idempotent, so call it only once.\n\
+\n\
+nss-init opens the database files read-only. If you are performing\n\
+operations that require write permission, for example S/MIME\n\
+operations such as adding a certificate, use NSS_InitReadWrite\n\
+instead.")
+     (configdir)
+     Lisp_Object configdir;
+{
+  SECStatus   secStatus;
+  
+  CHECK_STRING (configdir, 0);
+  
+  secStatus = NSS_Init(XSTRING(configdir)->data);
+  
+  return secStatus == SECSuccess ? Qt : Qnil;
+}
+
+DEFUN ("nss-initreadwrite", Fnss_initreadwrite, Snss_initreadwrite,
+       1, 1, 0,
+       "Initialize the Network Security Services.\n\
+nss-initreadwrite opens the certN.db, keyN.db, and secmod.db files\n\
+(where N is a numeric digit) with both read and write permission in\n\
+CONFIGDIR directory.  `nss-initreadwrite' is not idempotent, so
+call\n\ it only once.\n\
+\n\
+Use nss-initreadwrite rather than nss-init if you are performing operations\n\
+that require write permission, such as some S/MIME operations.")
+     (configdir)
+     Lisp_Object configdir;
+{
+  SECStatus   secStatus;
+  
+  CHECK_STRING (configdir, 0);
+  
+  secStatus = NSS_InitReadWrite(XSTRING(configdir)->data);
+  
+  return secStatus == SECSuccess ? Qt : Qnil;
+}
+
+DEFUN ("pr-geterror", Fpr_geterror, Spr_geterror,
+       0, 0, 0,
+       "Get last error code. XXX")
+     ()
+{
+  Lisp_Object lispy_val;
+  PRErrorCode err;
+
+  err = PR_GetError();
+
+  XSETINT (lispy_val, err);
+
+  return lispy_val;
+}
+
+DEFUN ("nss-setdomesticpolicy", Fnss_setdomesticpolicy, Snss_setdomesticpolicy,
+       0, 0, 0,
+       "Configures cipher suites to conform with current U.S. export\n\
+regulations related to domestic software products with encryption\n\
+features.")
+     ()
+{
+  SECStatus   secStatus;
+  
+  secStatus = NSS_SetDomesticPolicy();
+  
+  return secStatus == SECSuccess ? Qt : Qnil;
+}
+
+DEFUN ("nss-setexportpolicy", Fnss_setexportpolicy, Snss_setexportpolicy,
+       0, 0, 0,
+       "Configures the SSL cipher suites to conform with current U.S. export\n\
+regulations related to international software products with encryption\n\
+features.")
+     ()
+{
+  SECStatus   secStatus;
+  
+  secStatus = NSS_SetExportPolicy();
+  
+  return secStatus == SECSuccess ? Qt : Qnil;
+}
+
+DEFUN ("nss-shutdown", Fnss_shutdown, Snss_shutdown,
+       0, 0, 0,
+       "Closes the key and certificate databases.")
+     ()
+{
+  NSS_Shutdown();
+
+  return Qt;
+}
+
+DEFUN ("ssl-cipherprefsetdefault", Fssl_cipherprefsetdefault,
+       Sssl_cipherprefsetdefault,
+       2, 2, 0,
+       "Enables or disables SSL2 or SSL3 cipher suites (subject to which\n\
+cipher suites are permitted or disallowed by previous calls to one or\n\
+more of the SSL Export Policy Functions). This function must be called\n\
+once for each cipher you want to enable or disable by default.")
+     (Cipher, enabled)
+     Lisp_Object Cipher, enabled;
+{
+  SECStatus secStatus;
+  PRInt32 pr_cipher;
+  PRBool pr_enabled;
+
+  pr_cipher = XFASTINT(Cipher);
+  pr_enabled = !NILP (enabled);
+  secStatus = SSL_CipherPrefSetDefault(pr_cipher, pr_enabled);
+
+  return secStatus == SECSuccess ? Qt : Qnil;
+}
+
+DEFUN ("ssl-importfd", Fssl_importfd, Sssl_importfd,
+       2, 2, 0,
+       "Imports a process FD into SSL using defaults from MODEL. XXX")
+     (model, fd)
+     Lisp_Object model, fd;
+{
+  PRFileDesc *pr_model, *pr_fd;
+
+  CHECK_PROCESS (fd, 0);
+
+  pr_fd = (PRFileDesc*) XPROCESS (fd)->nss_fd;
+  if (NILP (model))
+    pr_model = NULL;
+  else
+    pr_model = (PRFileDesc*) XPROCESS (model)->nss_fd;
+  
+  pr_fd = SSL_ImportFD(pr_model, pr_fd);
+  if (pr_fd == NULL) {
+    return Qnil;
+  }
+  XSETINT (XPROCESS (fd)->nss_fd, pr_fd);
+
+  return fd;
+}
+
+DEFUN ("ssl-optionset", Fssl_optionset, Sssl_optionset,
+       3, 3, 0,
+       "Sets a single configuration parameter of a specified socket. Call once
+for each parameter you want to change. XXX")
+     (fd, option, on)
+     Lisp_Object fd, option, on;
+{
+  SECStatus   secStatus;
+  PRFileDesc *pr_fd;
+  PRInt32 pr_option;
+  PRBool pr_on;
+
+  CHECK_PROCESS (fd, 0);
+
+  pr_fd = (PRFileDesc*) XPROCESS (fd)->nss_fd;
+  pr_option = XFASTINT(option);
+  if (NILP(on))
+    pr_on = PR_FALSE;
+  else
+    pr_on = PR_TRUE;
+
+  secStatus = SSL_OptionSet(pr_fd, pr_option, pr_on);
+
+  return secStatus == SECSuccess ? Qt : Qnil;
+}
+
+/* XXX SSL_GetClientAuthDataHook */
+
+/* XXX SSL_AuthCertificateHook */
+
+SECStatus 
+myBadCertHandler(void *arg, PRFileDesc *socket) 
+{
+  Lisp_Object *fd = (Lisp_Object*)arg;
+  Lisp_Object args[3];
+  SECStatus secStatus = SECFailure;
+
+  if (!NILP (XPROCESS(*fd)->ssl_badcerthook))
+    {
+      args[0] = XPROCESS(*fd)->ssl_badcerthook;
+      args[1] = XPROCESS(*fd)->ssl_badcerthook_arg;
+      if (!NILP(Ffuncall (2, args)))
+	secStatus = SECSuccess;
+    }
+
+  return secStatus;
+}
+
+DEFUN ("ssl-badcerthook", Fssl_badcerthook, Sssl_badcerthook,
+       2, 3, 0,
+       "Sets up a callback function to deal with a situation where the SSL_AuthCertificate callback function has failed. This callback function allows the application to override the decision made by the certificate authorization callback and authorize the certificate for use in the SSL connection. XXX")
+     (fd, f, arg)
+     Lisp_Object fd, f, arg;
+{
+  SECStatus   secStatus;
+  PRFileDesc *pr_fd;
+
+  CHECK_PROCESS (fd, 0);
+
+  pr_fd = (PRFileDesc*) XPROCESS (fd)->nss_fd;
+
+  XPROCESS (fd)->ssl_badcerthook = f;
+  XPROCESS (fd)->ssl_badcerthook_arg = arg;
+
+  secStatus = SSL_BadCertHook(pr_fd, 
+			      (SSLBadCertHandler)myBadCertHandler, (void*)&fd);
+
+  return secStatus == SECSuccess ? Qt : Qnil;
+}
+
+/* XXX SSL_HandshakeCallback */
+
+DEFUN ("ssl-setpkcs11pinarg", Fssl_setpkcs11pinarg, Sssl_setpkcs11pinarg,
+       2, 2, 0,
+       "Sets the argument passed to the password callback function\n\
+specified by a call to pk11-setpasswordfunc. XXX")
+     (fd, a)
+     Lisp_Object fd, a;
+{
+  SECStatus   secStatus;
+  PRFileDesc *pr_fd;
+
+  CHECK_PROCESS (fd, 0);
+
+  pr_fd = (PRFileDesc*) XPROCESS (fd)->nss_fd;
+
+  /* Set certdb password. */
+  secStatus = SSL_SetPKCS11PinArg(pr_fd, (void*)XSTRING(a)->data);
+
+  return secStatus == SECSuccess ? Qt : Qnil;
+}
+
+DEFUN ("ssl-seturl", Fssl_seturl, Sssl_seturl,
+       2, 2, 0,
+       "Sets the domain name of the intended server in the clients SSL\n\
+socket. XXX")
+     (fd, url)
+     Lisp_Object fd, url;
+{
+  SECStatus   secStatus;
+  PRFileDesc *pr_fd;
+
+  CHECK_PROCESS (fd, 0);
+
+  pr_fd = (PRFileDesc*) XPROCESS (fd)->nss_fd;
+
+  /* Set SSL end-point hostname */
+  secStatus = SSL_SetURL(pr_fd, XSTRING(url)->data);
+
+  return secStatus == SECSuccess ? Qt : Qnil;
+}
+
+DEFUN ("ssl-resethandshake", Fssl_resethandshake, Sssl_resethandshake,
+       2, 2, 0,
+       "Resets the handshake state for a specified process. XXX")
+     (fd, asServer)
+     Lisp_Object fd, asServer;
+{
+  SECStatus   secStatus;
+  PRFileDesc *pr_fd;
+  PRBool pr_asServer;
+
+  CHECK_PROCESS (fd, 0);
+
+  pr_fd = (PRFileDesc*) XPROCESS (fd)->nss_fd;
+  if (NILP (asServer))
+    pr_asServer = PR_FALSE;
+  else
+    pr_asServer = PR_TRUE;
+
+  /* Start SSL handshake.*/
+  secStatus = SSL_ResetHandshake(pr_fd, pr_asServer);
+
+  return secStatus == SECSuccess ? Qt : Qnil;
+}
+
+DEFUN ("ssl-forcehandshake", Fssl_forcehandshake, Sssl_forcehandshake,
+       1, 1, 0,
+       "Drives a handshake for a specified SSL process to completion on a
+process that has already been prepared to do a handshake or is in the
+middle of doing a handshake. XXX")
+     (fd)
+     Lisp_Object fd;
+{
+  SECStatus   secStatus;
+  PRFileDesc *pr_fd, *sslin;
+  PRBool pr_asServer;
+
+  CHECK_PROCESS (fd, 0);
+
+  pr_fd = (PRFileDesc*) XPROCESS (fd)->nss_fd;
+
+  /* Finish SSL handshake.*/
+  secStatus = SSL_ForceHandshake(pr_fd);
+
+  /* XXX */
+  printSecurityInfo(pr_fd);
+
+  return secStatus == SECSuccess ? Qt : Qnil;
+}
+
 /* 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
@@ -2067,6 +2374,18 @@
 #endif
 #endif
 
+  {
+    PRFileDesc *tmp;
+
+    tmp = PR_ImportTCPSocket(inch);
+    if (tmp == NULL) {
+      puts("can't import socket");
+      abort();
+    }
+    /* FIXME: ugly */
+    XSETINT (XPROCESS (proc)->nss_fd, tmp); 
+  }
+
   XPROCESS (proc)->childp = Fcons (host, Fcons (service, Qnil));
   XPROCESS (proc)->command_channel_p = Qnil;
   XPROCESS (proc)->buffer = buffer;
@@ -2918,12 +3237,20 @@
     bcopy (XSTRING (p->decoding_buf)->data, chars, carryover);
 
   if (proc_buffered_char[channel] < 0)
-    nbytes = emacs_read (channel, chars + carryover, 1024 - carryover);
+    if (NETCONN_P(proc))
+      nbytes = emacs_socketread (XPROCESS(proc)->nss_fd,
+				 chars + carryover, 1024 - carryover);
+    else
+      nbytes = emacs_read (channel, chars + carryover, 1024 - carryover);
   else
     {
       chars[carryover] = proc_buffered_char[channel];
       proc_buffered_char[channel] = -1;
-      nbytes = emacs_read (channel, chars + carryover + 1,  1023 - carryover);
+      if (NETCONN_P(proc))
+	nbytes = emacs_socketread (XPROCESS(proc)->nss_fd,
+				   chars + carryover + 1,  1023 - carryover);
+      else
+	nbytes = emacs_read (channel, chars + carryover + 1,  1023 - carryover);
       if (nbytes < 0)
 	nbytes = 1;
       else
@@ -3385,8 +3712,12 @@
 	  while (this > 0)
 	    {
 	      old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
-	      rv = emacs_write (XINT (XPROCESS (proc)->outfd),
-				(char *) buf, this);
+	      if (NETCONN_P(proc))
+		rv = emacs_socketwrite (XPROCESS (proc)->nss_fd,
+					(char *) buf, this);
+	      else
+		rv = emacs_write (XINT (XPROCESS (proc)->outfd),
+				  (char *) buf, this);
 	      signal (SIGPIPE, old_sigpipe);
 
 	      if (rv < 0)
@@ -4594,6 +4925,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 +5018,22 @@
 /*  defsubr (&Sprocess_connection); */
   defsubr (&Sset_process_coding_system);
   defsubr (&Sprocess_coding_system);
+
+  /* NSS/SSL bindings: */
+  defsubr (&Snss_init);
+  defsubr (&Snss_initreadwrite);
+  defsubr (&Spr_geterror);
+  defsubr (&Snss_setdomesticpolicy);
+  defsubr (&Snss_setexportpolicy);
+  defsubr (&Snss_shutdown);
+  defsubr (&Sssl_cipherprefsetdefault);
+  defsubr (&Sssl_importfd);
+  defsubr (&Sssl_optionset);
+  defsubr (&Sssl_badcerthook);
+  defsubr (&Sssl_setpkcs11pinarg);
+  defsubr (&Sssl_seturl);
+  defsubr (&Sssl_resethandshake);
+  defsubr (&Sssl_forcehandshake);
 }
 
 
diff -ur --new-file 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	Sun May  6 00:45:48 2001
@@ -91,6 +91,10 @@
     /* Flag to set coding-system of the process buffer from the
        coding_system used to decode process output.  */
     Lisp_Object inherit_coding_system_flag;
+    /* Ugly hack to store NSS fd pointer until I change GC in alloc.c */
+    Lisp_Object nss_fd;
+    /* BadCertHook */
+    Lisp_Object ssl_badcerthook, ssl_badcerthook_arg;
 };
 
 /* Every field in the preceding structure except for the first two
diff -ur --new-file 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	Sat May  5 22:09:48 2001
@@ -3269,6 +3269,8 @@
   return rtnval;
 }
 
+#include <nspr.h>
+
 int
 emacs_read (fildes, buf, nbyte)
      int fildes;
@@ -3276,9 +3278,24 @@
      unsigned int nbyte;
 {
   register int rtnval;
-  
+
   while ((rtnval = read (fildes, buf, nbyte)) == -1
 	 && (errno == EINTR));
+
+  return (rtnval);
+}
+
+int
+emacs_socketread (fildes, buf, nbyte)
+     PRFileDesc *fildes;
+     char *buf;
+     unsigned int nbyte;
+{
+  register int rtnval;
+
+  while ((rtnval = PR_Read (fildes, buf, nbyte)) == -1
+	 && (errno == EINTR));
+
   return (rtnval);
 }
 
@@ -3295,6 +3312,35 @@
   while (nbyte > 0)
     {
       rtnval = write (fildes, buf, nbyte);
+
+      if (rtnval == -1)
+	{
+	  if (errno == EINTR)
+	    continue;
+	  else
+	    return (bytes_written ? bytes_written : -1);
+	}
+
+      buf += rtnval;
+      nbyte -= rtnval;
+      bytes_written += rtnval;
+    }
+  return (bytes_written);
+}
+
+int
+emacs_socketwrite (fildes, buf, nbyte)
+     PRFileDesc *fildes;
+     char *buf;
+     unsigned int nbyte;
+{
+  register int rtnval, bytes_written;
+
+  bytes_written = 0;
+
+  while (nbyte > 0)
+    {
+      rtnval = PR_Write (fildes, buf, nbyte);
 
       if (rtnval == -1)
 	{
