| 1529 | } |
| 1530 | |
| 1531 | static bool activation_source_open(const char *path, activation_native_file_t *file_out) { |
| 1532 | *file_out = ACTIVATION_INVALID_FILE; |
| 1533 | char *directory = NULL; |
| 1534 | char *name = NULL; |
| 1535 | if (!activation_target_parts(path, &directory, &name)) { |
| 1536 | return false; |
| 1537 | } |
| 1538 | #ifdef _WIN32 |
| 1539 | activation_file_identity_t directory_identity; |
| 1540 | activation_file_identity_t expected; |
| 1541 | bool exists = false; |
| 1542 | bool src_dir_ok = activation_source_directory_secure(directory, &directory_identity); |
| 1543 | /* The source (a downloaded release bundle) follows the machine's |
| 1544 | * default-owner policy; its bytes are pinned by identity recheck plus the |
| 1545 | * staged copy's build-fingerprint validation, so a trusted owner |
| 1546 | * (user/Administrators/SYSTEM) is sufficient here. Targets keep the |
| 1547 | * exact-current-owner rule. */ |
| 1548 | bool snapshot_ok = |
| 1549 | src_dir_ok && activation_external_snapshot_with_owner(path, false, &exists, &expected); |
| 1550 | if (!src_dir_ok || !snapshot_ok || !exists) { |
| 1551 | free(directory); |
| 1552 | free(name); |
| 1553 | return false; |
| 1554 | } |
| 1555 | wchar_t *wide = activation_utf8_to_wide(path); |
| 1556 | if (!wide) { |
| 1557 | free(directory); |
| 1558 | free(name); |
| 1559 | return false; |
| 1560 | } |
| 1561 | HANDLE file = |
| 1562 | CreateFileW(wide, GENERIC_READ | FILE_READ_ATTRIBUTES | READ_CONTROL, |
| 1563 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, |
| 1564 | FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_SEQUENTIAL_SCAN, NULL); |
| 1565 | free(wide); |
| 1566 | activation_file_identity_t actual; |
| 1567 | activation_file_identity_t directory_now; |
| 1568 | bool valid = file != INVALID_HANDLE_VALUE && activation_windows_identity(file, &actual, true) && |
| 1569 | activation_windows_owner_is_trusted(file) && activation_windows_acl_secure(file) && |
| 1570 | activation_identity_equal(&actual, &expected) && |
| 1571 | activation_source_directory_secure(directory, &directory_now) && |
| 1572 | activation_identity_equal(&directory_now, &directory_identity); |
| 1573 | if (!valid) { |
| 1574 | if (file != INVALID_HANDLE_VALUE) { |
| 1575 | (void)CloseHandle(file); |
| 1576 | } |
| 1577 | free(directory); |
| 1578 | free(name); |
| 1579 | return false; |
| 1580 | } |
| 1581 | #else |
| 1582 | int directory_fd = -1; |
| 1583 | activation_file_identity_t directory_identity; |
| 1584 | if (!activation_directory_secure(directory, &directory_fd, &directory_identity)) { |
| 1585 | free(directory); |
| 1586 | free(name); |
| 1587 | return false; |
| 1588 | } |
no test coverage detected