import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,49 @@
#! gmake
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
include config.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
export:: private_export

View file

@ -0,0 +1,829 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
** secutil.c - various functions used by security stuff
**
*/
#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 "basicutil.h"
#include <stdarg.h>
#include <sys/stat.h>
#include <errno.h>
#ifdef XP_UNIX
#include <unistd.h>
#endif
#include "secoid.h"
#include "sslt.h"
extern long DER_GetInteger(const SECItem *src);
static PRBool wrapEnabled = PR_TRUE;
void
SECU_EnableWrap(PRBool enable)
{
wrapEnabled = enable;
}
PRBool
SECU_GetWrapEnabled(void)
{
return wrapEnabled;
}
void
SECU_PrintErrMsg(FILE *out, int level, const char *progName, const char *msg,
...)
{
va_list args;
PRErrorCode err = PORT_GetError();
const char *errString = PORT_ErrorToString(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(const char *progName, const char *msg, ...)
{
va_list args;
PRErrorCode err = PORT_GetError();
const char *errName = PR_ErrorToName(err);
const char *errString = PR_ErrorToString(err, 0);
va_start(args, msg);
fprintf(stderr, "%s: ", progName);
vfprintf(stderr, msg, args);
if (errName != NULL) {
fprintf(stderr, ": %s", errName);
} else {
fprintf(stderr, ": error %d", (int)err);
}
if (errString != NULL && PORT_Strlen(errString) > 0)
fprintf(stderr, ": %s\n", errString);
va_end(args);
}
void
SECU_PrintSystemError(const char *progName, const 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_TextFileToItem(SECItem *dst, PRFileDesc *src)
{
PRFileInfo info;
PRInt32 numBytes;
PRStatus prStatus;
unsigned char *buf;
if (src == PR_STDIN)
return secu_StdinToItem(dst);
prStatus = PR_GetOpenFileInfo(src, &info);
if (prStatus != PR_SUCCESS) {
PORT_SetError(SEC_ERROR_IO);
return SECFailure;
}
buf = (unsigned char *)PORT_Alloc(info.size);
if (!buf)
return SECFailure;
numBytes = PR_Read(src, buf, info.size);
if (numBytes != info.size) {
PORT_SetError(SEC_ERROR_IO);
goto loser;
}
if (buf[numBytes - 1] == '\n')
numBytes--;
#ifdef _WINDOWS
if (buf[numBytes - 1] == '\r')
numBytes--;
#endif
/* XXX workaround for 3.1, not all utils zero dst before sending */
dst->data = 0;
if (!SECITEM_AllocItem(NULL, dst, numBytes))
goto loser;
memcpy(dst->data, buf, numBytes);
PORT_Free(buf);
return SECSuccess;
loser:
PORT_Free(buf);
return SECFailure;
}
#define INDENT_MULT 4
void
SECU_Indent(FILE *out, int level)
{
int i;
for (i = 0; i < level; i++) {
fprintf(out, " ");
}
}
void
SECU_Newline(FILE *out)
{
fprintf(out, "\n");
}
void
SECU_PrintAsHex(FILE *out, const SECItem *data, const char *m, int level)
{
unsigned i;
int column = 0;
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:", m);
level++;
if (wrapEnabled)
fprintf(out, "\n");
}
if (wrapEnabled) {
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 (wrapEnabled &&
(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 (wrapEnabled && column > 76) {
SECU_Newline(out);
SECU_Indent(out, level);
column = level * INDENT_MULT;
}
}
}
if (column != level * INDENT_MULT) {
SECU_Newline(out);
}
}
const char *hex = "0123456789abcdef";
const char printable[257] = {
"................" /* 0x */
"................" /* 1x */
" !\"#$%&'()*+,-./" /* 2x */
"0123456789:;<=>?" /* 3x */
"@ABCDEFGHIJKLMNO" /* 4x */
"PQRSTUVWXYZ[\\]^_" /* 5x */
"`abcdefghijklmno" /* 6x */
"pqrstuvwxyz{|}~." /* 7x */
"................" /* 8x */
"................" /* 9x */
"................" /* ax */
"................" /* bx */
"................" /* cx */
"................" /* dx */
"................" /* ex */
"................" /* fx */
};
void
SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len)
{
const unsigned char *cp = (const unsigned char *)vp;
char buf[80];
char *bp;
char *ap;
fprintf(out, "%s [Len: %d]\n", msg, len);
memset(buf, ' ', sizeof buf);
bp = buf;
ap = buf + 50;
while (--len >= 0) {
unsigned char ch = *cp++;
*bp++ = hex[(ch >> 4) & 0xf];
*bp++ = hex[ch & 0xf];
*bp++ = ' ';
*ap++ = printable[ch];
if (ap - buf >= 66) {
*ap = 0;
fprintf(out, " %s\n", buf);
memset(buf, ' ', sizeof buf);
bp = buf;
ap = buf + 50;
}
}
if (bp > buf) {
*ap = 0;
fprintf(out, " %s\n", buf);
}
}
/* This expents i->data[0] to be the MSB of the integer.
** if you want to print a DER-encoded integer (with the tag and length)
** call SECU_PrintEncodedInteger();
*/
void
SECU_PrintInteger(FILE *out, const SECItem *i, const char *m, int level)
{
int iv;
if (!i || !i->len || !i->data) {
SECU_Indent(out, level);
if (m) {
fprintf(out, "%s: (null)\n", m);
} else {
fprintf(out, "(null)\n");
}
} else if (i->len > 4) {
SECU_PrintAsHex(out, i, m, level);
} else {
if (i->type == siUnsignedInteger && *i->data & 0x80) {
/* Make sure i->data has zero in the highest bite
* if i->data is an unsigned integer */
SECItem tmpI;
char data[] = { 0, 0, 0, 0, 0 };
PORT_Memcpy(data + 1, i->data, i->len);
tmpI.len = i->len + 1;
tmpI.data = (void *)data;
iv = DER_GetInteger(&tmpI);
} else {
iv = DER_GetInteger(i);
}
SECU_Indent(out, level);
if (m) {
fprintf(out, "%s: %d (0x%x)\n", m, iv, iv);
} else {
fprintf(out, "%d (0x%x)\n", iv, iv);
}
}
}
#if defined(DEBUG) || defined(FORCE_PR_ASSERT)
/* Returns true iff a[i].flag has a duplicate in a[i+1 : count-1] */
static PRBool
HasShortDuplicate(int i, secuCommandFlag *a, int count)
{
char target = a[i].flag;
int j;
/* duplicate '\0' flags are okay, they are used with long forms */
for (j = i + 1; j < count; j++) {
if (a[j].flag && a[j].flag == target) {
return PR_TRUE;
}
}
return PR_FALSE;
}
/* Returns true iff a[i].longform has a duplicate in a[i+1 : count-1] */
static PRBool
HasLongDuplicate(int i, secuCommandFlag *a, int count)
{
int j;
char *target = a[i].longform;
if (!target)
return PR_FALSE;
for (j = i + 1; j < count; j++) {
if (a[j].longform && strcmp(a[j].longform, target) == 0) {
return PR_TRUE;
}
}
return PR_FALSE;
}
/* Returns true iff a has no short or long form duplicates
*/
PRBool
HasNoDuplicates(secuCommandFlag *a, int count)
{
int i;
for (i = 0; i < count; i++) {
if (a[i].flag && HasShortDuplicate(i, a, count)) {
return PR_FALSE;
}
if (a[i].longform && HasLongDuplicate(i, a, count)) {
return PR_FALSE;
}
}
return PR_TRUE;
}
#endif
SECStatus
SECU_ParseCommandLine(int argc, char **argv, char *progName,
const secuCommand *cmd)
{
PRBool found;
PLOptState *optstate;
PLOptStatus status;
char *optstring;
PLLongOpt *longopts = NULL;
int i, j;
int lcmd = 0, lopt = 0;
PR_ASSERT(HasNoDuplicates(cmd->commands, cmd->numCommands));
PR_ASSERT(HasNoDuplicates(cmd->options, cmd->numOptions));
optstring = (char *)PORT_Alloc(cmd->numCommands + 2 * cmd->numOptions + 1);
if (optstring == NULL)
return SECFailure;
j = 0;
for (i = 0; i < cmd->numCommands; i++) {
if (cmd->commands[i].flag) /* single character option ? */
optstring[j++] = cmd->commands[i].flag;
if (cmd->commands[i].longform)
lcmd++;
}
for (i = 0; i < cmd->numOptions; i++) {
if (cmd->options[i].flag) {
optstring[j++] = cmd->options[i].flag;
if (cmd->options[i].needsArg)
optstring[j++] = ':';
}
if (cmd->options[i].longform)
lopt++;
}
optstring[j] = '\0';
if (lcmd + lopt > 0) {
longopts = PORT_NewArray(PLLongOpt, lcmd + lopt + 1);
if (!longopts) {
PORT_Free(optstring);
return SECFailure;
}
j = 0;
for (i = 0; j < lcmd && i < cmd->numCommands; i++) {
if (cmd->commands[i].longform) {
longopts[j].longOptName = cmd->commands[i].longform;
longopts[j].longOption = 0;
longopts[j++].valueRequired = cmd->commands[i].needsArg;
}
}
lopt += lcmd;
for (i = 0; j < lopt && i < cmd->numOptions; i++) {
if (cmd->options[i].longform) {
longopts[j].longOptName = cmd->options[i].longform;
longopts[j].longOption = 0;
longopts[j++].valueRequired = cmd->options[i].needsArg;
}
}
longopts[j].longOptName = NULL;
}
optstate = PL_CreateLongOptState(argc, argv, optstring, longopts);
if (!optstate) {
PORT_Free(optstring);
PORT_Free(longopts);
return SECFailure;
}
/* Parse command line arguments */
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
const char *optstatelong;
char option = optstate->option;
/* positional parameter, single-char option or long opt? */
if (optstate->longOptIndex == -1) {
/* not a long opt */
if (option == '\0')
continue; /* it's a positional parameter */
optstatelong = "";
} else {
/* long opt */
if (option == '\0')
option = '\377'; /* force unequal with all flags */
optstatelong = longopts[optstate->longOptIndex].longOptName;
}
found = PR_FALSE;
for (i = 0; i < cmd->numCommands; i++) {
if (cmd->commands[i].flag == option ||
cmd->commands[i].longform == optstatelong) {
cmd->commands[i].activated = PR_TRUE;
if (optstate->value) {
cmd->commands[i].arg = (char *)optstate->value;
}
found = PR_TRUE;
break;
}
}
if (found)
continue;
for (i = 0; i < cmd->numOptions; i++) {
if (cmd->options[i].flag == option ||
cmd->options[i].longform == optstatelong) {
cmd->options[i].activated = PR_TRUE;
if (optstate->value) {
cmd->options[i].arg = (char *)optstate->value;
} else if (cmd->options[i].needsArg) {
status = PL_OPT_BAD;
goto loser;
}
found = PR_TRUE;
break;
}
}
if (!found) {
status = PL_OPT_BAD;
break;
}
}
loser:
PL_DestroyOptState(optstate);
PORT_Free(optstring);
if (longopts)
PORT_Free(longopts);
if (status == PL_OPT_BAD)
return SECFailure;
return SECSuccess;
}
char *
SECU_GetOptionArg(const secuCommand *cmd, int optionNum)
{
if (optionNum < 0 || optionNum >= cmd->numOptions)
return NULL;
if (cmd->options[optionNum].activated)
return PL_strdup(cmd->options[optionNum].arg);
else
return NULL;
}
void
SECU_PrintPRandOSError(const char *progName)
{
char buffer[513];
PRInt32 errLen = PR_GetErrorTextLength();
if (errLen > 0 && errLen < sizeof buffer) {
PR_GetErrorText(buffer);
}
SECU_PrintError(progName, "function failed");
if (errLen > 0 && errLen < sizeof buffer) {
PR_fprintf(PR_STDERR, "\t%s\n", buffer);
}
}
SECOidTag
SECU_StringToSignatureAlgTag(const char *alg)
{
SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
if (alg) {
if (!PL_strcmp(alg, "MD2")) {
hashAlgTag = SEC_OID_MD2;
} else if (!PL_strcmp(alg, "MD4")) {
hashAlgTag = SEC_OID_MD4;
} else if (!PL_strcmp(alg, "MD5")) {
hashAlgTag = SEC_OID_MD5;
} else if (!PL_strcmp(alg, "SHA1")) {
hashAlgTag = SEC_OID_SHA1;
} else if (!PL_strcmp(alg, "SHA224")) {
hashAlgTag = SEC_OID_SHA224;
} else if (!PL_strcmp(alg, "SHA256")) {
hashAlgTag = SEC_OID_SHA256;
} else if (!PL_strcmp(alg, "SHA384")) {
hashAlgTag = SEC_OID_SHA384;
} else if (!PL_strcmp(alg, "SHA512")) {
hashAlgTag = SEC_OID_SHA512;
}
}
return hashAlgTag;
}
/* 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)
{
unsigned 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;
}
SSLNamedGroup
groupNameToNamedGroup(char *name)
{
if (PL_strlen(name) == 4) {
if (!strncmp(name, "P256", 4)) {
return ssl_grp_ec_secp256r1;
}
if (!strncmp(name, "P384", 4)) {
return ssl_grp_ec_secp384r1;
}
if (!strncmp(name, "P521", 4)) {
return ssl_grp_ec_secp521r1;
}
}
if (PL_strlen(name) == 6) {
if (!strncmp(name, "x25519", 6)) {
return ssl_grp_ec_curve25519;
}
if (!strncmp(name, "FF2048", 6)) {
return ssl_grp_ffdhe_2048;
}
if (!strncmp(name, "FF3072", 6)) {
return ssl_grp_ffdhe_3072;
}
if (!strncmp(name, "FF4096", 6)) {
return ssl_grp_ffdhe_4096;
}
if (!strncmp(name, "FF6144", 6)) {
return ssl_grp_ffdhe_6144;
}
if (!strncmp(name, "FF8192", 6)) {
return ssl_grp_ffdhe_8192;
}
}
return ssl_grp_none;
}
SECStatus
parseGroupList(const char *arg, SSLNamedGroup **enabledGroups,
unsigned int *enabledGroupsCount)
{
SSLNamedGroup *groups;
char *str;
char *p;
unsigned int numValues = 0;
unsigned int count = 0;
/* Count the number of groups. */
str = PORT_Strdup(arg);
if (!str) {
return SECFailure;
}
p = strtok(str, ",");
while (p) {
++numValues;
p = strtok(NULL, ",");
}
PORT_Free(str);
str = NULL;
groups = PORT_ZNewArray(SSLNamedGroup, numValues);
if (!groups) {
goto done;
}
/* Get group names. */
str = PORT_Strdup(arg);
if (!str) {
goto done;
}
p = strtok(str, ",");
while (p) {
SSLNamedGroup group = groupNameToNamedGroup(p);
if (group == ssl_grp_none) {
count = 0;
goto done;
}
groups[count++] = group;
p = strtok(NULL, ",");
}
done:
if (str) {
PORT_Free(str);
}
if (!count) {
PORT_Free(groups);
return SECFailure;
}
*enabledGroupsCount = count;
*enabledGroups = groups;
return SECSuccess;
}

