1 | /*␊ |
2 | Copyright 2021 Grégory Soutadé␊ |
3 | ␊ |
4 | This file is part of libgourou.␊ |
5 | ␊ |
6 | libgourou is free software: you can redistribute it and/or modify␊ |
7 | it under the terms of the GNU Lesser General Public License as published by␊ |
8 | the Free Software Foundation, either version 3 of the License, or␊ |
9 | (at your option) any later version.␊ |
10 | ␊ |
11 | libgourou is distributed in the hope that it will be useful,␊ |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of␊ |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the␊ |
14 | GNU Lesser General Public License for more details.␊ |
15 | ␊ |
16 | You should have received a copy of the GNU Lesser General Public License␊ |
17 | along with libgourou. If not, see <http://www.gnu.org/licenses/>.␊ |
18 | */␊ |
19 | ␊ |
20 | #ifndef _LIBGOUROU_H_␊ |
21 | #define _LIBGOUROU_H_␊ |
22 | ␊ |
23 | #include "bytearray.h"␊ |
24 | #include "device.h"␊ |
25 | #include "user.h"␊ |
26 | #include "fulfillment_item.h"␊ |
27 | #include "drmprocessorclient.h"␊ |
28 | ␊ |
29 | #include <pugixml.hpp>␊ |
30 | ␊ |
31 | #ifndef HOBBES_DEFAULT_VERSION␊ |
32 | #define HOBBES_DEFAULT_VERSION "10.0.4"␊ |
33 | #endif␊ |
34 | ␊ |
35 | #ifndef DEFAULT_ADEPT_DIR␊ |
36 | #define DEFAULT_ADEPT_DIR "./.adept"␊ |
37 | #endif␊ |
38 | ␊ |
39 | #ifndef ACS_SERVER␊ |
40 | #define ACS_SERVER "http://adeactivate.adobe.com/adept"␊ |
41 | #endif␊ |
42 | ␊ |
43 | #define LIBGOUROU_VERSION "0.8"␊ |
44 | ␊ |
45 | namespace gourou␊ |
46 | {␊ |
47 | /**␊ |
48 | * @brief Main class that handle all ADEPTS functions (fulfill, download, signIn, activate)␊ |
49 | */␊ |
50 | class DRMProcessor␊ |
51 | {␊ |
52 | public:␊ |
53 | ␊ |
54 | ␉static const std::string VERSION;␊ |
55 | ␊ |
56 | ␉enum ITEM_TYPE { EPUB=0, PDF };␊ |
57 | ␉/**␊ |
58 | ␉ * @brief Main constructor. To be used once all is configured (user has signedIn, device is activated)␊ |
59 | ␉ *␊ |
60 | ␉ * @param client Client processor␊ |
61 | ␉ * @param deviceFile Path of device.xml␊ |
62 | ␉ * @param activationFile Path of activation.xml␊ |
63 | ␉ * @param deviceKeyFile Path of devicesalt␊ |
64 | ␉ */␊ |
65 | DRMProcessor(DRMProcessorClient* client, const std::string& deviceFile, const std::string& activationFile, const std::string& deviceKeyFile);␊ |
66 | ␉␊ |
67 | ␉~DRMProcessor();␊ |
68 | ␊ |
69 | ␉/**␊ |
70 | ␉ * @brief Fulfill ACSM file to server in order to retrieve ePub fulfillment item␊ |
71 | ␉ *␊ |
72 | ␉ * @param ACSMFile Path of ACSMFile␊ |
73 | ␉ *␊ |
74 | ␉ * @return a FulfillmentItem if all is OK␊ |
75 | ␉ */␊ |
76 | ␉FulfillmentItem* fulfill(const std::string& ACSMFile);␊ |
77 | ␊ |
78 | ␉/**␊ |
79 | ␉ * @brief Once fulfilled, ePub file needs to be downloaded.␊ |
80 | ␉ * During this operation, DRM information is added into downloaded file␊ |
81 | ␉ *␊ |
82 | ␉ * @param item Item from fulfill() method␊ |
83 | ␉ * @param path Output file path ␊ |
84 | ␉ * @param resume false if target file should be truncated, true to try resume download␊ |
85 | ␉ *␊ |
86 | ␉ * @return Type of downloaded item␊ |
87 | ␉ */␊ |
88 | ␉ITEM_TYPE download(FulfillmentItem* item, std::string path, bool resume=false);␊ |
89 | ␊ |
90 | ␉/**␊ |
91 | ␉ * @brief SignIn into ACS Server (required to activate device)␊ |
92 | ␉ * ␊ |
93 | ␉ * @param adobeID AdobeID username␊ |
94 | ␉ * @param adobePassword Adobe password␊ |
95 | ␉ */␊ |
96 | ␉void signIn(const std::string& adobeID, const std::string& adobePassword);␊ |
97 | ␊ |
98 | ␉/**␊ |
99 | ␉ * @brief Activate newly created device (user must have successfuly signedIn before)␊ |
100 | ␉ */␊ |
101 | ␉void activateDevice();␊ |
102 | ␊ |
103 | ␉/**␊ |
104 | ␉ * @brief Return loaned book to server␊ |
105 | ␉ *␊ |
106 | ␉ * @param loanID Loan ID received during fulfill␊ |
107 | ␉ * @param operatorURL URL of operator that loans this book␊ |
108 | ␉ */␊ |
109 | ␉void returnLoan(const std::string& loanID, const std::string& operatorURL);␊ |
110 | ␉␊ |
111 | ␉/**␊ |
112 | ␉ * @brief Create a new ADEPT environment (device.xml, devicesalt and activation.xml).␊ |
113 | ␉ *␊ |
114 | ␉ * @param client Client processor␊ |
115 | ␉ * @param randomSerial Always generate a new device (or not)␊ |
116 | ␉ * @param dirName Directory where to put generated files (.adept)␊ |
117 | ␉ * @param hobbes Override hobbes default version␊ |
118 | ␉ * @param ACSServer Override main ACS server (default adeactivate.adobe.com)␊ |
119 | ␉ */␊ |
120 | static DRMProcessor* createDRMProcessor(DRMProcessorClient* client,␊ |
121 | ␉␉␉␉␉␉bool randomSerial=false, const std::string& dirName=std::string(DEFAULT_ADEPT_DIR),␊ |
122 | ␉␉␉␉␉␉const std::string& hobbes=std::string(HOBBES_DEFAULT_VERSION),␊ |
123 | ␉␉␉␉␉␉const std::string& ACSServer=ACS_SERVER);␊ |
124 | ␊ |
125 | ␉/**␊ |
126 | ␉ * @brief Get current log level␊ |
127 | ␉ */␊ |
128 | ␉static int getLogLevel();␊ |
129 | ␊ |
130 | ␉/**␊ |
131 | ␉ * @brief Set log level (higher number for verbose output)␊ |
132 | ␉ */␊ |
133 | ␉static void setLogLevel(int logLevel);␊ |
134 | ␊ |
135 | ␉/**␊ |
136 | ␉ * Functions used internally, should not be called by user␊ |
137 | ␉ */␊ |
138 | ␊ |
139 | ␉/**␊ |
140 | ␉ * @brief Send HTTP (GET or POST) request␊ |
141 | ␉ *␊ |
142 | ␉ * @param URL HTTP URL␊ |
143 | ␉ * @param POSTData POST data if needed, if not set, a GET request is done␊ |
144 | ␉ * @param contentType Optional content type of POST Data␊ |
145 | ␉ * @param responseHeaders Optional Response headers of HTTP request␊ |
146 | ␉ * @param fd Optional File descriptor to write received data␊ |
147 | ␉ * @param resume false if target file should be truncated, true to try resume download (works only in combination of a valid fd)␊ |
148 | ␉ *␊ |
149 | ␉ * @return data of HTTP response␊ |
150 | ␉ */␊ |
151 | ␉ByteArray sendRequest(const std::string& URL, const std::string& POSTData=std::string(), const char* contentType=0, std::map<std::string, std::string>* responseHeaders=0, int fd=0, bool resume=false);␊ |
152 | ␊ |
153 | ␉/**␊ |
154 | ␉ * @brief Send HTTP POST request to URL with document as POSTData␊ |
155 | ␉ */␊ |
156 | ␉ByteArray sendRequest(const pugi::xml_document& document, const std::string& url);␊ |
157 | ␊ |
158 | ␉/**␊ |
159 | ␉ * @brief In place encrypt data with private device key␊ |
160 | ␉ */␊ |
161 | ␉ByteArray encryptWithDeviceKey(const unsigned char* data, unsigned int len);␊ |
162 | ␊ |
163 | ␉/**␊ |
164 | ␉ * @brief In place decrypt data with private device key␊ |
165 | ␉ */␊ |
166 | ␉ByteArray decryptWithDeviceKey(const unsigned char* data, unsigned int len);␊ |
167 | ␊ |
168 | ␉/**␊ |
169 | ␉ * @brief Return base64 encoded value of RSA public key␊ |
170 | ␉ */␊ |
171 | ␉std::string serializeRSAPublicKey(void* rsa);␊ |
172 | ␊ |
173 | ␉/**␊ |
174 | ␉ * @brief Return base64 encoded value of RSA private key encrypted with private device key␊ |
175 | ␉ */␊ |
176 | ␉std::string serializeRSAPrivateKey(void* rsa);␊ |
177 | ␊ |
178 | ␉/**␊ |
179 | ␉ * @brief Export clear private license key into path␊ |
180 | ␉ */␊ |
181 | ␉void exportPrivateLicenseKey(std::string path);␊ |
182 | ␉␊ |
183 | ␉/**␊ |
184 | ␉ * @brief Get current user␊ |
185 | ␉ */␊ |
186 | ␉User* getUser() { return user; }␊ |
187 | ␊ |
188 | ␉/**␊ |
189 | ␉ * @brief Get current device␊ |
190 | ␉ */␊ |
191 | ␉Device* getDevice() { return device; }␊ |
192 | ␊ |
193 | ␉/**␊ |
194 | ␉ * @brief Get current client␊ |
195 | ␉ */␊ |
196 | ␉DRMProcessorClient* getClient() { return client; }␊ |
197 | ␉␉␊ |
198 | ␉/**␊ |
199 | ␉ * @brief Remove ADEPT DRM␊ |
200 | ␉ * Warning: for PDF format, filenameIn must be different than filenameOut␊ |
201 | ␉ *␊ |
202 | ␉ * @param filenameIn Input file (with ADEPT DRM)␊ |
203 | ␉ * @param filenameOut Output file (without ADEPT DRM)␊ |
204 | ␉ * @param type Type of file (ePub or PDF)␊ |
205 | ␉ * @param encryptionKey Optional encryption key, do not try to decrypt the one inside input file␊ |
206 | ␉ * @param encryptionKeySize Size of encryption key (if provided)␊ |
207 | ␉ */␊ |
208 | ␉void removeDRM(const std::string& filenameIn, const std::string& filenameOut, ITEM_TYPE type, const unsigned char* encryptionKey=0, unsigned encryptionKeySize=0);␊ |
209 | ␉␊ |
210 | private:␊ |
211 | ␉gourou::DRMProcessorClient* client;␊ |
212 | gourou::Device* device;␊ |
213 | gourou::User* user;␊ |
214 | ␉␊ |
215 | DRMProcessor(DRMProcessorClient* client);␊ |
216 | ␉␊ |
217 | ␉void pushString(void* sha_ctx, const std::string& string);␊ |
218 | ␉void pushTag(void* sha_ctx, uint8_t tag);␊ |
219 | ␉void hashNode(const pugi::xml_node& root, void *sha_ctx, std::map<std::string,std::string> nsHash);␊ |
220 | ␉void hashNode(const pugi::xml_node& root, unsigned char* sha_out);␊ |
221 | ␉void signNode(pugi::xml_node& rootNode);␊ |
222 | ␉void addNonce(pugi::xml_node& root);␊ |
223 | ␉void buildAuthRequest(pugi::xml_document& authReq);␊ |
224 | ␉void buildInitLicenseServiceRequest(pugi::xml_document& initLicReq, std::string operatorURL);␊ |
225 | ␉void doOperatorAuth(std::string operatorURL);␊ |
226 | ␉void operatorAuth(std::string operatorURL);␊ |
227 | ␉void buildFulfillRequest(pugi::xml_document& acsmDoc, pugi::xml_document& fulfillReq);␊ |
228 | ␉void buildActivateReq(pugi::xml_document& activateReq);␊ |
229 | ␉void buildReturnReq(pugi::xml_document& returnReq, const std::string& loanID, const std::string& operatorURL);␊ |
230 | ␉ByteArray sendFulfillRequest(const pugi::xml_document& document, const std::string& url);␊ |
231 | ␉void buildSignInRequest(pugi::xml_document& signInRequest, const std::string& adobeID, const std::string& adobePassword, const std::string& authenticationCertificate);␊ |
232 | ␉void fetchLicenseServiceCertificate(const std::string& licenseURL,␊ |
233 | ␉␉␉␉␉ const std::string& operatorURL);␊ |
234 | ␉std::string encryptedKeyFirstPass(pugi::xml_document& rightsDoc, const std::string& encryptedKey, const std::string& keyType, ITEM_TYPE type);␊ |
235 | ␉void decryptADEPTKey(const std::string& encryptedKey, unsigned char* decryptedKey);␊ |
236 | ␉void removeEPubDRM(const std::string& filenameIn, const std::string& filenameOut, const unsigned char* encryptionKey, unsigned encryptionKeySize);␊ |
237 | ␉void generatePDFObjectKey(int version,␊ |
238 | ␉␉␉␉ const unsigned char* masterKey, unsigned int masterKeyLength,␊ |
239 | ␉␉␉␉ int objectId, int objectGenerationNumber,␊ |
240 | ␉␉␉␉ unsigned char* keyOut);␊ |
241 | ␉void removePDFDRM(const std::string& filenameIn, const std::string& filenameOut, const unsigned char* encryptionKey, unsigned encryptionKeySize);␊ |
242 | };␊ |
243 | }␊ |
244 | ␊ |
245 | #endif␊ |