Bagikan melalui


Schannel

Paket keamanan Saluran Aman (Schannel), yang pengidentifikasi layanan autentikasinya RPC_C_AUTHN_GSS_SCHANNEL, mendukung protokol berbasis kunci publik berikut: SSL (Secure Sockets Layer) versi 2.0 dan 3.0, Transport Layer Security (TLS) 1.0, dan Private Communication Technology (PCT) 1.0. TLS 1.0 adalah versi SSL 3.0 standar yang sedikit dimodifikasi yang dikeluarkan oleh Internet Engineering Task Force (IETF) pada Januari 1999, dalam dokumen RFC 2246. Karena TLS telah distandarkan, pengembang didorong untuk menggunakan TLS daripada SSL. PCT disertakan hanya untuk kompatibilitas mundur dan tidak boleh digunakan untuk pengembangan baru. Ketika paket keamanan Schannel digunakan, DCOM secara otomatis menegosiasikan protokol terbaik, tergantung pada kemampuan klien dan server.

Topik berikut secara singkat menjelaskan protokol TLS dan cara kerjanya dengan DCOM.

Catatan

Semua informasi tentang protokol TLS di bagian ini juga berlaku untuk protokol SSL dan PCT.

 

Kapan Menggunakan TLS

TLS adalah satu-satunya opsi keamanan yang tersedia ketika server perlu membuktikan identitas mereka kepada klien anonim. Ini sangat penting untuk situs web yang ingin berpartisipasi dalam e-niaga karena membantu melindungi transmisi informasi sensitif seperti nomor kartu kredit. TLS memastikan bahwa pelanggan e-niaga dapat yakin dengan siapa mereka berbisnis karena mereka diberi bukti identitas server. Ini juga memberi server e-niaga efisiensi untuk tidak harus menyangkut dirinya sendiri dengan mengautentikasi identitas setiap pelanggannya.

TLS mengharuskan semua server membuktikan identitasnya kepada klien. Selain itu, TLS menyediakan opsi untuk meminta klien membuktikan identitas mereka ke server. Autentikasi bersama ini dapat berguna dalam membatasi akses halaman web tertentu dalam intranet perusahaan besar.

TLS mendukung tingkat autentikasi terkuat dan menawarkan arsitektur terbuka yang memungkinkan kekuatan enkripsi meningkat dari waktu ke waktu untuk mengikuti inovasi teknologi. TLS adalah pilihan terbaik untuk lingkungan di mana tingkat keamanan tertinggi diinginkan untuk data saat transit.

Ringkasan Singkat Tentang Cara Kerja TLS

TLS dibangun di atas infrastruktur kunci publik (PKI), yang menggunakan pasangan kunci publik/privat untuk mengaktifkan enkripsi data dan membangun integritas data, dan menggunakan sertifikat X.509 untuk autentikasi.

Banyak protokol keamanan, seperti protokol Kerberos v5, bergantung pada satu kunci untuk mengenkripsi dan mendekripsi data. Oleh karena itu, protokol tersebut bergantung pada pertukaran kunci enkripsi yang aman; dalam protokol Kerberos, hal ini dilakukan melalui tiket yang diperoleh dari Key Distribution Center (KDC). Ini mengharuskan semua orang yang menggunakan protokol Kerberos terdaftar di KDC, yang akan menjadi batasan yang tidak praktis untuk server web e-niaga yang dimaksudkan untuk menarik jutaan pelanggan dari seluruh dunia. Oleh karena itu, TLS bergantung pada PKI, yang menggunakan dua kunci untuk enkripsi dataâ €"ketika satu kunci pasangan mengenkripsi data, hanya kunci lain dari pasangan yang dapat mendekripsinya. Manfaat prinsip dari desain ini adalah bahwa enkripsi dapat dilakukan tanpa memerlukan pertukaran kunci enkripsi yang aman.