View file

@ -0,0 +1,137 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _BASIC_UTILS_H_
#define _BASIC_UTILS_H_
#include "seccomon.h"
#include "secitem.h"
#include "secoid.h"
#include "secoidt.h"
#include "secport.h"
#include "prerror.h"
#include "base64.h"
#include "secasn1.h"
#include "secder.h"
#include "sslt.h"
#include <stdio.h>
#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
/* print out an error message */
extern void SECU_PrintError(const char *progName, const char *msg, ...);
/* print out a system error message */
extern void SECU_PrintSystemError(const char *progName, const char *msg, ...);
/* print a formatted error message */
extern void SECU_PrintErrMsg(FILE *out, int level, const char *progName,
const char *msg, ...);
/* 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);
/* Indent based on "level" */
extern void SECU_Indent(FILE *out, int level);
/* Print a newline to out */
extern void SECU_Newline(FILE *out);
/* Print integer value and hex */
extern void SECU_PrintInteger(FILE *out, const SECItem *i, const char *m,
int level);
/* Print SECItem as hex */
extern void SECU_PrintAsHex(FILE *out, const 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);
#ifdef HAVE_EPV_TEMPLATE
/* Dump contents of private key */
extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
#endif
/* Init PKCS11 stuff */
extern SECStatus SECU_PKCS11Init(PRBool readOnly);
/* Dump contents of signed data */
extern int SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
int level, SECU_PPFunc inner);
extern void SECU_PrintString(FILE *out, const SECItem *si, const char *m,
int level);
extern void SECU_PrintAny(FILE *out, const SECItem *i, const char *m, int level);
extern void SECU_PrintPRandOSError(const char *progName);
/* 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);
SECStatus parseGroupList(const char *arg, SSLNamedGroup **enabledGroups,
unsigned int *enabledGroupsCount);
SSLNamedGroup groupNameToNamedGroup(char *name);
/*
*
* Error messaging
*
*/
void printflags(char *trusts, unsigned int flags);
#if !defined(XP_UNIX) && !defined(XP_OS2)
extern int ffs(unsigned int i);
#endif
#include "secerr.h"
extern const char *hex;
extern const char printable[];
#endif /* _BASIC_UTILS_H_ */

