Exemplo n.º 1
0
/**
 * Signs all documents in container.
 *
 * @param signer signer implementation.
 * @param profile signature profile (e.g. BES, TM).
 * @throws BDocException exception is throws if signing the BDCO container failed.
 */
void digidoc::BDoc::sign(Signer* signer, Type profile) throw(BDocException)
{
    if (!signer)
        THROW_BDOCEXCEPTION("Null pointer in digidoc::BDoc::sign");

    DEBUG("sign(signer = %p, profile=%d)", signer, profile);

    // Create signature by type.
    Signature* signature = NULL;
    switch(profile)
    {
    case BES:
        signature = new SignatureBES(newSignatureId(), *this);
        break;
    case TM:
        signature = new SignatureTM(newSignatureId(), *this);
        break;
    default:
        THROW_BDOCEXCEPTION("Unknown signature profile: %d", profile);
        break;
    }

    try
    {
        // Finalize the signature by calculating signature.
        signature->sign(signer);
    }
    catch(const SignatureException& e)
    {
        delete signature;
        THROW_BDOCEXCEPTION_CAUSE(e, "Failed to sign BDOC container.");
    }
    catch(const SignException& e)
    {
        delete signature;
        THROW_BDOCEXCEPTION_CAUSE(e, "Failed to sign BDOC container.");
    }

    // Add the created signature to the signatures list.
    addSignature(signature);
}
Exemplo n.º 2
0
/**
 * Signs all documents in container.
 *
 * @param signer signer implementation.
 * @param profile signature profile (e.g. BES, TM).
 * @throws BDocException exception is throws if signing the BDCO container failed.
 */
void digidoc::BDoc::sign(Signer* signer, Signature::Type profile) throw(BDocException)
{
    if (signer == NULL)
    {
        THROW_BDOCEXCEPTION("Null pointer in digidoc::BDoc::sign");
    }

    DEBUG("sign(signer = 0x%X, profile=%d)", (unsigned int)signer, profile);

    // Create signature by type.
    Signature* signature = NULL;
    if(profile == Signature::BES)
    {
        signature = new SignatureBES(*this);
    }
    else if(profile == Signature::TM)
    {
        signature = new SignatureTM(*this);
    }
	else if(profile == Signature::MOBILE)
	{
		try {
			signature = new SignatureMobile( signer->signaturePath(), *this);
		} catch(const Exception& e) {
			THROW_BDOCEXCEPTION_CAUSE(e, "MobileSignature");
		}
		addSignature( signature );
		return;
	}
	else
    {
        THROW_BDOCEXCEPTION("Unknown signature profile: %d", profile);
    }

    // Calculate digests for the documents and add these to the signature reference.
    for(std::vector<Document>::iterator iter = documents.begin(); iter != documents.end(); iter++)
    {
        try
        {
            DEBUG("Adding document '%s', '%s' to the signature references.", iter->getPath().c_str(), iter->getMediaType().c_str());
            // URIs must encode non-ASCII characters in the format %HH where HH is the hex representation of the character
            std::string uri = std::string("/") + digidoc::util::String::toUriFormat(digidoc::util::File::fileName(iter->getPath()));
            std::auto_ptr<Digest> calc = Digest::create();
            std::vector<unsigned char> digest = iter->calcDigest(calc.get());
            DEBUGMEM("digest", &digest[0], digest.size());
            signature->addReference(uri, calc->getUri(), digest);
        }
        catch(const Exception& e)
        {
            delete signature;
            THROW_BDOCEXCEPTION_CAUSE(e, "Failed to calculate digests for document '%s'.", iter->getPath().c_str());
        }
    }

    try
    {
        // Finalize the signature by calculating signature.
        signature->sign(signer);
    }
    catch(const SignatureException& e)
    {
        delete signature;
        THROW_BDOCEXCEPTION_CAUSE(e, "Failed to sign BDOC container.");
    }
    catch(const SignException& e)
    {
        delete signature;
        THROW_BDOCEXCEPTION_CAUSE(e, "Failed to sign BDOC container.");
    }

    // Add the created signature to the signatures list.
    addSignature(signature);
}
Exemplo n.º 3
0
/**
 * Parses manifest file and checks that files described in manifest exist, also
 * checks that no extra file do exist that are not described in manifest.xml.
 *
 * Note: If non-ascii characters are present in XML data, we depend on the LANG variable to be set properly 
 * (see iconv --list for the list of supported encoding values for libiconv).
 *
 * @param path directory on disk of the BDOC container.
 * @throws IOException exception is thrown if the manifest.xml file parsing failed.
 * @throws BDocException
 */
