Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 305047 Details for
Bug 346731
Port crypto-utils to use NSS library for cryptography
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
diff current sources against F-9-split tag
crypto-utils.346731.diff (text/plain), 244.32 KB, created by
Elio Maldonado Batiz
on 2008-05-11 02:10:31 UTC
(
hide
)
Description:
diff current sources against F-9-split tag
Filename:
MIME Type:
Creator:
Elio Maldonado Batiz
Created:
2008-05-11 02:10:31 UTC
Size:
244.32 KB
patch
obsolete
>? devel/crypto-rand-1.2.tar.gz >? devel/crypto-rand-1.3 >? devel/crypto-rand-1.3.tar.gz >? devel/i686 >? devel/keyutil >Index: devel/Makefile >=================================================================== >RCS file: /cvs/extras/rpms/crypto-utils/devel/Makefile,v >retrieving revision 1.4 >retrieving revision 1.6 >diff -u -p -r1.4 -r1.6 >--- devel/Makefile 24 Oct 2007 14:03:17 -0000 1.4 >+++ devel/Makefile 7 May 2008 18:31:38 -0000 1.6 >@@ -1,5 +1,5 @@ > # Makefile for source rpm: crypto-utils >-# $Id: Makefile,v 1.4 2007/10/24 14:03:17 jorton Exp $ >+# $Id: Makefile,v 1.6 2008/05/07 18:31:38 emaldonado Exp $ > NAME := crypto-utils > SPECFILE = $(firstword $(wildcard *.spec)) > >@@ -20,13 +20,19 @@ endif > > include $(MAKEFILE_COMMON) > >-certwatch: certwatch.c >- gcc -Wall -Werror -O2 -g $< -o $@ -lcrypto >+certwatch: certwatch.c pemutil.c >+ gcc -Wall -Werror -O2 -g $^ -o $@ \ >+ -lnspr4 -lnss3 -I/usr/include/nspr4 -I/usr/include/nss3 > > test-certwatch: certwatch > ./certwatch > >-genkey: genkey.pl Makefile >+keyutil: keyutil.c keyutil.h certext.c secutil.c secutil.h secerror.c >+ gcc -Wall -Werror -O2 -g $^ -o $@ \ >+ -lnspr4 -lnss3 -I/usr/include/nspr4 -I/usr/include/nss3 >+ chmod 755 $@ >+ >+genkey: genkey.pl keyutil Makefile > sed -e "s|^\$$bindir.*$$|\$$bindir = \"/usr/bin\";|" \ > -e "s|^\$$ssltop.*$$|\$$ssltop = \"$(PWD)\";|" \ > -e "s|^\$$sslconf.*$$|\$$sslconf = \"/etc/pki/tls/openssl.cnf\";|" \ >@@ -40,6 +46,30 @@ test-genkey: genkey > mkdir -p certs private > ./genkey --test `hostname` > >+######################################################################### >+# Individual testing targets. >+######################################################################### >+ >+test-genreq-modssl: genkey >+ perl ./genkey --genreq test.`hostname` >+ >+test-makecert-modssl: genkey >+ perl ./genkey --makeca test.`hostname` >+ >+test-genreq-modnss: genkey >+ perl ./genkey --genreq -nss test.`hostname` >+ >+test-makecert-modnss: genkey >+ perl ./genkey --makeca -nss test.`hostname` >+ >+prepare-tests: >+ mkdir -p certs private >+ >+cleanup-tests: certs private >+ rm -f -r certs private >+ >+######################################################################### >+ > date.xml: > date +"%e %B %Y" | tr -d '\n' > $@ > >Index: devel/NSPRerrs.h >=================================================================== >RCS file: devel/NSPRerrs.h >diff -N devel/NSPRerrs.h >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ devel/NSPRerrs.h 3 May 2008 22:54:55 -0000 1.2 >@@ -0,0 +1,153 @@ >+/* ***** BEGIN LICENSE BLOCK ***** >+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 >+ * >+ * The contents of this file are subject to the Mozilla Public License Version >+ * 1.1 (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * http://www.mozilla.org/MPL/ >+ * >+ * Software distributed under the License is distributed on an "AS IS" basis, >+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License >+ * for the specific language governing rights and limitations under the >+ * License. >+ * >+ * The Original Code is the Netscape security libraries. >+ * >+ * The Initial Developer of the Original Code is >+ * Netscape Communications Corporation. >+ * Portions created by the Initial Developer are Copyright (C) 1994-2000 >+ * the Initial Developer. All Rights Reserved. >+ * >+ * Contributor(s): >+ * >+ * Alternatively, the contents of this file may be used under the terms of >+ * either the GNU General Public License Version 2 or later (the "GPL"), or >+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), >+ * in which case the provisions of the GPL or the LGPL are applicable instead >+ * of those above. If you wish to allow use of your version of this file only >+ * under the terms of either the GPL or the LGPL, and not to allow others to >+ * use your version of this file under the terms of the MPL, indicate your >+ * decision by deleting the provisions above and replace them with the notice >+ * and other provisions required by the GPL or the LGPL. If you do not delete >+ * the provisions above, a recipient may use your version of this file under >+ * the terms of any one of the MPL, the GPL or the LGPL. >+ * >+ * ***** END LICENSE BLOCK ***** */ >+/* General NSPR 2.0 errors */ >+/* Caller must #include "<rerror.h> */ >+ >+ER2( PR_OUT_OF_MEMORY_ERROR, "Memory allocation attempt failed." ) >+ER2( PR_BAD_DESCRIPTOR_ERROR, "Invalid file descriptor." ) >+ER2( PR_WOULD_BLOCK_ERROR, "The operation would have blocked." ) >+ER2( PR_ACCESS_FAULT_ERROR, "Invalid memory address argument." ) >+ER2( PR_INVALID_METHOD_ERROR, "Invalid function for file type." ) >+ER2( PR_ILLEGAL_ACCESS_ERROR, "Invalid memory address argument." ) >+ER2( PR_UNKNOWN_ERROR, "Some unknown error has occurred." ) >+ER2( PR_PENDING_INTERRUPT_ERROR,"Operation interrupted by another thread." ) >+ER2( PR_NOT_IMPLEMENTED_ERROR, "function not implemented." ) >+ER2( PR_IO_ERROR, "I/O function error." ) >+ER2( PR_IO_TIMEOUT_ERROR, "I/O operation timed out." ) >+ER2( PR_IO_PENDING_ERROR, "I/O operation on busy file descriptor." ) >+ER2( PR_DIRECTORY_OPEN_ERROR, "The directory could not be opened." ) >+ER2( PR_INVALID_ARGUMENT_ERROR, "Invalid function argument." ) >+ER2( PR_ADDRESS_NOT_AVAILABLE_ERROR, "Network address not available (in use?)." ) >+ER2( PR_ADDRESS_NOT_SUPPORTED_ERROR, "Network address type not supported." ) >+ER2( PR_IS_CONNECTED_ERROR, "Already connected." ) >+ER2( PR_BAD_ADDRESS_ERROR, "Network address is invalid." ) >+ER2( PR_ADDRESS_IN_USE_ERROR, "Local Network address is in use." ) >+ER2( PR_CONNECT_REFUSED_ERROR, "Connection refused by peer." ) >+ER2( PR_NETWORK_UNREACHABLE_ERROR, "Network address is presently unreachable." ) >+ER2( PR_CONNECT_TIMEOUT_ERROR, "Connection attempt timed out." ) >+ER2( PR_NOT_CONNECTED_ERROR, "Network file descriptor is not connected." ) >+ER2( PR_LOAD_LIBRARY_ERROR, "Failure to load dynamic library." ) >+ER2( PR_UNLOAD_LIBRARY_ERROR, "Failure to unload dynamic library." ) >+ER2( PR_FIND_SYMBOL_ERROR, >+"Symbol not found in any of the loaded dynamic libraries." ) >+ER2( PR_INSUFFICIENT_RESOURCES_ERROR, "Insufficient system resources." ) >+ER2( PR_DIRECTORY_LOOKUP_ERROR, >+"A directory lookup on a network address has failed." ) >+ER2( PR_TPD_RANGE_ERROR, >+"Attempt to access a TPD key that is out of range." ) >+ER2( PR_PROC_DESC_TABLE_FULL_ERROR, "Process open FD table is full." ) >+ER2( PR_SYS_DESC_TABLE_FULL_ERROR, "System open FD table is full." ) >+ER2( PR_NOT_SOCKET_ERROR, >+"Network operation attempted on non-network file descriptor." ) >+ER2( PR_NOT_TCP_SOCKET_ERROR, >+"TCP-specific function attempted on a non-TCP file descriptor." ) >+ER2( PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "TCP file descriptor is already bound." ) >+ER2( PR_NO_ACCESS_RIGHTS_ERROR, "Access Denied." ) >+ER2( PR_OPERATION_NOT_SUPPORTED_ERROR, >+"The requested operation is not supported by the platform." ) >+ER2( PR_PROTOCOL_NOT_SUPPORTED_ERROR, >+"The host operating system does not support the protocol requested." ) >+ER2( PR_REMOTE_FILE_ERROR, "Access to the remote file has been severed." ) >+ER2( PR_BUFFER_OVERFLOW_ERROR, >+"The value requested is too large to be stored in the data buffer provided." ) >+ER2( PR_CONNECT_RESET_ERROR, "TCP connection reset by peer." ) >+ER2( PR_RANGE_ERROR, "Unused." ) >+ER2( PR_DEADLOCK_ERROR, "The operation would have deadlocked." ) >+ER2( PR_FILE_IS_LOCKED_ERROR, "The file is already locked." ) >+ER2( PR_FILE_TOO_BIG_ERROR, >+"Write would result in file larger than the system allows." ) >+ER2( PR_NO_DEVICE_SPACE_ERROR, "The device for storing the file is full." ) >+ER2( PR_PIPE_ERROR, "Unused." ) >+ER2( PR_NO_SEEK_DEVICE_ERROR, "Unused." ) >+ER2( PR_IS_DIRECTORY_ERROR, >+"Cannot perform a normal file operation on a directory." ) >+ER2( PR_LOOP_ERROR, "Symbolic link loop." ) >+ER2( PR_NAME_TOO_LONG_ERROR, "File name is too long." ) >+ER2( PR_FILE_NOT_FOUND_ERROR, "File not found." ) >+ER2( PR_NOT_DIRECTORY_ERROR, >+"Cannot perform directory operation on a normal file." ) >+ER2( PR_READ_ONLY_FILESYSTEM_ERROR, >+"Cannot write to a read-only file system." ) >+ER2( PR_DIRECTORY_NOT_EMPTY_ERROR, >+"Cannot delete a directory that is not empty." ) >+ER2( PR_FILESYSTEM_MOUNTED_ERROR, >+"Cannot delete or rename a file object while the file system is busy." ) >+ER2( PR_NOT_SAME_DEVICE_ERROR, >+"Cannot rename a file to a file system on another device." ) >+ER2( PR_DIRECTORY_CORRUPTED_ERROR, >+"The directory object in the file system is corrupted." ) >+ER2( PR_FILE_EXISTS_ERROR, >+"Cannot create or rename a filename that already exists." ) >+ER2( PR_MAX_DIRECTORY_ENTRIES_ERROR, >+"Directory is full. No additional filenames may be added." ) >+ER2( PR_INVALID_DEVICE_STATE_ERROR, >+"The required device was in an invalid state." ) >+ER2( PR_DEVICE_IS_LOCKED_ERROR, "The device is locked." ) >+ER2( PR_NO_MORE_FILES_ERROR, "No more entries in the directory." ) >+ER2( PR_END_OF_FILE_ERROR, "Encountered end of file." ) >+ER2( PR_FILE_SEEK_ERROR, "Seek error." ) >+ER2( PR_FILE_IS_BUSY_ERROR, "The file is busy." ) >+ER2( PR_IN_PROGRESS_ERROR, >+"Operation is still in progress (probably a non-blocking connect)." ) >+ER2( PR_ALREADY_INITIATED_ERROR, >+"Operation has already been initiated (probably a non-blocking connect)." ) >+ >+#ifdef PR_GROUP_EMPTY_ERROR >+ER2( PR_GROUP_EMPTY_ERROR, "The wait group is empty." ) >+#endif >+ >+#ifdef PR_INVALID_STATE_ERROR >+ER2( PR_INVALID_STATE_ERROR, "Object state improper for request." ) >+#endif >+ >+#ifdef PR_NETWORK_DOWN_ERROR >+ER2( PR_NETWORK_DOWN_ERROR, "Network is down." ) >+#endif >+ >+#ifdef PR_SOCKET_SHUTDOWN_ERROR >+ER2( PR_SOCKET_SHUTDOWN_ERROR, "The socket was previously shut down." ) >+#endif >+ >+#ifdef PR_CONNECT_ABORTED_ERROR >+ER2( PR_CONNECT_ABORTED_ERROR, "TCP Connection aborted." ) >+#endif >+ >+#ifdef PR_HOST_UNREACHABLE_ERROR >+ER2( PR_HOST_UNREACHABLE_ERROR, "Host is unreachable." ) >+#endif >+ >+/* always last */ >+ER2( PR_MAX_ERROR, "Placeholder for the end of the list" ) >Index: devel/SECerrs.h >=================================================================== >RCS file: devel/SECerrs.h >diff -N devel/SECerrs.h >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ devel/SECerrs.h 3 May 2008 22:54:55 -0000 1.2 >@@ -0,0 +1,548 @@ >+/* ***** BEGIN LICENSE BLOCK ***** >+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 >+ * >+ * The contents of this file are subject to the Mozilla Public License Version >+ * 1.1 (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * http://www.mozilla.org/MPL/ >+ * >+ * Software distributed under the License is distributed on an "AS IS" basis, >+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License >+ * for the specific language governing rights and limitations under the >+ * License. >+ * >+ * The Original Code is the Netscape security libraries. >+ * >+ * The Initial Developer of the Original Code is >+ * Netscape Communications Corporation. >+ * Portions created by the Initial Developer are Copyright (C) 1994-2000 >+ * the Initial Developer. All Rights Reserved. >+ * >+ * Contributor(s): >+ * >+ * Alternatively, the contents of this file may be used under the terms of >+ * either the GNU General Public License Version 2 or later (the "GPL"), or >+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), >+ * in which case the provisions of the GPL or the LGPL are applicable instead >+ * of those above. If you wish to allow use of your version of this file only >+ * under the terms of either the GPL or the LGPL, and not to allow others to >+ * use your version of this file under the terms of the MPL, indicate your >+ * decision by deleting the provisions above and replace them with the notice >+ * and other provisions required by the GPL or the LGPL. If you do not delete >+ * the provisions above, a recipient may use your version of this file under >+ * the terms of any one of the MPL, the GPL or the LGPL. >+ * >+ * ***** END LICENSE BLOCK ***** */ >+ >+/* General security error codes */ >+/* Caller must #include <secerr.h> */ >+ >+ER3(SEC_ERROR_IO, SEC_ERROR_BASE + 0, >+"An I/O error occurred during security authorization.") >+ >+ER3(SEC_ERROR_LIBRARY_FAILURE, SEC_ERROR_BASE + 1, >+"security library failure.") >+ >+ER3(SEC_ERROR_BAD_DATA, SEC_ERROR_BASE + 2, >+"security library: received bad data.") >+ >+ER3(SEC_ERROR_OUTPUT_LEN, SEC_ERROR_BASE + 3, >+"security library: output length error.") >+ >+ER3(SEC_ERROR_INPUT_LEN, SEC_ERROR_BASE + 4, >+"security library has experienced an input length error.") >+ >+ER3(SEC_ERROR_INVALID_ARGS, SEC_ERROR_BASE + 5, >+"security library: invalid arguments.") >+ >+ER3(SEC_ERROR_INVALID_ALGORITHM, SEC_ERROR_BASE + 6, >+"security library: invalid algorithm.") >+ >+ER3(SEC_ERROR_INVALID_AVA, SEC_ERROR_BASE + 7, >+"security library: invalid AVA.") >+ >+ER3(SEC_ERROR_INVALID_TIME, SEC_ERROR_BASE + 8, >+"Improperly formatted time string.") >+ >+ER3(SEC_ERROR_BAD_DER, SEC_ERROR_BASE + 9, >+"security library: improperly formatted DER-encoded message.") >+ >+ER3(SEC_ERROR_BAD_SIGNATURE, SEC_ERROR_BASE + 10, >+"Peer's certificate has an invalid signature.") >+ >+ER3(SEC_ERROR_EXPIRED_CERTIFICATE, SEC_ERROR_BASE + 11, >+"Peer's Certificate has expired.") >+ >+ER3(SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_BASE + 12, >+"Peer's Certificate has been revoked.") >+ >+ER3(SEC_ERROR_UNKNOWN_ISSUER, SEC_ERROR_BASE + 13, >+"Peer's Certificate issuer is not recognized.") >+ >+ER3(SEC_ERROR_BAD_KEY, SEC_ERROR_BASE + 14, >+"Peer's public key is invalid.") >+ >+ER3(SEC_ERROR_BAD_PASSWORD, SEC_ERROR_BASE + 15, >+"The security password entered is incorrect.") >+ >+ER3(SEC_ERROR_RETRY_PASSWORD, SEC_ERROR_BASE + 16, >+"New password entered incorrectly. Please try again.") >+ >+ER3(SEC_ERROR_NO_NODELOCK, SEC_ERROR_BASE + 17, >+"security library: no nodelock.") >+ >+ER3(SEC_ERROR_BAD_DATABASE, SEC_ERROR_BASE + 18, >+"security library: bad database.") >+ >+ER3(SEC_ERROR_NO_MEMORY, SEC_ERROR_BASE + 19, >+"security library: memory allocation failure.") >+ >+ER3(SEC_ERROR_UNTRUSTED_ISSUER, SEC_ERROR_BASE + 20, >+"Peer's certificate issuer has been marked as not trusted by the user.") >+ >+ER3(SEC_ERROR_UNTRUSTED_CERT, SEC_ERROR_BASE + 21, >+"Peer's certificate has been marked as not trusted by the user.") >+ >+ER3(SEC_ERROR_DUPLICATE_CERT, (SEC_ERROR_BASE + 22), >+"Certificate already exists in your database.") >+ >+ER3(SEC_ERROR_DUPLICATE_CERT_NAME, (SEC_ERROR_BASE + 23), >+"Downloaded certificate's name duplicates one already in your database.") >+ >+ER3(SEC_ERROR_ADDING_CERT, (SEC_ERROR_BASE + 24), >+"Error adding certificate to database.") >+ >+ER3(SEC_ERROR_FILING_KEY, (SEC_ERROR_BASE + 25), >+"Error refiling the key for this certificate.") >+ >+ER3(SEC_ERROR_NO_KEY, (SEC_ERROR_BASE + 26), >+"The private key for this certificate cannot be found in key database") >+ >+ER3(SEC_ERROR_CERT_VALID, (SEC_ERROR_BASE + 27), >+"This certificate is valid.") >+ >+ER3(SEC_ERROR_CERT_NOT_VALID, (SEC_ERROR_BASE + 28), >+"This certificate is not valid.") >+ >+ER3(SEC_ERROR_CERT_NO_RESPONSE, (SEC_ERROR_BASE + 29), >+"Cert Library: No Response") >+ >+ER3(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, (SEC_ERROR_BASE + 30), >+"The certificate issuer's certificate has expired. Check your system date and time.") >+ >+ER3(SEC_ERROR_CRL_EXPIRED, (SEC_ERROR_BASE + 31), >+"The CRL for the certificate's issuer has expired. Update it or check your system date and time.") >+ >+ER3(SEC_ERROR_CRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 32), >+"The CRL for the certificate's issuer has an invalid signature.") >+ >+ER3(SEC_ERROR_CRL_INVALID, (SEC_ERROR_BASE + 33), >+"New CRL has an invalid format.") >+ >+ER3(SEC_ERROR_EXTENSION_VALUE_INVALID, (SEC_ERROR_BASE + 34), >+"Certificate extension value is invalid.") >+ >+ER3(SEC_ERROR_EXTENSION_NOT_FOUND, (SEC_ERROR_BASE + 35), >+"Certificate extension not found.") >+ >+ER3(SEC_ERROR_CA_CERT_INVALID, (SEC_ERROR_BASE + 36), >+"Issuer certificate is invalid.") >+ >+ER3(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, (SEC_ERROR_BASE + 37), >+"Certificate path length constraint is invalid.") >+ >+ER3(SEC_ERROR_CERT_USAGES_INVALID, (SEC_ERROR_BASE + 38), >+"Certificate usages field is invalid.") >+ >+ER3(SEC_INTERNAL_ONLY, (SEC_ERROR_BASE + 39), >+"**Internal ONLY module**") >+ >+ER3(SEC_ERROR_INVALID_KEY, (SEC_ERROR_BASE + 40), >+"The key does not support the requested operation.") >+ >+ER3(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 41), >+"Certificate contains unknown critical extension.") >+ >+ER3(SEC_ERROR_OLD_CRL, (SEC_ERROR_BASE + 42), >+"New CRL is not later than the current one.") >+ >+ER3(SEC_ERROR_NO_EMAIL_CERT, (SEC_ERROR_BASE + 43), >+"Not encrypted or signed: you do not yet have an email certificate.") >+ >+ER3(SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, (SEC_ERROR_BASE + 44), >+"Not encrypted: you do not have certificates for each of the recipients.") >+ >+ER3(SEC_ERROR_NOT_A_RECIPIENT, (SEC_ERROR_BASE + 45), >+"Cannot decrypt: you are not a recipient, or matching certificate and \ >+private key not found.") >+ >+ER3(SEC_ERROR_PKCS7_KEYALG_MISMATCH, (SEC_ERROR_BASE + 46), >+"Cannot decrypt: key encryption algorithm does not match your certificate.") >+ >+ER3(SEC_ERROR_PKCS7_BAD_SIGNATURE, (SEC_ERROR_BASE + 47), >+"Signature verification failed: no signer found, too many signers found, \ >+or improper or corrupted data.") >+ >+ER3(SEC_ERROR_UNSUPPORTED_KEYALG, (SEC_ERROR_BASE + 48), >+"Unsupported or unknown key algorithm.") >+ >+ER3(SEC_ERROR_DECRYPTION_DISALLOWED, (SEC_ERROR_BASE + 49), >+"Cannot decrypt: encrypted using a disallowed algorithm or key size.") >+ >+ >+/* Fortezza Alerts */ >+ER3(XP_SEC_FORTEZZA_BAD_CARD, (SEC_ERROR_BASE + 50), >+"Fortezza card has not been properly initialized. \ >+Please remove it and return it to your issuer.") >+ >+ER3(XP_SEC_FORTEZZA_NO_CARD, (SEC_ERROR_BASE + 51), >+"No Fortezza cards Found") >+ >+ER3(XP_SEC_FORTEZZA_NONE_SELECTED, (SEC_ERROR_BASE + 52), >+"No Fortezza card selected") >+ >+ER3(XP_SEC_FORTEZZA_MORE_INFO, (SEC_ERROR_BASE + 53), >+"Please select a personality to get more info on") >+ >+ER3(XP_SEC_FORTEZZA_PERSON_NOT_FOUND, (SEC_ERROR_BASE + 54), >+"Personality not found") >+ >+ER3(XP_SEC_FORTEZZA_NO_MORE_INFO, (SEC_ERROR_BASE + 55), >+"No more information on that Personality") >+ >+ER3(XP_SEC_FORTEZZA_BAD_PIN, (SEC_ERROR_BASE + 56), >+"Invalid Pin") >+ >+ER3(XP_SEC_FORTEZZA_PERSON_ERROR, (SEC_ERROR_BASE + 57), >+"Couldn't initialize Fortezza personalities.") >+/* end fortezza alerts. */ >+ >+ER3(SEC_ERROR_NO_KRL, (SEC_ERROR_BASE + 58), >+"No KRL for this site's certificate has been found.") >+ >+ER3(SEC_ERROR_KRL_EXPIRED, (SEC_ERROR_BASE + 59), >+"The KRL for this site's certificate has expired.") >+ >+ER3(SEC_ERROR_KRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 60), >+"The KRL for this site's certificate has an invalid signature.") >+ >+ER3(SEC_ERROR_REVOKED_KEY, (SEC_ERROR_BASE + 61), >+"The key for this site's certificate has been revoked.") >+ >+ER3(SEC_ERROR_KRL_INVALID, (SEC_ERROR_BASE + 62), >+"New KRL has an invalid format.") >+ >+ER3(SEC_ERROR_NEED_RANDOM, (SEC_ERROR_BASE + 63), >+"security library: need random data.") >+ >+ER3(SEC_ERROR_NO_MODULE, (SEC_ERROR_BASE + 64), >+"security library: no security module can perform the requested operation.") >+ >+ER3(SEC_ERROR_NO_TOKEN, (SEC_ERROR_BASE + 65), >+"The security card or token does not exist, needs to be initialized, or has been removed.") >+ >+ER3(SEC_ERROR_READ_ONLY, (SEC_ERROR_BASE + 66), >+"security library: read-only database.") >+ >+ER3(SEC_ERROR_NO_SLOT_SELECTED, (SEC_ERROR_BASE + 67), >+"No slot or token was selected.") >+ >+ER3(SEC_ERROR_CERT_NICKNAME_COLLISION, (SEC_ERROR_BASE + 68), >+"A certificate with the same nickname already exists.") >+ >+ER3(SEC_ERROR_KEY_NICKNAME_COLLISION, (SEC_ERROR_BASE + 69), >+"A key with the same nickname already exists.") >+ >+ER3(SEC_ERROR_SAFE_NOT_CREATED, (SEC_ERROR_BASE + 70), >+"error while creating safe object") >+ >+ER3(SEC_ERROR_BAGGAGE_NOT_CREATED, (SEC_ERROR_BASE + 71), >+"error while creating baggage object") >+ >+ER3(XP_JAVA_REMOVE_PRINCIPAL_ERROR, (SEC_ERROR_BASE + 72), >+"Couldn't remove the principal") >+ >+ER3(XP_JAVA_DELETE_PRIVILEGE_ERROR, (SEC_ERROR_BASE + 73), >+"Couldn't delete the privilege") >+ >+ER3(XP_JAVA_CERT_NOT_EXISTS_ERROR, (SEC_ERROR_BASE + 74), >+"This principal doesn't have a certificate") >+ >+ER3(SEC_ERROR_BAD_EXPORT_ALGORITHM, (SEC_ERROR_BASE + 75), >+"Required algorithm is not allowed.") >+ >+ER3(SEC_ERROR_EXPORTING_CERTIFICATES, (SEC_ERROR_BASE + 76), >+"Error attempting to export certificates.") >+ >+ER3(SEC_ERROR_IMPORTING_CERTIFICATES, (SEC_ERROR_BASE + 77), >+"Error attempting to import certificates.") >+ >+ER3(SEC_ERROR_PKCS12_DECODING_PFX, (SEC_ERROR_BASE + 78), >+"Unable to import. Decoding error. File not valid.") >+ >+ER3(SEC_ERROR_PKCS12_INVALID_MAC, (SEC_ERROR_BASE + 79), >+"Unable to import. Invalid MAC. Incorrect password or corrupt file.") >+ >+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, (SEC_ERROR_BASE + 80), >+"Unable to import. MAC algorithm not supported.") >+ >+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE,(SEC_ERROR_BASE + 81), >+"Unable to import. Only password integrity and privacy modes supported.") >+ >+ER3(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, (SEC_ERROR_BASE + 82), >+"Unable to import. File structure is corrupt.") >+ >+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, (SEC_ERROR_BASE + 83), >+"Unable to import. Encryption algorithm not supported.") >+ >+ER3(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, (SEC_ERROR_BASE + 84), >+"Unable to import. File version not supported.") >+ >+ER3(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT,(SEC_ERROR_BASE + 85), >+"Unable to import. Incorrect privacy password.") >+ >+ER3(SEC_ERROR_PKCS12_CERT_COLLISION, (SEC_ERROR_BASE + 86), >+"Unable to import. Same nickname already exists in database.") >+ >+ER3(SEC_ERROR_USER_CANCELLED, (SEC_ERROR_BASE + 87), >+"The user pressed cancel.") >+ >+ER3(SEC_ERROR_PKCS12_DUPLICATE_DATA, (SEC_ERROR_BASE + 88), >+"Not imported, already in database.") >+ >+ER3(SEC_ERROR_MESSAGE_SEND_ABORTED, (SEC_ERROR_BASE + 89), >+"Message not sent.") >+ >+ER3(SEC_ERROR_INADEQUATE_KEY_USAGE, (SEC_ERROR_BASE + 90), >+"Certificate key usage inadequate for attempted operation.") >+ >+ER3(SEC_ERROR_INADEQUATE_CERT_TYPE, (SEC_ERROR_BASE + 91), >+"Certificate type not approved for application.") >+ >+ER3(SEC_ERROR_CERT_ADDR_MISMATCH, (SEC_ERROR_BASE + 92), >+"Address in signing certificate does not match address in message headers.") >+ >+ER3(SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, (SEC_ERROR_BASE + 93), >+"Unable to import. Error attempting to import private key.") >+ >+ER3(SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, (SEC_ERROR_BASE + 94), >+"Unable to import. Error attempting to import certificate chain.") >+ >+ER3(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, (SEC_ERROR_BASE + 95), >+"Unable to export. Unable to locate certificate or key by nickname.") >+ >+ER3(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, (SEC_ERROR_BASE + 96), >+"Unable to export. Private Key could not be located and exported.") >+ >+ER3(SEC_ERROR_PKCS12_UNABLE_TO_WRITE, (SEC_ERROR_BASE + 97), >+"Unable to export. Unable to write the export file.") >+ >+ER3(SEC_ERROR_PKCS12_UNABLE_TO_READ, (SEC_ERROR_BASE + 98), >+"Unable to import. Unable to read the import file.") >+ >+ER3(SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, (SEC_ERROR_BASE + 99), >+"Unable to export. Key database corrupt or deleted.") >+ >+ER3(SEC_ERROR_KEYGEN_FAIL, (SEC_ERROR_BASE + 100), >+"Unable to generate public/private key pair.") >+ >+ER3(SEC_ERROR_INVALID_PASSWORD, (SEC_ERROR_BASE + 101), >+"Password entered is invalid. Please pick a different one.") >+ >+ER3(SEC_ERROR_RETRY_OLD_PASSWORD, (SEC_ERROR_BASE + 102), >+"Old password entered incorrectly. Please try again.") >+ >+ER3(SEC_ERROR_BAD_NICKNAME, (SEC_ERROR_BASE + 103), >+"Certificate nickname already in use.") >+ >+ER3(SEC_ERROR_NOT_FORTEZZA_ISSUER, (SEC_ERROR_BASE + 104), >+"Peer FORTEZZA chain has a non-FORTEZZA Certificate.") >+ >+ER3(SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY, (SEC_ERROR_BASE + 105), >+"A sensitive key cannot be moved to the slot where it is needed.") >+ >+ER3(SEC_ERROR_JS_INVALID_MODULE_NAME, (SEC_ERROR_BASE + 106), >+"Invalid module name.") >+ >+ER3(SEC_ERROR_JS_INVALID_DLL, (SEC_ERROR_BASE + 107), >+"Invalid module path/filename") >+ >+ER3(SEC_ERROR_JS_ADD_MOD_FAILURE, (SEC_ERROR_BASE + 108), >+"Unable to add module") >+ >+ER3(SEC_ERROR_JS_DEL_MOD_FAILURE, (SEC_ERROR_BASE + 109), >+"Unable to delete module") >+ >+ER3(SEC_ERROR_OLD_KRL, (SEC_ERROR_BASE + 110), >+"New KRL is not later than the current one.") >+ >+ER3(SEC_ERROR_CKL_CONFLICT, (SEC_ERROR_BASE + 111), >+"New CKL has different issuer than current CKL. Delete current CKL.") >+ >+ER3(SEC_ERROR_CERT_NOT_IN_NAME_SPACE, (SEC_ERROR_BASE + 112), >+"The Certifying Authority for this certificate is not permitted to issue a \ >+certificate with this name.") >+ >+ER3(SEC_ERROR_KRL_NOT_YET_VALID, (SEC_ERROR_BASE + 113), >+"The key revocation list for this certificate is not yet valid.") >+ >+ER3(SEC_ERROR_CRL_NOT_YET_VALID, (SEC_ERROR_BASE + 114), >+"The certificate revocation list for this certificate is not yet valid.") >+ >+ER3(SEC_ERROR_UNKNOWN_CERT, (SEC_ERROR_BASE + 115), >+"The requested certificate could not be found.") >+ >+ER3(SEC_ERROR_UNKNOWN_SIGNER, (SEC_ERROR_BASE + 116), >+"The signer's certificate could not be found.") >+ >+ER3(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, (SEC_ERROR_BASE + 117), >+"The location for the certificate status server has invalid format.") >+ >+ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, (SEC_ERROR_BASE + 118), >+"The OCSP response cannot be fully decoded; it is of an unknown type.") >+ >+ER3(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, (SEC_ERROR_BASE + 119), >+"The OCSP server returned unexpected/invalid HTTP data.") >+ >+ER3(SEC_ERROR_OCSP_MALFORMED_REQUEST, (SEC_ERROR_BASE + 120), >+"The OCSP server found the request to be corrupted or improperly formed.") >+ >+ER3(SEC_ERROR_OCSP_SERVER_ERROR, (SEC_ERROR_BASE + 121), >+"The OCSP server experienced an internal error.") >+ >+ER3(SEC_ERROR_OCSP_TRY_SERVER_LATER, (SEC_ERROR_BASE + 122), >+"The OCSP server suggests trying again later.") >+ >+ER3(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, (SEC_ERROR_BASE + 123), >+"The OCSP server requires a signature on this request.") >+ >+ER3(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, (SEC_ERROR_BASE + 124), >+"The OCSP server has refused this request as unauthorized.") >+ >+ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, (SEC_ERROR_BASE + 125), >+"The OCSP server returned an unrecognizable status.") >+ >+ER3(SEC_ERROR_OCSP_UNKNOWN_CERT, (SEC_ERROR_BASE + 126), >+"The OCSP server has no status for the certificate.") >+ >+ER3(SEC_ERROR_OCSP_NOT_ENABLED, (SEC_ERROR_BASE + 127), >+"You must enable OCSP before performing this operation.") >+ >+ER3(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, (SEC_ERROR_BASE + 128), >+"You must set the OCSP default responder before performing this operation.") >+ >+ER3(SEC_ERROR_OCSP_MALFORMED_RESPONSE, (SEC_ERROR_BASE + 129), >+"The response from the OCSP server was corrupted or improperly formed.") >+ >+ER3(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, (SEC_ERROR_BASE + 130), >+"The signer of the OCSP response is not authorized to give status for \ >+this certificate.") >+ >+ER3(SEC_ERROR_OCSP_FUTURE_RESPONSE, (SEC_ERROR_BASE + 131), >+"The OCSP response is not yet valid (contains a date in the future).") >+ >+ER3(SEC_ERROR_OCSP_OLD_RESPONSE, (SEC_ERROR_BASE + 132), >+"The OCSP response contains out-of-date information.") >+ >+ER3(SEC_ERROR_DIGEST_NOT_FOUND, (SEC_ERROR_BASE + 133), >+"The CMS or PKCS #7 Digest was not found in signed message.") >+ >+ER3(SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE, (SEC_ERROR_BASE + 134), >+"The CMS or PKCS #7 Message type is unsupported.") >+ >+ER3(SEC_ERROR_MODULE_STUCK, (SEC_ERROR_BASE + 135), >+"PKCS #11 module could not be removed because it is still in use.") >+ >+ER3(SEC_ERROR_BAD_TEMPLATE, (SEC_ERROR_BASE + 136), >+"Could not decode ASN.1 data. Specified template was invalid.") >+ >+ER3(SEC_ERROR_CRL_NOT_FOUND, (SEC_ERROR_BASE + 137), >+"No matching CRL was found.") >+ >+ER3(SEC_ERROR_REUSED_ISSUER_AND_SERIAL, (SEC_ERROR_BASE + 138), >+"You are attempting to import a cert with the same issuer/serial as \ >+an existing cert, but that is not the same cert.") >+ >+ER3(SEC_ERROR_BUSY, (SEC_ERROR_BASE + 139), >+"NSS could not shutdown. Objects are still in use.") >+ >+ER3(SEC_ERROR_EXTRA_INPUT, (SEC_ERROR_BASE + 140), >+"DER-encoded message contained extra unused data.") >+ >+ER3(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE, (SEC_ERROR_BASE + 141), >+"Unsupported elliptic curve.") >+ >+ER3(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM, (SEC_ERROR_BASE + 142), >+"Unsupported elliptic curve point form.") >+ >+ER3(SEC_ERROR_UNRECOGNIZED_OID, (SEC_ERROR_BASE + 143), >+"Unrecognized Object Identifier.") >+ >+ER3(SEC_ERROR_OCSP_INVALID_SIGNING_CERT, (SEC_ERROR_BASE + 144), >+"Invalid OCSP signing certificate in OCSP response.") >+ >+ER3(SEC_ERROR_REVOKED_CERTIFICATE_CRL, (SEC_ERROR_BASE + 145), >+"Certificate is revoked in issuer's certificate revocation list.") >+ >+ER3(SEC_ERROR_REVOKED_CERTIFICATE_OCSP, (SEC_ERROR_BASE + 146), >+"Issuer's OCSP responder reports certificate is revoked.") >+ >+ER3(SEC_ERROR_CRL_INVALID_VERSION, (SEC_ERROR_BASE + 147), >+"Issuer's Certificate Revocation List has an unknown version number.") >+ >+ER3(SEC_ERROR_CRL_V1_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 148), >+"Issuer's V1 Certificate Revocation List has a critical extension.") >+ >+ER3(SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 149), >+"Issuer's V2 Certificate Revocation List has an unknown critical extension.") >+ >+ER3(SEC_ERROR_UNKNOWN_OBJECT_TYPE, (SEC_ERROR_BASE + 150), >+"Unknown object type specified.") >+ >+ER3(SEC_ERROR_INCOMPATIBLE_PKCS11, (SEC_ERROR_BASE + 151), >+"PKCS #11 driver violates the spec in an incompatible way.") >+ >+ER3(SEC_ERROR_NO_EVENT, (SEC_ERROR_BASE + 152), >+"No new slot event is available at this time.") >+ >+ER3(SEC_ERROR_CRL_ALREADY_EXISTS, (SEC_ERROR_BASE + 153), >+"CRL already exists.") >+ >+ER3(SEC_ERROR_NOT_INITIALIZED, (SEC_ERROR_BASE + 154), >+"NSS is not initialized.") >+ >+ER3(SEC_ERROR_TOKEN_NOT_LOGGED_IN, (SEC_ERROR_BASE + 155), >+"The operation failed because the PKCS#11 token is not logged in.") >+ >+ER3(SEC_ERROR_OCSP_RESPONDER_CERT_INVALID, (SEC_ERROR_BASE + 156), >+"Configured OCSP responder's certificate is invalid.") >+ >+ER3(SEC_ERROR_OCSP_BAD_SIGNATURE, (SEC_ERROR_BASE + 157), >+"OCSP response has an invalid signature.") >+ >+ER3(SEC_ERROR_OUT_OF_SEARCH_LIMITS, (SEC_ERROR_BASE + 158), >+"Cert validation search is out of search limits") >+ >+ER3(SEC_ERROR_INVALID_POLICY_MAPPING, (SEC_ERROR_BASE + 159), >+"Policy mapping contains anypolicy") >+ >+ER3(SEC_ERROR_POLICY_VALIDATION_FAILED, (SEC_ERROR_BASE + 160), >+"Cert chain fails policy validation") >+ >+ER3(SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE, (SEC_ERROR_BASE + 161), >+"Unknown location type in cert AIA extension") >+ >+ER3(SEC_ERROR_BAD_HTTP_RESPONSE, (SEC_ERROR_BASE + 162), >+"Server returned bad HTTP response") >+ >+ER3(SEC_ERROR_BAD_LDAP_RESPONSE, (SEC_ERROR_BASE + 163), >+"Server returned bad LDAP response") >+ >+ER3(SEC_ERROR_FAILED_TO_ENCODE_DATA, (SEC_ERROR_BASE + 164), >+"Failed to encode data with ASN1 encoder") >+ >+ER3(SEC_ERROR_BAD_INFO_ACCESS_LOCATION, (SEC_ERROR_BASE + 165), >+"Bad information access location in cert extension") >+ >+ER3(SEC_ERROR_LIBPKIX_INTERNAL, (SEC_ERROR_BASE + 166), >+"Libpkix internal error occured during cert validation.") >Index: devel/certext.c >=================================================================== >RCS file: devel/certext.c >diff -N devel/certext.c >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ devel/certext.c 3 May 2008 22:54:55 -0000 1.2 >@@ -0,0 +1,1852 @@ >+/* >+ Copyright 2005 Red Hat, Inc. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. >+ >+ In addition, as a special exception, Red Hat, Inc. gives permission >+ to link the code of this program with the OpenSSL library (or with >+ modified versions of OpenSSL that use the same license as OpenSSL), >+ and distribute linked combinations including the two. You must obey >+ the GNU General Public License in all respects for all of the code >+ used other than OpenSSL. If you modify this file, you may extend >+ this exception to your version of the file, but you are not >+ obligated to do so. If you do not wish to do so, delete this >+ exception statement from your version. >+ >+*/ >+ >+/* ***** BEGIN LICENSE BLOCK ***** >+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 >+ * >+ * The contents of this file are subject to the Mozilla Public License Version >+ * 1.1 (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * http://www.mozilla.org/MPL/ >+ * >+ * Software distributed under the License is distributed on an "AS IS" basis, >+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License >+ * for the specific language governing rights and limitations under the >+ * License. >+ * >+ * The Original Code is the Netscape security libraries. >+ * >+ * The Initial Developer of the Original Code is >+ * Netscape Communications Corporation. >+ * Portions created by the Initial Developer are Copyright (C) 1994-2000 >+ * the Initial Developer. All Rights Reserved. >+ * >+ * Contributor(s): >+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories >+ * >+ * Alternatively, the contents of this file may be used under the terms of >+ * either the GNU General Public License Version 2 or later (the "GPL"), or >+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), >+ * in which case the provisions of the GPL or the LGPL are applicable instead >+ * of those above. If you wish to allow use of your version of this file only >+ * under the terms of either the GPL or the LGPL, and not to allow others to >+ * use your version of this file under the terms of the MPL, indicate your >+ * decision by deleting the provisions above and replace them with the notice >+ * and other provisions required by the GPL or the LGPL. If you do not delete >+ * the provisions above, a recipient may use your version of this file under >+ * the terms of any one of the MPL, the GPL or the LGPL. >+ * >+ * ***** END LICENSE BLOCK ***** */ >+ >+/* >+** certext.c >+** >+** part of certutil for managing certificates extensions >+** >+*/ >+#include <stdio.h> >+#include <string.h> >+#include <stdlib.h> >+ >+#include "secutil.h" >+ >+#include <unistd.h> >+ >+#include <cert.h> >+#include <prprf.h> >+#include <certt.h> >+ >+#include "keyutil.h" >+ >+#define GEN_BREAK(e) rv=e; break; >+ >+/* CERT_EncodeSubjectKeyID is a private function decleared in <xconst.h> */ >+ >+/* Begin From NSS's xconst.c */ >+static const SEC_ASN1Template CERTSubjectKeyIDTemplate[] = { >+ { SEC_ASN1_OCTET_STRING } >+}; >+ >+SECStatus >+CERT_EncodeSubjectKeyID(PRArenaPool *arena, const SECItem* srcString, >+ SECItem *encodedValue) >+{ >+ SECStatus rv = SECSuccess; >+ >+ if (!srcString) { >+ PORT_SetError(SEC_ERROR_INVALID_ARGS); >+ return SECFailure; >+ } >+ if (SEC_ASN1EncodeItem (arena, encodedValue, srcString, >+ CERTSubjectKeyIDTemplate) == NULL) { >+ rv = SECFailure; >+ } >+ >+ return(rv); >+} >+/* End From xconst.c */ >+ >+ >+/* From oidstring.c */ >+/* if to->data is not NULL, and to->len is large enough to hold the result, >+ * then the resultant OID will be copyed into to->data, and to->len will be >+ * changed to show the actual OID length. >+ * Otherwise, memory for the OID will be allocated (from the caller's >+ * PLArenaPool, if pool is non-NULL) and to->data will receive the address >+ * of the allocated data, and to->len will receive the OID length. >+ * The original value of to->data is not freed when a new buffer is allocated. >+ * >+ * The input string may begin with "OID." and this still be ignored. >+ * The length of the input string is given in len. If len == 0, then >+ * len will be computed as strlen(from), meaning it must be NUL terminated. >+ * It is an error if from == NULL, or if *from == '\0'. >+ */ >+ >+SECStatus >+SEC_StringToOID(PLArenaPool *pool, SECItem *to, const char *from, PRUint32 len) >+{ >+ /*PRUint32 result_len = 0;*/ >+ PRUint32 decimal_numbers = 0; >+ PRUint32 result_bytes = 0; >+ SECStatus rv; >+ PRUint8 result[1024]; >+ >+ static const PRUint32 max_decimal = (0xffffffff / 10); >+ static const char OIDstring[] = {"OID."}; >+ >+ if (!from || !to) { >+ PORT_SetError(SEC_ERROR_INVALID_ARGS); >+ return SECFailure; >+ } >+ if (!len) { >+ len = PL_strlen(from); >+ } >+ if (len >= 4 && !PL_strncasecmp(from, OIDstring, 4)) { >+ from += 4; /* skip leading "OID." if present */ >+ len -= 4; >+ } >+ if (!len) { >+bad_data: >+ PORT_SetError(SEC_ERROR_BAD_DATA); >+ return SECFailure; >+ } >+ do { >+ PRUint32 decimal = 0; >+ while (len > 0 && isdigit(*from)) { >+ PRUint32 addend = (*from++ - '0'); >+ --len; >+ if (decimal > max_decimal) /* overflow */ >+ goto bad_data; >+ decimal = (decimal * 10) + addend; >+ if (decimal < addend) /* overflow */ >+ goto bad_data; >+ } >+ if (len != 0 && *from != '.') { >+ goto bad_data; >+ } >+ if (decimal_numbers == 0) { >+ if (decimal > 2) >+ goto bad_data; >+ result[0] = decimal * 40; >+ result_bytes = 1; >+ } else if (decimal_numbers == 1) { >+ if (decimal > 40) >+ goto bad_data; >+ result[0] += decimal; >+ } else { >+ /* encode the decimal number, */ >+ PRUint8 * rp; >+ PRUint32 num_bytes = 0; >+ PRUint32 tmp = decimal; >+ while (tmp) { >+ num_bytes++; >+ tmp >>= 7; >+ } >+ if (!num_bytes ) >+ ++num_bytes; /* use one byte for a zero value */ >+ if (num_bytes + result_bytes > sizeof result) >+ goto bad_data; >+ tmp = num_bytes; >+ rp = result + result_bytes - 1; >+ rp[tmp] = (PRUint8)(decimal & 0x7f); >+ decimal >>= 7; >+ while (--tmp > 0) { >+ rp[tmp] = (PRUint8)(decimal | 0x80); >+ decimal >>= 7; >+ } >+ result_bytes += num_bytes; >+ } >+ ++decimal_numbers; >+ if (len > 0) { /* skip trailing '.' */ >+ ++from; >+ --len; >+ } >+ } while (len > 0); >+ /* now result contains result_bytes of data */ >+ if (to->data && to->len >= result_bytes) { >+ PORT_Memcpy(to->data, result, to->len = result_bytes); >+ rv = SECSuccess; >+ } else { >+ SECItem result_item = {siBuffer, NULL, 0 }; >+ result_item.data = result; >+ result_item.len = result_bytes; >+ rv = SECITEM_CopyItem(pool, to, &result_item); >+ } >+ return rv; >+} >+ >+static char * >+Gets_s(char *buff, size_t size) { >+ char *str; >+ >+ if (buff == NULL || size < 1) { >+ PORT_Assert(0); >+ return NULL; >+ } >+ if ((str = fgets(buff, size, stdin)) != NULL) { >+ int len = PORT_Strlen(str); >+ /* >+ * fgets() automatically converts native text file >+ * line endings to '\n'. As defensive programming >+ * (just in case fgets has a bug or we put stdin in >+ * binary mode by mistake), we handle three native >+ * text file line endings here: >+ * '\n' Unix (including Linux and Mac OS X) >+ * '\r''\n' DOS/Windows & OS/2 >+ * '\r' Mac OS Classic >+ * len can not be less then 1, since in case with >+ * empty string it has at least '\n' in the buffer >+ */ >+ if (buff[len - 1] == '\n' || buff[len - 1] == '\r') { >+ buff[len - 1] = '\0'; >+ if (len > 1 && buff[len - 2] == '\r') >+ buff[len - 2] = '\0'; >+ } >+ } else { >+ buff[0] = '\0'; >+ } >+ return str; >+} >+ >+ >+static SECStatus >+PrintChoicesAndGetAnswer(char* str, char* rBuff, int rSize) >+{ >+ fprintf(stdout, str); >+ fprintf(stdout, " > "); >+ fflush (stdout); >+ if (Gets_s(rBuff, rSize) == NULL) { >+ PORT_SetError(SEC_ERROR_INPUT_LEN); >+ return SECFailure; >+ } >+ return SECSuccess; >+} >+ >+static CERTGeneralName * >+GetGeneralName (PRArenaPool *arena) >+{ >+ CERTGeneralName *namesList = NULL; >+ CERTGeneralName *current; >+ CERTGeneralName *tail = NULL; >+ SECStatus rv = SECSuccess; >+ int intValue; >+ char buffer[512]; >+ void *mark; >+ >+ PORT_Assert (arena); >+ mark = PORT_ArenaMark (arena); >+ do { >+ if (PrintChoicesAndGetAnswer( >+ "\nSelect one of the following general name type: \n" >+ "\t2 - rfc822Name\n" >+ "\t3 - dnsName\n" >+ "\t5 - directoryName\n" >+ "\t7 - uniformResourceidentifier\n" >+ "\t8 - ipAddress\n" >+ "\t9 - registerID\n" >+ "\tAny other number to finish\n" >+ "\t\tChoice:", buffer, sizeof(buffer)) == SECFailure) { >+ GEN_BREAK (SECFailure); >+ } >+ intValue = PORT_Atoi (buffer); >+ /* >+ * Should use ZAlloc instead of Alloc to avoid problem with garbage >+ * initialized pointers in CERT_CopyName >+ */ >+ switch (intValue) { >+ case certRFC822Name: >+ case certDNSName: >+ case certDirectoryName: >+ case certURI: >+ case certIPAddress: >+ case certRegisterID: >+ break; >+ default: >+ intValue = 0; /* force a break for anything else */ >+ } >+ >+ if (intValue == 0) >+ break; >+ >+ if (namesList == NULL) { >+ namesList = current = tail = >+ PORT_ArenaZNew(arena, CERTGeneralName); >+ } else { >+ current = PORT_ArenaZNew(arena, CERTGeneralName); >+ } >+ if (current == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ current->type = intValue; >+ puts ("\nEnter data:"); >+ fflush (stdout); >+ if (Gets_s (buffer, sizeof(buffer)) == NULL) { >+ PORT_SetError(SEC_ERROR_INPUT_LEN); >+ GEN_BREAK (SECFailure); >+ } >+ switch (current->type) { >+ case certURI: >+ case certDNSName: >+ case certRFC822Name: >+ current->name.other.data = >+ PORT_ArenaAlloc (arena, strlen (buffer)); >+ if (current->name.other.data == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ PORT_Memcpy(current->name.other.data, buffer, >+ current->name.other.len = strlen(buffer)); >+ break; >+ >+ case certEDIPartyName: >+ case certIPAddress: >+ case certOtherName: >+ case certRegisterID: >+ case certX400Address: { >+ >+ current->name.other.data = >+ PORT_ArenaAlloc (arena, strlen (buffer) + 2); >+ if (current->name.other.data == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ PORT_Memcpy (current->name.other.data + 2, buffer, >+ strlen (buffer)); >+ /* This may not be accurate for all cases. For now, >+ * use this tag type */ >+ current->name.other.data[0] = >+ (char)(((current->type - 1) & 0x1f)| 0x80); >+ current->name.other.data[1] = (char)strlen (buffer); >+ current->name.other.len = strlen (buffer) + 2; >+ break; >+ } >+ >+ case certDirectoryName: >+ { >+ CERTName *directoryName = NULL; >+ >+ directoryName = CERT_AsciiToName (buffer); >+ if (!directoryName) { >+ fprintf(stderr, "certutil: improperly formatted name: " >+ "\"%s\"\n", buffer); >+ break; >+ } >+ >+ rv = CERT_CopyName (arena, ¤t->name.directoryName, >+ directoryName); >+ CERT_DestroyName (directoryName); >+ >+ break; >+ } >+ } >+ if (rv != SECSuccess) >+ break; >+ current->l.next = &(namesList->l); >+ current->l.prev = &(tail->l); >+ tail->l.next = &(current->l); >+ tail = current; >+ >+ } while (1); >+ >+ if (rv != SECSuccess) { >+ PORT_ArenaRelease (arena, mark); >+ namesList = NULL; >+ } >+ return (namesList); >+} >+ >+static SECStatus >+GetString(PRArenaPool *arena, char *prompt, SECItem *value) >+{ >+ char buffer[251]; >+ char *buffPrt; >+ >+ buffer[0] = '\0'; >+ value->data = NULL; >+ value->len = 0; >+ >+ puts (prompt); >+ buffPrt = Gets_s (buffer, sizeof(buffer)); >+ /* returned NULL here treated the same way as empty string */ >+ if (buffPrt && strlen (buffer) > 0) { >+ value->data = PORT_ArenaAlloc (arena, strlen (buffer)); >+ if (value->data == NULL) { >+ PORT_SetError (SEC_ERROR_NO_MEMORY); >+ return (SECFailure); >+ } >+ PORT_Memcpy (value->data, buffer, value->len = strlen(buffer)); >+ } >+ return (SECSuccess); >+} >+ >+static PRBool >+GetYesNo(char *prompt) >+{ >+ char buf[3]; >+ char *buffPrt; >+ >+ buf[0] = 'n'; >+ puts(prompt); >+ buffPrt = Gets_s(buf, sizeof(buf)); >+ return (buffPrt && (buf[0] == 'y' || buf[0] == 'Y')) ? PR_TRUE : PR_FALSE; >+} >+ >+static SECStatus >+AddKeyUsage (void *extHandle) >+{ >+ SECItem bitStringValue; >+ unsigned char keyUsage = 0x0; >+ char buffer[5]; >+ int value; >+ PRBool yesNoAns; >+ >+ while (1) { >+ if (PrintChoicesAndGetAnswer( >+ "\t\t0 - Digital Signature\n" >+ "\t\t1 - Non-repudiation\n" >+ "\t\t2 - Key encipherment\n" >+ "\t\t3 - Data encipherment\n" >+ "\t\t4 - Key agreement\n" >+ "\t\t5 - Cert signing key\n" >+ "\t\t6 - CRL signing key\n" >+ "\t\tOther to finish\n", >+ buffer, sizeof(buffer)) == SECFailure) { >+ return SECFailure; >+ } >+ value = PORT_Atoi (buffer); >+ if (value < 0 || value > 6) >+ break; >+ if (value == 0) { >+ /* Checking that zero value of variable 'value' >+ * corresponds to '0' input made by user */ >+ char *chPtr = strchr(buffer, '0'); >+ if (chPtr == NULL) { >+ continue; >+ } >+ } >+ keyUsage |= (0x80 >> value); >+ } >+ >+ bitStringValue.data = &keyUsage; >+ bitStringValue.len = 1; >+ yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); >+ >+ return (CERT_EncodeAndAddBitStrExtension >+ (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue, >+ yesNoAns)); >+ >+} >+ >+ >+static CERTOidSequence * >+CreateOidSequence(void) >+{ >+ CERTOidSequence *rv = (CERTOidSequence *)NULL; >+ PRArenaPool *arena = (PRArenaPool *)NULL; >+ >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if( (PRArenaPool *)NULL == arena ) { >+ goto loser; >+ } >+ >+ rv = (CERTOidSequence *)PORT_ArenaZNew(arena, CERTOidSequence); >+ if( (CERTOidSequence *)NULL == rv ) { >+ goto loser; >+ } >+ >+ rv->oids = (SECItem **)PORT_ArenaZNew(arena, SECItem *); >+ if( (SECItem **)NULL == rv->oids ) { >+ goto loser; >+ } >+ >+ rv->arena = arena; >+ return rv; >+ >+loser: >+ if( (PRArenaPool *)NULL != arena ) { >+ PORT_FreeArena(arena, PR_FALSE); >+ } >+ >+ return (CERTOidSequence *)NULL; >+} >+ >+static void >+DestroyOidSequence(CERTOidSequence *os) >+{ >+ if (os->arena) { >+ PORT_FreeArena(os->arena, PR_FALSE); >+ } >+} >+ >+static SECStatus >+AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag) >+{ >+ SECItem **oids; >+ PRUint32 count = 0; >+ SECOidData *od; >+ >+ od = SECOID_FindOIDByTag(oidTag); >+ if( (SECOidData *)NULL == od ) { >+ return SECFailure; >+ } >+ >+ for( oids = os->oids; (SECItem *)NULL != *oids; oids++ ) { >+ count++; >+ } >+ >+ /* ArenaZRealloc */ >+ >+ { >+ PRUint32 i; >+ >+ oids = (SECItem **)PORT_ArenaZNewArray(os->arena, SECItem *, count + 2); >+ if( (SECItem **)NULL == oids ) { >+ return SECFailure; >+ } >+ >+ for( i = 0; i < count; i++ ) { >+ oids[i] = os->oids[i]; >+ } >+ >+ /* ArenaZFree(os->oids); */ >+ } >+ >+ os->oids = oids; >+ os->oids[count] = &od->oid; >+ >+ return SECSuccess; >+} >+ >+SEC_ASN1_MKSUB(SEC_ObjectIDTemplate) >+ >+const SEC_ASN1Template CERT_OidSeqTemplate[] = { >+ { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, offsetof(CERTOidSequence, oids), >+ SEC_ASN1_SUB(SEC_ObjectIDTemplate) } >+}; >+ >+ >+static SECItem * >+EncodeOidSequence(CERTOidSequence *os) >+{ >+ SECItem *rv; >+ >+ rv = (SECItem *)PORT_ArenaZNew(os->arena, SECItem); >+ if( (SECItem *)NULL == rv ) { >+ goto loser; >+ } >+ >+ if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) { >+ goto loser; >+ } >+ >+ return rv; >+ >+loser: >+ return (SECItem *)NULL; >+} >+ >+static SECStatus >+AddExtKeyUsage (void *extHandle) >+{ >+ char buffer[5]; >+ int value; >+ CERTOidSequence *os; >+ SECStatus rv; >+ SECItem *item; >+ PRBool yesNoAns; >+ >+ os = CreateOidSequence(); >+ if( (CERTOidSequence *)NULL == os ) { >+ return SECFailure; >+ } >+ >+ while (1) { >+ if (PrintChoicesAndGetAnswer( >+ "\t\t0 - Server Auth\n" >+ "\t\t1 - Client Auth\n" >+ "\t\t2 - Code Signing\n" >+ "\t\t3 - Email Protection\n" >+ "\t\t4 - Timestamp\n" >+ "\t\t5 - OCSP Responder\n" >+ "\t\t6 - Step-up\n" >+ "\t\tOther to finish\n", >+ buffer, sizeof(buffer)) == SECFailure) { >+ GEN_BREAK(SECFailure); >+ } >+ value = PORT_Atoi(buffer); >+ >+ if (value == 0) { >+ /* Checking that zero value of variable 'value' >+ * corresponds to '0' input made by user */ >+ char *chPtr = strchr(buffer, '0'); >+ if (chPtr == NULL) { >+ continue; >+ } >+ } >+ >+ switch( value ) { >+ case 0: >+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH); >+ break; >+ case 1: >+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH); >+ break; >+ case 2: >+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN); >+ break; >+ case 3: >+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT); >+ break; >+ case 4: >+ rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP); >+ break; >+ case 5: >+ rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER); >+ break; >+ case 6: >+ rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED); >+ break; >+ default: >+ goto endloop; >+ } >+ >+ if( SECSuccess != rv ) goto loser; >+ } >+ >+endloop: >+ item = EncodeOidSequence(os); >+ >+ yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); >+ >+ rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, item, >+ yesNoAns, PR_TRUE); >+ /*FALLTHROUGH*/ >+loser: >+ DestroyOidSequence(os); >+ return rv; >+} >+ >+static SECStatus >+AddNscpCertType (void *extHandle) >+{ >+ SECItem bitStringValue; >+ unsigned char keyUsage = 0x0; >+ char buffer[5]; >+ int value; >+ PRBool yesNoAns; >+ >+ while (1) { >+ if (PrintChoicesAndGetAnswer( >+ "\t\t0 - SSL Client\n" >+ "\t\t1 - SSL Server\n" >+ "\t\t2 - S/MIME\n" >+ "\t\t3 - Object Signing\n" >+ "\t\t4 - Reserved for future use\n" >+ "\t\t5 - SSL CA\n" >+ "\t\t6 - S/MIME CA\n" >+ "\t\t7 - Object Signing CA\n" >+ "\t\tOther to finish\n", >+ buffer, sizeof(buffer)) == SECFailure) { >+ return SECFailure; >+ } >+ value = PORT_Atoi (buffer); >+ if (value < 0 || value > 7) >+ break; >+ if (value == 0) { >+ /* Checking that zero value of variable 'value' >+ * corresponds to '0' input made by user */ >+ char *chPtr = strchr(buffer, '0'); >+ if (chPtr == NULL) { >+ continue; >+ } >+ } >+ keyUsage |= (0x80 >> value); >+ } >+ >+ bitStringValue.data = &keyUsage; >+ bitStringValue.len = 1; >+ yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); >+ >+ return (CERT_EncodeAndAddBitStrExtension >+ (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue, >+ yesNoAns)); >+ >+} >+ >+static SECStatus >+AddSubjectAltNames(PRArenaPool *arena, CERTGeneralName **existingListp, >+ const char *names, CERTGeneralNameType type) >+{ >+ CERTGeneralName *nameList = NULL; >+ CERTGeneralName *current = NULL; >+ PRCList *prev = NULL; >+ const char *cp; >+ char *tbuf; >+ SECStatus rv = SECSuccess; >+ >+ >+ /* >+ * walk down the comma separated list of names. NOTE: there is >+ * no sanity checks to see if the email address look like >+ * email addresses. >+ */ >+ for (cp=names; cp; cp = PORT_Strchr(cp,',')) { >+ int len; >+ char *end; >+ >+ if (*cp == ',') { >+ cp++; >+ } >+ end = PORT_Strchr(cp,','); >+ len = end ? end-cp : PORT_Strlen(cp); >+ if (len <= 0) { >+ continue; >+ } >+ tbuf = PORT_ArenaAlloc(arena,len+1); >+ PORT_Memcpy(tbuf,cp,len); >+ tbuf[len] = 0; >+ current = (CERTGeneralName *) PORT_ZAlloc(sizeof(CERTGeneralName)); >+ if (!current) { >+ rv = SECFailure; >+ break; >+ } >+ if (prev) { >+ current->l.prev = prev; >+ prev->next = &(current->l); >+ } else { >+ nameList = current; >+ } >+ current->type = type; >+ current->name.other.data = (unsigned char *)tbuf; >+ current->name.other.len = PORT_Strlen(tbuf); >+ prev = &(current->l); >+ } >+ /* at this point nameList points to the head of a doubly linked, >+ * but not yet circular, list and current points to its tail. */ >+ if (rv == SECSuccess && nameList) { >+ if (*existingListp != NULL) { >+ PRCList *existingprev; >+ /* add nameList to the end of the existing list */ >+ existingprev = (*existingListp)->l.prev; >+ (*existingListp)->l.prev = &(current->l); >+ nameList->l.prev = existingprev; >+ existingprev->next = &(nameList->l); >+ current->l.next = &((*existingListp)->l); >+ } >+ else { >+ /* make nameList circular and set it as the new existingList */ >+ nameList->l.prev = prev; >+ current->l.next = &(nameList->l); >+ *existingListp = nameList; >+ } >+ } >+ return rv; >+} >+ >+static SECStatus >+AddEmailSubjectAlt(PRArenaPool *arena, CERTGeneralName **existingListp, >+ const char *emailAddrs) >+{ >+ return AddSubjectAltNames(arena, existingListp, emailAddrs, >+ certRFC822Name); >+} >+ >+static SECStatus >+AddDNSSubjectAlt(PRArenaPool *arena, CERTGeneralName **existingListp, >+ const char *dnsNames) >+{ >+ return AddSubjectAltNames(arena, existingListp, dnsNames, certDNSName); >+} >+ >+ >+static SECStatus >+AddBasicConstraint(void *extHandle) >+{ >+ CERTBasicConstraints basicConstraint; >+ SECStatus rv; >+ char buffer[10]; >+ PRBool yesNoAns; >+ >+ do { >+ basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT; >+ basicConstraint.isCA = GetYesNo ("Is this a CA certificate [y/N]?"); >+ >+ buffer[0] = '\0'; >+ if (PrintChoicesAndGetAnswer("Enter the path length constraint, " >+ "enter to skip [<0 for unlimited path]:", >+ buffer, sizeof(buffer)) == SECFailure) { >+ GEN_BREAK(SECFailure); >+ } >+ if (PORT_Strlen (buffer) > 0) >+ basicConstraint.pathLenConstraint = PORT_Atoi (buffer); >+ >+ yesNoAns = GetYesNo ("Is this a critical extension [y/N]?"); >+ >+ rv = SECU_EncodeAndAddExtensionValue(NULL, extHandle, >+ &basicConstraint, yesNoAns, SEC_OID_X509_BASIC_CONSTRAINTS, >+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeBasicConstraintValue); >+ } while (0); >+ >+ return (rv); >+} >+ >+static SECStatus >+AddAuthKeyID (void *extHandle) >+{ >+ CERTAuthKeyID *authKeyID = NULL; >+ PRArenaPool *arena = NULL; >+ SECStatus rv = SECSuccess; >+ PRBool yesNoAns; >+ >+ do { >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if ( !arena ) { >+ SECU_PrintError(progName, "out of memory"); >+ GEN_BREAK (SECFailure); >+ } >+ >+ if (GetYesNo ("Enter value for the authKeyID extension [y/N]?") == 0) >+ break; >+ >+ authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID); >+ if (authKeyID == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ rv = GetString (arena, "Enter value for the key identifier fields," >+ "enter to omit:", &authKeyID->keyID); >+ if (rv != SECSuccess) >+ break; >+ >+ SECU_SECItemHexStringToBinary(&authKeyID->keyID); >+ >+ authKeyID->authCertIssuer = GetGeneralName (arena); >+ if (authKeyID->authCertIssuer == NULL && >+ SECFailure == PORT_GetError ()) >+ break; >+ >+ >+ rv = GetString (arena, "Enter value for the authCertSerial field, " >+ "enter to omit:", &authKeyID->authCertSerialNumber); >+ >+ yesNoAns = GetYesNo ("Is this a critical extension [y/N]?"); >+ >+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, >+ authKeyID, yesNoAns, SEC_OID_X509_AUTH_KEY_ID, >+ (EXTEN_EXT_VALUE_ENCODER) CERT_EncodeAuthKeyID); >+ if (rv) >+ break; >+ >+ } while (0); >+ if (arena) >+ PORT_FreeArena (arena, PR_FALSE); >+ return (rv); >+} >+ >+static SECStatus >+AddSubjKeyID (void *extHandle) >+{ >+ SECItem keyID; >+ PRArenaPool *arena = NULL; >+ SECStatus rv = SECSuccess; >+ PRBool yesNoAns; >+ >+ do { >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if ( !arena ) { >+ SECU_PrintError(progName, "out of memory"); >+ GEN_BREAK (SECFailure); >+ } >+ printf("Adding Subject Key ID extension.\n"); >+ >+ rv = GetString (arena, "Enter value for the key identifier fields," >+ "enter to omit:", &keyID); >+ if (rv != SECSuccess) >+ break; >+ >+ SECU_SECItemHexStringToBinary(&keyID); >+ >+ yesNoAns = GetYesNo ("Is this a critical extension [y/N]?"); >+ >+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, >+ &keyID, yesNoAns, SEC_OID_X509_SUBJECT_KEY_ID, >+ (EXTEN_EXT_VALUE_ENCODER) CERT_EncodeSubjectKeyID); >+ if (rv) >+ break; >+ >+ } while (0); >+ if (arena) >+ PORT_FreeArena (arena, PR_FALSE); >+ return (rv); >+} >+ >+static SECStatus >+AddCrlDistPoint(void *extHandle) >+{ >+ PRArenaPool *arena = NULL; >+ CERTCrlDistributionPoints *crlDistPoints = NULL; >+ CRLDistributionPoint *current; >+ SECStatus rv = SECSuccess; >+ int count = 0, intValue; >+ char buffer[512]; >+ >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if ( !arena ) >+ return (SECFailure); >+ >+ do { >+ current = NULL; >+ >+ current = PORT_ArenaZNew(arena, CRLDistributionPoint); >+ if (current == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ /* Get the distributionPointName fields - this field is optional */ >+ if (PrintChoicesAndGetAnswer( >+ "Enter the type of the distribution point name:\n" >+ "\t1 - Full Name\n\t2 - Relative Name\n\tAny other " >+ "number to finish\n\t\tChoice: ", >+ buffer, sizeof(buffer)) == SECFailure) { >+ GEN_BREAK (SECFailure); >+ } >+ intValue = PORT_Atoi (buffer); >+ switch (intValue) { >+ case generalName: >+ current->distPointType = intValue; >+ current->distPoint.fullName = GetGeneralName (arena); >+ rv = PORT_GetError(); >+ break; >+ >+ case relativeDistinguishedName: { >+ CERTName *name; >+ >+ current->distPointType = intValue; >+ puts ("Enter the relative name: "); >+ fflush (stdout); >+ if (Gets_s (buffer, sizeof(buffer)) == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ /* For simplicity, use CERT_AsciiToName to converse from a string >+ to NAME, but we only interest in the first RDN */ >+ name = CERT_AsciiToName (buffer); >+ if (!name) { >+ GEN_BREAK (SECFailure); >+ } >+ rv = CERT_CopyRDN (arena, ¤t->distPoint.relativeName, >+ name->rdns[0]); >+ CERT_DestroyName (name); >+ break; >+ } >+ } >+ if (rv != SECSuccess) >+ break; >+ >+ /* Get the reason flags */ >+ if (PrintChoicesAndGetAnswer( >+ "\nSelect one of the following for the reason flags\n" >+ "\t0 - unused\n\t1 - keyCompromise\n" >+ "\t2 - caCompromise\n\t3 - affiliationChanged\n" >+ "\t4 - superseded\n\t5 - cessationOfOperation\n" >+ "\t6 - certificateHold\n" >+ "\tAny other number to finish\t\tChoice: ", >+ buffer, sizeof(buffer)) == SECFailure) { >+ GEN_BREAK(SECFailure); >+ } >+ intValue = PORT_Atoi (buffer); >+ if (intValue == 0) { >+ /* Checking that zero value of variable 'value' >+ * corresponds to '0' input made by user */ >+ char *chPtr = strchr(buffer, '0'); >+ if (chPtr == NULL) { >+ intValue = -1; >+ } >+ } >+ if (intValue >= 0 && intValue <8) { >+ current->reasons.data = PORT_ArenaAlloc (arena, sizeof(char)); >+ if (current->reasons.data == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ *current->reasons.data = (char)(0x80 >> intValue); >+ current->reasons.len = 1; >+ } >+ puts ("Enter value for the CRL Issuer name:\n"); >+ current->crlIssuer = GetGeneralName (arena); >+ if (current->crlIssuer == NULL && (rv = PORT_GetError()) == SECFailure) >+ break; >+ >+ if (crlDistPoints == NULL) { >+ crlDistPoints = PORT_ArenaZNew(arena, CERTCrlDistributionPoints); >+ if (crlDistPoints == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ } >+ >+ crlDistPoints->distPoints = >+ PORT_ArenaGrow (arena, crlDistPoints->distPoints, >+ sizeof (*crlDistPoints->distPoints) * count, >+ sizeof (*crlDistPoints->distPoints) *(count + 1)); >+ if (crlDistPoints->distPoints == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ crlDistPoints->distPoints[count] = current; >+ ++count; >+ if (GetYesNo("Enter another value for the CRLDistributionPoint " >+ "extension [y/N]?") == 0) { >+ /* Add null to the end to mark end of data */ >+ crlDistPoints->distPoints = >+ PORT_ArenaGrow(arena, crlDistPoints->distPoints, >+ sizeof (*crlDistPoints->distPoints) * count, >+ sizeof (*crlDistPoints->distPoints) *(count + 1)); >+ crlDistPoints->distPoints[count] = NULL; >+ break; >+ } >+ >+ >+ } while (1); >+ >+ if (rv == SECSuccess) { >+ PRBool yesNoAns = GetYesNo ("Is this a critical extension [y/N]?"); >+ >+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, >+ crlDistPoints, yesNoAns, SEC_OID_X509_CRL_DIST_POINTS, >+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCRLDistributionPoints); >+ } >+ if (arena) >+ PORT_FreeArena (arena, PR_FALSE); >+ return (rv); >+} >+ >+ >+ >+static SECStatus >+AddPolicyConstraints(void *extHandle) >+{ >+ CERTCertificatePolicyConstraints *policyConstr; >+ PRArenaPool *arena = NULL; >+ SECStatus rv = SECSuccess; >+ SECItem *item, *dummy; >+ char buffer[512]; >+ int value; >+ PRBool yesNoAns; >+ PRBool skipExt = PR_TRUE; >+ >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if ( !arena ) { >+ SECU_PrintError(progName, "out of memory"); >+ return SECFailure; >+ } >+ >+ policyConstr = PORT_ArenaZNew(arena, CERTCertificatePolicyConstraints); >+ if (policyConstr == NULL) { >+ SECU_PrintError(progName, "out of memory"); >+ goto loser; >+ } >+ >+ if (PrintChoicesAndGetAnswer("for requireExplicitPolicy enter the number " >+ "of certs in path\nbefore explicit policy is required\n" >+ "(press Enter to omit)", buffer, sizeof(buffer)) == SECFailure) { >+ goto loser; >+ } >+ >+ if (PORT_Strlen(buffer)) { >+ value = PORT_Atoi(buffer); >+ if (value < 0) { >+ goto loser; >+ } >+ item = &policyConstr->explicitPolicySkipCerts; >+ dummy = SEC_ASN1EncodeInteger(arena, item, value); >+ if (!dummy) { >+ goto loser; >+ } >+ skipExt = PR_FALSE; >+ } >+ >+ if (PrintChoicesAndGetAnswer("for inihibitPolicyMapping enter " >+ "the number of certs in path\n" >+ "after which policy mapping is not allowed\n" >+ "(press Enter to omit)", buffer, sizeof(buffer)) == SECFailure) { >+ goto loser; >+ } >+ >+ if (PORT_Strlen(buffer)) { >+ value = PORT_Atoi(buffer); >+ if (value < 0) { >+ goto loser; >+ } >+ item = &policyConstr->inhibitMappingSkipCerts; >+ dummy = SEC_ASN1EncodeInteger(arena, item, value); >+ if (!dummy) { >+ goto loser; >+ } >+ skipExt = PR_FALSE; >+ } >+ >+ >+ if (!skipExt) { >+ yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); >+ >+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, policyConstr, >+ yesNoAns, SEC_OID_X509_POLICY_CONSTRAINTS, >+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodePolicyConstraintsExtension); >+ } else { >+ fprintf(stdout, "Policy Constraint extensions must contain " >+ "at least one policy field\n"); >+ rv = SECFailure; >+ } >+ >+loser: >+ if (arena) { >+ PORT_FreeArena (arena, PR_FALSE); >+ } >+ return (rv); >+} >+ >+ >+static SECStatus >+AddInhibitAnyPolicy(void *extHandle) >+{ >+ CERTCertificateInhibitAny certInhibitAny; >+ PRArenaPool *arena = NULL; >+ SECStatus rv = SECSuccess; >+ SECItem *item, *dummy; >+ char buffer[10]; >+ int value; >+ PRBool yesNoAns; >+ >+ >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if ( !arena ) { >+ SECU_PrintError(progName, "out of memory"); >+ return SECFailure; >+ } >+ >+ if (PrintChoicesAndGetAnswer("Enter the number of certs in the path " >+ "permitted to use anyPolicy.\n" >+ "(press Enter for 0)", >+ buffer, sizeof(buffer)) == SECFailure) { >+ goto loser; >+ } >+ >+ item = &certInhibitAny.inhibitAnySkipCerts; >+ value = PORT_Atoi(buffer); >+ if (value < 0) { >+ goto loser; >+ } >+ dummy = SEC_ASN1EncodeInteger(arena, item, value); >+ if (!dummy) { >+ goto loser; >+ } >+ >+ yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); >+ >+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &certInhibitAny, >+ yesNoAns, SEC_OID_X509_INHIBIT_ANY_POLICY, >+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInhibitAnyExtension); >+loser: >+ if (arena) { >+ PORT_FreeArena (arena, PR_FALSE); >+ } >+ return (rv); >+} >+ >+ >+static SECStatus >+AddPolicyMappings(void *extHandle) >+{ >+ CERTPolicyMap **policyMapArr = NULL; >+ CERTPolicyMap *current; >+ PRArenaPool *arena = NULL; >+ SECStatus rv = SECSuccess; >+ int count = 0; >+ char buffer[512]; >+ >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if ( !arena ) { >+ SECU_PrintError(progName, "out of memory"); >+ return SECFailure; >+ } >+ >+ do { >+ if (PrintChoicesAndGetAnswer("Enter an Object Identifier (dotted " >+ "decimal format) for Issuer Domain Policy", >+ buffer, sizeof(buffer)) == SECFailure) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ current = PORT_ArenaZNew(arena, CERTPolicyMap); >+ if (current == NULL) { >+ GEN_BREAK(SECFailure); >+ } >+ >+ rv = SEC_StringToOID(arena, ¤t->issuerDomainPolicy, buffer, 0); >+ if (rv == SECFailure) { >+ GEN_BREAK(SECFailure); >+ } >+ >+ if (PrintChoicesAndGetAnswer("Enter an Object Identifier for " >+ "Subject Domain Policy", >+ buffer, sizeof(buffer)) == SECFailure) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ rv = SEC_StringToOID(arena, ¤t->subjectDomainPolicy, buffer, 0); >+ if (rv == SECFailure) { >+ GEN_BREAK(SECFailure); >+ } >+ >+ if (policyMapArr == NULL) { >+ policyMapArr = PORT_ArenaZNew(arena, CERTPolicyMap *); >+ if (policyMapArr == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ } >+ >+ policyMapArr = PORT_ArenaGrow(arena, policyMapArr, >+ sizeof (current) * count, >+ sizeof (current) *(count + 1)); >+ if (policyMapArr == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ policyMapArr[count] = current; >+ ++count; >+ >+ if (!GetYesNo("Enter another Policy Mapping [y/N]")) { >+ /* Add null to the end to mark end of data */ >+ policyMapArr = PORT_ArenaGrow (arena, policyMapArr, >+ sizeof (current) * count, >+ sizeof (current) *(count + 1)); >+ if (policyMapArr == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ policyMapArr[count] = NULL; >+ break; >+ } >+ >+ } while (1); >+ >+ if (rv == SECSuccess) { >+ CERTCertificatePolicyMappings mappings; >+ PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); >+ >+ mappings.arena = arena; >+ mappings.policyMaps = policyMapArr; >+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &mappings, >+ yesNoAns, SEC_OID_X509_POLICY_MAPPINGS, >+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodePolicyMappingExtension); >+ } >+ if (arena) >+ PORT_FreeArena (arena, PR_FALSE); >+ return (rv); >+} >+ >+enum PoliciQualifierEnum { >+ cpsPointer = 1, >+ userNotice = 2 >+}; >+ >+static CERTPolicyQualifier ** >+RequestPolicyQualifiers(PRArenaPool *arena, SECItem *policyID) >+{ >+ CERTPolicyQualifier **policyQualifArr = NULL; >+ CERTPolicyQualifier *current; >+ SECStatus rv = SECSuccess; >+ int count = 0; >+ char buffer[512]; >+ void *mark; >+ SECOidData *oid = NULL; >+ int intValue = 0; >+ int inCount = 0; >+ >+ PORT_Assert(arena); >+ mark = PORT_ArenaMark(arena); >+ do { >+ current = PORT_ArenaZNew(arena, CERTPolicyQualifier); >+ if (current == NULL) { >+ GEN_BREAK(SECFailure); >+ } >+ >+ /* Get the accessMethod fields */ >+ SECU_PrintObjectID(stdout, policyID, >+ "Choose the type of qualifier for policy" , 0); >+ >+ if (PrintChoicesAndGetAnswer( >+ "\t1 - CPS Pointer qualifier\n" >+ "\t2 - User notice qualifier\n" >+ "\tAny other number to finish\n" >+ "\t\tChoice: ", buffer, sizeof(buffer)) == SECFailure) { >+ GEN_BREAK (SECFailure); >+ } >+ intValue = PORT_Atoi(buffer); >+ switch (intValue) { >+ case cpsPointer: { >+ SECItem input; >+ >+ oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CPS_POINTER_QUALIFIER); >+ if (PrintChoicesAndGetAnswer("Enter CPS pointer URI: ", >+ buffer, sizeof(buffer)) == SECFailure) { >+ GEN_BREAK (SECFailure); >+ } >+ input.len = PORT_Strlen(buffer); >+ input.data = (void*)PORT_ArenaStrdup(arena, buffer); >+ if (input.data == NULL || >+ SEC_ASN1EncodeItem(arena, ¤t->qualifierValue, &input, >+ SEC_ASN1_GET(SEC_IA5StringTemplate)) == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ break; >+ } >+ case userNotice: { >+ SECItem **noticeNumArr; >+ CERTUserNotice *notice = PORT_ArenaZNew(arena, CERTUserNotice); >+ if (!notice) { >+ GEN_BREAK(SECFailure); >+ } >+ >+ oid = SECOID_FindOIDByTag(SEC_OID_PKIX_USER_NOTICE_QUALIFIER); >+ >+ if (GetYesNo("\t add a User Notice reference? [y/N]")) { >+ >+ if (PrintChoicesAndGetAnswer("Enter user organization string: ", >+ buffer, sizeof(buffer)) == SECFailure) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ notice->noticeReference.organization.type = siAsciiString; >+ notice->noticeReference.organization.len = >+ PORT_Strlen(buffer); >+ notice->noticeReference.organization.data = >+ (void*)PORT_ArenaStrdup(arena, buffer); >+ >+ >+ noticeNumArr = PORT_ArenaZNewArray(arena, SECItem *, 2); >+ if (!noticeNumArr) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ do { >+ SECItem *noticeNum; >+ >+ noticeNum = PORT_ArenaZNew(arena, SECItem); >+ >+ if (PrintChoicesAndGetAnswer( >+ "Enter User Notice reference number " >+ "(or -1 to quit): ", >+ buffer, sizeof(buffer)) == SECFailure) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ intValue = PORT_Atoi(buffer); >+ if (noticeNum == NULL) { >+ if (intValue < 0) { >+ fprintf(stdout, "a noticeReference must have at " >+ "least one reference number\n"); >+ GEN_BREAK (SECFailure); >+ } >+ } else { >+ if (intValue >= 0) { >+ noticeNumArr = PORT_ArenaGrow(arena, noticeNumArr, >+ sizeof (current) * inCount, >+ sizeof (current) *(inCount + 1)); >+ if (noticeNumArr == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ } else { >+ break; >+ } >+ } >+ if (!SEC_ASN1EncodeInteger(arena, noticeNum, intValue)) { >+ GEN_BREAK (SECFailure); >+ } >+ noticeNumArr[inCount++] = noticeNum; >+ noticeNumArr[inCount] = NULL; >+ >+ } while (1); >+ if (rv == SECFailure) { >+ GEN_BREAK(SECFailure); >+ } >+ notice->noticeReference.noticeNumbers = noticeNumArr; >+ rv = CERT_EncodeNoticeReference(arena, ¬ice->noticeReference, >+ ¬ice->derNoticeReference); >+ if (rv == SECFailure) { >+ GEN_BREAK(SECFailure); >+ } >+ } >+ if (GetYesNo("\t EnterUser Notice explicit text? [y/N]")) { >+ /* Getting only 200 bytes - RFC limitation */ >+ if (PrintChoicesAndGetAnswer( >+ "\t", buffer, 200) == SECFailure) { >+ GEN_BREAK (SECFailure); >+ } >+ notice->displayText.type = siAsciiString; >+ notice->displayText.len = PORT_Strlen(buffer); >+ notice->displayText.data = >+ (void*)PORT_ArenaStrdup(arena, buffer); >+ if (notice->displayText.data == NULL) { >+ GEN_BREAK(SECFailure); >+ } >+ } >+ >+ rv = CERT_EncodeUserNotice(arena, notice, ¤t->qualifierValue); >+ if (rv == SECFailure) { >+ GEN_BREAK(SECFailure); >+ } >+ >+ break; >+ } >+ } >+ if (rv == SECFailure || oid == NULL || >+ SECITEM_CopyItem(arena, ¤t->qualifierID, &oid->oid) >+ == SECFailure) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ if (!policyQualifArr) { >+ policyQualifArr = PORT_ArenaZNew(arena, CERTPolicyQualifier *); >+ } else { >+ policyQualifArr = PORT_ArenaGrow (arena, policyQualifArr, >+ sizeof (current) * count, >+ sizeof (current) *(count + 1)); >+ } >+ if (policyQualifArr == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ policyQualifArr[count] = current; >+ ++count; >+ >+ if (!GetYesNo ("Enter another policy qualifier [y/N]")) { >+ /* Add null to the end to mark end of data */ >+ policyQualifArr = PORT_ArenaGrow(arena, policyQualifArr, >+ sizeof (current) * count, >+ sizeof (current) *(count + 1)); >+ if (policyQualifArr == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ policyQualifArr[count] = NULL; >+ break; >+ } >+ >+ } while (1); >+ >+ if (rv != SECSuccess) { >+ PORT_ArenaRelease (arena, mark); >+ policyQualifArr = NULL; >+ } >+ return (policyQualifArr); >+} >+ >+static SECStatus >+AddCertPolicies(void *extHandle) >+{ >+ CERTPolicyInfo **certPoliciesArr = NULL; >+ CERTPolicyInfo *current; >+ PRArenaPool *arena = NULL; >+ SECStatus rv = SECSuccess; >+ int count = 0; >+ char buffer[512]; >+ >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if ( !arena ) { >+ SECU_PrintError(progName, "out of memory"); >+ return SECFailure; >+ } >+ >+ do { >+ current = PORT_ArenaZNew(arena, CERTPolicyInfo); >+ if (current == NULL) { >+ GEN_BREAK(SECFailure); >+ } >+ >+ if (PrintChoicesAndGetAnswer("Enter a CertPolicy Object Identifier " >+ "(dotted decimal format)\n" >+ "or \"any\" for AnyPolicy:", >+ buffer, sizeof(buffer)) == SECFailure) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ if (strncmp(buffer, "any", 3) == 0) { >+ /* use string version of X509_CERTIFICATE_POLICIES.anyPolicy */ >+ strcpy(buffer, "OID.2.5.29.32.0"); >+ } >+ rv = SEC_StringToOID(arena, ¤t->policyID, buffer, 0); >+ >+ if (rv == SECFailure) { >+ GEN_BREAK(SECFailure); >+ } >+ >+ current->policyQualifiers = >+ RequestPolicyQualifiers(arena, ¤t->policyID); >+ >+ if (!certPoliciesArr) { >+ certPoliciesArr = PORT_ArenaZNew(arena, CERTPolicyInfo *); >+ } else { >+ certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr, >+ sizeof (current) * count, >+ sizeof (current) *(count + 1)); >+ } >+ if (certPoliciesArr == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ certPoliciesArr[count] = current; >+ ++count; >+ >+ if (!GetYesNo ("Enter another PolicyInformation field [y/N]?")) { >+ /* Add null to the end to mark end of data */ >+ certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr, >+ sizeof (current) * count, >+ sizeof (current) *(count + 1)); >+ if (certPoliciesArr == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ certPoliciesArr[count] = NULL; >+ break; >+ } >+ >+ } while (1); >+ >+ if (rv == SECSuccess) { >+ CERTCertificatePolicies policies; >+ PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); >+ >+ policies.arena = arena; >+ policies.policyInfos = certPoliciesArr; >+ >+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &policies, >+ yesNoAns, SEC_OID_X509_CERTIFICATE_POLICIES, >+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCertPoliciesExtension); >+ } >+ if (arena) >+ PORT_FreeArena(arena, PR_FALSE); >+ return (rv); >+} >+ >+enum AuthInfoAccessTypesEnum { >+ caIssuers = 1, >+ ocsp = 2 >+}; >+ >+enum SubjInfoAccessTypesEnum { >+ caRepository = 1, >+ timeStamping = 2 >+}; >+ >+/* Encode and add an AIA or SIA extension */ >+static SECStatus >+AddInfoAccess(void *extHandle, PRBool addSIAExt, PRBool isCACert) >+{ >+ CERTAuthInfoAccess **infoAccArr = NULL; >+ CERTAuthInfoAccess *current; >+ PRArenaPool *arena = NULL; >+ SECStatus rv = SECSuccess; >+ int count = 0; >+ char buffer[512]; >+ SECOidData *oid = NULL; >+ int intValue = 0; >+ >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if ( !arena ) { >+ SECU_PrintError(progName, "out of memory"); >+ return SECFailure; >+ } >+ >+ do { >+ current = NULL; >+ current = PORT_ArenaZNew(arena, CERTAuthInfoAccess); >+ if (current == NULL) { >+ GEN_BREAK(SECFailure); >+ } >+ >+ /* Get the accessMethod fields */ >+ if (addSIAExt) { >+ if (isCACert) { >+ puts("Adding \"CA Repository\" access method type for " >+ "Subject Information Access extension:\n"); >+ intValue = caRepository; >+ } else { >+ puts("Adding \"Time Stamping Services\" access method type for " >+ "Subject Information Access extension:\n"); >+ intValue = timeStamping; >+ } >+ } else { >+ PrintChoicesAndGetAnswer("Enter access method type " >+ "for Authority Information Access extension:\n" >+ "\t1 - CA Issuers\n\t2 - OCSP\n\tAny" >+ "other number to finish\n\tChoice", >+ buffer, sizeof(buffer)); >+ intValue = PORT_Atoi(buffer); >+ } >+ if (addSIAExt) { >+ switch (intValue) { >+ case caRepository: >+ oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_REPOSITORY); >+ break; >+ >+ case timeStamping: >+ oid = SECOID_FindOIDByTag(SEC_OID_PKIX_TIMESTAMPING); >+ break; >+ } >+ } else { >+ switch (intValue) { >+ case caIssuers: >+ oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_ISSUERS); >+ break; >+ >+ case ocsp: >+ oid = SECOID_FindOIDByTag(SEC_OID_PKIX_OCSP); >+ break; >+ } >+ } >+ if (oid == NULL || >+ SECITEM_CopyItem(arena, ¤t->method, &oid->oid) >+ == SECFailure) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ current->location = GetGeneralName(arena); >+ if (!current->location) { >+ GEN_BREAK(SECFailure); >+ } >+ >+ if (infoAccArr == NULL) { >+ infoAccArr = PORT_ArenaZNew(arena, CERTAuthInfoAccess *); >+ } else { >+ infoAccArr = PORT_ArenaGrow(arena, infoAccArr, >+ sizeof (current) * count, >+ sizeof (current) *(count + 1)); >+ } >+ if (infoAccArr == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ infoAccArr[count] = current; >+ ++count; >+ >+ PR_snprintf(buffer, sizeof(buffer), "Add another location to the %s" >+ " Information Access extension [y/N]", >+ (addSIAExt) ? "Subject" : "Authority"); >+ >+ if (GetYesNo (buffer) == 0) { >+ /* Add null to the end to mark end of data */ >+ infoAccArr = PORT_ArenaGrow(arena, infoAccArr, >+ sizeof (current) * count, >+ sizeof (current) *(count + 1)); >+ if (infoAccArr == NULL) { >+ GEN_BREAK (SECFailure); >+ } >+ infoAccArr[count] = NULL; >+ break; >+ } >+ >+ } while (1); >+ >+ if (rv == SECSuccess) { >+ int oidIdent = SEC_OID_X509_AUTH_INFO_ACCESS; >+ >+ PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?"); >+ >+ if (addSIAExt) { >+ oidIdent = SEC_OID_X509_SUBJECT_INFO_ACCESS; >+ } >+ rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, infoAccArr, >+ yesNoAns, oidIdent, >+ (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInfoAccessExtension); >+ } >+ if (arena) >+ PORT_FreeArena(arena, PR_FALSE); >+ return (rv); >+} >+ >+SECStatus >+AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames, >+ certutilExtnList extList) >+{ >+ SECStatus rv = SECSuccess; >+ char *errstring = NULL; >+ >+ do { >+ /* Add key usage extension */ >+ if (extList[ext_keyUsage]) { >+ rv = AddKeyUsage(extHandle); >+ if (rv) { >+ errstring = "KeyUsage"; >+ break; >+ } >+ } >+ >+ /* Add extended key usage extension */ >+ if (extList[ext_extKeyUsage]) { >+ rv = AddExtKeyUsage(extHandle); >+ if (rv) { >+ errstring = "ExtendedKeyUsage"; >+ break; >+ } >+ } >+ >+ /* Add basic constraint extension */ >+ if (extList[ext_basicConstraint]) { >+ rv = AddBasicConstraint(extHandle); >+ if (rv) { >+ errstring = "BasicConstraint"; >+ break; >+ } >+ } >+ >+ if (extList[ext_authorityKeyID]) { >+ rv = AddAuthKeyID(extHandle); >+ if (rv) { >+ errstring = "AuthorityKeyID"; >+ break; >+ } >+ } >+ >+ if (extList[ext_subjectKeyID]) { >+ rv = AddSubjKeyID(extHandle); >+ if (rv) { >+ errstring = "SubjectKeyID"; >+ break; >+ } >+ } >+ >+ if (extList[ext_CRLDistPts]) { >+ rv = AddCrlDistPoint(extHandle); >+ if (rv) { >+ errstring = "CRLDistPoints"; >+ break; >+ } >+ } >+ >+ if (extList[ext_NSCertType]) { >+ rv = AddNscpCertType(extHandle); >+ if (rv) { >+ errstring = "NSCertType"; >+ break; >+ } >+ } >+ >+ if (extList[ext_authInfoAcc] || extList[ext_subjInfoAcc]) { >+ rv = AddInfoAccess(extHandle, extList[ext_subjInfoAcc], >+ extList[ext_basicConstraint]); >+ if (rv) { >+ errstring = "InformationAccess"; >+ break; >+ } >+ } >+ >+ if (extList[ext_certPolicies]) { >+ rv = AddCertPolicies(extHandle); >+ if (rv) { >+ errstring = "Policies"; >+ break; >+ } >+ } >+ >+ if (extList[ext_policyMappings]) { >+ rv = AddPolicyMappings(extHandle); >+ if (rv) { >+ errstring = "PolicyMappings"; >+ break; >+ } >+ } >+ >+ if (extList[ext_policyConstr]) { >+ rv = AddPolicyConstraints(extHandle); >+ if (rv) { >+ errstring = "PolicyConstraints"; >+ break; >+ } >+ } >+ >+ if (extList[ext_inhibitAnyPolicy]) { >+ rv = AddInhibitAnyPolicy(extHandle); >+ if (rv) { >+ errstring = "InhibitAnyPolicy"; >+ break; >+ } >+ } >+ >+ if (emailAddrs || dnsNames) { >+ PRArenaPool *arena; >+ CERTGeneralName *namelist = NULL; >+ SECItem item = { 0, NULL, 0 }; >+ >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if (arena == NULL) { >+ rv = SECFailure; >+ break; >+ } >+ >+ rv = AddEmailSubjectAlt(arena, &namelist, emailAddrs); >+ >+ rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames); >+ >+ if (rv == SECSuccess) { >+ rv = CERT_EncodeAltNameExtension(arena, namelist, &item); >+ if (rv == SECSuccess) { >+ rv = CERT_AddExtension(extHandle, >+ SEC_OID_X509_SUBJECT_ALT_NAME, >+ &item, PR_FALSE, PR_TRUE); >+ } >+ } >+ PORT_FreeArena(arena, PR_FALSE); >+ if (rv) { >+ errstring = "SubjectAltName"; >+ break; >+ } >+ } >+ } while (0); >+ >+ if (rv != SECSuccess) { >+ SECU_PrintError(progName, "Problem creating %s extension", errstring); >+ } >+ return rv; >+} >Index: devel/certwatch.c >=================================================================== >RCS file: /cvs/extras/rpms/crypto-utils/devel/certwatch.c,v >retrieving revision 1.10 >retrieving revision 1.13 >diff -u -p -r1.10 -r1.13 >--- devel/certwatch.c 23 Aug 2007 10:09:40 -0000 1.10 >+++ devel/certwatch.c 6 May 2008 16:15:36 -0000 1.13 >@@ -27,13 +27,63 @@ > > */ > >-/* $Id: certwatch.c,v 1.10 2007/08/23 10:09:40 jorton Exp $ */ >+/* ***** BEGIN LICENSE BLOCK ***** >+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 >+ * >+ * The contents of this file are subject to the Mozilla Public License Version >+ * 1.1 (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * http://www.mozilla.org/MPL/ >+ * >+ * Software distributed under the License is distributed on an "AS IS" basis, >+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License >+ * for the specific language governing rights and limitations under the >+ * License. >+ * >+ * The Original Code is the Netscape security libraries. >+ * >+ * The Initial Developer of the Original Code is >+ * Netscape Communications Corporation. >+ * Portions created by the Initial Developer are Copyright (C) 1994-2000 >+ * the Initial Developer. All Rights Reserved. >+ * >+ * Contributor(s): >+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories >+ * >+ * Alternatively, the contents of this file may be used under the terms of >+ * either the GNU General Public License Version 2 or later (the "GPL"), or >+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), >+ * in which case the provisions of the GPL or the LGPL are applicable instead >+ * of those above. If you wish to allow use of your version of this file only >+ * under the terms of either the GPL or the LGPL, and not to allow others to >+ * use your version of this file under the terms of the MPL, indicate your >+ * decision by deleting the provisions above and replace them with the notice >+ * and other provisions required by the GPL or the LGPL. If you do not delete >+ * the provisions above, a recipient may use your version of this file under >+ * the terms of any one of the MPL, the GPL or the LGPL. >+ * >+ * ***** END LICENSE BLOCK ***** */ >+ >+ >+/* $Id: certwatch.c,v 1.13 2008/05/06 16:15:36 emaldonado Exp $ */ > > /* Certificate expiry warning generation code, based on code from > * Stronghold. Joe Orton <jorton@redhat.com> */ > >-#include <openssl/x509.h> >-#include <openssl/pem.h> >+/* Replaced usage of OpenSSL with NSS. >+ * Elio Maldonado <emaldona@redhat.com> */ >+ >+#include <nspr.h> >+#include <nss.h> >+#include <cert.h> >+#include <certt.h> >+#include <prlong.h> >+#include <prtime.h> >+#include <pk11func.h> >+#include <assert.h> >+#include <secmod.h> >+#include <base64.h> >+#include <seccomon.h> > > #include <stdio.h> > #include <string.h> >@@ -41,55 +91,109 @@ > #include <getopt.h> > #include <time.h> > >+#define TIME_BUF_SIZE 100 >+ >+/* Return a certificate structure from a pem-encoded cert in a file; >+ * or NULL on failure. Semantics similar to the OpenSSL call >+ * PEM_read_X509(fp, NULL, NULL, NULL); >+ */ >+extern CERTCertificate * >+PEMUTIL_PEM_read_X509(const char *filename); >+ >+/* size big enough for formatting time buffer */ >+#define TIME_SIZE 30 >+ > static int warn_period = 30; > static char *warn_address = "root"; > >-/* Turn an ASN.1 UTCTIME object into a time_t. */ >-static time_t decode_utctime(const ASN1_UTCTIME *utc) >+/* Format a PRTime value into a buffer with format "%a %b %d %H:%M:%S %Y" >+ * and return the buffer. The buffer returned must the freed with PORT_Free. >+ * Semantics are similar to asctime. >+ */ >+char * AsciiTime(PRTime time) >+{ >+ PRExplodedTime printable; >+ char *timebuf; >+ >+ PR_ExplodeTime(time, PR_GMTParameters, &printable); >+ timebuf = PORT_Alloc(TIME_BUF_SIZE); >+ (void) PR_FormatTime(timebuf, TIME_BUF_SIZE, "%a %b %d %H:%M:%S %Y", &printable); >+ if (strlen(timebuf) < TIME_BUF_SIZE) timebuf[strlen(timebuf)] = '\0'; >+ return (timebuf); >+} >+ >+/* Uses the password passed in the -f(pwfile) argument of the command line. >+ * After use once, null it out otherwise PKCS11 calls us forever.? >+ * >+ * Code based on SECU_GetModulePassword from the Mozilla NSS secutils >+ * imternal librart. >+ */ >+static char *GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg) > { >- struct tm tm = {0}; >- int i = utc->length; >+ int i; >+ unsigned char phrase[200]; >+ PRFileDesc *fd; >+ PRInt32 nb; >+ char *pwFile = arg; >+ >+ if (!pwFile) return 0; >+ if (retry) return 0; /* no good retrying - file contents will be the same */ >+ if (!(fd = PR_Open(pwFile, PR_RDONLY, 0))) return 0; > >- if (i < 10) >- return -1; >- for (i = 0; i < 10; i++) >- if ((utc->data[i] > '9') || (utc->data[i] < '0')) >- return -1; >- >- tm.tm_year = (utc->data[0]-'0') * 10 + (utc->data[1]-'0'); >- >- /* Deal with Year 2000 like eay did */ >- if (tm.tm_year < 70) >- tm.tm_year += 100; >- >- tm.tm_mon = (utc->data[2]-'0') * 10 + (utc->data[3]-'0') - 1; >- tm.tm_mday = (utc->data[4]-'0') * 10 + (utc->data[5]-'0'); >- tm.tm_hour = (utc->data[6]-'0') * 10 + (utc->data[7]-'0'); >- tm.tm_min = (utc->data[8]-'0') * 10 + (utc->data[9]-'0'); >- tm.tm_sec = (utc->data[10]-'0') * 10 + (utc->data[11]-'0'); >+ nb = PR_Read(fd, phrase, sizeof(phrase)); >+ PR_Close(fd); >+ >+ /* handle the Windows EOL case */ >+ i = 0; >+ while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb) i++; >+ phrase[i] = '\0'; >+ if (nb == 0) return NULL; > >- return mktime(&tm) - timezone; >+ return (char*) PORT_Strdup((char*)phrase); >+} >+ >+/* Format a PRTime value into a buffer with format "%a %b %d %H:%M:%S %Y"; >+ * semantics are those of ctime_r(). */ >+char *pr_ctime(PRTime time, char *buf, int size) >+{ >+ PRUint32 bytesCopied; >+ PRExplodedTime et; >+ PR_ExplodeTime(time, PR_GMTParameters, &et); >+ bytesCopied = PR_FormatTime(buf, size, "%a %b %d %H:%M:%S %Y", &et); >+ if (!bytesCopied) return NULL; >+ return buf; > } > > /* Print a warning message that the certificate in 'filename', issued > * to hostname 'hostname', will expire (or has expired). */ > static int warning(FILE *out, const char *filename, const char *hostname, >- time_t start, time_t end, time_t now, int quiet) >+ SECCertTimeValidity validity, >+ PRTime start, PRTime end, PRTime now, int quiet) > { >- int renew = 1, days = (end - now) / (3600 * 24); /* days till expiry */ >+ /* Note that filename can be the cert nickname. */ >+ int renew = 1; > char subj[50]; >- >- if (start > now) { >+ PRTime prtimeDiff; >+ >+ LL_SUB(prtimeDiff, end, start); >+ >+ if ( LL_CMP(start, >, now) ) { > strcpy(subj, "is not yet valid"); > renew = 0; >- } else if (days < 0) { >- strcpy(subj, "has expired"); >- } else if (days == 0) { >+ } else if (LL_EQ(now, end)) { > strcpy(subj, "will expire today"); >- } else if (days == 1) { >+ } else if (LL_EQ(prtimeDiff, 1)) { > sprintf(subj, "will expire tomorrow"); >- } else if (days < warn_period) { >- sprintf(subj, "will expire in %d days", days); >+ } else if (LL_CMP(prtimeDiff, <, warn_period)) { >+ sprintf(subj, "will expire on %s", AsciiTime(end)); >+ { >+ int days; /* days till expiry */ >+ LL_L2I(days, prtimeDiff); >+ days = (days) / (3600 * 24); >+ assert(0 < days); >+ assert(days < warn_period); >+ sprintf(subj, "will expire in %d days", days); >+ } > } else { > return 0; /* nothing to warn about. */ > } >@@ -104,7 +208,7 @@ static int warning(FILE *out, const char > " ################# SSL Certificate Warning ################\n\n"); > > fprintf(out, >- " Certificate for hostname '%s', in file:\n" >+ " Certificate for hostname '%s', in file (or by nickname):\n" > " %s\n\n", > hostname, filename); > >@@ -115,9 +219,10 @@ static int warning(FILE *out, const char > " web site using SSL until the certificate is renewed.\n", > out); > } else { >- char until[30] = "(unknown date)"; >- ctime_r(&start, until); >- if (strlen(until) > 2) until[strlen(until)-1] = '\0'; >+ char until[TIME_SIZE]; >+ char *result = pr_ctime(start, until, TIME_SIZE); >+ assert(result == until); >+ if (strlen(until) < sizeof(until)) until[strlen(until)] = '\0'; > fprintf(out, > " The certificate is not valid until %s.\n\n" > " Browsers will not be able to correctly connect to this\n" >@@ -133,56 +238,73 @@ static int warning(FILE *out, const char > } > > /* Extract the common name of 'cert' into 'buf'. */ >-static int get_common_name(X509 *cert, char *buf, size_t bufsiz) >+static int get_common_name(CERTCertificate *cert, char *buf, size_t bufsiz) > { >- X509_NAME *name = X509_get_subject_name(cert); >- >+ /* FIXME --- truncating names with spaces */ >+ size_t namelen; >+ char *name = CERT_GetCommonName(&cert->subject); >+ > if (!name) return -1; > >- return X509_NAME_get_text_by_NID(name, NID_commonName, buf, bufsiz) == -1; >+ namelen = strlen(name); >+ if (bufsiz < namelen+1) return -1; >+ >+ strncpy(buf, name, namelen); >+ buf[namelen] = '\0'; >+ PORT_Free(name); >+ >+ return 0; > } > >-/* Check whether the certificate in filename 'filename' has expired; >+/* Check whether the certificate in filename 'name' has expired; > * issue a warning message if 'quiet' is zero. If quiet is non-zero, > * returns one to indicate that a warning would have been issued, zero > * to indicate no warning would be issued, or -1 if an error >- * occurred. */ >-static int check_cert(const char *filename, int quiet) >+ * occurred. >+ * >+ * When byNickname is 1 then 'name' is a nickname to search >+ * for in the database otherwise it's the certificate file. >+ */ >+static int check_cert(const char *name, int byNickname, int quiet) > { >- X509 *cert; >- FILE *fp; >- ASN1_UTCTIME *notAfter, *notBefore; >- time_t begin, end, now; >+ CERTCertificate *cert; >+ SECCertTimeValidity validity; >+ PRTime notBefore, notAfter; > char cname[128]; >+ >+ int doWarning = 0; > > /* parse the cert */ >- if ((fp = fopen(filename, "r")) == NULL) return -1; >- cert = PEM_read_X509(fp, NULL, NULL, NULL); >- fclose(fp); >+ cert = byNickname >+ ? CERT_FindCertByNickname(CERT_GetDefaultCertDB(), (char *)name) >+ : PEMUTIL_PEM_read_X509(name); > if (cert == NULL) return -1; > > /* determine the validity period of the cert. */ >- notAfter = X509_get_notAfter(cert); >- notBefore = X509_get_notBefore(cert); >- >- /* get time_t's out of X509 times */ >- begin = decode_utctime(notBefore); >- end = decode_utctime(notAfter); >- now = time(NULL); >- if (end == -1 || begin == -1 || now == -1) return -1; >+ validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE); >+ if (validity == secCertTimeUndetermined) goto cleanup; > >+ /* get times out of the cert */ >+ if (CERT_GetCertTimes(cert, ¬Before, ¬After) >+ != SECSuccess) goto cleanup; >+ > /* find the subject's commonName attribute */ > if (get_common_name(cert, cname, sizeof cname)) >- return -1; >+ goto cleanup; > >- X509_free(cert); >- >- /* don't warn about the automatically generate certificate */ >+ /* don't warn about the automatically generated certificate */ > if (strcmp(cname, "localhost") == 0 || > strcmp(cname, "localhost.localdomain") == 0) >- return -1; >+ goto cleanup; >+ >+ doWarning = 1; /* ok so far, may do the warning */ > >- return warning(stdout, filename, cname, begin, end, now, quiet); >+cleanup: >+ if (cert) CERT_DestroyCertificate(cert); >+ if (!doWarning) return -1; >+ >+ return warning(stdout, name, cname, validity, >+ notBefore, notAfter, PR_Now(), quiet); > } > > int main(int argc, char **argv) >@@ -192,14 +314,25 @@ int main(int argc, char **argv) > { "quiet", no_argument, NULL, 'q' }, > { "period", required_argument, NULL, 'p' }, > { "address", required_argument, NULL, 'a' }, >+ { "configdir", required_argument, NULL, 'd' }, >+ { "passwordfile", required_argument, NULL, 'w' }, >+ { "certdbprefix", required_argument, NULL, 'c' }, >+ { "keydbprexix", required_argument, NULL, 'k' }, > { NULL } > }; > >+ char *certDBPrefix = ""; >+ char *keyDBPrefix = ""; >+ >+ char *configdir = NULL; /* contains the cert database */ >+ char *passwordfile = NULL; /* module password file */ >+ int byNickname = 0; /* whether to search by nickname */ >+ > /* The 'timezone' global is needed to adjust local times from > * mktime() back to UTC: */ > tzset(); > >- while ((optc = getopt_long(argc, argv, "qp:a:", options, NULL)) != -1) { >+ while ((optc = getopt_long(argc, argv, "qp:a:d:w:c:k:", options, NULL)) != -1) { > switch (optc) { > case 'q': > quiet = 1; >@@ -210,11 +343,50 @@ int main(int argc, char **argv) > case 'a': > warn_address = strdup(optarg); > break; >+ case 'd': >+ configdir = strdup(optarg); >+ byNickname = 1; >+ break; >+ case 'w': >+ passwordfile = strdup(optarg); >+ break; >+ case 'c': >+ certDBPrefix = strdup(optarg); >+ break; >+ case 'k': >+ keyDBPrefix = strdup(optarg); >+ break; > default: > exit(2); > break; > } > } >+ >+ /* NSS initialization */ >+ >+ if (byNickname) { >+ /* cert in database */ >+ if (NSS_Initialize(configdir, certDBPrefix, keyDBPrefix, >+ SECMOD_DB, NSS_INIT_READONLY) != SECSuccess) { >+ return EXIT_FAILURE; >+ } >+ /* in case module requires a password */ >+ if (passwordfile) { >+ PK11_SetPasswordFunc(GetModulePassword); >+ } >+ } else { >+ /* cert in a pem file */ >+ char *certDir = getenv("SSL_DIR"); /* Look in $SSL_DIR */ >+ if (!certDir) { >+ certDir = "/etc/pki/nssdb"; >+ } >+ if (NSS_Initialize(certDir, certDBPrefix, keyDBPrefix, >+ SECMOD_DB, NSS_INIT_READONLY) != SECSuccess) { >+ printf("NSS_Init(\"%s\") failed\n", certDir); >+ return EXIT_FAILURE; >+ } >+ } > >- return check_cert(argv[optind], quiet) == 1 ? EXIT_SUCCESS : EXIT_FAILURE; >+ /* When byNickname is 1 argv[optind] is a nickname otherwise a filename. */ >+ return check_cert(argv[optind], byNickname, quiet) == 1 ? EXIT_SUCCESS : EXIT_FAILURE; > } >Index: devel/certwatch.cron >=================================================================== >RCS file: /cvs/extras/rpms/crypto-utils/devel/certwatch.cron,v >retrieving revision 1.4 >retrieving revision 1.6 >diff -u -p -r1.4 -r1.6 >--- devel/certwatch.cron 26 Apr 2005 12:39:15 -0000 1.4 >+++ devel/certwatch.cron 6 May 2008 16:21:49 -0000 1.6 >@@ -6,6 +6,50 @@ > # CERTWATCH_OPTS variable; see the man page for details. > # > >+# For certificates in pem files >+watch_files_certs() >+{ >+ test -x /etc/httpd/modules/mod_ssl.so || return 0 >+ test -r /etc/httpd/conf/httpd.conf || return 0 >+ >+ set -o pipefail # pick up exit code of httpd not sort >+ >+ certs=`${httpd} ${OPTIONS} -t -DDUMP_CERTS 2>/dev/null | /bin/sort -u` >+ RETVAL=$? >+ test $RETVAL -eq 0 || return >+ >+ for c in $certs; do >+ # Check whether a warning message is needed, then issue one if so. >+ /usr/bin/certwatch $CERTWATCH_OPTS -q "$c" && >+ /usr/bin/certwatch $CERTWATCH_OPTS "$c" | /usr/sbin/sendmail -oem -oi -t 2>/dev/null >+ done >+} >+ >+# For certificates in the database >+watch_database_certs() >+{ >+ test -x /usr/bin/certutil || return 0 >+ test -x /usr/lib/httpd/modules/libmodnss.so || return 0 >+ test -r /etc/httpd/conf.d/nss.conf || return 0 >+ >+ # find path to mod_nss' database >+ database=`/usr/bin/gawk '/^NSSCertificateDatabase/ { print $2 }' /etc/httpd/conf.d/nss.conf` >+ >+ # find the database prefix if any from the mod_nss config file >+ dbprefix=`/usr/bin/gawk '/^NSSDBPrefix/ { print $2 }' /etc/httpd/conf.d/nss.conf` >+ >+ set -o pipefail # pick up exit code of certutil not gawk >+ nicknames=`certutil -L -d $database | /usr/bin/gawk '{ print $1 }'` >+ RETVAL=$? >+ test $RETVAL -eq 0 || return 0 >+ >+ for n in $nicknames; do >+ # Check whether a warning message is needed, then issue one if so. >+ /usr/bin/certwatch $CERTWATCH_OPTS -q -d "$database" -c "$dbprefix" -k "$dbprefix" "$n" && >+ /usr/bin/certwatch $CERTWATCH_OPTS -d "$database" -c "$dbprefix" -k "$dbprefix" "$n" | /usr/sbin/sendmail -oem -oi -t 2>/dev/null >+ done >+} >+ > [ -r /etc/sysconfig/httpd ] && . /etc/sysconfig/httpd > > # Use configured httpd binary >@@ -15,19 +59,8 @@ httpd=${HTTPD-/usr/sbin/httpd} > test -z "${NOCERTWATCH}" || exit 0 > test -x ${httpd} || exit 0 > test -x /usr/bin/certwatch || exit 0 >-test -r /etc/httpd/conf/httpd.conf || exit 0 > test -x /usr/sbin/sendmail || exit 0 >-test -x /etc/httpd/modules/mod_ssl.so || exit 0 > test -x /bin/sort || exit 0 > >-set -o pipefail # pick up exit code of httpd not sort >- >-certs=`${httpd} ${OPTIONS} -t -DDUMP_CERTS 2>/dev/null | /bin/sort -u` >-RETVAL=$? >-test $RETVAL -eq 0 || exit 0 >- >-for c in $certs; do >- # Check whether a warning message is needed, then issue one if so. >- /usr/bin/certwatch $CERTWATCH_OPTS -q "$c" && >- /usr/bin/certwatch $CERTWATCH_OPTS "$c" | /usr/sbin/sendmail -oem -oi -t 2>/dev/null >-done >+watch_files_certs >+watch_database_certs >Index: devel/certwatch.xml >=================================================================== >RCS file: /cvs/extras/rpms/crypto-utils/devel/certwatch.xml,v >retrieving revision 1.4 >retrieving revision 1.5 >diff -u -p -r1.4 -r1.5 >--- devel/certwatch.xml 24 Oct 2007 14:03:17 -0000 1.4 >+++ devel/certwatch.xml 1 May 2008 01:16:30 -0000 1.5 >@@ -49,6 +49,9 @@ > the certificate, the certificate is ignored and no output is > produced. In quiet mode, no output is given, but the exit status > can still be used.</para> >+ >+ <para>The certificate can be specified by its nickname or by a >+ path to the containing file.</para> > > </refsect1> > >@@ -86,6 +89,14 @@ > default is <literal>root</literal>.</simpara></listitem> > </varlistentry> > >+ <varlistentry> >+ <term><option>--directory <replaceable>cert-directory</replaceable></option>, >+ <option>-d <replaceable>cert-directory</replaceable></option></term> >+ >+ <listitem><simpara>Specify the database directory containing the certificate >+ and key database files. The default is yet to be determined.</simpara></listitem> >+ </varlistentry> >+ > </variablelist> > </refsect1> > >Index: devel/copying >=================================================================== >RCS file: devel/copying >diff -N devel/copying >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ devel/copying 1 May 2008 01:04:05 -0000 1.1 >@@ -0,0 +1,341 @@ >+ >+ GNU GENERAL PUBLIC LICENSE >+ Version 2, June 1991 >+ >+ Copyright (C) 1989, 1991 Free Software Foundation, Inc. >+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ Everyone is permitted to copy and distribute verbatim copies >+ of this license document, but changing it is not allowed. >+ >+ Preamble >+ >+ The licenses for most software are designed to take away your >+freedom to share and change it. By contrast, the GNU General Public >+License is intended to guarantee your freedom to share and change free >+software--to make sure the software is free for all its users. This >+General Public License applies to most of the Free Software >+Foundation's software and to any other program whose authors commit to >+using it. (Some other Free Software Foundation software is covered by >+the GNU Library General Public License instead.) You can apply it to >+your programs, too. >+ >+ When we speak of free software, we are referring to freedom, not >+price. Our General Public Licenses are designed to make sure that you >+have the freedom to distribute copies of free software (and charge for >+this service if you wish), that you receive source code or can get it >+if you want it, that you can change the software or use pieces of it >+in new free programs; and that you know you can do these things. >+ >+ To protect your rights, we need to make restrictions that forbid >+anyone to deny you these rights or to ask you to surrender the rights. >+These restrictions translate to certain responsibilities for you if you >+distribute copies of the software, or if you modify it. >+ >+ For example, if you distribute copies of such a program, whether >+gratis or for a fee, you must give the recipients all the rights that >+you have. You must make sure that they, too, receive or can get the >+source code. And you must show them these terms so they know their >+rights. >+ >+ We protect your rights with two steps: (1) copyright the software, and >+(2) offer you this license which gives you legal permission to copy, >+distribute and/or modify the software. >+ >+ Also, for each author's protection and ours, we want to make certain >+that everyone understands that there is no warranty for this free >+software. If the software is modified by someone else and passed on, we >+want its recipients to know that what they have is not the original, so >+that any problems introduced by others will not reflect on the original >+authors' reputations. >+ >+ Finally, any free program is threatened constantly by software >+patents. We wish to avoid the danger that redistributors of a free >+program will individually obtain patent licenses, in effect making the >+program proprietary. To prevent this, we have made it clear that any >+patent must be licensed for everyone's free use or not licensed at all. >+ >+ The precise terms and conditions for copying, distribution and >+modification follow. >+ >+ GNU GENERAL PUBLIC LICENSE >+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION >+ >+ 0. This License applies to any program or other work which contains >+a notice placed by the copyright holder saying it may be distributed >+under the terms of this General Public License. The "Program", below, >+refers to any such program or work, and a "work based on the Program" >+means either the Program or any derivative work under copyright law: >+that is to say, a work containing the Program or a portion of it, >+either verbatim or with modifications and/or translated into another >+language. (Hereinafter, translation is included without limitation in >+the term "modification".) Each licensee is addressed as "you". >+ >+Activities other than copying, distribution and modification are not >+covered by this License; they are outside its scope. The act of >+running the Program is not restricted, and the output from the Program >+is covered only if its contents constitute a work based on the >+Program (independent of having been made by running the Program). >+Whether that is true depends on what the Program does. >+ >+ 1. You may copy and distribute verbatim copies of the Program's >+source code as you receive it, in any medium, provided that you >+conspicuously and appropriately publish on each copy an appropriate >+copyright notice and disclaimer of warranty; keep intact all the >+notices that refer to this License and to the absence of any warranty; >+and give any other recipients of the Program a copy of this License >+along with the Program. >+ >+You may charge a fee for the physical act of transferring a copy, and >+you may at your option offer warranty protection in exchange for a fee. >+ >+ 2. You may modify your copy or copies of the Program or any portion >+of it, thus forming a work based on the Program, and copy and >+distribute such modifications or work under the terms of Section 1 >+above, provided that you also meet all of these conditions: >+ >+ a) You must cause the modified files to carry prominent notices >+ stating that you changed the files and the date of any change. >+ >+ b) You must cause any work that you distribute or publish, that in >+ whole or in part contains or is derived from the Program or any >+ part thereof, to be licensed as a whole at no charge to all third >+ parties under the terms of this License. >+ >+ c) If the modified program normally reads commands interactively >+ when run, you must cause it, when started running for such >+ interactive use in the most ordinary way, to print or display an >+ announcement including an appropriate copyright notice and a >+ notice that there is no warranty (or else, saying that you provide >+ a warranty) and that users may redistribute the program under >+ these conditions, and telling the user how to view a copy of this >+ License. (Exception: if the Program itself is interactive but >+ does not normally print such an announcement, your work based on >+ the Program is not required to print an announcement.) >+ >+These requirements apply to the modified work as a whole. If >+identifiable sections of that work are not derived from the Program, >+and can be reasonably considered independent and separate works in >+themselves, then this License, and its terms, do not apply to those >+sections when you distribute them as separate works. But when you >+distribute the same sections as part of a whole which is a work based >+on the Program, the distribution of the whole must be on the terms of >+this License, whose permissions for other licensees extend to the >+entire whole, and thus to each and every part regardless of who wrote it. >+ >+Thus, it is not the intent of this section to claim rights or contest >+your rights to work written entirely by you; rather, the intent is to >+exercise the right to control the distribution of derivative or >+collective works based on the Program. >+ >+In addition, mere aggregation of another work not based on the Program >+with the Program (or with a work based on the Program) on a volume of >+a storage or distribution medium does not bring the other work under >+the scope of this License. >+ >+ 3. You may copy and distribute the Program (or a work based on it, >+under Section 2) in object code or executable form under the terms of >+Sections 1 and 2 above provided that you also do one of the following: >+ >+ a) Accompany it with the complete corresponding machine-readable >+ source code, which must be distributed under the terms of Sections >+ 1 and 2 above on a medium customarily used for software interchange; or, >+ >+ b) Accompany it with a written offer, valid for at least three >+ years, to give any third party, for a charge no more than your >+ cost of physically performing source distribution, a complete >+ machine-readable copy of the corresponding source code, to be >+ distributed under the terms of Sections 1 and 2 above on a medium >+ customarily used for software interchange; or, >+ >+ c) Accompany it with the information you received as to the offer >+ to distribute corresponding source code. (This alternative is >+ allowed only for noncommercial distribution and only if you >+ received the program in object code or executable form with such >+ an offer, in accord with Subsection b above.) >+ >+The source code for a work means the preferred form of the work for >+making modifications to it. For an executable work, complete source >+code means all the source code for all modules it contains, plus any >+associated interface definition files, plus the scripts used to >+control compilation and installation of the executable. However, as a >+special exception, the source code distributed need not include >+anything that is normally distributed (in either source or binary >+form) with the major components (compiler, kernel, and so on) of the >+operating system on which the executable runs, unless that component >+itself accompanies the executable. >+ >+If distribution of executable or object code is made by offering >+access to copy from a designated place, then offering equivalent >+access to copy the source code from the same place counts as >+distribution of the source code, even though third parties are not >+compelled to copy the source along with the object code. >+ >+ 4. You may not copy, modify, sublicense, or distribute the Program >+except as expressly provided under this License. Any attempt >+otherwise to copy, modify, sublicense or distribute the Program is >+void, and will automatically terminate your rights under this License. >+However, parties who have received copies, or rights, from you under >+this License will not have their licenses terminated so long as such >+parties remain in full compliance. >+ >+ 5. You are not required to accept this License, since you have not >+signed it. However, nothing else grants you permission to modify or >+distribute the Program or its derivative works. These actions are >+prohibited by law if you do not accept this License. Therefore, by >+modifying or distributing the Program (or any work based on the >+Program), you indicate your acceptance of this License to do so, and >+all its terms and conditions for copying, distributing or modifying >+the Program or works based on it. >+ >+ 6. Each time you redistribute the Program (or any work based on the >+Program), the recipient automatically receives a license from the >+original licensor to copy, distribute or modify the Program subject to >+these terms and conditions. You may not impose any further >+restrictions on the recipients' exercise of the rights granted herein. >+You are not responsible for enforcing compliance by third parties to >+this License. >+ >+ 7. If, as a consequence of a court judgment or allegation of patent >+infringement or for any other reason (not limited to patent issues), >+conditions are imposed on you (whether by court order, agreement or >+otherwise) that contradict the conditions of this License, they do not >+excuse you from the conditions of this License. If you cannot >+distribute so as to satisfy simultaneously your obligations under this >+License and any other pertinent obligations, then as a consequence you >+may not distribute the Program at all. For example, if a patent >+license would not permit royalty-free redistribution of the Program by >+all those who receive copies directly or indirectly through you, then >+the only way you could satisfy both it and this License would be to >+refrain entirely from distribution of the Program. >+ >+If any portion of this section is held invalid or unenforceable under >+any particular circumstance, the balance of the section is intended to >+apply and the section as a whole is intended to apply in other >+circumstances. >+ >+It is not the purpose of this section to induce you to infringe any >+patents or other property right claims or to contest validity of any >+such claims; this section has the sole purpose of protecting the >+integrity of the free software distribution system, which is >+implemented by public license practices. Many people have made >+generous contributions to the wide range of software distributed >+through that system in reliance on consistent application of that >+system; it is up to the author/donor to decide if he or she is willing >+to distribute software through any other system and a licensee cannot >+impose that choice. >+ >+This section is intended to make thoroughly clear what is believed to >+be a consequence of the rest of this License. >+ >+ 8. If the distribution and/or use of the Program is restricted in >+certain countries either by patents or by copyrighted interfaces, the >+original copyright holder who places the Program under this License >+may add an explicit geographical distribution limitation excluding >+those countries, so that distribution is permitted only in or among >+countries not thus excluded. In such case, this License incorporates >+the limitation as if written in the body of this License. >+ >+ 9. The Free Software Foundation may publish revised and/or new versions >+of the General Public License from time to time. Such new versions will >+be similar in spirit to the present version, but may differ in detail to >+address new problems or concerns. >+ >+Each version is given a distinguishing version number. If the Program >+specifies a version number of this License which applies to it and "any >+later version", you have the option of following the terms and conditions >+either of that version or of any later version published by the Free >+Software Foundation. If the Program does not specify a version number of >+this License, you may choose any version ever published by the Free Software >+Foundation. >+ >+ 10. If you wish to incorporate parts of the Program into other free >+programs whose distribution conditions are different, write to the author >+to ask for permission. For software which is copyrighted by the Free >+Software Foundation, write to the Free Software Foundation; we sometimes >+make exceptions for this. Our decision will be guided by the two goals >+of preserving the free status of all derivatives of our free software and >+of promoting the sharing and reuse of software generally. >+ >+ NO WARRANTY >+ >+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY >+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN >+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES >+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED >+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF >+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS >+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE >+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, >+REPAIR OR CORRECTION. >+ >+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING >+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR >+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, >+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING >+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED >+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY >+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER >+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE >+POSSIBILITY OF SUCH DAMAGES. >+ >+ END OF TERMS AND CONDITIONS >+ >+ How to Apply These Terms to Your New Programs >+ >+ If you develop a new program, and you want it to be of the greatest >+possible use to the public, the best way to achieve this is to make it >+free software which everyone can redistribute and change under these terms. >+ >+ To do so, attach the following notices to the program. It is safest >+to attach them to the start of each source file to most effectively >+convey the exclusion of warranty; and each file should have at least >+the "copyright" line and a pointer to where the full notice is found. >+ >+ <one line to give the program's name and a brief idea of what it does.> >+ Copyright (C) 19yy <name of author> >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA >+ >+ >+Also add information on how to contact you by electronic and paper mail. >+ >+If the program is interactive, make it output a short notice like this >+when it starts in an interactive mode: >+ >+ Gnomovision version 69, Copyright (C) 19yy name of author >+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. >+ This is free software, and you are welcome to redistribute it >+ under certain conditions; type `show c' for details. >+ >+The hypothetical commands `show w' and `show c' should show the appropriate >+parts of the General Public License. Of course, the commands you use may >+be called something other than `show w' and `show c'; they could even be >+mouse-clicks or menu items--whatever suits your program. >+ >+You should also get your employer (if you work as a programmer) or your >+school, if any, to sign a "copyright disclaimer" for the program, if >+necessary. Here is a sample; alter the names: >+ >+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program >+ `Gnomovision' (which makes passes at compilers) written by James Hacker. >+ >+ <signature of Ty Coon>, 1 April 1989 >+ Ty Coon, President of Vice >+ >+This General Public License does not permit incorporating your program into >+proprietary programs. If your program is a subroutine library, you may >+consider it more useful to permit linking proprietary applications with the >+library. If this is what you want to do, use the GNU Library General >+Public License instead of this License. >Index: devel/crypto-utils.spec >=================================================================== >RCS file: /cvs/extras/rpms/crypto-utils/devel/crypto-utils.spec,v >retrieving revision 1.38 >diff -u -p -r1.38 crypto-utils.spec >--- devel/crypto-utils.spec 3 Mar 2008 19:03:09 -0000 1.38 >+++ devel/crypto-utils.spec 11 May 2008 01:31:12 -0000 >@@ -3,8 +3,8 @@ > > Summary: SSL certificate and key management utilities > Name: crypto-utils >-Version: 2.3 >-Release: 10 >+Version: 2.4 >+Release: 1 > Source: crypto-rand-%{crver}.tar.gz > Source1: genkey.pl > Source2: certwatch.c >@@ -14,12 +14,22 @@ Source5: genkey.xml > Source6: keyrand.c > Source7: COPYING > Source8: keyrand.xml >+Source9: pemutil.c >+Source10: keyutil.c >+Source11: certext.c >+Source12: secutil.c >+Source13: secerror.c >+Source14: keyutil.h >+Source15: secutil.h >+Source16: NSPRerrs.h >+Source17: SECerrs.h >+Source18: copying > Group: Applications/System > License: MIT and GPLv2+ > BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root >-BuildRequires: openssl-devel, pkgconfig, newt-devel, xmlto >+BuildRequires: nss-devel, pkgconfig, newt-devel, xmlto > BuildRequires: perl-devel, perl(Newt), perl(ExtUtils::MakeMaker) >-Requires: perl(Newt), openssl >= 0.9.7f-4 >+Requires: perl(Newt), nss >= 3.11.99 > Requires: %(eval `perl -V:version`; echo "perl(:MODULE_COMPAT_$version)") > Obsoletes: crypto-rand > >@@ -34,8 +44,16 @@ SSL certificates and keys. > %configure --with-newt=%{_prefix} CFLAGS="$CFLAGS -fPIC" > make -C librand > >-cc $RPM_OPT_FLAGS -Wall -Werror -I/usr/include/openssl \ >- $RPM_SOURCE_DIR/certwatch.c -o certwatch -lcrypto >+cc $RPM_OPT_FLAGS -Wall -Werror -I/usr/include/nspr4 -I/usr/include/nss3 \ >+ $RPM_SOURCE_DIR/certwatch.c $RPM_SOURCE_DIR/pemutil.c \ >+ -o certwatch -lnspr4 -lnss3 >+ >+cc $RPM_OPT_FLAGS -Wall -Werror -I/usr/include/nspr4 -I/usr/include/nss3 \ >+ $RPM_SOURCE_DIR/keyutil.c \ >+ $RPM_SOURCE_DIR/certext.c \ >+ $RPM_SOURCE_DIR/secutil.c \ >+ $RPM_SOURCE_DIR/secerror.c \ >+ -o keyutil -lnspr4 -lnss3 > > cc $RPM_OPT_FLAGS -Wall -Werror \ > $RPM_SOURCE_DIR/keyrand.c -o keyrand -lnewt >@@ -85,6 +103,9 @@ for f in certwatch genkey keyrand; do > install -c -m 644 ${f}.1 $RPM_BUILD_ROOT%{_mandir}/man1/${f}.1 > done > >+# install keyutil >+install -c -m 755 keyutil $RPM_BUILD_ROOT%{_bindir}/keyutil >+ > # install genkey > sed -e "s|^\$bindir.*$|\$bindir = \"%{_bindir}\";|" \ > -e "s|^\$ssltop.*$|\$ssltop = \"/etc/pki/tls\";|" \ >Index: devel/genkey.pl >=================================================================== >RCS file: /cvs/extras/rpms/crypto-utils/devel/genkey.pl,v >retrieving revision 1.8 >diff -u -p -r1.8 genkey.pl >--- devel/genkey.pl 30 Oct 2007 16:15:10 -0000 1.8 >+++ devel/genkey.pl 11 May 2008 01:31:13 -0000 >@@ -32,11 +32,12 @@ > # 200308 Adapted for Taroon > # 200308 Fix warnings in UTF-8 locale > # 200409 Added --days support >+# 200804 Use NSS library for cryptography [Bug 346731] > # > # > $bindir = "%INSTDIR%/bin"; > $ssltop = "%INSTDIR%/conf/ssl"; >-$sslconf = "%INSTDIR%/conf/ssl/openssl.conf"; >+$nssconf = "/etc/httpd/conf.d/nss.conf"; > $cadir = "$ssltop/CA"; > > use Crypt::Makerand; >@@ -68,10 +69,11 @@ sub usage > { > print STDERR <<EOH; > Usage: genkey [options] servername >- --test Test mode, skip random data creation, overwrite existing key >+ --test Test mode, faster seeding, overwrite existing key > --genreq Just generate a CSR from an existing key > --makeca Generate a private CA key instead > --days Days until expiry of self-signed certificate (default 30) >+ --nss Use the nss database for keys and certificates > EOH > exit 1; > } >@@ -118,15 +120,21 @@ my $test_mode = ''; > my $genreq_mode = ''; > my $ca_mode = ''; > my $cert_days = 30; >+my $nss =''; >+my $modNssDbDir = ''; >+my $nssNickname = ''; >+my $nssDBPrefix = ''; > GetOptions('test|t' => \$test_mode, > 'genreq' => \$genreq_mode, >- 'days=i' => \$cert_days, >+ 'days=i' => \$cert_days, >+ 'nss|n' => \$nss, > 'makeca' => \$ca_mode) or usage(); > usage() unless @ARGV != 0; > $skip_random = $test_mode; >-$overwrite_key = $test_mode; >+$overwrite_key = $test_mode && !$nss; > $servername = $ARGV[0]; > $randfile = $ssltop."/.rand.".$$; >+$tmpPasswordFile = ''; # none has been created yet > $keyfile = $ssltop."/private/".$servername.".key"; > if ($ca_mode) { > $keyfile = $cadir."/private/".$servername; >@@ -136,7 +144,7 @@ if ($ca_mode) { > my $bits = 0; > my $myca = "Other"; > my $useca = 0; >-my $cadetails; >+my $subject; > # > > Newt::Init(); >@@ -160,11 +168,23 @@ if (!$genreq_mode && -f $keyfile && !$ov > exit 1; > } > >-if ($genreq_mode && !(-f $keyfile)) { >- Newt::newtWinMessage("Error", "Close", >- "You do not have a key file for this host"); >- Newt::Finished(); >- exit 1; >+# Either mod_nss or mod_ssl is required >+requireModule(); >+ >+# For mod_nss we need these variables set >+if ($nss) { >+ # the configuration file is required >+ if (!nssconfigFound()) { >+ Newt::newtWinMessage("Error", "Close", >+ "Could not find mod_nss's nss.conf file". >+ "for this host:\n\nPress return to exit"); >+ Newt::Finished(); >+ exit 1; >+ } >+ >+ $modNssDbDir = getModNSSDatabase(); >+ $nssNickname = getNSSNickname(); >+ $nssDBPrefix = getNSSDBPrefix(); > } > > ###################################################################### >@@ -183,32 +203,36 @@ if ($genreq_mode && !(-f $keyfile)) { > my @windows; > if ($genreq_mode) { > $useca = 1; >- @windows = (genReqWindow, >+ @windows = ( >+ getkeysizeWindow, >+ customKeySizeWindow, >+ getRandomDataWindow, >+ passwordWindow, >+ genReqWindow, > ); > $doingwhat="CSR generation"; > } elsif ($ca_mode) { > @windows = (CAwelcomeWindow, > getkeysizeWindow, > customKeySizeWindow, >- getRandomDataWindow, ## leaves newt suspended >- generateKey, >+ getRandomDataWindow, >+ passwordWindow, > genCACertWindow, >- encryptKeyWindow, > ); >- $doingwhat="CA key generation"; >+ $doingwhat="CA cert generation"; > } else { > @windows = (welcomeWindow, > getkeysizeWindow, > customKeySizeWindow, >- getRandomDataWindow, ## leaves newt suspended >- generateKey, >+ getRandomDataWindow, > wantCAWindow, >+ passwordWindow, > genReqWindow, >- genCertWindow, >- encryptKeyWindow, >- ### @EXTRA@ ### Leave this comment here. >- ); >- $doingwhat="key generation"; >+ genReqWindow, >+ genCertWindow, >+ ### @EXTRA@ ### Leave this comment here. >+ ); >+ $doingwhat="testing CSR and cert generation"; > } > > my $screen = 0; >@@ -247,10 +271,15 @@ while ($screen <= $#windows) { > } > > # Exit >+clearSensitiveData(); > Newt::Finished(); > exit 1 if ($result eq "Cancel"); > exit 0; > >+# >+# end main >+# >+ > ###################################################################### > # Handy functions > >@@ -279,6 +308,91 @@ sub NextBackCancelButton { > ->Add(2, 0, $cancelb, Newt::NEWT_ANCHOR_LEFT(), 1, 1, 0, 0); > } > >+# Require that this Apache module (mod_nss or mod_ssl) be installed >+sub requireModule { >+ >+ my $module = $nss ? "mod_nss" : "mod_ssl"; >+ my $not_installed_msg = `rpm -q $module | grep "not installed"`; >+ >+ if ($not_installed_msg) { >+ Newt::newtWinMessage("Error", "Close", >+ "$not_installed_msg". >+ "\nIt is required to generate this type of CSRs or certs". >+ "for this host:\n\nPress return to exit"); >+ Newt::Finished(); >+ exit 1; >+ } >+} >+ >+# Check that nss.conf exists >+sub nssconfigFound { >+ # if it isn't in its usual place >+ if (!$nssconf || !(-f $nssconf)) { >+ # do an rpm query >+ my $cmd = 'rpm -ql mod_nss'; >+ my $tmplist = "list"; >+ system("$cmd > $tmplist"); >+ $nssconf = `grep nss.conf $tmplist`; >+ unlink($tmplist); >+ } >+ return ($nssconf && (-f $nssconf)); >+} >+ >+# Returns the mod_nss database directory path. >+sub getModNSSDatabase { >+ >+ # Extract the value from the mod_nss configuration file. >+ my $cmd ='/usr/bin/gawk \'/^NSSCertificateDatabase/ { print $2 }\'' . " $nssconf"; >+ my $dbfile = "dbdirectory"; >+ system("$cmd > $dbfile"); >+ open(DIR, "<$dbfile"); >+ my $dbdir = ''; >+ chomp($dbdir = <DIR>); >+ >+ unlink($dbfile); >+ >+ return $dbdir; >+} >+ >+# Returns the rsa server name. >+sub getNSSNickname { >+ >+ # Extract the value from the mod_nss configuration file. >+ my $cmd ='/usr/bin/gawk \'/^NSSNickname/ { print $2 }\'' . " $nssconf"; >+ my $nicknamefile = "nssnickname"; >+ system("$cmd > $nicknamefile"); >+ open(NICK, "<$nicknamefile"); >+ my $nickname = ''; >+ chomp($nickname = <NICK>); >+ unlink($nicknamefile); >+ return $nickname; >+} >+ >+# Returns the nss database prefix >+sub getNSSDBPrefix { >+ >+ # Extract the value from the mod_nss configuration file. >+ my $cmd ='/usr/bin/gawk \'/^NSSDBPrefix/ { print $2 }\'' . " $nssconf"; >+ my $prefixfile = "dbprefix"; >+ system("$cmd > $prefixfile"); >+ open(PREFIX, "<$prefixfile"); >+ my $prefix = ''; >+ chomp($prefix = <PREFIX>); >+ unlink($prefixfile); >+ >+ return $prefix; >+} >+ >+# Erases and deletes the password file >+sub clearSensitiveData { >+ if (-f $tmpPasswordFile) { >+ open(DOOMED,$tmpPasswordFile); >+ truncate(DOOMED,0); >+ close(DOOMED); >+ unlink($tmpPasswordFile); >+ } >+} >+ > ###################################################################### > # The window functions > >@@ -436,6 +550,11 @@ EOT > sub welcomeWindow() > { > my $name = $servername; >+ my $where_key = $nss >+ ? $modNssDbDir."/$nssDBPrefix"."key3.db" : "$ssltop/private/$name.key"; >+ my $where_cert = $nss >+ ? $modNssDbDir."/$nssDBPrefix"."cert8.db" : "$ssltop/certs/$name.cert"; >+ my $what = $nss ? "directory" : "file"; > my $message = <<EOT; > You are now generating a new keypair which will be used to encrypt all > SSL traffic to the server named $name. >@@ -443,12 +562,12 @@ Optionally you can also create a certifi > certificate authority (CA) for signing. > > The key will be stored in >- $ssltop/private/$name.key >+ $where_key > The certificate stored in >- $ssltop/certs/$name.cert >+ $where_cert > >-If the key generation fails, move the file >- $ssltop/private/$name.key >+If the key generation fails, move the $what >+ $where_key > to a backup location and try again. > EOT > >@@ -470,15 +589,16 @@ EOT > sub CAwelcomeWindow() > { > my $name = $servername; >+ my $where = $nss ? $modNssDbDir."/$nssDBPrefix"."key3.db" : "$cadir/private/$name"; > my $message = <<EOT; > You are now generating a new keypair which will be used for your > private CA > > The key will be stored in >- $cadir/private/$name >+ $where > > If the key generation fails, move the file >- $cadir/private/$name >+ $where > to a backup location and try again. > EOT > >@@ -522,18 +642,111 @@ sub wantCAWindow > return "Next"; > } > >-sub encryptKeyWindow >+# Save the passphrase to a temporary file. >+sub savePassword > { >+ my ($passwd) = @_; >+ >+ $tmpPasswordFile = ".passwordfile.".$$; >+ >+ if (!open (SESAME, ">$tmpPasswordFile")) { >+ Newt::newtWinMessage("Error", "Close", >+ "Unable to save passphrase to $tmpPasswordFile". >+ "\n\nPress return to continue"); >+ $tmpPasswordFile = ''; # mark it as never created >+ return "Back"; >+ } >+ print SESAME $passwd; >+ close(SESAME); >+ # This file will be deleted on program exit. >+ >+ return "Next"; >+} >+ >+sub moduleAccesPasswordWindow >+{ >+ my $message = <<EOT; >+At this stage you can provide the module acess passphrase. >+EOT >+ $panel = Newt::Panel(1, 3, "Module access"); >+ $panel->Add(0, 0, Newt::Textbox(70, 5, 0, $message)); >+ >+ my $checkbox = Newt::Checkbox("Module access password if any"); >+ $panel->Add(0, 1, $checkbox); >+ $panel->Add(0, 2, NextBackCancelButton()); >+ >+ $ret = &RunForm($panel); >+ >+ my $plain = 1; >+ $plain = 0 if $checkbox->Checked(); >+ >+ $panel->Hide(); >+ undef $panel; >+ >+ return $ret if ($ret eq "Back" or $ret eq "Cancel" or $plain == 1); >+ >+ $panel = Newt::Panel(1, 3, "Enter the module passphrase"); >+ >+ $message = <<EOT; >+This is the passphrase to your module. >+EOT >+ $panel->Add(0, 0, Newt::Textbox(70, 5, 0, $message)); >+ $subp = Newt::Panel(2,2); >+ $entp1 = AddField($subp,0,"Passphrase","",30,0, >+ Newt::NEWT_FLAG_HIDDEN()); >+ >+ $panel->Add(0, 1, $subp, 0, 0, 1); >+ $panel->Add(0, 2, NextBackCancelButton()); >+ >+ while (1) { >+ # Clear the password entry box to avoid confusion on looping >+ $entp1->Set(""); >+ $panel->Focus($entp1); >+ >+ # Pass "Ignore" to make enter go to next widget. >+ $ret = &RunForm($panel, "Ignore"); >+ >+ if ($ret eq "Cancel" or $ret eq "Back") { >+ $panel->Hide(); >+ undef $subp; >+ undef $panel; >+ return $ret; >+ } >+ $pass1 = $entp1->Get(); >+ >+ last; >+ } >+ >+ $panel->Hide(); >+ undef $panel; >+ >+ return $ret if ($ret eq "Back" or $ret eq "Cancel"); >+ >+ # Save it to a temporary file to supply to the nss utilities, >+ # the file will be erased upon exit >+ savePassword($pass1); >+ >+ return "Next"; >+ >+} >+ >+# Prompts for key encryption password >+# When using NSS it prompts for the >+# module acces password instead. >+sub passwordWindow >+{ >+ return moduleAccesPasswordWindow() if $nss; >+ > my $message = <<EOT; > At this stage you can set the passphrase on your private key. If you > set the passphrase you will have to enter it every time the server > starts. The passphrase you use to encrypt your key must be the same > for all the keys used by the same server installation. > >-If you do not encrypt your passphrase, if someone breaks into your >+If you do not encrypt your key, then if someone breaks into your > server and grabs the file containing your key, they will be able to > decrypt all communications to and from the server that were negotiated >-using that key. If your passphrase is encrypted it would be much more >+using that key. If your key is encrypted it would be much more > work for someone to retrieve the private key. > EOT > $panel = Newt::Panel(1, 3, "Protecting your private key"); >@@ -617,104 +830,206 @@ EOT > > return $ret if ($ret eq "Back" or $ret eq "Cancel"); > >- my $enckey = $keyfile . ".tmp"; >- >- unlink($enckey); >+ # Save it to a temporary file to supply to the nss utilities, >+ # the file will be erased upon exit >+ savePassword($pass1); > >- if (!open (PIPE, >- "|$bindir/openssl rsa -des3 -in $keyfile -passout stdin ". >- "-out $enckey")) { >- Newt::newtWinMessage("Error", "Close", >- "Unable to set passphrase". >- "\n\nPress return to continue"); >- return "Back"; >- } >- print PIPE $pass1."\n"; >- close(PIPE); >- >- if (-f $enckey) { >- if (chmod(0400, $enckey) != 1 >- || !rename($enckey, $keyfile)) { >- Newt::newtWinMessage("Error", "Close", >- "Could not install private key file.\n". >- "$! - $enckey"); >- unlink($enckey); >- return "Back"; >- } >- } else { >- Newt:newtWinMessage("Error", "Close", >- "Unable to set passphrase\n\n". >- "Press return to continue"); >- return "Back"; >- } > return "Next"; > } > >-sub genReqblah() >-{ >- my ($name) = @_; >- my $message = <<EOT; >-Now we will create a self-signed certificate for use until the CA of your >-choice signs your certificate. You will have to use this cert until >-your CA responds with the actual signed certificate. >-EOT >- >- my $panel = Newt::Panel(1, 2, "Keypair generation"); >- my $text = Newt::Textbox(70, 10, 0, $message); >- my $ret; >- >- $text->TakesFocus(1); >- >- $panel->Add(0, 0, $text); >- $panel->Add(0, 1, NextBackCancelButton()); >- >- $ret = &RunForm($panel); >- >- $panel->Hide(); >- undef $panel; >+# >+# Bottleneck routine to call the nss utilities. >+# Calls are bracketed by newt suspend and resume >+# enabling user interaction from the nss utilities >+# and trace messages to the console. >+# >+sub nssUtilCmd { >+ >+ my ($cmd, $args) = @_; > >- return $ret; >+ Newt::Suspend(); >+ print STDOUT "$cmd $args"."\n"; >+ system("$cmd $args"); >+ # change to system("gdb $cmd"); >+ # to break into the debugger >+ print STDERR "$cmd returned $!"."\n" if $!; >+ Newt::Resume(); > } > > # >-# makeCert >-# >-# Given a keyfile, expiry date, and set of certificate information >-# create a X509 certificate to make a key and store it >+# make a certificate using the database > # >- >-sub makeCert >+sub makeCertNSS > { >- my ($keyfile,$certfile,$cert,$days) = @_; >- use Fcntl; >+ my ($certfile, # output >+ $subject, $days, $nickname, >+ $noisefile, $pwdfile) = @_; >+ >+ # If no days specified it's a ca so use 2 years >+ use integer; >+ my $months = $days / 30; >+ my $trustargs = "\"" . "TCu,TCu,TCuw". "\""; >+ >+ my $args = "-S "; >+ $args .= "-n $nickname "; >+ $args .= "-s $subject "; >+ $args .= "-x "; ## self-signed >+ $args .= "-t $trustargs "; >+ $args .= "-k rsa "; >+ $args .= "-g $bits "; >+ $args .= "-v $months "; >+ $args .= "-a "; >+ $args .= "-f $pwdfile " if $pwdfile; >+ $args .= "-z $noisefile " if $noisefile; >+ $args .= "-d $modNssDbDir "; >+ $args .= "-p $nssDBPrefix " if $nssDBPrefix; >+ $args .= "-o $certfile "; >+ >+ nssUtilCmd("$bindir/certutil", $args); > >- $tempfile = "/tmp/rand.".$$; >- if (!sysopen(OUT, $tempfile, O_WRONLY|O_EXCL|O_CREAT)) { >- Newt::newtWinMessage("Fatal Error", "Close", "Could not write to ". >- "temporary file $tempfile"); >- Newt::Finished(); >+ unlink($noisefile); >+ >+ if (!-f $certfile) { >+ Newt::newtWinMessage("Error", "Close", >+ "Was not able to create a certificate for this ". >+ "host:\n\nPress return to exit"); >+ Newt::Finished(); > exit 1; > } >+} >+ >+# Create a certificate-signing request file that can be submitted to >+# a Certificate Authority for processing into a finished certificate. >+sub genRequestNSS >+{ >+ my ($csrfile, # output >+ $subject, $days, $noisefile, $pwdfile) = @_; >+ >+ use integer; >+ my $months = $days / 30; >+ >+ my $args = "-R "; >+ >+ $args .= "-s $subject "; >+ $args .= "-d $modNssDbDir "; >+ $args .= "-p $nssDBPrefix " if $nssDDPrefix; >+ $args .= "-a "; ## using ascii >+ $args .= "-k rsa "; >+ $args .= "-g $bits "; >+ $args .= "-f $pwdfile " if $pwdfile; >+ $args .= "-v $months "; >+ $args .= "-z $noisefile " if $noisefile; >+ $args .= "-o $csrfile "; >+ >+ nssUtilCmd("$bindir/certutil", $args); > >- foreach my $field ('C', 'ST', 'L', 'O', 'OU', 'CN', >- 'Challenge', 'CompanyName') { >- my $value = $cert{$field} || '.'; >- print OUT "$value\n"; >+ unlink($noisefile); >+ >+ if (!-f $csrfile) { >+ Newt::newtWinMessage("Error", "Close", >+ "Was not able to create a CSR for this ". >+ "host:\n\nPress return to exit"); >+ Newt::Finished(); >+ exit 1; > } >- close(OUT); >+} >+ >+# Generate a CA certificate file. >+# Use keyutil which supports exporting the key. >+sub makeCertOpenSSL >+{ >+ my ($keyfile, $certfile, # output >+ $subject, $days, $noisefile, $pwdfile) = @_; > >- system("$bindir/openssl req -config $sslconf -new -key $keyfile $days -out $certfile < $tempfile 2> /dev/null"); >- unlink($tempfile); >+ use integer; >+ my $months = $days ? $days / 30 : 24; >+ >+ # build the arguments for a gen cert call, self-signed >+ my $args = "-c makecert "; >+ $args .= "-g $bits "; >+ $args .= "-s $subject "; >+ $args .= "-v $months "; >+ $args .= "-a "; ## using ascii >+ $args .= "-z $noisefile " if $noisefile; >+ $args .= "-e $pwdfile " if $pwdfile; >+ # there is no password when the >+ # user wants the key in the clar >+ $args .= "-o $certfile "; >+ $args .= "-k $keyfile"; >+ >+ nssUtilCmd("$bindir/keyutil", $args); > > if (!-f $certfile) { > Newt::newtWinMessage("Error", "Close", >- "Was not able to create a certificate for this ". >- "host:\n\nPress return to exit"); >- Newt::Finished(); >- exit 1; >+ "Was not able to create a certificate for this ". >+ "host:\n\nPress return to exit"); >+ unlink($noisefile); >+ Newt::Finished(); >+ exit 1; > } >+ if ($keyfile && (-f $keyfile)) { >+ if (chmod(0400, $keyfile) != 1) { >+ Newt::newtWinMessage("Error", "Close", >+ "Could not set permissions of private key file.\n". >+ "$keyfile"); >+ Newt::Finished(); >+ unlink($noisefile); >+ exit 1; >+ } >+ } >+ unlink($noisefile); > } > >+# Create a certificate-signing request file that can be submitted to a >+# Certificate Authority (CA) for processing into a finished certificate. >+# Use keyutil which exports key. >+sub genRequestOpenSSL >+{ >+ my ($keyfile,$csrfile, # output >+ $subject,$days,$noisefile,$pwdfile) = @_; >+ >+ use integer; >+ my $months = $days ? $days / 30 : 24; >+ >+ # build the arguments for a gen request call >+ my $args = "-c genreq "; >+ $args .= "-g $bits "; >+ $args .= "-s $subject "; >+ $args .= "-v $months "; >+ $args .= "-o $csrfile "; >+ $args .= "-k $keyfile "; >+ $args .= "-e $pwdfile " if $pwdfile; >+ # there is no password when the >+ # user wants the key in the clear >+ $args .= "-z $noisefile " if $noisefile; >+ >+ nssUtilCmd("$bindir/keyutil", $args); >+ >+ unlink($noisefile); >+ Newt::Resume(); >+ >+ if (!-f $csrfile) { >+ Newt::newtWinMessage("Error", "Close", >+ "Unable to create a cert signing request for this ". >+ "host:\n\nPress return to exit"); >+ Newt::Finished(); >+ exit 1; >+ } >+ if ($keyfile && !(-f $keyfile)) { >+ Newt::newtWinMessage("Error", "Close", >+ "Unable to create a key for this ". >+ "host:\n\nPress return to exit"); >+ Newt::Finished(); >+ exit 1; >+ } >+ if (chmod(0400, $keyfile) != 1) { >+ Newt::newtWinMessage("Error", "Close", >+ "Could not set permissions of private key file.\n". >+ "$keyfile"); >+ Newt::Finished(); >+ exit 1; >+ } >+} > > sub AddField > { >@@ -763,10 +1078,6 @@ sub getCertDetails > Newt::NEWT_ENTRY_SCROLL()); > > if ($iscsr) { >-# TODO: difficult to fit this message in and keep the form <25 rows >-# $subp->Add(0, 6, Newt::Label("Please enter the following 'extra' ". >-# "attributes\nto be sent with your ". >-# "certificate request.")); > > my $msg = "Extra attributes for certificate request:"; > >@@ -815,10 +1126,22 @@ sub getCertDetails > $cert{'O'} = $ents{'O'}->Get(); > $cert{'OU'} = $ents{'OU'}->Get(); > $cert{'CN'} = $ents{'CN'}->Get(); >+ >+ # Build the subject from the details >+ >+ $SEP = ", "; >+ $subject = 'CN' . "=" . $cert{'CN'}; >+ $subject = $subject . $SEP . 'OU' . "=" . $cert{'OU'} if $cert{'OU'}; >+ $subject = $subject . $SEP . 'O' . "=" . $cert{'O'} if $cert{'O'}; >+ $subject = $subject . $SEP . 'L' . "=" . $cert{'L'} if $cert{'L'}; >+ $subject = $subject . $SEP . 'ST' . "=" . $cert{'ST'} if $cert{'ST'}; >+ $subject = $subject . $SEP . 'C' . "=" . $cert{'C'} if $cert{'C'}; > > if ($iscsr) { >- $cert{'CompanyName'} = $ents{'CompanyName'}->Get(); >- $cert{'Challenge'} = $ents{'Challenge'}->Get(); >+ $cert{'CompanyName'} = $ents{'CompanyName'}->Get(); >+ $cert{'Challenge'} = $ents{'Challenge'}->Get(); >+ $subject = $subject . $SEP . 'CompanyName' ."=" . $cert{'CompanyName'} if $cert{'CompanyName'}; >+ $subject = $subject . $SEP . 'Challenge' ."=" . $cert{'Challenge'} if $cert{'Challenge'}; > } > > $panel->Hide(); >@@ -826,7 +1149,9 @@ sub getCertDetails > undef $subp; > undef $panel; > >- $cadetails = $cert; >+ # must escape the double quotes because >+ # it will be embedded in another string >+ $subject = "\"" . "$subject" . "\""; > > return "Next"; > } >@@ -888,14 +1213,27 @@ sub genReqWindow > my $ret = getCertDetails($servername,$msg, 1); > return $ret unless ($ret eq "Next"); > >- makeCert($keyfile,$csrfile,$cadetails,""); >+ if ($nss) { >+ genRequestNSS($csrfile, $subject, 730, $randfile, $tmpPasswordFile); >+ } else { >+ genRequestOpenSSL($keyfile, $csrfile, >+ $subject, 730, $randfile, $tmpPasswordFile); >+ } > > # Now make a temporary cert > > if (!$genreq_mode) { >- if (!-f $certfile) { >- makeCert($keyfile,$certfile,$cadetails,"-days $cert_days -x509"); >- } >+ if (!-f $certfile) { >+ if ($nss) { >+ makeCertNSS($certfile, >+ $subject, $cert_days, $nssNickname, >+ $randfile, $tmpPasswordFile); >+ } else { >+ makeCertOpenSSL($keyfile,$certfile, >+ $subject, $cert_days, >+ $randfile, $tmpPasswordFile); >+ } >+ } > } > > undef $csrtext; >@@ -998,7 +1336,15 @@ sub genCertWindow > my $ret = getCertDetails($servername,$msg, 0); > return $ret unless ($ret eq "Next"); > >- makeCert($keyfile,$certfile,$cadetails,"-days $cert_days -x509"); >+ if ($nss) { >+ makeCertNSS($certfile, # output >+ $subject,$cert_days,$nssNickname, >+ $randfile,$tmpPasswordFile); >+ } else { >+ makeCertOpenSSL($keyfile,$certfile, # output >+ $subject,$cert_days, >+ $randfile,$tmpPasswordFile); >+ } > > return "Next"; > } >@@ -1019,7 +1365,13 @@ sub genCACertWindow > my $ret = getCertDetails("",$msg, 0); > return $ret unless ($ret eq "Next"); > >- makeCert($keyfile,$certfile,$cadetails,"-days 730 -x509"); >+ if ($nss) { >+ makeCertNSS($certfile,$subject,730,$nssNickname, >+ $randfile,$tmpPasswordFile); >+ } else { >+ makeCertOpenSSL($keyfile,$certfile,$subject,730, >+ $randfile,$tmpPasswordFile); >+ } > > return "Next"; > } >@@ -1041,29 +1393,13 @@ sub getRandomDataWindow() > Newt::Suspend(); > > system("$bindir/keyrand $randbits $randfile"); >+ >+ Newt::Resume(); > } else { >- Newt::Suspend(); >+# No extra random seed is being provided to nss. Rely >+# on nss faster autoseeding process. The nss utilities >+# will prompt the user for some keystrokes. >+ $randfile = ''; > } > return "Next"; > } >- >-sub generateKey() >-{ >- print STDERR "\nPlease wait - generating the key (this may take some time)\n\n"; >- >- # Actually generate the key >- # >- system("$bindir/openssl genrsa -rand $randfile $bits > $keyfile"); >- unlink($randfile); >- Newt::Resume(); >- >- if (chmod(0400, $keyfile) != 1) { >- Newt::newtWinMessage("Error", "Close", >- "Could not set permissions of private key file.\n". >- "$1 - $keyfile"); >- Newt::Finished(); >- exit 1; >- } >- >- return "Skip"; >-} >Index: devel/genkey.xml >=================================================================== >RCS file: /cvs/extras/rpms/crypto-utils/devel/genkey.xml,v >retrieving revision 1.6 >diff -u -p -r1.6 genkey.xml >--- devel/genkey.xml 30 Oct 2007 16:15:10 -0000 1.6 >+++ devel/genkey.xml 11 May 2008 01:31:13 -0000 >@@ -34,6 +34,7 @@ > <group> > <arg><option>--genreq</option></arg> > <arg><option>--makeca</option></arg> >+ <arg><option>--nss</option></arg> > </group> > <arg choice="req"><replaceable>hostname</replaceable></arg> > </cmdsynopsis> >@@ -49,6 +50,11 @@ > corresponding private key in > <filename>/etc/pki/tls/private/</filename>. </para> > >+ <para>When using mod_nss the private key is stored in the >+ nss database. Consult the nss.conf file in >+ <filename>/etc/httpd/conf.d/</filename> >+ for the location of the database. </para> >+ > <para><command>genkey</command> will prompt for the size of key > desired; whether or not to generate a CSR; whether or not an > encrypted private key is desired; the certificate subject DN >@@ -58,6 +64,11 @@ > private key using the truerand library and also by prompting the > user for entry of random text.</para> > >+ <para><option>nss</option> indicates that mod_nss database >+ should be used to store keys and certificates. This option >+ requires mod_nss to be installed. Conversely, mod_ssl is >+ required if nss is not specified.</para> >+ > </refsect1> > > <refsect1> >Index: devel/keyutil.c >=================================================================== >RCS file: devel/keyutil.c >diff -N devel/keyutil.c >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ devel/keyutil.c 11 May 2008 01:31:13 -0000 >@@ -0,0 +1,1414 @@ >+/* >+ Copyright 2005 Red Hat, Inc. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. >+ >+ In addition, as a special exception, Red Hat, Inc. gives permission >+ to link the code of this program with the OpenSSL library (or with >+ modified versions of OpenSSL that use the same license as OpenSSL), >+ and distribute linked combinations including the two. You must obey >+ the GNU General Public License in all respects for all of the code >+ used other than OpenSSL. If you modify this file, you may extend >+ this exception to your version of the file, but you are not >+ obligated to do so. If you do not wish to do so, delete this >+ exception statement from your version. >+ >+*/ >+ >+/* ***** BEGIN LICENSE BLOCK ***** >+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 >+ * >+ * The contents of this file are subject to the Mozilla Public License Version >+ * 1.1 (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * http://www.mozilla.org/MPL/ >+ * >+ * Software distributed under the License is distributed on an "AS IS" basis, >+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License >+ * for the specific language governing rights and limitations under the >+ * License. >+ * >+ * The Original Code is the Netscape security libraries. >+ * >+ * The Initial Developer of the Original Code is >+ * Netscape Communications Corporation. >+ * Portions created by the Initial Developer are Copyright (C) 1994-2000 >+ * the Initial Developer. All Rights Reserved. >+ * >+ * Contributor(s): >+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories >+ * >+ * Alternatively, the contents of this file may be used under the terms of >+ * either the GNU General Public License Version 2 or later (the "GPL"), or >+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), >+ * in which case the provisions of the GPL or the LGPL are applicable instead >+ * of those above. If you wish to allow use of your version of this file only >+ * under the terms of either the GPL or the LGPL, and not to allow others to >+ * use your version of this file under the terms of the MPL, indicate your >+ * decision by deleting the provisions above and replace them with the notice >+ * and other provisions required by the GPL or the LGPL. If you do not delete >+ * the provisions above, a recipient may use your version of this file under >+ * the terms of any one of the MPL, the GPL or the LGPL. >+ * >+ * ***** END LICENSE BLOCK ***** */ >+ >+/* >+** keyutil.c >+** >+** utility for managing certificates and the cert database >+** >+*/ >+#include <stdio.h> >+#include <string.h> >+#include <stdlib.h> >+ >+#include <unistd.h> >+#include <sys/time.h> >+#include <termios.h> >+ >+#include <prerror.h> >+#include <secerr.h> >+ >+#include <nspr.h> >+#include <nss.h> >+#include <cert.h> >+#include <certt.h> >+#include <prio.h> >+#include <prlong.h> >+#include <prtime.h> >+#include <pkcs11.h> >+#include <pk11pub.h> >+#include <pkcs11t.h> >+#include <assert.h> >+#include <secmod.h> >+#include <base64.h> >+#include <seccomon.h> >+#include <secmodt.h> >+#include <secoidt.h> >+#include <keythi.h> >+#include <keyhi.h> >+#include <cryptohi.h> >+#include <plarenas.h> >+#include <secasn1.h> >+ >+#include <secpkcs5.h> >+#include <keythi.h> >+#include <secmodt.h> >+ >+#include <stdio.h> >+#include <string.h> >+#include <stdlib.h> >+#include <getopt.h> >+#include <time.h> >+ >+#include "keyutil.h" >+#include "secutil.h" >+ >+#define MIN_KEY_BITS 512 >+/* MAX_KEY_BITS should agree with MAX_RSA_MODULUS in freebl */ >+#define MAX_KEY_BITS 8192 >+#define DEFAULT_KEY_BITS 1024 >+ >+#define SEC_CT_PRIVATE_KEY "private-key" >+#define SEC_CT_PUBLIC_KEY "public-key" >+#define SEC_CT_CERTIFICATE "certificate" >+#define SEC_CT_CERTIFICATE_REQUEST "certificate-request" >+#define SEC_CT_PKCS7 "pkcs7" >+#define SEC_CT_CRL "crl" >+ >+#define NS_CERTREQ_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----" >+#define NS_CERTREQ_TRAILER "-----END NEW CERTIFICATE REQUEST-----" >+ >+#define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----" >+#define NS_CERT_TRAILER "-----END CERTIFICATE-----" >+ >+#define NS_CRL_HEADER "-----BEGIN CRL-----" >+#define NS_CRL_TRAILER "-----END CRL-----" >+ >+#define KEY_HEADER "-----BEGIN PRIVATE KEY-----" >+#define KEY_TRAILER "-----END PRIVATE KEY-----" >+ >+#define ENCRYPTED_KEY_HEADER "-----BEGIN ENCRYPTED PRIVATE KEY-----" >+#define ENCRYPTED_KEY_TRAILER "-----END ENCRYPTED PRIVATE KEY-----" >+ >+#define REP_MECHANISM mechanism[testId/2/2%46] >+ >+#define NUM_KEYSTROKES 120 >+#define RAND_BUF_SIZE 60 >+ >+#define ERROR_BREAK rv = SECFailure;break; >+ >+#define GEN_BREAK(e) rv=e; break; >+ >+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" >+ >+ >+char *progName; >+ >+static void >+Usage(char *progName) >+{ >+ fprintf(stderr, "Usage: %s [options] arguments\n", progName); >+ fprintf(stderr, "-h print this help message"); >+ fprintf(stderr, "-c command one of [genreq|makecert]"); >+ fprintf(stderr, "-s subject subject distinguished name"); >+ fprintf(stderr, "-g keysize in bits"); >+ fprintf(stderr, "-v validity in months"); >+ fprintf(stderr, "-z noise file"); >+ fprintf(stderr, "-f key encryption password file"); >+ fprintf(stderr, "-f module access password file"); >+ fprintf(stderr, "-d digest algorithm"); >+ fprintf(stderr, "-i input (key to encrypt)"); >+ fprintf(stderr, "-k key out, when csr or cert generation"); >+ fprintf(stderr, "-o output (a csr or cert)"); >+ fprintf(stderr, "-p passout, the pbe password"); >+ fprintf(stderr, "\n"); >+ exit(1); >+} >+ >+/* >+ * Modelled after the one in certutil >+ */ >+static CERTCertificateRequest * >+GetCertRequest(PRFileDesc *inFile, PRBool ascii) >+{ >+ CERTCertificateRequest *certReq = NULL; >+ CERTSignedData signedData; >+ PRArenaPool *arena = NULL; >+ SECItem reqDER; >+ SECStatus rv; >+ >+ reqDER.data = NULL; >+ do { >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if (arena == NULL) { >+ GEN_BREAK(SECFailure); >+ } >+ >+ rv = SECU_ReadDERFromFile(&reqDER, inFile, ascii); >+ if (rv) { >+ GEN_BREAK(rv); >+ } >+ certReq = (CERTCertificateRequest*) PORT_ArenaZAlloc >+ (arena, sizeof(CERTCertificateRequest)); >+ if (!certReq) { >+ GEN_BREAK(SECFailure); >+ } >+ certReq->arena = arena; >+ >+ /* Since cert request is a signed data, must decode to get the inner >+ data >+ */ >+ PORT_Memset(&signedData, 0, sizeof(signedData)); >+ rv = SEC_ASN1DecodeItem(arena, &signedData, >+ SEC_ASN1_GET(CERT_SignedDataTemplate), &reqDER); >+ if (rv) { >+ GEN_BREAK(rv); >+ } >+ rv = SEC_ASN1DecodeItem(arena, certReq, >+ SEC_ASN1_GET(CERT_CertificateRequestTemplate), &signedData.data); >+ if (rv) { >+ GEN_BREAK(rv); >+ } >+ rv = CERT_VerifySignedDataWithPublicKeyInfo(&signedData, >+ &certReq->subjectPublicKeyInfo, NULL /* wincx */); >+ } while (0); >+ >+ if (reqDER.data) { >+ SECITEM_FreeItem(&reqDER, PR_FALSE); >+ } >+ >+ if (rv) { >+ SECU_PrintError(progName, "bad certificate request\n"); >+ if (arena) { >+ PORT_FreeArena(arena, PR_FALSE); >+ } >+ certReq = NULL; >+ } >+ >+ return certReq; >+} >+ >+static SECStatus >+CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType, >+ SECOidTag hashAlgTag, CERTName *subject, char *phone, int ascii, >+ const char *emailAddrs, const char *dnsNames, >+ certutilExtnList extnList, >+ PRFileDesc *outFile) >+{ >+ CERTSubjectPublicKeyInfo *spki; >+ CERTCertificateRequest *cr; >+ SECItem *encoding; >+ SECOidTag signAlgTag; >+ SECItem result; >+ SECStatus rv; >+ PRArenaPool *arena; >+ PRInt32 numBytes; >+ void *extHandle; >+ >+ /* Create info about public key */ >+ spki = SECKEY_CreateSubjectPublicKeyInfo(pubk); >+ if (!spki) { >+ SECU_PrintError(progName, "unable to create subject public key"); >+ return SECFailure; >+ } >+ >+ /* Generate certificate request */ >+ cr = CERT_CreateCertificateRequest(subject, spki, NULL); >+ if (!cr) { >+ SECU_PrintError(progName, "unable to make certificate request"); >+ return SECFailure; >+ } >+ >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if ( !arena ) { >+ SECU_PrintError(progName, "out of memory"); >+ return SECFailure; >+ } >+ >+ extHandle = CERT_StartCertificateRequestAttributes(cr); >+ if (extHandle == NULL) { >+ PORT_FreeArena (arena, PR_FALSE); >+ return SECFailure; >+ } >+ if (AddExtensions(extHandle, emailAddrs, dnsNames, extnList) >+ != SECSuccess) { >+ PORT_FreeArena (arena, PR_FALSE); >+ return SECFailure; >+ } >+ CERT_FinishExtensions(extHandle); >+ CERT_FinishCertificateRequestAttributes(cr); >+ >+ /* Der encode the request */ >+ encoding = SEC_ASN1EncodeItem(arena, NULL, cr, >+ SEC_ASN1_GET(CERT_CertificateRequestTemplate)); >+ if (encoding == NULL) { >+ SECU_PrintError(progName, "der encoding of request failed"); >+ return SECFailure; >+ } >+ >+ /* Sign the request */ >+ signAlgTag = SEC_GetSignatureAlgorithmOidTag(keyType, hashAlgTag); >+ if (signAlgTag == SEC_OID_UNKNOWN) { >+ SECU_PrintError(progName, "unknown Key or Hash type"); >+ return SECFailure; >+ } >+ rv = SEC_DerSignData(arena, &result, encoding->data, encoding->len, >+ privk, signAlgTag); >+ if (rv) { >+ SECU_PrintError(progName, "signing of data failed"); >+ return SECFailure; >+ } >+ >+ /* Encode request in specified format */ >+ if (ascii) { >+ char *obuf; >+ char *name, *email, *org, *state, *country; >+ SECItem *it; >+ int total; >+ >+ it = &result; >+ >+ obuf = BTOA_ConvertItemToAscii(it); >+ total = PL_strlen(obuf); >+ >+ name = CERT_GetCommonName(subject); >+ if (!name) { >+ name = strdup("(not specified)"); >+ } >+ >+ if (!phone) >+ phone = strdup("(not specified)"); >+ >+ email = CERT_GetCertEmailAddress(subject); >+ if (!email) >+ email = strdup("(not specified)"); >+ >+ org = CERT_GetOrgName(subject); >+ if (!org) >+ org = strdup("(not specified)"); >+ >+ state = CERT_GetStateName(subject); >+ if (!state) >+ state = strdup("(not specified)"); >+ >+ country = CERT_GetCountryName(subject); >+ if (!country) >+ country = strdup("(not specified)"); >+ >+ PR_fprintf(outFile, "%s\n", NS_CERTREQ_HEADER); >+ numBytes = PR_Write(outFile, obuf, total); >+ if (numBytes != total) { >+ SECU_PrintSystemError(progName, "write error"); >+ return SECFailure; >+ } >+ PR_fprintf(outFile, "\n%s\n", NS_CERTREQ_TRAILER); >+ } else { >+ numBytes = PR_Write(outFile, result.data, result.len); >+ if (numBytes != (int)result.len) { >+ SECU_PrintSystemError(progName, "write error"); >+ return SECFailure; >+ } >+ } >+ return SECSuccess; >+} >+ >+static CERTCertificate * >+MakeV1Cert(CERTCertDBHandle * handle, >+ CERTCertificateRequest *req, >+ char *issuerNickName, >+ PRBool selfsign, >+ unsigned int serialNumber, >+ int warpmonths, >+ int validityMonths) >+{ >+ CERTCertificate *issuerCert = NULL; >+ CERTValidity *validity; >+ CERTCertificate *cert = NULL; >+ PRExplodedTime printableTime; >+ PRTime now, after; >+ >+ if ( !selfsign ) { >+ issuerCert = CERT_FindCertByNicknameOrEmailAddr(handle, issuerNickName); >+ if (!issuerCert) { >+ SECU_PrintError(progName, "could not find certificate named \"%s\"", >+ issuerNickName); >+ return NULL; >+ } >+ } >+ >+ now = PR_Now(); >+ PR_ExplodeTime (now, PR_GMTParameters, &printableTime); >+ if ( warpmonths ) { >+ printableTime.tm_month += warpmonths; >+ now = PR_ImplodeTime (&printableTime); >+ PR_ExplodeTime (now, PR_GMTParameters, &printableTime); >+ } >+ printableTime.tm_month += validityMonths; >+ after = PR_ImplodeTime (&printableTime); >+ >+ /* note that the time is now in micro-second unit */ >+ validity = CERT_CreateValidity (now, after); >+ if (validity) { >+ cert = CERT_CreateCertificate(serialNumber, >+ (selfsign ? &req->subject >+ : &issuerCert->subject), >+ validity, req); >+ >+ CERT_DestroyValidity(validity); >+ } >+ if ( issuerCert ) { >+ CERT_DestroyCertificate (issuerCert); >+ } >+ >+ return(cert); >+} >+ >+static SECItem * >+SignCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool selfsign, >+ SECOidTag hashAlgTag, >+ SECKEYPrivateKey *privKey, char *issuerNickName, void *pwarg) >+{ >+ SECItem der; >+ SECItem *result = NULL; >+ SECKEYPrivateKey *caPrivateKey = NULL; >+ SECStatus rv; >+ PRArenaPool *arena; >+ SECOidTag algID; >+ void *dummy; >+ >+ if ( !selfsign ) { >+ CERTCertificate *issuer = PK11_FindCertFromNickname(issuerNickName, pwarg); >+ if ( (CERTCertificate *)NULL == issuer ) { >+ SECU_PrintError(progName, "unable to find issuer with nickname %s", >+ issuerNickName); >+ return (SECItem *)NULL; >+ } >+ >+ privKey = caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg); >+ CERT_DestroyCertificate(issuer); >+ if (caPrivateKey == NULL) { >+ SECU_PrintError(progName, "unable to retrieve key %s", issuerNickName); >+ return NULL; >+ } >+ } >+ >+ arena = cert->arena; >+ >+ algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, hashAlgTag); >+ if (algID == SEC_OID_UNKNOWN) { >+ fprintf(stderr, "Unknown key or hash type for issuer."); >+ goto done; >+ } >+ >+ rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0); >+ if (rv != SECSuccess) { >+ fprintf(stderr, "Could not set signature algorithm id."); >+ goto done; >+ } >+ >+ /* we only deal with cert v3 here */ >+ *(cert->version.data) = 2; >+ cert->version.len = 1; >+ >+ der.len = 0; >+ der.data = NULL; >+ dummy = SEC_ASN1EncodeItem (arena, &der, cert, >+ SEC_ASN1_GET(CERT_CertificateTemplate)); >+ if (!dummy) { >+ fprintf (stderr, "Could not encode certificate.\n"); >+ goto done; >+ } >+ >+ result = (SECItem *) PORT_ArenaZAlloc (arena, sizeof (SECItem)); >+ if (result == NULL) { >+ fprintf (stderr, "Could not allocate item for certificate data.\n"); >+ goto done; >+ } >+ >+ rv = SEC_DerSignData(arena, result, der.data, der.len, privKey, algID); >+ if (rv != SECSuccess) { >+ fprintf (stderr, "Could not sign encoded certificate data.\n"); >+ /* result allocated out of the arena, it will be freed >+ * when the arena is freed */ >+ result = NULL; >+ goto done; >+ } >+ cert->derCert = *result; >+done: >+ if (caPrivateKey) { >+ SECKEY_DestroyPrivateKey(caPrivateKey); >+ } >+ return result; >+} >+ >+static SECStatus >+CreateCert( >+ CERTCertDBHandle *handle, >+ char *issuerNickName, >+ PRFileDesc *inFile, >+ PRFileDesc *outFile, >+ SECKEYPrivateKey *selfsignprivkey, >+ void *pwarg, >+ SECOidTag hashAlgTag, >+ unsigned int serialNumber, >+ int warpmonths, >+ int validityMonths, >+ const char *emailAddrs, >+ const char *dnsNames, >+ PRBool ascii, >+ PRBool selfsign, >+ certutilExtnList extnList, >+ CERTCertificate **outCert) >+{ >+ void *extHandle; >+ SECItem *certDER; >+ PRArenaPool *arena = NULL; >+ SECItem reqDER; >+ CERTCertExtension **CRexts; >+ CERTCertificate *subjectCert = NULL; >+ CERTCertificateRequest *certReq = NULL; >+ SECStatus rv = SECSuccess; >+ >+ reqDER.data = NULL; >+ do { >+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ if (!arena) { >+ GEN_BREAK (SECFailure); >+ } >+ >+ /* Create a certrequest object from the input cert request der */ >+ certReq = GetCertRequest(inFile, ascii); >+ if (certReq == NULL) { >+ GEN_BREAK (SECFailure) >+ } >+ >+ subjectCert = MakeV1Cert (handle, certReq, issuerNickName, selfsign, >+ serialNumber, warpmonths, validityMonths); >+ if (subjectCert == NULL) { >+ GEN_BREAK (SECFailure) >+ } >+ >+ extHandle = CERT_StartCertExtensions (subjectCert); >+ if (extHandle == NULL) { >+ GEN_BREAK (SECFailure) >+ } >+ >+ rv = AddExtensions(extHandle, emailAddrs, dnsNames, extnList); >+ if (rv != SECSuccess) { >+ GEN_BREAK (SECFailure) >+ } >+ >+ if (certReq->attributes != NULL && >+ certReq->attributes[0] != NULL && >+ certReq->attributes[0]->attrType.data != NULL && >+ certReq->attributes[0]->attrType.len > 0 && >+ SECOID_FindOIDTag(&certReq->attributes[0]->attrType) >+ == SEC_OID_PKCS9_EXTENSION_REQUEST) { >+ rv = CERT_GetCertificateRequestExtensions(certReq, &CRexts); >+ if (rv != SECSuccess) >+ break; >+ rv = CERT_MergeExtensions(extHandle, CRexts); >+ if (rv != SECSuccess) >+ break; >+ } >+ >+ CERT_FinishExtensions(extHandle); >+ >+ certDER = SignCert(handle, subjectCert, selfsign, hashAlgTag, >+ selfsignprivkey, issuerNickName,pwarg); >+ >+ if (certDER) { >+ if (ascii) { >+ PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CERT_HEADER, >+ BTOA_DataToAscii(certDER->data, certDER->len), >+ NS_CERT_TRAILER); >+ } else { >+ PR_Write(outFile, certDER->data, certDER->len); >+ } >+ } >+ >+ } while (0); >+ >+ CERT_DestroyCertificateRequest(certReq); >+ PORT_FreeArena (arena, PR_FALSE); >+ if (rv == SECSuccess) { >+ PR_fprintf(PR_STDOUT, "%s Copying the cert pointer\n", progName); >+ *outCert = subjectCert; >+ } else { >+ PRErrorCode perr = PR_GetError(); >+ fprintf(stderr, "%s: unable to create cert, (%s)\n", >+ progName, SECU_Strerror(perr)); >+ if (subjectCert) >+ CERT_DestroyCertificate (subjectCert); >+ } >+ >+ return (rv); >+} >+ >+ >+typedef struct KeyPairStr KeyPair; >+ >+typedef struct _PrivateKeyStr PrivateKey; >+ >+ >+/* Keyutil commands */ >+typedef enum _CommandType { >+ cmd_CertReq, >+ cmd_CreateNewCert >+} CommandType; >+ >+/* >+ * Get the key encryption password from a password file. >+ * Stores the password from pwFile in pwitem. >+ */ >+PRBool GetKeyPassword(const char *pwFile, SECItem *pwitem) >+{ >+ int i; >+ unsigned char phrase[200]; >+ PRFileDesc *fd; >+ PRInt32 nb; >+ >+ if (!pwFile) >+ return PR_FALSE; >+ >+ fd = PR_Open(pwFile, PR_RDONLY, 0); >+ if (!fd) >+ return PR_FALSE; >+ >+ nb = PR_Read(fd, phrase, sizeof(phrase)); >+ PR_Close(fd); >+ >+ /* handle the Windows EOL case */ >+ i = 0; >+ while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb) >+ i++; >+ phrase[i] = '\0'; >+ if (nb == 0) >+ return PR_FALSE; >+ >+ pwitem->data = (unsigned char *) PORT_Strdup((char*)phrase); >+ pwitem->len = (unsigned int) strlen((char*)phrase); >+ pwitem->type = siBuffer; >+ >+ return PR_TRUE; >+} >+ >+/* returns 0 for success, -1 for failure (EOF encountered) */ >+static int >+UpdateRNG(void) >+{ >+ char randbuf[RAND_BUF_SIZE]; >+ int fd, count; >+ int c; >+ int rv = 0; >+ cc_t orig_cc_min; >+ cc_t orig_cc_time; >+ tcflag_t orig_lflag; >+ struct termios tio; >+ char meter[] = { >+ "\r| |" }; >+ >+#define FPS fprintf(stderr, >+ FPS "\n"); >+ FPS "A random seed must be generated that will be used in the\n"); >+ FPS "creation of your key. One of the easiest ways to create a\n"); >+ FPS "random seed is to use the timing of keystrokes on a keyboard.\n"); >+ FPS "\n"); >+ FPS "To begin, type keys on the keyboard until this progress meter\n"); >+ FPS "is full. DO NOT USE THE AUTOREPEAT FUNCTION ON YOUR KEYBOARD!\n"); >+ FPS "\n"); >+ FPS "\n"); >+ FPS "Continue typing until the progress meter is full:\n\n"); >+ FPS meter); >+ FPS "\r|"); >+ >+ /* turn off echo on stdin & return on 1 char instead of NL */ >+ fd = fileno(stdin); >+ >+ tcgetattr(fd, &tio); >+ orig_lflag = tio.c_lflag; >+ orig_cc_min = tio.c_cc[VMIN]; >+ orig_cc_time = tio.c_cc[VTIME]; >+ tio.c_lflag &= ~ECHO; >+ tio.c_lflag &= ~ICANON; >+ tio.c_cc[VMIN] = 1; >+ tio.c_cc[VTIME] = 0; >+ tcsetattr(fd, TCSAFLUSH, &tio); >+ >+ /* Get random noise from keyboard strokes */ >+ count = 0; >+ while (count < sizeof randbuf) { >+ c = getc(stdin); >+ if (c == EOF) { >+ rv = -1; >+ break; >+ } >+ randbuf[count] = c; >+ if (count == 0 || c != randbuf[count-1]) { >+ count++; >+ FPS "*"); >+ } >+ } >+ PK11_RandomUpdate(randbuf, sizeof randbuf); >+ memset(randbuf, 0, sizeof randbuf); >+ >+ FPS "\n\n"); >+ FPS "Finished. Press enter to continue: "); >+ >+ while ((c = getc(stdin)) != '\n' && c != EOF) >+ ; >+ if (c == EOF) >+ rv = -1; >+ FPS "\n"); >+ >+#undef FPS >+ >+ /* set back termio the way it was */ >+ tio.c_lflag = orig_lflag; >+ tio.c_cc[VMIN] = orig_cc_min; >+ tio.c_cc[VTIME] = orig_cc_time; >+ tcsetattr(fd, TCSAFLUSH, &tio); >+ >+ return rv; >+} >+ >+static SECStatus >+CERTUTIL_FileForRNG(const char *noise) >+{ >+ char buf[2048]; >+ PRFileDesc *fd; >+ PRInt32 count; >+ >+ fd = PR_Open(noise,PR_RDONLY,0); >+ if (!fd) { >+ fprintf(stderr, "%s: failed to open noise file %s\n", progName, noise); >+ return SECFailure; >+ } >+ >+ do { >+ count = PR_Read(fd,buf,sizeof(buf)); >+ if (count > 0) { >+ PK11_RandomUpdate(buf,count); >+ } >+ } while (count > 0); >+ >+ PR_Close(fd); >+ return SECSuccess; >+} >+ >+SECKEYPrivateKey * >+GenerateRSAPrivateKey(KeyType keytype, >+ PK11SlotInfo *slot, >+ int rsasize, >+ int publicExponent, >+ char *noise, >+ SECKEYPublicKey **pubkeyp, >+ secuPWData *accessPassword) >+{ >+ CK_MECHANISM_TYPE mechanism; >+ PK11RSAGenParams rsaparams; >+ SECKEYPrivateKey * privKey = NULL; >+ >+ if (slot == NULL) >+ return NULL; >+ >+ if (PK11_Authenticate(slot, PR_TRUE, accessPassword) != SECSuccess) >+ return NULL; >+ >+ /* >+ * Do some random-number initialization. >+ */ >+ >+ if (noise) { >+ SECStatus rv = CERTUTIL_FileForRNG(noise); >+ if (rv != SECSuccess) { >+ PORT_SetError(PR_END_OF_FILE_ERROR); /* XXX */ >+ return NULL; >+ } >+ } else { >+ int rv = UpdateRNG(); >+ if (rv) { >+ PORT_SetError(PR_END_OF_FILE_ERROR); >+ return NULL; >+ } >+ } >+ >+ rsaparams.keySizeInBits = rsasize; >+ rsaparams.pe = publicExponent; >+ mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; >+ >+ fprintf(stderr, "\n\n"); >+ fprintf(stderr, "Generating key. This may take a few moments...\n\n"); >+ >+ privKey = PK11_GenerateKeyPair(slot, >+ mechanism, &rsaparams, pubkeyp, >+ PR_FALSE /* isPerm */, >+ PR_TRUE /* isSensitive*/, >+ accessPassword /* wincx */ >+ ); >+ >+ assert(privKey); >+ assert(pubkeyp); >+ return privKey; >+} >+ >+/* >+ * Decrypt the private key >+ */ >+SECStatus DecryptKey( >+ SECKEYEncryptedPrivateKeyInfo *epki, >+ SECOidTag algTag, >+ SECItem *pwitem, >+ secuPWData *accessPassword, >+ SECItem *derPKI) >+{ >+ SECItem *cryptoParam = NULL; >+ PK11SymKey *symKey = NULL; >+ PK11Context *ctx = NULL; >+ SECStatus rv = SECSuccess; >+ >+ if (!pwitem) { >+ return SEC_ERROR_INVALID_ARGS; >+ } >+ >+ do { >+ SECAlgorithmID algid = epki->algorithm; >+ CK_MECHANISM_TYPE cryptoMechType; >+ CK_MECHANISM cryptoMech; >+ CK_ATTRIBUTE_TYPE operation = CKA_DECRYPT; >+ PK11SlotInfo *slot = NULL; >+ >+ cryptoMechType = PK11_GetPBECryptoMechanism(&algid, &cryptoParam, pwitem); >+ if (cryptoMechType == CKM_INVALID_MECHANISM) { >+ ERROR_BREAK; >+ } >+ >+ cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMechType); >+ cryptoMech.pParameter = cryptoParam ? cryptoParam->data : NULL; >+ cryptoMech.ulParameterLen = cryptoParam ? cryptoParam->len : 0; >+ >+ slot = PK11_GetBestSlot(cryptoMechType, NULL); >+ if (!slot) { >+ ERROR_BREAK; >+ } >+ >+ symKey = PK11_PBEKeyGen(slot, &algid, pwitem, PR_FALSE, accessPassword); >+ if (symKey == NULL) { >+ ERROR_BREAK; >+ } >+ >+ ctx = PK11_CreateContextBySymKey(cryptoMechType, operation, symKey, cryptoParam); >+ if (ctx == NULL) { >+ ERROR_BREAK; >+ } >+ >+ rv = PK11_CipherOp(ctx, >+ derPKI->data, /* out */ >+ (int *)(&derPKI->len), /* out len */ >+ (int)epki->encryptedData.len, /* max out */ >+ epki->encryptedData.data, /* in */ >+ (int)epki->encryptedData.len); /* in len */ >+ >+ assert(derPKI->len == epki->encryptedData.len); >+ assert(rv == SECSuccess); >+ rv = PK11_Finalize(ctx); >+ assert(rv == SECSuccess); >+ >+ } while (0); >+ >+ /* cleanup */ >+ if (symKey) { >+ PK11_FreeSymKey(symKey); >+ } >+ if (cryptoParam) { >+ SECITEM_ZfreeItem(cryptoParam, PR_TRUE); >+ cryptoParam = NULL; >+ } >+ if (ctx) { >+ PK11_DestroyContext(ctx, PR_TRUE); >+ } >+ >+ return rv; >+ >+} >+ >+/* Output the private key to a file */ >+static SECStatus >+KeyOut(const char *keyoutfile, >+ const char *key_pwd_file, >+ SECKEYPrivateKey *privkey, >+ SECKEYPublicKey *pubkey, >+ SECOidTag algTag, >+ secuPWData *accessPassword, >+ PRBool ascii) >+{ >+ >+#define RAND_PASS_LEN 6 >+ >+ PRFileDesc *keyOutFile = NULL; >+ PRUint32 total = 0; >+ PRUint32 numBytes = 0; >+ SECItem *derEPKI = NULL; >+ SECItem derPKI = { 0, NULL, 0 }; >+ SECItem pwitem = { 0, NULL, 0 }; >+ PRArenaPool *arenaForEPKI = NULL; >+ PLArenaPool *arenaForPKI = NULL; >+ SECKEYEncryptedPrivateKeyInfo *epki = NULL; >+ unsigned char randomPassword[RAND_PASS_LEN]; >+ >+ int rv = SECSuccess; >+ >+ do { >+ /* Caller wants an encrypted key. Get >+ * the password from the file */ >+ if (key_pwd_file) { >+ if (!GetKeyPassword(key_pwd_file, &pwitem)) { >+ return 255; >+ } >+ } else { >+ /* Caller wants clear keys. Make up a dummy >+ * password to get NSS to export an encrypted >+ * key which we will decrypt. >+ */ >+ rv = PK11_GenerateRandom(randomPassword, RAND_PASS_LEN); >+ if (rv != SECSuccess) GEN_BREAK(rv); >+ pwitem.data = randomPassword; >+ pwitem.len = RAND_PASS_LEN; >+ pwitem.type = siBuffer; >+ } >+ >+ keyOutFile = PR_Open(keyoutfile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 00660); >+ if (!keyOutFile) { >+ PR_fprintf(PR_STDERR, >+ "%s -o: unable to open \"%s\" for writing\n", >+ progName, keyoutfile); >+ GEN_BREAK(255); >+ } >+ >+ epki = PK11_ExportEncryptedPrivKeyInfo(NULL, >+ algTag, &pwitem, privkey, 1000, accessPassword); >+ if (!epki) { >+ rv = PORT_GetError(); >+ SECU_PrintError(progName, >+ "Can't export private key info (%d)\n", rv); >+ GEN_BREAK(rv); >+ } >+ >+ arenaForEPKI = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); >+ assert(arenaForEPKI); >+ >+ if (key_pwd_file) { >+ /* NULL dest to let it allocate memory for us */ >+ derEPKI = SEC_ASN1EncodeItem(arenaForEPKI, NULL, epki, >+ SECKEY_EncryptedPrivateKeyInfoTemplate); >+ if (rv != SECSuccess) { >+ PR_fprintf(PR_STDERR, "%s ASN1 Encode failed (%dl)\n", >+ progName, rv); >+ GEN_BREAK(rv); >+ } >+ >+ } else { >+ /* Make a decrypted key the one to write out. */ >+ >+ arenaForPKI = PORT_NewArena(2048); >+ if (!arenaForPKI) { >+ GEN_BREAK(PR_OUT_OF_MEMORY_ERROR); >+ } >+ >+ derPKI.data = PORT_ArenaAlloc(arenaForPKI, epki->encryptedData.len); >+ derPKI.len = epki->encryptedData.len; >+ derPKI.type = siBuffer; >+ >+ rv = DecryptKey(epki, algTag, &pwitem, accessPassword, &derPKI); >+ if (rv) { >+ GEN_BREAK(rv); >+ } >+ } >+ >+ if (ascii) { >+ /* we could be exporting a clear or encrypted key */ >+ SECItem *src = key_pwd_file ? derEPKI : &derPKI; >+ char *header = key_pwd_file ? ENCRYPTED_KEY_HEADER : KEY_HEADER; >+ char *trailer = key_pwd_file ? ENCRYPTED_KEY_TRAILER : KEY_TRAILER; >+ char *b64 = NULL; >+ do { >+ >+ b64 = BTOA_ConvertItemToAscii(src); >+ if (b64) >+ break; >+ >+ total = PL_strlen(b64); >+ >+ PR_fprintf(keyOutFile, "%s\n", header); >+ >+ numBytes = PR_Write(keyOutFile, b64, total); >+ >+ if (numBytes != total) { >+ printf("Wrote %d bytes, instead of %d\n", numBytes, total); >+ break; >+ } >+ >+ PR_fprintf(keyOutFile, "\n%s\n", trailer); >+ >+ } while (0); >+ >+ if (b64) { >+ PORT_Free(b64); >+ } >+ >+ } else { >+ if (key_pwd_file) { >+ /* Write out the encrypted key */ >+ numBytes = PR_Write(keyOutFile, derEPKI, derEPKI->len); >+ } else { >+ /* Write out the unencrypted key */ >+ numBytes = PR_Write(keyOutFile, &derPKI, derPKI.len); >+ if (numBytes != derEPKI->len) { >+ printf("Wrote %d bytes, instead of %d\n", numBytes, derPKI.len); >+ } >+ } >+ } >+ >+ printf("Wrote %d bytes of encoded data to %s \n", numBytes, keyoutfile); >+ /* can we read it and reverse operations */ >+ >+ } while (0); >+ >+ if (keyOutFile) { >+ PR_Close(keyOutFile); >+ } >+ >+ if (derEPKI != NULL) >+ PORT_Free(derEPKI); >+ >+ if (arenaForEPKI) { >+ PORT_FreeArena(arenaForEPKI, PR_FALSE); >+ } >+ >+ if (arenaForPKI) { >+ PORT_FreeArena(arenaForPKI, PR_FALSE); >+ } >+ >+ if (!key_pwd_file) { >+ /* paranoia, though stack-based object we clear it anyway */ >+ memset(randomPassword, 0, RAND_PASS_LEN); >+ } >+ >+ return rv; >+} >+ >+/* Generate a certificate signing request >+ * or a self_signed certificate. >+ */ >+static int keyutil_main( >+ CERTCertDBHandle *certHandle, >+ const char *noisefile, >+ const char *access_pwd_file, >+ const char *key_pwd_file, >+ const char *subjectstr, >+ int keysize, >+ int warpmonths, >+ int validityMonths, >+ PRBool ascii, >+ const char *certreqfile, >+ const char *certfile, >+ const char *keyoutfile) >+{ >+ static certutilExtnList nullextnlist = {PR_FALSE}; >+ >+ CERTCertificate *cert = NULL; >+ PRFileDesc *outFile = NULL; >+ PRFileDesc *keyOutFile = NULL; >+ CERTName *subject = NULL; >+ SECKEYPrivateKey *privkey = NULL; >+ SECKEYPublicKey *pubkey = NULL; >+ /* PK11_GetInternalSlot() ? */ >+ PK11SlotInfo *slot = PK11_GetInternalKeySlot(); >+ secuPWData accessPassword = { PW_NONE, 0 }; >+ KeyType keytype = rsaKey; >+ SECOidTag hashAlgTag = SEC_OID_UNKNOWN; >+ PRBool doCert = certfile != NULL; >+ int rv; >+ >+ outFile = PR_Open(certreqfile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 00660); >+ if (!outFile) { >+ PR_fprintf(PR_STDERR, >+ "%s -o: unable to open \"%s\" for writing (%ld, %ld)\n", >+ progName, certreqfile, >+ PR_GetError(), PR_GetOSError()); >+ return 255; >+ } >+ printf("Opened %s for writing\n", certreqfile); >+ if (access_pwd_file) { >+ accessPassword.source = PW_FROMFILE; >+ accessPassword.data = (char *)access_pwd_file; >+ } >+ >+ privkey = GenerateRSAPrivateKey(keytype, slot, >+ keysize, 65537L, (char *)noisefile, &pubkey, &accessPassword); >+ >+ if (!privkey) { >+ PR_fprintf(PR_STDERR, >+ "%s Keypair generation failed: \"%d\"\n", >+ progName, PORT_GetError()); >+ rv = 255; >+ goto shutdown; >+ } >+ PR_fprintf(PR_STDOUT, "%s Got a key\n", progName); >+ /* >+ * Certificate request >+ */ >+ subject = CERT_AsciiToName((char *)subjectstr); >+ if (!subject) { >+ PR_fprintf(PR_STDERR, "%s -s: improperly formatted name: \"%s\"\n", >+ progName, subjectstr); >+ rv = 255; >+ goto shutdown; >+ } >+ >+ hashAlgTag = SEC_OID_MD5; >+ >+ /* Make a cert request */ >+ rv = CertReq(privkey, pubkey, rsaKey, hashAlgTag, subject, >+ NULL, /* PhoneNumber */ >+ ascii, /* ASCIIForIO */ >+ NULL, /* ExtendedEmailAddrs */ >+ NULL, /* ExtendedDNSNames */ >+ nullextnlist, /* certutil_extns */ >+ outFile); >+ >+ PR_Close(outFile); >+ if (rv) { >+ PR_fprintf(PR_STDERR, "%s CertReq failed: \"%d\"\n", >+ progName, PORT_GetError()); >+ rv = 255; >+ goto shutdown; >+ } >+ >+ PR_fprintf(PR_STDOUT, "%s Made a cert request\n", progName); >+ if (doCert) { >+ >+ /* If making a cert, we already have a cert request file. >+ * without any extensions, load it with any command line extensions >+ * and output the cert to other file. Delete the request file. >+ */ >+ PRFileDesc *inFile = NULL; >+ unsigned int serialNumber; >+ >+ /* Make a default serial number from the current time. */ >+ PRTime now = PR_Now(); >+ LL_USHR(now, now, 19); >+ LL_L2UI(serialNumber, now); >+ >+ privkey->wincx = &accessPassword; >+ PR_Close(outFile); >+ >+ inFile = PR_Open(certreqfile, PR_RDONLY, 0); >+ assert(inFile); >+ if (!inFile) { >+ PR_fprintf(PR_STDERR, "Failed to open file \"%s\" (%ld, %ld) for reading.\n", >+ certreqfile, PR_GetError(), PR_GetOSError()); >+ rv = SECFailure; >+ goto shutdown; >+ } >+ >+ outFile = PR_Open(certfile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 00660); >+ >+ if (!outFile) { >+ PR_fprintf(PR_STDERR, "Failed to open file \"%s\" (%ld, %ld).\n", >+ certfile, PR_GetError(), PR_GetOSError()); >+ rv = SECFailure; >+ goto shutdown; >+ } >+ >+ /* Create a certificate (-C or -S). */ >+ >+ /* issuerName == subject */ >+ rv = CreateCert(certHandle, >+ "tempnickname", inFile, outFile, >+ privkey, &accessPassword, hashAlgTag, >+ serialNumber, warpmonths, validityMonths, >+ NULL, NULL, ascii, PR_TRUE, NULL, >+ &cert); >+ /* >+ ExtendedEmailAddrs,ExtendedDNSNames, >+ ASCIIForIO,SelfSign,certutil_extns, thecert >+ */ >+ if (rv) { >+ PR_fprintf(PR_STDERR, "Failed to create certificate \"%s\" (%ld).\n", >+ outFile, PR_GetError()); >+ rv = SECFailure; >+ goto shutdown; >+ } >+ PR_fprintf(PR_STDOUT, "%s Created a cert\n", progName); >+ >+ /* Sanity check: Check cert validity against current time. */ >+ >+ /* for fips - must log in to get private key */ >+ if (slot && PK11_NeedLogin(slot)) { >+ SECStatus newrv = PK11_Authenticate(slot, PR_TRUE, &accessPassword); >+ if (newrv != SECSuccess) { >+ SECU_PrintError(progName, "could not authenticate to token %s.", >+ PK11_GetTokenName(slot)); >+ goto shutdown; >+ } >+ } >+ } >+ >+ /* If the caller wants the private key extract it and save it to a file. */ >+ if (keyoutfile) { >+ /* Two candidate tags to use: SEC_OID_DES_EDE3_CBC and >+ * SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC >+ */ >+ rv = KeyOut(keyoutfile, key_pwd_file, >+ privkey, pubkey, SEC_OID_DES_EDE3_CBC, >+ &accessPassword, ascii); >+ if (rv != SECSuccess) { >+ SECU_PrintError(progName, "Failed to write the key"); >+ } else { >+ printf("%s Wrote the key to\n%s\n", progName, keyoutfile); >+ } >+ } >+ >+shutdown: >+ if (cert) { >+ CERT_DestroyCertificate(cert); >+ } >+ if (keyOutFile) { >+ PR_Close(keyOutFile); >+ } >+ if (slot) { >+ PK11_FreeSlot(slot); >+ } >+ if (privkey) { >+ SECKEY_DestroyPrivateKey(privkey); >+ } >+ if (pubkey) { >+ SECKEY_DestroyPublicKey(pubkey); >+ } >+ >+ return rv == SECSuccess ? 0 : 255; >+} >+ >+/* $Id: keyutil.c,v 1.3 2008/05/03 22:54:55 emaldonado Exp $ */ >+ >+/* Key generation, encryption, and certificate utility code, based on >+ * code from NSS's security utilities and the certutil application. >+ * Elio Maldonado <emaldona@redhat.com> >+ */ >+ >+ >+int main(int argc, char **argv) >+{ >+ int optc, rv = 0; >+ static const struct option options[] = { >+ { "command", required_argument, NULL, 'c' }, >+ { "subject", required_argument, NULL, 's' }, >+ { "gkeysize", required_argument, NULL, 'g' }, >+ { "validity", required_argument, NULL, 'v' }, >+ { "encpwdfile", required_argument, NULL, 'e' }, >+ { "filepwdnss", required_argument, NULL, 'f' }, >+ { "digest", required_argument, NULL, 'd' }, >+ { "znoisefile", required_argument, NULL, 'z' }, >+ { "input", required_argument, NULL, 'i' }, /* key in */ >+ { "passout", required_argument, NULL, 'p' }, >+ { "output", required_argument, NULL, 'o' }, /* reg, cert, enckey */ >+ { "keyout", required_argument, NULL, 'k' }, /* plaintext key */ >+ { "ascii", no_argument, NULL, 'a' }, /* ascii */ >+ { "help", no_argument, NULL, 'h' }, >+ { NULL } >+ }; >+ char *cmdstr = NULL; >+ char *noisefile = NULL; >+ int keysize = 1024; >+ int warpmonths = 0; >+ int validity_months = 24; >+ char *keyfile = NULL; >+ char *outfile = NULL; >+ char *subject = NULL; >+ char *access_pwd_file = NULL; >+ char *key_pwd_file = NULL; >+ char *digestAlgorithm = "md5"; >+ char *keyoutfile = 0; >+ PRBool ascii = PR_FALSE; >+ CERTCertDBHandle *certHandle = 0; >+ SECStatus status = 0; >+ CommandType cmd = cmd_CertReq; >+ PRBool initialized = PR_FALSE; >+ >+ while ((optc = getopt_long(argc, argv, "ac:s:g:v:e:f:d:z:i:p:o:k:h", options, NULL)) != -1) { >+ switch (optc) { >+ case 'a': >+ ascii = PR_TRUE; >+ break; >+ case 'c': >+ cmdstr = strdup(optarg); >+ printf("cmdstr: %s\n", cmdstr); >+ if (strcmp(cmdstr, "genreq") == 0) { >+ cmd = cmd_CertReq; >+ printf("\ncmd_CertReq\n"); >+ } else if (strcmp(cmdstr, "makecert") == 0) { >+ cmd = cmd_CreateNewCert; >+ printf("\ncmd_CreateNewCert\n"); >+ } else { >+ printf("\nInvalid argument: %s\n", cmdstr); >+ exit(2); >+ } >+ printf("command: %s\n", cmdstr); >+ break; >+ case 's': >+ subject = strdup(optarg); >+ printf("subject = %s\n", subject); >+ break; >+ case 'g': >+ keysize = atoi(optarg); >+ printf("keysize = %d bits\n", keysize); >+ break; >+ case 'v': >+ validity_months = atoi(optarg); >+ printf("valid for %d months\n", validity_months); >+ break; >+ case 'e': >+ key_pwd_file = strdup(optarg); >+ printf("key encryption password from = %s\n", key_pwd_file); >+ break; >+ case 'f': >+ access_pwd_file = strdup(optarg); >+ printf("module access password from = %s\n", access_pwd_file); >+ break; >+ case 'd': >+ digestAlgorithm = strdup(optarg); >+ printf("message digest %s\n", digestAlgorithm); >+ break; >+ case 'z': >+ noisefile = strdup(optarg); >+ printf("random seed from %s\n", noisefile); >+ break; >+ case 'i': >+ keyfile = strdup(optarg); >+ printf("will process a key from %s\n", keyfile); >+ break; >+ case 'o': >+ /* could be req or cert */ >+ outfile = strdup(optarg); >+ printf("output will be written to %s\n", outfile); >+ break; >+ case 'k': >+ /* private key out in plaintext - side effect of req and cert */ >+ keyoutfile = strdup(optarg); >+ printf("output key written to %s\n", keyoutfile); >+ break; >+ case 'h': >+ Usage(progName); >+ break; >+ default: >+ printf("Bad arguments\n"); >+ Usage(progName); >+ break; >+ } >+ } >+ >+ /* Initialize NSPR and NSS. */ >+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); >+ >+ status = NSS_NoDB_Init(NULL); >+ if (status != SECSuccess ) { >+ printf("NSS initialization failed\n"); >+ return EXIT_FAILURE; >+ } >+ initialized = PR_TRUE; >+ >+ certHandle = CERT_GetDefaultCertDB(); >+ assert(certHandle); >+ >+ switch (cmd) { >+ case cmd_CertReq: >+ /* certfile NULL signals only the request is needed */ >+ rv = keyutil_main(certHandle, >+ noisefile, access_pwd_file, key_pwd_file, >+ subject, keysize, warpmonths, validity_months, >+ ascii, outfile, NULL, keyoutfile); >+ break; >+ case cmd_CreateNewCert: >+ rv = keyutil_main(certHandle, >+ noisefile, access_pwd_file, key_pwd_file, >+ subject, keysize, warpmonths, validity_months, >+ ascii, "tmprequest", outfile, keyoutfile); >+ break; >+ default: >+ printf("\nEntered an inconsistent state, bailing out\n"); >+ rv = -1; >+ break; >+ } >+ >+ if ((initialized == PR_TRUE) && NSS_Shutdown() != SECSuccess) { >+ exit(1); >+ } >+ PR_Cleanup(); >+ >+ return rv; >+} >Index: devel/keyutil.h >=================================================================== >RCS file: devel/keyutil.h >diff -N devel/keyutil.h >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ devel/keyutil.h 3 May 2008 22:54:55 -0000 1.2 >@@ -0,0 +1,98 @@ >+/* >+ Copyright 2005 Red Hat, Inc. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. >+ >+ In addition, as a special exception, Red Hat, Inc. gives permission >+ to link the code of this program with the OpenSSL library (or with >+ modified versions of OpenSSL that use the same license as OpenSSL), >+ and distribute linked combinations including the two. You must obey >+ the GNU General Public License in all respects for all of the code >+ used other than OpenSSL. If you modify this file, you may extend >+ this exception to your version of the file, but you are not >+ obligated to do so. If you do not wish to do so, delete this >+ exception statement from your version. >+ >+*/ >+ >+/* ***** BEGIN LICENSE BLOCK ***** >+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 >+ * >+ * The contents of this file are subject to the Mozilla Public License Version >+ * 1.1 (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * http://www.mozilla.org/MPL/ >+ * >+ * Software distributed under the License is distributed on an "AS IS" basis, >+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License >+ * for the specific language governing rights and limitations under the >+ * License. >+ * >+ * The Original Code is the Netscape security libraries. >+ * >+ * The Initial Developer of the Original Code is >+ * Netscape Communications Corporation. >+ * Portions created by the Initial Developer are Copyright (C) 1994-2000 >+ * the Initial Developer. All Rights Reserved. >+ * >+ * Contributor(s): >+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories >+ * >+ * Alternatively, the contents of this file may be used under the terms of >+ * either the GNU General Public License Version 2 or later (the "GPL"), or >+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), >+ * in which case the provisions of the GPL or the LGPL are applicable instead >+ * of those above. If you wish to allow use of your version of this file only >+ * under the terms of either the GPL or the LGPL, and not to allow others to >+ * use your version of this file under the terms of the MPL, indicate your >+ * decision by deleting the provisions above and replace them with the notice >+ * and other provisions required by the GPL or the LGPL. If you do not delete >+ * the provisions above, a recipient may use your version of this file under >+ * the terms of any one of the MPL, the GPL or the LGPL. >+ * >+ * ***** END LICENSE BLOCK ***** */ >+ >+#ifndef _KEYUTIL_H >+#define _KEYUTIL_H >+ >+#include "secutil.h" >+ >+extern char *progName; >+ >+enum certutilExtns { >+ ext_keyUsage = 0, >+ ext_basicConstraint, >+ ext_authorityKeyID, >+ ext_CRLDistPts, >+ ext_NSCertType, >+ ext_extKeyUsage, >+ ext_authInfoAcc, >+ ext_subjInfoAcc, >+ ext_certPolicies, >+ ext_policyMappings, >+ ext_policyConstr, >+ ext_inhibitAnyPolicy, >+ ext_subjectKeyID, >+ ext_End >+}; >+ >+typedef PRBool certutilExtnList[ext_End]; >+ >+extern SECStatus >+AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames, >+ certutilExtnList extList); >+ >+#endif /* _KEYUTIL_H */ >+ >Index: devel/pemutil.c >=================================================================== >RCS file: devel/pemutil.c >diff -N devel/pemutil.c >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ devel/pemutil.c 3 May 2008 22:54:55 -0000 1.2 >@@ -0,0 +1,215 @@ >+/* >+ Copyright 2008 Red Hat, Inc. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. >+ >+ In addition, as a special exception, Red Hat, Inc. gives permission >+ to link the code of this program with the OpenSSL library (or with >+ modified versions of OpenSSL that use the same license as OpenSSL), >+ and distribute linked combinations including the two. You must obey >+ the GNU General Public License in all respects for all of the code >+ used other than OpenSSL. If you modify this file, you may extend >+ this exception to your version of the file, but you are not >+ obligated to do so. If you do not wish to do so, delete this >+ exception statement from your version. >+ >+*/ >+ >+/* Certificate processing utilities, based on code from Mozilla >+ * Network Security Services internal secutils static library. >+ */ >+ >+/* ***** BEGIN LICENSE BLOCK ***** >+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 >+ * >+ * The contents of this file are subject to the Mozilla Public License Version >+ * 1.1 (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * http://www.mozilla.org/MPL/ >+ * >+ * Software distributed under the License is distributed on an "AS IS" basis, >+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License >+ * for the specific language governing rights and limitations under the >+ * License. >+ * >+ * The Original Code is the Netscape security libraries. >+ * >+ * The Initial Developer of the Original Code is >+ * Netscape Communications Corporation. >+ * Portions created by the Initial Developer are Copyright (C) 1994-2000 >+ * the Initial Developer. All Rights Reserved. >+ * >+ * Contributor(s): >+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories >+ * >+ * Alternatively, the contents of this file may be used under the terms of >+ * either the GNU General Public License Version 2 or later (the "GPL"), or >+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), >+ * in which case the provisions of the GPL or the LGPL are applicable instead >+ * of those above. If you wish to allow use of your version of this file only >+ * under the terms of either the GPL or the LGPL, and not to allow others to >+ * use your version of this file under the terms of the MPL, indicate your >+ * decision by deleting the provisions above and replace them with the notice >+ * and other provisions required by the GPL or the LGPL. If you do not delete >+ * the provisions above, a recipient may use your version of this file under >+ * the terms of any one of the MPL, the GPL or the LGPL. >+ * >+ * ***** END LICENSE BLOCK ***** */ >+ >+/* >+ * The exported function here is PEMUTIL_PEM_read_X509. A function like >+ * this belongs in nss_compat_ossl. Elio Maldonado <emaldona@redhat.com> >+ */ >+ >+#include <cert.h> >+#include <certt.h> >+#include <nspr.h> >+#include <seccomon.h> >+#include <base64.h> >+#include <assert.h> >+ >+/* TODO: When CERT_NewTempCertificate becomes public in NSS 3.12 >+ * remove this extern declaration and the following #define. >+ */ >+extern CERTCertificate * >+__CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, >+ char *nickname, PRBool isperm, PRBool copyDER); >+ >+#define CERT_NewTempCertificate __CERT_NewTempCertificate >+ >+ >+#define TIME_BUF_SIZE 100 >+ >+/* decode a SECItem containing either a SEC_ASN1_GENERALIZED_TIME >+ or a SEC_ASN1_UTC_TIME */ >+extern SECStatus DER_DecodeTimeChoice(PRTime* output, const SECItem* input); >+ >+ >+/* Loads the contents of a file into a SECItem. >+ * Code is from the NSS security utilities. >+ */ >+static SECStatus FileToItem(SECItem *dst, PRFileDesc *src) >+{ >+ PRFileInfo info; >+ PRInt32 numBytes; >+ PRStatus prStatus; >+ >+ prStatus = PR_GetOpenFileInfo(src, &info); >+ >+ if (prStatus != PR_SUCCESS) { >+ return SECFailure; >+ } >+ >+ /* XXX workaround for 3.1, not all utils zero dst before sending */ >+ dst->data = 0; >+ if (!SECITEM_AllocItem(NULL, dst, info.size)) >+ goto loser; >+ >+ numBytes = PR_Read(src, dst->data, info.size); >+ if (numBytes != info.size) >+ goto loser; >+ >+ return SECSuccess; >+loser: >+ SECITEM_FreeItem(dst, PR_FALSE); >+ dst->data = NULL; >+ return SECFailure; >+} >+ >+/* Load a DER encoding into a SECItem. >+ * Code is from the NSS security utilities. >+ */ >+static SECStatus ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii) >+{ >+ SECStatus rv; >+ if (ascii) { >+ /* First convert ascii to binary */ >+ SECItem filedata; >+ char *asc, *body; >+ >+ /* Read in ascii data */ >+ rv = FileToItem(&filedata, inFile); >+ asc = (char *)filedata.data; >+ if (!asc) { >+ return SECFailure; >+ } >+ >+ /* check for headers and trailers and remove them */ >+ if ((body = strstr(asc, "-----BEGIN")) != NULL) { >+ char *trailer = NULL; >+ asc = body; >+ body = PORT_Strchr(body, '\n'); >+ if (!body) >+ body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */ >+ if (body) >+ trailer = strstr(++body, "-----END"); >+ if (trailer != NULL) { >+ *trailer = '\0'; >+ } else { >+ /*printf("input has header but no trailer\n");*/ >+ PORT_Free(filedata.data); >+ return SECFailure; >+ } >+ } else { >+ body = asc; >+ } >+ >+ /* Convert to binary */ >+ rv = ATOB_ConvertAsciiToItem(der, body); >+ if (rv) { >+ /* printf("ATOB_ConvertAsciiToItem failed\n");*/ >+ PORT_Free(filedata.data); >+ return SECFailure; >+ } >+ >+ PORT_Free(filedata.data); >+ } else { >+ /* Read in binary der */ >+ rv = FileToItem(der, inFile); >+ if (rv) { >+ return SECFailure; >+ } >+ } >+ return SECSuccess; >+} >+ >+ >+/* Return a certificate structure from a pem-encoded cert in a file; >+ * or NULL on failure. Semantics similar to an OpenSSL >+ * PEM_read_X509(fp, NULL, NULL, NULL); call >+ */ >+CERTCertificate * >+PEMUTIL_PEM_read_X509(const char *filename) >+{ >+ CERTCertificate *cert = NULL; >+ PRFileDesc *fd = NULL; >+ SECItem derCert; >+ >+ fd = PR_Open(filename, PR_RDONLY, 0); >+ if (!fd) return NULL; >+ >+ /* Read in a DER from a file, it is ascii */ >+ if (SECSuccess != ReadDERFromFile(&derCert, fd, PR_TRUE)) >+ goto cleanup; >+ >+ /* create a temporary cert in the database */ >+ cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), >+ &derCert, NULL, PR_FALSE, PR_FALSE); >+ /* noNickname, notPerm, noCopy */ >+ cleanup: >+ if (fd) PR_Close(fd); >+ >+ return cert; >+} >Index: devel/secerror.c >=================================================================== >RCS file: devel/secerror.c >diff -N devel/secerror.c >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ devel/secerror.c 3 May 2008 22:54:55 -0000 1.2 >@@ -0,0 +1,111 @@ >+/* ***** BEGIN LICENSE BLOCK ***** >+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 >+ * >+ * The contents of this file are subject to the Mozilla Public License Version >+ * 1.1 (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * http://www.mozilla.org/MPL/ >+ * >+ * Software distributed under the License is distributed on an "AS IS" basis, >+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License >+ * for the specific language governing rights and limitations under the >+ * License. >+ * >+ * The Original Code is the Netscape security libraries. >+ * >+ * The Initial Developer of the Original Code is >+ * Netscape Communications Corporation. >+ * Portions created by the Initial Developer are Copyright (C) 1994-2000 >+ * the Initial Developer. All Rights Reserved. >+ * >+ * Contributor(s): >+ * >+ * Alternatively, the contents of this file may be used under the terms of >+ * either the GNU General Public License Version 2 or later (the "GPL"), or >+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), >+ * in which case the provisions of the GPL or the LGPL are applicable instead >+ * of those above. If you wish to allow use of your version of this file only >+ * under the terms of either the GPL or the LGPL, and not to allow others to >+ * use your version of this file under the terms of the MPL, indicate your >+ * decision by deleting the provisions above and replace them with the notice >+ * and other provisions required by the GPL or the LGPL. If you do not delete >+ * the provisions above, a recipient may use your version of this file under >+ * the terms of any one of the MPL, the GPL or the LGPL. >+ * >+ * ***** END LICENSE BLOCK ***** */ >+#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> >+#include <stdio.h> >+ >+const tuple_str errStrings[] = { >+ >+/* keep this list in asceding order of error numbers */ >+/* SSLerrs.h not needed */ >+#include "SECerrs.h" >+#include "NSPRerrs.h" >+ >+}; >+ >+const PRInt32 numStrings = sizeof(errStrings) / sizeof(tuple_str); >+ >+/* Returns a UTF-8 encoded constant error string for "errNum". >+ * Returns NULL of errNum is unknown. >+ */ >+const char * >+SECU_Strerror(PRErrorCode errNum) { >+ PRInt32 low = 0; >+ PRInt32 high = numStrings - 1; >+ PRInt32 i; >+ PRErrorCode num; >+ static int initDone; >+ >+ /* make sure table is in ascending order. >+ * binary search depends on it. >+ */ >+ if (!initDone) { >+ PRErrorCode lastNum = ((PRInt32)0x80000000); >+ for (i = low; i <= high; ++i) { >+ num = errStrings[i].errNum; >+ if (num <= lastNum) { >+ fprintf(stderr, >+"sequence error in error strings at item %d\n" >+"error %d (%s)\n" >+"should come after \n" >+"error %d (%s)\n", >+ i, lastNum, errStrings[i-1].errString, >+ num, errStrings[i].errString); >+ } >+ lastNum = num; >+ } >+ initDone = 1; >+ } >+ >+ /* Do binary search of table. */ >+ while (low + 1 < high) { >+ i = (low + high) / 2; >+ num = errStrings[i].errNum; >+ if (errNum == num) >+ return errStrings[i].errString; >+ if (errNum < num) >+ high = i; >+ else >+ low = i; >+ } >+ if (errNum == errStrings[low].errNum) >+ return errStrings[low].errString; >+ if (errNum == errStrings[high].errNum) >+ return errStrings[high].errString; >+ return NULL; >+} >Index: devel/secutil.c >=================================================================== >RCS file: devel/secutil.c >diff -N devel/secutil.c >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ devel/secutil.c 3 May 2008 22:54:55 -0000 1.2 >@@ -0,0 +1,500 @@ >+/* >+ Copyright 2005 Red Hat, Inc. >+ >+ This program is free software; you can redistribute it and/or modify >+ it under the terms of the GNU General Public License as published by >+ the Free Software Foundation; either version 2 of the License, or >+ (at your option) any later version. >+ >+ This program is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+ GNU General Public License for more details. >+ >+ You should have received a copy of the GNU General Public License >+ along with this program; if not, write to the Free Software >+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. >+ >+ In addition, as a special exception, Red Hat, Inc. gives permission >+ to link the code of this program with the OpenSSL library (or with >+ modified versions of OpenSSL that use the same license as OpenSSL), >+ and distribute linked combinations including the two. You must obey >+ the GNU General Public License in all respects for all of the code >+ used other than OpenSSL. If you modify this file, you may extend >+ this exception to your version of the file, but you are not >+ obligated to do so. If you do not wish to do so, delete this >+ exception statement from your version. >+ >+*/ >+ >+/* ***** BEGIN LICENSE BLOCK ***** >+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 >+ * >+ * The contents of this file are subject to the Mozilla Public License Version >+ * 1.1 (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * http://www.mozilla.org/MPL/ >+ * >+ * Software distributed under the License is distributed on an "AS IS" basis, >+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License >+ * for the specific language governing rights and limitations under the >+ * License. >+ * >+ * The Original Code is the Netscape security libraries. >+ * >+ * The Initial Developer of the Original Code is >+ * Netscape Communications Corporation. >+ * Portions created by the Initial Developer are Copyright (C) 1994-2000 >+ * the Initial Developer. All Rights Reserved. >+ * >+ * Contributor(s): >+ * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories >+ * >+ * Alternatively, the contents of this file may be used under the terms of >+ * either the GNU General Public License Version 2 or later (the "GPL"), or >+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), >+ * in which case the provisions of the GPL or the LGPL are applicable instead >+ * of those above. If you wish to allow use of your version of this file only >+ * under the terms of either the GPL or the LGPL, and not to allow others to >+ * use your version of this file under the terms of the MPL, indicate your >+ * decision by deleting the provisions above and replace them with the notice >+ * and other provisions required by the GPL or the LGPL. If you do not delete >+ * the provisions above, a recipient may use your version of this file under >+ * the terms of any one of the MPL, the GPL or the LGPL. >+ * >+ * ***** END LICENSE BLOCK ***** */ >+/* >+** secutil.c - various functions used by security stuff >+** >+** This code comes from the NSS internal library used by the >+** the NSS security tools. >+** >+*/ >+ >+#include <prtypes.h> >+#include <prtime.h> >+#include <prlong.h> >+#include <prerror.h> >+#include <prprf.h> >+#include <plgetopt.h> >+#include <prenv.h> >+#include <prnetdb.h> >+ >+#include <cryptohi.h> >+#include <secpkcs7.h> >+#include <secpkcs5.h> >+#include <stdarg.h> >+ >+#include <sys/stat.h> >+#include <errno.h> >+ >+#include <unistd.h> >+ >+/* for SEC_TraverseNames */ >+#include <cert.h> >+#include <certt.h> >+#include <certdb.h> >+ >+#include <secmod.h> >+#include <pk11func.h> >+#include <secoid.h> >+ >+#include "secutil.h" >+ >+char * >+SECU_GetString(int16 error_number) >+{ >+ >+ static char errString[80]; >+ sprintf(errString, "Unknown error string (%d)", error_number); >+ return errString; >+} >+ >+void >+SECU_PrintErrMsg(FILE *out, int level, char *progName, char *msg, ...) >+{ >+ va_list args; >+ PRErrorCode err = PORT_GetError(); >+ const char * errString = SECU_Strerror(err); >+ >+ va_start(args, msg); >+ >+ SECU_Indent(out, level); >+ fprintf(out, "%s: ", progName); >+ vfprintf(out, msg, args); >+ if (errString != NULL && PORT_Strlen(errString) > 0) >+ fprintf(out, ": %s\n", errString); >+ else >+ fprintf(out, ": error %d\n", (int)err); >+ >+ va_end(args); >+} >+ >+void SECU_PrintError(char *progName, char *msg, ...) >+{ >+ SECU_PrintErrMsg(stderr, 0, progName, msg); >+} >+ >+#define INDENT_MULT 4 >+void >+SECU_Indent(FILE *out, int level) >+{ >+ int i; >+ >+ for (i = 0; i < level; i++) { >+ fprintf(out, " "); >+ } >+} >+ >+static void secu_Newline(FILE *out) >+{ >+ fprintf(out, "\n"); >+} >+ >+void >+SECU_PrintAsHex(FILE *out, SECItem *data, const char *m, int level) >+{ >+ unsigned i; >+ int column; >+ PRBool isString = PR_TRUE; >+ PRBool isWhiteSpace = PR_TRUE; >+ PRBool printedHex = PR_FALSE; >+ unsigned int limit = 15; >+ >+ if ( m ) { >+ SECU_Indent(out, level); fprintf(out, "%s:\n", m); >+ level++; >+ } >+ >+ SECU_Indent(out, level); column = level*INDENT_MULT; >+ if (!data->len) { >+ fprintf(out, "(empty)\n"); >+ return; >+ } >+ /* take a pass to see if it's all printable. */ >+ for (i = 0; i < data->len; i++) { >+ unsigned char val = data->data[i]; >+ if (!val || !isprint(val)) { >+ isString = PR_FALSE; >+ break; >+ } >+ if (isWhiteSpace && !isspace(val)) { >+ isWhiteSpace = PR_FALSE; >+ } >+ } >+ >+ /* Short values, such as bit strings (which are printed with this >+ ** function) often look like strings, but we want to see the bits. >+ ** so this test assures that short values will be printed in hex, >+ ** perhaps in addition to being printed as strings. >+ ** The threshold size (4 bytes) is arbitrary. >+ */ >+ if (!isString || data->len <= 4) { >+ for (i = 0; i < data->len; i++) { >+ if (i != data->len - 1) { >+ fprintf(out, "%02x:", data->data[i]); >+ column += 3; >+ } else { >+ fprintf(out, "%02x", data->data[i]); >+ column += 2; >+ break; >+ } >+ if (column > 76 || (i % 16 == limit)) { >+ secu_Newline(out); >+ SECU_Indent(out, level); >+ column = level*INDENT_MULT; >+ limit = i % 16; >+ } >+ } >+ printedHex = PR_TRUE; >+ } >+ if (isString && !isWhiteSpace) { >+ if (printedHex != PR_FALSE) { >+ secu_Newline(out); >+ SECU_Indent(out, level); column = level*INDENT_MULT; >+ } >+ for (i = 0; i < data->len; i++) { >+ unsigned char val = data->data[i]; >+ >+ if (val) { >+ fprintf(out,"%c",val); >+ column++; >+ } else { >+ column = 77; >+ } >+ if (column > 76) { >+ secu_Newline(out); >+ SECU_Indent(out, level); column = level*INDENT_MULT; >+ } >+ } >+ } >+ >+ if (column != level*INDENT_MULT) { >+ secu_Newline(out); >+ } >+} >+ >+/* This function does NOT expect a DER type and length. */ >+SECOidTag >+SECU_PrintObjectID(FILE *out, SECItem *oid, char *m, int level) >+{ >+ SECOidData *oiddata; >+ char * oidString = NULL; >+ >+ oiddata = SECOID_FindOID(oid); >+ if (oiddata != NULL) { >+ const char *name = oiddata->desc; >+ SECU_Indent(out, level); >+ if (m != NULL) >+ fprintf(out, "%s: ", m); >+ fprintf(out, "%s\n", name); >+ return oiddata->offset; >+ } >+ oidString = CERT_GetOidString(oid); >+ if (oidString) { >+ SECU_Indent(out, level); >+ if (m != NULL) >+ fprintf(out, "%s: ", m); >+ fprintf(out, "%s\n", oidString); >+ PR_smprintf_free(oidString); >+ return SEC_OID_UNKNOWN; >+ } >+ SECU_PrintAsHex(out, oid, m, level); >+ return SEC_OID_UNKNOWN; >+} >+ >+ >+void >+SECU_PrintSystemError(char *progName, char *msg, ...) >+{ >+ va_list args; >+ >+ va_start(args, msg); >+ fprintf(stderr, "%s: ", progName); >+ vfprintf(stderr, msg, args); >+ fprintf(stderr, ": %s\n", strerror(errno)); >+ va_end(args); >+} >+ >+SECStatus >+secu_StdinToItem(SECItem *dst) >+{ >+ unsigned char buf[1000]; >+ PRInt32 numBytes; >+ PRBool notDone = PR_TRUE; >+ >+ dst->len = 0; >+ dst->data = NULL; >+ >+ while (notDone) { >+ numBytes = PR_Read(PR_STDIN, buf, sizeof(buf)); >+ >+ if (numBytes < 0) { >+ return SECFailure; >+ } >+ >+ if (numBytes == 0) >+ break; >+ >+ if (dst->data) { >+ unsigned char * p = dst->data; >+ dst->data = (unsigned char*)PORT_Realloc(p, dst->len + numBytes); >+ if (!dst->data) { >+ PORT_Free(p); >+ } >+ } else { >+ dst->data = (unsigned char*)PORT_Alloc(numBytes); >+ } >+ if (!dst->data) { >+ return SECFailure; >+ } >+ PORT_Memcpy(dst->data + dst->len, buf, numBytes); >+ dst->len += numBytes; >+ } >+ >+ return SECSuccess; >+} >+ >+SECStatus >+SECU_FileToItem(SECItem *dst, PRFileDesc *src) >+{ >+ PRFileInfo info; >+ PRInt32 numBytes; >+ PRStatus prStatus; >+ >+ if (src == PR_STDIN) >+ return secu_StdinToItem(dst); >+ >+ prStatus = PR_GetOpenFileInfo(src, &info); >+ >+ if (prStatus != PR_SUCCESS) { >+ PORT_SetError(SEC_ERROR_IO); >+ return SECFailure; >+ } >+ >+ /* XXX workaround for 3.1, not all utils zero dst before sending */ >+ dst->data = 0; >+ if (!SECITEM_AllocItem(NULL, dst, info.size)) >+ goto loser; >+ >+ numBytes = PR_Read(src, dst->data, info.size); >+ if (numBytes != info.size) { >+ PORT_SetError(SEC_ERROR_IO); >+ goto loser; >+ } >+ >+ return SECSuccess; >+loser: >+ SECITEM_FreeItem(dst, PR_FALSE); >+ dst->data = NULL; >+ return SECFailure; >+} >+ >+SECStatus >+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii) >+{ >+ SECStatus rv; >+ if (ascii) { >+ /* First convert ascii to binary */ >+ SECItem filedata; >+ char *asc, *body; >+ >+ /* Read in ascii data */ >+ rv = SECU_FileToItem(&filedata, inFile); >+ asc = (char *)filedata.data; >+ if (!asc) { >+ fprintf(stderr, "unable to read data from input file\n"); >+ return SECFailure; >+ } >+ >+ /* check for headers and trailers and remove them */ >+ if ((body = strstr(asc, "-----BEGIN")) != NULL) { >+ char *trailer = NULL; >+ asc = body; >+ body = PORT_Strchr(body, '\n'); >+ if (!body) >+ body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */ >+ if (body) >+ trailer = strstr(++body, "-----END"); >+ if (trailer != NULL) { >+ *trailer = '\0'; >+ } else { >+ fprintf(stderr, "input has header but no trailer\n"); >+ PORT_Free(filedata.data); >+ return SECFailure; >+ } >+ } else { >+ body = asc; >+ } >+ >+ /* Convert to binary */ >+ rv = ATOB_ConvertAsciiToItem(der, body); >+ if (rv) { >+ fprintf(stderr, "error converting ascii to binary (%d)\n", >+ PORT_GetError()); >+ PORT_Free(filedata.data); >+ return SECFailure; >+ } >+ >+ PORT_Free(filedata.data); >+ } else { >+ /* Read in binary der */ >+ rv = SECU_FileToItem(der, inFile); >+ if (rv) { >+ fprintf(stderr, "error converting der (%d)\n", >+ PORT_GetError()); >+ return SECFailure; >+ } >+ } >+ return SECSuccess; >+} >+ >+/* Encodes and adds extensions to the CRL or CRL entries. */ >+SECStatus >+SECU_EncodeAndAddExtensionValue(PRArenaPool *arena, void *extHandle, >+ void *value, PRBool criticality, int extenType, >+ EXTEN_EXT_VALUE_ENCODER EncodeValueFn) >+{ >+ SECItem encodedValue; >+ SECStatus rv; >+ >+ encodedValue.data = NULL; >+ encodedValue.len = 0; >+ do { >+ rv = (*EncodeValueFn)(arena, value, &encodedValue); >+ if (rv != SECSuccess) >+ break; >+ >+ rv = CERT_AddExtension(extHandle, extenType, &encodedValue, >+ criticality, PR_TRUE); >+ if (rv != SECSuccess) >+ break; >+ >+ } while (0); >+ >+ return (rv); >+} >+ >+/* Caller ensures that dst is at least item->len*2+1 bytes long */ >+void >+SECU_SECItemToHex(const SECItem * item, char * dst) >+{ >+ if (dst && item && item->data) { >+ unsigned char * src = item->data; >+ unsigned int len = item->len; >+ for (; len > 0; --len, dst += 2) { >+ sprintf(dst, "%02x", *src++); >+ } >+ *dst = '\0'; >+ } >+} >+ >+static unsigned char nibble(char c) { >+ c = PORT_Tolower(c); >+ return ( c >= '0' && c <= '9') ? c - '0' : >+ ( c >= 'a' && c <= 'f') ? c - 'a' +10 : -1; >+} >+ >+SECStatus >+SECU_SECItemHexStringToBinary(SECItem* srcdest) >+{ >+ int i; >+ >+ if (!srcdest) { >+ PORT_SetError(SEC_ERROR_INVALID_ARGS); >+ return SECFailure; >+ } >+ if (srcdest->len < 4 || (srcdest->len % 2) ) { >+ /* too short to convert, or even number of characters */ >+ PORT_SetError(SEC_ERROR_BAD_DATA); >+ return SECFailure; >+ } >+ if (PORT_Strncasecmp((const char*)srcdest->data, "0x", 2)) { >+ /* wrong prefix */ >+ PORT_SetError(SEC_ERROR_BAD_DATA); >+ return SECFailure; >+ } >+ >+ /* 1st pass to check for hex characters */ >+ for (i=2; i<srcdest->len; i++) { >+ char c = PORT_Tolower(srcdest->data[i]); >+ if (! ( ( c >= '0' && c <= '9') || >+ ( c >= 'a' && c <= 'f') >+ ) ) { >+ PORT_SetError(SEC_ERROR_BAD_DATA); >+ return SECFailure; >+ } >+ } >+ >+ /* 2nd pass to convert */ >+ for (i=2; i<srcdest->len; i+=2) { >+ srcdest->data[(i-2)/2] = (nibble(srcdest->data[i]) << 4) + >+ nibble(srcdest->data[i+1]); >+ } >+ >+ /* adjust length */ >+ srcdest->len -= 2; >+ srcdest->len /= 2; >+ return SECSuccess; >+} >+ >Index: devel/secutil.h >=================================================================== >RCS file: devel/secutil.h >diff -N devel/secutil.h >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ devel/secutil.h 3 May 2008 22:54:55 -0000 1.2 >@@ -0,0 +1,460 @@ >+/* ***** BEGIN LICENSE BLOCK ***** >+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 >+ * >+ * The contents of this file are subject to the Mozilla Public License Version >+ * 1.1 (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * http://www.mozilla.org/MPL/ >+ * >+ * Software distributed under the License is distributed on an "AS IS" basis, >+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License >+ * for the specific language governing rights and limitations under the >+ * License. >+ * >+ * The Original Code is the Netscape security libraries. >+ * >+ * The Initial Developer of the Original Code is >+ * Netscape Communications Corporation. >+ * Portions created by the Initial Developer are Copyright (C) 1994-2000 >+ * the Initial Developer. All Rights Reserved. >+ * >+ * Contributor(s): >+ * >+ * Alternatively, the contents of this file may be used under the terms of >+ * either the GNU General Public License Version 2 or later (the "GPL"), or >+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), >+ * in which case the provisions of the GPL or the LGPL are applicable instead >+ * of those above. If you wish to allow use of your version of this file only >+ * under the terms of either the GPL or the LGPL, and not to allow others to >+ * use your version of this file under the terms of the MPL, indicate your >+ * decision by deleting the provisions above and replace them with the notice >+ * and other provisions required by the GPL or the LGPL. If you do not delete >+ * the provisions above, a recipient may use your version of this file under >+ * the terms of any one of the MPL, the GPL or the LGPL. >+ * >+ * ***** END LICENSE BLOCK ***** */ >+#ifndef _SEC_UTIL_H_ >+#define _SEC_UTIL_H_ >+ >+#include <seccomon.h> >+#include <secitem.h> >+#include <prerror.h> >+#include <base64.h> >+#include <key.h> >+#include <secpkcs7.h> >+#include <secasn1.h> >+#include <secder.h> >+#include <stdio.h> >+ >+#define SEC_CT_PRIVATE_KEY "private-key" >+#define SEC_CT_PUBLIC_KEY "public-key" >+#define SEC_CT_CERTIFICATE "certificate" >+#define SEC_CT_CERTIFICATE_REQUEST "certificate-request" >+#define SEC_CT_PKCS7 "pkcs7" >+#define SEC_CT_CRL "crl" >+ >+#define NS_CERTREQ_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----" >+#define NS_CERTREQ_TRAILER "-----END NEW CERTIFICATE REQUEST-----" >+ >+#define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----" >+#define NS_CERT_TRAILER "-----END CERTIFICATE-----" >+ >+#define NS_CRL_HEADER "-----BEGIN CRL-----" >+#define NS_CRL_TRAILER "-----END CRL-----" >+ >+/* From libsec/pcertdb.c --- it's not declared in sec.h */ >+extern SECStatus SEC_AddPermCertificate(CERTCertDBHandle *handle, >+ SECItem *derCert, char *nickname, CERTCertTrust *trust); >+ >+ >+#ifdef SECUTIL_NEW >+typedef int (*SECU_PPFunc)(PRFileDesc *out, SECItem *item, >+ char *msg, int level); >+#else >+typedef int (*SECU_PPFunc)(FILE *out, SECItem *item, char *msg, int level); >+#endif >+ >+typedef struct { >+ enum { >+ PW_NONE = 0, >+ PW_FROMFILE = 1, >+ PW_PLAINTEXT = 2, >+ PW_EXTERNAL = 3 >+ } source; >+ char *data; >+} secuPWData; >+ >+/* >+** Change a password on a token, or initialize a token with a password >+** if it does not already have one. >+** Use passwd to send the password in plaintext, pwFile to specify a >+** file containing the password, or NULL for both to prompt the user. >+*/ >+SECStatus SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile); >+ >+/* >+** Change a password on a token, or initialize a token with a password >+** if it does not already have one. >+** In this function, you can specify both the old and new passwords >+** as either a string or file. NOTE: any you don't specify will >+** be prompted for >+*/ >+SECStatus SECU_ChangePW2(PK11SlotInfo *slot, char *oldPass, char *newPass, >+ char *oldPwFile, char *newPwFile); >+ >+/* These were stolen from the old sec.h... */ >+/* >+** Check a password for legitimacy. Passwords must be at least 8 >+** characters long and contain one non-alphabetic. Return DSTrue if the >+** password is ok, DSFalse otherwise. >+*/ >+extern PRBool SEC_CheckPassword(char *password); >+ >+/* >+** Blind check of a password. Complement to SEC_CheckPassword which >+** ignores length and content type, just retuning DSTrue is the password >+** exists, DSFalse if NULL >+*/ >+extern PRBool SEC_BlindCheckPassword(char *password); >+ >+/* >+** Get a password. >+** First prompt with "msg" on "out", then read the password from "in". >+** The password is then checked using "chkpw". >+*/ >+extern char *SEC_GetPassword(FILE *in, FILE *out, char *msg, >+ PRBool (*chkpw)(char *)); >+ >+char *SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg); >+ >+char *SECU_GetPasswordString(void *arg, char *prompt); >+ >+/* >+** Write a dongle password. >+** Uses MD5 to hash constant system data (hostname, etc.), and then >+** creates RC4 key to encrypt a password "pw" into a file "fd". >+*/ >+extern SECStatus SEC_WriteDongleFile(int fd, char *pw); >+ >+/* >+** Get a dongle password. >+** Uses MD5 to hash constant system data (hostname, etc.), and then >+** creates RC4 key to decrypt and return a password from file "fd". >+*/ >+extern char *SEC_ReadDongleFile(int fd); >+ >+ >+/* End stolen headers */ >+ >+/* Just sticks the two strings together with a / if needed */ >+char *SECU_AppendFilenameToDir(char *dir, char *filename); >+ >+/* Returns result of getenv("SSL_DIR") or NULL */ >+extern char *SECU_DefaultSSLDir(void); >+ >+/* >+** Should be called once during initialization to set the default >+** directory for looking for cert.db, key.db, and cert-nameidx.db files >+** Removes trailing '/' in 'base' >+** If 'base' is NULL, defaults to set to .netscape in home directory. >+*/ >+extern char *SECU_ConfigDirectory(const char* base); >+ >+/* >+** Basic callback function for SSL_GetClientAuthDataHook >+*/ >+extern int >+SECU_GetClientAuthData(void *arg, PRFileDesc *fd, >+ struct CERTDistNamesStr *caNames, >+ struct CERTCertificateStr **pRetCert, >+ struct SECKEYPrivateKeyStr **pRetKey); >+ >+/* print out an error message */ >+extern void SECU_PrintError(char *progName, char *msg, ...); >+ >+/* print out a system error message */ >+extern void SECU_PrintSystemError(char *progName, char *msg, ...); >+ >+/* Return informative error string */ >+extern const char * SECU_Strerror(PRErrorCode errNum); >+ >+/* revalidate the cert and print information about cert verification >+ * failure at time == now */ >+extern void >+SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle, >+ CERTCertificate *cert, PRBool checksig, >+ SECCertificateUsage certUsage, void *pinArg, PRBool verbose); >+ >+/* revalidate the cert and print information about cert verification >+ * failure at specified time */ >+extern void >+SECU_printCertProblemsOnDate(FILE *outfile, CERTCertDBHandle *handle, >+ CERTCertificate *cert, PRBool checksig, SECCertificateUsage certUsage, >+ void *pinArg, PRBool verbose, PRTime datetime); >+ >+/* print out CERTVerifyLog info. */ >+extern void >+SECU_displayVerifyLog(FILE *outfile, CERTVerifyLog *log, >+ PRBool verbose); >+ >+/* Read the contents of a file into a SECItem */ >+extern SECStatus SECU_FileToItem(SECItem *dst, PRFileDesc *src); >+extern SECStatus SECU_TextFileToItem(SECItem *dst, PRFileDesc *src); >+ >+/* Read in a DER from a file, may be ascii */ >+extern SECStatus >+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii); >+ >+/* Indent based on "level" */ >+extern void SECU_Indent(FILE *out, int level); >+ >+/* Print integer value and hex */ >+extern void SECU_PrintInteger(FILE *out, SECItem *i, char *m, int level); >+ >+/* Print ObjectIdentifier symbolically */ >+extern SECOidTag SECU_PrintObjectID(FILE *out, SECItem *oid, char *m, int level); >+ >+/* Print AlgorithmIdentifier symbolically */ >+extern void SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m, >+ int level); >+ >+/* Print SECItem as hex */ >+extern void SECU_PrintAsHex(FILE *out, SECItem *i, const char *m, int level); >+ >+/* dump a buffer in hex and ASCII */ >+extern void SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len); >+ >+/* >+ * Format and print the UTC Time "t". If the tag message "m" is not NULL, >+ * do indent formatting based on "level" and add a newline afterward; >+ * otherwise just print the formatted time string only. >+ */ >+extern void SECU_PrintUTCTime(FILE *out, SECItem *t, char *m, int level); >+ >+/* >+ * Format and print the Generalized Time "t". If the tag message "m" >+ * is not NULL, * do indent formatting based on "level" and add a newline >+ * afterward; otherwise just print the formatted time string only. >+ */ >+extern void SECU_PrintGeneralizedTime(FILE *out, SECItem *t, char *m, >+ int level); >+ >+/* >+ * Format and print the UTC or Generalized Time "t". If the tag message >+ * "m" is not NULL, do indent formatting based on "level" and add a newline >+ * afterward; otherwise just print the formatted time string only. >+ */ >+extern void SECU_PrintTimeChoice(FILE *out, SECItem *t, char *m, int level); >+ >+/* callback for listing certs through pkcs11 */ >+extern SECStatus SECU_PrintCertNickname(CERTCertListNode* cert, void *data); >+ >+/* Dump all certificate nicknames in a database */ >+extern SECStatus >+SECU_PrintCertificateNames(CERTCertDBHandle *handle, PRFileDesc* out, >+ PRBool sortByName, PRBool sortByTrust); >+ >+/* See if nickname already in database. Return 1 true, 0 false, -1 error */ >+int SECU_CheckCertNameExists(CERTCertDBHandle *handle, char *nickname); >+ >+/* Dump contents of cert req */ >+extern int SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m, >+ int level); >+ >+/* Dump contents of certificate */ >+extern int SECU_PrintCertificate(FILE *out, SECItem *der, char *m, int level); >+ >+/* print trust flags on a cert */ >+extern void SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, >+ int level); >+ >+/* Dump contents of an RSA public key */ >+extern int SECU_PrintRSAPublicKey(FILE *out, SECItem *der, char *m, int level); >+ >+extern int SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m, >+ int level); >+ >+#ifdef HAVE_EPV_TEMPLATE >+/* Dump contents of private key */ >+extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level); >+#endif >+ >+/* Print the MD5 and SHA1 fingerprints of a cert */ >+extern int SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, >+ int level); >+ >+/* Pretty-print any PKCS7 thing */ >+extern int SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, >+ int level); >+ >+/* Init PKCS11 stuff */ >+extern SECStatus SECU_PKCS11Init(PRBool readOnly); >+ >+/* Dump contents of signed data */ >+extern int SECU_PrintSignedData(FILE *out, SECItem *der, char *m, int level, >+ SECU_PPFunc inner); >+ >+/* Print cert data and its trust flags */ >+extern SECStatus SEC_PrintCertificateAndTrust(CERTCertificate *cert, >+ const char *label, >+ CERTCertTrust *trust); >+ >+extern int SECU_PrintCrl(FILE *out, SECItem *der, char *m, int level); >+ >+extern void >+SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level); >+ >+extern void SECU_PrintString(FILE *out, SECItem *si, char *m, int level); >+extern void SECU_PrintAny(FILE *out, SECItem *i, char *m, int level); >+ >+extern void SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level); >+extern void SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value, >+ char *msg, int level); >+ >+extern void SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions, >+ char *msg, int level); >+ >+extern void SECU_PrintName(FILE *out, CERTName *name, char *msg, int level); >+ >+#ifdef SECU_GetPassword >+/* Convert a High public Key to a Low public Key */ >+extern SECKEYLowPublicKey *SECU_ConvHighToLow(SECKEYPublicKey *pubHighKey); >+#endif >+ >+extern char *SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg); >+ >+extern SECStatus DER_PrettyPrint(FILE *out, SECItem *it, PRBool raw); >+extern void SEC_Init(void); >+ >+extern char *SECU_SECModDBName(void); >+ >+extern void SECU_PrintPRandOSError(char *progName); >+ >+extern SECStatus SECU_RegisterDynamicOids(void); >+ >+/* Identifies hash algorithm tag by its string representation. */ >+extern SECOidTag SECU_StringToSignatureAlgTag(const char *alg); >+ >+/* Store CRL in output file or pk11 db. Also >+ * encodes with base64 and exports to file if ascii flag is set >+ * and file is not NULL. */ >+extern SECStatus SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl, >+ PRFileDesc *outFile, PRBool ascii, char *url); >+ >+ >+/* >+** DER sign a single block of data using private key encryption and the >+** MD5 hashing algorithm. This routine first computes a digital signature >+** using SEC_SignData, then wraps it with an CERTSignedData and then der >+** encodes the result. >+** "arena" is the memory arena to use to allocate data from >+** "sd" returned CERTSignedData >+** "result" the final der encoded data (memory is allocated) >+** "buf" the input data to sign >+** "len" the amount of data to sign >+** "pk" the private key to encrypt with >+*/ >+extern SECStatus SECU_DerSignDataCRL(PRArenaPool *arena, CERTSignedData *sd, >+ unsigned char *buf, int len, >+ SECKEYPrivateKey *pk, SECOidTag algID); >+ >+typedef enum { >+ noKeyFound = 1, >+ noSignatureMatch = 2, >+ failToEncode = 3, >+ failToSign = 4, >+ noMem = 5 >+} SignAndEncodeFuncExitStat; >+ >+extern SECStatus >+SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl, >+ SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode); >+ >+extern SECStatus >+SECU_CopyCRL(PRArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl); >+ >+/* >+** Finds the crl Authority Key Id extension. Returns NULL if no such extension >+** was found. >+*/ >+CERTAuthKeyID * >+SECU_FindCRLAuthKeyIDExten (PRArenaPool *arena, CERTSignedCrl *crl); >+ >+/* >+ * Find the issuer of a crl. Cert usage should be checked before signing a crl. >+ */ >+CERTCertificate * >+SECU_FindCrlIssuer(CERTCertDBHandle *dbHandle, SECItem* subject, >+ CERTAuthKeyID* id, PRTime validTime); >+ >+ >+/* call back function used in encoding of an extension. Called from >+ * SECU_EncodeAndAddExtensionValue */ >+typedef SECStatus (* EXTEN_EXT_VALUE_ENCODER) (PRArenaPool *extHandleArena, >+ void *value, SECItem *encodedValue); >+ >+/* Encodes and adds extensions to the CRL or CRL entries. */ >+SECStatus >+SECU_EncodeAndAddExtensionValue(PRArenaPool *arena, void *extHandle, >+ void *value, PRBool criticality, int extenType, >+ EXTEN_EXT_VALUE_ENCODER EncodeValueFn); >+ >+/* Caller ensures that dst is at least item->len*2+1 bytes long */ >+void >+SECU_SECItemToHex(const SECItem * item, char * dst); >+ >+/* Requires 0x prefix. Case-insensitive. Will do in-place replacement if >+ * successful */ >+SECStatus >+SECU_SECItemHexStringToBinary(SECItem* srcdest); >+ >+/* >+ * >+ * Utilities for parsing security tools command lines >+ * >+ */ >+ >+/* A single command flag */ >+typedef struct { >+ char flag; >+ PRBool needsArg; >+ char *arg; >+ PRBool activated; >+ char *longform; >+} secuCommandFlag; >+ >+/* A full array of command/option flags */ >+typedef struct >+{ >+ int numCommands; >+ int numOptions; >+ >+ secuCommandFlag *commands; >+ secuCommandFlag *options; >+} secuCommand; >+ >+/* fill the "arg" and "activated" fields for each flag */ >+SECStatus >+SECU_ParseCommandLine(int argc, char **argv, char *progName, >+ const secuCommand *cmd); >+char * >+SECU_GetOptionArg(const secuCommand *cmd, int optionNum); >+ >+/* >+ * >+ * Error messaging >+ * >+ */ >+ >+/* Return informative error string */ >+char *SECU_ErrorString(int16 err); >+ >+/* Return informative error string. Does not call XP_GetString */ >+char *SECU_ErrorStringRaw(int16 err); >+ >+void printflags(char *trusts, unsigned int flags); >+ >+#include <secerr.h> >+#include <sslerr.h> >+ >+#endif /* _SEC_UTIL_H_ */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 346731
:
299417
|
299418
|
299429
|
299430
|
299432
|
304057
|
304280
|
304281
|
304282
|
304284
|
304285
|
304286
|
304287
|
304288
|
304289
|
304290
|
305047
|
305048
|
308356
|
320816
|
320817
|
320818
|
320819
|
320820
|
320821
|
320822
|
320823
|
321049
|
321051
|
321681
|
321682
|
321683
|
321684