View file

@ -0,0 +1,388 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "secutil.h"
typedef enum {
tagDone,
lengthDone,
leafDone,
compositeDone,
notDone,
parseError,
parseComplete
} ParseState;
typedef unsigned char Byte;
typedef void (*ParseProc)(BERParse *h, unsigned char **buf, int *len);
typedef struct {
SECArb arb;
int pos; /* length from global start to item start */
SECArb *parent;
} ParseStackElem;
struct BERParseStr {
PLArenaPool *his;
PLArenaPool *mine;
ParseProc proc;
int stackDepth;
ParseStackElem *stackPtr;
ParseStackElem *stack;
int pending; /* bytes remaining to complete this part */
int pos; /* running length of consumed characters */
ParseState state;
PRBool keepLeaves;
PRBool derOnly;
BERFilterProc filter;
void *filterArg;
BERNotifyProc before;
void *beforeArg;
BERNotifyProc after;
void *afterArg;
};
#define UNKNOWN -1
static unsigned char
NextChar(BERParse *h, unsigned char **buf, int *len)
{
unsigned char c = *(*buf)++;
(*len)--;
h->pos++;
if (h->filter)
(*h->filter)(h->filterArg, &c, 1);
return c;
}
static void
ParseTag(BERParse *h, unsigned char **buf, int *len)
{
SECArb *arb = &(h->stackPtr->arb);
arb->tag = NextChar(h, buf, len);
PORT_Assert(h->state == notDone);
/*
* NOTE: This does not handle the high-tag-number form
*/
if ((arb->tag & DER_HIGH_TAG_NUMBER) == DER_HIGH_TAG_NUMBER) {
PORT_SetError(SEC_ERROR_BAD_DER);
h->state = parseError;
return;
}
h->pending = UNKNOWN;
arb->length = UNKNOWN;
if (arb->tag & DER_CONSTRUCTED) {
arb->body.cons.numSubs = 0;
arb->body.cons.subs = NULL;
} else {
arb->body.item.len = UNKNOWN;
arb->body.item.data = NULL;
}
h->state = tagDone;
}
static void
ParseLength(BERParse *h, unsigned char **buf, int *len)
{
Byte b;
SECArb *arb = &(h->stackPtr->arb);
PORT_Assert(h->state == notDone);
if (h->pending == UNKNOWN) {
b = NextChar(h, buf, len);
if ((b & 0x80) == 0) { /* short form */
arb->length = b;
/*
* if the tag and the length are both zero bytes, then this
* should be the marker showing end of list for the
* indefinite length composite
*/
if (arb->length == 0 && arb->tag == 0)
h->state = compositeDone;
else
h->state = lengthDone;
return;
}
h->pending = b & 0x7f;
/* 0 implies this is an indefinite length */
if (h->pending > 4) {
PORT_SetError(SEC_ERROR_BAD_DER);
h->state = parseError;
return;
}
arb->length = 0;
}
while ((*len > 0) && (h->pending > 0)) {
b = NextChar(h, buf, len);
arb->length = (arb->length << 8) + b;
h->pending--;
}
if (h->pending == 0) {
if (h->derOnly && (arb->length == 0))
h->state = parseError;
else
h->state = lengthDone;
}
return;
}
static void
ParseLeaf(BERParse *h, unsigned char **buf, int *len)
{
int count;
SECArb *arb = &(h->stackPtr->arb);
PORT_Assert(h->state == notDone);
PORT_Assert(h->pending >= 0);
if (*len < h->pending)
count = *len;
else
count = h->pending;
if (h->keepLeaves)
memcpy(arb->body.item.data + arb->body.item.len, *buf, count);
if (h->filter)
(*h->filter)(h->filterArg, *buf, count);
*buf += count;
*len -= count;
arb->body.item.len += count;
h->pending -= count;
h->pos += count;
if (h->pending == 0) {
h->state = leafDone;
}
return;
}
static void
CreateArbNode(BERParse *h)
{
SECArb *arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));
*arb = h->stackPtr->arb;
/*
* Special case closing the root
*/
if (h->stackPtr == h->stack) {
PORT_Assert(arb->tag & DER_CONSTRUCTED);
h->state = parseComplete;
} else {
SECArb *parent = h->stackPtr->parent;
parent->body.cons.subs = DS_ArenaGrow(
h->his, parent->body.cons.subs,
(parent->body.cons.numSubs) * sizeof(SECArb *),
(parent->body.cons.numSubs + 1) * sizeof(SECArb *));
parent->body.cons.subs[parent->body.cons.numSubs] = arb;
parent->body.cons.numSubs++;
h->proc = ParseTag;
h->state = notDone;
h->pending = UNKNOWN;
}
if (h->after)
(*h->after)(h->afterArg, arb, h->stackPtr - h->stack, PR_FALSE);
}
SECStatus
BER_ParseSome(BERParse *h, unsigned char *buf, int len)
{
if (h->state == parseError)
return PR_TRUE;
while (len) {
(*h->proc)(h, &buf, &len);
if (h->state == parseComplete) {
PORT_SetError(SEC_ERROR_BAD_DER);
h->state = parseError;
return PR_TRUE;
}
if (h->state == parseError)
return PR_TRUE;
PORT_Assert(h->state != parseComplete);
if (h->state <= compositeDone) {
if (h->proc == ParseTag) {
PORT_Assert(h->state == tagDone);
h->proc = ParseLength;
h->state = notDone;
} else if (h->proc == ParseLength) {
SECArb *arb = &(h->stackPtr->arb);
PORT_Assert(h->state == lengthDone || h->state == compositeDone);
if (h->before)
(*h->before)(h->beforeArg, arb,
h->stackPtr - h->stack, PR_TRUE);
/*
* Check to see if this is the end of an indefinite
* length composite
*/
if (h->state == compositeDone) {
SECArb *parent = h->stackPtr->parent;
PORT_Assert(parent);
PORT_Assert(parent->tag & DER_CONSTRUCTED);
if (parent->length != 0) {
PORT_SetError(SEC_ERROR_BAD_DER);
h->state = parseError;
return PR_TRUE;
}
/*
* NOTE: This does not check for an indefinite length
* composite being contained inside a definite length
* composite. It is not clear that is legal.
*/
h->stackPtr--;
CreateArbNode(h);
} else {
h->stackPtr->pos = h->pos;
if (arb->tag & DER_CONSTRUCTED) {
SECArb *parent;
/*
* Make sure there is room on the stack before we
* stick anything else there.
*/
PORT_Assert(h->stackPtr - h->stack < h->stackDepth);
if (h->stackPtr - h->stack == h->stackDepth - 1) {
int newDepth = h->stackDepth * 2;
h->stack = DS_ArenaGrow(h->mine, h->stack,
sizeof(ParseStackElem) *
h->stackDepth,
sizeof(ParseStackElem) *
newDepth);
h->stackPtr = h->stack + h->stackDepth + 1;
h->stackDepth = newDepth;
}
parent = &(h->stackPtr->arb);
h->stackPtr++;
h->stackPtr->parent = parent;
h->proc = ParseTag;
h->state = notDone;
h->pending = UNKNOWN;
} else {
if (arb->length < 0) {
PORT_SetError(SEC_ERROR_BAD_DER);
h->state = parseError;
return PR_TRUE;
}
arb->body.item.len = 0;
if (arb->length > 0 && h->keepLeaves) {
arb->body.item.data =
PORT_ArenaAlloc(h->his, arb->length);
} else {
arb->body.item.data = NULL;
}
h->proc = ParseLeaf;
h->state = notDone;
h->pending = arb->length;
}
}
} else {
ParseStackElem *parent;
PORT_Assert(h->state = leafDone);
PORT_Assert(h->proc == ParseLeaf);
for (;;) {
CreateArbNode(h);
if (h->stackPtr == h->stack)
break;
parent = (h->stackPtr - 1);
PORT_Assert(parent->arb.tag & DER_CONSTRUCTED);
if (parent->arb.length == 0) /* need explicit end */
break;
if (parent->pos + parent->arb.length > h->pos)
break;
if (parent->pos + parent->arb.length < h->pos) {
PORT_SetError(SEC_ERROR_BAD_DER);
h->state = parseError;
return PR_TRUE;
}
h->stackPtr = parent;
}
}
}
}
return PR_FALSE;
}
BERParse *
BER_ParseInit(PLArenaPool *arena, PRBool derOnly)
{
BERParse *h;
PLArenaPool *temp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (temp == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return NULL;
}
h = PORT_ArenaAlloc(temp, sizeof(BERParse));
if (h == NULL) {
PORT_FreeArena(temp, PR_FALSE);
PORT_SetError(SEC_ERROR_NO_MEMORY);
return NULL;
}
h->his = arena;
h->mine = temp;
h->proc = ParseTag;
h->stackDepth = 20;
h->stack = PORT_ArenaZAlloc(h->mine,
sizeof(ParseStackElem) * h->stackDepth);
h->stackPtr = h->stack;
h->state = notDone;
h->pos = 0;
h->keepLeaves = PR_TRUE;
h->before = NULL;
h->after = NULL;
h->filter = NULL;
h->derOnly = derOnly;
return h;
}
SECArb *
BER_ParseFini(BERParse *h)
{
PLArenaPool *myArena = h->mine;
SECArb *arb;
if (h->state != parseComplete) {
arb = NULL;
} else {
arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));
*arb = h->stackPtr->arb;
}
PORT_FreeArena(myArena, PR_FALSE);
return arb;
}
void
BER_SetFilter(BERParse *h, BERFilterProc proc, void *instance)
{
h->filter = proc;
h->filterArg = instance;
}
void
BER_SetLeafStorage(BERParse *h, PRBool keep)
{
h->keepLeaves = keep;
}
void
BER_SetNotifyProc(BERParse *h, BERNotifyProc proc, void *instance,
PRBool beforeData)
{
if (beforeData) {
h->before = proc;
h->beforeArg = instance;
} else {
h->after = proc;
h->afterArg = instance;
}
}