void digidoc::BDoc::parseManifestAndLoadFiles(std::string path) throw(IOException, BDocException)
{
    DEBUG("BDoc::readManifest(path = '%s')", path.c_str());

    try
    {
        // Parse manifest file.
        std::string fileName = util::File::path(path, "META-INF/manifest.xml");
        xml_schema::Properties properties;
        properties.schema_location(MANIFEST_NAMESPACE, Conf::getInstance()->getManifestXsdPath());
        std::auto_ptr<manifest::Manifest> manifest(manifest::manifest(fileName, xml_schema::Flags::dont_initialize, properties));

        // Extract and validate file list from manifest.
        std::set<std::string> manifestFiles;
        bool mimetypeChecked = false;
        for(manifest::Manifest::File_entrySequence::const_iterator iter = manifest->file_entry().begin(); iter != manifest->file_entry().end(); iter++)
        {
            DEBUG("full_path = '%s', media_type = '%s'", iter->full_path().c_str(), iter->media_type().c_str());
            // Check container mimetype.
            if(std::string("/").compare(iter->full_path()) == 0)
            {
                if(mimetypeChecked)
                {
                    THROW_BDOCEXCEPTION("Manifest has more than one container media type defined.");
                }

                if(getMimeType().compare(iter->media_type()) != 0)
                {
                    THROW_BDOCEXCEPTION("Manifest has incorrect BDCO container media type defined '%s', expecting '%s'.", iter->media_type().c_str(), getMimeType().c_str());
                }

                DEBUG("BDOC mimetype OK");
                mimetypeChecked = true;
                continue;
            }

            // Check that file reference is not defined already and add relative file reference to set.
            if(manifestFiles.find(iter->full_path()) != manifestFiles.end())
            {
                THROW_BDOCEXCEPTION("Manifest multiple entries defined for file '%s'.", iter->media_type().c_str());
            }
            manifestFiles.insert(iter->full_path());

            // Add document to documents list.
            if(iter->full_path().find_first_of("/") == std::string::npos)
            {
                if(!util::File::fileExists(util::File::path(path, iter->full_path())))
                {
                    THROW_BDOCEXCEPTION("File described in manifest '%s' does not exist in BDOC container.", iter->full_path().c_str());
                }
                documents.push_back(Document(util::File::path(path, iter->full_path()), iter->media_type()));
                continue;
            }

            // Add signature to signatures list.
            DEBUG("%s :: %u", iter->full_path().c_str(), iter->full_path().find_first_of("META-INF/"));
            std::string signatureFileName = (iter->full_path().substr((iter->full_path().find('/'))+1));

            if(iter->full_path().find_first_of("META-INF/") == 0)
            {
                DEBUG("signature filename :: '%s'", signatureFileName.c_str());

                if(signatureFileName.find_first_of("/") != std::string::npos)
                {
                    THROW_BDOCEXCEPTION("Unexpected file described in manifest '%s'.", iter->full_path().c_str());
                }

                if(!util::File::fileExists(util::File::path(util::File::path(path, "META-INF"), signatureFileName)))
                {
                    THROW_BDOCEXCEPTION("File described in manifest '%s' does not exist in BDOC container.", iter->full_path().c_str());
                }

                std::string signaturePath = util::File::path(util::File::path(path, "META-INF"), signatureFileName);    

                try
                {
                    if(SignatureBES::MEDIA_TYPE == iter->media_type())
                    {
                        signatures.push_back(new SignatureBES(signaturePath, *this));
                    }
                    else if(SignatureTM::MEDIA_TYPE == iter->media_type())
                    {
                        signatures.push_back(new SignatureTM(signaturePath, *this));
                    }
                    else
                    {
                        THROW_BDOCEXCEPTION("Unknown signature media type '%s'.", iter->media_type().c_str());
                    }
                }
                catch(const SignatureException& e)
                {
                    THROW_BDOCEXCEPTION_CAUSE(e, "Failed to parse signature '%s', type '%s'.", signaturePath.c_str(), iter->media_type().c_str());
                }

                continue;
            }

            // Found unexpected file description in manifest.
            THROW_BDOCEXCEPTION("Unexpected file description found in container manifest.");
        }

        if(!mimetypeChecked)
        {
            THROW_BDOCEXCEPTION("Manifest file does not have BDOC media type described.");
        }

        // Check that there are no unexpected files in container.
        std::vector<std::string> containerFiles = util::File::listFiles(path, true, true, true);
        for(std::vector<std::string>::const_iterator iter = containerFiles.begin(); iter != containerFiles.end(); iter++)
        {

            std::string containerFile = *iter;
            if(std::string("mimetype").compare(containerFile) == 0
            || std::string("META-INF/manifest.xml").compare(containerFile) == 0)
            {
                continue;
            }

            std::replace(containerFile.begin(), containerFile.end(), '\\', '/');
            if(manifestFiles.find(containerFile) == manifestFiles.end())
            {
                THROW_BDOCEXCEPTION("File '%s' found in BDOC container is not described in manifest.", containerFile.c_str());
            }
        }
    }
    catch(const xml_schema::Exception& e)
    {
        std::ostringstream oss;
        oss << e;
        THROW_IOEXCEPTION("Failed to parse manifest XML: %s", oss.str().c_str());
    }
}