7.9 KiB
Config Updater (config_updater.c/h)
Модуль обеспечивает согласованные X25519-ключи и node_id в INI-файле до его загрузки ядром. При включённом REALITY также обеспечивает private_key и непустой список short_ids. Публичный контракт приведён в config_updater.h, общий разбор строк — в config_ini.h.
Выбор значений
Имена секций сравниваются целиком без учёта регистра, пробелы вокруг имени секции, ключа и значения удаляются. Имена ключей чувствительны к регистру. Комментарии — #. Последнее текстовое значение ключа во всех соответствующих секциях определяет результат, включая пустое или некорректное. Опции из других секций не участвуют.
- Корректный my_private_key — ровно 64 HEX-символа; его бинарное значение сохраняется.
- my_public_key вычисляется через sc_compute_public_key_from_private().
- my_node_id вычисляется через sc_derive_node_id_from_pubkey(): SHA256 публичного ключа, первые восемь байтов в представлении функции, старший бит сброшен.
- Если приватный ключ отсутствует или некорректен, создаётся новая идентичность.
- Сравнение HEX выполняется по байтам: регистр букв не вызывает перезапись.
- При включённом REALITY некорректный/отсутствующий private_key генерируется заново. Некорректный/пустой/отсутствующий short_ids заменяется четырьмя случайными ID. Корректный список сохраняется целиком. Ошибка одного элемента отклоняет весь список.
- При выключенном REALITY его параметры не исправляются.
HEX проверяется посимвольно до декодирования. Частичные результаты проверки не применяются. Встроенный NUL и физические строки длиннее 1022 байтов до LF запрещены; CR учитывается в этом пределе.
Изменение текста
Исправный файл остаётся побайтно неизменным. Если поле требует исправления, обновляются все его вхождения в соответствующих секциях. Недостающие поля добавляются в конец последней подходящей секции; отсутствующая секция создаётся в конце файла.
Посторонние строки сохраняются побайтно. В изменяемых строках сохраняются пробелы, комментарии и окончания строк вокруг заменяемого значения. Добавляемые строки используют тип первого окончания строки в файле, либо LF. При необходимости добавляется разделитель после последней строки без LF. Новый или пустой файл получает [global] с тремя полями идентичности.
Перед записью итоговый текст проверяется строгими декодерами и штатным парсером. Это проверка полей идентичности и необходимых параметров REALITY; парсер продолжает логировать и пропускать некоторые ошибки прочих опций.
Запись и ошибки
config_ensure_keys_and_node_id(filename) принимает непустой путь. Вызывающая сторона исключает параллельную запись конфигурации. Возврат 0 означает корректные значения и, если требовалось обновление, успешную запись. Возврат -1 означает ошибку с диагностикой CONFIG.
Новый файл создаётся только при ENOENT. Ошибка доступа, чтения, выделения памяти или закрытия входного файла прекращает операцию. Временный файл создаётся эксклюзивно рядом с исходным. Проверяются запись, fflush, синхронизация и fclose до замены имени.
На POSIX применяется rename, затем fsync каталога:
- До успешного rename исходный файл при ошибках сохраняется.
- Ошибка fsync каталога после rename возвращает -1 и логируется с replaced=1. Файл уже заменён; устойчивость замены к аварии не подтверждена.
- Сохраняются uid/gid и обычные права доступа (0777); новый файл имеет 0600. ACL, xattrs и специальные биты режима не копируются.
- Временный файл удаляется при ошибках до публикации; ошибка удаления логируется.
На Windows используются _commit и ReplaceFileA для существующего файла либо MoveFileExA с MOVEFILE_WRITE_THROUGH для нового. Модуль не расширяет гарантии восстановления после ошибок этих Windows API.
Если требуется запись, символические ссылки/reparse points и файлы с несколькими жёсткими ссылками отклоняются. Проверка исправного файла по ссылке возможна без записи.
Логи показывают причину генерации, изменяемые поля, этап ошибки и факт замены файла. Значения приватных ключей updater не выводит.
Вспомогательная функция
bytes_to_hex(bytes, len, hex_str, hex_len) записывает 2len строчных HEX-символов и NUL. Буферы не перекрываются. bytes и hex_str обязательны; hex_len задаёт ёмкость результата. При недостаточной ёмкости или NULL функция обнуляет доступный hex_str[0]; усечения нет. Проверка ёмкости не вычисляет переполняющееся 2len+1. При len=0 результат пустой.
Проверки
tests/test_config_updater.c проверяет сохранение идентичности, регистр, пробелы, секции и дубли, CRLF, повторный вызов, строгий HEX/списки, длинные строки/NUL, ссылки, права доступа, ошибки файловых операций и отказы памяти. Внедрение ошибок через Linux/ELF linker wrappers не добавляет тестовых веток в рабочий код. tests/test_reality_config.c проверяет базовые сценарии генерации REALITY.