View file

@ -0,0 +1,15 @@
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# Override TARGETS variable so that only static libraries
# are specifed as dependencies within rules.mk.
#
TARGETS = $(LIBRARY)
SHARED_LIBRARY =
IMPORT_LIBRARY =
PROGRAM =

View file

@ -0,0 +1,594 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "secutil.h"
#include "secoid.h"
#ifdef __sun
extern int fprintf(FILE *strm, const char *format, ... /* args */);
extern int fflush(FILE *stream);
#endif
#define RIGHT_MARGIN 24
/*#define RAW_BYTES 1 */
static int prettyColumn = 0;
static int
getInteger256(const unsigned char *data, unsigned int nb)
{
int val;
switch (nb) {
case 1:
val = data[0];
break;
case 2:
val = (data[0] << 8) | data[1];
break;
case 3:
val = (data[0] << 16) | (data[1] << 8) | data[2];
break;
case 4:
/* If the most significant bit of data[0] is 1, val would be negative.
* Treat it as an error.
*/
if (data[0] & 0x80) {
PORT_SetError(SEC_ERROR_BAD_DER);
return -1;
}
val = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
break;
default:
PORT_SetError(SEC_ERROR_BAD_DER);
return -1;
}
return val;
}
static int
prettyNewline(FILE *out)
{
int rv;
if (prettyColumn != -1) {
rv = fprintf(out, "\n");
prettyColumn = -1;
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
}
return 0;
}
static int
prettyIndent(FILE *out, unsigned level)
{
unsigned int i;
int rv;
if (prettyColumn == -1) {
prettyColumn = level;
for (i = 0; i < level; i++) {
rv = fprintf(out, " ");
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
}
}
return 0;
}
static int
prettyPrintByte(FILE *out, unsigned char item, unsigned int level)
{
int rv;
rv = prettyIndent(out, level);
if (rv < 0)
return rv;
rv = fprintf(out, "%02x ", item);
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
prettyColumn++;
if (prettyColumn >= RIGHT_MARGIN) {
return prettyNewline(out);
}
return 0;
}
static int
prettyPrintLeaf(FILE *out, const unsigned char *data,
unsigned int len, unsigned int lv)
{
unsigned int i;
int rv;
for (i = 0; i < len; i++) {
rv = prettyPrintByte(out, *data++, lv);
if (rv < 0)
return rv;
}
return prettyNewline(out);
}
static int
prettyPrintStringStart(FILE *out, const unsigned char *str,
unsigned int len, unsigned int level)
{
#define BUF_SIZE 100
unsigned char buf[BUF_SIZE];
int rv;
if (len >= BUF_SIZE)
len = BUF_SIZE - 1;
rv = prettyNewline(out);
if (rv < 0)
return rv;
rv = prettyIndent(out, level);
if (rv < 0)
return rv;
memcpy(buf, str, len);
buf[len] = '\000';
rv = fprintf(out, "\"%s\"", buf);
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
return 0;
#undef BUF_SIZE
}
static int
prettyPrintString(FILE *out, const unsigned char *str,
unsigned int len, unsigned int level, PRBool raw)
{
int rv;
rv = prettyPrintStringStart(out, str, len, level);
if (rv < 0)
return rv;
rv = prettyNewline(out);
if (rv < 0)
return rv;
if (raw) {
rv = prettyPrintLeaf(out, str, len, level);
if (rv < 0)
return rv;
}
return 0;
}
static int
prettyPrintTime(FILE *out, const unsigned char *str,
unsigned int len, unsigned int level, PRBool raw, PRBool utc)
{
SECItem time_item;
int rv;
rv = prettyPrintStringStart(out, str, len, level);
if (rv < 0)
return rv;
time_item.data = (unsigned char *)str;
time_item.len = len;
rv = fprintf(out, " (");
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
if (utc)
SECU_PrintUTCTime(out, &time_item, NULL, 0);
else
SECU_PrintGeneralizedTime(out, &time_item, NULL, 0);
rv = fprintf(out, ")");
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
rv = prettyNewline(out);
if (rv < 0)
return rv;
if (raw) {
rv = prettyPrintLeaf(out, str, len, level);
if (rv < 0)
return rv;
}
return 0;
}
static int
prettyPrintObjectID(FILE *out, const unsigned char *data,
unsigned int len, unsigned int level, PRBool raw)
{
SECOidData *oiddata;
SECItem oiditem;
unsigned int i;
unsigned long val;
int rv;
/*
* First print the Object Id in numeric format
*/
rv = prettyIndent(out, level);
if (rv < 0)
return rv;
if (len == 0) {
PORT_SetError(SEC_ERROR_BAD_DER);
return -1;
}
val = data[0];
i = val % 40;
val = val / 40;
rv = fprintf(out, "%lu %u ", val, i);
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
val = 0;
for (i = 1; i < len; ++i) {
unsigned long j;
j = data[i];
val = (val << 7) | (j & 0x7f);
if (j & 0x80)
continue;
rv = fprintf(out, "%lu ", val);
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
val = 0;
}
/*
* Now try to look it up and print a symbolic version.
*/
oiditem.data = (unsigned char *)data;
oiditem.len = len;
oiddata = SECOID_FindOID(&oiditem);
if (oiddata != NULL) {
i = PORT_Strlen(oiddata->desc);
if ((prettyColumn + 1 + (i / 3)) > RIGHT_MARGIN) {
rv = prettyNewline(out);
if (rv < 0)
return rv;
}
rv = prettyIndent(out, level);
if (rv < 0)
return rv;
rv = fprintf(out, "(%s)", oiddata->desc);
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
}
rv = prettyNewline(out);
if (rv < 0)
return rv;
if (raw) {
rv = prettyPrintLeaf(out, data, len, level);
if (rv < 0)
return rv;
}
return 0;
}
static char *prettyTagType[32] = {
"End of Contents",
"Boolean",
"Integer",
"Bit String",
"Octet String",
"NULL",
"Object Identifier",
"0x07",
"0x08",
"0x09",
"Enumerated",
"0x0B",
"UTF8 String",
"0x0D",
"0x0E",
"0x0F",
"Sequence",
"Set",
"0x12",
"Printable String",
"T61 String",
"0x15",
"IA5 String",
"UTC Time",
"Generalized Time",
"0x19",
"Visible String",
"0x1B",
"Universal String",
"0x1D",
"BMP String",
"High-Tag-Number"
};
static int
prettyPrintTag(FILE *out, const unsigned char *src, const unsigned char *end,
unsigned char *codep, unsigned int level, PRBool raw)
{
int rv;
unsigned char code, tagnum;
if (src >= end) {
PORT_SetError(SEC_ERROR_BAD_DER);
return -1;
}
code = *src;
tagnum = code & SEC_ASN1_TAGNUM_MASK;
/*
* NOTE: This code does not (yet) handle the high-tag-number form!
*/
if (tagnum == SEC_ASN1_HIGH_TAG_NUMBER) {
PORT_SetError(SEC_ERROR_BAD_DER);
return -1;
}
if (raw)
rv = prettyPrintByte(out, code, level);
else
rv = prettyIndent(out, level);
if (rv < 0)
return rv;
if (code & SEC_ASN1_CONSTRUCTED) {
rv = fprintf(out, "C-");
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
}
switch (code & SEC_ASN1_CLASS_MASK) {
case SEC_ASN1_UNIVERSAL:
rv = fprintf(out, "%s ", prettyTagType[tagnum]);
break;
case SEC_ASN1_APPLICATION:
rv = fprintf(out, "Application: %d ", tagnum);
break;
case SEC_ASN1_CONTEXT_SPECIFIC:
rv = fprintf(out, "[%d] ", tagnum);
break;
case SEC_ASN1_PRIVATE:
rv = fprintf(out, "Private: %d ", tagnum);
break;
}
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
*codep = code;
return 1;
}
static int
prettyPrintLength(FILE *out, const unsigned char *data, const unsigned char *end,
int *lenp, PRBool *indefinitep, unsigned int lv, PRBool raw)
{
unsigned char lbyte;
int lenLen;
int rv;
if (data >= end) {
PORT_SetError(SEC_ERROR_BAD_DER);
return -1;
}
rv = fprintf(out, " ");
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
*indefinitep = PR_FALSE;
lbyte = *data++;
lenLen = 1;
if (lbyte >= 0x80) {
/* Multibyte length */
unsigned nb = (unsigned)(lbyte & 0x7f);
if (nb > 4) {
PORT_SetError(SEC_ERROR_BAD_DER);
return -1;
}
if (nb > 0) {
int il;
if ((data + nb) > end) {
PORT_SetError(SEC_ERROR_BAD_DER);
return -1;
}
il = getInteger256(data, nb);
if (il < 0)
return -1;
*lenp = (unsigned)il;
} else {
*lenp = 0;
*indefinitep = PR_TRUE;
}
lenLen += nb;
if (raw) {
unsigned int i;
rv = prettyPrintByte(out, lbyte, lv);
if (rv < 0)
return rv;
for (i = 0; i < nb; i++) {
rv = prettyPrintByte(out, data[i], lv);
if (rv < 0)
return rv;
}
}
} else {
*lenp = lbyte;
if (raw) {
rv = prettyPrintByte(out, lbyte, lv);
if (rv < 0)
return rv;
}
}
if (*indefinitep)
rv = fprintf(out, "(indefinite)\n");
else
rv = fprintf(out, "(%d)\n", *lenp);
if (rv < 0) {
PORT_SetError(SEC_ERROR_IO);
return rv;
}
prettyColumn = -1;
return lenLen;
}
static int
prettyPrintItem(FILE *out, const unsigned char *data, const unsigned char *end,
unsigned int lv, PRBool raw)
{
int slen;
int lenLen;
const unsigned char *orig = data;
int rv;
while (data < end) {
unsigned char code;
PRBool indefinite;
slen = prettyPrintTag(out, data, end, &code, lv, raw);
if (slen < 0)
return slen;
data += slen;
lenLen = prettyPrintLength(out, data, end, &slen, &indefinite, lv, raw);
if (lenLen < 0)
return lenLen;
data += lenLen;
/*
* Just quit now if slen more bytes puts us off the end.
*/
if ((data + slen) > end) {
PORT_SetError(SEC_ERROR_BAD_DER);
return -1;
}
if (code & SEC_ASN1_CONSTRUCTED) {
if (slen > 0 || indefinite) {
slen = prettyPrintItem(out, data,
slen == 0 ? end : data + slen,
lv + 1, raw);
if (slen < 0)
return slen;
data += slen;
}
} else if (code == 0) {
if (slen != 0 || lenLen != 1) {
PORT_SetError(SEC_ERROR_BAD_DER);
return -1;
}
break;
} else {
switch (code) {
case SEC_ASN1_PRINTABLE_STRING:
case SEC_ASN1_IA5_STRING:
case SEC_ASN1_VISIBLE_STRING:
rv = prettyPrintString(out, data, slen, lv + 1, raw);
if (rv < 0)
return rv;
break;
case SEC_ASN1_UTC_TIME:
rv = prettyPrintTime(out, data, slen, lv + 1, raw, PR_TRUE);
if (rv < 0)
return rv;
break;
case SEC_ASN1_GENERALIZED_TIME:
rv = prettyPrintTime(out, data, slen, lv + 1, raw, PR_FALSE);
if (rv < 0)
return rv;
break;
case SEC_ASN1_OBJECT_ID:
rv = prettyPrintObjectID(out, data, slen, lv + 1, raw);
if (rv < 0)
return rv;
break;
case SEC_ASN1_BOOLEAN: /* could do nicer job */
case SEC_ASN1_INTEGER: /* could do nicer job */
case SEC_ASN1_BIT_STRING: /* could do nicer job */
case SEC_ASN1_OCTET_STRING:
case SEC_ASN1_NULL:
case SEC_ASN1_ENUMERATED: /* could do nicer job, as INTEGER */
case SEC_ASN1_UTF8_STRING:
case SEC_ASN1_T61_STRING: /* print as printable string? */
case SEC_ASN1_UNIVERSAL_STRING:
case SEC_ASN1_BMP_STRING:
default:
rv = prettyPrintLeaf(out, data, slen, lv + 1);
if (rv < 0)
return rv;
break;
}
data += slen;
}
}
rv = prettyNewline(out);
if (rv < 0)
return rv;
return data - orig;
}
SECStatus
DER_PrettyPrint(FILE *out, const SECItem *it, PRBool raw)
{
int rv;
prettyColumn = -1;
rv = prettyPrintItem(out, it->data, it->data + it->len, 0, raw);
if (rv < 0)
return SECFailure;
return SECSuccess;
}

