Add fetchLicenseServiceCertificate() because not all signing certificates (to be included into rights.xml) are the same than the one fetched at authentication

This commit is contained in:
Grégory Soutadé 2021-08-21 20:46:09 +02:00
parent 7f5a4900e0
commit 8bc346d139
5 changed files with 98 additions and 16 deletions

View File

@ -194,6 +194,8 @@ namespace gourou
void buildActivateReq(pugi::xml_document& activateReq);
ByteArray sendFulfillRequest(const pugi::xml_document& document, const std::string& url);
void buildSignInRequest(pugi::xml_document& signInRequest, const std::string& adobeID, const std::string& adobePassword, const std::string& authenticationCertificate);
void fetchLicenseServiceCertificate(const std::string& licenseURL,
const std::string& operatorURL);
};
}

View File

@ -14,13 +14,15 @@
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with libgourou. If not, see <http://www.gnu.org/licenses/>.
along with libgourou. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _USER_H_
#define _USER_H_
#include <string>
#include <map>
#include "bytearray.h"
#include <pugixml.hpp>
@ -46,7 +48,7 @@ namespace gourou
std::string& getDeviceFingerprint();
std::string& getUsername();
std::string& getLoginMethod();
std::string& getCertificate();
std::string getLicenseServiceCertificate(std::string url);
std::string& getAuthenticationCertificate();
std::string& getPrivateLicenseKey();
@ -95,7 +97,7 @@ namespace gourou
std::string deviceFingerprint;
std::string username;
std::string loginMethod;
std::string certificate;
std::map<std::string,std::string> licenseServiceCertificates;
std::string authenticationCertificate;
std::string privateLicenseKey;

View File

@ -36,6 +36,12 @@ namespace gourou
if (downloadURL == "")
EXCEPTION(FFI_INVALID_FULFILLMENT_DATA, "No download URL in document");
node = doc.select_node("/envelope/fulfillmentResult/resourceItemInfo/resource").node();
resource = node.first_child().value();
if (resource == "")
EXCEPTION(FFI_INVALID_FULFILLMENT_DATA, "No resource in document");
pugi::xml_node licenseToken = doc.select_node("/envelope/fulfillmentResult/resourceItemInfo/licenseToken").node();
if (!licenseToken)
@ -56,11 +62,13 @@ namespace gourou
if (!newLicenseToken.attribute("xmlns"))
newLicenseToken.append_attribute("xmlns") = ADOBE_ADEPT_NS;
pugi::xml_node licenseServiceInfo = root.append_child("licenseServiceInfo");
licenseServiceInfo.append_attribute("xmlns") = ADOBE_ADEPT_NS;
licenseServiceInfo.append_copy(licenseToken.select_node("licenseURL").node());
pugi::xml_node certificate = licenseServiceInfo.append_child("certificate");
certificate.append_child(pugi::node_pcdata).set_value(user->getCertificate().c_str());
pugi::xml_node licenseServiceInfo = root.append_child("adept:licenseServiceInfo");
pugi::xml_node licenseURL = licenseToken.select_node("licenseURL").node();
licenseURL.set_name("adept:licenseURL");
licenseServiceInfo.append_copy(licenseURL);
pugi::xml_node certificate = licenseServiceInfo.append_child("adept:certificate");
std::string certificateValue = user->getLicenseServiceCertificate(licenseURL.first_child().value());
certificate.append_child(pugi::node_pcdata).set_value(certificateValue.c_str());
}
std::string FulfillmentItem::getMetadata(std::string name)
@ -88,4 +96,9 @@ namespace gourou
{
return downloadURL;
}
std::string FulfillmentItem::getResource()
{
return resource;
}
}

View File