PKI menggunakan teknik di mana salah satu kunci dirahasiakan dan hanya tersedia untuk prinsipal yang terdaftar, sementara kunci lainnya dipublikasikan bagi siapa saja untuk diakses. Jika seseorang ingin mengirim pesan privat ke pemilik pasangan kunci, pesan dapat dienkripsi dengan kunci publik dan hanya kunci privat yang dapat digunakan untuk mendekripsi pesan.

Pasangan kunci juga digunakan untuk memverifikasi integritas data yang dikirim. Untuk melakukan ini, pemilik pasangan kunci dapat melampirkan tanda tangan digital ke data sebelum mengirimkannya. Membuat tanda tangan digital melibatkan penghitungan hash data dan mengenkripsi hash dengan kunci privat. Siapa pun yang menggunakan kunci publik untuk mendekripsi tanda tangan digital diyakinkan bahwa tanda tangan digital harus berasal hanya dari orang yang memiliki kunci privat. Selain itu, penerima dapat menghitung hash data menggunakan algoritma yang sama dengan pengirim, dan jika hash terhitung cocok dengan yang dikirim dalam tanda tangan digital, penerima dapat yakin bahwa data tidak dimodifikasi setelah ditandatangani secara digital.

Salah satu kerugian menggunakan PKI untuk enkripsi data volume tinggi adalah performanya yang relatif lambat. Karena matematika intensif yang terlibat, enkripsi dan dekripsi data menggunakan sandi asimetris yang bergantung pada pasangan kunci bisa hingga 1.000 kali lebih lambat daripada enkripsi dan dekripsi menggunakan sandi simetris yang hanya bergantung pada satu kunci. Oleh karena itu, TLS menggunakan PKI hanya untuk menghasilkan tanda tangan digital dan untuk menegosiasikan kunci tunggal khusus sesi yang akan digunakan oleh klien dan server untuk enkripsi dan dekripsi data massal. TLS mendukung berbagai sandi simetris kunci tunggal, dan sandi tambahan dapat ditambahkan di masa depan.

Untuk informasi selengkapnya tentang protokol jabat tangan TLS, lihat Protokol Jabat Tangan TLS.

Untuk detail selengkapnya mengenai kriptografi di balik protokol TLS, lihat Esensi Kriptografi.

Sertifikat X.509

Masalah penting yang harus ditangani oleh PKI adalah kemampuan untuk mempercayai keaslian kunci publik yang sedang digunakan. Ketika Anda menggunakan kunci publik yang dikeluarkan untuk perusahaan yang ingin Anda lakukan bisnis dengan, Anda ingin yakin bahwa kunci sebenarnya milik perusahaan daripada pencuri yang ingin menemukan nomor kartu kredit Anda.

Untuk menjamin identitas prinsipal yang memegang pasangan kunci, prinsipal dikeluarkan sertifikat X.509 oleh otoritas sertifikasi (CA). Sertifikat ini berisi informasi yang mengidentifikasi prinsipal, berisi kunci umum utama, dan ditandatangani secara digital oleh CA. Tanda tangan digital ini menunjukkan bahwa CA percaya bahwa kunci umum yang terkandung dalam sertifikat benar-benar milik prinsipal yang diidentifikasi oleh sertifikat.

Dan bagaimana kau mempercayai CA? Karena CA sendiri memegang sertifikat X.509 yang telah ditandatangani oleh CA tingkat yang lebih tinggi. Rantai tanda tangan sertifikat ini berlanjut sampai mencapai CA akar, yang merupakan CA yang menandatangani sertifikatnya sendiri. Jika Anda mempercayai integritas OS akar sertifikat, Anda harus dapat mempercayai keaslian sertifikat itu sendiri. Oleh karena itu, memilih CA akar yang bersedia Anda percayai adalah tugas penting bagi administrator sistem.

Sertifikat Klien

Ketika protokol lapisan transportasi keamanan pertama kali muncul, tujuan utamanya adalah untuk menjamin bahwa klien terhubung ke server autentik dan membantu melindungi privasi data saat transit. Namun, SSL 3.0 dan TLS 1.0 juga menyertakan dukungan untuk transmisi sertifikat klien selama jabat tangan protokol. Fitur opsional ini memungkinkan autentikasi bersama klien dan server.

