зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1738222 - land NSS 4b8ce9641338 UPGRADE_NSS_RELEASE, r=jschanck
Differential Revision: https://phabricator.services.mozilla.com/D131519
This commit is contained in:
Родитель
77fbb0cc69
Коммит
9d4b719a04
|
@ -9,7 +9,7 @@ system_lib_option("--with-system-nss", help="Use system NSS")
|
|||
imply_option("--with-system-nspr", True, when="--with-system-nss")
|
||||
|
||||
nss_pkg = pkg_check_modules(
|
||||
"NSS", "nss >= 3.72", when="--with-system-nss", config=False
|
||||
"NSS", "nss >= 3.73", when="--with-system-nss", config=False
|
||||
)
|
||||
|
||||
set_config("MOZ_SYSTEM_NSS", True, when="--with-system-nss")
|
||||
|
|
|
@ -1 +1 @@
|
|||
NSS_3_72_RTM
|
||||
4b8ce9641338
|
|
@ -1 +1 @@
|
|||
NSS_3_71_BRANCH
|
||||
NSS_3_72_BRANCH
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Dockerfile for running fuzzing tests.
|
||||
# Used for ASAN and Coverity based static-analysis.
|
||||
# Used for ASAN.
|
||||
# Note that when running this, you need to add `--cap-add SYS_PTRACE` to the
|
||||
# docker invocation or ASAN won't work.
|
||||
# On taskcluster for ASAN use `features: ["allowPtrace"]`.
|
||||
|
|
|
@ -1148,33 +1148,6 @@ async function scheduleTools() {
|
|||
]
|
||||
}));
|
||||
|
||||
queue.scheduleTask(merge(base, {
|
||||
symbol: "coverity",
|
||||
name: "coverity",
|
||||
image: FUZZ_IMAGE,
|
||||
tags: ['code-review'],
|
||||
env: {
|
||||
USE_64: "1",
|
||||
CC: "clang",
|
||||
CCC: "clang++",
|
||||
NSS_AUTOMATION: "1"
|
||||
},
|
||||
features: ["taskclusterProxy"],
|
||||
scopes: ["secrets:get:project/relman/coverity-nss"],
|
||||
artifacts: {
|
||||
"public/code-review/coverity.json": {
|
||||
expires: 24 * 7,
|
||||
type: "file",
|
||||
path: "/home/worker/nss/coverity/coverity.json"
|
||||
}
|
||||
},
|
||||
command: [
|
||||
"/bin/bash",
|
||||
"-c",
|
||||
"bin/checkout.sh && nss/automation/taskcluster/scripts/run_coverity.sh"
|
||||
]
|
||||
}));
|
||||
|
||||
queue.scheduleTask(merge(base, {
|
||||
symbol: "hacl",
|
||||
name: "hacl",
|
||||
|
|
|
@ -10,12 +10,6 @@ const main = async () => {
|
|||
// Init try syntax filter.
|
||||
if (process.env.TC_PROJECT == "nss-try") {
|
||||
await try_syntax.initFilter();
|
||||
} else {
|
||||
// Coverity should not be run on landings, only by request (typically
|
||||
// by Phabricator).
|
||||
queue.filter(task => {
|
||||
return task.symbol != "coverity";
|
||||
});
|
||||
}
|
||||
|
||||
// Extend the task graph.
|
||||
|
|
|
@ -57,7 +57,7 @@ function parseOptions(opts) {
|
|||
}
|
||||
|
||||
// Parse tools.
|
||||
let allTools = ["clang-format", "scan-build", "coverity", "hacl", "saw", "abi", "coverage"];
|
||||
let allTools = ["clang-format", "scan-build", "hacl", "saw", "abi", "coverage"];
|
||||
let tools = intersect(opts.tools.split(/\s*,\s*/), allTools);
|
||||
|
||||
// If the given value is "all" run all tools.
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source $(dirname "$0")/tools.sh
|
||||
|
||||
# Clone NSPR if needed.
|
||||
if [ ! -d "nspr" ]; then
|
||||
hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
|
||||
|
||||
if [[ -f nss/nspr.patch && "$ALLOW_NSPR_PATCH" == "1" ]]; then
|
||||
pushd nspr
|
||||
cat ../nss/nspr.patch | patch -p1
|
||||
popd
|
||||
fi
|
||||
fi
|
||||
|
||||
# Build and run Coverity
|
||||
cd nss
|
||||
./mach static-analysis
|
||||
|
||||
# Return the exit code of the Coverity Analysis
|
||||
exit $?
|
|
@ -76,6 +76,7 @@ NSS_SRCDIRS = \
|
|||
symkeyutil \
|
||||
tests \
|
||||
tstclnt \
|
||||
validation \
|
||||
vfychain \
|
||||
vfyserv \
|
||||
modutil \
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#! 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 ../platlibs.mk
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
|
||||
include ../platrules.mk
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#
|
||||
# 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 = ../..
|
||||
|
||||
DEFINES += -DNSPR20
|
||||
|
||||
# MODULE public and private header directories are implicitly REQUIRED.
|
||||
MODULE = nss
|
||||
|
||||
CSRCS = \
|
||||
validation.c \
|
||||
$(NULL)
|
||||
|
||||
# The MODULE is always implicitly required.
|
||||
# Listing it here in REQUIRES makes it appear twice in the cc command line.
|
||||
REQUIRES = dbm seccmd
|
||||
|
||||
PROGRAM = validation
|
||||
|
||||
# USE_STATIC_LIBS = 1
|
|
@ -0,0 +1,251 @@
|
|||
/* 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/. */
|
||||
|
||||
#ifdef _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#include "nspr.h"
|
||||
#include "secutil.h"
|
||||
#include "pk11func.h"
|
||||
#include "nss.h"
|
||||
#include "secport.h"
|
||||
#include "secpkcs5.h"
|
||||
#include "sechash.h"
|
||||
#include "certdb.h"
|
||||
#include "secmod.h"
|
||||
|
||||
static char *progName;
|
||||
PRBool debug = PR_FALSE;
|
||||
|
||||
#define ERR_USAGE 2
|
||||
#define ERR_PK11GETSLOT 13
|
||||
|
||||
static void
|
||||
Usage()
|
||||
{
|
||||
#define FPS PR_fprintf(PR_STDERR,
|
||||
FPS "Usage: %s [-d certdir] [-P dbprefix] [-h tokenname]\n",
|
||||
progName);
|
||||
FPS "\t\t [-k slotpwfile | -K slotpw] [-v]\n");
|
||||
|
||||
exit(ERR_USAGE);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
tagULong,
|
||||
tagVersion,
|
||||
tagUtf8
|
||||
} tagType;
|
||||
|
||||
typedef struct {
|
||||
const char *attributeName;
|
||||
tagType attributeStorageType;
|
||||
} attributeTag;
|
||||
|
||||
enum {
|
||||
opt_CertDir = 0,
|
||||
opt_TokenName,
|
||||
opt_SlotPWFile,
|
||||
opt_SlotPW,
|
||||
opt_DBPrefix,
|
||||
opt_Debug
|
||||
};
|
||||
|
||||
static secuCommandFlag validation_options[] =
|
||||
{
|
||||
{ /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_SlotPWFile */ 'k', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_SlotPW */ 'K', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_DBPrefix */ 'P', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_Debug */ 'v', PR_FALSE, 0, PR_FALSE }
|
||||
};
|
||||
|
||||
void
|
||||
dump_Raw(char *label, CK_ATTRIBUTE *attr)
|
||||
{
|
||||
int i;
|
||||
unsigned char *value = (unsigned char *)attr->pValue;
|
||||
printf("0x");
|
||||
for (i = 0; i < attr->ulValueLen; i++) {
|
||||
printf("%02x", value[i]);
|
||||
}
|
||||
printf("<%s>\n", label);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
dump_validations(CK_OBJECT_CLASS objc, CK_ATTRIBUTE *template, int count,
|
||||
attributeTag *tags, PK11SlotInfo *slot)
|
||||
{
|
||||
PK11GenericObject *objs, *obj;
|
||||
|
||||
objs = PK11_FindGenericObjects(slot, objc);
|
||||
|
||||
for (obj = objs; obj != NULL; obj = PK11_GetNextGenericObject(obj)) {
|
||||
int i;
|
||||
printf("Validation Object:\n");
|
||||
PK11_ReadRawAttributes(NULL, PK11_TypeGeneric, obj, template, count);
|
||||
for (i = 0; i < count; i++) {
|
||||
CK_ULONG ulong;
|
||||
CK_VERSION version;
|
||||
int len = template[i].ulValueLen;
|
||||
printf(" %s: ", tags[i].attributeName);
|
||||
if (len < 0) {
|
||||
printf("<failed>\n");
|
||||
} else if (len == 0) {
|
||||
printf("<empty>\n");
|
||||
} else
|
||||
switch (tags[i].attributeStorageType) {
|
||||
case tagULong:
|
||||
if (len != sizeof(CK_ULONG)) {
|
||||
dump_Raw("bad ulong", &template[i]);
|
||||
break;
|
||||
}
|
||||
ulong = *(CK_ULONG *)template[i].pValue;
|
||||
printf("%ld\n", ulong);
|
||||
break;
|
||||
case tagVersion:
|
||||
if (len != sizeof(CK_VERSION)) {
|
||||
dump_Raw("bad version", &template[i]);
|
||||
break;
|
||||
}
|
||||
version = *(CK_VERSION *)template[i].pValue;
|
||||
printf("%d.%d\n", version.major, version.minor);
|
||||
break;
|
||||
case tagUtf8:
|
||||
printf("%.*s\n", len, (char *)template[i].pValue);
|
||||
break;
|
||||
default:
|
||||
dump_Raw("unknown tag", &template[i]);
|
||||
break;
|
||||
}
|
||||
PORT_Free(template[i].pValue);
|
||||
template[i].pValue = NULL;
|
||||
template[i].ulValueLen = 0;
|
||||
}
|
||||
}
|
||||
PK11_DestroyGenericObjects(objs);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
secuPWData slotPw = { PW_NONE, NULL };
|
||||
secuPWData p12FilePw = { PW_NONE, NULL };
|
||||
PK11SlotInfo *slot = NULL;
|
||||
char *slotname = NULL;
|
||||
char *dbprefix = "";
|
||||
char *nssdir = NULL;
|
||||
SECStatus rv;
|
||||
secuCommand validation;
|
||||
int local_errno = 0;
|
||||
|
||||
CK_ATTRIBUTE validation_template[] = {
|
||||
{ CKA_NSS_VALIDATION_TYPE, NULL, 0 },
|
||||
{ CKA_NSS_VALIDATION_VERSION, NULL, 0 },
|
||||
{ CKA_NSS_VALIDATION_LEVEL, NULL, 0 },
|
||||
{ CKA_NSS_VALIDATION_MODULE_ID, NULL, 0 }
|
||||
};
|
||||
attributeTag validation_tags[] = {
|
||||
{ "Validation Type", tagULong },
|
||||
{ "Validation Version", tagVersion },
|
||||
{ "Validation Level", tagULong },
|
||||
{ "Validation Module ID", tagUtf8 },
|
||||
};
|
||||
|
||||
#ifdef _CRTDBG_MAP_ALLOC
|
||||
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
||||
#endif
|
||||
|
||||
validation.numCommands = 0;
|
||||
validation.commands = 0;
|
||||
validation.numOptions = PR_ARRAY_SIZE(validation_options);
|
||||
validation.options = validation_options;
|
||||
|
||||
progName = strrchr(argv[0], '/');
|
||||
progName = progName ? progName + 1 : argv[0];
|
||||
|
||||
rv = SECU_ParseCommandLine(argc, argv, progName, &validation);
|
||||
|
||||
if (rv != SECSuccess)
|
||||
Usage();
|
||||
|
||||
debug = validation.options[opt_Debug].activated;
|
||||
|
||||
slotname = SECU_GetOptionArg(&validation, opt_TokenName);
|
||||
|
||||
if (validation.options[opt_SlotPWFile].activated) {
|
||||
slotPw.source = PW_FROMFILE;
|
||||
slotPw.data = PORT_Strdup(validation.options[opt_SlotPWFile].arg);
|
||||
}
|
||||
|
||||
if (validation.options[opt_SlotPW].activated) {
|
||||
slotPw.source = PW_PLAINTEXT;
|
||||
slotPw.data = PORT_Strdup(validation.options[opt_SlotPW].arg);
|
||||
}
|
||||
|
||||
if (validation.options[opt_CertDir].activated) {
|
||||
nssdir = validation.options[opt_CertDir].arg;
|
||||
}
|
||||
if (validation.options[opt_DBPrefix].activated) {
|
||||
dbprefix = validation.options[opt_DBPrefix].arg;
|
||||
}
|
||||
|
||||
PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
|
||||
if (nssdir == NULL && NSS_NoDB_Init("") == SECSuccess) {
|
||||
rv = SECSuccess;
|
||||
/* if the system isn't already in FIPS mode, we need
|
||||
* to switch to FIPS mode */
|
||||
if (!PK11_IsFIPS()) {
|
||||
/* flip to FIPS mode */
|
||||
SECMODModule *module = SECMOD_GetInternalModule();
|
||||
rv = SECMOD_DeleteInternalModule(module->commonName);
|
||||
}
|
||||
} else if (nssdir != NULL) {
|
||||
rv = NSS_Initialize(nssdir, dbprefix, dbprefix, "secmod.db", 0);
|
||||
}
|
||||
if (rv != SECSuccess) {
|
||||
SECU_PrintPRandOSError(progName);
|
||||
local_errno = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!slotname || PL_strcmp(slotname, "internal") == 0)
|
||||
slot = PK11_GetInternalKeySlot();
|
||||
else
|
||||
slot = PK11_FindSlotByName(slotname);
|
||||
|
||||
if (!slot) {
|
||||
SECU_PrintError(progName, "Invalid slot \"%s\"",
|
||||
slotname ? "internal" : slotname);
|
||||
local_errno = ERR_PK11GETSLOT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rv = dump_validations(CKO_NSS_VALIDATION,
|
||||
validation_template,
|
||||
PR_ARRAY_SIZE(validation_template),
|
||||
validation_tags,
|
||||
slot);
|
||||
|
||||
done:
|
||||
if (slotPw.data != NULL)
|
||||
PORT_ZFree(slotPw.data, PL_strlen(slotPw.data));
|
||||
if (p12FilePw.data != NULL)
|
||||
PORT_ZFree(p12FilePw.data, PL_strlen(p12FilePw.data));
|
||||
if (slotname) {
|
||||
PORT_Free(slotname);
|
||||
}
|
||||
if (slot)
|
||||
PK11_FreeSlot(slot);
|
||||
if (NSS_Shutdown() != SECSuccess) {
|
||||
local_errno = 1;
|
||||
}
|
||||
PL_ArenaFinish();
|
||||
PR_Cleanup();
|
||||
return local_errno;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
# 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',
|
||||
'../../cmd/platlibs.gypi'
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'validation',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'validation.c'
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/exports.gyp:dbm_exports',
|
||||
'<(DEPTH)/exports.gyp:nss_exports'
|
||||
]
|
||||
}
|
||||
],
|
||||
'target_defaults': {
|
||||
'defines': [
|
||||
'NSPR20'
|
||||
]
|
||||
},
|
||||
'variables': {
|
||||
'module': 'nss'
|
||||
}
|
||||
}
|
|
@ -10,4 +10,3 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -1073,6 +1073,7 @@ pkix_CacheCert_Lookup(
|
|||
(PKIX_PL_Object *)cert,
|
||||
plContext),
|
||||
PKIX_LISTAPPENDITEMFAILED);
|
||||
*pFound = PKIX_TRUE;
|
||||
} else {
|
||||
PKIX_DECREF(selectorError);
|
||||
}
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define NSS_VERSION "3.72" _NSS_CUSTOMIZED
|
||||
#define NSS_VERSION "3.73" _NSS_CUSTOMIZED " Beta"
|
||||
#define NSS_VMAJOR 3
|
||||
#define NSS_VMINOR 72
|
||||
#define NSS_VMINOR 73
|
||||
#define NSS_VPATCH 0
|
||||
#define NSS_VBUILD 0
|
||||
#define NSS_BETA PR_FALSE
|
||||
#define NSS_BETA PR_TRUE
|
||||
|
||||
#ifndef RC_INVOKED
|
||||
|
||||
|
|
|
@ -59,3 +59,7 @@ ifdef NSS_ENABLE_FIPS_INDICATORS
|
|||
DEFINES += -DNSS_ENABLE_FIPS_INDICATORS
|
||||
endif
|
||||
|
||||
ifdef NSS_FIPS_MODULE_ID
|
||||
DEFINES += -DNSS_FIPS_MODULE_ID=\"${NSS_FIPS_MODULE_ID}\"
|
||||
endif
|
||||
|
||||
|
|
|
@ -75,7 +75,6 @@ static char libraryDescription_space[33];
|
|||
* failure so that there are at most 60 login attempts per minute.
|
||||
*/
|
||||
static PRIntervalTime loginWaitTime;
|
||||
static PRUint32 minSessionObjectHandle = 1U;
|
||||
|
||||
#define __PASTE(x, y) x##y
|
||||
|
||||
|
@ -1672,8 +1671,6 @@ sftk_handleObject(SFTKObject *object, SFTKSession *session)
|
|||
{
|
||||
SFTKSlot *slot = session->slot;
|
||||
SFTKAttribute *attribute;
|
||||
SFTKObject *duplicateObject = NULL;
|
||||
CK_OBJECT_HANDLE handle;
|
||||
CK_BBOOL ckfalse = CK_FALSE;
|
||||
CK_BBOOL cktrue = CK_TRUE;
|
||||
CK_RV crv;
|
||||
|
@ -1711,30 +1708,13 @@ sftk_handleObject(SFTKObject *object, SFTKSession *session)
|
|||
* token objects and will have a token object handle assigned to
|
||||
* them by a call to sftk_mkHandle in the handler for each object
|
||||
* class, invoked below.
|
||||
*
|
||||
*
|
||||
* It may be helpful to note/remember that
|
||||
* sftk_narrowToXxxObject uses sftk_isToken,
|
||||
* sftk_isToken examines the sign bit of the object's handle, but
|
||||
* sftk_isTrue(...,CKA_TOKEN) examines the CKA_TOKEN attribute.
|
||||
*/
|
||||
do {
|
||||
PRUint32 wrappedAround;
|
||||
|
||||
duplicateObject = NULL;
|
||||
PZ_Lock(slot->objectLock);
|
||||
wrappedAround = slot->sessionObjectHandleCount & SFTK_TOKEN_MASK;
|
||||
handle = slot->sessionObjectHandleCount & ~SFTK_TOKEN_MASK;
|
||||
if (!handle) /* don't allow zero handle */
|
||||
handle = minSessionObjectHandle;
|
||||
slot->sessionObjectHandleCount = (handle + 1U) | wrappedAround;
|
||||
/* Is there already a session object with this handle? */
|
||||
if (wrappedAround) {
|
||||
sftkqueue_find(duplicateObject, handle, slot->sessObjHashTable,
|
||||
slot->sessObjHashSize);
|
||||
}
|
||||
PZ_Unlock(slot->objectLock);
|
||||
} while (duplicateObject != NULL);
|
||||
object->handle = handle;
|
||||
object->handle = sftk_getNextHandle(slot);
|
||||
|
||||
/* get the object class */
|
||||
attribute = sftk_FindAttribute(object, CKA_CLASS);
|
||||
|
@ -2875,10 +2855,15 @@ SFTK_SlotInit(char *configdir, char *updatedir, char *updateID,
|
|||
goto mem_loser;
|
||||
|
||||
slot->sessionIDCount = 0;
|
||||
slot->sessionObjectHandleCount = minSessionObjectHandle;
|
||||
slot->sessionObjectHandleCount = NSC_MIN_SESSION_OBJECT_HANDLE;
|
||||
slot->slotID = slotID;
|
||||
sftk_setStringName(params->slotdes ? params->slotdes : sftk_getDefSlotName(slotID), slot->slotDescription,
|
||||
sizeof(slot->slotDescription), PR_TRUE);
|
||||
crv = sftk_InitSession(&slot->moduleObjects, slot, slotID, NULL, NULL,
|
||||
CKF_SERIAL_SESSION);
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* call the reinit code to set everything that changes between token
|
||||
* init calls */
|
||||
|
@ -2887,6 +2872,12 @@ SFTK_SlotInit(char *configdir, char *updatedir, char *updateID,
|
|||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
if (sftk_isFIPS(slotID)) {
|
||||
crv = sftk_CreateValidationObjects(slot);
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
crv = sftk_RegisterSlot(slot, moduleIndex);
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
|
@ -3032,6 +3023,8 @@ SFTK_DestroySlotData(SFTKSlot *slot)
|
|||
|
||||
SFTK_ShutdownSlot(slot);
|
||||
|
||||
sftk_ClearSession(&slot->moduleObjects);
|
||||
|
||||
if (slot->tokObjHashTable) {
|
||||
PL_HashTableDestroy(slot->tokObjHashTable);
|
||||
slot->tokObjHashTable = NULL;
|
||||
|
@ -3262,6 +3255,7 @@ nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
|
|||
CK_RV crv = CKR_OK;
|
||||
SECStatus rv;
|
||||
CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *)pReserved;
|
||||
PRBool destroy_freelist_on_error = PR_TRUE;
|
||||
int i;
|
||||
unsigned int moduleIndex = isFIPS ? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE;
|
||||
|
||||
|
@ -3341,7 +3335,14 @@ nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
|
|||
"disabled FIPS mode");
|
||||
}
|
||||
}
|
||||
/* if we have a peer open, we don't want to destroy the freelist
|
||||
* from under the peer if we fail, the free list will be
|
||||
* destroyed in that case when the C_Finalize is called for
|
||||
* the peer */
|
||||
destroy_freelist_on_error = PR_FALSE;
|
||||
}
|
||||
/* allow us to create objects in SFTK_SlotInit */
|
||||
sftk_InitFreeLists();
|
||||
|
||||
for (i = 0; i < paramStrings.token_count; i++) {
|
||||
crv = SFTK_SlotInit(paramStrings.configdir,
|
||||
|
@ -3355,8 +3356,9 @@ nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
|
|||
loser:
|
||||
sftk_freeParams(¶mStrings);
|
||||
}
|
||||
if (CKR_OK == crv) {
|
||||
sftk_InitFreeLists();
|
||||
if (destroy_freelist_on_error && (CKR_OK != crv)) {
|
||||
/* idempotent. If the list are already freed, this is a noop */
|
||||
sftk_CleanupFreeLists();
|
||||
}
|
||||
|
||||
#ifndef NO_FORK_CHECK
|
||||
|
|
|
@ -49,6 +49,8 @@
|
|||
#define NSC_SEARCH_BLOCK_SIZE 5
|
||||
#define NSC_SLOT_LIST_BLOCK_SIZE 10
|
||||
|
||||
#define NSC_MIN_SESSION_OBJECT_HANDLE 1U
|
||||
|
||||
#define NSC_FIPS_MODULE 1
|
||||
#define NSC_NON_FIPS_MODULE 0
|
||||
|
||||
|
@ -375,6 +377,9 @@ struct SFTKSlotStr {
|
|||
char tokDescription[33]; /* per load */
|
||||
char updateTokDescription[33]; /* per load */
|
||||
char slotDescription[65]; /* invariant */
|
||||
SFTKSession moduleObjects; /* global session to hang module specific
|
||||
* objects like profile objects or
|
||||
* validation objects */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -766,6 +771,7 @@ extern CK_RV sftk_DeleteObject(SFTKSession *session, SFTKObject *object);
|
|||
extern void sftk_ReferenceObject(SFTKObject *object);
|
||||
extern SFTKObject *sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle,
|
||||
SFTKSession *session);
|
||||
extern CK_OBJECT_HANDLE sftk_getNextHandle(SFTKSlot *slot);
|
||||
extern void sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object);
|
||||
extern void sftk_AddObject(SFTKSession *session, SFTKObject *object);
|
||||
/* clear out all the existing object ID to database key mappings.
|
||||
|
@ -787,7 +793,11 @@ extern SFTKSlot *sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle);
|
|||
extern CK_SLOT_ID sftk_SlotIDFromSessionHandle(CK_SESSION_HANDLE handle);
|
||||
extern SFTKSession *sftk_SessionFromHandle(CK_SESSION_HANDLE handle);
|
||||
extern void sftk_FreeSession(SFTKSession *session);
|
||||
extern void sftk_ClearSession(SFTKSession *session);
|
||||
extern void sftk_DestroySession(SFTKSession *session);
|
||||
extern CK_RV sftk_InitSession(SFTKSession *session, SFTKSlot *slot,
|
||||
CK_SLOT_ID slotID, CK_NOTIFY notify,
|
||||
CK_VOID_PTR pApplication, CK_FLAGS flags);
|
||||
extern SFTKSession *sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify,
|
||||
CK_VOID_PTR pApplication, CK_FLAGS flags);
|
||||
extern void sftk_update_state(SFTKSlot *slot, SFTKSession *session);
|
||||
|
@ -955,6 +965,9 @@ CK_FLAGS sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE op);
|
|||
* FIPS security policy */
|
||||
PRBool sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech,
|
||||
CK_ATTRIBUTE_TYPE op, SFTKObject *source);
|
||||
/* add validation objects to the slot */
|
||||
CK_RV sftk_CreateValidationObjects(SFTKSlot *slot);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif /* _PKCS11I_H_ */
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "sftkdb.h"
|
||||
#include "softoken.h"
|
||||
#include "secoid.h"
|
||||
#include "softkver.h"
|
||||
|
||||
#if !defined(NSS_FIPS_DISABLED) && defined(NSS_ENABLE_FIPS_INDICATORS)
|
||||
/* this file should be supplied by the vendor and include all the
|
||||
|
@ -1243,6 +1244,36 @@ sftk_FreeObject(SFTKObject *object)
|
|||
return SFTK_Busy;
|
||||
}
|
||||
|
||||
/* find the next available object handle that isn't currently in use */
|
||||
/* NOTE: This function could loop forever if we've exhausted all
|
||||
* 3^31-1 handles. This is highly unlikely (NSS has been running for
|
||||
* decades with this code) uless we start increasing the size of the
|
||||
* SFTK_TOKEN_MASK (which is just the high bit currently). */
|
||||
CK_OBJECT_HANDLE
|
||||
sftk_getNextHandle(SFTKSlot *slot)
|
||||
{
|
||||
CK_OBJECT_HANDLE handle;
|
||||
SFTKObject *duplicateObject = NULL;
|
||||
do {
|
||||
PRUint32 wrappedAround;
|
||||
|
||||
duplicateObject = NULL;
|
||||
PZ_Lock(slot->objectLock);
|
||||
wrappedAround = slot->sessionObjectHandleCount & SFTK_TOKEN_MASK;
|
||||
handle = slot->sessionObjectHandleCount & ~SFTK_TOKEN_MASK;
|
||||
if (!handle) /* don't allow zero handle */
|
||||
handle = NSC_MIN_SESSION_OBJECT_HANDLE;
|
||||
slot->sessionObjectHandleCount = (handle + 1U) | wrappedAround;
|
||||
/* Is there already a session object with this handle? */
|
||||
if (wrappedAround) {
|
||||
sftkqueue_find(duplicateObject, handle, slot->sessObjHashTable,
|
||||
slot->sessObjHashSize);
|
||||
}
|
||||
PZ_Unlock(slot->objectLock);
|
||||
} while (duplicateObject != NULL);
|
||||
return handle;
|
||||
}
|
||||
|
||||
/*
|
||||
* add an object to a slot and session queue. These two functions
|
||||
* adopt the object.
|
||||
|
@ -1848,23 +1879,13 @@ sftk_FreeContext(SFTKSessionContext *context)
|
|||
}
|
||||
|
||||
/*
|
||||
* create a new nession. NOTE: The session handle is not set, and the
|
||||
* Init a new session. NOTE: The session handle is not set, and the
|
||||
* session is not added to the slot's session queue.
|
||||
*/
|
||||
SFTKSession *
|
||||
sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
|
||||
CK_FLAGS flags)
|
||||
CK_RV
|
||||
sftk_InitSession(SFTKSession *session, SFTKSlot *slot, CK_SLOT_ID slotID,
|
||||
CK_NOTIFY notify, CK_VOID_PTR pApplication, CK_FLAGS flags)
|
||||
{
|
||||
SFTKSession *session;
|
||||
SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
|
||||
|
||||
if (slot == NULL)
|
||||
return NULL;
|
||||
|
||||
session = (SFTKSession *)PORT_Alloc(sizeof(SFTKSession));
|
||||
if (session == NULL)
|
||||
return NULL;
|
||||
|
||||
session->next = session->prev = NULL;
|
||||
session->enc_context = NULL;
|
||||
session->hash_context = NULL;
|
||||
|
@ -1873,8 +1894,7 @@ sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
|
|||
session->objectIDCount = 1;
|
||||
session->objectLock = PZ_NewLock(nssILockObject);
|
||||
if (session->objectLock == NULL) {
|
||||
PORT_Free(session);
|
||||
return NULL;
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
session->objects[0] = NULL;
|
||||
|
||||
|
@ -1887,12 +1907,38 @@ sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
|
|||
sftk_update_state(slot, session);
|
||||
/* no ops completed yet, so the last one couldn't be a FIPS op */
|
||||
session->lastOpWasFIPS = PR_FALSE;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new session and init it.
|
||||
*/
|
||||
SFTKSession *
|
||||
sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
|
||||
CK_FLAGS flags)
|
||||
{
|
||||
SFTKSession *session;
|
||||
SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
|
||||
CK_RV crv;
|
||||
|
||||
if (slot == NULL)
|
||||
return NULL;
|
||||
|
||||
session = (SFTKSession *)PORT_Alloc(sizeof(SFTKSession));
|
||||
if (session == NULL)
|
||||
return NULL;
|
||||
|
||||
crv = sftk_InitSession(session, slot, slotID, notify, pApplication, flags);
|
||||
if (crv != CKR_OK) {
|
||||
PORT_Free(session);
|
||||
return NULL;
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
/* free all the data associated with a session. */
|
||||
void
|
||||
sftk_DestroySession(SFTKSession *session)
|
||||
sftk_ClearSession(SFTKSession *session)
|
||||
{
|
||||
SFTKObjectList *op, *next;
|
||||
|
||||
|
@ -1918,6 +1964,13 @@ sftk_DestroySession(SFTKSession *session)
|
|||
if (session->search) {
|
||||
sftk_FreeSearch(session->search);
|
||||
}
|
||||
}
|
||||
|
||||
/* free the data associated with the session, and the session */
|
||||
void
|
||||
sftk_DestroySession(SFTKSession *session)
|
||||
{
|
||||
sftk_ClearSession(session);
|
||||
PORT_Free(session);
|
||||
}
|
||||
|
||||
|
@ -2386,3 +2439,70 @@ sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech, CK_ATTRIBUTE_TYPE op,
|
|||
return PR_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* create the FIPS Validation objects. If the vendor
|
||||
* doesn't supply an NSS_FIPS_MODULE_ID, at compile time,
|
||||
* then we assumethis is an unvalidated module.
|
||||
*/
|
||||
CK_RV
|
||||
sftk_CreateValidationObjects(SFTKSlot *slot)
|
||||
{
|
||||
const char *module_id;
|
||||
int module_id_len;
|
||||
CK_RV crv = CKR_OK;
|
||||
/* we currently use vendor specific values until the validation
|
||||
* objects are approved for PKCS #11 v3.2. */
|
||||
CK_OBJECT_CLASS cko_validation = CKO_NSS_VALIDATION;
|
||||
CK_NSS_VALIDATION_TYPE ckv_fips = CKV_NSS_FIPS_140;
|
||||
CK_VERSION fips_version = { 3, 0 }; /* FIPS-140-3 */
|
||||
CK_ULONG fips_level = 1; /* or 2 if you validated at level 2 */
|
||||
|
||||
#ifndef NSS_FIPS_MODULE_ID
|
||||
#define NSS_FIPS_MODULE_ID "Generic NSS " SOFTOKEN_VERSION " Unvalidated"
|
||||
#endif
|
||||
module_id = NSS_FIPS_MODULE_ID;
|
||||
module_id_len = sizeof(NSS_FIPS_MODULE_ID) - 1;
|
||||
SFTKObject *object;
|
||||
|
||||
object = sftk_NewObject(slot); /* fill in the handle later */
|
||||
if (object == NULL) {
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
object->isFIPS = PR_FALSE;
|
||||
|
||||
crv = sftk_AddAttributeType(object, CKA_CLASS,
|
||||
&cko_validation, sizeof(cko_validation));
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_TYPE,
|
||||
&ckv_fips, sizeof(ckv_fips));
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_VERSION,
|
||||
&fips_version, sizeof(fips_version));
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_LEVEL,
|
||||
&fips_level, sizeof(fips_level));
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_MODULE_ID,
|
||||
module_id, module_id_len);
|
||||
if (crv != CKR_OK) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* future, fill in validation certificate information from a supplied
|
||||
* pointer to a config file */
|
||||
object->handle = sftk_getNextHandle(slot);
|
||||
object->slot = slot;
|
||||
sftk_AddObject(&slot->moduleObjects, object);
|
||||
loser:
|
||||
sftk_FreeObject(object);
|
||||
return crv;
|
||||
}
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define SOFTOKEN_VERSION "3.72" SOFTOKEN_ECC_STRING
|
||||
#define SOFTOKEN_VERSION "3.73" SOFTOKEN_ECC_STRING " Beta"
|
||||
#define SOFTOKEN_VMAJOR 3
|
||||
#define SOFTOKEN_VMINOR 72
|
||||
#define SOFTOKEN_VMINOR 73
|
||||
#define SOFTOKEN_VPATCH 0
|
||||
#define SOFTOKEN_VBUILD 0
|
||||
#define SOFTOKEN_BETA PR_FALSE
|
||||
#define SOFTOKEN_BETA PR_TRUE
|
||||
|
||||
#endif /* _SOFTKVER_H_ */
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
|
||||
*/
|
||||
#define NSSUTIL_VERSION "3.72"
|
||||
#define NSSUTIL_VERSION "3.73 Beta"
|
||||
#define NSSUTIL_VMAJOR 3
|
||||
#define NSSUTIL_VMINOR 72
|
||||
#define NSSUTIL_VMINOR 73
|
||||
#define NSSUTIL_VPATCH 0
|
||||
#define NSSUTIL_VBUILD 0
|
||||
#define NSSUTIL_BETA PR_FALSE
|
||||
#define NSSUTIL_BETA PR_TRUE
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
#define CKO_NSS_BUILTIN_ROOT_LIST (CKO_NSS + 4)
|
||||
#define CKO_NSS_NEWSLOT (CKO_NSS + 5)
|
||||
#define CKO_NSS_DELSLOT (CKO_NSS + 6)
|
||||
#define CKO_NSS_VALIDATION (CKO_NSS + 7)
|
||||
|
||||
#define CKV_NSS_FIPS_140 (CKO_NSS + 1)
|
||||
|
||||
/*
|
||||
* NSS-defined key types
|
||||
|
@ -99,6 +102,11 @@
|
|||
#define CKA_NSS_SERVER_DISTRUST_AFTER (CKA_NSS + 35)
|
||||
#define CKA_NSS_EMAIL_DISTRUST_AFTER (CKA_NSS + 36)
|
||||
|
||||
#define CKA_NSS_VALIDATION_TYPE (CKA_NSS + 36)
|
||||
#define CKA_NSS_VALIDATION_VERSION (CKA_NSS + 37)
|
||||
#define CKA_NSS_VALIDATION_LEVEL (CKA_NSS + 38)
|
||||
#define CKA_NSS_VALIDATION_MODULE_ID (CKA_NSS + 39)
|
||||
|
||||
/*
|
||||
* Trust attributes:
|
||||
*
|
||||
|
@ -344,6 +352,9 @@ typedef struct CK_NSS_AEAD_PARAMS {
|
|||
#define CKR_NSS_CERTDB_FAILED (CKR_NSS + 1)
|
||||
#define CKR_NSS_KEYDB_FAILED (CKR_NSS + 2)
|
||||
|
||||
/* NSS specific types */
|
||||
typedef CK_ULONG CK_NSS_VALIDATION_TYPE;
|
||||
|
||||
/* Mandatory parameter for the CKM_NSS_HKDF_* key deriviation mechanisms.
|
||||
See RFC 5869.
|
||||
|
||||
|
|
|
@ -41,277 +41,6 @@ def run_tests(test, cycles="standard", env={}, silent=False):
|
|||
subprocess.check_call(command, env=os_env, stdout=stdout, stderr=stderr)
|
||||
|
||||
|
||||
class coverityAction(argparse.Action):
|
||||
|
||||
def get_coverity_remote_cfg(self):
|
||||
secret_name = 'project/relman/coverity-nss'
|
||||
secrets_url = 'http://taskcluster/secrets/v1/secret/{}'.format(secret_name)
|
||||
|
||||
print('Using symbol upload token from the secrets service: "{}"'.
|
||||
format(secrets_url))
|
||||
|
||||
import requests
|
||||
res = requests.get(secrets_url)
|
||||
res.raise_for_status()
|
||||
secret = res.json()
|
||||
cov_config = secret['secret'] if 'secret' in secret else None
|
||||
|
||||
if cov_config is None:
|
||||
print('Ill formatted secret for Coverity. Aborting analysis.')
|
||||
return None
|
||||
|
||||
return cov_config
|
||||
|
||||
def get_coverity_local_cfg(self, path):
|
||||
try:
|
||||
import yaml
|
||||
file_handler = open(path)
|
||||
config = yaml.safe_load(file_handler)
|
||||
except Exception:
|
||||
print('Unable to load coverity config from {}'.format(path))
|
||||
return None
|
||||
return config
|
||||
|
||||
def get_cov_config(self, path):
|
||||
cov_config = None
|
||||
if self.local_config:
|
||||
cov_config = self.get_coverity_local_cfg(path)
|
||||
else:
|
||||
cov_config = self.get_coverity_remote_cfg()
|
||||
|
||||
if cov_config is None:
|
||||
print('Unable to load Coverity config.')
|
||||
return 1
|
||||
|
||||
self.cov_analysis_url = cov_config.get('package_url')
|
||||
self.cov_package_name = cov_config.get('package_name')
|
||||
self.cov_url = cov_config.get('server_url')
|
||||
self.cov_port = cov_config.get('server_port')
|
||||
self.cov_auth = cov_config.get('auth_key')
|
||||
self.cov_package_ver = cov_config.get('package_ver')
|
||||
self.cov_full_stack = cov_config.get('full_stack', False)
|
||||
|
||||
return 0
|
||||
|
||||
def download_coverity(self):
|
||||
if self.cov_url is None or self.cov_port is None or self.cov_analysis_url is None or self.cov_auth is None:
|
||||
print('Missing Coverity config options!')
|
||||
return 1
|
||||
|
||||
COVERITY_CONFIG = '''
|
||||
{
|
||||
"type": "Coverity configuration",
|
||||
"format_version": 1,
|
||||
"settings": {
|
||||
"server": {
|
||||
"host": "%s",
|
||||
"port": %s,
|
||||
"ssl" : true,
|
||||
"on_new_cert" : "trust",
|
||||
"auth_key_file": "%s"
|
||||
},
|
||||
"stream": "NSS",
|
||||
"cov_run_desktop": {
|
||||
"build_cmd": ["%s"],
|
||||
"clean_cmd": ["%s", "-cc"],
|
||||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
# Generate the coverity.conf and auth files
|
||||
build_cmd = os.path.join(cwd, 'build.sh')
|
||||
cov_auth_path = os.path.join(self.cov_state_path, 'auth')
|
||||
cov_setup_path = os.path.join(self.cov_state_path, 'coverity.conf')
|
||||
cov_conf = COVERITY_CONFIG % (self.cov_url, self.cov_port, cov_auth_path, build_cmd, build_cmd)
|
||||
|
||||
def download(artifact_url, target):
|
||||
import requests
|
||||
resp = requests.get(artifact_url, verify=False, stream=True)
|
||||
resp.raise_for_status()
|
||||
|
||||
# Extract archive into destination
|
||||
with tarfile.open(fileobj=io.BytesIO(resp.content)) as tar:
|
||||
tar.extractall(target)
|
||||
|
||||
download(self.cov_analysis_url, self.cov_state_path)
|
||||
|
||||
with open(cov_auth_path, 'w') as f:
|
||||
f.write(self.cov_auth)
|
||||
|
||||
# Modify it's permission to 600
|
||||
os.chmod(cov_auth_path, 0o600)
|
||||
|
||||
with open(cov_setup_path, 'a') as f:
|
||||
f.write(cov_conf)
|
||||
|
||||
def setup_coverity(self, config_path, storage_path=None, force_download=True):
|
||||
rc = self.get_cov_config(config_path)
|
||||
|
||||
if rc != 0:
|
||||
return rc
|
||||
|
||||
if storage_path is None:
|
||||
# If storage_path is None we set the context of the coverity into the cwd.
|
||||
storage_path = cwd
|
||||
|
||||
self.cov_state_path = os.path.join(storage_path, "coverity")
|
||||
|
||||
if force_download is True or not os.path.exists(self.cov_state_path):
|
||||
shutil.rmtree(self.cov_state_path, ignore_errors=True)
|
||||
os.mkdir(self.cov_state_path)
|
||||
|
||||
# Download everything that we need for Coverity from out private instance
|
||||
self.download_coverity()
|
||||
|
||||
self.cov_path = os.path.join(self.cov_state_path, self.cov_package_name)
|
||||
self.cov_run_desktop = os.path.join(self.cov_path, 'bin', 'cov-run-desktop')
|
||||
self.cov_translate = os.path.join(self.cov_path, 'bin', 'cov-translate')
|
||||
self.cov_configure = os.path.join(self.cov_path, 'bin', 'cov-configure')
|
||||
self.cov_work_path = os.path.join(self.cov_state_path, 'data-coverity')
|
||||
self.cov_idir_path = os.path.join(self.cov_work_path, self.cov_package_ver, 'idir')
|
||||
|
||||
if not os.path.exists(self.cov_path) or \
|
||||
not os.path.exists(self.cov_run_desktop) or \
|
||||
not os.path.exists(self.cov_translate) or \
|
||||
not os.path.exists(self.cov_configure):
|
||||
print('Missing Coverity in {}'.format(self.cov_path))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
def run_process(self, args, cwd=cwd):
|
||||
proc = subprocess.Popen(args, cwd=cwd)
|
||||
status = None
|
||||
while status is None:
|
||||
try:
|
||||
status = proc.wait()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
return status
|
||||
|
||||
def cov_is_file_in_source(self, abs_path):
|
||||
if os.path.islink(abs_path):
|
||||
abs_path = os.path.realpath(abs_path)
|
||||
return abs_path
|
||||
|
||||
def dump_cov_artifact(self, cov_results, source, output):
|
||||
import json
|
||||
|
||||
def relpath(path):
|
||||
'''Build path relative to repository root'''
|
||||
if path.startswith(cwd):
|
||||
return os.path.relpath(path, cwd)
|
||||
return path
|
||||
|
||||
# Parse Coverity json into structured issues
|
||||
with open(cov_results) as f:
|
||||
result = json.load(f)
|
||||
|
||||
# Parse the issues to a standard json format
|
||||
issues_dict = {'files': {}}
|
||||
|
||||
files_list = issues_dict['files']
|
||||
|
||||
def build_element(issue):
|
||||
# We look only for main event
|
||||
event_path = next((event for event in issue['events'] if event['main'] is True), None)
|
||||
|
||||
dict_issue = {
|
||||
'line': issue['mainEventLineNumber'],
|
||||
'flag': issue['checkerName'],
|
||||
'message': event_path['eventDescription'],
|
||||
'extra': {
|
||||
'category': issue['checkerProperties']['category'],
|
||||
'stateOnServer': issue['stateOnServer'],
|
||||
'stack': []
|
||||
}
|
||||
}
|
||||
|
||||
# Embed all events into extra message
|
||||
for event in issue['events']:
|
||||
dict_issue['extra']['stack'].append({'file_path': relpath(event['strippedFilePathname']),
|
||||
'line_number': event['lineNumber'],
|
||||
'path_type': event['eventTag'],
|
||||
'description': event['eventDescription']})
|
||||
|
||||
return dict_issue
|
||||
|
||||
for issue in result['issues']:
|
||||
path = self.cov_is_file_in_source(issue['strippedMainEventFilePathname'])
|
||||
if path is None:
|
||||
# Since we skip a result we should log it
|
||||
print('Skipping CID: {0} from file: {1} since it\'s not related with the current patch.'.format(
|
||||
issue['stateOnServer']['cid'], issue['strippedMainEventFilePathname']))
|
||||
continue
|
||||
# If path does not start with `cwd` skip it
|
||||
if not path.startswith(cwd):
|
||||
continue
|
||||
path = relpath(path)
|
||||
if path in files_list:
|
||||
files_list[path]['warnings'].append(build_element(issue))
|
||||
else:
|
||||
files_list[path] = {'warnings': [build_element(issue)]}
|
||||
|
||||
with open(output, 'w') as f:
|
||||
json.dump(issues_dict, f)
|
||||
|
||||
def mutate_paths(self, paths):
|
||||
for index in xrange(len(paths)):
|
||||
paths[index] = os.path.abspath(paths[index])
|
||||
|
||||
def __call__(self, parser, args, paths, option_string=None):
|
||||
self.local_config = True
|
||||
config_path = args.config
|
||||
storage_path = args.storage
|
||||
|
||||
have_paths = True
|
||||
if len(paths) == 0:
|
||||
have_paths = False
|
||||
print('No files have been specified for analysis, running Coverity on the entire project.')
|
||||
|
||||
self.mutate_paths(paths)
|
||||
|
||||
if config_path is None:
|
||||
self.local_config = False
|
||||
print('No coverity config path has been specified, so running in automation.')
|
||||
if 'NSS_AUTOMATION' not in os.environ:
|
||||
print('Coverity based static-analysis cannot be ran outside automation.')
|
||||
return 1
|
||||
|
||||
rc = self.setup_coverity(config_path, storage_path, args.force)
|
||||
if rc != 0:
|
||||
return 1
|
||||
|
||||
# First run cov-run-desktop --setup in order to setup the analysis env
|
||||
cmd = [self.cov_run_desktop, '--setup']
|
||||
print('Running {} --setup'.format(self.cov_run_desktop))
|
||||
|
||||
rc = self.run_process(args=cmd, cwd=self.cov_path)
|
||||
|
||||
if rc != 0:
|
||||
print('Running {} --setup failed!'.format(self.cov_run_desktop))
|
||||
return rc
|
||||
|
||||
cov_result = os.path.join(self.cov_state_path, 'cov-results.json')
|
||||
|
||||
# Once the capture is performed we need to do the actual Coverity Desktop analysis
|
||||
if have_paths:
|
||||
cmd = [self.cov_run_desktop, '--json-output-v6', cov_result] + paths
|
||||
else:
|
||||
cmd = [self.cov_run_desktop, '--json-output-v6', cov_result, '--analyze-captured-source']
|
||||
|
||||
print('Running Coverity Analysis for {}'.format(cmd))
|
||||
|
||||
rc = self.run_process(cmd, cwd=self.cov_state_path)
|
||||
|
||||
if rc != 0:
|
||||
print('Coverity Analysis failed!')
|
||||
|
||||
# On automation, like try, we want to build an artifact with the results.
|
||||
if 'NSS_AUTOMATION' in os.environ:
|
||||
self.dump_cov_artifact(cov_result, cov_result, "/home/worker/nss/coverity/coverity.json")
|
||||
|
||||
|
||||
class cfAction(argparse.Action):
|
||||
docker_command = None
|
||||
restorecon = None
|
||||
|
@ -535,31 +264,6 @@ def parse_arguments():
|
|||
help="Specify files or directories to run clang-format on",
|
||||
action=cfAction)
|
||||
|
||||
parser_sa = subparsers.add_parser(
|
||||
'static-analysis',
|
||||
help="""
|
||||
Run static-analysis tools based on coverity.
|
||||
|
||||
By default this runs only on automation and provides a list of issues that
|
||||
are only present locally.
|
||||
""")
|
||||
parser_sa.add_argument(
|
||||
'--config', help='Path to Coverity config file. Only used for local runs.',
|
||||
default=None)
|
||||
parser_sa.add_argument(
|
||||
'--storage', help="""
|
||||
Path where to store Coverity binaries and results. If none, the base repository will be used.
|
||||
""",
|
||||
default=None)
|
||||
parser_sa.add_argument(
|
||||
'--force', help='Force the re-download of the coverity artefact.',
|
||||
action='store_true')
|
||||
parser_sa.add_argument(
|
||||
'<file>',
|
||||
nargs='*',
|
||||
help="Specify files to run Coverity on. If no files are specified the analysis will check the entire project.",
|
||||
action=coverityAction)
|
||||
|
||||
parser_test = subparsers.add_parser(
|
||||
'tests', help='Run tests through tests/all.sh.')
|
||||
tests = [
|
||||
|
|
|
@ -131,6 +131,7 @@
|
|||
'cmd/smimetools/smimetools.gyp:cmsutil',
|
||||
'cmd/ssltap/ssltap.gyp:ssltap',
|
||||
'cmd/symkeyutil/symkeyutil.gyp:symkeyutil',
|
||||
'cmd/validation/validation.gyp:validation',
|
||||
'nss-tool/nss_tool.gyp:nss',
|
||||
'nss-tool/nss_tool.gyp:hw-support',
|
||||
],
|
||||
|
|
Загрузка…
Ссылка в новой задаче