1 /*  $Id: test_resource_info.cpp 534857 2017-05-03 12:26:07Z ivanov $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author:  Aleksey Grichenko
27  *
28  * File Description:
29  *   Test for secure resources API
30  *
31  */
32 
33 #include <ncbi_pch.hpp>
34 #include <corelib/ncbiapp.hpp>
35 #include <corelib/ncbiargs.hpp>
36 #include <corelib/ncbifile.hpp>
37 #include <corelib/resource_info.hpp>
38 
39 #include <common/test_assert.h>  /* This header must go last */
40 
41 USING_NCBI_SCOPE;
42 
43 
44 //////////////////////////////////////////////////////////////////////////////
45 //
46 // Test application
47 //
48 
49 
50 class CResInfoTest : public CNcbiApplication
51 {
52 public:
53     void Init(void);
54     int  Run(void);
55 };
56 
57 
Init(void)58 void CResInfoTest::Init(void)
59 {
60     unique_ptr<CArgDescriptions> arg_desc(new CArgDescriptions);
61     string prog_description = "Test for CNcbiResourceInfo\n";
62     arg_desc->SetUsageContext(GetArguments().GetProgramBasename(), prog_description, false);
63     SetupArgDescriptions(arg_desc.release());
64 }
65 
66 
67 const char*  src_name  = "resinfo_plain.txt";
68 
69 const char*  test1_res = "resource_info/some_user@some_server";
70 const char*  test1_pwd = "resinfo_password";
71 const char*  test1_val = "server_password";
72 
73 const char*  test2_res = "resource_info/some_user@some_server";
74 const char*  test2_pwd = "resinfo_password2";
75 const char*  test2_val = "server_password2";
76 const char*  test2_ex  = "username=anyone&server=server_name";
77 
78 const char*  test3_res = "resource_info2/another_user@another_server";
79 const char*  test3_pwd = "resinfo_password";
80 const char*  test3_val = "server_password";
81 const char*  test3_ex  = "username=onemore&server=server_name";
82 
83 typedef CNcbiResourceInfo::TExtraValuesMap TExtraValuesMap;
84 typedef CNcbiResourceInfo::TExtraValues    TExtraValues;
85 
86 
CheckExtra(const CNcbiResourceInfo & info,const string & ref)87 void CheckExtra(const CNcbiResourceInfo& info, const string& ref)
88 {
89     // The order of extra values is undefined
90     const TExtraValuesMap& info_ex = info.GetExtraValues().GetPairs();
91     TExtraValues ref_ex_pairs;
92     ref_ex_pairs.Parse(ref);
93     const TExtraValuesMap& ref_ex = ref_ex_pairs.GetPairs();
94     _ASSERT(info_ex.size() == ref_ex.size());
95     ITERATE(TExtraValuesMap, it, info_ex) {
96         TExtraValuesMap::const_iterator match = ref_ex.find(it->first);
97         _ASSERT(match != ref_ex.end());
98         _ASSERT(match->second == it->second);
99     }
100 }
101 
102 
Run(void)103 int CResInfoTest::Run(void)
104 {
105     string enc_name = CFile::GetTmpName();
106     _ASSERT(!enc_name.empty());
107     //CFileDeleteAtExit::Add(enc_name);
108 
109     {{
110         // Encode and save the source plaintext file
111         CNcbiResourceInfoFile newfile(enc_name);
112         newfile.ParsePlainTextFile(src_name);
113         newfile.SaveFile();
114     }}
115 
116     // Load the created file and get some resource info
117     CNcbiResourceInfoFile resfile(enc_name);
118 
119     const CNcbiResourceInfo& info1 =
120         resfile.GetResourceInfo(test1_res, test1_pwd);
121     _ASSERT(info1); // success?
122     _ASSERT(info1.GetValue() == test1_val); // check main value
123     _ASSERT(info1.GetExtraValues().GetPairs().empty()); // no extra data
124 
125     const CNcbiResourceInfo& info2 =
126         resfile.GetResourceInfo(test2_res, test2_pwd);
127     _ASSERT(info2); // success?
128     _ASSERT(info2.GetValue() == test2_val); // check main value
129     CheckExtra(info2, test2_ex);
130 
131     const CNcbiResourceInfo& info3 =
132         resfile.GetResourceInfo(test3_res, test3_pwd);
133     _ASSERT(info3); // success?
134     _ASSERT(info3.GetValue() == test3_val); // check main value
135     CheckExtra(info3, test3_ex);
136 
137     // Test string encryption/decrypton using an explicit password.
138     string data = "Test CNcbiEncrypt class";
139     string key = CNcbiEncrypt::GenerateKey("foobar");
140     _ASSERT(key == "2BCB50C9A5FC53A1608242FE827BAE228:0AA2C441A5F2F3DB7E9565E9349C18AB");
141     string encr = CNcbiEncrypt::Encrypt(data, "foobar");
142     string decr = CNcbiEncrypt::Decrypt(encr, "foobar");
143     _ASSERT(decr == data);
144     // Test v1 decryption
145     string v1_encr = "1BCB50C9A5FC53A1608242FE827BAE228:A8F7030E91CCF4E5FDF7C0F3F734BEBBDA2AAB8583729E9E5F438D1E569F2F21";
146     decr = CNcbiEncrypt::Decrypt(v1_encr, "foobar");
147     _ASSERT(decr == data);
148 
149     // Test decryption using ncbi keys file, the key is a non-default one
150     // (not the first key in the file).
151     decr = CNcbiEncrypt::Decrypt(encr);
152     _ASSERT(decr == data);
153 
154     // Test automatic key selection.
155     encr = CNcbiEncrypt::Encrypt(data);
156     decr = CNcbiEncrypt::Decrypt(encr);
157     _ASSERT(decr == data);
158     v1_encr = "1E5606B599D707645329ABE4E0E3F6AC9:52CE4D659462C9ABA48CF7588D8E1FD9D5CD52EFCE578B0A40AF9B4D1208CF9F";
159     decr = CNcbiEncrypt::Decrypt(v1_encr);
160     _ASSERT(decr == data);
161 
162     // Test domain encryption.
163     encr = CNcbiEncrypt::EncryptForDomain(data, "domain");
164     // Automatic domain key selection.
165     decr = CNcbiEncrypt::Decrypt(encr);
166     _ASSERT(decr == data);
167     // Explicit domain
168     decr = CNcbiEncrypt::DecryptForDomain(encr, "domain");
169     _ASSERT(decr == data);
170     // Two domains
171     decr = CNcbiEncrypt::DecryptForDomain(encr, "domain2");
172     _ASSERT(decr == data);
173     v1_encr = "11BDF0BA7079A8C2BD6656D3CF2D79160:3F7930D402567001F058086D263539596792628CEEF15AFE9D7E84FCD9C7BC14/domain";
174     decr = CNcbiEncrypt::Decrypt(v1_encr);
175     _ASSERT(decr == data);
176 
177     // Test IsEncrypted()
178     // Encrypted data
179     _ASSERT(CNcbiEncrypt::IsEncrypted("1E5606B599D707645329ABE4E0E3F6AC9:52CE4D659462C9ABA48CF7588D8E1FD9D5CD52EFCE578B0A40AF9B4D1208CF9F"));
180     // Encrypted data with domain
181     _ASSERT(CNcbiEncrypt::IsEncrypted("11BDF0BA7079A8C2BD6656D3CF2D79160:3F7930D402567001F058086D263539596792628CEEF15AFE9D7E84FCD9C7BC14/domain"));
182     // False-positive - the format is correct, but the string contains garbage.
183     _ASSERT(CNcbiEncrypt::IsEncrypted("10123456789ABCDEF0123456789ABCDEF:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"));
184     // False-positive - the format is correct (with domain), but the string contains garbage.
185     _ASSERT(CNcbiEncrypt::IsEncrypted("10123456789ABCDEF0123456789ABCDEF:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF/not an actual domain"));
186     // Empty domain
187     _ASSERT(!CNcbiEncrypt::IsEncrypted("10123456789ABCDEF0123456789ABCDEF:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF/"));
188     // Missing version
189     _ASSERT(!CNcbiEncrypt::IsEncrypted("0123456789ABCDEF0123456789ABCDEF:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"));
190     // Invalid version
191     _ASSERT(!CNcbiEncrypt::IsEncrypted("00123456789ABCDEF0123456789ABCDEF:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"));
192     // Wrong checksum length
193     _ASSERT(!CNcbiEncrypt::IsEncrypted("10123456789ABCDEF0123456789ABCDE:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"));
194     _ASSERT(!CNcbiEncrypt::IsEncrypted("10123456789ABCDEF0123456789ABCDEFF:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"));
195     // Checksum is not a HEX value
196     _ASSERT(!CNcbiEncrypt::IsEncrypted("10123456789ABCDEF0123456789ABCDEz:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"));
197     // Missing checksum separator
198     _ASSERT(!CNcbiEncrypt::IsEncrypted("10123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"));
199     // Empty encrypted part
200     _ASSERT(!CNcbiEncrypt::IsEncrypted("10123456789ABCDEF0123456789ABCDEF:"));
201     // Data has wrong length
202     _ASSERT(!CNcbiEncrypt::IsEncrypted("10123456789ABCDEF0123456789ABCDEF:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDE"));
203     _ASSERT(!CNcbiEncrypt::IsEncrypted("10123456789ABCDEF0123456789ABCDEF:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEFF"));
204     // Data is not a HEX string
205     _ASSERT(!CNcbiEncrypt::IsEncrypted("10123456789ABCDEF0123456789ABCDEF:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEz"));
206 
207     // Test registry glue
208     bool caught_exception = false;
209     const CNcbiRegistry& reg = GetConfig();
210     string s = reg.GetEncryptedString("NCBI_KEY", "Paths",
211                                       IRegistry::fPlaintextAllowed);
212     _ASSERT(s == ".");
213     try {
214         reg.GetEncryptedString("NCBI_KEY", "Paths");
215     } catch (CRegistryException&) {
216         caught_exception = true;
217     }
218     _ASSERT(caught_exception);
219 
220     s = reg.GetEncryptedString("sect", "val1", 0, "foobar");
221     _ASSERT(s == data);
222     try {
223         caught_exception = false;
224         reg.GetEncryptedString("sect", "val1", 0, "baz");
225     } catch (CRegistryException&) {
226         caught_exception = true;
227     }
228     _ASSERT(caught_exception);
229     // Decrypt with the default key
230     s = reg.GetEncryptedString("sect", "val1");
231     _ASSERT(s == data);
232     // Decrypt with a non-default key
233     s = reg.GetEncryptedString("sect", "val2");
234     _ASSERT(s == data);
235     // Decryt with a domain key
236     s = reg.GetEncryptedString("sect", "val3");
237     _ASSERT(s == data);
238 
239     cout << "All tests passed" << endl;
240     return 0;
241 }
242 
243 
244 /////////////////////////////////////////////////////////////////////////////
245 //  MAIN
246 
main(int argc,const char * argv[])247 int main(int argc, const char* argv[])
248 {
249     return CResInfoTest().AppMain(argc, argv);
250 }
251