ocspclnt.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,221 行 · 第 1/3 页

C
1,221
字号
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//* * Test program for client-side OCSP. * * $Id: ocspclnt.c,v 1.1 2000/03/31 20:09:29 relyea%netscape.com Exp $ */#include "secutil.h"#include "nspr.h"#include "plgetopt.h"#include "nss.h"#include "cert.h"#include "ocsp.h"#include "xconst.h"	/*			 * XXX internal header file; needed to get at			 * cert_DecodeAuthInfoAccessExtension -- would be			 * nice to not need this, but that would require			 * better/different APIs.			 */#ifndef NO_PP		/*			 * Compile with this every once in a while to be			 * sure that no dependencies on it get added			 * outside of the pretty-printing routines.			 */#include "ocspti.h"	/* internals for pretty-printing routines *only* */#endif	/* NO_PP */#define DEFAULT_DB_DIR	"~/.netscape"static voidsynopsis (char *program_name){    PRFileDesc *pr_stderr;    pr_stderr = PR_STDERR;    PR_fprintf (pr_stderr, "Usage:");    PR_fprintf (pr_stderr,		"\t%s -p [-d <dir>]\n",		program_name);    PR_fprintf (pr_stderr,		"\t%s -P [-d <dir>]\n",		program_name);    PR_fprintf (pr_stderr,		"\t%s -r <name> [-L] [-s <name>] [-d <dir>]\n",		program_name);    PR_fprintf (pr_stderr,		"\t%s -R <name> [-l <location>] [-s <name>] [-d <dir>]\n",		program_name);    PR_fprintf (pr_stderr,		"\t%s -S <name> [-l <location> -t <name>]\n",		program_name);    PR_fprintf (pr_stderr,		"\t\t [-s <name>] [-w <time>] [-d <dir>]\n");    PR_fprintf (pr_stderr,		"\t%s -V <name> -u <usage> [-l <location> -t <name>]\n",		program_name);    PR_fprintf (pr_stderr,		"\t\t [-s <name>] [-w <time>] [-d <dir>]\n");}static voidshort_usage (char *program_name){    PR_fprintf (PR_STDERR,		"Type %s -H for more detailed descriptions\n",		program_name);    synopsis (program_name);}static voidlong_usage (char *program_name){    PRFileDesc *pr_stderr;    pr_stderr = PR_STDERR;    synopsis (program_name);    PR_fprintf (pr_stderr, "\nCommands (must specify exactly one):\n");    PR_fprintf (pr_stderr,		"  %-13s Pretty-print a binary request read from stdin\n",		"-p");    PR_fprintf (pr_stderr,		"  %-13s Pretty-print a binary response read from stdin\n",		"-P");    PR_fprintf (pr_stderr,		"  %-13s Create a request for cert \"nickname\" on stdout\n",		"-r nickname");    PR_fprintf (pr_stderr,		"  %-13s Get response for cert \"nickname\", dump to stdout\n",		"-R nickname");    PR_fprintf (pr_stderr,		"  %-13s Get status for cert \"nickname\"\n",		"-S nickname");    PR_fprintf (pr_stderr,		"  %-13s Fully verify cert \"nickname\", w/ status check\n",		"-V nickname");    PR_fprintf (pr_stderr, "Options:\n");    PR_fprintf (pr_stderr,		"  %-13s Add the service locator extension to the request\n",		"-L");    PR_fprintf (pr_stderr,		"  %-13s Find security databases in \"dbdir\" (default %s)\n",		"-d dbdir", DEFAULT_DB_DIR);    PR_fprintf (pr_stderr,		"  %-13s Use \"location\" as URL of responder\n",		"-l location");    PR_fprintf (pr_stderr,		"  %-13s Trust cert \"nickname\" as response signer\n",		"-t nickname");    PR_fprintf (pr_stderr,		"  %-13s Sign requests with cert \"nickname\"\n",		"-s nickname");    PR_fprintf (pr_stderr,		"  %-13s Type of certificate usage for verification:\n",		"-u usage");    PR_fprintf (pr_stderr,		"%-17s c   SSL Client\n", "");    PR_fprintf (pr_stderr,		"%-17s s   SSL Server\n", "");    PR_fprintf (pr_stderr,		"%-17s e   Email Recipient\n", "");    PR_fprintf (pr_stderr,		"%-17s E   Email Signer\n", "");    PR_fprintf (pr_stderr,		"%-17s S   Object Signer\n", "");    PR_fprintf (pr_stderr,		"%-17s C   CA\n", "");    PR_fprintf (pr_stderr,		"  %-13s Validity time (default current time), one of:\n",		"-w time");    PR_fprintf (pr_stderr,		"%-17s %-25s (GMT)\n", "", "YYMMDDhhmm[ss]Z");    PR_fprintf (pr_stderr,		"%-17s %-25s (later than GMT)\n", "", "YYMMDDhhmm[ss]+hhmm");    PR_fprintf (pr_stderr,		"%-17s %-25s (earlier than GMT)\n", "", "YYMMDDhhmm[ss]-hhmm");}/* * XXX This is a generic function that would probably make a good * replacement for SECU_DER_Read (which is not at all specific to DER, * despite its name), but that requires fixing all of the tools... * Still, it should be done, whenenver I/somebody has the time. * (Also, consider whether this actually belongs in the security * library itself, not just in the command library.) * * This function takes an open file (a PRFileDesc *) and reads the * entire file into a SECItem.  (Obviously, the file is intended to * be small enough that such a thing is advisable.)  Both the SECItem * and the buffer it points to are allocated from the heap; the caller * is expected to free them.  ("SECITEM_FreeItem(item, PR_TRUE)") */static SECItem *read_file_into_item (PRFileDesc *in_file, SECItemType si_type){    PRStatus	 prv;    SECItem 	*item;    PRFileInfo	 file_info;    PRInt32	 bytes_read;    prv = PR_GetOpenFileInfo (in_file, &file_info);    if (prv != PR_SUCCESS)	return NULL;    if (file_info.size ==  0) {	/* XXX Need a better error; just grabbed this one for expediency. */	PORT_SetError (SEC_ERROR_INPUT_LEN);	return NULL;    }    if (file_info.size > 0xffff) {	/* I think this is too big. */	PORT_SetError (SEC_ERROR_NO_MEMORY);	return NULL;    }    item = PORT_Alloc (sizeof (SECItem));    if (item == NULL)	return NULL;    item->type = si_type;    item->len = (unsigned int) file_info.size;    item->data = PORT_Alloc ((size_t)item->len);    if (item->data == NULL)	goto loser;    bytes_read = PR_Read (in_file, item->data, (PRInt32) item->len);    if (bytes_read < 0) {	/* Something went wrong; error is already set for us. */	goto loser;    } else if (bytes_read == 0) {	/* Something went wrong; we read nothing.  But no system/nspr error. */	/* XXX Need to set an error here. */	goto loser;    } else if (item->len != (unsigned int)bytes_read) {	/* Something went wrong; we read less (or more!?) than we expected. */	/* XXX Need to set an error here. */	goto loser;    }    return item;loser:    SECITEM_FreeItem (item, PR_TRUE);    return NULL;}/* * Create a DER-encoded OCSP request (for the certificate whose nickname * is "name") and dump it out. */static SECStatuscreate_request (FILE *out_file, CERTCertDBHandle *handle, const char *cert_name,		PRBool add_service_locator, PRBool add_acceptable_responses){    CERTCertificate *cert = NULL;    CERTCertList *certs = NULL;    CERTOCSPRequest *request = NULL;    int64 now = PR_Now();    SECItem *encoding = NULL;    SECStatus rv = SECFailure;    if (handle == NULL || cert_name == NULL)	goto loser;    cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) cert_name);    if (cert == NULL)	goto loser;    /*     * We need to create a list of one.     */    certs = CERT_NewCertList();    if (certs == NULL)	goto loser;    if (CERT_AddCertToListTail (certs, cert) != SECSuccess)	goto loser;    /*     * Now that cert is included in the list, we need to be careful     * that we do not try to destroy it twice.  This will prevent that.     */    cert = NULL;    request = CERT_CreateOCSPRequest (certs, now, add_service_locator, NULL);    if (request == NULL)	goto loser;    if (add_acceptable_responses) {	rv = CERT_AddOCSPAcceptableResponses(request,					     SEC_OID_PKIX_OCSP_BASIC_RESPONSE);	if (rv != SECSuccess)	    goto loser;    }    encoding = CERT_EncodeOCSPRequest (NULL, request, NULL);    if (encoding == NULL)	goto loser;    if (fwrite (encoding->data, encoding->len, 1, out_file) != 1)	goto loser;    rv = SECSuccess;loser:    if (encoding != NULL)	SECITEM_FreeItem(encoding, PR_TRUE);    if (request != NULL)	CERT_DestroyOCSPRequest(request);    if (certs != NULL)	CERT_DestroyCertList (certs);    if (cert != NULL)	CERT_DestroyCertificate (cert);    return rv;}/* * Create a DER-encoded OCSP request (for the certificate whose nickname is * "cert_name"), then get and dump a corresponding response.  The responder * location is either specified explicitly (as "responder_url") or found * via the AuthorityInfoAccess URL in the cert. */static SECStatusdump_response (FILE *out_file, CERTCertDBHandle *handle, const char *cert_name,	       const char *responder_url){    CERTCertificate *cert = NULL;    CERTCertList *certs = NULL;    char *loc = NULL;    int64 now = PR_Now();    SECItem *response = NULL;    SECStatus rv = SECFailure;    PRBool includeServiceLocator;    if (handle == NULL || cert_name == NULL)	goto loser;    cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) cert_name);    if (cert == NULL)	goto loser;    if (responder_url != NULL) {	loc = (char *) responder_url;	includeServiceLocator = PR_TRUE;    } else {	loc = CERT_GetOCSPAuthorityInfoAccessLocation (cert);	if (loc == NULL)	    goto loser;	includeServiceLocator = PR_FALSE;    }    /*     * We need to create a list of one.     */    certs = CERT_NewCertList();    if (certs == NULL)	goto loser;    if (CERT_AddCertToListTail (certs, cert) != SECSuccess)	goto loser;    /*     * Now that cert is included in the list, we need to be careful     * that we do not try to destroy it twice.  This will prevent that.     */    cert = NULL;    response = CERT_GetEncodedOCSPResponse (NULL, certs, loc, now,					    includeServiceLocator,					    NULL, NULL, NULL);    if (response == NULL)	goto loser;    if (fwrite (response->data, response->len, 1, out_file) != 1)	goto loser;    rv = SECSuccess;loser:    if (response != NULL)	SECITEM_FreeItem (response, PR_TRUE);    if (certs != NULL)	CERT_DestroyCertList (certs);    if (loc != NULL && loc != responder_url)	PORT_Free (loc);    if (cert != NULL)	CERT_DestroyCertificate (cert);    return rv;}/* * Get the status for the specified certificate (whose nickname is "cert_name"). * Directly use the OCSP function rather than doing a full verification. */static SECStatusget_cert_status (FILE *out_file, CERTCertDBHandle *handle,		 const char *cert_name, int64 verify_time){    CERTCertificate *cert = NULL;    SECStatus rv = SECFailure;    if (handle == NULL || cert_name == NULL)	goto loser;    cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) cert_name);    if (cert == NULL)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?