View file

@ -0,0 +1,27 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
{
'includes': [
'../../coreconf/config.gypi'
],
'targets': [
{
'target_name': 'cmd_lib_exports',
'type': 'none',
'copies': [
{
'files': [
'basicutil.h',
'pk11table.h',
'secutil.h'
],
'destination': '<(nss_private_dist_dir)/<(module)'
}
]
}
],
'variables': {
'module': 'nss'
}
}

View file

@ -0,0 +1,21 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if !defined(XP_UNIX) && !defined(XP_OS2)
int
ffs(unsigned int i)
{
int rv = 1;
if (!i)
return 0;
while (!(i & 1)) {
i >>= 1;
++rv;
}
return rv;
}
#endif

View file

@ -0,0 +1,36 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
{
'includes': [
'../../coreconf/config.gypi'
],
'targets': [
{
'target_name': 'sectool',
'type': 'static_library',
'standalone_static_library': 1,
'sources': [
'basicutil.c',
'derprint.c',
'ffs.c',
'moreoids.c',
'pk11table.c',
'pppolicy.c',
'secpwd.c',
'secutil.c'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
]
}
],
'target_defaults': {
'defines': [
'NSPR20'
]
},
'variables': {
'module': 'nss'
}
}

View file

@ -0,0 +1,39 @@
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
CORE_DEPTH = ../..
LIBRARY_NAME = sectool
# MODULE public and private header directories are implicitly REQUIRED.
MODULE = nss
DEFINES = -DNSPR20
ifdef NSS_BUILD_SOFTOKEN_ONLY
PRIVATE_EXPORTS = basicutil.h \
pk11table.h \
$(NULL)
CSRCS = basicutil.c \
pk11table.c \
$(NULL)
else
PRIVATE_EXPORTS = basicutil.h \
secutil.h \
pk11table.h \
$(NULL)
CSRCS = basicutil.c \
secutil.c \
secpwd.c \
derprint.c \
moreoids.c \
pppolicy.c \
ffs.c \
pk11table.c \
$(NULL)
endif
NO_MD_RELEASE = 1

View file

