Example #1
0
/*
 *  R e m o v e A l l A r c
 *
 *  Remove .arc directories that are lingering
 *  from a previous run of signtool.
 *
 */
int
RemoveAllArc(char *tree)
{
    PRDir * dir;
    PRDirEntry * entry;
    char	*archive = NULL;
    int	retval = 0;

    dir = PR_OpenDir (tree);
    if (!dir)
        return - 1;

    for (entry = PR_ReadDir (dir, 0); entry; entry = PR_ReadDir (dir,
            0)) {

        if (entry->name[0] == '.') {
            continue;
        }

        if (archive)
            PR_Free(archive);
        archive = PR_smprintf("%s/%s", tree, entry->name);

        if (PL_strcaserstr (entry->name, ".arc")
                == (entry->name + strlen(entry->name) - 4) ) {

            if (verbosity >= 0) {
                PR_fprintf(outputFD, "removing: %s\n", archive);
            }

            if (rm_dash_r(archive)) {
                PR_fprintf(errorFD, "Error removing %s\n", archive);
                errorCount++;
                retval = -1;
                goto finish;
            }
        } else if (is_dir(archive)) {
            if (RemoveAllArc(archive)) {
                retval = -1;
                goto finish;
            }
        }
    }

finish:
    PR_CloseDir (dir);
    if (archive)
        PR_Free(archive);

    return retval;
}
Example #2
0
/*
 *  r m _ d a s h _ r
 *
 *  Remove a file, or a directory recursively.
 *
 */
int
rm_dash_r(char *path)
{
    PRDir *dir;
    PRDirEntry *entry;
    PRFileInfo fileinfo;
    char filename[FNSIZE];

    if (PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) {
        /*fprintf(stderr, "Error: Unable to access %s\n", filename);*/
        return -1;
    }
    if (fileinfo.type == PR_FILE_DIRECTORY) {

        dir = PR_OpenDir(path);
        if (!dir) {
            PR_fprintf(errorFD, "Error: Unable to open directory %s.\n", path);
            errorCount++;
            return -1;
        }

        /* Recursively delete all entries in the directory */
        while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
            sprintf(filename, "%s/%s", path, entry->name);
            if (rm_dash_r(filename))
                return -1;
        }

        if (PR_CloseDir(dir) != PR_SUCCESS) {
            PR_fprintf(errorFD, "Error: Could not close %s.\n", path);
            errorCount++;
            return -1;
        }

        /* Delete the directory itself */
        if (PR_RmDir(path) != PR_SUCCESS) {
            PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
            errorCount++;
            return -1;
        }
    } else {
        if (PR_Delete(path) != PR_SUCCESS) {
            PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
            errorCount++;
            return -1;
        }
    }
    return 0;
}
Example #3
0
/*********************************************************************
 *
 * m a i n
 */
