Uwierzytelnianie do Apache'a za pomocą certyfikatów kwalifikowanych
02 listopada 2009, 16:06:01Mając do dyspozycji certyfikat kwalifikowany, chciałem użyć go do silnego uwierzytelniania do serwisu www. Nie spodziewałem się większych problemów, jednak okazało się, że sprawa nie jest taka prosta jak się na początku wydawało - i stąd ta notka.
Nie będę pisał o samym uwierzytelnianiu za pomocą certyfikatów klienta - w sieci napisano na ten temat sporo. Skupię się na problemach specyficznych dla polskich certyfikatów kwalifikowanych.
Po pierwsze, apache musi mieć ustawiony certyfikat Narodowego Centrum Certyfikacji za pomocą dyrektywy SSLCACertificateFile lub SSLCACertificatePath w pliku konfiguracyjnym. Certyfikaty można pobrać stąd. Po restarcie apache'a w logach SSL'a na poziomie debug powinniśmy mieć informację:
[debug] ssl_engine_init.c(1092): CA certificate: /C=PL/O=CZiC Centrast SA w imieniu Ministra Gospodarki/CN=CZiC Centrast SA [debug] ssl_engine_init.c(1092): CA certificate: /C=PL/O=Minister wlasciwy do spraw gospodarki/CN=Narodowe Centrum Certyfikacji (NCCert) [
Pierwszy problem - na początku żadna ze sprawdzanych przeze mnie przeglądarek nie chciała użyć (zaprezentować) certyfikatu serwerowi, pomimo, że był widoczny dla samej przeglądarki (pod IE jako certyfikat osobisty w Opcje internetowe / Zawartość / Certyfikaty, w FF Opcje/zaawansowane/szyfrowanie/certyfikaty).
W FF sprawa okazała się prosta - wystarczyło zarejestrować w przeglądarce certyfikaty wystawców (CA). W IE niestety to nie pomogło - przeglądarka pokazywała listę wyboru certyfikatu, ale pustą. Przyczyna, dla jakiej IE ignorował certyfikat, okazała się dość poważna i miała mieć jeszcze dość poważne następstwa - mianowicie rozszerzenie KeyUsage, definiujące możliwości użycia klucza, w certyfikacie kwalifikowanym ma ustawiony jedynie bit nonRepudation, i nie ma ustawionego bitu digitalSignature, wymaganego m.in. do uwierzytelniania klienta. Trochę więcej przeczytać o tym można np. tutaj. W skrócie - bit nonRepudation ustawiony w KeyUsage - określa użycie certyfikatu (a dokładniej klucza prywatnego) do typowego podpisu elektronicznego pod dokumentem, czyli w celu potwierdzenia "niezaprzeczalności" Natomiast bit digitalSignature zezwala użycie klucza w pozostałych przypadkach, m.in. w celu uwierzytelnienia w systemie informatycznym. Takie rozdzielenie ma sens, jeśli chodzi o zapewnienie większego bezpieczeństwa użycia naszego podpisu elektronicznego - bez tego mechanizmu można sobie wyobrazić "zły" serwer, który przy okazji uwierzytelniania klienta za pomocą certyfikatu klienta podsyła nam zamiast losowych wartości challenge skróty jakichś dokumentów, które byśmy nieświadomie podpisywali naszym e-podpisem...
Okazuje się, że w IE można jednak wymusić użycie certyfikatu bez bitu digitalSignature w KeyUsage do autoryzacji klienta, aplikując do rejestru:
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl] "FEATURE_CLIENTAUTHCERTFILTER"=dword:00000001
Po zaaplikowaniu powyższego wpisu do rejestru IE powinien pozwolić na wybranie certyfikatu kwalifikowanego do uwierzytelniania.
Niestety, pomimo że zarówno FF jak i IE pozwalały wybrać certyfikat, Apache dalej odmawiał posłuszeństwa. Dalsze śledztwo wykazało, że z dwóch powodów. Po pierwsze - brak bitu digitalSignature w KeyUsage - Apache honoruje to rozszerzenie i odrzuca certyfikaty klienta nie mające ustawionego bitu digitalSignature. Po drugie - Apache odrzuca certyfikaty mające nieznane rozszerzenia oznaczone jako "krytyczne" - a posiadany przeze mnie certyfikat kwalifikowany takowe posiadał. Rozwiązanie - poniższy patch, powodujący ignorowanie powyższych błędów.
--- apache2-2.2.8/modules/ssl/ssl_engine_kernel.c.orig 2006-07-12 05:38:44.000000000 +0200
+++ apache2-2.2.8/modules/ssl/ssl_engine_kernel.c 2009-10-28 17:19:26.000000000 +0100
@@ -1285,6 +1285,16 @@
/*
* And finally signal OpenSSL the (perhaps changed) state
*/
+
+ if(errnum == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION || errnum == X509_V_ERR_INVALID_PURPOSE) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "ignoring unhandled critical extension or invalid certificate purpose");
+ sslconn->verify_error = NULL;
+ ctx->error = X509_V_OK;
+ SSL_set_verify_result(ssl, X509_V_OK);
+ ok = TRUE;
+ }
+
+
return ok;
}
Powyższy patch nie jest chyba zbyt dużym gwałtem na bezpieczeństwo apache'a - powyższy kod wywoływany jest tylko dla certyfikatów klienta, ignorowane są jedynie nieznane rozszerzenia w certyfikacie i rozszerzenie KeyUsage
Konkluzja - certyfikatów kwalifikowanych niestety nie powinno używać się do uwierzytelniania klienta via SSL ale jak ktoś się wyjątkowo uprze to się da :)
I na koniec KONKURS. Tutaj stoi sobie poprawiony j.w. apache, wpuszczający tylko za okazaniem certyfikatu kwalifikowanego. Pierwszej osobie która powie w komentarzu co znajduje się na podanej stronie stawiam piwo :)
Tagi: certyfikat kwalifikowany klienta apache