logo Обзор КриптоПро NGate для защищённого доступа к корпоративным ресурсам
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline MotoArhangel  
#1 Оставлено : 17 февраля 2019 г. 5:33:25(UTC)
MotoArhangel

Статус: Участник

Группы: Участники
Зарегистрирован: 22.12.2014(UTC)
Сообщений: 23
Российская Федерация

Сказал(а) «Спасибо»: 9 раз
Добрый день.
Столкнулся с проблемой при проверке наличия сертификата. Представленная ниже функция работает, но иногда выдает ошибку
Цитата:
[ 9:03:49 ] При проверке сертификата guts_2012(Root).cer произошла ошибка:-2146885628
.
Что то не доделал или излишне извратился?
Код:
function FindCert(const Store, FileName: string): Integer;
var
  CertFile: file;
  hStore: HCERTSTORE;
  PKCS7Length: Integer;
  Buf: Pointer;
  pFindCon, pCertCon: PCCERT_CONTEXT;
  leng: Integer;
begin
  Result := -1;
  try
    try
      AssignFile(CertFile, FileName);
      ReSet(CertFile, 1);
      PKCS7Length := FileSize(CertFile);
      Buf := AllocMem(PKCS7Length);
      if not Assigned(Buf) then
        Abort;
      blockread(CertFile, Buf^, PKCS7Length, leng);
      if PKCS7Length <> leng then
        RaiseLastOSError;
      hStore := CertOpenSystemStore(0, pChar(Store));
      pCertCon := CertCreateCertificateContext(X509_ASN_ENCODING or
        PKCS_7_ASN_ENCODING, Buf, PKCS7Length);
      if not Assigned(pCertCon) then
        RaiseLastOSError;
      pFindCon := CertFindCertificateInStore(hStore, X509_ASN_ENCODING or
        PKCS_7_ASN_ENCODING, 0, CERT_FIND_EXISTING, pCertCon, nil);
      if Assigned(pFindCon) then
      begin
        CertFreeCertificateContext(pFindCon);
        Result := 0;
        Exit;
      end
        else RaiseLastOSError;
    finally
      if Assigned(Buf)
        then FreeMem(Buf);
      CloseFile(CertFile);
      if Assigned(pCertCon)
        then CertFreeCertificateContext(pCertCon);
      CertCloseStore(hStore, 0);
    end;
  except
    on E: EOSError do
      Result := E.ErrorCode;
    on E: EInOutError do
      Result := E.ErrorCode;
  end;
end;

Отредактировано пользователем 17 февраля 2019 г. 5:38:21(UTC)  | Причина: Не указана

Offline Андрей Писарев  
#2 Оставлено : 18 февраля 2019 г. 1:22:30(UTC)
Андрей Писарев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 8,400
Мужчина

Сказал «Спасибо»: 298 раз
Поблагодарили: 1184 раз в 928 постах
Здравствуйте.

Ошибка возникает на строке 35?
Цитата:

else RaiseLastOSError;




Error number 0x80092004 (-2146885628).
Объект или свойство не найдено.


Вернуть текст сообщения: SysErrorMessage(код ошибки)

Код ошибки = GetLastError - вызывать, если функции вернули false

Цитата:

RaiseLastOSError - если только для себя код пишите...
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Андрей Писарев за этот пост.
MotoArhangel оставлено 21.02.2019(UTC)
Offline two_oceans  
#3 Оставлено : 18 февраля 2019 г. 7:07:43(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 710
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 45 раз
Поблагодарили: 151 раз в 144 постах
На вид все в порядке. Ну своеобразно конечно ищете - весь контекст передаете, по идее отпечатка сертификата достаточно для однозначной идентифицикации сертификата. Отпечаток можно получить из свойства CERT_HASH_PROP_ID (или CERT_SHA1_HASH_PROP_ID) контекста сертификата (buffer это указатель на память, вместо pchar у меня другой тип, соль в том что pchar содержит #0 в конце, а тут возвращается значение двоичное):
Код:
CertGetCertificateContextProperty(pCertCont,param, PByte(buffer), DataLen)

и заполнить блоб хэша:
Код:
c.cbData:=DataLen;
c.pbData:=buffer;

искать по блобу хэша
Код:
  CertCont:=CertFindCertificateInStore(hCStore,X509_ASN_ENCODING or PKCS_7_ASN_ENCODING{enc},0{flag},CERT_FIND_HASH,@c,nil);
  res:=GetLastError();
  writeln(stderr,inttohex(res,8));
  // CRYPT_E_NOT_FOUND $80092004
  if res=$80092004 then CertCont:=nil;

Другой вопрос, что меня тоже приколы с нахождением функцией CertFindCertificateInStore: 1) уже в какой-то теме расписывал - по поготовленной записи о ExtenededKeyUsage с поиском CERT_FIND_ENHKEY_USAGE вообще ничего не находит (такая же ошибка $80092004), хоть одно назначение указываю, хоть все что есть в сертификате. Хотел автоматом подхватывать новую ЭП-ОВ на ту же организацию после замены сертификата, но пришлось сохранять отпечаток и искать по нему.

2) по отпечатку внезапно отказывается находить в режиме запуска программы от системы (из php в сервисе Apache), в хранилище My компьютера сертификат установлен, причем перечисление сразу же после поиска на том же самом хендле хранилища сертификат показывает, свойства контекста сертификата читаются - значит и сертификат есть и права есть. Отпечаток из перечисленного сертификата побайтово идентичен данным для поиска. В режиме запуска от обычного пользователя по эти данным находит, то есть данные для поиска отпечатка подготовлены верно. НО от системы не находит - флаг для чтения при открытии хранилища как-то мешает поиску? Вот как открываю хранилище для обычного пользователя и для системы:
Код:
CertOpenSystemStore(0,'MY');
CertOpenStore(CERT_STORE_PROV_SYSTEM_A,0,0,CERT_STORE_OPEN_EXISTING_FLAG or CERT_STORE_READONLY_FLAG or CERT_SYSTEM_STORE_LOCAL_MACHINE,Pchar('MY'));
Для системы по первому варианту тоже открывается, но там конечно ничего нет.