int
main(int argc, char *argv[])
{
    PRBool readOnly;
    int retval = 0;

    outputFD = PR_STDOUT;
    errorFD = PR_STDERR;

    progName = argv[0];

    if (argc < 2) {
        Usage();
    }

    excludeDirs = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
                                  PL_CompareStrings, NULL, NULL);
    extensions = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
                                 PL_CompareStrings, NULL, NULL);

    if (parse_args(argc, argv)) {
        retval = -1;
        goto cleanup;
    }

    /* Parse the command file if one was given */
    if (cmdFile) {
        if (ProcessCommandFile()) {
            retval = -1;
            goto cleanup;
        }
    }

    /* Set up output redirection */
    if (outfile) {
        if (PR_Access(outfile, PR_ACCESS_EXISTS) == PR_SUCCESS) {
            /* delete the file if it is already present */
            PR_fprintf(errorFD,
                       "warning: %s already exists and will be overwritten.\n",
                       outfile);
            warningCount++;
            if (PR_Delete(outfile) != PR_SUCCESS) {
                PR_fprintf(errorFD, "ERROR: unable to delete %s.\n", outfile);
                errorCount++;
                exit(ERRX);
            }
        }
        outputFD = PR_Open(outfile,
                           PR_WRONLY |
                               PR_CREATE_FILE | PR_TRUNCATE,
                           0777);
        if (!outputFD) {
            PR_fprintf(errorFD, "ERROR: Unable to create %s.\n",
                       outfile);
            errorCount++;
            exit(ERRX);
        }
        errorFD = outputFD;
    }

    /* This seems to be a fairly common user error */

    if (verify && list_certs > 0) {
        PR_fprintf(errorFD, "%s: Can't use -l and -v at the same time\n",
                   PROGRAM_NAME);
        errorCount++;
        retval = -1;
        goto cleanup;
    }

    /* -J assumes -Z now */

    if (javascript && zipfile) {
        PR_fprintf(errorFD, "%s: Can't use -J and -Z at the same time\n",
                   PROGRAM_NAME);
        PR_fprintf(errorFD, "%s: -J option will create the jar files for you\n",
                   PROGRAM_NAME);
        errorCount++;
        retval = -1;
        goto cleanup;
    }

    /* -X needs -Z */

    if (xpi_arc && !zipfile) {
        PR_fprintf(errorFD, "%s: option XPI (-X) requires option jarfile (-Z)\n",
                   PROGRAM_NAME);
        errorCount++;
        retval = -1;
        goto cleanup;
    }

    /* Less common mixing of -L with various options */

    if (list_certs > 0 &&
        (tell_who || zipfile || javascript ||
         scriptdir || extensionsGiven || exclusionsGiven || install_script)) {
        PR_fprintf(errorFD, "%s: Can't use -l or -L with that option\n",
                   PROGRAM_NAME);
        errorCount++;
        retval = -1;
        goto cleanup;
    }

    if (!cert_dir)
        cert_dir = get_default_cert_dir();

    VerifyCertDir(cert_dir, keyName);

    if (compression_level < MIN_COMPRESSION_LEVEL ||
        compression_level > MAX_COMPRESSION_LEVEL) {
        PR_fprintf(errorFD, "Compression level must be between %d and %d.\n",
                   MIN_COMPRESSION_LEVEL, MAX_COMPRESSION_LEVEL);
        errorCount++;
        retval = -1;
        goto cleanup;
    }

    if (jartree && !keyName) {
        PR_fprintf(errorFD, "You must specify a key with which to sign.\n");
        errorCount++;
        retval = -1;
        goto cleanup;
    }

    readOnly = (genkey == NULL); /* only key generation requires write */
    if (InitCrypto(cert_dir, readOnly)) {
        PR_fprintf(errorFD, "ERROR: Cryptographic initialization failed.\n");
        errorCount++;
        retval = -1;
        goto cleanup;
    }

    if (enableOCSP) {
        SECStatus rv = CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
        if (rv != SECSuccess) {
            PR_fprintf(errorFD, "ERROR: Attempt to enable OCSP Checking failed.\n");
            errorCount++;
            retval = -1;
        }
    }

    if (verify) {
        if (VerifyJar(verify)) {
            errorCount++;
            retval = -1;
            goto cleanup;
        }
    } else if (list_certs) {
        if (ListCerts(keyName, list_certs)) {
            errorCount++;
            retval = -1;
            goto cleanup;
        }
    } else if (list_modules) {
        JarListModules();
    } else if (genkey) {
        if (GenerateCert(genkey, keySize, token)) {
            errorCount++;
            retval = -1;
            goto cleanup;
        }
    } else if (tell_who) {
        if (JarWho(tell_who)) {
            errorCount++;
            retval = -1;
            goto cleanup;
        }
    } else if (javascript && jartree) {
        /* make sure directory exists */
        PRDir *dir;
        dir = PR_OpenDir(jartree);
        if (!dir) {
            PR_fprintf(errorFD, "ERROR: unable to open directory %s.\n",
                       jartree);
            errorCount++;
            retval = -1;
            goto cleanup;
        } else {
            PR_CloseDir(dir);
        }

        /* undo junk from prior runs of signtool*/
        if (RemoveAllArc(jartree)) {
            PR_fprintf(errorFD, "Error removing archive directories under %s\n",
                       jartree);
            errorCount++;
            retval = -1;
            goto cleanup;
        }

        /* traverse all the htm|html files in the directory */
        if (InlineJavaScript(jartree, !noRecurse)) {
            retval = -1;
            goto cleanup;
        }

        /* sign any resultant .arc directories created in above step */
        if (SignAllArc(jartree, keyName, javascript, metafile, install_script,
                       optimize, !noRecurse)) {
            retval = -1;
            goto cleanup;
        }

        if (!leaveArc) {
            RemoveAllArc(jartree);
        }

        if (errorCount > 0 || warningCount > 0) {
            PR_fprintf(outputFD, "%d error%s, %d warning%s.\n",
                       errorCount,
                       errorCount == 1 ? "" : "s", warningCount, warningCount == 1 ? "" : "s");
        } else {
            PR_fprintf(outputFD, "Directory %s signed successfully.\n",
                       jartree);
        }
    } else if (jartree) {
        SignArchive(jartree, keyName, zipfile, javascript, metafile,
                    install_script, optimize, !noRecurse);
    } else
        Usage();