Keputusan apakah akan menggunakan sertifikat klien harus dibuat dalam konteks aplikasi. Sertifikat klien tidak perlu jika persyaratan utama mengautentikasi server. Namun, jika autentikasi klien sangat penting, sertifikat klien dapat digunakan daripada mengandalkan autentikasi kustom dalam aplikasi. Menggunakan sertifikat klien lebih disukai daripada autentikasi kustom karena memberi pengguna skenario akses menyeluruh.

Menggunakan TLS di COM

TLS hanya mendukung tingkat peniruan identitas (RPC_C_IMP_LEVEL_IMPERSONATE). Jika COM menegosiasikan TLS sebagai layanan autentikasi pada proksi, COM akan mengatur tingkat peniruan identitas untuk meniru terlepas dari proses default. Agar peniruan identitas berfungsi dengan baik di TLS, klien harus memberikan sertifikat X.509 ke server dan server harus memiliki sertifikat yang dipetakan ke akun pengguna tertentu di server. Untuk informasi selengkapnya, lihat Panduan Langkah demi Langkah untuk Memetakan Sertifikat ke Akun Pengguna.

TLS tidak mendukung penyelubungan. Jika bendera kloning dan TLS ditentukan dalam CoInitializeSecurity atau panggilan IClientSecurity::SetBlanket, E_INVALIDARG akan dikembalikan.

TLS tidak berfungsi dengan tingkat autentikasi yang diatur ke Tidak Ada. Jabat tangan antara klien dan server memeriksa tingkat autentikasi yang ditetapkan oleh masing-masing dan memilih pengaturan keamanan yang lebih tinggi untuk koneksi.

Parameter keamanan untuk TLS dapat diatur dengan memanggil CoInitializeSecurity dan CoSetProxyBlanket. Bagian berikut menjelaskan nuansa yang terlibat dalam melakukan panggilan tersebut.

Cara Server Mengatur Selimut Keamanan

Jika server ingin menggunakan TLS, server harus menentukan Schannel (RPC_C_AUTHN_GSS_SCHANNEL) sebagai layanan autentikasi dalam parameter asAuthSvc dari CoInitializeSecurity. Untuk mencegah klien terhubung ke server dengan menggunakan layanan autentikasi yang kurang aman, server hanya harus menentukan Schannel sebagai layanan autentikasi saat memanggil CoInitializeSecurity. Server tidak dapat mengubah selimut keamanan setelah disebut CoInitializeSecurity.

Untuk menggunakan TLS, parameter berikut harus ditentukan saat server memanggil CoInitializeSecurity:

  • pVoid harus berupa pointer ke objek IAccessControl atau pointer ke SECURITY_DESCRIPTOR. Ini tidak boleh NULL atau penunjuk ke AppID.
  • cAuthSvc tidak boleh 0 atau -1. Server COM tidak pernah memilih Schannel ketika cAuthSvcadalah -1.
  • asAuthSvc harus menentukan Schannel sebagai layanan autentikasi yang memungkinkan. Ini dilakukan dengan mengatur parameter SOLE_AUTHENTICATION_SERVICE berikut untuk anggota Schannel dari SOLE_AUTHENTICATION_LIST:
    • dwAuthnSvc harus RPC_C_AUTHN_GSS_SCHANNEL.
    • dwAuthzSvc harus RPC_C_AUTHZ_NONE. Saat ini, diabaikan.
    • pPrincipalName harus menjadi penunjuk ke CERT_CONTEXT, dilemparkan sebagai pointer ke OLECHAR, yang mewakili sertifikat X.509 server.
  • dwAuthnLevel menunjukkan tingkat autentikasi minimum yang akan diterima dari klien untuk koneksi yang berhasil. Ini tidak dapat RPC_C_AUTHN_LEVEL_NONE.
  • dwCapabilities tidak boleh memiliki set bendera EOAC_APPID. Bendera EOAC_ACCESS_CONTROL harus diatur jika pVoid menunjuk ke objek IAccessControl; tidak boleh diatur jika pVoid menunjuk ke SECURITY_DESCRIPTOR. Untuk bendera lain yang mungkin diatur, lihat CoInitializeSecurity.