@ -33,6 +33,7 @@
#define ASN_TEXT 0x04
#define ASN_ATTRIBUTE 0x05
namespace gourou
{
GOUROU_LOG_LEVEL logLevel = WARN;
@ -453,6 +454,49 @@ namespace gourou
appendTextElem(activationToken, "adept:device", user->getDeviceUUID());
}
void DRMProcessor::fetchLicenseServiceCertificate(const std::string& licenseURL,
const std::string& operatorURL)
{
if (user->getLicenseServiceCertificate(licenseURL) != "")
return;
std::string licenseServiceInfoReq = operatorURL + "/LicenseServiceInfo?licenseURL=" + licenseURL;
ByteArray replyData;
replyData = sendRequest(licenseServiceInfoReq);
pugi::xml_document licenseServicesDoc;
licenseServicesDoc.load_buffer(replyData.data(), replyData.length());
// Add new license certificate
pugi::xml_document activationDoc;
user->readActivation(activationDoc);
pugi::xml_node root;
pugi::xpath_node xpathRes = activationDoc.select_node("//adept:licenseServices");
// Create adept:licenseServices if it doesn't exists
if (!xpathRes)
{
xpathRes = activationDoc.select_node("/activationInfo");
root = xpathRes.node();
root = root.append_child("adept:licenseServices");
root.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
}
else
root = xpathRes.node();
root = root.append_child("adept:licenseServiceInfo");
std::string certificate = extractTextElem(licenseServicesDoc,
"/licenseServiceInfo/certificate");
appendTextElem(root, "adept:licenseURL", licenseURL);
appendTextElem(root, "adept:certificate", certificate);
user->updateActivationFile(activationDoc);
}
FulfillmentItem* DRMProcessor::fulfill(const std::string& ACSMFile)
{
if (!user->getPKCS12().length())
@ -495,15 +539,16 @@ namespace gourou
EXCEPTION(FF_NO_OPERATOR_URL, "OperatorURL not found in ACSM document");
std::string operatorURL = node.node().first_child().value();
operatorURL = trim(operatorURL) + "/Fulfill";
operatorURL = trim(operatorURL);
std::string fulfillURL = operatorURL + "/Fulfill";
operatorAuth(operatorURL);
operatorAuth(fulfillURL);
ByteArray replyData;
try
{
replyData = sendRequest(fulfillReq, operatorURL);
replyData = sendRequest(fulfillReq, fulfillURL);
}
catch (gourou::Exception& e)
{
@ -515,8 +560,8 @@ namespace gourou
if (e.getErrorCode() == GOUROU_ADEPT_ERROR &&
errorMsg.find("E_ADEPT_DISTRIBUTOR_AUTH") != std::string::npos)
{
doOperatorAuth(operatorURL);
replyData = sendRequest(fulfillReq, operatorURL);
doOperatorAuth(fulfillURL);
replyData = sendRequest(fulfillReq, fulfillURL);
}
else
{
@ -528,6 +573,10 @@ namespace gourou
fulfillReply.load_string((const char*)replyData.data());
std::string licenseURL = extractTextElem(fulfillReply, "//licenseToken/licenseURL");
fetchLicenseServiceCertificate(licenseURL, operatorURL);
return new FulfillmentItem(fulfillReply, user);
}

View File

@ -48,7 +48,6 @@ namespace gourou {
uuid = gourou::extractTextElem(activationDoc, "//adept:user", throwOnNull);
deviceUUID = gourou::extractTextElem(activationDoc, "//device", throwOnNull);
deviceFingerprint = gourou::extractTextElem(activationDoc, "//fingerprint", throwOnNull);
certificate = gourou::extractTextElem(activationDoc, "//adept:certificate", throwOnNull);
authenticationCertificate = gourou::extractTextElem(activationDoc, "//adept:authenticationCertificate", throwOnNull);
privateLicenseKey = gourou::extractTextElem(activationDoc, "//adept:privateLicenseKey", throwOnNull);
username = gourou::extractTextElem(activationDoc, "//adept:username", throwOnNull);
@ -61,6 +60,15 @@ namespace gourou {
if (throwOnNull)
EXCEPTION(USER_INVALID_ACTIVATION_FILE, "Invalid activation file");
}
pugi::xpath_node_set nodeSet = activationDoc.select_nodes("//adept:licenseServices/adept:licenseServiceInfo");
for (pugi::xpath_node_set::const_iterator it = nodeSet.begin();
it != nodeSet.end(); ++it)
{
std::string url = gourou::extractTextElem(it->node(), "adept:licenseURL");
std::string certificate = gourou::extractTextElem(it->node(), "adept:certificate");
licenseServiceCertificates[url] = certificate;
}
}
catch(gourou::Exception& e)
{
@ -74,7 +82,6 @@ namespace gourou {
std::string& User::getDeviceFingerprint() { return deviceFingerprint; }
std::string& User::getUsername() { return username; }
std::string& User::getLoginMethod() { return loginMethod; }
std::string& User::getCertificate() { return certificate; }
std::string& User::getAuthenticationCertificate() { return authenticationCertificate; }
std::string& User::getPrivateLicenseKey() { return privateLicenseKey; }
@ -200,4 +207,13 @@ namespace gourou {
return user;
}
std::string User::getLicenseServiceCertificate(std::string url)
{
if (licenseServiceCertificates.count(trim(url)))
return licenseServiceCertificates[trim(url)];
return "";
}
}