cleanup:
    if (extensions) {
        PL_HashTableDestroy(extensions);
        extensions = NULL;
    }
    if (excludeDirs) {
        PL_HashTableDestroy(excludeDirs);
        excludeDirs = NULL;
    }
    if (outputFD != PR_STDOUT) {
        PR_Close(outputFD);
    }
    rm_dash_r(TMP_OUTPUT);
    if (retval == 0) {
        if (NSS_Shutdown() != SECSuccess) {
            exit(1);
        }
    }
    return retval;
}
Example #4
0
/*************************************************************************
 *
 * V e r i f y J a r
 */
int
VerifyJar(char *filename)
{
    FILE *fp;

    int ret;
    int status;
    int failed = 0;
    char *err;

    JAR *jar;
    JAR_Context *ctx;

    JAR_Item *it;

    jar = JAR_new();

    if ((fp = fopen(filename, "r")) == NULL) {
        perror(filename);
        exit(ERRX);
    } else
        fclose(fp);

    JAR_set_callback(JAR_CB_SIGNAL, jar, jar_cb);

    status = JAR_pass_archive(jar, jarArchGuess, filename, "some-url");

    if (status < 0 || jar->valid < 0) {
        failed = 1;
        PR_fprintf(outputFD,
                   "\nNOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
                   filename);
        if (status < 0) {
            const char *errtext;

            if (status >= JAR_BASE && status <= JAR_BASE_END) {
                errtext = JAR_get_error(status);
            } else {
                errtext = SECU_Strerror(PORT_GetError());
            }

            PR_fprintf(outputFD, "  (reported reason: %s)\n\n",
                       errtext);

            /* corrupt files should not have their contents listed */

            if (status == JAR_ERR_CORRUPT)
                return -1;
        }
        PR_fprintf(outputFD,
                   "entries shown below will have their digests checked only.\n");
        jar->valid = 0;
    } else
        PR_fprintf(outputFD,
                   "archive \"%s\" has passed crypto verification.\n", filename);

    if (verify_global(jar))
        failed = 1;

    PR_fprintf(outputFD, "\n");
    PR_fprintf(outputFD, "%16s   %s\n", "status", "path");
    PR_fprintf(outputFD, "%16s   %s\n", "------------", "-------------------");

    ctx = JAR_find(jar, NULL, jarTypeMF);

    while (JAR_find_next(ctx, &it) >= 0) {
        if (it && it->pathname) {
            rm_dash_r(TMP_OUTPUT);
            ret = JAR_verified_extract(jar, it->pathname, TMP_OUTPUT);
            /* if (ret < 0) printf ("error %d on %s\n", ret, it->pathname); */
            if (ret < 0)
                failed = 1;

            if (ret == JAR_ERR_PNF)
                err = "NOT PRESENT";
            else if (ret == JAR_ERR_HASH)
                err = "HASH FAILED";
            else
                err = "NOT VERIFIED";

            PR_fprintf(outputFD, "%16s   %s\n",
                       ret >= 0 ? "verified" : err, it->pathname);

            if (ret != 0 && ret != JAR_ERR_PNF && ret != JAR_ERR_HASH)
                PR_fprintf(outputFD, "      (reason: %s)\n",
                           JAR_get_error(ret));
        }
    }

    JAR_find_end(ctx);

    if (status < 0 || jar->valid < 0) {
        failed = 1;
        PR_fprintf(outputFD,
                   "\nNOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
                   filename);
        give_help(status);
    }

    JAR_destroy(jar);

    if (failed)
        return -1;
    return 0;
}
Example #5
0
/***************************************************************************
 *
 * v e r i f y _ g l o b a l
 */
