1/* 2 * Copyright (c) 2023 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 */ 15extern crate key_enable; 16extern crate ylong_json; 17 18use std::thread; 19use ylong_json::JsonValue; 20use key_enable::cert_chain_utils::PemCollection; 21use key_enable::cert_path_utils::TrustCertPath; 22use key_enable::profile_utils::{UDID, get_udid, validate_bundle_and_distribution_type}; 23 24 25// pem_cert_file 26const VALID_PEM_CERT: &str = "/data/test/tmp/valid_pem_cert.json"; 27const NON_EXISTEND_PEM_CERT: &str = "/data/test/tmp/non_existent_cert_path.json"; 28const INVALID_STRUCTURE_PEM_CERT: &str = "/data/test/tmp/invalid_structure_cert_path.json"; 29const EMPTY_PEM_CERT: &str = "/data/test/tmp/empty_pem_cert.json"; 30// cert_path_file 31const VALID_CERT_PATH: &str = "/data/test/tmp/valid_cert_path.json"; 32const NON_EXISTEND_CERT_PATH: &str = "/data/test/tmp/non_existent_cert_path.json"; 33const INVALID_STRUCTURE_CERT_PATH: &str = "/data/test/tmp/invalid_structure_cert_path.json"; 34const EMPTY_CERT_PATH: &str = "/data/test/tmp/empty_cert_path.json"; 35 36const ALLOWED_ROOT_CERT_MEMBER_NAMES: &[&str] = &[ 37 "C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Root CA G2", 38 "C=CN, O=OpenHarmony, OU=OpenHarmony Team, CN=OpenHarmony Application Root CA", 39 "C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Root CA G2 Test", 40]; 41 42#[test] 43fn test_load_pem_cert_from_valid_json_file() { 44 // test is_debuggable true 45 let mut root_cert = PemCollection::new(); 46 root_cert.load_pem_certs_from_json_file(VALID_PEM_CERT, ALLOWED_ROOT_CERT_MEMBER_NAMES); 47 assert_eq!(root_cert.pem_data.len(), 3); 48} 49 50#[test] 51fn test_invalid_pem_cert_file_path() { 52 let mut root_cert = PemCollection::new(); 53 root_cert.load_pem_certs_from_json_file(NON_EXISTEND_PEM_CERT, ALLOWED_ROOT_CERT_MEMBER_NAMES); 54 assert!(root_cert.pem_data.is_empty()); 55} 56 57#[test] 58fn test_invalid_pem_cert_json_structure() { 59 let mut root_cert = PemCollection::new(); 60 root_cert 61 .load_pem_certs_from_json_file(INVALID_STRUCTURE_PEM_CERT, ALLOWED_ROOT_CERT_MEMBER_NAMES); 62 assert!(root_cert.pem_data.is_empty()); 63} 64 65#[test] 66fn test_empty_pem_cert_json_file() { 67 let mut root_cert = PemCollection::new(); 68 root_cert.load_pem_certs_from_json_file(EMPTY_PEM_CERT, ALLOWED_ROOT_CERT_MEMBER_NAMES); 69 assert!(root_cert.pem_data.is_empty()); 70} 71 72#[test] 73fn test_successful_load_cert_path() { 74 let mut cert_paths = TrustCertPath::new(); 75 cert_paths.load_cert_path_from_json_file(VALID_CERT_PATH); 76 assert_eq!(cert_paths.profile_signers.len(), 4); 77 assert_eq!(cert_paths.app_sources.len(), 6); 78} 79#[test] 80fn test_invalid_cert_path_file_path() { 81 let mut cert_paths = TrustCertPath::new(); 82 cert_paths.load_cert_path_from_json_file(NON_EXISTEND_CERT_PATH); 83 assert!( 84 cert_paths.app_sources.is_empty(), 85 "Expected cert_paths.app_sources to be empty for an empty JSON file" 86 ); 87} 88 89#[test] 90fn test_invalid_cert_path_json_structure() { 91 let mut cert_paths = TrustCertPath::new(); 92 cert_paths.load_cert_path_from_json_file(INVALID_STRUCTURE_CERT_PATH); 93 assert!( 94 cert_paths.app_sources.is_empty(), 95 "Expected cert_paths.app_sources to be empty for an empty JSON file" 96 ); 97} 98 99#[test] 100fn test_empty_cert_path_json_file() { 101 let mut cert_paths = TrustCertPath::new(); 102 cert_paths.load_cert_path_from_json_file(EMPTY_CERT_PATH); 103 assert!( 104 cert_paths.app_sources.is_empty(), 105 "Expected cert_paths.app_sources to be empty for an empty JSON file" 106 ); 107} 108 109#[test] 110fn test_parse_enterprise_profile() { 111 let profile_str = r#" 112 { 113 "version-name": "2.0.0", 114 "version-code": 2, 115 "app-distribution-type": "enterprise", 116 "uuid": "", 117 "validity": { 118 "not-before": 1, 119 "not-after": 2 120 }, 121 "type": "release", 122 "bundle-info": { 123 "developer-id": "", 124 "distribution-certificate": "", 125 "bundle-name": "com.test.enterprise", 126 "apl": "normal", 127 "app-feature": "test_app", 128 "app-identifier": "123123" 129 }, 130 "acls": { 131 "allowed-acls": [ 132 "" 133 ] 134 }, 135 "app-privilege-capabilities": [], 136 "permissions": { 137 "restricted-permissions": [ 138 "" 139 ] 140 } 141 } 142 "#; 143 let profile_json =JsonValue::from_text(profile_str).unwrap(); 144 let result = validate_bundle_and_distribution_type(&profile_json, true); 145 assert!(result.is_ok()); 146} 147 148#[test] 149fn test_parse_enterprise_normal_profile() { 150 let profile_str = r#" 151 { 152 "version-name": "2.0.0", 153 "version-code": 2, 154 "app-distribution-type": "enterprise_normal", 155 "uuid": "", 156 "validity": { 157 "not-before": 1, 158 "not-after": 2 159 }, 160 "type": "release", 161 "bundle-info": { 162 "developer-id": "", 163 "distribution-certificate": "", 164 "bundle-name": "com.test.enterprise_normal", 165 "apl": "normal", 166 "app-feature": "test_app", 167 "app-identifier": "123123" 168 }, 169 "acls": { 170 "allowed-acls": [ 171 "" 172 ] 173 }, 174 "app-privilege-capabilities": [], 175 "permissions": { 176 "restricted-permissions": [ 177 "" 178 ] 179 } 180 } 181 "#; 182 let profile_json =JsonValue::from_text(profile_str).unwrap(); 183 let result = validate_bundle_and_distribution_type(&profile_json, true); 184 assert!(result.is_ok()); 185} 186 187#[test] 188fn test_parse_enterprise_mdm_profile() { 189 let profile_str = r#" 190 { 191 "version-name": "2.0.0", 192 "version-code": 2, 193 "app-distribution-type": "enterprise_mdm", 194 "uuid": "", 195 "validity": { 196 "not-before": 1, 197 "not-after": 2 198 }, 199 "type": "release", 200 "bundle-info": { 201 "developer-id": "", 202 "distribution-certificate": "", 203 "bundle-name": "com.test.enterprise_mdm", 204 "apl": "normal", 205 "app-feature": "test_app", 206 "app-identifier": "123123" 207 }, 208 "acls": { 209 "allowed-acls": [ 210 "" 211 ] 212 }, 213 "app-privilege-capabilities": [], 214 "permissions": { 215 "restricted-permissions": [ 216 "" 217 ] 218 } 219 } 220 "#; 221 let profile_json =JsonValue::from_text(profile_str).unwrap(); 222 let result = validate_bundle_and_distribution_type(&profile_json, true); 223 assert!(result.is_ok()); 224} 225 226#[test] 227fn test_parse_debug_profile() { 228 let profile_str = r#" 229 { 230 "version-name": "2.0.0", 231 "version-code": 2, 232 "app-distribution-type": "developer", 233 "uuid": "", 234 "validity": { 235 "not-before": 1, 236 "not-after": 2 237 }, 238 "type": "debug", 239 "bundle-info": { 240 "developer-id": "", 241 "development-certificate": "", 242 "bundle-name": "com.test.developer", 243 "apl": "normal", 244 "app-feature": "test_app", 245 "app-identifier": "123123" 246 }, 247 "acls": { 248 "allowed-acls": [ 249 "" 250 ] 251 }, 252 "app-privilege-capabilities": [], 253 "permissions": { 254 "restricted-permissions": [ 255 "" 256 ] 257 }, 258 "debug-info": { 259 "device-ids": [], 260 "device-id-type": "udid" 261 } 262 } 263 "#; 264 let udid = get_udid().expect("Failed to get UDID"); 265 let mut profile_json =JsonValue::from_text(profile_str).unwrap(); 266 profile_json["debug-info"]["device-ids"][0] = JsonValue::String(udid); 267 let result = validate_bundle_and_distribution_type(&profile_json, true); 268 assert!(result.is_ok()); 269} 270 271#[test] 272fn test_parse_iternaltesting_profile() { 273 let profile_str = r#" 274 { 275 "version-name": "2.0.0", 276 "version-code": 2, 277 "app-distribution-type": "internaltesting", 278 "uuid": "", 279 "validity": { 280 "not-before": 1, 281 "not-after": 2 282 }, 283 "type": "release", 284 "bundle-info": { 285 "developer-id": "", 286 "distribution-certificate": "", 287 "bundle-name": "com.test.internaltesting", 288 "apl": "normal", 289 "app-feature": "test_app", 290 "app-identifier": "123123" 291 }, 292 "acls": { 293 "allowed-acls": [ 294 "" 295 ] 296 }, 297 "app-privilege-capabilities": [], 298 "permissions": { 299 "restricted-permissions": [ 300 "" 301 ] 302 }, 303 "debug-info": { 304 "device-ids": [], 305 "device-id-type": "udid" 306 } 307 } 308 "#; 309 let udid = get_udid().expect("Failed to get UDID"); 310 let mut profile_json =JsonValue::from_text(profile_str).unwrap(); 311 profile_json["debug-info"]["device-ids"][0] = JsonValue::String(udid); 312 let result = validate_bundle_and_distribution_type(&profile_json, true); 313 assert!(result.is_ok()); 314} 315 316#[test] 317fn test_parse_invalid_profile() { 318 let no_type_profile = r#" 319 { 320 "version-name": "2.0.0", 321 "version-code": 2, 322 "app-distribution-type": "internaltesting", 323 "uuid": "", 324 "validity": { 325 "not-before": 1, 326 "not-after": 2 327 }, 328 "bundle-info": { 329 "developer-id": "", 330 "distribution-certificate": "", 331 "bundle-name": "com.test.internaltesting", 332 "apl": "normal", 333 "app-feature": "test_app", 334 "app-identifier": "123123" 335 }, 336 "acls": { 337 "allowed-acls": [ 338 "" 339 ] 340 }, 341 "app-privilege-capabilities": [], 342 "permissions": { 343 "restricted-permissions": [ 344 "" 345 ] 346 }, 347 "debug-info": { 348 "device-ids": [], 349 "device-id-type": "udid" 350 } 351 } 352 "#; 353 let no_distribution_profile = r#" 354 { 355 "version-name": "2.0.0", 356 "version-code": 2, 357 "uuid": "", 358 "validity": { 359 "not-before": 1, 360 "not-after": 2 361 }, 362 "type": "release", 363 "bundle-info": { 364 "developer-id": "", 365 "distribution-certificate": "", 366 "bundle-name": "com.test.internaltesting", 367 "apl": "normal", 368 "app-feature": "test_app", 369 "app-identifier": "123123" 370 }, 371 "acls": { 372 "allowed-acls": [ 373 "" 374 ] 375 }, 376 "app-privilege-capabilities": [], 377 "permissions": { 378 "restricted-permissions": [ 379 "" 380 ] 381 }, 382 "debug-info": { 383 "device-ids": [], 384 "device-id-type": "udid" 385 } 386 } 387 "#; 388 let no_debug_info_profile = r#" 389 { 390 "version-name": "2.0.0", 391 "version-code": 2, 392 "app-distribution-type": "internaltesting", 393 "uuid": "", 394 "validity": { 395 "not-before": 1, 396 "not-after": 2 397 }, 398 "type": "release", 399 "bundle-info": { 400 "developer-id": "", 401 "distribution-certificate": "", 402 "bundle-name": "com.test.internaltesting", 403 "apl": "normal", 404 "app-feature": "test_app", 405 "app-identifier": "123123" 406 }, 407 "acls": { 408 "allowed-acls": [ 409 "" 410 ] 411 }, 412 "app-privilege-capabilities": [], 413 "permissions": { 414 "restricted-permissions": [ 415 "" 416 ] 417 } 418 } 419 "#; 420 let udid = get_udid().expect("Failed to get UDID"); 421 let mut no_type_profile_json =JsonValue::from_text(no_type_profile).unwrap(); 422 no_type_profile_json["debug-info"]["device-ids"][0] = JsonValue::String(udid.clone()); 423 let result = validate_bundle_and_distribution_type(&no_type_profile_json, true); 424 assert!(result.is_err()); 425 426 let mut no_distribution_profile_json =JsonValue::from_text(no_distribution_profile).unwrap(); 427 no_distribution_profile_json["debug-info"]["device-ids"][0] = JsonValue::String(udid.clone()); 428 let result = validate_bundle_and_distribution_type(&no_distribution_profile_json, true); 429 assert!(result.is_err()); 430 431 let no_debug_info_profile_json =JsonValue::from_text(no_debug_info_profile).unwrap(); 432 let result = validate_bundle_and_distribution_type(&no_debug_info_profile_json, true); 433 assert!(result.is_err()); 434} 435 436#[test] 437fn test_get_udid_once() { 438 let udid_from_get = get_udid().expect("Failed to get UDID"); 439 let udid_from_global = UDID.clone().expect("UDID is None"); 440 441 assert_eq!(udid_from_get, udid_from_global); 442} 443 444#[test] 445fn test_get_udid_concurrent() { 446 let num_threads = 10; 447 let mut handles = vec![]; 448 449 for _ in 0..num_threads { 450 let handle = thread::spawn(|| { 451 let udid = get_udid().expect("Failed to get UDID"); 452 assert_eq!(udid, UDID.clone().expect("UDID is None")); 453 }); 454 handles.push(handle); 455 } 456 457 for handle in handles { 458 handle.join().expect("Thread panicked"); 459 } 460}