@ -0,0 +1,167 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "secoid.h"
#include "secmodt.h" /* for CKM_INVALID_MECHANISM */
#define OI(x) \
{ \
siDEROID, (unsigned char *)x, sizeof x \
}
#define OD(oid, tag, desc, mech, ext) \
{ \
OI(oid) \
, tag, desc, mech, ext \
}
#define ODN(oid, desc) \
{ \
OI(oid) \
, 0, desc, CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION \
}
#define OIDT static const unsigned char
/* OIW Security Special Interest Group defined algorithms. */
#define OIWSSIG 0x2B, 13, 3, 2
OIDT oiwMD5RSA[] = { OIWSSIG, 3 };
OIDT oiwDESCBC[] = { OIWSSIG, 7 };
OIDT oiwRSAsig[] = { OIWSSIG, 11 };
OIDT oiwDSA[] = { OIWSSIG, 12 };
OIDT oiwMD5RSAsig[] = { OIWSSIG, 25 };
OIDT oiwSHA1[] = { OIWSSIG, 26 };
OIDT oiwDSASHA1[] = { OIWSSIG, 27 };
OIDT oiwDSASHA1param[] = { OIWSSIG, 28 };
OIDT oiwSHA1RSA[] = { OIWSSIG, 29 };
/* Microsoft OIDs. (1 3 6 1 4 1 311 ... ) */
#define MICROSOFT 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37
OIDT mCTL[] = { MICROSOFT, 10, 3, 1 }; /* Cert Trust List signing */
OIDT mTSS[] = { MICROSOFT, 10, 3, 2 }; /* Time Stamp Signing */
OIDT mSGC[] = { MICROSOFT, 10, 3, 3 }; /* Server gated cryptography */
OIDT mEFS[] = { MICROSOFT, 10, 3, 4 }; /* Encrypted File System */
OIDT mSMIME[] = { MICROSOFT, 16, 4 }; /* SMIME encryption key prefs */
OIDT mECRTT[] = { MICROSOFT, 20, 2 }; /* Enrollment cert type xtn */
OIDT mEAGNT[] = { MICROSOFT, 20, 2, 1 }; /* Enrollment Agent */
OIDT mKPSCL[] = { MICROSOFT, 20, 2, 2 }; /* KP SmartCard Logon */
OIDT mNTPN[] = { MICROSOFT, 20, 2, 3 }; /* NT Principal Name */
OIDT mCASRV[] = { MICROSOFT, 21, 1 }; /* CertServ CA version */
/* AOL OIDs (1 3 6 1 4 1 1066 ... ) */
#define AOL 0x2B, 0x06, 0x01, 0x04, 0x01, 0x88, 0x2A
/* PKIX IDs (1 3 6 1 5 5 7 ...) */
#define ID_PKIX 0x2B, 6, 1, 5, 5, 7
/* PKIX Access Descriptors (methods for Authority Info Access Extns) */
#define ID_AD ID_PKIX, 48
OIDT padOCSP[] = { ID_AD, 1 }; /* OCSP method */
OIDT padCAissuer[] = { ID_AD, 2 }; /* URI (for CRL ?) */
OIDT padTimeStamp[] = { ID_AD, 3 }; /* time stamping */
/* ISO Cert Extension type OIDs (id-ce) (2 5 29 ...) */
#define X500 0x55
#define X520_ATTRIBUTE_TYPE X500, 0x04
#define X500_ALG X500, 0x08
#define X500_ALG_ENCRYPTION X500_ALG, 0x01
#define ID_CE X500, 29
OIDT cePlcyObs[] = { ID_CE, 3 }; /* Cert policies, obsolete. */
OIDT cePlcyCns[] = { ID_CE, 36 }; /* Cert policy constraints. */
/* US Company arc (2 16 840 1 ...) */
#define USCOM 0x60, 0x86, 0x48, 0x01
#define USGOV USCOM, 0x65
#define USDOD USGOV, 2
#define ID_INFOSEC USDOD, 1
/* Verisign PKI OIDs (2 16 840 1 113733 1 ...) */
#define VERISIGN_PKI USCOM, 0x86, 0xf8, 0x45, 1
#define VERISIGN_XTN VERISIGN_PKI, 6
#define VERISIGN_POL VERISIGN_PKI, 7 /* Cert policies */
#define VERISIGN_TNET VERISIGN_POL, 23 /* Verisign Trust Network */
OIDT vcx7[] = { VERISIGN_XTN, 7 }; /* Cert Extension 7 (?) */
OIDT vcp1[] = { VERISIGN_TNET, 1 }; /* class 1 cert policy */
OIDT vcp2[] = { VERISIGN_TNET, 2 }; /* class 2 cert policy */
OIDT vcp3[] = { VERISIGN_TNET, 3 }; /* class 3 cert policy */
OIDT vcp4[] = { VERISIGN_TNET, 4 }; /* class 4 cert policy */
/* ------------------------------------------------------------------- */
static const SECOidData oids[] = {
/* OIW Security Special Interest Group OIDs */
ODN(oiwMD5RSA, "OIWSecSIG MD5 with RSA"),
ODN(oiwDESCBC, "OIWSecSIG DES CBC"),
ODN(oiwRSAsig, "OIWSecSIG RSA signature"),
ODN(oiwDSA, "OIWSecSIG DSA"),
ODN(oiwMD5RSAsig, "OIWSecSIG MD5 with RSA signature"),
ODN(oiwSHA1, "OIWSecSIG SHA1"),
ODN(oiwDSASHA1, "OIWSecSIG DSA with SHA1"),
ODN(oiwDSASHA1param, "OIWSecSIG DSA with SHA1 with params"),
ODN(oiwSHA1RSA, "OIWSecSIG MD5 with RSA"),
/* Microsoft OIDs */
ODN(mCTL, "Microsoft Cert Trust List signing"),
ODN(mTSS, "Microsoft Time Stamp signing"),
ODN(mSGC, "Microsoft SGC SSL server"),
ODN(mEFS, "Microsoft Encrypted File System"),
ODN(mSMIME, "Microsoft SMIME preferences"),
ODN(mECRTT, "Microsoft Enrollment Cert Type Extension"),
ODN(mEAGNT, "Microsoft Enrollment Agent"),
ODN(mKPSCL, "Microsoft KP SmartCard Logon"),
ODN(mNTPN, "Microsoft NT Principal Name"),
ODN(mCASRV, "Microsoft CertServ CA version"),
/* PKIX OIDs */
ODN(padOCSP, "PKIX OCSP method"),
ODN(padCAissuer, "PKIX CA Issuer method"),
ODN(padTimeStamp, "PKIX Time Stamping method"),
/* ID_CE OIDs. */
ODN(cePlcyObs, "Certificate Policies (Obsolete)"),
ODN(cePlcyCns, "Certificate Policy Constraints"),
/* Verisign OIDs. */
ODN(vcx7, "Verisign Cert Extension 7 (?)"),
ODN(vcp1, "Verisign Class 1 Certificate Policy"),
ODN(vcp2, "Verisign Class 2 Certificate Policy"),
ODN(vcp3, "Verisign Class 3 Certificate Policy"),
ODN(vcp4, "Verisign Class 4 Certificate Policy"),
};
static const unsigned int numOids = (sizeof oids) / (sizeof oids[0]);
/* Fetch and register an oid if it hasn't been done already */
void
SECU_cert_fetchOID(SECOidTag *data, const SECOidData *src)
{
if (*data == SEC_OID_UNKNOWN) {
/* AddEntry does the right thing if someone else has already
* added the oid. (that is return that oid tag) */
*data = SECOID_AddEntry(src);
}
}
SECStatus
SECU_RegisterDynamicOids(void)
{
unsigned int i;
SECStatus rv = SECSuccess;
for (i = 0; i < numOids; ++i) {
SECOidTag tag = SECOID_AddEntry(&oids[i]);
if (tag == SEC_OID_UNKNOWN) {
rv = SECFailure;
#ifdef DEBUG_DYN_OIDS
fprintf(stderr, "Add OID[%d] failed\n", i);
} else {
fprintf(stderr, "Add OID[%d] returned tag %d\n", i, tag);
#endif
}
}
return rv;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,178 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _PK11_TABLE_H_
#define _PK11_TABLE_H_
/*
* Supported functions..
*/
#include <pkcs11.h>
#include "nspr.h"
#include "prtypes.h"
typedef enum {
F_No_Function,
#undef CK_NEED_ARG_LIST
#define CK_PKCS11_FUNCTION_INFO(func) F_##func,
#include "pkcs11f.h"
#undef CK_NEED_ARG_LISt
#undef CK_PKCS11_FUNCTION_INFO
F_SetVar,
F_SetStringVar,
F_NewArray,
F_NewInitializeArgs,
F_NewTemplate,
F_NewMechanism,
F_BuildTemplate,
F_SetTemplate,
F_Print,
F_SaveVar,
F_RestoreVar,
F_Increment,
F_Decrement,
F_Delete,
F_List,
F_Run,
F_Load,
F_Unload,
F_System,
F_Loop,
F_Time,
F_Help,
F_Quit,
F_QuitIf,
F_QuitIfString
} FunctionType;
/*
* Supported Argument Types
*/
typedef enum {
ArgNone,
ArgVar,
ArgULong,
ArgChar,
ArgUTF8,
ArgInfo,
ArgSlotInfo,
ArgTokenInfo,
ArgSessionInfo,
ArgAttribute,
ArgMechanism,
ArgMechanismInfo,
ArgInitializeArgs,
ArgFunctionList,
/* Modifier Flags */
ArgMask = 0xff,
ArgOut = 0x100,
ArgArray = 0x200,
ArgNew = 0x400,
ArgFile = 0x800,
ArgStatic = 0x1000,
ArgOpt = 0x2000,
ArgFull = 0x4000
} ArgType;
typedef enum _constType {
ConstNone,
ConstBool,
ConstInfoFlags,
ConstSlotFlags,
ConstTokenFlags,
ConstSessionFlags,
ConstMechanismFlags,
ConstInitializeFlags,
ConstUsers,
ConstSessionState,
ConstObject,
ConstHardware,
ConstKeyType,
ConstCertType,
ConstAttribute,
ConstMechanism,
ConstResult,
ConstTrust,
ConstAvailableSizes,
ConstCurrentSize
} ConstType;
typedef struct _constant {
const char *name;
CK_ULONG value;
ConstType type;
ConstType attrType;
} Constant;
/*
* Values structures.
*/
typedef struct _values {
ArgType type;
ConstType constType;
int size;
char *filename;
void *data;
int reference;
int arraySize;
} Value;
/*
* Variables
*/
typedef struct _variable Variable;
struct _variable {
Variable *next;
char *vname;
Value *value;
};
/* NOTE: if you change MAX_ARGS, you need to change the commands array
* below as well.
*/
#define MAX_ARGS 10
/*
* structure for master command array
*/
typedef struct _commands {
char *fname;
FunctionType fType;
char *helpString;
ArgType args[MAX_ARGS];
} Commands;
typedef struct _module {
PRLibrary *library;
CK_FUNCTION_LIST *functionList;
} Module;
typedef struct _topics {
char *name;
char *helpString;
} Topics;
/*
* the command array itself. Make name to function and it's arguments
*/
extern const char **valueString;
extern const int valueCount;
extern const char **constTypeString;
extern const int constTypeCount;
extern const Constant *consts;
extern const unsigned int constCount;
extern const Commands *commands;
extern const int commandCount;
extern const Topics *topics;
extern const int topicCount;
extern const char *
getName(CK_ULONG value, ConstType type);
extern const char *
getNameFromAttribute(CK_ATTRIBUTE_TYPE type);
extern unsigned int totalKnownType(ConstType type);
#endif /* _PK11_TABLE_H_ */

View file

@ -0,0 +1,263 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Support for various policy related extensions
*/
#include "seccomon.h"
#include "secport.h"
#include "secder.h"
#include "cert.h"
#include "secoid.h"
#include "secasn1.h"
#include "secerr.h"
#include "nspr.h"
#include "secutil.h"
/* This implementation is derived from the one in nss/lib/certdb/policyxtn.c .
** The chief difference is the addition of the OPTIONAL flag to many
** parts. The idea is to be able to parse and print as much of the
** policy extension as possible, even if some parts are invalid.
**
** If this approach still is unable to decode policy extensions that
** contain invalid parts, then the next approach will be to parse
** the PolicyInfos as a SEQUENCE of ANYs, and then parse each of them
** as PolicyInfos, with the PolicyQualifiers being ANYs, and finally
** parse each of the PolicyQualifiers.
*/
static const SEC_ASN1Template secu_PolicyQualifierTemplate[] = {
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(CERTPolicyQualifier) },
{ SEC_ASN1_OBJECT_ID,
offsetof(CERTPolicyQualifier, qualifierID) },
{ SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
offsetof(CERTPolicyQualifier, qualifierValue) },
{ 0 }
};
static const SEC_ASN1Template secu_PolicyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(CERTPolicyInfo) },
{ SEC_ASN1_OBJECT_ID,
offsetof(CERTPolicyInfo, policyID) },
{ SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL,
offsetof(CERTPolicyInfo, policyQualifiers),
secu_PolicyQualifierTemplate },
{ 0 }
};
static const SEC_ASN1Template secu_CertificatePoliciesTemplate[] = {
{ SEC_ASN1_SEQUENCE_OF,
offsetof(CERTCertificatePolicies, policyInfos),
secu_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) }
};
static CERTCertificatePolicies *
secu_DecodeCertificatePoliciesExtension(SECItem *extnValue)
{
PLArenaPool *arena = NULL;
SECStatus rv;
CERTCertificatePolicies *policies;
CERTPolicyInfo **policyInfos, *policyInfo;
CERTPolicyQualifier **policyQualifiers, *policyQualifier;
SECItem newExtnValue;
/* make a new arena */
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena) {
goto loser;
}
/* allocate the certifiate policies structure */
policies = PORT_ArenaZNew(arena, CERTCertificatePolicies);
if (policies == NULL) {
goto loser;
}
policies->arena = arena;
/* copy the DER into the arena, since Quick DER returns data that points
into the DER input, which may get freed by the caller */
rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
if (rv != SECSuccess) {
goto loser;
}
/* decode the policy info */
rv = SEC_QuickDERDecodeItem(arena, policies,
secu_CertificatePoliciesTemplate,
&newExtnValue);
if (rv != SECSuccess) {
goto loser;
}
/* initialize the oid tags */
policyInfos = policies->policyInfos;
while (policyInfos != NULL && *policyInfos != NULL) {
policyInfo = *policyInfos;
policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID);
policyQualifiers = policyInfo->policyQualifiers;
while (policyQualifiers && *policyQualifiers != NULL) {
policyQualifier = *policyQualifiers;
policyQualifier->oid =
SECOID_FindOIDTag(&policyQualifier->qualifierID);
policyQualifiers++;
}
policyInfos++;
}
return (policies);
loser:
if (arena != NULL) {
PORT_FreeArena(arena, PR_FALSE);
}
return (NULL);
}
static char *
itemToString(SECItem *item)
{
char *string;
string = PORT_ZAlloc(item->len + 1);
if (string == NULL)
return NULL;
PORT_Memcpy(string, item->data, item->len);
string[item->len] = 0;
return string;
}
static SECStatus
secu_PrintUserNoticeQualifier(FILE *out, SECItem *qualifierValue,
char *msg, int level)
{
CERTUserNotice *userNotice = NULL;
if (qualifierValue)
userNotice = CERT_DecodeUserNotice(qualifierValue);
if (userNotice) {
if (userNotice->noticeReference.organization.len != 0) {
char *string =
itemToString(&userNotice->noticeReference.organization);
SECItem **itemList = userNotice->noticeReference.noticeNumbers;
while (itemList && *itemList) {
SECU_PrintInteger(out, *itemList, string, level + 1);
itemList++;
}
PORT_Free(string);
}
if (userNotice->displayText.len != 0) {
SECU_PrintString(out, &userNotice->displayText,
"Display Text", level + 1);
}
CERT_DestroyUserNotice(userNotice);
return SECSuccess;
}
return SECFailure; /* caller will print this value */
}
static SECStatus
secu_PrintPolicyQualifier(FILE *out, CERTPolicyQualifier *policyQualifier,
char *msg, int level)
{
SECStatus rv;
SECItem *qualifierValue = &policyQualifier->qualifierValue;
SECU_PrintObjectID(out, &policyQualifier->qualifierID,
"Policy Qualifier Name", level);
if (!qualifierValue->data) {
SECU_Indent(out, level);
fprintf(out, "Error: missing qualifier\n");
} else
switch (policyQualifier->oid) {
case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
rv = secu_PrintUserNoticeQualifier(out, qualifierValue, msg, level);
if (SECSuccess == rv)
break;
/* fall through on error */
case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
default:
SECU_PrintAny(out, qualifierValue, "Policy Qualifier Data", level);
break;
}
return SECSuccess;
}
static SECStatus
secu_PrintPolicyInfo(FILE *out, CERTPolicyInfo *policyInfo, char *msg, int level)
{
CERTPolicyQualifier **policyQualifiers;
policyQualifiers = policyInfo->policyQualifiers;
SECU_PrintObjectID(out, &policyInfo->policyID, "Policy Name", level);
while (policyQualifiers && *policyQualifiers != NULL) {
secu_PrintPolicyQualifier(out, *policyQualifiers, "", level + 1);
policyQualifiers++;
}
return SECSuccess;
}
void
SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level)
{
CERTCertificatePolicies *policies = NULL;
CERTPolicyInfo **policyInfos;
if (msg) {
SECU_Indent(out, level);
fprintf(out, "%s: \n", msg);
level++;
}
policies = secu_DecodeCertificatePoliciesExtension(value);
if (policies == NULL) {
SECU_PrintAny(out, value, "Invalid Policy Data", level);
return;
}
policyInfos = policies->policyInfos;
while (policyInfos && *policyInfos != NULL) {
secu_PrintPolicyInfo(out, *policyInfos, "", level);
policyInfos++;
}
CERT_DestroyCertificatePoliciesExtension(policies);
}
void
SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value,
char *msg, int level)
{
CERTPrivKeyUsagePeriod *prd;
PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena) {
goto loser;
}
prd = CERT_DecodePrivKeyUsagePeriodExtension(arena, value);
if (!prd) {
goto loser;
}
if (prd->notBefore.data) {
SECU_PrintGeneralizedTime(out, &prd->notBefore, "Not Before", level);
}
if (prd->notAfter.data) {
SECU_PrintGeneralizedTime(out, &prd->notAfter, "Not After ", level);
}
if (!prd->notBefore.data && !prd->notAfter.data) {
SECU_Indent(out, level);
fprintf(out, "Error: notBefore or notAfter MUST be present.\n");
loser:
SECU_PrintAny(out, value, msg, level);
}
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
}
}

