• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "param_check_utils.h"
17 
18 #include "cloud/cloud_db_constant.h"
19 #include "cloud/cloud_storage_utils.h"
20 #include "db_common.h"
21 #include "db_constant.h"
22 #include "db_errno.h"
23 #include "log_print.h"
24 #include "platform_specific.h"
25 
26 namespace DistributedDB {
CheckDataDir(const std::string & dataDir,std::string & canonicalDir)27 bool ParamCheckUtils::CheckDataDir(const std::string &dataDir, std::string &canonicalDir)
28 {
29     if (dataDir.empty() || (dataDir.length() > DBConstant::MAX_DATA_DIR_LENGTH)) {
30         LOGE("Invalid data directory[%zu]", dataDir.length());
31         return false;
32     }
33 
34     // After normalizing the path, determine whether the path is a legal path considered by the program.
35     // There has been guaranteed by the upper layer, So there is no need trustlist set here.
36     return (OS::GetRealPath(dataDir, canonicalDir) == E_OK);
37 }
38 
IsStoreIdSafe(const std::string & storeId)39 bool ParamCheckUtils::IsStoreIdSafe(const std::string &storeId)
40 {
41     if (storeId.empty() || (storeId.length() > DBConstant::MAX_STORE_ID_LENGTH)) {
42         LOGE("Invalid store id[%zu]", storeId.length());
43         return false;
44     }
45 
46     auto iter = std::find_if_not(storeId.begin(), storeId.end(),
47         [](char value) { return (std::isalnum(value) || value == '_'); });
48     if (iter != storeId.end()) {
49         LOGE("Invalid store id format");
50         return false;
51     }
52     return true;
53 }
54 
CheckStoreParameter(const std::string & storeId,const std::string & appId,const std::string & userId,bool isIgnoreUserIdCheck)55 bool ParamCheckUtils::CheckStoreParameter(const std::string &storeId, const std::string &appId,
56     const std::string &userId, bool isIgnoreUserIdCheck)
57 {
58     if (!IsStoreIdSafe(storeId)) {
59         return false;
60     }
61     if (!isIgnoreUserIdCheck) {
62         if (userId.empty() || userId.length() > DBConstant::MAX_USER_ID_LENGTH) {
63             LOGE("Invalid user info[%zu][%zu]", userId.length(), appId.length());
64             return false;
65         }
66         if (userId.find(DBConstant::ID_CONNECTOR) != std::string::npos) {
67             LOGE("Invalid userId character in the store para info.");
68             return false;
69         }
70     }
71     if (appId.empty() || appId.length() > DBConstant::MAX_APP_ID_LENGTH) {
72         LOGE("Invalid app info[%zu][%zu]", userId.length(), appId.length());
73         return false;
74     }
75 
76     if ((appId.find(DBConstant::ID_CONNECTOR) != std::string::npos) ||
77         (storeId.find(DBConstant::ID_CONNECTOR) != std::string::npos)) {
78         LOGE("Invalid character in the store para info.");
79         return false;
80     }
81     return true;
82 }
83 
CheckEncryptedParameter(CipherType cipher,const CipherPassword & passwd)84 bool ParamCheckUtils::CheckEncryptedParameter(CipherType cipher, const CipherPassword &passwd)
85 {
86     if (cipher != CipherType::DEFAULT && cipher != CipherType::AES_256_GCM) {
87         LOGE("Invalid cipher type!");
88         return false;
89     }
90 
91     return (passwd.GetSize() != 0);
92 }
93 
CheckConflictNotifierType(int conflictType)94 bool ParamCheckUtils::CheckConflictNotifierType(int conflictType)
95 {
96     if (conflictType <= 0) {
97         return false;
98     }
99     // Divide the type into different types.
100     if (conflictType >= CONFLICT_NATIVE_ALL) {
101         conflictType -= CONFLICT_NATIVE_ALL;
102     }
103     if (conflictType >= CONFLICT_FOREIGN_KEY_ORIG) {
104         conflictType -= CONFLICT_FOREIGN_KEY_ORIG;
105     }
106     if (conflictType >= CONFLICT_FOREIGN_KEY_ONLY) {
107         conflictType -= CONFLICT_FOREIGN_KEY_ONLY;
108     }
109     return (conflictType == 0);
110 }
111 
CheckSecOption(const SecurityOption & secOption)112 bool ParamCheckUtils::CheckSecOption(const SecurityOption &secOption)
113 {
114     if (secOption.securityLabel > S4 || secOption.securityLabel < NOT_SET) {
115         LOGE("[DBCommon] SecurityLabel is invalid, label is [%d].", secOption.securityLabel);
116         return false;
117     }
118     if (secOption.securityFlag != 0) {
119         if ((secOption.securityLabel != S3 && secOption.securityLabel != S4) || secOption.securityFlag != SECE) {
120             LOGE("[DBCommon] SecurityFlag is invalid.");
121             return false;
122         }
123     }
124     return true;
125 }
126 
CheckObserver(const Key & key,unsigned int mode)127 bool ParamCheckUtils::CheckObserver(const Key &key, unsigned int mode)
128 {
129     if (key.size() > DBConstant::MAX_KEY_SIZE) {
130         return false;
131     }
132 
133     if (mode > OBSERVER_CHANGES_LOCAL_ONLY || mode < OBSERVER_CHANGES_NATIVE) {
134         return false;
135     }
136     return true;
137 }
138 
IsS3SECEOpt(const SecurityOption & secOpt)139 bool ParamCheckUtils::IsS3SECEOpt(const SecurityOption &secOpt)
140 {
141     SecurityOption S3SeceOpt = {SecurityLabel::S3, SecurityFlag::SECE};
142     return (secOpt == S3SeceOpt);
143 }
144 
CheckAndTransferAutoLaunchParam(const AutoLaunchParam & param,bool checkDir,SchemaObject & schemaObject,std::string & canonicalDir)145 int ParamCheckUtils::CheckAndTransferAutoLaunchParam(const AutoLaunchParam &param, bool checkDir,
146     SchemaObject &schemaObject, std::string &canonicalDir)
147 {
148     if ((param.option.notifier && !ParamCheckUtils::CheckConflictNotifierType(param.option.conflictType)) ||
149         (!param.option.notifier && param.option.conflictType != 0)) {
150         LOGE("[AutoLaunch] CheckConflictNotifierType is invalid.");
151         return -E_INVALID_ARGS;
152     }
153     if (!ParamCheckUtils::CheckStoreParameter(param.storeId, param.appId, param.userId)) {
154         LOGE("[AutoLaunch] CheckStoreParameter is invalid.");
155         return -E_INVALID_ARGS;
156     }
157 
158     const AutoLaunchOption &option = param.option;
159     if (!ParamCheckUtils::CheckSecOption(option.secOption)) {
160         LOGE("[AutoLaunch] CheckSecOption is invalid.");
161         return -E_INVALID_ARGS;
162     }
163 
164     if (option.isEncryptedDb) {
165         if (!ParamCheckUtils::CheckEncryptedParameter(option.cipher, option.passwd)) {
166             LOGE("[AutoLaunch] CheckEncryptedParameter is invalid.");
167             return -E_INVALID_ARGS;
168         }
169     }
170 
171     if (!param.option.schema.empty()) {
172         schemaObject.ParseFromSchemaString(param.option.schema);
173         if (!schemaObject.IsSchemaValid()) {
174             LOGE("[AutoLaunch] ParseFromSchemaString is invalid.");
175             return -E_INVALID_SCHEMA;
176         }
177     }
178 
179     if (!checkDir) {
180         canonicalDir = param.option.dataDir;
181         return E_OK;
182     }
183 
184     if (!ParamCheckUtils::CheckDataDir(param.option.dataDir, canonicalDir)) {
185         LOGE("[AutoLaunch] CheckDataDir is invalid.");
186         return -E_INVALID_ARGS;
187     }
188     return E_OK;
189 }
190 
GetValidCompressionRate(uint8_t compressionRate)191 uint8_t ParamCheckUtils::GetValidCompressionRate(uint8_t compressionRate)
192 {
193     // Valid when between 1 and 100. When compressionRate is invalid, change it to default rate.
194     if (compressionRate < 1 || compressionRate > DBConstant::DEFAULT_COMPTRESS_RATE) {
195         LOGD("Invalid compression rate:%" PRIu8, compressionRate);
196         compressionRate = DBConstant::DEFAULT_COMPTRESS_RATE;
197     }
198     return compressionRate;
199 }
200 
CheckRelationalTableName(const std::string & tableName)201 bool ParamCheckUtils::CheckRelationalTableName(const std::string &tableName)
202 {
203     if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) {
204         return false;
205     }
206     return tableName.compare(0, DBConstant::SYSTEM_TABLE_PREFIX.size(), DBConstant::SYSTEM_TABLE_PREFIX) != 0;
207 }
208 
CheckTableReference(const std::vector<TableReferenceProperty> & tableReferenceProperty)209 bool ParamCheckUtils::CheckTableReference(const std::vector<TableReferenceProperty> &tableReferenceProperty)
210 {
211     if (tableReferenceProperty.empty()) {
212         LOGI("[CheckTableReference] tableReferenceProperty is empty");
213         return true;
214     }
215 
216     std::vector<std::vector<int>> dependency;
217     std::map<std::string, int, CaseInsensitiveComparator> tableName2Int;
218     int index = 0;
219     for (const auto &item : tableReferenceProperty) {
220         if (item.sourceTableName.empty() || item.targetTableName.empty() || item.columns.empty()) {
221             LOGE("[CheckTableReference] table name or column is empty");
222             return false;
223         }
224         std::vector<int> vec;
225         for (const auto &tableName : { item.sourceTableName, item.targetTableName }) {
226             if (tableName2Int.find(tableName) != tableName2Int.end()) {
227                 vec.push_back(tableName2Int.at(tableName));
228             } else {
229                 vec.push_back(index);
230                 tableName2Int[tableName] = index;
231                 index++;
232             }
233         }
234         if (std::find(dependency.begin(), dependency.end(), vec) != dependency.end()) {
235             LOGE("[CheckTableReference] set multiple reference for two tables is not support.");
236             return false;
237         }
238         dependency.emplace_back(vec);
239     }
240 
241     if (DBCommon::IsCircularDependency(index, dependency)) {
242         LOGE("[CheckTableReference] circular reference is not support.");
243         return false;
244     }
245     return true;
246 }
247 
CheckSharedTableName(const DataBaseSchema & schema)248 bool ParamCheckUtils::CheckSharedTableName(const DataBaseSchema &schema)
249 {
250     DataBaseSchema lowerSchema = schema;
251     TransferSchemaToLower(lowerSchema);
252     std::set<std::string> tableNames;
253     std::set<std::string> sharedTableNames;
254     for (const auto &tableSchema : lowerSchema.tables) {
255         if (tableSchema.sharedTableName.empty()) {
256             continue;
257         }
258         if (tableSchema.sharedTableName == tableSchema.name) {
259             LOGE("[CheckSharedTableName] Shared table name and table name are same.");
260             return false;
261         }
262         if (sharedTableNames.find(tableSchema.sharedTableName) != sharedTableNames.end() ||
263             sharedTableNames.find(tableSchema.name) != sharedTableNames.end() ||
264             tableNames.find(tableSchema.sharedTableName) != tableNames.end() ||
265             tableNames.find(tableSchema.name) != tableNames.end()) {
266             LOGE("[CheckSharedTableName] Shared table names or table names are duplicate.");
267             return false;
268         }
269         if (!CheckRelationalTableName(tableSchema.sharedTableName)) {
270             return false;
271         }
272         tableNames.insert(tableSchema.name);
273         sharedTableNames.insert(tableSchema.sharedTableName);
274         std::set<std::string> fields;
275         for (const auto &field : tableSchema.fields) {
276             if (fields.find(field.colName) != fields.end() || field.colName == CloudDbConstant::CLOUD_OWNER ||
277                 field.colName == CloudDbConstant::CLOUD_PRIVILEGE) {
278                 LOGE("[CheckSharedTableName] fields are duplicate.");
279                 return false;
280             }
281             fields.insert(field.colName);
282         }
283     }
284     return true;
285 }
286 
TransferSchemaToLower(DataBaseSchema & schema)287 void ParamCheckUtils::TransferSchemaToLower(DataBaseSchema &schema)
288 {
289     for (auto &tableSchema : schema.tables) {
290         std::transform(tableSchema.name.begin(), tableSchema.name.end(), tableSchema.name.begin(), tolower);
291         std::transform(tableSchema.sharedTableName.begin(), tableSchema.sharedTableName.end(),
292             tableSchema.sharedTableName.begin(), tolower);
293         for (auto &field : tableSchema.fields) {
294             std::transform(field.colName.begin(), field.colName.end(), field.colName.begin(), tolower);
295         }
296     }
297 }
298 } // namespace DistributedDB