Initial checkin of the PSM server

This commit is contained in:
ddrinan%netscape.com 2000-04-12 00:05:55 +00:00
parent 227679761c
commit 77f8a8b6ac
79 changed files with 43625 additions and 0 deletions

View File

@ -0,0 +1,101 @@
/* General NSPR 2.0 errors */
/* Caller must #include "prerror.h" */
ER2( PR_OUT_OF_MEMORY_ERROR, "Memory allocation attempt failed." )
ER2( PR_BAD_DESCRIPTOR_ERROR, "Invalid file descriptor." )
ER2( PR_WOULD_BLOCK_ERROR, "The operation would have blocked." )
ER2( PR_ACCESS_FAULT_ERROR, "Invalid memory address argument." )
ER2( PR_INVALID_METHOD_ERROR, "Invalid function for file type." )
ER2( PR_ILLEGAL_ACCESS_ERROR, "Invalid memory address argument." )
ER2( PR_UNKNOWN_ERROR, "Some unknown error has occurred." )
ER2( PR_PENDING_INTERRUPT_ERROR,"Operation interrupted by another thread." )
ER2( PR_NOT_IMPLEMENTED_ERROR, "function not implemented." )
ER2( PR_IO_ERROR, "I/O function error." )
ER2( PR_IO_TIMEOUT_ERROR, "I/O operation timed out." )
ER2( PR_IO_PENDING_ERROR, "I/O operation on busy file descriptor." )
ER2( PR_DIRECTORY_OPEN_ERROR, "The directory could not be opened." )
ER2( PR_INVALID_ARGUMENT_ERROR, "Invalid function argument." )
ER2( PR_ADDRESS_NOT_AVAILABLE_ERROR, "Network address not available (in use?)." )
ER2( PR_ADDRESS_NOT_SUPPORTED_ERROR, "Network address type not supported." )
ER2( PR_IS_CONNECTED_ERROR, "Already connected." )
ER2( PR_BAD_ADDRESS_ERROR, "Network address is invalid." )
ER2( PR_ADDRESS_IN_USE_ERROR, "Local Network address is in use." )
ER2( PR_CONNECT_REFUSED_ERROR, "Connection refused by peer." )
ER2( PR_NETWORK_UNREACHABLE_ERROR, "Network address is presently unreachable." )
ER2( PR_CONNECT_TIMEOUT_ERROR, "Connection attempt timed out." )
ER2( PR_NOT_CONNECTED_ERROR, "Network file descriptor is not connected." )
ER2( PR_LOAD_LIBRARY_ERROR, "Failure to load dynamic library." )
ER2( PR_UNLOAD_LIBRARY_ERROR, "Failure to unload dynamic library." )
ER2( PR_FIND_SYMBOL_ERROR,
"Symbol not found in any of the loaded dynamic libraries." )
ER2( PR_INSUFFICIENT_RESOURCES_ERROR, "Insufficient system resources." )
ER2( PR_DIRECTORY_LOOKUP_ERROR,
"A directory lookup on a network address has failed." )
ER2( PR_TPD_RANGE_ERROR,
"Attempt to access a TPD key that is out of range." )
ER2( PR_PROC_DESC_TABLE_FULL_ERROR, "Process open FD table is full." )
ER2( PR_SYS_DESC_TABLE_FULL_ERROR, "System open FD table is full." )
ER2( PR_NOT_SOCKET_ERROR,
"Network operation attempted on non-network file descriptor." )
ER2( PR_NOT_TCP_SOCKET_ERROR,
"TCP-specific function attempted on a non-TCP file descriptor." )
ER2( PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "TCP file descriptor is already bound." )
ER2( PR_NO_ACCESS_RIGHTS_ERROR, "Access Denied." )
ER2( PR_OPERATION_NOT_SUPPORTED_ERROR,
"The requested operation is not supported by the platform." )
ER2( PR_PROTOCOL_NOT_SUPPORTED_ERROR,
"The host operating system does not support the protocol requested." )
ER2( PR_REMOTE_FILE_ERROR, "Access to the remote file has been severed." )
ER2( PR_BUFFER_OVERFLOW_ERROR,
"The value requested is too large to be stored in the data buffer provided." )
ER2( PR_CONNECT_RESET_ERROR, "TCP connection reset by peer." )
ER2( PR_RANGE_ERROR, "Unused." )
ER2( PR_DEADLOCK_ERROR, "The operation would have deadlocked." )
ER2( PR_FILE_IS_LOCKED_ERROR, "The file is already locked." )
ER2( PR_FILE_TOO_BIG_ERROR,
"Write would result in file larger than the system allows." )
ER2( PR_NO_DEVICE_SPACE_ERROR, "The device for storing the file is full." )
ER2( PR_PIPE_ERROR, "Unused." )
ER2( PR_NO_SEEK_DEVICE_ERROR, "Unused." )
ER2( PR_IS_DIRECTORY_ERROR,
"Cannot perform a normal file operation on a directory." )
ER2( PR_LOOP_ERROR, "Symbolic link loop." )
ER2( PR_NAME_TOO_LONG_ERROR, "File name is too long." )
ER2( PR_FILE_NOT_FOUND_ERROR, "File not found." )
ER2( PR_NOT_DIRECTORY_ERROR,
"Cannot perform directory operation on a normal file." )
ER2( PR_READ_ONLY_FILESYSTEM_ERROR,
"Cannot write to a read-only file system." )
ER2( PR_DIRECTORY_NOT_EMPTY_ERROR,
"Cannot delete a directory that is not empty." )
ER2( PR_FILESYSTEM_MOUNTED_ERROR,
"Cannot delete or rename a file object while the file system is busy." )
ER2( PR_NOT_SAME_DEVICE_ERROR,
"Cannot rename a file to a file system on another device." )
ER2( PR_DIRECTORY_CORRUPTED_ERROR,
"The directory object in the file system is corrupted." )
ER2( PR_FILE_EXISTS_ERROR,
"Cannot create or rename a filename that already exists." )
ER2( PR_MAX_DIRECTORY_ENTRIES_ERROR,
"Directory is full. No additional filenames may be added." )
ER2( PR_INVALID_DEVICE_STATE_ERROR,
"The required device was in an invalid state." )
ER2( PR_DEVICE_IS_LOCKED_ERROR, "The device is locked." )
ER2( PR_NO_MORE_FILES_ERROR, "No more entries in the directory." )
ER2( PR_END_OF_FILE_ERROR, "Encountered end of file." )
ER2( PR_FILE_SEEK_ERROR, "Seek error." )
ER2( PR_FILE_IS_BUSY_ERROR, "The file is busy." )
ER2( PR_IN_PROGRESS_ERROR,
"Operation is still in progress (probably a non-blocking connect)." )
ER2( PR_ALREADY_INITIATED_ERROR,
"Operation has already been initiated (probably a non-blocking connect)." )
#ifdef PR_GROUP_EMPTY_ERROR
ER2( PR_GROUP_EMPTY_ERROR, "The wait group is empty." )
#endif
#ifdef PR_INVALID_STATE_ERROR
ER2( PR_INVALID_STATE_ERROR, "Object state improper for request." )
#endif
ER2( PR_MAX_ERROR, "Placeholder for the end of the list" )

View File

@ -0,0 +1,385 @@
/* General security error codes */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
/* Caller must #include "secerr.h" */
ER3(SEC_ERROR_IO, SEC_ERROR_BASE + 0,
"An I/O error occurred during security authorization.")
ER3(SEC_ERROR_LIBRARY_FAILURE, SEC_ERROR_BASE + 1,
"security library failure.")
ER3(SEC_ERROR_BAD_DATA, SEC_ERROR_BASE + 2,
"security library: received bad data.")
ER3(SEC_ERROR_OUTPUT_LEN, SEC_ERROR_BASE + 3,
"security library: output length error.")
ER3(SEC_ERROR_INPUT_LEN, SEC_ERROR_BASE + 4,
"security library has experienced an input length error.")
ER3(SEC_ERROR_INVALID_ARGS, SEC_ERROR_BASE + 5,
"security library: invalid arguments.")
ER3(SEC_ERROR_INVALID_ALGORITHM, SEC_ERROR_BASE + 6,
"security library: invalid algorithm.")
ER3(SEC_ERROR_INVALID_AVA, SEC_ERROR_BASE + 7,
"security library: invalid AVA.")
ER3(SEC_ERROR_INVALID_TIME, SEC_ERROR_BASE + 8,
"security library: invalid time.")
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.")
#if 0 /* This was defined AFTER HCL 1.5 was released. */
ER3(SEC_ERROR_CERT_NOT_IN_NAME_SPACE, (SEC_ERROR_BASE + 112),
"The Certifying Authority for this certifcate is not permitted to issue a \
certifcate with this name.")
#endif

View File

@ -0,0 +1,323 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
/* SSL-specific security error codes */
/* caller must include "sslerr.h" */
ER3(SSL_ERROR_EXPORT_ONLY_SERVER, SSL_ERROR_BASE + 0,
"Unable to communicate securely. Peer does not support high-grade encryption.")
ER3(SSL_ERROR_US_ONLY_SERVER, SSL_ERROR_BASE + 1,
"Unable to communicate securely. Peer requires high-grade encryption which is not supported.")
ER3(SSL_ERROR_NO_CYPHER_OVERLAP, SSL_ERROR_BASE + 2,
"Cannot communicate securely with peer: no common encryption algorithm(s).")
ER3(SSL_ERROR_NO_CERTIFICATE, SSL_ERROR_BASE + 3,
"Unable to find the certificate or key necessary for authentication.")
ER3(SSL_ERROR_BAD_CERTIFICATE, SSL_ERROR_BASE + 4,
"Unable to communicate securely with peer: peers's certificate was rejected.")
/* unused (SSL_ERROR_BASE + 5),*/
ER3(SSL_ERROR_BAD_CLIENT, SSL_ERROR_BASE + 6,
"The server has encountered bad data from the client.")
ER3(SSL_ERROR_BAD_SERVER, SSL_ERROR_BASE + 7,
"The client has encountered bad data from the server.")
ER3(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE, SSL_ERROR_BASE + 8,
"Unsupported certificate type.")
ER3(SSL_ERROR_UNSUPPORTED_VERSION, SSL_ERROR_BASE + 9,
"Peer using unsupported version of security protocol.")
/* unused (SSL_ERROR_BASE + 10),*/
ER3(SSL_ERROR_WRONG_CERTIFICATE, SSL_ERROR_BASE + 11,
"Client authentication failed: private key in key database does not match public key in certificate database.")
ER3(SSL_ERROR_BAD_CERT_DOMAIN, SSL_ERROR_BASE + 12,
"Unable to communicate securely with peer: requested domain name does not match the server's certificate.")
/* SSL_ERROR_POST_WARNING (SSL_ERROR_BASE + 13),
defined in sslerr.h
*/
ER3(SSL_ERROR_SSL2_DISABLED, (SSL_ERROR_BASE + 14),
"Peer only supports SSL version 2, which is locally disabled.")
ER3(SSL_ERROR_BAD_MAC_READ, (SSL_ERROR_BASE + 15),
"SSL received a record with an incorrect Message Authentication Code.")
ER3(SSL_ERROR_BAD_MAC_ALERT, (SSL_ERROR_BASE + 16),
"SSL peer reports incorrect Message Authentication Code.")
ER3(SSL_ERROR_BAD_CERT_ALERT, (SSL_ERROR_BASE + 17),
"SSL peer cannot verify your certificate.")
ER3(SSL_ERROR_REVOKED_CERT_ALERT, (SSL_ERROR_BASE + 18),
"SSL peer rejected your certificate as revoked.")
ER3(SSL_ERROR_EXPIRED_CERT_ALERT, (SSL_ERROR_BASE + 19),
"SSL peer rejected your certificate as expired.")
ER3(SSL_ERROR_SSL_DISABLED, (SSL_ERROR_BASE + 20),
"Cannot connect: SSL is disabled.")
ER3(SSL_ERROR_FORTEZZA_PQG, (SSL_ERROR_BASE + 21),
"Cannot connect: SSL peer is in another FORTEZZA domain.")
ER3(SSL_ERROR_UNKNOWN_CIPHER_SUITE , (SSL_ERROR_BASE + 22),
"An unknown SSL cipher suite has been requested.")
ER3(SSL_ERROR_NO_CIPHERS_SUPPORTED , (SSL_ERROR_BASE + 23),
"No cipher suites are present and enabled in this program.")
ER3(SSL_ERROR_BAD_BLOCK_PADDING , (SSL_ERROR_BASE + 24),
"SSL received a record with bad block padding.")
ER3(SSL_ERROR_RX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 25),
"SSL received a record that exceeded the maximum permissible length.")
ER3(SSL_ERROR_TX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 26),
"SSL attempted to send a record that exceeded the maximum permissible length.")
/*
* Received a malformed (too long or short or invalid content) SSL handshake.
*/
ER3(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST , (SSL_ERROR_BASE + 27),
"SSL received a malformed Hello Request handshake message.")
ER3(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO , (SSL_ERROR_BASE + 28),
"SSL received a malformed Client Hello handshake message.")
ER3(SSL_ERROR_RX_MALFORMED_SERVER_HELLO , (SSL_ERROR_BASE + 29),
"SSL received a malformed Server Hello handshake message.")
ER3(SSL_ERROR_RX_MALFORMED_CERTIFICATE , (SSL_ERROR_BASE + 30),
"SSL received a malformed Certificate handshake message.")
ER3(SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 31),
"SSL received a malformed Server Key Exchange handshake message.")
ER3(SSL_ERROR_RX_MALFORMED_CERT_REQUEST , (SSL_ERROR_BASE + 32),
"SSL received a malformed Certificate Request handshake message.")
ER3(SSL_ERROR_RX_MALFORMED_HELLO_DONE , (SSL_ERROR_BASE + 33),
"SSL received a malformed Server Hello Done handshake message.")
ER3(SSL_ERROR_RX_MALFORMED_CERT_VERIFY , (SSL_ERROR_BASE + 34),
"SSL received a malformed Certificate Verify handshake message.")
ER3(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 35),
"SSL received a malformed Client Key Exchange handshake message.")
ER3(SSL_ERROR_RX_MALFORMED_FINISHED , (SSL_ERROR_BASE + 36),
"SSL received a malformed Finished handshake message.")
/*
* Received a malformed (too long or short) SSL record.
*/
ER3(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER , (SSL_ERROR_BASE + 37),
"SSL received a malformed Change Cipher Spec record.")
ER3(SSL_ERROR_RX_MALFORMED_ALERT , (SSL_ERROR_BASE + 38),
"SSL received a malformed Alert record.")
ER3(SSL_ERROR_RX_MALFORMED_HANDSHAKE , (SSL_ERROR_BASE + 39),
"SSL received a malformed Handshake record.")
ER3(SSL_ERROR_RX_MALFORMED_APPLICATION_DATA , (SSL_ERROR_BASE + 40),
"SSL received a malformed Application Data record.")
/*
* Received an SSL handshake that was inappropriate for the state we're in.
* E.g. Server received message from server, or wrong state in state machine.
*/
ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST , (SSL_ERROR_BASE + 41),
"SSL received an unexpected Hello Request handshake message.")
ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO , (SSL_ERROR_BASE + 42),
"SSL received an unexpected Client Hello handshake message.")
ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO , (SSL_ERROR_BASE + 43),
"SSL received an unexpected Server Hello handshake message.")
ER3(SSL_ERROR_RX_UNEXPECTED_CERTIFICATE , (SSL_ERROR_BASE + 44),
"SSL received an unexpected Certificate handshake message.")
ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 45),
"SSL received an unexpected Server Key Exchange handshake message.")
ER3(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST , (SSL_ERROR_BASE + 46),
"SSL received an unexpected Certificate Request handshake message.")
ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE , (SSL_ERROR_BASE + 47),
"SSL received an unexpected Server Hello Done handshake message.")
ER3(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY , (SSL_ERROR_BASE + 48),
"SSL received an unexpected Certificate Verify handshake message.")
ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 49),
"SSL received an unexpected Cllient Key Exchange handshake message.")
ER3(SSL_ERROR_RX_UNEXPECTED_FINISHED , (SSL_ERROR_BASE + 50),
"SSL received an unexpected Finished handshake message.")
/*
* Received an SSL record that was inappropriate for the state we're in.
*/
ER3(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER , (SSL_ERROR_BASE + 51),
"SSL received an unexpected Change Cipher Spec record.")
ER3(SSL_ERROR_RX_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 52),
"SSL received an unexpected Alert record.")
ER3(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE , (SSL_ERROR_BASE + 53),
"SSL received an unexpected Handshake record.")
ER3(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA, (SSL_ERROR_BASE + 54),
"SSL received an unexpected Application Data record.")
/*
* Received record/message with unknown discriminant.
*/
ER3(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE , (SSL_ERROR_BASE + 55),
"SSL received a record with an unknown content type.")
ER3(SSL_ERROR_RX_UNKNOWN_HANDSHAKE , (SSL_ERROR_BASE + 56),
"SSL received a handshake message with an unknown message type.")
ER3(SSL_ERROR_RX_UNKNOWN_ALERT , (SSL_ERROR_BASE + 57),
"SSL received an alert record with an unknown alert description.")
/*
* Received an alert reporting what we did wrong. (more alerts above)
*/
ER3(SSL_ERROR_CLOSE_NOTIFY_ALERT , (SSL_ERROR_BASE + 58),
"SSL peer has closed this connection.")
ER3(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 59),
"SSL peer was not expecting a handshake message it received.")
ER3(SSL_ERROR_DECOMPRESSION_FAILURE_ALERT , (SSL_ERROR_BASE + 60),
"SSL peer was unable to succesfully decompress an SSL record it received.")
ER3(SSL_ERROR_HANDSHAKE_FAILURE_ALERT , (SSL_ERROR_BASE + 61),
"SSL peer was unable to negotiate an acceptable set of security parameters.")
ER3(SSL_ERROR_ILLEGAL_PARAMETER_ALERT , (SSL_ERROR_BASE + 62),
"SSL peer rejected a handshake message for unacceptable content.")
ER3(SSL_ERROR_UNSUPPORTED_CERT_ALERT , (SSL_ERROR_BASE + 63),
"SSL peer does not support certificates of the type it received.")
ER3(SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT , (SSL_ERROR_BASE + 64),
"SSL peer had some unspecified issue with the certificate it received.")
ER3(SSL_ERROR_GENERATE_RANDOM_FAILURE , (SSL_ERROR_BASE + 65),
"SSL experienced a failure of its random number generator.")
ER3(SSL_ERROR_SIGN_HASHES_FAILURE , (SSL_ERROR_BASE + 66),
"Unable to digitally sign data required to verify your certificate.")
ER3(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE , (SSL_ERROR_BASE + 67),
"SSL was unable to extract the public key from the peer's certificate.")
ER3(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 68),
"Unspecified failure while processing SSL Server Key Exchange handshake.")
ER3(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 69),
"Unspecified failure while processing SSL Client Key Exchange handshake.")
ER3(SSL_ERROR_ENCRYPTION_FAILURE , (SSL_ERROR_BASE + 70),
"Bulk data encryption algorithm failed in selected cipher suite.")
ER3(SSL_ERROR_DECRYPTION_FAILURE , (SSL_ERROR_BASE + 71),
"Bulk data decryption algorithm failed in selected cipher suite.")
ER3(SSL_ERROR_SOCKET_WRITE_FAILURE , (SSL_ERROR_BASE + 72),
"Attempt to write encrypted data to underlying socket failed.")
ER3(SSL_ERROR_MD5_DIGEST_FAILURE , (SSL_ERROR_BASE + 73),
"MD5 digest function failed.")
ER3(SSL_ERROR_SHA_DIGEST_FAILURE , (SSL_ERROR_BASE + 74),
"SHA-1 digest function failed.")
ER3(SSL_ERROR_MAC_COMPUTATION_FAILURE , (SSL_ERROR_BASE + 75),
"MAC computation failed.")
ER3(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE , (SSL_ERROR_BASE + 76),
"Failure to create Symmetric Key context.")
ER3(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE , (SSL_ERROR_BASE + 77),
"Failure to unwrap the Symmetric key in Client Key Exchange message.")
ER3(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED , (SSL_ERROR_BASE + 78),
"SSL Server attempted to use domestic-grade public key with export cipher suite.")
ER3(SSL_ERROR_IV_PARAM_FAILURE , (SSL_ERROR_BASE + 79),
"PKCS11 code failed to translate an IV into a param.")
ER3(SSL_ERROR_INIT_CIPHER_SUITE_FAILURE , (SSL_ERROR_BASE + 80),
"Failed to initialize the selected cipher suite.")
ER3(SSL_ERROR_SESSION_KEY_GEN_FAILURE , (SSL_ERROR_BASE + 81),
"Client failed to generate session keys for SSL session.")
ER3(SSL_ERROR_NO_SERVER_KEY_FOR_ALG , (SSL_ERROR_BASE + 82),
"Server has no key for the attempted key exchange algorithm.")
ER3(SSL_ERROR_TOKEN_INSERTION_REMOVAL , (SSL_ERROR_BASE + 83),
"PKCS#11 token was inserted or removed while operation was in progress.")
ER3(SSL_ERROR_TOKEN_SLOT_NOT_FOUND , (SSL_ERROR_BASE + 84),
"No PKCS#11 token could be found to do a required operation.")
ER3(SSL_ERROR_NO_COMPRESSION_OVERLAP , (SSL_ERROR_BASE + 85),
"Cannot communicate securely with peer: no common compression algorithm(s).")
ER3(SSL_ERROR_HANDSHAKE_NOT_COMPLETED , (SSL_ERROR_BASE + 86),
"Cannot initiate another SSL handshake until current handshake is complete.")
ER3(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE , (SSL_ERROR_BASE + 87),
"Received incorrect handshakes hash values from peer.")
ER3(SSL_ERROR_CERT_KEA_MISMATCH , (SSL_ERROR_BASE + 88),
"The certificate provided cannot be used with the selected key exchange algorithm.")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,165 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __ADVISOR_H__
#define __ADVISOR_H__
/*
Security advisor object. We create this in order to determine what to show
in the generic "Security Info" pane, and to convey the right URL back to
the client for loading.
Created by mwelch 1999 February
*/
#include "resource.h"
#include "ctrlconn.h"
#include "certres.h"
#include "p7cinfo.h"
#include "slist.h"
#include "sslskst.h"
typedef struct InfoSecAdvisor
{
PRInt32 infoContext;
PRInt32 resID;
char *hostname;
char *senderAddr;
PRUint32 encryptedP7CInfo;
PRUint32 signedP7CInfo;
PRInt32 decodeError;
PRInt32 verifyError;
PRInt32 encryptthis;
PRInt32 signthis;
PRInt32 numRecipients;
char **recipients;
} InfoSecAdvisor;
typedef struct SSMSecurityAdvisorContext
{
SSMResource super;
/* Reference to Cartman object which we use to display
"Security Info" pane */
SSMResource *m_infoSource;
/* Width and height of the security advisor window,
loaded from resource file */
PRUint32 m_width, m_height;
/* Cached URL which we send back to client upon request */
char *m_url;
SSMSortedList *m_certhash;
PRIntn m_certsIncluded;
char *m_nickname;
PRInt32 infoContext;
PRInt32 resID;
char *hostname;
char *senderAddr;
PRUint32 encryptedP7CInfo;
PRUint32 signedP7CInfo;
PRInt32 decodeError;
PRInt32 verifyError;
PRInt32 encryptthis;
PRInt32 signthis;
PRInt32 numRecipients;
char **recipients;
char *selectedItemPage;
PRInt32 encrypted_b;
PRInt32 signed_b;
SSMP7ContentInfo * encryptedP7CInfoRes;
SSMP7ContentInfo * signedP7CInfoRes;
SSMSSLSocketStatus * socketStatus;
#if 0
/* data for Java principals */
char* m_principalsData;
#endif
} SSMSecurityAdvisorContext;
SSMStatus SSMSecurityAdvisorContext_Create(SSMControlConnection *ctrl,
InfoSecAdvisor *info,
SSMResource **res);
SSMStatus SSMSecurityAdvisorContext_Destroy(SSMResource *res, PRBool doFree);
void SSMSecurityAdvisorContext_Invariant(SSMSecurityAdvisorContext *ct);
SSMStatus SSMSecurityAdvisorContext_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMSecurityAdvisorContext_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMSecurityAdvisorContext_SetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value);
SSMStatus SSMSecurityAdvisorContext_FormSubmitHandler(SSMResource *res,
HTTPRequest *req);
SSMStatus SSMSecurityAdvisorContext_Print(SSMResource *res,
char *fmt, PRIntn numParam,
char **value, char **resultStr);
SSMStatus SSMSecurityAdvisorContext_DoPKCS12Response(HTTPRequest *req,
const char *responseKey);
SSMStatus SSMSecurityAdvisorContext_DoPKCS12Restore(SSMSecurityAdvisorContext *res,
HTTPRequest *req);
SSMStatus SSMSecurityAdvisorContext_DoPKCS12Backup(SSMSecurityAdvisorContext *cx,
HTTPRequest *req);
SSMStatus SSMSecurityAdvisorContext_Process_cert_mine_form(SSMSecurityAdvisorContext *res,
HTTPRequest *req);
SSMStatus SSMSecurityAdvisorContext_sa_selected_item(SSMTextGenContext* cx);
SSMStatus SSM_FreeTarget(SSMTextGenContext *cx);
SSMStatus
SSMSecurityAdvisorContext_GetPrefListKeywordHandler(SSMTextGenContext* cx);
SSMStatus SSM_SetDBPasswordHandler(HTTPRequest * req);
#if 0
SSMStatus SSM_JavaPrincipalsKeywordHandler(SSMTextGenContext* cx);
void SSM_HandleGetJavaPrincipalsReply(SSMControlConnection* ctrl,
SECItem* message);
#endif
SSMStatus SSM_RemovePrivilegesHandler(HTTPRequest* req);
SSMStatus SSM_OCSPResponderList(SSMTextGenContext* cx);
char* SSM_GetOCSPURL(CERTCertificate *cert, PrefSet *prefs);
PRBool SSM_IsOCSPEnabled(SSMControlConnection *connection);
#endif

View File

@ -0,0 +1,548 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "ctrlconn.h"
#include "cert.h"
#include "secasn1.h"
#include "secder.h"
#include "xconst.h"
#include "secerr.h"
#include "newproto.h"
#include "messages.h"
#include "certres.h"
#include "pk11func.h"
#include "secoid.h"
typedef struct CERTRenewalWindow {
SECItem begin;
SECItem end;
} CERTRenewalWindow;
const static SEC_ASN1Template CERT_RenewalWindowTemplate[] = {
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(CERTRenewalWindow) },
{ SEC_ASN1_GENERALIZED_TIME,
offsetof(CERTRenewalWindow,begin) },
{ SEC_ASN1_OPTIONAL | SEC_ASN1_GENERALIZED_TIME,
offsetof(CERTRenewalWindow,end) },
{ 0 }
};
PRBool CERT_HasRenewalExtension(CERTCertificate *cert)
{
int rv;
SECItem *derWindow = NULL;
PRBool ret = PR_FALSE;
/* Allocate from the heap, so that we can free eveything later */
derWindow = SECITEM_AllocItem(NULL, NULL, 0);
if (derWindow == NULL) {
goto loser;
}
/* Get the renewal window extension */
rv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME,
derWindow);
if (rv == SECSuccess) {
ret = PR_TRUE;
}
loser:
if (derWindow) {
SECITEM_FreeItem(derWindow, PR_TRUE);
}
return ret;
}
PRBool CERT_InRenewalWindow(CERTCertificate *cert, int64 t)
{
int rv;
int64 begin, end;
CERTRenewalWindow *window = NULL;
SECItem *derWindow = NULL;
PRArenaPool *arena = NULL;
PRBool ret = PR_FALSE;
/* Allocate from the heap, so that we can free eveything later */
derWindow = SECITEM_AllocItem(NULL, NULL, 0);
if (derWindow == NULL) {
goto loser;
}
/* Get the renewal window extension */
rv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME,
derWindow);
if (rv == SECFailure) {
goto loser;
}
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL)
goto loser;
window = (CERTRenewalWindow*)PORT_ArenaZAlloc(arena,
sizeof(CERTRenewalWindow));
if (window == NULL) {
goto loser;
}
/* Decode the extension */
rv = SEC_ASN1DecodeItem(arena, window, CERT_RenewalWindowTemplate, derWindow);
if (rv) {
goto loser;
}
/* Decode the times */
rv = DER_GeneralizedTimeToTime(&begin, &window->begin);
if (window->end.data) {
rv = DER_GeneralizedTimeToTime(&end, &window->end);
} else {
rv = DER_UTCTimeToTime(&end, &cert->validity.notAfter);
}
/* Is this cert in the renewal window */
if (LL_CMP(t,>,begin) && LL_CMP(t,<,end)) {
ret = PR_TRUE;
} else {
ret = PR_FALSE;
}
loser:
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
}
if (derWindow) {
SECITEM_FreeItem(derWindow, PR_TRUE);
}
return ret;
}
PRBool CERT_RenewalWindowExpired(CERTCertificate *cert, int64 t)
{
int rv;
int64 begin, end;
CERTRenewalWindow *window = NULL;
SECItem *derWindow = NULL;
PRArenaPool *arena = NULL;
PRBool ret = PR_FALSE;
/* Allocate from the heap, so that we can free eveything later */
derWindow = SECITEM_AllocItem(NULL, NULL, 0);
if (derWindow == NULL) {
goto loser;
}
/* Get the renewal window extension */
rv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME,
derWindow);
if (rv == SECFailure) {
goto loser;
}
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL)
goto loser;
window = (CERTRenewalWindow*)PORT_ArenaZAlloc(arena,
sizeof(CERTRenewalWindow));
if (window == NULL) {
goto loser;
}
/* Decode the extension */
rv = SEC_ASN1DecodeItem(arena, window, CERT_RenewalWindowTemplate, derWindow);
if (rv) {
goto loser;
}
/* Decode the times */
rv = DER_GeneralizedTimeToTime(&begin, &window->begin);
if (window->end.data) {
rv = DER_GeneralizedTimeToTime(&end, &window->end);
} else {
rv = DER_UTCTimeToTime(&end, &cert->validity.notAfter);
}
/* Has the renewal window expired */
if (LL_CMP(t,>,end)) {
ret = PR_TRUE;
} else {
ret = PR_FALSE;
}
loser:
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
}
if (derWindow) {
SECITEM_FreeItem(derWindow, PR_TRUE);
}
return ret;
}
char * CERT_GetAuthorityInfoAccessLocation(CERTCertificate *cert, int method)
{
CERTGeneralName *locname = NULL;
SECItem *location = NULL;
SECItem *encodedAuthInfoAccess = NULL;
CERTAuthInfoAccess **authInfoAccess = NULL;
char *locURI = NULL;
PRArenaPool *arena = NULL;
SECStatus rv;
int i;
/*
* Allocate this one from the heap because it will get filled in
* by CERT_FindCertExtension which will also allocate from the heap,
* and we can free the entire thing on our way out.
*/
encodedAuthInfoAccess = SECITEM_AllocItem(NULL, NULL, 0);
if (encodedAuthInfoAccess == NULL)
goto loser;
rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS,
encodedAuthInfoAccess);
if (rv == SECFailure)
goto loser;
/*
* The rest of the things allocated in the routine will come out of
* this arena, which is temporary just for us to decode and get at the
* AIA extension. The whole thing will be destroyed on our way out,
* after we have copied the location string (url) itself (if found).
*/
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL)
goto loser;
authInfoAccess = cert_DecodeAuthInfoAccessExtension(arena,
encodedAuthInfoAccess);
if (authInfoAccess == NULL)
goto loser;
for (i = 0; authInfoAccess[i] != NULL; i++) {
if (SECOID_FindOIDTag(&authInfoAccess[i]->method) == method)
locname = authInfoAccess[i]->location;
}
/*
* If we found an AIA extension, but it did not include an OCSP method,
* that should look to our caller as if we did not find the extension
* at all, because it is only an OCSP method that we care about.
* So set the same error that would be set if the AIA extension was
* not there at all.
*/
if (locname == NULL) {
PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
goto loser;
}
/*
* The following is just a pointer back into locname (i.e. not a copy);
* thus it should not be freed.
*/
location = CERT_GetGeneralNameByType(locname, certURI, PR_FALSE);
if (location == NULL) {
/*
* XXX Appears that CERT_GetGeneralNameByType does not set an
* error if there is no name by that type. For lack of anything
* better, act as if the extension was not found. In the future
* this should probably be something more like the extension was
* badly formed.
*/
PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
goto loser;
}
/*
* That location is really a string, but it has a specified length
* without a null-terminator. We need a real string that does have
* a null-terminator, and we need a copy of it anyway to return to
* our caller -- so allocate and copy.
*/
locURI = PORT_Alloc(location->len + 1);
if (locURI == NULL) {
goto loser;
}
PORT_Memcpy(locURI, location->data, location->len);
locURI[location->len] = '\0';
loser:
if (arena != NULL)
PORT_FreeArena(arena, PR_FALSE);
if (encodedAuthInfoAccess != NULL)
SECITEM_FreeItem(encodedAuthInfoAccess, PR_TRUE);
return locURI;
}
SSMStatus
SendRenewalUIEvent(SSMControlConnection *conn,
char *url)
{
SECItem event;
SSMStatus rv = PR_SUCCESS;
SSMResourceID rid = 0;
UIEvent reply;
if (!conn->m_doesUI) {
return SSM_FAILURE;
}
/* Generate the actual message to send to the client. */
reply.resourceID = rid;
reply.width = 715;
reply.height = 545;
reply.isModal = CM_FALSE;
reply.url = url;
reply.clientContext.len = 0;
reply.clientContext.data = NULL;
if (CMT_EncodeMessage(UIEventTemplate, (CMTItem*)&event, &reply) != CMTSuccess) {
goto loser;
}
/* Post the message on the outgoing control channel. */
rv = SSM_SendQMessage(conn->m_controlOutQ, SSM_PRIORITY_NORMAL,
SSM_EVENT_MESSAGE | SSM_UI_EVENT,
(int) event.len, (char *) event.data, PR_FALSE);
if (rv != PR_SUCCESS) goto loser;
goto done;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
PR_FREEIF(event.data);
return rv;
}
SECStatus CheckCertificate(CERTCertificate * cert, void * arg)
{
char *url = NULL;
SSMControlConnection *ctrl = (SSMControlConnection *)arg;
SSMStatus rv;
SSMResourceID certID;
SSMResourceCert * certRes = NULL;
CERTCertificate *otherCert = NULL;
CERTCertList *certs = NULL;
CERTCertListNode *node;
/* Is this cert in the renewal window */
if (CERT_InRenewalWindow(cert, PR_Now()) == PR_FALSE) {
goto done;
}
/* Get the AIA */
url = CERT_GetAuthorityInfoAccessLocation(cert, SEC_OID_CERT_RENEWAL_LOCATOR);
if (!url) {
goto done;
}
/* Should we renew this cert? Check the case where it has already been renewed */
/* but the old cert is still there waith a valid renewal window */
certs = PK11_FindCertsFromNickname(cert->nickname, ctrl);
if (!cert) {
goto done;
}
/* Interate through the certs */
node = CERT_LIST_HEAD(certs);
while (!CERT_LIST_END(node, certs)) {
otherCert = node->cert;
/* This is the cert we are renewing */
if (otherCert == cert) {
goto endloop;
}
/* This cert has expired */
if (CERT_CheckCertValidTimes(otherCert, PR_Now(), PR_FALSE) != secCertTimeValid) {
goto endloop;
}
/* This cert has different key usage */
if (cert->keyUsage != otherCert->keyUsage) {
goto endloop;
}
/* This cert renewal window has not expired - don't renew our cert */
if (CERT_HasRenewalExtension(otherCert) && !CERT_RenewalWindowExpired(otherCert, PR_Now())) {
goto done;
}
endloop:
node = CERT_LIST_NEXT(node);
}
/* Create a resource for this cert and get an id */
rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
cert,
ctrl,
&certID,
(SSMResource**)&certRes);
if (rv != PR_SUCCESS) {
goto done;
}
SSM_LockUIEvent((SSMResource*)certRes);
/* Send a UI event to client */
rv = SSMControlConnection_SendUIEvent(ctrl, "get",
"cert_renewal",
&(certRes->super), NULL, &(&(ctrl->super.super))->m_clientContext);
if (rv != SSM_SUCCESS) {
goto loser;
}
SSM_WaitUIEvent((SSMResource*)certRes, PR_INTERVAL_NO_TIMEOUT);
if ((certRes->super.m_buttonType == SSM_BUTTON_OK) && (certRes->m_renewCert == PR_TRUE)) {
/* Send a UI event asking about renewal */
/* Send UI prompting the user */
SendRenewalUIEvent(ctrl, url);
}
loser:
done:
if (certs) {
CERT_DestroyCertList(certs);
}
if (certRes) {
SSM_FreeResource(certRes);
}
PR_FREEIF(url);
return SECSuccess;
}
void SSM_CertificateRenewalThread(void * arg)
{
int series, slotSeries[255], i = 0;
PK11SlotList * slots = NULL;
PK11SlotListElement * le = NULL;
SSMControlConnection *ctrl = (SSMControlConnection *)arg;
/* Initialize slot series array to zero */
memset(slotSeries, 0, sizeof(slotSeries));
/* Get a list of tokens installed */
slots = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, ctrl);
if (!slots) {
return;
}
while (1) {
/* Interate over the list of slots */
for (le = slots->head, i= 0; le; le = le->next, i++) {
/* If there is no token present then we are no interested */
if (!PK11_IsPresent(le->slot)) {
continue;
}
/* If token not logged in, then we are not interested */
if (!PK11_IsLoggedIn(le->slot, ctrl)) {
continue;
}
/* If token is read-only, then we are not interested */
if (PK11_IsReadOnly(le->slot)) {
continue;
}
/* Get the series and mark as checked */
series = PK11_GetSlotSeries(le->slot);
if (slotSeries[i] == series) {
continue;
}
slotSeries[i] = series;
/* Interate all the certs on the token */
PK11_TraverseCertsInSlot(le->slot, CheckCertificate, ctrl);
}
/* Sleep for one minute */
PR_Sleep(PR_TicksPerSecond()*60);
}
if (slots) {
PK11_FreeSlotList(slots);
}
}
SSMStatus SSM_RenewalCertInfoHandler(SSMTextGenContext* cx)
{
SSMStatus rv;
SSMResource* target = NULL;
SSMResourceCert* renewalCertRes = NULL;
CERTCertificate* renewalCert = NULL;
char *fmt = NULL, *issuerCN = NULL;
char *validNotBefore = NULL, *validNotAfter = NULL;
PR_ASSERT(cx != NULL);
PR_ASSERT(cx->m_request != NULL);
PR_ASSERT(cx->m_params != NULL);
PR_ASSERT(cx->m_result != NULL);
/* retrieve the renewal cert */
target = SSMTextGen_GetTargetObject(cx);
renewalCertRes = (SSMResourceCert*)target;
renewalCert = renewalCertRes->cert;
if (renewalCert == NULL) {
goto loser;
}
/* Get the info */
/* This is: Name, issuer, valid from and valid to */
issuerCN = CERT_GetCommonName(&renewalCert->issuer),
validNotBefore = DER_UTCDayToAscii(&renewalCert->validity.notBefore);
validNotAfter = DER_UTCDayToAscii(&renewalCert->validity.notAfter);
rv = SSM_GetAndExpandTextKeyedByString(cx, "cert_renewal_cert_info", &fmt);
if (rv != SSM_SUCCESS) {
goto loser;
}
cx->m_result = PR_smprintf(fmt, renewalCert->nickname, validNotBefore, validNotAfter, issuerCN);
PR_FREEIF(fmt);
PR_FREEIF(issuerCN);
PR_FREEIF(validNotBefore);
PR_FREEIF(validNotAfter);
return SSM_SUCCESS;
loser:
PR_FREEIF(fmt);
PR_FREEIF(issuerCN);
PR_FREEIF(validNotBefore);
PR_FREEIF(validNotAfter);
return SSM_FAILURE;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,71 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "textgen.h"
#include "minihttp.h"
#include "certres.h"
typedef enum
{
certHashRemove = (int) -1,
certHashAdd = 1
} ssmCertHashAction;
/* Since there isn't a strict 1-1 match between SSLCA and SECCertUsage
(we lump SSL and SSL-with-step-up certs together at the moment, for eg),
we have an enum of our own to indicate what to get from the cert db. */
typedef enum
{
clNoUsage = -1,
clAllMine = 0,
clSSLClient,
clEmailSigner,
clMyObjSigning,
clSSLServer,
clEmailRecipient,
clAllCA
} ssmCLCertUsage;
typedef struct
{
char * certEntry;
ssmCLCertUsage usage;
PRBool isEmailSigner;
} ssmCertData;
SSMStatus SSM_CertListKeywordHandler(SSMTextGenContext *cx);
SSMStatus SSM_SetLocaleCommandHandler(HTTPRequest *req);
SSMStatus SSM_ReloadTextCommandHandler(HTTPRequest *req);
SSMStatus SSM_ChangeCertSecAdvisorList(HTTPRequest * req, char * nickname,
ssmCertHashAction action);
PRIntn certlist_compare_strings(const void * v1, const void *v2);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,134 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __NSM_CERTRES_H__
#define __NSM_CERTRES_H__
#include "servimpl.h"
#include "resource.h"
#include "cert.h"
#include "certdb.h"
#include "secder.h"
#include "ctrlconn.h"
#include "minihttp.h"
#include "textgen.h"
struct _ssm_resource_cert;
typedef SSMStatus (*SSMCertResourceVerifyFunc)
(struct _ssm_resource_cert * resource,
SECCertUsage certUsage);
typedef SSMStatus (*SSMCertResourceDeleteCertFunc)
(struct _ssm_resource_cert * resource);
typedef struct _ssm_resource_cert
{
SSMResource super;
CERTCertificate * cert;
SSMCertResourceVerifyFunc m_verify_func;
SSMCertResourceDeleteCertFunc m_deletecert_func;
PRBool m_markedForDeletion;
PRBool m_renewCert;
} SSMResourceCert;
/*
* Cert resource can be created from a CERTCertificate or when unpickling.
*/
typedef enum {
SSM_RESOURCE_CERT_CREATE_NEW = 0L,
SSM_RESOURCE_CERT_CREATE_UNPICKLE
} SSMResourceCertCreate;
/* Functions of the certResource class */
SSMStatus SSMResourceCert_Create(void * arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMResourceCert_Init(SSMResourceCert * certResource,
SSMControlConnection * conn,
void * arg);
SSMStatus SSMResourceCert_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMResourceCert_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMResourceCert_Destroy(SSMResource *res, PRBool doFree);
SSMStatus SSMResourceCert_Pickle(SSMResource *res, PRIntn *len, void ** rdata);
SSMStatus SSMResourceCert_Verify(SSMResourceCert * resource,
SECCertUsage certUsage);
SSMStatus SSMResourceCert_DeleteCert(SSMResourceCert * resource);
SSMStatus SSMResourceCert_Unpickle(SSMResource ** resource,
SSMControlConnection * conn, PRInt32 len,
void * value);
SSMStatus SSMResourceCert_HTML(SSMResource *res, PRIntn * len, void ** value);
SSMStatus SSMResourceCert_FormSubmitHandler(SSMResource *res, HTTPRequest *req);
/* Other cert resource functions */
SSMStatus SSM_VerifyCert(SSMResourceCert * resource,
SECCertUsage certUsage);
SSMStatus SSM_DeleteCert(SSMResourceCert * resource);
SSMStatus SSM_DeleteCertHandler(HTTPRequest * req);
SSMStatus SSM_HTTPCertListHandler(HTTPRequest * req);
SSMStatus SSM_ViewCertInfoKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_VerifyCertKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_SelectCertKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_ChooseCertUsageHandler(HTTPRequest * req);
SSMStatus SSM_EditCertKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_EditCertificateTrustHandler(HTTPRequest * req);
SSMStatus SSM_DeleteCertHelpKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_DeleteCertWarnKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_ObtainNewCertSite(SSMTextGenContext * cx);
SSMStatus SSM_ProcessLDAPRequestHandler(HTTPRequest * req);
SSMStatus SSM_LDAPServerListKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_ProcessLDAPWindow(HTTPRequest * req);
SSMStatus
SSM_ProcessCertUIAction(HTTPRequest * req, CERTCertificate * cert);
SSMStatus SSM_ProcessCertDeleteButton(HTTPRequest * req);
int SSM_CertListCount(CERTCertList *certList);
SSMStatus SSM_OCSPOptionsKeywordHandler(SSMTextGenContext *cx);
SSMStatus SSM_OCSPDefaultResponderKeywordHandler(SSMTextGenContext *cx);
SSMStatus
SSM_CompleteLDAPLookup(SSMControlConnection *ctrl, char * ldapserver,
char * emailaddr);
char * SSM_GetCAPolicyString(char * org, unsigned long noticeNum, void * arg);
#endif

View File

@ -0,0 +1,251 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
/* LDAP Cert Search */
#include <ldap.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "certsearch.h"
/* XXX TRUE & FALSE is not defined (on Unix): get by for now by using this
* macro */
#define SSM_LDAP_TRUE 1
#define SSM_LDAP_FALSE 0
int LDAPCertSearch (const char * rcpt_address, const char * server_name,
const char * baseDN, int port, int connect_type,
const char * certdb_path, const char * auth_dn,
const char * auth_password, const char * mail_attribs,
const char * cert_attribs, cert_struct * certs[])
{
int rtnval;
LDAP * ld;
char *filter, *tstr, *tmpstr, *tmpstr1;
int addr_len, attr_count = 0, filter_length = 0;
char mail_array[3][80];
char **cert_attrib_array, **tmp_cert_array;
LDAPMessage *reslt, *entry;
int attrib_name_count, entry_count;
void * cert;
/* First some simple param checking */
if (!server_name || !*server_name)
return 1;
if (!rcpt_address || !*rcpt_address)
return 2;
if (connect_type < CLEAR_ANON || connect_type > SSL_CERTAUTH)
return 3;
if (!cert_attribs || !*cert_attribs)
return 2;
/* Okay, try to init connection to LDAP Server */
if (connect_type == CLEAR_ANON || connect_type == CLEAR_AUTH)
ld = ldap_init(server_name, 389);
#if 0
/* don't bother with SSL yet */
else { /* SSL Connection */
/* First init Client connection to db files needed */
if (connect_type == SSL_CERTAUTH) {
/* don't bother yet. keydbpath is full path of key3.db file (e.g. ...users/bruces)
if (ldapssl_clientauth_init(certdb_path, NULL, needkeydb, keydbpath,
NULL) < 0)
return 4; */
} else {
if (ldapssl_client_init(certdb_path, NULL) < 0)
return 4;
}
/* Now attempt SSL connection to LDAP Server */
ld = ldapssl_init(server_name, port, 1);
}
#endif
if (!ld) /* failed to init connection to LDAP server */
return 4;
/* Now bind to server (NULL/Anon bind if not AUTH type connection) */
if (connect_type == CLEAR_ANON || connect_type == SSL_ANON)
rtnval = ldap_simple_bind_s(ld, NULL, NULL);
else if (connect_type == CLEAR_AUTH || connect_type == SSL_AUTH)
rtnval = ldap_simple_bind_s(ld, auth_dn, auth_password);
/* else if (connect_type == SSL_CERTAUTH)
rtnval = ldap_sasl_bind_s(ld, auth_dn, [mechanism], [cred], NULL,
NULL, servercredp) */
if (rtnval != LDAP_SUCCESS)
return 5;
/*
// Now ready to search
*/
/* First create the filter from attrib(s) and rcpt_address */
/* first compute size of filter to create, and collect mail attribs */
addr_len = strlen(rcpt_address);
tmpstr1 = (char *)PR_Malloc(strlen(mail_attribs)+1);
strcpy(tmpstr1, mail_attribs);
tmpstr = tmpstr1;
while (tstr = strchr(tmpstr, ',')) {
*tstr = '\0';
filter_length += addr_len + strlen(tmpstr) + 5;
strcpy(mail_array[attr_count++], tmpstr);
tmpstr = tstr+1;
}
/* and get last mail attribute */
filter_length += addr_len + strlen(tmpstr) + 5;
strcpy(mail_array[attr_count++], tmpstr);
filter = (char *)PR_Malloc(filter_length);
PR_Free(tmpstr1);
/* should figure out way to generalize this :-( */
if (attr_count == 1)
sprintf(filter, "(%s=%s)", mail_array[0], rcpt_address);
else if (attr_count == 2)
sprintf(filter, "(|(%s=%s)(%s=%s))", mail_array[0], rcpt_address,
mail_array[1], rcpt_address);
else if (attr_count == 3)
sprintf(filter, "(|(%s=%s)(%s=%s)(%s=%s))", mail_array[0], rcpt_address,
mail_array[1], rcpt_address, mail_array[2], rcpt_address);
else
return 6; /* too many mail attribs (should fix this eventually) */
/* Also get list of Cert attribs */
cert_attrib_array = (char **)PR_Malloc(50); /* space for array of ptrs */
tmp_cert_array = cert_attrib_array;
tmpstr = (char *)PR_Malloc(strlen(cert_attribs)+1);
strcpy(tmpstr, cert_attribs);
tmpstr1 = tmpstr;
while (tstr = strchr(tmpstr, ',')) {
*tstr = '\0';
*tmp_cert_array = (char *)PR_Malloc(strlen(tmpstr)+1);
strcpy(*tmp_cert_array, tmpstr);
*tmp_cert_array++;
tmpstr = tstr+1;
}
/* get last attribute, and put in NULL entry as end */
*tmp_cert_array = (char *)PR_Malloc(strlen(tmpstr)+1);
strcpy(*tmp_cert_array, tmpstr);
*tmp_cert_array++;
*tmp_cert_array = NULL;
PR_Free(tmpstr1);
/* Now perform the search and check response */
rtnval = ldap_search_s(ld, baseDN, LDAP_SCOPE_SUBTREE, filter,
cert_attrib_array, SSM_LDAP_FALSE, &reslt);
PR_Free(filter);
if (rtnval != LDAP_SUCCESS) {
for (tmp_cert_array = cert_attrib_array; *tmp_cert_array;
tmp_cert_array++)
PR_Free(*tmp_cert_array);
PR_Free(cert_attrib_array);
return 7; /* LDAP Failure */
}
entry_count = ldap_count_entries(ld, reslt);
if (entry_count == 0) {
for (tmp_cert_array = cert_attrib_array; *tmp_cert_array;
tmp_cert_array++)
PR_Free(*tmp_cert_array);
PR_Free(cert_attrib_array);
ldap_msgfree(reslt);
ldap_unbind(ld);
return -1; /* no entry found for rcpt */
}
if (entry_count > 1) {
for (tmp_cert_array = cert_attrib_array; *tmp_cert_array;
tmp_cert_array++)
PR_Free(*tmp_cert_array);
PR_Free(cert_attrib_array);
ldap_msgfree(reslt);
ldap_unbind(ld);
return 8; /* multiple entries found for rcpt */
}
/*
*Okay, got an entry, check for Cert
*/
rtnval = 9; /* default is to return no attrib found */
/* Now check each cert attribute type */
entry = ldap_first_entry(ld, reslt);
attrib_name_count = 0;
tmp_cert_array = cert_attrib_array;
while (*tmp_cert_array) {
struct berval cert_attrib_struct;
struct berval **cert_out_list;
struct cert_struct_def * cert_ptr;
int valcount=0;
cert_out_list = ldap_get_values_len(ld, entry, *tmp_cert_array);
if (cert_out_list) { /* Values found for this cert attr */
while (SSM_LDAP_TRUE) { /* just get count for malloc first */
if (!cert_out_list[valcount++])
break;
}
certs[attrib_name_count] = PR_Malloc(valcount * sizeof(cert_struct));
cert_ptr = certs[attrib_name_count];
valcount =0;
while (SSM_LDAP_TRUE) {
if (!cert_out_list[valcount])
break;
cert_attrib_struct = *cert_out_list[valcount++];
cert = PR_Malloc(cert_attrib_struct.bv_len);
memcpy(cert, cert_attrib_struct.bv_val,
cert_attrib_struct.bv_len);
cert_ptr->cert = cert;
cert_ptr->cert_len = cert_attrib_struct.bv_len;
cert_ptr++;
rtnval = 0; /* found at least one Cert */
}
cert_ptr->cert_len = 0; /* end list */
}
ldap_value_free_len(cert_out_list);
*tmp_cert_array++;
attrib_name_count++;
}
for (tmp_cert_array = cert_attrib_array; *tmp_cert_array;
tmp_cert_array++)
PR_Free(*tmp_cert_array);
PR_Free(cert_attrib_array);
ldap_msgfree(reslt);
ldap_unbind(ld);
return rtnval;
}

View File

@ -0,0 +1,54 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef CERTSEARCH_H
#define CERTSEARCH_H
#define CLEAR_ANON 1
#define CLEAR_AUTH 2
#define SSL_ANON 3
#define SSL_AUTH 4
#define SSL_CERTAUTH 5
typedef struct cert_struct_def {
int cert_len;
void * cert;
} cert_struct;
int LDAPCertSearch (const char * rcpt_address, const char * server_name,
const char * baseDN, int port, int connect_type,
const char * certdb_path, const char * auth_dn,
const char * auth_password, const char * mail_attribs,
const char * cert_attribs, cert_struct * certs[]);
#endif

View File

@ -0,0 +1,373 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "collectn.h"
#include "prerror.h"
#include "prmem.h"
#include "seccomon.h"
#include "serv.h"
SSMCollection *
SSM_NewCollection(void)
{
SSMCollection *coll;
coll = PR_NEWZAP(SSMCollection);
if (coll == NULL)
goto loser;
coll->lock = PR_NewMonitor();
if (coll->lock == NULL)
goto loser;
PR_INIT_CLIST(&coll->list);
return coll;
loser:
SSM_DestroyCollection(coll);
return NULL;
}
SSMStatus
SSM_DestroyCollection(SSMCollection *victim)
{
if (victim == NULL)
return PR_SUCCESS;
PR_ASSERT(victim->nItems == 0);
if (victim->nItems != 0)
return PR_FAILURE;
if (victim->lock)
PR_DestroyMonitor(victim->lock);
PR_Free(victim);
return PR_SUCCESS;
}
static SSMListItem *
new_list_item(PRIntn priority, void *data)
{
SSMListItem *item;
item = PR_NEWZAP(SSMListItem);
if (item == NULL)
return NULL;
item->priority = priority;
item->data = data;
return item;
}
static SSMListItem *
find_list_item(SSMCollection *list, void *which)
{
PRCList *link;
for(link = PR_LIST_HEAD(&list->list); link != &list->list;
link = PR_NEXT_LINK(link))
{
SSMListItem *item = (SSMListItem *) link;
if (item->data == which)
return item;
}
return NULL;
}
/* Insert (item) into the list before (before).
If (before) is NULL, append to the list. */
SSMStatus
ssm_InsertSafe(SSMCollection *list, PRIntn priority, void *data, void *before)
{
SSMListItem *beforeItem = NULL, *item;
if ((data == NULL) || (list == NULL))
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
/* Find (before) in the list if it's here. */
if (before == NULL)
beforeItem = (SSMListItem *) &list->list;
else
beforeItem = find_list_item(list, before);
/* Create a new list item. */
item = new_list_item(priority, data);
if (item == NULL)
return PR_FAILURE;
PR_INSERT_BEFORE(&item->link, &beforeItem->link);
list->nItems++;
list->priorityCount[priority]++;
return PR_SUCCESS;
}
/* Insert (data) into the list before (before).
If (before) is NULL, append to the list. */
SSMStatus
SSM_Insert(SSMCollection *list, PRIntn priority, void *data, void *before)
{
SSMStatus rv;
if (list == NULL)
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
PR_EnterMonitor(list->lock);
rv = ssm_InsertSafe(list, priority, data, before);
PR_Notify(list->lock);
PR_ExitMonitor(list->lock);
return rv;
}
/* Remove (data) from the list. */
SSMStatus
ssm_RemoveSafe(SSMCollection *list, void *data)
{
SSMStatus rv = PR_SUCCESS;
SSMListItem *item;
if ((data == NULL) || (list == NULL))
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
item = find_list_item(list, data);
if (item == NULL)
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
if ((item->priority >= 0) && (item->priority < SSM_PRIORITY_MAX))
list->priorityCount[item->priority]--;
PR_REMOVE_LINK(&item->link);
PR_Free(item);
list->nItems--;
return rv;
}
/* Remove (item) from the list. */
SSMStatus
SSM_Remove(SSMCollection *list, void *item)
{
SSMStatus rv;
if (list == NULL)
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
PR_EnterMonitor(list->lock);
rv = ssm_RemoveSafe(list, item);
PR_Notify(list->lock);
PR_ExitMonitor(list->lock);
return rv;
}
/* Count the number of items in the list. */
PRIntn
ssm_CountSafe(SSMCollection *list, PRIntn priority)
{
PRIntn result = 0;
PRIntn i;
if (priority == SSM_PRIORITY_ANY)
result = list->nItems;
else
{
for(i=priority; i <= SSM_PRIORITY_MAX; i++)
result += list->priorityCount[i];
}
return result;
}
/* Count the number of items in the list. */
PRIntn
SSM_CountPriority(SSMCollection *list, PRIntn priority)
{
int count;
if ((list == NULL)
|| (priority < SSM_PRIORITY_ANY)
|| (priority > SSM_PRIORITY_MAX))
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return -1;
}
PR_EnterMonitor(list->lock);
count = ssm_CountSafe(list, priority);
PR_ExitMonitor(list->lock);
return count;
}
PRIntn
SSM_Count(SSMCollection *list)
{
return SSM_CountPriority(list, SSM_PRIORITY_ANY);
}
/* Get (which)th item from the list. zero-based index. */
void *
SSM_At(SSMCollection *list, PRIntn which)
{
PRCList *link;
if ((list == NULL) || (which >= list->nItems)) {
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return NULL;
}
PR_EnterMonitor(list->lock);
link = PR_LIST_HEAD(&list->list);
for ( ; which > 0 ; which--) {
link = PR_NEXT_LINK(link);
}
PR_ExitMonitor(list->lock);
return ((SSMListItem *) link)->data;
}
SSMStatus
SSM_Enqueue(SSMCollection *list, PRIntn priority, void *item)
{
/* Insert this element at the end. */
return SSM_Insert(list, priority, item, NULL);
}
SSMListItem *
ssm_FirstAtPriority(SSMCollection *list, PRIntn priority)
{
SSMListItem *result;
SSMListItem *link;
result = NULL; /* in case we fail */
if ((list == NULL) || (priority > SSM_PRIORITY_MAX))
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return NULL;
}
if (PR_CLIST_IS_EMPTY(&list->list))
result = NULL;
else if (priority == SSM_PRIORITY_ANY)
result = (SSMListItem *) PR_LIST_HEAD(&list->list);
else /* asked for priority and list not empty */
{
/* Find the first element from the list at (priority). */
link = (SSMListItem *) PR_LIST_HEAD(&list->list);
while((link != (SSMListItem *) &list->list) &&
(link->priority < priority))
link = (SSMListItem *) PR_NEXT_LINK(&link->link);
if (link != (SSMListItem *) &list->list)
result = link;
}
return result;
}
SSMStatus
SSM_Dequeue(SSMCollection *list, PRIntn priority,
void **result, PRBool doBlock)
{
void *data = NULL;
SSMListItem *link;
SSMStatus rv = PR_SUCCESS;
*result = NULL; /* in case we fail */
if (list == NULL) {
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
PR_EnterMonitor(list->lock);
while(doBlock && (ssm_CountSafe(list, priority) == 0)) {
rv = PR_Wait(list->lock, PR_INTERVAL_NO_TIMEOUT);
if (rv == PR_PENDING_INTERRUPT_ERROR)
{
/* We got interrupted, bail */
return rv;
}
/* SSM_DEBUG("ssm_CountSafe (prio %d) is %d.\n",
priority, ssm_CountSafe(list, priority));*/
}
/* Pop the first element from the list at (priority). */
if (!PR_CLIST_IS_EMPTY(&list->list)) {
link = ssm_FirstAtPriority(list, priority);
if (link)
{
data = link->data;
if ((link->priority >= 0) && (link->priority < SSM_PRIORITY_MAX))
list->priorityCount[link->priority]--;
PR_REMOVE_LINK(&link->link);
PR_Free(link);
list->nItems--;
}
}
PR_Notify(list->lock);
PR_ExitMonitor(list->lock);
*result = data;
return PR_SUCCESS;
}

View File

@ -0,0 +1,203 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __COLLECTN_H__
#define __COLLECTN_H__
#include "prtypes.h"
#include "prmon.h"
#include "prclist.h"
#include "ssmdefs.h"
/* definitions for priority */
#define SSM_PRIORITY_ANY -1
#define SSM_PRIORITY_NORMAL 0
#define SSM_PRIORITY_UI 1
#define SSM_PRIORITY_SHUTDOWN 30 /* always pull this if it's available */
#define SSM_PRIORITY_MAX 31
/* This is an ordered collection of items without repetition. */
/* This is to be used as a link in a PRCList.
* You can cast any of the PRCList *'s in the list to one of these.
* See prclist.h for details.
*/
typedef struct _SSMListItem
{
PRCList link;
PRIntn priority;
void *data;
} SSMListItem;
/* An ordered collection, implemented in terms of PRCList. */
struct _SSMCollection
{
PRMonitor *lock;
PRIntn nItems;
PRIntn priorityCount[SSM_PRIORITY_MAX+1];
PRCList list;
};
typedef struct _SSMCollection SSMCollection;
/************************************************************
** FUNCTION: SSM_NewCollection
** RETURNS:
** SSMCollection *
** returns a pointer to a new SSMCollection.
** return NULL on error.
**
*************************************************************/
SSMCollection *SSM_NewCollection(void);
/************************************************************
** FUNCTION: SSM_DestroyCollection
** INPUTS:
** victim
** The collection to be destroyed.
** RETURNS:
** PR_SUCCESS on success.
** PR_FAILURE on failure. This can't happen (yet).
**
*************************************************************/
SSMStatus SSM_DestroyCollection(SSMCollection *victim);
/************************************************************
** FUNCTION: SSM_Enqueue
** DESCRIPTION: Append (item) to (list).
** INPUTS:
** list
** The collection to be added to.
** priority
** The priority of the new item in the queue.
** item
** The data item to be enqueued.
** RETURNS:
** PR_SUCCESS on success.
** PR_FAILURE on failure.
**
*************************************************************/
SSMStatus SSM_Enqueue(SSMCollection *list, PRIntn priority, void *item);
/************************************************************
** FUNCTION: SSM_Dequeue
** DESCRIPTION: Retrieve a data item from the head of (list).
** INPUTS:
** list
** The collection to be retrieved from.
** priority
** The priority level of items to be removed from the queue.
** Anything below the given priority level is ignored.
** Pass SSM_PRIORITY_ANY to fetch the first item from the
** queue regardless of priority.
** doBlock
** PR_TRUE if the function should block on an empty collection.
** PR_FALSE if the function should not block.
** OUTPUTS:
** item
** A pointer to the void * to hold the retrieved item.
** RETURNS:
** PR_SUCCESS on success.
** PR_FAILURE on failure.
**
*************************************************************/
SSMStatus SSM_Dequeue(SSMCollection *list, PRIntn priority, void **item, PRBool doBlock);
/************************************************************
** FUNCTION: SSM_Insert
** DESCRIPTION: Insert a new data item into (list) before (before).
** INPUTS:
** list
** The collection to be retrieved from.
** priority
** The priority of the item to be inserted.
** item
** The data item to insert.
** before
** The list member before which to insert.
** RETURNS:
** PR_SUCCESS on success.
** PR_FAILURE on failure.
**
*************************************************************/
SSMStatus SSM_Insert(SSMCollection *list, PRIntn priority,
void *item, void *before);
/************************************************************
** FUNCTION: SSM_Remove
** DESCRIPTION: Remove (item) from (list).
** INPUTS:
** list
** The collection to be removed from.
** item
** The data item to be removed.
** RETURNS:
** PR_SUCCESS on success.
** PR_FAILURE on failure.
**
*************************************************************/
SSMStatus SSM_Remove(SSMCollection *list, void *item);
/************************************************************
** FUNCTION: SSM_Count
** DESCRIPTION: Returns the number of items in (list).
** INPUTS:
** list
** The collection to be counted.
** priority
** Only count items at or above (priority). Pass SSM_PRIORITY_ANY
** to count all items in the list.
** RETURNS:
** The number of items in the list.
**
*************************************************************/
PRIntn SSM_Count(SSMCollection *list);
PRIntn SSM_CountPriority(SSMCollection *list, PRIntn priority);
/************************************************************
** FUNCTION: SSM_At
** DESCRIPTION: Get the (which)'th item in (list).
** INPUTS:
** list
** The collection to be indexed.
** which
** Index of item to retrieve. Zero is first item.
**
*************************************************************/
void *SSM_At(SSMCollection *list, PRIntn which);
#endif /* __COLLECTN_H__ */

View File

@ -0,0 +1,366 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "connect.h"
#include "ssmerrs.h"
#include "ctrlconn.h"
#include "prinrval.h"
#include "crmf.h"
#define SSMRESOURCE(conn) (&(conn)->super)
/*
ssm_ConnectionCreate creates an SSMConnection object.
The value argument is ignored.
*/
SSMStatus
SSMConnection_Create(void *arg, SSMControlConnection * connection,
SSMResource **res)
{
SSMStatus rv = PR_SUCCESS;
SSMConnection *conn;
SSMControlConnection * owner;
*res = NULL; /* in case we fail */
conn = (SSMConnection *) PR_CALLOC(sizeof(SSMConnection));
if (!conn)
goto loser;
if (connection)
owner = connection;
else
owner = (SSMControlConnection *)conn;
rv = SSMConnection_Init(owner, (SSMConnection *) arg,
SSM_RESTYPE_CONNECTION);
if (rv != PR_SUCCESS) goto loser;
SSMConnection_Invariant(conn);
*res = &conn->super;
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
if (conn)
{
SSM_ShutdownResource(SSMRESOURCE(conn), rv);
SSM_FreeResource(&conn->super);
}
return rv;
}
/* As a sanity check, make sure we have data structures consistent
with our type. */
void SSMConnection_Invariant(SSMConnection *conn)
{
#ifdef DEBUG
if (conn)
{
SSMResource_Invariant(&(conn->super));
SSM_LockResource(SSMRESOURCE(conn));
PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(conn), SSM_RESTYPE_CONNECTION));
PR_ASSERT(conn->m_children != NULL);
SSM_UnlockResource(SSMRESOURCE(conn));
#if 0
if (conntype == SSM_DATA_CONNECTION)
{
PR_ASSERT(!conn->m_children);
PR_ASSERT(!conn->m_readThread);
PR_ASSERT(!conn->m_writeThread);
PR_ASSERT(!conn->m_controlOutQ);
}
else /* control connection */
{
PR_ASSERT(conn->m_children);
PR_ASSERT(!conn->m_readClientThread);
PR_ASSERT(!conn->m_writeClientThread);
PR_ASSERT(!conn->m_readTargetThread);
PR_ASSERT(!conn->m_writeTargetThread);
PR_ASSERT(!conn->m_incomingQ);
PR_ASSERT(!conn->m_outgoingQ);
PR_ASSERT(conn->m_resourceID == 0);
}
#endif
}
#endif
}
SSMStatus
SSMConnection_DetachChild(SSMConnection *parent, SSMConnection *child)
{
SSMStatus rv;
SSM_LockResource(&parent->super);
/* Remove the child from the parent's collection of children. */
rv = SSM_Remove(parent->m_children, child);
child->m_parent = NULL;
/* If the parent is detaching (due to destruction), free the child. */
if (&parent->super.m_refCount == 0)
SSM_FreeResource(&child->super);
SSM_UnlockResource(&parent->super);
return rv;
}
SSMStatus
SSMConnection_AttachChild(SSMConnection *parent, SSMConnection *child)
{
SSMStatus rv;
SSM_LockResource(&parent->super);
rv = SSM_Insert(parent->m_children, SSM_PRIORITY_NORMAL, child, NULL);
SSM_UnlockResource(&parent->super);
return rv;
}
SSMStatus
SSMConnection_Shutdown(SSMResource *res, SSMStatus status)
{
SSMConnection *conn = (SSMConnection *) res;
SSMStatus rv;
SSM_LockResource(SSMRESOURCE(conn));
rv = SSMResource_Shutdown(res, status);
if (SSMRESOURCE(conn)->m_threadCount == 0)
{
SSMConnection *child;
/* Shut down child connections. */
SSM_Dequeue(conn->m_children, SSM_PRIORITY_ANY,
(void **) &child, PR_FALSE);
while(child != NULL)
{
SSM_ShutdownResource(&child->super, (SSMStatus) PR_PENDING_INTERRUPT_ERROR);
SSMConnection_DetachChild(conn, child);
child = NULL;
}
}
SSM_UnlockResource(SSMRESOURCE(conn));
return rv;
}
SSMStatus
SSMConnection_Destroy(SSMResource *res, PRBool doFree)
{
SSMStatus rv = PR_SUCCESS;
SSMConnection *conn = (SSMConnection *) res;
SSMResource *child = NULL;
/* Destroy the collection of child connections. */
if (conn->m_children)
{
/* Detach all children. */
do
{
SSM_Dequeue(conn->m_children, SSM_PRIORITY_ANY,
(void **) &child, PR_FALSE);
if (child && (child != SSMRESOURCE(conn)))
{
SSM_DEBUG("Freeing child connection %lx.\n",
(unsigned long) child);
SSM_FreeResource(child);
}
}
while (child != NULL);
PR_ASSERT(SSM_Count(conn->m_children) == 0);
SSM_DestroyCollection(conn->m_children);
}
/* If we're attached to a parent, detach from the parent's collection. */
if (conn->m_parent)
SSMConnection_DetachChild(conn->m_parent, conn);
SSMResource_Destroy(res, PR_FALSE);
if (doFree) {
PR_Free(res);
}
return rv;
}
SSMStatus
SSMConnection_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count)
{
SSMStatus rv;
rv = SSMResource_GetAttrIDs(res, ids, count);
if (rv != PR_SUCCESS)
goto loser;
*ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 2) * sizeof(SSMResourceID));
if (! *ids) goto loser;
(*ids)[*count++] = SSM_FID_CONN_ALIVE;
(*ids)[*count++] = SSM_FID_CONN_PARENT;
goto done;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMConnection *conn = (SSMConnection *) res;
SSMStatus rv = PR_SUCCESS;
/* see what it is */
switch(attrID)
{
case SSM_FID_CONN_ALIVE:
value->u.numeric = (PRUint32) (conn->super.m_threadCount > 0);
value->type = SSM_NUMERIC_ATTRIBUTE;
break;
case SSM_FID_CONN_PARENT:
rv = SSM_ClientGetResourceReference(SSMRESOURCE(conn->m_parent),
&value->u.rid);
value->type = SSM_RID_ATTRIBUTE;
break;
default:
rv = SSMResource_GetAttr(res,attrID,attrType,value);
if (rv != PR_SUCCESS)
goto loser;
}
loser:
return rv;
}
SSMStatus
SSMConnection_SetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value)
{
SSMStatus rv;
/* we own nothing, defer to superclass */
rv = SSMResource_SetAttr(res,attrID,value);
return rv;
}
SSMStatus
SSMConnection_Init(SSMControlConnection *ctrl, SSMConnection *connection,
SSMResourceType type)
{
SSMStatus rv = PR_SUCCESS;
SSMControlConnection * owner;
if (type == SSM_RESTYPE_CONTROL_CONNECTION)
owner = (SSMControlConnection *)connection;
else owner = ctrl;
rv = SSMResource_Init(owner, &connection->super, type);
if (rv != PR_SUCCESS) goto loser;
/* Attach ourselves to the parent first, then set the member */
if (ctrl != NULL) {
rv = SSMConnection_AttachChild(&(ctrl->super), connection);
if (rv != PR_SUCCESS)
goto loser;
}
connection->m_parent = &(ctrl->super);
connection->m_children = SSM_NewCollection();
if (!connection->m_children) goto loser;
/* hang our hooks */
connection->m_auth_func = SSMConnection_Authenticate;
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
return rv;
}
SSMStatus SSMConnection_Authenticate(SSMConnection *conn, char *nonce)
{
/* Abstract method, report failure by default */
return SSM_FAILURE;
}
/* Given a RID and a proposed nonce, see if the connection exists
and if the nonce matches. */
SSMStatus SSM_AuthenticateConnection(SSMControlConnection * ctrl,
SSMResourceID rid, char *nonce)
{
SSMResource *obj = NULL;
SSMConnection *conn;
SSMStatus rv;
/* Find the connection object. */
rv = (SSMStatus) SSMControlConnection_GetResource(ctrl, rid, &obj);
if (rv != SSM_SUCCESS)
goto loser;
PR_ASSERT(obj);
SSM_LockResource(obj);
if (!SSM_IsAKindOf(obj, SSM_RESTYPE_CONNECTION))
goto loser;
conn = (SSMConnection *) obj;
if (!conn->m_auth_func)
goto loser;
rv = (*conn->m_auth_func)(conn, nonce);
goto done;
loser:
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
done:
if (obj) SSM_UnlockResource(obj);
return rv;
}

View File

@ -0,0 +1,154 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_CONNECT_H__
#define __SSM_CONNECT_H__
#include "ssmdefs.h"
#include "collectn.h"
#include "hashtbl.h"
#include "resource.h"
#include "pkcs11t.h"
#include "plarena.h"
#include "mcom_db.h"
#include "seccomon.h"
#include "secmodt.h"
#include "prinrval.h"
/* Cartman password policy */
#define SSM_MIN_PWD_LEN 0
#define SSM_MAX_PWD_LEN 64
typedef struct SSMConnection SSMConnection;
typedef SSMStatus (*SSMConnectionAuthenticateFunc)(SSMConnection *conn,
char *nonce);
struct SSMConnection
{
SSMResource super;
/*
---------------------------------------------
Generic fields, applicable to all connections
---------------------------------------------
*/
/* ### mwelch - children/parent should perhaps be put in subclasses,
but we may use these in multiple ways in the future */
/* Parent connection object. If this is a data object, m_parent points
to the control connection which spawned it. */
SSMConnection * m_parent;
/* Child connection objects. If this is a control object, the collection
is filled with data connection objects. */
SSMCollection *m_children;
/* The function to call when we want to validate an incoming connection */
SSMConnectionAuthenticateFunc m_auth_func;
};
/*
* Information for authenticated tokens.
*/
#define SSM_MINUTES_WAIT_PASSWORD 10
#define SSM_PASSWORD_WAIT_TIME (SSM_MINUTES_WAIT_PASSWORD*PR_TicksPerSecond()*60)
#define SSM_NO_PASSWORD 0x99999999
#define SSM_CANCEL_PASSWORD 0x99999998
struct _SSM_TokenInfoStr {
PK11SlotInfo * slot;
PRInt32 tokenID;
char * encrypted;
PRInt32 encryptedLen;
PK11SymKey * symKey;
};
typedef struct _SSM_TokenInfoStr SSM_TokenInfo;
/* Password callback */
char * SSM_GetPasswdCallback(PK11SlotInfo *slot, PRBool retry, void *arg);
PRBool SSM_VerifyPasswdCallback(PK11SlotInfo * slot, void * arg);
#ifdef ALLOW_STANDALONE
/* For standalone mode only */
char * SSM_StandaloneGetPasswdCallback(PK11SlotInfo *slot, PRBool retry,
void *arg);
PRBool SSM_StandaloneVerifyPasswdCallback(PK11SlotInfo * slot, void * arg);
#endif
char * SSM_GetAuthentication(PK11SlotInfo * slot, PRBool retry, PRBool init,
SSMResource * conn);
SSMStatus SSM_SetUserPassword(PK11SlotInfo * slot, SSMResource * ct);
SSMStatus SSMConnection_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMConnection_Init(SSMControlConnection *ctrl,
SSMConnection *conn, SSMResourceType type);
SSMStatus SSMConnection_Shutdown(SSMResource *conn, SSMStatus status);
SSMStatus SSMConnection_Destroy(SSMResource *conn, PRBool doFree);
void SSMConnection_Invariant(SSMConnection *conn);
SSMStatus SSMConnection_AttachChild(SSMConnection *parent, SSMConnection *child);
SSMStatus SSMConnection_DetachChild(SSMConnection *parent, SSMConnection *child);
SSMStatus SSMConnection_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMConnection_SetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value);
SSMStatus SSMConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
/* Given a RID and a proposed nonce, see if the connection exists
and if the nonce matches. */
SSMStatus SSMConnection_Authenticate(SSMConnection *conn, char *nonce);
/* Function to encrypt password to storing it in Cartman */
SSMStatus SSM_EncryptPasswd(PK11SlotInfo * slot, char * passwd,
SSM_TokenInfo ** info);
SSMStatus SSMControlConnection_WaitPassword(SSMConnection * conn,
PRInt32 key, char ** str);
SSMStatus SSM_AskUserPassword(SSMResource * conn,
PK11SlotInfo * slot, PRInt32 retry, PRBool init);
/* Function returning user prompt */
char * SSM_GetPrompt(PK11SlotInfo *slot, PRBool retry, PRBool init);
#define XP_SEC_ERROR_PWD "Successive login failures may disable this card or database. Password is invalid. Retry?\n %s\n"
#define XP_SEC_ENTER_PWD "Please enter the password or the pin for\n%s."
#define XP_SEC_SET_PWD "Please enter the password or the pin for\n%s. Remember this password, you will need \nit to access your certificates."
#endif

View File

@ -0,0 +1,113 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include <stdio.h>
#include <stdlib.h>
/* We really do have 'long long' on the Mac, but NSPR doesn't yet know this.
Need to define this before including NSPR to get the right defn of PRInt64. */
#if 0
#ifdef XP_MAC
#define HAVE_LONG_LONG
#endif
#endif
#include "prtime.h"
#include "prenv.h"
#include "prlong.h"
char * timebombVar = "NSM_TIMEBOMB";
#define SSM_SEC_PER_24HRS (60 * 60 * 24)
int main()
{
FILE * headerFile, * timeFile;
int daysToLive;
char * tmp = PR_GetEnv(timebombVar);
PRTime timeNow, lifeTime, expire, tmpVal, days, tmpMilli;
PRInt32 timeHi, timeLow;
daysToLive = atoi(tmp);
timeNow = PR_Now();
LL_I2L(tmpVal, SSM_SEC_PER_24HRS);
LL_I2L(days, daysToLive);
LL_MUL(tmpMilli, days, tmpVal);
LL_MUL(lifeTime, tmpMilli, PR_USEC_PER_SEC);
LL_ADD(expire, timeNow, lifeTime);
LL_SHR(tmpVal, expire, 32);
LL_L2UI(timeHi, tmpVal);
LL_L2UI(timeLow, expire);
timeFile = fopen("timestamp.h", "w");
if (!timeFile) {
printf("Can't create timestamp.h.\n");
goto loser;
}
fprintf(timeFile, "/*\n * Created automatically, do not edit!\n */\n\n");
fprintf(timeFile, "/* This build of Cartman will expire at this time. */ \n");
fprintf(timeFile, "static PRTime expirationTime = LL_INIT(0x%lx, 0x%lx);\n", timeHi,
timeLow);
fclose(timeFile);
headerFile = fopen("timebomb.h", "w");
if (!headerFile) {
printf("Can't open timebomb.h for writing!\n");
goto loser;
}
fprintf(headerFile,
"/* This file is generated automatically by createBomb.c, do not edit! */\n\n\n");
/*
* Function declarations that are used for the timebomb.
* Definitions are in timebomb.c, included in frontend.c.
*/
fprintf(headerFile,
"\n\n/* Functions used in Cartman for the timebomb. */\n");
fprintf(headerFile,
"/*\n * Set SSMTimeBombExpired to PR_TRUE if Cartman has expired. \n */\n");
fprintf(headerFile, "void SSM_CheckTimeBomb();\n\n");
fprintf(headerFile,
"/*\n * Run this function from frontend thread of control connection\n * if Cartman has expired. \n */\n");
fprintf(headerFile, "void SSM_CartmanHasExpired(SSMControlConnection * control);\n\n");
fclose(headerFile);
loser:
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,404 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef _CRMFRES_H_
#define _CRMFRES_H_
#include "cmmf.h"
#include "keyres.h"
#include "ssmdefs.h"
#include "ctrlconn.h"
/*
* FILE: crmfres.h
* ---------------
* This file defines the public interface for the class SSMCRMFRequest
* which is to be used in Cartman to implement all necessary CRMF
* functionality.
*/
/*
* STRUCTURE: SSMCRMFRequest
* -------------------------
* This is the structure used to implement the SSMCRMFRequest
* class. This class will be used to create CRMF Requests within
* Cartman. SSMCRMFRequest sub-classess off of SSMResource so it
* must always follow any guidelines for naming and defining presented
* by the SSMResource class.
*
* The fields:
*
* super The mandatory first member for any class sub-classing
* from SSMResource.
*
* m_KeyGenType An enumerated type indicating what type of key pair
* we are creating a request for. This value is used
* to set the appropriate keyUsage extensions and also
* determining the proper method to set for
* Proof-Of-Possession. Look at the file
* ns/security/ssm/lib/protocol/ssmders.h for valid values.
* This value is set by the client.
*
* m_KeyPair A pointer to a key pair associated with the instantiation
* of the CRMF request. The members mPrivKey and mPubKey
* must be non-NULL values when a new request is created.
*
* m_CRMFRequest This is the member that holds all of the state information
* about the CRMF request.
*
* m_Connection This is the control connection associated with the
* request.
*/
typedef struct SSMCRMFRequest {
SSMResource super; /* This must always be the first member of the
* structure. Don't even think of adding another
* field before it or removing it.
*/
SSMKeyGenType m_KeyGenType;
SSMKeyPair *m_KeyPair;
CRMFCertRequest *m_CRMFRequest;
SSMControlConnection *m_Connection;
} SSMCRMFRequest;
/*
* STRUCTURE: SSMCRMFRequestArg
* ----------------------------
* This structure will be used to pass the initialization information
* to the SSMCRMFRequest_Init function.
*
* keyPair The key pair that will be associated with the
* new CRMF request.
*
* connection The control connection to be associated with the
* new CRMF request. The SSMCRMFRequest object will
* use to get to the certificate and key databases.
*/
typedef struct SSMCRMFRequestArgStr {
SSMKeyPair *keyPair;
SSMControlConnection *connection;
} SSMCRMFRequestArg;
/*
* FUNCTION:SSM_CreateNewCRMFRequest
* ---------------------------------
* INPUTS:
* msg
* The message from the client requesting a new CRMF request.
* connection
* The control connection to be associated with the new request.
* destID
* Pointer to a pre-allocated chunk of memory where the function
* will place the ID of the newly created SSMCRMFRequest Object.
*
* NOTES:
* This function takes the message received by the client, interprets
* the message, creates a new SSMCRMFObject, adds it to the Global Resource
* table, and places the resource id of the new object at *destID. To free
* the returned object, call SSM_FreeResource and pass in the object object
* ID placed at *destID by this function.
*
* RETURN:
* The function returns PR_SUCCESS when successful. Any other return value
* should be interpreted as an error.
*/
SSMStatus SSM_CreateNewCRMFRequest(SECItem *msg,
SSMControlConnection *connection,
SSMResourceID *destID);
/*
* FUNCTION: SSMCRMFRequest_Create
* -------------------------------
* INPUTS:
* arg
* The creation argument for the SSMCRMFRequest class. This should
* be a pointer to SSMKeyPair resource.
* res
* Pointer to a pre-allocated chunk of memory where the function can
* place the value of the pointer to the newly created SSMCRMFRequest
* object
*
* NOTES:
* This function serves as the constructor for the SSMCRMFRequest class. This
* function over-rides the function SSMResource_Create which is the super
* class for SSMCRMFRequest.
*
* RETURN:
* Returns PR_SUCCESS upon successful creation. Any other error indicates an
* error.
*/
SSMStatus SSMCRMFRequest_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
/*
* FUNCTION: SSMCRMFRequest_Init
* -----------------------------
* INPUTS:
* inCRMFReq
* A pointer to a newly allocated SSMCRMFRequest which needs to be
* initialized.
* type
* The type for the class that is being initialized. This value should
* always be SSM_RESTYPE_CRMFREQ. (Unless one day someone decides to
* sub-class off of SSMCRMFRequest.)
* inKeyPair
* The Key Pair to associate with the CRMF request being initialized.
* inConnection
* The control connection to be associated with the request being
* initialized.
*
* NOTES:
* This function intializes a new SSMCRMFRequest object. This function will
* initialize its super-class member and make sure the passed in key pair has
* non-NULL values for mPrivKey and mPubKey before getting a reference to the
* passed in key pair. Finally, the function creates a
* new NSS based CRMF request and sets the following fields in the request:
* 1) version is set v3 Cert
* 2) The Public Key value in the request
*
* RETURN:
* The function returns PR_SUCCESS upon successful initialization. Any other
* return value should be interpreted as an error.
*/
SSMStatus SSMCRMFRequest_Init(SSMCRMFRequest *inCRMFReq,
SSMControlConnection * conn,
SSMResourceType type,
SSMKeyPair *inKeyPair,
SSMControlConnection *inConnection);
/*
* FUNCTION: SSMCRMFRequest_Destroy
* --------------------------------
* INPUTS:
* inRequest
* A pointer to a SSMResource of type SSM_RESTYPE_CRMFREQ to be
* destroyed.
* doFree
* Until the day when someone creates a sub-class of SSMCRMFRequest,
* this value should always be PR_TRUE.
*
* NOTES:
* This function takes of freeing up all memory associated with the
* SSMCRMFRequest. First the funciton will release the reference obtained
* for the member mKeyPair in the function SSMCRMFRequest_Init. The function
* then calls CRMF_DestroyCertRequest to free the memory used by mCRMFRequest.
* Finally, the function calls SSMResource_Destroy to free up the SSMResource
* member before calling free on the pointer passed in.
*
* RETURN:
* Function returns PR_SUCCESS upon successful destruction of the object. Any
* other return value should be interpreted as an error.
*/
SSMStatus SSMCRMFRequest_Destroy(SSMResource *inRequest, PRBool doFree);
/*
* FUNCTION: SSMCRMFRequest_SetAttr
* --------------------------------
* INPUTS:
* res
* A pointer to a SSMResource of type SSM_RESTYPE_CRMFREQ
* attrID
* The attribute to set in the request.
* value
* The data to use when setting the desired attribute.
*
* NOTES:
* This function over-rides SSMResource_SetAttr which all classes inherit
* from the SSMResource class. This function will set the following
* attributes (these attributes are defined in
* ns/security/ssm/lib/protocol/rsrcids.h):
*
* SSMAttributeID SSMResourceAttrType Value(s)
* -------------- ------------------- --------
* SSM_FID_CRMFREQ_KEY_TYPE SSM_NUMERIC_ATTRIBUTE A pointer to any
* enumerated value
* with type of
* SSMKeyGenType.
*
* SSM_FID_CRMFREQ_DN SSM_STRING_ATTRIBUTE An RFC1485
* formatted DN.
*
* SSM_FID_REGTOKEN SSM_STRING_ATTRIBUTE A string to place
* as the Registration
* token for the
* request.
*
* SSM_FID_AUTHENTICATOR SSM_STRING_ATTRIBUTE A string to place
* as the
* Authenticator token
* in the request.
*
* SSM_FID_CRMFREQ_ESCROW_AUTHORITY SSM_STRING_ATTRIBUTE A base64 encoded
* DER cert to use for
* creating the
* PKIArchiveOptions
* control.
*
* NOTES:
* The function return PR_SUCCESS if setting the field with the given data
* was successful. Any other return value should be considered an error.
*
*/
SSMStatus SSMCRMFRequest_SetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value);
/*
* FUNCTION: SSMCRMFRequest_SetEscrowAuthority
* -------------------------------------------
* INPUTS:
* crmfReq
* The CRMFRequest resource to add the escrow authority to.
* eaCert
* The Certificate that belongs to the CA that wants to
* escrow the private key associated with the request.
* NOTES:
* This function will wrap the private key in an EncryptedKey type
* defined by CRMF and include in the CRMF request that is generated.
*
* RETURN:
* PR_SUCCESS indicates the private key associated with the requested
* was successfully wrapped and made a part of the CRMF request. Any
* other return value indicates an error in trying to wrap the private
* and include it in the CRMF request.
*/
SSMStatus SSMCRMFRequest_SetEscrowAuthority(SSMCRMFRequest *crmfReq,
CERTCertificate *eaCert);
/*
* FUNCTION: SSM_EncodeCRMFRequests
* --------------------------------
* INPUTS:
* msg
* The message received from the client requesting CRMF messages to
* be encoded.
* destDER
* Pointer to a pre-allocated chunk of memory where the function can
* place a pointer to the base64 encoded CRMF CertReqMessages
* destLen
* Pointer to a pre-allocated piece of memory where the function can
* place the length of the string returned in *destDER.
*
* NOTES:
* This function takes a message request from the client to encode CRMF
* requests. The output will be base64 DER-formatted bytes of the type
* CertReqMessages as defined by the CRMF Internet Draft. The function
* will allocate a buffer in memory to store the DER using PORT_Alloc and
* place a pointer to the buffer at *destDER.
*
* RETURN:
* The function will return PR_SUCCESS if encoding the requests was successful.
* Any other return value should be treated as an error and the values at
* *destDER and *destLen should be ignored.
*/
SSMStatus SSM_EncodeCRMFRequests(SSMControlConnection * ctrl, SECItem *msg,
char **destDER, SSMPRUint32 *destLen);
/*
* FUNCTION: SSM_ProcessCMMFCertResponse
* -------------------------------------
* INPUTS:
* msg
* The message received from the client requesting Cartman to
* process a CMMF response.
* connection
* The control connection associated with the CMMF response.
* The connection is necessary so that the function can find
* the appropriate cetificate database for placing the decoded
* certificates.
*
* NOTES:
* This function serves as the back-end for the JavaScript method
* crypto.importUserCertificates. It will decode the base64 DER blob passed
* in and process it. Eventually this function will also start the process
* of backing up the certificate when Cartman supports that feature.
* View the document at http://warp/hardcore/library/arch/cert-issue.html
* to see a detailed explanation for what this function doess.
*
*/
SSMStatus SSM_ProcessCMMFCertResponse(SECItem *msg,
SSMControlConnection *connection);
/*
* FUNCTION: SSM_RespondToPOPChallenge
* -----------------------------------
* INPUTS:
* msg
* The message received from the client requesting that Cartman
* respond to a challenge.
* ctrl
* The Control Connection associated with the message to process.
* challengeResponse
* A pointer to a pre-allocated pointer where the function can place
* a copy of the base64 encoded response to the challenge. The
* response will be a POPODecKeyRespContent defined in the CMMF
* internet draft.
* responseLen
* A pointer to a pre-allocated PRUint32 where the function can place
* the length of the response returned via the challengeResponse input
* parameter.
*
* NOTES:
* This function servers as the back-end for the JavaScript method
* crypto.popChallengeRespone. The function will decode the base64 DER blob
* passed in and process it. The function
*/
SSMStatus SSM_RespondToPOPChallenge(SECItem *msg,
SSMControlConnection *ctrl,
char **challengeResponse,
PRUint32 *responseLen);
typedef struct SSMCRMFThreadArgStr {
SSMControlConnection *ctrl;
SECItem *msg;
} SSMCRMFThreadArg;
/*
* FUNCTION: SSM_CRMFEncodeThread
* ------------------------------
* INPUTS:
* arg
* A pointer to a structure of type SSMCRMFThreadArg which the function
* will use to encode a CRMF request.
* NOTES:
* This function is intended to encode a CRMF request taking a message from
* the client as its argument along with the associated control thread. This
* function will send the reply back to the client in case of success or
* failure so the client may proceed with its operations.
* RETURN:
* No return value.
*/
void SSM_CRMFEncodeThread(void *arg);
#endif /* _CRMFRES_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,255 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_CTRLCONN_H__
#define __SSM_CTRLCONN_H__
#include "connect.h"
#include "cert.h"
#include "key.h"
#include "hashtbl.h"
#include "obscure.h"
#include "prefs.h"
/*
Control connections.
*/
extern SSMHashTable * ctrlConnections;
struct SSMControlConnection
{
SSMConnection super;
/*
---------------------------------------------
Control connection-specific fields
---------------------------------------------
*/
PRUint32 m_version; /* Protocol version supported by client */
char * m_nonce; /* Nonce used for verifying data connections */
PRFileDesc * m_socket; /* Socket serviced by this connection object */
PRThread * m_writeThread;/* Write Control thread (writes m_socket) */
PRThread * m_frontEndThread; /* Front end thread - reads m_socket */
PRThread * m_certRenewalThread; /* Front end thread - reads m_socket */
char * m_profileName; /* Name of user profile (where to find
certs etc) */
char * m_dirRoot; /* Path to directory for certs for control connection */
/* Queue for outgoing messages */
SSMCollection *m_controlOutQ; /* Control msg queue: from readMsg thread
to writeMsg thread */
CERTCertDBHandle *m_certdb;
SECKEYKeyDBHandle *m_keydb;
/* Fields used for out-of-band password requests */
SSMHashTable * m_passwdTable;
PRMonitor * m_passwdLock;
SSMHashTable * m_encrPasswdTable;
PRMonitor * m_encrPasswdLock;
PRInt32 m_waiting;
SSMHashTable *m_resourceDB;
SSMHashTable *m_classRegistry;
SSMHashTable * m_resourceIdDB;
SSMResourceID m_lastRID;
SSMHashTable * m_certIdDB;
SECItem * m_secAdvisorList;
PRInt32 m_certNext;
/* Data socket and port */
PRFileDesc * m_dataSocket;
PRIntn m_dataPort;
PRBool m_doesUI;
PrefSet* m_prefs;
PRBool m_pkcs11Init;
};
SSMStatus SSM_InitPolicyHandler(void);
SSMStatus SSMControlConnection_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMControlConnection_Init(SSMControlConnection *res,
SSMResourceType type,
PRFileDesc *socket);
SSMStatus SSMControlConnection_Shutdown(SSMResource *conn, SSMStatus status);
SSMStatus SSMControlConnection_Destroy(SSMResource *res, PRBool doFree);
SSMStatus SSMControlConnection_GetAttrIDs(SSMResource* res, SSMAttributeID** ids,
PRIntn* count);
SSMStatus SSMControlConnection_GetAttr(SSMResource *res, SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
void SSMControlConnection_Invariant(SSMControlConnection *conn);
SSMStatus SSMControlConnection_ProcessMessage(SSMControlConnection* control,
SECItem* msg);
void SSM_WriteCtrlThread(void * arg);
void SSM_FrontEndThread(void * arg);
void SSM_CertificateRenewalThread(void * arg);
SSMStatus SSMControlConnection_Authenticate(SSMConnection *arg, char *nonce);
void SSMControlConnection_CertLookUp(SSMControlConnection * connection,
void * arg, SSMResource ** res);
SSMStatus SSMControlConnection_SendUIEvent(SSMControlConnection *conn,
char *command,
char *baseRef,
SSMResource *target, /* can pass NULL */
char *otherParams /* can pass NULL */,
CMTItem * clientContext /* can pass NULL */);
/*
* NOTES
* These functions save the pref change properly in memory and in client file.
* They check first whether the value has changed and perform saving
* operations.
* These functions do not belong to the prefs API because these specifically
* send the changes to the plugin. Once we have our own prefs library ready
* and complete the migration, these functions should be called only when
* application-specific prefs are saved back to client pref file.
* Since these functions pack one item only, if you have to send a lot of
* pref changes and performance is critical, it is not recommended to call
* these functions repeatedly.
*
*/
SSMStatus SSMControlConnection_SaveStringPref(SSMControlConnection* ctrl,
char* key, char* value);
SSMStatus SSMControlConnection_SaveBoolPref(SSMControlConnection* ctrl,
char* key, PRBool value);
SSMStatus SSMControlConnection_SaveIntPref(SSMControlConnection* ctrl,
char* key, PRIntn value);
void SSMControlConnection_CertLookUp(SSMControlConnection * connection,
void * arg, SSMResource ** res);
void SSM_LockPasswdTable(SSMConnection * conn);
SSMStatus SSM_UnlockPasswdTable(SSMConnection *conn);
SSMStatus SSM_WaitPasswdTable(SSMConnection * conn);
SSMStatus SSM_NotifyAllPasswdTable(SSMConnection * conn);
SSMStatus SSMControlConnection_AddResource(SSMResource * res, SSMResourceID rid);
SSMStatus SSMControlConnection_GetResource(SSMControlConnection * connection,
SSMResourceID rid,
SSMResource ** res);
SSMStatus SSMControlConnection_GetGlobalResourceID(SSMControlConnection
*connection,
SSMResource * res,
SSMResourceID * rid);
SSMResourceID SSMControlConnection_GenerateResourceID(SSMControlConnection *conn);
SSMStatus SSM_GetControlConnection(SSMResourceID rid,
SSMControlConnection **connection);
SSMStatus SSMControlConnection_FormSubmitHandler(SSMResource* res,
HTTPRequest* req);
void SSMControlConnection_RecycleItem(SECItem* msg);
SSMStatus SSMControlConnection_GenerateNonce(SSMControlConnection *conn);
/* from processmsg.c */
SSMStatus
SSMControlConnection_ProcessVerifyCertRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessImportCertRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessConserveRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessPickleRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessUnpickleRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessCertRequest(SSMControlConnection * ctrl,
SECItem * msg);
PRStatus
SSMControlConnection_ProcessKeygenTag(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessPKCS11Request(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessCRMFRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessMiscRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessFormSigningRequest(SSMControlConnection * ctrl,
SECItem *msg);
SSMStatus
SSMControlConnection_ProcessTLSRequest(SSMControlConnection * ctrl,
SECItem *msg);
SSMStatus
SSMControlConnection_ProcessProxyStepUpRequest(SSMControlConnection* ctrl,
SECItem* msg);
SSMStatus
SSMControlConnection_ProcessSecCfgRequest(SSMControlConnection * ctrl,
SECItem *msg);
SSMStatus
SSMControlConnection_ProcessGenKeyOldStyleToken(SSMControlConnection * ctrl,
SECItem *msg);
SSMStatus
SSMControlConnection_ProcessGenKeyPassword(SSMControlConnection * ctrl,
SECItem *msg);
SSMStatus
SSM_CertCAImportCommandHandler2(HTTPRequest * req);
void
ssm_ShutdownNSS(SSMControlConnection *ctrl);
SSMStatus
SSM_UseAsDefaultEmailIfNoneSet(SSMControlConnection *ctrl,
CERTCertificate *cert, PRBool onFrontEndThread);
CERTCertList *
SSMControlConnection_CreateCertListByNickname(SSMControlConnection * ctrl,
char * nick, PRBool email);
SSMStatus
ssmcontrolconnection_encode_err_reply(SECItem *msg, SSMStatus rv);
SSMStatus
ssmcontrolconnection_send_message_to_client(SSMControlConnection *ctrl,
SECItem *msg);
#endif /* __SSM_CTRLCONN_H__ */

View File

@ -0,0 +1,439 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "connect.h"
#include "dataconn.h"
#include "ctrlconn.h"
#include "servimpl.h"
#include "serv.h"
#include "ssmerrs.h"
#define SSMCONNECTION(p) (&(p)->super)
#define SSMRESOURCE(p) (&(p)->super.super)
/* How many milliseconds to wait for client input */
#define SSM_READCLIENT_POKE_INTERVAL 30000
SSMStatus SSMDataConnection_Create(void *arg, SSMControlConnection * connection,
SSMResource **res)
{
SSMStatus rv = PR_SUCCESS;
SSMDataConnection *conn;
*res = NULL; /* in case we fail */
conn = (SSMDataConnection *) PR_CALLOC(sizeof(SSMDataConnection));
if (!conn) goto loser;
rv = SSMDataConnection_Init(conn, (SSMControlConnection *) arg,
SSM_RESTYPE_DATA_CONNECTION);
if (rv != PR_SUCCESS) goto loser;
SSMDataConnection_Invariant(conn);
*res = SSMRESOURCE(conn);
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
if (conn)
{
SSM_ShutdownResource(SSMRESOURCE(conn), rv);
SSM_FreeResource(SSMRESOURCE(conn));
}
return rv;
}
SSMStatus SSMDataConnection_Init(SSMDataConnection *conn,
SSMControlConnection *parent,
SSMResourceType type)
{
SSMStatus rv = PR_SUCCESS;
SSMResourceType parentType = RESOURCE_CLASS(parent);
PR_ASSERT(parent != NULL);
PR_ASSERT((parentType == SSM_RESTYPE_CONTROL_CONNECTION) || (parentType == SSM_RESTYPE_CONNECTION));
if (!parent) goto loser;
rv = SSMConnection_Init(parent, SSMCONNECTION(conn), type);
if (rv != PR_SUCCESS) goto loser;
/* Initialize data shutdown queue. */
conn->m_shutdownQ = SSM_NewCollection();
if (conn->m_shutdownQ == NULL) {
goto loser;
}
/* Hang our shutdown func. */
SSMCONNECTION(conn)->m_auth_func = SSMDataConnection_Authenticate;
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
return rv;
}
SSMStatus SSMDataConnection_Destroy(SSMResource *res, PRBool doFree)
{
SSMDataConnection *conn = (SSMDataConnection *) res;
/* We should be shut down. */
PR_ASSERT(res->m_threadCount == 0);
/* Drain and destroy the queue. */
if (conn->m_shutdownQ) {
ssm_DrainAndDestroyQueue(&(conn->m_shutdownQ));
}
/* Destroy superclass fields. */
SSMConnection_Destroy(&(conn->super.super), PR_FALSE);
/* Free the connection object if asked. */
if (doFree)
PR_DELETE(conn);
return PR_SUCCESS;
}
void
SSMDataConnection_Invariant(SSMDataConnection *conn)
{
if (conn)
{
SSMConnection_Invariant(&conn->super);
SSM_LockResource(SSMRESOURCE(conn));
PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(conn), SSM_RESTYPE_DATA_CONNECTION));
PR_ASSERT(conn->m_shutdownQ != NULL);
SSM_UnlockResource(SSMRESOURCE(conn));
}
}
SSMStatus
SSMDataConnection_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count)
{
SSMStatus rv;
rv = SSMConnection_GetAttrIDs(res, ids, count);
if (rv != PR_SUCCESS)
goto loser;
*ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 1) * sizeof(SSMAttributeID));
if (! *ids) goto loser;
(*ids)[*count++] = SSM_FID_CONN_DATA_PENDING;
goto done;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMDataConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMStatus rv = PR_SUCCESS;
/* see what it is */
switch(attrID)
{
case SSM_FID_CONN_DATA_PENDING:
/* this is not used: will set it to zero for now */
*(PRUint32*)value->u.numeric = (PRUint32)0;
value->type = SSM_NUMERIC_ATTRIBUTE;
break;
default:
rv = SSMConnection_GetAttr(res,attrID,attrType,value);
if (rv != PR_SUCCESS) goto loser;
}
goto done;
loser:
value->type = SSM_NO_ATTRIBUTE;
done:
return rv;
}
SSMStatus SSMDataConnection_SetupClientSocket(SSMDataConnection* conn)
{
SSMControlConnection* parent = NULL;
char* pNonce;
char* temp = NULL; /* for nonce verification */
PRFileDesc* socket = NULL; /* client socket */
PRNetAddr clientAddr;
SSMStatus status = PR_FAILURE;
PRIntn read;
PR_ASSERT(conn != NULL);
/* Allocate a nonce-sized chunk of memory to read into.
(See below.) */
parent = (SSMControlConnection*)(conn->super.m_parent);
PR_ASSERT(parent != NULL);
pNonce = parent->m_nonce;
PR_ASSERT(pNonce != NULL);
SSM_DEBUG("I think my parent's nonce is `%s'.\n", pNonce);
temp = (char*)PORT_ZAlloc(strlen(pNonce));
while ((socket == NULL) && (SSMRESOURCE(conn)->m_status == PR_SUCCESS)) {
SSM_DEBUG("accepting next connect.\n");
/* Wait forever for a connection. (for now) */
socket = PR_Accept(SSMRESOURCE(conn)->m_connection->m_dataSocket,
&clientAddr, PR_INTERVAL_NO_TIMEOUT);
SSM_DEBUG("accepted connection.\n");
if ((SSMRESOURCE(conn)->m_status != PR_SUCCESS) && socket) {
/* May have gotten a socket, but we're shutting down.
Close and zero out the socket. */
PR_Close(socket);
SSM_LockResource(SSMRESOURCE(conn));
socket = conn->m_clientSocket = NULL;
SSM_UnlockResource(SSMRESOURCE(conn));
}
if (socket && !SSM_SocketPeerCheck(socket, PR_FALSE))
{
/*
Failed peer check. Close socket and listen again.
### mwelch - Could have a denial of service attack here if
someone keeps trying to connect to this port.
*/
PR_Close(socket);
socket = NULL;
continue;
}
if (socket) {
SSM_LockResource(SSMRESOURCE(conn));
conn->m_clientSocket = socket;
SSM_UnlockResource(SSMRESOURCE(conn));
SSM_DEBUG("reading/verifying nonce.\n");
status = PR_SUCCESS;
/* Read the nonce from the client. If we didn't get the right
nonce, reject the connection. */
if ((temp) && (pNonce != NULL)) {
read = SSM_ReadThisMany(socket, temp, strlen(pNonce));
if ((unsigned int)read != strlen(pNonce)) {
status = PR_GetError();
}
}
if ((status != PR_SUCCESS) || (memcmp(temp, pNonce,
strlen(pNonce)))) {
#ifdef DEBUG
char thing1[255];
char thing2[255];
strncpy(thing1, temp, strlen(pNonce));
strncpy(thing2, temp, strlen(pNonce));
/* Bad nonce, no biscuit! Shut down connection
and wait for another on the data port. */
SSM_DEBUG("Bad nonce, no biscuit!\n");
SSM_DEBUG("(`%s' != `%s')\n", thing1, thing2);
#endif
SSM_LockResource(SSMRESOURCE(conn));
PR_Close(conn->m_clientSocket);
conn->m_clientSocket = socket = NULL;
SSM_UnlockResource(SSMRESOURCE(conn));
}
}
else {
/* Tear everything down, didn't get a connection. */
SSM_DEBUG("Shutdown during connection setup.\n");
goto loser;
}
}
SSM_DEBUG("Nonce is valid.\n");
/* We have a socket. Close the data port. */
SSM_LockResource(SSMRESOURCE(conn));
SSM_DEBUG("Socket is %ld.\n", socket);
SSM_UnlockResource(SSMRESOURCE(conn));
loser:
if (temp != NULL) {
PR_Free(temp);
}
return status;
}
SSMStatus SSMDataConnection_ReadFromSocket(SSMDataConnection* conn,
PRInt32* read,
char* buffer)
{
SSMStatus status;
#if 0
SSMStatus osStat;
char statBuf[256];
#endif
PR_ASSERT(conn != NULL);
PR_ASSERT(buffer != NULL);
/* Attempt to read LINESIZE bytes from the socket. */
do {
SSM_DEBUG("Attempting to read %ld bytes.\n", *read);
*read = PR_Recv(conn->m_clientSocket, buffer, *read, 0,
PR_MillisecondsToInterval(SSM_READCLIENT_POKE_INTERVAL));
if (*read < 0) {
status = PR_GetError(); /* save status for later use */
#if 0
osStat = PR_GetOSError(); /* just for fun */
PR_GetErrorText(statBuf);
#endif
}
SSM_DEBUG("Got %ld bytes of data, status == %ld.\n", (long)(*read),
(long)status);
}
while ((*read == -1) && (status == PR_IO_TIMEOUT_ERROR) &&
SSMRESOURCE(conn)->m_status == PR_SUCCESS);
/* Don't mask an error if we got one, but set it if we didn't get any
* data (because that indicates a socket closure).
*/
if ((*read < 0) && (status == PR_SUCCESS)) {
status = PR_FAILURE;
}
else if (*read >= 0) {
status = PR_SUCCESS; /* clear the error from when we waited */
}
#if 0
/* Null terminate the buffer so that we can dump it. */
if (*read >= 0) {
buffer[*read] = '\0';
}
#endif
if (*read > 0) {
SSM_DEBUG("got %ld bytes of data: <%s>\n", *read, buffer);
}
return status;
}
SSMStatus
SSMDataConnection_Shutdown(SSMResource *res, SSMStatus status)
{
SSMStatus rv, trv;
PRThread *closer = PR_GetCurrentThread();
SSMDataConnection *conn = (SSMDataConnection *) res;
/* SSMDataConnection_Invariant(conn); -- could be called from loser */
/* Lock down the resource before shutting it down */
SSM_LockResource(SSMRESOURCE(conn));
/* If we're called from a service thread, clear that thread's
place in the connection object so it doesn't get interrupted */
if ((closer == conn->m_dataServiceThread) && (closer != NULL)) {
conn->m_dataServiceThread = NULL;
/* Decrement living thread counter */
SSMRESOURCE(conn)->m_threadCount--;
}
/* shut down base class */
rv = SSMConnection_Shutdown(res, status);
if ((SSMRESOURCE(conn)->m_status != PR_SUCCESS) &&
(rv != SSM_ERR_ALREADY_SHUT_DOWN) &&
(conn->m_clientSocket != NULL))
{
SSM_DEBUG("Shutting down data connection abnormally (rv == %d).\n",
SSMRESOURCE(conn)->m_status);
SSM_DEBUG("shutting down client socket.\n");
PR_Shutdown(conn->m_clientSocket, PR_SHUTDOWN_SEND);
/* if this is called by a control thread, send a message to the
* data service thread to shut down
*/
if ((closer != conn->m_dataServiceThread) &&
(conn->m_shutdownQ != NULL)) {
SSM_DEBUG("Send shutdown msg to data Q.\n");
trv = SSM_SendQMessage(conn->m_shutdownQ, SSM_PRIORITY_SHUTDOWN,
SSM_DATA_PROVIDER_SHUTDOWN, 0, NULL,
PR_TRUE);
}
if (conn->m_dataServiceThread) {
PR_Interrupt(conn->m_dataServiceThread);
}
}
/* If the client sockets is/are now unused, close them. */
if (SSMRESOURCE(conn)->m_threadCount == 0)
{
/* Close the client socket with linger */
if (conn->m_clientSocket)
{
SSM_DEBUG("Close data socket.\n");
trv = PR_Close(conn->m_clientSocket);
conn->m_clientSocket = NULL;
SSM_DEBUG("Closed client socket (rv == %d).\n",trv);
}
}
SSM_UnlockResource(SSMRESOURCE(conn));
return rv; /* so that subclasses know to perform shutdown */
}
SSMStatus
SSMDataConnection_Authenticate(SSMConnection *arg, char *nonce)
{
SSMStatus rv = SSM_FAILURE;
SSMConnection *parent = arg->m_parent;
/* Parent has the nonce, so authenticate there. */
if (parent &&
SSM_IsAKindOf(&(parent->super), SSM_RESTYPE_CONTROL_CONNECTION))
rv = SSMControlConnection_Authenticate(parent, nonce);
return rv;
}

View File

@ -0,0 +1,141 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_DATACONN_H__
#define __SSM_DATACONN_H__
#include "connect.h"
#include "ctrlconn.h"
/*
Cartman data connection/thread architecture:
Data connections are opened by the control connection in response
to a Request {SSL,etc.} Data message. There is one thread per data
connection that handles the data traffic, and there is one queue that
receives a shutdown message from a control thread.
If an exception or other termination occurs on either side, the
m_status flag is changed to the specific exception code, and sockets
are closed on either side (after final thread shutdown).
(### mwelch This has the effect of setting SO_LINGER on the outgoing
data stream, is this an issue?)
*/
/*
Data connection objects.
*/
typedef struct SSMDataConnection
{
SSMConnection super;
/*
---------------------------------------------
Data connection-specific fields - need to
merge with control fields or do something more
elegant in the long term.
---------------------------------------------
*/
PRUint32 m_dataType; /* What type of service are we
providing to client? */
PRThread* m_dataServiceThread; /* one and only data thread */
SSMCollection* m_shutdownQ; /* data queue that delivers a shutdown
message to the data service thread */
PRFileDesc *m_clientSocket; /* Client socket */
PRBool m_sendResult; /* When this connection shuts down,
send a result back to the client
(usage depends on subclass) */
} SSMDataConnection;
SSMStatus SSMDataConnection_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMDataConnection_Init(SSMDataConnection *conn,
SSMControlConnection *parent,
SSMResourceType type);
SSMStatus SSMDataConnection_Destroy(SSMResource *res, PRBool doFree);
void SSMDataConnection_Invariant(SSMDataConnection *conn);
SSMStatus SSMDataConnection_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMDataConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMDataConnection_Shutdown(SSMResource *arg, SSMStatus status);
SSMStatus SSMDataConnection_Authenticate(SSMConnection *arg, char *nonce);
/*
* Function: SSMStatus SSMDataConnection_SetupClientSocket()
* Purpose: sets up the client data socket and authenticates the connection.
* (blocking I/O)
* Arguments and return values:
* - conn: data connection object
* - returns: PR_SUCCESS if successful, error code otherwise
*/
SSMStatus SSMDataConnection_SetupClientSocket(SSMDataConnection* conn);
/*
* Function: SSMStatus SSMDataConnection_ReadFromSocket()
* Purpose: reads data from the client data socket and fill the buffer. When
* particular write target threads read data from the data socket,
* it is recommended that they use this function with the notable
* exception of SSL connections.
* Arguments and return values:
* - conn: data connection object
* - read: this is a value-result argument. It should be set to the data
* chunk size. One should always use LINESIZE unless there is a
* compelling reason to do otherwise. On return, this value will be
* filled with the actual size of the data (or 0 if EOF or < 0 if
* error).
* - buffer: data buffer. The memory should have been allocated before this
* function is called. The buffer size should be at least equal to
* the read size (thus the reason for specifying read value upon
* input).
* - returns: PR_SUCCESS if successful, error code otherwise
*
* Note: this is a blocking I/O operation.
*/
SSMStatus SSMDataConnection_ReadFromSocket(SSMDataConnection* conn,
PRInt32* read,
char* buffer);
#endif

View File

@ -0,0 +1,244 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "ctrlconn.h"
#include "dataconn.h"
#include "sslconn.h"
#include "p7cinfo.h"
#include "hashconn.h"
#include "servimpl.h"
#include "newproto.h"
#include "messages.h"
#include "serv.h"
#include "advisor.h"
#include "ssmerrs.h"
#ifdef TIMEBOMB
#include "timebomb.h"
#include "timebomb.c"
#endif
/* The ONLY reason why we can use these macros for both control and
data connections is that they inherit from the same superclass.
Do NOT try this at home. */
#define SSMCONNECTION(c) (&(c)->super)
#define SSMRESOURCE(c) (&(c)->super.super)
extern long ssm_ctrl_count;
/* This thread reads the control connection socket and
* forwards messages to appropriate queues.
*/
void SSM_FrontEndThread(void * arg)
{
PRFileDesc * socket = NULL;
SECItem * message = NULL;
SSMControlConnection * control = NULL;
PRIntn read;
SSMStatus rv = PR_SUCCESS;
char * passwd = NULL;
char * tmp;
PasswordReply reply;
CMTMessageHeader header;
control = (SSMControlConnection *)arg;
SSM_RegisterNewThread("ctrl frontend", (SSMResource *) arg);
SSM_DEBUG("initializing.\n");
if (!control || !control->m_socket)
{
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
goto loser;
}
control->m_frontEndThread = PR_GetCurrentThread();
socket = control->m_socket;
#ifdef TIMEBOMB
if (SSMTimeBombExpired)
SSM_CartmanHasExpired(control);
#endif
/* start a write thread for this connection */
SSM_DEBUG("creating accompanying write thread.\n");
control->m_writeThread = SSM_CreateThread(SSMRESOURCE(control),
SSM_WriteCtrlThread);
if (!control->m_writeThread)
{
rv = PR_FAILURE;
goto loser;
}
/* initialize connection outgoing queue */
SSM_DEBUG("Initialize OUT queue for control connection\n");
SSM_SendQMessage(control->m_controlOutQ,
SSM_PRIORITY_NORMAL,
SSM_DATA_PROVIDER_OPEN, 0, NULL,
PR_TRUE);
while ((SSMRESOURCE(control)->m_status == PR_SUCCESS)
&& (rv == PR_SUCCESS))
{
/* read and process data here
*/
SSM_DEBUG("waiting for new message from socket.\n");
read = SSM_ReadThisMany(socket, &header, sizeof(CMTMessageHeader));
if (read != sizeof(CMTMessageHeader))
{
SSM_DEBUG("Bytes read (%ld) != bytes expected (%ld). (hdr)\n",
(long) read,
(long) sizeof(CMTMessageHeader));
rv = PR_FAILURE;
goto loser;
}
message = SSM_ConstructMessage(PR_ntohl(header.len));
if (!message)
{
SSM_DEBUG("Missing message.\n");
rv = PR_OUT_OF_MEMORY_ERROR;
goto loser;
}
message->type = (SECItemType) PR_ntohl(header.type);
/* Read the message body */
SSM_DEBUG("reading %ld more from socket.\n", message->len);
read = SSM_ReadThisMany(socket, (void *)message->data, message->len);
if ((unsigned int) read != message->len)
{
SSM_DEBUG("Bytes read (%ld) != bytes expected (%ld). (msg)\n",
(long) read,
(long) message->len);
rv = PR_GetError();
if (rv == PR_SUCCESS) rv = PR_FAILURE;
goto loser;
}
/*
* Message successfully received, now file it to appropriate queue
*//*
if ((message->type & SSM_CATEGORY_MASK) == SSM_EVENT_MESSAGE) {
*/
switch (message->type &SSM_CATEGORY_MASK) {
case SSM_EVENT_MESSAGE:
switch (message->type & SSM_TYPE_MASK) {
case SSM_AUTH_EVENT:
/* deal with authentication message */
/* Decode the the password reply message */
if (CMT_DecodeMessage(PasswordReplyTemplate, &reply, (CMTItem*)message) != CMTSuccess) {
goto loser;
}
/* Get the lock for the password hash table */
SSM_LockPasswdTable((SSMConnection *) control);
rv = SSM_HashRemove(control->m_passwdTable, reply.tokenID, (void **)&tmp);
if (rv != PR_SUCCESS) {
SSM_DEBUG("Passwd request for token %d hasn't been registered.\n",
reply.tokenID);
SSM_DEBUG("Drop the message, continue waiting...\n");
PR_Free(passwd);
passwd = NULL;
goto done_auth;
}
if (reply.result != 0) {
SSM_DEBUG("Error getting password %d.\n", reply.result);
reply.passwd = (char*)SSM_CANCEL_PASSWORD;
}
if (!reply.passwd) {
/* user entered a zero length password, which is valid */
reply.passwd = "";
}
rv = SSM_HashInsert(control->m_passwdTable, reply.tokenID,
reply.passwd);
if (rv != PR_SUCCESS)
SSM_DEBUG("%ld: can't enter passwd in hash table.\n", control);
passwd = NULL; /* passwd is now pointed to the hash table entry */
/* notify all waiting threads that the password has arrived */
SSM_DEBUG("%ld : notify password table that passwd is available\n",
control);
rv = SSM_NotifyAllPasswdTable((SSMConnection *)control);
if (rv != PR_SUCCESS) {
SSM_DEBUG("Error on NotifyAll on the password table:%d.\n",
PR_GetError());
goto done_auth;
}
done_auth:
/* We are done, release the lock */
SSM_UnlockPasswdTable((SSMConnection *)control);
break;
case SSM_FILE_PATH_EVENT:
SSM_HandleFilePathReply(control, message);
break;
case SSM_PROMPT_EVENT:
SSM_HandleUserPromptReply(control, message);
break;
#if 0
case SSM_GET_JAVA_PRINCIPALS_EVENT:
SSM_HandleGetJavaPrincipalsReply(control, message);
break;
#endif
case SSM_MISC_EVENT:
if ((message->type & SSM_SUBTYPE_MASK) == SSM_MISC_PUT_RNG_DATA)
{
/* Got fodder for the RNG. Seed it. */
SSM_DEBUG("Got %ld bytes of RNG seed data.\n", message->len);
rv = RNG_RandomUpdate(message->data, message->len)
== SECSuccess ? SSM_SUCCESS : SSM_FAILURE;
}
default:
break;
}
break;
default:
/* process the message */
rv = SSMControlConnection_ProcessMessage(control, message);
}
/* Free the message */
SSM_FreeMessage(message);
message = NULL;
} /* end of the read-socket loop */
loser:
SSM_DEBUG("shutting down, status = %ld.\n", rv);
if (control)
{
SSM_ShutdownResource(SSMRESOURCE(control), rv);
SSM_FreeResource(SSMRESOURCE(control));
}
return;
}

View File

@ -0,0 +1,413 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "hashconn.h"
#include "dataconn.h"
#include "serv.h"
#include "servimpl.h"
#include "ssmerrs.h"
#include "newproto.h"
#include "messages.h"
#include "collectn.h"
/* Shorthand macros for inherited classes */
#define SSMRESOURCE(sslconn) (&(sslconn)->super.super.super)
#define SSMCONNECTION(sslconn) (&(sslconn)->super.super)
#define SSMDATACONNECTION(sslconn) (&(sslconn)->super)
void SSMHashConnection_ServiceThread(void * arg);
SSMStatus SSMHashConnection_StartHashing(SSMHashConnection *conn);
SSMStatus SSMHashConnection_FinishHashing(SSMHashConnection *conn);
SSMStatus SSMHashConnection_Create(void *arg, SSMControlConnection * connection,
SSMResource **res)
{
SSMStatus rv = PR_SUCCESS;
SSMHashConnection *conn;
*res = NULL; /* in case we fail */
conn = (SSMHashConnection *) PR_CALLOC(sizeof(SSMHashConnection));
if (!conn) goto loser;
SSMRESOURCE(conn)->m_connection = connection;
rv = SSMHashConnection_Init(conn, (SSMHashInitializer *) arg,
SSM_RESTYPE_HASH_CONNECTION);
if (rv != PR_SUCCESS) goto loser;
SSMHashConnection_Invariant(conn);
*res = SSMRESOURCE(conn);
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
if (conn)
{
SSM_ShutdownResource(SSMRESOURCE(conn), rv); /* force destroy */
SSM_FreeResource(SSMRESOURCE(conn));
}
return rv;
}
SSMStatus SSMHashConnection_Init(SSMHashConnection *conn,
SSMHashInitializer *init,
SSMResourceType type)
{
SSMStatus rv = PR_SUCCESS;
SSMControlConnection *parent = init->m_parent;
rv = SSMDataConnection_Init(SSMDATACONNECTION(conn), parent, type);
if (rv != PR_SUCCESS) goto loser;
/* Add the hash type. */
conn->m_type = init->m_hashtype;
/* Verify that the hash type is something we can work with. */
SSMHashConnection_StartHashing(conn);
rv = (conn->m_context) ? PR_SUCCESS : PR_INVALID_ARGUMENT_ERROR;
SSMHashConnection_FinishHashing(conn);
conn->m_resultLen = 0;
if (rv != PR_SUCCESS) goto loser;
/* Spin the service thread to set up the SSL connection. */
SSM_DEBUG("Creating hash service thread.\n");
SSM_GetResourceReference(SSMRESOURCE(conn));
SSMDATACONNECTION(conn)->m_dataServiceThread =
SSM_CreateThread(SSMRESOURCE(conn),
SSMHashConnection_ServiceThread);
if (SSMDATACONNECTION(conn)->m_dataServiceThread == NULL) {
goto loser;
}
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
return rv;
}
SSMStatus
SSMHashConnection_FinishHashing(SSMHashConnection *conn)
{
SSMStatus rv = SSM_SUCCESS;
SSM_LockResource(SSMRESOURCE(conn));
/* If we have a context, end the hash. */
if (conn->m_context)
{
HASH_End(conn->m_context, conn->m_result, &conn->m_resultLen,
SSM_HASH_RESULT_LEN);
if (conn->m_resultLen == 0)
rv = SSM_FAILURE;
HASH_Destroy(conn->m_context);
conn->m_context = NULL;
}
SSM_UnlockResource(SSMRESOURCE(conn));
return rv;
}
SSMStatus
SSMHashConnection_StartHashing(SSMHashConnection *conn)
{
PR_ASSERT(conn->m_context == NULL);
SSM_LockResource(SSMRESOURCE(conn));
if (conn->m_context)
SSMHashConnection_FinishHashing(conn);
conn->m_resultLen = 0;
conn->m_context = HASH_Create(conn->m_type);
SSM_UnlockResource(SSMRESOURCE(conn));
return (conn->m_context ? PR_SUCCESS : PR_FAILURE);
}
SSMStatus SSMHashConnection_Destroy(SSMResource *res, PRBool doFree)
{
SSMHashConnection *conn = (SSMHashConnection *) res;
if (doFree)
SSM_DEBUG("SSMHashConnection_Destroy called.\n");
/* We should be shut down. */
PR_ASSERT(res->m_threadCount == 0);
/* Destroy our fields. */
SSM_LockResource(SSMRESOURCE(conn));
if (conn->m_context)
SSMHashConnection_FinishHashing(conn);
SSM_UnlockResource(SSMRESOURCE(conn));
/* Destroy superclass fields. */
SSMDataConnection_Destroy(SSMRESOURCE(conn), PR_FALSE);
/* Free the connection object if asked. */
if (doFree)
PR_DELETE(conn);
return PR_SUCCESS;
}
void
SSMHashConnection_Invariant(SSMHashConnection *conn)
{
SSMDataConnection_Invariant(SSMDATACONNECTION(conn));
/* our specific invariants */
SSM_LockResource(SSMRESOURCE(conn));
/* we should not be simultaneously hashed and hashing */
if (conn->m_context)
PR_ASSERT(conn->m_resultLen == 0);
SSM_UnlockResource(SSMRESOURCE(conn));
}
SSMStatus
SSMHashConnection_Shutdown(SSMResource *arg, SSMStatus status)
{
SSMStatus rv;
PR_ASSERT(SSM_IsAKindOf(arg, SSM_RESTYPE_HASH_CONNECTION));
/* Call our superclass shutdown. Thread control is handled there. */
rv = SSMDataConnection_Shutdown(arg, status);
return rv;
}
/*
Hashing is performed by a single service thread. This thread
feeds data from the outgoing queue into the hash context.
*/
void SSMHashConnection_ServiceThread(void * arg)
{
SSMStatus rv = PR_SUCCESS;
SSMHashConnection * conn;
SSMControlConnection *ctrl;
SECItem *msg;
PRIntn read;
char buffer[LINESIZE+1] = {0};
SSM_RegisterNewThread("hash service", (SSMResource *) arg);
conn = (SSMHashConnection *)arg;
SSM_DEBUG("initializing.\n");
if (!arg)
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
goto loser;
}
SSMDATACONNECTION(conn)->m_dataServiceThread = PR_GetCurrentThread();
/* set up the client data socket and authenticate it with nonce */
rv = SSMDataConnection_SetupClientSocket(SSMDATACONNECTION(conn));
if (rv != PR_SUCCESS) {
goto loser;
}
/* Start hashing. */
SSM_DEBUG("creating hash context.\n");
SSMHashConnection_StartHashing(conn);
/* Loop for as long as we have data. */
while ((SSMRESOURCE(conn)->m_status == PR_SUCCESS) &&
(SSM_Count(SSMDATACONNECTION(conn)->m_shutdownQ) == 0) &&
(rv == PR_SUCCESS)) {
read = LINESIZE; /* set the read size to the default line size */
rv = SSMDataConnection_ReadFromSocket(SSMDATACONNECTION(conn),
(PRInt32*)&read, buffer);
if (read > 0) {
/* there is data, add it to hash */
SSM_DEBUG("Received %ld bytes of data for hasher.\n", read);
PR_ASSERT(conn->m_context);
HASH_Update(conn->m_context, (unsigned char *) buffer, (unsigned int)read);
}
else {
/* either EOF or an error condition */
goto finish;
}
}
finish:
SSM_DEBUG("Got shutdown msg.\n");
/* Lock the resource object, so that we know that attribute requests
won't be pending while we work. */
SSM_LockResource(SSMRESOURCE(conn));
/* SSM_ShutdownResource(SSMRESOURCE(conn), PR_SUCCESS);*/
SSMHashConnection_FinishHashing(conn);
/* If we've been asked to return the result, do it now. */
if (SSMDATACONNECTION(conn)->m_sendResult) {
SSM_DEBUG("Responding to deferred hash result request.\n");
msg = (SECItem*)PORT_ZAlloc(sizeof(SECItem));
PR_ASSERT(msg != NULL); /* need to have some preallocated
failure to send */
if (conn->m_result) {
SSMAttributeValue value;
GetAttribReply reply;
value.type = SSM_STRING_ATTRIBUTE;
value.u.string.len = conn->m_resultLen;
value.u.string.data = conn->m_result;
msg->type = (SECItemType) (SSM_REPLY_OK_MESSAGE | SSM_RESOURCE_ACTION
| SSM_GET_ATTRIBUTE | SSM_STRING_ATTRIBUTE);
reply.result = rv;
reply.value = value;
if (CMT_EncodeMessage(GetAttribReplyTemplate, (CMTItem*)msg, &reply) != CMTSuccess) {
goto loser;
}
SSM_DEBUG("Generated a reply (t %lx/l %ld/d %lx)\n",
msg->type, msg->len, msg->data);
value.u.string.data = NULL;
SSM_DestroyAttrValue(&value, PR_FALSE);
}
else {
SingleNumMessage reply;
msg->type = (SECItemType) (SSM_REPLY_ERR_MESSAGE | SSM_RESOURCE_ACTION
| SSM_GET_ATTRIBUTE | SSM_STRING_ATTRIBUTE);
reply.value = SSM_ERR_ATTRIBUTE_MISSING;
if (CMT_EncodeMessage(GetAttribReplyTemplate, (CMTItem*)msg, &reply) != CMTSuccess) {
goto loser;
}
SSM_DEBUG("Generated error reply (t %lx/l %ld/d %lx)\n",
msg->type, msg->len, msg->data);
}
/* Post this message to the parent's control queue
for delivery back to the client. */
ctrl = (SSMControlConnection*)SSMCONNECTION(conn)->m_parent;
PR_ASSERT(SSM_IsAKindOf(&ctrl->super.super, SSM_RESTYPE_CONTROL_CONNECTION));
rv = SSM_SendQMessage(ctrl->m_controlOutQ,
SSM_PRIORITY_NORMAL,
msg->type, msg->len,
(char*)msg->data, PR_TRUE);
SSM_FreeMessage(msg);
if (rv != PR_SUCCESS) goto loser;
}
SSM_UnlockResource(SSMRESOURCE(conn));
loser:
SSM_DEBUG("** Thread shutting down ** (%ld)\n", rv);
if (conn != NULL) {
SSM_ShutdownResource(SSMRESOURCE(conn), rv);
SSM_FreeResource(SSMRESOURCE(conn));
}
}
SSMStatus
SSMHashConnection_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count)
{
SSMStatus rv;
rv = SSMDataConnection_GetAttrIDs(res, ids, count);
if (rv != PR_SUCCESS)
goto loser;
*ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 1) * sizeof(SSMAttributeID));
if (! *ids) goto loser;
(*ids)[*count++] = SSM_FID_HASHCONN_RESULT;
goto done;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMHashConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMStatus rv = PR_SUCCESS;
SSMHashConnection *hc = (SSMHashConnection *) res;
if (! hc)
return PR_INVALID_ARGUMENT_ERROR;
SSMHashConnection_Invariant(hc);
SSM_LockResource(SSMRESOURCE(hc));
/* see what it is */
switch(attrID)
{
case SSM_FID_HASHCONN_RESULT:
if (hc->m_resultLen == 0)
{
/* Still waiting on hashing to finish.
Set the flag which tells us to return the attribute
when we finish. */
SSMDATACONNECTION(hc)->m_sendResult = PR_TRUE;
rv = SSM_ERR_DEFER_RESPONSE;
goto loser;
}
/* XXX Fix this. Return the hash result in a string. */
value->type = SSM_STRING_ATTRIBUTE;
value->u.string.len = hc->m_resultLen;
value->u.string.data = (unsigned char *) PR_CALLOC(hc->m_resultLen);
if (value->u.string.data)
memcpy(value->u.string.data, hc->m_result, hc->m_resultLen);
else
value->u.string.len = 0;
break;
default:
rv = SSMDataConnection_GetAttr(res,attrID,attrType,value);
if (rv != PR_SUCCESS)
goto loser;
}
goto done;
loser:
value->type = SSM_NO_ATTRIBUTE;
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
done:
SSM_UnlockResource(SSMRESOURCE(hc));
return rv;
}

View File

@ -0,0 +1,85 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_HASHCONN_H__
#define __SSM_HASHCONN_H__
#include "prerror.h"
#include "sechash.h"
#include "ctrlconn.h"
#include "dataconn.h"
#define SSM_HASH_RESULT_LEN 1024
/* Used to initialize an SSMHashConnection */
typedef struct SSMHashInitializer
{
SSMControlConnection *m_parent;
HASH_HashType m_hashtype;
} SSMHashInitializer;
/*
Hash connection object
*/
typedef struct SSMHashConnection
{
SSMDataConnection super;
HASHContext *m_context;
HASH_HashType m_type;
PRUint32 m_resultLen;
unsigned char m_result[SSM_HASH_RESULT_LEN];
} SSMHashConnection;
SSMStatus SSMHashConnection_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMHashConnection_Init(SSMHashConnection *conn,
SSMHashInitializer *init,
SSMResourceType type);
SSMStatus SSMHashConnection_Destroy(SSMResource *res, PRBool doFree);
void SSMHashConnection_Invariant(SSMHashConnection *conn);
SSMStatus SSMHashConnection_Shutdown(SSMResource *arg, SSMStatus status);
SSMStatus SSMHashConnection_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMHashConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
#endif

View File

@ -0,0 +1,418 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
/*
hashtbl.c -- hash tables for Cartman, specifically for use with
resources (32-bit integer keys).
*/
#include "hashtbl.h"
#define BUCKETNUM(key) ((key) & (HASH_NUM_BUCKETS-1))
/* SSMHashBucket support routines */
void ssmbucket_invariant(SSMHashBucket *bucket)
{
PR_ASSERT(bucket->m_size >= 0);
PR_ASSERT(bucket->m_allocSize > 0);
PR_ASSERT(bucket->m_size <= bucket->m_allocSize);
PR_ASSERT(bucket->m_keys != NULL);
PR_ASSERT(bucket->m_values != NULL);
}
SSMStatus ssmbucket_remove(SSMHashBucket *bucket, PRIntn whichElem)
{
SSMHashKey *keyptr;
void **valptr;
PRIntn numToMove;
ssmbucket_invariant(bucket);
PR_ASSERT(whichElem < bucket->m_size);
if (whichElem >= bucket->m_size) return PR_FAILURE;
keyptr = bucket->m_keys + whichElem;
valptr = bucket->m_values + whichElem;
numToMove = bucket->m_size - (whichElem + 1);
memmove(keyptr, keyptr + 1, numToMove * sizeof(SSMHashKey));
memmove(valptr, valptr + 1, numToMove * sizeof(void *));
bucket->m_size--;
ssmbucket_invariant(bucket);
return PR_SUCCESS;
}
PRIntn ssmbucket_find(SSMHashBucket *bucket, SSMHashKey key)
{
PRIntn i;
for(i=0;i<bucket->m_size; i++)
{
if (bucket->m_keys[i] == key)
return i;
}
return -1;
}
SSMStatus ssmbucket_grow(SSMHashBucket *bucket)
{
size_t newSize;
SSMHashKey *newKeys = NULL;
void **newValues = NULL;
ssmbucket_invariant(bucket);
/* If we're growing, double the size */
newSize = bucket->m_allocSize * 2;
/* realloc the memory. is this broken? */
newKeys = (SSMHashKey *) PR_REALLOC(bucket->m_keys, newSize * sizeof(SSMHashKey));
if (!newKeys) goto loser;
newValues = (void **) PR_REALLOC(bucket->m_values, newSize * sizeof(void *));
if (!newValues) goto loser;
bucket->m_keys = newKeys;
bucket->m_values = newValues;
bucket->m_allocSize = newSize;
ssmbucket_invariant(bucket);
return PR_SUCCESS;
loser:
if (newKeys) PR_Free(newKeys);
if (newValues) PR_Free(newValues);
return PR_FAILURE;
}
SSMStatus ssmbucket_add(SSMHashBucket *bucket, SSMHashKey key, void *value)
{
PRIntn newSize = bucket->m_size + 1;
SSMStatus rv = PR_SUCCESS;
ssmbucket_invariant(bucket);
if (bucket->m_size >= bucket->m_allocSize)
rv = ssmbucket_grow(bucket);
if (rv == PR_SUCCESS)
{
bucket->m_keys[newSize-1] = key;
bucket->m_values[newSize-1] = value;
bucket->m_size = newSize;
}
ssmbucket_invariant(bucket);
return rv;
}
SSMStatus ssmbucket_free(SSMHashBucket *bucket)
{
if (bucket)
{
if (bucket->m_keys)
{
PR_Free(bucket->m_keys);
bucket->m_keys = NULL;
}
if (bucket->m_values)
{
PR_Free(bucket->m_values);
bucket->m_values = NULL;
}
bucket->m_size = bucket->m_allocSize = 0;
}
return PR_SUCCESS;
}
SSMStatus ssmbucket_init(SSMHashBucket *bucket)
{
bucket->m_keys = NULL;
bucket->m_values = NULL;
bucket->m_keys = (SSMHashKey *) PR_CALLOC(2 * sizeof(SSMHashKey));
if (!bucket->m_keys) goto loser;
bucket->m_values = (void **) PR_CALLOC(2 * sizeof(void *));
if (!bucket->m_values) goto loser;
bucket->m_size = 0;
bucket->m_allocSize = 2;
return PR_SUCCESS;
loser:
ssmbucket_free(bucket);
return PR_FAILURE;
}
/************************************************************
** FUNCTION: SSM_HashInsert
** DESCRIPTION: Insert a new data item keyed by (key) into (hash).
** INPUTS:
** hash
** The hash into which the item is to be inserted.
** key
** The key used to store the item.
** value
** The item to be inserted.
** RETURNS:
** PR_SUCCESS on success.
** PR_FAILURE on failure.
**
*************************************************************/
SSMStatus SSM_HashInsert(SSMHashTable *hash, SSMHashKey key, void *value)
{
PRIntn whichElem;
if ((hash == NULL) || (value == NULL))
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
PR_EnterMonitor(hash->m_hashLock);
/* If the key already exists, replace the value.
Otherwise, add the new key/value. */
whichElem = ssmbucket_find(&(hash->m_buckets[BUCKETNUM(key)]), key);
if (whichElem >= 0)
hash->m_buckets[BUCKETNUM(key)].m_values[whichElem] = value;
else
ssmbucket_add(&(hash->m_buckets[BUCKETNUM(key)]), key, value);
PR_ExitMonitor(hash->m_hashLock);
return PR_SUCCESS;
}
SSMStatus ssm_HashFindValue(SSMHashTable *hash, SSMHashKey key, void **value,
PRBool removeElem)
{
PRIntn whichElem;
SSMStatus rv = PR_SUCCESS;
if ((hash == NULL) || (value == NULL))
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
PR_EnterMonitor(hash->m_hashLock);
*value = NULL; /* in case we fail */
whichElem = ssmbucket_find(&(hash->m_buckets[BUCKETNUM(key)]), key);
if (whichElem >= 0)
{
*value = hash->m_buckets[BUCKETNUM(key)].m_values[whichElem];
if (removeElem)
rv = ssmbucket_remove(&(hash->m_buckets[BUCKETNUM(key)]),
whichElem);
}
else
rv = PR_FAILURE;
PR_ExitMonitor(hash->m_hashLock);
return rv;
}
/************************************************************
** FUNCTION: SSM_HashFind
** DESCRIPTION: Get the item whose key is (key).
** INPUTS:
** hash
** The hash from which the item is to be retrieved.
** key
** The key used to store the item.
** value
** The item to be returned. Set to NULL if no suitable
** item is found.
** RETURNS:
** PR_SUCCESS on success.
** PR_FAILURE on failure.
**
*************************************************************/
SSMStatus SSM_HashFind(SSMHashTable *hash, SSMHashKey key, void **value)
{
return ssm_HashFindValue(hash, key, value, PR_FALSE);
}
/************************************************************
** FUNCTION: SSM_HashRemove
** DESCRIPTION: Remove from a hash the item whose key is (key).
** INPUTS:
** hash
** The hash from which the item is to be removed.
** key
** The key used to store the item.
** value
** The value removed from the hash.
** RETURNS:
** PR_SUCCESS on success.
** PR_FAILURE on failure.
**
*************************************************************/
SSMStatus SSM_HashRemove(SSMHashTable *hash, SSMHashKey key, void **value)
{
return ssm_HashFindValue(hash, key, value, PR_TRUE);
}
/************************************************************
** FUNCTION: SSM_HashKeys
** DESCRIPTION: Get keys for all items stored in the hash.
** INPUTS:
** hash
** The hash from which the keys are to be returned.
** keys
** Returns an array of keys. The array is allocated using PR_Malloc.
** numKeys
** Returns the number of keys in the array.
** RETURNS:
** PR_SUCCESS on success.
** PR_FAILURE on failure.
**
*************************************************************/
SSMStatus SSM_HashKeys(SSMHashTable *hash, SSMHashKey **keys, PRIntn *numKeys)
{
SSMHashKey *rkeys = NULL, *walk;
PRIntn i, howMany;
/* in case we fail */
*keys = NULL;
*numKeys = 0;
if (hash == NULL)
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
PR_EnterMonitor(hash->m_hashLock);
rkeys = (SSMHashKey *) PR_CALLOC(hash->m_size * sizeof(SSMHashKey));
if (!rkeys)
return PR_FAILURE;
/* Walk through all the buckets, grabbing their keys. */
walk = rkeys;
for(i=0;i<HASH_NUM_BUCKETS;i++)
{
howMany = hash->m_buckets[i].m_size;
(void) memcpy(walk, hash->m_buckets[i].m_keys,
hash->m_buckets[i].m_size * sizeof(SSMHashKey));
walk += howMany;
}
PR_ExitMonitor(hash->m_hashLock);
*keys = rkeys;
*numKeys = hash->m_size;
return PR_SUCCESS;
}
/************************************************************
** FUNCTION: SSM_HashDestroy
** DESCRIPTION: Destroy a hash. Items in the hash are not freed.
** INPUTS:
** hash
** The hash to be destroyed.
** RETURNS:
** PR_SUCCESS on success.
** PR_FAILURE on failure.
**
*************************************************************/
SSMStatus SSM_HashDestroy(SSMHashTable *hash)
{
if (hash)
{
PRIntn i;
for (i=0;i<HASH_NUM_BUCKETS;i++)
ssmbucket_free(&(hash->m_buckets[i]));
PR_DestroyMonitor(hash->m_hashLock);
PR_Free(hash);
}
return PR_SUCCESS;
}
/************************************************************
** FUNCTION: SSM_HashCreate
** DESCRIPTION: Create and initialize a hash.
** INPUTS:
** hash
** Returns the newly created hash.
** RETURNS:
** PR_SUCCESS on success.
** PR_FAILURE on failure.
**
*************************************************************/
SSMStatus SSM_HashCreate(SSMHashTable **hash)
{
PRIntn i;
SSMHashTable *rhash;
*hash = NULL; /* in case we fail */
rhash = (SSMHashTable *) PR_CALLOC(sizeof(SSMHashTable));
if (!rhash) goto loser;
for(i=0;i<HASH_NUM_BUCKETS;i++)
{
if (ssmbucket_init(&(rhash->m_buckets[i])))
goto loser;
}
rhash->m_hashLock = PR_NewMonitor();
if (!rhash->m_hashLock)
goto loser;
*hash = rhash;
return PR_SUCCESS;
loser:
if (rhash)
SSM_HashDestroy(rhash);
return PR_FAILURE;
}
SSMStatus SSM_HashCount(SSMHashTable *hash, PRIntn *numItems)
{
*numItems = 0; /* in case we fail */
if (hash == NULL)
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
*numItems = hash->m_size;
return PR_SUCCESS;
}

View File

@ -0,0 +1,192 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_HASHTBL_H__
#define __SSM_HASHTBL_H__
#include "nspr.h"
#include "prtypes.h"
#include "prmem.h"
#include "seccomon.h"
#include "secitem.h"
#include "ssmdefs.h"
/* It's a cheap method of hashing; we use the lower HASH_USE_LOW_BITS
bits of the key to determine what bucket it fits in.
Oh, what a hack. */
#define HASH_USE_LOW_BITS 4
#define HASH_NUM_BUCKETS (1 << HASH_USE_LOW_BITS)
typedef PRInt32 SSMHashKey;
struct _ssm_hashbucket
{
SSMHashKey *m_keys;
void **m_values;
PRIntn m_size;
PRIntn m_allocSize;
};
typedef struct _ssm_hashbucket SSMHashBucket;
struct _ssm_hashtbl
{
SSMHashBucket m_buckets[HASH_NUM_BUCKETS];
PRIntn m_size;
PRMonitor * m_hashLock;
};
typedef struct _ssm_hashtbl SSMHashTable;
/************************************************************
** FUNCTION: SSM_HashInsert
** DESCRIPTION: Insert a new data item keyed by (key) into (hash).
** INPUTS:
** hash
** The hash into which the item is to be inserted.
** key
** The key used to store the item.
** value
** The item to be inserted.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or the underlying NSPR error,
** if it is available.
**
*************************************************************/
SSMStatus SSM_HashInsert(SSMHashTable *hash, SSMHashKey key, void *value);
/************************************************************
** FUNCTION: SSM_HashFind
** DESCRIPTION: Get the item whose key is (key).
** INPUTS:
** hash
** The hash from which the item is to be retrieved.
** key
** The key used to store the item.
** value
** The item to be returned. Set to NULL if no suitable
** item is found.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or the underlying NSPR error,
** if it is available.
**
*************************************************************/
SSMStatus SSM_HashFind(SSMHashTable *hash, SSMHashKey key, void **value);
/************************************************************
** FUNCTION: SSM_HashRemove
** DESCRIPTION: Remove from a hash the item whose key is (key).
** INPUTS:
** hash
** The hash from which the item is to be removed.
** key
** The key used to store the item.
** value
** The value removed from the hash.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or the underlying NSPR error,
** if it is available.
**
*************************************************************/
SSMStatus SSM_HashRemove(SSMHashTable *hash, SSMHashKey key, void **value);
/************************************************************
** FUNCTION: SSM_HashKeys
** DESCRIPTION: Get keys for all items stored in the hash.
** INPUTS:
** hash
** The hash from which the keys are to be returned.
** keys
** Returns an array of keys. The array is allocated using PR_Malloc.
** numKeys
** Returns the number of keys in the array.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or the underlying NSPR error,
** if it is available.
**
*************************************************************/
SSMStatus SSM_HashKeys(SSMHashTable *hash, SSMHashKey **keys, PRIntn *numKeys);
/************************************************************
** FUNCTION: SSM_HashCount
** DESCRIPTION: Returns a count of the number of items in the hash.
** INPUTS:
** hash
** The hash to be counted.
** numItems
** Returns the number of items in the hash.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or the underlying NSPR error,
** if it is available.
**
*************************************************************/
SSMStatus SSM_HashCount(SSMHashTable *hash, PRIntn *numItems);
/************************************************************
** FUNCTION: SSM_HashDestroy
** DESCRIPTION: Destroy a hash. Items in the hash are not freed.
** INPUTS:
** hash
** The hash to be destroyed.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or the underlying NSPR error,
** if it is available.
**
*************************************************************/
SSMStatus SSM_HashDestroy(SSMHashTable *hash);
/************************************************************
** FUNCTION: SSM_HashCreate
** DESCRIPTION: Create and initialize a hash.
p** INPUTS:
** hash
** Returns the newly created hash.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or the underlying NSPR error,
** if it is available.
**
*************************************************************/
SSMStatus SSM_HashCreate(SSMHashTable **hash);
#endif /* __SSM_HASHTBL_H__ */

View File

@ -0,0 +1,138 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "serv.h"
#include "kgenctxt.h"
#include "pk11func.h"
#define SSMRESOURCE(object) (&(object)->super)
SSMStatus
SSMKeyPair_Create(void *arg, SSMControlConnection * connection,
SSMResource **res)
{
SSMKeyPair *keyPair = NULL;
SSMKeyPairArg *keyPairArg = (SSMKeyPairArg*)arg;
SSMStatus rv;
keyPair = SSM_ZNEW(SSMKeyPair);
if (keyPair == NULL) {
goto loser;
}
rv = SSMKeyPair_Init(keyPair, connection, SSM_RESTYPE_KEY_PAIR,
keyPairArg->keyGenContext);
if (rv != PR_SUCCESS) {
goto loser;
}
*res = SSMRESOURCE(keyPair);
return PR_SUCCESS;
loser:
if (keyPair != NULL) {
SSM_FreeResource (SSMRESOURCE(keyPair));
}
return PR_FAILURE;
}
SSMStatus
SSMKeyPair_Init(SSMKeyPair *inKeyPair, SSMControlConnection *connection,
SSMResourceType type, SSMKeyGenContext *keyGenContext)
{
SSMStatus rv = PR_SUCCESS;
rv = SSMResource_Init(connection, &inKeyPair->super, type);
inKeyPair->m_KeyGenContext = keyGenContext;
inKeyPair->m_KeyGenType = invalidKeyGen;
SSM_ClientGetResourceReference(SSMRESOURCE(inKeyPair), NULL);
return rv;
}
SSMStatus
SSMKeyPair_Destroy(SSMResource *res, PRBool doFree)
{
SSMKeyPair *keyPair = (SSMKeyPair*)res;
SSM_LockResource(SSMRESOURCE(keyPair));
if (keyPair->m_PubKey) {
SECKEY_DestroyPublicKey(keyPair->m_PubKey);
}
if (keyPair->m_PrivKey) {
SECKEY_DestroyPrivateKey(keyPair->m_PrivKey);
}
SSM_UnlockResource(SSMRESOURCE(keyPair));
SSMResource_Destroy(SSMRESOURCE(keyPair), PR_FALSE);
if (doFree) {
PORT_Free(keyPair);
}
return PR_SUCCESS;
}
SSMStatus
SSMKeyPair_SetKeyGenType(SSMKeyPair *inKeyPair,
SSMKeyGenType inKeyGenType)
{
if (inKeyPair->m_KeyGenType != invalidKeyGen) {
return PR_FAILURE;
}
inKeyPair->m_KeyGenType = inKeyGenType;
return PR_SUCCESS;
}
SSMStatus
SSMKeyPair_SetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value)
{
SSMKeyPair *keyPair = (SSMKeyPair*)res;
SSMStatus rv;
PR_ASSERT(SSM_IsAKindOf(res, SSM_RESTYPE_KEY_PAIR));
switch(attrID) {
case SSM_FID_KEYPAIR_KEY_GEN_TYPE:
SSM_DEBUG("Setting the key gen type to %d.\n", value->u.numeric);
if (value->type != SSM_NUMERIC_ATTRIBUTE) {
rv = PR_FAILURE;
break;
}
rv = SSMKeyPair_SetKeyGenType(keyPair, (SSMKeyGenType)value->u.numeric);
break;
default:
SSM_DEBUG("Got unknown KeyPair Set Attr request %d.\n", attrID);
rv = PR_FAILURE;
break;
}
return rv;
}

View File

@ -0,0 +1,117 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef _KEYRES_H_
#define _KEYRES_H_
#include "resource.h"
#include "key.h"
#include "ctrlconn.h"
/*
* FUNCTION: SSM_GenerateKeyPairs
* INPUTS:
* msg
* The message sent by the client requesting the key generation.
* destID
* A pointer to pre-allocated memory where the funciton can place
* a copy of the resource id to associate with the newly generated
* key pair.
* NOTES:
* This function takes a key pair generation method message and performs the
* actual key generation.
*
* RETURN:
* PRSuccess if the key generation is successfull. Any other return value
* indicates an error while trying to generate the key pair.
*/
extern SSMStatus SSM_GenerateKeyPair(SECItem *msg, SSMResourceID *destID);
/* Forward declare this structure so that builds will work.
* Unfortunately, there is a circular dependency here.
*/
typedef struct SSMKeyGenContext SSMKeyGenContext;
/* Now we begin to define the KeyPair class */
typedef struct SSMKeyPair {
SSMResource super;
SECKEYPublicKey *m_PubKey;
SECKEYPrivateKey *m_PrivKey;
SSMKeyGenContext *m_KeyGenContext;
SSMKeyGenType m_KeyGenType;
} SSMKeyPair;
/*
* This structure should be passed as the argument when creating
* a key pair.
*/
typedef struct SSMKeyPairArgStr {
SSMKeyGenContext *keyGenContext;
} SSMKeyPairArg;
/*
* FUNCTION: SSMKeyPair_Create
* INPUTS:
* arg
* An opaque pointer that gets passed while creation is taking place
* within the resource code.
* res
* A pointer to a pointer where a copy of the pointer to the instatiated
* class can be placed.
* NOTES:
* This is the constructor "method" the resource builder will call when
* instatiating a key pair class.
*
* RETURN:
* PRSuccess if creation was successful. In this case, a valid pointer
* to an SSMResource will be placed at *res.
* Any other return value indicates failure and the value at *res should
* be ignored.
*/
extern SSMStatus SSMKeyPair_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
extern SSMStatus SSMKeyPair_Init(SSMKeyPair *inKeyPair,
SSMControlConnection *conn,
SSMResourceType type,
SSMKeyGenContext *keyGenContext);
extern SSMStatus
SSMKeyPair_SetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value);
extern SSMStatus SSMKeyPair_Destroy(SSMResource *res, PRBool doFree);
#endif /* _KEYRES_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,189 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef _KGENCTXT_H_
#define _KGENCTXT_H_
#include "resource.h"
#include "keyres.h"
#include "ctrlconn.h"
#include "secmodti.h"
#include "minihttp.h"
typedef enum {
SSM_CRMF_KEYGEN = (PRInt32) 1,
SSM_OLD_STYLE_KEYGEN
} SSMKeyGenContextType;
/* Parameters used to create a key gen context */
typedef struct SSMKeyGenContextCreateArg
{
SSMControlConnection *parent;
SSMKeyGenContextType type;
CMTItem *param;
} SSMKeyGenContextCreateArg;
typedef struct SSMKeyGenParams
{
PRUint32 slotID;
PRUint32 keyGenMechanism;
SSMKeyPair *kp;
void *actualParams;
} SSMKeyGenParams;
/*
Key generation context. This object helps transactionalize
the generation of one or more key pairs for new certificates.
This object has associated with it an incoming queue for key generation
and flush requests, and a worker thread to do the key generation.
*/
struct SSMKeyGenContext
{
SSMResource super;
/* Control connection which created us (and to whom we send
completion responses */
SSMControlConnection *m_parent;
/* Context is used for CRMF or old-style keygen */
SSMKeyGenContextType m_ctxtype;
/* Queue for messages from control connection dispatcher */
SSMCollection *m_incomingQ;
/* Thread which processes keygen requests. */
PRThread *m_serviceThread;
/* Slot for a token used to generate keys. */
PK11SlotInfo * slot;
char *m_slotName;
PRBool m_disableEscrowWarning;
/* UI information for slot selection. */
PRMonitor *slotSelectLock;
PRBool slotUIWaiting;
PRBool slotUIComplete;
/* key exchange mechanism */
PRUint32 mech;
/* public key string, for use with KEYGEN tag */
char * keystring;
/* The number of requests we've completed. */
PRUint32 m_count;
SSMKeyGenParams **m_keyGens; /* We will finish these up
* once we get the Finish Key Gen message
*/
CERTCertificate *m_eaCert;
PRInt32 m_numKeyGens;
PRInt32 m_allocKeyGens;
PRBool m_userCancel;
CMTItem m_context;
};
typedef enum
{
SSM_KEYGEN_CXT_MESSAGE_NONE = (PRIntn) 0,
SSM_KEYGEN_CXT_MESSAGE_DATA_PROVIDER_OPEN = SSM_DATA_PROVIDER_OPEN,
SSM_KEYGEN_CXT_MESSAGE_DATA_PROVIDER_SHUTDOWN = SSM_DATA_PROVIDER_SHUTDOWN,
SSM_KEYGEN_CXT_MESSAGE_GEN_KEY = SSM_REQUEST_MESSAGE |
SSM_PKCS11_ACTION | SSM_CREATE_KEY_PAIR,
SSM_KEYGEN_CXT_MESSAGE_ESCROW_WARNING
} SSMKeyGenContextQMessages;
/* The parameter passed as data when sending a message
* for ESCROW_WARNING
*/
typedef struct SSMEscrowWarnParam
{
CERTCertificate *escrowCA;
} SSMEscrowWarnParam;
SSMStatus SSMKeyGenContext_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMKeyGenContext_Init(SSMKeyGenContext *ct,
SSMKeyGenContextCreateArg *arg,
SSMResourceType type);
SSMStatus SSMKeyGenContext_SetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value);
SSMStatus SSMKeyGenContext_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMKeyGenContext_Destroy(SSMResource *res, PRBool doFree);
SSMStatus SSMKeyGenContext_Shutdown(SSMResource *res, SSMStatus status);
SSMStatus SSMKeyGenContext_SetStatus(SSMKeyGenContext *ct, SSMStatus s);
SSMStatus SSMKeyGenContext_NewKeyPair(SSMKeyGenContext *ct,
SSMKeyPair **kp,
SECItem *msg);
SSMStatus SSMKeyGenContext_Print(SSMResource *res,
char *fmt,
PRIntn numParams,
char ** value,
char **resultStr);
SSMStatus SSMKeyGenContext_FormSubmitHandler(SSMResource * res,
HTTPRequest * req);
void SSMKeyGenContext_Invariant(SSMKeyGenContext *ct);
SSMStatus SSMKeyGenContext_FinishGeneratingAllKeyPairs(SSMControlConnection *ctrl,
SECItem *msg);
SSMStatus SSMKeyGenContext_BeginGeneratingKeyPair(SSMControlConnection * ctrl,
SECItem *msg,
SSMResourceID *destID);
void SSMKeyGenContext_CancelKeyGen(SSMKeyGenContext *ct);
/* Get a slot to perform keygen :
* returns SSM_SUCCESS if the slot is available, stored in keyctxt,
* or SSM_ERR_DEFER_RESPONSE if need to wait for user response,
* SSM_FAILURE on failure.
*/
struct SSMTextGenContext;
struct HTTPRequest;
SSMStatus SSMKeyGenContext_GetSlot(SSMKeyGenContext * keyctxt,
CK_MECHANISM_TYPE mechanism);
SSMStatus SSMTokenUI_KeywordHandler(struct SSMTextGenContext * cx);
SSMStatus SSMTokenUI_CommandHandler(struct HTTPRequest * req);
SSMStatus SSMTokenUI_GetNames(SSMResource * res, PRBool start, char ** name);
CK_MECHANISM_TYPE
SSMKeyGenContext_GenMechToAlgMech(CK_MECHANISM_TYPE mechanism);
#endif /* _KGENCTXT_H_ */

View File

@ -0,0 +1,65 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
// ===========================================================================
// CCompleteApp.h ©1994-1998 Metrowerks Inc. All rights reserved.
// ===========================================================================
#pragma once
#include <PP_Prefix.h>
#include <LApplication.h>
class CBasicApp : public PP_PowerPlant::LApplication {
public:
CBasicApp(); // constructor registers PPobs
virtual ~CBasicApp(); // stub destructor
// this overriding method handles application commands
virtual Boolean ObeyCommand(PP_PowerPlant::CommandT inCommand, void* ioParam);
// this overriding method returns the status of menu items
virtual void FindCommandStatus(PP_PowerPlant::CommandT inCommand,
Boolean &outEnabled, Boolean &outUsesMark,
PP_PowerPlant::Char16 &outMark, Str255 outName);
protected:
virtual void StartUp(); // override startup functions
};
extern CBasicApp *gTheApp;

611
security/psm/server/main.c Normal file
View File

@ -0,0 +1,611 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "serv.h"
#include "secport.h"
#include "dataconn.h"
#include "ctrlconn.h"
#include "minihttp.h"
#include "ciferfam.h"
#include "secmime.h"
#include "messages.h"
#include "textgen.h"
#include "oldfunc.h"
#include "nss.h"
#include "p12plcy.h"
#include "nlslayer.h"
void SSM_InitLogging(void);
#ifdef TIMEBOMB
#include "timebomb.h"
#endif
#ifdef WIN32
#include <wtypes.h>
#include <winreg.h>
#include <winerror.h>
#endif
#ifdef XP_UNIX
#include <signal.h>
#include <unistd.h>
#ifndef SIG_ERR
#define SIG_ERR -1
#endif /*SIG_ERR*/
#endif /*XP_UNIX*/
#define POLICY_TYPE_INDEX 0
SSMCollection * connections = NULL;
SSMHashTable * tokenList = NULL;
PRMonitor * tokenLock = NULL;
SSMHashTable * ctrlConnections = NULL;
SSMPolicyType policyType = ssmDomestic;
/*
* The following is a quick write of enabling various ciphers. This code is
* essentially moved from the server core code. Eventually we will need to
* place this data and functionality in a more modular way.
*/
#define SSM_POLICY_END 0 /* end of table */
#define SSM_POLICY_SSL 1 /* SSL ciphersuites: not really used */
#define SSM_POLICY_PK12 2 /* PKCS #12 ciphersuites */
#define SSM_POLICY_SMIME 3 /* S/MIME ciphersuites */
typedef struct {
PRInt32 policy;
PRInt32 key;
PRInt32 value;
} SSMPolicyEntry;
static SSMPolicyEntry ssmPK12PolicyTable[] =
{
{SSM_POLICY_PK12, PKCS12_RC4_40, (PRInt32)PR_TRUE},
{SSM_POLICY_PK12, PKCS12_RC4_128, (PRInt32)PR_TRUE},
{SSM_POLICY_PK12, PKCS12_RC2_CBC_40, (PRInt32)PR_TRUE},
{SSM_POLICY_PK12, PKCS12_RC2_CBC_128, (PRInt32)PR_TRUE},
{SSM_POLICY_PK12, PKCS12_DES_56, (PRInt32)PR_TRUE},
{SSM_POLICY_PK12, PKCS12_DES_EDE3_168, (PRInt32)PR_TRUE},
{SSM_POLICY_END, 0, 0}
};
static SSMPolicyEntry ssmSMIMEPolicyTable[] =
{
{SSM_POLICY_SMIME, SMIME_RC2_CBC_40, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_RC2_CBC_64, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_RC2_CBC_128, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_DES_CBC_56, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_DES_EDE3_168, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_RC5PAD_64_16_40, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_RC5PAD_64_16_64, (PRInt32)PR_TRUE},
{SSM_POLICY_SMIME, SMIME_RC5PAD_64_16_128, (PRInt32)PR_TRUE},
{SSM_POLICY_END, 0, 0}
};
static SSMStatus SSM_InstallPK12Policy(void)
{
const SSMPolicyEntry* entry = ssmPK12PolicyTable;
int i;
for (i = 0; entry[i].policy != SSM_POLICY_END; i++) {
if (SEC_PKCS12EnableCipher(entry[i].key, entry[i].value) !=
SECSuccess) {
return SSM_FAILURE;
}
}
return SSM_SUCCESS;
}
static SSMStatus SSM_InstallSMIMEPolicy(void)
{
const SSMPolicyEntry* entry = ssmSMIMEPolicyTable;
int i;
for (i = 0; entry[i].policy != SSM_POLICY_END; i++) {
if (SECMIME_SetPolicy(entry[i].key, entry[i].value) != SECSuccess) {
return SSM_FAILURE;
}
}
return SSM_SUCCESS;
}
/* XXX sjlee: we don't need to do a similar thing for SSL as we can call an
* NSS function to do it
*/
#if 0
/*
* This function is required by svrplcy to set the
* utility policy. This will tell us what kind of
* policy we are running.
*/
SECStatus Utility_SetPolicy(long which, int policy)
{
if (which == POLICY_TYPE_INDEX) {
switch (policy) {
case SVRPLCYDomestic:
policyType = ssmDomestic;
break;
case SVRPLCYExport:
policyType = ssmExport;
break;
case SVRPLCYFrance:
policyType = ssmFrance;
break;
default:
/* This is an unknown policy type. */
PR_ASSERT(0);
break;
}
}
return SECSuccess;
}
#endif
void SSM_SetPolicy(void)
{
#if 0
SVRPLCY_InstallSSLPolicy();
SVRPLCY_InstallPK12Policy();
SVRPLCY_InstallSMIMEPolicy();
SVRPLCY_InstallUtilityPolicy();
#else
/* Always domestic policy now */
NSS_SetDomesticPolicy();
SSM_InstallPK12Policy();
SSM_InstallSMIMEPolicy();
#endif
}
SSMPolicyType
SSM_GetPolicy(void)
{
return policyType;
}
static void
enable_SMIME_cipher_prefs(void)
{
SSMPolicyType policy;
policy = SSM_GetPolicy();
switch (policy)
{
case ssmDomestic:
SECMIME_EnableCipher(SMIME_DES_EDE3_168, 1);
SECMIME_EnableCipher(SMIME_RC2_CBC_128, 1);
SECMIME_EnableCipher(SMIME_RC2_CBC_64, 1);
SECMIME_EnableCipher(SMIME_DES_CBC_56, 1);
#if 0
SECMIME_EnableCipher(SMIME_RC5PAD_64_16_128, 1);
SECMIME_EnableCipher(SMIME_RC5PAD_64_16_64, 1);
SECMIME_EnableCipher(SMIME_FORTEZZA, 1);
#endif
case ssmExport:
SECMIME_EnableCipher(SMIME_RC2_CBC_40, 1);
#if 0
SECMIME_EnableCipher(SMIME_RC5PAD_64_16_40, 1);
#endif
case ssmFrance:
default:
break;
}
/* now tell secmime that we've sent it the last preference */
SECMIME_EnableCipher(CIPHER_FAMILYID_MASK, 0);
}
SECStatus
ssm_InitializePKCS11Strings(void)
{
char *manufacturerID = NULL;
char *libraryDescription = NULL;
char *tokenDescription = NULL;
char *privateTokenDescription = NULL;
char *slotDescription = NULL;
char *privateSlotDescription = NULL;
char *fipsSlotDescription = NULL;
char *fipsPrivateSlotDescription = NULL;
SSMTextGenContext *cx;
SSMStatus rv;
rv = SSMTextGen_NewTopLevelContext(NULL, &cx);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "manufacturerID", &manufacturerID);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "libraryDescription",
&libraryDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "tokenDescription",
&tokenDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "privateTokenDescription",
&privateTokenDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "slotDescription", &slotDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "privateSlotDescription",
&privateSlotDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "fipsSlotDescription",
&fipsSlotDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_FindUTF8StringInBundles(cx, "fipsPrivateSlotDescription",
&fipsPrivateSlotDescription);
if (rv != SSM_SUCCESS) {
goto loser;
}
if (cx != NULL) {
SSMTextGen_DestroyContext(cx);
}
PK11_ConfigurePKCS11(manufacturerID, libraryDescription, tokenDescription,
privateTokenDescription, slotDescription,
privateSlotDescription, fipsSlotDescription,
fipsPrivateSlotDescription, 0, 0);
return SECSuccess;
loser:
PR_FREEIF(manufacturerID);
PR_FREEIF(libraryDescription);
PR_FREEIF(tokenDescription);
PR_FREEIF(privateTokenDescription);
PR_FREEIF(slotDescription);
PR_FREEIF(privateSlotDescription);
if (cx != NULL) {
SSMTextGen_DestroyContext(cx);
}
return SECFailure;
}
#ifdef XP_UNIX
#define CATCH_SIGNAL_DEFAULT(SIGNAL) \
if (((int)signal(SIGNAL, psm_signal_handler_default)) == ((int)SIG_ERR)) \
goto loser;
#define CATCH_SIGNAL_IGNORE(SIGNAL) \
if (((int)signal(SIGNAL, psm_signal_handler_ignore)) == ((int)SIG_ERR)) \
goto loser;
static void
psm_signal_handler_default(int sig)
{
#ifdef DEBUG
printf ("Trapping the signal %d\n", sig);
#endif
SSM_ReleaseLockFile();
kill(getpid(),SIGKILL);
}
static void
psm_signal_handler_ignore(int sig)
{
#ifdef DEBUG
printf ("Ignoring the signal %d\n", sig);
#endif
signal(sig,psm_signal_handler_ignore);
}
static SSMStatus
psm_catch_signals(void)
{
CATCH_SIGNAL_IGNORE(SIGHUP);
CATCH_SIGNAL_DEFAULT(SIGINT);
CATCH_SIGNAL_DEFAULT(SIGQUIT);
CATCH_SIGNAL_DEFAULT(SIGILL);
CATCH_SIGNAL_DEFAULT(SIGTRAP);
CATCH_SIGNAL_DEFAULT(SIGABRT);
CATCH_SIGNAL_DEFAULT(SIGIOT);
#ifdef SIGEMT
CATCH_SIGNAL_DEFAULT(SIGEMT);
#endif
CATCH_SIGNAL_DEFAULT(SIGFPE);
CATCH_SIGNAL_DEFAULT(SIGBUS);
CATCH_SIGNAL_DEFAULT(SIGSEGV);
#ifdef SIGSYS
CATCH_SIGNAL_DEFAULT(SIGSYS);
#endif
CATCH_SIGNAL_IGNORE(SIGPIPE);
CATCH_SIGNAL_DEFAULT(SIGTERM);
#ifndef LINUX
CATCH_SIGNAL_DEFAULT(SIGUSR1);
#endif
CATCH_SIGNAL_DEFAULT(SIGUSR2);
#ifdef SIGXCPU
CATCH_SIGNAL_DEFAULT(SIGXCPU);
#endif
#ifdef SIGDANGER
CATCH_SIGNAL_DEFAULT(SIGDANGER);
#endif
return SSM_SUCCESS;
loser:
return SSM_FAILURE;
}
#endif
#if defined(XP_PC) && !defined(DEBUG)
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
LPSTR lpszLine, int nShow)
#else
#ifdef macintosh
/*
We run RunMacPSM in a separate thread off the main thread.
This is because we can't do any blocking I/O routines on the main
thread, because Mac NSPR doesn't own the original thread used to
run the app.
*/
void RunMacPSM(void *arg)
#else
int main(int argc, char ** argv)
#endif
#endif
{
#ifdef macintosh
#pragma unused(arg)
#endif
#if (defined(XP_PC) && !defined(DEBUG)) || (defined(macintosh))
/* substitute argc and argv for NSPR */
int argc = 0;
char *argv[] = {"", NULL};
#endif
PRIntn result = 0;
#ifdef DEBUG
PR_STDIO_INIT();
#endif
#ifdef DEBUG
/* Initialize logging. */
SSM_InitLogging();
#endif
#ifdef TIMEBOMB
SSM_CheckTimebomb();
#endif
#ifdef XP_UNIX
if (psm_catch_signals() != SSM_SUCCESS) {
SSM_DEBUG("Couldn't set signal handlers. Quitting\n");
exit(1);
}
#endif
SSM_SetPolicy();
enable_SMIME_cipher_prefs();
if (SSM_GetPolicy() == ssmDomestic) {
SSM_EnableHighGradeKeyGen();
}
/* Initialize NLS layer */
if (nlsInit() != PR_TRUE) {
SSM_DEBUG("Failed to initialize the NLS layer\n");
exit(1);
}
/* Initialize global list of control connections. */
connections = SSM_NewCollection();
if (connections == NULL)
{
SSM_DEBUG("Can't initialize! (%ld)\n", (long) result);
exit(1);
}
/* Initialize global list of tokens */
result = SSM_HashCreate(&tokenList);
if (result != PR_SUCCESS || !tokenList) {
SSM_DEBUG("Can't initialize - tokenList \n");
exit(result);
}
tokenLock = PR_NewMonitor();
if (!tokenLock) {
SSM_DEBUG("Can't initialize - tokenLock\n");
exit(1);
}
/* Initialize hash table of control connections */
result = SSM_HashCreate(&ctrlConnections);
if (result != PR_SUCCESS || !ctrlConnections) {
SSM_DEBUG("Can't initialize global table for control connections \n");
exit(result);
}
/* Initialize resource table */
SSM_ResourceInit();
if (SSM_InitPolicyHandler() != PR_SUCCESS) {
SSM_DEBUG("Couldn't initialize the Policy Handler.\n");
exit (1);
}
/* initialize random number generator */
SSM_DEBUG("Initializing random number generator.\n");
RNG_RNGInit();
RNG_SystemInfoForRNG();
/*
* All the ciphers except SSL_RSA_WITH_NULL_MD5 are on by default.
* Enable encryption, enable NULL cipher.
*/
#ifdef XP_MAC
result = mainLoop(argc, argv);
#else
result = PR_Initialize(mainLoop, argc, argv, 0);
#endif
#ifdef DEBUG
printf("main: Finishing (%ld)\n", (long) result);
#endif
#ifdef XP_UNIX
SSM_ReleaseLockFile();
#endif
#ifndef XP_MAC
return result;
#endif
}
#ifdef XP_MAC
void *
psm_malloc(unsigned long numbytes)
{
return NewPtrClear(numbytes);
}
void
psm_free(void *ptr)
{
DisposePtr((char *) ptr);
}
#endif
PRIntn mainLoop(PRIntn argc, char ** argv)
{
PRFileDesc *socket, *respsocket;
PRNetAddr clientaddr;
SSMControlConnection *curconnect;
SSMResourceID ctrlID;
SSMStatus status = PR_FAILURE;
PRBool alive = PR_TRUE;
/* Register ourselves so that logs, etc can identify us */
SSM_RegisterThread("main", NULL);
/* Open NLS stuff */
SSM_DEBUG("Initializing NLS.\n");
#ifdef XP_MAC
SSM_InitNLS(":ui:");
#else
SSM_InitNLS("ui");
#endif
ssm_InitializePKCS11Strings();
/* Initialize the protocol */
#ifdef XP_MAC
CMT_Init(malloc, free);
#else
CMT_Init(PR_Malloc, PR_Free);
#endif
/* Open the HTTP listener */
SSM_DEBUG("Opening HTTP thread.\n");
status = SSM_InitHTTP();
if (status != SSM_SUCCESS)
{
SSM_DEBUG("Couldn't open web port. Exiting.\n");
goto loser;
}
/* open a port for control connections, with well-known port# */
socket = SSM_OpenControlPort();
if (!socket)
{
SSM_DEBUG("Couldn't open control port. Exiting.\n");
goto loser;
}
while (alive)
{
/* wait until there is incoming request */
respsocket = PR_Accept(socket, &clientaddr, PR_INTERVAL_NO_TIMEOUT);
/* while (respsocket == NULL)
{
if (PR_GetError() != PR_WOULD_BLOCK_ERROR)
goto loser;
PR_Sleep(CARTMAN_SPINTIME);
#ifdef DEBUG
printf("master: Still ready for client connection on port %d\n", CARTMAN_PORT); fflush(stdout);
#endif
respsocket = PR_Accept(socket, &clientaddr,
PR_SecondsToInterval(2));
} */
if (!respsocket) {
/* accept failed: abort */
status = PR_GetError();
SSM_DEBUG("Error %d accepting control connection. Exiting.\n",
status);
goto loser;
}
if (SSM_SocketPeerCheck(respsocket, PR_TRUE)) {
SSM_DEBUG("creating control connection.\n");
status = SSM_CreateResource(SSM_RESTYPE_CONTROL_CONNECTION,
respsocket,
NULL,
&ctrlID,
(SSMResource **) &curconnect);
if (status != PR_SUCCESS)
break;
PR_ASSERT(RESOURCE_CLASS(curconnect) == SSM_RESTYPE_CONTROL_CONNECTION);
}
else {
/* connection did not come from localhost: shut down the
* connection and continue to loop
*/
SSM_DEBUG("Connection attempt from a non-local host!\n");
status = PR_Shutdown(respsocket, PR_SHUTDOWN_BOTH);
respsocket = NULL;
}
} /* end while(true) */
loser:
/* Shut down the HTTP thread. */
if (httpListenThread != NULL){
PR_Interrupt(httpListenThread);
}
exit(1);
/* ### mwelch - should we return meaningful error code? */
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,219 @@
/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_MINIHTTP_H__
#define __SSM_MINIHTTP_H__
#include "ssmerrs.h"
#include "ssmdefs.h"
#include "serv.h"
#include "prthread.h"
#include "ctrlconn.h"
#include "nlsutil.h"
/* Result codes; see
http://info.internet.isi.edu:80/in-notes/rfc/files/rfc2068.txt
for more information */
typedef enum
{
HTTP_OK = (PRInt32) 200,
HTTP_NO_CONTENT = 204,
HTTP_BAD_REQUEST = 400,
HTTP_UNAUTHORIZED = 401,
HTTP_FORBIDDEN = 403,
HTTP_NOT_FOUND = 404,
HTTP_METHOD_NOT_ALLOWED = 405,
HTTP_INTERNAL_ERROR = 500,
HTTP_NOT_IMPLEMENTED = 501,
HTTP_SERVICE_UNAVAILABLE = 503,
HTTP_GATEWAY_TIMEOUT = 504,
HTTP_VERSION_UNSUPPORTED = 505
} HTTPErrorCode;
/* ### mwelch - This has to be done better after the 11/1998 demo. */
typedef enum
{
SSM_UI_NULL = (PRUint32) 0,
SSM_UI_KEYGEN_PROGRESS, /* Frameset containing keygen components */
SSM_UI_DIALOG_FRAMESET, /* Generic frameset for dialogs */
SSM_UI_DIALOG_FB, /* Dialogs: NSM -> client feedback, kept open */
SSM_UI_DIALOG_CANCEL /* A "cancel" command invokable by the client */
} SSMDialogSelector;
struct HTTPRequest
{
PRFileDesc *sock; /* Socket with which we talk to client */
char *rawreqbuf; /* Copy of the raw request we got */
char *reqbuf; /* The HTTP request we got,
which is later parsed */
char **paramNames; /* Names of parameters passed to the URL */
char **paramValues; /* Values of parameters passed to the URL */
PRUint32 numParams; /* How many parameters were passed */
PRUint32 slen; /* The amount of actual text in the buffer(s) */
PRUint32 len; /* The allocated length of the buffer(s) */
char *hdrbuf; /* Response header */
SSMStatus rv; /* Internal result code (used if an
internal error occurred) */
HTTPErrorCode httprv; /* HTTP result code (200, 401, 404, etc) */
char *errormsg; /* if a problem occurs, send this string back
to the client. */
char *filename; /* Canned file to fetch from data, if any */
/* These point to chars within (reqbuf). */
char *handlerName; /* Command requested by client */
char *params; /* Parameters passed to GET */
char *agent; /* User-Agent value */
char *ctrlrid; /* Authorization: RID of control connection */
char *password; /* Authorization: RID of nonce */
char *referer; /* The URL for the referer */
SSMControlConnection *ctrlconn;
/* Control connection owning this connection */
SSMResource *target; /* Target resource, if any */
char *language; /* Accept-Language value */
char *charset; /* Accept-Charset value */
PRBool sentResponse; /* Have we already sent a response to the user? */
PRBool keepSock; /* Are we keeping this socket (eg for logging)? */
PRBool processText; /* Should we interpret files we send out as text? */
SSMResourceID rid; /* ID of requested resource */
};
/* Typedef for a command handler. */
typedef SSMStatus (*SSMCommandHandlerFunc)(HTTPRequest *req);
/* Register a command handler. */
SSMStatus SSM_HTTPRegisterCommandHandler(const char *name,
SSMCommandHandlerFunc func);
/* function to parse the request and submit html */
SSMStatus SSM_HTTPGetGenericLump(HTTPRequest *req, PRBool binary);
/* The default handler, which uses baseRef as a prefix for two strings
to use in processing and returning HTTP headers and content. Can be
called by other handlers if no special header/content processing
for the user is necessary. */
SSMStatus SSM_HTTPDefaultCommandHandler(HTTPRequest *req);
/* ### sjlee: This function is called when you need to sleep one second
* before closing the window due to collision of dialog windows
* this is really the default command handler with a sleep
*/
SSMStatus SSM_HTTPCloseAndSleep(HTTPRequest* req);
/* Handler for getting binary data. This should be consolidated with
the default handler. */
SSMStatus SSM_HTTPGetBinaryHandler(HTTPRequest *req);
/* Handler for monitoring resources. */
SSMStatus SSM_HTTPMonitorResourceHandler(HTTPRequest *req);
/* Handler which shuts down a resource. */
SSMStatus SSM_HTTPShutdownResourceHandler(HTTPRequest *req);
/* Hello World example */
SSMStatus SSM_HTTPHelloWorld(HTTPRequest *req);
/* NLS Hello World example */
SSMStatus SSM_HTTPHelloWorldWithNLS(HTTPRequest *req);
/* SSM_HTTPThread listens to the HTTP socket for connections from
one or more clients. (arg) should be an open socket (PRFileDesc*),
therefore the port needs to have been created before being passed
to this thread. */
void SSM_HTTPThread(void *arg);
/* Open the HTTP listener. */
SSMStatus SSM_InitHTTP(void);
/* Get the port on which we're listening for HTTP connections. */
PRUint32 SSM_GetHTTPPort(void);
/* Construct a URL and size info based on a known page/access point
and control connection. */
SSMStatus SSM_GenerateURL(SSMControlConnection *conn,
char *command,
char *baseRef,
SSMResource *targetRes, /* can pass NULL for this */
char *otherParams,
PRUint32 *width, PRUint32 *height,
char **url);
/* Main listening thread for HTTP requests */
extern PRThread *httpListenThread;
extern PRUint32 httpListenPort;
/* Command handler utilities */
SSMStatus SSM_HTTPParamByName(HTTPRequest *req,
const char *key, const char **value);
SSMStatus SSM_RIDTextToResource(HTTPRequest *req, const char *ridText,
SSMResource **res);
SSMStatus SSM_HTTPReportError(HTTPRequest *req, HTTPErrorCode statusCode);
void SSM_HTTPReportSpecificError(HTTPRequest *req, char *fmt, ...);
SSMStatus SSM_HTTPParamValue(HTTPRequest *req, const char *key, char **value);
SSMStatus SSM_HTTPAddParamValue(HTTPRequest *req, const char * key,
const char * value);
SSMStatus
SSM_HTTPSendOKHeader(HTTPRequest *req,
char * addtlHeaders,
char * contentType);
SSMStatus
SSM_HTTPSendUTF8String(HTTPRequest *req, char * str);
SSMStatus
SSM_HTTPCloseWindow(HTTPRequest *req);
char * SSM_ConvertStringToHTMLString(char * string);
SSMStatus SSM_ProcessPasswordWindow(HTTPRequest * req);
#endif

View File

@ -0,0 +1,406 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "resource.h"
#include "kgenctxt.h"
#include "nlsutil.h"
#include "base64.h"
#include "pk11func.h"
#include "textgen.h"
#include "minihttp.h"
#include "connect.h"
#include "messages.h"
/* lock to wait for UI */
typedef struct {
PRMonitor * lock;
PRBool UIComplete;
} SSMTokenUI_Monitor;
#define SSM_PARENT_CONN(x) &((x)->m_parent->super)
#if 0 /* XXX not used? */
static SSMTokenUI_Monitor UIlock;
#endif
PK11SlotListElement * PK11_GetNextSafe(PK11SlotList *list,
PK11SlotListElement *le,
PRBool restart);
SSMStatus SSMTokenUI_GetNames(SSMResource * res, PRBool start, char ** name);
SSMStatus SSM_SetUserPasswordCommunicator(PK11SlotInfo * slot,
SSMKeyGenContext *ct);
CK_MECHANISM_TYPE
SSMKeyGenContext_GenMechToAlgMech(CK_MECHANISM_TYPE mechanism)
{
CK_MECHANISM_TYPE searchMech;
/* We are interested in slots based on the ability to perform
a given algorithm, not on their ability to generate keys usable
by that algorithm. Therefore, map keygen-specific mechanism tags
to tags for the corresponding crypto algorthm. */
switch(mechanism)
{
case CKM_RSA_PKCS_KEY_PAIR_GEN:
searchMech = CKM_RSA_PKCS;
break;
case CKM_DSA_KEY_PAIR_GEN:
searchMech = CKM_DSA;
break;
case CKM_RC4_KEY_GEN:
searchMech = CKM_RC4;
break;
case CKM_DH_PKCS_KEY_PAIR_GEN:
searchMech = CKM_DH_PKCS_DERIVE; /* ### mwelch is this right? */
break;
case CKM_DES_KEY_GEN:
/* What do we do about DES keygen? Right now, we're just using
DES_KEY_GEN to look for tokens, because otherwise we'll have
to search the token list three times. */
default:
searchMech = mechanism;
break;
}
return searchMech;
}
SSMStatus SSMKeyGenContext_GetSlot(SSMKeyGenContext * keyctxt,
CK_MECHANISM_TYPE mechanism)
{
SSMStatus rv = SSM_SUCCESS;
PK11SlotList * slotList = NULL;
CK_MECHANISM_TYPE searchMech;
PRBool reLock;
searchMech = SSMKeyGenContext_GenMechToAlgMech(mechanism);
if (!keyctxt->slot ||
!PK11_DoesMechanism(keyctxt->slot, searchMech)) {
slotList = PK11_GetAllTokens(searchMech, PR_TRUE, PR_TRUE,
keyctxt->super.m_connection);
if (!keyctxt)
goto loser;
if (!slotList || !slotList->head)
goto loser;
if (!slotList->head->next) {
/* only one slot available, just return it */
keyctxt->slot = slotList->head->slot;
keyctxt->m_slotName = strdup(PK11_GetSlotName(keyctxt->slot));
} else {
char * mech = PR_smprintf("mech=%d&task=keygen&unused=unused", searchMech);
if (keyctxt->m_ctxtype == SSM_OLD_STYLE_KEYGEN) {
CMTItem msg;
GenKeyOldStyleTokenRequest request;
char ** tokenNames = NULL;
int numtokens = 0;
PK11SlotListElement * slotElement;
slotElement = PK11_GetFirstSafe(slotList);
while(slotElement) {
numtokens++;
tokenNames = (char **) PR_REALLOC(tokenNames, numtokens*sizeof(*tokenNames));
tokenNames[numtokens - 1] = strdup(PK11_GetTokenName(slotElement->slot));
slotElement = PK11_GetNextSafe(slotList, slotElement, PR_FALSE);
}
/* send message to plugin: use native UI for select token dialog */
SSM_LockUIEvent(&keyctxt->super);
request.rid = keyctxt->super.m_id;
request.numtokens = numtokens;
request.tokenNames = tokenNames;
msg.type = SSM_REPLY_OK_MESSAGE | SSM_KEYGEN_TAG | SSM_KEYGEN_TOKEN;
if (CMT_EncodeMessage(GenKeyOldStyleTokenRequestTemplate, &msg,
&request) != CMTSuccess)
goto loser;
SSM_SendQMessage(keyctxt->super.m_connection->m_controlOutQ,
SSM_PRIORITY_NORMAL,
msg.type, msg.len, (char *)msg.data, PR_TRUE);
SSM_WaitUIEvent(&keyctxt->super, PR_INTERVAL_NO_TIMEOUT);
SSM_UnlockUIEvent(&keyctxt->super);
keyctxt->slot = (PK11SlotInfo*)keyctxt->super.m_uiData;
} else /* post UI event */ {
/* post a UI event to ask user for the slot */
SSM_LockUIEvent(&keyctxt->super);
/* Release the lock on the resource temporarily while
* the UI happens.
*/
rv = SSM_UnlockResource(&keyctxt->super);
reLock = (rv == PR_SUCCESS) ? PR_TRUE : PR_FALSE;
rv = SSMControlConnection_SendUIEvent(keyctxt->super.m_connection,
"get",
"select_token",
(SSMResource *)keyctxt,
mech,
&((SSMResource*)keyctxt)->m_clientContext);
if (rv != SSM_SUCCESS) {
if (keyctxt->super.m_UILock != NULL) {
PR_ExitMonitor(keyctxt->super.m_UILock);
}
goto loser;
}
/* wait until the UI dialog box is done */
SSM_WaitUIEvent(&keyctxt->super, PR_INTERVAL_NO_TIMEOUT);
if (reLock) {
/* Get the lock back. */
SSM_LockResource(&keyctxt->super);
}
SSM_UnlockUIEvent(&keyctxt->super);
PR_Free(mech);
/* ok, the return from UI is processed in command handler */
/* Make sure password prompt doesn't get sucked away by
* the disappearing dialog
*/
PR_Sleep(PR_TicksPerSecond());
keyctxt->slot = (PK11SlotInfo*)keyctxt->super.m_uiData;
if (keyctxt->slot != NULL) {
keyctxt->m_slotName = strdup(PK11_GetSlotName(keyctxt->slot));
}
} /* end of post UI event */
} /* end of multiple tokens available */
/* Get a slot reference so it doesn't disappear */
if (keyctxt->slot) {
PK11_ReferenceSlot(keyctxt->slot);
}
}
/* we should have a slot now */
if (keyctxt->slot == NULL)
goto loser;
/* Before we authenticate, make sure the user initialized the DB. */
if (PK11_NeedUserInit(keyctxt->slot))
rv = SSM_SetUserPasswordCommunicator(keyctxt->slot, keyctxt);
rv = PK11_Authenticate(keyctxt->slot, PR_FALSE, keyctxt);
if (rv != SECSuccess) {
goto loser;
}
goto done;
loser:
if (rv == SSM_SUCCESS)
rv = SSM_FAILURE;
keyctxt->slot = NULL;
done:
if (slotList)
PK11_FreeSlotList(slotList);
return rv;
}
/* send a message to communicator to display UI for setting slot password */
SSMStatus
SSM_SetUserPasswordCommunicator(PK11SlotInfo * slot,
SSMKeyGenContext *ct)
{
CMTItem msg;
GenKeyOldStylePasswordRequest passwdmsg;
SSMStatus rv = SSM_FAILURE;
PRBool reLock = PR_FALSE;
PR_ASSERT(SSM_IsAKindOf(&ct->super, SSM_RESTYPE_KEYGEN_CONTEXT));
switch (ct->m_ctxtype) {
case (SSM_CRMF_KEYGEN):
rv = SSM_SetUserPassword(slot, &ct->super);
break;
case (SSM_OLD_STYLE_KEYGEN):
SSM_LockUIEvent(&ct->super);
passwdmsg.rid = ct->super.m_id;
passwdmsg.tokenName = PK11_GetTokenName(slot);
passwdmsg.internal = (CMBool) PK11_IsInternal(slot);
passwdmsg.minpwdlen = PR_MAX(SSM_MIN_PWD_LEN,PK11_GetMinimumPwdLength(slot));
passwdmsg.maxpwdlen = slot->maxPassword;
msg.type = SSM_REPLY_OK_MESSAGE | SSM_KEYGEN_TAG | SSM_KEYGEN_PASSWORD;
if (CMT_EncodeMessage(GenKeyOldStylePasswordRequestTemplate, &msg,
&passwdmsg) != CMTSuccess)
goto loser;
rv = SSM_SendQMessage(ct->super.m_connection->m_controlOutQ,
SSM_PRIORITY_NORMAL,
msg.type, msg.len, (char *)msg.data, PR_TRUE);
if (rv != SSM_SUCCESS)
SSM_UnlockUIEvent(&ct->super);
else
SSM_WaitUIEvent(&ct->super, PR_INTERVAL_NO_TIMEOUT);
break;
default:
SSM_DEBUG("Unknown keygen type!\n");
goto loser;
}
loser:
if (rv != SSM_SUCCESS)
SSM_DEBUG("SetUserPasswordComm: can't send password request msg!\n");
return rv;
}
SSMStatus
ssmpkcs11_convert_slot(SSMTextGenContext *cx,
PRInt32 slotIndex,
PK11SlotInfo *slot,
char *fmt,
PRBool accumulate);
SSMStatus SSMTokenUI_KeywordHandler(SSMTextGenContext * cx)
{
SSMResource *ctxt = NULL;
SSMStatus rv;
char * tempUStr = NULL;
char * wrapper = NULL;
CK_MECHANISM_TYPE searchMech;
char *searchMechStr;
static PK11SlotList * slotList;
static PK11SlotListElement * slotElement;
PRIntn i = 0;
if (!cx || !cx->m_request || !cx->m_params || !cx->m_result)
goto loser;
ctxt = SSMTextGen_GetTargetObject(cx);
/* Get the wrapper string from the properties file. */
wrapper = (char *) SSM_At(cx->m_params, 0);
rv = SSM_GetAndExpandTextKeyedByString(cx, wrapper, &tempUStr);
if (rv != PR_SUCCESS)
goto loser;
rv = SSM_HTTPParamValue(cx->m_request, "action", &searchMechStr);
if (rv != SSM_SUCCESS)
goto loser;
searchMech = atoi(searchMechStr);
slotList = PK11_GetAllTokens(searchMech, PR_TRUE, PR_TRUE,
ctxt->m_connection);
if (!slotList)
goto loser;
slotElement = PK11_GetFirstSafe(slotList);
while(slotElement)
{
rv = ssmpkcs11_convert_slot(cx, i++, slotElement->slot, tempUStr,
PR_TRUE);
if (rv != SSM_SUCCESS)
goto loser;
slotElement = PK11_GetNextSafe(slotList, slotElement, PR_FALSE);
}
rv = SSM_SUCCESS;
goto done;
loser:
SSM_DEBUG("Errors creating token list!\n");
SSMTextGen_UTF8StringClear(&cx->m_result);
if (rv==SSM_SUCCESS)
rv = SSM_FAILURE;
done:
PR_FREEIF(tempUStr);
return rv;
}
PK11SlotInfo *
SSMPKCS11_FindSlotByID(SECMODModuleID modID,
CK_SLOT_ID slotID);
SSMStatus
figure_out_token_selection(char *str,
SECMODModuleID *modID,
CK_SLOT_ID *slotID)
{
char *walk;
walk = PL_strchr(str, '+');
if (!walk)
return SSM_FAILURE;
*walk++ = '\0';
*modID = atoi(str);
*slotID = atoi(walk);
return SSM_SUCCESS;
}
SSMStatus
SSMTokenUI_CommandHandler(HTTPRequest * req)
{
SSMStatus rv;
char * tokenName = NULL;
SSMResource *res;
SECMODModuleID modID;
CK_SLOT_ID slotID;
PK11SlotInfo *slot;
if (!req->target)
goto loser;
res = req->target;
res->m_uiData = NULL;
/* check the parameter values */
if (res->m_buttonType == SSM_BUTTON_CANCEL)
{
slot = NULL;
goto done; /* return the closing javascript */
}
/* Determine what token the user selected. */
rv = SSM_HTTPParamValue(req, "token", &tokenName);
if (rv != SSM_SUCCESS)
{
req->httprv = HTTP_BAD_REQUEST;
goto loser;
}
rv = figure_out_token_selection(tokenName, &modID, &slotID);
if (rv != SSM_SUCCESS)
goto loser;
slot = SSMPKCS11_FindSlotByID(modID, slotID);
if (!slot)
goto loser;
done:
/* Tell the keygen context what token was selected. */
res->m_uiData = slot;
SSM_NotifyUIEvent(res);
/* Done with our part, so pass back whatever the dialog wants in
order to close the window. */
return SSM_HTTPCloseAndSleep(req);
loser:
res->m_uiData = NULL;
SSM_NotifyUIEvent(res);
SSM_DEBUG("Can't get input from token_select dialog!\n");
return SSM_FAILURE;
}

View File

@ -0,0 +1,55 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef _NLSLAYER_H_
#define _NLSLAYER_H_
PRBool nlsInit();
char* nlsGetUTF8String(const char *name);
void * nlsNewDateFormat();
void nlsFreeDateFormat(void * p);
char * nslPRTimeToUTF8String(void* p, PRInt64 t);
PRBool nlsUnicodeToUTF8(unsigned char * inBuf, unsigned int inBufBytes,
unsigned char * outBuf, unsigned int maxOutBufLen,
unsigned int * outBufLen);
PRBool nlsUTF8ToUnicode(unsigned char * inBuf, unsigned int inBufBytes,
unsigned char * outBuf, unsigned int maxOutBufLen,
unsigned int * outBufLen);
PRBool nlsUnicodeToASCII(unsigned char * inBuf, unsigned int inBufBytes,
unsigned char * outBuf, unsigned int maxOutBufLen,
unsigned int * outBufLen);
PRBool nlsASCIIToUnicode(unsigned char * inBuf, unsigned int inBufBytes,
unsigned char * outBuf, unsigned int maxOutBufLen,
unsigned int * outBufLen);
#endif /* _NLSLAYER_H_ */

View File

@ -0,0 +1,101 @@
/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "nlsutil.h"
#include "serv.h" /* for SSM_DEBUG */
#include "ssmerrs.h"
#include "resource.h"
/* atoi() for a UnicodeString. (sigh) */
PRInt32
SSMTextGen_atoi(char *str)
{
PRInt32 result = -1;
/* Extract the text by converting to ASCII. */
if (str)
{
/* Convert the text into a number, if possible. */
PR_sscanf(str, "%ld", &result);
}
return result;
}
/* Debug a UnicodeString. */
#ifdef DEBUG
void
SSM_DebugUTF8String(char *prefix, char *ustr)
{
char *ch;
if (ustr)
{
ch = ustr;
if (ch)
SSM_DEBUG("%s:\n%s\n"
"End of text\n", (prefix ? prefix : ""), ch);
}
else
SSM_DEBUG("%s: (null string)\n", (prefix ? prefix : ""));
}
#endif
/* Clear a UnicodeString. */
void
SSMTextGen_UTF8StringClear(char **str)
{
if (str && *str)
{
PR_Free(*str);
*str = NULL;
}
}
SSMStatus
SSM_ConcatenateUTF8String(char **prefix, char *suffix)
{
char *tmp;
if (prefix == NULL || suffix == NULL) {
return SSM_FAILURE;
}
tmp = PR_smprintf("%s%s", (*prefix) ? *prefix : "", suffix);
if (tmp == NULL) {
return SSM_FAILURE;
}
PR_Free(*prefix);
*prefix = tmp;
return SSM_SUCCESS;
}

View File

@ -0,0 +1,54 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __nlsutil_h__
#define __nlsutil_h__
#include "resource.h"
#include "minihttp.h"
/* Clear a UnicodeString. */
void SSMTextGen_UTF8StringClear(char **str);
PRInt32 SSMTextGen_atoi(char *str);
#ifdef DEBUG
void SSM_DebugUTF8String(char *prefix, char *ustr);
#else
#define SSM_DebugUTF8String(p,u)
#endif
SSMStatus SSM_ConcatenateUTF8String(char **prefix, char *suffix);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef _OLDFUNC_H_
#define _OLDFUNC_H_
#include "keyres.h"
#include "base64.h"
#include "secasn1.h"
#include "secder.h"
#include "certt.h"
#include "certdb.h"
#include "cryptohi.h"
#include "kgenctxt.h"
#include "textgen.h"
#include "secdert.h"
#include "minihttp.h"
#include "ssldlgs.h"
#define SSM_MAX_KEY_BITS 2048L
/* this needs to be localized */
#define XP_HIGH_GRADE "1024 (High Grade)"
#define XP_MEDIUM_GRADE " 768 (Medium Grade)"
#define XP_LOW_GRADE " 512 (Low Grade)"
typedef struct SECKeySizeChoiceInfoStr {
char *name;
int size;
unsigned int enabled;
} SECKeySizeChoiceInfo;
extern void _ssm_compress_spaces(char *psrc);
SSMStatus SSM_OKButtonCommandHandler(HTTPRequest *req);
SSMStatus SSM_CertCAImportCommandHandler1(HTTPRequest * req);
SSMStatus SSM_CertCAImportCommandHandler2(HTTPRequest * req);
SSMStatus SSM_FinishImportCACertHandler(HTTPRequest * req);
SSMStatus SSM_SubmitFormFromButtonHandler(HTTPRequest * req);
SSMStatus SSM_SubmitFormFromButtonAndFreeTarget(HTTPRequest * req);
SSMStatus SSM_CACertKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_CAPolicyKeywordHandler(SSMTextGenContext * cx);
SSMStatus SSM_EnableHighGradeKeyGen(void);
PRBool SSM_KeyGenAllowedForSize(int size);
char * default_nickname(CERTCertificate *cert, SSMControlConnection *conn);
PRBool certificate_conflict(SSMControlConnection * cx, SECItem * derCert,
CERTCertDBHandle * handle, PRBool sendUIEvent);
#endif

View File

@ -0,0 +1,954 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "p12res.h"
#include "minihttp.h"
#include "pk11func.h"
#include "secmod.h"
#include "p12.h"
#include "p12plcy.h"
#include "secerr.h"
#include "newproto.h"
#include "messages.h"
#include "advisor.h"
#include "nlslayer.h"
#define SSMRESOURCE(object) (&object->super)
#define PKCS12_IN_BUFFER_SIZE 2048
static SSMStatus
ssmpkcs12context_createpkcs12file(SSMPKCS12Context *cx,
PRBool forceAuthenticate,
CERTCertificate **certArr,
PRIntn numCerts);
SECStatus
SSM_UnicodeConversion(SECItem *dest, SECItem *src,
PRBool toUnicode, PRBool swapBytes)
{
unsigned int allocLen;
if(!dest || !src) {
return SECFailure;
}
allocLen = ((toUnicode) ? (src->len << 2) : src->len);
if (allocLen == 0) {
/* empty string: we need to pad it by 2 bytes */
allocLen = 2;
}
dest->data = SSM_ZNEW_ARRAY(unsigned char, allocLen);
if(!SSM_UCS2_ASCIIConversion(toUnicode, src->data, src->len,
dest->data, allocLen, &dest->len,
swapBytes)) {
PR_Free(dest->data);
dest->data = NULL;
return SECFailure;
}
return SECSuccess;
}
SSMStatus
SSMPKCS12Context_Create(void *arg, SSMControlConnection *ctrl,
SSMResource **res)
{
SSMPKCS12Context *cxt = NULL;
SSMPKCS12CreateArg *createArg = (SSMPKCS12CreateArg*)arg;
SSMStatus rv;
cxt = SSM_ZNEW(SSMPKCS12Context);
if (cxt == NULL) {
return SSM_ERR_OUT_OF_MEMORY;
}
rv = SSMPKCS12Context_Init(ctrl,cxt,SSM_RESTYPE_PKCS12_CONTEXT ,
createArg->isExportContext);
if (rv != PR_SUCCESS) {
goto loser;
}
*res = SSMRESOURCE(cxt);
return PR_SUCCESS;
loser:
if (cxt != NULL) {
SSM_FreeResource(SSMRESOURCE(cxt));
}
*res = NULL;
return rv;
}
SSMStatus
SSMPKCS12Context_Init(SSMControlConnection *ctrl, SSMPKCS12Context *res,
SSMResourceType type, PRBool isExportContext)
{
res->m_isExportContext = isExportContext;
res->m_password = NULL;
res->m_inputProcessed = PR_FALSE;
res->m_file = NULL;
res->m_digestFile = NULL;
res->m_error = PR_FALSE;
return SSMResource_Init(ctrl, SSMRESOURCE(res), type);
}
SSMStatus
SSMPKCS12Context_Destroy(SSMResource *res, PRBool doFree)
{
SSMPKCS12Context *cxt = (SSMPKCS12Context*)res;
SSMResource_Destroy(res, PR_FALSE);
if (cxt->m_password != NULL) {
PR_Free(cxt->m_password);
cxt->m_password = NULL;
}
if (cxt->m_cert != NULL) {
CERT_DestroyCertificate(cxt->m_cert);
cxt->m_cert = NULL;
}
if (doFree) {
PR_Free(res);
}
return PR_SUCCESS;
}
static SSMStatus
SSMPKCS12Context_HandlePasswordRequest(SSMResource *res,
HTTPRequest *req)
{
char *password, *confirmPassword;
SSMPKCS12Context *p12Cxt = (SSMPKCS12Context*)res;
SSMStatus rv = SSM_FAILURE;
/* Let's get the password out of the dialog. */
if (res->m_buttonType != SSM_BUTTON_OK) {
goto loser;
}
rv = SSM_HTTPParamValue(req, "passwd", &password);
if (rv != SSM_SUCCESS) {
goto loser;
}
rv = SSM_HTTPParamValue(req, "confirmPasswd", &confirmPassword);
if (rv != SSM_SUCCESS) {
goto loser;
}
if (strcmp(password, confirmPassword) != 0) {
/* Should re-prompt, but for now we fail. */
rv = SSM_FAILURE;
goto loser;
}
p12Cxt->m_password = PL_strdup(password);
goto done;
loser:
p12Cxt->m_password = NULL;
done:
SSM_LockResource(res);
SSM_NotifyResource(res);
SSM_UnlockResource(res);
SSM_HTTPDefaultCommandHandler(req);
p12Cxt->m_inputProcessed = PR_TRUE;
return rv;
}
SSMStatus
SSMPKCS12Context_FormSubmitHandler(SSMResource *res, HTTPRequest *req)
{
char *formName;
SSMStatus rv=SSM_FAILURE;
rv = SSM_HTTPParamValue(req, "formName", &formName);
if (rv != SSM_SUCCESS) {
goto loser;
}
if (!strcmp(formName, "cert_backup_form")) {
rv = SSMPKCS12Context_HandlePasswordRequest(res, req);
} else if (!strcmp(formName, "set_db_password")) {
rv = SSM_SetDBPasswordHandler(req);
} else {
goto loser;
}
return rv;
loser:
SSM_HTTPDefaultCommandHandler(req);
return SSM_FAILURE;
}
static void
ssmpkcs12context_writetoexportfile(void *arg, const char *buf,
unsigned long len)
{
SSMPKCS12Context *p12Cxt = (SSMPKCS12Context*)arg;
PRInt32 bytesWritten;
if (p12Cxt == NULL) {
return;
}
if (p12Cxt->m_file == NULL) {
p12Cxt->m_error = PR_TRUE;
return;
}
bytesWritten = PR_Write(p12Cxt->m_file, buf, len);
if (bytesWritten != len) {
p12Cxt->m_error = PR_TRUE;
}
}
SSMStatus
SSMPKCS12Context_CreatePKCS12FileForMultipleCerts(SSMPKCS12Context *p12Cxt,
PRBool forceAuthenticate,
CERTCertificate **certArr,
PRIntn numCerts)
{
return ssmpkcs12context_createpkcs12file(p12Cxt, forceAuthenticate,
certArr, numCerts);
}
SSMStatus
SSMPKCS12Context_CreatePKCS12File(SSMPKCS12Context *cxt,
PRBool forceAuthenticate)
{
return ssmpkcs12context_createpkcs12file(cxt, forceAuthenticate,
&cxt->m_cert, 1);
}
static SSMStatus
ssmpkcs12context_createpkcs12file(SSMPKCS12Context *cxt,
PRBool forceAuthenticate,
CERTCertificate **certArr,
PRIntn numCerts)
{
SEC_PKCS12ExportContext *p12ecx = NULL;
SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
SECItem pwitem = { siBuffer, NULL, 0 };
PK11SlotInfo *slot = NULL;
PK11SlotInfo *slotToUse = NULL;
SSMControlConnection *ctrl;
SSMStatus rv=SSM_FAILURE;
int i;
if (cxt == NULL || certArr == NULL || numCerts == 0) {
return SSM_ERR_BAD_REQUEST;
}
/*
* We're about to send the UI event requesting the password to use
* when encrypting
*/
SSM_LockResource(&cxt->super);
cxt->m_inputProcessed = PR_FALSE;
rv = SSMControlConnection_SendUIEvent(SSMRESOURCE(cxt)->m_connection,
"get", "cert_backup",
SSMRESOURCE(cxt),
(numCerts > 1) ? "multipleCerts=1" :
NULL,
&SSMRESOURCE(cxt)->m_clientContext);
if (rv != SSM_SUCCESS) {
SSM_UnlockResource(SSMRESOURCE(cxt));
goto loser;
}
/*
* Wait until the form is submitted to proceed. We'll get notified.
*/
SSM_WaitResource(SSMRESOURCE(cxt), PR_INTERVAL_NO_TIMEOUT);
SSM_UnlockResource(SSMRESOURCE(cxt));
if (cxt->m_password == NULL ||
cxt->super.m_buttonType == SSM_BUTTON_CANCEL) {
rv = SSM_ERR_NO_PASSWORD;
goto loser;
}
/* Wait for the dialog box to go down so that when it disappears,
* the window doesn't take away the password prompt.
*/
PR_Sleep(PR_TicksPerSecond());
ctrl = SSMRESOURCE(cxt)->m_connection;
pwitem.data = (unsigned char *) cxt->m_password;
pwitem.len = strlen(cxt->m_password);
PK11_FindObjectForCert(certArr[0], ctrl, &slot);
if (slot == NULL) {
rv = SSM_FAILURE;
goto loser;
}
slotToUse = slot;
if (forceAuthenticate && PK11_NeedLogin(slot)) {
PK11_Logout(slot);
}
if (PK11_Authenticate(slot, PR_TRUE, ctrl) != SECSuccess) {
rv = SSM_ERR_BAD_DB_PASSWORD;
goto loser;
}
p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, ctrl);
if (p12ecx == NULL) {
rv = SSM_FAILURE;
goto loser;
}
if (SEC_PKCS12AddPasswordIntegrity(p12ecx, &pwitem, SEC_OID_SHA1)
!= SECSuccess) {
rv = SSM_ERR_BAD_PASSWORD;
goto loser;
}
for (i=0; i <numCerts; i++) {
PK11_FindObjectForCert(certArr[i], ctrl, &slot);
if (slot != slotToUse) {
continue;
}
keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
if (!SEC_PKCS12IsEncryptionAllowed() || PK11_IsFIPS()) {
certSafe = keySafe;
} else {
certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, &pwitem,
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
}
if (certSafe == NULL || keySafe == NULL) {
rv = SSM_FAILURE;
goto loser;
}
if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, certArr[i],
SSMRESOURCE(cxt)->m_connection->m_certdb,
keySafe, NULL, PR_TRUE, &pwitem,
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
!= SECSuccess) {
rv = SSM_FAILURE;
goto loser;
}
}
/* Done with the password, free it */
PR_Free(cxt->m_password);
cxt->m_password = NULL;
rv = SSM_RequestFilePathFromUser(SSMRESOURCE(cxt),
"pkcs12_export_file_prompt",
"*.p12",
PR_FALSE);
if (rv != SSM_SUCCESS || cxt->super.m_fileName == NULL) {
rv = SSM_ERR_BAD_FILENAME;
goto loser;
}
cxt->m_file = PR_Open (cxt->super.m_fileName,
PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
0600);
if (cxt->m_file == NULL) {
rv = SSM_ERR_BAD_FILENAME;
goto loser;
}
if (SEC_PKCS12Encode(p12ecx, ssmpkcs12context_writetoexportfile, cxt)
!= SECSuccess) {
rv = SSM_FAILURE;
goto loser;
}
PR_Close(cxt->m_file);
if (slotToUse) {
PK11_FreeSlot(slotToUse);
}
SEC_PKCS12DestroyExportContext(p12ecx);
return SSM_SUCCESS;
loser:
if (p12ecx != NULL) {
SEC_PKCS12DestroyExportContext(p12ecx);
}
if (slot && cxt->m_cert && (slot != cxt->m_cert->slot)) {
PK11_FreeSlot(slot);
}
PR_FREEIF(cxt->m_password);
cxt->m_password = NULL;
return rv;
}
/* This function converts ASCII strings to UCS2 strings in Network Byte Order.
** The "swapBytes" argument is ignored.
** The PKCS#12 code only makes it true on Little Endian systems,
** where it was intended to force the output into NBO.
*/
PRBool
SSM_UCS2_ASCIIConversion(PRBool toUnicode,
unsigned char *inBuf,
unsigned int inBufLen,
unsigned char *outBuf,
unsigned int maxOutBufLen,
unsigned int *outBufLen,
PRBool swapBytes)
{
if (!inBuf || !outBuf || !outBufLen) {
return PR_FALSE;
}
if (toUnicode) {
PRBool rv;
#ifdef DEBUG
unsigned int outLen;
int i;
fprintf(stderr,"\n---ssm_ConvertAsciiToUCS2---\nInput: inBuf= ");
for (i = 0; i < inBufLen; i++) {
fprintf(stderr, "%c", inBuf[i]);
}
fprintf(stderr,"\ninBufLen=%d\n", inBufLen);
#endif
rv = nlsASCIIToUnicode(inBuf, inBufLen,
outBuf, maxOutBufLen, outBufLen);
#ifdef DEBUG
outLen = *outBufLen;
fprintf(stderr,"output: outBuf= ");
for(i = 0; i < outLen; i++) {
fprintf(stderr, "%c ", outBuf[i]);
}
fprintf(stderr,"\noutBuf= ");
for(i = 0; i < outLen; i++) {
fprintf(stderr,"%2x ", outBuf[i]);
}
fprintf(stderr,"\noutLen = %d\n", outLen);
#endif /* DEBUG */
return rv;
}
PR_ASSERT(PR_FALSE); /* not supported yet */
return PR_FALSE;
}
PRBool
SSM_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
unsigned int inBufLen,unsigned char *outBuf,
unsigned int maxOutBufLen, unsigned int *outBufLen)
{
PRBool retval;
#ifdef DEBUG
unsigned int i;
#endif
if(!inBuf || !outBuf || !outBufLen) {
return PR_FALSE;
}
*outBufLen = 0;
#ifdef DEBUG
fprintf(stderr,"---UCS2_UTF8Conversion (%s) ---\nInput: \n",
(toUnicode?"to UCS2":"to UTF8"));
for(i=0; i< inBufLen; i++) {
fprintf(stderr,"%c", (char) inBuf[i]);
}
fprintf(stderr,"\n");
for(i=0; i< inBufLen; i++) {
fprintf(stderr,"%2x ", (char) inBuf[i]);
}
fprintf(stderr,"\n");
#endif
if(toUnicode) {
retval = nlsUTF8ToUnicode(inBuf, inBufLen, outBuf, maxOutBufLen,
outBufLen);
} else {
retval = nlsUnicodeToUTF8(inBuf, inBufLen, outBuf, maxOutBufLen,
outBufLen);
}
#ifdef DEBUG
fprintf(stderr,"Output: \n");
for(i=0; i< *outBufLen; i++) {
fprintf(stderr,"%c", (char) outBuf[i]);
}
fprintf(stderr,"\n");
for(i=0; i< *outBufLen; i++) {
fprintf(stderr,"%2x ", (char) outBuf[i]);
}
fprintf(stderr,"\n\n");
#endif
return retval;
}
static SECStatus
ssmpkcs12context_digestopen(void *arg, PRBool readData)
{
char *tmpFileName=NULL;
char filePathSep;
SSMPKCS12Context *cxt = (SSMPKCS12Context *)arg;
#if defined(XP_UNIX)
filePathSep = '/';
#elif defined(WIN32)
filePathSep = '\\';
#elif defined(XP_MAC)
filePathSep = ':';
#else
#error Tell me what the file path separator is of this platform.
#endif
tmpFileName = PR_smprintf("%s%c%s",
SSMRESOURCE(cxt)->m_connection->m_dirRoot,
filePathSep,
".nsm_p12_tmp");
if (tmpFileName == NULL) {
return SECFailure;
}
if (readData) {
cxt->m_digestFile = PR_Open(tmpFileName,
PR_RDONLY, 0400);
} else {
cxt->m_digestFile = PR_Open(tmpFileName,
PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE,
0600);
}
cxt->m_tempFilePath = tmpFileName;
if (cxt->m_digestFile == NULL) {
cxt->m_error = PR_TRUE;
return SECFailure;
}
return SECSuccess;
}
static SECStatus
ssmpkcs12context_digestclose(void *arg, PRBool removeFile)
{
SSMPKCS12Context *cxt = (SSMPKCS12Context*)arg;
if (cxt == NULL || cxt->m_digestFile == NULL) {
return SECFailure;
}
PR_Close(cxt->m_digestFile);
cxt->m_digestFile = NULL;
if (removeFile) {
PR_Delete(cxt->m_tempFilePath);
PR_Free(cxt->m_tempFilePath);
cxt->m_tempFilePath = NULL;
}
return SECSuccess;
}
static int
ssmpkcs12context_digestread(void *arg, unsigned char *buf, unsigned long len)
{
SSMPKCS12Context *cxt = (SSMPKCS12Context*)arg;
if (cxt == NULL || cxt->m_digestFile == NULL) {
return -1;
}
if (buf == NULL || len == 0) {
return -1;
}
return PR_Read(cxt->m_digestFile, buf, len);
}
static int
ssmpkcs12context_digestwrite(void *arg, unsigned char *buf, unsigned long len)
{
SSMPKCS12Context *cxt = (SSMPKCS12Context *)arg;
if (cxt == NULL || cxt->m_digestFile == NULL) {
return -1;
}
if (buf == NULL || len == 0) {
return -1;
}
return PR_Write(cxt->m_digestFile, buf, len);
}
SECItem*
SSM_NicknameCollisionCallback(SECItem *old_nick, PRBool *cancel,
void *wincx)
{
/* We don't handle this yet */
*cancel = PR_TRUE;
return NULL;
}
static PK11SlotInfo*
SSMPKCS12Context_ChooseSlotForImport(SSMPKCS12Context *cxt,
PK11SlotList *slotList)
{
char mech[20];
SSMStatus rv;
PR_snprintf(mech, 20, "mech=%d&task=import&unused=unused", CKM_RSA_PKCS);
SSM_LockUIEvent(&cxt->super);
rv = SSMControlConnection_SendUIEvent(cxt->super.m_connection,
"get",
"select_token",
&cxt->super,
mech, &SSMRESOURCE(cxt)->m_clientContext);
if (rv != SSM_SUCCESS) {
SSM_UnlockResource(&cxt->super);
return NULL;
}
SSM_WaitUIEvent(&cxt->super, PR_INTERVAL_NO_TIMEOUT);
/* Wait so damn window goes away without swallowing up
* the password prompt that will come up next.
*/
PR_Sleep(PR_TicksPerSecond());
return (PK11SlotInfo*)cxt->super.m_uiData;
}
static PK11SlotInfo*
SSMPKCS12Context_GetSlotForImport(SSMPKCS12Context *cxt)
{
PK11SlotList *slotList;
PK11SlotInfo *slot = NULL;
slotList = PK11_GetAllTokens(CKM_RSA_PKCS, PR_TRUE, PR_TRUE,
cxt->super.m_connection);
if (slotList == NULL || slotList->head == NULL) {
/* Couldn't find a slot, let's try the internal slot
* and see what happens
*/
slot = PK11_GetInternalKeySlot();
} else if (slotList->head->next == NULL) {
/*
* Only one slot, return it.
*/
slot = PK11_ReferenceSlot(slotList->head->slot);
} else {
slot = SSMPKCS12Context_ChooseSlotForImport(cxt, slotList);
}
if (slotList)
PK11_FreeSlotList(slotList);
return slot;
}
SSMStatus
SSMPKCS12Context_RestoreCertFromPKCS12File(SSMPKCS12Context *cxt)
{
SSMStatus rv;
SECItem passwdReq;
char *prompt=NULL;
PK11SlotInfo *slot=NULL;
SEC_PKCS12DecoderContext *p12dcx=NULL;
PRBool swapUnicode = PR_FALSE;
unsigned char *buf=NULL;
SECItem pwItem = { siBuffer, NULL, 0 }, uniPwItem = { siBuffer, NULL, 0 };
SECStatus srv;
CERTCertList *certList=NULL;
CERTCertListNode *node=NULL;
PromptRequest request;
if (cxt == NULL || cxt->m_isExportContext) {
return SSM_FAILURE;
}
#ifdef IS_LITTLE_ENDIAN
swapUnicode = PR_TRUE;
#endif
rv = SSM_RequestFilePathFromUser(SSMRESOURCE(cxt),
"pkcs12_import_file_prompt",
"*.p12",
PR_TRUE);
if (rv != SSM_SUCCESS || cxt->super.m_fileName == NULL) {
rv = SSM_ERR_BAD_FILENAME;
goto loser;
}
prompt = SSM_GetCharFromKey("pkcs12_request_password_prompt",
"ISO-8859-1");
if (prompt == NULL) {
rv = SSM_FAILURE;
goto loser;
}
request.resID = SSMRESOURCE(cxt)->m_id;
request.prompt = prompt;
request.clientContext = SSMRESOURCE(cxt)->m_clientContext;
if (CMT_EncodeMessage(PromptRequestTemplate, (CMTItem*)&passwdReq, &request) != CMTSuccess) {
rv = SSM_FAILURE;
goto loser;
}
passwdReq.type = (SECItemType) (SSM_EVENT_MESSAGE | SSM_PROMPT_EVENT);
SSM_LockResource(SSMRESOURCE(cxt));
cxt->m_password = NULL;
rv = SSM_SendQMessage(SSMRESOURCE(cxt)->m_connection->m_controlOutQ,
20,
passwdReq.type,
passwdReq.len,
(char*)passwdReq.data,
PR_TRUE);
SSM_WaitResource(SSMRESOURCE(cxt), SSM_PASSWORD_WAIT_TIME);
SSM_UnlockResource(SSMRESOURCE(cxt));
if (cxt->m_password == NULL) {
rv = SSM_ERR_NO_PASSWORD;
goto loser;
}
cxt->m_file = PR_Open(SSMRESOURCE(cxt)->m_fileName,
PR_RDONLY, 0400);
if (cxt->m_file == NULL) {
rv = SSM_ERR_BAD_FILENAME;
goto loser;
}
slot = SSMPKCS12Context_GetSlotForImport(cxt);
if (slot == NULL) {
goto loser;
}
if (PK11_NeedLogin(slot)) {
/* we should log out only if the slot needs login */
PK11_Logout(slot);
}
/* User has not initialize DB, ask for a password. */
if (PK11_NeedUserInit(slot)) {
rv = SSM_SetUserPassword(slot, SSMRESOURCE(cxt));
if (rv != SSM_SUCCESS) {
rv = SSM_ERR_NEED_USER_INIT_DB;
goto loser;
}
}
if (PK11_Authenticate(slot, PR_FALSE, SSMRESOURCE(cxt)->m_connection)
!= SECSuccess) {
rv = SSM_ERR_BAD_DB_PASSWORD;
goto loser;
}
pwItem.data = (unsigned char *) cxt->m_password;
pwItem.len = strlen(cxt->m_password);
if (SSM_UnicodeConversion(&uniPwItem, &pwItem, PR_TRUE,
swapUnicode) != SECSuccess) {
rv = SSM_ERR_BAD_PASSWORD;
goto loser;
}
p12dcx = SEC_PKCS12DecoderStart(&uniPwItem, slot,
SSMRESOURCE(cxt)->m_connection,
ssmpkcs12context_digestopen,
ssmpkcs12context_digestclose,
ssmpkcs12context_digestread,
ssmpkcs12context_digestwrite,
cxt);
if (p12dcx == NULL) {
rv = SSM_FAILURE;
goto loser;
}
buf = SSM_NEW_ARRAY(unsigned char, PKCS12_IN_BUFFER_SIZE);
if (buf == NULL) {
rv = SSM_ERR_OUT_OF_MEMORY;
goto loser;
}
cxt->m_file = PR_Open(SSMRESOURCE(cxt)->m_fileName, PR_RDONLY, 0400);
if (cxt->m_file == NULL) {
rv = SSM_ERR_BAD_FILENAME;
goto loser;
}
while (PR_TRUE) {
int readLen = PR_Read(cxt->m_file, buf, PKCS12_IN_BUFFER_SIZE);
if (readLen < 0) {
rv = SSM_FAILURE;
goto loser;
}
srv = SEC_PKCS12DecoderUpdate(p12dcx, buf, readLen);
if (srv != SECSuccess || readLen != PKCS12_IN_BUFFER_SIZE) {
break;
}
}
if (srv != SECSuccess) {
rv = SSM_ERR_CANNOT_DECODE;
goto loser;
}
if (SEC_PKCS12DecoderVerify(p12dcx) != SECSuccess) {
rv = SSM_FAILURE;
goto loser;
}
if (SEC_PKCS12DecoderValidateBags(p12dcx, SSM_NicknameCollisionCallback)
!= SECSuccess) {
if (PORT_GetError() == SEC_ERROR_PKCS12_DUPLICATE_DATA) {
rv = SSM_PKCS12_CERT_ALREADY_EXISTS;
} else {
rv = SSM_FAILURE;
}
goto loser;
}
if (SEC_PKCS12DecoderImportBags(p12dcx) != SECSuccess) {
rv = SSM_FAILURE;
goto loser;
}
PR_Close(cxt->m_file);
cxt->m_file = NULL;
PR_Free(prompt);
PK11_FreeSlot(slot);
certList = SEC_PKCS12DecoderGetCerts(p12dcx);
if (certList != NULL) {
for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
node = CERT_LIST_NEXT(node)) {
if ((node->cert->trust) &&
(node->cert->trust->emailFlags & CERTDB_USER) &&
CERT_VerifyCertNow(cxt->super.m_connection->m_certdb,
node->cert, PR_TRUE, certUsageEmailSigner,
cxt) == SSM_SUCCESS) {
rv = SSM_UseAsDefaultEmailIfNoneSet(cxt->super.m_connection,
node->cert, PR_FALSE);
if (rv == SSM_SUCCESS) {
/* We just made this cert the default new cert */
rv = SSM_ERR_NEW_DEF_MAIL_CERT;
break;
}
}
}
CERT_DestroyCertList(certList);
certList = NULL;
}
SEC_PKCS12DecoderFinish(p12dcx);
return (rv == SSM_ERR_NEW_DEF_MAIL_CERT) ? rv : SSM_SUCCESS;
loser:
if (cxt->m_file != NULL) {
PR_Close(cxt->m_file);
cxt->m_file = NULL;
}
if (prompt != NULL) {
PR_Free(prompt);
}
if (slot != NULL) {
PK11_FreeSlot(slot);
}
if (p12dcx != NULL) {
SEC_PKCS12DecoderFinish(p12dcx);
}
if (buf != NULL) {
PR_Free(buf);
}
cxt->m_error = PR_TRUE;
return rv;
}
SSMStatus
SSMPKCS12Context_ProcessPromptReply(SSMResource *res,
char *reply)
{
SSMPKCS12Context *cxt = (SSMPKCS12Context*)res;
if (!SSM_IsAKindOf(res, SSM_RESTYPE_PKCS12_CONTEXT)) {
return PR_FAILURE;
}
cxt->m_password = reply?PL_strdup(reply):NULL;
SSM_LockResource(res);
SSM_NotifyResource(res);
SSM_UnlockResource(res);
return PR_SUCCESS;
}
SSMStatus
SSMPKCS12Context_Print(SSMResource *res,
char *fmt,
PRIntn numParams,
char **value,
char **resultStr)
{
char mechStr[48];
SSMStatus rv = SSM_FAILURE;
PR_ASSERT(resultStr != NULL);
if (resultStr == NULL) {
rv = SSM_FAILURE;
goto done;
}
if (numParams) {
rv = SSMResource_Print(res, fmt, numParams, value, resultStr);
goto done;
}
PR_snprintf(mechStr, 48, "%d", CKM_RSA_PKCS);
*resultStr = PR_smprintf(fmt, res->m_id, mechStr, "");
rv = (*resultStr == NULL) ? SSM_FAILURE : SSM_SUCCESS;
done:
return rv;
}
void SSMPKCS12Context_BackupMultipleCertsThread(void *arg)
{
SSMPKCS12Context *p12Cxt = (SSMPKCS12Context*)arg;
SSMStatus rv;
SSMControlConnection *connection = p12Cxt->super.m_connection;
PRIntn i;
SSM_RegisterThread("PKCS12", NULL);
SSM_DEBUG("About to backup some certs.\n");
rv = SSMControlConnection_SendUIEvent(connection,
"get", "backup_new_cert",
&p12Cxt->super, NULL,
&p12Cxt->super.m_clientContext);
PR_ASSERT(SSMRESOURCE(p12Cxt)->m_buttonType == SSM_BUTTON_NONE);
if (rv == SSM_SUCCESS) {
while (SSMRESOURCE(p12Cxt)->m_buttonType == SSM_BUTTON_NONE) {
SSM_WaitForOKCancelEvent(SSMRESOURCE(p12Cxt),
PR_INTERVAL_NO_TIMEOUT);
}
}
/*
* Eventhough we tell Nova to use a context it provided to us,
* it still tries to use the top-most window to bring up the
* next dialog. Meaning I still have to insert this freakin'
* sleep.
*
* XXX -javi
*/
PR_Sleep(PR_TicksPerSecond());
#if 0
/*
* Disable this for now, until we figure out how we're really gonna
* support putting multiple cert/key pairs in one P12 file.
*/
SSMPKCS12Context_CreatePKCS12FileForMultipleCerts(p12Cxt, PR_FALSE,
p12Cxt->arg->certs,
p12Cxt->arg->numCerts);
#endif
for (i=0; i<p12Cxt->arg->numCerts;i++) {
p12Cxt->m_cert = p12Cxt->arg->certs[i];
SSMPKCS12Context_CreatePKCS12File(p12Cxt, PR_FALSE);
/*
* ARGH!! If we do more than one, then Communicator crashes
* because it tries to use a window that no longer exists as
* the base for the next window.
*/
PR_Sleep(PR_TicksPerSecond());
}
PR_Free(p12Cxt->arg->certs);
PR_Free(p12Cxt->arg);
p12Cxt->arg = NULL;
p12Cxt->m_thread = NULL;
SSM_FreeResource(&p12Cxt->super);
SSM_DEBUG("Done backing up certs.\n");
}
SSMStatus
SSM_WarnPKCS12Incompatibility(SSMTextGenContext *cx)
{
SSMStatus rv;
char *value;
rv = SSM_HTTPParamValue(cx->m_request, "multipleCerts", &value);
PR_FREEIF(cx->m_result);
cx->m_result = NULL;
if (rv == SSM_SUCCESS) {
rv = SSM_FindUTF8StringInBundles(cx, "pkcs12_incompatible_warn",
&cx->m_result);
if (rv != SSM_SUCCESS) {
cx->m_result = PL_strdup("");
}
} else {
cx->m_result = PL_strdup("");
}
return SSM_SUCCESS;
}

View File

@ -0,0 +1,121 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef P12RES_H_
#define P12RES_H_
#include "resource.h"
#include "ctrlconn.h"
/*
* Initially, this will only be used as a resource to use in doing UI
* events necessary for PKCS12 operations.
*/
typedef struct SSMPKCS12ContextStr SSMPKCS12Context;
typedef struct SSMPKCS12BackupThreadArgStr {
CERTCertificate **certs;
PRIntn numCerts;
} SSMPKCS12BackupThreadArg;
struct SSMPKCS12ContextStr {
SSMResource super;
char *m_password;
PRFileDesc *m_file;
PRFileDesc *m_digestFile;
char *m_tempFilePath;
PRBool m_error;
PRBool m_inputProcessed;
PRBool m_isExportContext; /* We're either importing or exporting. */
CERTCertificate *m_cert;
PRThread *m_thread; /* A thread for doing backup when doing
* CMMF.
*/
SSMPKCS12BackupThreadArg *arg;
};
typedef struct SSMPKCS12CreateArgStr {
PRBool isExportContext;
} SSMPKCS12CreateArg;
SSMStatus
SSMPKCS12Context_Create(void *arg, SSMControlConnection *ctrl,
SSMResource **res);
SSMStatus
SSMPKCS12Context_Init(SSMControlConnection *ctrl, SSMPKCS12Context *res,
SSMResourceType type, PRBool isExportContext);
SSMStatus
SSMPKCS12Context_Destroy(SSMResource *res, PRBool doFree);
SSMStatus
SSMPKCS12Context_FormSubmitHandler(SSMResource *res, HTTPRequest *req);
SSMStatus
SSMPKCS12Context_Print(SSMResource *res,
char *fmt,
PRIntn numParams,
char **value,
char **resultStr);
SSMStatus
SSMPKCS12Context_CreatePKCS12File(SSMPKCS12Context *cxt,
PRBool forceAuthenticate);
SSMStatus
SSMPKCS12Context_RestoreCertFromPKCS12File(SSMPKCS12Context *cxt);
SSMStatus
SSMPKCS12Context_ProcessPromptReply(SSMResource *res,
char *reply);
PRBool
SSM_UCS2_ASCIIConversion(PRBool toUnicode,
unsigned char *inBuf, unsigned int inBufLen,
unsigned char *outBuf, unsigned int maxOutBufLen,
unsigned int *outBufLen, PRBool swapBytes);
PRBool
SSM_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf,
unsigned int inBufLen,unsigned char *outBuf,
unsigned int maxOutBufLen, unsigned int *outBufLen);
SSMStatus
SSMPKCS12Context_CreatePKCS12FileForMultipleCerts(SSMPKCS12Context *p12Cxt,
PRBool forceAuthenticate,
CERTCertificate **certArr,
PRIntn numCerts);
void SSMPKCS12Context_BackupMultipleCertsThread(void *arg);
#endif /*P12RES_H_*/

View File

@ -0,0 +1,280 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "p7cinfo.h"
#include "ssmerrs.h"
/* Shorthand macros for inherited classes */
#define SSMRESOURCE(ci) (&(ci)->super)
SSMStatus
SSMP7ContentInfo_Create(void *arg, SSMControlConnection * connection,
SSMResource **res)
{
SSMStatus rv = PR_SUCCESS;
SSMP7ContentInfo *ci;
*res = NULL; /* in case we fail */
ci = (SSMP7ContentInfo *) PR_CALLOC(sizeof(SSMP7ContentInfo));
if (!ci) goto loser;
SSMRESOURCE(ci)->m_connection = connection;
rv = SSMP7ContentInfo_Init(ci, connection, (SEC_PKCS7ContentInfo *) arg,
SSM_RESTYPE_PKCS7_CONTENT_INFO);
if (rv != PR_SUCCESS) goto loser;
SSMP7ContentInfo_Invariant(ci);
*res = SSMRESOURCE(ci);
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
if (ci)
{
SSMRESOURCE(ci)->m_refCount = 1; /* force destroy */
SSM_FreeResource(SSMRESOURCE(ci));
}
return rv;
}
SSMStatus
SSMP7ContentInfo_Init(SSMP7ContentInfo *ci, SSMControlConnection * conn,
SEC_PKCS7ContentInfo *cinfo,
SSMResourceType type)
{
SSMStatus rv = PR_SUCCESS;
/* Initialize superclass */
rv = SSMResource_Init(conn, SSMRESOURCE(ci), type);
if (rv != PR_SUCCESS) goto loser;
/* Fill in the content info */
PR_ASSERT(cinfo != NULL);
ci->m_cinfo = cinfo;
/* Sanity check before returning */
SSMP7ContentInfo_Invariant(ci);
goto done;
loser:
/* member destruct, if any are allocated, will happen in the
_Destroy method */
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMP7ContentInfo_Destroy(SSMResource *res, PRBool doFree)
{
SSMP7ContentInfo *ci = (SSMP7ContentInfo *) res;
SSMP7ContentInfo_Invariant(ci);
/* Destroy our members. */
if (ci->m_cinfo)
{
SEC_PKCS7DestroyContentInfo(ci->m_cinfo);
ci->m_cinfo = NULL;
}
/* Destroy superclass. */
SSMResource_Destroy(res, PR_FALSE);
/* Free if asked. */
if (doFree)
PR_Free(res);
return PR_SUCCESS;
}
void
SSMP7ContentInfo_Invariant(SSMP7ContentInfo *ci)
{
/* Superclass invariant */
SSMResource_Invariant(SSMRESOURCE(ci));
SSM_LockResource(SSMRESOURCE(ci));
/* Class check */
PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(ci), SSM_RESTYPE_PKCS7_CONTENT_INFO));
/* Member check */
PR_ASSERT(ci->m_cinfo != NULL);
if (ci->m_signerCert)
PR_ASSERT(SSM_IsAKindOf(&(ci->m_signerCert->super),SSM_RESTYPE_CERTIFICATE));
SSM_UnlockResource(SSMRESOURCE(ci));
}
SSMStatus
SSMP7ContentInfo_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count)
{
SSMStatus rv;
rv = SSMResource_GetAttrIDs(res, ids, count);
if (rv != PR_SUCCESS)
goto loser;
*ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 3) * sizeof(SSMAttributeID));
if (! *ids) goto loser;
(*ids)[*count++] = SSM_FID_P7CINFO_IS_SIGNED;
(*ids)[*count++] = SSM_FID_P7CINFO_IS_ENCRYPTED;
(*ids)[*count++] = SSM_FID_P7CINFO_SIGNER_CERT;
goto done;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMP7ContentInfo_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMP7ContentInfo *cinfo = (SSMP7ContentInfo *) res;
SEC_PKCS7ContentInfo *info;
SSMStatus rv = SSM_SUCCESS;
SSMP7ContentInfo_Invariant(cinfo);
if (!cinfo)
{
rv = PR_INVALID_ARGUMENT_ERROR;
goto loser;
}
SSM_LockResource(SSMRESOURCE(cinfo));
info = cinfo->m_cinfo;
if (!info)
{
rv = SSM_ERR_ATTRIBUTE_MISSING;
goto loser;
}
/* see what it is */
switch(attrID)
{
case SSM_FID_P7CINFO_IS_SIGNED:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = SEC_PKCS7ContentIsSigned(cinfo->m_cinfo);
rv = SSM_SUCCESS;
break;
case SSM_FID_P7CINFO_IS_ENCRYPTED:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = SEC_PKCS7ContentIsEncrypted(cinfo->m_cinfo);
rv = SSM_SUCCESS;
break;
case SSM_FID_P7CINFO_SIGNER_CERT:
/* Make sure we have a cert to return. */
rv = SSM_ERR_ATTRIBUTE_MISSING; /* by default */
/* want signed data */
if ((info->content.signedData) &&
/* want signer info */
(info->content.signedData->signerInfos) &&
/* 1 and only 1 signer
### mwelch what if we have more than one? */
(info->content.signedData->signerInfos[0]) &&
(info->content.signedData->signerInfos[1] == NULL))
{
/* Get the cert, wrap it in a resource, and return its ID. */
CERTCertificate *cert =
info->content.signedData->signerInfos[0]->cert;
SSMResourceID certID;
if (!cert) goto loser; /* we could still have a null cert */
rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
cert,
SSMRESOURCE(cinfo)->m_connection,
&certID,
(SSMResource **) &cinfo->m_signerCert);
SSMP7ContentInfo_Invariant(cinfo);
value->type = SSM_RID_ATTRIBUTE;
rv = SSM_ClientGetResourceReference(&cinfo->m_signerCert->super,
&certID);
if (rv != PR_SUCCESS)
goto loser;
rv = SSM_SUCCESS;
value->type = SSM_RID_ATTRIBUTE;
value->u.numeric = certID;
SSM_FreeResource(&cinfo->m_signerCert->super);
}
break;
default:
rv = SSMResource_GetAttr(res,attrID,attrType,value);
if (rv != PR_SUCCESS) goto loser;
}
goto done;
loser:
value->type = SSM_NO_ATTRIBUTE;
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
done:
if (cinfo)
SSM_UnlockResource(SSMRESOURCE(cinfo));
return rv;
}
SSMStatus SSMP7ContentInfo_VerifyDetachedSignature(SSMP7ContentInfo *ci,
SECCertUsage usage,
HASH_HashType hash,
PRBool keepCerts,
PRIntn digestLen,
char *detachedDigest)
{
SSMStatus rv = PR_FAILURE;
SECItem digest;
SSMP7ContentInfo_Invariant(ci);
digest.len = digestLen;
digest.data = (unsigned char*) detachedDigest;
if (ci->m_cinfo)
{
if (SEC_PKCS7VerifyDetachedSignature(ci->m_cinfo, usage,
&digest, hash, keepCerts))
rv = SSM_SUCCESS;
}
return rv;
}

View File

@ -0,0 +1,86 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_P7CINFO_H__
#define __SSM_P7CINFO_H__
#include "secpkcs7.h"
#include "resource.h"
#include "certres.h"
/* Initialization parameters for an SSMSSLSocketStatus. */
/*
Wrapper for the SEC_PKCS7ContentInfo structure. This is generated by
several calls within the PKCS7 library, including PKCS7 decoder streams.
*/
typedef struct SSMP7ContentInfo
{
SSMResource super;
SEC_PKCS7ContentInfo *m_cinfo;
SSMResourceCert *m_signerCert;
} SSMP7ContentInfo;
SSMStatus SSMP7ContentInfo_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMP7ContentInfo_Init(SSMP7ContentInfo *ss,
SSMControlConnection * conn,
SEC_PKCS7ContentInfo *cinfo,
SSMResourceType type);
SSMStatus SSMP7ContentInfo_Destroy(SSMResource *res, PRBool doFree);
void SSMP7ContentInfo_Invariant(SSMP7ContentInfo *ss);
SSMStatus SSMP7ContentInfo_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMP7ContentInfo_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
/*
Functions which involve a PKCS7ContentInfo resource, but which
aren't immediately germane to the object itself (if that makes
sense)
*/
SSMStatus SSMP7ContentInfo_VerifyDetachedSignature(SSMP7ContentInfo *ci,
SECCertUsage usage,
HASH_HashType hash,
PRBool keepCerts,
PRIntn digestLen,
char *detachedDigest);
#endif

View File

@ -0,0 +1,513 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "p7dconn.h"
#include "serv.h"
#include "servimpl.h"
#include "ssmerrs.h"
#include "newproto.h"
#include "messages.h"
#include "collectn.h"
#include "secmime.h"
/* Shorthand macros for inherited classes */
#define SSMRESOURCE(conn) (&(conn)->super.super.super)
#define SSMCONNECTION(conn) (&(conn)->super.super)
#define SSMDATACONNECTION(conn) (&(conn)->super)
#define SSM_PARENT_CONN(conn) ((SSMControlConnection*)((conn)->super.super.m_parent))
void SSMP7DecodeConnection_ServiceThread(void * arg);
SSMStatus SSMP7DecodeConnection_StartDecoding(SSMP7DecodeConnection *conn);
/* callbacks for PKCS7 decoder */
void SSMP7DecodeConnection_ContentCallback(void *arg,
const char *buf,
unsigned long len);
PK11SymKey * SSMP7DecodeConnection_GetDecryptKey(void *arg,
SECAlgorithmID *algid);
PRBool SSMP7DecodeConnection_DecryptionAllowed(SECAlgorithmID *algid,
PK11SymKey *bulkkey);
SECItem * SSMP7DecodeConnection_GetPasswordKey(void *arg,
SECKEYKeyDBHandle *handle);
SSMStatus SSMP7DecodeConnection_Create(void *arg,
SSMControlConnection * connection,
SSMResource **res)
{
SSMStatus rv = PR_SUCCESS;
SSMP7DecodeConnection *conn;
*res = NULL; /* in case we fail */
conn = (SSMP7DecodeConnection *) PR_CALLOC(sizeof(SSMP7DecodeConnection));
if (!conn) goto loser;
SSMRESOURCE(conn)->m_connection = connection;
rv = SSMP7DecodeConnection_Init(conn, (SSMInfoP7Decode*) arg,
SSM_RESTYPE_PKCS7_DECODE_CONNECTION);
if (rv != PR_SUCCESS) goto loser;
SSMP7DecodeConnection_Invariant(conn);
*res = SSMRESOURCE(conn);
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
if (conn)
{
SSM_ShutdownResource(SSMRESOURCE(conn), rv); /* force destroy */
SSM_FreeResource(SSMRESOURCE(conn));
}
return rv;
}
SSMStatus SSMP7DecodeConnection_Init(SSMP7DecodeConnection *conn,
SSMInfoP7Decode *info,
SSMResourceType type)
{
SSMStatus rv = PR_SUCCESS;
rv = SSMDataConnection_Init(SSMDATACONNECTION(conn), info->ctrl, type);
if (rv != PR_SUCCESS) goto loser;
/* Start the decoder */
if (SSMP7DecodeConnection_StartDecoding(conn) != SSM_SUCCESS) {
goto loser;
}
/* Save the client UI context */
SSMRESOURCE(conn)->m_clientContext = info->clientContext;
/* Spin the service thread. */
SSM_DEBUG("Creating decoder service thread.\n");
SSM_GetResourceReference(SSMRESOURCE(conn));
SSMDATACONNECTION(conn)->m_dataServiceThread =
SSM_CreateThread(SSMRESOURCE(conn),
SSMP7DecodeConnection_ServiceThread);
if (SSMDATACONNECTION(conn)->m_dataServiceThread == NULL) {
goto loser;
}
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
return rv;
}
SSMStatus
SSMP7DecodeConnection_FinishDecoding(SSMP7DecodeConnection *conn)
{
SEC_PKCS7ContentInfo *p7info = NULL;
SSMResourceID resID;
SSMStatus rv = SSM_SUCCESS;
if (conn->m_cinfo)
{
SSM_FreeResource(&conn->m_cinfo->super);
conn->m_cinfo = NULL;
}
if (conn->m_context)
{
p7info = SEC_PKCS7DecoderFinish(conn->m_context);
if (!p7info) {
conn->m_error = PR_GetError();
}
conn->m_context = NULL;
if (p7info)
{
rv = SSM_CreateResource(SSM_RESTYPE_PKCS7_CONTENT_INFO,
p7info,
SSM_PARENT_CONN(conn),
&resID,
(SSMResource **) &conn->m_cinfo);
}
else
rv = PR_FAILURE;
SSM_LockResource(&conn->super.super.super);
SSM_NotifyResource(&conn->super.super.super);
SSM_UnlockResource(&conn->super.super.super);
}
return rv;
}
SSMStatus
SSMP7DecodeConnection_StartDecoding(SSMP7DecodeConnection *conn)
{
PR_ASSERT(conn->m_context == NULL);
SSM_LockResource(SSMRESOURCE(conn));
if (conn->m_context)
SSMP7DecodeConnection_FinishDecoding(conn);
conn->m_context =
SEC_PKCS7DecoderStart(SSMP7DecodeConnection_ContentCallback,
conn,
SSMP7DecodeConnection_GetPasswordKey,
conn,
SSMP7DecodeConnection_GetDecryptKey,
conn,
SSMP7DecodeConnection_DecryptionAllowed);
SSM_UnlockResource(SSMRESOURCE(conn));
/* Did we get a context */
if (!conn->m_context) {
conn->m_error = PR_GetError();
return PR_FAILURE;
} else {
return PR_SUCCESS;
}
}
SSMStatus SSMP7DecodeConnection_Destroy(SSMResource *res, PRBool doFree)
{
SSMP7DecodeConnection *conn = (SSMP7DecodeConnection *) res;
if (doFree)
SSM_DEBUG("SSMP7DecodeConnection_Destroy called.\n");
/* We should be shut down. */
PR_ASSERT(res->m_threadCount == 0);
/* Destroy our fields. */
SSM_LockResource(SSMRESOURCE(conn));
if (conn->m_context)
SSMP7DecodeConnection_FinishDecoding(conn);
if (conn->m_cinfo)
{
SSM_FreeResource(&conn->m_cinfo->super);
conn->m_cinfo = NULL;
}
SSM_UnlockResource(SSMRESOURCE(conn));
/* Destroy superclass fields. */
SSMDataConnection_Destroy(SSMRESOURCE(conn), PR_FALSE);
/* Free the connection object if asked. */
if (doFree)
PR_DELETE(conn);
return PR_SUCCESS;
}
void
SSMP7DecodeConnection_Invariant(SSMP7DecodeConnection *conn)
{
SSMDataConnection_Invariant(SSMDATACONNECTION(conn));
/* our specific invariants */
SSM_LockResource(SSMRESOURCE(conn));
/* check class */
PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(conn), SSM_RESTYPE_PKCS7_DECODE_CONNECTION));
/* we should not be simultaneously decoded and decoding */
if (conn->m_context)
PR_ASSERT(conn->m_cinfo == NULL);
SSM_UnlockResource(SSMRESOURCE(conn));
}
SSMStatus
SSMP7DecodeConnection_Shutdown(SSMResource *arg, SSMStatus status)
{
SSMStatus rv = SSM_SUCCESS;
/* Call our superclass shutdown. */
rv = SSMDataConnection_Shutdown(arg, status);
return rv;
}
/*
PKCS7 decoding is performed by a single service thread. This thread
feeds data from the outgoing queue into the PKCS7 decoder.
*/
void SSMP7DecodeConnection_ServiceThread(void * arg)
{
SSMStatus rv = PR_SUCCESS;
SSMP7DecodeConnection* conn;
SSMControlConnection* ctrl;
SECItem* msg;
PRIntn read;
char buffer[LINESIZE+1] = {0};
SSM_RegisterNewThread("p7decode", (SSMResource *) arg);
conn = (SSMP7DecodeConnection *)arg;
SSM_DEBUG("initializing.\n");
if (!arg)
{
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
goto loser;
}
SSMDATACONNECTION(conn)->m_dataServiceThread = PR_GetCurrentThread();
/* set up the client data socket and authenticate it with nonce */
rv = SSMDataConnection_SetupClientSocket(SSMDATACONNECTION(conn));
if (rv != PR_SUCCESS) {
goto loser;
}
/* Start decoding */
SSM_DEBUG("Start updating decoder..\n");
while ((SSMRESOURCE(conn)->m_status == PR_SUCCESS) &&
(SSM_Count(SSMDATACONNECTION(conn)->m_shutdownQ) == 0) &&
(rv == PR_SUCCESS)) {
read = LINESIZE; /* set the read size to the default line size */
rv = SSMDataConnection_ReadFromSocket(SSMDATACONNECTION(conn),
(PRInt32*)&read, buffer);
if (read > 0) {
/* there is data, pass it along to PKCS7 */
SSM_DEBUG("Received %ld bytes of data for decoder.\n", read);
PR_ASSERT(conn->m_context);
if (SEC_PKCS7DecoderUpdate(conn->m_context, buffer, read) != SECSuccess) {
conn->m_error = PR_GetError();
goto finish;
}
} else {
/* either EOF or an error condition */
/* If we have a decoder in progress, stop it. */
SSM_LockResource(SSMRESOURCE(conn));
if (conn->m_context) {
SSM_DEBUG("Stopping PKCS7 decoder, generating content info struct.\n");
SSMP7DecodeConnection_FinishDecoding(conn);
}
SSM_UnlockResource(SSMRESOURCE(conn));
break;
}
}
finish:
/* we have an EOF, shut down the client socket */
PR_ASSERT(SSMDATACONNECTION(conn)->m_clientSocket != NULL);
if (SSMDATACONNECTION(conn)->m_clientSocket != NULL) {
SSM_DEBUG("shutting down client socket.\n");
SSM_LockResource(SSMRESOURCE(conn));
PR_Shutdown(SSMDATACONNECTION(conn)->m_clientSocket,
PR_SHUTDOWN_SEND);
SSM_UnlockResource(SSMRESOURCE(conn));
}
/* If we've been asked to return the result, return it. */
if (SSMDATACONNECTION(conn)->m_sendResult) {
SSM_DEBUG("Responding to deferred content info request.\n");
msg = (SECItem*)PORT_ZAlloc(sizeof(SECItem));
PR_ASSERT(msg != NULL); /* need to have some preallocated
failure to send */
if (conn->m_cinfo) {
SSMAttributeValue value;
GetAttribReply reply;
value.type = SSM_RID_ATTRIBUTE;
rv = SSM_ClientGetResourceReference(&conn->m_cinfo->super,
&value.u.rid);
if (rv != PR_SUCCESS) {
goto loser;
}
msg->type = (SECItemType) (SSM_REPLY_OK_MESSAGE | SSM_RESOURCE_ACTION
| SSM_GET_ATTRIBUTE | SSM_RID_ATTRIBUTE);
reply.result = SSM_SUCCESS;
reply.value = value;
if (CMT_EncodeMessage(GetAttribReplyTemplate, (CMTItem*)msg, &reply) != CMTSuccess) {
goto loser;
}
SSM_DEBUG("Generated a reply (t %lx/l %ld/d %lx)\n",
msg->type, msg->len, msg->data);
/*
* We don't need the content info anymore since we sent it back
* Is it OK to release our reference?
*/
SSM_FreeResource(&conn->m_cinfo->super);
conn->m_cinfo = NULL;
}
else {
SingleNumMessage reply;
msg->type = (SECItemType) (SSM_REPLY_ERR_MESSAGE | SSM_RESOURCE_ACTION
| SSM_GET_ATTRIBUTE | SSM_STRING_ATTRIBUTE);
reply.value = SSM_ERR_ATTRIBUTE_MISSING;
if (CMT_EncodeMessage(SingleNumMessageTemplate, (CMTItem*)msg, &reply) != CMTSuccess) {
goto loser;
}
SSM_DEBUG("Generated error reply (t %lx/l %ld/d %lx)\n",
msg->type, msg->len, msg->data);
}
/* Post this message to the parent's control queue
for delivery back to the client. */
ctrl = (SSMControlConnection*)(SSMCONNECTION(conn)->m_parent);
PR_ASSERT(SSM_IsAKindOf(&ctrl->super.super, SSM_RESTYPE_CONTROL_CONNECTION));
rv = SSM_SendQMessage(ctrl->m_controlOutQ,
SSM_PRIORITY_NORMAL,
msg->type, msg->len,
(char*)msg->data, PR_TRUE);
SSM_FreeMessage(msg);
if (rv != PR_SUCCESS) goto loser;
}
loser:
SSM_DEBUG("** Thread shutting down ** (%ld)\n", rv);
if (conn != NULL) {
SSM_ShutdownResource(SSMRESOURCE(conn), rv);
SSM_FreeResource(SSMRESOURCE(conn));
}
}
SSMStatus
SSMP7DecodeConnection_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count)
{
SSMStatus rv;
rv = SSMDataConnection_GetAttrIDs(res, ids, count);
if (rv != PR_SUCCESS)
goto loser;
*ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 1) * sizeof(SSMAttributeID));
if (! *ids) goto loser;
(*ids)[*count++] = SSM_FID_P7CONN_CONTENT_INFO;
goto done;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMP7DecodeConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMStatus rv = PR_SUCCESS;
SSMP7DecodeConnection *dc = (SSMP7DecodeConnection *) res;
SSMP7DecodeConnection_Invariant(dc);
/* see what it is */
switch(attrID)
{
case SSM_FID_P7CONN_CONTENT_INFO:
if (!dc->m_cinfo) {
SSM_LockResource(res);
SSM_WaitResource(res, PR_TicksPerSecond());
SSM_UnlockResource(res);
/*
* If it's still NULL, then something really bad happened.
*/
if (!dc->m_cinfo)
goto loser;
}
/* Allocate a resource ID */
value->type = SSM_RID_ATTRIBUTE;
rv = SSM_ClientGetResourceReference(&dc->m_cinfo->super, &value->u.rid);
if (rv != PR_SUCCESS)
goto loser;
/* Let's get rid of our reference to it and let the client inherit it.
*/
SSM_LockResource(res);
SSM_FreeResource(&dc->m_cinfo->super);
dc->m_cinfo = NULL;
SSM_UnlockResource(res);
break;
case SSM_FID_RESOURCE_ERROR:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = dc->m_error;
break;
default:
rv = SSMDataConnection_GetAttr(res,attrID,attrType,value);
if (rv != PR_SUCCESS)
goto loser;
}
goto done;
loser:
value->type = SSM_NO_ATTRIBUTE;
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
done:
return rv;
}
/* Callback functions for decoder. For now, use empty/default functions. */
void SSMP7DecodeConnection_ContentCallback(void *arg,
const char *buf,
unsigned long len)
{
SSMStatus rv;
SSMP7DecodeConnection *conn = (SSMP7DecodeConnection *)arg;
PRIntn sent = 0;
SSM_DEBUG("writing data to socket.\n");
PR_ASSERT(SSMDATACONNECTION(conn)->m_clientSocket != NULL);
sent = PR_Send(SSMDATACONNECTION(conn)->m_clientSocket, (void*)buf,
(PRIntn)len, 0, PR_INTERVAL_NO_TIMEOUT);
if (sent != (PRIntn)len) {
rv = PR_GetError();
SSM_DEBUG("error writing data: %d \n", rv);
}
}
PK11SymKey * SSMP7DecodeConnection_GetDecryptKey(void *arg,
SECAlgorithmID *algid)
{
return NULL;
}
PRBool SSMP7DecodeConnection_DecryptionAllowed(SECAlgorithmID *algid,
PK11SymKey *bulkkey)
{
return SECMIME_DecryptionAllowed(algid, bulkkey);
}
SECItem * SSMP7DecodeConnection_GetPasswordKey(void *arg,
SECKEYKeyDBHandle *handle)
{
return NULL;
}

View File

@ -0,0 +1,81 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_P7DCONN_H__
#define __SSM_P7DCONN_H__
#include "prerror.h"
#include "secpkcs7.h"
#include "dataconn.h"
#include "p7cinfo.h"
/* Initialization parameters for an SSMP7DecodeConnection. */
typedef struct SSMInfoP7Decode {
SSMControlConnection *ctrl;
CMTItem clientContext;
} SSMInfoP7Decode;
/*
PKCS7 decoder data connections.
*/
typedef struct SSMP7DecodeConnection
{
SSMDataConnection super;
SEC_PKCS7DecoderContext *m_context;
SSMP7ContentInfo *m_cinfo;
PRInt32 m_error;
} SSMP7DecodeConnection;
SSMStatus SSMP7DecodeConnection_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMP7DecodeConnection_Init(SSMP7DecodeConnection *conn,
SSMInfoP7Decode *info,
SSMResourceType type);
SSMStatus SSMP7DecodeConnection_Destroy(SSMResource *res, PRBool doFree);
void SSMP7DecodeConnection_Invariant(SSMP7DecodeConnection *conn);
SSMStatus SSMP7DecodeConnection_Shutdown(SSMResource *arg, SSMStatus status);
SSMStatus SSMP7DecodeConnection_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMP7DecodeConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
#endif

View File

@ -0,0 +1,450 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "p7econn.h"
#include "serv.h"
#include "servimpl.h"
#include "ssmerrs.h"
#include "newproto.h"
#include "messages.h"
#include "collectn.h"
/* Shorthand macros for inherited classes */
#define SSMRESOURCE(conn) (&(conn)->super.super.super)
#define SSMCONNECTION(conn) (&(conn)->super.super)
#define SSMDATACONNECTION(conn) (&(conn)->super)
#define SSM_PARENT_CONN(conn) ((SSMControlConnection*)((conn)->super.super.m_parent))
void SSMP7EncodeConnection_ServiceThread(void * arg);
/* callbacks for PKCS7 encoder */
void SSMP7EncodeConnection_ContentCallback(void *arg,
const char *buf,
unsigned long len);
SECItem * SSMP7EncodeConnection_GetPasswordKey(void *arg,
SECKEYKeyDBHandle *handle);
SSMStatus SSMP7EncodeConnection_Create(void *arg,
SSMControlConnection *connection,
SSMResource **res)
{
SSMStatus rv = PR_SUCCESS;
SSMP7EncodeConnection *conn;
*res = NULL; /* in case we fail */
conn = (SSMP7EncodeConnection *) PR_CALLOC(sizeof(SSMP7EncodeConnection));
if (!conn)
goto loser;
SSMRESOURCE(conn)->m_connection = connection;
rv = SSMP7EncodeConnection_Init(conn, (SSMInfoP7Encode *) arg,
SSM_RESTYPE_PKCS7_ENCODE_CONNECTION);
if (rv != PR_SUCCESS)
goto loser;
SSMP7EncodeConnection_Invariant(conn);
*res = SSMRESOURCE(conn);
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
if (conn) {
SSM_ShutdownResource(SSMRESOURCE(conn), rv); /* force destroy */
SSM_FreeResource(SSMRESOURCE(conn));
}
return rv;
}
SSMStatus SSMP7EncodeConnection_Init(SSMP7EncodeConnection *conn,
SSMInfoP7Encode *info,
SSMResourceType type)
{
SSMStatus rv = PR_SUCCESS;
SSMP7ContentInfo *cinfo;
rv = SSMDataConnection_Init(SSMDATACONNECTION(conn), info->ctrl, type);
if (rv != PR_SUCCESS)
goto loser;
/* Spin the service thread. */
SSM_DEBUG("Creating encoder service thread.\n");
SSM_GetResourceReference(SSMRESOURCE(conn));
rv = SSMControlConnection_GetResource(SSM_PARENT_CONN(conn), info->ciRID,
(SSMResource **)&cinfo);
if (rv != PR_SUCCESS)
goto loser;
conn->m_cinfo = cinfo;
/* Save the client UI context */
SSMRESOURCE(conn)->m_clientContext = info->clientContext;
SSMDATACONNECTION(conn)->m_dataServiceThread =
SSM_CreateThread(SSMRESOURCE(conn),
SSMP7EncodeConnection_ServiceThread);
if (SSMDATACONNECTION(conn)->m_dataServiceThread == NULL) {
goto loser;
}
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
return rv;
}
SSMStatus
SSMP7EncodeConnection_FinishEncoding(SSMP7EncodeConnection *conn)
{
SECStatus rv = SECSuccess;
SSM_LockResource(SSMRESOURCE(conn));
if (conn->m_cinfo) {
SSM_FreeResource(&conn->m_cinfo->super);
conn->m_cinfo = NULL;
}
if (conn->m_context) {
conn->m_retValue = SEC_PKCS7EncoderFinish(conn->m_context,
SSMP7EncodeConnection_GetPasswordKey,
conn);
conn->m_error = PR_GetError();
conn->m_context = NULL;
}
SSM_UnlockResource(SSMRESOURCE(conn));
return rv;
}
SSMStatus
SSMP7EncodeConnection_StartEncoding(SSMP7EncodeConnection *conn)
{
PR_ASSERT(conn->m_context == NULL);
SSM_LockResource(SSMRESOURCE(conn));
if (conn->m_context)
SSMP7EncodeConnection_FinishEncoding(conn);
conn->m_context =
SEC_PKCS7EncoderStart(conn->m_cinfo->m_cinfo,
SSMP7EncodeConnection_ContentCallback,
conn, NULL);
SSM_UnlockResource(SSMRESOURCE(conn));
return PR_SUCCESS;
}
SSMStatus SSMP7EncodeConnection_Destroy(SSMResource *res, PRBool doFree)
{
SSMP7EncodeConnection *conn = (SSMP7EncodeConnection *) res;
if (doFree)
SSM_DEBUG("SSMHashConnection_Destroy called.\n");
/* We should be shut down. */
PR_ASSERT(res->m_threadCount == 0);
/* Destroy our fields. */
SSM_LockResource(SSMRESOURCE(conn));
if (conn->m_context)
SSMP7EncodeConnection_FinishEncoding(conn);
if (conn->m_cinfo) {
SSM_FreeResource(&conn->m_cinfo->super);
conn->m_cinfo = NULL;
}
SSM_UnlockResource(SSMRESOURCE(conn));
/* Destroy superclass fields. */
SSMDataConnection_Destroy(SSMRESOURCE(conn), PR_FALSE);
/* Free the connection object if asked. */
if (doFree)
PR_DELETE(conn);
return PR_SUCCESS;
}
void
SSMP7EncodeConnection_Invariant(SSMP7EncodeConnection *conn)
{
SSMDataConnection_Invariant(SSMDATACONNECTION(conn));
/* our specific invariants */
SSM_LockResource(SSMRESOURCE(conn));
/* check class */
PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(conn),
SSM_RESTYPE_PKCS7_ENCODE_CONNECTION));
/* we should not be simultaneously encoded and encoding */
if (conn->m_context)
PR_ASSERT(conn->m_cinfo != NULL);
SSM_UnlockResource(SSMRESOURCE(conn));
}
SSMStatus
SSMP7EncodeConnection_Shutdown(SSMResource *arg, SSMStatus status)
{
SSMStatus rv = SSM_SUCCESS;
/* Call our superclass shutdown. */
rv = SSMDataConnection_Shutdown(arg, status);
return rv;
}
/*
PKCS7 decoding is performed by a single service thread. This thread
feeds data from the outgoing queue into the PKCS7 encoder.
*/
void SSMP7EncodeConnection_ServiceThread(void * arg)
{
SSMStatus rv = PR_SUCCESS;
SSMP7EncodeConnection * conn;
SSMControlConnection *ctrl;
SECItem *msg;
PRIntn read;
char buffer[LINESIZE+1] = {0};
SSM_RegisterNewThread("p7encode", (SSMResource *) arg);
conn = (SSMP7EncodeConnection *)arg;
SSM_DEBUG("initializing.\n");
if (!arg) {
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
goto loser;
}
SSMDATACONNECTION(conn)->m_dataServiceThread = PR_GetCurrentThread();
/* set up the client data socket and authenticate it with nonce */
rv = SSMDataConnection_SetupClientSocket(SSMDATACONNECTION(conn));
if (rv != PR_SUCCESS) {
goto loser;
}
/* Start encoding */
SSM_DEBUG("Creating encoder.\n");
SSMP7EncodeConnection_StartEncoding(conn);
while ((SSMRESOURCE(conn)->m_status == PR_SUCCESS) &&
(SSM_Count(SSMDATACONNECTION(conn)->m_shutdownQ) == 0) &&
(rv == PR_SUCCESS)) {
read = LINESIZE; /* set the read size to the default line size */
rv = SSMDataConnection_ReadFromSocket(SSMDATACONNECTION(conn),
(PRInt32*)&read, buffer);
if (read > 0) {
/* there is data, pass it along to PKCS7 */
SSM_DEBUG("Received %ld bytes of data for encoder.\n", read);
PR_ASSERT(conn->m_context);
SEC_PKCS7EncoderUpdate(conn->m_context, buffer, read);
}
else {
/* either EOF or an error condition */
goto finish;
}
}
finish:
SSM_DEBUG("Stopping PKCS7 encoder.\n");
/* If we have a encoder in progress, stop it. */
SSM_LockResource(SSMRESOURCE(conn));
if (conn->m_context) {
SSMP7EncodeConnection_FinishEncoding(conn);
}
SSM_UnlockResource(SSMRESOURCE(conn));
if (rv == PR_SUCCESS) {
/* we have an EOF, shut down the client socket. */
PR_ASSERT(SSMDATACONNECTION(conn)->m_clientSocket != NULL);
if (SSMDATACONNECTION(conn)->m_clientSocket != NULL) {
SSM_DEBUG("shutting down client socket.\n");
SSM_LockResource(SSMRESOURCE(conn));
PR_Shutdown(SSMDATACONNECTION(conn)->m_clientSocket,
PR_SHUTDOWN_SEND);
SSM_UnlockResource(SSMRESOURCE(conn));
}
}
/* If we've been asked to return the result, return it. */
if (SSMDATACONNECTION(conn)->m_sendResult) {
SSM_DEBUG("Responding to deferred content info request.\n");
msg = (SECItem*)PORT_ZAlloc(sizeof(SECItem));
PR_ASSERT(msg != NULL); /* need to have some preallocated
failure to send */
if (conn->m_cinfo) {
SSMAttributeValue value;
GetAttribReply reply;
value.type = SSM_RID_ATTRIBUTE;
rv = SSM_ClientGetResourceReference(&conn->m_cinfo->super,
&value.u.rid);
if (rv != PR_SUCCESS) {
goto loser;
}
msg->type = (SECItemType) (SSM_REPLY_OK_MESSAGE | SSM_RESOURCE_ACTION
| SSM_GET_ATTRIBUTE | SSM_RID_ATTRIBUTE);
reply.value = value;
reply.result = SSM_SUCCESS;
if (CMT_EncodeMessage(GetAttribReplyTemplate, (CMTItem*)msg, &reply) != CMTSuccess) {
goto loser;
}
SSM_DEBUG("Generated a reply (t %lx/l %ld/d %lx)\n",
msg->type, msg->len, msg->data);
} else {
SingleNumMessage reply;
msg->type = (SECItemType) (SSM_REPLY_ERR_MESSAGE | SSM_RESOURCE_ACTION
| SSM_GET_ATTRIBUTE | SSM_STRING_ATTRIBUTE);
reply.value = SSM_ERR_ATTRIBUTE_MISSING;
if (CMT_EncodeMessage(SingleNumMessageTemplate, (CMTItem*)msg, &reply) != CMTSuccess) {
goto loser;
}
SSM_DEBUG("Generated error reply (t %lx/l %ld/d %lx)\n",
msg->type, msg->len, msg->data);
}
/* Post this message to the parent's control queue
for delivery back to the client. */
ctrl = (SSMControlConnection*)(SSMCONNECTION(conn)->m_parent);
PR_ASSERT(SSM_IsAKindOf(&ctrl->super.super,
SSM_RESTYPE_CONTROL_CONNECTION));
rv = SSM_SendQMessage(ctrl->m_controlOutQ,
SSM_PRIORITY_NORMAL,
msg->type, msg->len,
(char*)msg->data, PR_TRUE);
SSM_FreeMessage(msg);
if (rv != PR_SUCCESS)
goto loser;
}
loser:
SSM_DEBUG("** Thread shutting down ** (%ld)\n", rv);
if (conn != NULL) {
SSM_ShutdownResource(SSMRESOURCE(conn), rv);
SSM_FreeResource(SSMRESOURCE(conn));
}
}
/* Callback functions for encoder. For now, use empty/default functions. */
void SSMP7EncodeConnection_ContentCallback(void *arg,
const char *buf,
unsigned long len)
{
SSMStatus rv;
SSMP7EncodeConnection *conn = (SSMP7EncodeConnection *)arg;
PRIntn sent = 0;
if (len == 0)
return;
SSM_DEBUG("writing data to socket.\n");
PR_ASSERT(SSMDATACONNECTION(conn)->m_clientSocket != NULL);
sent = PR_Send(SSMDATACONNECTION(conn)->m_clientSocket, (void*)buf,
(PRIntn)len, 0, PR_INTERVAL_NO_TIMEOUT);
if (sent != (PRIntn)len) {
rv = PR_GetError();
SSM_DEBUG("error writing data: %d \n", rv);
}
}
SECItem * SSMP7EncodeConnection_GetPasswordKey(void *arg,
SECKEYKeyDBHandle *handle)
{
return NULL;
}
SSMStatus SSMP7EncodeConnection_SetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value)
{
switch(attrID) {
case SSM_FID_CLIENT_CONTEXT:
SSM_DEBUG("Setting PKCS7 Encode client context\n");
if (value->type != SSM_STRING_ATTRIBUTE) {
goto loser;
}
if (!(res->m_clientContext.data = (unsigned char *) PR_Malloc(value->u.string.len))) {
goto loser;
}
memcpy(res->m_clientContext.data, value->u.string.data, value->u.string.len);
res->m_clientContext.len = value->u.string.len;
break;
default:
SSM_DEBUG("Got unknown P7 Encoder Set Attribute Request %d\n", attrID);
goto loser;
break;
}
return PR_SUCCESS;
loser:
return PR_FAILURE;
}
SSMStatus SSMP7EncodeConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMP7EncodeConnection *ec = (SSMP7EncodeConnection*)res;
SSMP7EncodeConnection_Invariant(ec);
switch (attrID) {
case SSM_FID_P7CONN_RETURN_VALUE:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = ec->m_retValue;
break;
case SSM_FID_P7CONN_ERROR_VALUE:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = ec->m_error;
break;
default:
SSM_DEBUG("Got unknown P7 Encoder Set Attribute Request %d\n", attrID);
goto loser;
break;
}
return PR_SUCCESS;
loser:
return PR_FAILURE;
}

View File

@ -0,0 +1,87 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_P7ECONN_H__
#define __SSM_P7ECONN_H__
#include "prerror.h"
#include "secpkcs7.h"
#include "dataconn.h"
#include "p7cinfo.h"
/*
PKCS7 encoder data connections.
*/
/* Initialization parameters for an SSMP7EncodeConnection. */
typedef struct SSMInfoP7Encode {
SSMControlConnection *ctrl;
SSMResourceID ciRID;
CMTItem clientContext;
} SSMInfoP7Encode;
typedef struct SSMP7EncodeConnection {
SSMDataConnection super;
SEC_PKCS7EncoderContext *m_context;
SSMP7ContentInfo *m_cinfo;
PRInt32 m_retValue;
PRInt32 m_error;
} SSMP7EncodeConnection;
SSMStatus SSMP7EncodeConnection_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMP7EncodeConnection_Init(SSMP7EncodeConnection *conn,
SSMInfoP7Encode *info,
SSMResourceType type);
SSMStatus SSMP7EncodeConnection_Destroy(SSMResource *res, PRBool doFree);
void SSMP7EncodeConnection_Invariant(SSMP7EncodeConnection *conn);
SSMStatus SSMP7EncodeConnection_Shutdown(SSMResource *arg, SSMStatus status);
SSMStatus SSMP7EncodeConnection_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMP7EncodeConnection_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMP7EncodeConnection_SetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value);
#endif /* __SSM_P7ECONN_H__ */

View File

@ -0,0 +1,947 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "connect.h"
#include "ssmerrs.h"
#include "ctrlconn.h"
#include "prinrval.h"
#include "crmf.h"
#include "newproto.h"
#include "messages.h"
#include "minihttp.h"
#include "textgen.h"
#include "sechash.h"
#include "pk11func.h"
extern SSMHashTable * tokenList;
extern PRMonitor * tokenLock;
#define SSMRESOURCE(conn) (&(conn)->super)
/* Make these into functions? */
#if 0
#define SSM_PARENT_CONN(x) ((((SSMConnection *)(x))->m_parent) != NULL)? \
(((SSMControlConnection *)(((SSMConnection *)(x))->m_parent))):\
((SSMControlConnection *)x)
#define SSM_PWD_TABLE(x) (SSM_PARENT_CONN(x))->m_passwdTable
#define SSM_OUT_QUEUE(x) (SSM_PARENT_CONN(x))->m_controlOutQ
#endif
#if 1
SSMControlConnection * SSM_PARENT_CONN (SSMConnection * x)
{
return (((((SSMConnection *)(x))->m_parent) != NULL)?
(((SSMControlConnection *)(((SSMConnection *)(x))->m_parent))):
((SSMControlConnection *)x));
}
SSMHashTable * SSM_PWD_TABLE(SSMConnection * x)
{
return (SSM_PARENT_CONN(x)->m_passwdTable);
}
SSMCollection * SSM_OUT_QUEUE(SSMConnection * x)
{
return (SSM_PARENT_CONN(x)->m_controlOutQ);
}
#endif
PRInt32 SSM_GetTokenKey(PK11SlotInfo * slot)
{
return ((PK11_GetSlotID(slot)<<16) | PK11_GetModuleID(slot));
}
char * SSM_GetPasswdCallback(PK11SlotInfo *slot, PRBool retry, void *arg)
{
return SSM_GetAuthentication(slot, retry, PR_FALSE, (SSMResource*)arg);
}
/* Do a couple of things in this functions:
* 1) Get a password from user, and authenticate to token.
* 2) Save this password encrypted in the global Cartman tokenList
* for future reference.
* Need to save password in case other users will need to authenticate
* to the same tokens, so we make sure they're using the correct
* passwords.
* 3) Save this password encrypted in the control connection table in
* case we will need to use it again.
*/
char * SSM_GetAuthentication(PK11SlotInfo * slot, PRBool retry, PRBool init,
SSMResource * res)
{
PRInt32 tokenKey;
SSMStatus rv = PR_SUCCESS;
char * passwd = NULL, * tmp = NULL;
PRBool first = PR_FALSE;
SSM_TokenInfo * info = NULL, * infoLocal = NULL;
SSMConnection *conn = &(res->m_connection->super);
tokenKey = SSM_GetTokenKey(slot);
/* register as interested in a password */
SSM_PARENT_CONN(conn)->m_waiting++;
/* Get passwd table lock. */
SSM_LockPasswdTable(conn);
/* Look for entry for moduleID/slotID. */
rv = SSM_HashFind(SSM_PWD_TABLE(conn), tokenKey, (void **)&passwd);
SSM_UnlockPasswdTable(conn);
if (rv != PR_SUCCESS) {
first = PR_TRUE;
/* no entry found, we are the first to authenticate to this slot */
SSM_DEBUG("%ld: creating passwd table entry for %s \n",
conn, PK11_GetSlotName(slot));
SSM_LockPasswdTable(conn);
rv = SSM_HashInsert(SSM_PWD_TABLE(conn),tokenKey,(void *)SSM_NO_PASSWORD);
SSM_UnlockPasswdTable(conn);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: could not create entry in password table\n", conn);
goto loser;
}
rv = SSM_AskUserPassword(res, slot, retry, init);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: error sending password request event\n", conn);
goto loser;
}
} /* end of the we-are-first-to-request-this-passwd-clause */
/* If no password found, wait for it */
if (!passwd || passwd == (char *)SSM_NO_PASSWORD) {
rv = SSMControlConnection_WaitPassword(conn, tokenKey, &passwd);
if (rv != PR_SUCCESS)
goto loser;
}
if (((int) passwd) == SSM_CANCEL_PASSWORD) {
/* no password was provided or user hit "Cancel" */
SSM_LockPasswdTable(conn);
rv = SSM_HashRemove(SSM_PWD_TABLE(conn), tokenKey, (void **)&passwd);
SSM_UnlockPasswdTable(conn);
if (rv != SSM_SUCCESS)
SSM_DEBUG("SSM_GetAuthentication: user hit Cancel, can't remove password from connection table\n");
passwd = NULL;
goto done;
}
if (first) {
/* We were the first to request the password,
* so we need to enter it in to the token list.
*/
/* encrypt the password */
if (SSM_EncryptPasswd(slot, passwd, &info) != SSM_SUCCESS) {
SSM_DEBUG("%ld: could not encrypt password\n.", conn);
goto loser;
}
/* Place encrypted passwd in Cartman-wide tokenList */
PR_EnterMonitor(tokenLock);
/* Remove from tokenList if already on the list - must be stale */
rv = SSM_HashRemove(tokenList, tokenKey, (void **)&tmp);
if (rv == SSM_SUCCESS && tmp && tmp != (char *)SSM_NO_PASSWORD
&& tmp != (char *)SSM_CANCEL_PASSWORD) { /* free stale data */
PR_Free(tmp);
tmp = NULL;
}
rv = SSM_HashInsert(tokenList, tokenKey, info);
PR_ExitMonitor(tokenLock);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: can't create encr passwd entry\n", conn, tokenKey);
goto loser;
}
/* Store encrypted password in control connection table */
infoLocal = (SSM_TokenInfo *) PORT_ZAlloc(sizeof(SSM_TokenInfo));
if (!infoLocal)
goto loser;
infoLocal->slot = info->slot;
infoLocal->tokenID = info->tokenID;
infoLocal->encryptedLen = info->encryptedLen;
infoLocal->symKey = info->symKey;
infoLocal->encrypted = (char *) PORT_ZAlloc(info->encryptedLen);
if (!infoLocal->encrypted)
goto loser;
memcpy(infoLocal->encrypted, info->encrypted, info->encryptedLen);
PR_EnterMonitor(SSM_PARENT_CONN(conn)->m_encrPasswdLock);
rv = SSM_HashRemove(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
(void **)&tmp);
if (rv == SSM_SUCCESS && tmp && tmp != (char *)SSM_NO_PASSWORD &&
tmp != (char *)SSM_CANCEL_PASSWORD ) {/* free stale data */
PR_Free(tmp);
tmp = NULL;
}
rv = SSM_HashInsert(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
infoLocal);
PR_ExitMonitor(SSM_PARENT_CONN(conn)->m_encrPasswdLock);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: cannot insert token %d entry in encrPasswdTable\n",
conn, tokenKey);
goto loser;
}
SSM_DEBUG("%ld: wait untill others are done with passwd, remove it\n",
conn);
/* while ((SSM_PARENT_CONN(conn))->m_waiting > 1)
* PR_Sleep(SSM_PASSWORD_WAIT_TIME);
*/
SSM_LockPasswdTable(conn);
rv = SSM_HashRemove(SSM_PWD_TABLE(conn), tokenKey, (void **)&passwd);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: could not remove passwd.\n", conn);
goto loser;
}
SSM_UnlockPasswdTable(conn);
} /* end of if-first clause */
goto done;
loser:
/* cleanup */
PR_FREEIF(passwd);
passwd = NULL;
if (info) {
PR_FREEIF(info->encrypted);
PR_Free(info);
}
if (infoLocal) {
PR_FREEIF(infoLocal->encrypted);
PR_Free(infoLocal);
}
done:
/* We are done receiving passwd */
(SSM_PARENT_CONN(conn))->m_waiting--;
return passwd ? strdup (passwd) : NULL;
}
/*
* We get this callback if the slot is already logged-in.
* Need to check client-supplied password against the password stored in
* tokenList.
*/
PRBool SSM_VerifyPasswdCallback(PK11SlotInfo * slot, void * arg)
{
char * passwd = NULL;
PRInt32 tokenKey;
SSM_TokenInfo * info = NULL;
SSM_TokenInfo * tokenInfo = NULL;
SSMStatus rv;
PRBool result = PR_FALSE;
SSMResource * res = (SSMResource*)arg;
SSMConnection * conn = &(res->m_connection->super);
PRInt32 doTry = 0;
void * tmp = NULL;
if (!slot || !arg)
goto loser;
tokenKey = PK11_GetSlotID(slot) ^ PK11_GetModuleID(slot);
info = (SSM_TokenInfo *) PORT_ZAlloc(sizeof(SSM_TokenInfo));
if (!info) {
SSM_DEBUG("Could not allocate memory in VerifyPasswdCallback.\n");
goto loser;
}
/* Get the password for this token.
* We might have to find it in the local encrypted password table or
* to request it from the client.
*/
rv = SSM_HashFind(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
(void **)&info);
if (rv != PR_SUCCESS || info == (void *)SSM_NO_PASSWORD) {
askpassword:
/* ask user for a password and store it in local passwd table */
rv = SSM_AskUserPassword(res, slot, doTry?PR_TRUE:PR_FALSE, PR_FALSE);
if (rv != PR_SUCCESS)
goto loser;
doTry++;
rv = SSMControlConnection_WaitPassword(conn, tokenKey, &passwd);
if (rv != PR_SUCCESS || !passwd)
goto loser;
rv = SSM_EncryptPasswd(slot, passwd, &info);
if (rv != SSM_SUCCESS)
goto loser;
} /* end of no password, ask user */
/* Now get the stored password for this token */
if (!tokenInfo) {
PR_EnterMonitor(tokenLock);
rv = SSM_HashFind(tokenList, tokenKey, (void **)&tokenInfo);
PR_ExitMonitor(tokenLock);
if (rv != PR_SUCCESS || !tokenInfo) {
SSM_DEBUG("Can't find token info in VerifyPasswd.\n");
goto loser;
}
}
/* Check password against tokenList entry */
if (memcmp(tokenInfo->encrypted, info->encrypted, tokenInfo->encryptedLen)
!= 0 || tokenInfo->encryptedLen != info->encryptedLen) {
/* Failed compare, bad password */
/* first clean up */
if (info) PR_Free(info);
info = NULL;
/* If not retry, ask client for password. */
if (doTry < 2 ) {
/* ask user again */
PR_Free(passwd);
passwd = NULL;
goto askpassword;
}
else
goto loser;
} /* end of password not verified */
SSM_DEBUG("Password verified OK.\n");
/* store password for local use */
PR_EnterMonitor(SSM_PARENT_CONN(conn)->m_encrPasswdLock);
SSM_HashRemove(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
(void **)&tmp);
if (tmp && tmp != (char *)SSM_NO_PASSWORD ) {/* free stale data */
PR_Free(tmp);
tmp = NULL;
}
rv = SSM_HashInsert(SSM_PARENT_CONN(conn)->m_encrPasswdTable, tokenKey,
info);
PR_ExitMonitor(SSM_PARENT_CONN(conn)->m_encrPasswdLock);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: cannot insert token %d entry in encrPasswdTable\n",
conn, tokenKey);
goto loser;
}
result = PR_TRUE;
goto done;
loser:
SSM_DEBUG("Password not verified. \n");
/* log out this slot?? */
if (info) {
if (info->encrypted)
PR_Free(info->encrypted);
PR_Free(info);
}
result = PR_FALSE;
done:
if (passwd)
PR_Free(passwd);
return result;
}
/* Encrypt password for storage */
#define SSM_PAD_BLOCK_SIZE(x, y) ((((x) + ((y)-1))/(y))*(y))
SSMStatus SSM_EncryptPasswd(PK11SlotInfo * slot, char * passwd,
SSM_TokenInfo ** tokenInfo)
{
int resultLen;
char *hashResult = NULL;
SSMStatus rv = SSM_SUCCESS;
SECStatus srv;
SSM_TokenInfo * info;
/* Hash the password. */
resultLen = HASH_ResultLen(HASH_AlgSHA1);
hashResult = (char *) PORT_ZAlloc(resultLen); /* because the original PORT_ZAlloc'd */
if (!hashResult)
goto loser;
srv = HASH_HashBuf(HASH_AlgSHA1, (unsigned char *) hashResult, (unsigned char *) passwd, strlen(passwd));
if (srv != SECSuccess)
goto loser;
/* fill in the tokenInfo structure */
info = (SSM_TokenInfo *) PORT_ZAlloc(sizeof(SSM_TokenInfo));
if (!info) {
SSM_DEBUG("EncryptPwd: could not allocate memory to token list entry.\n");
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
goto loser;
}
info->encrypted = hashResult;
info->encryptedLen = resultLen;
info->slot = slot;
info->tokenID = SSM_GetTokenKey(slot);
*tokenInfo = info;
goto done;
loser:
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
PR_FREEIF(hashResult);
done:
return rv;
}
SSMStatus SSM_NotEncryptPasswd(PK11SlotInfo * slot, char * passwd,
SSM_TokenInfo * info)
{
CK_MECHANISM_TYPE mechanism;
/* CK_SESSION_HANDLE session = CK_INVALID_SESSION; */
PRInt32 keyLength, blockSize, outlen;
PRUint32 encryptedLength;
PK11SymKey * symKey;
SECStatus rv;
char * encrypted = NULL;
PK11Context * context=NULL;
SECItem *params;
if (!slot || !passwd || !info) {
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
goto loser;
}
mechanism = CRMF_GetBestWrapPadMechanism(slot);
keyLength = PK11_GetBestKeyLength(slot, mechanism);
/* session = PK11_GetRWSession(slot);
if (session == CK_INVALID_SESSION)
goto loser;*/
blockSize = PK11_GetBlockSize(mechanism, NULL);
/*
* A password is encrypted when we first authenticate to token.
* In this case, generate a symmetric Key on the slot.
* If the key is already present, it means that the password for this
* slot has already been encrypted and stored, need to encrypt
* new password with the same key to compare against the stored
* password.
*/
/* If no symKey found, generate one */
if (!info->symKey) {
symKey = PK11_KeyGen(slot, mechanism, NULL, keyLength, NULL);
if (!symKey) {
SSM_DEBUG("Failed to generate symKey to encrypt passwd.\n");
goto loser;
}
} else
symKey = info->symKey;
encryptedLength = SSM_PAD_BLOCK_SIZE(strlen(passwd)+1, blockSize);
encrypted = (char *) PORT_ZAlloc(encryptedLength);
if (!encrypted) {
SSM_DEBUG("Could not allocate space for encrypted password. \n");
goto loser;
}
params = CRMF_GetIVFromMechanism(mechanism);
context=PK11_CreateContextBySymKey(mechanism, CKA_ENCRYPT,
symKey, params);
if (params != NULL) {
SECITEM_FreeItem(params, PR_TRUE);
}
if (!context) {
SSM_DEBUG("Can't create context to encrypt password: %d.\n",
PR_GetError());
goto loser;
}
rv = PK11_CipherOp(context, (unsigned char *) encrypted, &outlen,
(int) encryptedLength,
(unsigned char *) passwd, strlen(passwd));
if (rv != PR_SUCCESS) {
SSM_DEBUG("Error encrypting password: %d\n", PR_GetError());
goto loser;
}
rv = PK11_DigestFinal(context, (unsigned char *) &encrypted[outlen],
(unsigned int *) &outlen, (unsigned int) blockSize);
if (rv != PR_SUCCESS) {
SSM_DEBUG("Error encrypting password: %d\n", PR_GetError());
goto loser;
}
PK11_DestroyContext(context, PR_TRUE);
/*if (session != CK_INVALID_SESSION)
PK11_RestoreROSession(slot, session);*/
/* fill in the tokenInfo structure */
info->encrypted = encrypted;
info->encryptedLen = encryptedLength;
info->slot = slot;
return SSM_SUCCESS;
loser:
SSM_DEBUG("Failed to encrypt password.\n");
if (context != NULL)
PK11_DestroyContext(context, PR_TRUE);
/*if (session != CK_INVALID_SESSION)
PK11_RestoreROSession(slot, session);*/
if (encrypted && *encrypted)
PR_Free(encrypted);
return SSM_FAILURE;
}
/* Needs to be fixed using NLS lib and proper string storage. -jane */
char * SSM_GetPrompt(PK11SlotInfo *slot, PRBool retry, PRBool init)
{
char * prompt = NULL, * tmp = NULL, * key;
SSMTextGenContext * cx;
SSMStatus rv;
PR_ASSERT(init != PR_TRUE);
rv = SSMTextGen_NewTopLevelContext(NULL, &cx);
if (rv != SSM_SUCCESS || !cx)
goto loser;
if (retry)
key = "retry_token_password";
else
key = "ask_token_password";
rv = SSM_GetAndExpandTextKeyedByString(cx, key, &tmp);
if (rv != SSM_SUCCESS || !tmp)
goto loser;
prompt = PR_smprintf(tmp, PK11_GetTokenName(slot));
loser:
PR_FREEIF(tmp);
return prompt;
}
/* Send a password request for the client */
SSMStatus SSM_AskUserPassword(SSMResource * res,
PK11SlotInfo * slot, PRInt32 retry, PRBool init)
{
SECItem message;
char * prompt = NULL;
PRInt32 tokenKey = SSM_GetTokenKey(slot);
SSMStatus rv = PR_FAILURE;
SSMConnection *conn = (SSMConnection *)res->m_connection;
PasswordRequest request;
prompt = SSM_GetPrompt(slot, retry, init);
retry++;
if (!prompt) {
SSM_DEBUG("%ld: error getting prompt for password request.\n", conn);
goto loser;
}
request.tokenKey = tokenKey;
request.prompt = prompt;
request.clientContext = res->m_clientContext;
if (CMT_EncodeMessage(PasswordRequestTemplate, (CMTItem*)&message, &request) != CMTSuccess) {
goto loser;
}
if (message.len == 0 || !message.data) {
SSM_DEBUG("%ld: could not create password request message.\n", conn);
goto loser;
}
message.type = (SECItemType) (SSM_EVENT_MESSAGE | SSM_AUTH_EVENT);
rv = SSM_SendQMessage(SSM_OUT_QUEUE(conn), SSM_PRIORITY_UI, message.type,
message.len, (char *)message.data, PR_TRUE);
if (rv != PR_SUCCESS) {
SSM_DEBUG("%ld: Can't enqueue password request. \n", conn);
goto loser;
}
loser:
if (prompt)
PR_Free(prompt);
if (message.data)
PR_Free(message.data);
return rv;
}
SSMStatus SSMControlConnection_WaitPassword(SSMConnection * conn,
PRInt32 key, char ** str)
{
char * passwd;
PRIntervalTime before;
SSMStatus rv = PR_FAILURE;
*str = NULL;
/* Wait no longer than our time-out period. */
before = PR_IntervalNow();
SSM_LockPasswdTable(conn);
wait:
SSM_DEBUG("%ld : waiting on password table for the password\n", conn);
SSM_WaitPasswdTable(conn);
/* Returned from wait.
* Look for password.
*/
rv = SSM_HashFind(SSM_PWD_TABLE(conn), key, (void **)&passwd);
if (rv!=PR_SUCCESS || !passwd || passwd ==(char *)SSM_NO_PASSWORD) {
/* password not found, check for timeout */
if (PR_IntervalNow() - before > SSM_PASSWORD_WAIT_TIME) {
SSM_DEBUG("%ld:Timed out waiting for password.Bailing out.\n",
conn);
SSM_UnlockPasswdTable(conn);
return PR_FAILURE;
}
else
goto wait; /* continue waiting */
} /* end of no password found */
SSM_UnlockPasswdTable(conn);
*str = passwd;
return rv;
}
extern PK11SlotListElement *
PK11_GetNextSafe(PK11SlotList * list, PK11SlotListElement * element,PRBool start);
PK11SlotListElement *
ssm_GetSlotWithPwd(PK11SlotList * slotlist, PK11SlotListElement * current,
PRBool start)
{
PK11SlotListElement * next = NULL;
PR_ASSERT(slotlist);
if (!current || start)
next = PK11_GetFirstSafe(slotlist);
else
next = PK11_GetNextSafe(slotlist, current, PR_FALSE);
while (next && PK11_NeedUserInit(next->slot) && !PK11_NeedLogin(next->slot))
next = PK11_GetNextSafe(slotlist, next, PR_FALSE);
return next;
}
PRIntn
ssm_NumSlotsWithPassword(PK11SlotList * slotList)
{
PRIntn numslots = 0;
PK11SlotListElement * element = PK11_GetFirstSafe(slotList);
while (element) {
if (PK11_NeedLogin(element->slot) || !PK11_NeedUserInit(element->slot))
numslots++;
element = PK11_GetNextSafe(slotList, element,PR_FALSE);
}
return numslots;
}
SSMStatus SSM_ReSetPasswordKeywordHandler(SSMTextGenContext * cx)
{
char * slotname = NULL;
PK11SlotInfo * slot;
char * tmp = NULL;
SSMStatus rv;
SSMResource * target = cx->m_request->target;
PK11SlotList * slotList = NULL;
PK11SlotListElement * el = NULL;
PR_ASSERT(cx != NULL);
PR_ASSERT(cx->m_request != NULL);
PR_ASSERT(&cx->m_result != NULL);
rv = SSM_HTTPParamValue(cx->m_request, "action", &slotname);
if (!slotname || strcmp(slotname, "")== 0)
slot = PK11_GetInternalKeySlot();
else if (strcmp(slotname, "all") == 0) {
/* ask user */
slotList = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_TRUE, PR_TRUE, target);
if (!slotList || !slotList->head)
goto loser;
if (ssm_NumSlotsWithPassword(slotList)>1) {
char * mech = PR_smprintf("mech=%d&unused1=unused1&unused2=unused2",CKM_INVALID_MECHANISM);
SSM_LockUIEvent(target);
rv = SSMControlConnection_SendUIEvent(cx->m_request->ctrlconn,
"get", "select_token",
target,mech,&target->m_clientContext);
SSM_WaitUIEvent(target, PR_INTERVAL_NO_TIMEOUT);
slot = (PK11SlotInfo *) target->m_uiData;
if (!slot)
goto cancel;
} else {
/* only one interesting slot in the list */
el = ssm_GetSlotWithPwd(slotList, NULL, PR_TRUE);
slot = el->slot;
}
}
else
slot = PK11_FindSlotByName(slotname);
if (!slot) {
SSM_DEBUG("ReSetPasswordKeywordHandler: bad slotname %s\n", slotname);
goto loser;
}
slotname = PK11_GetTokenName(slot);
if (PK11_NeedPWInitForSlot(slot))
rv = SSM_GetAndExpandTextKeyedByString(cx, "set_new_password", &tmp);
else
rv = SSM_GetAndExpandTextKeyedByString(cx, "reset_password", &tmp);
if (rv != SSM_SUCCESS)
goto loser;
PR_FREEIF(cx->m_result);
cx->m_result = PR_smprintf(tmp, slotname);
return rv;
loser:
if (cx->m_result)
PR_Free(cx->m_result);
cx->m_result = NULL;
return PR_FAILURE;
cancel:
SSM_HTTPCloseWindow(cx->m_request);
goto loser;
}
PRBool
ssm_VerifyPwdLength(char * password)
{
if (!password)
return (!SSM_MIN_PWD_LEN);
if (strlen(password) < SSM_MIN_PWD_LEN)
return PR_FALSE;
if (strlen(password) > SSM_MAX_PWD_LEN)
return PR_FALSE;
return PR_TRUE;
}
SSMStatus SSM_PasswordPrefKeywordHandler(SSMTextGenContext * cx)
{
char * fmt = NULL, * checked = NULL;
char * markchecked[] = { "", "", ""};
SSMStatus rv;
PRIntn askpw, timeout;
PR_ASSERT(cx != NULL);
PR_ASSERT(cx->m_request != NULL);
PR_ASSERT(cx->m_result != NULL);
/* need to get the table and fill it with current preferences */
rv = SSM_GetAndExpandTextKeyedByString(cx, "password_lifetime", &fmt);
if (rv != SSM_SUCCESS || !fmt)
goto done;
rv = SSM_GetAndExpandTextKeyedByString(cx, "text_checked", &checked);
if (rv != SSM_SUCCESS || !checked)
goto done;
rv = PREF_GetIntPref(cx->m_request->ctrlconn->m_prefs,
"security.ask_for_password", &askpw);
if (rv != SSM_SUCCESS)
goto done;
rv = PREF_GetIntPref(cx->m_request->ctrlconn->m_prefs,
"security.password_lifetime", &timeout);
if (rv != SSM_SUCCESS)
goto done;
markchecked[askpw] = checked;
PR_FREEIF(cx->m_result);
cx->m_result = PR_smprintf(fmt, markchecked[0], markchecked[1],
markchecked[2], timeout);
done:
return rv;
}
SSMStatus SSM_SetDBPasswordHandler(HTTPRequest * req)
{
SSMStatus rv = SSM_FAILURE;
char * oldpassword, * newpassword, *repeatpassword, * action;
PK11SlotInfo * slot;
char * responseKey = NULL;
char * result = NULL;
char * slotname = NULL, * askpwdoption, * pwdlifetime;
PRIntn askpw, timeout;
rv = SSM_HTTPParamValue(req, "baseRef", &action);
if (rv != SSM_SUCCESS || strcmp(action, "windowclose_doclose_js")!= 0)
SSM_DEBUG("SetDBPasswordHandler: bad action %s\n", action);
rv = SSM_HTTPParamValue(req, "slot", &slotname);
if (rv != SSM_SUCCESS || !slotname ||
!(slot = PK11_FindSlotByName(slotname)))
goto loser;
/* process password preferences */
rv = SSM_HTTPParamValue(req, "passwordlife", &askpwdoption);
if (rv != SSM_SUCCESS || !askpwdoption)
goto loser;
rv = SSM_HTTPParamValue(req, "passwordwillexpire", &pwdlifetime);
if (rv != SSM_SUCCESS || !pwdlifetime)
goto loser;
if (strcmp(askpwdoption, "firsttime") == 0)
askpw = 0;
else if (strcmp(askpwdoption, "everytime") == 0)
askpw = 1;
else if (strcmp(askpwdoption, "expiretime")==0) {
askpw = 2;
}
else {
SSM_DEBUG("SetDBPasswordHandler: bad password lifetime parameter %s\n",
askpwdoption);
goto loser;
}
timeout = atoi(pwdlifetime);
if (askpw == 2 && !timeout)
goto loser;
PK11_SetSlotPWValues(slot, askpw, timeout);
rv = SSMControlConnection_SaveIntPref(req->ctrlconn,
"security.ask_for_password", askpw);
if (rv != PR_SUCCESS)
goto loser;
rv = SSMControlConnection_SaveIntPref(req->ctrlconn,
"security.password_lifetime", timeout);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_HTTPParamValue(req, "newpassword", &newpassword);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_HTTPParamValue(req, "repeatpassword", &repeatpassword);
if (rv != SSM_SUCCESS)
goto loser;
if (!PK11_NeedPWInitForSlot(slot)) {
/* oldpassword doesn't make sense for password initialization dialog */
rv = SSM_HTTPParamValue(req, "oldpassword", &oldpassword);
if (rv != SSM_SUCCESS) {
goto loser;
}
/* we do this check to find the case where the user changed only password
* settings, not the password itself
*/
if ((oldpassword[0] == '\0') && (newpassword[0] == '\0') &&
(repeatpassword[0] == '\0')) {
rv = SSM_HTTPDefaultCommandHandler(req);
goto done;
}
}
if (!ssm_VerifyPwdLength(newpassword))
goto loser;
if (strcmp(newpassword, repeatpassword) != 0)
goto loser;
if (!PK11_NeedPWInitForSlot(slot)) { /* there is some password on the DB */
if (!oldpassword)
goto loser;
if (PK11_CheckUserPassword(slot, oldpassword) !=
SECSuccess)
goto loser;
if (PK11_ChangePW(slot, oldpassword, newpassword) !=
SECSuccess)
goto loser;
}
else
{
if (PK11_NeedUserInit(slot)) {
if (PK11_InitPin(slot, NULL, newpassword) != SECSuccess)
goto loser;
}
else {
if (PK11_ChangePW(slot, NULL, newpassword) != SECSuccess)
goto loser;
}
}
result = PR_smprintf("result=password_success");
loser:
if (!result)
result = PR_smprintf("result=password_failure");
rv = SSM_HTTPCloseAndSleep(req);
if (rv != SSM_SUCCESS)
SSM_DEBUG("SetDBPasswordHandler: failure in DefaultCommandHandler\n");
/* post status if password dialog was invoked from the SecurityAdvisor */
if (SSM_IsA(req->target, SSM_RESTYPE_SECADVISOR_CONTEXT))
SSMControlConnection_SendUIEvent(req->ctrlconn, "get",
"show_followup", NULL,
result,
&((SSMResource *)req->ctrlconn)->m_clientContext);
PR_FREEIF(responseKey);
done:
if (req->target && req->target->m_UILock)
SSM_NotifyUIEvent(req->target);
return rv;
}
SSMStatus SSM_ShowFollowupKeywordHandler(SSMTextGenContext * cx)
{
char * resultvalue;
SSMStatus rv;
PR_ASSERT(cx != NULL);
PR_ASSERT(cx->m_request != NULL);
PR_ASSERT(cx->m_result != NULL);
rv = SSM_HTTPParamValue(cx->m_request, "result", &resultvalue);
if (rv != SSM_SUCCESS || !resultvalue)
goto loser;
if (!strcmp(resultvalue, "password_success"))
rv = SSM_GetAndExpandTextKeyedByString(cx, "set_password_success",
&cx->m_result);
else if (!strcmp(resultvalue,"password_failure"))
rv = SSM_GetAndExpandTextKeyedByString(cx, "set_password_failure",
&cx->m_result);
else if (!strcmp(resultvalue, "no_ldap_setup"))
rv = SSM_GetAndExpandTextKeyedByString(cx, "no_ldap_server_set",
&cx->m_result);
loser:
return rv;
}
SSMStatus SSM_SetUserPassword(PK11SlotInfo * slot, SSMResource * ct)
{
SSMStatus rv;
char * params = PR_smprintf("slot=%s&mechanism=%d",
PK11_GetTokenName(slot),
CKM_INVALID_MECHANISM);
SSM_LockUIEvent(ct);
rv = SSMControlConnection_SendUIEvent(ct->m_connection,
"get", "set_password",
ct, params,
&ct->m_clientContext);
if (rv != SSM_SUCCESS)
goto loser;
SSM_WaitUIEvent(ct, PR_INTERVAL_NO_TIMEOUT);
return rv;
loser:
SSM_UnlockUIEvent(ct);
return rv;
}
SSMStatus SSM_ProcessPasswordWindow(HTTPRequest * req)
{
SSMStatus rv = SSM_FAILURE;
SSMResource * target = NULL;
if (!req || !req->ctrlconn)
goto loser;
/*
* The window contents aren't going to change, so just send back
* a NO_CONTENT error which causes leave its content as is.
*/
rv = SSM_HTTPReportError(req, HTTP_NO_CONTENT);
target = (req->target ? req->target : (SSMResource *) req->ctrlconn);
/* send UI event to bring up the dialog */
SSM_LockUIEvent(&req->ctrlconn->super.super);
rv = SSMControlConnection_SendUIEvent(req->ctrlconn, "get",
"set_password", target,
"slot=all&mech=1",
&target->m_clientContext);
if (rv != SSM_SUCCESS) {
SSM_UnlockUIEvent(&req->ctrlconn->super.super);
goto loser;
}
SSM_WaitUIEvent(&req->ctrlconn->super.super, PR_INTERVAL_NO_TIMEOUT);
loser:
return rv;
}

View File

@ -0,0 +1,961 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "pkcs11ui.h"
#include "pkcs11.h"
#include "pk11func.h"
#include "plstr.h"
#include "secmod.h"
#include "secmodti.h"
#include "minihttp.h"
#include "textgen.h"
/* Utility */
PK11SlotInfo *
SSMPKCS11_FindSlotByID(SECMODModuleID modID,
CK_SLOT_ID slotID)
{
SECMODModule *mod = NULL;
PRIntn i;
mod = SECMOD_FindModuleByID(modID);
if (mod)
{
for(i=0;i<mod->slotCount;i++)
{
if (mod->slots[i]->slotID == slotID)
return mod->slots[i];
}
}
return NULL;
}
/*
---------------------------------------------------------
PKCS11 module processing (list, add, delete)
---------------------------------------------------------
*/
SSMStatus
ssmpkcs11_convert_module(SSMTextGenContext *cx,
PRInt32 modIndex,
SECMODModule *mod,
char *fmt)
{
char *dllName = NULL;
char *tempStr = NULL;
char *lib_ch = NULL;
CK_INFO modInfo;
SSMStatus rv = SSM_FAILURE;
SECStatus srv;
/* 65? Why 65??? It's what's was used in the original UI. */
char buf[65];
char buf2[65];
srv = PK11_GetModInfo(mod, &modInfo);
if (srv != SECSuccess)
goto loser;
/* we provide the space in (buf), so we don't deallocate lib_ch */
lib_ch = PK11_MakeString(NULL,buf2,(char *)modInfo.libraryDescription,
sizeof(modInfo.libraryDescription));
if (mod->dllName)
{
char *cursor, *newString;
int numSlashes = 0, newLen, i, j, oldLen;
dllName = mod->dllName;
/*
* Now we need to escape the '\' characters so the string shows
* up correctly in the UI.
*/
/* First count them to see if we even need to re-allocate*/
cursor = dllName;
while ((cursor = PL_strchr(cursor, '\\')) != NULL) {
numSlashes++;
cursor++;
}
if (numSlashes > 0) {
oldLen = PL_strlen(dllName);
newLen = oldLen + numSlashes + 1;
newString = SSM_NEW_ARRAY(char, newLen);
/*
* If we can't allocate a new buffer, then let's just display
* the original string. That's better than not displaying
* anything.
*/
if (newString != NULL) {
for (i=0, j=0; i<oldLen+1; i++,j++){
newString[j] = dllName[i];
if (newString[j] == '\\'){
newString[j+1] = '\\';
j++;
}
}
dllName = newString;
}
}
}
else
{
rv = SSM_GetAndExpandText(cx, "text_pk11_no_dll", &dllName);
if (rv != SSM_SUCCESS)
goto loser;
}
PR_snprintf(buf, sizeof(buf), "%d.%d",
modInfo.libraryVersion.major, modInfo.libraryVersion.minor);
tempStr = PR_smprintf(fmt, modIndex, (long)mod->moduleID, lib_ch,
mod->commonName, dllName, buf);
if (tempStr == NULL) {
rv = SSM_FAILURE;
goto loser;
}
rv = SSM_ConcatenateUTF8String(&cx->m_result, tempStr);
loser:
if (dllName && dllName != mod->dllName)
PR_Free(dllName);
PR_FREEIF (tempStr);
return rv;
}
/*
PKCS11 module list keyword handler.
Syntax: {_pk11modules <wrapper_key>}
*/
SSMStatus
SSM_PKCS11ModulesKeywordHandler(SSMTextGenContext *cx)
{
SSMStatus rv = SSM_SUCCESS;
char *wrapperKey = NULL;
char *wrapperStr = NULL;
SECMODModuleList *modList = SECMOD_GetDefaultModuleList();
SECMODModuleList *modWalk = NULL;
SECMODListLock *modLock = SECMOD_GetDefaultModuleListLock();
PRBool gotLock = PR_FALSE; /* indicates whether we should release at end */
PRInt32 i=0;
/* Check for parameter validity */
PR_ASSERT(cx);
PR_ASSERT(cx->m_request);
PR_ASSERT(cx->m_params);
PR_ASSERT(cx->m_result);
if (!cx || !cx->m_request || !cx->m_params || !cx->m_result)
{
rv = PR_INVALID_ARGUMENT_ERROR;
goto real_loser; /* really bail here */
}
if (SSM_Count(cx->m_params) != 1)
{
SSM_HTTPReportSpecificError(cx->m_request, "_certList: "
"Incorrect number of parameters "
"(%d supplied, 1 needed).\n",
SSM_Count(cx->m_params));
goto user_loser;
}
/* Convert parameters to something we can use in finding certs. */
wrapperKey = (char *) SSM_At(cx->m_params, 0);
PR_ASSERT(wrapperKey);
/* Get the wrapper text. */
rv = SSM_GetAndExpandTextKeyedByString(cx, wrapperKey, &wrapperStr);
if (rv != SSM_SUCCESS)
goto real_loser; /* error string set by the called function */
/* Iterate over the PKCS11 modules. Put relevant info from each
into its own copy of the wrapper text. */
SECMOD_GetReadLock(modLock);
gotLock = PR_TRUE;
modWalk = modList;
while (modWalk)
{
rv = ssmpkcs11_convert_module(cx, i++, modWalk->module, wrapperStr);
modWalk = modWalk->next;
}
goto done;
user_loser:
/* If we reach this point, something in the input is wrong, but we
can still send something back to the client to indicate that a
problem has occurred. */
/* If we can't do what we're about to do, really bail. */
if (!cx->m_request || !cx->m_request->errormsg)
goto real_loser;
/* Clear the string we were accumulating. */
SSMTextGen_UTF8StringClear(&cx->m_result);
/* Use the result string given to us to explain what happened. */
SSM_ConcatenateUTF8String(&cx->m_result, cx->m_request->errormsg);
/* Clear the result string, since we're sending this inline */
SSMTextGen_UTF8StringClear(&cx->m_request->errormsg);
goto done;
real_loser:
/* If we reach this point, then we are so screwed that we cannot
send anything vaguely normal back to the client. Bail. */
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
done:
PR_FREEIF(wrapperStr);
if (modLock && gotLock)
SECMOD_ReleaseReadLock(modLock);
return rv;
}
/*
---------------------------------------------------------
PKCS11 slot code
---------------------------------------------------------
*/
enum
{
SSM_PK11STR_SLOT_LOGGED_IN = (long) 0,
SSM_PK11STR_SLOT_NOT_LOGGED_IN,
SSM_PK11STR_SLOT_NO_LOGIN_REQUIRED,
SSM_PK11STR_SLOT_NOT_PRESENT,
SSM_PK11STR_SLOT_UNINITIALIZED,
SSM_PK11STR_SLOT_DISABLED,
SSM_PK11STR_SLOT_READY,
SSM_PK11STR_SLOT_STRING_COUNT
};
static char *slotStringKeys[] =
{
"text_pk11_slot_logged_in",
"text_pk11_slot_not_logged_in",
"text_pk11_slot_no_login_required",
"text_pk11_slot_not_present",
"text_pk11_slot_uninitialized",
"text_pk11_slot_disabled",
"text_pk11_slot_ready"
};
static char **slotStrings = NULL;
void
ssmpkcs11_initialize_slot_labels(SSMTextGenContext *cx)
{
SSMStatus rv = SSM_SUCCESS;
PRIntn i;
slotStrings = (char **) PR_Calloc(SSM_PK11STR_SLOT_STRING_COUNT + 1,
sizeof(char**));
PR_ASSERT(slotStrings);
for(i=0;i<SSM_PK11STR_SLOT_STRING_COUNT;i++)
{
rv = SSM_FindUTF8StringInBundles(cx, slotStringKeys[i],
&slotStrings[i]);
PR_ASSERT(rv == SSM_SUCCESS);
}
}
SSMStatus
ssmpkcs11_convert_slot(SSMTextGenContext *cx,
PRInt32 slotIndex,
PK11SlotInfo *slot,
char *fmt,
PRBool accumulate) /* accumulate in cx->m_result? */
{
char *name = NULL;
char *statusStr = NULL;
char *serial = NULL;
char *version = NULL;
char *tempStr = NULL;
long status, slotID = 0, moduleID = 0;
CK_TOKEN_INFO tokenInfo;
SSMStatus rv = SSM_FAILURE;
SECStatus srv = SECSuccess;
/* 65? Why 65??? It's what's was used in the original UI. */
char buf[65];
char empty[1] = { '\0' } ;
if (!slotStrings)
ssmpkcs11_initialize_slot_labels(cx);
/* If we have a NULL slot, return blank information. */
if (!slot)
{
name = empty;
statusStr = empty;
serial = empty;
version = empty;
slotID = 0;
goto show_stuff;
}
/* Get the slot name. Either the default name or the name of the token
in the slot will be used. */
if (PK11_IsPresent(slot))
name = PK11_GetTokenName(slot);
else
name = PK11_GetSlotName(slot);
/* Report the status of the slot. */
if (PK11_IsDisabled(slot))
status = SSM_PK11STR_SLOT_DISABLED;
else if (!PK11_IsPresent(slot))
status = SSM_PK11STR_SLOT_NOT_PRESENT;
else if (PK11_NeedLogin(slot) && PK11_NeedUserInit(slot))
status = SSM_PK11STR_SLOT_UNINITIALIZED;
else if (PK11_NeedLogin(slot) && !PK11_IsLoggedIn(slot, NULL))
status = SSM_PK11STR_SLOT_NOT_LOGGED_IN;
else if (PK11_NeedLogin(slot))
status = SSM_PK11STR_SLOT_LOGGED_IN;
else
status = SSM_PK11STR_SLOT_READY;
statusStr = slotStrings[status];
/* Get the serial number and version. */
/* This is how the old UI determines if there's a token in, so... */
if (PK11_IsPresent(slot))
srv = PK11_GetTokenInfo(slot, &tokenInfo);
if (PK11_IsPresent(slot) && (srv == SECSuccess))
{
/* Get serial number and version from the token info. */
serial = PK11_MakeString(NULL, NULL, (char*)tokenInfo.serialNumber,
sizeof(tokenInfo.serialNumber));
PR_snprintf(buf, sizeof(buf), "%d.%d",
tokenInfo.firmwareVersion.major,
tokenInfo.firmwareVersion.minor);
version = buf;
}
else
{
/* Get serial number and version from the slot info. */
CK_SLOT_INFO slotInfo;
srv = PK11_GetSlotInfo(slot, &slotInfo);
if (srv != SECSuccess)
goto loser;
serial = empty;
PR_snprintf(buf, sizeof(buf), "%d.%d",
slotInfo.firmwareVersion.major,
slotInfo.firmwareVersion.minor);
version = buf;
}
slotID = (long) (slot->slotID);
moduleID = (long) (slot->module->moduleID);
show_stuff:
tempStr = PR_smprintf(fmt, slotIndex, slotID, moduleID, name,
statusStr, serial, version);
if (accumulate)
{
rv = SSM_ConcatenateUTF8String(&cx->m_result, tempStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
}
else
rv = SSM_HTTPSendUTF8String(cx->m_request, tempStr);
loser:
/* The data that isn't freed is either because it's a member of the
* data in a structure of the PK11 libraries or its a static local
* variable.
*/
if (serial && serial != empty)
PR_Free(serial);
PR_FREEIF(tempStr);
return rv;
}
/*
PKCS11 slot list keyword handler.
Syntax: {_pk11slots <moduleID>,<wrapper_key>}
*/
SSMStatus
SSM_PKCS11SlotsKeywordHandler(SSMTextGenContext *cx)
{
SSMStatus rv = SSM_SUCCESS;
SECMODModule *module = NULL;
char *wrapperKey = NULL;
char *moduleIDStr = NULL;
long moduleID;
char *wrapperStr = NULL;
PRInt32 i=0;
/* Check for parameter validity */
PR_ASSERT(cx);
PR_ASSERT(cx->m_request);
PR_ASSERT(cx->m_params);
PR_ASSERT(cx->m_result);
if (!cx || !cx->m_request || !cx->m_params || !cx->m_result)
{
rv = PR_INVALID_ARGUMENT_ERROR;
goto real_loser; /* really bail here */
}
if (SSM_Count(cx->m_params) != 2)
{
SSM_HTTPReportSpecificError(cx->m_request, "_certList: "
"Incorrect number of parameters "
"(%d supplied, 2 needed).\n",
SSM_Count(cx->m_params));
goto user_loser;
}
/* Convert parameters to something we can use in finding certs. */
moduleIDStr = (char *) SSM_At(cx->m_params, 0);
PR_ASSERT(moduleIDStr);
wrapperKey = (char *) SSM_At(cx->m_params, 1);
PR_ASSERT(wrapperKey);
/* Find the module we're looking for based on the module ID. */
module = SECMOD_FindModuleByID((SECMODModuleID) moduleID);
if (!module)
goto user_loser;
/* Get the wrapper text. */
rv = SSM_GetAndExpandTextKeyedByString(cx, wrapperKey, &wrapperStr);
if (rv != SSM_SUCCESS)
goto real_loser; /* error string set by the called function */
/* Iterate over the slots from this module. Put relevant info from each
into its own copy of the wrapper text. */
for(i=0;i<module->slotCount;i++)
{
rv = ssmpkcs11_convert_slot(cx, i, module->slots[i], wrapperStr,
PR_TRUE);
if (rv != SSM_SUCCESS)
goto user_loser;
}
goto done;
user_loser:
/* If we reach this point, something in the input is wrong, but we
can still send something back to the client to indicate that a
problem has occurred. */
/* If we can't do what we're about to do, really bail. */
if (!cx->m_request || !cx->m_request->errormsg)
goto real_loser;
/* Clear the string we were accumulating. */
SSMTextGen_UTF8StringClear(&cx->m_result);
/* Use the result string given to us to explain what happened. */
SSM_ConcatenateUTF8String(&cx->m_result, cx->m_request->errormsg);
/* Clear the result string, since we're sending this inline */
SSMTextGen_UTF8StringClear(&cx->m_request->errormsg);
goto done;
real_loser:
/* If we reach this point, then we are so screwed that we cannot
send anything vaguely normal back to the client. Bail. */
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
done:
PR_FREEIF(wrapperStr);
if (module)
SECMOD_DestroyModule(module);
return rv;
}
SSMStatus
ssm_pkcs11_chuck_property(SSMTextGenContext *cx, char *propName)
{
char *text = NULL;
SSMStatus rv;
rv = SSM_GetAndExpandText(cx, propName, &text);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_HTTPSendUTF8String(cx->m_request, text);
loser:
PR_FREEIF(text);
SSMTextGen_UTF8StringClear(&cx->m_result);
return rv;
}
/* PKCS11ShowSlots?module=<moduleID> */
SSMStatus
SSM_ShowSlotsCommandHandler(HTTPRequest *req)
{
SSMTextGenContext *cx = NULL;
char *tmpl = NULL, *type = NULL;
char *nomod_ch = NULL;
char *modID_ch = NULL;
long moduleID;
SECMODModule *module = NULL;
PRIntn i;
SSMStatus rv;
/* If we have a "no_module" parameter, then there
is no module for which to load slots. */
rv = SSM_HTTPParamValue(req, "no_module", &nomod_ch);
if (rv == SSM_SUCCESS)
goto display_stuff;
rv = SSM_HTTPParamValue(req, "module", &modID_ch);
if (rv != SSM_SUCCESS)
goto display_stuff;
if (modID_ch)
{
/* Convert the module ID into a real module ID. */
PR_sscanf(modID_ch, "%ld", &moduleID);
/* Find the module we're looking for based on the module ID. */
module = SECMOD_FindModuleByID((SECMODModuleID) moduleID);
if (!module)
goto loser;
}
display_stuff:
/* Make a new top-level text gen context to chuck text back. */
rv = SSMTextGen_NewTopLevelContext(req, &cx);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_GetAndExpandText(cx, "adv_modules_slotlist_type", &type);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_HTTPSendOKHeader(req, NULL, type);
if (rv != SSM_SUCCESS)
goto loser;
/* Chuck out part 1. */
rv = ssm_pkcs11_chuck_property(cx, "adv_modules_slotlist_part1");
if (rv != SSM_SUCCESS)
goto loser;
/* Get the template for the JS slot list. */
rv = SSM_GetAndExpandText(cx, "adv_modules_slotlist_js_template", &tmpl);
if (rv != SSM_SUCCESS)
goto loser;
/* Iterate over the slots from this module. Put relevant info from each
into its own copy of the wrapper text. */
if (module)
{
for(i=0;i<module->slotCount;i++)
{
rv = ssmpkcs11_convert_slot(cx, i, module->slots[i], tmpl,
PR_FALSE);
if (rv != SSM_SUCCESS)
goto loser;
}
}
PR_Free(tmpl);
tmpl = NULL;
/* Chuck out part 2. */
rv = ssm_pkcs11_chuck_property(cx, "adv_modules_slotlist_part2");
if (rv != SSM_SUCCESS)
goto loser;
/* Get the template for the selectable slot list. */
rv = SSM_GetAndExpandText(cx, "adv_modules_slotlist_select_template", &tmpl);
if (rv != SSM_SUCCESS)
goto loser;
/* Iterate over the slots from this module. Put relevant info from each
into its own copy of the wrapper text. */
if (module)
{
for(i=0;i<module->slotCount;i++)
{
rv = ssmpkcs11_convert_slot(cx, i, module->slots[i], tmpl,
PR_FALSE);
if (rv != SSM_SUCCESS)
goto loser;
}
}
/* Chuck out part 3. */
rv = ssm_pkcs11_chuck_property(cx, "adv_modules_slotlist_part3");
req->sentResponse = PR_TRUE;
goto done;
loser:
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
done:
if (cx)
SSMTextGen_DestroyContext(cx);
PR_FREEIF(tmpl);
return rv;
}
SSMStatus
ssm_find_module_from_request(HTTPRequest *req, SECMODModule **mod)
{
char *modID_ch = NULL;
PRInt32 moduleID;
SSMStatus rv;
rv = SSM_HTTPParamValue(req, "module", &modID_ch);
if (rv != SSM_SUCCESS)
goto done;
if (modID_ch)
{
/* Convert the module ID into a real module ID. */
PR_sscanf(modID_ch, "%ld", &moduleID);
/* Find the module we're looking for based on the module ID. */
*mod = SECMOD_FindModuleByID((SECMODModuleID) moduleID);
}
done:
if ((!*mod) && (rv == SSM_SUCCESS))
rv = SSM_FAILURE;
return rv;
}
PK11SlotInfo *
find_slot_by_ID(SECMODModule *mod, CK_SLOT_ID slotID)
{
int i;
PK11SlotInfo *slot;
for (i=0; i < mod->slotCount; i++) {
slot = mod->slots[i];
if (slot->slotID == (CK_SLOT_ID) slotID)
return PK11_ReferenceSlot(slot);
}
return NULL;
}
SSMStatus
ssm_find_slot_from_request(HTTPRequest *req, PK11SlotInfo **slot)
{
char *slotID_ch = NULL;
PRInt32 slotID;
SECMODModule *mod;
SSMStatus rv = SSM_SUCCESS;
rv = ssm_find_module_from_request(req, &mod);
if (rv != SSM_SUCCESS)
goto done;
rv = SSM_HTTPParamValue(req, "slot", &slotID_ch);
if (rv != SSM_SUCCESS)
goto done;
if (slotID_ch)
{
/* Convert the module ID into a real module ID. */
PR_sscanf(slotID_ch, "%ld", &slotID);
/* Find the module we're looking for based on the module ID. */
*slot = find_slot_by_ID(mod, (CK_SLOT_ID) slotID);
}
done:
if ((!*slot) && (rv == SSM_SUCCESS))
rv = SSM_FAILURE;
return rv;
}
SSMStatus
ssmpkcs11_show_slot_info(HTTPRequest *req, PK11SlotInfo *slot)
{
char *wrapperStr = NULL;
char *tmpl = NULL;
char *type = NULL;
SSMTextGenContext *cx;
SSMStatus rv;
/* Make a new top-level text gen context to chuck text back. */
rv = SSMTextGen_NewTopLevelContext(req, &cx);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_GetAndExpandText(cx, "adv_modules_slot_info_type", &type);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_HTTPSendOKHeader(req, NULL, type);
if (rv != SSM_SUCCESS)
goto loser;
rv = SSM_GetAndExpandText(cx, "adv_modules_slot_info_content", &wrapperStr);
if (rv != SSM_SUCCESS)
goto loser; /* error string set by the called function */
rv = ssmpkcs11_convert_slot(cx, 0, slot, wrapperStr, PR_FALSE);
goto done;
loser:
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
done:
if (cx)
SSMTextGen_DestroyContext(cx);
PR_FREEIF(tmpl);
PR_FREEIF(type);
PR_FREEIF(wrapperStr);
return rv;
}
SSMStatus
SSM_ShowSlotCommandHandler(HTTPRequest *req)
{
SSMStatus rv;
PK11SlotInfo *slot;
/* Find the slot. */
rv = ssm_find_slot_from_request(req, &slot);
if (rv != SSM_SUCCESS)
goto loser;
/* Display the slot info. */
rv = ssmpkcs11_show_slot_info(req, slot);
req->sentResponse = PR_TRUE;
loser:
if (slot)
PK11_FreeSlot(slot);
return rv;
}
SSMStatus
SSM_LoginSlotCommandHandler(HTTPRequest *req)
{
SSMStatus rv;
PK11SlotInfo *slot;
/* Find the slot. */
rv = ssm_find_slot_from_request(req, &slot);
if (rv != SSM_SUCCESS)
goto loser;
/* Log into the slot. */
PK11_Authenticate(slot, PR_TRUE, req->ctrlconn);
/* Display the slot info. */
rv = ssmpkcs11_show_slot_info(req, slot);
req->sentResponse = PR_TRUE;
loser:
if (slot)
PK11_FreeSlot(slot);
return rv;
}
SSMStatus
SSM_LogoutSlotCommandHandler(HTTPRequest *req)
{
SSMStatus rv;
PK11SlotInfo *slot;
/* Find the slot. */
rv = ssm_find_slot_from_request(req, &slot);
if (rv != SSM_SUCCESS)
goto loser;
/* Log out of the slot. */
PK11_Logout(slot);
/* Display the slot info. */
rv = ssmpkcs11_show_slot_info(req, slot);
req->sentResponse = PR_TRUE;
loser:
if (slot)
PK11_FreeSlot(slot);
return rv;
}
SSMStatus
SSM_LogoutAllSlotsCommandHandler(HTTPRequest *req)
{
SSMStatus rv;
PK11SlotInfo *slot;
/* Find the slot. */
rv = ssm_find_slot_from_request(req, &slot);
/* Not relevant if we find the slot here,
just remember to display (or not) whatever slot we have */
if (rv != SSM_SUCCESS)
slot = NULL;
/* Log out of all slots. */
PK11_LogoutAll();
/* Display the slot info (if any). */
rv = ssmpkcs11_show_slot_info(req, slot);
req->sentResponse = PR_TRUE;
if (slot)
PK11_FreeSlot(slot);
return rv;
}
/*
---------------------------------------------------------
FIPS mode code
---------------------------------------------------------
*/
/*
FIPS mode keyword handler.
Syntax: {_fipsmode <true_text>,<false_text>}
where <true_text> is displayed if FIPS mode is on, <false_text> otherwise.
*/
SSMStatus
SSM_PKCS11FIPSModeKeywordHandler(SSMTextGenContext *cx)
{
SSMStatus rv = SSM_SUCCESS;
char *param = NULL;
char *tempStr = NULL;
PR_ASSERT(cx);
PR_ASSERT(cx->m_params);
PR_ASSERT(cx->m_result);
if (!cx || !cx->m_params || !cx->m_result)
{
rv = PR_INVALID_ARGUMENT_ERROR;
goto loser;
}
/* Figure out if we're in FIPS mode. */
if (PK11_IsFIPS())
param = (char *) SSM_At(cx->m_params, 0);
else
param = (char *) SSM_At(cx->m_params, 1);
/* Display the appropriate string. */
rv = SSMTextGen_SubstituteString(cx, param, &tempStr);
if (rv != SSM_SUCCESS)
goto loser; /* error string set by the called function */
rv = SSM_ConcatenateUTF8String(&cx->m_result, tempStr);
if (rv == SSM_SUCCESS)
goto done;
loser:
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
done:
PR_FREEIF(tempStr);
return rv;
}
void
SSM_TrimTrailingWhitespace(char *str)
{
char *end = &(str[strlen(str)]);
char *start = str;
do
{
end--;
}
while ((end >= start) &&
((*end == ' ') || (*end == '\0')));
*(++end) = '\0';
}
/*
Command handler to set FIPS mode.
Syntax: setFIPSMode?fips={on|off}&baseRef=<baseRef>&target=<ctrlconn>
*/
SSMStatus
SSM_SetFIPSModeCommandHandler(HTTPRequest *req)
{
char *fips_ch = NULL, *baseRef_ch = NULL;
SECStatus srv = SECSuccess;
PRBool oldFIPS, newFIPS;
SSMStatus rv = SSM_SUCCESS;
rv = SSM_HTTPParamValue(req, "fips", &fips_ch);
if (rv != SSM_SUCCESS)
goto loser;
newFIPS = !PL_strncmp(fips_ch, "on", 2);
oldFIPS = PK11_IsFIPS();
if (newFIPS != oldFIPS)
{
/*
Turning FIPS mode on/off requires the exact same operation:
deleting the built-in PKCS11 module.
### mwelch We need these calls to differentiate between
secmod dbs!
*/
SECMODModule *internal;
CK_INFO modInfo;
internal = SECMOD_GetInternalModule();
if (!internal)
goto loser;
srv = PK11_GetModInfo(internal, &modInfo);
if (srv != SECSuccess)
goto loser;
SSM_TrimTrailingWhitespace((char*) modInfo.libraryDescription);
/* Delete the {FIPS,non-FIPS} internal module, so that
it will be replaced by the {non-FIPS,FIPS} counterpart. */
srv = SECMOD_DeleteInternalModule(internal->commonName);
if (srv != SECSuccess)
goto loser;
}
/* if there's a baseRef, send it back. otherwise, no content. */
rv = SSM_HTTPParamValue(req, "baseRef", &baseRef_ch);
if (rv == SSM_SUCCESS)
{
/* send what was requested */
rv = SSM_HTTPCloseAndSleep(req);
}
goto done;
loser:
if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
SSM_HTTPReportSpecificError(req, "SetFIPSModeCommandHandler: Error %d "
"attempting to change FIPS mode.",
srv != SECSuccess ? srv : rv);
done:
return rv;
}

View File

@ -0,0 +1,51 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __pkcs11ui_h__
#define __pkcs11ui_h__
#include "textgen.h"
#include "minihttp.h"
SSMStatus SSM_PKCS11ModulesKeywordHandler(SSMTextGenContext *cx);
SSMStatus SSM_PKCS11SlotsKeywordHandler(SSMTextGenContext *cx);
SSMStatus SSM_PKCS11FIPSModeKeywordHandler(SSMTextGenContext *cx);
SSMStatus SSM_SetFIPSModeCommandHandler(HTTPRequest *req);
SSMStatus SSM_ShowSlotsCommandHandler(HTTPRequest *req);
SSMStatus SSM_ShowSlotCommandHandler(HTTPRequest *req);
SSMStatus SSM_LoginSlotCommandHandler(HTTPRequest *req);
SSMStatus SSM_LogoutSlotCommandHandler(HTTPRequest *req);
SSMStatus SSM_LogoutAllSlotsCommandHandler(HTTPRequest *req);
#endif

1234
security/psm/server/prefs.c Normal file

File diff suppressed because it is too large Load Diff

344
security/psm/server/prefs.h Normal file
View File

@ -0,0 +1,344 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef _PREFS_H_
#define _PREFS_H_
#if 0
#include "prtypes.h"
#include "ssmdefs.h"
typedef struct PrefFileStr PrefFile;
/************************************************************
** FUNCTION: PREF_OpenPrefs
**
** DESCRIPTION: Creates a PrefFile object for the preferences file.
** If the file does not exist, it does not create it, and
** returns a default set of preferences. To create the
** preference file you must call PREF_WritePrefs() or
** PREF_ClosePrefs(). If the file has already been
** opened, the reference count is incremented and the
** same object is returned.
**
** INPUTS:
** filename
** The name of the preferences file to open.
**
** RETURNS:
** If successful, returns a pointer to a PrefFile object.
** If failed, returns NULL.
**
*************************************************************/
PrefFile *
PREF_OpenPrefs(char *filename);
/************************************************************
** FUNCTION: PREF_WritePrefs
**
** DESCRIPTION: Writes out the contents of prefs to the preferences
** file. If the file does not exist, it is created.
**
** INPUTS:
** prefs
** The PrefFile object to write.
**
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns PR_FAILURE.
**
*************************************************************/
SSMStatus
PREF_WritePrefs(PrefFile *prefs);
/************************************************************
** FUNCTION: PREF_ClosePrefs
**
** DESCRIPTION: Closes the PrefFile object. If this is the last
** reference to to object, the contents are written out
** and the object is destroyed.
**
** INPUTS:
** prefs
** The PrefFile object to close.
**
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns PR_FAILURE.
**
*************************************************************/
SSMStatus
PREF_ClosePrefs(PrefFile *prefs);
/************************************************************
** FUNCTION: PREF_SetStringPref
**
** DESCRIPTION: Sets a preference with a string value. The preference
** will be created if it does not already exist.
**
** INPUTS:
** prefs
** The PrefFile object.
** name
** The name of the preference.
** value
** The value of the preference.
**
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns PR_FAILURE.
**
*************************************************************/
SSMStatus
PREF_SetStringPref(PrefFile *prefs, char *name, char *value);
/************************************************************
** FUNCTION: PREF_GetStringPref
**
** DESCRIPTION: Gets the value of a string preference. The returned
** string must be freed with PR_Free().
**
** INPUTS:
** prefs
** The PrefFile object.
** name
** The name of the preference.
**
** RETURNS:
** If successful, returns a new string containing the value of
** the preference.
** If failed, returns NULL.
**
*************************************************************/
char *
PREF_GetStringPref(PrefFile *prefs, char *name);
#else /* PREFS LITE (tm) */
/* XXX sjlee
* The following set of APIs describe the preference management system which
* we will use for the time being until a fully-functional prefs/profs library
* comes online, thus the name PREFS LITE.
*/
#include "prtypes.h"
#include "ssmdefs.h"
#include "plhash.h"
/* pref types used for sending (and receiving) pref messages */
#define STRING_PREF 0
#define BOOL_PREF 1
#define INT_PREF 2
typedef struct PrefSetStr PrefSet;
/*
* Function: PrefSet* PREF_NewPrefs()
* Purpose: Creates a PrefSet object. The object is not associated with a
* file, and the values are initially filled with default values.
* Return values:
* - a pointer to a PrefSet object; if failure, returns NULL
*/
PrefSet* PREF_NewPrefs(void);
/*
* Function: SSMStatus PREF_ClosePrefs()
* Purpose: Closes the PrefSet object and frees the memory. We do not write
* changes back to the client at this time.
* Arguments and return values:
* - prefs: the PrefSet object to close
* - returns: PR_SUCCESS if successful; PR_FAILURE if failure
*/
SSMStatus PREF_ClosePrefs(PrefSet* prefs);
/*
* Function: SSMStatus PREF_GetStringPref()
* Purpose: Retrieves the string pref for (key) from (prefs).
* Arguments and return values:
* - prefs: the pref set
* - key: the key for the pref item
* - value: on return, filled with a pointer to the string pref value (or it
* be NULL if NULL was the legally assigned value). Since this
* points to an existing string (not a new string), the caller
* should not free it. If the pref item does not exist, (*value) is
* NULL.
* - returns: PR_SUCCESS if successful; error code otherwise
*
* Notes: Note that NULL is a legal string value for a pref item. One should
* check the return value (SSMStatus) to see if an error occurred.
*/
SSMStatus PREF_GetStringPref(PrefSet* prefs, char* key, char** value);
/*
* Function: SSMStatus PREF_CopyStringPref()
* Purpose: identical to PREF_GetStringPref() except that it creates a new
* string
* Arguments and return values:
* - prefs: the pref set
* - key: the key for the pref item
* - value: on return, filled with a pointer to the string newly allocated
* that contains the pref value (or NULL if the value is NULL).
* - returns: PR_SUCCESS if successful; error code otherwise
*
* Notes: Use this function instead of PREF_GetStringPref() if you need a
* newly allocated string. The caller is responsible for freeing
* the string when done.
*/
SSMStatus PREF_CopyStringPref(PrefSet* prefs, char* key, char** value);
/*
* Function: SSMStatus PREF_SetStringPref()
* Purpose: Sets the string pref for (key) in (prefs).
* Arguments and return values:
* - prefs: the pref set
* - key: the key for the pref item
* - value: the string value to set for the key. NULL may be used for a
* value.
* - returns: PR_SUCCESS if successful; error code otherwise
*/
SSMStatus PREF_SetStringPref(PrefSet* prefs, char* key, char* value);
/*
* Function: PRBool PREF_StringPrefChanged()
* Purpose: Compares the value in the set with the given value and determines
* if it has changed
* Arguments and return values:
* - prefs: the pref set
* - key: the key for the pref item
* - value: the string value to compare. NULL may be used for a value.
* - returns: PR_TRUE if the value does not match or the key was not found
* (i.e. change needs to be saved); otherwise PR_FALSE
*
* Notes: this is useful when one wants to determine the items that need
* to be permanently saved.
*/
PRBool PREF_StringPrefChanged(PrefSet* prefs, char* key, char* value);
/*
* Function: SSMStatus PREF_GetBoolPref()
* Purpose: Retrieves the boolean pref for (key) from (prefs).
* Arguments and return values:
* - prefs: the pref set
* - key: the key for the pref item
* - value: on return, filled with the boolean pref value.
* - returns: PR_SUCCESS if successful; error code otherwise
*/
SSMStatus PREF_GetBoolPref(PrefSet* prefs, char* key, PRBool* value);
/*
* Function: SSMStatus PREF_SetBoolPref()
* Purpose: Sets the boolean pref for (key) in (prefs).
* Arguments and return values:
* - prefs: the pref set
* - key: the key for the pref item
* - value: the boolean value to set for the key.
* - returns: PR_SUCCESS if successful; error code otherwise
*/
SSMStatus PREF_SetBoolPref(PrefSet* prefs, char* key, PRBool value);
/*
* Function: PRBool PREF_BoolPrefChanged()
* Purpose: Compares the value in the set with the given value and determines
* if it has changed
* Arguments and return values:
* - prefs: the pref set
* - key: the key for the pref item
* - value: the boolean value to compare.
* - returns: PR_TRUE if the value does not match or the key was not found
* (i.e. change needs to be saved); otherwise PR_FALSE
*
* Notes: this is useful when one wants to determine the items that need
* to be permanently saved.
*/
PRBool PREF_BoolPrefChanged(PrefSet* prefs, char* key, PRBool value);
/*
* Function: SSMStatus PREF_GetIntPref()
* Purpose: Retrieves the integer pref for (key) from (prefs).
* Arguments and return values:
* - prefs: the pref set
* - key: the key for the pref item
* - value: on return, filled with the integer pref value
* - returns: PR_SUCCESS if successful; error code otherwise
*/
SSMStatus PREF_GetIntPref(PrefSet* prefs, char* key, PRIntn* value);
/*
* Function: SSMStatus PREF_SetIntPref()
* Purpose: Sets the integer pref (key) in (prefs).
* Arguments and return values:
* - prefs: the prefs set
* - key: the key for the pref item
* - value: the integer value to set for the key
* - returns: PR_SUCCESS if successful; error code otherwise
*/
SSMStatus PREF_SetIntPref(PrefSet* prefs, char* key, PRIntn value);
/*
* Function: PRBool PREF_IntPrefChanged()
* Purpose: Compares the value in the set with the given value and determines
* if it has changed
* Arguments and return values:
* - prefs: the pref set
* - key: the key for the pref item
* - value: the integer value to compare.
* - returns: PR_TRUE if the value does not match or the key was not found
* (i.e. change needs to be saved); otherwise PR_FALSE
*
* Notes: this is useful when one wants to determine the items that need
* to be permanently saved.
*/
PRBool PREF_IntPrefChanged(PrefSet* prefs, char* key, PRIntn value);
/****
* Functions and typedefs needed to iterated over multiple similar pref items.
* Used to find all specified LDAP servers for UI lookup.
***/
typedef struct
{
char* childList;
char* parent;
unsigned int bufsize;
} PrefChildIter;
SSMStatus PREF_CreateChildList(PrefSet * prefs, const char* parent_key,
char ***child_list);
SSMStatus pref_append_value(char *** list, char * value);
#endif /* PREFS LITE (tm) */
#endif /* _PREFS_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,66 @@
#ifndef PROCESSMSG_H_
#define PROCESSMSG_H_
SSMStatus
SSMControlConnection_ProcessDecodeAndCreateTempCert(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessDestroyCert(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessGetKeyChoiceList(SSMControlConnection * ctrl,
SECItem * msg);
/* This function runs on a separate thread and has a single argument */
typedef struct {
SSMControlConnection * ctrl;
SECItem * msg;
} genKeyArg;
void
SSMControlConnection_ProcessGenKeyOldStyle(void * arg);
SSMStatus
SSMControlConnection_ProcessDecodeCertRequest(SSMControlConnection * ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessFindCertByNickname(SSMControlConnection *ctrl, SECItem *msg);
SSMStatus
SSMControlConnection_ProcessFindCertByKey(SSMControlConnection *ctrl, SECItem *msg);
SSMStatus
SSMControlConnection_ProcessFindCertByEmailAddr(SSMControlConnection *ctrl, SECItem *msg);
SSMStatus
SSMControlConnection_ProcessAddCertToDB(SSMControlConnection *ctrl, SECItem *msg);
SSMStatus
SSMControlConnection_ProcessMatchUserCert(SSMControlConnection *ctrl, SECItem *msg);
SSMStatus SSMControlConnection_ProcessPickleSecurityStatusRequest(SSMControlConnection* ctrl,
SECItem* msg);
SSMStatus
SSMControlConnection_ProcessLocalizedTextRequest(SSMControlConnection *ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessRedirectCompare(SSMControlConnection *ctrl,
SECItem * msg);
SSMStatus
SSMControlConnection_ProcessDecodeCRLRequest(SSMControlConnection *ctrl,
SECItem *msg);
PRStatus
SSMControlConnection_ProcessSecurityAdvsiorRequest(SSMControlConnection *ctrl,
SECItem *msg);
SSMStatus
SSMControlConnection_ProcessGetExtensionRequest(SSMControlConnection *ctrl,
SECItem *msg);
SSMStatus
SSMControlConnection_ProcessHTMLCertInfoRequest(SSMControlConnection *ctrl,
SECItem *msg);
#endif /*PROCESSMSG_H_*/

View File

@ -0,0 +1,412 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "ctrlconn.h"
#include "serv.h"
#ifdef WIN32
#include <windows.h>
#include <winreg.h>
#endif
#ifdef WIN32
/* local prototypes */
char* SSM_PREF_WinRegQueryCharValueEx(HKEY key, const char* subKey);
char* SSM_PROF_WinGetNetworkProfileDir(void);
char* SSM_PROF_WinGetProfileDirFromName(const char* profName);
char* SSM_PROF_WinGetDefaultProfileDB(void);
#endif
char* SSM_PROF_GetProfileDirectory(SSMControlConnection* conn)
{
char* path = NULL;
PRFileInfo info;
#ifdef WIN32
char* profDB = NULL;
#endif
if (conn == NULL) {
goto loser;
}
#if defined(XP_UNIX)
path = PR_smprintf("%s/.netscape", PR_GetEnv("HOME"));
if (path == NULL) {
goto loser;
}
#elif defined(WIN32)
/* Folks tell me that the correct way to get it is through the Netscape
* registry, not the Windows registry, but I can't confirm that story.
* I will keep investigating.
* Furthermore, if we complete migration and once Cartman owns its own
* registry space, we will not have to worry about locating the profile
* directory this way.
*/
#if 0 /* XXX for now we only get the default directory */
/* check network installations */
path = SSM_PROF_WinGetNetworkProfileDir();
if (path != NULL) {
goto check;
}
/* next, try to get it directly from the user registry */
path = SSM_PROF_WinGetProfileDirFromName(conn->m_profileName);
if (path != NULL) {
goto check;
}
#endif
/* couldn't find the profile; look for the default */
profDB = SSM_PROF_WinGetDefaultProfileDB();
if (profDB == NULL) {
goto loser;
}
/* get the profile directory */
path = PR_smprintf("%s\\%s", profDB, conn->m_profileName);
if ((PR_GetFileInfo(path, &info) != PR_SUCCESS) ||
(info.type != PR_FILE_DIRECTORY)) {
/* couldn't find it there either; try to guess it */
SSM_DEBUG("Cannot find a profile in %s. Trying again...\n", path);
PR_Free(path);
path = PR_smprintf("C:\\Program Files\\Netscape\\Users\\%s",
conn->m_profileName);
if (path == NULL) {
goto loser;
}
}
else {
goto done;
}
#endif
/* check whether the directory exists */
if ((PR_GetFileInfo(path, &info) != PR_SUCCESS) ||
(info.type != PR_FILE_DIRECTORY)) {
SSM_DEBUG("Can't find a profile in %s.\n", path);
goto loser;
}
/* success */
SSM_DEBUG("The directory is %s.\n", path);
goto done;
loser:
if (path != NULL) {
PR_Free(path);
path = NULL;
}
done:
#ifdef WIN32
if (profDB != NULL) {
PR_Free(profDB);
}
#endif
return path;
}
#ifdef WIN32
/* Function: char* SSM_PROF_WinGetNetworkProfileDir(void)
* Purpose: returns the profile directory from Windows registry in case of
* network installation
* Arguments and return values:
* - returns: profile directory; NULL otherwise
*
* Note: this is still Nova-specific. Seamonkey does not support network
* installations?
* Key: "HKEY_CURRENT_USER\SOFTWARE\Netscape\Netscape Navigator\UserInfo\
* DirRoot"
*/
char* SSM_PROF_WinGetNetworkProfileDir(void)
{
char* subKey = "SOFTWARE\\Netscape\\Netscape Navigator\\UserInfo";
LONG rv;
char* ret = NULL;
HKEY keyRet = NULL;
rv = RegOpenKeyEx(HKEY_CURRENT_USER, subKey, (DWORD)0, KEY_QUERY_VALUE,
&keyRet);
if (rv != ERROR_SUCCESS) {
return ret;
}
ret = SSM_PREF_WinRegQueryCharValueEx(keyRet, "DirRoot");
if (ret == NULL) {
goto loser;
}
/* success */
goto done;
loser:
if (ret != NULL) {
PR_Free(ret);
ret = NULL;
}
done:
if (keyRet != NULL) {
RegCloseKey(keyRet);
}
return ret;
}
/* Function: char* SSM_PROF_WinGetProfileDirFromName()
* Purpose: returns the profile directory that belongs to the profile from
* the registry
* Arguments and return values:
* - profName: profile name
* - returns: profile directory; NULL if failure
*
* Note: this is still Nova-specific. A lot has to be ifdef'd when Seamonkey
* comes online.
* key: "HKEY_LOCAL_MACHINE\SOFTWARE\Netscape\Netscape Navigator\Users\(name)\
* DirRoot"
*/
char* SSM_PROF_WinGetProfileDirFromName(const char* profName)
{
char* subKey = NULL;
LONG rv;
char* ret = NULL;
HKEY keyRet = NULL;
PR_ASSERT(profName != NULL);
subKey = PR_smprintf("SOFTWARE\\Netscape\\Netscape Navigator\\Users\\%s",
profName);
if (subKey == NULL) {
return ret;
}
/* open the user's registry key */
rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, (DWORD)0, KEY_QUERY_VALUE,
&keyRet);
if (rv != ERROR_SUCCESS) {
goto loser;
}
/* get the string */
ret = SSM_PREF_WinRegQueryCharValueEx(keyRet, "DirRoot");
if (ret == NULL) {
goto loser;
}
/* success */
goto done;
loser:
if (ret != NULL) {
PR_Free(ret);
ret = NULL;
}
done:
if (keyRet != NULL) {
RegCloseKey(keyRet);
}
return ret;
}
void ssm_prof_cut_idstring(char** idString)
{
char* marker = NULL;
char* subString = NULL;
PRUint32 fullLength;
int subSize;
PR_ASSERT(*idString != NULL);
fullLength = strlen(*idString);
/* traverse backward to find the last backslash */
marker = strrchr(*idString, '\\');
if (marker == NULL) {
/* no backslash? strange but return */
return;
}
/* found the backslash */
subSize = marker - *idString;
subString = (char*)PR_Calloc(fullLength-subSize+1, sizeof(char));
if (subString == NULL) {
goto loser;
}
memcpy(subString, marker, fullLength-subSize);
if (_stricmp(subString, "Communicator") == 0 ||
_stricmp(subString, "Commun~1") == 0) {
/* "Communicator" is at the end of the installation directory path.
* Take it out.
*/
char* newID = NULL;
newID = (char*)PR_Calloc(subSize+1, sizeof(char));
if (newID != NULL) {
memcpy(newID, *idString, subSize);
PR_Free(*idString);
*idString = PL_strdup(newID);
PR_Free(newID);
}
}
loser:
return;
}
/* Function: char* SSM_PROF_WinGetDefaultProfileDB()
* Purpose: tries to deduce the default profile db of the current version of
* Communicator
* Arguments and return values:
* - returns: newly allocated profile db string; NULL if failure
*
* Note: This is Nova-specific. Now, this function is being used to supply
* the "default" profile directory for 3rd party applications.
* Key: "HKEY_LOCAL_MACHINE\SOFTWARE\Netscape\Netscape Navigator\(current
* version)\Main\Install Directory"
*/
char* SSM_PROF_WinGetDefaultProfileDB(void)
{
char* subKey = "SOFTWARE\\Netscape\\Netscape Navigator";
LONG rv;
char* ret = NULL;
HKEY keyRet = NULL;
char* cvString = NULL;
char* idKey = NULL;
char* idString = NULL;
/* open the program registry */
rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, (DWORD)0, KEY_QUERY_VALUE,
&keyRet);
if (rv != ERROR_SUCCESS) {
return ret;
}
/* get the current version info first */
cvString = SSM_PREF_WinRegQueryCharValueEx(keyRet, "currentVersion");
if (cvString == NULL) {
goto loser;
}
/* now, get the actual default install directory for the current version */
idKey = PR_smprintf("%s\\%s\\Main", subKey, cvString);
if (idKey == NULL) {
goto loser;
}
/* open a new key for the install directory */
RegCloseKey(keyRet);
rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, idKey, (DWORD)0, KEY_QUERY_VALUE,
&keyRet);
if (rv != ERROR_SUCCESS) {
return ret;
}
idString = SSM_PREF_WinRegQueryCharValueEx(keyRet, "Install Directory");
if (idString == NULL) {
goto loser;
}
/* wait, we would like to remove "Communicator" at the end of the
* installation path to get the profiles directory correctly
*/
ssm_prof_cut_idstring(&idString);
if (idString == NULL) {
goto loser;
}
/* append the user name */
ret = PR_smprintf("%s\\Users", idString);
if (ret == NULL) {
goto loser;
}
goto done;
loser:
if (ret != NULL) {
PR_Free(ret);
ret = NULL;
}
done:
if (cvString != NULL) {
PR_Free(cvString);
}
if (idKey != NULL) {
PR_Free(idKey);
}
if (idString != NULL) {
PR_Free(idString);
}
if (keyRet != NULL) {
RegCloseKey(keyRet);
}
return ret;
}
/* allocates memory for and retrieves string data from the Windows registry
* (wrapper for RegQueryValueEx())
* this should be incorporated in the prefs headers later
* Warning: key should have been already opened with RegOpenKeyEx()!
*/
char* SSM_PREF_WinRegQueryCharValueEx(HKEY key, const char* subKey)
{
LONG rv;
DWORD type;
DWORD size = 0;
char* data = NULL;
PR_ASSERT(key != NULL && subKey != NULL);
/* size the string */
rv = RegQueryValueEx(key, (LPTSTR)subKey, NULL, &type, NULL, &size);
if (rv != ERROR_SUCCESS || size == 0) {
goto loser;
}
data = (char*)PR_Malloc(size);
if (data == NULL) {
goto loser;
}
rv = RegQueryValueEx(key, (LPTSTR)subKey, NULL, &type, (LPBYTE)data,
&size);
if (rv != ERROR_SUCCESS || size == 0) {
goto loser;
}
goto done;
loser:
if (data != NULL) {
PR_Free(data);
data = NULL;
}
done:
return data;
}
#endif

View File

@ -0,0 +1,50 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_PROFILE_H__
#define __SSM_PROFILE_H__
#include "ctrlconn.h"
/* Function: char* SSM_PROF_GetProfileDirectory()
* Purpose: given the control connection, locates the profile directory which
* contains the cert/key database
* Arguments and return values:
* - conn: control connection; the most useful information here is the
* profile name (or lack thereof) and the type of client (not used
* actively yet)
* - returns: char* string for the profile path; the existence of the directory
* is also checked; the string should be freed by the caller
*/
char* SSM_PROF_GetProfileDirectory(SSMControlConnection* conn);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,576 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
/*
SSMResource is the base class for anything that wants to be accessible
to the NSM client.
To subclass from SSMResource, you *must* do the following:
* Define a resource type for your class in the SSMResourceType enumerated
type below.
* Embed an SSMResource struct as the first member of your class struct.
This is the way that polymorphism works in this class system: you can freely
change type on a pointer to an SSMResource or its subclasses, because
the memory pointed to is guaranteed to consist of the base class followed
by subclass members. Subsequently, to subclass from any subclass of
SSMResource, you must embed an instance of the existing class as the
first member of your subclass.
(This is how it's done in C++, btw. Why don't we use C++, you ask?
Because of variations among C++ compilers, and because the rest of the
group will hate us if we do.)
* Provide the following member functions for your class:
- SSMStatus YourClassName_Create (void *arg, SSMResource **res)
Requirement: MANDATORY
Description: This creates an instance of your class. Necessary because
you need to allocate a properly sized chunk of memory,
and because the _Create routine also must call the correct
_Init method to properly initialize member data.
Parameters: arg - an initialization argument specific to the class.
res - Returns the newly created instance, or NULL if error.
Return value - PR_SUCCESS for success, etc.
- SSMStatus YourClassName_Init([signature varies])
Requirement: MANDATORY
Description: This initializes member data in your class.
Parameters: Dependent on how your class needs to be initialized.
The calling convention is used only by your _Create method,
and by the _Init method of all subclasses of your class.
- SSMStatus YourClassName_Destroy(SSMResource *res, PRBool doFree)
Requirement: MANDATORY
Description: This deallocates member data in an instance of your
class, and optionally deallocates the class instance
itself (if doFree is true). When calling superclass
_Destroy functions, should always pass PR_FALSE in
doFree. The default method deallocates the object with
PR_Free.
Parameters: res - An instance of your class.
doFree - if PR_TRUE, you must free (res). Presumably,
if doFree is true, then this object was created
by your _Create method above, so use whatever
memory deallocator corresponds to how the
instance was allocated in _Create.
Return value - PR_SUCCESS if successful, etc.
- SSMStatus YourClassName_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count)
Requirement: MANDATORY
Description: This is called when the client or part of the NSM server
wants to know all the available attributes of a particular
object.
Parameters: res - An instance of your class.
ids - Returns an array (allocated with PR_CALLOC) of
the available IDs.
count - Returns the number of IDs in (ids).
Return value - PR_SUCCESS if successful
(Other underlying errors as appropriate)
- SSMStatus YourClassName_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value)
Requirement: MANDATORY
Description: This is called when a client requests data from an
instance of your class. The default method simply
returns PR_FAILURE.
Parameters: res - An instance of your class.
attrID - The ID of the requested member data.
value - The attribute value struct to be filled in.
Return value - PR_SUCCESS if successful
SSM_ERR_BAD_FID: Field ID is incorrect.
(Other underlying errors as appropriate)
- SSMStatus YourClassName_SetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value)
Requirement: Optional
Description: This is called when a client wants to change a member
of an instance of your class. This only needs to be
implemented if you want to accept values from the
client (most classes will not want to do this). The
default method simply returns PR_FAILURE.
Parameters: res - An instance of your class.
attrID - The ID of the member to be changed.
value - The value to set the attribute to.
Return value - PR_SUCCESS if successful
SSM_ERR_BAD_FID: Field ID is incorrect.
SSM_ERR_ATTRTYPE_MISMATCH: Type mismatch
(Other underlying errors as appropriate)
- void YourClassName_Invariant(YourClassName *obj)
Requirement: Optional (but recommended)
Description: Performs invariant checking on member data particular
to your class. Normally this is done by calling PR_ASSERT
on typical expected conditions in your member data.
Your invariant method should call the superclass' Invariant
method to ensure proper invariant checking of the whole
instance.
Parameters: obj - An instance of your class.
Return value - PR_SUCCESS if successful
(Errors as appropriate)
* Register your class by making a call to SSM_RegisterResourceType
from inside SSM_ResourceInit in resource.c, passing whatever
methods your class overrides. Note that in some subclasses (such as
SSMConnection), additional virtual functions are provided for other
polymorphic functionality. You'll need to override those methods
inside your _Init routine directly.
*/
#ifndef __SSM_RESOURCE_H__
#define __SSM_RESOURCE_H__
#include "ssmdefs.h"
#include "ssmerrs.h"
#include "rsrcids.h"
#include "hashtbl.h"
#include "protocol.h"
#include "protocolf.h"
#include "prtypes.h"
#include "nspr.h"
#include "serv.h"
#include "collectn.h"
/* typedef struct SSMResource SSMResource; */
/* SSMControlConnection is defined in ctrlcon.h */
/* typedef struct SSMControlConnection SSMControlConnection; */
typedef struct HTTPRequest HTTPRequest;
typedef SSMStatus (*SSMResourceCreateFunc) (void *arg,
SSMControlConnection * conn,
SSMResource **res);
typedef SSMStatus (*SSMResourceDestroyFunc)(SSMResource *res, PRBool doFree);
typedef SSMStatus (*SSMResourceGetAttrIDsFunc)(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
typedef SSMStatus (*SSMResourceGetAttrFunc)(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
typedef SSMStatus (*SSMResourceSetAttrFunc)(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value);
typedef SSMStatus (*SSMResourceShutdownFunc)(SSMResource *res,
SSMStatus status);
typedef SSMStatus (*SSMResourcePickleFunc)(SSMResource *res,
PRIntn * len,
void **value);
typedef SSMStatus (*SSMResourceUnpickleFunc)(SSMResource ** res,
SSMControlConnection * conn,
PRIntn len, void * value);
typedef SSMStatus (*SSMResourceHTMLFunc)(SSMResource *res,
PRIntn * len,
void ** value);
/* be sure to include <nlsutil.h> before your implementations */
typedef SSMStatus (*SSMResourcePrintFunc)(SSMResource *res,
char *fmt,
PRIntn numParams,
char ** value,
char **resultStr);
typedef SSMStatus (*SSMSubmitHandlerFunc)(struct SSMResource *res,
HTTPRequest *req);
/* What do we do with a resource when the client wants to destroy it? */
typedef enum
{
SSM_CLIENTDEST_NOTHING = (PRUint32) 0, /* take no action */
SSM_CLIENTDEST_FREE, /* free the resource */
SSM_CLIENTDEST_SHUTDOWN /* shut down threads
before freeing object */
} SSMClientDestroyAction;
typedef enum
{
SSM_BUTTON_NONE = 0,
SSM_BUTTON_CANCEL,
SSM_BUTTON_OK
} SSMUIButtonType;
typedef struct SSMResourceClass SSMResourceClass;
/* typedef struct SSMResource SSMResource; */
struct SSMResource
{
SSMResourceClass *m_class; /* Pointer to class object */
SSMResourceID m_id;
SSMResourceType m_classType;
SSMControlConnection* m_connection; /* Control connection
that owns the resource */
SSMStatus m_status; /* Status of last closing thread.
Indicates whether to do an
emergency shutdown (interrupt all
threads, post shutdown msgs, etc.)
or to allow continuing operation. */
PRIntn m_threadCount; /* Number of service threads */
PRMonitor * m_lock; /* Thread lock for this connection
object */
PRMonitor * m_UILock; /* Use this lock for waiting and
* notifying for UI events.
*/
PRBool m_UIBoolean; /* This value is set by the Notify
* on UILock.
*/
PRIntn m_refCount; /* Reference count */
PRIntn m_clientCount; /* Number of client references */
SSMUIButtonType m_buttonType; /* This will be set when a UI event
* button event happens and the
* target is the resource.
*/
char * m_formName; /* The name of the form that created
* the UI event causing the form submit
* handler to get called.
*/
char * m_fileName; /* If this object requested a file path,
* then this field will be used to
* store the returned value.
*/
void * m_uiData; /* Using this value to pass misc UI
* information.
*/
CMTItem m_clientContext; /* This is set by client and passed back
* to client during UI operations */
PRThread * m_waitThread; /*Thread waiting for us to shut down*/
SSMClientDestroyAction m_clientDest;/* what to do if client destroys us */
SSMResourceDestroyFunc m_destroy_func;
SSMResourceShutdownFunc m_shutdown_func;
SSMResourceGetAttrIDsFunc m_getids_func;
SSMResourceGetAttrFunc m_get_func;
SSMResourceSetAttrFunc m_set_func;
SSMResourcePickleFunc m_pickle_func;
SSMResourceHTMLFunc m_html_func;
SSMResourcePrintFunc m_print_func;
SSMSubmitHandlerFunc m_submit_func;
PRBool m_resourceShutdown;
};
/* Macros */
#define RESOURCE_CLASS(x) ( ((SSMResource *) (x))->m_classType )
/************************************************************
** FUNCTION: SSM_CreateResource
**
** DESCRIPTION: Create a new resource of type (type). If (rawData)
** is not NULL, get initial values from that structure.
** rawData is treated differently depending on the type
** of resource being created; for example, a certificate
** object will store a reference to the certificate
** structure in (rawData), whereas a connection resource
** will copy values out of an SSMHashTable pointed to
** by (rawData).
** INPUTS:
** type
** The type of resource to be created.
** arg
** A type-dependent initial value for attribute(s) of the newly
** created resource.
** resID
** Returns the ID of the newly created resource.
** result
** Returns a pointer to the newly created resource.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or the underlying NSPR error,
** if it is available.
**
*************************************************************/
SSMStatus SSM_CreateResource(SSMResourceType type,
void *arg,
SSMControlConnection * conn,
SSMResourceID *resID,
SSMResource **result);
/************************************************************
** FUNCTION: SSM_GetResAttribute
**
** DESCRIPTION: Get an attribute from an SSMResource object.
**
** INPUTS:
** res
** The resource from which an attribute is to be retrieved.
** attrID
** The field/resource ID of the attribute.
** attrType
** The expected type of the retrieved attribute.
** value
** The attribute value to be filled in.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or the underlying NSPR error,
** if it is available.
**
** NOTES:
** ### mwelch All this memory allocation can be problematic.
*************************************************************/
SSMStatus SSM_GetResAttribute(SSMResource *res, SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
/************************************************************
** FUNCTION: SSM_SetResAttribute
**
** DESCRIPTION: Set an attribute on an SSMResource object. If
** the attribute does not yet exist, it is created.
**
** INPUTS:
** res
** The resource in which an attribute is to be changed.
** attrID
** The field/resource ID of the attribute.
** value
** A pointer to the value of the newly changed attribute. The value
** is copied into the resource.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or the underlying NSPR error,
** if it is available.
*************************************************************/
SSMStatus SSM_SetResAttribute(SSMResource *res, SSMAttributeID attrID,
SSMAttributeValue *value);
/************************************************************
** FUNCTION: SSM_PickleResource
**
** DESCRIPTION: Pickle resource.
**
** INPUTS:
** res
** The resource to be pickled.
**
** OUTPUTS:
** len
** Length of the pickled blob.
** value
** Pickled resource.
**
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or NSPR error code.
*************************************************************/
SSMStatus
SSM_PickleResource(SSMResource * res, PRIntn * len, void ** value);
/************************************************************
** FUNCTION: SSM_FreeResource
**
** DESCRIPTION: Free a reference on (res). If the reference count
** reaches 0, (res) is destroyed.
**
** INPUTS:
** res
** The resource to be dereferenced.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or the underlying NSPR error,
** if it is available.
*************************************************************/
SSMStatus SSM_FreeResource(SSMResource *res);
/************************************************************
** FUNCTION: SSM_GetResourceReference
**
** DESCRIPTION: Get a reference on (res).
**
** INPUTS:
** res
** The resource to be referenced.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE or the underlying NSPR error,
** if it is available.
*************************************************************/
SSMStatus SSM_GetResourceReference(SSMResource *res);
/************************************************************
** FUNCTION: SSM_RegisterResourceType
**
** DESCRIPTION: Register a resource type within the Cartman server.
**
** INPUTS:
** type
** The new type to be registered.
** superClass
** Inherit functions from the already-registered superclass.
** if (superClass) is not SSM_RESTYPE_NULL and any function
** parameters below are NULL, those functions are inherited
** from the indicated superclass.
** createFunc, rDestFunc, setFunc, getFunc
** Accessor functions for the resource.
** RETURNS:
** If successful, returns PR_SUCCESS.
** If failed, returns either PR_FAILURE, the underlying NSPR error,
** or the following values:
** SSM_ERR_INVALID_FUNC: (superClass) was SSM_RESTYPE_NULL
** and one or more of the function parameters
** was also NULL.
*************************************************************/
SSMStatus SSM_RegisterResourceType(char * className,
SSMResourceType type,
SSMResourceType superClass,
SSMClientDestroyAction cDestAction,
SSMResourceCreateFunc createFunc,
SSMResourceDestroyFunc destFunc,
SSMResourceShutdownFunc shutdownFunc,
SSMResourceGetAttrIDsFunc getIDsFunc,
SSMResourceGetAttrFunc getFunc,
SSMResourceSetAttrFunc setFunc,
SSMResourcePickleFunc pickleFunc,
SSMResourceUnpickleFunc unpickleFunc,
SSMResourceHTMLFunc htmlFunc,
SSMResourcePrintFunc printFunc,
SSMSubmitHandlerFunc submitFunc);
PRBool SSM_IsA(SSMResource *res, SSMResourceType type);
PRBool SSM_IsAKindOf(SSMResource *res, SSMResourceType type);
SSMStatus SSM_ClientGetResourceReference(SSMResource *res, SSMResourceID *id);
SSMStatus SSM_ShutdownResource(SSMResource *res, SSMStatus status);
SSMStatus SSM_ClientDestroyResource(SSMControlConnection *connection,
SSMResourceID rid, SSMResourceType type);
void SSM_LockResource(SSMResource *res);
SSMStatus SSM_UnlockResource(SSMResource *res);
SSMStatus SSM_WaitResource(SSMResource *res, PRIntervalTime ticks);
SSMStatus SSM_WaitForOKCancelEvent(SSMResource *res, PRIntervalTime ticks);
SSMStatus SSM_NotifyOKCancelEvent(SSMResource *res);
SSMStatus SSM_NotifyResource(SSMResource *res);
void SSM_LockUIEvent(SSMResource *res);
SSMStatus SSM_UnlockUIEvent(SSMResource *res);
SSMStatus SSM_WaitUIEvent(SSMResource *res, PRIntervalTime ticks);
SSMStatus SSM_NotifyUIEvent(SSMResource *);
SSMStatus SSM_PickleResource(SSMResource * res, PRIntn * len, void ** value);
SSMStatus SSM_UnpickleResource(SSMResource ** res, SSMResourceType type,
SSMControlConnection * connection,
PRIntn len, void * value);
SSMStatus SSM_MessageFormatResource(SSMResource *res, char *fmt, PRIntn numParam,
char ** value,
char **resultStr);
SSMStatus SSMResource_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMResource_Destroy(SSMResource *res, PRBool doFree);
SSMStatus SSMResource_Shutdown(SSMResource *res, SSMStatus status);
SSMStatus SSMResource_Init(SSMControlConnection * conn, SSMResource *res,
SSMResourceType type);
void SSMResource_Invariant(SSMResource *res);
SSMStatus SSMResource_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMResource_SetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMAttributeValue *value);
SSMStatus SSMResource_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMResource_Pickle(SSMResource *res,
PRIntn * len,
void **value);
SSMStatus SSMResource_Unpickle(SSMResource ** res,
SSMControlConnection *conn,
PRIntn len,
void * value);
SSMStatus SSMResource_HTML(SSMResource *res,
PRIntn * len,
void ** value);
SSMStatus SSMResource_Print(SSMResource *res,
char *fmt,
PRIntn numParam,
char **value,
char **resultStr);
SSMStatus SSMResource_FormSubmitHandler(SSMResource *res,
HTTPRequest *req);
/* ALWAYS pass in msg a string allocated by NSPR (PR_smprintf for example),
because the string is freed from within SSM_Debug. */
void SSM_Debug(SSMResource *res, char *msg);
char * SSM_ResourceClassName(SSMResource *res);
/* Wait for a resource to shut down. */
SSMStatus SSM_WaitForResourceShutdown(SSMResource *res);
/* Register a thread with a resource (or pass arg==NULL for standalone) */
void SSM_RegisterThread(char *threadName, SSMResource *arg);
void SSM_RegisterNewThread(char *threadName, SSMResource *ptr);
SSMStatus
SSM_ShutdownResource(SSMResource *res, SSMStatus status);
SSMStatus SSM_HandlePromptReply(SSMResource *res, char *reply);
/* Initialize resources. Only called by main. */
SSMStatus SSM_ResourceInit();
/* Create a resource thread */
PRThread *
SSM_CreateThread(SSMResource *res, void (*func)(void *arg));
#endif

179
security/psm/server/serv.h Normal file
View File

@ -0,0 +1,179 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SERV_H__
#define __SERV_H__
#include "prio.h"
#include "prtypes.h"
#include "prnetdb.h"
#include "prprf.h"
#include "prinit.h"
#include "prthread.h"
#include "prinrval.h"
#include "prmon.h"
#include "prmem.h"
#include "prerror.h"
#include <stdlib.h>
#include "seccomon.h"
#include "ssmdefs.h"
#include "servimpl.h"
#include "protocol.h"
#include "ssmerrs.h"
/* extern int errno; */
#undef ALLOW_STANDALONE
#ifdef ALLOW_STANDALONE
extern PRBool standalone;
#define SSM_ENV_STANDALONE "NSM_STANDALONE"
#endif
/* Environment variables we pay attention to */
#ifdef DEBUG
#define SSM_ENV_SUPPRESS_CONSOLE "NSM_SUPPRESS_CONSOLE"
#define SSM_ENV_LOG_FILE "NSM_LOG_FILE"
/* Password must be base64 encoded. */
#define SSM_ENV_STATIC_PASSWORD "NSM_PASSWORD"
#endif
#define MAX_CONNECTIONS 5
#define LINESIZE 512
#define DATA_CONN_MSG_SIZE sizeof(PRFileDesc *)
#define CARTMAN_WAIT_BEFORE_SLEEP (PR_TicksPerSecond() * 60)
#define CARTMAN_SPINTIME CARTMAN_WAIT_BEFORE_SLEEP
#define CARTMAN_KEEP_CONNECTION_ALIVE (CARTMAN_WAIT_BEFORE_SLEEP * 900)
/* Some macros to cut down typing when doing memory allocation.*/
#define SSM_NEW PR_NEW
#define SSM_ZNEW PR_NEWZAP
#define SSM_NEW_ARRAY(type,size) (type*)PR_Malloc((size)*sizeof(type))
#define SSM_ZNEW_ARRAY(type,size) (type*)PR_Calloc((size),sizeof(type))
/* Safe strcmp() which compares only based on the shorter
of the two lengths. DO NOT USE if you really want to determine
string equality -- this is used for sloppy parameter matches. */
#define MIN_STRCMP(x,y) strncmp((x), (y), MIN(strlen(x),strlen(y)))
/* forward declare this type to eliminate circular dependencies */
typedef struct SSMResource SSMResource;
typedef struct SSMControlConnection SSMControlConnection;
extern PRUint32 httpPort;
PRIntn mainLoop(PRIntn argc, char ** argv);
PRFileDesc * SSM_OpenControlPort(void);
PRFileDesc * SSM_OpenPort(void);
PRBool SSM_SocketPeerCheck(PRFileDesc *sock, PRBool isCtrl);
SSMPolicyType SSM_GetPolicy(void);
#define THREAD_NAME_LEN 128
SSMStatus SSM_AddLogSocket(PRFileDesc *sock);
void SSM_DebugP(char *fmt, ...);
#if defined(WIN32)
#define STRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n))
#elif defined(XP_UNIX)
#define STRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n))
#else
/* Should really figure out how this platform does this */
int SSM_strncasecmp(const char *s1, const char *s2, size_t count);
#define STRNCASECMP(s1,s2,n) SSM_strncasecmp((s1),(s2),(n))
#endif
#ifdef DEBUG
#define SSM_DEBUG SSM_DebugP
#else
#define SSM_DEBUG if(0) SSM_DebugP
#endif
void SSM_DumpBuffer(char *buf, PRIntn len);
SECItem * SSM_ConstructMessage(PRUintn size);
void SSM_FreeEvent(SECItem * event);
void SSM_FreeResponse(SSMResponse * response);
void SSM_FreeMessage(SECItem * msg);
int ssm_ReadThisMany(PRFileDesc * sockID, void * buffer, int thisMany);
int ssm_WriteThisMany(PRFileDesc * sockID, void * buffer, int thisMany);
/* Macros used in http and base64 processing */
#undef IS_EOL
#define IS_EOL(c) (((c) == 0x0A) || ((c) == 0x0D))
#undef IS_WHITESPACE
#define IS_WHITESPACE(c) (((c) == '\t') || ((c) == '\n') \
|| ((c) == '\r') || ((c) == ' '))
extern SSMPolicyType policyType;
SSMStatus SSM_CloseSocketWithLinger(PRFileDesc *sock);
SSMStatus SSM_RequestFilePathFromUser(SSMResource *res,
const char *promptKey,
const char *fileRegEx,
PRBool getExistingFile);
char* SSM_GetCharFromKey(const char *key, const char *locale);
void SSM_HandleFilePathReply(SSMControlConnection *ctrl,
SECItem *msg);
void SSM_HandleUserPromptReply(SSMControlConnection *ctrl,
SECItem *msg);
char * SSM_ConvertStringToHTMLString(char * string);
SSMStatus SSM_CopyCMTItem(CMTItem *dest, CMTItem *source);
#ifdef XP_UNIX
void SSM_ReleaseLockFile();
#endif /*XP_UNIX*/
/* Function used on Mac to register threads for later destruction at app quit time. */
#ifdef XP_MAC
PRThread * SSM_CreateAndRegisterThread(PRThreadType type,
void (*start)(void *arg),
void *arg,
PRThreadPriority priority,
PRThreadScope scope,
PRThreadState state,
PRUint32 stackSize);
void SSM_KillAllThreads(void);
#else
#define SSM_CreateAndRegisterThread PR_CreateThread
#endif
#endif

View File

@ -0,0 +1,83 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SERVIMPL_H__
#define __SERVIMPL_H__
#include "ssmdefs.h"
#include "collectn.h"
#include "hashtbl.h"
/* Doc subdirectory */
#ifdef XP_UNIX
#define PSM_DOC_DIR "./doc/"
#else
#ifdef XP_MAC
#define PSM_DOC_DIR ":doc:"
#else
#define PSM_DOC_DIR ".\\doc\\"
#endif
#endif
/* Messages passed between data service threads */
typedef enum
{
SSM_DATA_BUFFER = (PRIntn) 0, /* "Here's data to write" */
SSM_DATA_PROVIDER_OPEN, /* "My end is open, about to queue data" */
SSM_DATA_PROVIDER_SHUTDOWN /* "My socket has closed" */
} SSMDataMessageType;
typedef struct _SSMResponse SSMResponse;
typedef struct _SSMResponseQueue SSMResponseQueue;
void SSM_InitNLS(char *dataDirectory);
SECItem * SSM_ConstructMessage(PRUintn size);
void SSM_FreeEvent(SECItem * event);
void SSM_FreeResponse(SSMResponse * response);
void SSM_FreeMessage(SECItem * msg);
int SSM_ReadThisMany(PRFileDesc * sockID, void * buffer, int thisMany);
int SSM_WriteThisMany(PRFileDesc * sockID, void * buffer, int thisMany);
SSMStatus SSM_SendQMessage(SSMCollection *c,
PRIntn priority,
PRIntn type, PRIntn length, char *data,
PRBool doBlock);
SSMStatus SSM_RecvQMessage(SSMCollection *c,
PRIntn priority,
PRIntn *type, PRIntn *length, char **data,
PRBool doBlock);
void ssm_DrainAndDestroyQueue(SSMCollection **coll);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,584 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "serv.h"
#include "minihttp.h"
#include "signtextres.h"
#include "protocolf.h"
#include "base64.h"
#include "secmime.h"
#include "newproto.h"
#include "messages.h"
#include "certres.h"
#define SSMRESOURCE(object) (&(object)->super)
SSMStatus
SSM_CreateSignTextRequest(SECItem *msg, SSMControlConnection *conn)
{
SSMStatus rv;
SSMSignTextResource *signTextRes = NULL;
int i;
SignTextRequest request;
/* Decode the sign text protocol message */
if (CMT_DecodeMessage(SignTextRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
goto loser;
}
/* Get the resource */
rv = SSMControlConnection_GetResource(conn, (SSMResourceID)request.resID,
(SSMResource**)&signTextRes);
if ((rv != PR_SUCCESS) || (signTextRes == NULL)) {
goto loser;
}
/* Get a reference to it */
SSM_GetResourceReference(SSMRESOURCE(signTextRes));
if (!SSM_IsAKindOf(SSMRESOURCE(signTextRes), SSM_RESTYPE_SIGNTEXT)) {
goto loser;
}
/* Set the request data */
signTextRes->m_stringToSign = PL_strdup(request.stringToSign);
signTextRes->m_hostName = PL_strdup(request.hostName);
if (PL_strcasecmp(request.caOption, "auto") == 0) {
signTextRes->m_autoFlag = PR_TRUE;
} else if (PL_strcasecmp(request.caOption, "ask") == 0) {
signTextRes->m_autoFlag = PR_FALSE;
} else {
goto loser;
}
signTextRes->m_numCAs = request.numCAs;
if (signTextRes->m_numCAs > 0) {
signTextRes->m_caNames = (char **) PR_CALLOC(sizeof(char*)*(signTextRes->m_numCAs));
if (!signTextRes->m_caNames) {
goto loser;
}
for (i=0;i<signTextRes->m_numCAs;i++) {
signTextRes->m_caNames[i] = PL_strdup(request.caNames[i]);
}
}
signTextRes->m_conn = conn;
signTextRes->m_action = SIGN_TEXT_WAITING;
signTextRes->m_thread = SSM_CreateAndRegisterThread(PR_USER_THREAD,
SSMSignTextResource_ServiceThread,
(void*)signTextRes,
PR_PRIORITY_NORMAL,
PR_LOCAL_THREAD,
PR_UNJOINABLE_THREAD, 0);
if (!signTextRes->m_thread) {
goto loser;
}
return PR_SUCCESS;
loser:
/* XXX Free request */
return PR_FAILURE;
}
SSMStatus
SSMSignTextResource_Create(void *arg, SSMControlConnection * conn, SSMResource **res)
{
SSMSignTextResource *signTextRes;
SSMStatus rv;
signTextRes = PR_NEWZAP(SSMSignTextResource);
if (!signTextRes) {
goto loser;
}
rv = SSMSignTextResource_Init(conn, signTextRes, SSM_RESTYPE_SIGNTEXT);
if (rv != PR_SUCCESS) {
goto loser;
}
*res = SSMRESOURCE(signTextRes);
return PR_SUCCESS;
loser:
if (signTextRes != NULL) {
SSM_FreeResource(SSMRESOURCE(signTextRes));
}
*res = NULL;
return PR_FAILURE;
}
SSMStatus
SSMSignTextResource_Init(SSMControlConnection *conn, SSMSignTextResource *in,
SSMResourceType type)
{
SSMStatus rv;
rv = SSMResource_Init(conn, SSMRESOURCE(in), type);
if (rv != PR_SUCCESS) {
goto loser;
}
/* Set all our data to zero */
in->m_stringToSign = NULL;
in->m_hostName = NULL;
in->m_autoFlag = PR_FALSE;
in->m_numCAs = 0;
in->m_caNames = NULL;
in->m_conn = conn;
in->m_thread = NULL;
in->m_certs = NULL;
in->m_action = SIGN_TEXT_INIT;
in->m_nickname = NULL;
in->m_resultString = NULL;
return PR_SUCCESS;
loser:
return PR_FAILURE;
}
SSMStatus SSMSignTextResource_Destroy(SSMResource *res, PRBool doFree)
{
SSMSignTextResource *signTextRes = (SSMSignTextResource*)res;
if (res == NULL) {
return PR_FAILURE;
}
PR_ASSERT(res->m_threadCount == 0);
/* Free our data */
/* Destroy the super class */
SSMResource_Destroy(res, PR_FALSE);
/* Free our memory */
if (doFree) {
PR_DELETE(signTextRes);
}
return PR_SUCCESS;
}
SSMStatus SSMSignTextResource_Shutdown(SSMResource *arg, SSMStatus status)
{
return PR_SUCCESS;
}
void
SSMSignTextResource_SendTaskCompletedEvent(SSMSignTextResource *res)
{
SECItem msg;
SSMStatus rv;
TaskCompletedEvent event;
/* Assemble the event. */
SSM_DEBUG("Sign Text Resource Task completed event: id %ld, status %d\n",
SSMRESOURCE(res)->m_id, SSMRESOURCE(res)->m_status);
event.resourceID = SSMRESOURCE(res)->m_id;
event.numTasks = 0;
event.result = SSMRESOURCE(res)->m_status;
if (CMT_EncodeMessage(TaskCompletedEventTemplate, (CMTItem*)&msg, &event) != CMTSuccess) {
return;
}
if (msg.data) {
/* Send the event to the control queue. */
rv = SSM_SendQMessage(SSMRESOURCE(res)->m_connection->m_controlOutQ,
SSM_PRIORITY_NORMAL,
SSM_EVENT_MESSAGE | SSM_TASK_COMPLETED_EVENT,
(int) msg.len, (char *) msg.data, PR_FALSE);
SSM_DEBUG("Sent message, rv = %d.\n", rv);
}
}
void
SSMSignTextResource_ServiceThread(void *arg)
{
SSMSignTextResource *signTextRes = (SSMSignTextResource*)arg;
SSMStatus rv;
unsigned char hashVal[SHA1_LENGTH];
SECItem digest, signedResult, *tmpItem;
SEC_PKCS7ContentInfo *ci = NULL;
CERTCertificate *cert = NULL;
CERTCertListNode *node;
int i,numCerts;
SSM_LockResource(SSMRESOURCE(signTextRes));
PR_ASSERT(signTextRes);
PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(signTextRes), SSM_RESTYPE_SIGNTEXT));
memset(&signedResult, 0, sizeof(SECItem));
/* Get the certificates */
signTextRes->m_certs = CERT_MatchUserCert(signTextRes->m_conn->m_certdb,
certUsageEmailSigner,
signTextRes->m_numCAs,
signTextRes->m_caNames,
signTextRes->m_conn);
numCerts = SSM_CertListCount(signTextRes->m_certs);
if((signTextRes->m_certs == NULL) || (numCerts == 0)) {
signTextRes->m_resultString = strdup("error:noMatchingCert");
goto loser;
}
/* Send UI event to client */
if (signTextRes->m_autoFlag == PR_TRUE) {
rv = SSMControlConnection_SendUIEvent(signTextRes->m_conn, "get", "signtext_auto", SSMRESOURCE(signTextRes), NULL,
&SSMRESOURCE(signTextRes)->m_clientContext);
} else {
rv = SSMControlConnection_SendUIEvent(signTextRes->m_conn, "get", "signtext_ask", SSMRESOURCE(signTextRes), NULL,
&SSMRESOURCE(signTextRes)->m_clientContext);
}
if (rv != PR_SUCCESS) {
goto loser;
}
/* Here we wait for the user to confirm or deny the signing */
SSM_WaitResource(SSMRESOURCE(signTextRes), PR_INTERVAL_NO_TIMEOUT);
switch (SSMRESOURCE(signTextRes)->m_buttonType) {
case SSM_BUTTON_OK:
/* Get the signing cert */
node = (CERTCertListNode *)PR_LIST_HEAD(&signTextRes->m_certs->list);
if (signTextRes->m_nickname == NULL ) {
/* this is the "auto" case */
cert = node->cert;
} else {
/* this is the "ask" case */
for ( i = 0; i < numCerts; i++ ) {
if ( PL_strcasecmp(signTextRes->m_nickname, node->cert->nickname) == 0 ) {
cert = node->cert;
break;
}
node = (struct CERTCertListNodeStr *) node->links.next;
}
}
/* Hash the string to be signed */
rv = HASH_HashBuf(HASH_AlgSHA1, hashVal,
(unsigned char *) signTextRes->m_stringToSign,
strlen(signTextRes->m_stringToSign));
if (rv != SECSuccess) {
goto loser;
}
digest.len = SHA1_LENGTH;
digest.data = hashVal;
/* Sign the hash */
ci = SECMIME_CreateSigned(cert, cert, cert->dbhandle, SEC_OID_SHA1,
&digest, NULL, signTextRes->m_conn);
if (ci == NULL) {
goto loser;
}
/* Create the PKCS#7 object */
tmpItem = SEC_PKCS7EncodeItem(NULL, &signedResult, ci, NULL, NULL,
signTextRes->m_conn);
if (tmpItem != &signedResult) {
goto loser;
}
/* Convert the result to base 64 */
signTextRes->m_resultString = BTOA_DataToAscii(signedResult.data, signedResult.len);
if (signTextRes->m_resultString == NULL) {
goto loser;
}
break;
case SSM_BUTTON_CANCEL:
signTextRes->m_resultString= PL_strdup("error:userCancel");
break;
default:
break;
}
SSM_UnlockResource(SSMRESOURCE(signTextRes));
loser:
/* Free data */
if (signTextRes->m_stringToSign) {
PR_Free(signTextRes->m_stringToSign);
}
if (signTextRes->m_hostName) {
PR_Free(signTextRes->m_hostName);
}
if (signTextRes->m_certs) {
CERT_DestroyCertList(signTextRes->m_certs);
}
/* Send the task complete event here */
SSMSignTextResource_SendTaskCompletedEvent(signTextRes);
return;
}
SSMStatus
SSMSignTextResource_Print(SSMResource *res,
char *fmt,
PRIntn numParam,
char ** value,
char **resultStr)
{
char *hostName = NULL, *stringToSign = NULL;
SSMSignTextResource *signTextRes = (SSMSignTextResource*)res;
hostName = signTextRes->m_hostName;
stringToSign = signTextRes->m_stringToSign;
if (numParam)
SSMResource_Print(res, fmt, numParam, value, resultStr);
else if (signTextRes->m_autoFlag) {
CERTCertListNode *node;
CERTCertificate *cert;
/* Get the cert nickname */
node = (CERTCertListNode*)PR_LIST_HEAD(&signTextRes->m_certs->list);
cert = node->cert;
/* Get the nickname */
*resultStr = PR_smprintf(fmt, signTextRes->super.m_id, hostName,
stringToSign, cert->nickname);
} else {
*resultStr = PR_smprintf(fmt, signTextRes->super.m_id, hostName,
stringToSign);
}
return (*resultStr != NULL) ? PR_SUCCESS : PR_FAILURE;
}
SSMStatus
SSMSignTextResource_GetAttr(SSMResource *res, SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMSignTextResource *signTextRes = (SSMSignTextResource*)res;
if (!signTextRes || !signTextRes->m_resultString) {
goto loser;
}
switch (attrID) {
case SSM_FID_SIGNTEXT_RESULT:
if (!signTextRes->m_resultString) {
goto loser;
}
value->type = SSM_STRING_ATTRIBUTE;
value->u.string.len = PL_strlen(signTextRes->m_resultString);
value->u.string.data = (unsigned char *) PL_strdup(signTextRes->m_resultString);
break;
default:
goto loser;
}
return PR_SUCCESS;
loser:
return PR_FAILURE;
}
SSMStatus
SSMSignTextResource_FormSubmitHandler(SSMResource* res,
HTTPRequest* req)
{
SSMStatus rv;
char* tmpStr;
SSMSignTextResource *signTextRes = (SSMSignTextResource*)res;
SSM_LockResource(res);
rv = SSM_HTTPParamValue(req, "baseRef", &tmpStr);
if (rv != SSM_SUCCESS ||
PL_strcmp(tmpStr, "windowclose_doclose_js") != 0) {
goto loser;
}
/* Detect which button was pressed */
if (res->m_buttonType == SSM_BUTTON_OK) {
/* Get the certificate nickname */
SSM_HTTPParamValue(req, "chose", &signTextRes->m_nickname);
}
loser:
/* Close the window */
SSM_HTTPCloseAndSleep(req);
/* Unblock the sign text thread waiting on this */
SSM_NotifyResource(res);
SSM_UnlockResource(res);
return rv;
}
SSMStatus SSM_SignTextCertListKeywordHandler(SSMTextGenContext* cx)
{
SSMStatus rv = SSM_SUCCESS;
SSMResource* target = NULL;
SSMSignTextResource* res;
char* prefix = NULL;
char* wrapper = NULL;
char* suffix = NULL;
char* tmpStr = NULL;
char* fmt = NULL;
const PRIntn CERT_LIST_PREFIX = (PRIntn)0;
const PRIntn CERT_LIST_WRAPPER = (PRIntn)1;
const PRIntn CERT_LIST_SUFFIX = (PRIntn)2;
const PRIntn CERT_LIST_PARAM_COUNT = (PRIntn)3;
/*
* make sure cx, cx->m_request, cx->m_params, cx->m_result are not
* NULL
*/
PR_ASSERT(cx != NULL && cx->m_request != NULL && cx->m_params != NULL &&
cx->m_result != NULL);
if (cx == NULL || cx->m_request == NULL || cx->m_params == NULL ||
cx->m_result == NULL) {
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
goto loser;
}
if (SSM_Count(cx->m_params) != CERT_LIST_PARAM_COUNT) {
SSM_HTTPReportSpecificError(cx->m_request, "_signtext_certList: ",
"Incorrect number of parameters "
" (%d supplied, %d needed).\n",
SSM_Count(cx->m_params),
CERT_LIST_PARAM_COUNT);
goto loser;
}
/* get the connection object */
target = SSMTextGen_GetTargetObject(cx);
PR_ASSERT(target != NULL);
res = (SSMSignTextResource*)target;
/* form the MessageFormat object */
/* find arguments (prefix, wrapper, and suffix) */
prefix = (char *) SSM_At(cx->m_params, CERT_LIST_PREFIX);
wrapper = (char *) SSM_At(cx->m_params, CERT_LIST_WRAPPER);
suffix = (char *) SSM_At(cx->m_params, CERT_LIST_SUFFIX);
PR_ASSERT(prefix != NULL && wrapper != NULL && suffix != NULL);
/* grab the prefix and expand it */
rv = SSM_GetAndExpandTextKeyedByString(cx, prefix, &tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
/* append the prefix */
rv = SSM_ConcatenateUTF8String(&cx->m_result, tmpStr);
SSMTextGen_UTF8StringClear(&tmpStr);
SSM_DebugUTF8String("signtext cert list prefix", cx->m_result);
/* grab the wrapper */
rv = SSM_GetAndExpandTextKeyedByString(cx, wrapper, &tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
SSM_DebugUTF8String("sign text cert list wrapper", fmt);
/* form the wrapped cert list UnicodeString */
rv = ssm_signtext_get_unicode_cert_list(res, tmpStr, &tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
/* append the wrapped cert list */
rv = SSM_ConcatenateUTF8String(&cx->m_result, tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
SSMTextGen_UTF8StringClear(&tmpStr);
/* grab the suffix and expand it */
rv = SSM_GetAndExpandTextKeyedByString(cx, suffix, &tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
SSM_DebugUTF8String("client cert list suffix", tmpStr);
/* append the suffix */
rv = SSM_ConcatenateUTF8String(&cx->m_result, tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
goto done;
loser:
if (rv == SSM_SUCCESS) {
rv = SSM_FAILURE;
}
done:
PR_FREEIF(fmt);
PR_FREEIF(tmpStr);
return rv;
}
/*
* Function: SSMStatus ssm_client_auth_get_unicode_cert_list()
* Purpose: forms the cert list UnicodeString
*
* Arguments and return values:
* - conn: SSL connection object
* - fmt: cert wrapper UnicodeString format
* - result: resulting UnicodeString
*
* Note: if we include the expired certs, we need to append to the end as
* well
*/
SSMStatus ssm_signtext_get_unicode_cert_list(SSMSignTextResource* res,
char* fmt,
char** result)
{
SSMStatus rv = SSM_SUCCESS;
char * tmpStr = NULL;
char * finalStr = NULL;
int i;
CERTCertListNode *head = NULL;
int numCerts;
PR_ASSERT(res != NULL && fmt != NULL && result != NULL);
/* in case we fail */
*result = NULL;
/* concatenate the string using the nicknames */
head = (CERTCertListNode *)PR_LIST_HEAD(&res->m_certs->list);
numCerts = SSM_CertListCount(res->m_certs);
for (i = 0; i < numCerts; i++) {
tmpStr = PR_smprintf(fmt, i, head->cert->nickname);
rv = SSM_ConcatenateUTF8String(&finalStr, tmpStr);
if (rv != SSM_SUCCESS) {
goto loser;
}
PR_Free(tmpStr);
tmpStr = NULL;
head = (CERTCertListNode *)head->links.next;
}
SSM_DebugUTF8String("client auth: final cert list", finalStr);
*result = finalStr;
return SSM_SUCCESS;
loser:
SSM_DEBUG("client auth: wrapping cert list failed.\n");
if (rv == SSM_SUCCESS) {
rv = SSM_FAILURE;
}
PR_FREEIF(finalStr);
PR_FREEIF(tmpStr);
return rv;
}

View File

@ -0,0 +1,81 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SIGNTEXTRES_H__
#define __SIGNTEXTRES_H__
#include "resource.h"
#include "ctrlconn.h"
#include "textgen.h"
typedef enum {
SIGN_TEXT_INIT,
SIGN_TEXT_WAITING,
SIGN_TEXT_OK,
SIGN_TEXT_CANCEL
} SignTextAction;
typedef struct
{
SSMResource super;
char *m_stringToSign;
char *m_hostName;
PRBool m_autoFlag;
PRInt32 m_numCAs;
char **m_caNames;
SSMControlConnection *m_conn;
PRThread *m_thread;
CERTCertList *m_certs;
SignTextAction m_action;
char *m_nickname;
char *m_resultString;
} SSMSignTextResource;
SSMStatus SSM_CreateSignTextRequest(SECItem* msg, SSMControlConnection* conn);
SSMStatus SSM_CreateNewSignTextRequest(SECItem *msg, SSMControlConnection *conn);
SSMStatus SSMSignTextResource_Create(void *arg, SSMControlConnection *conn, SSMResource **res);
SSMStatus SSMSignTextResource_Init(SSMControlConnection *conn, SSMSignTextResource *res, SSMResourceType type);
SSMStatus SSMSignTextResource_Destroy(SSMResource *res, PRBool doFree);
SSMStatus SSMSignTextResource_Shutdown(SSMResource *res, SSMStatus status);
SSMStatus SSMSignTextResource_GetAttr(SSMResource *res, SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMSignTextResource_Print(SSMResource *res, char *fmt, PRIntn numParam,
char ** value, char **resultStr);
SSMStatus SSMSignTextResource_FormSubmitHandler(SSMResource* res, HTTPRequest* req);
void SSMSignTextResource_ServiceThread(void *arg);
SSMStatus SSM_SignTextCertListKeywordHandler(SSMTextGenContext* cx);
SSMStatus ssm_signtext_get_unicode_cert_list(SSMSignTextResource* res,
char* fmt,
char** result);
SSMStatus SSM_CreateSignTextRequest(SECItem *msg, SSMControlConnection *conn);
#endif /* __SIGNTEXTRES_H__ */

280
security/psm/server/slist.c Normal file
View File

@ -0,0 +1,280 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "slist.h"
SSMSortedList *
SSMSortedList_New(SSMSortedListFn * functions)
{
SSMSortedList * list = NULL;
if (!functions)
goto loser;
list = PR_NEWZAP(SSMSortedList);
if (list == NULL)
goto loser;
list->lock = PR_NewMonitor();
if (list->lock == NULL)
goto loser;
list->func.keyCompare = functions->keyCompare;
list->func.freeListItemData = functions->freeListItemData;
list->func.freeListItemKey = functions->freeListItemKey;
PR_INIT_CLIST(&list->list);
list->nItems = 0;
return list;
loser:
if (list) {
if (list->lock)
PR_DestroyMonitor(list->lock);
PR_Free(list);
}
return NULL;
}
SSMStatus
SSMSortedList_Destroy(SSMSortedList *victim)
{
PRCList * link, *next;
if (!victim)
goto done;
PR_EnterMonitor(victim->lock);
/* free elements */
for(link = PR_LIST_HEAD(&victim->list); link != &victim->list;){
next = PR_NEXT_LINK(link);
slist_remove_item(victim, (SSMSortedListItem *)link, PR_TRUE);
link = next;
}
PR_ExitMonitor(victim->lock);
PR_ASSERT(victim->nItems == 0);
PR_DestroyMonitor(victim->lock);
PR_Free(victim);
done:
return SSM_SUCCESS;
}
SSMSortedListItem * slist_remove_item(SSMSortedList * list,
SSMSortedListItem * item,
PRBool doFree)
{
PR_REMOVE_LINK(&item->link);
list->nItems--;
if (doFree) {
list->func.freeListItemData(item->data);
list->func.freeListItemKey(item->key);
PR_Free(item);
return NULL;
}
else return item;
}
SSMStatus
SSMSortedList_Insert(SSMSortedList * slist, void * key, void * data)
{
SSMSortedListItem * item, * nextItem;
if (!slist)
goto loser;
item = slist_allocate_item(key, data);
if (!item)
goto loser;
PR_EnterMonitor(slist->lock);
nextItem = slist_find_next(slist, key);
PR_INSERT_BEFORE(&item->link, &nextItem->link);
slist->nItems++;
PR_ExitMonitor(slist->lock);
return SSM_SUCCESS;
loser:
return SSM_FAILURE;
}
SSMSortedListItem * slist_allocate_item(void * key, void * data)
{
SSMSortedListItem * item;
item = PR_NEWZAP(SSMSortedListItem);
if (item)
{
item->data = data;
item->key = key;
}
return item;
}
SSMStatus
SSMSortedList_Find(SSMSortedList * slist, void * key, void ** data)
{
SSMStatus rv = SSM_FAILURE;
SSMSortedListItem * item;
if (!slist || !data)
goto loser;
*data = NULL;
PR_EnterMonitor(slist->lock);
item = slist_find_item(slist, key);
if (item) {
*data = item->data;
rv = SSM_SUCCESS;
}
PR_ExitMonitor(slist->lock);
loser:
return rv;
}
SSMStatus
SSMSortedList_Remove(SSMSortedList * slist, void * key, void ** data)
{
SSMSortedListItem * item;
SSMStatus rv = SSM_FAILURE;
if (!slist)
goto loser;
PR_EnterMonitor(slist->lock);
item = slist_find_item(slist, key);
if (item) {
rv = SSM_SUCCESS;
if (data)
*data = item->data;
slist_remove_item(slist, item, PR_FALSE);
slist->func.freeListItemKey(item->key);
PR_Free(item);
}
PR_ExitMonitor(slist->lock);
loser:
return rv;
}
SSMStatus
SSMSortedList_FindNext(SSMSortedList * slist, void * key, void ** data)
{
SSMSortedListItem * item;
if (!slist || !data)
return SSM_FAILURE;
PR_EnterMonitor(slist->lock);
item = slist_find_next(slist, key);
*data = item->data;
PR_ExitMonitor(slist->lock);
return SSM_SUCCESS;
}
SSMSortedListItem *
slist_find_next(SSMSortedList * slist, void * key)
{
PRCList * link;
SSMSortedListItem * item;
for(link = PR_LIST_HEAD(&slist->list); link != &slist->list;
link = PR_NEXT_LINK(link))
if (slist->func.keyCompare(((SSMSortedListItem *)link)->key, key) > 0) {
/* insert here */
item = (SSMSortedListItem *)link;
goto done;
}
item = (SSMSortedListItem *)&slist->list;
done:
return item;
}
PRBool
SSMSortedList_Lookup(SSMSortedList * slist, void * key)
{
SSMSortedListItem * item;
if (!slist)
goto loser;
PR_EnterMonitor(slist->lock);
item = slist_find_item(slist, key);
PR_ExitMonitor(slist->lock);
if (item)
return PR_TRUE;
loser:
return PR_FALSE;
}
SSMSortedListItem *
slist_find_item(SSMSortedList * slist, void * key)
{
PRCList * link;
for(link = PR_LIST_HEAD(&slist->list); link != &slist->list;
link = PR_NEXT_LINK(link))
if (slist->func.keyCompare(((SSMSortedListItem *)link)->key, key) == 0) /* found it */
return ((SSMSortedListItem *)link);
return NULL;
}
PRIntn
SSMSortedList_Enumerate(SSMSortedList * slist, SSMSortedListEnumerator_fn func,
void * arg)
{
PRCList * link;
PRIntn numentries = 0;
SSMStatus rv;
if (!slist || !func)
goto loser;
PR_EnterMonitor(slist->lock);
for(link = PR_LIST_HEAD(&slist->list); link != &slist->list;
link = PR_NEXT_LINK(link)) {
rv = func(numentries, arg, ((SSMSortedListItem *)link)->key,
((SSMSortedListItem *)link)->data);
if (rv == SSM_SUCCESS)
numentries ++;
}
PR_ExitMonitor(slist->lock);
loser:
return numentries;
}

115
security/psm/server/slist.h Normal file
View File

@ -0,0 +1,115 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SORTEDLIST_H__
#define __SORTEDLIST_H__
#include "prtypes.h"
#include "prmon.h"
#include "prclist.h"
#include "ssmerrs.h"
#include "ssmdefs.h"
#include "nspr.h"
struct _SSMSortedListItem;
typedef PRIntn (* SSMCompare_fn)(const void * p1, const void * p2);
typedef void (* SSMListFree_fn)(void * data);
typedef SSMStatus (* SSMSortedListEnumerator_fn)(PRIntn index, void * arg,
void * key, void * data);
/* This is an ordered collection of items without repetition. */
/* This is to be used as a link in a PRCList.
* You can cast any of the PRCList *'s in the list to one of these.
* See prclist.h for details.
*/
typedef struct _SSMSortedListItem
{
PRCList link;
void *key;
void *data;
} SSMSortedListItem;
typedef struct _SSMSortedListFn
{
SSMCompare_fn keyCompare;
SSMListFree_fn freeListItemData;
SSMListFree_fn freeListItemKey;
} SSMSortedListFn;
/* An ordered collection, implemented in terms of PRCList. */
struct _SSMSortedList
{
PRCList list;
PRMonitor *lock;
PRIntn nItems;
SSMSortedListFn func;
};
typedef struct _SSMSortedList SSMSortedList;
SSMSortedList*
SSMSortedList_New(SSMSortedListFn * functions);
SSMStatus
SSMSortedList_Destroy(SSMSortedList *victim);
SSMStatus
SSMSortedList_Insert(SSMSortedList * slist, void * key, void * data);
SSMStatus
SSMSortedList_Find(SSMSortedList * slist, void * key, void ** data);
PRBool
SSMSortedList_Lookup(SSMSortedList * slist, void * key);
SSMStatus
SSMSortedList_FindNext(SSMSortedList * slist, void * key, void ** data);
SSMStatus
SSMSortedList_Remove(SSMSortedList * slist, void * key, void ** data);
PRIntn
SSMSortedList_Enumerate(SSMSortedList * slist, SSMSortedListEnumerator_fn func,
void * arg);
/*
SSMStatus
SSMSortedList_AtSorted(SSMSortedList *list, PRIntn which,
void ** key, void **data);
*/
SSMSortedListItem *
slist_remove_item(SSMSortedList * list, SSMSortedListItem * item, PRBool doFree);
SSMSortedListItem *
slist_allocate_item(void * key, void * data);
SSMSortedListItem *
slist_find_next(SSMSortedList * slist, void * key);
SSMSortedListItem *
slist_find_item(SSMSortedList * slist, void * key);
#endif /* __SORTEDLIST_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,153 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_SSLCONN_H__
#define __SSM_SSLCONN_H__
#include <stdio.h>
#include <string.h>
#include "prerror.h"
#include "pk11func.h"
#include "secitem.h"
#include "ssl.h"
#include "prnetdb.h"
#include "certt.h"
#include "nss.h"
#include "nspr.h"
#include "secrng.h"
#include "secder.h"
#include "key.h"
#include "sslproto.h"
#include "ctrlconn.h"
#include "dataconn.h"
#include "sslskst.h"
/* Initialization parameters for an SSMSSLDataConnection. */
typedef struct SSMInfoSSL {
SSMControlConnection* parent;
char* hostIP;
char* hostName;
PRUint32 flags;
PRUint32 port;
PRBool forceHandshake;
PRBool isTLS;
CMTItem clientContext;
} SSMInfoSSL;
/* enum for determining how long we will accept this server cert */
typedef enum {BSCA_PERMANENT = 0, BSCA_SESSION = 1, BSCA_NO = 2} SSMBadServerCertAccept;
/* data related with UI */
typedef struct _SSMSSLUIInfo {
PRBool UICompleted;
int numFilteredCerts;
char** certNicknames;
int chosen; /* index of the chosen cert */
/* fields for bad server cert UI */
SSMBadServerCertAccept trustBadServerCert;
/* whether the user decided to use the cert */
} SSMSSLUIInfo;
/*
Data connections.
*/
typedef struct SSMSSLDataConnection {
SSMDataConnection super;
PRBool clientSSL;
char* hostIP;
char* hostName;
PRUint32 flags;
PRUint32 port;
PRBool forceHandshake;
PRBool isTLS; /* TRUE if the connection starts out as a cleartext and
* is SSL-ified later
*/
PRBool isSecure; /* SMTP | Proxy: whether the connection is secure
* SSL: always true
*/
PRFileDesc* socketSSL;
PRFileDesc* stepUpFD; /* FD used by control connection to wake up
SSL thread when it's time to enable TLS/SSL
on a previously cleartext connection (eg SMTP) */
CMTItem* stepUpContext; /* Client context used for step-up */
#if 0
PRMonitor* sslLock;
#endif
SSMSSLSocketStatus* m_sockStat;
PRInt32 m_error;
SSMSSLUIInfo m_UIInfo; /* field related with UI action */
PRInt32 m_sslServerError;
PRBool m_statusFetched;
} SSMSSLDataConnection;
SSMStatus SSMSSLDataConnection_Create(void* arg,
SSMControlConnection* ctrlconn,
SSMResource** res);
SSMStatus SSMSSLDataConnection_Shutdown(SSMResource* arg, SSMStatus status);
SSMStatus SSMSSLDataConnection_Init(SSMSSLDataConnection* conn,
SSMInfoSSL* info, SSMResourceType type);
SSMStatus SSMSSLDataConnection_Destroy(SSMResource* res, PRBool doFree);
void SSMSSLDataConnection_Invariant(SSMSSLDataConnection* conn);
SSMStatus SSMSSLDataConnection_GetAttrIDs(SSMResource* res,
SSMAttributeID** ids, PRIntn* count);
SSMStatus SSMSSLDataConnection_GetAttr(SSMResource* res, SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMSSLDataConnection_SetAttr(SSMResource * res,
SSMResourceAttrType attrID,
SSMAttributeValue *value);
SSMStatus SSMSSLDataConnection_PickleSecurityStatus(SSMSSLDataConnection* conn,
PRIntn* len, void** blob,
PRIntn* securityLevel);
SSMStatus SSMSSLDataConnection_FormSubmitHandler(SSMResource* res,
HTTPRequest* req);
SECStatus SSM_DoubleCheckServerCert(CERTCertificate* cert,
SSMSSLDataConnection* conn);
SECStatus SSM_LDAPSSLGetClientAuthData(void* arg, PRFileDesc* socket,
CERTDistNames* caNames,
CERTCertificate** pRetCert,
SECKEYPrivateKey** pRetKey);
SECStatus SSM_LDAPSetupSSL(PRFileDesc* socket, PRFileDesc** sslSocket,
CERTCertDBHandle* certdb, const char* hostname,
SSMResource* caller);
#endif /* __SSM_SSLCONN_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,202 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_SSLDLGS_H__
#define __SSM_SSLDLGS_H__
#include "textgen.h"
#include "minihttp.h"
#include "sslconn.h"
#include "certt.h"
/*
* Function: SSMStatus SSM_ServerCertKeywordHandler()
* Purpose: keyword handler for "_server_cert_info"
* performs substitution for cert info data
* syntax: {_server_cert_info cert_format,wrapper}
* cert_format: either simple_cert_format (0) or
* pretty_cert_format (1)
* Arguments and return values:
* - cx: SSMTextGenContext to be manipulated
* - returns: SSM_SUCCESS if successful; error code otherwise
*
*/
SSMStatus SSM_ServerCertKeywordHandler(SSMTextGenContext* cx);
/*
* Function: SSMStatus SSM_FormatCert()
* Purpose: creates a UnicodeString that is used in expanding the keyword
* "_server_cert_info" from the given cert
* this function provides info on hostname, issuer name, and validity
* period. Any UI dialog that uses a subset of this info can use
* this function.
* Arguments and return values
* - cert: server cert to be manipulated
* - fmt: message format (shouldn't be NULL)
* - result: resulting expanded string (shouldn't be NULL)
*
* Note: note that this is very similar to a _Print method. In fact,
* this could be turned into SSMResourceCert_Print() method w/o too many
* changes.
*/
SSMStatus SSM_FormatCert(CERTCertificate* cert, char* fmt,
char** result);
/*
* Function: SSMStatus SSM_HTTPBadClientAuthButtonHandler()
* Purpose: command handler for "BCAButton" (button handling
* for bad client auth dialogs)
* Arguments and return values:
* - req: request object to be manipulated
* - returns: SSM_SUCCESS if successful; error code otherwise
*
* Note: we use this command handler instead of the default handler
* to block the SSL threads while this dialog is up.
*/
SSMStatus SSM_HTTPBadClientAuthButtonHandler(HTTPRequest* req);
/*
* Function: SSMStatus SSM_SSLMakeBadClientAuthDialog()
* Purpose: make "no cert" dialog by sending the "no cert" UI event
* Arguments and return values:
* - conn: SSL connection object
* - returns: SSM_SUCCESS if successful; error code otherwise
*
* Note: URL: ".../get?baseRef=bad_client_auth&target=(conn ID)"
* blocks until the dialog is complete
*/
SSMStatus SSM_SSLMakeBadClientAuthDialog(SSMSSLDataConnection* conn);
/*
* Function: SSMStatus SSM_SSLMakeClientAuthDialog()
* Purpose: generates the client auth cert selection dialog and receives
* a chosen cert nickname from the user
* Arguments and return values:
* - conn: SSL connection object to be manipulated; m_UIInfo.chosenNickname
* will be populated as a result of the dialog
* - returns: SSM_SUCCESS if successful; otherwise error code
*
* Note: (design issue) how do we handle "cancel" event? Do we display the
* "no cert" dialog and exit, or we just exit? Probably we just exit.
*/
SSMStatus SSM_SSLMakeClientAuthDialog(SSMSSLDataConnection* conn);
/*
* Function: SSMStatus SSM_ClientAuthCertListKeywordHandler()
* Purpose: formats the client cert list according to the given format
* for the cert selection dialog
* syntax: {_client_auth_certList prefix,wrapper,suffix}
* where wrapper is for the individual cert
* Arguments and return values:
* - cx: text context to be manipulated
* - returns: SSM_SUCCESS if successful; error code otherwise
*
* Note:
*/
SSMStatus SSM_ClientAuthCertListKeywordHandler(SSMTextGenContext* cx);
/*
* Function: SSMStatus SSM_HTTPClientAuthButtonHandler()
* Purpose: handles the user input for buttons in cert selection dialog
* URL: "CAButton?baseRef=windowclose_doclose_js&target={0}&chosen=0&do_ok={text_ok}" or "CAButton?...&target={0}&do_cancel={text_cancel}", etc.
*/
SSMStatus SSM_HTTPClientAuthButtonHandler(HTTPRequest* req);
SECStatus SSM_SSLMakeCertExpiredDialog(CERTCertificate* cert,
SSMSSLDataConnection* conn);
SECStatus SSM_SSLMakeCertBadDomainDialog(CERTCertificate* cert,
SSMSSLDataConnection* conn);
SSMStatus SSM_ClientAuthCertSelectionButtonHandler(HTTPRequest* req);
SSMStatus SSM_ServerAuthFailureButtonHandler(HTTPRequest* req);
SSMStatus SSM_ServerAuthUnknownIssuerButtonHandler(HTTPRequest* req);
SSMStatus SSM_CurrentTimeKeywordHandler(SSMTextGenContext* cx);
/*
* Function: SSMStatus SSM_ServerAuthDomainKeywordHandler()
* Purpose: formats the domain name mismatch warning string for server auth
* syntax: {_server_cert_domain_info bad_domain_wrapper}
* Arguments and return values
* - cx: text context to be manipulated
* - returns: SSM_SUCCESS if successful; error code otherwise
*
* Note: I wrote a separate keyword handler although there is a generic
* server cert info keyword handler; this is the only place where
* one needs the URL hostname and it turns out to be simpler and more
* efficient to write a separate handler for this purpose
*/
SSMStatus SSM_ServerAuthDomainNameKeywordHandler(SSMTextGenContext* cx);
/*
* Function: SSMStatus SSM_VerifyServerCertKeywordHandler()
* Purpose: handles the nickname substitution for keyword
* "_verify_server_cert"
* Arguments and return values:
* - cx: text context to be manipulated
* - returns: SSM_SUCCESS if successful; error code otherwise
*
* Note: since this only comes from the server auth failure dialog, we know
* beforehand that the cert is bad (thus no need really to verify the
* cert). This might change if we want to print out the nature of the
* error. Also, if we want to consolidate this view cert window
* handling (it's not clear how we can do that because we have different
* certs and different targets for different cases), this function
* may have to be modified.
*/
SSMStatus SSM_VerifyServerCertKeywordHandler(SSMTextGenContext* cx);
/*
* Function: SSMStatus SSM_PrettyFormatCert()
* Purpose: formats the cert info for "View Security Certificate" dialogs
* this function provides info on issuer name, serial number,
* validity period, finger print, and comment. Any dialog that
* needs a subset of the parameters can use this function to format
* the cert
* Arguments and return values:
* - cert: cert to be presented
* - fmt: MessageFormat object
* - result: UnicodeString to be returned as a result of the operation
* - returns: SSM_SUCCESS if successful; error code otherwise
*
* Note: this provides no information on whether the cert is valid or not
* lot of the code is borrowed from CERT_HTMLInfo() from NSS
* we also access lots of internal cert fields but can't help it...
*/
SSMStatus SSM_PrettyFormatCert(CERTCertificate* cert, char* fmt,
char** result);
SECStatus SSM_SSLMakeUnknownIssuerDialog(CERTCertificate* cert,
SSMSSLDataConnection* conn);
SSMStatus SSM_HTTPUnknownIssuerStep1ButtonHandler(HTTPRequest* req);
#endif /* __SSM_SSLDLGS_H__ */

View File

@ -0,0 +1,107 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "nspr.h"
struct tuple_str {
PRErrorCode errNum;
const char * errString;
};
typedef struct tuple_str tuple_str;
#define ER2(a,b) {a, b},
#define ER3(a,b,c) {a, c},
#include "secerr.h"
#include "sslerr.h"
const tuple_str errStrings[] = {
/* keep this list in asceding order of error numbers */
#include "SSLerrs.h"
#include "SECerrs.h"
#include "NSPRerrs.h"
};
const PRInt32 numStrings = sizeof(errStrings) / sizeof(tuple_str);
/* Returns a UTF-8 encoded constant error string for "errNum".
* Returns NULL of errNum is unknown.
*/
const char *
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;
}

View File

@ -0,0 +1,503 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "sslconn.h"
#include "ctrlconn.h"
#include "serv.h"
#include "servimpl.h"
/* Shorthand macros for inherited classes */
#define SSMRESOURCE(ss) (&(ss)->super)
/* implemented in resource.c: this should belong to resource.h! */
SSMStatus SSM_UnpickleResource(SSMResource** res, SSMResourceType type,
SSMControlConnection* connection,
PRIntn len, void* value);
SSMStatus
SSMSSLSocketStatus_Create(void *arg, SSMControlConnection * connection,
SSMResource **res)
{
SSMStatus rv = PR_SUCCESS;
SSMSSLSocketStatus *ss;
*res = NULL; /* in case we fail */
ss = (SSMSSLSocketStatus *) PR_CALLOC(sizeof(SSMSSLSocketStatus));
if (!ss) goto loser;
rv = SSMSSLSocketStatus_Init(ss, connection,
(PRFileDesc *) arg,
SSM_RESTYPE_SSL_SOCKET_STATUS);
if (rv != PR_SUCCESS) goto loser;
SSMSSLSocketStatus_Invariant(ss);
*res = &ss->super;
return PR_SUCCESS;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
if (ss)
{
SSMRESOURCE(ss)->m_refCount = 1; /* force destroy */
SSM_FreeResource(SSMRESOURCE(ss));
}
return rv;
}
SSMStatus
SSMSSLSocketStatus_Init(SSMSSLSocketStatus *ss,
SSMControlConnection * connection,
PRFileDesc *fd, SSMResourceType type)
{
SSMStatus rv = PR_SUCCESS;
int keySize, secretKeySize, level;
SSMResource *certObj;
SSMResourceID certRID;
CERTCertificate *cert;
/* Initialize superclass */
SSMResource_Init(connection, SSMRESOURCE(ss), type);
/* Get the peer cert and import it into an NSM object */
cert = SSL_PeerCertificate(fd);
if (!cert) goto loser;
rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE, cert,
SSMRESOURCE(ss)->m_connection, &certRID,
&certObj);
if (rv != PR_SUCCESS) goto loser;
ss->m_cert = (SSMResourceCert*)certObj;
/* Get the other socket status information */
rv = SSL_SecurityStatus(fd, &level, &ss->m_cipherName,
&keySize,
&secretKeySize,
NULL, NULL);
if (rv != PR_SUCCESS) goto loser;
ss->m_keySize = keySize;
ss->m_secretKeySize = secretKeySize;
ss->m_level = level;
/* Sanity check before returning */
SSMSSLSocketStatus_Invariant(ss);
goto done;
loser:
/* member destruct, if any are allocated, will happen in the
_Destroy method */
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMSSLSocketStatus_Destroy(SSMResource *res, PRBool doFree)
{
SSMSSLSocketStatus *ss = (SSMSSLSocketStatus *) res;
SSMSSLSocketStatus_Invariant(ss);
/* Destroy our members. */
if (ss->m_cert)
{
SSM_FreeResource(&ss->m_cert->super);
ss->m_cert = NULL;
}
if (ss->m_cipherName)
{
PORT_Free(ss->m_cipherName);
ss->m_cipherName = NULL;
}
/* Destroy superclass. */
SSMResource_Destroy(res, PR_FALSE);
/* Free if asked. */
if (doFree)
PR_Free(res);
return PR_SUCCESS;
}
void
SSMSSLSocketStatus_Invariant(SSMSSLSocketStatus *ss)
{
/* Superclass invariant */
SSMResource_Invariant(SSMRESOURCE(ss));
/* Class check */
PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(ss), SSM_RESTYPE_SSL_SOCKET_STATUS));
/* Member check */
#if 0
/* Make sure we used a cert to initialize ourselves */
if (ss->m_cert)
PR_ASSERT(ss->m_cert != NULL);
#endif
}
SSMStatus
SSMSSLSocketStatus_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count)
{
SSMStatus rv;
rv = SSMResource_GetAttrIDs(res, ids, count);
if (rv != PR_SUCCESS)
goto loser;
*ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 4) * sizeof(SSMAttributeID));
if (! *ids) goto loser;
(*ids)[*count++] = SSM_FID_SSS_KEYSIZE;
(*ids)[*count++] = SSM_FID_SSS_SECRET_KEYSIZE;
(*ids)[*count++] = SSM_FID_SSS_CERT_ID;
(*ids)[*count++] = SSM_FID_SSS_CIPHER_NAME;
goto done;
loser:
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
return rv;
}
SSMStatus
SSMSSLSocketStatus_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value)
{
SSMStatus rv = PR_SUCCESS;
SSMSSLSocketStatus *ss = (SSMSSLSocketStatus *) res;
char *tmpstr = NULL;
SSM_DEBUG("socket status get attr is called.\n");
SSMSSLSocketStatus_Invariant(ss);
/* see what it is */
switch(attrID)
{
case SSM_FID_SSS_KEYSIZE:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = ss->m_keySize;
break;
case SSM_FID_SSS_SECRET_KEYSIZE:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = ss->m_secretKeySize;
break;
case SSM_FID_SSS_CERT_ID:
value->type = SSM_RID_ATTRIBUTE;
value->u.numeric = ss->m_cert->super.m_id;
break;
case SSM_FID_SSS_SECURITY_LEVEL:
value->type = SSM_NUMERIC_ATTRIBUTE;
value->u.numeric = ss->m_level;
break;
case SSM_FID_SSS_CIPHER_NAME:
value->type = SSM_STRING_ATTRIBUTE;
value->u.string.len = PL_strlen(ss->m_cipherName);
value->u.string.data = (unsigned char *) PL_strdup(ss->m_cipherName);
break;
case SSM_FID_SSS_HTML_STATUS:
value->type = SSM_STRING_ATTRIBUTE;
rv = (*res->m_html_func)(res, NULL, (void**)&tmpstr);
value->u.string.len = PL_strlen(tmpstr);
value->u.string.data = (unsigned char *) PL_strdup(tmpstr);
break;
default:
rv = SSMResource_GetAttr(res,attrID,attrType,value);
if (rv != PR_SUCCESS)
goto loser;
}
goto done;
loser:
value->type = SSM_NO_ATTRIBUTE;
if (rv == PR_SUCCESS) rv = PR_FAILURE;
done:
if (tmpstr != NULL)
PR_Free(tmpstr);
return rv;
}
SSMStatus SSMSSLSocketStatus_Pickle(SSMResource *res, PRIntn * len,
void **value)
{
int blobSize, certSize;
SSMStatus rv;
SSMSSLSocketStatus * resource = (SSMSSLSocketStatus *)res;
void * certBlob, *curptr, *tmpStr = NULL;
if (!res || !value) {
rv = PR_INVALID_ARGUMENT_ERROR;
goto loser;
}
/* in case we fail */
*value = NULL;
if (len) *len = 0;
#if 0
/* first, pickle cert */
rv = SSMControlConnection_GetResource(res->m_connection,
resource->m_certID,
(SSMResource **)&certObj);
if (rv != PR_SUCCESS) goto loser;
#endif
rv = SSM_PickleResource(&resource->m_cert->super, &certSize, &certBlob);
if (rv != PR_SUCCESS)
goto loser;
/* allocate memory for the pickled blob */
blobSize = certSize + sizeof(PRUint32)*5 +
SSMSTRING_PADDED_LENGTH(strlen(resource->m_cipherName));
curptr = PORT_ZAlloc(blobSize);
if (!curptr) {
rv = PR_OUT_OF_MEMORY_ERROR;
goto loser;
}
*value = curptr;
*(PRUint32 *)curptr = resource->m_keySize;
curptr = (PRUint32 *)curptr + 1;
*(PRUint32 *)curptr = resource->m_secretKeySize;
curptr = (PRUint32 *)curptr + 1;
*(PRInt32*)curptr = resource->m_level;
curptr = (PRInt32 *)curptr + 1;
*(PRInt32*)curptr = resource->m_error;
curptr = (PRInt32 *)curptr + 1;
rv = SSM_StringToSSMString((SSMString **)&tmpStr, 0, resource->m_cipherName);
if (rv != PR_SUCCESS)
goto loser;
memcpy(curptr, tmpStr, SSM_SIZEOF_STRING(*(SSMString *)tmpStr));
curptr = (char *)curptr + SSM_SIZEOF_STRING(*(SSMString *)tmpStr);
PR_Free(tmpStr);
tmpStr = NULL;
/* copy cert into the blob */
memcpy(curptr, certBlob, certSize);
if (len) *len = blobSize;
return rv;
loser:
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
if (value && *value)
PR_Free(*value);
if (len)
*len = 0;
if (tmpStr)
PR_Free(tmpStr);
return rv;
}
SSMStatus SSMSSLSocketStatus_Unpickle(SSMResource ** res,
SSMControlConnection * connection,
PRInt32 len,
void *value)
{
SSMStatus rv = PR_SUCCESS;
SSMSSLSocketStatus *ss;
void * curptr = NULL;
PRUint32 strLength = 0, certLength = 0;
SSMResource * certResource = NULL;
if (!res || !value) {
rv = PR_INVALID_ARGUMENT_ERROR;
goto loser;
}
*res = NULL; /* in case we fail */
ss = (SSMSSLSocketStatus *) PR_CALLOC(sizeof(SSMSSLSocketStatus));
if (!ss) goto loser;
ss->m_cipherName = NULL;
ss->m_cert = NULL;
/* Initialize superclass */
SSMResource_Init(connection, SSMRESOURCE(ss),
SSM_RESTYPE_SSL_SOCKET_STATUS);
/* Unpickle socket status data */
curptr = value;
ss->m_keySize = *(PRUint32 *)curptr;
curptr =(PRUint32 *)curptr + 1;
ss->m_secretKeySize = *(PRUint32 *)curptr;
curptr =(PRUint32 *)curptr + 1;
ss->m_level = *(PRInt32 *)curptr;
curptr = (PRInt32 *)curptr + 1;
ss->m_error = *(PRInt32 *)curptr;
curptr = (PRInt32 *)curptr + 1;
/* Fix this */
rv = SSM_SSMStringToString(&ss->m_cipherName, (int *) &strLength,
(SSMString *)curptr);
if (rv != PR_SUCCESS || ss->m_cipherName == NULL || strLength == 0)
goto loser;
curptr = (char *)curptr + SSMSTRING_PADDED_LENGTH(strLength) +
sizeof(PRUint32);
/* Unpickle cert */
certLength = len - ((unsigned long)curptr - (unsigned long)value);
rv = SSM_UnpickleResource(&certResource, SSM_RESTYPE_CERTIFICATE,
connection, certLength, curptr);
if (rv != PR_SUCCESS || !certResource)
goto loser;
#if 0
ss->m_certID = certResource->m_id;
#endif
ss->m_cert = (SSMResourceCert*)certResource;
/* Sanity check before returning */
SSMSSLSocketStatus_Invariant(ss);
*res = SSMRESOURCE(ss);
goto done;
loser:
if (ss) {
if (ss->m_cipherName)
PR_Free(ss->m_cipherName);
if (ss->m_cert) {
SSM_FreeResource(&ss->m_cert->super);
#if 0
(*(certResource->m_destroy_func))(certResource, PR_TRUE);
#endif
}
PR_Free(certResource);
}
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
done:
return rv;
}
SSMStatus SSMSSLSocketStatus_HTML(SSMResource *res, PRIntn *len, void ** value)
{
SSMStatus rv = PR_SUCCESS;
SSMSSLSocketStatus * resource = (SSMSSLSocketStatus *)res;
char * line = NULL;
if (!res || !value) {
rv = PR_INVALID_ARGUMENT_ERROR;
goto loser;
}
if (len) *len = 0;
*value = NULL;
switch (resource->m_level) {
case SSL_SECURITY_STATUS_ON_HIGH:
#ifdef FORTEZZA
case SSL_SECURITY_STATUS_FORTEZZA:
#endif
line = PR_smprintf("%s", SECURITY_HIGH_MESSAGE);
break;
case SSL_SECURITY_STATUS_ON_LOW:
line = PR_smprintf("%s", SECURITY_LOW_MESSAGE);
break;
default:
*value = PR_smprintf("%s", SECURITY_NO_MESSAGE);
goto done;
}
if (resource->m_keySize != resource->m_secretKeySize) {
*value = PR_smprintf("%s (%s, %d bit with %d secret).", line,
resource->m_cipherName,
resource->m_keySize,
resource->m_secretKeySize);
} else {
*value = PR_smprintf("%s (%s, %d bit).", line,
resource->m_cipherName,
resource->m_keySize);
}
goto done;
loser:
if (value && *value)
PR_Free(*value);
*value = NULL;
if (len && *len)
*len = 0;
if (rv == PR_SUCCESS)
rv = PR_FAILURE;
done:
if (value && *value && len)
*len = strlen((char *)*value)+1;
if (line)
PR_Free(line);
return rv;
}
SSMStatus SSMSSLSocketStatus_UpdateSecurityStatus(SSMSSLSocketStatus* ss,
PRFileDesc* socket)
{
SSMStatus rv = PR_SUCCESS;
int keySize, secretKeySize, level;
/* ss should not be NULL when this function is called */
PR_ASSERT(ss != NULL);
/* Get the security status information */
if (ss->m_cipherName != NULL) {
PR_Free(ss->m_cipherName);
ss->m_cipherName = NULL;
}
rv = SSL_SecurityStatus(socket, &level, &ss->m_cipherName, &keySize,
&secretKeySize, NULL, NULL);
if (rv != PR_SUCCESS) {
goto loser;
}
ss->m_keySize = keySize;
ss->m_secretKeySize = secretKeySize;
ss->m_level = level;
/* Sanity check before returning */
SSMSSLSocketStatus_Invariant(ss);
goto done;
loser:
if (rv == PR_SUCCESS) {
rv = PR_FAILURE;
}
if (ss->m_cipherName != NULL) {
PR_Free(ss->m_cipherName);
ss->m_cipherName = NULL;
}
done:
return rv;
}

View File

@ -0,0 +1,134 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSM_SSLSKST_H__
#define __SSM_SSLSKST_H__
#include <stdio.h>
#include <string.h>
#include "prerror.h"
#include "pk11func.h"
#include "secitem.h"
#include "ssl.h"
#include "prnetdb.h"
#include "certt.h"
#include "nss.h"
#include "nspr.h"
#include "secrng.h"
#include "secder.h"
#include "key.h"
#include "sslproto.h"
#include "ctrlconn.h"
#include "dataconn.h"
#include "certres.h"
/* Initialization parameters for an SSMSSLSocketStatus. */
/*
SSL Socket Status object. This encapsulates the information about an SSL
connection.
*/
typedef struct SSMSSLSocketStatus
{
SSMResource super;
PRUint32 m_keySize;
PRUint32 m_secretKeySize;
PRInt32 m_level;
char *m_cipherName;
PRInt32 m_error;
SSMResourceCert *m_cert; /* placeholder - will we want to get an
SSMCertificate object ref later? */
} SSMSSLSocketStatus;
SSMStatus SSMSSLSocketStatus_Create(void *arg, SSMControlConnection * conn,
SSMResource **res);
SSMStatus SSMSSLSocketStatus_Init(SSMSSLSocketStatus *ss,
SSMControlConnection * connection,
PRFileDesc *fd, SSMResourceType type);
SSMStatus SSMSSLSocketStatus_Destroy(SSMResource *res, PRBool doFree);
void SSMSSLSocketStatus_Invariant(SSMSSLSocketStatus *ss);
SSMStatus SSMSSLSocketStatus_GetAttrIDs(SSMResource *res,
SSMAttributeID **ids,
PRIntn *count);
SSMStatus SSMSSLSocketStatus_GetAttr(SSMResource *res,
SSMAttributeID attrID,
SSMResourceAttrType attrType,
SSMAttributeValue *value);
SSMStatus SSMSSLSocketStatus_Pickle(SSMResource *res, PRIntn * len,
void **value);
SSMStatus SSMSSLSocketStatus_Unpickle(SSMResource **res,
SSMControlConnection * conn, PRIntn len,
void *value);
SSMStatus SSMSSLSocketStatus_HTML(SSMResource *res, PRIntn *len, void ** value);
/*
* Function: SSMStatus SSMSSLSocketStatus_UpdateSecurityStatus()
* Purpose: updates the security status
* Arguments and return values:
* - ss: socket status (it should not be NULL when called)
* - socket: SSL socket
* - returns: PR_SUCCESS if the update is successful; PR_FAILURE otherwise
*
* Note: if the update fails, one can keep doing other work but (obviously)
* should not attempt to use any of the security-related values
*/
SSMStatus SSMSSLSocketStatus_UpdateSecurityStatus(SSMSSLSocketStatus* ss,
PRFileDesc* socket);
/*
* The following string are used to present security status in HTML format.
*/
#ifdef XP_UNIX
#define SECURITY_LOW_MESSAGE "This is a secure document that uses a medium-grade encryption key suited\nfor U.S. export"
#define SECURITY_HIGH_MESSAGE "This is a secure document that uses a high-grade encryption key for U.S.\ndomestic use only"
#define SECURITY_NO_MESSAGE "This is an insecure document that is not encrypted and offers no security\nprotection."
#else
#define SECURITY_LOW_MESSAGE "This is a secure document that uses a medium-grade encryption key suited for U.S. export"
#define SECURITY_HIGH_MESSAGE "This is a secure document that uses a high-grade encryption key for U.S. domestic use only"
#define SECURITY_NO_MESSAGE "This is an insecure document that is not encrypted and offers no security protection."
#endif
#endif

View File

@ -0,0 +1,79 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef __SSMERRS_H__
#define __SSMERRS_H__
#include "prtypes.h"
enum
{
SSM_SUCCESS = (int) 0,
SSM_FAILURE = (int) PR_FAILURE,
SSM_ERROR_BASE = (int) -10000,
SSM_ERR_ALREADY_SHUT_DOWN,
SSM_ERR_INVALID_FUNC,
SSM_ERR_BAD_RESOURCE_TYPE,
SSM_ERR_BAD_RESOURCE_ID,
SSM_ERR_BAD_ATTRIBUTE_ID,
SSM_ERR_ATTRIBUTE_TYPE_MISMATCH,
SSM_ERR_ATTRIBUTE_MISSING,
SSM_ERR_DEFER_RESPONSE, /* internal: tell control connection to wait
on a response from another thread -- the
response is placed in the control queue */
SSM_ERR_BAD_REQUEST, /* couldn't understand the request */
SSM_ERR_USER_CANCEL, /* explicit cancel by user */
SSM_ERR_WAIT_TIMEOUT, /* wait has timed out */
SSM_ERR_CLIENT_DESTROY, /* explicit destroy by client sw */
SSM_ERR_NO_USER_CERT, /* there was no usable user cert for client auth */
SSM_ERR_NO_TARGET, /*Could not find a target to handle a form submission */
SSM_ERR_NO_BUTTON, /* Could not find an OK or Cancel value in a
form submission
*/
SSM_ERR_NO_FORM_NAME,
SSM_ERR_OUT_OF_MEMORY,
SSM_TIME_EXPIRED,
SSM_ERR_NO_PASSWORD,
SSM_ERR_BAD_PASSWORD,
SSM_ERR_BAD_DB_PASSWORD,
SSM_ERR_BAD_FILENAME,
SSM_ERR_NEED_USER_INIT_DB,
SSM_ERR_CANNOT_DECODE,
SSM_ERR_NEW_DEF_MAIL_CERT,
SSM_PKCS12_CERT_ALREADY_EXISTS,
SSM_ERR_MAX_ERR
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,144 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
/*
Include file for libnls related utilities. Separated because there
are a lot of headers for libnls, and only those objects which override
the default Print function (see resource.h) should be including
these files.
mwelch - 1999 January
*/
#ifndef __textgen_h__
#define __textgen_h__
#include "nlsutil.h"
#include "minihttp.h"
#include "resource.h"
#include "ctrlconn.h"
/* Indices for the resource bundles.
Keep in sync with (resBundleNames) below. */
typedef enum
{
SSM_RESBNDL_TEXT = (PRInt32) 0,
SSM_RESBNDL_UI,
SSM_RESBNDL_BIN,
SSM_RESBNDL_DOC,
SSM_RESBNDL_COUNT
} SSMResourceBundleIndex;
extern char *resBundleNames[];
/* Text generator state, used by keyword handlers */
typedef struct SSMTextGenContext
{
struct SSMTextGenContext *m_caller; /* who called us, if at all */
HTTPRequest * m_request; /* the HTTP request being processed */
char* m_keyword; /* the keywd by which we are called */
SSMCollection * m_params; /* params to this keyword */
char* m_result; /* where we store the result */
} SSMTextGenContext;
/* Create/destroy a textgen context. */
SSMStatus SSMTextGen_NewContext(SSMTextGenContext *caller, /* can be NULL */
HTTPRequest *req,
char *keyword,
char **params,
SSMTextGenContext **result);
/* Create a top-level textgen context. */
SSMStatus SSMTextGen_NewTopLevelContext(HTTPRequest *req,
SSMTextGenContext **result);
void SSMTextGen_DestroyContext(SSMTextGenContext *victim);
/* Helper routines used with a TextGenContext */
SSMResource *SSMTextGen_GetTargetObject(SSMTextGenContext *cx);
SSMResource *SSMTextGen_GetControlConnection(SSMTextGenContext *cx);
/*
Top level routine called by non-NLS-using parts of Cartman.
Retrieves a string, expands it, then formats it according to the
_Print method of the target object.
*/
SSMStatus SSM_GetUTF8Text(SSMTextGenContext *cx, /* can be NULL */
const char *key,
char **resultText);
/* Get a numeric parameter from the properties file. */
SSMStatus SSM_GetNumber(SSMTextGenContext *cx, char *key, PRInt32 *param);
/* Just gets and expands a string. Can pass NULL for (res). */
SSMStatus SSM_GetAndExpandText(SSMTextGenContext *cx,
const char *key, char **result);
SSMStatus SSM_GetAndExpandTextKeyedByString(SSMTextGenContext *cx,
const char *key,
char **result);
/* Keyword processing function. */
typedef SSMStatus (*KeywordHandlerFunc)(SSMTextGenContext *cx);
SSMStatus SSM_HelloKeywordHandler(SSMTextGenContext *cx);
/* Register a keyword callback. */
SSMStatus SSM_RegisterKeywordHandler(char *keyword,
KeywordHandlerFunc func);
/* Perform NLS-specific initialization. (dataDirectory) contains the path
of the directory containing the "conv" folder with conversion libraries
for the current locale. */
void SSM_InitNLS(char *dataDirectory);
/* Given a key and a context, cycle through resource bundles until
we find a match for the desired key. */
SSMStatus
SSM_FindUTF8StringInBundles(SSMTextGenContext *cx,
const char *key,
char **utf8result);
SSMStatus SSMTextGen_SubstituteString(SSMTextGenContext *cx,
char *str,
char **result);
SSMStatus
SSM_WarnPKCS12Incompatibility(SSMTextGenContext *cx);
SSMStatus
SSM_PassVariable(SSMTextGenContext *cx);
#endif

View File

@ -0,0 +1,101 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
/*****************************************************************************
*
* Timebomb code
*
*****************************************************************************/
#ifdef TIMEBOMB
#include "prlong.h"
#include "timestamp.h"
extern SSMTimeBombExpired;
SSMStatus SSMControlConnection_ProcessHello(SSMControlConnection *ctrl,
SECItem *msg);
SSMStatus SSMTimebomb_SendMessage(SSMControlConnection * control,
SECItem * message);
SECItem * SSMTimebomb_GetMessage(SSMControlConnection * control);
void SSM_CheckTimebomb(void)
{
PRTime timeNow = PR_Now();
if (LL_CMP(timeNow, >,expirationTime))
SSMTimeBombExpired = PR_TRUE;
else SSMTimeBombExpired = PR_FALSE;
}
void SSM_CartmanHasExpired(SSMControlConnection * control)
{
/* time has expired for this module */
SSMStatus rv = PR_SUCCESS;
SECItem * message = NULL;
PRInt32 tmp, sent;
SingleNumMessage reply;
SSM_DEBUG("timebomb: wait for hello message\n");
/* first, let control connection establish, to get browser to come up */
message = SSMTimebomb_GetMessage(control);
if (!message)
goto loser;
/* PR_ASSERT(message &&
(message->type&SSM_TYPE_MASK == SSM_HELLO_MESSAGE));
*/
tmp = message->type & SSM_TYPE_MASK;
if (tmp != SSM_HELLO_MESSAGE)
SSM_DEBUG("timebomb: type is %x \n", tmp);
PR_ASSERT(tmp == SSM_HELLO_MESSAGE);
SSM_FreeMessage(message);
message = SSM_ConstructMessage(0);
if (!message)
goto loser;
message->type = SSM_REPLY_ERR_MESSAGE | SSM_HELLO_MESSAGE;
reply.value = SSM_TIME_EXPIRED;
if (CMT_EncodeMessage(SingleNumMessageTemplate, message, &reply) != CMTSuccess) {
goto loser;
}
if (!message->len || !message->data)
goto loser;
SSMTimebomb_SendMessage(control, message);
SSM_DEBUG("timebomb: sent error reply for hello message, exiting...\n");
loser:
/* there is some error. Clean up and exit */
done:
/* just quit */
exit(0);
}
#endif /* TIMEBOMB */