Linux のコード例Linux code examples

このトピックでは、Linux バージョンの RMS SDK の重要なシナリオとコード要素について説明します。This topic introduces you to important scenarios and code elements for the Linux version of the RMS SDK.

次のコード スニペットは、サンプル アプリケーション、rms_sample および rmsauth_sample からのものです。The code snippets below are from the sample applications, rms_sample and rmsauth_sample. 詳しくは、GitHub リポジトリの「サンプル」をご覧ください。For more information, see samples at the GitHub repository.

シナリオ: 保護されたファイルから保護ポリシー情報にアクセスするScenario: Access protection policy information from a protected file

RMS 保護ファイルを開いて読み取ります ソース: rms_sample/mainwindow.cppOpens and reads an RMS protected file Source: rms_sample/mainwindow.cpp

説明: ユーザーからファイル名を取得したら、証明書を読み取り (MainWindow::addCertificates を参照)、クライアント ID とリダイレクト URL で承認コールバックを設定し、ConvertFromPFile を呼び出してから (次のコード例を参照)、保護ポリシー名、説明、およびコンテンツの有効期日を読み取ります。Description: After getting a file name from the user, reading the certificates (see MainWindow::addCertificates), setting up the authorization callback with Client ID and Redirect URL, calling ConvertFromPFile (see following code example), then reading out the protection policy name, description and content validity date.

C++ :C++:

void MainWindow::ConvertFromPFILE(const string& fileIn,
    const string& clientId,
    const string& redirectUrl,
    const string& clientEmail) 
{
// add trusted certificates using HttpHelpers of RMS and Auth SDKs
addCertificates();

// create shared in/out streams
auto inFile = make_shared<ifstream>(
fileIn, ios_base::in | ios_base::binary);

if (!inFile->is_open()) {
 AddLog("ERROR: Failed to open ", fileIn.c_str());
return;
}

string fileOut;

// generate output filename
auto pos = fileIn.find_last_of('.');

if (pos != string::npos) {
 fileOut = fileIn.substr(0, pos);
}

 // create streams
auto outFile = make_shared<fstream>(
fileOut, ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary);

if (!outFile->is_open()) {
 AddLog("ERROR: Failed to open ", fileOut.c_str());
 return;
  }

try
{
// create authentication context
AuthCallback auth(clientId, redirectUrl);

// process conversion
auto pfs = PFileConverter::ConvertFromPFile(
  clientEmail,
  inFile,
  outFile,
  auth,
  this->consent);

AddLog("Successfully converted to ", fileOut.c_str());
}
catch (const rmsauth::Exception& e)
{
AddLog("ERROR: ", e.error().c_str());
}
catch (const rmscore::exceptions::RMSException& e) {
AddLog("ERROR: ", e.what());
}
inFile->close();
outFile->close();
}

保護されたファイル ストリームを作成します ソース: rms_sample/pfileconverter.cppCreate a protected file stream Source: rms_sample/pfileconverter.cpp

説明: このメソッドは、SDK メソッドProtectedFileStream:: 獲得を通じて渡されたバッキングストリームから、保護されたファイルストリームを作成します。このメソッドは、呼び出し元に返されます。Description: This method creates a protected file stream from the passed in backing stream through the SDK method, ProtectedFileStream::Acquire, which is then returned to the caller.

C++ :C++:

shared_ptr<GetProtectedFileStreamResult>PFileConverter::ConvertFromPFile(
const string           & userId,
shared_ptr<istream>      inStream,
shared_ptr<iostream>     outStream,
IAuthenticationCallback& auth,
IConsentCallback       & consent)
{
auto inIStream = rmscrypto::api::CreateStreamFromStdStream(inStream);

auto fsResult = ProtectedFileStream::Acquire(
inIStream,
userId,
auth,
consent,
POL_None,
static_cast<ResponseCacheFlags>(RESPONSE_CACHE_INMEMORY
                                | RESPONSE_CACHE_ONDISK));

if ((fsResult.get() != nullptr) && (fsResult->m_status == Success) &&
  (fsResult->m_stream != nullptr)) {
auto pfs = fsResult->m_stream;

// preparing
readPosition  = 0;
writePosition = 0;
totalSize     = pfs->Size();

// start threads
for (size_t i = 0; i < THREADS_NUM; ++i) {
  threadPool.push_back(thread(WorkerThread,
                              static_pointer_cast<iostream>(outStream), pfs,
                              false));
}

for (thread& t: threadPool) {
  if (t.joinable()) {
    t.join();
  }
}
}
  return fsResult;
}