View file

@ -0,0 +1,168 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "secutil.h"
/*
* NOTE: The contents of this file are NOT used by the client.
* (They are part of the security library as a whole, but they are
* NOT USED BY THE CLIENT.) Do not change things on behalf of the
* client (like localizing strings), or add things that are only
* for the client (put them elsewhere).
*/
#ifdef XP_UNIX
#include <termios.h>
#endif
#if defined(XP_UNIX) || defined(XP_BEOS)
#include <unistd.h> /* for isatty() */
#endif
#if defined(_WINDOWS)
#include <conio.h>
#include <io.h>
#define QUIET_FGETS quiet_fgets
static char *quiet_fgets(char *buf, int length, FILE *input);
#else
#define QUIET_FGETS fgets
#endif
static void
echoOff(int fd)
{
#if defined(XP_UNIX)
if (isatty(fd)) {
struct termios tio;
tcgetattr(fd, &tio);
tio.c_lflag &= ~ECHO;
tcsetattr(fd, TCSAFLUSH, &tio);
}
#endif
}
static void
echoOn(int fd)
{
#if defined(XP_UNIX)
if (isatty(fd)) {
struct termios tio;
tcgetattr(fd, &tio);
tio.c_lflag |= ECHO;
tcsetattr(fd, TCSAFLUSH, &tio);
}
#endif
}
char *
SEC_GetPassword(FILE *input, FILE *output, char *prompt,
PRBool (*ok)(char *))
{
#if defined(_WINDOWS)
int isTTY = (input == stdin);
#define echoOn(x)
#define echoOff(x)
#else
int infd = fileno(input);
int isTTY = isatty(infd);
#endif
char phrase[200] = { '\0' }; /* ensure EOF doesn't return junk */
for (;;) {
/* Prompt for password */
if (isTTY) {
fprintf(output, "%s", prompt);
fflush(output);
echoOff(infd);
}
if (QUIET_FGETS(phrase, sizeof(phrase), input) == NULL) {
return NULL;
}
if (isTTY) {
fprintf(output, "\n");
echoOn(infd);
}
/* stomp on newline */
phrase[PORT_Strlen(phrase) - 1] = 0;
/* Validate password */
if (!(*ok)(phrase)) {
/* Not weird enough */
if (!isTTY)
return NULL;
fprintf(output, "Password must be at least 8 characters long with one or more\n");
fprintf(output, "non-alphabetic characters\n");
continue;
}
return (char *)PORT_Strdup(phrase);
}
}
PRBool
SEC_CheckPassword(char *cp)
{
int len;
char *end;
len = PORT_Strlen(cp);
if (len < 8) {
return PR_FALSE;
}
end = cp + len;
while (cp < end) {
unsigned char ch = *cp++;
if (!((ch >= 'A') && (ch <= 'Z')) &&
!((ch >= 'a') && (ch <= 'z'))) {
/* pass phrase has at least one non alphabetic in it */
return PR_TRUE;
}
}
return PR_FALSE;
}
PRBool
SEC_BlindCheckPassword(char *cp)
{
if (cp != NULL) {
return PR_TRUE;
}
return PR_FALSE;
}
/* Get a password from the input terminal, without echoing */
#if defined(_WINDOWS)
static char *
quiet_fgets(char *buf, int length, FILE *input)
{
int c;
char *end = buf;
/* fflush (input); */
memset(buf, 0, length);
if (!isatty(fileno(input))) {
return fgets(buf, length, input);
}
while (1) {
c = getch(); /* getch gets a character from the console */
if (c == '\b') {
if (end > buf)
end--;
}
else if (--length > 0)
*end++ = c;
if (!c || c == '\n' || c == '\r')
break;
}
return buf;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,432 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _SEC_UTIL_H_
#define _SEC_UTIL_H_
#include "seccomon.h"
#include "secitem.h"
#include "secport.h"
#include "prerror.h"
#include "base64.h"
#include "key.h"
#include "secpkcs7.h"
#include "secasn1.h"
#include "secder.h"
#include <stdio.h>
#include "basicutil.h"
#include "sslerr.h"
#include "sslt.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_CERTIFICATE_ID "certificate-identity"
#define SEC_CT_PKCS7 "pkcs7"
#define SEC_CT_CRL "crl"
#define SEC_CT_NAME "name"
#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 SECU_Strerror PORT_ErrorToString
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 PR_GetEnvSecure("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);
extern PRBool SECU_GetWrapEnabled(void);
extern void SECU_EnableWrap(PRBool enable);
extern PRBool SECU_GetUtf8DisplayEnabled(void);
extern void SECU_EnableUtf8Display(PRBool enable);
/* 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 in a DER from a file, may be ascii */
extern SECStatus
SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii,
PRBool warnOnPrivateKeyInAsciiFile);
/* Print integer value and hex */
extern void SECU_PrintInteger(FILE *out, const SECItem *i, const char *m,
int level);
/* Print ObjectIdentifier symbolically */
extern SECOidTag SECU_PrintObjectID(FILE *out, const SECItem *oid,
const char *m, int level);
/* Print AlgorithmIdentifier symbolically */
extern void SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m,
int level);
/*
* 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, const SECItem *t, const 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, const SECItem *t,
const 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, const SECItem *t, const 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, const SECItem *der, const char *m,
int level);
extern int SECU_PrintCertificateBasicInfo(FILE *out, const SECItem *der, const char *m,
int level);
extern int SECU_PrintDumpDerIssuerAndSerial(FILE *out, SECItem *der, char *m,
int level);
/* Dump contents of a DER certificate name (issuer or subject) */
extern int SECU_PrintDERName(FILE *out, SECItem *der, const char *m, int level);
/* print trust flags on a cert */
extern void SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, 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
/* Dump contents of an RSA public key */
extern void SECU_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level);
/* Dump contents of a DSA public key */
extern void SECU_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level);
/* 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, const char *m,
int level, SECU_PPFunc inner);
/* Dump contents of signed data, excluding the signature */
extern int SECU_PrintSignedContent(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, const SECItem *si, const char *m,
int level);
extern void SECU_PrintAny(FILE *out, const SECItem *i, const 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_PrintNameQuotesOptional(FILE *out, CERTName *name,
const char *msg, int level,
PRBool quotes);
extern void SECU_PrintName(FILE *out, CERTName *name, const char *msg,
int level);
extern void SECU_PrintRDN(FILE *out, CERTRDN *rdn, const 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, const SECItem *it, PRBool raw);
extern char *SECU_SECModDBName(void);
/* Fetch and register an oid if it hasn't been done already */
extern void SECU_cert_fetchOID(SECOidTag *data, const SECOidData *src);
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(PLArenaPool *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(PLArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl);
/*
** Finds the crl Authority Key Id extension. Returns NULL if no such extension
** was found.
*/
CERTAuthKeyID *
SECU_FindCRLAuthKeyIDExten(PLArenaPool *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)(PLArenaPool *extHandleArena,
void *value, SECItem *encodedValue);
/* Encodes and adds extensions to the CRL or CRL entries. */
SECStatus
SECU_EncodeAndAddExtensionValue(PLArenaPool *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);
/* Parse a version range string, with "min" and "max" version numbers,
* separated by colon (":"), and return the result in vr and v2.
*
* Both min and max values are optional.
* The following syntax is used to specify the enabled protocol versions:
* A string with only a max value is expected as ":{max}",
* and all implemented versions less than or equal to max will be enabled.
* A string with only a min value is expected as "{min}:",
* and all implemented versions greater than or equal to min will be enabled.
* A string consisting of a colon only means "all versions enabled".
*
* In order to avoid a link dependency from libsectool to libssl,
* the caller must provide the desired default values for the min/max values,
* by providing defaultVersionRange (which can be obtained from libssl by
* calling SSL_VersionRangeGetSupported).
*/
SECStatus
SECU_ParseSSLVersionRangeString(const char *input,
const SSLVersionRange defaultVersionRange,
SSLVersionRange *vrange);
/*
** Read a hex string into a SecItem.
*/
extern SECItem *SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item,
const char *str);
/*
*
* Error messaging
*
*/
void printflags(char *trusts, unsigned int flags);
#if !defined(XP_UNIX) && !defined(XP_OS2)
extern int ffs(unsigned int i);
#endif
/* Finds certificate by searching it in the DB or by examinig file
* in the local directory. */
CERTCertificate *
SECU_FindCertByNicknameOrFilename(CERTCertDBHandle *handle,
char *name, PRBool ascii,
void *pwarg);
#include "secerr.h"
#include "sslerr.h"
#endif /* _SEC_UTIL_H_ */