Untuk informasi selengkapnya tentang menggunakan CoInitializeSecurity, lihat Mengatur Keamanan Processwide dengan CoInitializeSecurity.

Cara Klien Mengatur Selimut Keamanan

Jika klien ingin menggunakan TLS, klien harus menentukan Schannel (RPC_C_AUTHN_GSS_SCHANNEL) dalam daftar layanan autentikasinya dalam parameter pAuthList coInitializeSecurity. Jika Schannel tidak ditentukan sebagai layanan autentikasi yang mungkin ketika CoInitializeSecurity dipanggil, panggilan selanjutnya ke CoSetProxyBlanket (atau IClientSecurity::SetBlanket) akan gagal jika mencoba menentukan Schannel sebagai layanan autentikasi.

Parameter berikut harus ditentukan saat klien memanggil CoInitializeSecurity:

  • dwAuthnLevel menentukan tingkat autentikasi default yang ingin digunakan klien. Ini tidak dapat RPC_C_AUTHN_LEVEL_NONE.
  • dwImpLevel harus RPC_C_IMP_LEVEL_IMPERSONATE.
  • pAuthList harus memiliki parameter SOLE_AUTHENTICATION_INFO berikut sebagai anggota daftar:
    • dwAuthnSvc harus RPC_C_AUTHN_GSS_SCHANNEL.
    • dwAuthzSvc harus RPC_C_AUTHZ_NONE.
    • pAuthInfo adalah penunjuk ke CERT_CONTEXT, dilemparkan sebagai pointer ke void, yang mewakili sertifikat X.509 klien. Jika klien tidak memiliki sertifikat atau tidak ingin menunjukkan sertifikatnya ke server, pAuthInfo harus NULL dan koneksi anonim akan dicoba dengan server.
  • dwCapabilities adalah sekumpulan bendera yang menunjukkan kemampuan klien tambahan. Lihat CoInitializeSecurity untuk informasi tentang bendera mana yang harus diatur.

Untuk informasi selengkapnya tentang menggunakan CoInitializeSecurity, lihat Mengatur Keamanan Processwide dengan CoInitializeSecurity.

Bagaimana Klien Mengubah Selimut Keamanan

Jika klien ingin menggunakan TLS tetapi mengubah selimut keamanan setelah memanggil CoInitializeSecurity, klien harus memanggil CoSetProxyBlanket atau IClientSecurity::SetBlanket dengan parameter yang mirip dengan yang digunakan dalam panggilan ke CoInitializeSecurity, dengan perbedaan berikut:

  • pServerPrincName menunjukkan nama utama server, baik dalam format msstd atau fullsic. Untuk informasi tentang format ini, lihat Nama Utama. Jika klien memiliki sertifikat X.509 server, klien dapat menemukan nama utama dengan memanggil RpcCertGeneratePrincipalName.
  • pAuthInfo adalah penunjuk ke CERT_CONTEXT, dilemparkan sebagai penunjuk ke RPC_AUTH_IDENTITY_HANDLE, yang mewakili sertifikat X.509 klien. Jika klien tidak memiliki sertifikat atau tidak ingin menunjukkan sertifikatnya ke server, pAuthInfo harus NULL dan koneksi anonim akan dicoba dengan server.
  • dwCapabilities terdiri dari bendera yang menunjukkan kemampuan klien tambahan. Hanya empat bendera yang dapat digunakan untuk mengubah pengaturan selimut keamanan: EOAC_DEFAULT, EOAC_MUTUAL_AUTH, EOAC_ANY_AUTHORITY (bendera ini tidak digunakan lagi), dan EOAC_MAKE_FULLSIC. Untuk informasi selengkapnya, lihat CoSetProxyBlanket.

