Игорь Шикарев дата публикации 22-01-2008 09:06 Фирма, в которой я в настоящее время тружусь, занимается написанием и сопровождением софта для касс и киосков по приему коммунальных платежей от населения. Помимо приема коммунальных платежей, кассы принимают платежи за сотовые телефоны, Яндекс-Деньги, WebMoney. Такие платежи проводятся через систему E-Port (http://www.e-port.ru/).
С ноября 2007 года непременным требованием E-Port стало, чтобы все поступающие пакеты в их систему имели цифровую подпись. Формирование закрытого и открытого ключа решено было делать при помощи OpenSSL (http://www.openssl.org/), а отсылки/приему пакетов, для большего контроля за происходящим решено было применять классы из библиотеки Synapse (http://www.ararat.cz/synapse/). Тем более в библиотеки была реализована возможность работы по протоколу HTTPS.
Программа, по передачи пакетов, была успешно модернизирована под новые требования, разработчики довольно потирали руки… Но как говорит народная мудрость: "Не все скоту (видимо близкий родич кота) масленица". При боевых испытаниях сервер приложений упорно останавливался с ошибкой, что не может загрузить библиотеку libeay32.dll, хотя библиотеки libssl32.dll и libeay32.dll исправно лежали рядом с сервером приложений.
Повторное тестирование на компьютере разработчика не внесло ясности, так как обычно у разработчика все всегда исправно работает. Поиски по интернету не дали вразумительного ответа, только насторожило большое количество криков о помощи по поводу ошибок при работе компонентов Indy и OpenSSL.
Как лекарство, предлагалось скачать "специальные рабочие" версии пары библиотек libssl32.dll и libeay32.dll. Скачивание "рабочих" версий не решало у нас проблему остановки сервера приложений из-за библиотеки libeay32.dll. Найти верную тропу для решения проблемы помог случай (а верней Ангел-хранитель подсказал, слава Богу!)… было вдруг замечено, что после запуска программы Macromedia Dreamweaver 8, и на машине разработчика возникала похожая ошибка о невозможности загрузить библиотеку libeay32.dll. После перегрузки компьютера, сервер приложений опять исправно начинал работать. Устроили с разработчиками маленький мозговой штурм и пришли к выводу (тут конечно гуру, которые разбираются в тонкостях загрузки библиотек в память операционной системы, могут меня поправить), что операционная система грузит в память библиотеки с использованием механизма отображения файлов в память, как идентификатор скорей всего используется имя самой библиотеки.
Т.е. если какое-то приложение уже обратилось к библиотеки libssl32.dll или libeay32.dll (к слову, Dreamweaver тоже использует пару libssl32.dll и libeay32.dll), то скорей всего моя программа при обращении к этим библиотекам получит уже отображенные в памяти их образы, а не будет загружать библиотеки, лежащие рядом с приложением. Проблему усложняет то, что libssl32.dll и libeay32.dll должны быть одной версии. У меня на некоторых машинах при испытаниях сервер приложений останавливался с ошибкой, что версия libeay32.dll не соответствует версии libssl32.dll.
На мой взгляд есть несколько решений возникшей проблемы:
- Использовать механизм инъекций в DLL, чтобы перехватывать вызов LoadLibrary и "подсовывать" нужную DLL при загрузки.
- Можно с помощью редактора PE информации поправить в libssl32.dll вызовы libeay32.dll на вызовы, к примеру, только_моя_dll_libeay32.dll
- Скачать исходники libssl32.dll и libeay32.dll и поправить их так, чтобы после компиляции получались DLL с именами synapse_libeay32.dll и synapse_libssl32.dll, и поправить исходники synapse, чтобы вызывались библиотеки с новыми именами.
Нами был выбран третий вариант, так как он был более понятен в реализации, а может быть просто на другие варианты не хватило мозгов. С сайта OpenSSL (http://www.openssl.org/), были скачаны исходники библиотеки openssl-0.9.8f.tar.gz, среда для компиляции была взята MinGW (http://www.mingw.org). Для того чтобы после компиляции библиотек получились имена synapse_libeay32.dll и synapse_libssl32.dll, необходимо в исходниках проделать следующие изменения:
- в файле util\mkdef.pl необходимо все вхождения строк SSLEAY и LIBEAY заменить на SYNAPSE_SSLEAY и SYNAPSE_LIBEAY соответственно. Для более точного понимания какие строки подверглись изменению, оригинальный текст файла сохранен в util\mkdef-orig.pl. Использую утилиту WinMerge, можно сравнить файлы по содержимому и увидеть какие строки подверглись модификации.
- Аналогичную процедуру необходимо проделать и с ms\mingw32.bat (оригинальный файл сохранен под именем ms\mingw32-orig.bat). Хочу заострить внимание читателя, что для утилиты dllwrap необходимо добавить ключ --nodelete, чтобы запретить удаление файлов dll, после завершения процесса компиляции и линковки.
Итак, исходники поправили, теперь можно приступить к процессу компиляции. Перед началом надо убедиться, что в путях поиска Windows содержатся пути до интерпретатора Perl и подкаталога bin в каталоге куда установлена MinGW. В командной строке переходим в каталог openssl-0.9.8f и запускаем ms\mingw32.bat. После окончания компиляции и линковки, в каталоге openssl-0.9.8f должны появиться два долгожданных файлика synapse_libeay32.dll и synapse_libssl32.dll. Если звезды для Вас сегодня неправильно расположены, то можно попытаться поправить карму, путем решения ошибок, на которых споткнулся процесс сборки. Либо скачать уже готовые библиотеки с моего сайта.
Осталось заменить в файле ssl_openssl_lib.pas библиотеки Synapse (http://www.ararat.cz/synapse/) ssleay32.dll и libeay32.dll на synapse_ssleay32.dll и synapse_libeay32.dll соответственно.
Описанное выше решение конфликтов библиотек OpenSSL, позволило сделать систему по обмену с E-Port стабильной и не зависимой от DLL HELL.
Обсуждение материала [ 28-01-2008 01:12 ] 15 сообщений |