static int
verify_global(JAR *jar)
{
    FILE *fp;
    JAR_Context *ctx;
    JAR_Item *it;
    JAR_Digest *globaldig;
    char *ext;
    unsigned char *md5_digest, *sha1_digest;
    unsigned int sha1_length, md5_length;
    int retval = 0;
    char buf[BUFSIZ];

    ctx = JAR_find(jar, "*", jarTypePhy);

    while (JAR_find_next(ctx, &it) >= 0) {
        if (!PORT_Strncmp(it->pathname, "META-INF", 8)) {
            for (ext = it->pathname; *ext; ext++)
                ;
            while (ext > it->pathname && *ext != '.')
                ext--;

            if (verbosity >= 0) {
                if (!PORT_Strcasecmp(ext, ".rsa")) {
                    PR_fprintf(outputFD, "found a RSA signature file: %s\n",
                               it->pathname);
                }

                if (!PORT_Strcasecmp(ext, ".dsa")) {
                    PR_fprintf(outputFD, "found a DSA signature file: %s\n",
                               it->pathname);
                }

                if (!PORT_Strcasecmp(ext, ".mf")) {
                    PR_fprintf(outputFD,
                               "found a MF master manifest file: %s\n",
                               it->pathname);
                }
            }

            if (!PORT_Strcasecmp(ext, ".sf")) {
                if (verbosity >= 0) {
                    PR_fprintf(outputFD,
                               "found a SF signature manifest file: %s\n",
                               it->pathname);
                }

                rm_dash_r(TMP_OUTPUT);
                if (JAR_extract(jar, it->pathname, TMP_OUTPUT) < 0) {
                    PR_fprintf(errorFD, "%s: error extracting %s\n",
                               PROGRAM_NAME, it->pathname);
                    errorCount++;
                    retval = -1;
                    continue;
                }

                md5_digest = NULL;
                sha1_digest = NULL;

                if ((fp = fopen(TMP_OUTPUT, "rb")) != NULL) {
                    while (fgets(buf, BUFSIZ, fp)) {
                        char *s;

                        if (*buf == 0 || *buf == '\n' || *buf == '\r')
                            break;

                        for (s = buf; *s && *s != '\n' && *s != '\r'; s++)
                            ;
                        *s = 0;

                        if (!PORT_Strncmp(buf, "MD5-Digest: ", 12)) {
                            md5_digest =
                                ATOB_AsciiToData(buf + 12, &md5_length);
                        }
                        if (!PORT_Strncmp(buf, "SHA1-Digest: ", 13)) {
                            sha1_digest =
                                ATOB_AsciiToData(buf + 13, &sha1_length);
                        }
                        if (!PORT_Strncmp(buf, "SHA-Digest: ", 12)) {
                            sha1_digest =
                                ATOB_AsciiToData(buf + 12, &sha1_length);
                        }
                    }

                    globaldig = jar->globalmeta;

                    if (globaldig && md5_digest && verbosity >= 0) {
                        PR_fprintf(outputFD,
                                   "  md5 digest on global metainfo: %s\n",
                                   PORT_Memcmp(md5_digest, globaldig->md5, MD5_LENGTH)
                                       ? "no match"
                                       : "match");
                    }

                    if (globaldig && sha1_digest && verbosity >= 0) {
                        PR_fprintf(outputFD,
                                   "  sha digest on global metainfo: %s\n",
                                   PORT_Memcmp(sha1_digest, globaldig->sha1, SHA1_LENGTH)
                                       ? "no match"
                                       : "match");
                    }

                    if (globaldig == NULL && verbosity >= 0) {
                        PR_fprintf(outputFD,
                                   "global metadigest is not available, strange.\n");
                    }

                    PORT_Free(md5_digest);
                    PORT_Free(sha1_digest);
                    fclose(fp);
                }
            }
        }
    }

    JAR_find_end(ctx);

    return retval;
}
Example #6
0
/*
/////////////////////////////////////////////////////////////////////////
// actually run the installation, copying files to and fro
*/
static Pk11Install_Error
DoInstall(JAR *jar, const char *installDir, const char *tempDir,
          Pk11Install_Platform *platform, PRFileDesc *feedback, PRBool noverify)
{
    Pk11Install_File *file;
    Pk11Install_Error ret;
    char *reldir;
    char *dest;
    char *modDest;
    char *cp;
    int i;
    int status;
    char *tempname, *temp;
    StringList executables;
    StringNode *execNode;
    PRProcessAttr *attr;
    PRProcess *proc;
    char *argv[2];
    char *envp[1];
    int errcode;

    ret = PK11_INSTALL_UNSPECIFIED;
    reldir = NULL;
    dest = NULL;
    modDest = NULL;
    tempname = NULL;

    StringList_new(&executables);
    /*
    // Create Temporary directory
    */
    tempname = PR_smprintf("%s/%s", tempDir, TEMPORARY_DIRECTORY_NAME);
    if (PR_Access(tempname, PR_ACCESS_EXISTS) == PR_SUCCESS) {
        /* Left over from previous run?  Delete it. */
        rm_dash_r(tempname);
    }
    if (PR_MkDir(tempname, 0700) != PR_SUCCESS) {
        error(PK11_INSTALL_CREATE_DIR, tempname);
        ret = PK11_INSTALL_CREATE_DIR;
        goto loser;
    }

    /*
    // Install all the files
    */
    for (i = 0; i < platform->numFiles; i++) {
        file = &platform->files[i];

        if (file->relativePath) {
            PRBool foundMarker = PR_FALSE;
            reldir = PR_Strdup(file->relativePath);

            /* Replace all the markers with the directories for which they stand */
            while (1) {
                if ((cp = PL_strcasestr(reldir, ROOT_MARKER))) {
                    /* Has a %root% marker  */
                    *cp = '\0';
                    temp = PR_smprintf("%s%s%s", reldir, installDir,
                                       cp + strlen(ROOT_MARKER));
                    PR_Free(reldir);
                    reldir = temp;
                    foundMarker = PR_TRUE;
                } else if ((cp = PL_strcasestr(reldir, TEMP_MARKER))) {
                    /* Has a %temp% marker */
                    *cp = '\0';
                    temp = PR_smprintf("%s%s%s", reldir, tempname,
                                       cp + strlen(TEMP_MARKER));
                    PR_Free(reldir);
                    reldir = temp;
                    foundMarker = PR_TRUE;
                } else {
                    break;
                }
            }
            if (!foundMarker) {
                /* Has no markers...this isn't really a relative directory */
                error(PK11_INSTALL_BOGUS_REL_DIR, file->relativePath);
                ret = PK11_INSTALL_BOGUS_REL_DIR;
                goto loser;
            }
            dest = reldir;
            reldir = NULL;
        } else if (file->absolutePath) {
            dest = PR_Strdup(file->absolutePath);
        }

        /* Remember if this is the module file, we'll need to add it later */
        if (i == platform->modFile) {
            modDest = PR_Strdup(dest);
        }

        /* Remember is this is an executable, we'll need to run it later */
        if (file->executable) {
            StringList_Append(&executables, dest);
            /*executables.Append(dest);*/
        }

        /* Make sure the directory we are targetting exists */
        if (make_dirs(dest, file->permissions)) {
            ret = PK11_INSTALL_CREATE_DIR;
            goto loser;
        }

        /* Actually extract the file onto the filesystem */
        if (noverify) {
            status = JAR_extract(jar, (char *)file->jarPath, dest);
        } else {
            status = JAR_verified_extract(jar, (char *)file->jarPath, dest);
        }
        if (status) {
            if (status >= JAR_BASE && status <= JAR_BASE_END) {
                error(PK11_INSTALL_JAR_EXTRACT, file->jarPath,
                      JAR_get_error(status));
            } else {
                error(PK11_INSTALL_JAR_EXTRACT, file->jarPath,
                      mySECU_ErrorString(PORT_GetError()));
            }
            ret = PK11_INSTALL_JAR_EXTRACT;
            goto loser;
        }
        if (feedback) {
            PR_fprintf(feedback, msgStrings[INSTALLED_FILE_MSG],
                       file->jarPath, dest);
        }

/* no NSPR command to change permissions? */
#ifdef XP_UNIX
        chmod(dest, file->permissions);
#endif

        /* Memory clean-up tasks */
        if (reldir) {
            PR_Free(reldir);
            reldir = NULL;
        }
        if (dest) {
            PR_Free(dest);
            dest = NULL;
        }
    }
    /* Make sure we found the module file */
    if (!modDest) {
        /* Internal problem here, since every platform is supposed to have
           a module file */
        error(PK11_INSTALL_NO_MOD_FILE, platform->moduleName);
        ret = PK11_INSTALL_NO_MOD_FILE;
        goto loser;
    }

    /*
    // Execute any executable files
    */
    {
        argv[1] = NULL;
        envp[0] = NULL;
        for (execNode = executables.head; execNode; execNode = execNode->next) {
            attr = PR_NewProcessAttr();
            argv[0] = PR_Strdup(execNode->str);

            /* Announce our intentions */
            if (feedback) {
                PR_fprintf(feedback, msgStrings[EXEC_FILE_MSG], execNode->str);
            }

            /* start the process */
            if (!(proc = PR_CreateProcess(execNode->str, argv, envp, attr))) {
                PR_Free(argv[0]);
                PR_DestroyProcessAttr(attr);
                error(PK11_INSTALL_EXEC_FILE, execNode->str);
                ret = PK11_INSTALL_EXEC_FILE;
                goto loser;
            }

            /* wait for it to finish */
            if (PR_WaitProcess(proc, &errcode) != PR_SUCCESS) {
                PR_Free(argv[0]);
                PR_DestroyProcessAttr(attr);
                error(PK11_INSTALL_WAIT_PROCESS, execNode->str);
                ret = PK11_INSTALL_WAIT_PROCESS;
                goto loser;
            }

            /* What happened? */
            if (errcode) {
                /* process returned an error */
                error(PK11_INSTALL_PROC_ERROR, execNode->str, errcode);
            } else if (feedback) {
                /* process ran successfully */
                PR_fprintf(feedback, msgStrings[EXEC_SUCCESS], execNode->str);
            }

            PR_Free(argv[0]);
            PR_DestroyProcessAttr(attr);
        }
    }

    /*
    // Add the module
    */
    status = Pk11Install_AddNewModule((char *)platform->moduleName,
                                      (char *)modDest, platform->mechFlags, platform->cipherFlags);

    if (status != SECSuccess) {
        error(PK11_INSTALL_ADD_MODULE, platform->moduleName);
        ret = PK11_INSTALL_ADD_MODULE;
        goto loser;
    }
    if (feedback) {
        PR_fprintf(feedback, msgStrings[INSTALLED_MODULE_MSG],
                   platform->moduleName);
    }

    if (feedback) {
        PR_fprintf(feedback, msgStrings[INSTALLATION_COMPLETE_MSG]);
    }

    ret = PK11_INSTALL_SUCCESS;

loser:
    if (reldir) {
        PR_Free(reldir);
    }
    if (dest) {
        PR_Free(dest);
    }
    if (modDest) {
        PR_Free(modDest);
    }
    if (tempname) {
        PRFileInfo info;
        if (PR_GetFileInfo(tempname, &info) == PR_SUCCESS) {
            if (info.type == PR_FILE_DIRECTORY) {
                /* Recursively remove temporary directory */
                if (rm_dash_r(tempname)) {
                    error(PK11_INSTALL_REMOVE_DIR,
                          tempname);
                    ret = PK11_INSTALL_REMOVE_DIR;
                }
            }
        }
        PR_Free(tempname);
    }
    StringList_delete(&executables);
    return ret;
}