В итоге плюнул, переделал через перечисление сертификатов в хранилище и сравнение нужных полей самой программой - в итоге и ExtenededKeyUsage в перечисленном сертификате совпадает с поисковой записью (разница только что CryptoAPI возвращает все в одном куске памяти, а я запрашиваю запись с указателями на другие куски памяти, причем все адреса кусочков памяти проверяю IsBadReadPtr и везде ложь).

Отредактировано пользователем 18 февраля 2019 г. 7:40:56(UTC)  | Причина: Не указана

Offline MotoArhangel  
#4 Оставлено : 21 февраля 2019 г. 16:17:40(UTC)
MotoArhangel

Статус: Участник

Группы: Участники
Зарегистрирован: 22.12.2014(UTC)
Сообщений: 23
Российская Федерация

Сказал(а) «Спасибо»: 9 раз
Всем спасибо.
Автор: Андрей Писарев Перейти к цитате

Вернуть текст сообщения: SysErrorMessage(код ошибки)

Код ошибки = GetLastError - вызывать, если функции вернули false

Цитата:

RaiseLastOSError - если только для себя код пишите...

Сразу не подумал) Решил вопрос.

Задам в этой же ветке. Ставлю корневой сертификат так:
Код:
  cert := GetCertContext(FileName);
  Store := CertOpenSystemStore(0, PWideChar(TypeCert));
  begin
.....
  CertAddCertificateContextToStore(Store, cert,CERT_STORE_ADD_ALWAYS, nil)
.....

Как его запихнуть в локальное хранилище, а не в хранилище пользователя?

Отредактировано пользователем 21 февраля 2019 г. 17:10:33(UTC)  | Причина: Не указана

Offline AlexEr81  
#5 Оставлено : 21 февраля 2019 г. 16:36:01(UTC)
AlexEr81

Статус: Активный участник

Группы: Участники
Зарегистрирован: 09.11.2012(UTC)
Сообщений: 64
Откуда: Ростовская область

Сказал(а) «Спасибо»: 8 раз
Поблагодарили: 1 раз в 1 постах
тут где-то было. Если "запустить от имени Администратора" ставится в локальный компьютер, иначе в текущего пользователя.
thanks 1 пользователь поблагодарил AlexEr81 за этот пост.
MotoArhangel оставлено 21.02.2019(UTC)
Offline Андрей Писарев  
#6 Оставлено : 21 февраля 2019 г. 21:40:42(UTC)
Андрей Писарев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 8,400
Мужчина

Сказал «Спасибо»: 298 раз
Поблагодарили: 1184 раз в 928 постах
Автор: AlexEr81 Перейти к цитате
тут где-то было. Если "запустить от имени Администратора" ставится в локальный компьютер, иначе в текущего пользователя.


или "нажать" ОК в системном диалоге ОС и установить в корневые текущего пользователя, "без диалога и повышения прав"
Техническую поддержку оказываем тут
Наша база знаний
Offline two_oceans  
#7 Оставлено : 22 февраля 2019 г. 8:10:59(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 710
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 45 раз
Поблагодарили: 151 раз в 144 постах
Автор: Андрей Писарев Перейти к цитате
Код ошибки = GetLastError - вызывать, если функции вернули false
Только не все функции возвращают логические результаты. В частности CertFindCertificateInStore возвращает указатель на контекст сертификата, поэтому совет не подходит.
Цитата:
Как его запихнуть в локальное хранилище, а не в хранилище пользователя?
Может быть использовать полный синтаксис открытия хранилища без флага чтения чтобы не зависеть от неявной интерпретации прав, что-то вроде:
Код:
hStore:=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,0,0,CERT_STORE_OPEN_EXISTING_FLAG or CERT_SYSTEM_STORE_LOCAL_MACHINE,PWidechar('MY'));

Отредактировано пользователем 22 февраля 2019 г. 8:13:10(UTC)  | Причина: Не указана

Offline Андрей Писарев  
#8 Оставлено : 22 февраля 2019 г. 9:05:14(UTC)
Андрей Писарев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 8,400
Мужчина

Сказал «Спасибо»: 298 раз
Поблагодарили: 1184 раз в 928 постах
Автор: two_oceans Перейти к цитате
Автор: Андрей Писарев Перейти к цитате
Код ошибки = GetLastError - вызывать, если функции вернули false
Только не все функции возвращают логические результаты.


Вроде понятно написано условие, нет?
Цитата:

, если функции вернули false



А какие функции возвращают true\false, кроме логических?
Техническую поддержку оказываем тут
Наша база знаний
Offline AlexEr81  
#9 Оставлено : 22 февраля 2019 г. 10:47:12(UTC)
AlexEr81

Статус: Активный участник

Группы: Участники
Зарегистрирован: 09.11.2012(UTC)
Сообщений: 64
Откуда: Ростовская область

Сказал(а) «Спасибо»: 8 раз
Поблагодарили: 1 раз в 1 постах
Автор: AlexEr81 Перейти к цитате
тут где-то было. Если "запустить от имени Администратора" ставится в локальный компьютер, иначе в текущего пользователя.



имел ввиду, что без прав администратора в локальный компьютер не ставится
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.