シナリオ: テンプレートを使用して新しい保護ファイルを作成するScenario: Create a new protected file using a template

ユーザーが選択したテンプレートを使用してファイルを保護します ソース: rms_sample/mainwindow.cppProtects a file with a user selected template Source: rms_sample/mainwindow.cpp

説明: ユーザーからファイル名を取得したら、証明書を読み取り (MainWindow::addCertificates を参照)、クライアント ID とリダイレクト URL で承認コールバックを設定し、選択したファイルを ConvertToPFileTemplates を呼び出して保護します (次のコード例を参照)。Description: After getting a file name from the user, reading the certificates (see MainWindow::addCertificates) and setting up the authorization callback with Client ID and Redirect URL, the selected file is protected by calling ConvertToPFileTemplates (see following code example).

C++ :C++:

void MainWindow::ConvertToPFILEUsingTemplates(const string& fileIn,
                                          const string& clientId,
                                          const string& redirectUrl,
                                          const string& clientEmail) 
{
// generate output filename
string fileOut = fileIn + ".pfile";

// add trusted certificates using HttpHelpers of RMS and Auth SDKs
addCertificates();

// create shared in/out streams
auto inFile = make_shared<ifstream>(
fileIn, ios_base::in | ios_base::binary);
auto outFile = make_shared<fstream>(
fileOut, ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary);

if (!inFile->is_open()) {
AddLog("ERROR: Failed to open ", fileIn.c_str());
return;
}

if (!outFile->is_open()) {
AddLog("ERROR: Failed to open ", fileOut.c_str());
return;
}

// find file extension
string fileExt;
auto   pos = fileIn.find_last_of('.');

if (pos != string::npos) {
fileExt = fileIn.substr(pos);
}

try {
// create authentication callback
AuthCallback auth(clientId, redirectUrl);

// process conversion
PFileConverter::ConvertToPFileTemplates(
  clientEmail, inFile, fileExt, outFile, auth,
  this->consent, this->templates);

AddLog("Successfully converted to ", fileOut.c_str());
}

catch (const rmsauth::Exception& e) { AddLog("ERROR: ", e.error().c_str()); outFile->close(); remove(fileOut.c_str()); } catch (const rmscore::exceptions::RMSException& e) { AddLog("ERROR: ", e.what());catch (const rmsauth::Exception& e) { AddLog("ERROR: ", e.error().c_str()); outFile->close(); remove(fileOut.c_str()); } catch (const rmscore::exceptions::RMSException& e) { AddLog("ERROR: ", e.what());

outFile->close();
remove(fileOut.c_str());
}
inFile->close();
outFile->close();
}

テンプレートから作成されたポリシーを使用してファイルを保護します ソース: rms_sample/pfileconverter.cppProtects a file using a policy created from a template Source: rms_sample/pfileconverter.cpp

説明: ユーザーに関連付けられたテンプレートの一覧がフェッチされ、選択したテンプレートがポリシーの作成に使用されます。このポリシーを使用してファイルを保護します。Description: A list of templates associated with the user is fetched and selected template is then used to create a policy which in turn is used to protect the file.

C++ :C++:

void PFileConverter::ConvertToPFileTemplates(const string           & userId,
                                         shared_ptr<istream>      inStream,
                                         const string           & fileExt,
                                         std::shared_ptr<iostream>outStream,
                                         IAuthenticationCallback& auth,
                                         IConsentCallback& /*consent*/,
                                         ITemplatesCallback     & templ)
{
auto templates = TemplateDescriptor::GetTemplateList(userId, auth);

rmscore::modernapi::AppDataHashMap signedData;

size_t pos = templ.SelectTemplate(templates);

if (pos < templates.size()) {
auto policy = UserPolicy::CreateFromTemplateDescriptor(
  templates[pos],
  userId,
  auth,
  USER_AllowAuditedExtraction,
  signedData);

ConvertToPFileUsingPolicy(policy, inStream, fileExt, outStream);
}
}

ポリシーを指定してファイルを保護します ソース: rms_sample/pfileconverter.cppProtects a file given a policy Source: rms_sample/pfileconverter.cpp

説明: 特定のポリシーを使用して保護されたファイル ストリームを作成し、そのファイルを保護します。Description: Create a protected file stream using the given policy then protect that file.

C++ :C++:

void PFileConverter::ConvertToPFileUsingPolicy(shared_ptr<UserPolicy>   policy,
                                           shared_ptr<istream>      inStream,
                                           const string           & fileExt,
                                           std::shared_ptr<iostream>outStream)
{
if (policy.get() != nullptr) {
auto outIStream = rmscrypto::api::CreateStreamFromStdStream(outStream);
auto pStream    = ProtectedFileStream::Create(policy, outIStream, fileExt);

// preparing
readPosition  = 0;
writePosition = pStream->Size();

inStream->seekg(0, ios::end);
totalSize = inStream->tellg();

// start threads
for (size_t i = 0; i < THREADS_NUM; ++i) {
  threadPool.push_back(thread(WorkerThread,
                              static_pointer_cast<iostream>(inStream),
                              pStream,
                              true));
}

for (thread& t: threadPool) {
  if (t.joinable()) {
    t.join();
  }
}

pStream->Flush();
}

シナリオ: カスタム保護を使用してファイルを保護するScenario: Protect a file using custom protection

カスタム保護を使用してファイルを保護します ソース: rms_sample/mainwindow.cppProtects a file using custom protection Source: rms_sample/mainwindow.cpp

説明: ユーザーからファイル名を取得したら、証明書を読み取り (MainWindow::addCertificates を参照)、ユーザーから権限情報を収集し、クライアント ID とリダイレクト URL で承認コールバックを設定し、選択したファイルを ConvertToPFilePredefinedRights を呼び出して保護します (次のコード例を参照)。Description: After getting a file name from the user, reading the certificates (see MainWindow::addCertificates), collecting rights information from the user, and setting up the authorization callback with Client ID and Redirect URL, the selected file is projected by calling ConvertToPFilePredefinedRights (see following code example).

C++ :C++:

void MainWindow::ConvertToPFILEUsingRights(const string            & fileIn,
                                       const vector<UserRights>& userRights,
                                       const string            & clientId,
                                       const string            & redirectUrl,
                                       const string            & clientEmail)
{
// generate output filename
string fileOut = fileIn + ".pfile";

// add trusted certificates using HttpHelpers of RMS and Auth SDKs
addCertificates();

// create shared in/out streams
auto inFile = make_shared<ifstream>(
fileIn, ios_base::in | ios_base::binary);
auto outFile = make_shared<fstream>(
fileOut, ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary);

if (!inFile->is_open()) {
AddLog("ERROR: Failed to open ", fileIn.c_str());
return;
}

if (!outFile->is_open()) {
AddLog("ERROR: Failed to open ", fileOut.c_str());
return;
}

// find file extension
string fileExt;
auto   pos = fileIn.find_last_of('.');

if (pos != string::npos) {
fileExt = fileIn.substr(pos);
}

// is anything to add
if (userRights.size() == 0) {
AddLog("ERROR: ", "Please fill email and check rights");
return;
}


try {
// create authentication callback
AuthCallback auth(clientId, redirectUrl);

// process conversion
PFileConverter::ConvertToPFilePredefinedRights(
  clientEmail,
  inFile,
  fileExt,
  outFile,
  auth,
  this->consent,
  userRights);

AddLog("Successfully converted to ", fileOut.c_str());
}
catch (const rmsauth::Exception& e) {
AddLog("ERROR: ", e.error().c_str());

outFile->close();
remove(fileOut.c_str());
}
catch (const rmscore::exceptions::RMSException& e) {
AddLog("ERROR: ", e.what());

outFile->close();
remove(fileOut.c_str());
}
inFile->close();
outFile->close();
}

ユーザーが選択した権限を指定して保護ポリシーを作成します ソース: rms_sample/pfileconverter.cppCreates a protection policy give user selected rights Source: rms_sample/pfileconverter.cpp

説明: ポリシー記述子を作成し、ユーザーの権限情報を使ってこれを入力し、このポリシー記述子を使用してユーザー ポリシーを作成します。Description: Create a policy descriptor and fill it with the user's rights information then, use the policy descriptor to create a user policy. このポリシーを使用して ConvertToPFileUsingPolicy への呼び出しにより選択したファイルを保護します (このトピックの前のセクションの説明を参照)。This policy is used to protect the selected file via a call to ConvertToPFileUsingPolicy (see this described in a previous section of this topic).

C++ :C++:

void PFileConverter::ConvertToPFilePredefinedRights(
const string            & userId,
shared_ptr<istream>       inStream,
const string            & fileExt,
shared_ptr<iostream>      outStream,
IAuthenticationCallback & auth,
IConsentCallback& /*consent*/,
const vector<UserRights>& userRights)
{
auto endValidation = chrono::system_clock::now() + chrono::hours(48);


PolicyDescriptor desc(userRights);

desc.Referrer(make_shared<string>("https://client.test.app"));
desc.ContentValidUntil(endValidation);
desc.AllowOfflineAccess(false);
desc.Name("Test Name");
desc.Description("Test Description");

auto policy = UserPolicy::Create(desc, userId, auth,
                               USER_AllowAuditedExtraction);
ConvertToPFileUsingPolicy(policy, inStream, fileExt, outStream);

WorkerThread - サポート メソッドWorkerThread - a supporting method

WorkerThread() メソッドは、上のシナリオ例の 2 つ (保護されたファイル ストリームの作成およびポリシーを指定してファイルを保護) によって、次の方法で呼び出されます。The WorkerThread() method is called by two of the previous example scenarios; Create a protected file stream and Protects a file given a policy in the following manner:

C++ :C++:

threadPool.push_back(thread(WorkerThread,
                              static_pointer_cast<iostream>(outStream), pfs,
                              false));

サポート メソッド、WorkerThread()Supporting method, WorkerThread()

C++ :C++:

static mutex   threadLocker;
static int64_t totalSize     = 0;
static int64_t readPosition  = 0;
static int64_t writePosition = 0;
static vector<thread> threadPool;

static void WorkerThread(shared_ptr<iostream>           stdStream,
                     shared_ptr<ProtectedFileStream>pStream,
                     bool                           modeWrite) {
vector<uint8_t> buffer(4096);
int64_t bufferSize = static_cast<int64_t>(buffer.size());

while (totalSize - readPosition > 0) {
// lock
threadLocker.lock();

// check remain
if (totalSize - readPosition <= 0) {
  threadLocker.unlock();
  return;
}

// get read/write offset
int64_t offsetRead  = readPosition;
int64_t offsetWrite = writePosition;
int64_t toProcess   = min(bufferSize, totalSize - readPosition);
readPosition  += toProcess;
writePosition += toProcess;

// no need to lock more
threadLocker.unlock();

if (modeWrite) {
  // stdStream is not thread safe!!!
  try {
    threadLocker.lock();

    stdStream->seekg(offsetRead);
    stdStream->read(reinterpret_cast<char *>(&buffer[0]), toProcess);
    threadLocker.unlock();
    auto written =
      pStream->WriteAsync(
        buffer.data(), toProcess, offsetWrite, std::launch::deferred).get();

    if (written != toProcess) {
      throw rmscore::exceptions::RMSStreamException("Error while writing data");
    }
  }
  catch (exception& e) {
    qDebug() << "Exception: " << e.what();
  }
} else {
  auto read =
    pStream->ReadAsync(&buffer[0],
                       toProcess,
                       offsetRead,
                       std::launch::deferred).get();

  if (read == 0) {
    break;
  }

  try {
    // stdStream is not thread safe!!!
    threadLocker.lock();

    // seek to write
    stdStream->seekp(offsetWrite);
    stdStream->write(reinterpret_cast<const char *>(buffer.data()), read);
    threadLocker.unlock();
  }
  catch (exception& e) {
    qDebug() << "Exception: " << e.what();
  }
}
}
}

シナリオ: RMS 認証Scenario: RMS authentication

次の例は、2 つの異なる認証方法 (UI を使用、または使用せずに Azure 認証 oAuth2 トークンを取得) を示しています。The following examples show two different authentication approaches; obtaining Azure Authentication oAuth2 token using UI and without UI. UI を使用した oAuth2 認証トークンの取得 ソース: rmsauth_sample/mainwindow.cppAcquiring oAuth2 Authentication Token with UI Source: rmsauth_sample/mainwindow.cpp

手順 1: rmsauth::FileCache オブジェクトの共有ポイントを作成します。Step 1: Create a shared point of rmsauth::FileCache object. 説明: キャッシュのパスを設定するか、既定値を使用できます。Description: You can set cache path or use default.

C++ :C++:

auto FileCachePtr = std::make_shared< rmsauth::FileCache>();

手順 2: rmsauth::AuthenticationContext オブジェクトを作成します。説明: Azure 証明機関 URIFileCache オブジェクトを指定します。Step 2: Create rmsauth::AuthenticationContext object Description: Specify Azure authority URI and FileCache object.

C++ :C++:

AuthenticationContext authContext(
                          std::string(“https://sts.aadrm.com/_sts/oauth/authorize”),
                          AuthorityValidationType::False,
                          FileCachePtr);

手順 3: AuthcontextオブジェクトのacquireTokenメソッドを呼び出し、次のパラメーターを指定します。説明:Step 3: Call acquireToken method of authContext object and specify next parameters: Description:

  • 要求されるリソース - アクセスする必要のある保護されたリソースRequested resource - protected resource you want to access
  • クライアントの一意な ID - 通常は GUIDClient unique ID - usually a GUID
  • リダイレクト URI - 認証トークンがフェッチされた後に回送される URIRedirection URI - the URI which will be readdressed after authentication token fetched
  • 認証プロンプトの動作 - PromptBehavior::Auto を設定した場合、必要に応じて、ライブラリによりキャッシュの使用トークンの更新が試行されますAuthentication prompt behavior - if you set PromptBehavior::Auto the library tries to use cache and refresh token if necessary
  • ユーザー ID - プロンプト ウィンドウに表示されるユーザー名User ID - User name displayed in the prompt window

C++ :C++:

auto result = authContext.acquireToken(
            std::string(“api.aadrm.com”),
            std::string(“4a63455a-cfa1-4ac6-bd2e-0d046cf1c3f7”),
            std::string(“https://client.test.app”),
            PromptBehavior::Auto,
            std::string(“john.smith@msopentechtest01.onmicrosoft.com”));

手順 4: 結果からアクセス トークンを取得します。説明: result-> accessToken() メソッドを呼び出します。Step 4: Get access token from result Description: Call result-> accessToken() method

いずれかの認証ライブラリ メソッドにより rmsauth::Exception が発生する場合がありますNote Any of the authentication library methods may raise rmsauth::Exception

UI なしの oAuth2 認証トークンの取得 ソース: rmsauth_sample/mainwindow.cppAcquiring oAuth2 Authentication Token without UI Source: rmsauth_sample/mainwindow.cpp

手順 1: rmsauth::FileCache オブジェクトの共有ポイントを作成します。説明: キャッシュのパスを設定するか、既定値を使用できます。Step 1: Create a shared point of rmsauth::FileCache object Description: You can set cache path or use default

C++ :C++:

auto FileCachePtr = std::make_shared< rmsauth::FileCache>();

手順 2: UserCredential オブジェクトを作成します。説明: ユーザー ログインパスワードを指定します。Step 2:Create UserCredential object Description: Specify user login and password

C++ :C++:

auto userCred = std::make_shared<UserCredential>("john.smith@msopentechtest01.onmicrosoft.com",
                                             "SomePass");

手順 3: rmsauth::AuthenticationContext オブジェクトを作成します。説明: Azure 証明機関 URIFileCache オブジェクトを指定します。Step 3:Create rmsauth::AuthenticationContext object Description: Specify Azure authority URI and FileCache object

C++ :C++:

AuthenticationContext authContext(
                    std::string(“https://sts.aadrm.com/_sts/oauth/authorize”),
                    AuthorityValidationType::False,
                    FileCachePtr);

手順 4: AuthcontextacquireTokenメソッドを呼び出し、パラメーターを指定します。Step 4: Call the acquireToken method of authContext and specify parameters:

  • 要求されるリソース - アクセスする必要のある保護されたリソースRequested resource - protected resource you want to access
  • クライアントの一意な ID - 通常は GUIDClient unique ID - usually a GUID
  • ユーザーの資格情報 - 作成されたオブジェクトを渡しますUser credentials - pass the created object

C++ :C++:

auto result = authContext.acquireToken(
            std::string(“api.aadrm.com”),
            std::string(“4a63455a-cfa1-4ac6-bd2e-0d046cf1c3f7”),
            userCred);

手順 5: 結果からアクセス トークンを取得します。説明: result-> accessToken() メソッドを呼び出します。Step 5: Get access token from result Description: Call result-> accessToken() method

いずれかの認証ライブラリ メソッドにより rmsauth::Exception が発生する場合がありますNote Any of the authentication library methods may raise rmsauth::Exception