Untuk informasi selengkapnya tentang menggunakan CoSetProxyBlanket, lihat Mengatur Keamanan di Tingkat Proksi Antarmuka.

Contoh: Klien Mengubah Selimut Keamanan

Contoh berikut menunjukkan bagaimana klien dapat mengubah selimut keamanan untuk mengakomodasi permintaan dari server agar klien memberikan sertifikat X.509-nya. Kode penanganan kesalahan dihilangkan untuk brevity.

void ClientChangesSecurity ()
{
  HCRYPTPROV                   provider           = 0;
  HCERTSTORE                   cert_store         = NULL;
  PCCERT_CONTEXT               client_cert        = NULL;
  PCCERT_CONTEXT               server_cert        = NULL;
  WCHAR                        *server_princ_name = NULL;
  ISecret                      *pSecret           = NULL;
  MULTI_QI                     server_instance;
  COSERVERINFO                 server_machine;
  SOLE_AUTHENTICATION_LIST     auth_list;
  SOLE_AUTHENTICATION_INFO     auth_info[1];



  // Specify all the authentication info. 
  // The client is willing to connect using SChannel,
  //   with no client certificate.
  auth_list.cAuthInfo     = 1;
  auth_list.aAuthInfo     = auth_info;
  auth_info[0].dwAuthnSvc = RPC_C_AUTHN_GSS_SCHANNEL;
  auth_info[0].dwAuthzSvc = RPC_C_AUTHZ_NONE;
  auth_info[0].pAuthInfo  = NULL;  // No certificate

  // Initialize client security with no client certificate.
  CoInitializeSecurity( NULL, -1, NULL, NULL,
                        RPC_C_AUTHN_LEVEL_PKT,
                        RPC_C_IMP_LEVEL_IMPERSONATE, &auth_list,
                        EOAC_NONE, NULL );
  
  // Specify info for the proxy.
  server_instance = {&IID_ISecret, NULL, S_OK};
  server_machine  = {0, L"ServerMachineName", NULL, 0};
  
  // Create a proxy.
  CoCreateInstanceEx( CLSID_Secret, NULL, CLSCTX_REMOTE_SERVER, 
                      &server_machine, 1, &server_instance);
  pSecret = (ISecret *) server_instance.pItf;

  //** The client obtained the server's certificate during the handshake.
  //** The server requests a certificate from the client.

  // Get the default certificate provider.
  CryptAcquireContext( &provider, NULL, NULL, PROV_RSA_SCHANNEL, 0 );

  // Open the certificate store.
  cert_store = CertOpenSystemStore( provider, L"my" );

  // Find the client's certificate.
  client_cert = 
    CertFindCertificateInStore( cert_store,
                                X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                                0,
                                CERT_FIND_SUBJECT_STR,
                                L"ClientName",  // Use the principal name
                                NULL );

  // Find the fullsic principal name of the server.
  RpcCertGeneratePrincipalName( server_cert, RPC_C_FULL_CERT_CHAIN, 
                                &server_princ_name );

  // Change the client's security: 
  // Increase the authentication level and attach a certificate.
  CoSetProxyBlanket( pSecret, RPC_C_AUTHN_GSS_SCHANNEL,
                     RPC_C_AUTHZ_NONE,
                     server_princ_name, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
                     RPC_C_IMP_LEVEL_IMPERSONATE, 
                     (RPC_AUTH_IDENTITY_HANDLE *) client_cert,
                     EOAC_NONE );

  cleanup:
  if (server_princ_name != NULL)
    RpcStringFree( &server_princ_name );
  if (client_cert != NULL)
    CertFreeCertificateContext(client_cert);
  if (server_cert != NULL)
    CertFreeCertificateContext(server_cert);
  if (cert_store != NULL)
    CertCloseStore( cert_store, CERT_CLOSE_STORE_CHECK_FLAG );
  if (provider != 0 )
    CryptReleaseContext( provider, 0 );
  if (pSecret != NULL)
    pSecret->Release();
  CoUninitialize();
}

PAKET COM dan Keamanan