Compare commits

...

210 Commits

Author SHA1 Message Date
318ad7f355 Version set to 1.0-alpha10 2016-08-23 14:53:27 +02:00
ef2042253c When server certificate has no subjectAltName(2), compare host name against Common Name 2016-08-23 14:29:47 +02:00
9b997408a1 Switched to Schannel to do the TLS 2016-08-23 13:53:23 +02:00
5720524abe Version set to 1.0-alpha9 2016-08-18 06:33:02 +02:00
1f1b9b1084 GUI boots with a predefined configuration on new profiles now
(closes #10)
2016-08-18 06:31:16 +02:00
076c6b77d7 GUI updated to show "<Your Provider>" when provider ID is blank 2016-08-18 06:30:02 +02:00
92460c571f Initial focus changed to the first non-mouse-wheel-capturing control to allow initial scrolling of the configuration dialog using mouse wheel 2016-08-17 16:42:19 +02:00
b79a2f26f6 Support for read-only lock added to GUI 2016-08-17 16:27:43 +02:00
373c83dbbe Provider identity and help-desk is configurable via GUI now 2016-08-17 15:56:11 +02:00
543dada025 Provider and method lists are arrays now, to allow random access for configuration dialog coming-up 2016-08-17 14:47:15 +02:00
ce22ec3bfa wxEAPCredentialsPanelPassBase >> wxEAPCredentialsPassPanelBase 2016-08-17 13:48:14 +02:00
a04647b7b5 Version set to 1.0-alpha8 2016-08-17 11:51:36 +02:00
df1d431bd0 - TLS revised (again)
- TLS Session resumption issues resolved
- Credential prompt has "Remember" checkbox initially selected when credentials originate from Windows Credential Manager
- Last authentication attempt failure notice is more general and no longer insinuate user credentials are the likely cause of the failure
- Additional log messages added
2016-08-17 11:50:34 +02:00
16527c8124 Client explicitly refuses to accept change cipher spec if no or NULL cipher was proposed now 2016-08-17 09:32:43 +02:00
69e6b775f8 Hello requests are no longer included in the handshake hashing (as per RFC) 2016-08-17 09:29:55 +02:00
c69316071f Support for encrypted change cipher spec messages added 2016-08-17 09:26:46 +02:00
a02d1e7094 Explicit checks on server certificate chain added:
- Certificate can not be self-signed: Cannot check trust against configured root CAs when server certificate is self-signed
- Server can provide full certificate chain up-to and including root CA. Importing root CA to the store for certificate chain validation would implicitly trust this certificate chain. Thus, we skip all self-signed certificates on import.
2016-08-17 09:22:38 +02:00
078636eb14 make_change_chiper_spec() removed as this message can simply be created using make_message() 2016-08-17 09:09:42 +02:00
cabae26e0b Flags describing handshake messages received assembled in a boolean table of flags 2016-08-17 09:01:11 +02:00
7376693838 Additional constants 2016-08-17 08:34:25 +02:00
a5b3914a09 Comments and some minor clean-up 2016-08-16 22:27:30 +02:00
8beb7bd27a Version set to 1.0-alpha7 2016-08-16 16:59:03 +02:00
00dd1277c5 Switched to the new key import method, as the old one had issues with PROV_RSA_AES crystallographic provider 2016-08-16 16:55:18 +02:00
e9839706b6 TLS clean-up 2016-08-16 16:44:19 +02:00
f5b03bc0bf Annotation update 2016-08-16 10:39:42 +02:00
c953fb8db4 Version set to 1.0-alpha6 2016-08-16 01:00:41 +02:00
db27355e46 Some last compiler warnings resolved 2016-08-16 00:58:22 +02:00
85d7c3d4ec Support for TLS 1.2 added 2016-08-16 00:47:47 +02:00
d68fd6ce08 Support for TLS 1.1 finished 2016-08-15 22:49:45 +02:00
82e910fea4 Late pad-checking added to prevent [Canvel, B] attack 2016-08-15 22:48:08 +02:00
7fa3289e3d Incorrect parameter reference fixed 2016-08-15 22:45:54 +02:00
de802b7a28 Byte-enums redefined & code clean-up 2016-08-15 21:01:38 +02:00
67fe27f6fd Support for stream ciphers added 2016-08-15 19:04:56 +02:00
c8cfe4da42 TLS version no longer static, thou still fixed to TLS 1.0 2016-08-15 19:04:21 +02:00
3267b7f53d Missing credential storage added 2016-08-15 18:36:01 +02:00
7b3ecda484 Clean-up 2016-08-15 18:35:15 +02:00
d8ccf7cbc0 Credential management revised 2016-08-15 17:33:10 +02:00
4dc7083028 wxEAPProviderLockedPanelBase renamed to wxEAPGeneralNotePanel to accommodate general use later 2016-08-15 16:53:42 +02:00
e34d2ba275 Prefast declaration update 2016-08-15 15:10:42 +02:00
3d6849a523 Peer correctly returns providers configuration instead of method configuration in method_tls::get_result() 2016-08-15 14:13:14 +02:00
217c3dd090 Issue with TLS credentials panel resetting PAP credentials in TTLS fixed 2016-08-15 14:05:14 +02:00
e807336e7b The TLS phase can be determined from flags alone, therefore m_phase member eliminated 2016-08-15 10:40:27 +02:00
95426cde7c Clean-up 2016-08-15 10:09:01 +02:00
92c62c53d7 16B PAP password padding added (RFC 5281) 2016-08-15 05:40:23 +02:00
99aa53726d - PPP authentication EAP response packet is correctly formed now
- MS-MPPE-Send-Key/MS-MPPE-Recv-Key sorted out
2016-08-14 21:04:19 +02:00
95e2f7e01b Encryption/decryption revised
- Number of memory copying reduced
- HMAC verification of server packets added
- Handshake hashing simplified
2016-08-14 18:51:18 +02:00
735d669887 Check for "change cipher spec" before server "finished" message added 2016-08-14 16:32:28 +02:00
a8db309a76 Wrong HMAC byte order issue fixed 2016-08-14 16:31:38 +02:00
7b94f01aa7 method_tls::create_key() optimization 2016-08-14 16:31:07 +02:00
12beee54ad Ambiguous variable name changed 2016-08-14 16:24:07 +02:00
956ef9bd4e CryptGenRandom() return status check added 2016-08-14 16:22:59 +02:00
f9c5f608d0 Fixed missing server handshake message hashing 2016-08-14 14:03:12 +02:00
4982fc1a9a Ambiguous logical expression equipped with parentheses 2016-08-14 14:01:20 +02:00
e7e8a88f32 Initialization of eap::tls_conn_state introduced 2016-08-14 13:59:54 +02:00
9a2663eb18 Non TLS1PRF case fixed in method_tls::prf() 2016-08-14 13:31:39 +02:00
940def31e6 Unused tls_conn_state member removed 2016-08-14 13:29:51 +02:00
47653492a2 Session key importing honours MSDN recommendation about exponent-one key usage 2016-08-14 12:44:49 +02:00
d1925a0704 method_tls::prf() simplified 2016-08-14 12:41:19 +02:00
a90a7722c7 PAP introduced 2016-08-13 18:56:37 +02:00
ae37c9aa6c TLS and TTLS distinction 2016-08-13 18:55:33 +02:00
cbda758178 MS-MPPE-Send-Key and MS-MPPE-Recv-Key are swapped now 2016-08-13 18:52:20 +02:00
04444eb99d Encrypted pre-master secret byte order is correct now 2016-08-13 18:51:14 +02:00
b7b45ea64c Cipher block length is correctly translated from bits to bytes now 2016-08-13 18:50:09 +02:00
4528f2d1fc Simplification 2016-08-13 18:48:56 +02:00
eb918f3141 Processing of vendor specific TLS messages introduced 2016-08-13 18:48:02 +02:00
c749753c68 State constants renamed more systematically 2016-08-13 18:45:40 +02:00
9f92a73aa1 make_handshake() renamed to make_message() and made more general 2016-08-13 18:42:52 +02:00
6d54d45512 Pre-master secret encryption moved to make_client_key_exchange() 2016-08-13 18:39:22 +02:00
9498e8c9a9 Fixed issue occurred after careless eap::tls_random::time elimination 2016-08-13 18:32:40 +02:00
f9c6bce0f8 Diameter AVP helper structures added 2016-08-13 18:26:19 +02:00
3d54c84430 method_ttls is now descendant of method_tls 2016-08-13 08:48:24 +02:00
1306c958fc config_method_ttls is now descendant of config_method_tls 2016-08-13 08:48:01 +02:00
09924ea3d2 credentials_ttls is descendant of credentials_tls again 2016-08-13 08:36:10 +02:00
537d0c0cbc Changing TLS configuration resets TLS session resumption 2016-08-13 08:31:03 +02:00
6408dbe237 Missing credentials error check lost with b71e30f642 reimplemented 2016-08-13 08:29:01 +02:00
534f6f6d7d tls_conn_state is class now 2016-08-13 08:09:47 +02:00
f7fdfb8dda EAP packet type check moved to Main.cpp 2016-08-13 08:09:13 +02:00
c7a41d891a TLS work continues... 2016-08-12 21:09:50 +02:00
a8c306953a TLS work continues... 2016-08-11 15:13:50 +02:00
77fe6b1bed TLS connection state moved from eap::method_tls to eap::method_tls::conn_state to make reusable later 2016-08-11 12:00:38 +02:00
659629ed93 Clean-up 2016-08-11 09:44:01 +02:00
6b4f597f27 - Microsoft's HMAC had problems with secrets longer than 16B, therefore we implemented our own
- Key generation finished
- Additional memory sanitization
2016-08-10 16:10:40 +02:00
fb0fa0de31 HMAC fixed to start with the correct key now 2016-08-10 11:18:20 +02:00
e92f47677d TLS implementation continues... 2016-08-09 18:37:12 +02:00
ba5bf1e533 HMAC cleanup 2016-08-09 06:39:33 +02:00
1bf51fda25 win_runtime_error moved to WinStd; eapxml functions return HRESULT now 2016-08-09 01:05:00 +02:00
b71e30f642 EAP_ERROR replaced with C++ exceptions for increased code readability 2016-08-08 22:59:17 +02:00
788c8cdb16 TLS implementation continues... 2016-08-08 18:52:13 +02:00
ce9e636840 TLS start packet processing logic made more robust 2016-08-08 10:42:24 +02:00
8f4c177d49 eap namespace clean-up 2016-08-08 10:13:34 +02:00
bf4b7f9787 Packet data updated correctly now; Missing server ACK detection added 2016-08-08 08:59:11 +02:00
be3c591955 TLS fragmented message correctly assembled now & Event manifest revised 2016-08-07 13:51:40 +02:00
d199cb68bb Work continues...
- More event reporting added
- unsigned long and DWORD replaced with unsigned int for code readability and (possibly) portability
- Client hello message fixed
- SSL version reverted to TLS 1.0, will catch-up later if required
2016-08-07 12:15:45 +02:00
e649a86b1f Error checking and size asserts added 2016-08-07 06:56:29 +02:00
a0efb6742d EAP-TTLS work continues... 2016-08-06 16:27:15 +02:00
b39cc927d2 Session.h/cpp >> Method.h/cpp 2016-08-06 10:36:58 +02:00
faadb712fc Sessions are actually methods now 2016-08-06 10:28:15 +02:00
97d0f75f8d eap::method introduced 2016-08-06 09:52:29 +02:00
4114863a94 Duplicate error logging removed 2016-08-06 08:21:14 +02:00
afe5450b95 Peer (Main.cpp) no longer manipulates session directly. Session management moved to eap::peer. 2016-08-06 08:06:38 +02:00
ac606b7a2e config_providers renamed to config_provider_list to avoid confusion with config_provider 2016-08-06 07:06:48 +02:00
2aa4bce8cc eap::config::m_module reference again 2016-08-06 07:01:12 +02:00
b0323d894a Issues with pre-shared credentials after being moved to heap fixed 2016-08-05 16:28:21 +02:00
42459ff16a EAP events changed to use numerical EAP type 2016-08-05 16:15:08 +02:00
2711425677 Documentation update 2016-08-05 15:52:27 +02:00
54bb2050fa peer and peer_ui are no longer templates; method specific BLOB management moved from Main(_UI).cpp to modules. 2016-08-05 15:45:45 +02:00
437f5f91b8 eap::peer<> and eap::session<> redundant template argument removed 2016-08-05 13:45:18 +02:00
91dcc0bbbc peer_base eliminated 2016-08-05 13:40:54 +02:00
a60458cdab eap::module is no longer abstract 2016-08-05 13:18:25 +02:00
4fc029138c config_method_with_cred is no longer a template 2016-08-05 11:51:59 +02:00
f4be571499 Pre-shared credentials moved to heap 2016-08-05 11:38:43 +02:00
460adb9858 m_module is now a pointer instead of reference 2016-08-05 11:23:59 +02:00
a9ecde86d9 TLS specific package communication moved from TTLS to TLS session 2016-08-05 11:01:30 +02:00
7e7c657358 Documentation update 2016-08-05 10:55:23 +02:00
f2aa43913d EAP-TTLS session development continues... 2016-08-05 00:32:57 +02:00
a102b43a19 eap::type_t >> winstd::eap_type_t 2016-08-04 12:08:20 +02:00
22a87bf90d eap::session::get_response_packet() implemented 2016-08-04 10:07:03 +02:00
caf0352833 Packet processing methods made pure virtual in eap::session<>, stubs created in eap::session_ttls 2016-08-03 15:31:06 +02:00
f68a65f8f8 eap::session<> remembers basic EAP session parameters now 2016-08-03 15:22:52 +02:00
3e82b7df49 eap::method_property => winstd::eap_method_prop 2016-08-03 15:09:58 +02:00
cb24fbd6a3 eap::peer_ttls::get_method_properties() implemented 2016-08-03 13:50:12 +02:00
b32b63631a Guests are not allowed to save credentials 2016-08-03 12:36:29 +02:00
5fe06deb97 Provider-locked configuration notice removed from credential prompt for aesthetic reasons 2016-08-03 12:35:51 +02:00
cadf7272df Credential UI revised to honor read-only, allow-save, and config/prompt mode correctly 2016-08-03 12:34:49 +02:00
2868fd3848 Cached credentials have priority now 2016-08-03 10:17:40 +02:00
9fed6dcf9d Sub-module update 2016-08-03 09:22:52 +02:00
a81ddde411 MSVC specific __super keyword replaced 2016-08-03 09:22:41 +02:00
aafd012809 Credential dialog is no longer displayed partially off the screen 2016-07-21 23:53:40 +02:00
3e60bebe3a Credential's "Remember" checkbox logic revised 2016-07-21 23:53:11 +02:00
6ae8029a47 config_method split into config_method and config_method_with_cred<> 2016-07-21 22:30:03 +02:00
ac88d55fe4 EapPeerInvokeConfigUI() checks for blank configuration now 2016-07-21 21:57:31 +02:00
955d7f5dc1 Missing credentials are correctly honoured now 2016-07-21 14:21:33 +02:00
b4667cac18 Inner-method-name-determining-from-NULL-pointer-crash fixed :) 2016-07-21 14:15:39 +02:00
98f20668c3 credentials_ttls::target_suffix() implemented 2016-07-21 14:14:26 +02:00
df773b649c Event colours updated for greater disambiguation between EAPHost and GÉANTLink entries 2016-07-21 13:29:55 +02:00
6d8bd3f1c1 Cached credentials are correctly honored now 2016-07-21 13:21:40 +02:00
fa84cf93b9 32-bit C compiler warning fixed 2016-07-21 12:52:30 +02:00
f459a036da peer_ttls::get_identity() finished 2016-07-21 12:36:18 +02:00
cc43b44d91 credentials_ttls::get_identity() introduced 2016-07-21 12:35:19 +02:00
35034789d2 String typing fixed 2016-07-21 12:34:49 +02:00
4834c9e4da credentials::get_name() fixed to return "<blank>" for empty credentials 2016-07-21 12:34:19 +02:00
ee8410bdb9 credentials::target_suffix() is public now, as it can be reused to provide GUI method identifier 2016-07-21 12:33:32 +02:00
d69e8b3f6a EapPeerGetIdentity() accounts for missing cached credentials now 2016-07-21 12:30:46 +02:00
4ab60271b7 Missing key-pair added to EAPTTLS resources 2016-07-21 12:29:49 +02:00
1b9f33a6fc Path-delimiters unified in RC files 2016-07-21 12:29:23 +02:00
627b20aabc pack() => operator <<, unpack() => operator >>, get_pk_size() => pksizeof() 2016-07-21 09:20:09 +02:00
51428d290f Memory overflow detection when packing/unpacking BLOB added 2016-07-20 19:29:21 +02:00
2f4425f38c EAPSerial.h merged into EAP.h 2016-07-20 18:17:25 +02:00
b26ab72e6e Some more template simplifications followed 2016-07-20 18:10:38 +02:00
9376404164 eap::config_provider changed from template to class followed by a mass detemplatization of other classes 2016-07-20 17:57:43 +02:00
a7d75ea72d eap::config_provider detemplatization 2016-07-20 16:47:37 +02:00
780b738842 config_provider::m_methods is a list of pointers to method configurations now paving the road to config_provider detemplatization 2016-07-20 16:04:56 +02:00
e87c0af221 Secondary method configurations properly initialized now 2016-07-20 15:33:00 +02:00
180d9b265c eap::config_method is no longer a template class 2016-07-20 15:21:58 +02:00
ce0bbc5b45 config_method::m_preshared moved to heap, which in turn required shift to virtual methods for packing/unpacking BLOBs 2016-07-20 14:59:12 +02:00
3e82e988d4 Identity of digital certificates is correctly resolved now 2016-07-20 12:59:58 +02:00
418e591aa6 Tool-tip update 2016-07-20 12:39:33 +02:00
b7ea2f7a72 EapPeerGetUIContext()/eap::session::get_ui_context() completed 2016-07-20 12:04:11 +02:00
07b4ce988b eap::credentials_ttls::m_inner is std::unique_ptr managed now
(Also fixes a memory leak caused by missing destructor pointer delete)
2016-07-20 11:47:40 +02:00
427e2fb892 config_method_ttls::m_inner is managed by std::unique_ptr now 2016-07-20 11:35:29 +02:00
db69c23689 usr => cred 2016-07-20 11:27:23 +02:00
43751ed908 Template arguments and type names unified 2016-07-20 11:25:03 +02:00
2a19b4624a Class consistency renaming 2016-07-20 11:05:01 +02:00
434e042f8b Class naming update 2016-07-20 10:37:12 +02:00
512f46f014 pack/unpack & load/save nesting arranged all the way up to eap::config 2016-07-20 10:31:34 +02:00
a92cafea36 eap::credentials::get_name() method introduced to allow more detailed display of certificate names 2016-07-20 10:05:36 +02:00
4f6943044f eap::credentials::m_identity replaced with virtual method get_identity() 2016-07-20 09:54:26 +02:00
504ea681a9 Strings packed/unpacked as zero-terminated (instead of length prefixed) now 2016-07-20 09:22:54 +02:00
54fc2dd830 Generic templates for data packing/unpacking replaced with specific to avoid accidental use 2016-07-20 09:14:47 +02:00
a0303f0a1f EAP-TTLS module and session data types for interactive prompt/response data changed to bool for simplicity of next commit 2016-07-20 09:10:54 +02:00
40c992e1a5 Memory sanitizing on BLOB free removed, since BLOBS are encrypted from d15b7066cd on 2016-07-20 08:48:28 +02:00
4630b32f77 target_suffix() method is private now 2016-07-19 13:39:41 +02:00
4acabbca4e Configuration and credentials logging introduced 2016-07-19 12:53:54 +02:00
2f28b89ab2 Trusted Root CA list displays the certificate names in the consistent way with credential certificates now 2016-07-19 12:15:01 +02:00
9257391938 eapxml::get_xpath() introduced 2016-07-19 12:05:38 +02:00
4e407b7dad Minor flaws with array and struct display fixed 2016-07-19 12:04:49 +02:00
faea2f3771 eap::get_cert_title() moved from TLS_UI to TLS 2016-07-19 12:03:02 +02:00
0ee9bade32 EAPMETHOD_TRACE_EAP_ERROR => EAPMETHOD_TRACE_EVT_EAP_ERROR 2016-07-19 08:54:32 +02:00
34f16478e4 EventMonitor icon added 2016-07-19 07:01:04 +02:00
00244e3846 EventMonitor is functional now 2016-07-18 16:49:55 +02:00
6822a91f41 Paths to files are generated using folder properties instead of component's key-file referencing to avoid ICE69 warnings 2016-07-18 09:46:47 +02:00
06adf7ddae EventMonitor replaced with Windows-based application (work in progress...) 2016-07-15 13:16:17 +02:00
8eb1936adf Internal and output folders now using $(MSBuildProjectName) instead of $(ProjectName), to distinguish project variations of essentially the same module 2016-07-15 12:45:34 +02:00
c8de331d50 Translation template added 2016-07-15 10:54:58 +02:00
560aa3068d General package information moved from NMAKE macros to Property table, to allow translation to other scripts (than Windows-1252 and Windows-1250) 2016-07-15 10:54:44 +02:00
d792520f51 Version set to 1.0-alpha5
(closes #2)
2016-06-23 17:19:47 +02:00
9f4c4514cb EAPHost trace added 2016-06-23 17:16:52 +02:00
de94d27380 EventMonitor added to MSI 2016-06-23 17:16:24 +02:00
ded87eb18c EventMonitor requires elevation now 2016-06-23 17:16:03 +02:00
0639169d9a EventMonitor utility is operational now 2016-06-23 15:46:58 +02:00
fa141fc525 Correct event is reported for DWORD-returning functions now 2016-06-23 15:46:12 +02:00
1fc77fc63d EAP method type is now a map 2016-06-23 15:44:57 +02:00
d15b7066cd RSA encryption replaced with RSA session key exchange and AES data encryption; BLOBs are encrypted again 2016-06-23 00:47:38 +02:00
922d0ac3d0 Additional RSA credential encryption replaced with product-specific entropy in user-specific encryption pass, to circumvent RSA data length limitation 2016-06-22 23:32:28 +02:00
f3cb90d1c3 EventMonitor development continues... 2016-06-22 18:03:47 +02:00
a7e0e5ebd8 MSIBUILD_PRODUCT_NAME check added 2016-06-22 18:02:42 +02:00
3238881af8 Event provider registration added 2016-06-22 18:02:20 +02:00
9d0d3418b0 Sub-module update 2016-06-22 18:01:52 +02:00
81a268df1b Sub-module update 2016-06-22 17:59:43 +02:00
d1a4487503 BLOB encryption temporary disabled, as RSA can not encrypt data this long 2016-06-22 17:59:26 +02:00
24008000a9 Merge branch 'master' of https://github.com/Amebis/GEANTLink 2016-06-22 09:18:41 +02:00
bdd3fc616c EAP BLOBs are encrypted now 2016-06-22 09:18:27 +02:00
e31fc08a64 EventMonitor utility introduced 2016-06-22 06:28:21 +02:00
a2ca2fd850 Logging and error reporting simplified 2016-06-21 13:15:50 +02:00
e98856f934 Support for provider contact info added 2016-06-21 10:46:05 +02:00
b634956901 Credentials dialog banner title now dynamic 2016-06-21 09:18:17 +02:00
0c8492ccd1 CredProtect() replaced with CryptProtectData() << the former didn't work between normal and UAC-elevated processes: stored credentials are no longer valid and should be reentered 2016-06-20 16:37:48 +02:00
768e0a5a36 Previously unused templates fixed 2016-06-20 16:24:58 +02:00
ac23d5f04f Custom credential prompt labels are honored now (for password-based methods) 2016-06-20 15:14:48 +02:00
e52b9a636f Support for read-only configurations added 2016-06-20 14:51:21 +02:00
126 changed files with 42883 additions and 4621 deletions

3
.gitmodules vendored
View File

@@ -4,3 +4,6 @@
[submodule "lib/WinStd"]
path = lib/WinStd
url = https://github.com/Amebis/WinStd.git
[submodule "lib/wxExtend"]
path = lib/wxExtend
url = https://github.com/Amebis/wxExtend.git

Binary file not shown.

View File

@@ -23,7 +23,7 @@
using namespace std;
using namespace winstd;
eap::module g_module(eap::type_undefined);
eap::module g_module;
static int CredWrite()
@@ -81,28 +81,25 @@ static int CredWrite()
}
// Write credentials.
EAP_ERROR *pEapError = NULL;
#ifdef _DEBUG
{
eap::credentials_pap cred_stored(g_module);
if (!cred_stored.retrieve(target_name.c_str(), &pEapError)) {
if (pEapError) {
OutputDebugStr(_T("%ls (error %u)\n"), pEapError->pRootCauseString, pEapError->dwWinError);
g_module.free_error_memory(pEapError);
pEapError = NULL;
} else
OutputDebugStr(_T("Reading credentials failed.\n"));
try {
cred_stored.retrieve(target_name.c_str());
} catch(win_runtime_error &err) {
OutputDebugStr(_T("%hs (error %u)\n"), err.what(), err.number());
} catch(...) {
OutputDebugStr(_T("Reading credentials failed.\n"));
}
}
#endif
if (!cred.store(target_name.c_str(), &pEapError)) {
if (pEapError) {
OutputDebugStr(_T("%ls (error %u)\n"), pEapError->pRootCauseString, pEapError->dwWinError);
g_module.free_error_memory(pEapError);
pEapError = NULL;
} else
OutputDebugStr(_T("Writing credentials failed.\n"));
try {
cred.store(target_name.c_str());
} catch(win_runtime_error &err) {
OutputDebugStr(_T("%hs (error %u)\n"), err.what(), err.number());
return 2;
} catch(...) {
OutputDebugStr(_T("Writing credentials failed.\n"));
return 2;
}

View File

@@ -20,6 +20,7 @@
#pragma once
#include "../lib/PAP/include/Config.h"
#include "../lib/PAP/include/Credentials.h"
#include "../lib/EAPBase/include/Module.h"

Binary file not shown.

View File

@@ -20,5 +20,5 @@
#pragma once
#include "../../lib/TTLS/include/Method.h"
#include "../../lib/TTLS/include/Module.h"
#include "../../lib/TTLS/include/Session.h"

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,9 @@
#pragma comment(lib, "msxml6.lib")
using namespace std;
using namespace winstd;
#if EAPMETHOD_TYPE==21
#define _EAPMETHOD_PEER_UI eap::peer_ttls_ui
@@ -70,6 +73,8 @@ BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID l
///
VOID WINAPI EapPeerFreeMemory(_In_ void *pUIContextData)
{
event_fn_auto event_auto(g_peer.get_event_fn_auto(__FUNCTION__));
if (pUIContextData)
g_peer.free_memory((BYTE*)pUIContextData);
}
@@ -82,6 +87,8 @@ VOID WINAPI EapPeerFreeMemory(_In_ void *pUIContextData)
///
VOID WINAPI EapPeerFreeErrorMemory(_In_ EAP_ERROR *ppEapError)
{
event_fn_auto event_auto(g_peer.get_event_fn_auto(__FUNCTION__));
if (ppEapError)
g_peer.free_error_memory(ppEapError);
}
@@ -96,57 +103,51 @@ DWORD WINAPI EapPeerConfigXml2Blob(
_In_ DWORD dwFlags,
_In_ EAP_METHOD_TYPE eapMethodType,
_In_ IXMLDOMDocument2 *pConfigDoc,
_Out_ BYTE **ppConfigOut,
_Out_ DWORD *pdwConfigOutSize,
_Out_ BYTE **pConnectionDataOut,
_Out_ DWORD *pdwConnectionDataOutSize,
_Out_ EAP_ERROR **ppEapError)
{
DWORD dwResult = ERROR_SUCCESS;
event_fn_auto_ret<DWORD> event_auto(g_peer.get_event_fn_auto(__FUNCTION__, dwResult));
#ifdef _DEBUG
//Sleep(10000);
#endif
// Parameter check
if (!ppEapError)
dwResult = ERROR_INVALID_PARAMETER;
else if (eapMethodType.eapType.type != EAPMETHOD_TYPE)
*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)eapMethodType.eapType.type, (int)EAPMETHOD_TYPE).c_str(), NULL);
return dwResult = ERROR_INVALID_PARAMETER;
assert(!*ppEapError);
if (eapMethodType.eapType.type != EAPMETHOD_TYPE)
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)eapMethodType.eapType.type, (int)EAPMETHOD_TYPE).c_str()));
else if (eapMethodType.dwAuthorId != 67532)
*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)eapMethodType.dwAuthorId, (int)67532).c_str(), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)eapMethodType.dwAuthorId, (int)67532).c_str()));
else if (!pConfigDoc)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pConfigDoc is NULL."), NULL);
else if (!ppConfigOut)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppConfigOut is NULL."), NULL);
else if (!pdwConfigOutSize)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pdwConfigOutSize is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pConfigDoc is NULL.")));
else if (!pConnectionDataOut)
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pConnectionDataOut is NULL.")));
else if (!pdwConnectionDataOutSize)
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pdwConnectionDataOutSize is NULL.")));
else {
UNREFERENCED_PARAMETER(dwFlags);
// <Config>
pConfigDoc->setProperty(winstd::bstr(L"SelectionNamespaces"), winstd::variant(L"xmlns:eaphostconfig=\"http://www.microsoft.com/provisioning/EapHostConfig\""));
winstd::com_obj<IXMLDOMElement> pXmlElConfig;
if ((dwResult = eapxml::select_element(pConfigDoc, winstd::bstr(L"//eaphostconfig:Config"), &pXmlElConfig)) != ERROR_SUCCESS)
return dwResult;
// Load configuration.
pConfigDoc->setProperty(winstd::bstr(L"SelectionNamespaces"), winstd::variant(L"xmlns:eap-metadata=\"urn:ietf:params:xml:ns:yang:ietf-eap-metadata\""));
_EAPMETHOD_PEER_UI::config_type cfg(g_peer);
if (!cfg.load(pXmlElConfig, ppEapError))
return dwResult = *ppEapError ? (*ppEapError)->dwWinError : ERROR_INVALID_DATA;
// Allocate BLOB for configuration.
assert(ppConfigOut);
assert(pdwConfigOutSize);
*pdwConfigOutSize = (DWORD)eapserial::get_pk_size(cfg);
*ppConfigOut = g_peer.alloc_memory(*pdwConfigOutSize);
if (!*ppConfigOut) {
*ppEapError = g_peer.make_error(dwResult = ERROR_OUTOFMEMORY, 0, NULL, NULL, NULL, winstd::tstring_printf(_T(__FUNCTION__) _T(" Error allocating memory for configuration BLOB (%uB)."), *pdwConfigOutSize).c_str(), NULL);
pConfigDoc->setProperty(bstr(L"SelectionNamespaces"), variant(L"xmlns:eaphostconfig=\"http://www.microsoft.com/provisioning/EapHostConfig\""));
com_obj<IXMLDOMElement> pXmlElConfig;
if (FAILED(eapxml::select_element(pConfigDoc, bstr(L"//eaphostconfig:Config"), &pXmlElConfig))) {
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" Error reading <Config> element.")));
return dwResult;
}
// Pack BLOB to output.
unsigned char *cursor = *ppConfigOut;
eapserial::pack(cursor, cfg);
assert(cursor - *ppConfigOut <= (ptrdiff_t)*pdwConfigOutSize);
// Load configuration.
pConfigDoc->setProperty(bstr(L"SelectionNamespaces"), variant(L"xmlns:eap-metadata=\"urn:ietf:params:xml:ns:yang:ietf-eap-metadata\""));
try {
g_peer.config_xml2blob(dwFlags, pXmlElConfig, pConnectionDataOut, pdwConnectionDataOutSize);
} catch (std::exception &err) {
g_peer.log_error(*ppEapError = g_peer.make_error(err));
dwResult = (*ppEapError)->dwWinError;
} catch (...) {
dwResult = ERROR_INVALID_DATA;
}
}
return dwResult;
@@ -161,45 +162,40 @@ DWORD WINAPI EapPeerConfigXml2Blob(
/// \sa [EapPeerConfigBlob2Xml function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363601.aspx)
///
DWORD WINAPI EapPeerConfigBlob2Xml(
_In_ DWORD dwFlags,
_In_ EAP_METHOD_TYPE eapMethodType,
_In_count_(dwConfigInSize) const BYTE *pConfigIn,
_In_ DWORD dwConfigInSize,
_Out_ IXMLDOMDocument2 **ppConfigDoc,
_Out_ EAP_ERROR **ppEapError)
_In_ DWORD dwFlags,
_In_ EAP_METHOD_TYPE eapMethodType,
_In_count_(dwConnectionDataSize) const BYTE *pConnectionData,
_In_ DWORD dwConnectionDataSize,
_Out_ IXMLDOMDocument2 **ppConfigDoc,
_Out_ EAP_ERROR **ppEapError)
{
DWORD dwResult = ERROR_SUCCESS;
event_fn_auto_ret<DWORD> event_auto(g_peer.get_event_fn_auto(__FUNCTION__, dwResult));
#ifdef _DEBUG
//Sleep(10000);
#endif
// Parameter check
if (!ppEapError)
dwResult = ERROR_INVALID_PARAMETER;
else if (eapMethodType.eapType.type != EAPMETHOD_TYPE)
*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)eapMethodType.eapType.type, (int)EAPMETHOD_TYPE).c_str(), NULL);
return dwResult = ERROR_INVALID_PARAMETER;
assert(!*ppEapError);
if (eapMethodType.eapType.type != EAPMETHOD_TYPE)
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)eapMethodType.eapType.type, (int)EAPMETHOD_TYPE).c_str()));
else if (eapMethodType.dwAuthorId != 67532)
*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)eapMethodType.dwAuthorId, (int)67532).c_str(), NULL);
else if (!pConfigIn && dwConfigInSize)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pConfigIn is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)eapMethodType.dwAuthorId, (int)67532).c_str()));
else if (!pConnectionData && dwConnectionDataSize)
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pConnectionData is NULL.")));
else if (!ppConfigDoc)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppConfigDoc is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" ppConfigDoc is NULL.")));
else {
UNREFERENCED_PARAMETER(dwFlags);
HRESULT hr;
// Unpack configuration.
_EAPMETHOD_PEER_UI::config_type cfg(g_peer);
if (pConfigIn || !dwConfigInSize) {
const unsigned char *cursor = pConfigIn;
eapserial::unpack(cursor, cfg);
assert(cursor - pConfigIn <= (ptrdiff_t)dwConfigInSize);
}
// Create configuration XML document.
winstd::com_obj<IXMLDOMDocument2> pDoc;
com_obj<IXMLDOMDocument2> pDoc;
if (FAILED(hr = pDoc.create(CLSID_DOMDocument60, NULL, CLSCTX_INPROC_SERVER))) {
*ppEapError = g_peer.make_error(dwResult = HRESULT_CODE(hr), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating XML document."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = HRESULT_CODE(hr), _T(__FUNCTION__) _T(" Error creating XML document.")));
return dwResult;
}
@@ -207,25 +203,33 @@ DWORD WINAPI EapPeerConfigBlob2Xml(
// Load empty XML configuration.
VARIANT_BOOL isSuccess = VARIANT_FALSE;
if (FAILED((hr = pDoc->loadXML(L"<Config xmlns=\"http://www.microsoft.com/provisioning/EapHostConfig\"><EAPIdentityProviderList xmlns=\"urn:ietf:params:xml:ns:yang:ietf-eap-metadata\"></EAPIdentityProviderList></Config>", &isSuccess))))
return dwResult = HRESULT_CODE(hr);
if (FAILED((hr = pDoc->loadXML(L"<Config xmlns=\"http://www.microsoft.com/provisioning/EapHostConfig\"><EAPIdentityProviderList xmlns=\"urn:ietf:params:xml:ns:yang:ietf-eap-metadata\"></EAPIdentityProviderList></Config>", &isSuccess)))) {
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = HRESULT_CODE(hr), _T(__FUNCTION__) _T(" Error loading XML document template.")));
return dwResult;
}
if (!isSuccess) {
*ppEapError = g_peer.make_error(dwResult = ERROR_XML_PARSE_ERROR, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Loading XML template failed."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_XML_PARSE_ERROR, _T(__FUNCTION__) _T(" Loading XML template failed.")));
return dwResult;
}
// Select <Config> node.
winstd::com_obj<IXMLDOMNode> pXmlElConfig;
pDoc->setProperty(winstd::bstr(L"SelectionNamespaces"), winstd::variant(L"xmlns:eaphostconfig=\"http://www.microsoft.com/provisioning/EapHostConfig\""));
if ((dwResult = eapxml::select_node(pDoc, winstd::bstr(L"eaphostconfig:Config"), &pXmlElConfig)) != ERROR_SUCCESS) {
*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_FOUND, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error selecting <Config> element."), NULL);
com_obj<IXMLDOMNode> pXmlElConfig;
pDoc->setProperty(bstr(L"SelectionNamespaces"), variant(L"xmlns:eaphostconfig=\"http://www.microsoft.com/provisioning/EapHostConfig\""));
if (FAILED(eapxml::select_node(pDoc, bstr(L"eaphostconfig:Config"), &pXmlElConfig))) {
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_FOUND, _T(__FUNCTION__) _T(" Error selecting <Config> element.")));
return dwResult;
}
// Save all providers.
pDoc->setProperty(winstd::bstr(L"SelectionNamespaces"), winstd::variant(L"xmlns:eap-metadata=\"urn:ietf:params:xml:ns:yang:ietf-eap-metadata\""));
if (!cfg.save(pDoc, pXmlElConfig, ppEapError))
return dwResult = *ppEapError ? (*ppEapError)->dwWinError : ERROR_INVALID_DATA;
// Save configuration.
pDoc->setProperty(bstr(L"SelectionNamespaces"), variant(L"xmlns:eap-metadata=\"urn:ietf:params:xml:ns:yang:ietf-eap-metadata\""));
try {
g_peer.config_blob2xml(dwFlags, pConnectionData, dwConnectionDataSize, pDoc, pXmlElConfig);
} catch (std::exception &err) {
g_peer.log_error(*ppEapError = g_peer.make_error(err));
return dwResult = (*ppEapError)->dwWinError;
} catch (...) {
return dwResult = ERROR_INVALID_DATA;
}
*ppConfigDoc = pDoc.detach();
}
@@ -251,52 +255,39 @@ DWORD WINAPI EapPeerInvokeConfigUI(
{
UNREFERENCED_PARAMETER(dwFlags);
DWORD dwResult = ERROR_SUCCESS;
winstd::actctx_activator actctx(g_act_ctx);
event_fn_auto_ret<DWORD> event_auto(g_peer.get_event_fn_auto(__FUNCTION__, dwResult));
actctx_activator actctx(g_act_ctx);
#ifdef _DEBUG
//Sleep(10000);
#endif
// Parameter check
if (!ppEapError)
dwResult = ERROR_INVALID_PARAMETER;
else if (!pEapType)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapType is NULL."), NULL);
return dwResult = ERROR_INVALID_PARAMETER;
assert(!*ppEapError);
if (!pEapType)
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pEapType is NULL.")));
else if (pEapType->eapType.type != EAPMETHOD_TYPE)
*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->eapType.type, (int)EAPMETHOD_TYPE).c_str(), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->eapType.type, (int)EAPMETHOD_TYPE).c_str()));
else if (pEapType->dwAuthorId != 67532)
*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)pEapType->dwAuthorId, (int)67532).c_str(), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)pEapType->dwAuthorId, (int)67532).c_str()));
else if (!pConnectionDataIn && dwConnectionDataInSize)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pConnectionDataIn is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pConnectionDataIn is NULL.")));
else if (!pdwConnectionDataOutSize)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pdwConnectionDataOutSize is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pdwConnectionDataOutSize is NULL.")));
else if (!ppConnectionDataOut)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppConnectionDataOut is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" ppConnectionDataOut is NULL.")));
else {
// Unpack configuration.
_EAPMETHOD_PEER_UI::config_type cfg(g_peer);
if (pConnectionDataIn || !dwConnectionDataInSize) {
const unsigned char *cursor = pConnectionDataIn;
eapserial::unpack(cursor, cfg);
assert(cursor - pConnectionDataIn <= (ptrdiff_t)dwConnectionDataInSize);
try {
g_peer.invoke_config_ui(hwndParent, pConnectionDataIn, dwConnectionDataInSize, ppConnectionDataOut, pdwConnectionDataOutSize);
} catch (std::exception &err) {
g_peer.log_error(*ppEapError = g_peer.make_error(err));
dwResult = (*ppEapError)->dwWinError;
} catch (...) {
dwResult = ERROR_INVALID_DATA;
}
if (!g_peer.invoke_config_ui(hwndParent, cfg, ppEapError))
return dwResult = *ppEapError ? (*ppEapError)->dwWinError : ERROR_INVALID_DATA;
// Allocate BLOB for configuration.
assert(ppConnectionDataOut);
assert(pdwConnectionDataOutSize);
*pdwConnectionDataOutSize = (DWORD)eapserial::get_pk_size(cfg);
*ppConnectionDataOut = g_peer.alloc_memory(*pdwConnectionDataOutSize);
if (!*ppConnectionDataOut) {
*ppEapError = g_peer.make_error(dwResult = ERROR_OUTOFMEMORY, 0, NULL, NULL, NULL, winstd::tstring_printf(_T(__FUNCTION__) _T(" Error allocating memory for configuration BLOB (%uB)."), *pdwConnectionDataOutSize).c_str(), NULL);
return dwResult;
}
// Pack BLOB to output.
unsigned char *cursor = *ppConnectionDataOut;
eapserial::pack(cursor, cfg);
assert(cursor - *ppConnectionDataOut <= (ptrdiff_t)*pdwConnectionDataOutSize);
}
return dwResult;
@@ -322,7 +313,8 @@ DWORD WINAPI EapPeerInvokeIdentityUI(
_Out_ EAP_ERROR **ppEapError)
{
DWORD dwResult = ERROR_SUCCESS;
winstd::actctx_activator actctx(g_act_ctx);
event_fn_auto_ret<DWORD> event_auto(g_peer.get_event_fn_auto(__FUNCTION__, dwResult));
actctx_activator actctx(g_act_ctx);
#ifdef _DEBUG
//Sleep(10000);
#endif
@@ -330,56 +322,34 @@ DWORD WINAPI EapPeerInvokeIdentityUI(
// Parameter check
if (!ppEapError)
dwResult = ERROR_INVALID_PARAMETER;
else if (!pEapType)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapType is NULL."), NULL);
assert(!*ppEapError);
if (!pEapType)
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pEapType is NULL.")));
else if (pEapType->eapType.type != EAPMETHOD_TYPE)
*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->eapType.type, (int)EAPMETHOD_TYPE).c_str(), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->eapType.type, (int)EAPMETHOD_TYPE).c_str()));
else if (pEapType->dwAuthorId != 67532)
*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)pEapType->dwAuthorId, (int)67532).c_str(), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)pEapType->dwAuthorId, (int)67532).c_str()));
else if (!pConnectionData && dwConnectionDataSize)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pConnectionData is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pConnectionData is NULL.")));
else if (!pUserData && dwUserDataSize)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pUserData is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pUserData is NULL.")));
else if (!pdwUserDataOutSize)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pdwUserDataOutSize is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pdwUserDataOutSize is NULL.")));
else if (!ppUserDataOut)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppUserDataOut is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" ppUserDataOut is NULL.")));
else if (!ppwszIdentity)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppwszIdentity is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" ppwszIdentity is NULL.")));
else {
// Unpack configuration.
_EAPMETHOD_PEER_UI::config_type cfg(g_peer);
if (pConnectionData || !dwConnectionDataSize) {
const unsigned char *cursor = pConnectionData;
eapserial::unpack(cursor, cfg);
assert(cursor - pConnectionData <= (ptrdiff_t)dwConnectionDataSize);
try {
g_peer.invoke_identity_ui(hwndParent, dwFlags, pConnectionData, dwConnectionDataSize, pUserData, dwUserDataSize, ppUserDataOut, pdwUserDataOutSize, ppwszIdentity);
} catch (std::exception &err) {
g_peer.log_error(*ppEapError = g_peer.make_error(err));
dwResult = (*ppEapError)->dwWinError;
} catch (...) {
dwResult = ERROR_INVALID_DATA;
}
// Unpack configuration.
_EAPMETHOD_PEER_UI::identity_type usr(g_peer);
if (pUserData || !dwUserDataSize) {
const unsigned char *cursor = pUserData;
eapserial::unpack(cursor, usr);
assert(cursor - pUserData <= (ptrdiff_t)dwUserDataSize);
}
if (!g_peer.invoke_identity_ui(hwndParent, dwFlags, cfg, usr, ppwszIdentity, ppEapError))
return dwResult = *ppEapError ? (*ppEapError)->dwWinError : ERROR_INVALID_DATA;
// Allocate BLOB for user data.
assert(ppUserDataOut);
assert(pdwUserDataOutSize);
*pdwUserDataOutSize = (DWORD)eapserial::get_pk_size(usr);
*ppUserDataOut = g_peer.alloc_memory(*pdwUserDataOutSize);
if (!*ppUserDataOut) {
*ppEapError = g_peer.make_error(dwResult = ERROR_OUTOFMEMORY, 0, NULL, NULL, NULL, winstd::tstring_printf(_T(__FUNCTION__) _T(" Error allocating memory for configuration BLOB (%uB)."), *pdwUserDataOutSize).c_str(), NULL);
return dwResult;
}
// Pack BLOB to output.
unsigned char *cursor = *ppUserDataOut;
eapserial::pack(cursor, usr);
assert(cursor - *ppUserDataOut <= (ptrdiff_t)*pdwUserDataOutSize);
}
return dwResult;
@@ -401,53 +371,39 @@ DWORD WINAPI EapPeerInvokeInteractiveUI(
_Out_ EAP_ERROR **ppEapError)
{
DWORD dwResult = ERROR_SUCCESS;
winstd::actctx_activator actctx(g_act_ctx);
event_fn_auto_ret<DWORD> event_auto(g_peer.get_event_fn_auto(__FUNCTION__, dwResult));
actctx_activator actctx(g_act_ctx);
#ifdef _DEBUG
//Sleep(10000);
#endif
// Parameter check
if (!ppEapError)
dwResult = ERROR_INVALID_PARAMETER;
else if (!pEapType)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapType is NULL."), NULL);
return dwResult = ERROR_INVALID_PARAMETER;
assert(!*ppEapError);
if (!pEapType)
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pEapType is NULL.")));
else if (pEapType->eapType.type != EAPMETHOD_TYPE)
*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->eapType.type, (int)EAPMETHOD_TYPE).c_str(), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->eapType.type, (int)EAPMETHOD_TYPE).c_str()));
else if (pEapType->dwAuthorId != 67532)
*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)pEapType->dwAuthorId, (int)67532).c_str(), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)pEapType->dwAuthorId, (int)67532).c_str()));
else if (!pUIContextData && dwUIContextDataSize)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pUIContextData is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pUIContextData is NULL.")));
else if (!pdwDataFromInteractiveUISize)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pdwDataFromInteractiveUISize is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pdwDataFromInteractiveUISize is NULL.")));
else if (!ppDataFromInteractiveUI)
*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppDataFromInteractiveUI is NULL."), NULL);
g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" ppDataFromInteractiveUI is NULL.")));
else {
// Unpack request.
_EAPMETHOD_PEER_UI::interactive_request_type req;
if (pUIContextData || !dwUIContextDataSize) {
const unsigned char *cursor = pUIContextData;
eapserial::unpack(cursor, req);
assert(cursor - pUIContextData <= (ptrdiff_t)dwUIContextDataSize);
try {
g_peer.invoke_interactive_ui(hwndParent, pUIContextData, dwUIContextDataSize, ppDataFromInteractiveUI, pdwDataFromInteractiveUISize);
} catch (std::exception &err) {
g_peer.log_error(*ppEapError = g_peer.make_error(err));
dwResult = (*ppEapError)->dwWinError;
} catch (...) {
dwResult = ERROR_INVALID_DATA;
}
_EAPMETHOD_PEER_UI::interactive_response_type res;
if (!g_peer.invoke_interactive_ui(hwndParent, req, res, ppEapError))
return dwResult = *ppEapError ? (*ppEapError)->dwWinError : ERROR_INVALID_DATA;
// Allocate BLOB for user data.
assert(ppDataFromInteractiveUI);
assert(pdwDataFromInteractiveUISize);
*pdwDataFromInteractiveUISize = (DWORD)eapserial::get_pk_size(res);
*ppDataFromInteractiveUI = g_peer.alloc_memory(*pdwDataFromInteractiveUISize);
if (!*ppDataFromInteractiveUI) {
*ppEapError = g_peer.make_error(dwResult = ERROR_OUTOFMEMORY, 0, NULL, NULL, NULL, winstd::tstring_printf(_T(__FUNCTION__) _T(" Error allocating memory for interactive response (%uB)."), *pdwDataFromInteractiveUISize).c_str(), NULL);
return dwResult;
}
// Pack BLOB to output.
unsigned char *cursor = *ppDataFromInteractiveUI;
eapserial::pack(cursor, res);
assert(cursor - *ppDataFromInteractiveUI <= (ptrdiff_t)*pdwDataFromInteractiveUISize);
}
return dwResult;

2
EventMonitor/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/temp
/*.user

86
EventMonitor/App.cpp Normal file
View File

@@ -0,0 +1,86 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StdAfx.h"
#if defined(__WXMSW__)
#pragma comment(lib, "msi.lib")
#endif
//////////////////////////////////////////////////////////////////////////
// wxEventMonitorApp
//////////////////////////////////////////////////////////////////////////
wxIMPLEMENT_APP(wxEventMonitorApp);
wxEventMonitorApp::wxEventMonitorApp() : wxApp()
{
}
bool wxEventMonitorApp::OnInit()
{
#if defined(__WXMSW__)
// To compensate migration to non-advertised shortcut, do the Microsoft Installer's feature completeness check manually.
// If execution got this far in the first place (EXE and dependent DLLs are present and loadable).
// Furthermore, this increments program usage counter.
if (::MsiQueryFeatureState(_T(PRODUCT_VERSION_GUID), _T("featEventMonitor")) != INSTALLSTATE_UNKNOWN)
::MsiUseFeature(_T(PRODUCT_VERSION_GUID), _T("featEventMonitor"));
#endif
wxConfigBase *cfgPrev = wxConfigBase::Set(new wxConfig(wxT("EventMonitor"), wxT(PRODUCT_NAME_STR)));
if (cfgPrev) wxDELETE(cfgPrev);
if (!wxApp::OnInit())
return false;
// Set desired locale.
wxLanguage language = (wxLanguage)wxConfigBase::Get()->Read(wxT("Language"), wxLANGUAGE_DEFAULT);
if (wxLocale::IsAvailable(language)) {
wxString sPath;
if (wxConfigBase::Get()->Read(wxT("LocalizationRepositoryPath"), &sPath))
m_locale.AddCatalogLookupPathPrefix(sPath);
if (m_locale.Init(language)) {
wxVERIFY(m_locale.AddCatalog(wxT("wxExtend") wxT(wxExtendVersion)));
wxVERIFY(m_locale.AddCatalog(wxT("EventMonitor")));
}
}
#ifdef __WXMSW__
// Find EventMonitor window if already running.
HWND okno = ::FindWindow(_T("wxWindowNR"), _("Event Monitor"));
if (okno) {
if (::IsIconic(okno))
::SendMessage(okno, WM_SYSCOMMAND, SC_RESTORE, 0);
::SetActiveWindow(okno);
::SetForegroundWindow(okno);
// Not an error condition actually; Just nothing else to do...
return false;
}
#endif
m_mainWnd = new wxEventMonitorFrame();
wxPersistentRegisterAndRestore<wxEventMonitorFrame>(m_mainWnd);
m_mainWnd->Show();
return true;
}

61
EventMonitor/App.h Normal file
View File

@@ -0,0 +1,61 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
///
/// EventMonitor application
///
class wxEventMonitorApp;
#pragma once
#include "Frame.h"
#include <wx/app.h>
#include <wx/config.h>
#include <wx/intl.h>
class wxEventMonitorApp : public wxApp
{
public:
wxEventMonitorApp();
///
/// Called when application initializes.
///
/// \returns
/// - \c true if initialization succeeded
/// - \c false otherwise
///
virtual bool OnInit();
///
/// Called when application uninitializes.
///
/// \returns Result code to return to OS
///
//virtual int OnExit();
public:
wxEventMonitorFrame *m_mainWnd; ///< Main window
wxLocale m_locale; ///< Current locale
};
wxDECLARE_APP(wxEventMonitorApp);

830
EventMonitor/ETWLog.cpp Normal file
View File

@@ -0,0 +1,830 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StdAfx.h"
#pragma comment(lib, "tdh.lib")
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
using namespace winstd;
//////////////////////////////////////////////////////////////////////////
// Local helper functions declarations
//////////////////////////////////////////////////////////////////////////
static tstring MapToString(_In_ const EVENT_MAP_INFO *pMapInfo, _In_ LPCBYTE pData);
static tstring DataToString(_In_ USHORT InType, _In_ USHORT OutType, _In_count_(nDataSize) LPCBYTE pData, _In_ SIZE_T nDataSize, _In_ const EVENT_MAP_INFO *pMapInfo, _In_ BYTE nPtrSize);
static ULONG GetArraySize(PEVENT_RECORD pEvent, PTRACE_EVENT_INFO pInfo, ULONG i, ULONG *pulArraySize);
static tstring PropertyToString(PEVENT_RECORD pEvent, PTRACE_EVENT_INFO pInfo, ULONG ulPropIndex, LPWSTR pStructureName, ULONG ulStructIndex, BYTE nPtrSize);
//////////////////////////////////////////////////////////////////////////
// wxETWEvent
//////////////////////////////////////////////////////////////////////////
const EVENT_RECORD wxETWEvent::s_record_null = {};
wxETWEvent::wxETWEvent(wxEventType type, const EVENT_RECORD &record) :
m_record(record),
wxEvent(0, type)
{
DoSetExtendedData(record.ExtendedDataCount, record.ExtendedData);
DoSetUserData(record.UserDataLength, record.UserData);
}
wxETWEvent::wxETWEvent(const wxETWEvent& event) :
m_record(event.m_record),
wxEvent(event)
{
DoSetExtendedData(event.m_record.ExtendedDataCount, event.m_record.ExtendedData);
DoSetUserData(event.m_record.UserDataLength, event.m_record.UserData);
}
wxETWEvent::~wxETWEvent()
{
if (m_record.ExtendedData)
delete (unsigned char*)m_record.ExtendedData;
if (m_record.UserData)
delete (unsigned char*)m_record.UserData;
}
bool wxETWEvent::SetExtendedData(size_t extended_data_count, const EVENT_HEADER_EXTENDED_DATA_ITEM *extended_data)
{
if (m_record.ExtendedData)
delete (unsigned char*)m_record.ExtendedData;
return DoSetExtendedData(extended_data_count, extended_data);
}
bool wxETWEvent::SetUserData(size_t user_data_length, const void *user_data)
{
if (m_record.UserData)
delete (unsigned char*)m_record.UserData;
return DoSetUserData(user_data_length, user_data);
}
bool wxETWEvent::DoSetExtendedData(size_t extended_data_count, const EVENT_HEADER_EXTENDED_DATA_ITEM *extended_data)
{
if (extended_data_count) {
wxASSERT_MSG(extended_data, wxT("extended data is NULL"));
// Count the total required memory.
size_t data_size = 0;
for (size_t i = 0; i < extended_data_count; i++)
data_size += extended_data[i].DataSize;
// Allocate memory for extended data.
m_record.ExtendedData = (EVENT_HEADER_EXTENDED_DATA_ITEM*)(new unsigned char[sizeof(EVENT_HEADER_EXTENDED_DATA_ITEM)*extended_data_count + data_size]);
wxCHECK_MSG(m_record.ExtendedData, false, wxT("extended data memory allocation failed"));
// Bulk-copy extended data descriptors.
memcpy(m_record.ExtendedData, extended_data, sizeof(EVENT_HEADER_EXTENDED_DATA_ITEM) * extended_data_count);
// Copy the data.
unsigned char *ptr = (unsigned char*)(m_record.ExtendedData + extended_data_count);
for (size_t i = 0; i < extended_data_count; i++) {
if (extended_data[i].DataSize) {
memcpy(ptr, (void*)(extended_data[i].DataPtr), extended_data[i].DataSize);
m_record.ExtendedData[i].DataPtr = (ULONGLONG)ptr;
ptr += extended_data[i].DataSize;
} else
m_record.ExtendedData[i].DataPtr = NULL;
}
} else
m_record.ExtendedData = NULL;
m_record.ExtendedDataCount = extended_data_count;
return true;
}
bool wxETWEvent::DoSetUserData(size_t user_data_length, const void *user_data)
{
if (user_data_length) {
wxASSERT_MSG(user_data, wxT("user data is NULL"));
// Allocate memory for user data.
m_record.UserData = new unsigned char[user_data_length];
wxCHECK_MSG(m_record.UserData, false, wxT("user data memory allocation failed"));
// Copy user data.
memcpy(m_record.UserData, user_data, user_data_length);
} else
m_record.UserData = NULL;
m_record.UserDataLength = user_data_length;
return true;
}
IMPLEMENT_DYNAMIC_CLASS(wxETWEvent, wxEvent)
wxDEFINE_EVENT(wxEVT_ETW_EVENT, wxETWEvent);
//////////////////////////////////////////////////////////////////////////
// wxEventTraceProcessorThread
//////////////////////////////////////////////////////////////////////////
wxEventTraceProcessorThread::wxEventTraceProcessorThread(wxEvtHandler *parent, const wxArrayString &sessions) :
m_parent(parent),
wxThread(wxTHREAD_JOINABLE)
{
EVENT_TRACE_LOGFILE tlf = {};
tlf.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD;
tlf.EventRecordCallback = EventRecordCallback;
tlf.Context = this;
for (size_t i = 0, i_end = sessions.GetCount(); i < i_end; i++) {
// Open trace.
tlf.LoggerName = (LPTSTR)(LPCTSTR)(sessions[i]);
event_trace trace;
if (!trace.create(&tlf)) {
wxLogError(_("Error opening event trace (error %u)."), GetLastError());
continue;
}
// Save trace to the table.
m_traces.push_back(trace.detach());
}
}
wxEventTraceProcessorThread::~wxEventTraceProcessorThread()
{
for (vector<TRACEHANDLE>::iterator trace = m_traces.begin(), trace_end = m_traces.end(); trace != trace_end; ++trace) {
TRACEHANDLE &h = *trace;
if (h) {
// Close trace.
CloseTrace(h);
}
}
}
void wxEventTraceProcessorThread::Abort()
{
for (vector<TRACEHANDLE>::iterator trace = m_traces.begin(), trace_end = m_traces.end(); trace != trace_end; ++trace) {
TRACEHANDLE &h = *trace;
if (h) {
// Close trace.
CloseTrace(h);
h = NULL;
}
}
}
wxThread::ExitCode wxEventTraceProcessorThread::Entry()
{
// Process events.
ProcessTrace(m_traces.data(), (ULONG)m_traces.size(), NULL, NULL);
return 0;
}
VOID WINAPI wxEventTraceProcessorThread::EventRecordCallback(_In_ PEVENT_RECORD pEvent)
{
wxASSERT_MSG(pEvent, wxT("event is NULL"));
wxASSERT_MSG(pEvent->UserContext, wxT("thread is NULL"));
wxEventTraceProcessorThread *_this = ((wxEventTraceProcessorThread*)pEvent->UserContext);
if (_this->TestDestroy()) {
// Event processing is pending destruction.
return;
}
_this->m_parent->QueueEvent(new wxETWEvent(wxEVT_ETW_EVENT, *pEvent));
}
//////////////////////////////////////////////////////////////////////////
// wxETWListCtrl
//////////////////////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE(wxETWListCtrl, wxListCtrl)
EVT_ETW_EVENT(wxETWListCtrl::OnETWEvent)
END_EVENT_TABLE()
// {6EB8DB94-FE96-443F-A366-5FE0CEE7FB1C}
const GUID wxETWListCtrl::s_provider_eaphost = { 0X6EB8DB94, 0XFE96, 0X443F, { 0XA3, 0X66, 0X5F, 0XE0, 0XCE, 0XE7, 0XFB, 0X1C } };
wxETWListCtrl::wxETWListCtrl(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name) :
m_proc(NULL),
m_item_id(0),
wxListCtrl(parent, id, pos, size, style, validator, name)
{
this->AppendColumn(_("Time" ), wxLIST_FORMAT_LEFT, 100);
this->AppendColumn(_("PID" ), wxLIST_FORMAT_LEFT, 50 );
this->AppendColumn(_("TID" ), wxLIST_FORMAT_LEFT, 50 );
this->AppendColumn(_("Source"), wxLIST_FORMAT_LEFT, 100);
this->AppendColumn(_("Event" ), wxLIST_FORMAT_LEFT, wxLIST_AUTOSIZE_USEHEADER);
// Start a new session.
ULONG ulResult;
for (unsigned int i = 0; ; i++) {
//tstring log_file(tstring_printf(i ? _T("test.etl") : _T("test %u.etl"), i));
tstring name(tstring_printf(i ? _T(PRODUCT_NAME_STR) _T(" Event Monitor Session %u") : _T(PRODUCT_NAME_STR) _T(" Event Monitor Session"), i));
// Allocate session properties.
ULONG
ulSizeName = (ULONG)((name .length() + 1)*sizeof(TCHAR)),
//ulSizeLogFile = (ULONG)((log_file.length() + 1)*sizeof(TCHAR)),
ulSize = sizeof(EVENT_TRACE_PROPERTIES) + ulSizeName /*+ ulSizeLogFile*/;
unique_ptr<EVENT_TRACE_PROPERTIES> properties((EVENT_TRACE_PROPERTIES*)new char[ulSize]);
wxASSERT_MSG(properties, wxT("error allocating session properties memory"));
// Initialize properties.
memset(properties.get(), 0, sizeof(EVENT_TRACE_PROPERTIES));
properties->Wnode.BufferSize = ulSize;
properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
properties->Wnode.ClientContext = 1; //QPC clock resolution
CoCreateGuid(&(properties->Wnode.Guid));
properties->LogFileMode = /*EVENT_TRACE_FILE_MODE_SEQUENTIAL |*/ EVENT_TRACE_REAL_TIME_MODE;
properties->MaximumFileSize = 1; // 1 MB
properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
//properties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + ulSizeName;
//memcpy((LPTSTR)((char*)properties.get() + properties->LogFileNameOffset), log_file.c_str(), ulSizeLogFile);
if ((ulResult = m_session.create(name.c_str(), properties.get())) == ERROR_SUCCESS) {
break;
} else if (ulResult == ERROR_ACCESS_DENIED) {
wxLogError(_("Access denied creating event session: you need administrative privileges (Run As Administrator) or be a member of Performance Log Users group to start event tracing session."));
return;
} else if (ulResult == ERROR_ALREADY_EXISTS) {
wxLogDebug(_("The %s event session already exists."), name.c_str());
// Do not despair... Retry with a new session name and ID.
continue;
} else {
wxLogError(_("Error creating event session (error %u)."), ulResult);
return;
}
}
// Enable event providers we are interested in to log events to our session.
if ((ulResult = EnableTraceEx(
&EAPMETHOD_TRACE_EVENT_PROVIDER,
&((const EVENT_TRACE_PROPERTIES*)m_session)->Wnode.Guid,
m_session,
EVENT_CONTROL_CODE_ENABLE_PROVIDER,
TRACE_LEVEL_VERBOSE,
0, 0,
0,
NULL)) != ERROR_SUCCESS)
{
wxLogError(_("Error enabling event provider (error %u)."), ulResult);
return;
}
if ((ulResult = EnableTraceEx(
&s_provider_eaphost,
&((const EVENT_TRACE_PROPERTIES*)m_session)->Wnode.Guid,
m_session,
EVENT_CONTROL_CODE_ENABLE_PROVIDER,
TRACE_LEVEL_VERBOSE,
0, 0,
0,
NULL)) != ERROR_SUCCESS)
{
// If the EAPHost trace provider failed to enable, do not despair.
wxLogDebug(_("Error enabling EAPHost event provider (error %u)."), ulResult);
}
// Process events in separate thread, not to block wxWidgets' message pump.
wxArrayString sessions;
sessions.Add(m_session.name());
m_proc = new wxEventTraceProcessorThread(this->GetEventHandler(), sessions);
wxASSERT_MSG(m_proc, wxT("error allocating thread memory"));
if (m_proc->Run() != wxTHREAD_NO_ERROR) {
wxFAIL_MSG("Can't create the thread!");
delete m_proc;
m_proc = NULL;
}
}
wxETWListCtrl::~wxETWListCtrl()
{
if (m_session) {
if (m_proc) {
m_proc->Abort();
m_proc->Delete();
delete m_proc;
}
// Disable event providers.
EnableTraceEx(
&s_provider_eaphost,
&((const EVENT_TRACE_PROPERTIES*)m_session)->Wnode.Guid,
m_session,
EVENT_CONTROL_CODE_DISABLE_PROVIDER,
TRACE_LEVEL_VERBOSE,
0, 0,
0,
NULL);
EnableTraceEx(
&EAPMETHOD_TRACE_EVENT_PROVIDER,
&((const EVENT_TRACE_PROPERTIES*)m_session)->Wnode.Guid,
m_session,
EVENT_CONTROL_CODE_DISABLE_PROVIDER,
TRACE_LEVEL_VERBOSE,
0, 0,
0,
NULL);
}
}
void wxETWListCtrl::OnETWEvent(wxETWEvent& event)
{
EVENT_RECORD &rec = event.GetRecord();
bool is_ours = IsEqualGUID(rec.EventHeader.ProviderId, EAPMETHOD_TRACE_EVENT_PROVIDER) ? true : false;
int column = 0;
// Prepare item to insert into the list.
wxListItem item;
item.SetId(m_item_id++);
item.SetTextColour(
rec.EventHeader.EventDescriptor.Level >= TRACE_LEVEL_VERBOSE ? (is_ours ? 0x666666 : 0xcccccc) :
rec.EventHeader.EventDescriptor.Level >= TRACE_LEVEL_INFORMATION ? (is_ours ? 0x000000 : 0xaaaaaa) :
rec.EventHeader.EventDescriptor.Level >= TRACE_LEVEL_WARNING ? (is_ours ? 0x00aacc : 0xaaeeee) :
(is_ours ? 0x0000ff : 0xaaaaff));
item.SetBackgroundColour(0xffffff);
{
// Output event time-stamp.
FILETIME ft;
ft.dwHighDateTime = rec.EventHeader.TimeStamp.HighPart;
ft.dwLowDateTime = rec.EventHeader.TimeStamp.LowPart;
SYSTEMTIME st, st_local;
FileTimeToSystemTime(&ft, &st);
SystemTimeToTzSpecificLocalTime(NULL, &st, &st_local);
ULONGLONG
ts = rec.EventHeader.TimeStamp.QuadPart,
nanosec = (ts % 10000000) * 100;
item.SetColumn(column++);
item.SetText(tstring_printf(_T("%04d-%02d-%02d %02d:%02d:%02d.%09I64u"),
st_local.wYear, st_local.wMonth, st_local.wDay, st_local.wHour, st_local.wMinute, st_local.wSecond, nanosec));
this->InsertItem(item);
}
// Output process ID.
item.SetColumn(column++);
item.SetText(wxString::Format(wxT("%u"), rec.EventHeader.ProcessId));
this->SetItem(item);
// Output thread ID.
item.SetColumn(column++);
item.SetText(wxString::Format(wxT("%u"), rec.EventHeader.ThreadId));
this->SetItem(item);
// Output event source.
item.SetColumn(column++);
item.SetText(is_ours ? wxT(PRODUCT_NAME_STR) : wxT("EAPHost"));
this->SetItem(item);
item.SetColumn(column++);
{
// Get event meta-info.
unique_ptr<TRACE_EVENT_INFO> info;
ULONG ulResult;
if ((ulResult = TdhGetEventInformation(&rec, 0, NULL, info)) == ERROR_SUCCESS) {
if (info->DecodingSource != DecodingSourceWPP) {
if (rec.EventHeader.Flags & EVENT_HEADER_FLAG_STRING_ONLY) {
// This is a string-only event. Print it.
item.SetText((LPCWSTR)rec.UserData);
} else {
// This is not a string-only event. Prepare parameters.
BYTE nPtrSize = (rec.EventHeader.Flags & EVENT_HEADER_FLAG_32_BIT_HEADER) ? 4 : 8;
vector<tstring> props;
vector<DWORD_PTR> props_msg;
props.reserve(info->TopLevelPropertyCount);
props_msg.reserve(info->TopLevelPropertyCount);
for (ULONG i = 0; i < info->TopLevelPropertyCount; i++) {
props.push_back(std::move(PropertyToString(&rec, info.get(), i, NULL, 0, nPtrSize)));
props_msg.push_back((DWORD_PTR)props[i].c_str());
}
if (info->EventMessageOffset) {
// Format the message.
item.SetText(wstring_msg(0, (LPCTSTR)((LPCBYTE)info.get() + info->EventMessageOffset), props_msg.data()).c_str());
}
}
} else if (info->EventMessageOffset) {
// This is a WPP event.
item.SetText((LPCWSTR)((LPCBYTE)info.get() + info->EventMessageOffset));
}
}
}
this->SetItem(item);
// Bring the record into view.
this->EnsureVisible(item.GetId());
}
//////////////////////////////////////////////////////////////////////////
// Local helper functions
//////////////////////////////////////////////////////////////////////////
static tstring MapToString(_In_ const EVENT_MAP_INFO *pMapInfo, _In_ LPCBYTE pData)
{
if ( (pMapInfo->Flag & EVENTMAP_INFO_FLAG_MANIFEST_VALUEMAP) ||
((pMapInfo->Flag & EVENTMAP_INFO_FLAG_WBEM_VALUEMAP ) && (pMapInfo->Flag & ~EVENTMAP_INFO_FLAG_WBEM_VALUEMAP) != EVENTMAP_INFO_FLAG_WBEM_FLAG))
{
if ((pMapInfo->Flag & EVENTMAP_INFO_FLAG_WBEM_NO_MAP) == EVENTMAP_INFO_FLAG_WBEM_NO_MAP)
return tstring_printf(_T("%ls"), (PBYTE)pMapInfo + pMapInfo->MapEntryArray[*(PULONG)pData].OutputOffset);
else {
for (ULONG i = 0; ; i++) {
if (i >= pMapInfo->EntryCount)
return tstring_printf(_T("%lu"), *(PULONG)pData);
else if (pMapInfo->MapEntryArray[i].Value == *(PULONG)pData)
return tstring_printf(_T("%ls"), (PBYTE)pMapInfo + pMapInfo->MapEntryArray[i].OutputOffset);
}
}
} else if (
(pMapInfo->Flag & EVENTMAP_INFO_FLAG_MANIFEST_BITMAP) ||
(pMapInfo->Flag & EVENTMAP_INFO_FLAG_WBEM_BITMAP ) ||
((pMapInfo->Flag & EVENTMAP_INFO_FLAG_WBEM_VALUEMAP ) && (pMapInfo->Flag & ~EVENTMAP_INFO_FLAG_WBEM_VALUEMAP) == EVENTMAP_INFO_FLAG_WBEM_FLAG))
{
tstring out;
if (pMapInfo->Flag & EVENTMAP_INFO_FLAG_WBEM_NO_MAP) {
for (ULONG i = 0; i < pMapInfo->EntryCount; i++)
if (*(PULONG)pData & (1 << i))
out.append(tstring_printf(out.empty() ? _T("%ls") : _T(" | %ls"), (PBYTE)pMapInfo + pMapInfo->MapEntryArray[i].OutputOffset));
} else {
for (ULONG i = 0; i < pMapInfo->EntryCount; i++)
if ((pMapInfo->MapEntryArray[i].Value & *(PULONG)pData) == pMapInfo->MapEntryArray[i].Value)
out.append(tstring_printf(out.empty() ? _T("%ls") : _T(" | %ls"), (PBYTE)pMapInfo + pMapInfo->MapEntryArray[i].OutputOffset));
}
return out.empty() ? tstring_printf(_T("%lu"), *(PULONG)pData) : out;
}
return _T("<unknown map>");
}
static tstring DataToString(_In_ USHORT InType, _In_ USHORT OutType, _In_count_(nDataSize) LPCBYTE pData, _In_ SIZE_T nDataSize, _In_ const EVENT_MAP_INFO *pMapInfo, _In_ BYTE nPtrSize)
{
assert(pData || !nDataSize);
switch (InType) {
case TDH_INTYPE_UNICODESTRING:
case TDH_INTYPE_NONNULLTERMINATEDSTRING:
case TDH_INTYPE_UNICODECHAR:
return tstring_printf(_T("%.*ls"), nDataSize/sizeof(WCHAR), pData);
case TDH_INTYPE_ANSISTRING:
case TDH_INTYPE_NONNULLTERMINATEDANSISTRING:
case TDH_INTYPE_ANSICHAR: {
// Convert strings from ANSI code page, all others (JSON, XML etc.) from UTF-8
wstring str;
MultiByteToWideChar(OutType == TDH_OUTTYPE_STRING ? CP_ACP : CP_UTF8, 0, (LPCSTR)pData, (int)nDataSize, str);
return tstring_printf(_T("%ls"), str.c_str());
}
case TDH_INTYPE_COUNTEDSTRING:
return DataToString(TDH_INTYPE_NONNULLTERMINATEDSTRING, OutType, (LPCBYTE)((PUSHORT)pData + 1), *(PUSHORT)pData, pMapInfo, nPtrSize);
case TDH_INTYPE_COUNTEDANSISTRING:
return DataToString(TDH_INTYPE_NONNULLTERMINATEDANSISTRING, OutType, (LPCBYTE)((PUSHORT)pData + 1), *(PUSHORT)pData, pMapInfo, nPtrSize);
case TDH_INTYPE_REVERSEDCOUNTEDSTRING:
return DataToString(TDH_INTYPE_NONNULLTERMINATEDSTRING, OutType, (LPCBYTE)((PUSHORT)pData + 1), MAKEWORD(HIBYTE(*(PUSHORT)pData), LOBYTE(*(PUSHORT)pData)), pMapInfo, nPtrSize);
case TDH_INTYPE_REVERSEDCOUNTEDANSISTRING:
return DataToString(TDH_INTYPE_NONNULLTERMINATEDANSISTRING, OutType, (LPCBYTE)((PUSHORT)pData + 1), MAKEWORD(HIBYTE(*(PUSHORT)pData), LOBYTE(*(PUSHORT)pData)), pMapInfo, nPtrSize);
case TDH_INTYPE_INT8:
assert(nDataSize >= sizeof(CHAR));
switch (OutType) {
case TDH_OUTTYPE_STRING: return DataToString(TDH_INTYPE_ANSICHAR, TDH_OUTTYPE_NULL, pData, nDataSize, pMapInfo, nPtrSize);
default : return tstring_printf(_T("%hd"), *(PCHAR)pData);
}
case TDH_INTYPE_UINT8:
assert(nDataSize >= sizeof(BYTE));
switch (OutType) {
case TDH_OUTTYPE_STRING : return DataToString(TDH_INTYPE_ANSICHAR, TDH_OUTTYPE_NULL, pData, nDataSize, pMapInfo, nPtrSize);
case TDH_OUTTYPE_HEXINT8: return tstring_printf(_T("0x%x"), *(PBYTE)pData);
default : return tstring_printf(_T("%hu" ), *(PBYTE)pData);
}
case TDH_INTYPE_INT16:
assert(nDataSize >= sizeof(SHORT));
return tstring_printf(_T("%hd"), *(PSHORT)pData);
case TDH_INTYPE_UINT16:
assert(nDataSize >= sizeof(USHORT));
switch (OutType) {
case TDH_OUTTYPE_PORT : return tstring_printf(_T("%hu" ), ntohs(*(PUSHORT)pData));
case TDH_OUTTYPE_HEXINT16: return tstring_printf(_T("0x%x"), *(PUSHORT)pData );
case TDH_OUTTYPE_STRING : return tstring_printf(_T("%lc" ), *(PUSHORT)pData );
default : return tstring_printf(_T("%hu" ), *(PUSHORT)pData );
}
case TDH_INTYPE_INT32:
assert(nDataSize >= sizeof(LONG));
switch (OutType) {
case TDH_OUTTYPE_HRESULT: return tstring_printf(_T("0x%x"), *(PLONG)pData);
default : return tstring_printf(_T("%ld" ), *(PLONG)pData);
}
case TDH_INTYPE_UINT32:
assert(nDataSize >= sizeof(ULONG));
switch (OutType) {
case TDH_OUTTYPE_HRESULT :
case TDH_OUTTYPE_WIN32ERROR:
case TDH_OUTTYPE_NTSTATUS :
case TDH_OUTTYPE_HEXINT32 : return tstring_printf(_T("0x%x" ), *(PULONG)pData);
case TDH_OUTTYPE_IPV4 : return tstring_printf(_T("%d.%d.%d.%d"), (*(PULONG)pData >> 0) & 0xff, (*(PULONG)pData >> 8) & 0xff, (*(PULONG)pData >> 16) & 0xff, (*(PULONG)pData >> 24) & 0xff);
default: return pMapInfo ? MapToString(pMapInfo, pData) : tstring_printf(_T("%lu"), *(PULONG)pData);
}
case TDH_INTYPE_HEXINT32:
return DataToString(TDH_INTYPE_UINT32, TDH_OUTTYPE_HEXINT32, pData, nDataSize, pMapInfo, nPtrSize);
case TDH_INTYPE_INT64:
assert(nDataSize >= sizeof(LONGLONG));
return tstring_printf(_T("%I64d"), *(PLONGLONG)pData);
case TDH_INTYPE_UINT64:
assert(nDataSize >= sizeof(ULONGLONG));
switch (OutType) {
case TDH_OUTTYPE_HEXINT64: return tstring_printf(_T("0x%I64x"), *(PULONGLONG)pData);
default : return tstring_printf(_T("%I64u" ), *(PULONGLONG)pData);
}
case TDH_INTYPE_HEXINT64:
return DataToString(TDH_INTYPE_UINT64, TDH_OUTTYPE_HEXINT64, pData, nDataSize, pMapInfo, nPtrSize);
case TDH_INTYPE_FLOAT:
assert(nDataSize >= sizeof(FLOAT));
return tstring_printf(_T("%f"), *(PFLOAT)pData);
case TDH_INTYPE_DOUBLE:
assert(nDataSize >= sizeof(DOUBLE));
return tstring_printf(_T("%I64f"), *(DOUBLE*)pData);
case TDH_INTYPE_BOOLEAN:
assert(nDataSize >= sizeof(ULONG)); // Yes, boolean is really 32-bit.
return *(PULONG)pData ? _T("true") : _T("false");
case TDH_INTYPE_BINARY:
switch (OutType) {
case TDH_OUTTYPE_IPV6: {
auto RtlIpv6AddressToString = (LPTSTR(NTAPI*)(const IN6_ADDR*, LPTSTR))GetProcAddress(GetModuleHandle(_T("ntdll.dll")),
#ifdef _UNICODE
"RtlIpv6AddressToStringW"
#else
"RtlIpv6AddressToStringA"
#endif
);
if (RtlIpv6AddressToString) {
TCHAR szIPv6Addr[47];
RtlIpv6AddressToString((IN6_ADDR*)pData, szIPv6Addr);
return tstring_printf(_T("%s"), szIPv6Addr);
} else
return _T("<IPv6 address>");
}
default: {
tstring out;
for (SIZE_T i = 0; i < nDataSize; i++)
out.append(tstring_printf(i ? _T(" %02x") : _T("%02x"), pData[i]));
return out;
}}
case TDH_INTYPE_HEXDUMP:
return DataToString(TDH_INTYPE_BINARY, TDH_OUTTYPE_NULL, pData, nDataSize, pMapInfo, nPtrSize);
case TDH_INTYPE_GUID: {
assert(nDataSize >= sizeof(GUID));
WCHAR szGuid[39];
StringFromGUID2(*(GUID*)pData, szGuid, _countof(szGuid));
return tstring_printf(_T("%ls"), szGuid);
}
case TDH_INTYPE_POINTER:
assert(nDataSize >= nPtrSize);
switch (nPtrSize) {
case sizeof(ULONG ): return tstring_printf(_T("0x%08x" ), *(PULONG )pData);
case sizeof(ULONGLONG): return tstring_printf(_T("0x%016I64x"), *(PULONGLONG)pData);
default: // Unsupported pointer size.
assert(0);
return _T("<pointer>");
}
case TDH_INTYPE_SIZET:
assert(nDataSize >= nPtrSize);
switch (nPtrSize) {
case sizeof(ULONG ): return tstring_printf(_T("%u" ), *(PULONG )pData);
case sizeof(ULONGLONG): return tstring_printf(_T("%I64u"), *(PULONGLONG)pData);
default: // Unsupported size_t size.
assert(0);
return _T("<size_t>");
}
case TDH_INTYPE_FILETIME: {
assert(nDataSize >= sizeof(FILETIME));
SYSTEMTIME st, st_local;
FileTimeToSystemTime((PFILETIME)pData, &st);
SystemTimeToTzSpecificLocalTime(NULL, &st, &st_local);
return DataToString(TDH_INTYPE_SYSTEMTIME, OutType, (LPCBYTE)&st_local, sizeof(st_local), pMapInfo, nPtrSize);
}
case TDH_INTYPE_SYSTEMTIME:
assert(nDataSize >= sizeof(SYSTEMTIME));
switch (OutType) {
case TDH_OUTTYPE_CULTURE_INSENSITIVE_DATETIME: return tstring_printf(_T("%04d-%02d-%02d %02d:%02d:%02d.%03u"), ((PSYSTEMTIME)pData)->wYear, ((PSYSTEMTIME)pData)->wMonth, ((PSYSTEMTIME)pData)->wDay, ((PSYSTEMTIME)pData)->wHour, ((PSYSTEMTIME)pData)->wMinute, ((PSYSTEMTIME)pData)->wSecond, ((PSYSTEMTIME)pData)->wMilliseconds);
default: {
tstring out;
return GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, (PSYSTEMTIME)pData, NULL, out) ? out : tstring(_T("<time>"));
}}
case TDH_INTYPE_WBEMSID:
// A WBEM SID is actually a TOKEN_USER structure followed
// by the SID. The size of the TOKEN_USER structure differs
// depending on whether the events were generated on a 32-bit
// or 64-bit architecture. Also the structure is aligned
// on an 8-byte boundary, so its size is 8 bytes on a
// 32-bit computer and 16 bytes on a 64-bit computer.
// Doubling the pointer size handles both cases.
assert(nDataSize >= (SIZE_T)nPtrSize * 2);
return (PULONG)pData > 0 ? DataToString(TDH_INTYPE_SID, OutType, pData + nPtrSize * 2, nDataSize - nPtrSize * 2, pMapInfo, nPtrSize) : _T("<WBEM SID>");
case TDH_INTYPE_SID: {
assert(nDataSize >= sizeof(SID));
tstring user_name, domain_name;
SID_NAME_USE eNameUse;
if (LookupAccountSid(NULL, (PSID)pData, &user_name, &domain_name, &eNameUse))
return tstring_printf(_T("%s\\%s"), domain_name.c_str(), user_name.c_str());
else {
unique_ptr<TCHAR[], LocalFree_delete<TCHAR[]> > sid;
if (GetLastError() == ERROR_NONE_MAPPED &&
ConvertSidToStringSid((PSID)pData, (LPTSTR*)&sid))
return tstring_printf(_T("%s"), sid.get());
else
return _T("<SID>");
}
}
default:
// It is not actually an error if we do not understand the given data type.
assert(0);
return _T("<unknown data type>");
}
}
static ULONG GetArraySize(PEVENT_RECORD pEvent, PTRACE_EVENT_INFO pInfo, ULONG i, ULONG *pulArraySize)
{
if (pInfo->EventPropertyInfoArray[i].Flags & PropertyParamCount) {
ULONG ulResult;
// Get array count property.
PROPERTY_DATA_DESCRIPTOR data_desc = { (ULONGLONG)((LPBYTE)pInfo + pInfo->EventPropertyInfoArray[pInfo->EventPropertyInfoArray[i].countPropertyIndex].NameOffset), ULONG_MAX };
vector<unsigned char> count;
if ((ulResult = TdhGetProperty(pEvent, 0, NULL, 1, &data_desc, count)) != ERROR_SUCCESS)
return ulResult;
// Copy count value to output.
switch (count.size()) {
case sizeof(BYTE ): *pulArraySize = *(const BYTE* )count.data(); break;
case sizeof(USHORT): *pulArraySize = *(const USHORT*)count.data(); break;
case sizeof(ULONG ): *pulArraySize = *(const ULONG* )count.data(); break;
default : return ERROR_MORE_DATA;
}
} else
*pulArraySize = pInfo->EventPropertyInfoArray[i].count;
return ERROR_SUCCESS;
}
static tstring PropertyToString(PEVENT_RECORD pEvent, PTRACE_EVENT_INFO pInfo, ULONG ulPropIndex, LPWSTR pStructureName, ULONG ulStructIndex, BYTE nPtrSize)
{
ULONG ulResult;
// Get the size of the array if the property is an array.
ULONG ulArraySize = 0;
if ((ulResult = GetArraySize(pEvent, pInfo, ulPropIndex, &ulArraySize)) != ERROR_SUCCESS)
return tstring_printf(_T("<Error getting array size (error %u)>"), ulResult);;
tstring out;
bool out_nonfirst = false;
if (pInfo->EventPropertyInfoArray[ulPropIndex].Flags & PropertyParamCount)
out += tstring_printf(_T("[%u]("), ulArraySize);
for (ULONG k = 0; k < ulArraySize; k++) {
if (pInfo->EventPropertyInfoArray[ulPropIndex].Flags & PropertyStruct) {
// The property is a structure: print the members of the structure.
if (out_nonfirst) out += _T(", "); else out_nonfirst = true;
out += _T('(');
for (USHORT j = pInfo->EventPropertyInfoArray[ulPropIndex].structType.StructStartIndex, usLastMember = pInfo->EventPropertyInfoArray[ulPropIndex].structType.StructStartIndex + pInfo->EventPropertyInfoArray[ulPropIndex].structType.NumOfStructMembers; j < usLastMember; j++) {
out += tstring_printf(_T("%ls: "), (LPBYTE)pInfo + pInfo->EventPropertyInfoArray[j].NameOffset);
out += PropertyToString(pEvent, pInfo, j, (LPWSTR)((LPBYTE)(pInfo) + pInfo->EventPropertyInfoArray[ulPropIndex].NameOffset), k, nPtrSize);
}
out += _T(')');
} else {
if (pInfo->EventPropertyInfoArray[ulPropIndex].nonStructType.InType == TDH_INTYPE_BINARY &&
pInfo->EventPropertyInfoArray[ulPropIndex].nonStructType.OutType == TDH_OUTTYPE_IPV6)
{
// The TDH API does not support IPv6 addresses. If the output type is TDH_OUTTYPE_IPV6,
// you will not be able to consume the rest of the event. If you try to consume the
// remainder of the event, you will get ERROR_EVT_INVALID_EVENT_DATA.
return _T("<The event contains an IPv6 address. Skipping.>");
} else {
vector<BYTE> data;
if (pStructureName) {
// To retrieve a member of a structure, you need to specify an array of descriptors.
// The first descriptor in the array identifies the name of the structure and the second
// descriptor defines the member of the structure whose data you want to retrieve.
PROPERTY_DATA_DESCRIPTOR data_desc[2] = {
{ (ULONGLONG)pStructureName , ulStructIndex },
{ (ULONGLONG)((LPBYTE)pInfo + pInfo->EventPropertyInfoArray[ulPropIndex].NameOffset), k }
};
ulResult = TdhGetProperty(pEvent, 0, NULL, _countof(data_desc), data_desc, data);
} else {
PROPERTY_DATA_DESCRIPTOR data_desc = { (ULONGLONG)((LPBYTE)pInfo + pInfo->EventPropertyInfoArray[ulPropIndex].NameOffset), k };
ulResult = TdhGetProperty(pEvent, 0, NULL, 1, &data_desc, data);
}
if (ulResult == ERROR_EVT_INVALID_EVENT_DATA) {
// This happens with empty/NULL data. Not an error actually.
assert(data.empty());
} else if (ulResult != ERROR_SUCCESS)
return tstring_printf(_T("<Error getting property (error %u)>"), ulResult);
// Get the name/value mapping if the property specifies a value map.
unique_ptr<EVENT_MAP_INFO> map_info;
ulResult = TdhGetEventMapInformation(pEvent, (LPWSTR)((LPBYTE)pInfo + pInfo->EventPropertyInfoArray[ulPropIndex].nonStructType.MapNameOffset), map_info);
if (ulResult == ERROR_NOT_FOUND) {
// name/value mapping not found. Not an error actually.
assert(!map_info);
} else if (ulResult != ERROR_SUCCESS)
return tstring_printf(_T("<Error getting map information (error %u)>"), ulResult);
else if (pInfo->DecodingSource == DecodingSourceXMLFile) {
// The mapped string values defined in a manifest will contain a trailing space
// in the EVENT_MAP_ENTRY structure. Replace the trailing space with a null-
// terminating character, so that the bit mapped strings are correctly formatted.
for (ULONG i = 0; i < map_info->EntryCount; i++) {
SIZE_T len = _tcslen((LPCTSTR)((PBYTE)map_info.get() + map_info->MapEntryArray[i].OutputOffset)) - 1;
((LPWSTR)((PBYTE)map_info.get() + map_info->MapEntryArray[i].OutputOffset))[len] = 0;
}
}
if (out_nonfirst) out += _T(", "); else out_nonfirst = true;
out += !data.empty() ? DataToString(
pInfo->EventPropertyInfoArray[ulPropIndex].nonStructType.InType,
pInfo->EventPropertyInfoArray[ulPropIndex].nonStructType.OutType,
data.data(),
data.size(),
map_info.get(),
nPtrSize) : _T("<null>");
}
}
}
if (pInfo->EventPropertyInfoArray[ulPropIndex].Flags & PropertyParamCount)
out += _T(')');
return out;
}

136
EventMonitor/ETWLog.h Normal file
View File

@@ -0,0 +1,136 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include <wx/event.h>
///
/// ETW event
///
class wxETWEvent;
wxDECLARE_EVENT(wxEVT_ETW_EVENT, wxETWEvent);
#define wxETWEventHandler(func) wxEVENT_HANDLER_CAST(wxETWEventFunction, func)
#define EVT_ETW_EVENT(func) wx__DECLARE_EVT0(wxEVT_ETW_EVENT, wxETWEventHandler(func))
///
/// Event list control
///
class wxETWListCtrl;
///
/// Event trace processor
///
class wxEventTraceProcessorThread;
#pragma once
#include <wx/listctrl.h>
#include <wx/thread.h>
#include <WinStd/ETW.h>
#include <vector>
class wxETWEvent : public wxEvent
{
public:
wxETWEvent(wxEventType type = wxEVT_NULL, const EVENT_RECORD &record = s_record_null);
wxETWEvent(const wxETWEvent& event);
virtual ~wxETWEvent();
virtual wxEvent *Clone() const { return new wxETWEvent(*this); }
inline const EVENT_RECORD& GetRecord() const { return m_record; }
inline EVENT_RECORD& GetRecord() { return m_record; }
inline const EVENT_HEADER& GetHeader() const { return m_record.EventHeader; }
inline const ETW_BUFFER_CONTEXT& GetBufferContext() const { return m_record.BufferContext; }
bool SetExtendedData(size_t extended_data_count, const EVENT_HEADER_EXTENDED_DATA_ITEM *extended_data);
inline size_t GetExtendedDataCount() const { return m_record.ExtendedDataCount; }
inline const EVENT_HEADER_EXTENDED_DATA_ITEM& GetExtendedData(size_t index) const { wxASSERT(index < m_record.ExtendedDataCount); return m_record.ExtendedData[index]; }
bool SetUserData(size_t user_data_length, const void *user_data);
inline size_t GetUserDataLength() const { return m_record.UserDataLength; }
inline void *GetUserData() const { return m_record.UserData; }
protected:
bool DoSetExtendedData(size_t extended_data_count, const EVENT_HEADER_EXTENDED_DATA_ITEM *extended_data);
bool DoSetUserData(size_t user_data_length, const void *user_data);
private:
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxETWEvent)
public:
static const EVENT_RECORD s_record_null;
protected:
EVENT_RECORD m_record; ///< ETW event record
};
typedef void (wxEvtHandler::*wxETWEventFunction)(wxETWEvent&);
class wxEventTraceProcessorThread : public wxThread
{
public:
wxEventTraceProcessorThread(wxEvtHandler *parent, const wxArrayString &sessions);
virtual ~wxEventTraceProcessorThread();
void Abort();
protected:
virtual ExitCode Entry();
private:
static VOID WINAPI EventRecordCallback(PEVENT_RECORD pEvent);
protected:
std::vector<TRACEHANDLE> m_traces; ///< An array of tracing sessions this thread is monitoring
wxEvtHandler *m_parent; ///< Pointer to the event handler this thread is sending record notifications
};
class wxETWListCtrl : public wxListCtrl
{
public:
wxETWListCtrl(
wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxPoint &pos = wxDefaultPosition,
const wxSize &size = wxDefaultSize,
long style = wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL|wxNO_BORDER,
const wxValidator &validator = wxDefaultValidator,
const wxString &name = wxListCtrlNameStr);
virtual ~wxETWListCtrl();
protected:
void OnETWEvent(wxETWEvent& event);
DECLARE_EVENT_TABLE()
public:
static const GUID s_provider_eaphost; ///< EAPHost event provider ID
protected:
winstd::event_session m_session; ///< Event session
wxEventTraceProcessorThread *m_proc; ///< Processor thread
long m_item_id; ///< Next free list item ID
};

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<OutDir>..\output\$(Platform).$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>..\lib\Events\build\temp\Events.$(Platform).$(Configuration).$(PlatformToolset);..\lib\WinStd\include;..\lib\wxExtend\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

Binary file not shown.

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{E0D0725B-B2FC-4225-9481-CA9B1B6306F2}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>EventMonitor</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\include\Win32.props" />
<Import Project="..\include\Debug.props" />
<Import Project="EventMonitor.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\include\x64.props" />
<Import Project="..\include\Debug.props" />
<Import Project="EventMonitor.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\include\Win32.props" />
<Import Project="..\include\Release.props" />
<Import Project="EventMonitor.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\include\x64.props" />
<Import Project="..\include\Release.props" />
<Import Project="EventMonitor.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<ItemGroup>
<ResourceCompile Include="EventMonitor.rc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="App.h" />
<ClInclude Include="ETWLog.h" />
<ClInclude Include="Frame.h" />
<ClInclude Include="LogPanel.h" />
<ClInclude Include="StdAfx.h" />
<ClInclude Include="wxEventMonitor_UI.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="App.cpp" />
<ClCompile Include="ETWLog.cpp" />
<ClCompile Include="Frame.cpp" />
<ClCompile Include="LogPanel.cpp" />
<ClCompile Include="StdAfx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="wxEventMonitor_UI.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\lib\Events\build\Events.vcxproj">
<Project>{d63f24bd-92a0-4d6b-8b69-ed947e4d2b1b}</Project>
</ProjectReference>
<ProjectReference Include="..\lib\WinStd\build\WinStd.vcxproj">
<Project>{47399d91-7eb9-41de-b521-514ba5db0c43}</Project>
</ProjectReference>
<ProjectReference Include="..\lib\wxExtend\build\wxExtendLib.vcxproj">
<Project>{d3e29951-d9f5-486d-a167-20ae8e90b1fa}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="locale\EventMonitor.pot" />
<None Include="res\EventMonitor.ico" />
<None Include="wxEventMonitor_UI.fbp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Resource Files\Localization">
<UniqueIdentifier>{e43059ae-37ac-4b28-84fb-18d1b3972b30}</UniqueIdentifier>
<Extensions>po;pot</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="EventMonitor.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="StdAfx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="App.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wxEventMonitor_UI.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Frame.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="LogPanel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ETWLog.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="StdAfx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="App.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wxEventMonitor_UI.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Frame.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LogPanel.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ETWLog.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="wxEventMonitor_UI.fbp">
<Filter>Resource Files</Filter>
</None>
<None Include="locale\EventMonitor.pot">
<Filter>Resource Files\Localization</Filter>
</None>
<None Include="res\EventMonitor.ico">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
</Project>

86
EventMonitor/Frame.cpp Normal file
View File

@@ -0,0 +1,86 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StdAfx.h"
//////////////////////////////////////////////////////////////////////////
// wxEventMonitorFrame
//////////////////////////////////////////////////////////////////////////
wxBEGIN_EVENT_TABLE(wxEventMonitorFrame, wxEventMonitorFrameBase)
EVT_MENU(wxID_EXIT, wxEventMonitorFrame::OnExit)
wxEND_EVENT_TABLE()
wxEventMonitorFrame::wxEventMonitorFrame() : wxEventMonitorFrameBase(NULL)
{
// Load main window icons.
#ifdef __WINDOWS__
wxIcon icon_small(wxT("00_EventMonitor.ico"), wxBITMAP_TYPE_ICO_RESOURCE, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
wxIconBundle icons;
icons.AddIcon(icon_small);
icons.AddIcon(wxIcon(wxT("00_EventMonitor.ico"), wxBITMAP_TYPE_ICO_RESOURCE, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON)));
SetIcons(icons);
#else
wxIcon icon_small(wxICON(00_EventMonitor.ico));
SetIcon(icon_small);
#endif
// Restore persistent state of wxAuiManager manually, since m_mgr is not on the heap.
wxPersistentAuiManager(&m_mgr).Restore();
}
void wxEventMonitorFrame::OnExit(wxCommandEvent& /*event*/)
{
Close();
}
//////////////////////////////////////////////////////////////////////////
// wxPersistentEventMonitorFrame
//////////////////////////////////////////////////////////////////////////
wxPersistentEventMonitorFrame::wxPersistentEventMonitorFrame(wxEventMonitorFrame *wnd) : wxPersistentTLW(wnd)
{
}
void wxPersistentEventMonitorFrame::Save() const
{
const wxEventMonitorFrame * const wnd = static_cast<const wxEventMonitorFrame*>(GetWindow());
wxPersistentEventMonitorLogPanel(wnd->m_panel).Save();
wxPersistentTLW::Save();
}
bool wxPersistentEventMonitorFrame::Restore()
{
const bool r = wxPersistentTLW::Restore();
wxEventMonitorFrame * const wnd = static_cast<wxEventMonitorFrame*>(GetWindow());
wxPersistentEventMonitorLogPanel(wnd->m_panel).Restore();
return r;
}

63
EventMonitor/Frame.h Normal file
View File

@@ -0,0 +1,63 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
///
/// EventMonitor main frame
///
class wxEventMonitorFrame;
///
/// Supports saving/restoring wxEventMonitorFrame GUI state
///
class wxPersistentEventMonitorFrame;
#pragma once;
#include "wxEventMonitor_UI.h"
#include <wx/persist/toplevel.h>
class wxEventMonitorFrame : public wxEventMonitorFrameBase
{
public:
wxEventMonitorFrame();
friend class wxPersistentEventMonitorFrame;
protected:
void OnExit(wxCommandEvent& event);
wxDECLARE_EVENT_TABLE();
};
class wxPersistentEventMonitorFrame : public wxPersistentTLW
{
public:
wxPersistentEventMonitorFrame(wxEventMonitorFrame *wnd);
virtual void Save() const;
virtual bool Restore();
};
inline wxPersistentObject *wxCreatePersistentObject(wxEventMonitorFrame *wnd)
{
return new wxPersistentEventMonitorFrame(wnd);
}

80
EventMonitor/LogPanel.cpp Normal file
View File

@@ -0,0 +1,80 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StdAfx.h"
//////////////////////////////////////////////////////////////////////////
// wxEventMonitorLogPanel
//////////////////////////////////////////////////////////////////////////
wxEventMonitorLogPanel::wxEventMonitorLogPanel(wxWindow* parent) : wxEventMonitorLogPanelBase(parent)
{
// Set focus.
m_log->SetFocus();
}
//////////////////////////////////////////////////////////////////////////
// wxPersistentEventMonitorLogPanel
//////////////////////////////////////////////////////////////////////////
wxPersistentEventMonitorLogPanel::wxPersistentEventMonitorLogPanel(wxEventMonitorLogPanel *wnd) : wxPersistentWindow<wxEventMonitorLogPanel>(wnd)
{
}
wxString wxPersistentEventMonitorLogPanel::GetKind() const
{
return wxT(wxPERSIST_TLW_KIND);
}
void wxPersistentEventMonitorLogPanel::Save() const
{
const wxEventMonitorLogPanel * const wnd = static_cast<const wxEventMonitorLogPanel*>(GetWindow());
// Save log's column widths.
wxListItem col;
col.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_WIDTH);
for (int i = 0, n = wnd->m_log->GetColumnCount(); i < n; i++) {
wnd->m_log->GetColumn(i, col);
SaveValue(wxString::Format(wxT("Column%sWidth"), col.GetText().c_str()), col.GetWidth());
}
}
bool wxPersistentEventMonitorLogPanel::Restore()
{
wxEventMonitorLogPanel * const wnd = static_cast<wxEventMonitorLogPanel*>(GetWindow());
// Restore log's column widths.
wxListItem col;
col.SetMask(wxLIST_MASK_TEXT);
for (int i = 0, n = wnd->m_log->GetColumnCount(); i < n; i++) {
wnd->m_log->GetColumn(i, col);
int width;
if (RestoreValue(wxString::Format(wxT("Column%sWidth"), col.GetText().c_str()), &width))
wnd->m_log->SetColumnWidth(i, width);
}
return true;
}

60
EventMonitor/LogPanel.h Normal file
View File

@@ -0,0 +1,60 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
///
/// EventMonitor trace log panel
///
class wxEventMonitorLogPanel;
///
/// Supports saving/restoring wxEventMonitorLogPanel state
///
class wxPersistentEventMonitorLogPanel;
#pragma once
#include "wxEventMonitor_UI.h"
#include <wx/persist/window.h>
class wxEventMonitorLogPanel : public wxEventMonitorLogPanelBase
{
public:
wxEventMonitorLogPanel(wxWindow* parent);
friend class wxPersistentEventMonitorLogPanel; // Allow saving/restoring window state.
};
class wxPersistentEventMonitorLogPanel : public wxPersistentWindow<wxEventMonitorLogPanel>
{
public:
wxPersistentEventMonitorLogPanel(wxEventMonitorLogPanel *wnd);
virtual wxString GetKind() const;
virtual void Save() const;
virtual bool Restore();
};
inline wxPersistentObject *wxCreatePersistentObject(wxEventMonitorLogPanel *wnd)
{
return new wxPersistentEventMonitorLogPanel(wnd);
}

9
EventMonitor/MSIBuild/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
/*-1.idt
/*-2.idt
/*-2.idtx
/*.Binary-1
/*.Binary-2
/*.Icon-1
/*.Icon-2
/*.lst
/*.msm

Binary file not shown.

21
EventMonitor/StdAfx.cpp Normal file
View File

@@ -0,0 +1,21 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 GÉANT
This file is part of GÉANTLink.
GÉANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GÉANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StdAfx.h"

48
EventMonitor/StdAfx.h Normal file
View File

@@ -0,0 +1,48 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 GÉANT
This file is part of GÉANTLink.
GÉANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GÉANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "App.h"
#include "ETWLog.h"
#include "Frame.h"
#include "LogPanel.h"
#include "../include/Version.h"
#include <wxex/common.h>
#include <wxex/persist/auimanager.h>
#include <WinStd/COM.h>
#include <WinStd/ETW.h>
#include <WinStd/Win.h>
#include <Windows.h>
#include <Msi.h>
#include <tchar.h>
#include <in6addr.h>
#include <MSTcpIP.h>
#include <Sddl.h>
#include <tchar.h>
#include <vector>
#include <EventsETW.h> // Must include after <Windows.h>

View File

@@ -0,0 +1,47 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: EventMonitor\n"
"POT-Creation-Date: 2016-07-15 13:05+0200\n"
"PO-Revision-Date: 2016-06-02 12:27+0200\n"
"Last-Translator: Simon Rozman <simon.rozman@amebis.si>\n"
"Language-Team: Amebis, d. o. o., Kamnik <info@amebis.si>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.8\n"
"X-Poedit-Basepath: ..\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language: en_US\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: _\n"
"X-Poedit-SearchPath-0: .\n"
#: App.cpp:69 wxEventMonitor_UI.h:54
msgid "Event Monitor"
msgstr ""
#: LogPanel.cpp:30
msgid "Time"
msgstr ""
#: LogPanel.cpp:31
msgid "Source"
msgstr ""
#: wxEventMonitor_UI.cpp:23
msgid "E&xit"
msgstr ""
#: wxEventMonitor_UI.cpp:23
msgid "Quit this program"
msgstr ""
#: wxEventMonitor_UI.cpp:26
#, fuzzy
msgid "&Program"
msgstr "You don't have %s subscription yet."
#: wxEventMonitor_UI.cpp:32
msgid "Log Trace"
msgstr ""

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,74 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jun 17 2015)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "ETWLog.h"
#include "wxEventMonitor_UI.h"
///////////////////////////////////////////////////////////////////////////
wxEventMonitorFrameBase::wxEventMonitorFrameBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxFrame( parent, id, title, pos, size, style, name )
{
this->SetSizeHints( wxSize( 150,150 ), wxDefaultSize );
m_mgr.SetManagedWindow(this);
m_mgr.SetFlags(wxAUI_MGR_DEFAULT);
m_menubar = new wxMenuBar( 0 );
m_menuProgram = new wxMenu();
wxMenuItem* m_menuItemExit;
m_menuItemExit = new wxMenuItem( m_menuProgram, wxID_EXIT, wxString( _("E&xit") ) + wxT('\t') + wxT("Alt+F4"), _("Quit this program"), wxITEM_NORMAL );
m_menuProgram->Append( m_menuItemExit );
m_menubar->Append( m_menuProgram, _("&Program") );
this->SetMenuBar( m_menubar );
m_panel = new wxEventMonitorLogPanel( this );
m_mgr.AddPane( m_panel, wxAuiPaneInfo() .Name( wxT("LogPanel") ).Center() .Caption( _("Log Trace") ).CaptionVisible( false ).CloseButton( false ).PaneBorder( false ).Dock().Resizable().FloatingSize( wxDefaultSize ).Floatable( false ) );
m_statusBar = this->CreateStatusBar( 1, wxST_SIZEGRIP, wxID_ANY );
m_mgr.Update();
this->Centre( wxBOTH );
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( wxEventMonitorFrameBase::OnClose ) );
this->Connect( wxEVT_ICONIZE, wxIconizeEventHandler( wxEventMonitorFrameBase::OnIconize ) );
this->Connect( wxEVT_IDLE, wxIdleEventHandler( wxEventMonitorFrameBase::OnIdle ) );
}
wxEventMonitorFrameBase::~wxEventMonitorFrameBase()
{
// Disconnect Events
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( wxEventMonitorFrameBase::OnClose ) );
this->Disconnect( wxEVT_ICONIZE, wxIconizeEventHandler( wxEventMonitorFrameBase::OnIconize ) );
this->Disconnect( wxEVT_IDLE, wxIdleEventHandler( wxEventMonitorFrameBase::OnIdle ) );
m_mgr.UnInit();
}
wxEventMonitorLogPanelBase::wxEventMonitorLogPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
{
wxBoxSizer* bSizerMain;
bSizerMain = new wxBoxSizer( wxVERTICAL );
m_log = new wxETWListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL|wxNO_BORDER );
bSizerMain->Add( m_log, 1, wxEXPAND, 5 );
this->SetSizer( bSizerMain );
this->Layout();
bSizerMain->Fit( this );
}
wxEventMonitorLogPanelBase::~wxEventMonitorLogPanelBase()
{
}

View File

@@ -0,0 +1,449 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="13" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">.</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">wxEventMonitor_UI</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="internationalize">1</property>
<property name="name">wxEventMonitor_UI</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header">#include &quot;StdAfx.h&quot;</property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_enum">1</property>
<property name="use_microsoft_bom">1</property>
<object class="Frame" expanded="1">
<property name="aui_managed">1</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center">wxBOTH</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size">150,150</property>
<property name="name">wxEventMonitorFrameBase</property>
<property name="pos"></property>
<property name="size">600,400</property>
<property name="style">wxDEFAULT_FRAME_STYLE</property>
<property name="subclass"></property>
<property name="title">Event Monitor</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name">EventMonitor</property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<property name="xrc_skip_sizer">1</property>
<event name="OnActivate"></event>
<event name="OnActivateApp"></event>
<event name="OnAuiFindManager"></event>
<event name="OnAuiPaneButton"></event>
<event name="OnAuiPaneClose"></event>
<event name="OnAuiPaneMaximize"></event>
<event name="OnAuiPaneRestore"></event>
<event name="OnAuiRender"></event>
<event name="OnChar"></event>
<event name="OnClose">OnClose</event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnHibernate"></event>
<event name="OnIconize">OnIconize</event>
<event name="OnIdle">OnIdle</event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
<object class="wxMenuBar" expanded="1">
<property name="bg"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Menu</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">m_menubar</property>
<property name="permission">protected</property>
<property name="pos"></property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
<object class="wxMenu" expanded="1">
<property name="label">&amp;Program</property>
<property name="name">m_menuProgram</property>
<property name="permission">protected</property>
<object class="wxMenuItem" expanded="0">
<property name="bitmap"></property>
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help">Quit this program</property>
<property name="id">wxID_EXIT</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">E&amp;xit</property>
<property name="name">m_menuItemExit</property>
<property name="permission">none</property>
<property name="shortcut">Alt+F4</property>
<property name="unchecked_bitmap"></property>
<event name="OnMenuSelection"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
</object>
<object class="CustomControl" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name">LogPanel</property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption">Log Trace</property>
<property name="caption_visible">0</property>
<property name="center_pane">0</property>
<property name="class">wxEventMonitorLogPanel</property>
<property name="close_button">0</property>
<property name="construction">m_panel = new wxEventMonitorLogPanel( this );&#x0A;</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="declaration">wxEventMonitorLogPanel* m_panel;</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Center</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">0</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="include">class wxEventMonitorLogPanel;</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_panel</property>
<property name="pane_border">0</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">public</property>
<property name="pin_button">0</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="settings"></property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
<object class="wxStatusBar" expanded="0">
<property name="bg"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="fields">1</property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">m_statusBar</property>
<property name="permission">protected</property>
<property name="pos"></property>
<property name="size"></property>
<property name="style">wxST_SIZEGRIP</property>
<property name="subclass"></property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="Panel" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">wxEventMonitorLogPanelBase</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="subclass"></property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name">EventMonitorLogPanel</property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<event name="OnAuiFindManager"></event>
<event name="OnAuiPaneButton"></event>
<event name="OnAuiPaneClose"></event>
<event name="OnAuiPaneMaximize"></event>
<event name="OnAuiPaneRestore"></event>
<event name="OnAuiRender"></event>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnInitDialog"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizerMain</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxListCtrl" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_log</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxLC_NO_SORT_HEADER|wxLC_REPORT|wxLC_SINGLE_SEL</property>
<property name="subclass">wxETWListCtrl; ETWLog.h</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxNO_BORDER</property>
<event name="OnChar"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnListBeginDrag"></event>
<event name="OnListBeginLabelEdit"></event>
<event name="OnListBeginRDrag"></event>
<event name="OnListCacheHint"></event>
<event name="OnListColBeginDrag"></event>
<event name="OnListColClick"></event>
<event name="OnListColDragging"></event>
<event name="OnListColEndDrag"></event>
<event name="OnListColRightClick"></event>
<event name="OnListDeleteAllItems"></event>
<event name="OnListDeleteItem"></event>
<event name="OnListEndLabelEdit"></event>
<event name="OnListInsertItem"></event>
<event name="OnListItemActivated"></event>
<event name="OnListItemDeselected"></event>
<event name="OnListItemFocused"></event>
<event name="OnListItemMiddleClick"></event>
<event name="OnListItemRightClick"></event>
<event name="OnListItemSelected"></event>
<event name="OnListKeyDown"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@@ -0,0 +1,80 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jun 17 2015)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __WXEVENTMONITOR_UI_H__
#define __WXEVENTMONITOR_UI_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
class wxETWListCtrl;
#include <wx/string.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/menu.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
class wxEventMonitorLogPanel;
#include <wx/statusbr.h>
#include <wx/frame.h>
#include <wx/aui/aui.h>
#include <wx/listctrl.h>
#include <wx/sizer.h>
#include <wx/panel.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class wxEventMonitorFrameBase
///////////////////////////////////////////////////////////////////////////////
class wxEventMonitorFrameBase : public wxFrame
{
private:
protected:
wxMenuBar* m_menubar;
wxMenu* m_menuProgram;
wxStatusBar* m_statusBar;
// Virtual event handlers, overide them in your derived class
virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
virtual void OnIconize( wxIconizeEvent& event ) { event.Skip(); }
virtual void OnIdle( wxIdleEvent& event ) { event.Skip(); }
public:
wxEventMonitorLogPanel* m_panel;
wxEventMonitorFrameBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Event Monitor"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 600,400 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL, const wxString& name = wxT("EventMonitor") );
wxAuiManager m_mgr;
~wxEventMonitorFrameBase();
};
///////////////////////////////////////////////////////////////////////////////
/// Class wxEventMonitorLogPanelBase
///////////////////////////////////////////////////////////////////////////////
class wxEventMonitorLogPanelBase : public wxPanel
{
private:
protected:
wxETWListCtrl* m_log;
public:
wxEventMonitorLogPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxT("EventMonitorLogPanel") );
~wxEventMonitorLogPanelBase();
};
#endif //__WXEVENTMONITOR_UI_H__

Binary file not shown.

View File

@@ -0,0 +1,41 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: GÉANTLink MSI\n"
"POT-Creation-Date: 2016-07-15 10:51+0200\n"
"PO-Revision-Date: 2016-06-02 12:27+0200\n"
"Last-Translator: Simon Rozman <simon.rozman@amebis.si>\n"
"Language-Team: Amebis, d. o. o., Kamnik <info@amebis.si>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.8\n"
"X-Poedit-Basepath: ../Main\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language: en_US\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-KeywordsList: _\n"
"X-Poedit-SearchPath-0: .\n"
#: En.Win32.Release.Property-2.idtx:6 En.x64.Release.Property-2.idtx:6
msgid "+386 1 8311 035"
msgstr ""
#: En.Win32.Release.Property-2.idtx:3 En.x64.Release.Property-2.idtx:3
#, fuzzy
msgid "1252"
msgstr "1250"
#: En.Win32.Release.Property-2.idtx:5 En.x64.Release.Property-2.idtx:5
msgid "Amebis, p. p. 69, SI-1241 Kamnik, Slovenia, E.U."
msgstr ""
#: En.Win32.Release.Property-2.idtx:4 En.x64.Release.Property-2.idtx:4
msgid "Amebis, Slovenia, E.U."
msgstr ""
#: En.Win32.Release.Property-2.idtx:7 En.Win32.Release.Property-2.idtx:8
#: En.Win32.Release.Property-2.idtx:9 En.x64.Release.Property-2.idtx:7
#: En.x64.Release.Property-2.idtx:8 En.x64.Release.Property-2.idtx:9
msgid "http://www.amebis.si/"
msgstr ""

BIN
Makefile

Binary file not shown.

Binary file not shown.

View File

@@ -40,6 +40,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TTLS_UI", "lib\TTLS_UI\buil
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MsiUseFeature", "MsiUseFeature\MsiUseFeature.vcxproj", "{679D03C5-CD70-4FFA-93F8-A4AB3637509B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EventMonitor", "EventMonitor\EventMonitor.vcxproj", "{E0D0725B-B2FC-4225-9481-CA9B1B6306F2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxExtendLib", "lib\wxExtend\build\wxExtendLib.vcxproj", "{D3E29951-D9F5-486D-A167-20AE8E90B1FA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -160,6 +164,22 @@ Global
{679D03C5-CD70-4FFA-93F8-A4AB3637509B}.Release|Win32.Build.0 = Release|Win32
{679D03C5-CD70-4FFA-93F8-A4AB3637509B}.Release|x64.ActiveCfg = Release|x64
{679D03C5-CD70-4FFA-93F8-A4AB3637509B}.Release|x64.Build.0 = Release|x64
{E0D0725B-B2FC-4225-9481-CA9B1B6306F2}.Debug|Win32.ActiveCfg = Debug|Win32
{E0D0725B-B2FC-4225-9481-CA9B1B6306F2}.Debug|Win32.Build.0 = Debug|Win32
{E0D0725B-B2FC-4225-9481-CA9B1B6306F2}.Debug|x64.ActiveCfg = Debug|x64
{E0D0725B-B2FC-4225-9481-CA9B1B6306F2}.Debug|x64.Build.0 = Debug|x64
{E0D0725B-B2FC-4225-9481-CA9B1B6306F2}.Release|Win32.ActiveCfg = Release|Win32
{E0D0725B-B2FC-4225-9481-CA9B1B6306F2}.Release|Win32.Build.0 = Release|Win32
{E0D0725B-B2FC-4225-9481-CA9B1B6306F2}.Release|x64.ActiveCfg = Release|x64
{E0D0725B-B2FC-4225-9481-CA9B1B6306F2}.Release|x64.Build.0 = Release|x64
{D3E29951-D9F5-486D-A167-20AE8E90B1FA}.Debug|Win32.ActiveCfg = Debug|Win32
{D3E29951-D9F5-486D-A167-20AE8E90B1FA}.Debug|Win32.Build.0 = Debug|Win32
{D3E29951-D9F5-486D-A167-20AE8E90B1FA}.Debug|x64.ActiveCfg = Debug|x64
{D3E29951-D9F5-486D-A167-20AE8E90B1FA}.Debug|x64.Build.0 = Debug|x64
{D3E29951-D9F5-486D-A167-20AE8E90B1FA}.Release|Win32.ActiveCfg = Release|Win32
{D3E29951-D9F5-486D-A167-20AE8E90B1FA}.Release|Win32.Build.0 = Release|Win32
{D3E29951-D9F5-486D-A167-20AE8E90B1FA}.Release|x64.ActiveCfg = Release|x64
{D3E29951-D9F5-486D-A167-20AE8E90B1FA}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -177,7 +197,9 @@ Global
{3D309C2E-64AB-4BC4-A16D-468571A2BC1A} = {E66A3FE1-4EE4-401F-8EAD-BE518B230393}
{9A25C261-8ADE-4938-8393-E857EF0E37E9} = {E66A3FE1-4EE4-401F-8EAD-BE518B230393}
{42F0F0F4-C928-4860-A4E4-94991C2C3D90} = {E66A3FE1-4EE4-401F-8EAD-BE518B230393}
{D3E29951-D9F5-486D-A167-20AE8E90B1FA} = {E66A3FE1-4EE4-401F-8EAD-BE518B230393}
{2D3CE079-7EB1-4F47-B79E-F0310671ECCB} = {7B5EC9B7-208C-426A-941D-DAF9271BD4A4}
{679D03C5-CD70-4FFA-93F8-A4AB3637509B} = {7B5EC9B7-208C-426A-941D-DAF9271BD4A4}
{E0D0725B-B2FC-4225-9481-CA9B1B6306F2} = {7B5EC9B7-208C-426A-941D-DAF9271BD4A4}
EndGlobalSection
EndGlobal

View File

@@ -24,15 +24,15 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IntDir>temp\$(ProjectName).$(Platform).$(Configuration).$(PlatformToolset)\</IntDir>
<OutDir>temp\$(ProjectName).$(Platform).$(Configuration).$(PlatformToolset)\</OutDir>
<IntDir>temp\$(MSBuildProjectName).$(Platform).$(Configuration).$(PlatformToolset)\</IntDir>
<OutDir>temp\$(MSBuildProjectName).$(Platform).$(Configuration).$(PlatformToolset)\</OutDir>
<IncludePath>$(WXWIN)\include\msvc;$(WXWIN)\include;$(IncludePath)</IncludePath>
<SourcePath>$(WXWIN)\src\aui;$(WXWIN)\src\cocoa;$(WXWIN)\src\common;$(WXWIN)\src\dfb;$(WXWIN)\src\expat;$(WXWIN)\src\generic;$(WXWIN)\src\gtk;$(WXWIN)\src\gtk1;$(WXWIN)\src\html;$(WXWIN)\src\jpeg;$(WXWIN)\src\motif;$(WXWIN)\src\msdos;$(WXWIN)\src\msw;$(WXWIN)\src\os2;$(WXWIN)\src\osx;$(WXWIN)\src\png;$(WXWIN)\src\propgrid;$(WXWIN)\src\regex;$(WXWIN)\src\ribbon;$(WXWIN)\src\richtext;$(WXWIN)\src\stc;$(WXWIN)\src\tiff;$(WXWIN)\src\univ;$(WXWIN)\src\unix;$(WXWIN)\src\x11;$(WXWIN)\src\xml;$(WXWIN)\src\xrc;$(WXWIN)\src\zlib;$(SourcePath)</SourcePath>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PreprocessorDefinitions>_WIN32_WINNT=0x0600;ISOLATION_AWARE_ENABLED=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WIN32_WINNT=0x0600;ISOLATION_AWARE_ENABLED=1;SECURITY_WIN32;CERT_CHAIN_PARA_HAS_EXTRA_FIELDS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>StdAfx.h</PrecompiledHeaderFile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

Binary file not shown.

View File

@@ -29,7 +29,7 @@
// Product version as a single DWORD
// Note: Used for version comparison within C/C++ code.
//
#define PRODUCT_VERSION 0x00ff0400
#define PRODUCT_VERSION 0x00ff0a00
//
// Product version by components
@@ -39,26 +39,26 @@
//
#define PRODUCT_VERSION_MAJ 0
#define PRODUCT_VERSION_MIN 255
#define PRODUCT_VERSION_REV 4
#define PRODUCT_VERSION_REV 10
#define PRODUCT_VERSION_BUILD 0
//
// Human readable product version and build year for UI
//
#define PRODUCT_VERSION_STR "1.0-alpha4"
#define PRODUCT_VERSION_STR "1.0-alpha10"
#define PRODUCT_BUILD_YEAR_STR "2016"
//
// Numerical version presentation for ProductVersion propery in
// MSI packages (syntax: N.N[.N[.N]])
//
#define PRODUCT_VERSION_INST "0.255.4"
#define PRODUCT_VERSION_INST "0.255.10"
//
// The product code for ProductCode property in MSI packages
// Replace with new on every version change, regardless how minor it is.
//
#define PRODUCT_VERSION_GUID "{18A0CABB-BDE9-499B-B840-E955C69F9386}"
#define PRODUCT_VERSION_GUID "{2A743CF3-8AAE-416B-B779-2EC1F509121D}"
//
// Since the product name is not finally confirmed at the time of

66
include/xgettext.targets Normal file
View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 1991-2016 Amebis
Copyright 2016 GÉANT
This file is part of GÉANTLink.
GÉANTLink is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GÉANTLink is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PropertyPageSchema Include="$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml" />
<AvailableItemName Include="POCompile">
<Targets>POCompile</Targets>
</AvailableItemName>
</ItemGroup>
<UsingTask TaskName="POCompile" TaskFactory="XamlTaskFactory" AssemblyName="Microsoft.Build.Tasks.v4.0">
<Task>$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml</Task>
</UsingTask>
<Target
Name="POCompile"
BeforeTargets="$(POCompileBeforeTargets)"
AfterTargets="$(POCompileAfterTargets)"
DependsOnTargets="$(POCompilationDependsOn)"
Inputs="@(POCompile);$(MSBuildProjectFile)"
Outputs="%(POCompile.OutputFile)"
>
<ItemGroup Condition="'@(SelectedFiles)' != ''">
<POCompile Remove="@(POCompile)" Condition="'%(Identity)' != '@(SelectedFiles)'" />
</ItemGroup>
<Message Text="Compiling localization catalogues..." />
<POCompile
Condition="'@(POCompile)' != '' and '%(POCompile.ExcludedFromBuild)' != 'true'"
Inputs="@(POCompile)"
OperationMode="%(POCompile.OperationMode)"
Strict="%(POCompile.Strict)"
CheckFormat="%(POCompile.CheckFormat)"
CheckHeader="%(POCompile.CheckHeader)"
CheckDomain="%(POCompile.CheckDomain)"
CheckCompat="%(POCompile.CheckCompat)"
CheckAccel="%(POCompile.CheckAccel)"
OutputFile="%(POCompile.OutputFile)"
UseFuzzy="%(POCompile.UseFuzzy)"
Alignment="%(POCompile.Alignment)"
Endianess="%(POCompile.Endianess)"
AdditionalOptions="%(POCompile.AdditionalOptions)"
CommandLineTemplate="%(POCompile.CommandLineTemplate)" />
</Target>
<Target Name="POCompilationClean">
<Delete Files="%(POCompile.OutputFile)" ContinueOnError="true" />
</Target>
<PropertyGroup>
<CleanDependsOn>POCompilationClean;$(CleanDependsOn);</CleanDependsOn>
</PropertyGroup>
</Project>

84
include/xgettext.xml Normal file
View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 1991-2016 Amebis
Copyright 2016 GÉANT
This file is part of GÉANTLink.
GÉANTLink is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GÉANTLink is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
-->
<ProjectSchemaDefinitions xmlns="clr-namespace:Microsoft.Build.Framework.XamlTypes;assembly=Microsoft.Build.Framework" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:transformCallback="Microsoft.Cpp.Dev10.ConvertPropertyCallback">
<Rule Name="POCompile" PageTemplate="tool" DisplayName="PO Compiler" SwitchPrefix="--" Order="200">
<Rule.DataSource>
<DataSource Persistence="ProjectFile" ItemType="POCompile" />
</Rule.DataSource>
<Rule.Categories>
<Category Name="General" DisplayName="General" />
<Category Name="Input" DisplayName="Input" />
<Category Name="Output" DisplayName="Output" />
<Category Name="Command Line" DisplayName="Command Line" Subtype="CommandLine" />
</Rule.Categories>
<EnumProperty Category="General" Name="OperationMode" DisplayName="Operation Mode" Description="Specifies the operation mode.">
<EnumValue Name="MO" DisplayName="Default" Description="Generate MO file (default)." />
<EnumValue Name="Java" Switch="java" DisplayName="Java" Description="Generate a Java ResourceBundle class." />
<EnumValue Name="Java2" Switch="java2" DisplayName="Java2" Description="Like Java, and assume Java2 (JDK 1.2 or higher)." />
<EnumValue Name="Csharp" Switch="csharp" DisplayName="C#" Description="Generate a .NET .dll file." />
<EnumValue Name="CsharpRes" Switch="csharp-resources" DisplayName="C# Resource" Description="Generate a .NET .resources file." />
<EnumValue Name="Tcl" Switch="tcl" DisplayName="Tcl" Description="Generate a tcl/msgcat .msg file." />
<EnumValue Name="Qt" Switch="qt" DisplayName="Qt" Description="Generate a Qt .qm file." />
<EnumValue Name="Desktop" Switch="desktop" DisplayName="Desktop Entry" Description="Generate a .desktop file." />
</EnumProperty>
<BoolProperty Category="General" Name="Strict" Switch="strict" DisplayName="Enable strict mode" Description="Enable strict Uniforum mode." />
<BoolProperty Category="Input" Name="CheckFormat" Switch="check-format" DisplayName="Check Format" Description="Check language dependent format strings." />
<BoolProperty Category="Input" Name="CheckHeader" Switch="check-header" DisplayName="Check Header" Description="Verify presence and contents of the header entry." />
<BoolProperty Category="Input" Name="CheckDomain" Switch="check-domain" DisplayName="Check Domain" Description="Check for conflicts between domain directives and the --output-file option." />
<BoolProperty Category="Input" Name="CheckCompat" Switch="check-compatibility" DisplayName="Check Compatibility" Description="Check that GNU msgfmt behaves like X/Open msgfmt." />
<EnumProperty Category="Input" Name="CheckAccel" DisplayName="Check Accelerators" Description="Check presence of keyboard accelerators for menu items.">
<EnumValue Name="None" DisplayName="None" Description="No check" />
<EnumValue Name="Amperstand" Switch="check-accelerators=&quot;&amp;&quot;" DisplayName="Amperstand" Description="Check keyborad accellerator marked with an amperstand &amp;." />
</EnumProperty>
<StringProperty Category="Output" Name="OutputFile" Switch="output-file=" DisplayName="Output File" Description="The name and location of the output file that compiler creates." Subtype="file" />
<BoolProperty Category="Output" Name="UseFuzzy" Switch="use-fuzzy" DisplayName="Use Fuzzy Entries" Description="Use fuzzy entries in output." />
<IntProperty Category="Output" Name="Alignment" Switch="alignment=" DisplayName="Align Strings" Description="Align strings to given bytes (default: 1)." />
<EnumProperty Category="Output" Name="Endianess" DisplayName="Endianess" Description="Write out 32-bit numbers in the given byte order (default: platform specific).">
<EnumValue Name="LSB" Switch="endianness=little" DisplayName="LSB" Description="Least significant byte first" />
<EnumValue Name="MSB" Switch="endianness=big" DisplayName="MSB" Description="Most significant byte first" />
</EnumProperty>
<StringListProperty Category="Command Line" Name="Inputs" Subtype="file" IsRequired="true" >
<StringListProperty.DataSource>
<DataSource Persistence="ProjectFile" ItemType="POCompile" SourceType="Item" />
</StringListProperty.DataSource>
</StringListProperty>
<StringProperty Category="Command Line" Name="AdditionalOptions" Subtype="AdditionalOptions" DisplayName="Additional Options" Description="Additional Options" />
<DynamicEnumProperty Category="Command Line" Name="POCompileBeforeTargets" EnumProvider="Targets" DisplayName="Execute Before" Description="Specifies the targets for the build customization to run before." IncludeInCommandLine="False">
<DynamicEnumProperty.ProviderSettings>
<NameValuePair Name="Exclude" Value="^POCompileBeforeTargets|^Compute" />
</DynamicEnumProperty.ProviderSettings>
<DynamicEnumProperty.DataSource>
<DataSource Persistence="ProjectFile" HasConfigurationCondition="true" />
</DynamicEnumProperty.DataSource>
</DynamicEnumProperty>
<DynamicEnumProperty Category="Command Line" Name="POCompileAfterTargets" EnumProvider="Targets" DisplayName="Execute After" Description="Specifies the targets for the build customization to run after." IncludeInCommandLine="False">
<DynamicEnumProperty.ProviderSettings>
<NameValuePair Name="Exclude" Value="^POCompileAfterTargets|^Compute" />
</DynamicEnumProperty.ProviderSettings>
<DynamicEnumProperty.DataSource>
<DataSource Persistence="ProjectFile" ItemType="" HasConfigurationCondition="true" />
</DynamicEnumProperty.DataSource>
</DynamicEnumProperty>
</Rule>
<ItemType Name="POCompile" DisplayName="PO Compiler" />
<FileExtension Name="*.po" ContentType="POCompile" />
<ContentType Name="POCompile" DisplayName="PO Compiler" ItemType="POCompile" />
</ProjectSchemaDefinitions>

View File

@@ -82,17 +82,16 @@
<ClInclude Include="..\include\Config.h" />
<ClInclude Include="..\include\Credentials.h" />
<ClInclude Include="..\include\EAP.h" />
<ClInclude Include="..\include\EAPSerial.h" />
<ClInclude Include="..\include\EAPXML.h" />
<ClInclude Include="..\include\Method.h" />
<ClInclude Include="..\include\Module.h" />
<ClInclude Include="..\include\Session.h" />
<ClInclude Include="..\src\StdAfx.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\Config.cpp" />
<ClCompile Include="..\src\Credentials.cpp" />
<ClCompile Include="..\src\Module.cpp" />
<ClCompile Include="..\src\Session.cpp" />
<ClCompile Include="..\src\Method.cpp" />
<ClCompile Include="..\src\StdAfx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>

View File

@@ -17,13 +17,10 @@
<ClInclude Include="..\include\EAP.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\EAPSerial.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\EAPXML.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\Session.h">
<ClInclude Include="..\include\Method.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\Config.h">
@@ -40,15 +37,15 @@
<ClCompile Include="..\src\StdAfx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\Session.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\Config.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\Credentials.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\Method.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\Module.cpp">
<Filter>Source Files</Filter>
</ClCompile>

File diff suppressed because it is too large Load Diff

View File

@@ -33,64 +33,10 @@ namespace eap
class credentials_pass;
}
namespace eapserial
{
///
/// Packs a method credentials
///
/// \param[inout] cursor Memory cursor
/// \param[in] val Credentials to pack
///
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::credentials &val);
///
/// Returns packed size of a method credentials
///
/// \param[in] val Credentials to pack
///
/// \returns Size of data when packed (in bytes)
///
inline size_t get_pk_size(const eap::credentials &val);
///
/// Unpacks a method credentials
///
/// \param[inout] cursor Memory cursor
/// \param[out] val Credentials to unpack to
///
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::credentials &val);
///
/// Packs a password based method credentials
///
/// \param[inout] cursor Memory cursor
/// \param[in] val Credentials to pack
///
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::credentials_pass &val);
///
/// Returns packed size of a password based method credentials
///
/// \param[in] val Credentials to pack
///
/// \returns Size of data when packed (in bytes)
///
inline size_t get_pk_size(const eap::credentials_pass &val);
///
/// Unpacks a password based method credentials
///
/// \param[inout] cursor Memory cursor
/// \param[out] val Credentials to unpack to
///
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::credentials_pass &val);
}
#pragma once
#include "Config.h"
#include "Module.h"
#include "EAPSerial.h"
#include "../../../include/Version.h"
@@ -108,11 +54,23 @@ namespace eap
{
class credentials : public config
{
public:
///
/// Credential source when combined
///
enum source_t {
source_unknown = -1, ///< Unknown source
source_cache = 0, ///< Credentials were obtained from EAPHost cache
source_preshared, ///< Credentials were set by method configuration
source_storage ///< Credentials were loaded from Windows Credential Manager
};
public:
///
/// Constructs credentials
///
/// \param[in] mod Reference of the EAP module to use for global services
/// \param[in] mod EAP module to use for global services
///
credentials(_In_ module &mod);
@@ -156,38 +114,12 @@ namespace eap
///
/// Test credentials if blank
///
/// \returns
/// - \c true if blank
/// - \c false otherwise
///
virtual bool empty() const;
/// \name XML configuration management
/// @{
///
/// Save credentials to XML document
///
/// \param[in] pDoc XML document
/// \param[in] pConfigRoot Suggested root element for saving credentials
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const;
///
/// Load credentials from XML document
///
/// \param[in] pConfigRoot Root element for loading credentials
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError);
/// @}
/// \name Storage
/// @{
@@ -195,30 +127,15 @@ namespace eap
/// Save credentials to Windows Credential Manager
///
/// \param[in] pszTargetName The name in Windows Credential Manager to store credentials as
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError) const = 0;
virtual void store(_In_z_ LPCTSTR pszTargetName) const = 0;
///
/// Retrieve credentials from Windows Credential Manager
///
/// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError) = 0;
///
/// Return target suffix for Windows Credential Manager credential name
///
virtual LPCTSTR target_suffix() const = 0;
virtual void retrieve(_In_z_ LPCTSTR pszTargetName) = 0;
///
/// Returns target name for Windows Credential Manager credential name
@@ -227,7 +144,7 @@ namespace eap
///
/// \returns Final target name to store/retrieve credentials in Windows Credential Manager
///
inline winstd::tstring target_name(_In_ LPCTSTR pszTargetName) const
inline winstd::tstring target_name(_In_z_ LPCTSTR pszTargetName) const
{
winstd::tstring target_name(_T(PRODUCT_NAME_STR) _T("/"));
target_name += pszTargetName;
@@ -237,10 +154,22 @@ namespace eap
return target_name;
}
///
/// Return target suffix for Windows Credential Manager credential name
///
virtual LPCTSTR target_suffix() const = 0;
/// @}
public:
std::wstring m_identity; ///< Identity (username\@domain, certificate name etc.)
///
/// Returns credential identity.
///
virtual std::wstring get_identity() const = 0;
///
/// Returns credential name (for GUI display).
///
virtual winstd::tstring get_name() const;
};
@@ -250,7 +179,7 @@ namespace eap
///
/// Constructs credentials
///
/// \param[in] mod Reference of the EAP module to use for global services
/// \param[in] mod EAP module to use for global services
///
credentials_pass(_In_ module &mod);
@@ -294,35 +223,55 @@ namespace eap
///
/// Test credentials if blank
///
/// \returns
/// - \c true if blank
/// - \c false otherwise
///
virtual bool empty() const;
/// \name XML configuration management
/// @{
///
/// Save credentials to XML document
/// Save to XML document
///
/// \param[in] pDoc XML document
/// \param[in] pConfigRoot Suggested root element for saving credentials
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
/// \param[in] pConfigRoot Suggested root element for saving
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const;
virtual void save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const;
///
/// Load credentials from XML document
/// Load from XML document
///
/// \param[in] pConfigRoot Root element for loading credentials
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
/// \param[in] pConfigRoot Root element for loading
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
virtual void load(_In_ IXMLDOMNode *pConfigRoot);
/// @}
/// \name BLOB management
/// @{
///
virtual bool load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError);
/// Packs a configuration
///
/// \param[inout] cursor Memory cursor
///
virtual void operator<<(_Inout_ cursor_out &cursor) const;
///
/// Returns packed size of a configuration
///
/// \returns Size of data when packed (in bytes)
///
virtual size_t get_pk_size() const;
///
/// Unpacks a configuration
///
/// \param[inout] cursor Memory cursor
///
virtual void operator>>(_Inout_ cursor_in &cursor);
/// @}
@@ -333,72 +282,30 @@ namespace eap
/// Save credentials to Windows Credential Manager
///
/// \param[in] pszTargetName The name in Windows Credential Manager to store credentials as
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError) const;
virtual void store(_In_z_ LPCTSTR pszTargetName) const;
///
/// Retrieve credentials from Windows Credential Manager
///
/// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError);
virtual void retrieve(_In_z_ LPCTSTR pszTargetName);
/// @}
///
/// Returns credential identity.
///
virtual std::wstring get_identity() const;
public:
std::wstring m_identity; ///< Identity (username\@domain, certificate name etc.)
winstd::sanitizing_wstring m_password; ///< Password
private:
/// \cond internal
static const unsigned char s_entropy[1024];
/// \endcond
};
}
namespace eapserial
{
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::credentials &val)
{
pack(cursor, val.m_identity);
}
inline size_t get_pk_size(const eap::credentials &val)
{
return get_pk_size(val.m_identity);
}
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::credentials &val)
{
unpack(cursor, val.m_identity);
}
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::credentials_pass &val)
{
pack(cursor, (const eap::credentials&)val);
pack(cursor, val.m_password );
}
inline size_t get_pk_size(const eap::credentials_pass &val)
{
return
get_pk_size((const eap::credentials&)val) +
get_pk_size(val.m_password );
}
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::credentials_pass &val)
{
unpack(cursor, (eap::credentials&)val);
unpack(cursor, val.m_password );
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,395 +0,0 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 GÉANT
This file is part of GÉANTLink.
GÉANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GÉANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include <WinStd/Crypt.h>
#include <sal.h>
#include <list>
#include <string>
#include <vector>
namespace eapserial
{
///
/// Packs a primitive data
///
/// \param[inout] cursor Memory cursor
/// \param[in] val Variable with data to pack
///
template <class T> inline void pack(_Inout_ unsigned char *&cursor, _In_ const T &val);
///
/// Returns packed size of a primitive data
///
/// \param[in] val Data to pack
///
/// \returns Size of data when packed (in bytes)
///
template <class T> inline size_t get_pk_size(_In_ const T &val);
///
/// Unpacks a primitive data
///
/// \param[inout] cursor Memory cursor
/// \param[out] val Variable to receive unpacked value
///
template <class T> inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ T &val);
///
/// Packs a string
///
/// \param[inout] cursor Memory cursor
/// \param[in] val String to pack
///
template<class _Elem, class _Traits, class _Ax> inline void pack(_Inout_ unsigned char *&cursor, _In_ const std::basic_string<_Elem, _Traits, _Ax> &val);
///
/// Returns packed size of a string
///
/// \param[in] val String to pack
///
/// \returns Size of data when packed (in bytes)
///
template<class _Elem, class _Traits, class _Ax> inline size_t get_pk_size(const std::basic_string<_Elem, _Traits, _Ax> &val);
///
/// Unpacks a string
///
/// \param[inout] cursor Memory cursor
/// \param[out] val String to unpack to
///
template<class _Elem, class _Traits, class _Ax> inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ std::basic_string<_Elem, _Traits, _Ax> &val);
///
/// Packs a wide string
///
/// \param[inout] cursor Memory cursor
/// \param[in] val String to pack
///
template<class _Traits, class _Ax> inline void pack(_Inout_ unsigned char *&cursor, _In_ const std::basic_string<wchar_t, _Traits, _Ax> &val);
///
/// Returns packed size of a wide string
///
/// \param[in] val String to pack
///
/// \returns Size of data when packed (in bytes)
///
template<class _Traits, class _Ax> inline size_t get_pk_size(const std::basic_string<wchar_t, _Traits, _Ax> &val);
///
/// Unpacks a wide string
///
/// \param[inout] cursor Memory cursor
/// \param[out] val String to unpack to
///
template<class _Traits, class _Ax> inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &val);
///
/// Packs a vector
///
/// \param[inout] cursor Memory cursor
/// \param[in] val Vector to pack
///
template<class _Ty, class _Ax> inline void pack(_Inout_ unsigned char *&cursor, _In_ const std::vector<_Ty, _Ax> &val);
///
/// Returns packed size of a vector
///
/// \param[in] val Vector to pack
///
/// \returns Size of data when packed (in bytes)
///
template<class _Ty, class _Ax> inline size_t get_pk_size(const std::vector<_Ty, _Ax> &val);
///
/// Unpacks a vector
///
/// \param[inout] cursor Memory cursor
/// \param[out] val Vector to unpack to
///
template<class _Ty, class _Ax> inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ std::vector<_Ty, _Ax> &val);
///
/// Packs a list
///
/// \param[inout] cursor Memory cursor
/// \param[in] val List to pack
///
template<class _Ty, class _Ax> inline void pack(_Inout_ unsigned char *&cursor, _In_ const std::list<_Ty, _Ax> &val);
///
/// Returns packed size of a list
///
/// \param[in] val List to pack
///
/// \returns Size of data when packed (in bytes)
///
template<class _Ty, class _Ax> inline size_t get_pk_size(const std::list<_Ty, _Ax> &val);
///
/// Unpacks a list
///
/// \param[inout] cursor Memory cursor
/// \param[out] val List to unpack to
///
template<class _Ty, class _Ax> inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ std::list<_Ty, _Ax> &val);
///
/// Packs a certificate context
///
/// \param[inout] cursor Memory cursor
/// \param[in] val Certificate context to pack
///
inline void pack(_Inout_ unsigned char *&cursor, _In_ const winstd::cert_context &val);
///
/// Returns packed size of a certificate context
///
/// \param[in] val Certificate context to pack
///
/// \returns Size of data when packed (in bytes)
///
inline size_t get_pk_size(const winstd::cert_context &val);
///
/// Unpacks a certificate context
///
/// \param[inout] cursor Memory cursor
/// \param[out] val Certificate context to unpack to
///
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ winstd::cert_context &val);
}
#pragma once
namespace eapserial
{
template <class T>
inline void pack(_Inout_ unsigned char *&cursor, _In_ const T &val)
{
memcpy(cursor, &val, sizeof(T));
cursor += sizeof(T);
}
template <class T>
inline size_t get_pk_size(_In_ const T &val)
{
UNREFERENCED_PARAMETER(val);
return sizeof(T);
}
template <class T>
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ T &val)
{
memcpy(&val, cursor, sizeof(T));
cursor += sizeof(T);
}
template<class _Elem, class _Traits, class _Ax>
inline void pack(_Inout_ unsigned char *&cursor, _In_ const std::basic_string<_Elem, _Traits, _Ax> &val)
{
std::basic_string<_Elem, _Traits, _Ax>::size_type count = val.length();
*(std::basic_string<_Elem, _Traits, _Ax>::size_type*&)cursor = count;
cursor += sizeof(std::basic_string<_Elem, _Traits, _Ax>::size_type);
size_t nSize = sizeof(_Elem)*count;
memcpy(cursor, (const _Elem*)val.c_str(), nSize);
cursor += nSize;
}
template<class _Elem, class _Traits, class _Ax>
inline size_t get_pk_size(const std::basic_string<_Elem, _Traits, _Ax> &val)
{
return sizeof(std::basic_string<_Elem, _Traits, _Ax>::size_type) + sizeof(_Elem)*val.length();
}
template<class _Elem, class _Traits, class _Ax>
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ std::basic_string<_Elem, _Traits, _Ax> &val)
{
std::basic_string<_Elem, _Traits, _Ax>::size_type count = *(const std::basic_string<_Elem, _Traits, _Ax>::size_type*&)cursor;
cursor += sizeof(std::basic_string<_Elem, _Traits, _Ax>::size_type);
val.assign((const _Elem*&)cursor, count);
cursor += sizeof(_Elem)*count;
}
template<class _Traits, class _Ax>
inline void pack(_Inout_ unsigned char *&cursor, _In_ const std::basic_string<wchar_t, _Traits, _Ax> &val)
{
std::string val_utf8;
WideCharToMultiByte(CP_UTF8, 0, val.c_str(), (int)val.length(), val_utf8, NULL, NULL);
pack(cursor, val_utf8);
}
template<class _Traits, class _Ax>
inline size_t get_pk_size(const std::basic_string<wchar_t, _Traits, _Ax> &val)
{
return sizeof(std::string::size_type) + WideCharToMultiByte(CP_UTF8, 0, val.c_str(), (int)val.length(), NULL, 0, NULL, NULL);
}
template<class _Traits, class _Ax>
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &val)
{
std::string val_utf8;
unpack(cursor, val_utf8);
MultiByteToWideChar(CP_UTF8, 0, val_utf8.c_str(), (int)val_utf8.length(), val);
}
template<class _Ty, class _Ax>
inline void pack(_Inout_ unsigned char *&cursor, _In_ const std::vector<_Ty, _Ax> &val)
{
std::vector<_Ty, _Ax>::size_type count = val.size();
*(std::vector<_Ty, _Ax>::size_type*&)cursor = count;
cursor += sizeof(std::vector<_Ty, _Ax>::size_type);
// Since we do not know wheter vector elements are primitives or objects, iterate instead of memcpy.
// For performance critical vectors of flat opaque data types write specialized template instantiation.
for (std::vector<_Ty, _Ax>::size_type i = 0; i < count; i++)
pack(cursor, val[i]);
}
template<class _Ty, class _Ax>
inline size_t get_pk_size(const std::vector<_Ty, _Ax> &val)
{
// Since we do not know wheter vector elements are primitives or objects, iterate instead of sizeof().
// For performance critical vectors of flat opaque data types write specialized template instantiation.
size_t size = sizeof(std::vector<_Ty, _Ax>::size_type);
for (std::vector<_Ty, _Ax>::size_type i = 0, count = val.size(); i < count; i++)
size += get_pk_size(val[i]);
return size;
}
template<class _Ty, class _Ax>
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ std::vector<_Ty, _Ax> &val)
{
std::vector<_Ty, _Ax>::size_type count = *(const std::vector<_Ty, _Ax>::size_type*&)cursor;
cursor += sizeof(std::vector<_Ty, _Ax>::size_type);
// Since we do not know wheter vector elements are primitives or objects, iterate instead of assign().
// For performance critical vectors of flat opaque data types write specialized template instantiation.
val.clear();
val.reserve(count);
for (std::vector<_Ty, _Ax>::size_type i = 0; i < count; i++) {
_Ty el;
unpack(cursor, el);
val.push_back(el);
}
}
template<class _Ty, class _Ax>
inline void pack(_Inout_ unsigned char *&cursor, _In_ const std::list<_Ty, _Ax> &val)
{
std::list<_Ty, _Ax>::size_type count = val.size();
*(std::list<_Ty, _Ax>::size_type*&)cursor = count;
cursor += sizeof(std::list<_Ty, _Ax>::size_type);
// Since we do not know wheter list elements are primitives or objects, iterate instead of memcpy.
// For performance critical vectors of flat opaque data types write specialized template instantiation.
for (std::list<_Ty, _Ax>::const_iterator i = val.cbegin(), i_end = val.cend(); i != i_end; ++i)
pack(cursor, *i);
}
template<class _Ty, class _Ax>
inline size_t get_pk_size(const std::list<_Ty, _Ax> &val)
{
// Since we do not know wheter list elements are primitives or objects, iterate instead of sizeof().
// For performance critical vectors of flat opaque data types write specialized template instantiation.
size_t size = sizeof(std::list<_Ty, _Ax>::size_type);
for (std::list<_Ty, _Ax>::const_iterator i = val.cbegin(), i_end = val.cend(); i != i_end; ++i)
size += get_pk_size(*i);
return size;
}
template<class _Ty, class _Ax>
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ std::list<_Ty, _Ax> &val)
{
std::list<_Ty, _Ax>::size_type count = *(const std::list<_Ty, _Ax>::size_type*&)cursor;
cursor += sizeof(std::list<_Ty, _Ax>::size_type);
// Since we do not know wheter list elements are primitives or objects, iterate instead of assign().
// For performance critical vectors of flat opaque data types write specialized template instantiation.
val.clear();
for (std::list<_Ty, _Ax>::size_type i = 0; i < count; i++) {
_Ty el;
unpack(cursor, el);
val.push_back(el);
}
}
inline void pack(_Inout_ unsigned char *&cursor, _In_ const winstd::cert_context &val)
{
if (val) {
*(DWORD*&)cursor = val->dwCertEncodingType;
cursor += sizeof(DWORD);
*(DWORD*&)cursor = val->cbCertEncoded;
cursor += sizeof(DWORD);
memcpy(cursor, val->pbCertEncoded, val->cbCertEncoded);
cursor += val->cbCertEncoded;
} else {
*(DWORD*&)cursor = 0;
cursor += sizeof(DWORD);
*(DWORD*&)cursor = 0;
cursor += sizeof(DWORD);
}
}
inline size_t get_pk_size(const winstd::cert_context &val)
{
return sizeof(DWORD) + sizeof(DWORD) + (val ? val->cbCertEncoded : 0);
}
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ winstd::cert_context &val)
{
DWORD dwCertEncodingType = *(DWORD*&)cursor;
cursor += sizeof(DWORD);
DWORD dwCertEncodedSize = *(DWORD*&)cursor;
cursor += sizeof(DWORD);
if (dwCertEncodedSize) {
val.create(dwCertEncodingType, (BYTE*)cursor, dwCertEncodedSize);
cursor += dwCertEncodedSize;
} else
val.free();
}
}

View File

@@ -27,27 +27,28 @@
namespace eapxml
{
inline DWORD get_document(_In_ IXMLDOMNode *pXmlNode, _Out_ IXMLDOMDocument2 **ppXmlDoc);
inline DWORD select_node(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrNodeName, _Out_ IXMLDOMNode **ppXmlNode);
inline DWORD select_nodes(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrNodeName, _Out_ IXMLDOMNodeList **ppXmlNodes);
inline DWORD select_element(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ IXMLDOMElement **ppXmlElement);
inline DWORD create_element(_In_ IXMLDOMDocument *pDoc, _In_z_ const BSTR bstrElementName, _In_z_ const BSTR bstrNamespace, _Out_ IXMLDOMElement **ppXmlElement);
inline DWORD create_element(_In_ IXMLDOMDocument *pDoc, IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementNameSelect, _In_z_ const BSTR bstrElementNameCreate, _In_z_ const BSTR bstrNamespace, _Out_ IXMLDOMElement **ppXmlElement);
inline HRESULT get_document(_In_ IXMLDOMNode *pXmlNode, _Out_ IXMLDOMDocument2 **ppXmlDoc);
inline HRESULT select_node(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrNodeName, _Out_ IXMLDOMNode **ppXmlNode);
inline HRESULT select_nodes(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrNodeName, _Out_ IXMLDOMNodeList **ppXmlNodes);
inline HRESULT select_element(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ IXMLDOMElement **ppXmlElement);
inline HRESULT create_element(_In_ IXMLDOMDocument *pDoc, _In_z_ const BSTR bstrElementName, _In_z_ const BSTR bstrNamespace, _Out_ IXMLDOMElement **ppXmlElement);
inline HRESULT create_element(_In_ IXMLDOMDocument *pDoc, IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementNameSelect, _In_z_ const BSTR bstrElementNameCreate, _In_z_ const BSTR bstrNamespace, _Out_ IXMLDOMElement **ppXmlElement);
inline bool has_parent(_In_ IXMLDOMNode *pXmlNode);
inline DWORD get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ BSTR *pbstrValue);
template<class _Traits, class _Ax> inline DWORD get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue);
inline DWORD get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ DWORD *pdwValue);
inline DWORD get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ bool *pbValue);
template<class _Ty, class _Ax> inline DWORD get_element_base64(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::vector<_Ty, _Ax> &aValue);
template<class _Ty, class _Ax> inline DWORD get_element_hex(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::vector<_Ty, _Ax> &aValue);
inline DWORD get_element_localized(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _In_z_ LPCWSTR pszLang, _Out_ BSTR *pbstrValue);
template<class _Traits, class _Ax> inline DWORD get_element_localized(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _In_z_ LPCWSTR pszLang, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue);
inline DWORD put_element(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _Out_ IXMLDOMElement **ppXmlElement);
inline DWORD put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_z_ const BSTR bstrValue);
inline DWORD put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_ DWORD dwValue);
inline DWORD put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_ bool bValue);
inline DWORD put_element_base64(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_count_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen);
inline DWORD put_element_hex(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_count_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen);
inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ BSTR *pbstrValue);
template<class _Traits, class _Ax> inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue);
inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ DWORD *pdwValue);
inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ bool *pbValue);
template<class _Ty, class _Ax> inline HRESULT get_element_base64(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::vector<_Ty, _Ax> &aValue);
template<class _Ty, class _Ax> inline HRESULT get_element_hex(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::vector<_Ty, _Ax> &aValue);
inline HRESULT get_element_localized(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _In_z_ LPCWSTR pszLang, _Out_ BSTR *pbstrValue);
template<class _Traits, class _Ax> inline HRESULT get_element_localized(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _In_z_ LPCWSTR pszLang, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue);
inline HRESULT put_element(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _Out_ IXMLDOMElement **ppXmlElement);
inline HRESULT put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_z_ const BSTR bstrValue);
inline HRESULT put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_ DWORD dwValue);
inline HRESULT put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_ bool bValue);
inline HRESULT put_element_base64(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_count_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen);
inline HRESULT put_element_hex(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_count_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen);
inline std::wstring get_xpath(_In_ IXMLDOMNode *pXmlNode);
}
#pragma once
@@ -61,7 +62,7 @@ namespace eapxml
namespace eapxml
{
inline DWORD get_document(_In_ IXMLDOMNode *pXmlNode, _Out_ IXMLDOMDocument2 **ppXmlDoc)
inline HRESULT get_document(_In_ IXMLDOMNode *pXmlNode, _Out_ IXMLDOMDocument2 **ppXmlDoc)
{
assert(pXmlNode);
assert(ppXmlDoc);
@@ -71,11 +72,11 @@ namespace eapxml
return
SUCCEEDED(hr = pXmlNode->get_ownerDocument(&doc)) &&
SUCCEEDED(hr = doc.query_interface(ppXmlDoc)) ? ERROR_SUCCESS : HRESULT_CODE(hr);
SUCCEEDED(hr = doc.query_interface(ppXmlDoc)) ? S_OK : hr;
}
inline DWORD select_node(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrNodeName, _Out_ IXMLDOMNode **ppXmlNode)
inline HRESULT select_node(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrNodeName, _Out_ IXMLDOMNode **ppXmlNode)
{
assert(pXmlParent);
assert(ppXmlNode);
@@ -84,11 +85,11 @@ namespace eapxml
return
SUCCEEDED(hr = pXmlParent->selectSingleNode(bstrNodeName, ppXmlNode)) ?
*ppXmlNode ? ERROR_SUCCESS : ERROR_NO_DATA : HRESULT_CODE(hr);
*ppXmlNode ? S_OK : E_NOT_SET : hr;
}
inline DWORD select_nodes(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrNodeName, _Out_ IXMLDOMNodeList **ppXmlNodes)
inline HRESULT select_nodes(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrNodeName, _Out_ IXMLDOMNodeList **ppXmlNodes)
{
assert(pXmlParent);
assert(ppXmlNodes);
@@ -97,26 +98,25 @@ namespace eapxml
return
SUCCEEDED(hr = pXmlParent->selectNodes(bstrNodeName, ppXmlNodes)) ?
*ppXmlNodes ? ERROR_SUCCESS : ERROR_NO_DATA : HRESULT_CODE(hr);
*ppXmlNodes ? S_OK : E_NOT_SET : hr;
}
inline DWORD select_element(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ IXMLDOMElement **ppXmlElement)
inline HRESULT select_element(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ IXMLDOMElement **ppXmlElement)
{
assert(ppXmlElement);
DWORD dwResult;
HRESULT hr;
winstd::com_obj<IXMLDOMNode> pXmlNode;
return
(dwResult = select_node(pXmlParent, bstrElementName, &pXmlNode)) == ERROR_SUCCESS ?
SUCCEEDED(hr = select_node(pXmlParent, bstrElementName, &pXmlNode)) ?
SUCCEEDED(hr = pXmlNode.query_interface(ppXmlElement)) ?
*ppXmlElement ? ERROR_SUCCESS : ERROR_NO_DATA : HRESULT_CODE(hr) : dwResult;
*ppXmlElement ? S_OK : E_NOT_SET : hr : hr;
}
inline DWORD create_element(_In_ IXMLDOMDocument *pDoc, _In_z_ const BSTR bstrElementName, _In_z_ const BSTR bstrNamespace, _Out_ IXMLDOMElement **ppXmlElement)
inline HRESULT create_element(_In_ IXMLDOMDocument *pDoc, _In_z_ const BSTR bstrElementName, _In_z_ const BSTR bstrNamespace, _Out_ IXMLDOMElement **ppXmlElement)
{
assert(pDoc);
assert(ppXmlElement);
@@ -128,23 +128,22 @@ namespace eapxml
return
SUCCEEDED(hr = pDoc->createNode(varNodeTypeEl, bstrElementName, bstrNamespace, &pXmlNode)) ?
SUCCEEDED(hr = pXmlNode.query_interface(ppXmlElement)) ?
*ppXmlElement ? ERROR_SUCCESS : ERROR_NO_DATA : HRESULT_CODE(hr) : HRESULT_CODE(hr);
*ppXmlElement ? S_OK : E_NOT_SET : hr : hr;
}
inline DWORD create_element(_In_ IXMLDOMDocument *pDoc, IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementNameSelect, _In_z_ const BSTR bstrElementNameCreate, _In_z_ const BSTR bstrNamespace, _Out_ IXMLDOMElement **ppXmlElement)
inline HRESULT create_element(_In_ IXMLDOMDocument *pDoc, IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementNameSelect, _In_z_ const BSTR bstrElementNameCreate, _In_z_ const BSTR bstrNamespace, _Out_ IXMLDOMElement **ppXmlElement)
{
assert(pDoc);
assert(pXmlParent);
assert(ppXmlElement);
DWORD dwResult;
HRESULT hr;
return
(dwResult = select_element(pXmlParent, bstrElementNameSelect, ppXmlElement)) == ERROR_SUCCESS ? ERROR_SUCCESS :
(dwResult = create_element(pDoc, bstrElementNameCreate, bstrNamespace, ppXmlElement)) == ERROR_SUCCESS ?
SUCCEEDED(hr = pXmlParent->appendChild(*ppXmlElement, NULL)) ? ERROR_SUCCESS : HRESULT_CODE(hr) : dwResult;
SUCCEEDED(hr = select_element(pXmlParent, bstrElementNameSelect, ppXmlElement)) ? S_OK :
SUCCEEDED(hr = create_element(pDoc, bstrElementNameCreate, bstrNamespace, ppXmlElement)) ?
SUCCEEDED(hr = pXmlParent->appendChild(*ppXmlElement, NULL)) ? S_OK : hr : hr;
}
@@ -158,51 +157,50 @@ namespace eapxml
}
inline DWORD get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ BSTR *pbstrValue)
inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ BSTR *pbstrValue)
{
assert(pbstrValue);
DWORD dwResult;
HRESULT hr;
winstd::com_obj<IXMLDOMElement> pXmlElement;
return
(dwResult = select_element(pXmlParent, bstrElementName, &pXmlElement)) == ERROR_SUCCESS ?
SUCCEEDED(hr = select_element(pXmlParent, bstrElementName, &pXmlElement)) ?
SUCCEEDED(hr = pXmlElement->get_text(pbstrValue)) ?
*pbstrValue ? ERROR_SUCCESS : ERROR_NO_DATA : HRESULT_CODE(hr) : dwResult;
*pbstrValue ? S_OK : E_NOT_SET : hr : hr;
}
template<class _Traits, class _Ax>
inline DWORD get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
{
winstd::bstr bstr;
DWORD dwResult = get_element_value(pXmlParent, bstrElementName, &bstr);
if (dwResult == ERROR_SUCCESS)
HRESULT hr = get_element_value(pXmlParent, bstrElementName, &bstr);
if (SUCCEEDED(hr))
sValue.assign(bstr, bstr.length());
return dwResult;
return hr;
}
inline DWORD get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ DWORD *pdwValue)
inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ DWORD *pdwValue)
{
assert(pdwValue);
winstd::bstr bstr;
DWORD dwResult = get_element_value(pXmlParent, bstrElementName, &bstr);
if (dwResult == ERROR_SUCCESS)
HRESULT hr = get_element_value(pXmlParent, bstrElementName, &bstr);
if (SUCCEEDED(hr))
*pdwValue = wcstoul(bstr, NULL, 10);
return dwResult;
return hr;
}
inline DWORD get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ bool *pbValue)
inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ bool *pbValue)
{
assert(pbValue);
winstd::bstr bstr;
DWORD dwResult = get_element_value(pXmlParent, bstrElementName, &bstr);
if (dwResult == ERROR_SUCCESS) {
HRESULT hr = get_element_value(pXmlParent, bstrElementName, &bstr);
if (SUCCEEDED(hr)) {
if (CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstr, bstr.length(), L"true" , -1, NULL, NULL, 0) == CSTR_EQUAL ||
CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstr, bstr.length(), L"1" , -1, NULL, NULL, 0) == CSTR_EQUAL)
*pbValue = true;
@@ -211,63 +209,62 @@ namespace eapxml
CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstr, bstr.length(), L"0" , -1, NULL, NULL, 0) == CSTR_EQUAL)
*pbValue = false;
else
dwResult = ERROR_INVALID_DATA;
hr = E_NOT_VALID_STATE;
}
return dwResult;
return hr;
}
template<class _Ty, class _Ax>
inline DWORD get_element_base64(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::vector<_Ty, _Ax> &aValue)
inline HRESULT get_element_base64(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::vector<_Ty, _Ax> &aValue)
{
winstd::bstr bstr;
DWORD dwResult = get_element_value(pXmlParent, bstrElementName, &bstr);
if (dwResult == ERROR_SUCCESS) {
HRESULT hr = get_element_value(pXmlParent, bstrElementName, &bstr);
if (SUCCEEDED(hr)) {
winstd::base64_dec dec;
bool is_last;
dec.decode(aValue, is_last, (BSTR)bstr, bstr.length());
}
return dwResult;
return hr;
}
template<class _Ty, class _Ax>
inline DWORD get_element_hex(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::vector<_Ty, _Ax> &aValue)
inline HRESULT get_element_hex(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::vector<_Ty, _Ax> &aValue)
{
winstd::bstr bstr;
DWORD dwResult = get_element_value(pXmlParent, bstrElementName, &bstr);
if (dwResult == ERROR_SUCCESS) {
HRESULT hr = get_element_value(pXmlParent, bstrElementName, &bstr);
if (SUCCEEDED(hr)) {
winstd::hex_dec dec;
bool is_last;
dec.decode(aValue, is_last, (BSTR)bstr, bstr.length());
}
return dwResult;
return hr;
}
inline DWORD get_element_localized(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _In_z_ LPCWSTR pszLang, _Out_ BSTR *pbstrValue)
inline HRESULT get_element_localized(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _In_z_ LPCWSTR pszLang, _Out_ BSTR *pbstrValue)
{
assert(pbstrValue);
HRESULT hr;
winstd::com_obj<IXMLDOMElement> pXmlElement;
DWORD dwResult = select_element(pXmlParent, bstrElementName, &pXmlElement);
if (dwResult != ERROR_SUCCESS)
return dwResult;
if (FAILED(hr = select_element(pXmlParent, bstrElementName, &pXmlElement)))
return hr;
winstd::com_obj<IXMLDOMNodeList> pXmlListLocalizedText;
long lCount = 0;
if (select_nodes(pXmlElement, winstd::bstr(L"eap-metadata:localized-text"), &pXmlListLocalizedText) != ERROR_SUCCESS ||
if (FAILED(select_nodes(pXmlElement, winstd::bstr(L"eap-metadata:localized-text"), &pXmlListLocalizedText)) ||
FAILED(pXmlListLocalizedText->get_length(&lCount)) ||
lCount <= 0)
{
return
SUCCEEDED(hr = pXmlElement->get_text(pbstrValue)) ?
*pbstrValue ? ERROR_SUCCESS : ERROR_NO_DATA : HRESULT_CODE(hr);
*pbstrValue ? S_OK : E_NOT_SET : hr;
}
winstd::bstr bstrDefault, bstrEn;
@@ -276,11 +273,11 @@ namespace eapxml
if (bstrDefault != NULL) {
// Return "C" localization.
*pbstrValue = bstrDefault.detach();
return ERROR_SUCCESS;
return S_OK;
} else if (bstrEn != NULL) {
// Return "en" localization.
*pbstrValue = bstrEn.detach();
return ERROR_SUCCESS;
return S_OK;
} else
return ERROR_NOT_FOUND;
}
@@ -291,12 +288,12 @@ namespace eapxml
{
// Read <lang>.
winstd::bstr bstrLang;
if (get_element_value(pXmlElLocalizedText, winstd::bstr(L"eap-metadata:lang"), &bstrLang) != ERROR_SUCCESS ||
if (FAILED(get_element_value(pXmlElLocalizedText, winstd::bstr(L"eap-metadata:lang"), &bstrLang)) ||
CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstrLang, bstrLang.length(), L"C" , -1, NULL, NULL, 0) == CSTR_EQUAL)
{
// <lang> is missing or "C" language found.
winstd::bstr bstr;
if ((dwResult = get_element_value(pXmlElLocalizedText, winstd::bstr(L"eap-metadata:text"), &bstr)) == ERROR_SUCCESS)
if (SUCCEEDED(hr = get_element_value(pXmlElLocalizedText, winstd::bstr(L"eap-metadata:text"), &bstr)))
bstrDefault.attach(bstr.detach());
} else if (CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstrLang, bstrLang.length(), pszLang, -1, NULL, NULL, 0) == CSTR_EQUAL) {
// Found an exact match.
@@ -304,7 +301,7 @@ namespace eapxml
} else if (CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstrLang, bstrLang.length(), L"en", -1, NULL, NULL, 0) == CSTR_EQUAL) {
// "en" language found.
winstd::bstr bstr;
if ((dwResult = get_element_value(pXmlElLocalizedText, winstd::bstr(L"eap-metadata:text"), &bstr)) == ERROR_SUCCESS)
if (SUCCEEDED(hr = get_element_value(pXmlElLocalizedText, winstd::bstr(L"eap-metadata:text"), &bstr)))
bstrEn.attach(bstr.detach());
}
}
@@ -313,17 +310,17 @@ namespace eapxml
template<class _Traits, class _Ax>
inline DWORD get_element_localized(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _In_z_ LPCWSTR pszLang, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
inline HRESULT get_element_localized(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _In_z_ LPCWSTR pszLang, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
{
winstd::bstr bstr;
DWORD dwResult = get_element_localized(pXmlParent, bstrElementName, pszLang, &bstr);
if (dwResult == ERROR_SUCCESS)
HRESULT hr = get_element_localized(pXmlParent, bstrElementName, pszLang, &bstr);
if (SUCCEEDED(hr))
sValue.assign(bstr, bstr.length());
return dwResult;
return hr;
}
inline DWORD put_element(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _Out_ IXMLDOMElement **ppXmlElement)
inline HRESULT put_element(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _Out_ IXMLDOMElement **ppXmlElement)
{
assert(pDoc);
assert(pCurrentDOMNode);
@@ -336,11 +333,11 @@ namespace eapxml
return
SUCCEEDED(hr = pDoc->createNode(varNodeTypeEl, bstrElementName, bstrNamespace, &pXmlEl)) &&
SUCCEEDED(hr = pCurrentDOMNode->appendChild(pXmlEl, NULL)) &&
SUCCEEDED(hr = pXmlEl.query_interface(ppXmlElement)) ? ERROR_SUCCESS : HRESULT_CODE(hr);
SUCCEEDED(hr = pXmlEl.query_interface(ppXmlElement)) ? S_OK : hr;
}
inline DWORD put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_z_ const BSTR bstrValue)
inline HRESULT put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_z_ const BSTR bstrValue)
{
assert(pDoc);
@@ -353,23 +350,23 @@ namespace eapxml
SUCCEEDED(hr = pDoc->createNode(varNodeTypeEl, bstrElementName, bstrNamespace, &pXmlEl)) &&
SUCCEEDED(hr = pDoc->createTextNode(bstrValue, &pXmlElText)) &&
SUCCEEDED(hr = pXmlEl->appendChild(pXmlElText, NULL)) &&
SUCCEEDED(hr = pCurrentDOMNode->appendChild(pXmlEl, NULL)) ? ERROR_SUCCESS : HRESULT_CODE(hr);
SUCCEEDED(hr = pCurrentDOMNode->appendChild(pXmlEl, NULL)) ? S_OK : hr;
}
inline DWORD put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_ DWORD dwValue)
inline HRESULT put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_ DWORD dwValue)
{
return put_element_value(pDoc, pCurrentDOMNode, bstrElementName, bstrNamespace, winstd::bstr(winstd::wstring_printf(L"%d", dwValue)));
}
inline DWORD put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_ bool bValue)
inline HRESULT put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_ bool bValue)
{
return put_element_value(pDoc, pCurrentDOMNode, bstrElementName, bstrNamespace, winstd::bstr(bValue ? L"true": L"false"));
}
inline DWORD put_element_base64(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_count_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen)
inline HRESULT put_element_base64(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_count_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen)
{
std::wstring sBase64;
winstd::base64_enc enc;
@@ -378,11 +375,25 @@ namespace eapxml
}
inline DWORD put_element_hex(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_count_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen)
inline HRESULT put_element_hex(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_count_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen)
{
std::wstring sHex;
winstd::hex_enc enc;
enc.encode(sHex, pValue, nValueLen);
return put_element_value(pDoc, pCurrentDOMNode, bstrElementName, bstrNamespace, winstd::bstr(sHex));
}
inline std::wstring get_xpath(_In_ IXMLDOMNode *pXmlNode)
{
if (pXmlNode) {
winstd::bstr bstr;
winstd::com_obj<IXMLDOMNode> pXmlNodeParent;
return
SUCCEEDED(pXmlNode->get_nodeName(&bstr)) ?
SUCCEEDED(pXmlNode->get_parentNode(&pXmlNodeParent)) ? get_xpath(pXmlNodeParent) + L"/" + (LPCWSTR)bstr : (LPCWSTR)bstr : L"?";
} else
return L"";
}
}

View File

@@ -0,0 +1,137 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 GÉANT
This file is part of GÉANTLink.
GÉANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GÉANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
namespace eap
{
///
/// EAP method base class
///
class method;
}
#pragma once
#include "Config.h"
#include "Credentials.h"
#include "Module.h"
#include <WinStd/EAP.h>
#include <Windows.h>
#include <eaptypes.h> // Must include after <Windows.h>
extern "C" {
#include <eapmethodpeerapis.h>
}
#include <sal.h>
namespace eap
{
class method
{
public:
///
/// Constructs an EAP method
///
/// \param[in] mod EAP module to use for global services
/// \param[in] cfg Providers configuration
/// \param[in] cred User credentials
///
method(_In_ module &module, _In_ config_provider_list &cfg, _In_ credentials &cred);
///
/// Moves an EAP method
///
/// \param[in] other EAP method to move from
///
method(_Inout_ method &&other);
///
/// Moves an EAP method
///
/// \param[in] other EAP method to move from
///
/// \returns Reference to this object
///
method& operator=(_Inout_ method &&other);
/// \name Packet processing
/// @{
///
/// Starts an EAP authentication session on the peer EAPHost using the EAP method.
///
/// \sa [EapPeerBeginSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363600.aspx)
///
virtual void begin_session(
_In_ DWORD dwFlags,
_In_ const EapAttributes *pAttributeArray,
_In_ HANDLE hTokenImpersonateUser,
_In_ DWORD dwMaxSendPacketSize);
///
/// Ends an EAP authentication session for the EAP method.
///
/// \sa [EapPeerEndSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363604.aspx)
///
virtual void end_session();
///
/// Processes a packet received by EAPHost from a supplicant.
///
/// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx)
///
virtual void process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize,
_Inout_ EapPeerMethodOutput *pEapOutput) = 0;
///
/// Obtains a response packet from the EAP method.
///
/// \sa [EapPeerGetResponsePacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363610.aspx)
///
virtual void get_response_packet(
_Inout_bytecap_(*dwSendPacketSize) EapPacket *pSendPacket,
_Inout_ DWORD *pdwSendPacketSize) = 0;
///
/// Obtains the result of an authentication session from the EAP method.
///
/// \sa [EapPeerGetResult function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363611.aspx)
///
virtual void get_result(
_In_ EapPeerMethodResultReason reason,
_Inout_ EapPeerMethodResult *ppResult) = 0;
/// @}
private:
// This class is noncopyable.
method(_In_ const method &other);
method& operator=(_In_ const method &other);
public:
module &m_module; ///< EAP module
config_provider_list &m_cfg; ///< Providers configuration
credentials &m_cred; ///< User credentials
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,234 +0,0 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 GÉANT
This file is part of GÉANTLink.
GÉANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GÉANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
namespace eap
{
///
/// EAP session
///
class session;
}
#pragma once
#include "Module.h"
#include <Windows.h>
#include <eaptypes.h> // Must include after <Windows.h>
extern "C" {
#include <eapmethodpeerapis.h>
}
#include <sal.h>
namespace eap
{
class session
{
public:
///
/// Constructs a session
///
/// \param[in] mod Reference of the EAP module to use for global services
///
session(_In_ module &mod);
///
/// Copies session
///
/// \param[in] other Session to copy from
///
session(_In_ const session &other);
///
/// Moves session
///
/// \param[in] other Session to move from
///
session(_Inout_ session &&other);
///
/// Copies session
///
/// \param[in] other Session to copy from
///
/// \returns Reference to this object
///
session& operator=(_In_ const session &other);
///
/// Moves session
///
/// \param[in] other Session to move from
///
/// \returns Reference to this object
///
session& operator=(_Inout_ session &&other);
/// \name Session start/end
/// @{
///
/// Starts an EAP authentication session on the peer EAPHost using the EAP method.
///
/// \sa [EapPeerBeginSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363600.aspx)
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool begin(
_In_ DWORD dwFlags,
_In_ const EapAttributes *pAttributeArray,
_In_ HANDLE hTokenImpersonateUser,
_In_ DWORD dwConnectionDataSize,
_In_count_(dwConnectionDataSize) const BYTE *pConnectionData,
_In_ DWORD dwUserDataSize,
_In_count_(dwUserDataSize) const BYTE *pUserData,
_In_ DWORD dwMaxSendPacketSize,
_Out_ EAP_ERROR **ppEapError);
///
/// Ends an EAP authentication session for the EAP method.
///
/// \sa [EapPeerEndSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363604.aspx)
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool end(_Out_ EAP_ERROR **ppEapError);
/// @}
/// \name Packet processing
/// @{
///
/// Processes a packet received by EAPHost from a supplicant.
///
/// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx)
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool process_request_packet(
_In_ DWORD dwReceivedPacketSize,
_In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket,
_Out_ EapPeerMethodOutput *pEapOutput,
_Out_ EAP_ERROR **ppEapError);
///
/// Obtains a response packet from the EAP method.
///
/// \sa [EapPeerGetResponsePacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363610.aspx)
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool get_response_packet(
_Inout_ DWORD *pdwSendPacketSize,
_Inout_bytecap_(*dwSendPacketSize) EapPacket *pSendPacket,
_Out_ EAP_ERROR **ppEapError);
///
/// Obtains the result of an authentication session from the EAP method.
///
/// \sa [EapPeerGetResult function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363611.aspx)
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool get_result(_In_ EapPeerMethodResultReason reason, _Out_ EapPeerMethodResult *ppResult, _Out_ EAP_ERROR **ppEapError);
/// @}
/// \name UI interaction
/// @{
///
/// Obtains the user interface context from the EAP method.
///
/// \note This function is always followed by the `EapPeerInvokeInteractiveUI()` function, which is followed by the `EapPeerSetUIContext()` function.
///
/// \sa [EapPeerGetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363612.aspx)
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool get_ui_context(
_Out_ DWORD *pdwUIContextDataSize,
_Out_ BYTE **ppUIContextData,
_Out_ EAP_ERROR **ppEapError);
///
/// Provides a user interface context to the EAP method.
///
/// \note This function is called after the UI has been raised through the `EapPeerGetUIContext()` function.
///
/// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx)
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool set_ui_context(
_In_ DWORD dwUIContextDataSize,
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
_In_ const EapPeerMethodOutput *pEapOutput,
_Out_ EAP_ERROR **ppEapError);
/// @}
/// \name Response attributes
/// @{
///
/// Obtains an array of EAP response attributes from the EAP method.
///
/// \sa [EapPeerGetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363609.aspx)
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool get_response_attributes(_Out_ EapAttributes *pAttribs, _Out_ EAP_ERROR **ppEapError);
///
/// Provides an updated array of EAP response attributes to the EAP method.
///
/// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx)
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool set_response_attributes(const _In_ EapAttributes *pAttribs, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError);
/// @}
public:
module &m_module; ///< Reference of the EAP module
};
}

View File

@@ -48,15 +48,697 @@ eap::config::config(_Inout_ config &&other) :
eap::config& eap::config::operator=(_In_ const config &other)
{
UNREFERENCED_PARAMETER(other);
assert(&m_module == &other.m_module); // Copy configuration within same module only!
if (this != &other)
assert(&m_module == &other.m_module);
return *this;
}
eap::config& eap::config::operator=(_Inout_ config &&other)
{
UNREFERENCED_PARAMETER(other);
assert(&m_module == &other.m_module); // Move configuration within same module only!
if (this != &other)
assert(&m_module == &other.m_module);
return *this;
}
void eap::config::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const
{
UNREFERENCED_PARAMETER(pDoc);
UNREFERENCED_PARAMETER(pConfigRoot);
}
void eap::config::load(_In_ IXMLDOMNode *pConfigRoot)
{
UNREFERENCED_PARAMETER(pConfigRoot);
}
void eap::config::operator<<(_Inout_ cursor_out &cursor) const
{
UNREFERENCED_PARAMETER(cursor);
}
size_t eap::config::get_pk_size() const
{
return 0;
}
void eap::config::operator>>(_Inout_ cursor_in &cursor)
{
UNREFERENCED_PARAMETER(cursor);
}
//////////////////////////////////////////////////////////////////////
// eap::config_method
//////////////////////////////////////////////////////////////////////
eap::config_method::config_method(_In_ module &mod) : config(mod)
{
}
eap::config_method::config_method(_In_ const config_method &other) : config(other)
{
}
eap::config_method::config_method(_Inout_ config_method &&other) : config(std::move(other))
{
}
eap::config_method& eap::config_method::operator=(_In_ const config_method &other)
{
if (this != &other)
(config&)*this = other;
return *this;
}
eap::config_method& eap::config_method::operator=(_Inout_ config_method &&other)
{
if (this != &other)
(config&&)*this = std::move(other);
return *this;
}
//////////////////////////////////////////////////////////////////////
// eap::config_method_with_cred
//////////////////////////////////////////////////////////////////////
eap::config_method_with_cred::config_method_with_cred(_In_ module &mod) :
m_allow_save(true),
m_use_preshared(false),
m_auth_failed(false),
config_method(mod)
{
}
eap::config_method_with_cred::config_method_with_cred(_In_ const config_method_with_cred &other) :
m_allow_save(other.m_allow_save),
m_use_preshared(other.m_use_preshared),
m_preshared(other.m_preshared ? (credentials*)other.m_preshared->clone() : nullptr),
m_auth_failed(other.m_auth_failed),
config_method(other)
{
}
eap::config_method_with_cred::config_method_with_cred(_Inout_ config_method_with_cred &&other) :
m_allow_save(std::move(other.m_allow_save)),
m_use_preshared(std::move(other.m_use_preshared)),
m_preshared(std::move(other.m_preshared)),
m_auth_failed(std::move(other.m_auth_failed)),
config_method(std::move(other))
{
}
eap::config_method_with_cred& eap::config_method_with_cred::operator=(_In_ const config_method_with_cred &other)
{
if (this != &other) {
(config_method&)*this = other;
m_allow_save = other.m_allow_save;
m_use_preshared = other.m_use_preshared;
m_preshared.reset(other.m_preshared ? (credentials*)other.m_preshared->clone() : nullptr);
m_auth_failed = other.m_auth_failed;
}
return *this;
}
eap::config_method_with_cred& eap::config_method_with_cred::operator=(_Inout_ config_method_with_cred &&other)
{
if (this != &other) {
(config_method&)*this = std::move(other );
m_allow_save = std::move(other.m_allow_save );
m_use_preshared = std::move(other.m_use_preshared);
m_preshared = std::move(other.m_preshared );
m_auth_failed = std::move(other.m_auth_failed );
}
return *this;
}
void eap::config_method_with_cred::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const
{
assert(pDoc);
assert(pConfigRoot);
const winstd::bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
HRESULT hr;
// <ClientSideCredential>
winstd::com_obj<IXMLDOMElement> pXmlElClientSideCredential;
if (FAILED(hr = eapxml::create_element(pDoc, pConfigRoot, winstd::bstr(L"eap-metadata:ClientSideCredential"), winstd::bstr(L"ClientSideCredential"), bstrNamespace, &pXmlElClientSideCredential)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <ClientSideCredential> element.");
// <ClientSideCredential>/<allow-save>
if (FAILED(hr = eapxml::put_element_value(pDoc, pXmlElClientSideCredential, winstd::bstr(L"allow-save"), bstrNamespace, m_allow_save)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <allow-save> element.");
if (m_use_preshared)
m_preshared->save(pDoc, pXmlElClientSideCredential);
}
void eap::config_method_with_cred::load(_In_ IXMLDOMNode *pConfigRoot)
{
assert(pConfigRoot);
m_allow_save = true;
m_use_preshared = false;
m_preshared->clear();
// <ClientSideCredential>
winstd::com_obj<IXMLDOMElement> pXmlElClientSideCredential;
if (SUCCEEDED(eapxml::select_element(pConfigRoot, winstd::bstr(L"eap-metadata:ClientSideCredential"), &pXmlElClientSideCredential))) {
std::wstring xpath(eapxml::get_xpath(pXmlElClientSideCredential));
// <allow-save>
eapxml::get_element_value(pXmlElClientSideCredential, winstd::bstr(L"eap-metadata:allow-save"), &m_allow_save);
m_module.log_config((xpath + L"/allow-save").c_str(), m_allow_save);
try {
m_preshared->load(pXmlElClientSideCredential);
m_use_preshared = true;
} catch (...) {
// This is not really an error - merely an indication pre-shared credentials are unavailable.
}
}
}
void eap::config_method_with_cred::operator<<(_Inout_ cursor_out &cursor) const
{
config_method::operator<<(cursor);
cursor << m_allow_save;
cursor << m_use_preshared;
cursor << *m_preshared;
cursor << m_auth_failed;
}
size_t eap::config_method_with_cred::get_pk_size() const
{
return
config_method::get_pk_size() +
pksizeof(m_allow_save ) +
pksizeof(m_use_preshared) +
pksizeof(*m_preshared ) +
pksizeof(m_auth_failed );
}
void eap::config_method_with_cred::operator>>(_Inout_ cursor_in &cursor)
{
config_method::operator>>(cursor);
cursor >> m_allow_save;
cursor >> m_use_preshared;
cursor >> *m_preshared;
cursor >> m_auth_failed;
}
//////////////////////////////////////////////////////////////////////
// eap::config_provider
//////////////////////////////////////////////////////////////////////
eap::config_provider::config_provider(_In_ module &mod) :
m_read_only(false),
config(mod)
{
}
eap::config_provider::config_provider(_In_ const config_provider &other) :
m_read_only(other.m_read_only),
m_id(other.m_id),
m_name(other.m_name),
m_help_email(other.m_help_email),
m_help_web(other.m_help_web),
m_help_phone(other.m_help_phone),
m_lbl_alt_credential(other.m_lbl_alt_credential),
m_lbl_alt_identity(other.m_lbl_alt_identity),
m_lbl_alt_password(other.m_lbl_alt_password),
config(other)
{
m_methods.reserve(other.m_methods.size());
for (vector<unique_ptr<config_method> >::const_iterator method = other.m_methods.cbegin(), method_end = other.m_methods.cend(); method != method_end; ++method)
m_methods.push_back(std::move(unique_ptr<config_method>(*method ? (config_method*)method->get()->clone() : nullptr)));
}
eap::config_provider::config_provider(_Inout_ config_provider &&other) :
m_read_only(std::move(other.m_read_only)),
m_id(std::move(other.m_id)),
m_name(std::move(other.m_name)),
m_help_email(std::move(other.m_help_email)),
m_help_web(std::move(other.m_help_web)),
m_help_phone(std::move(other.m_help_phone)),
m_lbl_alt_credential(std::move(other.m_lbl_alt_credential)),
m_lbl_alt_identity(std::move(other.m_lbl_alt_identity)),
m_lbl_alt_password(std::move(other.m_lbl_alt_password)),
m_methods(std::move(other.m_methods)),
config(std::move(other))
{
}
eap::config_provider& eap::config_provider::operator=(_In_ const config_provider &other)
{
if (this != &other) {
(config&)*this = other;
m_read_only = other.m_read_only;
m_id = other.m_id;
m_name = other.m_name;
m_help_email = other.m_help_email;
m_help_web = other.m_help_web;
m_help_phone = other.m_help_phone;
m_lbl_alt_credential = other.m_lbl_alt_credential;
m_lbl_alt_identity = other.m_lbl_alt_identity;
m_lbl_alt_password = other.m_lbl_alt_password;
m_methods.clear();
m_methods.reserve(other.m_methods.size());
for (vector<unique_ptr<config_method> >::const_iterator method = other.m_methods.cbegin(), method_end = other.m_methods.cend(); method != method_end; ++method)
m_methods.push_back(std::move(unique_ptr<config_method>(*method ? (config_method*)method->get()->clone() : nullptr)));
}
return *this;
}
eap::config_provider& eap::config_provider::operator=(_Inout_ config_provider &&other)
{
if (this != &other) {
(config&&)*this = std::move(other);
m_read_only = std::move(m_read_only);
m_id = std::move(other.m_id);
m_name = std::move(other.m_name);
m_help_email = std::move(other.m_help_email);
m_help_web = std::move(other.m_help_web);
m_help_phone = std::move(other.m_help_phone);
m_lbl_alt_credential = std::move(other.m_lbl_alt_credential);
m_lbl_alt_identity = std::move(other.m_lbl_alt_identity);
m_lbl_alt_password = std::move(other.m_lbl_alt_password);
m_methods = std::move(other.m_methods);
}
return *this;
}
eap::config* eap::config_provider::clone() const
{
return new config_provider(*this);
}
void eap::config_provider::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const
{
config::save(pDoc, pConfigRoot);
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
HRESULT hr;
// <read-only>
if (FAILED(hr = eapxml::put_element_value(pDoc, pConfigRoot, bstr(L"read-only"), bstrNamespace, m_read_only)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <read-only> element.");
// <ID>
if (!m_id.empty())
if (FAILED(hr = eapxml::put_element_value(pDoc, pConfigRoot, bstr(L"ID"), bstrNamespace, bstr(m_id))))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <ID> element.");
// <ProviderInfo>
com_obj<IXMLDOMElement> pXmlElProviderInfo;
if (FAILED(hr = eapxml::create_element(pDoc, pConfigRoot, bstr(L"eap-metadata:ProviderInfo"), bstr(L"ProviderInfo"), bstrNamespace, &pXmlElProviderInfo)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <ProviderInfo> element.");
// <ProviderInfo>/<DisplayName>
if (!m_name.empty())
if (FAILED(hr = eapxml::put_element_value(pDoc, pXmlElProviderInfo, bstr(L"DisplayName"), bstrNamespace, bstr(m_name))))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <DisplayName> element.");
// <ProviderInfo>/<Helpdesk>
com_obj<IXMLDOMElement> pXmlElHelpdesk;
if (FAILED(hr = eapxml::create_element(pDoc, pXmlElProviderInfo, bstr(L"eap-metadata:Helpdesk"), bstr(L"Helpdesk"), bstrNamespace, &pXmlElHelpdesk)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <Helpdesk> element.");
// <ProviderInfo>/<Helpdesk>/<EmailAddress>
if (!m_help_email.empty())
if (FAILED(hr = eapxml::put_element_value(pDoc, pXmlElHelpdesk, bstr(L"EmailAddress"), bstrNamespace, bstr(m_help_email))))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <EmailAddress> element.");
// <ProviderInfo>/<Helpdesk>/<WebAddress>
if (!m_help_web.empty())
if (FAILED(hr = eapxml::put_element_value(pDoc, pXmlElHelpdesk, bstr(L"WebAddress"), bstrNamespace, bstr(m_help_web))))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <WebAddress> element.");
// <ProviderInfo>/<Helpdesk>/<Phone>
if (!m_help_phone.empty())
if (FAILED(hr = eapxml::put_element_value(pDoc, pXmlElHelpdesk, bstr(L"Phone"), bstrNamespace, bstr(m_help_phone))))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <Phone> element.");
// <ProviderInfo>/<CredentialPrompt>
if (!m_lbl_alt_credential.empty())
if (FAILED(hr = eapxml::put_element_value(pDoc, pXmlElProviderInfo, bstr(L"CredentialPrompt"), bstrNamespace, bstr(m_lbl_alt_credential))))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <CredentialPrompt> element.");
// <ProviderInfo>/<UserNameLabel>
if (!m_lbl_alt_identity.empty())
if (FAILED(hr = eapxml::put_element_value(pDoc, pXmlElProviderInfo, bstr(L"UserNameLabel"), bstrNamespace, bstr(m_lbl_alt_identity))))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <UserNameLabel> element.");
// <ProviderInfo>/<PasswordLabel>
if (!m_lbl_alt_password.empty())
if (FAILED(hr = eapxml::put_element_value(pDoc, pXmlElProviderInfo, bstr(L"PasswordLabel"), bstrNamespace, bstr(m_lbl_alt_password))))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <PasswordLabel> element.");
// <AuthenticationMethods>
com_obj<IXMLDOMElement> pXmlElAuthenticationMethods;
if (FAILED(hr = eapxml::create_element(pDoc, pConfigRoot, bstr(L"eap-metadata:AuthenticationMethods"), bstr(L"AuthenticationMethods"), bstrNamespace, &pXmlElAuthenticationMethods)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <AuthenticationMethods> element.");
for (vector<unique_ptr<config_method> >::const_iterator method = m_methods.cbegin(), method_end = m_methods.cend(); method != method_end; ++method) {
// <AuthenticationMethod>
com_obj<IXMLDOMElement> pXmlElAuthenticationMethod;
if (FAILED(hr = eapxml::create_element(pDoc, bstr(L"AuthenticationMethod"), bstrNamespace, &pXmlElAuthenticationMethod)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <AuthenticationMethod> element.");
// <AuthenticationMethod>/...
method->get()->save(pDoc, pXmlElAuthenticationMethod);
if (FAILED(hr = pXmlElAuthenticationMethods->appendChild(pXmlElAuthenticationMethod, NULL)))
throw com_runtime_error(hr, __FUNCTION__ " Error appending <AuthenticationMethod> element.");
}
}
void eap::config_provider::load(_In_ IXMLDOMNode *pConfigRoot)
{
assert(pConfigRoot);
HRESULT hr;
wstring xpath(eapxml::get_xpath(pConfigRoot));
config::load(pConfigRoot);
// <read-only>
if (FAILED(hr = eapxml::get_element_value(pConfigRoot, bstr(L"eap-metadata:read-only"), &m_read_only)))
m_read_only = true;
m_module.log_config((xpath + L"/read-only").c_str(), m_read_only);
// <ID>
m_id.clear();
eapxml::get_element_value(pConfigRoot, bstr(L"eap-metadata:ID"), m_id);
m_module.log_config((xpath + L"/ID").c_str(), m_id.c_str());
// <ProviderInfo>
m_name.clear();
m_help_email.clear();
m_help_web.clear();
m_help_phone.clear();
m_lbl_alt_credential.clear();
m_lbl_alt_identity.clear();
m_lbl_alt_password.clear();
com_obj<IXMLDOMElement> pXmlElProviderInfo;
if (SUCCEEDED(eapxml::select_element(pConfigRoot, bstr(L"eap-metadata:ProviderInfo"), &pXmlElProviderInfo))) {
wstring lang;
LoadString(m_module.m_instance, 2, lang);
wstring xpathProviderInfo(xpath + L"/ProviderInfo");
// <DisplayName>
eapxml::get_element_localized(pXmlElProviderInfo, bstr(L"eap-metadata:DisplayName"), lang.c_str(), m_name);
m_module.log_config((xpathProviderInfo + L"/DisplayName").c_str(), m_name.c_str());
com_obj<IXMLDOMElement> pXmlElHelpdesk;
if (SUCCEEDED(eapxml::select_element(pXmlElProviderInfo, bstr(L"eap-metadata:Helpdesk"), &pXmlElHelpdesk))) {
wstring xpathHelpdesk(xpathProviderInfo + L"/Helpdesk");
// <Helpdesk>/<EmailAddress>
eapxml::get_element_localized(pXmlElHelpdesk, bstr(L"eap-metadata:EmailAddress"), lang.c_str(), m_help_email);
m_module.log_config((xpathHelpdesk + L"/EmailAddress").c_str(), m_help_email.c_str());
// <Helpdesk>/<WebAddress>
eapxml::get_element_localized(pXmlElHelpdesk, bstr(L"eap-metadata:WebAddress"), lang.c_str(), m_help_web);
m_module.log_config((xpathHelpdesk + L"/WebAddress").c_str(), m_help_web.c_str());
// <Helpdesk>/<Phone>
eapxml::get_element_localized(pXmlElHelpdesk, bstr(L"eap-metadata:Phone"), lang.c_str(), m_help_phone);
m_module.log_config((xpathHelpdesk + L"/Phone").c_str(), m_help_phone.c_str());
}
// <CredentialPrompt>
eapxml::get_element_localized(pXmlElProviderInfo, bstr(L"eap-metadata:CredentialPrompt"), lang.c_str(), m_lbl_alt_credential);
m_module.log_config((xpathProviderInfo + L"/CredentialPrompt").c_str(), m_lbl_alt_credential.c_str());
// <UserNameLabel>
eapxml::get_element_localized(pXmlElProviderInfo, bstr(L"eap-metadata:UserNameLabel"), lang.c_str(), m_lbl_alt_identity);
m_module.log_config((xpathProviderInfo + L"/UserNameLabel").c_str(), m_lbl_alt_identity.c_str());
// <PasswordLabel>
eapxml::get_element_localized(pXmlElProviderInfo, bstr(L"eap-metadata:PasswordLabel"), lang.c_str(), m_lbl_alt_password);
m_module.log_config((xpathProviderInfo + L"/PasswordLabel").c_str(), m_lbl_alt_password.c_str());
}
// Iterate authentication methods (<AuthenticationMethods>).
m_methods.clear();
com_obj<IXMLDOMNodeList> pXmlListMethods;
if (FAILED(hr = eapxml::select_nodes(pConfigRoot, bstr(L"eap-metadata:AuthenticationMethods/eap-metadata:AuthenticationMethod"), &pXmlListMethods)))
throw com_runtime_error(hr, __FUNCTION__ " Error selecting <AuthenticationMethods>/<AuthenticationMethod> elements.");
long lCount = 0;
pXmlListMethods->get_length(&lCount);
for (long i = 0; i < lCount; i++) {
com_obj<IXMLDOMNode> pXmlElMethod;
pXmlListMethods->get_item(i, &pXmlElMethod);
unique_ptr<config_method> cfg(m_module.make_config_method());
// Check EAP method type (<EAPMethod>).
DWORD dwMethodID;
if (SUCCEEDED(eapxml::get_element_value(pXmlElMethod, bstr(L"eap-metadata:EAPMethod"), &dwMethodID))) {
if ((eap_type_t)dwMethodID != cfg->get_method_id()) {
// Wrong type.
continue;
}
}
// Load configuration.
cfg->load(pXmlElMethod);
// Add configuration to the list.
m_methods.push_back(std::move(cfg));
}
}
void eap::config_provider::operator<<(_Inout_ cursor_out &cursor) const
{
config::operator<<(cursor);
cursor << m_read_only ;
cursor << m_id ;
cursor << m_name ;
cursor << m_help_email ;
cursor << m_help_web ;
cursor << m_help_phone ;
cursor << m_lbl_alt_credential;
cursor << m_lbl_alt_identity ;
cursor << m_lbl_alt_password ;
cursor << m_methods ;
}
size_t eap::config_provider::get_pk_size() const
{
return
config::get_pk_size() +
pksizeof(m_read_only ) +
pksizeof(m_id ) +
pksizeof(m_name ) +
pksizeof(m_help_email ) +
pksizeof(m_help_web ) +
pksizeof(m_help_phone ) +
pksizeof(m_lbl_alt_credential) +
pksizeof(m_lbl_alt_identity ) +
pksizeof(m_lbl_alt_password ) +
pksizeof(m_methods );
}
void eap::config_provider::operator>>(_Inout_ cursor_in &cursor)
{
config::operator>>(cursor);
cursor >> m_read_only ;
cursor >> m_id ;
cursor >> m_name ;
cursor >> m_help_email ;
cursor >> m_help_web ;
cursor >> m_help_phone ;
cursor >> m_lbl_alt_credential;
cursor >> m_lbl_alt_identity ;
cursor >> m_lbl_alt_password ;
list<config_method>::size_type count;
bool is_nonnull;
cursor >> count;
m_methods.clear();
for (list<config_method>::size_type i = 0; i < count; i++) {
cursor >> is_nonnull;
if (is_nonnull) {
unique_ptr<config_method> el(m_module.make_config_method());
cursor >> *el;
m_methods.push_back(std::move(el));
} else
m_methods.push_back(nullptr);
}
}
//////////////////////////////////////////////////////////////////////
// eap::config_provider_list
//////////////////////////////////////////////////////////////////////
eap::config_provider_list::config_provider_list(_In_ module &mod) : config(mod)
{
}
eap::config_provider_list::config_provider_list(_In_ const config_provider_list &other) :
m_providers(other.m_providers),
config(other)
{
}
eap::config_provider_list::config_provider_list(_Inout_ config_provider_list &&other) :
m_providers(std::move(other.m_providers)),
config(std::move(other))
{
}
eap::config_provider_list& eap::config_provider_list::operator=(_In_ const config_provider_list &other)
{
if (this != &other) {
(config&)*this = other;
m_providers = other.m_providers;
}
return *this;
}
eap::config_provider_list& eap::config_provider_list::operator=(_Inout_ config_provider_list &&other)
{
if (this != &other) {
(config&&)*this = std::move(other);
m_providers = std::move(other.m_providers);
}
return *this;
}
eap::config* eap::config_provider_list::clone() const
{
return new config_provider_list(*this);
}
void eap::config_provider_list::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const
{
config::save(pDoc, pConfigRoot);
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
HRESULT hr;
// Select <EAPIdentityProviderList> node.
com_obj<IXMLDOMNode> pXmlElIdentityProviderList;
if (FAILED(hr = eapxml::select_node(pConfigRoot, bstr(L"eap-metadata:EAPIdentityProviderList"), &pXmlElIdentityProviderList)))
throw com_runtime_error(hr, __FUNCTION__ " Error selecting <EAPIdentityProviderList> element.");
for (vector<config_provider>::const_iterator provider = m_providers.cbegin(), provider_end = m_providers.cend(); provider != provider_end; ++provider) {
// <EAPIdentityProvider>
com_obj<IXMLDOMElement> pXmlElIdentityProvider;
if (FAILED(hr = eapxml::create_element(pDoc, bstr(L"EAPIdentityProvider"), bstrNamespace, &pXmlElIdentityProvider)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <EAPIdentityProvider> element.");
// <EAPIdentityProvider>/...
provider->save(pDoc, pXmlElIdentityProvider);
if (FAILED(hr = pXmlElIdentityProviderList->appendChild(pXmlElIdentityProvider, NULL)))
throw com_runtime_error(hr, __FUNCTION__ " Error appending <EAPIdentityProvider> element.");
}
}
void eap::config_provider_list::load(_In_ IXMLDOMNode *pConfigRoot)
{
assert(pConfigRoot);
HRESULT hr;
config::load(pConfigRoot);
// Iterate authentication providers (<EAPIdentityProvider>).
com_obj<IXMLDOMNodeList> pXmlListProviders;
if (FAILED(hr = eapxml::select_nodes(pConfigRoot, bstr(L"eap-metadata:EAPIdentityProviderList/eap-metadata:EAPIdentityProvider"), &pXmlListProviders)))
throw com_runtime_error(hr, __FUNCTION__ " Error selecting <EAPIdentityProviderList><EAPIdentityProvider> elements.");
long lCount = 0;
pXmlListProviders->get_length(&lCount);
for (long i = 0; i < lCount; i++) {
com_obj<IXMLDOMNode> pXmlElProvider;
pXmlListProviders->get_item(i, &pXmlElProvider);
config_provider prov(m_module);
// Load provider.
prov.load(pXmlElProvider);
// Add provider to the list.
m_providers.push_back(std::move(prov));
}
}
void eap::config_provider_list::operator<<(_Inout_ cursor_out &cursor) const
{
config::operator<<(cursor);
cursor << m_providers;
}
size_t eap::config_provider_list::get_pk_size() const
{
return
config::get_pk_size() +
pksizeof(m_providers);
}
void eap::config_provider_list::operator>>(_Inout_ cursor_in &cursor)
{
config::operator>>(cursor);
list<config_provider>::size_type count;
cursor >> count;
m_providers.clear();
for (list<config_provider>::size_type i = 0; i < count; i++) {
config_provider el(m_module);
cursor >> el;
m_providers.push_back(std::move(el));
}
}

View File

@@ -36,14 +36,12 @@ eap::credentials::credentials(_In_ module &mod) : config(mod)
eap::credentials::credentials(_In_ const credentials &other) :
m_identity(other.m_identity),
config(other)
{
}
eap::credentials::credentials(_Inout_ credentials &&other) :
m_identity(std::move(other.m_identity)),
config(std::move(other))
{
}
@@ -51,10 +49,8 @@ eap::credentials::credentials(_Inout_ credentials &&other) :
eap::credentials& eap::credentials::operator=(_In_ const credentials &other)
{
if (this != &other) {
if (this != &other)
(config&)*this = other;
m_identity = other.m_identity;
}
return *this;
}
@@ -62,10 +58,8 @@ eap::credentials& eap::credentials::operator=(_In_ const credentials &other)
eap::credentials& eap::credentials::operator=(_Inout_ credentials &&other)
{
if (this != &other) {
if (this != &other)
(config&)*this = std::move(other);
m_identity = std::move(other.m_identity);
}
return *this;
}
@@ -73,42 +67,19 @@ eap::credentials& eap::credentials::operator=(_Inout_ credentials &&other)
void eap::credentials::clear()
{
m_identity.clear();
}
bool eap::credentials::empty() const
{
return m_identity.empty();
}
bool eap::credentials::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const
{
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
DWORD dwResult;
// <UserName>
if ((dwResult = eapxml::put_element_value(pDoc, pConfigRoot, bstr(L"UserName"), bstrNamespace, bstr(m_identity))) != ERROR_SUCCESS) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <UserName> element."), NULL);
return false;
}
// Base class always report empty credentials.
return true;
}
bool eap::credentials::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError)
tstring eap::credentials::get_name() const
{
assert(pConfigRoot);
DWORD dwResult;
if ((dwResult = eapxml::get_element_value(pConfigRoot, bstr(L"eap-metadata:UserName"), m_identity)) != ERROR_SUCCESS) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error reading <UserName> element."), NULL);
return false;
}
return true;
return !empty() ? get_identity() : _T("<blank>");
}
@@ -122,6 +93,7 @@ eap::credentials_pass::credentials_pass(_In_ module &mod) : credentials(mod)
eap::credentials_pass::credentials_pass(_In_ const credentials_pass &other) :
m_identity(other.m_identity),
m_password(other.m_password),
credentials(other)
{
@@ -129,6 +101,7 @@ eap::credentials_pass::credentials_pass(_In_ const credentials_pass &other) :
eap::credentials_pass::credentials_pass(_Inout_ credentials_pass &&other) :
m_identity(std::move(other.m_identity)),
m_password(std::move(other.m_password)),
credentials(std::move(other))
{
@@ -139,6 +112,7 @@ eap::credentials_pass& eap::credentials_pass::operator=(_In_ const credentials_p
{
if (this != &other) {
(credentials&)*this = other;
m_identity = other.m_identity;
m_password = other.m_password;
}
@@ -150,6 +124,7 @@ eap::credentials_pass& eap::credentials_pass::operator=(_Inout_ credentials_pass
{
if (this != &other) {
(credentials&)*this = std::move(other);
m_identity = std::move(other.m_identity);
m_password = std::move(other.m_password);
}
@@ -160,91 +135,114 @@ eap::credentials_pass& eap::credentials_pass::operator=(_Inout_ credentials_pass
void eap::credentials_pass::clear()
{
credentials::clear();
m_identity.clear();
m_password.clear();
}
bool eap::credentials_pass::empty() const
{
return credentials::empty() && m_password.empty();
return credentials::empty() && m_identity.empty() && m_password.empty();
}
bool eap::credentials_pass::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const
void eap::credentials_pass::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const
{
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
DWORD dwResult;
assert(pDoc);
assert(pConfigRoot);
if (!credentials::save(pDoc, pConfigRoot, ppEapError))
return false;
credentials::save(pDoc, pConfigRoot);
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
HRESULT hr;
// <UserName>
if (FAILED(hr = eapxml::put_element_value(pDoc, pConfigRoot, bstr(L"UserName"), bstrNamespace, bstr(m_identity))))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <UserName> element.");
// <Password>
bstr pass(m_password);
dwResult = eapxml::put_element_value(pDoc, pConfigRoot, bstr(L"Password"), bstrNamespace, pass);
hr = eapxml::put_element_value(pDoc, pConfigRoot, bstr(L"Password"), bstrNamespace, pass);
SecureZeroMemory((BSTR)pass, sizeof(OLECHAR)*pass.length());
if (dwResult != ERROR_SUCCESS) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <Password> element."), NULL);
return false;
}
return true;
if (FAILED(hr))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <Password> element.");
}
bool eap::credentials_pass::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError)
void eap::credentials_pass::load(_In_ IXMLDOMNode *pConfigRoot)
{
assert(pConfigRoot);
DWORD dwResult;
HRESULT hr;
if (!credentials::load(pConfigRoot, ppEapError))
return false;
credentials::load(pConfigRoot);
std::wstring xpath(eapxml::get_xpath(pConfigRoot));
if (FAILED(hr = eapxml::get_element_value(pConfigRoot, bstr(L"eap-metadata:UserName"), m_identity)))
throw com_runtime_error(hr, __FUNCTION__ " Error reading <UserName> element.");
m_module.log_config((xpath + L"/UserName").c_str(), m_identity.c_str());
bstr pass;
if ((dwResult = eapxml::get_element_value(pConfigRoot, bstr(L"eap-metadata:Password"), &pass)) != ERROR_SUCCESS) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error reading <Password> element."), NULL);
return false;
}
if (FAILED(hr = eapxml::get_element_value(pConfigRoot, bstr(L"eap-metadata:Password"), &pass)))
throw com_runtime_error(hr, __FUNCTION__ " Error reading <Password> element.");
m_password = pass;
SecureZeroMemory((BSTR)pass, sizeof(OLECHAR)*pass.length());
return true;
m_module.log_config((xpath + L"/Password").c_str(),
#ifdef _DEBUG
m_password.c_str()
#else
L"********"
#endif
);
}
bool eap::credentials_pass::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError) const
void eap::credentials_pass::operator<<(_Inout_ cursor_out &cursor) const
{
credentials::operator<<(cursor);
cursor << m_identity;
cursor << m_password;
}
size_t eap::credentials_pass::get_pk_size() const
{
return
credentials::get_pk_size() +
pksizeof(m_identity) +
pksizeof(m_password);
}
void eap::credentials_pass::operator>>(_Inout_ cursor_in &cursor)
{
credentials::operator>>(cursor);
cursor >> m_identity;
cursor >> m_password;
}
void eap::credentials_pass::store(_In_z_ LPCTSTR pszTargetName) const
{
assert(pszTargetName);
assert(ppEapError);
string password_enc;
// Prepare cryptographics provider.
crypt_prov cp;
if (!cp.create(NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptAcquireContext failed."), NULL);
return false;
}
// Encrypt password.
vector<unsigned char> password;
if (!m_module.encrypt_md5(cp, m_password, password, ppEapError))
return false;
// Convert encrypted password to Base64, since CredProtectA() fail for binary strings.
string password_base64;
base64_enc enc;
enc.encode(password_base64, password.data(), password.size());
// Convert password to UTF-8.
sanitizing_string cred_utf8;
WideCharToMultiByte(CP_UTF8, 0, m_password.c_str(), (int)m_password.length(), cred_utf8, NULL, NULL);
// Encrypt the password using user's key.
CRED_PROTECTION_TYPE cpt;
if (!CredProtectA(TRUE, password_base64.c_str(), (DWORD)password_base64.length(), password_enc, &cpt)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredProtect failed."), NULL);
return false;
}
DATA_BLOB cred_blob = { (DWORD)cred_utf8.size() , (LPBYTE)cred_utf8.data() };
DATA_BLOB entropy_blob = { sizeof(s_entropy), (LPBYTE)s_entropy };
data_blob cred_enc;
if (!CryptProtectData(&cred_blob, NULL, &entropy_blob, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &cred_enc))
throw win_runtime_error(__FUNCTION__ " CryptProtectData failed.");
tstring target(target_name(pszTargetName));
// Write credentials.
assert(password_enc.size() < CRED_MAX_CREDENTIAL_BLOB_SIZE);
assert(cred_enc.cbData < CRED_MAX_CREDENTIAL_BLOB_SIZE);
assert(m_identity.length() < CRED_MAX_USERNAME_LENGTH );
CREDENTIAL cred = {
0, // Flags
@@ -252,56 +250,125 @@ bool eap::credentials_pass::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **
(LPTSTR)target.c_str(), // TargetName
_T(""), // Comment
{ 0, 0 }, // LastWritten
(DWORD)password_enc.size(), // CredentialBlobSize
(LPBYTE)password_enc.data(),// CredentialBlob
cred_enc.cbData, // CredentialBlobSize
cred_enc.pbData, // CredentialBlob
CRED_PERSIST_ENTERPRISE, // Persist
0, // AttributeCount
NULL, // Attributes
NULL, // TargetAlias
(LPTSTR)m_identity.c_str() // UserName
};
if (!CredWrite(&cred, 0)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredWrite failed."), NULL);
return false;
}
return true;
if (!CredWrite(&cred, 0))
throw win_runtime_error(__FUNCTION__ " CredWrite failed.");
}
bool eap::credentials_pass::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError)
void eap::credentials_pass::retrieve(_In_z_ LPCTSTR pszTargetName)
{
assert(pszTargetName);
// Read credentials.
unique_ptr<CREDENTIAL, CredFree_delete<CREDENTIAL> > cred;
if (!CredRead(target_name(pszTargetName).c_str(), CRED_TYPE_GENERIC, 0, (PCREDENTIAL*)&cred)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredRead failed."), NULL);
return false;
}
m_identity = cred->UserName;
if (!CredRead(target_name(pszTargetName).c_str(), CRED_TYPE_GENERIC, 0, (PCREDENTIAL*)&cred))
throw win_runtime_error(__FUNCTION__ " CredRead failed.");
// Decrypt the password using user's key.
string password_base64;
if (!CredUnprotectA(TRUE, (LPCSTR)(cred->CredentialBlob), cred->CredentialBlobSize, password_base64)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredUnprotect failed."), NULL);
return false;
}
DATA_BLOB cred_enc = { cred->CredentialBlobSize, cred->CredentialBlob };
DATA_BLOB entropy_blob = { sizeof(s_entropy) , (LPBYTE)s_entropy };
data_blob cred_int;
if (!CryptUnprotectData(&cred_enc, NULL, &entropy_blob, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN | CRYPTPROTECT_VERIFY_PROTECTION, &cred_int))
throw win_runtime_error(__FUNCTION__ " CryptUnprotectData failed.");
// Convert Base64 to binary encrypted password, since CredProtectA() fail for binary strings.
vector<unsigned char> password;
base64_dec dec;
bool is_last;
dec.decode(password, is_last, password_base64.c_str(), password_base64.length());
// Convert password from UTF-8.
MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)cred_int.pbData, (int)cred_int.cbData, m_password);
SecureZeroMemory(cred_int.pbData, cred_int.cbData);
// Prepare cryptographics provider.
crypt_prov cp;
if (!cp.create(NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptAcquireContext failed."), NULL);
return false;
}
if (cred->UserName)
m_identity = cred->UserName;
else
m_identity.clear();
// Decrypt password.
return m_module.decrypt_md5(cp, password.data(), password.size(), m_password, ppEapError);
wstring xpath(pszTargetName);
m_module.log_config((xpath + L"/Username").c_str(), m_identity.c_str());
m_module.log_config((xpath + L"/Password").c_str(),
#ifdef _DEBUG
m_password.c_str()
#else
L"********"
#endif
);
}
std::wstring eap::credentials_pass::get_identity() const
{
return m_identity;
}
const unsigned char eap::credentials_pass::s_entropy[1024] = {
0x40, 0x88, 0xd3, 0x13, 0x81, 0x8a, 0xf6, 0x74, 0x55, 0x8e, 0xcc, 0x73, 0x2c, 0xf8, 0x93, 0x37,
0x4f, 0xeb, 0x1d, 0x66, 0xb7, 0xfb, 0x47, 0x75, 0xb4, 0xfd, 0x07, 0xbb, 0xf6, 0xb3, 0x05, 0x30,
0x4a, 0xc0, 0xff, 0x05, 0xbd, 0x1e, 0x2f, 0x55, 0xc8, 0x77, 0x70, 0x47, 0xc9, 0x85, 0x57, 0x22,
0x8e, 0x54, 0x0b, 0x4d, 0x26, 0x80, 0x11, 0x0c, 0x52, 0x55, 0xc2, 0x3b, 0x9b, 0xd2, 0x19, 0x61,
0xf1, 0x71, 0xf5, 0x4b, 0x49, 0x73, 0xf9, 0x6d, 0x44, 0xd2, 0x90, 0x92, 0x2d, 0xae, 0xc6, 0xbb,
0x3d, 0xfe, 0x52, 0x47, 0x82, 0xc1, 0xa9, 0xe1, 0x6a, 0xd1, 0xd2, 0x4e, 0x3d, 0x9b, 0x4e, 0xc0,
0x40, 0x36, 0x79, 0xd3, 0x88, 0xfc, 0x0b, 0x79, 0x8c, 0xb2, 0x9d, 0x74, 0x13, 0x29, 0x59, 0x0c,
0xe0, 0x87, 0x34, 0x7d, 0xc1, 0x30, 0xd4, 0xe9, 0x98, 0xd1, 0x3f, 0x82, 0xcb, 0x8b, 0x44, 0x09,
0x2d, 0xc5, 0x9e, 0x3d, 0x66, 0xe5, 0x1a, 0x9d, 0xa6, 0x87, 0x20, 0x7f, 0x55, 0xd7, 0x89, 0xf2,
0xbb, 0x5f, 0x00, 0xf9, 0x38, 0xd3, 0x49, 0x10, 0x6f, 0x3a, 0xab, 0x5d, 0x8f, 0x73, 0x8c, 0xbc,
0x6f, 0xf1, 0xef, 0x83, 0x43, 0xcb, 0xc9, 0xb7, 0x9f, 0x24, 0xe4, 0x91, 0x3a, 0xe6, 0xab, 0x6c,
0xf2, 0xfd, 0x66, 0xf0, 0xb1, 0x1a, 0xc8, 0xc4, 0x6b, 0x9d, 0xa7, 0x10, 0x7d, 0x30, 0x29, 0x1b,
0xe5, 0xfe, 0x1c, 0x97, 0x86, 0x1e, 0x80, 0xe5, 0x12, 0x0a, 0x2a, 0x0d, 0xd9, 0x4a, 0x35, 0xe5,
0xab, 0xdf, 0x61, 0x76, 0x4e, 0x36, 0xff, 0xb1, 0x26, 0x5e, 0x12, 0x7f, 0xdf, 0xd7, 0x98, 0x55,
0xf9, 0x89, 0x30, 0xcc, 0xe9, 0xf6, 0xd0, 0xc0, 0x69, 0xf4, 0x78, 0x81, 0x10, 0xeb, 0x34, 0xf3,
0x5a, 0x8a, 0x62, 0xd4, 0x97, 0xe6, 0xb7, 0x98, 0x86, 0x5f, 0xb6, 0xcb, 0x9c, 0xab, 0xd6, 0xe9,
0xda, 0x2b, 0x41, 0xbb, 0xa3, 0x37, 0x1f, 0x7d, 0x4e, 0x19, 0x13, 0xc3, 0xab, 0x23, 0x4d, 0xa6,
0x51, 0xa9, 0x07, 0x60, 0xb9, 0x0c, 0x49, 0xce, 0x40, 0x29, 0x15, 0x0d, 0x10, 0xde, 0xc9, 0x0c,
0x11, 0x91, 0xdc, 0xdf, 0xc8, 0xac, 0x13, 0xe5, 0xe9, 0x11, 0xdc, 0x47, 0xb7, 0xb3, 0xf5, 0xd0,
0xc4, 0x38, 0x10, 0x17, 0xf7, 0x93, 0x93, 0x6b, 0x56, 0x10, 0xc6, 0xa6, 0x4c, 0xf8, 0x9c, 0x52,
0xb7, 0xbd, 0x87, 0xe8, 0xff, 0x84, 0x01, 0xbb, 0x40, 0x84, 0x03, 0x19, 0x6f, 0xf7, 0x46, 0x6f,
0x10, 0xc0, 0x85, 0xdf, 0xfd, 0xad, 0x00, 0xf6, 0xd5, 0x05, 0x22, 0xf4, 0x28, 0x87, 0xf6, 0x0c,
0xca, 0xda, 0x9a, 0x67, 0x63, 0xa4, 0x2d, 0x4d, 0xa5, 0x06, 0xa1, 0x8b, 0x32, 0x9b, 0xb0, 0xed,
0x05, 0x8e, 0x36, 0xa4, 0xbe, 0xa0, 0x9c, 0x78, 0xfa, 0x2c, 0x9e, 0x99, 0x02, 0x50, 0x63, 0xd4,
0xd5, 0x4a, 0x9b, 0xc3, 0x81, 0x95, 0xab, 0x18, 0x47, 0x3d, 0x44, 0x15, 0x33, 0x79, 0xd0, 0x53,
0x4e, 0xfc, 0x2f, 0x66, 0xc9, 0x7c, 0xb9, 0xda, 0xa2, 0xce, 0xfa, 0x39, 0xea, 0x72, 0x2c, 0xe2,
0x5c, 0x1f, 0x7e, 0xcd, 0x2a, 0x3e, 0x11, 0x19, 0x06, 0xc7, 0x03, 0x89, 0x4c, 0xd3, 0x73, 0xea,
0xa5, 0x69, 0x1e, 0x68, 0x04, 0xcd, 0xbb, 0xc4, 0x74, 0x7b, 0x1e, 0x75, 0x6f, 0xf1, 0x89, 0xea,
0x21, 0xdf, 0x9e, 0x1b, 0x27, 0x4a, 0x20, 0xb4, 0x5b, 0x72, 0x68, 0x8e, 0x47, 0xe2, 0x18, 0x75,
0x36, 0x82, 0xae, 0xa9, 0xa9, 0x40, 0xe5, 0x19, 0xa7, 0xea, 0x48, 0xad, 0x26, 0x7c, 0x93, 0x3e,
0xbf, 0x48, 0x6c, 0x3e, 0x66, 0xf7, 0x3c, 0x8f, 0x3c, 0x0e, 0x77, 0xc8, 0xb5, 0x56, 0x3b, 0x3a,
0x25, 0x13, 0x49, 0xb4, 0xcc, 0xbb, 0x8e, 0x94, 0x73, 0xa4, 0x35, 0x16, 0x95, 0x74, 0xa5, 0x98,
0xa4, 0x61, 0xa2, 0x36, 0xaf, 0x7f, 0xdf, 0x04, 0xce, 0x34, 0xd3, 0xfc, 0x09, 0x83, 0x43, 0xc1,
0x7a, 0x22, 0xc7, 0xfa, 0x3d, 0x97, 0xce, 0xc0, 0xcd, 0x15, 0xa4, 0x97, 0xb4, 0xd4, 0x55, 0x51,
0xf1, 0xef, 0x81, 0x1a, 0xce, 0x1f, 0x5a, 0x2d, 0xba, 0xce, 0xec, 0xbd, 0x85, 0x57, 0x53, 0xc6,
0x2f, 0x2a, 0x84, 0xab, 0xf3, 0x6e, 0x3b, 0xac, 0xf8, 0x73, 0xf2, 0x20, 0x42, 0x6f, 0xc4, 0xe2,
0x20, 0xb7, 0xf8, 0x5e, 0xbd, 0xe7, 0xd2, 0x2b, 0xe6, 0x10, 0xc2, 0x66, 0xe7, 0x25, 0xf9, 0xb9,
0xcb, 0xe4, 0x85, 0xbd, 0xf9, 0x62, 0x10, 0xfd, 0x67, 0x8f, 0x3f, 0x15, 0x4b, 0x10, 0x9e, 0xde,
0x8a, 0x9c, 0xb5, 0x46, 0xb7, 0x96, 0xa8, 0x9d, 0xe8, 0xf1, 0xde, 0x34, 0xcf, 0x4c, 0xa4, 0xe6,
0x35, 0x24, 0xcf, 0x47, 0xc5, 0x2d, 0xf2, 0xe3, 0x15, 0xf3, 0x39, 0xb7, 0x45, 0x2c, 0x92, 0x23,
0x37, 0x28, 0xfa, 0x7b, 0x7b, 0xe9, 0xc3, 0x04, 0x57, 0x0c, 0x30, 0xab, 0x52, 0x3a, 0x1d, 0xf7,
0x3a, 0x7b, 0xa0, 0xf0, 0x22, 0x14, 0xa8, 0xc7, 0x4e, 0xd5, 0x8b, 0x9a, 0xac, 0x67, 0x33, 0x0a,
0xa2, 0xa4, 0x76, 0x65, 0x45, 0x48, 0x7d, 0x92, 0xd7, 0xdb, 0xb1, 0x51, 0xae, 0x5f, 0x95, 0x1c,
0x8c, 0xe0, 0xaa, 0x28, 0x72, 0xbb, 0x2d, 0x97, 0x65, 0xfb, 0x3f, 0x41, 0x06, 0x46, 0xd1, 0x8c,
0x99, 0x64, 0x0e, 0xc7, 0xf0, 0x82, 0x1f, 0x1e, 0x5e, 0x8a, 0xc8, 0x6e, 0x29, 0xf0, 0xa8, 0x38,
0xa5, 0x38, 0x12, 0xaa, 0x9d, 0x60, 0x3d, 0x40, 0xfc, 0x29, 0x17, 0xc5, 0xe1, 0x1d, 0xba, 0x14,
0x45, 0xf0, 0x16, 0x32, 0x8f, 0x37, 0x88, 0xad, 0x7c, 0x77, 0x57, 0x06, 0x89, 0x70, 0x1f, 0x0e,
0x88, 0x9d, 0x2b, 0x5f, 0x83, 0x69, 0xb0, 0x48, 0x03, 0x86, 0xe4, 0x2e, 0x1c, 0xfb, 0x85, 0xb1,
0xce, 0x1c, 0x0e, 0xe0, 0xd4, 0x17, 0x0f, 0xb2, 0xf1, 0x79, 0xde, 0x8f, 0xd2, 0x0a, 0xa5, 0x10,
0xee, 0x9e, 0x05, 0x57, 0x0d, 0x42, 0x21, 0xaa, 0x53, 0xb1, 0x53, 0xd9, 0x59, 0x8b, 0x43, 0x22,
0x82, 0xbe, 0xa3, 0x2a, 0x79, 0x89, 0x46, 0xc4, 0x18, 0x31, 0x3e, 0xd4, 0x3d, 0x79, 0x9b, 0x06,
0xde, 0x7e, 0xe5, 0x20, 0xdd, 0xae, 0x34, 0xa8, 0x31, 0xc2, 0xdf, 0x61, 0x6d, 0x1b, 0x47, 0xc4,
0xae, 0x25, 0x44, 0xa8, 0x79, 0x5c, 0x2b, 0x4a, 0x17, 0x6e, 0x7a, 0xe5, 0xf1, 0x48, 0x3f, 0x82,
0x24, 0x6a, 0xc5, 0xc1, 0xfc, 0x65, 0x61, 0xca, 0xe4, 0x89, 0x52, 0x14, 0xe4, 0xb3, 0x7a, 0x24,
0xc2, 0xe5, 0x59, 0x1d, 0x55, 0xa3, 0x95, 0x16, 0xe2, 0xcf, 0x07, 0xd8, 0xad, 0x9c, 0x30, 0xbe,
0x96, 0xee, 0x80, 0x54, 0x63, 0xe7, 0xd4, 0xa6, 0xac, 0xe8, 0x15, 0xd4, 0xfc, 0x7b, 0xf8, 0xee,
0x0e, 0x88, 0x51, 0xd9, 0xad, 0x6f, 0x0d, 0xea, 0x19, 0x3a, 0x1a, 0x20, 0xbc, 0x99, 0x59, 0xcc,
0xba, 0x19, 0xc8, 0x26, 0x79, 0x79, 0xe8, 0xf6, 0x3f, 0xa0, 0xdb, 0xa6, 0x52, 0x4d, 0xc0, 0x98,
0x22, 0xcf, 0x30, 0xae, 0xdf, 0x22, 0x94, 0x5c, 0x19, 0x01, 0xe3, 0xf0, 0x44, 0x23, 0xe5, 0xeb,
0x70, 0x1a, 0xd2, 0x7f, 0xe8, 0x91, 0x1b, 0x55, 0xe7, 0xcb, 0x0d, 0xc2, 0x53, 0xa0, 0xe6, 0x7a,
0x48, 0xab, 0x05, 0xbb, 0x55, 0x28, 0x98, 0x12, 0xe5, 0xd1, 0xd9, 0x44, 0xe9, 0xa8, 0x8d, 0xa4,
0x68, 0xc8, 0x21, 0xa8, 0xe9, 0x49, 0x46, 0x22, 0xce, 0x81, 0xfe, 0x4a, 0xe3, 0xa0, 0x1c, 0xb0,
0x30, 0x29, 0x39, 0x9a, 0xd6, 0xab, 0x2e, 0xc6, 0x42, 0x47, 0x5e, 0x54, 0xbb, 0x90, 0xe6, 0x98,
0xe6, 0x52, 0x58, 0x58, 0x1e, 0xd0, 0x00, 0x9c, 0x8f, 0x4a, 0x17, 0x7e, 0x8a, 0x5a, 0xef, 0x3e,
};

View File

@@ -0,0 +1,74 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StdAfx.h"
using namespace std;
using namespace winstd;
//////////////////////////////////////////////////////////////////////
// eap::method
//////////////////////////////////////////////////////////////////////
eap::method::method(_In_ module &module, _In_ config_provider_list &cfg, _In_ credentials &cred) :
m_module(module),
m_cfg(cfg),
m_cred(cred)
{
}
eap::method::method(_Inout_ method &&other) :
m_module(other.m_module),
m_cfg(other.m_cfg),
m_cred(other.m_cred)
{
}
eap::method& eap::method::operator=(_Inout_ method &&other)
{
if (this != std::addressof(other)) {
assert(std::addressof(m_module) == std::addressof(other.m_module)); // Move method within same module only!
assert(std::addressof(m_cfg ) == std::addressof(other.m_cfg )); // Move method with same configuration only!
assert(std::addressof(m_cred ) == std::addressof(other.m_cred )); // Move method with same credentials only!
}
return *this;
}
void eap::method::begin_session(
_In_ DWORD dwFlags,
_In_ const EapAttributes *pAttributeArray,
_In_ HANDLE hTokenImpersonateUser,
_In_ DWORD dwMaxSendPacketSize)
{
UNREFERENCED_PARAMETER(dwFlags);
UNREFERENCED_PARAMETER(pAttributeArray);
UNREFERENCED_PARAMETER(hTokenImpersonateUser);
UNREFERENCED_PARAMETER(dwMaxSendPacketSize);
}
void eap::method::end_session()
{
}

View File

@@ -28,12 +28,12 @@ using namespace winstd;
// eap::module
//////////////////////////////////////////////////////////////////////
eap::module::module(type_t eap_method) :
eap::module::module(eap_type_t eap_method) :
m_eap_method(eap_method),
m_instance(NULL)
{
m_ep.create(&EAPMETHOD_TRACE_EVENT_PROVIDER);
m_ep.write(&EAPMETHOD_TRACE_EVT_MODULE_LOAD, event_data((BYTE)m_eap_method), event_data::blank);
m_ep.write(&EAPMETHOD_TRACE_EVT_MODULE_LOAD, event_data((unsigned int)m_eap_method), event_data::blank);
m_heap.create(0, 0, 0);
}
@@ -41,17 +41,17 @@ eap::module::module(type_t eap_method) :
eap::module::~module()
{
m_ep.write(&EAPMETHOD_TRACE_EVT_MODULE_UNLOAD, event_data((BYTE)m_eap_method), event_data::blank);
m_ep.write(&EAPMETHOD_TRACE_EVT_MODULE_UNLOAD, event_data((unsigned int)m_eap_method), event_data::blank);
}
EAP_ERROR* eap::module::make_error(_In_ DWORD dwErrorCode, _In_ DWORD dwReasonCode, _In_ LPCGUID pRootCauseGuid, _In_ LPCGUID pRepairGuid, _In_ LPCGUID pHelpLinkGuid, _In_z_ LPCWSTR pszRootCauseString, _In_z_ LPCWSTR pszRepairString) const
EAP_ERROR* eap::module::make_error(_In_ DWORD dwErrorCode, _In_opt_z_ LPCWSTR pszRootCauseString, _In_opt_z_ LPCWSTR pszRepairString, _In_opt_ DWORD dwReasonCode, _In_opt_ LPCGUID pRootCauseGuid, _In_opt_ LPCGUID pRepairGuid, _In_opt_ LPCGUID pHelpLinkGuid) const
{
// Calculate memory size requirement.
SIZE_T
nRootCauseSize = pszRootCauseString != NULL && pszRootCauseString[0] ? (wcslen(pszRootCauseString) + 1)*sizeof(WCHAR) : 0,
nRepairStringSize = pszRepairString != NULL && pszRepairString [0] ? (wcslen(pszRepairString ) + 1)*sizeof(WCHAR) : 0,
nEapErrorSize = sizeof(EAP_ERROR) + nRootCauseSize + nRepairStringSize;
nEapErrorSize = sizeof(EAP_ERROR) + nRootCauseSize + nRepairStringSize;
EAP_ERROR *pError = (EAP_ERROR*)HeapAlloc(m_heap, 0, nEapErrorSize);
if (!pError)
@@ -81,110 +81,242 @@ EAP_ERROR* eap::module::make_error(_In_ DWORD dwErrorCode, _In_ DWORD dwReasonCo
} else
pError->pRepairString = NULL;
// Write trace event.
vector<EVENT_DATA_DESCRIPTOR> evt_desc;
evt_desc.reserve(8);
evt_desc.push_back(event_data(pError->dwWinError));
evt_desc.push_back(event_data(pError->type.eapType.type));
evt_desc.push_back(event_data(pError->dwReasonCode));
evt_desc.push_back(event_data(&(pError->rootCauseGuid), sizeof(GUID)));
evt_desc.push_back(event_data(&(pError->repairGuid), sizeof(GUID)));
evt_desc.push_back(event_data(&(pError->helpLinkGuid), sizeof(GUID)));
evt_desc.push_back(event_data(pError->pRootCauseString));
evt_desc.push_back(event_data(pError->pRepairString));
m_ep.write(&EAPMETHOD_TRACE_EAP_ERROR, (ULONG)evt_desc.size(), evt_desc.data());
return pError;
}
EAP_ERROR* eap::module::make_error(_In_ std::exception &err) const
{
wstring what;
MultiByteToWideChar(CP_ACP, 0, err.what(), -1, what);
{
win_runtime_error &e(dynamic_cast<win_runtime_error&>(err));
if (&e)
return make_error(e.number(), what.c_str());
}
{
com_runtime_error &e(dynamic_cast<com_runtime_error&>(err));
if (&e)
return make_error(HRESULT_CODE(e.number()), what.c_str());
}
{
sec_runtime_error &e(dynamic_cast<sec_runtime_error&>(err));
if (&e)
return make_error(HRESULT_CODE(e.number()), what.c_str());
}
{
invalid_argument &e(dynamic_cast<invalid_argument&>(err));
if (&e)
return make_error(ERROR_INVALID_PARAMETER, what.c_str());
}
wstring name;
MultiByteToWideChar(CP_ACP, 0, typeid(err).name(), -1, name);
name += L": ";
name += what;
return make_error(ERROR_INVALID_DATA, name.c_str());
}
BYTE* eap::module::alloc_memory(_In_ size_t size)
{
return (BYTE*)HeapAlloc(m_heap, 0, size);
BYTE *p = (BYTE*)HeapAlloc(m_heap, 0, size);
if (!p)
throw win_runtime_error(winstd::string_printf(__FUNCTION__ " Error allocating memory for BLOB (%uB).", size));
return p;
}
void eap::module::free_memory(_In_ BYTE *ptr)
{
ETW_FN_VOID;
#if !EAP_ENCRYPT_BLOBS
// Since we do security here and some of the BLOBs contain credentials, sanitize every memory block before freeing.
SecureZeroMemory(ptr, HeapSize(m_heap, 0, ptr));
#endif
HeapFree(m_heap, 0, ptr);
}
void eap::module::free_error_memory(_In_ EAP_ERROR *err)
{
ETW_FN_VOID;
// pRootCauseString and pRepairString always trail the ppEapError to reduce number of (de)allocations.
HeapFree(m_heap, 0, err);
}
bool eap::module::encrypt(_In_ HCRYPTPROV hProv, _In_bytecount_(size) const void *data, _In_ size_t size, _Out_ std::vector<unsigned char> &enc, _Out_ EAP_ERROR **ppEapError, _Out_opt_ HCRYPTHASH hHash) const
void eap::module::log_error(_In_ const EAP_ERROR *err) const
{
assert(ppEapError);
assert(err);
// Import the public key.
// Write trace event.
vector<EVENT_DATA_DESCRIPTOR> evt_desc;
evt_desc.reserve(8);
evt_desc.push_back(event_data(err->dwWinError));
DWORD dwType = err->type.eapType.type;
evt_desc.push_back(event_data(dwType));
evt_desc.push_back(event_data(err->dwReasonCode));
evt_desc.push_back(event_data(&(err->rootCauseGuid), sizeof(GUID)));
evt_desc.push_back(event_data(&(err->repairGuid), sizeof(GUID)));
evt_desc.push_back(event_data(&(err->helpLinkGuid), sizeof(GUID)));
evt_desc.push_back(event_data(err->pRootCauseString));
evt_desc.push_back(event_data(err->pRepairString));
m_ep.write(&EAPMETHOD_TRACE_EVT_EAP_ERROR, (ULONG)evt_desc.size(), evt_desc.data());
}
eap::config_method* eap::module::make_config_method()
{
return NULL;
}
std::vector<unsigned char> eap::module::encrypt(_In_ HCRYPTPROV hProv, _In_bytecount_(size) const void *data, _In_ size_t size, _Out_opt_ HCRYPTHASH hHash) const
{
// Generate 256-bit AES session key.
crypt_key key_aes;
if (!CryptGenKey(hProv, CALG_AES_256, MAKELONG(CRYPT_EXPORTABLE, 256), &key_aes))
throw win_runtime_error(__FUNCTION__ " CryptGenKey failed.");
// Import the public RSA key.
HRSRC res = FindResource(m_instance, MAKEINTRESOURCE(IDR_EAP_KEY_PUBLIC), RT_RCDATA);
assert(res);
HGLOBAL res_handle = LoadResource(m_instance, res);
assert(res_handle);
crypt_key key;
crypt_key key_rsa;
unique_ptr<CERT_PUBLIC_KEY_INFO, LocalFree_delete<CERT_PUBLIC_KEY_INFO> > keyinfo_data;
DWORD keyinfo_size = 0;
if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, (const BYTE*)::LockResource(res_handle), ::SizeofResource(m_instance, res), CRYPT_DECODE_ALLOC_FLAG, NULL, &keyinfo_data, &keyinfo_size)) {
*ppEapError = make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptDecodeObjectEx failed."), NULL);
return false;
}
if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, (const BYTE*)::LockResource(res_handle), ::SizeofResource(m_instance, res), CRYPT_DECODE_ALLOC_FLAG, NULL, &keyinfo_data, &keyinfo_size))
throw win_runtime_error(__FUNCTION__ " CryptDecodeObjectEx failed.");
if (!key_rsa.import_public(hProv, X509_ASN_ENCODING, keyinfo_data.get()))
throw win_runtime_error(__FUNCTION__ " Public key import failed.");
if (!key.import_public(hProv, X509_ASN_ENCODING, keyinfo_data.get())) {
*ppEapError = make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Public key import failed."), NULL);
return false;
}
// Export AES session key encrypted with public RSA key.
vector<unsigned char, sanitizing_allocator<unsigned char> > buf;
if (!CryptExportKey(key_aes, key_rsa, SIMPLEBLOB, 0, buf))
throw win_runtime_error(__FUNCTION__ " CryptExportKey failed.");
std::vector<unsigned char> enc(buf.begin(), buf.end());
// Pre-allocate memory to allow space, as encryption will grow the data.
buf.assign((const unsigned char*)data, (const unsigned char*)data + size);
DWORD dwBlockLen;
vector<unsigned char, sanitizing_allocator<unsigned char> > buf(size);
memcpy(buf.data(), data, size);
if (!CryptGetKeyParam(key, KP_BLOCKLEN, dwBlockLen, 0)) dwBlockLen = 0;
buf.reserve((size + dwBlockLen - 1) / dwBlockLen * dwBlockLen);
if (!CryptGetKeyParam(key_aes, KP_BLOCKLEN, dwBlockLen, 0)) dwBlockLen = 0;
buf.reserve((size + dwBlockLen) / dwBlockLen * dwBlockLen);
// Encrypt the data using our public key.
if (!CryptEncrypt(key, hHash, TRUE, 0, buf)) {
*ppEapError = make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Encrypting data failed."), NULL);
return false;
}
// Encrypt the data using AES key.
if (!CryptEncrypt(key_aes, hHash, TRUE, 0, buf))
throw win_runtime_error(__FUNCTION__ " CryptEncrypt failed.");
// Copy encrypted data.
enc.assign(buf.begin(), buf.end());
return true;
// Append encrypted data.
enc.insert(enc.cend(), buf.begin(), buf.end());
return enc;
}
bool eap::module::encrypt_md5(_In_ HCRYPTPROV hProv, _In_bytecount_(size) const void *data, _In_ size_t size, _Out_ std::vector<unsigned char> &enc, _Out_ EAP_ERROR **ppEapError) const
std::vector<unsigned char> eap::module::encrypt_md5(_In_ HCRYPTPROV hProv, _In_bytecount_(size) const void *data, _In_ size_t size) const
{
// Create hash.
crypt_hash hash;
if (!hash.create(hProv, CALG_MD5)) {
*ppEapError = make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Creating MD5 hash failed."), NULL);
return false;
}
if (!hash.create(hProv, CALG_MD5))
throw win_runtime_error(__FUNCTION__ " Creating MD5 hash failed.");
// Encrypt data.
if (!encrypt(hProv, data, size, enc, ppEapError, hash))
return false;
std::vector<unsigned char> enc(std::move(encrypt(hProv, data, size, hash)));
// Calculate MD5 hash.
vector<unsigned char> hash_bin;
if (!CryptGetHashParam(hash, HP_HASHVAL, hash_bin, 0)) {
*ppEapError = make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Calculating MD5 hash failed."), NULL);
return false;
}
if (!CryptGetHashParam(hash, HP_HASHVAL, hash_bin, 0))
throw invalid_argument(__FUNCTION__ " Calculating MD5 hash failed.");
// Append hash.
enc.insert(enc.end(), hash_bin.begin(), hash_bin.end());
return true;
return enc;
}
//////////////////////////////////////////////////////////////////////
// eap::peer
//////////////////////////////////////////////////////////////////////
eap::peer::peer(_In_ eap_type_t eap_method) : module(eap_method)
{
}
void eap::peer::query_credential_input_fields(
_In_ HANDLE hUserImpersonationToken,
_In_ DWORD dwFlags,
_In_ DWORD dwConnectionDataSize,
_In_count_(dwConnectionDataSize) const BYTE *pConnectionData,
_Inout_ EAP_CONFIG_INPUT_FIELD_ARRAY *pEapConfigInputFieldsArray) const
{
UNREFERENCED_PARAMETER(hUserImpersonationToken);
UNREFERENCED_PARAMETER(dwFlags);
UNREFERENCED_PARAMETER(dwConnectionDataSize);
UNREFERENCED_PARAMETER(pConnectionData);
UNREFERENCED_PARAMETER(pEapConfigInputFieldsArray);
throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported.");
}
void eap::peer::query_user_blob_from_credential_input_fields(
_In_ HANDLE hUserImpersonationToken,
_In_ DWORD dwFlags,
_In_ DWORD dwConnectionDataSize,
_In_count_(dwConnectionDataSize) const BYTE *pConnectionData,
_In_ const EAP_CONFIG_INPUT_FIELD_ARRAY *pEapConfigInputFieldArray,
_Inout_ DWORD *pdwUsersBlobSize,
_Inout_ BYTE **ppUserBlob) const
{
UNREFERENCED_PARAMETER(hUserImpersonationToken);
UNREFERENCED_PARAMETER(dwFlags);
UNREFERENCED_PARAMETER(dwConnectionDataSize);
UNREFERENCED_PARAMETER(pConnectionData);
UNREFERENCED_PARAMETER(pEapConfigInputFieldArray);
UNREFERENCED_PARAMETER(pdwUsersBlobSize);
UNREFERENCED_PARAMETER(ppUserBlob);
throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported.");
}
void eap::peer::query_interactive_ui_input_fields(
_In_ DWORD dwVersion,
_In_ DWORD dwFlags,
_In_ DWORD dwUIContextDataSize,
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
_Inout_ EAP_INTERACTIVE_UI_DATA *pEapInteractiveUIData) const
{
UNREFERENCED_PARAMETER(dwVersion);
UNREFERENCED_PARAMETER(dwFlags);
UNREFERENCED_PARAMETER(dwUIContextDataSize);
UNREFERENCED_PARAMETER(pUIContextData);
UNREFERENCED_PARAMETER(pEapInteractiveUIData);
throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported.");
}
void eap::peer::query_ui_blob_from_interactive_ui_input_fields(
_In_ DWORD dwVersion,
_In_ DWORD dwFlags,
_In_ DWORD dwUIContextDataSize,
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
_In_ const EAP_INTERACTIVE_UI_DATA *pEapInteractiveUIData,
_Inout_ DWORD *pdwDataFromInteractiveUISize,
_Inout_ BYTE **ppDataFromInteractiveUI) const
{
UNREFERENCED_PARAMETER(dwVersion);
UNREFERENCED_PARAMETER(dwFlags);
UNREFERENCED_PARAMETER(dwUIContextDataSize);
UNREFERENCED_PARAMETER(pUIContextData);
UNREFERENCED_PARAMETER(pEapInteractiveUIData);
UNREFERENCED_PARAMETER(pdwDataFromInteractiveUISize);
UNREFERENCED_PARAMETER(ppDataFromInteractiveUI);
throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported.");
}

View File

@@ -1,187 +0,0 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 GÉANT
This file is part of GÉANTLink.
GÉANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GÉANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StdAfx.h"
using namespace std;
using namespace winstd;
//////////////////////////////////////////////////////////////////////
// eap::session
//////////////////////////////////////////////////////////////////////
eap::session::session(_In_ module &mod) :
m_module(mod)
{
}
eap::session::session(_In_ const session &other) :
m_module(other.m_module)
{
}
eap::session::session(_Inout_ session &&other) :
m_module(other.m_module)
{
}
eap::session& eap::session::operator=(_In_ const session &other)
{
UNREFERENCED_PARAMETER(other);
assert(&m_module == &other.m_module); // Copy session within same module only!
return *this;
}
eap::session& eap::session::operator=(_Inout_ session &&other)
{
UNREFERENCED_PARAMETER(other);
assert(&m_module == &other.m_module); // Move session within same module only!
return *this;
}
bool eap::session::begin(
_In_ DWORD dwFlags,
_In_ const EapAttributes *pAttributeArray,
_In_ HANDLE hTokenImpersonateUser,
_In_ DWORD dwConnectionDataSize,
_In_count_(dwConnectionDataSize) const BYTE *pConnectionData,
_In_ DWORD dwUserDataSize,
_In_count_(dwUserDataSize) const BYTE *pUserData,
_In_ DWORD dwMaxSendPacketSize,
_Out_ EAP_ERROR **ppEapError)
{
UNREFERENCED_PARAMETER(dwFlags);
UNREFERENCED_PARAMETER(pAttributeArray);
UNREFERENCED_PARAMETER(hTokenImpersonateUser);
UNREFERENCED_PARAMETER(dwConnectionDataSize);
UNREFERENCED_PARAMETER(pConnectionData);
UNREFERENCED_PARAMETER(dwUserDataSize);
UNREFERENCED_PARAMETER(pUserData);
UNREFERENCED_PARAMETER(dwMaxSendPacketSize);
UNREFERENCED_PARAMETER(ppEapError);
return true;
}
bool eap::session::end(_Out_ EAP_ERROR **ppEapError)
{
UNREFERENCED_PARAMETER(ppEapError);
return true;
}
bool eap::session::process_request_packet(
_In_ DWORD dwReceivedPacketSize,
_In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket,
_Out_ EapPeerMethodOutput *pEapOutput,
_Out_ EAP_ERROR **ppEapError)
{
UNREFERENCED_PARAMETER(dwReceivedPacketSize);
UNREFERENCED_PARAMETER(pReceivedPacket);
UNREFERENCED_PARAMETER(pEapOutput);
assert(ppEapError);
*ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Not supported."), NULL);
return false;
}
bool eap::session::get_response_packet(
_Inout_ DWORD *pdwSendPacketSize,
_Inout_bytecap_(*dwSendPacketSize) EapPacket *pSendPacket,
_Out_ EAP_ERROR **ppEapError)
{
UNREFERENCED_PARAMETER(pdwSendPacketSize);
UNREFERENCED_PARAMETER(pSendPacket);
assert(ppEapError);
*ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Not supported."), NULL);
return false;
}
bool eap::session::get_result(_In_ EapPeerMethodResultReason reason, _Out_ EapPeerMethodResult *ppResult, _Out_ EAP_ERROR **ppEapError)
{
UNREFERENCED_PARAMETER(reason);
UNREFERENCED_PARAMETER(ppResult);
assert(ppEapError);
*ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Not supported."), NULL);
return false;
}
bool eap::session::get_ui_context(
_Out_ DWORD *pdwUIContextDataSize,
_Out_ BYTE **ppUIContextData,
_Out_ EAP_ERROR **ppEapError)
{
UNREFERENCED_PARAMETER(pdwUIContextDataSize);
UNREFERENCED_PARAMETER(ppUIContextData);
assert(ppEapError);
*ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Not supported."), NULL);
return false;
}
bool eap::session::set_ui_context(
_In_ DWORD dwUIContextDataSize,
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
_In_ const EapPeerMethodOutput *pEapOutput,
_Out_ EAP_ERROR **ppEapError)
{
UNREFERENCED_PARAMETER(dwUIContextDataSize);
UNREFERENCED_PARAMETER(pUIContextData);
UNREFERENCED_PARAMETER(pEapOutput);
assert(ppEapError);
*ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Not supported."), NULL);
return false;
}
bool eap::session::get_response_attributes(_Out_ EapAttributes *pAttribs, _Out_ EAP_ERROR **ppEapError)
{
UNREFERENCED_PARAMETER(pAttribs);
assert(ppEapError);
*ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Not supported."), NULL);
return false;
}
bool eap::session::set_response_attributes(const _In_ EapAttributes *pAttribs, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError)
{
UNREFERENCED_PARAMETER(pAttribs);
UNREFERENCED_PARAMETER(pEapOutput);
assert(ppEapError);
*ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Not supported."), NULL);
return false;
}

View File

@@ -22,14 +22,14 @@
#include "../include/Config.h"
#include "../include/Credentials.h"
#include "../include/Method.h"
#include "../include/Module.h"
#include "../include/Session.h"
#include "../include/EAP.h"
#include "../include/EAPSerial.h"
#include "../include/EAPXML.h"
#include <WinStd/Cred.h>
#include <WinStd/ETW.h>
#include <WinStd/Sec.h>
#include <EventsETW.h>

View File

@@ -87,6 +87,7 @@
<ItemGroup>
<ClCompile Include="..\res\wxEAP_UI.cpp" />
<ClCompile Include="..\src\EAP_UI.cpp" />
<ClCompile Include="..\src\Module.cpp" />
<ClCompile Include="..\src\StdAfx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>

View File

@@ -38,6 +38,9 @@
<ClCompile Include="..\res\wxEAP_UI.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\Module.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\res\wxEAP_UI.fbp">

View File

@@ -18,46 +18,88 @@
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include <wx/hyperlink.h>
#include <wx/icon.h>
#include <wx/scrolwin.h>
#include <wx/statbmp.h>
#include <Windows.h>
///
/// EAP configuration dialog
///
template <class _Tcfg, class _wxT> class wxEAPConfigDialog;
///
/// EAP credentials dialog
///
class wxEAPCredentialsDialog;
///
/// EAP dialog banner
/// Reusable EAP dialog banner for `wxEAPConfigDialog` and `wxEAPCredentialsDialog`
///
class wxEAPBannerPanel;
///
/// Base template for credentials configuration panel
/// EAP top-most configuration dialog
///
template <class _Tcfg, class _Tcred, class _Tpanel> class wxEAPCredentialsConfigPanel;
template <class _wxT> class wxEAPConfigDialog;
///
/// Base template for all credential panels
/// EAP general-use dialog
///
template <class _Tbase, class _Tcred> class wxCredentialsPanel;
class wxEAPGeneralDialog;
///
/// Password credentials panel
/// EAP top-most credential dialog
///
class wxPasswordCredentialsPanel;
class wxEAPCredentialsDialog;
///
/// EAP general note
///
class wxEAPNotePanel;
///
/// EAP provider-locked congifuration note
///
class wxEAPProviderLockedPanel;
///
/// EAP credential warning note
///
class wxEAPCredentialWarningPanel;
///
/// EAP Configuration window
///
class wxEAPConfigWindow;
///
/// EAP provider identity config panel
///
class wxEAPProviderIdentityPanel;
///
/// EAP provider configuration dialog
///
class wxEAPConfigProvider;
///
/// Base template for credential configuration panel
///
template <class _Tcred, class _wxT> class wxEAPCredentialsConfigPanel;
///
/// Base template for all credential entry panels
///
template <class _Tcred, class _Tbase> class wxEAPCredentialsPanelBase;
///
/// Generic password credential entry panel
///
template <class _Tcred, class _Tbase> class wxPasswordCredentialsPanel;
///
/// Sets icon from resource
///
inline bool wxSetIconFromResource(wxStaticBitmap *bmp, wxIcon &icon, HINSTANCE hinst, PCWSTR pszName);
///
/// Returns GUI displayable provider name
///
inline wxString wxEAPGetProviderName(const std::wstring &id);
#pragma once
#include <wx/msw/winundef.h> // Fixes `CreateDialog` name collision
@@ -78,47 +120,52 @@ inline bool wxSetIconFromResource(wxStaticBitmap *bmp, wxIcon &icon, HINSTANCE h
#include <memory>
template <class _Tmeth, class _wxT>
class wxEAPBannerPanel : public wxEAPBannerPanelBase
{
public:
///
/// Constructs a banner pannel and set the title text to product name
///
wxEAPBannerPanel(wxWindow* parent);
protected:
/// \cond internal
virtual bool AcceptsFocusFromKeyboard() const;
/// \endcond
};
template <class _wxT>
class wxEAPConfigDialog : public wxEAPConfigDialogBase
{
public:
///
/// Configuration provider data type
///
typedef eap::config_provider<_Tmeth> _Tprov;
///
/// Configuration data type
///
typedef eap::config_providers<_Tprov> config_type;
///
/// This data type
///
typedef wxEAPConfigDialog<_Tmeth, _wxT> _T;
public:
///
/// Constructs a configuration dialog
///
wxEAPConfigDialog(config_type &cfg, wxWindow* parent) :
/// \param[inout] cfg Providers configuration data
/// \param[in] parent Parent window
///
wxEAPConfigDialog(eap::config_provider_list &cfg, wxWindow* parent) :
m_cfg(cfg),
wxEAPConfigDialogBase(parent)
{
// Set extra style here, as wxFormBuilder overrides all default flags.
this->SetExtraStyle(this->GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
for (std::list<_Tprov>::iterator provider = m_cfg.m_providers.begin(), provider_end = m_cfg.m_providers.end(); provider != provider_end; ++provider) {
for (std::vector<eap::config_provider>::iterator provider = m_cfg.m_providers.begin(), provider_end = m_cfg.m_providers.end(); provider != provider_end; ++provider) {
bool is_single = provider->m_methods.size() == 1;
std::list<_Tmeth>::size_type count = 0;
std::list<_Tmeth>::iterator method = provider->m_methods.begin(), method_end = provider->m_methods.end();
std::vector<std::unique_ptr<eap::config_method> >::size_type count = 0;
std::vector<std::unique_ptr<eap::config_method> >::iterator method = provider->m_methods.begin(), method_end = provider->m_methods.end();
for (; method != method_end; ++method, count++)
m_providers->AddPage(
new _wxT(
provider->m_methods.front(),
*provider,
*method->get(),
provider->m_id.c_str(),
m_providers),
is_single ? provider->m_id : winstd::tstring_printf(_T("%s (%u)"), provider->m_id.c_str(), count));
is_single ?
wxEAPGetProviderName(provider->m_id) :
winstd::tstring_printf(_T("%s (%u)"), wxEAPGetProviderName(provider->m_id), count));
}
this->Layout();
@@ -130,35 +177,57 @@ public:
protected:
/// \cond internal
virtual void OnInitDialog(wxInitDialogEvent& event)
{
// Forward the event to child panels.
for (wxWindowList::compatibility_iterator provider = m_providers->GetChildren().GetFirst(); provider; provider = provider->GetNext()) {
_wxT *prov = wxDynamicCast(provider->GetData(), _wxT);
wxWindow *prov = wxDynamicCast(provider->GetData(), wxWindow);
if (prov)
prov->GetEventHandler()->ProcessEvent(event);
}
}
virtual void OnUpdateUI(wxUpdateUIEvent& event)
{
UNREFERENCED_PARAMETER(event);
m_advanced->Enable(!m_cfg.m_providers.at(m_providers->GetSelection()).m_read_only);
}
virtual void OnAdvanced(wxCommandEvent& event)
{
UNREFERENCED_PARAMETER(event);
wxEAPConfigProvider dlg(m_cfg.m_providers.at(m_providers->GetSelection()), this);
dlg.ShowModal();
}
/// \endcond
protected:
config_type &m_cfg; ///< EAP providers configuration
eap::config_provider_list &m_cfg; ///< EAP providers configuration
};
class wxEAPCredentialsDialog : public wxEAPCredentialsDialogBase
class wxEAPGeneralDialog : public wxEAPGeneralDialogBase
{
public:
///
/// Constructs a credential dialog
/// Constructs a dialog
///
wxEAPCredentialsDialog(wxWindow* parent);
wxEAPGeneralDialog(wxWindow* parent, const wxString& title = wxEmptyString);
///
/// Adds panels to the dialog
///
void AddContents(wxPanel **contents, size_t content_count);
void AddContent(wxPanel **contents, size_t content_count);
///
/// Adds single panel to the dialog
///
void AddContent(wxPanel *content);
protected:
/// \cond internal
@@ -167,41 +236,220 @@ protected:
};
class wxEAPBannerPanel : public wxEAPBannerPanelBase
class wxEAPCredentialsDialog : public wxEAPGeneralDialog
{
public:
///
/// Constructs a banner pannel and set the title text to product name
/// Constructs a credential dialog
///
wxEAPBannerPanel(wxWindow* parent);
protected:
/// \cond internal
virtual bool AcceptsFocusFromKeyboard() const { return false; }
/// \endcond
wxEAPCredentialsDialog(const eap::config_provider &prov, wxWindow* parent);
};
template <class _Tcfg, class _Tcred, class _Tpanel>
class wxEAPNotePanel : public wxEAPNotePanelBase
{
public:
///
/// Constructs an empty notice pannel
///
wxEAPNotePanel(wxWindow* parent);
protected:
/// \cond internal
virtual bool AcceptsFocusFromKeyboard() const;
template<class _Elem, class _Traits, class _Ax>
static std::basic_string<_Elem, _Traits, _Ax> GetPhoneNumber(_In_z_ const _Elem *num)
{
assert(num);
std::basic_string<_Elem, _Traits, _Ax> str;
for (; *num; num++) {
_Elem c = *num;
if ('0' <= c && c <= '9' || c == '+' || c == '*' || c == '#')
str += c;
}
return str;
}
template<class _Elem>
static std::basic_string<_Elem, std::char_traits<_Elem>, std::allocator<_Elem> > GetPhoneNumber(_In_z_ const _Elem *num)
{
return GetPhoneNumber<_Elem, std::char_traits<_Elem>, std::allocator<_Elem> >(num);
}
void CreateContactFields(const eap::config_provider &prov);
/// \endcond
protected:
wxStaticText *m_provider_notice;
wxStaticText *m_help_web_label;
wxHyperlinkCtrl *m_help_web_value;
wxStaticText *m_help_email_label;
wxHyperlinkCtrl *m_help_email_value;
wxStaticText *m_help_phone_label;
wxHyperlinkCtrl *m_help_phone_value;
};
class wxEAPProviderLockedPanel : public wxEAPNotePanel
{
public:
///
/// Constructs a notice pannel and set the title text
///
wxEAPProviderLockedPanel(const eap::config_provider &prov, wxWindow* parent);
protected:
winstd::library m_shell32; ///< shell32.dll resource library reference
wxIcon m_icon; ///< Panel icon
};
class wxEAPCredentialWarningPanel : public wxEAPNotePanel
{
public:
///
/// Constructs a notice pannel and set the title text
///
wxEAPCredentialWarningPanel(const eap::config_provider &prov, wxWindow* parent);
protected:
winstd::library m_shell32; ///< shell32.dll resource library reference
wxIcon m_icon; ///< Panel icon
};
class wxEAPConfigWindow : public wxScrolledWindow
{
public:
///
/// Constructs a configuration window
///
/// \param[in] prov Provider configuration data
/// \param[inout] cfg Configuration data
/// \param[in] parent Parent window
///
wxEAPConfigWindow(const eap::config_provider &prov, eap::config_method &cfg, wxWindow* parent);
///
/// Destructs the configuration window
///
virtual ~wxEAPConfigWindow();
protected:
/// \cond internal
virtual void OnInitDialog(wxInitDialogEvent& event);
virtual void OnUpdateUI(wxUpdateUIEvent& event);
/// \endcond
protected:
const eap::config_provider &m_prov; ///< EAP provider
eap::config_method &m_cfg; ///< Method configuration
};
class wxEAPProviderIdentityPanel : public wxEAPProviderIdentityPanelBase
{
public:
///
/// Constructs a provider identity pannel
///
/// \param[inout] prov Provider configuration data
/// \param[in] parent Parent window
///
wxEAPProviderIdentityPanel(eap::config_provider &prov, wxWindow* parent);
friend class wxEAPConfigProvider; // Allows direct setting of keyboard focus
protected:
/// \cond internal
virtual bool TransferDataToWindow();
virtual bool TransferDataFromWindow();
/// \endcond
protected:
eap::config_provider &m_prov; ///< EAP method configuration
winstd::library m_shell32; ///< shell32.dll resource library reference
wxIcon m_icon; ///< Panel icon
};
class wxEAPProviderLockPanel : public wxEAPProviderLockPanelBase
{
public:
///
/// Constructs a provider lock pannel
///
/// \param[inout] prov Provider configuration data
/// \param[in] parent Parent window
///
wxEAPProviderLockPanel(eap::config_provider &prov, wxWindow* parent);
protected:
/// \cond internal
virtual bool TransferDataToWindow();
virtual bool TransferDataFromWindow();
/// \endcond
protected:
eap::config_provider &m_prov; ///< EAP method configuration
winstd::library m_shell32; ///< shell32.dll resource library reference
wxIcon m_icon; ///< Panel icon
};
class wxEAPConfigProvider : public wxEAPGeneralDialog
{
public:
///
/// Constructs a provider config dialog
///
/// \param[inout] prov Provider configuration data
/// \param[in] parent Parent window
///
wxEAPConfigProvider(eap::config_provider &prov, wxWindow* parent);
protected:
eap::config_provider &m_prov; ///< EAP method configuration
wxEAPProviderIdentityPanel *m_identity; ///< Provider identity panel
wxEAPProviderLockPanel *m_lock; ///< Provider lock panel
};
template <class _Tcred, class _wxT>
class wxEAPCredentialsConfigPanel : public wxEAPCredentialsConfigPanelBase
{
public:
///
/// Constructs a credential configuration panel
///
/// \param[in] prov Provider configuration data
/// \param[inout] cfg Configuration data
/// \param[in] pszCredTarget Target name of credentials in Windows Credential Manager. Can be further decorated to create final target name.
/// \param[in] parent Parent window
///
wxEAPCredentialsConfigPanel(_Tcfg &cfg, LPCTSTR pszCredTarget, wxWindow *parent) :
wxEAPCredentialsConfigPanel(const eap::config_provider &prov, eap::config_method_with_cred &cfg, LPCTSTR pszCredTarget, wxWindow *parent) :
m_prov(prov),
m_cfg(cfg),
m_target(pszCredTarget),
m_cred(m_cfg.m_module),
m_cred(cfg.m_module),
wxEAPCredentialsConfigPanelBase(parent)
{
// Load and set icon.
if (m_shell32.load(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
wxSetIconFromResource(m_credentials_icon, m_icon, m_shell32, MAKEINTRESOURCE(48));
wxSetIconFromResource(m_credentials_icon, m_icon, m_shell32, MAKEINTRESOURCE(/*16770*/269));
}
///
/// Sets keyboard focus to the first control that do not capture mouse wheel
///
inline void SetFocusFromKbd()
{
m_own->SetFocusFromKbd();
}
protected:
@@ -209,29 +457,28 @@ protected:
virtual bool TransferDataToWindow()
{
wxCHECK(wxEAPCredentialsConfigPanelBase::TransferDataToWindow(), false);
if (!m_cfg.m_use_preshared) {
if (!m_cfg.m_use_preshared)
m_own->SetValue(true);
} else {
else
m_preshared->SetValue(true);
m_cred = m_cfg.m_preshared;
}
return true;
m_cred = *(_Tcred*)m_cfg.m_preshared.get();
return wxEAPCredentialsConfigPanelBase::TransferDataToWindow();
}
virtual bool TransferDataFromWindow()
{
if (m_own->GetValue()) {
m_cfg.m_use_preshared = false;
} else {
m_cfg.m_use_preshared = true;
m_cfg.m_preshared = m_cred;
wxCHECK(wxEAPCredentialsConfigPanelBase::TransferDataFromWindow(), false);
if (!m_prov.m_read_only) {
// This is not a provider-locked configuration. Save the data.
m_cfg.m_use_preshared = !m_own->GetValue();
*m_cfg.m_preshared = m_cred;
}
return wxEAPCredentialsConfigPanelBase::TransferDataFromWindow();
return true;
}
@@ -240,33 +487,62 @@ protected:
UNREFERENCED_PARAMETER(event);
DWORD dwResult;
bool has_own;
std::unique_ptr<CREDENTIAL, winstd::CredFree_delete<CREDENTIAL> > cred;
if (CredRead(m_cred.target_name(m_target.c_str()).c_str(), CRED_TYPE_GENERIC, 0, (PCREDENTIAL*)&cred)) {
m_identity_own->SetValue(cred->UserName && cred->UserName[0] != 0 ? cred->UserName : _("<blank>"));
has_own = true;
} else if ((dwResult = GetLastError()) == ERROR_NOT_FOUND) {
m_identity_own->Clear();
has_own = false;
if (m_cfg.m_allow_save) {
bool has_own;
std::unique_ptr<CREDENTIAL, winstd::CredFree_delete<CREDENTIAL> > cred;
if (CredRead(m_cred.target_name(m_target.c_str()).c_str(), CRED_TYPE_GENERIC, 0, (PCREDENTIAL*)&cred)) {
m_own_identity->SetValue(cred->UserName && cred->UserName[0] != 0 ? cred->UserName : _("<blank>"));
has_own = true;
} else if ((dwResult = GetLastError()) == ERROR_NOT_FOUND) {
m_own_identity->Clear();
has_own = false;
} else {
m_own_identity->SetValue(wxString::Format(_("<error %u>"), dwResult));
has_own = true;
}
if (m_own->GetValue()) {
m_own_identity->Enable(true);
m_own_set ->Enable(true);
m_own_clear ->Enable(has_own);
} else {
m_own_identity->Enable(false);
m_own_set ->Enable(false);
m_own_clear ->Enable(false);
}
} else {
m_identity_own->SetValue(wxString::Format(_("<error %u>"), dwResult));
has_own = true;
m_own_identity->Clear();
m_own_identity->Enable(false);
m_own_set ->Enable(false);
m_own_clear ->Enable(false);
}
if (m_own->GetValue()) {
m_identity_own ->Enable(true);
m_set_own ->Enable(true);
m_clear_own ->Enable(has_own);
m_identity_preshared->Enable(false);
m_identity_preshared->SetValue(wxEmptyString);
m_set_preshared ->Enable(false);
m_preshared_identity->SetValue(!m_cred.empty() ? m_cred.get_name() : _("<blank>"));
if (m_prov.m_read_only) {
// This is provider-locked configuration. Disable controls.
// To avoid run-away selection of radio buttons, disable the selected one last.
if (m_own->GetValue()) {
m_preshared->Enable(false);
m_own ->Enable(false);
} else {
m_own ->Enable(false);
m_preshared->Enable(false);
}
m_preshared_identity->Enable(false);
m_preshared_set ->Enable(false);
} else {
m_identity_own ->Enable(false);
m_set_own ->Enable(false);
m_clear_own ->Enable(false);
m_identity_preshared->Enable(true);
m_identity_preshared->SetValue(!m_cred.empty() ? m_cred.m_identity : _("<blank>"));
m_set_preshared ->Enable(true);
// This is not a provider-locked configuration. Selectively enable/disable controls.
m_own ->Enable(true);
m_preshared ->Enable(true);
if (m_own->GetValue()) {
m_preshared_identity->Enable(false);
m_preshared_set ->Enable(false);
} else {
m_preshared_identity->Enable(true);
m_preshared_set ->Enable(true);
}
}
}
@@ -275,12 +551,31 @@ protected:
{
UNREFERENCED_PARAMETER(event);
wxEAPCredentialsDialog dlg(this);
// Read credentials from Credential Manager
_Tcred cred(m_cfg.m_module);
try {
cred.retrieve(m_target.c_str());
} catch (winstd::win_runtime_error &err) {
if (err.number() != ERROR_NOT_FOUND)
wxLogError(winstd::tstring_printf(_("Error reading credentials from Credential Manager: %hs (error %u)"), err.what(), err.number()).c_str());
} catch (...) {
wxLogError(_("Reading credentials failed."));
}
_Tpanel *panel = new _Tpanel(m_cred, m_target.c_str(), &dlg, true);
dlg.AddContents((wxPanel**)&panel, 1);
dlg.ShowModal();
// Display credential prompt.
wxEAPCredentialsDialog dlg(m_prov, this);
_wxT *panel = new _wxT(m_prov, m_cfg, cred, m_target.c_str(), &dlg, true);
dlg.AddContent(panel);
if (dlg.ShowModal() == wxID_OK && panel->GetRememberValue()) {
// Write credentials to credential manager.
try {
cred.store(m_target.c_str());
} catch (winstd::win_runtime_error &err) {
wxLogError(winstd::tstring_printf(_("Error writing credentials to Credential Manager: %hs (error %u)"), err.what(), err.number()).c_str());
} catch (...) {
wxLogError(_("Writing credentials failed."));
}
}
}
@@ -297,130 +592,202 @@ protected:
{
UNREFERENCED_PARAMETER(event);
wxEAPCredentialsDialog dlg(this);
wxEAPCredentialsDialog dlg(m_prov, this);
_Tpanel *panel = new _Tpanel(m_cred, _T(""), &dlg, true);
_wxT *panel = new _wxT(m_prov, m_cfg, m_cred, _T(""), &dlg, true);
dlg.AddContents((wxPanel**)&panel, 1);
dlg.AddContent(panel);
dlg.ShowModal();
}
/// \endcond
protected:
_Tcfg &m_cfg; ///< EAP configuration
winstd::library m_shell32; ///< shell32.dll resource library reference
wxIcon m_icon; ///< Panel icon
winstd::tstring m_target; ///< Credential Manager target
const eap::config_provider &m_prov; ///< EAP provider
eap::config_method_with_cred &m_cfg; ///< EAP method configuration
winstd::library m_shell32; ///< shell32.dll resource library reference
wxIcon m_icon; ///< Panel icon
winstd::tstring m_target; ///< Credential Manager target
private:
_Tcred m_cred; ///< Temporary credential data
_Tcred m_cred; ///< Temporary credential data
};
template <class _Tbase, class _Tcred>
class wxCredentialsPanel : public _Tbase
template <class _Tcred, class _Tbase>
class wxEAPCredentialsPanelBase : public _Tbase
{
private:
/// \cond internal
typedef wxEAPCredentialsPanelBase<_Tcred, _Tbase> _Tthis;
/// \endcond
public:
///
/// Constructs a credentials panel
///
/// \param[in] prov Provider configuration data
/// \param[in] cfg Configuration data
/// \param[inout] cred Credentials data
/// \param[in] pszCredTarget Target name of credentials in Windows Credential Manager. Can be further decorated to create final target name.
/// \param[in] parent Parent window
/// \param[in] is_config Is this panel used to pre-enter credentials? When \c true, the "Remember" checkbox is always selected and disabled.
///
wxCredentialsPanel(_Tcred &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false) :
wxEAPCredentialsPanelBase(const eap::config_provider &prov, const eap::config_method_with_cred &cfg, _Tcred &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false) :
m_prov(prov),
m_cfg(cfg),
m_cred(cred),
m_target(pszCredTarget),
m_is_config(is_config),
_Tbase(parent)
{
if (m_target.empty() || is_config) {
// No Credential Manager, or user is setting credentials via configuration UI.
// => Pointless if not stored to Credential Manager
this->Connect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(_Tthis::OnUpdateUI));
}
virtual ~wxEAPCredentialsPanelBase()
{
this->Disconnect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(_Tthis::OnUpdateUI));
}
inline void SetRememberValue(bool val)
{
return m_remember->SetValue(val);
}
inline bool GetRememberValue() const
{
return m_remember->GetValue();
}
protected:
/// \cond internal
virtual void OnUpdateUI(wxUpdateUIEvent& event)
{
UNREFERENCED_PARAMETER(event);
if (m_is_config) {
// Configuration mode
// Always store credentials (somewhere).
m_remember->SetValue(true);
m_remember->Enable(false);
} else if (m_cfg.m_use_preshared) {
// Credential prompt mode & Using pre-shared credentials
m_remember->SetValue(false);
m_remember->Enable(false);
} else if (!m_cfg.m_allow_save) {
// Credential prompt mode & using own credentials & saving is not allowed
m_remember->SetValue(false);
m_remember->Enable(false);
}
}
/// \endcond
protected:
const eap::config_provider &m_prov; ///< Provider configuration
const eap::config_method_with_cred &m_cfg; ///< Method configuration
_Tcred &m_cred; ///< Credentials
winstd::tstring m_target; ///< Credential Manager target
bool m_is_config; ///< Is this a configuration dialog?
};
template <class _Tcred, class _Tbase>
class wxPasswordCredentialsPanel : public wxEAPCredentialsPanelBase<_Tcred, _Tbase>
{
public:
///
/// Constructs a password credentials panel
///
/// \param[in] prov Provider configuration data
/// \param[in] cfg Configuration data
/// \param[inout] cred Credentials data
/// \param[in] pszCredTarget Target name of credentials in Windows Credential Manager. Can be further decorated to create final target name.
/// \param[in] parent Parent window
/// \param[in] is_config Is this panel used to pre-enter credentials? When \c true, the "Remember" checkbox is always selected and disabled.
///
wxPasswordCredentialsPanel(const eap::config_provider &prov, const eap::config_method_with_cred &cfg, _Tcred &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false) :
wxEAPCredentialsPanelBase<_Tcred, _Tbase>(prov, cfg, cred, pszCredTarget, parent, is_config)
{
// Load and set icon.
if (m_shell32.load(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
wxSetIconFromResource(m_credentials_icon, m_icon, m_shell32, MAKEINTRESOURCE(269));
bool layout = false;
if (!m_prov.m_lbl_alt_credential.empty()) {
m_credentials_label->SetLabel(m_prov.m_lbl_alt_credential);
m_credentials_label->Wrap( 446 );
layout = true;
}
if (!m_prov.m_lbl_alt_identity.empty()) {
m_identity_label->SetLabel(m_prov.m_lbl_alt_identity);
layout = true;
}
if (!m_prov.m_lbl_alt_password.empty()) {
m_password_label->SetLabel(m_prov.m_lbl_alt_password);
layout = true;
}
if (layout)
this->Layout();
}
protected:
/// \cond internal
virtual bool TransferDataToWindow()
{
wxCHECK(_Tbase::TransferDataToWindow(), false);
m_identity->SetValue(m_cred.m_identity);
m_identity->SetSelection(0, -1);
m_password->SetValue(m_cred.m_password.empty() ? wxEmptyString : s_dummy_password);
if (!m_target.empty()) {
// Read credentials from Credential Manager
EAP_ERROR *pEapError;
if (m_cred.retrieve(m_target.c_str(), &pEapError)) {
m_remember->SetValue(true);
} else if (pEapError) {
if (pEapError->dwWinError != ERROR_NOT_FOUND)
wxLogError(winstd::tstring_printf(_("Error reading credentials from Credential Manager: %ls (error %u)"), pEapError->pRootCauseString, pEapError->dwWinError).c_str());
m_cred.m_module.free_error_memory(pEapError);
} else
wxLogError(_("Reading credentials failed."));
return wxEAPCredentialsPanelBase<_Tcred, wxEAPCredentialsPassPanelBase>::TransferDataToWindow();
}
virtual bool TransferDataFromWindow()
{
if (!wxEAPCredentialsPanelBase<_Tcred, wxEAPCredentialsPassPanelBase>::TransferDataFromWindow())
return false;
m_cred.m_identity = m_identity->GetValue();
wxString pass = m_password->GetValue();
if (pass.compare(s_dummy_password) != 0) {
m_cred.m_password = pass;
pass.assign(pass.length(), wxT('*'));
}
return true;
}
virtual bool TransferDataFromWindow()
virtual void OnUpdateUI(wxUpdateUIEvent& event)
{
if (!m_target.empty()) {
// Write credentials to credential manager.
if (m_remember->GetValue()) {
EAP_ERROR *pEapError;
if (!m_cred.store(m_target.c_str(), &pEapError)) {
if (pEapError) {
wxLogError(winstd::tstring_printf(_("Error writing credentials to Credential Manager: %ls (error %u)"), pEapError->pRootCauseString, pEapError->dwWinError).c_str());
m_cred.m_module.free_error_memory(pEapError);
} else
wxLogError(_("Writing credentials failed."));
}
}
if (!m_is_config && m_cfg.m_use_preshared) {
// Credential prompt mode & Using pre-shared credentials
m_identity_label->Enable(false);
m_identity ->Enable(false);
m_password_label->Enable(false);
m_password ->Enable(false);
}
return _Tbase::TransferDataFromWindow();
wxEAPCredentialsPanelBase<_Tcred, wxEAPCredentialsPassPanelBase>::OnUpdateUI(event);
}
/// \endcond
protected:
_Tcred &m_cred; ///< Password credentials
winstd::tstring m_target; ///< Credential Manager target
};
class wxPasswordCredentialsPanel : public wxCredentialsPanel<wxPasswordCredentialsPanelBase, eap::credentials_pass>
{
public:
///
/// Constructs a password credentials panel
///
/// \param[inout] cred Credentials data
/// \param[in] pszCredTarget Target name of credentials in Windows Credential Manager. Can be further decorated to create final target name.
/// \param[in] parent Parent window
/// \param[in] is_config Is this panel used to pre-enter credentials? When \c true, the "Remember" checkbox is always selected and disabled.
///
wxPasswordCredentialsPanel(eap::credentials_pass &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false);
protected:
/// \cond internal
virtual bool TransferDataToWindow();
virtual bool TransferDataFromWindow();
/// \endcond
protected:
winstd::library m_shell32; ///< shell32.dll resource library reference
wxIcon m_icon; ///< Panel icon
winstd::library m_shell32; ///< shell32.dll resource library reference
wxIcon m_icon; ///< Panel icon
private:
static const wxStringCharType *s_dummy_password;
};
template <class _Tcred, class _Tbase>
const wxStringCharType *wxPasswordCredentialsPanel<_Tcred, _Tbase>::s_dummy_password = wxT("dummypass");
inline bool wxSetIconFromResource(wxStaticBitmap *bmp, wxIcon &icon, HINSTANCE hinst, PCWSTR pszName)
{
@@ -434,3 +801,10 @@ inline bool wxSetIconFromResource(wxStaticBitmap *bmp, wxIcon &icon, HINSTANCE h
} else
return false;
}
inline wxString wxEAPGetProviderName(const std::wstring &id)
{
return
!id.empty() ? id : _("<Your Organization>");
}

View File

@@ -21,11 +21,11 @@
namespace eap
{
///
/// EAP UI peer base abstract class template
/// EAP UI peer base abstract class
///
/// A group of methods all EAP UI peers must or should implement.
///
template <class _Tmeth, class _Tid, class _Tint, class _Tintres> class peer_ui;
class peer_ui;
}
#pragma once
@@ -35,75 +35,79 @@ namespace eap
namespace eap
{
template <class _Tcfg, class _Tid, class _Tint, class _Tintres>
class peer_ui : public peer_base<_Tcfg, _Tid, _Tint, _Tintres>
class peer_ui : public module
{
public:
///
/// Constructs a EAP UI peer module for the given EAP type
///
peer_ui(_In_ type_t eap_method) : peer_base<_Tcfg, _Tid, _Tint, _Tintres>(eap_method) {}
/// \param[in] eap_method EAP method type ID
///
peer_ui(_In_ winstd::eap_type_t eap_method);
///
/// Converts XML into the configuration BLOB.
///
/// \sa [EapPeerConfigXml2Blob function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363602.aspx)
///
virtual void config_xml2blob(
_In_ DWORD dwFlags,
_In_ IXMLDOMNode *pConfigRoot,
_Inout_ BYTE **pConnectionDataOut,
_Inout_ DWORD *pdwConnectionDataOutSize) = 0;
///
/// Converts the configuration BLOB to XML.
///
/// The configuration BLOB is returned in the `ppConnectionDataOut` parameter of the `EapPeerInvokeConfigUI` function.
///
/// \sa [EapPeerConfigBlob2Xml function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363601.aspx)
///
virtual void config_blob2xml(
_In_ DWORD dwFlags,
_In_count_(dwConnectionDataSize) const BYTE *pConnectionData,
_In_ DWORD dwConnectionDataSize,
_In_ IXMLDOMDocument *pDoc,
_In_ IXMLDOMNode *pConfigRoot) = 0;
///
/// Raises the EAP method's specific connection configuration user interface dialog on the client.
///
/// \sa [EapPeerInvokeConfigUI function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363614.aspx)
///
/// \param[in] hwndParent Parent window
/// \param[inout] cfg Configuration to edit
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool invoke_config_ui(
_In_ HWND hwndParent,
_Inout_ config_type &cfg,
_Out_ EAP_ERROR **ppEapError) = 0;
virtual void invoke_config_ui(
_In_ HWND hwndParent,
_In_count_(dwConnectionDataInSize) const BYTE *pConnectionDataIn,
_In_ DWORD dwConnectionDataInSize,
_Inout_ BYTE **ppConnectionDataOut,
_Inout_ DWORD *pdwConnectionDataOutSize) = 0;
///
/// Raises a custom interactive user interface dialog to obtain user identity information for the EAP method on the client.
///
/// \sa [EapPeerInvokeIdentityUI function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363615.aspx)
///
/// \param[in] hwndParent Parent window
/// \param[in] dwFlags Flags passed to `EapPeerInvokeIdentityUI()` call
/// \param[inout] cfg Configuration
/// \param[inout] usr User data to edit
/// \param[out] ppwszIdentity Pointer to user identity. Free using `module::free_memory()`.
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool invoke_identity_ui(
_In_ HWND hwndParent,
_In_ DWORD dwFlags,
_Inout_ config_type &cfg,
_Inout_ identity_type &usr,
_Out_ LPWSTR *ppwszIdentity,
_Out_ EAP_ERROR **ppEapError) = 0;
virtual void invoke_identity_ui(
_In_ HWND hwndParent,
_In_ DWORD dwFlags,
_In_count_(dwConnectionDataSize) const BYTE *pConnectionData,
_In_ DWORD dwConnectionDataSize,
_In_count_(dwUserDataSize) const BYTE *pUserData,
_In_ DWORD dwUserDataSize,
_Inout_ BYTE **ppUserDataOut,
_Inout_ DWORD *pdwUserDataOutSize,
_Inout_ LPWSTR *ppwszIdentity) = 0;
///
/// Raises a custom interactive user interface dialog for the EAP method on the client.
///
/// \sa [EapPeerInvokeInteractiveUI function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363616.aspx)
///
/// \param[in] hwndParent Parent window
/// \param[in] req Interactive request
/// \param[out] res Interactive response
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool invoke_interactive_ui(
_In_ HWND hwndParent,
_In_ const interactive_request_type &req,
_Out_ interactive_response_type &res,
_Out_ EAP_ERROR **ppEapError) = 0;
virtual void invoke_interactive_ui(
_In_ HWND hwndParent,
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
_In_ DWORD dwUIContextDataSize,
_Inout_ BYTE **ppDataFromInteractiveUI,
_Inout_ DWORD *pdwDataFromInteractiveUISize) = 0;
};
}

View File

@@ -28,6 +28,20 @@ wxEAPConfigDialogBase::wxEAPConfigDialogBase( wxWindow* parent, wxWindowID id, c
sb_content->Add( m_providers, 1, wxEXPAND|wxALL, 10 );
wxBoxSizer* sb_bottom_horiz;
sb_bottom_horiz = new wxBoxSizer( wxHORIZONTAL );
wxBoxSizer* sb_bottom_horiz_inner;
sb_bottom_horiz_inner = new wxBoxSizer( wxHORIZONTAL );
m_advanced = new wxButton( this, wxID_ANY, _("Advanced..."), wxDefaultPosition, wxDefaultSize, 0 );
m_advanced->SetToolTip( _("Opens dialog with provider settings") );
sb_bottom_horiz_inner->Add( m_advanced, 0, wxALL, 5 );
sb_bottom_horiz->Add( sb_bottom_horiz_inner, 1, wxEXPAND, 5 );
m_buttons = new wxStdDialogButtonSizer();
m_buttonsOK = new wxButton( this, wxID_OK );
m_buttons->AddButton( m_buttonsOK );
@@ -35,7 +49,10 @@ wxEAPConfigDialogBase::wxEAPConfigDialogBase( wxWindow* parent, wxWindowID id, c
m_buttons->AddButton( m_buttonsCancel );
m_buttons->Realize();
sb_content->Add( m_buttons, 0, wxEXPAND|wxALL, 5 );
sb_bottom_horiz->Add( m_buttons, 0, wxEXPAND|wxALL, 5 );
sb_content->Add( sb_bottom_horiz, 0, wxEXPAND, 5 );
this->SetSizer( sb_content );
@@ -44,16 +61,20 @@ wxEAPConfigDialogBase::wxEAPConfigDialogBase( wxWindow* parent, wxWindowID id, c
// Connect Events
this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( wxEAPConfigDialogBase::OnInitDialog ) );
this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( wxEAPConfigDialogBase::OnUpdateUI ) );
m_advanced->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPConfigDialogBase::OnAdvanced ), NULL, this );
}
wxEAPConfigDialogBase::~wxEAPConfigDialogBase()
{
// Disconnect Events
this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( wxEAPConfigDialogBase::OnInitDialog ) );
this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( wxEAPConfigDialogBase::OnUpdateUI ) );
m_advanced->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPConfigDialogBase::OnAdvanced ), NULL, this );
}
wxEAPCredentialsDialogBase::wxEAPCredentialsDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
wxEAPGeneralDialogBase::wxEAPGeneralDialogBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
@@ -84,13 +105,13 @@ wxEAPCredentialsDialogBase::wxEAPCredentialsDialogBase( wxWindow* parent, wxWind
sb_content->Fit( this );
// Connect Events
this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( wxEAPCredentialsDialogBase::OnInitDialog ) );
this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( wxEAPGeneralDialogBase::OnInitDialog ) );
}
wxEAPCredentialsDialogBase::~wxEAPCredentialsDialogBase()
wxEAPGeneralDialogBase::~wxEAPGeneralDialogBase()
{
// Disconnect Events
this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( wxEAPCredentialsDialogBase::OnInitDialog ) );
this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( wxEAPGeneralDialogBase::OnInitDialog ) );
}
@@ -99,26 +120,54 @@ wxEAPBannerPanelBase::wxEAPBannerPanelBase( wxWindow* parent, wxWindowID id, con
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) );
this->SetMinSize( wxSize( -1,48 ) );
wxBoxSizer* sc_content;
sc_content = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* sb_content;
sb_content = new wxBoxSizer( wxVERTICAL );
m_title = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT );
m_title->Wrap( -1 );
m_title->SetFont( wxFont( 18, 70, 90, 90, false, wxEmptyString ) );
m_title->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) );
sc_content->Add( m_title, 0, wxALL|wxEXPAND, 5 );
sb_content->Add( m_title, 0, wxALL|wxEXPAND, 5 );
this->SetSizer( sc_content );
this->SetSizer( sb_content );
this->Layout();
sc_content->Fit( this );
sb_content->Fit( this );
}
wxEAPBannerPanelBase::~wxEAPBannerPanelBase()
{
}
wxEAPNotePanelBase::wxEAPNotePanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
{
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_INFOBK ) );
wxBoxSizer* sb_note_horiz;
sb_note_horiz = new wxBoxSizer( wxHORIZONTAL );
m_note_icon = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
sb_note_horiz->Add( m_note_icon, 0, wxALL, 5 );
m_note_vert = new wxBoxSizer( wxVERTICAL );
m_note_label = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_note_label->Wrap( 449 );
m_note_vert->Add( m_note_label, 0, wxALL|wxEXPAND, 5 );
sb_note_horiz->Add( m_note_vert, 1, wxEXPAND, 5 );
this->SetSizer( sb_note_horiz );
this->Layout();
}
wxEAPNotePanelBase::~wxEAPNotePanelBase()
{
}
wxEAPCredentialsConfigPanelBase::wxEAPCredentialsConfigPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
{
wxStaticBoxSizer* sb_credentials;
@@ -151,10 +200,10 @@ wxEAPCredentialsConfigPanelBase::wxEAPCredentialsConfigPanelBase( wxWindow* pare
sz_own_inner->Add( m_own, 2, wxEXPAND, 5 );
m_identity_own = new wxTextCtrl( sb_credentials->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
m_identity_own->SetToolTip( _("Enter your user name here (user@domain.org, DOMAINUser, etc.)") );
m_own_identity = new wxTextCtrl( sb_credentials->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
m_own_identity->SetToolTip( _("Your credentials loaded from Windows Credential Manager") );
sz_own_inner->Add( m_identity_own, 3, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
sz_own_inner->Add( m_own_identity, 3, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
sz_own->Add( sz_own_inner, 1, wxEXPAND|wxBOTTOM, 5 );
@@ -162,15 +211,15 @@ wxEAPCredentialsConfigPanelBase::wxEAPCredentialsConfigPanelBase( wxWindow* pare
wxBoxSizer* sb_buttons_own;
sb_buttons_own = new wxBoxSizer( wxHORIZONTAL );
m_clear_own = new wxButton( sb_credentials->GetStaticBox(), wxID_ANY, _("&Clear Credentials"), wxDefaultPosition, wxDefaultSize, 0 );
m_clear_own->SetToolTip( _("Click to clear your credentials from Credential Manager.\nNote: You will be prompted to enter credentials when connecting.") );
m_own_clear = new wxButton( sb_credentials->GetStaticBox(), wxID_ANY, _("&Clear Credentials"), wxDefaultPosition, wxDefaultSize, 0 );
m_own_clear->SetToolTip( _("Click to clear your credentials from Credential Manager.\nNote: You will be prompted to enter credentials when connecting.") );
sb_buttons_own->Add( m_clear_own, 0, wxRIGHT, 5 );
sb_buttons_own->Add( m_own_clear, 0, wxRIGHT, 5 );
m_set_own = new wxButton( sb_credentials->GetStaticBox(), wxID_ANY, _("&Set Credentials..."), wxDefaultPosition, wxDefaultSize, 0 );
m_set_own->SetToolTip( _("Click here to set or modify your credentials") );
m_own_set = new wxButton( sb_credentials->GetStaticBox(), wxID_ANY, _("&Set Credentials..."), wxDefaultPosition, wxDefaultSize, 0 );
m_own_set->SetToolTip( _("Click here to set or modify your credentials") );
sb_buttons_own->Add( m_set_own, 0, wxLEFT, 5 );
sb_buttons_own->Add( m_own_set, 0, wxLEFT, 5 );
sz_own->Add( sb_buttons_own, 0, wxALIGN_RIGHT, 5 );
@@ -189,10 +238,10 @@ wxEAPCredentialsConfigPanelBase::wxEAPCredentialsConfigPanelBase( wxWindow* pare
sz_preshared_inner->Add( m_preshared, 2, wxEXPAND, 5 );
m_identity_preshared = new wxTextCtrl( sb_credentials->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
m_identity_preshared->SetToolTip( _("Enter your user name here (user@domain.org, DOMAINUser, etc.)") );
m_preshared_identity = new wxTextCtrl( sb_credentials->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY );
m_preshared_identity->SetToolTip( _("Common (pre-shared) credentials") );
sz_preshared_inner->Add( m_identity_preshared, 3, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
sz_preshared_inner->Add( m_preshared_identity, 3, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
sz_preshared->Add( sz_preshared_inner, 1, wxEXPAND|wxBOTTOM, 5 );
@@ -200,10 +249,10 @@ wxEAPCredentialsConfigPanelBase::wxEAPCredentialsConfigPanelBase( wxWindow* pare
wxBoxSizer* sb_buttons_preshared;
sb_buttons_preshared = new wxBoxSizer( wxHORIZONTAL );
m_set_preshared = new wxButton( sb_credentials->GetStaticBox(), wxID_ANY, _("&Set Credentials..."), wxDefaultPosition, wxDefaultSize, 0 );
m_set_preshared->SetToolTip( _("Click here to set or modify your credentials") );
m_preshared_set = new wxButton( sb_credentials->GetStaticBox(), wxID_ANY, _("&Set Credentials..."), wxDefaultPosition, wxDefaultSize, 0 );
m_preshared_set->SetToolTip( _("Click here to set or modify your credentials") );
sb_buttons_preshared->Add( m_set_preshared, 0, 0, 5 );
sb_buttons_preshared->Add( m_preshared_set, 0, 0, 5 );
sz_preshared->Add( sb_buttons_preshared, 0, wxALIGN_RIGHT, 5 );
@@ -226,22 +275,22 @@ wxEAPCredentialsConfigPanelBase::wxEAPCredentialsConfigPanelBase( wxWindow* pare
// Connect Events
this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( wxEAPCredentialsConfigPanelBase::OnUpdateUI ) );
m_clear_own->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPCredentialsConfigPanelBase::OnClearOwn ), NULL, this );
m_set_own->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPCredentialsConfigPanelBase::OnSetOwn ), NULL, this );
m_set_preshared->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPCredentialsConfigPanelBase::OnSetPreshared ), NULL, this );
m_own_clear->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPCredentialsConfigPanelBase::OnClearOwn ), NULL, this );
m_own_set->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPCredentialsConfigPanelBase::OnSetOwn ), NULL, this );
m_preshared_set->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPCredentialsConfigPanelBase::OnSetPreshared ), NULL, this );
}
wxEAPCredentialsConfigPanelBase::~wxEAPCredentialsConfigPanelBase()
{
// Disconnect Events
this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( wxEAPCredentialsConfigPanelBase::OnUpdateUI ) );
m_clear_own->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPCredentialsConfigPanelBase::OnClearOwn ), NULL, this );
m_set_own->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPCredentialsConfigPanelBase::OnSetOwn ), NULL, this );
m_set_preshared->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPCredentialsConfigPanelBase::OnSetPreshared ), NULL, this );
m_own_clear->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPCredentialsConfigPanelBase::OnClearOwn ), NULL, this );
m_own_set->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPCredentialsConfigPanelBase::OnSetOwn ), NULL, this );
m_preshared_set->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPCredentialsConfigPanelBase::OnSetPreshared ), NULL, this );
}
wxPasswordCredentialsPanelBase::wxPasswordCredentialsPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
wxEAPCredentialsPassPanelBase::wxEAPCredentialsPassPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
{
wxStaticBoxSizer* sb_credentials;
sb_credentials = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Client Credentials") ), wxVERTICAL );
@@ -302,6 +351,168 @@ wxPasswordCredentialsPanelBase::wxPasswordCredentialsPanelBase( wxWindow* parent
this->Layout();
}
wxPasswordCredentialsPanelBase::~wxPasswordCredentialsPanelBase()
wxEAPCredentialsPassPanelBase::~wxEAPCredentialsPassPanelBase()
{
}
wxEAPProviderIdentityPanelBase::wxEAPProviderIdentityPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
{
wxStaticBoxSizer* sb_provider_id;
sb_provider_id = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Your Organization") ), wxVERTICAL );
wxBoxSizer* sb_provider_id_horiz;
sb_provider_id_horiz = new wxBoxSizer( wxHORIZONTAL );
m_provider_id_icon = new wxStaticBitmap( sb_provider_id->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
sb_provider_id_horiz->Add( m_provider_id_icon, 0, wxALL, 5 );
wxBoxSizer* sb_provider_id_vert;
sb_provider_id_vert = new wxBoxSizer( wxVERTICAL );
m_provider_id_label = new wxStaticText( sb_provider_id->GetStaticBox(), wxID_ANY, _("Describe your organization to customize user prompts. When organization is introduced, end-users find program messages easier to understand and act."), wxDefaultPosition, wxDefaultSize, 0 );
m_provider_id_label->Wrap( 446 );
sb_provider_id_vert->Add( m_provider_id_label, 0, wxALL|wxEXPAND, 5 );
wxBoxSizer* sb_provider_name;
sb_provider_name = new wxBoxSizer( wxVERTICAL );
m_provider_name_label = new wxStaticText( sb_provider_id->GetStaticBox(), wxID_ANY, _("Your organization &name:"), wxDefaultPosition, wxDefaultSize, 0 );
m_provider_name_label->Wrap( -1 );
sb_provider_name->Add( m_provider_name_label, 0, wxBOTTOM, 5 );
m_provider_name = new wxTextCtrl( sb_provider_id->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_provider_name->SetToolTip( _("Your organization name as it will appear on helpdesk contact notifications") );
sb_provider_name->Add( m_provider_name, 0, wxEXPAND|wxBOTTOM, 5 );
m_provider_name_note = new wxStaticText( sb_provider_id->GetStaticBox(), wxID_ANY, _("(Keep it short, please)"), wxDefaultPosition, wxDefaultSize, 0 );
m_provider_name_note->Wrap( -1 );
sb_provider_name->Add( m_provider_name_note, 0, wxALIGN_RIGHT, 5 );
sb_provider_id_vert->Add( sb_provider_name, 0, wxEXPAND|wxALL, 5 );
wxBoxSizer* sb_provider_helpdesk;
sb_provider_helpdesk = new wxBoxSizer( wxVERTICAL );
m_provider_helpdesk_label = new wxStaticText( sb_provider_id->GetStaticBox(), wxID_ANY, _("Helpdesk contact &information:"), wxDefaultPosition, wxDefaultSize, 0 );
m_provider_helpdesk_label->Wrap( -1 );
sb_provider_helpdesk->Add( m_provider_helpdesk_label, 0, wxBOTTOM, 5 );
wxFlexGridSizer* sb_provider_helpdesk_inner;
sb_provider_helpdesk_inner = new wxFlexGridSizer( 0, 2, 0, 0 );
sb_provider_helpdesk_inner->AddGrowableCol( 1 );
sb_provider_helpdesk_inner->SetFlexibleDirection( wxBOTH );
sb_provider_helpdesk_inner->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_provider_web_icon = new wxStaticText( sb_provider_id->GetStaticBox(), wxID_ANY, _(""), wxDefaultPosition, wxDefaultSize, 0 );
m_provider_web_icon->Wrap( -1 );
m_provider_web_icon->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Wingdings") ) );
sb_provider_helpdesk_inner->Add( m_provider_web_icon, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
m_provider_web = new wxTextCtrl( sb_provider_id->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_provider_web->SetToolTip( _("Your helpdesk website") );
sb_provider_helpdesk_inner->Add( m_provider_web, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
m_provider_email_icon = new wxStaticText( sb_provider_id->GetStaticBox(), wxID_ANY, _("*"), wxDefaultPosition, wxDefaultSize, 0 );
m_provider_email_icon->Wrap( -1 );
m_provider_email_icon->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Wingdings") ) );
sb_provider_helpdesk_inner->Add( m_provider_email_icon, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
m_provider_email = new wxTextCtrl( sb_provider_id->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_provider_email->SetToolTip( _("Your helpdesk e-mail address") );
sb_provider_helpdesk_inner->Add( m_provider_email, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
m_provider_phone_icon = new wxStaticText( sb_provider_id->GetStaticBox(), wxID_ANY, _(")"), wxDefaultPosition, wxDefaultSize, 0 );
m_provider_phone_icon->Wrap( -1 );
m_provider_phone_icon->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxT("Wingdings") ) );
sb_provider_helpdesk_inner->Add( m_provider_phone_icon, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_provider_phone = new wxTextCtrl( sb_provider_id->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_provider_phone->SetToolTip( _("Your helpdesk phone number") );
sb_provider_helpdesk_inner->Add( m_provider_phone, 1, wxEXPAND|wxALIGN_CENTER_VERTICAL, 5 );
sb_provider_helpdesk->Add( sb_provider_helpdesk_inner, 1, wxEXPAND, 5 );
sb_provider_id_vert->Add( sb_provider_helpdesk, 1, wxEXPAND, 5 );
sb_provider_id_horiz->Add( sb_provider_id_vert, 1, wxEXPAND, 5 );
sb_provider_id->Add( sb_provider_id_horiz, 1, wxEXPAND, 5 );
this->SetSizer( sb_provider_id );
this->Layout();
// Connect Events
this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( wxEAPProviderIdentityPanelBase::OnUpdateUI ) );
}
wxEAPProviderIdentityPanelBase::~wxEAPProviderIdentityPanelBase()
{
// Disconnect Events
this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( wxEAPProviderIdentityPanelBase::OnUpdateUI ) );
}
wxEAPProviderLockPanelBase::wxEAPProviderLockPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
{
wxStaticBoxSizer* sb_provider_lock;
sb_provider_lock = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Configuration Lock") ), wxVERTICAL );
wxBoxSizer* sb_provider_lock_horiz;
sb_provider_lock_horiz = new wxBoxSizer( wxHORIZONTAL );
m_provider_lock_icon = new wxStaticBitmap( sb_provider_lock->GetStaticBox(), wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
sb_provider_lock_horiz->Add( m_provider_lock_icon, 0, wxALL, 5 );
wxBoxSizer* sb_provider_lock_vert;
sb_provider_lock_vert = new wxBoxSizer( wxVERTICAL );
m_provider_lock_label = new wxStaticText( sb_provider_lock->GetStaticBox(), wxID_ANY, _("Your configuration can be locked to prevent accidental modification by end-users. Users will only be allowed to enter credentials."), wxDefaultPosition, wxDefaultSize, 0 );
m_provider_lock_label->Wrap( 446 );
sb_provider_lock_vert->Add( m_provider_lock_label, 0, wxALL|wxEXPAND, 5 );
wxBoxSizer* sb_provider_name;
sb_provider_name = new wxBoxSizer( wxVERTICAL );
m_provider_lock = new wxCheckBox( sb_provider_lock->GetStaticBox(), wxID_ANY, _("&Lock this configuration and prevent any further modification via user interface."), wxDefaultPosition, wxDefaultSize, 0 );
sb_provider_name->Add( m_provider_lock, 0, wxEXPAND|wxBOTTOM, 5 );
m_provider_lock_note = new wxStaticText( sb_provider_lock->GetStaticBox(), wxID_ANY, _("(Warning: Once locked, you can not revert using this dialog!)"), wxDefaultPosition, wxDefaultSize, 0 );
m_provider_lock_note->Wrap( -1 );
sb_provider_name->Add( m_provider_lock_note, 0, wxALIGN_RIGHT, 5 );
sb_provider_lock_vert->Add( sb_provider_name, 0, wxEXPAND|wxALL, 5 );
sb_provider_lock_horiz->Add( sb_provider_lock_vert, 1, wxEXPAND, 5 );
sb_provider_lock->Add( sb_provider_lock_horiz, 1, wxEXPAND, 5 );
this->SetSizer( sb_provider_lock );
this->Layout();
// Connect Events
this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( wxEAPProviderLockPanelBase::OnUpdateUI ) );
}
wxEAPProviderLockPanelBase::~wxEAPProviderLockPanelBase()
{
// Disconnect Events
this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( wxEAPProviderLockPanelBase::OnUpdateUI ) );
}

File diff suppressed because it is too large Load Diff

View File

@@ -18,8 +18,8 @@ class wxEAPBannerPanel;
#include <wx/settings.h>
#include <wx/string.h>
#include <wx/notebook.h>
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/dialog.h>
#include <wx/stattext.h>
#include <wx/panel.h>
@@ -44,12 +44,15 @@ class wxEAPConfigDialogBase : public wxDialog
protected:
wxEAPBannerPanel *m_banner;
wxNotebook* m_providers;
wxButton* m_advanced;
wxStdDialogButtonSizer* m_buttons;
wxButton* m_buttonsOK;
wxButton* m_buttonsCancel;
// Virtual event handlers, overide them in your derived class
virtual void OnInitDialog( wxInitDialogEvent& event ) { event.Skip(); }
virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnAdvanced( wxCommandEvent& event ) { event.Skip(); }
public:
@@ -60,9 +63,9 @@ class wxEAPConfigDialogBase : public wxDialog
};
///////////////////////////////////////////////////////////////////////////////
/// Class wxEAPCredentialsDialogBase
/// Class wxEAPGeneralDialogBase
///////////////////////////////////////////////////////////////////////////////
class wxEAPCredentialsDialogBase : public wxDialog
class wxEAPGeneralDialogBase : public wxDialog
{
private:
@@ -79,8 +82,8 @@ class wxEAPCredentialsDialogBase : public wxDialog
public:
wxEAPCredentialsDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("EAP Credentials"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE );
~wxEAPCredentialsDialogBase();
wxEAPGeneralDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE );
~wxEAPGeneralDialogBase();
};
@@ -92,15 +95,34 @@ class wxEAPBannerPanelBase : public wxPanel
private:
protected:
wxStaticText* m_title;
public:
wxStaticText* m_title;
wxEAPBannerPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = 0 );
~wxEAPBannerPanelBase();
};
///////////////////////////////////////////////////////////////////////////////
/// Class wxEAPNotePanelBase
///////////////////////////////////////////////////////////////////////////////
class wxEAPNotePanelBase : public wxPanel
{
private:
protected:
wxStaticBitmap* m_note_icon;
wxBoxSizer* m_note_vert;
wxStaticText* m_note_label;
public:
wxEAPNotePanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,-1 ), long style = wxSIMPLE_BORDER|wxTAB_TRAVERSAL );
~wxEAPNotePanelBase();
};
///////////////////////////////////////////////////////////////////////////////
/// Class wxEAPCredentialsConfigPanelBase
///////////////////////////////////////////////////////////////////////////////
@@ -112,12 +134,12 @@ class wxEAPCredentialsConfigPanelBase : public wxPanel
wxStaticBitmap* m_credentials_icon;
wxStaticText* m_credentials_label;
wxRadioButton* m_own;
wxTextCtrl* m_identity_own;
wxButton* m_clear_own;
wxButton* m_set_own;
wxTextCtrl* m_own_identity;
wxButton* m_own_clear;
wxButton* m_own_set;
wxRadioButton* m_preshared;
wxTextCtrl* m_identity_preshared;
wxButton* m_set_preshared;
wxTextCtrl* m_preshared_identity;
wxButton* m_preshared_set;
// Virtual event handlers, overide them in your derived class
virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); }
@@ -134,9 +156,9 @@ class wxEAPCredentialsConfigPanelBase : public wxPanel
};
///////////////////////////////////////////////////////////////////////////////
/// Class wxPasswordCredentialsPanelBase
/// Class wxEAPCredentialsPassPanelBase
///////////////////////////////////////////////////////////////////////////////
class wxPasswordCredentialsPanelBase : public wxPanel
class wxEAPCredentialsPassPanelBase : public wxPanel
{
private:
@@ -151,8 +173,64 @@ class wxPasswordCredentialsPanelBase : public wxPanel
public:
wxPasswordCredentialsPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,-1 ), long style = wxTAB_TRAVERSAL );
~wxPasswordCredentialsPanelBase();
wxEAPCredentialsPassPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,-1 ), long style = wxTAB_TRAVERSAL );
~wxEAPCredentialsPassPanelBase();
};
///////////////////////////////////////////////////////////////////////////////
/// Class wxEAPProviderIdentityPanelBase
///////////////////////////////////////////////////////////////////////////////
class wxEAPProviderIdentityPanelBase : public wxPanel
{
private:
protected:
wxStaticBitmap* m_provider_id_icon;
wxStaticText* m_provider_id_label;
wxStaticText* m_provider_name_label;
wxTextCtrl* m_provider_name;
wxStaticText* m_provider_name_note;
wxStaticText* m_provider_helpdesk_label;
wxStaticText* m_provider_web_icon;
wxTextCtrl* m_provider_web;
wxStaticText* m_provider_email_icon;
wxTextCtrl* m_provider_email;
wxStaticText* m_provider_phone_icon;
wxTextCtrl* m_provider_phone;
// Virtual event handlers, overide them in your derived class
virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); }
public:
wxEAPProviderIdentityPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,-1 ), long style = wxTAB_TRAVERSAL );
~wxEAPProviderIdentityPanelBase();
};
///////////////////////////////////////////////////////////////////////////////
/// Class wxEAPProviderLockPanelBase
///////////////////////////////////////////////////////////////////////////////
class wxEAPProviderLockPanelBase : public wxPanel
{
private:
protected:
wxStaticBitmap* m_provider_lock_icon;
wxStaticText* m_provider_lock_label;
wxCheckBox* m_provider_lock;
wxStaticText* m_provider_lock_note;
// Virtual event handlers, overide them in your derived class
virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); }
public:
wxEAPProviderLockPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,-1 ), long style = wxTAB_TRAVERSAL );
~wxEAPProviderLockPanelBase();
};

View File

@@ -22,10 +22,26 @@
//////////////////////////////////////////////////////////////////////
// wxEAPCredentialsDialog
// wxEAPBannerPanel
//////////////////////////////////////////////////////////////////////
wxEAPCredentialsDialog::wxEAPCredentialsDialog(wxWindow* parent) : wxEAPCredentialsDialogBase(parent)
wxEAPBannerPanel::wxEAPBannerPanel(wxWindow* parent) : wxEAPBannerPanelBase(parent)
{
m_title->SetLabelText(wxT(PRODUCT_NAME_STR));
}
bool wxEAPBannerPanel::AcceptsFocusFromKeyboard() const
{
return false;
}
//////////////////////////////////////////////////////////////////////
// wxEAPGeneralDialog
//////////////////////////////////////////////////////////////////////
wxEAPGeneralDialog::wxEAPGeneralDialog(wxWindow* parent, const wxString& title) : wxEAPGeneralDialogBase(parent, wxID_ANY, title)
{
// Set extra style here, as wxFormBuilder overrides all default flags.
this->SetExtraStyle(this->GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
@@ -34,7 +50,7 @@ wxEAPCredentialsDialog::wxEAPCredentialsDialog(wxWindow* parent) : wxEAPCredenti
}
void wxEAPCredentialsDialog::AddContents(wxPanel **contents, size_t content_count)
void wxEAPGeneralDialog::AddContent(wxPanel **contents, size_t content_count)
{
if (content_count) {
for (size_t i = 0; i < content_count; i++)
@@ -47,7 +63,13 @@ void wxEAPCredentialsDialog::AddContents(wxPanel **contents, size_t content_coun
}
void wxEAPCredentialsDialog::OnInitDialog(wxInitDialogEvent& event)
void wxEAPGeneralDialog::AddContent(wxPanel *content)
{
AddContent(&content, 1);
}
void wxEAPGeneralDialog::OnInitDialog(wxInitDialogEvent& event)
{
for (wxSizerItemList::compatibility_iterator panel = m_panels->GetChildren().GetFirst(); panel; panel = panel->GetNext())
panel->GetData()->GetWindow()->GetEventHandler()->ProcessEvent(event);
@@ -55,52 +77,269 @@ void wxEAPCredentialsDialog::OnInitDialog(wxInitDialogEvent& event)
//////////////////////////////////////////////////////////////////////
// wxEAPBannerPanel
// wxEAPCredentialsDialog
//////////////////////////////////////////////////////////////////////
wxEAPBannerPanel::wxEAPBannerPanel(wxWindow* parent) : wxEAPBannerPanelBase(parent)
wxEAPCredentialsDialog::wxEAPCredentialsDialog(const eap::config_provider &prov, wxWindow* parent) : wxEAPGeneralDialog(parent, _("EAP Credentials"))
{
m_title->SetLabelText(wxT(PRODUCT_NAME_STR));
// Set banner title.
m_banner->m_title->SetLabel(wxString::Format(_("%s Credentials"), wxEAPGetProviderName(prov.m_id).c_str()));
}
//////////////////////////////////////////////////////////////////////
// wxPasswordCredentialsPanel
// wxEAPNotePanel
//////////////////////////////////////////////////////////////////////
const wxStringCharType *wxPasswordCredentialsPanel::s_dummy_password = wxT("dummypass");
wxEAPNotePanel::wxEAPNotePanel(wxWindow* parent) :
m_provider_notice(NULL),
m_help_web_label(NULL),
m_help_web_value(NULL),
m_help_email_label(NULL),
m_help_email_value(NULL),
m_help_phone_label(NULL),
m_help_phone_value(NULL),
wxEAPNotePanelBase(parent)
{
}
wxPasswordCredentialsPanel::wxPasswordCredentialsPanel(eap::credentials_pass &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config) :
wxCredentialsPanel<wxPasswordCredentialsPanelBase, eap::credentials_pass>(cred, pszCredTarget, parent, is_config)
bool wxEAPNotePanel::AcceptsFocusFromKeyboard() const
{
return m_help_web_value || m_help_email_value || m_help_phone_label;
}
void wxEAPNotePanel::CreateContactFields(const eap::config_provider &prov)
{
if (!prov.m_help_email.empty() || !prov.m_help_web.empty() || !prov.m_help_phone.empty()) {
m_provider_notice = new wxStaticText(this, wxID_ANY, wxString::Format(_("For additional help and instructions, please contact %s at:"),
!prov.m_name.empty() ? prov.m_name.c_str() :
!prov.m_id .empty() ? winstd::tstring_printf(_("your %ls provider"), prov.m_id.c_str()).c_str() : _("your provider")), wxDefaultPosition, wxDefaultSize, 0);
m_provider_notice->Wrap(449);
m_note_vert->Add(m_provider_notice, 0, wxUP|wxLEFT|wxRIGHT|wxEXPAND, 5);
wxFlexGridSizer* sb_contact_tbl;
sb_contact_tbl = new wxFlexGridSizer(0, 2, 5, 5);
sb_contact_tbl->AddGrowableCol(1);
sb_contact_tbl->SetFlexibleDirection(wxBOTH);
sb_contact_tbl->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
wxFont font_wingdings(-1, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("Wingdings"));
if (!prov.m_help_web.empty()) {
m_help_web_label = new wxStaticText(this, wxID_ANY, wxT("\xb6"), wxDefaultPosition, wxDefaultSize, 0);
m_help_web_label->Wrap(-1);
m_help_web_label->SetFont(font_wingdings);
sb_contact_tbl->Add(m_help_web_label, 0, wxEXPAND|wxALIGN_TOP, 5);
m_help_web_value = new wxHyperlinkCtrl(this, wxID_ANY, prov.m_help_web, prov.m_help_web, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
m_help_web_value->SetToolTip(_("Open the default web browser"));
sb_contact_tbl->Add(m_help_web_value, 0, wxEXPAND|wxALIGN_TOP, 5);
}
if (!prov.m_help_email.empty()) {
m_help_email_label = new wxStaticText(this, wxID_ANY, wxT("\x2a"), wxDefaultPosition, wxDefaultSize, 0);
m_help_email_label->Wrap(-1);
m_help_email_label->SetFont(font_wingdings);
sb_contact_tbl->Add(m_help_email_label, 0, wxEXPAND|wxALIGN_TOP, 5);
m_help_email_value = new wxHyperlinkCtrl(this, wxID_ANY, prov.m_help_email, wxString(wxT("mailto:")) + prov.m_help_email, wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
m_help_email_value->SetToolTip(_("Open your e-mail program"));
sb_contact_tbl->Add(m_help_email_value, 0, wxEXPAND|wxALIGN_TOP, 5);
}
if (!prov.m_help_phone.empty()) {
m_help_phone_label = new wxStaticText(this, wxID_ANY, wxT("\x29"), wxDefaultPosition, wxDefaultSize, 0);
m_help_phone_label->Wrap(-1);
m_help_phone_label->SetFont(font_wingdings);
sb_contact_tbl->Add(m_help_phone_label, 0, wxEXPAND|wxALIGN_TOP, 5);
m_help_phone_value = new wxHyperlinkCtrl(this, wxID_ANY, prov.m_help_phone, wxString(wxT("tel:")) + GetPhoneNumber(prov.m_help_phone.c_str()), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
m_help_phone_value->SetToolTip(_("Dial the phone number"));
sb_contact_tbl->Add(m_help_phone_value, 0, wxEXPAND|wxALIGN_TOP, 5);
}
m_note_vert->Add(sb_contact_tbl, 0, wxLEFT|wxRIGHT|wxDOWN|wxEXPAND, 5);
}
}
//////////////////////////////////////////////////////////////////////
// wxEAPProviderLockedPanel
//////////////////////////////////////////////////////////////////////
wxEAPProviderLockedPanel::wxEAPProviderLockedPanel(const eap::config_provider &prov, wxWindow* parent) : wxEAPNotePanel(parent)
{
// Load and set icon.
if (m_shell32.load(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
wxSetIconFromResource(m_credentials_icon, m_icon, m_shell32, MAKEINTRESOURCE(269));
wxSetIconFromResource(m_note_icon, m_icon, m_shell32, MAKEINTRESOURCE(48));
m_note_label->SetLabel(wxString::Format(_("%s has pre-set parts of this configuration. Those parts are locked to prevent accidental modification."),
!prov.m_name.empty() ? prov.m_name.c_str() :
!prov.m_id .empty() ? winstd::tstring_printf(_("Your %ls provider"), prov.m_id.c_str()).c_str() : _("Your provider")));
m_note_label->Wrap(449);
CreateContactFields(prov);
this->Layout();
}
bool wxPasswordCredentialsPanel::TransferDataToWindow()
{
wxCHECK(__super::TransferDataToWindow(), false);
//////////////////////////////////////////////////////////////////////
// wxEAPCredentialWarningPanel
//////////////////////////////////////////////////////////////////////
m_identity->SetValue(m_cred.m_identity);
m_identity->SetSelection(0, -1);
m_password->SetValue(m_cred.m_password.empty() ? wxEmptyString : s_dummy_password);
wxEAPCredentialWarningPanel::wxEAPCredentialWarningPanel(const eap::config_provider &prov, wxWindow* parent) : wxEAPNotePanel(parent)
{
// Load and set icon.
if (m_shell32.load(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
wxSetIconFromResource(m_note_icon, m_icon, m_shell32, MAKEINTRESOURCE(161));
m_note_label->SetLabel(_("Previous attempt to connect failed. Please, make sure your credentials are correct, or try again later."));
m_note_label->Wrap(449);
CreateContactFields(prov);
this->Layout();
}
//////////////////////////////////////////////////////////////////////
// wxEAPConfigWindow
//////////////////////////////////////////////////////////////////////
wxEAPConfigWindow::wxEAPConfigWindow(const eap::config_provider &prov, eap::config_method &cfg, wxWindow* parent) :
m_prov(prov),
m_cfg(cfg),
wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL)
{
this->SetScrollRate(5, 5);
// Connect Events
this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxEAPConfigWindow::OnInitDialog));
this->Connect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(wxEAPConfigWindow::OnUpdateUI));
}
wxEAPConfigWindow::~wxEAPConfigWindow()
{
// Disconnect Events
this->Disconnect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(wxEAPConfigWindow::OnUpdateUI));
this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxEAPConfigWindow::OnInitDialog));
}
void wxEAPConfigWindow::OnInitDialog(wxInitDialogEvent& event)
{
UNREFERENCED_PARAMETER(event);
// Call TransferDataToWindow() manually, as wxScrolledWindow somehow skips that.
TransferDataToWindow();
}
void wxEAPConfigWindow::OnUpdateUI(wxUpdateUIEvent& event)
{
UNREFERENCED_PARAMETER(event);
if (m_parent && m_parent->IsKindOf(wxCLASSINFO(wxNotebook))) {
// We're a notebook page. Set the ID of our provider as our page label.
wxNotebook *notebook = (wxNotebook*)m_parent;
int idx = notebook->FindPage(this);
if (idx != wxNOT_FOUND)
notebook->SetPageText(idx, wxEAPGetProviderName(m_prov.m_id));
} else
this->SetLabel(wxEAPGetProviderName(m_prov.m_id));
}
//////////////////////////////////////////////////////////////////////
// wxEAPProviderIdentityPanel
//////////////////////////////////////////////////////////////////////
wxEAPProviderIdentityPanel::wxEAPProviderIdentityPanel(eap::config_provider &prov, wxWindow* parent) :
m_prov(prov),
wxEAPProviderIdentityPanelBase(parent)
{
// Load and set icon.
if (m_shell32.load(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
wxSetIconFromResource(m_provider_id_icon, m_icon, m_shell32, MAKEINTRESOURCE(259));
}
bool wxEAPProviderIdentityPanel::TransferDataToWindow()
{
m_provider_name ->SetValue(m_prov.m_id );
m_provider_web ->SetValue(m_prov.m_help_web );
m_provider_email->SetValue(m_prov.m_help_email);
m_provider_phone->SetValue(m_prov.m_help_phone);
return wxEAPProviderIdentityPanelBase::TransferDataToWindow();
}
bool wxEAPProviderIdentityPanel::TransferDataFromWindow()
{
wxCHECK(wxEAPProviderIdentityPanelBase::TransferDataFromWindow(), false);
m_prov.m_id = m_provider_name ->GetValue();
m_prov.m_help_web = m_provider_web ->GetValue();
m_prov.m_help_email = m_provider_email->GetValue();
m_prov.m_help_phone = m_provider_phone->GetValue();
return true;
}
bool wxPasswordCredentialsPanel::TransferDataFromWindow()
//////////////////////////////////////////////////////////////////////
// wxEAPProviderLockPanel
//////////////////////////////////////////////////////////////////////
wxEAPProviderLockPanel::wxEAPProviderLockPanel(eap::config_provider &prov, wxWindow* parent) :
m_prov(prov),
wxEAPProviderLockPanelBase(parent)
{
m_cred.m_identity = m_identity->GetValue();
wxString pass = m_password->GetValue();
if (pass.compare(s_dummy_password) != 0) {
m_cred.m_password = pass;
pass.assign(pass.length(), wxT('*'));
}
return __super::TransferDataFromWindow();
// Load and set icon.
if (m_shell32.load(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
wxSetIconFromResource(m_provider_lock_icon, m_icon, m_shell32, MAKEINTRESOURCE(1003));
}
bool wxEAPProviderLockPanel::TransferDataToWindow()
{
m_provider_lock->SetValue(m_prov.m_read_only);
return wxEAPProviderLockPanelBase::TransferDataToWindow();
}
bool wxEAPProviderLockPanel::TransferDataFromWindow()
{
wxCHECK(wxEAPProviderLockPanelBase::TransferDataFromWindow(), false);
m_prov.m_read_only = m_provider_lock->GetValue();
return true;
}
//////////////////////////////////////////////////////////////////////
// wxEAPConfigProvider
//////////////////////////////////////////////////////////////////////
wxEAPConfigProvider::wxEAPConfigProvider(eap::config_provider &prov, wxWindow* parent) :
m_prov(prov),
wxEAPGeneralDialog(parent, _("Provider Settings"))
{
// Set banner title.
m_banner->m_title->SetLabel(_("Provider Settings"));
m_identity = new wxEAPProviderIdentityPanel(prov, this);
AddContent(m_identity);
m_lock = new wxEAPProviderLockPanel(prov, this);
AddContent(m_lock);
m_identity->m_provider_name->SetFocusFromKbd();
}

View File

@@ -0,0 +1,32 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StdAfx.h"
using namespace std;
using namespace winstd;
//////////////////////////////////////////////////////////////////////
// eap::peer_ui
//////////////////////////////////////////////////////////////////////
eap::peer_ui::peer_ui(_In_ eap_type_t eap_method) : module(eap_method)
{
}

Binary file not shown.

Binary file not shown.

View File

@@ -93,6 +93,7 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)EventsETW.h;$(IntDir)EventsETW.rc;$(IntDir)EventsETW_MSG00001.bin;$(IntDir)EventsETWTEMP.BIN;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)EventsETW.h;$(IntDir)EventsETW.rc;$(IntDir)EventsETW_MSG00001.bin;$(IntDir)EventsETWTEMP.BIN;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)EventsETW.h;$(IntDir)EventsETW.rc;$(IntDir)EventsETW_MSG00001.bin;$(IntDir)EventsETWTEMP.BIN;%(Outputs)</Outputs>
<SubType>Designer</SubType>
</CustomBuild>
</ItemGroup>
<ItemGroup>

Binary file not shown.

View File

@@ -25,35 +25,7 @@ namespace eap
///
/// PAP configuration
///
class config_pap;
}
namespace eapserial
{
///
/// Packs a PAP based method configuration
///
/// \param[inout] cursor Memory cursor
/// \param[in] val Configuration to pack
///
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::config_pap &val);
///
/// Returns packed size of a PAP based method configuration
///
/// \param[in] val Configuration to pack
///
/// \returns Size of data when packed (in bytes)
///
inline size_t get_pk_size(const eap::config_pap &val);
///
/// Unpacks a PAP based method configuration
///
/// \param[inout] cursor Memory cursor
/// \param[out] val Configuration to unpack to
///
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::config_pap &val);
class config_method_pap;
}
#pragma once
@@ -68,29 +40,29 @@ namespace eapserial
namespace eap
{
class config_pap : public config_method<credentials_pap>
class config_method_pap : public config_method_with_cred
{
public:
///
/// Constructs configuration
///
/// \param[in] mod Reference of the EAP module to use for global services
/// \param[in] mod EAP module to use for global services
///
config_pap(_In_ module &mod);
config_method_pap(_In_ module &mod);
///
/// Copies configuration
///
/// \param[in] other Configuration to copy from
///
config_pap(_In_ const config_pap &other);
config_method_pap(_In_ const config_method_pap &other);
///
/// Moves configuration
///
/// \param[in] other Configuration to move from
///
config_pap(_Inout_ config_pap &&other);
config_method_pap(_Inout_ config_method_pap &&other);
///
/// Copies configuration
@@ -99,7 +71,7 @@ namespace eap
///
/// \returns Reference to this object
///
config_pap& operator=(_In_ const config_pap &other);
config_method_pap& operator=(_In_ const config_method_pap &other);
///
/// Moves configuration
@@ -108,7 +80,7 @@ namespace eap
///
/// \returns Reference to this object
///
config_pap& operator=(_Inout_ config_pap &&other);
config_method_pap& operator=(_Inout_ config_method_pap &&other);
///
/// Clones configuration
@@ -122,27 +94,6 @@ namespace eap
///
/// \returns `eap::type_pap`
///
virtual eap::type_t get_method_id() const;
virtual winstd::eap_type_t get_method_id() const;
};
}
namespace eapserial
{
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::config_pap &val)
{
pack(cursor, (const eap::config_method<eap::credentials_pap>&)val);
}
inline size_t get_pk_size(const eap::config_pap &val)
{
return get_pk_size((const eap::config_method<eap::credentials_pap>&)val);
}
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::config_pap &val)
{
unpack(cursor, (eap::config_method<eap::credentials_pap>&)val);
}
}

View File

@@ -18,9 +18,6 @@
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../../EAPBase/include/EAP.h"
namespace eap
{
///
@@ -29,36 +26,10 @@ namespace eap
class credentials_pap;
}
namespace eapserial
{
///
/// Packs a PAP method credentials
///
/// \param[inout] cursor Memory cursor
/// \param[in] val Credentials to pack
///
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::credentials_pap &val);
///
/// Returns packed size of a PAP method credentials
///
/// \param[in] val Credentials to pack
///
/// \returns Size of data when packed (in bytes)
///
inline size_t get_pk_size(const eap::credentials_pap &val);
///
/// Unpacks a PAP method credentials
///
/// \param[inout] cursor Memory cursor
/// \param[out] val Credentials to unpack to
///
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::credentials_pap &val);
}
#pragma once
#include "Config.h"
#include "../../EAPBase/include/Credentials.h"
#include <Windows.h>
@@ -74,7 +45,7 @@ namespace eap
///
/// Constructs credentials
///
/// \param[in] mod Reference of the EAP module to use for global services
/// \param[in] mod EAP module to use for global services
///
credentials_pap(_In_ module &mod);
@@ -126,26 +97,25 @@ namespace eap
virtual LPCTSTR target_suffix() const;
/// @}
///
/// Combine credentials in the following order:
///
/// 1. Cached credentials
/// 2. Pre-configured credentials
/// 3. Stored credentials
///
/// \param[in] cred_cached Cached credentials (optional, can be \c NULL)
/// \param[in] cfg Method configuration
/// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from (optional, can be \c NULL)
///
/// \returns
/// - \c true if credentials were set;
/// - \c false otherwise
///
source_t combine(
_In_ const credentials_pap *cred_cached,
_In_ const config_method_pap &cfg,
_In_opt_z_ LPCTSTR pszTargetName);
};
}
namespace eapserial
{
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::credentials_pap &val)
{
pack(cursor, (const eap::credentials_pass&)val);
}
inline size_t get_pk_size(const eap::credentials_pap &val)
{
return get_pk_size((const eap::credentials_pass&)val);
}
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::credentials_pap &val)
{
unpack(cursor, (eap::credentials_pass&)val);
}
}

View File

@@ -20,53 +20,57 @@
#include "StdAfx.h"
using namespace std;
using namespace winstd;
//////////////////////////////////////////////////////////////////////
// eap::config_pap
// eap::config_method_pap
//////////////////////////////////////////////////////////////////////
eap::config_pap::config_pap(_In_ module &mod) : config_method<credentials_pap>(mod)
eap::config_method_pap::config_method_pap(_In_ module &mod) : config_method_with_cred(mod)
{
m_preshared.reset(new credentials_pap(mod));
}
eap::config_method_pap::config_method_pap(_In_ const config_method_pap &other) :
config_method_with_cred(other)
{
}
eap::config_pap::config_pap(_In_ const config_pap &other) :
config_method<credentials_pap>(other)
eap::config_method_pap::config_method_pap(_Inout_ config_method_pap &&other) :
config_method_with_cred(std::move(other))
{
}
eap::config_pap::config_pap(_Inout_ config_pap &&other) :
config_method<credentials_pap>(std::move(other))
{
}
eap::config_pap& eap::config_pap::operator=(_In_ const config_pap &other)
eap::config_method_pap& eap::config_method_pap::operator=(_In_ const config_method_pap &other)
{
if (this != &other)
(config_method<credentials_pap>&)*this = other;
(config_method_with_cred&)*this = other;
return *this;
}
eap::config_pap& eap::config_pap::operator=(_Inout_ config_pap &&other)
eap::config_method_pap& eap::config_method_pap::operator=(_Inout_ config_method_pap &&other)
{
if (this != &other)
(config_method<credentials_pap>&&)*this = std::move(other);
(config_method_with_cred&&)*this = std::move(other);
return *this;
}
eap::config* eap::config_pap::clone() const
eap::config* eap::config_method_pap::clone() const
{
return new config_pap(*this);
return new config_method_pap(*this);
}
eap::type_t eap::config_pap::get_method_id() const
eap_type_t eap::config_method_pap::get_method_id() const
{
return eap::type_pap;
return eap_type_pap;
}

View File

@@ -20,6 +20,9 @@
#include "StdAfx.h"
using namespace std;
using namespace winstd;
//////////////////////////////////////////////////////////////////////
// eap::credentials_pap
@@ -70,3 +73,40 @@ LPCTSTR eap::credentials_pap::target_suffix() const
{
return _T("PAP");
}
eap::credentials::source_t eap::credentials_pap::combine(
_In_ const credentials_pap *cred_cached,
_In_ const config_method_pap &cfg,
_In_opt_z_ LPCTSTR pszTargetName)
{
if (cred_cached) {
// Using EAP service cached credentials.
*this = *cred_cached;
m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_CACHED1, event_data((unsigned int)eap_type_pap), event_data(credentials_pap::get_name()), event_data::blank);
return source_cache;
}
if (cfg.m_use_preshared) {
// Using preshared credentials.
*this = *(credentials_pap*)cfg.m_preshared.get();
m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_PRESHARED1, event_data((unsigned int)eap_type_pap), event_data(credentials_pap::get_name()), event_data::blank);
return source_preshared;
}
if (pszTargetName) {
try {
credentials_pap cred_loaded(m_module);
cred_loaded.retrieve(pszTargetName);
// Using stored credentials.
*this = std::move(cred_loaded);
m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_STORED1, event_data((unsigned int)eap_type_pap), event_data(credentials_pap::get_name()), event_data::blank);
return source_storage;
} catch (...) {
// Not actually an error.
}
}
return source_unknown;
}

View File

@@ -23,15 +23,20 @@
#include "../../PAP/include/Credentials.h"
///
/// PAP credentials configuration panel
/// PAP credential configuration panel
///
typedef wxEAPCredentialsConfigPanel<eap::config_pap, eap::credentials_pap, wxPasswordCredentialsPanel> wxPAPCredentialsConfigPanel;
typedef wxEAPCredentialsConfigPanel<eap::credentials_pap, wxPasswordCredentialsPanel<eap::credentials_pap, wxEAPCredentialsPassPanelBase> > wxPAPCredentialsConfigPanel;
///
/// PAP configuration panel
///
class wxPAPConfigPanel;
///
/// PAP credential entry panel
///
typedef wxPasswordCredentialsPanel<eap::credentials_pap, wxEAPCredentialsPassPanelBase> wxPAPCredentialsPanel;
#pragma once
#include <wx/panel.h>
@@ -46,7 +51,7 @@ public:
///
/// Constructs a configuration panel
///
wxPAPConfigPanel(eap::config_pap &cfg, LPCTSTR pszCredTarget, wxWindow* parent);
wxPAPConfigPanel(const eap::config_provider &prov, eap::config_method_pap &cfg, LPCTSTR pszCredTarget, wxWindow* parent);
///
/// Destructs the configuration panel
@@ -60,5 +65,4 @@ protected:
protected:
wxPAPCredentialsConfigPanel *m_credentials; ///< Credentials configuration panel
wxStaticText *m_label; ///< No-configuration notice
};

View File

@@ -1,21 +1,21 @@
/*
/*
Copyright 2015-2016 Amebis
Copyright 2016 GÉANT
Copyright 2016 G<EFBFBD>ANT
This file is part of GÉANTLink.
This file is part of G<EFBFBD>ANTLink.
GÉANTLink is free software: you can redistribute it and/or modify it
G<EFBFBD>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GÉANTLink is distributed in the hope that it will be useful, but
G<EFBFBD>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
along with G<EFBFBD>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StdAfx.h"
@@ -25,23 +25,13 @@
// wxPAPConfigPanel
//////////////////////////////////////////////////////////////////////
wxPAPConfigPanel::wxPAPConfigPanel(eap::config_pap &cfg, LPCTSTR pszCredTarget, wxWindow* parent) : wxPanel(parent)
wxPAPConfigPanel::wxPAPConfigPanel(const eap::config_provider &prov, eap::config_method_pap &cfg, LPCTSTR pszCredTarget, wxWindow* parent) : wxPanel(parent)
{
wxBoxSizer* sb_content;
sb_content = new wxBoxSizer( wxVERTICAL );
if (cfg.m_allow_save) {
m_credentials = new wxPAPCredentialsConfigPanel(cfg, pszCredTarget, this);
sb_content->Add(m_credentials, 0, wxEXPAND, 5);
m_label = NULL;
} else {
m_credentials = NULL;
m_label = new wxStaticText(this, wxID_ANY, _("This method requires no additional settings."), wxDefaultPosition, wxDefaultSize, 0);
m_label->Wrap(-1);
sb_content->Add(m_label, 0, wxEXPAND, 5);
}
m_credentials = new wxPAPCredentialsConfigPanel(prov, cfg, pszCredTarget, this);
sb_content->Add(m_credentials, 0, wxEXPAND, 5);
this->SetSizer(sb_content);
this->Layout();

View File

@@ -81,10 +81,13 @@
<ItemGroup>
<ClInclude Include="..\include\Config.h" />
<ClInclude Include="..\include\Credentials.h" />
<ClInclude Include="..\include\Method.h" />
<ClInclude Include="..\include\TLS.h" />
<ClInclude Include="..\src\StdAfx.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\Config.cpp" />
<ClCompile Include="..\src\Method.cpp" />
<ClCompile Include="..\src\StdAfx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
@@ -92,6 +95,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\src\Credentials.cpp" />
<ClCompile Include="..\src\TLS.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@@ -20,6 +20,12 @@
<ClInclude Include="..\include\Credentials.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\Method.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\TLS.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\StdAfx.cpp">
@@ -31,5 +37,11 @@
<ClCompile Include="..\src\Credentials.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\Method.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\TLS.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -18,6 +18,11 @@
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include <WinStd/Common.h>
#include <Windows.h>
#include <WinCrypt.h> // Must include after <Windows.h>
#include <sal.h>
namespace eap
@@ -25,40 +30,19 @@ namespace eap
///
/// TLS configuration
///
class config_tls;
}
namespace eapserial
{
///
/// Packs a TLS method configuration
///
/// \param[inout] cursor Memory cursor
/// \param[in] val Configuration to pack
///
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::config_tls &val);
class config_method_tls;
///
/// Returns packed size of a TLS method configuration
/// Helper function to compile human-readable certificate name for UI display
///
/// \param[in] val Configuration to pack
///
/// \returns Size of data when packed (in bytes)
///
inline size_t get_pk_size(const eap::config_tls &val);
///
/// Unpacks a TLS method configuration
///
/// \param[inout] cursor Memory cursor
/// \param[out] val Configuration to unpack to
///
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::config_tls &val);
winstd::tstring get_cert_title(PCCERT_CONTEXT cert);
}
#pragma once
#include "Credentials.h"
#include "Method.h"
#include "TLS.h"
#include "../../EAPBase/include/Config.h"
@@ -72,29 +56,29 @@ namespace eapserial
namespace eap
{
class config_tls : public config_method<credentials_tls>
class config_method_tls : public config_method_with_cred
{
public:
///
/// Constructs configuration
///
/// \param[in] mod Reference of the EAP module to use for global services
/// \param[in] mod EAP module to use for global services
///
config_tls(_In_ module &mod);
config_method_tls(_In_ module &mod);
///
/// Copies configuration
///
/// \param[in] other Configuration to copy from
///
config_tls(_In_ const config_tls &other);
config_method_tls(_In_ const config_method_tls &other);
///
/// Moves configuration
///
/// \param[in] other Configuration to move from
///
config_tls(_Inout_ config_tls &&other);
config_method_tls(_Inout_ config_method_tls &&other);
///
/// Copies configuration
@@ -103,7 +87,7 @@ namespace eap
///
/// \returns Reference to this object
///
config_tls& operator=(_In_ const config_tls &other);
config_method_tls& operator=(_In_ const config_method_tls &other);
///
/// Moves configuration
@@ -112,7 +96,7 @@ namespace eap
///
/// \returns Reference to this object
///
config_tls& operator=(_Inout_ config_tls &&other);
config_method_tls& operator=(_Inout_ config_method_tls &&other);
///
/// Clones configuration
@@ -125,29 +109,45 @@ namespace eap
/// @{
///
/// Save configuration to XML document
/// Save to XML document
///
/// \param[in] pDoc XML document
/// \param[in] pConfigRoot Suggested root element for saving configuration
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
/// \param[in] pConfigRoot Suggested root element for saving
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const;
virtual void save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const;
///
/// Load configuration from XML document
/// Load from XML document
///
/// \param[in] pConfigRoot Root element for loading configuration
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
/// \param[in] pConfigRoot Root element for loading
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
virtual void load(_In_ IXMLDOMNode *pConfigRoot);
/// @}
/// \name BLOB management
/// @{
///
virtual bool load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError);
/// Packs a configuration
///
/// \param[inout] cursor Memory cursor
///
virtual void operator<<(_Inout_ cursor_out &cursor) const;
///
/// Returns packed size of a configuration
///
/// \returns Size of data when packed (in bytes)
///
virtual size_t get_pk_size() const;
///
/// Unpacks a configuration
///
/// \param[inout] cursor Memory cursor
///
virtual void operator>>(_Inout_ cursor_in &cursor);
/// @}
@@ -156,7 +156,7 @@ namespace eap
///
/// \returns `eap::type_tls`
///
virtual eap::type_t get_method_id() const;
virtual winstd::eap_type_t get_method_id() const;
///
/// Adds CA to the list of trusted root CA's
@@ -167,34 +167,6 @@ namespace eap
public:
std::list<winstd::cert_context> m_trusted_root_ca; ///< Trusted root CAs
std::list<std::string> m_server_names; ///< Acceptable authenticating server names
std::list<std::wstring> m_server_names; ///< Acceptable authenticating server names
};
}
namespace eapserial
{
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::config_tls &val)
{
pack(cursor, (const eap::config_method<eap::credentials_tls>&)val);
pack(cursor, val.m_trusted_root_ca);
pack(cursor, val.m_server_names );
}
inline size_t get_pk_size(const eap::config_tls &val)
{
return
get_pk_size((const eap::config_method<eap::credentials_tls>&)val) +
get_pk_size(val.m_trusted_root_ca) +
get_pk_size(val.m_server_names );
}
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::config_tls &val)
{
unpack(cursor, (eap::config_method<eap::credentials_tls>&)val);
unpack(cursor, val.m_trusted_root_ca);
unpack(cursor, val.m_server_names );
}
}

View File

@@ -28,38 +28,11 @@ namespace eap
class credentials_tls;
}
namespace eapserial
{
///
/// Packs a TLS method credentials
///
/// \param[inout] cursor Memory cursor
/// \param[in] val Credentials to pack
///
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::credentials_tls &val);
///
/// Returns packed size of a TLS method credentials
///
/// \param[in] val Credentials to pack
///
/// \returns Size of data when packed (in bytes)
///
inline size_t get_pk_size(const eap::credentials_tls &val);
///
/// Unpacks a TLS method credentials
///
/// \param[inout] cursor Memory cursor
/// \param[out] val Credentials to unpack to
///
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::credentials_tls &val);
}
#pragma once
#include "Config.h"
#include "../../EAPBase/include/Credentials.h"
#include "../../EAPBase/include/EAPSerial.h"
#include <WinStd/Crypt.h>
@@ -75,7 +48,7 @@ namespace eap
///
/// Constructs credentials
///
/// \param[in] mod Reference of the EAP module to use for global services
/// \param[in] mod EAP module to use for global services
///
credentials_tls(_In_ module &mod);
@@ -126,35 +99,55 @@ namespace eap
///
/// Test credentials if blank
///
/// \returns
/// - \c true if blank
/// - \c false otherwise
///
virtual bool empty() const;
/// \name XML credentials management
/// @{
///
/// Save credentials to XML document
/// Save to XML document
///
/// \param[in] pDoc XML document
/// \param[in] pConfigRoot Suggested root element for saving credentials
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
/// \param[in] pConfigRoot Suggested root element for saving
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const;
virtual void save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const;
///
/// Load credentials from XML document
/// Load from XML document
///
/// \param[in] pConfigRoot Root element for loading credentials
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
/// \param[in] pConfigRoot Root element for loading
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
virtual void load(_In_ IXMLDOMNode *pConfigRoot);
/// @}
/// \name BLOB management
/// @{
///
virtual bool load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError);
/// Packs a configuration
///
/// \param[inout] cursor Memory cursor
///
virtual void operator<<(_Inout_ cursor_out &cursor) const;
///
/// Returns packed size of a configuration
///
/// \returns Size of data when packed (in bytes)
///
virtual size_t get_pk_size() const;
///
/// Unpacks a configuration
///
/// \param[inout] cursor Memory cursor
///
virtual void operator>>(_Inout_ cursor_in &cursor);
/// @}
@@ -165,67 +158,59 @@ namespace eap
/// Save credentials to Windows Credential Manager
///
/// \param[in] pszTargetName The name in Windows Credential Manager to store credentials as
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError) const;
virtual void store(_In_z_ LPCTSTR pszTargetName) const;
///
/// Retrieve credentials from Windows Credential Manager
///
/// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError);
virtual void retrieve(_In_z_ LPCTSTR pszTargetName);
///
/// Return target suffix for Windows Credential Manager credential name
///
virtual LPCTSTR target_suffix() const { return _T("TLS"); }
virtual LPCTSTR target_suffix() const;
/// @}
///
/// Returns credential identity.
///
virtual std::wstring get_identity() const;
///
/// Returns credential name (for GUI display).
///
virtual winstd::tstring get_name() const;
///
/// Combine credentials in the following order:
///
/// 1. Cached credentials
/// 2. Pre-configured credentials
/// 3. Stored credentials
///
/// \param[in] cred_cached Cached credentials (optional, can be \c NULL)
/// \param[in] cfg Method configuration
/// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from (optional, can be \c NULL)
///
/// \returns
/// - \c true if credentials were set;
/// - \c false otherwise
///
source_t combine(
_In_ const credentials_tls *cred_cached,
_In_ const config_method_tls &cfg,
_In_opt_z_ LPCTSTR pszTargetName);
public:
winstd::cert_context m_cert; ///< Client certificate
private:
/// \cond internal
static const unsigned char s_entropy[1024];
/// \endcond
};
}
namespace eapserial
{
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::credentials_tls &val)
{
// Don't save m_identity. We rebuild it on every load.
//pack(cursor, (const eap::credentials&)val);
pack(cursor, val.m_cert );
}
inline size_t get_pk_size(const eap::credentials_tls &val)
{
return
// Don't save m_identity. We rebuild it on every load.
//get_pk_size((const eap::credentials&)val) +
get_pk_size(val.m_cert );
}
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::credentials_tls &val)
{
// Don't load m_identity. We rebuild it on load.
//unpack(cursor, (eap::credentials&)val);
unpack(cursor, val.m_cert );
if (val.m_cert) {
// Generate identity. TODO: Find which CERT_NAME_... constant returns valid identity (username@domain or DOMAIN\Username).
CertGetNameString(val.m_cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, val.m_identity);
}
}
}

260
lib/TLS/include/Method.h Normal file
View File

@@ -0,0 +1,260 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
namespace eap
{
///
/// EAP-TLS method
///
class method_tls;
}
#pragma once
#include "Config.h"
#include "Credentials.h"
#include "TLS.h"
#include "../../EAPBase/include/Method.h"
#include <WinStd/Crypt.h>
#include <WinStd/Sec.h>
#include <list>
#include <vector>
namespace eap
{
class method_tls : public method
{
public:
#pragma warning(push)
#pragma warning(disable: 4480)
///
/// EAP-TLS request packet flags
///
/// \sa [The EAP-TLS Authentication Protocol (Chapter: 3.1 EAP-TLS Request Packet)](https://tools.ietf.org/html/rfc5216#section-3.1)
///
enum flags_req_t : unsigned char {
flags_req_length_incl = 0x80, ///< Length included
flags_req_more_frag = 0x40, ///< More fragments
flags_req_start = 0x20, ///< Start
};
///
/// EAP-TLS response packet flags
///
/// \sa [The EAP-TLS Authentication Protocol (Chapter: 3.2 EAP-TLS Response Packet)](https://tools.ietf.org/html/rfc5216#section-3.2)
///
enum flags_res_t : unsigned char {
flags_res_length_incl = 0x80, ///< Length included
flags_res_more_frag = 0x40, ///< More fragments
};
#pragma warning(pop)
///
/// EAP-TLS packet (data)
///
class packet
{
public:
///
/// Constructs an empty packet
///
packet();
///
/// Copies a packet
///
/// \param[in] other Packet to copy from
///
packet(_In_ const packet &other);
///
/// Moves a packet
///
/// \param[in] other Packet to move from
///
packet(_Inout_ packet &&other);
///
/// Copies a packet
///
/// \param[in] other Packet to copy from
///
/// \returns Reference to this object
///
packet& operator=(_In_ const packet &other);
///
/// Moves a packet
///
/// \param[in] other Packet to move from
///
/// \returns Reference to this object
///
packet& operator=(_Inout_ packet &&other);
///
/// Empty the packet
///
void clear();
public:
EapCode m_code; ///< Packet code
unsigned char m_id; ///< Packet ID
unsigned char m_flags; ///< Packet flags
std::vector<unsigned char> m_data; ///< Packet data
};
public:
///
/// Constructs an EAP method
///
/// \param[in] mod EAP module to use for global services
/// \param[in] cfg Providers configuration
/// \param[in] cred User credentials
///
method_tls(_In_ module &module, _In_ config_provider_list &cfg, _In_ credentials_tls &cred);
///
/// Moves an EAP method
///
/// \param[in] other EAP method to move from
///
method_tls(_Inout_ method_tls &&other);
///
/// Destructor
///
virtual ~method_tls();
///
/// Moves an EAP method
///
/// \param[in] other EAP method to move from
///
/// \returns Reference to this object
///
method_tls& operator=(_Inout_ method_tls &&other);
/// \name Packet processing
/// @{
///
/// Starts an EAP authentication session on the peer EAPHost using the EAP method.
///
/// \sa [EapPeerBeginSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363600.aspx)
///
virtual void begin_session(
_In_ DWORD dwFlags,
_In_ const EapAttributes *pAttributeArray,
_In_ HANDLE hTokenImpersonateUser,
_In_ DWORD dwMaxSendPacketSize);
///
/// Processes a packet received by EAPHost from a supplicant.
///
/// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx)
///
virtual void process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize,
_Inout_ EapPeerMethodOutput *pEapOutput);
///
/// Obtains a response packet from the EAP method.
///
/// \sa [EapPeerGetResponsePacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363610.aspx)
///
virtual void get_response_packet(
_Inout_bytecap_(*dwSendPacketSize) EapPacket *pSendPacket,
_Inout_ DWORD *pdwSendPacketSize);
///
/// Obtains the result of an authentication session from the EAP method.
///
/// \sa [EapPeerGetResult function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363611.aspx)
///
virtual void get_result(
_In_ EapPeerMethodResultReason reason,
_Inout_ EapPeerMethodResult *ppResult);
/// @}
protected:
///
/// Process handshake
///
void process_handshake();
///
/// Process application data
///
void process_application_data();
///
/// Processes an application message
///
/// \param[in] msg Application message data
/// \param[in] size_msg Application message data size
///
virtual void process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg);
#ifndef SCHANNEL_SRV_CERT_CHECK
///
/// Verifies server's certificate if trusted by configuration
///
void verify_server_trust() const;
#endif
protected:
credentials_tls &m_cred; ///< EAP-TLS user credentials
packet m_packet_req; ///< Request packet
packet m_packet_res; ///< Response packet
HANDLE m_user_ctx; ///< Handle to user context
winstd::tstring m_sc_target_name; ///< Schannel target name
winstd::sec_credentials m_sc_cred; ///< Schannel client credentials
std::vector<unsigned char> m_sc_queue; ///< TLS data queue
winstd::sec_context m_sc_ctx; ///< Schannel context
enum {
phase_unknown = -1, ///< Unknown phase
phase_handshake_init = 0, ///< Handshake initialize
phase_handshake_cont, ///< Handshake continue
phase_application_data, ///< Exchange application data
phase_shutdown, ///< Connection shut down
} m_phase; ///< What phase is our communication at?
// The following members are required to avoid memory leakage in get_result()
EAP_ATTRIBUTES m_eap_attr_desc; ///< EAP Radius attributes descriptor
std::vector<winstd::eap_attr> m_eap_attr; ///< EAP Radius attributes
BYTE *m_blob_cfg; ///< Configuration BLOB
#ifdef EAP_USE_NATIVE_CREDENTIAL_CACHE
BYTE *m_blob_cred; ///< Credentials BLOB
#endif
};
}

517
lib/TLS/include/TLS.h Normal file
View File

@@ -0,0 +1,517 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../../EAPBase/include/EAP.h"
namespace eap
{
///
/// TLS packet type
///
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter: A.1. Record Layer](https://tools.ietf.org/html/rfc5246#appendix-A.1)
///
enum tls_message_type_t;
///
/// TLS handshake type
///
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter: A.4. Handshake Protocol](https://tools.ietf.org/html/rfc5246#appendix-A.4)
///
enum tls_handshake_type_t;
///
/// TLS alert level
///
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter: 7.2. Alert Protocol)](https://tools.ietf.org/html/rfc5246#section-7.2)
///
enum tls_alert_level_t;
///
/// TLS alert description
///
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter: 7.2. Alert Protocol)](https://tools.ietf.org/html/rfc5246#section-7.2)
///
enum tls_alert_desc_t;
///
/// TLS protocol version
///
struct tls_version;
extern const tls_version tls_version_1_0;
extern const tls_version tls_version_1_1;
extern const tls_version tls_version_1_2;
///
/// TLS client/server random
///
struct tls_random;
///
/// Master secret
///
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (8.1. Computing the Master Secret)](https://tools.ietf.org/html/rfc5246#section-8.1)
///
struct tls_master_secret;
///
/// HMAC padding
///
/// \sa [HMAC: Keyed-Hashing for Message Authentication](https://tools.ietf.org/html/rfc2104)
///
struct hmac_padding;
///
/// Our own implementation of HMAC hashing
/// Microsoft's implementation ([MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/aa382379.aspx)) is flaky.
///
/// \sa [HMAC: Keyed-Hashing for Message Authentication](https://tools.ietf.org/html/rfc2104)
///
class hmac_hash;
///
/// TLS client connection state
///
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter 6.1. Connection States)](https://tools.ietf.org/html/rfc5246#section-6.1)
///
class tls_conn_state;
}
/////
///// Packs a TLS connection state
/////
///// \param[inout] cursor Memory cursor
///// \param[in] val Variable with data to pack
/////
//inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const eap::tls_conn_state &val);
//
/////
///// Returns packed size of TLS connection state
/////
///// \param[in] val Data to pack
/////
///// \returns Size of data when packed (in bytes)
/////
//inline size_t pksizeof(_In_ const eap::tls_conn_state &val);
//
/////
///// Unpacks a TLS connection state
/////
///// \param[inout] cursor Memory cursor
///// \param[out] val Variable to receive unpacked value
/////
//inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ eap::tls_conn_state &val);
#pragma once
#include <memory>
namespace eap
{
#pragma warning(push)
#pragma warning(disable: 4480)
enum tls_message_type_t : unsigned char
{
tls_message_type_change_cipher_spec = 20,
tls_message_type_alert = 21,
tls_message_type_handshake = 22,
tls_message_type_application_data = 23,
};
enum tls_handshake_type_t : unsigned char
{
tls_handshake_type_hello_request = 0,
tls_handshake_type_client_hello = 1,
tls_handshake_type_server_hello = 2,
tls_handshake_type_certificate = 11,
tls_handshake_type_server_key_exchange = 12,
tls_handshake_type_certificate_request = 13,
tls_handshake_type_server_hello_done = 14,
tls_handshake_type_certificate_verify = 15,
tls_handshake_type_client_key_exchange = 16,
tls_handshake_type_finished = 20,
tls_handshake_type_min = 0, ///< First existing handshake message
tls_handshake_type_max = 21 ///< First non-existing (officially) handshake message
};
enum tls_alert_level_t : unsigned char
{
tls_alert_level_warning = 1,
tls_alert_level_fatal = 2,
};
enum tls_alert_desc_t : unsigned char
{
tls_alert_desc_close_notify = 0,
tls_alert_desc_unexpected_message = 10,
tls_alert_desc_bad_record_mac = 20,
tls_alert_desc_decryption_failed = 21, // reserved
tls_alert_desc_record_overflow = 22,
tls_alert_desc_decompression_failure = 30,
tls_alert_desc_handshake_failure = 40,
tls_alert_desc_no_certificate = 41, // reserved
tls_alert_desc_bad_certificate = 42,
tls_alert_desc_unsupported_certificate = 43,
tls_alert_desc_certificate_revoked = 44,
tls_alert_desc_certificate_expired = 45,
tls_alert_desc_certificate_unknown = 46,
tls_alert_desc_illegal_parameter = 47,
tls_alert_desc_unknown_ca = 48,
tls_alert_desc_access_denied = 49,
tls_alert_desc_decode_error = 50,
tls_alert_desc_decrypt_error = 51,
tls_alert_desc_export_restriction = 60, // reserved
tls_alert_desc_protocol_version = 70,
tls_alert_desc_insufficient_security = 71,
tls_alert_desc_internal_error = 80,
tls_alert_desc_user_canceled = 90,
tls_alert_desc_no_renegotiation = 100,
tls_alert_desc_unsupported_extension = 110,
};
#pragma warning(pop)
#pragma pack(push)
#pragma pack(1)
///
/// TLS protocol version
///
struct __declspec(novtable) tls_version
{
unsigned char major; ///< Major version
unsigned char minor; ///< Minor version
///
/// Copies a TLS version
///
/// \param[in] other Version to copy from
///
/// \returns Reference to this object
///
inline tls_version& operator=(_In_ const tls_version &other)
{
if (this != std::addressof(other)) {
major = other.major;
minor = other.minor;
}
return *this;
}
///
/// Is version less than?
///
/// \param[in] other Protocol version to compare against
/// \return
/// - Non zero when protocol version is less than h;
/// - Zero otherwise.
///
inline bool operator<(_In_ const tls_version &other) const
{
return major < other.major || major == other.major && minor < other.minor;
}
///
/// Is version less than or equal to?
///
/// \param[in] other Protocol version to compare against
/// \return
/// - Non zero when protocol version is less than or equal to h;
/// - Zero otherwise.
///
inline bool operator<=(_In_ const tls_version &other) const
{
return !operator>(other);
}
///
/// Is version greater than or equal to?
///
/// \param[in] other Protocol version to compare against
/// \return
/// - Non zero when protocol version is greater than or equal to h;
/// - Zero otherwise.
///
inline bool operator>=(_In_ const tls_version &other) const
{
return !operator<(other);
}
///
/// Is version greater than?
///
/// \param[in] other Protocol version to compare against
/// \return
/// - Non zero when protocol version is greater than h;
/// - Zero otherwise.
///
inline bool operator>(_In_ const tls_version &other) const
{
return other.major < major || other.major == major && other.minor < minor;
}
///
/// Is version not equal to?
///
/// \param[in] other Protocol version to compare against
/// \return
/// - Non zero when protocol version is not equal to h;
/// - Zero otherwise.
///
inline bool operator!=(_In_ const tls_version &other) const
{
return !operator==(other);
}
///
/// Is version equal to?
///
/// \param[in] other Protocol version to compare against
/// \return
/// - Non zero when protocol version is equal to h;
/// - Zero otherwise.
///
inline bool operator==(_In_ const tls_version &other) const
{
return major == other.major && minor == other.minor;
}
};
#pragma pack(pop)
#pragma pack(push)
#pragma pack(1)
struct __declspec(novtable) tls_random : public sanitizing_blob_xf<32>
{
///
/// Generate TLS random
///
/// \param[in] cp Handle of the cryptographics provider
///
void randomize(_In_ HCRYPTPROV cp);
};
#pragma pack(pop)
#pragma pack(push)
#pragma pack(1)
struct __declspec(novtable) tls_master_secret : public sanitizing_blob_xf<48>
{
///
/// Constructor
///
tls_master_secret();
///
/// Constructs a pre-master secret
///
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter 7.4.7.1. RSA-Encrypted Premaster Secret Message)](https://tools.ietf.org/html/rfc5246#section-7.4.7.1)
///
/// \param[in] cp Handle of the cryptographics provider
/// \param[in] ver TLS version
///
tls_master_secret(_In_ HCRYPTPROV cp, _In_ tls_version ver);
///
/// Copies a master secret
///
/// \param[in] other Master secret to copy from
///
tls_master_secret(_In_ const sanitizing_blob_f<48> &other);
#ifdef _DEBUG
///
/// Moves the master secret
///
/// \param[inout] other Master secret to move from
///
tls_master_secret(_Inout_ sanitizing_blob_zf<48> &&other);
#endif
};
#pragma pack(pop)
#pragma pack(push)
#pragma pack(1)
struct __declspec(novtable) hmac_padding : public sanitizing_blob_xf<64>
{
///
/// Constructor
///
hmac_padding();
///
/// Derive padding from secret
///
/// \param[in] cp Handle of the cryptographics provider
/// \param[in] alg Hashing algorithm
/// \param[in] secret HMAC secret
/// \param[in] size_secret \p secret size
/// \param[in] pad Padding value to XOR with (0x36=inner, 0x5c=outer...)
///
hmac_padding(
_In_ HCRYPTPROV cp,
_In_ ALG_ID alg,
_In_bytecount_(size_secret ) const void *secret,
_In_ size_t size_secret,
_In_opt_ unsigned char pad = 0x36);
///
/// Copies a padding
///
/// \param[in] other Master secret to copy from
///
hmac_padding(_In_ const sanitizing_blob_f<64> &other);
#ifdef _DEBUG
///
/// Moves the padding
///
/// \param[inout] other Padding to move from
///
hmac_padding(_Inout_ sanitizing_blob_zf<64> &&other);
#endif
};
#pragma pack(pop)
class hmac_hash
{
public:
///
/// Construct new HMAC hashing object
///
/// \param[in] cp Handle of the cryptographics provider
/// \param[in] alg Hashing algorithm
/// \param[in] secret HMAC secret
/// \param[in] size_secret \p secret size
///
hmac_hash(
_In_ HCRYPTPROV cp,
_In_ ALG_ID alg,
_In_bytecount_(size_secret ) const void *secret,
_In_ size_t size_secret);
///
/// Construct new HMAC hashing object using already prepared inner padding
///
/// \param[in] cp Handle of the cryptographics provider
/// \param[in] alg Hashing algorithm
/// \param[in] padding HMAC secret XOR inner padding
///
hmac_hash(
_In_ HCRYPTPROV cp,
_In_ ALG_ID alg,
_In_ const hmac_padding &padding);
///
/// Provides access to inner hash object to hash data at will.
///
/// \returns Inner hashing object handle
///
inline operator HCRYPTHASH()
{
return m_hash_inner;
}
///
/// Completes hashing and returns hashed data.
///
/// \param[out] val Calculated hash value
///
template<class _Ty, class _Ax>
inline void calculate(_Out_ std::vector<_Ty, _Ax> &val)
{
// Calculate inner hash.
if (!CryptGetHashParam(m_hash_inner, HP_HASHVAL, val, 0))
throw win_runtime_error(__FUNCTION__ " Error calculating inner hash.");
// Hash inner hash with outer hash.
if (!CryptHashData(m_hash_outer, (const BYTE*)val.data(), (DWORD)(val.size() * sizeof(_Ty)), 0))
throw win_runtime_error(__FUNCTION__ " Error hashing inner hash.");
// Calculate outer hash.
if (!CryptGetHashParam(m_hash_outer, HP_HASHVAL, val, 0))
throw win_runtime_error(__FUNCTION__ " Error calculating outer hash.");
}
protected:
winstd::crypt_hash m_hash_inner; ///< Inner hashing object
winstd::crypt_hash m_hash_outer; ///< Outer hashing object
};
class tls_conn_state
{
public:
///
/// Constructs a connection state
///
tls_conn_state();
///
/// Copy a connection state
///
/// \param[in] other Connection state to copy from
///
tls_conn_state(_In_ const tls_conn_state &other);
///
/// Moves a connection state
///
/// \param[inout] other Connection state to move from
///
tls_conn_state(_Inout_ tls_conn_state &&other);
///
/// Copy a connection state
///
/// \param[inout] other Connection state to copy from
///
/// \returns Reference to this object
///
tls_conn_state& operator=(_In_ const tls_conn_state &other);
///
/// Moves a connection state
///
/// \param[in] other Connection state to move from
///
/// \returns Reference to this object
///
tls_conn_state& operator=(_Inout_ tls_conn_state &&other);
public:
ALG_ID m_alg_encrypt; ///< Bulk encryption algorithm
size_t m_size_enc_key; ///< Encryption key size in bytes (has to comply with `m_alg_encrypt`)
size_t m_size_enc_iv; ///< Encryption initialization vector size in bytes (has to comply with `m_alg_encrypt`)
size_t m_size_enc_block; ///< Encryption block size in bytes (has to comply with `m_alg_encrypt`)
winstd::crypt_key m_key; ///< Key for encrypting messages
ALG_ID m_alg_mac; ///< Message authenticy check algorithm
size_t m_size_mac_key; ///< Message authenticy check algorithm key size (has to comply with `m_alg_mac`)
size_t m_size_mac_hash; ///< Message authenticy check algorithm result size (has to comply with `m_alg_mac`)
hmac_padding m_padding_hmac; ///< Padding (key) for HMAC calculation
};
}

View File

@@ -20,39 +20,78 @@
#include "StdAfx.h"
#pragma comment(lib, "Cryptui.lib")
using namespace std;
using namespace winstd;
//////////////////////////////////////////////////////////////////////
// eap::config_tls
// eap::get_cert_title
//////////////////////////////////////////////////////////////////////
eap::config_tls::config_tls(_In_ module &mod) : config_method<credentials_tls>(mod)
tstring eap::get_cert_title(PCCERT_CONTEXT cert)
{
tstring name, str, issuer, title;
FILETIME ft;
SYSTEMTIME st;
// Prepare certificate information
CertGetNameString(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, name);
title += name;
FileTimeToLocalFileTime(&(cert->pCertInfo->NotBefore), &ft);
FileTimeToSystemTime(&ft, &st);
GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, str);
title += _T(", ");
title += str;
FileTimeToLocalFileTime(&(cert->pCertInfo->NotAfter ), &ft);
FileTimeToSystemTime(&ft, &st);
GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, str);
title += _T('-');
title += str;
CertGetNameString(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, issuer);
if (name != issuer) {
title += _T(", ");
title += issuer;
}
return title;
}
eap::config_tls::config_tls(_In_ const config_tls &other) :
//////////////////////////////////////////////////////////////////////
// eap::config_method_tls
//////////////////////////////////////////////////////////////////////
eap::config_method_tls::config_method_tls(_In_ module &mod) : config_method_with_cred(mod)
{
m_preshared.reset(new credentials_tls(mod));
}
eap::config_method_tls::config_method_tls(_In_ const config_method_tls &other) :
m_trusted_root_ca(other.m_trusted_root_ca),
m_server_names(other.m_server_names),
config_method<credentials_tls>(other)
config_method_with_cred(other)
{
}
eap::config_tls::config_tls(_Inout_ config_tls &&other) :
eap::config_method_tls::config_method_tls(_Inout_ config_method_tls &&other) :
m_trusted_root_ca(std::move(other.m_trusted_root_ca)),
m_server_names(std::move(other.m_server_names)),
config_method<credentials_tls>(std::move(other))
config_method_with_cred(std::move(other))
{
}
eap::config_tls& eap::config_tls::operator=(_In_ const eap::config_tls &other)
eap::config_method_tls& eap::config_method_tls::operator=(_In_ const config_method_tls &other)
{
if (this != &other) {
(config_method<credentials_tls>&)*this = other;
(config_method_with_cred&)*this = other;
m_trusted_root_ca = other.m_trusted_root_ca;
m_server_names = other.m_server_names;
}
@@ -61,10 +100,10 @@ eap::config_tls& eap::config_tls::operator=(_In_ const eap::config_tls &other)
}
eap::config_tls& eap::config_tls::operator=(_Inout_ eap::config_tls &&other)
eap::config_method_tls& eap::config_method_tls::operator=(_Inout_ config_method_tls &&other)
{
if (this != &other) {
(config_method<credentials_tls>&&)*this = std::move(other);
(config_method_with_cred&&)*this = std::move(other);
m_trusted_root_ca = std::move(other.m_trusted_root_ca);
m_server_names = std::move(other.m_server_names);
}
@@ -73,90 +112,80 @@ eap::config_tls& eap::config_tls::operator=(_Inout_ eap::config_tls &&other)
}
eap::config* eap::config_tls::clone() const
eap::config* eap::config_method_tls::clone() const
{
return new config_tls(*this);
return new config_method_tls(*this);
}
bool eap::config_tls::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const
void eap::config_method_tls::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const
{
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
DWORD dwResult;
HRESULT hr;
assert(pDoc);
assert(pConfigRoot);
if (!config_method<credentials_tls>::save(pDoc, pConfigRoot, ppEapError))
return false;
config_method_with_cred::save(pDoc, pConfigRoot);
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
HRESULT hr;
// <ServerSideCredential>
com_obj<IXMLDOMElement> pXmlElServerSideCredential;
if ((dwResult = eapxml::create_element(pDoc, pConfigRoot, bstr(L"eap-metadata:ServerSideCredential"), bstr(L"ServerSideCredential"), bstrNamespace, &pXmlElServerSideCredential)) != ERROR_SUCCESS) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <ServerSideCredential> element."), NULL);
return false;
}
if (FAILED(hr = eapxml::create_element(pDoc, pConfigRoot, bstr(L"eap-metadata:ServerSideCredential"), bstr(L"ServerSideCredential"), bstrNamespace, &pXmlElServerSideCredential)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <ServerSideCredential> element.");
for (list<cert_context>::const_iterator i = m_trusted_root_ca.begin(), i_end = m_trusted_root_ca.end(); i != i_end; ++i) {
// <CA>
com_obj<IXMLDOMElement> pXmlElCA;
if ((dwResult = eapxml::create_element(pDoc, bstr(L"CA"), bstrNamespace, &pXmlElCA))) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <CA> element."), NULL);
return false;
}
if (FAILED(hr = eapxml::create_element(pDoc, bstr(L"CA"), bstrNamespace, &pXmlElCA)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <CA> element.");
// <CA>/<format>
if ((dwResult = eapxml::put_element_value(pDoc, pXmlElCA, bstr(L"format"), bstrNamespace, bstr(L"PEM"))) != ERROR_SUCCESS) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <format> element."), NULL);
return false;
}
if (FAILED(hr = eapxml::put_element_value(pDoc, pXmlElCA, bstr(L"format"), bstrNamespace, bstr(L"PEM"))))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <format> element.");
// <CA>/<cert-data>
const cert_context &cc = *i;
if ((dwResult = eapxml::put_element_base64(pDoc, pXmlElCA, bstr(L"cert-data"), bstrNamespace, cc->pbCertEncoded, cc->cbCertEncoded)) != ERROR_SUCCESS) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <cert-data> element."), NULL);
return false;
}
if (FAILED(hr = eapxml::put_element_base64(pDoc, pXmlElCA, bstr(L"cert-data"), bstrNamespace, cc->pbCertEncoded, cc->cbCertEncoded)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <cert-data> element.");
if (FAILED(hr = pXmlElServerSideCredential->appendChild(pXmlElCA, NULL))) {
*ppEapError = m_module.make_error(HRESULT_CODE(hr), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error appending <CA> element."), NULL);
return false;
}
if (FAILED(hr = pXmlElServerSideCredential->appendChild(pXmlElCA, NULL)))
throw com_runtime_error(hr, __FUNCTION__ " Error appending <CA> element.");
}
// <ServerName>
for (list<string>::const_iterator i = m_server_names.begin(), i_end = m_server_names.end(); i != i_end; ++i) {
wstring str;
MultiByteToWideChar(CP_UTF8, 0, i->c_str(), (int)i->length(), str);
if ((dwResult = eapxml::put_element_value(pDoc, pXmlElServerSideCredential, bstr(L"ServerName"), bstrNamespace, bstr(str))) != ERROR_SUCCESS) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <ServerName> element."), NULL);
return false;
}
for (list<wstring>::const_iterator i = m_server_names.begin(), i_end = m_server_names.end(); i != i_end; ++i) {
if (FAILED(hr = eapxml::put_element_value(pDoc, pXmlElServerSideCredential, bstr(L"ServerName"), bstrNamespace, bstr(*i))))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <ServerName> element.");
}
return true;
}
bool eap::config_tls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError)
void eap::config_method_tls::load(_In_ IXMLDOMNode *pConfigRoot)
{
if (!config_method<credentials_tls>::load(pConfigRoot, ppEapError))
return false;
assert(pConfigRoot);
config_method_with_cred::load(pConfigRoot);
std::wstring xpath(eapxml::get_xpath(pConfigRoot));
m_trusted_root_ca.clear();
m_server_names.clear();
// <ServerSideCredential>
com_obj<IXMLDOMElement> pXmlElServerSideCredential;
if (eapxml::select_element(pConfigRoot, bstr(L"eap-metadata:ServerSideCredential"), &pXmlElServerSideCredential) == ERROR_SUCCESS) {
if (SUCCEEDED(eapxml::select_element(pConfigRoot, bstr(L"eap-metadata:ServerSideCredential"), &pXmlElServerSideCredential))) {
std::wstring xpathServerSideCredential(xpath + L"/ServerSideCredential");
// <CA>
com_obj<IXMLDOMNodeList> pXmlListCAs;
long lCACount = 0;
if (eapxml::select_nodes(pXmlElServerSideCredential, bstr(L"eap-metadata:CA"), &pXmlListCAs) == ERROR_SUCCESS && SUCCEEDED(pXmlListCAs->get_length(&lCACount))) {
if (SUCCEEDED(eapxml::select_nodes(pXmlElServerSideCredential, bstr(L"eap-metadata:CA"), &pXmlListCAs)) && SUCCEEDED(pXmlListCAs->get_length(&lCACount))) {
for (long j = 0; j < lCACount; j++) {
// Load CA certificate.
com_obj<IXMLDOMNode> pXmlElCA;
pXmlListCAs->get_item(j, &pXmlElCA);
bstr bstrFormat;
if (eapxml::get_element_value(pXmlElCA, bstr(L"eap-metadata:format"), &bstrFormat) != ERROR_SUCCESS) {
if (FAILED(eapxml::get_element_value(pXmlElCA, bstr(L"eap-metadata:format"), &bstrFormat))) {
// <format> not specified.
continue;
}
@@ -167,46 +196,72 @@ bool eap::config_tls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEa
}
vector<unsigned char> aData;
if (eapxml::get_element_base64(pXmlElCA, bstr(L"eap-metadata:cert-data"), aData) != ERROR_SUCCESS) {
if (FAILED(eapxml::get_element_base64(pXmlElCA, bstr(L"eap-metadata:cert-data"), aData))) {
// Error reading <cert-data> element.
continue;
}
add_trusted_ca(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, aData.data(), (DWORD)aData.size());
}
// Log loaded CA certificates.
list<tstring> cert_names;
for (std::list<winstd::cert_context>::const_iterator cert = m_trusted_root_ca.cbegin(), cert_end = m_trusted_root_ca.cend(); cert != cert_end; ++cert)
cert_names.push_back(std::move(get_cert_title(*cert)));
m_module.log_config((xpathServerSideCredential + L"/CA").c_str(), cert_names);
}
// <ServerName>
com_obj<IXMLDOMNodeList> pXmlListServerIDs;
long lServerIDCount = 0;
if (eapxml::select_nodes(pXmlElServerSideCredential, bstr(L"eap-metadata:ServerName"), &pXmlListServerIDs) == ERROR_SUCCESS && SUCCEEDED(pXmlListServerIDs->get_length(&lServerIDCount))) {
if (SUCCEEDED(eapxml::select_nodes(pXmlElServerSideCredential, bstr(L"eap-metadata:ServerName"), &pXmlListServerIDs)) && SUCCEEDED(pXmlListServerIDs->get_length(&lServerIDCount))) {
for (long j = 0; j < lServerIDCount; j++) {
// Load server name (<ServerName>).
com_obj<IXMLDOMNode> pXmlElServerID;
pXmlListServerIDs->get_item(j, &pXmlElServerID);
bstr bstrServerID;
pXmlElServerID->get_text(&bstrServerID);
// Server names (FQDNs) are always ASCII. Hopefully. Convert them to UTF-8 anyway for consistent comparison. CP_ANSI varies.
string str;
WideCharToMultiByte(CP_UTF8, 0, bstrServerID, bstrServerID.length(), str, NULL, NULL);
m_server_names.push_back(str);
m_server_names.push_back(wstring(bstrServerID));
}
m_module.log_config((xpathServerSideCredential + L"/ServerName").c_str(), m_server_names);
}
}
return true;
}
eap::type_t eap::config_tls::get_method_id() const
void eap::config_method_tls::operator<<(_Inout_ cursor_out &cursor) const
{
return eap::type_tls;
config_method_with_cred::operator<<(cursor);
cursor << m_trusted_root_ca;
cursor << m_server_names ;
}
bool eap::config_tls::add_trusted_ca(_In_ DWORD dwCertEncodingType, _In_ const BYTE *pbCertEncoded, _In_ DWORD cbCertEncoded)
size_t eap::config_method_tls::get_pk_size() const
{
return
config_method_with_cred::get_pk_size() +
pksizeof(m_trusted_root_ca) +
pksizeof(m_server_names );
}
void eap::config_method_tls::operator>>(_Inout_ cursor_in &cursor)
{
config_method_with_cred::operator>>(cursor);
cursor >> m_trusted_root_ca;
cursor >> m_server_names ;
}
eap_type_t eap::config_method_tls::get_method_id() const
{
return eap_type_tls;
}
bool eap::config_method_tls::add_trusted_ca(_In_ DWORD dwCertEncodingType, _In_ const BYTE *pbCertEncoded, _In_ DWORD cbCertEncoded)
{
cert_context cert;
if (!cert.create(dwCertEncodingType, pbCertEncoded, cbCertEncoded)) {

View File

@@ -88,185 +88,272 @@ bool eap::credentials_tls::empty() const
}
bool eap::credentials_tls::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const
void eap::credentials_tls::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const
{
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
DWORD dwResult;
HRESULT hr;
assert(pDoc);
assert(pConfigRoot);
// Don't save m_identity. We rebuild it on every load.
//if (!credentials::save(pDoc, pConfigRoot, ppEapError))
// return false;
credentials::save(pDoc, pConfigRoot);
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
HRESULT hr;
// <ClientCertificate>
com_obj<IXMLDOMElement> pXmlElClientCertificate;
if ((dwResult = eapxml::create_element(pDoc, bstr(L"ClientCertificate"), bstrNamespace, &pXmlElClientCertificate))) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <ClientCertificate> element."), NULL);
return false;
}
if (FAILED(hr = eapxml::create_element(pDoc, bstr(L"ClientCertificate"), bstrNamespace, &pXmlElClientCertificate)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <ClientCertificate> element.");
if (m_cert) {
// <ClientCertificate>/<format>
if ((dwResult = eapxml::put_element_value(pDoc, pXmlElClientCertificate, bstr(L"format"), bstrNamespace, bstr(L"PEM"))) != ERROR_SUCCESS) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <format> element."), NULL);
return false;
}
if (FAILED(hr = eapxml::put_element_value(pDoc, pXmlElClientCertificate, bstr(L"format"), bstrNamespace, bstr(L"PEM"))))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <format> element.");
// <ClientCertificate>/<cert-data>
if ((dwResult = eapxml::put_element_base64(pDoc, pXmlElClientCertificate, bstr(L"cert-data"), bstrNamespace, m_cert->pbCertEncoded, m_cert->cbCertEncoded)) != ERROR_SUCCESS) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <cert-data> element."), NULL);
return false;
}
if (FAILED(hr = eapxml::put_element_base64(pDoc, pXmlElClientCertificate, bstr(L"cert-data"), bstrNamespace, m_cert->pbCertEncoded, m_cert->cbCertEncoded)))
throw com_runtime_error(hr, __FUNCTION__ " Error creating <cert-data> element.");
}
if (FAILED(hr = pConfigRoot->appendChild(pXmlElClientCertificate, NULL))) {
*ppEapError = m_module.make_error(HRESULT_CODE(hr), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error appending <ClientCertificate> element."), NULL);
return false;
}
return true;
if (FAILED(hr = pConfigRoot->appendChild(pXmlElClientCertificate, NULL)))
throw com_runtime_error(hr, __FUNCTION__ " Error appending <ClientCertificate> element.");
}
bool eap::credentials_tls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError)
void eap::credentials_tls::load(_In_ IXMLDOMNode *pConfigRoot)
{
assert(pConfigRoot);
DWORD dwResult;
HRESULT hr;
// Don't load m_identity. We rebuild it on load.
//if (!credentials::load(pConfigRoot, ppEapError))
// return false;
credentials::load(pConfigRoot);
std::wstring xpath(eapxml::get_xpath(pConfigRoot));
m_identity.clear();
m_cert.free();
// <ClientCertificate>
com_obj<IXMLDOMElement> pXmlElClientCertificate;
if ((dwResult = eapxml::select_element(pConfigRoot, bstr(L"eap-metadata:ClientCertificate"), &pXmlElClientCertificate)) != ERROR_SUCCESS) {
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error reading <ClientCertificate> element."), NULL);
return false;
}
if (FAILED(hr = eapxml::select_element(pConfigRoot, bstr(L"eap-metadata:ClientCertificate"), &pXmlElClientCertificate)))
throw com_runtime_error(hr, __FUNCTION__ " Error reading <ClientCertificate> element.");
// <ClientCertificate>/<format>
bstr bstrFormat;
if ((dwResult = eapxml::get_element_value(pXmlElClientCertificate, bstr(L"eap-metadata:format"), &bstrFormat)) == ERROR_SUCCESS) {
if (SUCCEEDED(eapxml::get_element_value(pXmlElClientCertificate, bstr(L"eap-metadata:format"), &bstrFormat))) {
if (CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstrFormat, bstrFormat.length(), L"PEM", -1, NULL, NULL, 0) == CSTR_EQUAL) {
// <ClientCertificate>/<cert-data>
vector<unsigned char> aData;
if ((dwResult = eapxml::get_element_base64(pXmlElClientCertificate, bstr(L"eap-metadata:cert-data"), aData)) == ERROR_SUCCESS) {
if (m_cert.create(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, aData.data(), (DWORD)aData.size())) {
// Generate identity. TODO: Find which CERT_NAME_... constant returns valid identity (username@domain or DOMAIN\Username).
CertGetNameString(m_cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, m_identity);
}
}
if (SUCCEEDED(eapxml::get_element_base64(pXmlElClientCertificate, bstr(L"eap-metadata:cert-data"), aData)))
m_cert.create(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, aData.data(), (DWORD)aData.size());
}
}
return true;
m_module.log_config((xpath + L"/ClientCertificate").c_str(), get_name().c_str());
}
bool eap::credentials_tls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError) const
void eap::credentials_tls::operator<<(_Inout_ cursor_out &cursor) const
{
credentials::operator<<(cursor);
cursor << m_cert;
}
size_t eap::credentials_tls::get_pk_size() const
{
return
credentials::get_pk_size() +
pksizeof(m_cert);
}
void eap::credentials_tls::operator>>(_Inout_ cursor_in &cursor)
{
credentials::operator>>(cursor);
cursor >> m_cert;
}
void eap::credentials_tls::store(_In_z_ LPCTSTR pszTargetName) const
{
assert(pszTargetName);
assert(ppEapError);
string cert_enc;
// Prepare cryptographics provider.
crypt_prov cp;
if (!cp.create(NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptAcquireContext failed."), NULL);
return false;
}
// Encrypt certificate.
vector<unsigned char> cert;
if (!m_module.encrypt_md5(cp, m_cert->pbCertEncoded, m_cert->cbCertEncoded, cert, ppEapError))
return false;
// Convert encrypted certificate to Base64, since CredProtectA() fail for binary strings.
string cert_base64;
base64_enc enc;
enc.encode(cert_base64, cert.data(), cert.size());
// Encrypt the certificate using user's key.
CRED_PROTECTION_TYPE cpt;
if (!CredProtectA(TRUE, cert_base64.c_str(), (DWORD)cert_base64.length(), cert_enc, &cpt)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredProtect failed."), NULL);
return false;
}
DATA_BLOB cred_blob = { m_cert->cbCertEncoded, m_cert->pbCertEncoded };
DATA_BLOB entropy_blob = { sizeof(s_entropy) , (LPBYTE)s_entropy };
data_blob cred_enc;
if (!CryptProtectData(&cred_blob, NULL, &entropy_blob, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &cred_enc))
throw win_runtime_error(__FUNCTION__ " CryptProtectData failed.");
tstring target(target_name(pszTargetName));
wstring name(std::move(get_name()));
// Write credentials.
assert(cert_enc.size() < CRED_MAX_CREDENTIAL_BLOB_SIZE);
assert(m_identity.length() < CRED_MAX_USERNAME_LENGTH );
assert(cred_enc.cbData < CRED_MAX_CREDENTIAL_BLOB_SIZE);
assert(name.length() < CRED_MAX_USERNAME_LENGTH );
CREDENTIAL cred = {
0, // Flags
CRED_TYPE_GENERIC, // Type
(LPTSTR)target.c_str(), // TargetName
_T(""), // Comment
{ 0, 0 }, // LastWritten
(DWORD)cert_enc.size(), // CredentialBlobSize
(LPBYTE)cert_enc.data(), // CredentialBlob
cred_enc.cbData, // CredentialBlobSize
cred_enc.pbData, // CredentialBlob
CRED_PERSIST_ENTERPRISE, // Persist
0, // AttributeCount
NULL, // Attributes
NULL, // TargetAlias
(LPTSTR)m_identity.c_str() // UserName
(LPTSTR)name.c_str() // UserName
};
if (!CredWrite(&cred, 0)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredWrite failed."), NULL);
return false;
}
return true;
if (!CredWrite(&cred, 0))
throw win_runtime_error(__FUNCTION__ " CredWrite failed.");
}
bool eap::credentials_tls::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError)
void eap::credentials_tls::retrieve(_In_z_ LPCTSTR pszTargetName)
{
assert(pszTargetName);
// Read credentials.
unique_ptr<CREDENTIAL, CredFree_delete<CREDENTIAL> > cred;
if (!CredRead(target_name(pszTargetName).c_str(), CRED_TYPE_GENERIC, 0, (PCREDENTIAL*)&cred)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredRead failed."), NULL);
return false;
}
if (!CredRead(target_name(pszTargetName).c_str(), CRED_TYPE_GENERIC, 0, (PCREDENTIAL*)&cred))
throw win_runtime_error(__FUNCTION__ " CredRead failed.");
// Decrypt the certificate using user's key.
string cert_base64;
if (!CredUnprotectA(TRUE, (LPCSTR)(cred->CredentialBlob), cred->CredentialBlobSize, cert_base64)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredUnprotect failed."), NULL);
return false;
}
DATA_BLOB cred_enc = { cred->CredentialBlobSize, cred->CredentialBlob };
DATA_BLOB entropy_blob = { sizeof(s_entropy) , (LPBYTE)s_entropy };
data_blob cred_int;
if (!CryptUnprotectData(&cred_enc, NULL, &entropy_blob, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN | CRYPTPROTECT_VERIFY_PROTECTION, &cred_int))
throw win_runtime_error(__FUNCTION__ " CryptUnprotectData failed.");
// Convert Base64 to binary encrypted certificate, since CredProtectA() fail for binary strings.
vector<unsigned char> cert;
base64_dec dec;
bool is_last;
dec.decode(cert, is_last, cert_base64.c_str(), cert_base64.length());
bool bResult = m_cert.create(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cred_int.pbData, cred_int.cbData);
SecureZeroMemory(cred_int.pbData, cred_int.cbData);
if (!bResult)
throw win_runtime_error(__FUNCTION__ " Error loading certificate.");
// Prepare cryptographics provider.
crypt_prov cp;
if (!cp.create(NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptAcquireContext failed."), NULL);
return false;
}
// Decrypt certificate.
vector<unsigned char, sanitizing_allocator<unsigned char> > _cert;
if (!m_module.decrypt_md5(cp, cert.data(), cert.size(), _cert, ppEapError))
return false;
if (!m_cert.create(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, _cert.data(), (DWORD)_cert.size())) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error loading certificate."), NULL);
return false;
}
// Generate identity. TODO: Find which CERT_NAME_... constant returns valid identity (username@domain or DOMAIN\Username).
CertGetNameString(m_cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, m_identity);
return true;
m_module.log_config((wstring(pszTargetName) + L"/Certificate").c_str(), get_name().c_str());
}
LPCTSTR eap::credentials_tls::target_suffix() const
{
return _T("TLS");
}
std::wstring eap::credentials_tls::get_identity() const
{
if (m_cert) {
wstring identity;
CertGetNameString(m_cert, CERT_NAME_EMAIL_TYPE, 0, NULL, identity);
return identity;
} else
return L"";
}
tstring eap::credentials_tls::get_name() const
{
return m_cert ? std::move(get_cert_title(m_cert)) : _T("<blank>");
}
eap::credentials::source_t eap::credentials_tls::combine(
_In_ const credentials_tls *cred_cached,
_In_ const config_method_tls &cfg,
_In_opt_z_ LPCTSTR pszTargetName)
{
if (cred_cached) {
// Using EAP service cached credentials.
*this = *cred_cached;
m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_CACHED1, event_data((unsigned int)eap_type_tls), event_data(credentials_tls::get_name()), event_data::blank);
return source_cache;
}
if (cfg.m_use_preshared) {
// Using preshared credentials.
*this = *(credentials_tls*)cfg.m_preshared.get();
m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_PRESHARED1, event_data((unsigned int)eap_type_tls), event_data(credentials_tls::get_name()), event_data::blank);
return source_preshared;
}
if (pszTargetName) {
try {
credentials_tls cred_loaded(m_module);
cred_loaded.retrieve(pszTargetName);
// Using stored credentials.
*this = std::move(cred_loaded);
m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_STORED1, event_data((unsigned int)eap_type_tls), event_data(credentials_tls::get_name()), event_data::blank);
return source_storage;
} catch (...) {
// Not actually an error.
}
}
return source_unknown;
}
const unsigned char eap::credentials_tls::s_entropy[1024] = {
0xb9, 0xd1, 0x62, 0xd4, 0x1c, 0xe6, 0x8c, 0x25, 0x98, 0x9b, 0x1d, 0xbc, 0x40, 0x46, 0x9e, 0x6d,
0x63, 0xba, 0xda, 0x78, 0x65, 0x56, 0x97, 0x4f, 0xa0, 0x89, 0xf4, 0xc5, 0x1b, 0xf5, 0x8d, 0x69,
0xa1, 0x8c, 0xf3, 0xf9, 0x91, 0x86, 0x7f, 0xf3, 0x47, 0x2e, 0x23, 0x61, 0xde, 0x4f, 0x61, 0x94,
0xba, 0xba, 0x27, 0x63, 0x0b, 0xf0, 0x4e, 0xa0, 0x24, 0xab, 0x17, 0x62, 0x3f, 0xc4, 0xd8, 0xad,
0xd6, 0x03, 0x1f, 0x3b, 0xdd, 0x88, 0xf7, 0x9a, 0x56, 0xf4, 0x0d, 0xce, 0x9b, 0x18, 0x33, 0x54,
0x5a, 0x1a, 0x3b, 0x91, 0x70, 0xf5, 0x95, 0x1c, 0x39, 0xe8, 0x42, 0x6c, 0x6e, 0xe6, 0x4d, 0xb8,
0x1c, 0xa6, 0xce, 0xad, 0xcd, 0x9e, 0x55, 0x88, 0x90, 0xff, 0x5e, 0x81, 0xdf, 0x08, 0x68, 0x54,
0xa1, 0x60, 0xfb, 0x41, 0x8a, 0xc1, 0xf2, 0xf0, 0xc4, 0x0e, 0xb9, 0xd1, 0x61, 0xa5, 0xc4, 0x02,
0xd9, 0x43, 0xbb, 0x16, 0x9f, 0x9a, 0xc3, 0xe0, 0x61, 0xf8, 0x57, 0x16, 0xb1, 0x7f, 0x00, 0x53,
0xf6, 0x8b, 0x97, 0x8f, 0xec, 0x3f, 0x72, 0x32, 0x0c, 0x0a, 0x80, 0x00, 0x4f, 0x87, 0x36, 0x2e,
0x24, 0x1d, 0xb4, 0xe5, 0x6c, 0x41, 0x34, 0xe9, 0x75, 0x4c, 0xf2, 0xdb, 0x16, 0xb5, 0x9a, 0x54,
0x40, 0xe9, 0x1f, 0xc0, 0xf1, 0xc5, 0x0d, 0x5d, 0xa7, 0xb5, 0x51, 0x15, 0x05, 0x95, 0xe2, 0x46,
0x9d, 0xc7, 0x74, 0xd7, 0xab, 0x93, 0xce, 0x7d, 0xf9, 0x61, 0x9d, 0x2b, 0xe7, 0x45, 0x61, 0x0b,
0xcc, 0x18, 0xf1, 0xf4, 0x00, 0xb9, 0x78, 0x23, 0x45, 0x8a, 0xd6, 0x1d, 0x95, 0x6b, 0x99, 0xe0,
0x21, 0x6b, 0x98, 0x91, 0xcb, 0x0e, 0x50, 0x9a, 0x2e, 0x64, 0xa2, 0xe9, 0x1b, 0x1f, 0x6e, 0x69,
0x78, 0x1d, 0xd1, 0xa1, 0xe5, 0x95, 0x34, 0x78, 0xf2, 0x8b, 0xe6, 0x38, 0x74, 0xd6, 0x48, 0x69,
0x62, 0xf6, 0xd3, 0x18, 0x1c, 0xb1, 0x0e, 0xc0, 0xdf, 0xff, 0x2e, 0xd3, 0xbc, 0x4e, 0xae, 0xd7,
0xe0, 0xb8, 0x47, 0x15, 0xcc, 0x10, 0xc3, 0x3a, 0x3d, 0x67, 0x79, 0x33, 0x1d, 0xb1, 0x73, 0xdf,
0xfb, 0xb2, 0x89, 0xbb, 0x04, 0x76, 0xec, 0x4a, 0x73, 0x73, 0xa8, 0x07, 0xb7, 0xb0, 0xbe, 0x15,
0xac, 0xc3, 0x32, 0x1e, 0x70, 0xc2, 0x0e, 0x8c, 0x29, 0x2e, 0x2d, 0xfc, 0x36, 0x1f, 0x9d, 0x90,
0x86, 0x1b, 0x12, 0xca, 0x82, 0x4d, 0xea, 0x9e, 0xb4, 0x5e, 0xb0, 0x33, 0xc4, 0x19, 0x25, 0x3f,
0x27, 0x11, 0x5a, 0x79, 0x91, 0x44, 0x2c, 0x50, 0x56, 0xe0, 0xd2, 0xb3, 0x81, 0x17, 0x3f, 0x06,
0x57, 0x39, 0x18, 0x2c, 0xd4, 0x1e, 0xf3, 0x90, 0x7e, 0xc3, 0x08, 0x50, 0x89, 0x7a, 0xf7, 0x7f,
0xe9, 0xf1, 0x2d, 0x73, 0x95, 0xd9, 0x2e, 0x83, 0xc8, 0x93, 0x33, 0xd9, 0x00, 0xc3, 0xa0, 0x43,
0x32, 0x57, 0x7b, 0xa9, 0xbf, 0x55, 0xfc, 0x35, 0xfb, 0x85, 0x08, 0x1c, 0x84, 0xa7, 0xce, 0xb0,
0x8b, 0xab, 0x56, 0xfa, 0x70, 0x9c, 0xd5, 0x8f, 0x21, 0xf6, 0x8f, 0x5e, 0xd5, 0x1b, 0x81, 0x17,
0xf7, 0x82, 0xb2, 0x28, 0xde, 0xc5, 0xc1, 0xba, 0xe7, 0xfa, 0x21, 0x06, 0xff, 0xf3, 0x27, 0xf8,
0x3a, 0x7d, 0xbc, 0x96, 0x5e, 0xdf, 0xf4, 0x89, 0x9f, 0x1c, 0x40, 0x03, 0x1a, 0xd2, 0x53, 0xb9,
0xe4, 0xeb, 0x16, 0xbf, 0xaa, 0xe3, 0xdf, 0x5d, 0x2a, 0xef, 0x16, 0x6f, 0x5d, 0x2b, 0x75, 0x4c,
0x0e, 0xe0, 0xda, 0xc4, 0xd7, 0x05, 0x52, 0x28, 0x25, 0xc4, 0x3f, 0xe0, 0x55, 0x07, 0x93, 0x21,
0x80, 0x2b, 0x49, 0x0c, 0x00, 0xd7, 0x13, 0xb3, 0xe0, 0x29, 0x93, 0x66, 0x0a, 0x4b, 0x88, 0x63,
0xac, 0x14, 0x5f, 0x9b, 0x1c, 0xf4, 0xe3, 0xe7, 0xeb, 0xac, 0x2d, 0xe3, 0x08, 0x7d, 0xcf, 0xce,
0x12, 0xf0, 0xcd, 0x68, 0x6e, 0xe2, 0x06, 0x16, 0x38, 0x17, 0x93, 0xbc, 0xf9, 0xfe, 0x8e, 0xb2,
0x14, 0x99, 0x76, 0x82, 0xf7, 0xc2, 0x93, 0x46, 0x95, 0xd7, 0x81, 0x03, 0x16, 0xae, 0xfc, 0x39,
0xb0, 0x26, 0xd1, 0x74, 0x73, 0x82, 0x21, 0xdb, 0x74, 0x48, 0xd7, 0xc2, 0xae, 0x73, 0x2d, 0x81,
0x84, 0x61, 0x6d, 0x1d, 0x8a, 0xb4, 0x9d, 0xb3, 0x2a, 0xa7, 0x9b, 0x08, 0x89, 0x2a, 0x96, 0x98,
0xc1, 0x64, 0xf2, 0x10, 0x8b, 0x8d, 0xaa, 0xbe, 0x0d, 0x37, 0xaa, 0x42, 0x94, 0x9f, 0xae, 0x18,
0x64, 0xcd, 0x77, 0x24, 0x41, 0xc8, 0x6a, 0xbc, 0x80, 0x7f, 0xd8, 0x1f, 0x94, 0x29, 0xe7, 0x38,
0xb8, 0x7f, 0x90, 0x54, 0xe4, 0xb6, 0xb8, 0x30, 0x7f, 0x40, 0xeb, 0x60, 0x6c, 0x6a, 0x07, 0x36,
0x5b, 0xfc, 0x09, 0x72, 0xff, 0x02, 0x96, 0xce, 0xd6, 0xdc, 0x07, 0x80, 0x25, 0x70, 0x6f, 0x9e,
0x63, 0xac, 0x97, 0x1d, 0x3d, 0x3a, 0x26, 0x83, 0xc8, 0xe3, 0x99, 0xa8, 0x10, 0xf4, 0x68, 0xf4,
0xf3, 0x8c, 0x38, 0x8d, 0xd2, 0x13, 0xd5, 0x95, 0xce, 0x80, 0x1e, 0xcf, 0x14, 0xb8, 0x16, 0x64,
0x28, 0xf1, 0x40, 0xd9, 0xa0, 0x24, 0x13, 0x84, 0x3b, 0x8b, 0x92, 0x73, 0x67, 0x77, 0x93, 0xfe,
0x07, 0x67, 0x7d, 0xcf, 0x7f, 0x9e, 0x7b, 0x74, 0x6a, 0x07, 0xb8, 0x1f, 0xdc, 0xa6, 0xdd, 0xbb,
0x63, 0xc8, 0x5d, 0xde, 0x48, 0x93, 0x34, 0xf3, 0x3b, 0xa6, 0x4d, 0x08, 0xdf, 0xd4, 0x40, 0x55,
0x0c, 0x85, 0x6c, 0xda, 0x41, 0xc2, 0xd5, 0x4f, 0x08, 0xfc, 0x87, 0x43, 0x22, 0x42, 0x59, 0x53,
0xbe, 0x21, 0xe4, 0x09, 0xcc, 0x6a, 0xa2, 0x50, 0x6e, 0x2d, 0x9a, 0x61, 0xdc, 0x36, 0xd0, 0x51,
0xab, 0xdb, 0x24, 0xad, 0x37, 0xe5, 0x47, 0x93, 0xcd, 0x74, 0x94, 0x17, 0x71, 0x8f, 0xc1, 0xca,
0x3f, 0xfa, 0x4f, 0xd8, 0xb5, 0xbb, 0xb6, 0xf3, 0xab, 0x7d, 0xa6, 0x65, 0x24, 0x42, 0x2a, 0x4b,
0x3a, 0xbb, 0x7c, 0xcf, 0x1e, 0x32, 0x12, 0xf4, 0xe1, 0x90, 0xb3, 0x50, 0xb1, 0xfc, 0x7c, 0x6b,
0x91, 0x06, 0x18, 0x02, 0x33, 0x83, 0x4b, 0x20, 0x75, 0xf5, 0xad, 0x37, 0x5d, 0xb8, 0xc2, 0xb5,
0x23, 0x28, 0x32, 0x50, 0x36, 0xd8, 0x6d, 0x65, 0x98, 0xca, 0x58, 0x51, 0x91, 0x72, 0x3b, 0x42,
0xd5, 0xcd, 0x09, 0x1e, 0xcf, 0x8c, 0x88, 0x4c, 0xf4, 0x4d, 0x31, 0x0b, 0xd3, 0x81, 0xe8, 0x28,
0x2b, 0xf6, 0x6d, 0x70, 0x34, 0x0f, 0x7e, 0x8d, 0xfc, 0x03, 0xc4, 0x8c, 0xf2, 0xc5, 0x6c, 0xbd,
0xf8, 0x14, 0xec, 0x2b, 0x0a, 0xb7, 0x7e, 0x8b, 0xcf, 0xb5, 0x58, 0xa5, 0x4d, 0x34, 0x61, 0x58,
0xa3, 0xfd, 0x72, 0x4e, 0x20, 0xbe, 0x96, 0xc4, 0x6c, 0xec, 0x1f, 0xb6, 0x0c, 0x15, 0xbc, 0x71,
0x30, 0xa1, 0x57, 0x13, 0x85, 0x5c, 0xf3, 0x36, 0x42, 0x8b, 0x22, 0x26, 0x5b, 0xfb, 0x76, 0x01,
0xf3, 0xf3, 0xff, 0xe1, 0x6b, 0xf3, 0x8c, 0x25, 0xe3, 0x60, 0xee, 0xc8, 0x8f, 0xe3, 0xdb, 0xa8,
0x6e, 0xed, 0x1e, 0x5a, 0xd4, 0xd2, 0xff, 0x28, 0xea, 0x63, 0x56, 0xc1, 0xc3, 0xee, 0x37, 0x57,
0xd7, 0x6d, 0x92, 0xf8, 0x2b, 0x9a, 0x55, 0x62, 0x7b, 0x08, 0x27, 0xde, 0x13, 0x27, 0x35, 0x30,
0x20, 0xb3, 0x43, 0x31, 0xeb, 0xf6, 0x28, 0xb4, 0x6e, 0x92, 0x82, 0x48, 0x1e, 0xbf, 0xe6, 0x3d,
0x84, 0x0d, 0x9f, 0x5f, 0x55, 0x97, 0x96, 0x26, 0x65, 0x59, 0xfa, 0x6a, 0x72, 0xc6, 0x49, 0xa5,
0x0d, 0xd0, 0x84, 0x17, 0x97, 0x56, 0x2e, 0xff, 0x82, 0x76, 0x61, 0x75, 0x9f, 0x15, 0xd2, 0x08,
0xbb, 0x24, 0xb5, 0xba, 0xaa, 0x5e, 0x20, 0xdd, 0x03, 0x4c, 0x3c, 0x54, 0xd8, 0x8f, 0x87, 0x49,
};

777
lib/TLS/src/Method.cpp Normal file
View File

@@ -0,0 +1,777 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StdAfx.h"
#pragma comment(lib, "Secur32.lib")
using namespace std;
using namespace winstd;
//////////////////////////////////////////////////////////////////////
// eap::method_tls::packet
//////////////////////////////////////////////////////////////////////
eap::method_tls::packet::packet() :
m_code((EapCode)0),
m_id(0),
m_flags(0)
{
}
eap::method_tls::packet::packet(_In_ const packet &other) :
m_code (other.m_code ),
m_id (other.m_id ),
m_flags(other.m_flags),
m_data (other.m_data )
{
}
eap::method_tls::packet::packet(_Inout_ packet &&other) :
m_code (std::move(other.m_code )),
m_id (std::move(other.m_id )),
m_flags(std::move(other.m_flags)),
m_data (std::move(other.m_data ))
{
}
eap::method_tls::packet& eap::method_tls::packet::operator=(_In_ const packet &other)
{
if (this != std::addressof(other)) {
m_code = other.m_code ;
m_id = other.m_id ;
m_flags = other.m_flags;
m_data = other.m_data ;
}
return *this;
}
eap::method_tls::packet& eap::method_tls::packet::operator=(_Inout_ packet &&other)
{
if (this != std::addressof(other)) {
m_code = std::move(other.m_code );
m_id = std::move(other.m_id );
m_flags = std::move(other.m_flags);
m_data = std::move(other.m_data );
}
return *this;
}
void eap::method_tls::packet::clear()
{
m_code = (EapCode)0;
m_id = 0;
m_flags = 0;
m_data.clear();
}
//////////////////////////////////////////////////////////////////////
// eap::method_tls
//////////////////////////////////////////////////////////////////////
eap::method_tls::method_tls(_In_ module &module, _In_ config_provider_list &cfg, _In_ credentials_tls &cred) :
m_cred(cred),
m_user_ctx(NULL),
m_phase(phase_unknown),
m_blob_cfg(NULL),
#ifdef EAP_USE_NATIVE_CREDENTIAL_CACHE
m_blob_cred(NULL),
#endif
method(module, cfg, cred)
{
}
eap::method_tls::method_tls(_Inout_ method_tls &&other) :
m_cred ( other.m_cred ),
m_packet_req (std::move(other.m_packet_req )),
m_packet_res (std::move(other.m_packet_res )),
m_user_ctx (std::move(other.m_user_ctx )),
m_sc_target_name(std::move(other.m_sc_target_name)),
m_sc_cred (std::move(other.m_sc_cred )),
m_sc_queue (std::move(other.m_sc_queue )),
m_sc_ctx (std::move(other.m_sc_ctx )),
m_phase (std::move(other.m_phase )),
method (std::move(other ))
{
}
eap::method_tls::~method_tls()
{
if (m_blob_cfg)
m_module.free_memory(m_blob_cfg);
#ifdef EAP_USE_NATIVE_CREDENTIAL_CACHE
if (m_blob_cred)
m_module.free_memory(m_blob_cred);
#endif
}
eap::method_tls& eap::method_tls::operator=(_Inout_ method_tls &&other)
{
if (this != std::addressof(other)) {
assert(std::addressof(m_cred) == std::addressof(other.m_cred)); // Move method with same credentials only!
(method&)*this = std::move(other );
m_packet_req = std::move(other.m_packet_req );
m_packet_res = std::move(other.m_packet_res );
m_user_ctx = std::move(other.m_user_ctx );
m_sc_target_name = std::move(other.m_sc_target_name);
m_sc_cred = std::move(other.m_sc_cred );
m_sc_queue = std::move(other.m_sc_queue );
m_sc_ctx = std::move(other.m_sc_ctx );
m_phase = std::move(other.m_phase );
}
return *this;
}
void eap::method_tls::begin_session(
_In_ DWORD dwFlags,
_In_ const EapAttributes *pAttributeArray,
_In_ HANDLE hTokenImpersonateUser,
_In_ DWORD dwMaxSendPacketSize)
{
method::begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize);
m_user_ctx = hTokenImpersonateUser;
user_impersonator impersonating(m_user_ctx);
// Get method configuration.
if (m_cfg.m_providers.empty() || m_cfg.m_providers.front().m_methods.empty())
throw invalid_argument(__FUNCTION__ " Configuration has no providers and/or methods.");
const config_provider &cfg_prov(m_cfg.m_providers.front());
const config_method_tls *cfg_method = dynamic_cast<const config_method_tls*>(cfg_prov.m_methods.front().get());
assert(cfg_method);
// Build (expected) server name(s) for Schannel.
m_sc_target_name.clear();
for (list<wstring>::const_iterator name = cfg_method->m_server_names.cbegin(), name_end = cfg_method->m_server_names.cend(); name != name_end; ++name) {
if (name != cfg_method->m_server_names.cbegin())
m_sc_target_name += _T(';');
#ifdef _UNICODE
m_sc_target_name.insert(m_sc_target_name.end(), name->begin(), name->end());
#else
string buf;
WideCharToMultiByte(CP_ACP, 0, name->c_str(), -1, buf, NULL, NULL);
m_sc_target_name.insert(m_sc_target_name.end(), buf.begin(), buf.end());
#endif
}
// Prepare client credentials for Schannel.
PCCERT_CONTEXT certs[] = { m_cred.m_cert ? m_cred.m_cert : NULL };
SCHANNEL_CRED cred = {
SCHANNEL_CRED_VERSION, // dwVersion
m_cred.m_cert ? 1 : 0, // cCreds
certs, // paCred
NULL, // hRootStore: Not valid for client credentials
0, // cMappers
NULL, // aphMappers
0, // cSupportedAlgs: Use system configured default
NULL, // palgSupportedAlgs: Use system configured default
0, // grbitEnabledProtocols: Use default
0, // dwMinimumCipherStrength: Use system configured default
0, // dwMaximumCipherStrength: Use system configured default
0, // dwSessionLifespan: Use system configured default = 10hr
#ifdef SCHANNEL_SRV_CERT_CHECK
SCH_CRED_AUTO_CRED_VALIDATION | // dwFlags: Let Schannel verify server certificate
#else
SCH_CRED_MANUAL_CRED_VALIDATION | // dwFlags: Prevent Schannel verify server certificate (we want to use custom root CA store and multiple name checking)
#endif
SCH_CRED_CACHE_ONLY_URL_RETRIEVAL_ON_CREATE | // dwFlags: Do not attempt online revocation check - we do not expect to have network connection yet
SCH_CRED_IGNORE_NO_REVOCATION_CHECK | // dwFlags: Ignore no-revocation-check errors (TODO: Test if this flag is required.)
SCH_CRED_IGNORE_REVOCATION_OFFLINE | // dwFlags: Ignore offline-revocation errors - we do not expect to have network connection yet
SCH_CRED_NO_DEFAULT_CREDS | // dwFlags: If client certificate we provided is not acceptable, do not try to select one on your own
(cfg_method->m_server_names.empty() ? SCH_CRED_NO_SERVERNAME_CHECK : 0) | // dwFlags: When no expected server name is given, do not do the server name check.
0x00400000 /*SCH_USE_STRONG_CRYPTO*/, // dwFlags: Do not use broken ciphers
0 // dwCredFormat
};
SECURITY_STATUS stat = m_sc_cred.acquire(NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, &cred);
if (FAILED(stat))
throw sec_runtime_error(stat, __FUNCTION__ " Error acquiring Schannel credentials handle.");
}
void eap::method_tls::process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize,
_Inout_ EapPeerMethodOutput *pEapOutput)
{
assert(pReceivedPacket && dwReceivedPacketSize >= 4);
assert(pEapOutput);
// Is this a valid EAP-TLS packet?
if (dwReceivedPacketSize < 6)
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, __FUNCTION__ " Packet is too small. EAP-%s packets should be at least 6B.");
//else if (pReceivedPacket->Data[0] != eap_type_tls) // Skip method check, to allow TTLS extension.
// throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, string_printf(__FUNCTION__ " Packet is not EAP-TLS (expected: %u, received: %u).", eap_type_tls, pReceivedPacket->Data[0]));
// Get packet data pointer and size for more readable code later on.
const unsigned char *packet_data_ptr;
size_t packet_data_size;
if (pReceivedPacket->Data[1] & flags_req_length_incl) {
// Length field is included.
packet_data_ptr = pReceivedPacket->Data + 6;
packet_data_size = dwReceivedPacketSize - 10;
} else {
// Length field not included.
packet_data_ptr = pReceivedPacket->Data + 2;
packet_data_size = dwReceivedPacketSize - 6;
}
// Do the EAP-TLS defragmentation.
if (pReceivedPacket->Data[1] & flags_req_more_frag) {
if (m_packet_req.m_data.empty()) {
// Start a new packet.
if (pReceivedPacket->Data[1] & flags_req_length_incl) {
// Preallocate data according to the Length field.
size_t size_tot = ntohl(*(unsigned int*)(pReceivedPacket->Data + 2));
m_packet_req.m_data.reserve(size_tot);
m_module.log_event(&EAPMETHOD_TLS_PACKET_RECV_FRAG_FIRST, event_data((unsigned int)eap_type_tls), event_data((unsigned int)packet_data_size), event_data((unsigned int)size_tot), event_data::blank);
} else {
// The Length field was not included. Odd. Nevermind, no pre-allocation then.
m_module.log_event(&EAPMETHOD_TLS_PACKET_RECV_FRAG_FIRST1, event_data((unsigned int)eap_type_tls), event_data((unsigned int)packet_data_size), event_data::blank);
}
} else {
// Mid fragment received.
m_module.log_event(&EAPMETHOD_TLS_PACKET_RECV_FRAG_MID, event_data((unsigned int)eap_type_tls), event_data((unsigned int)packet_data_size), event_data((unsigned int)m_packet_req.m_data.size()), event_data::blank);
}
m_packet_req.m_data.insert(m_packet_req.m_data.end(), packet_data_ptr, packet_data_ptr + packet_data_size);
// Reply with ACK packet.
m_packet_res.m_code = EapCodeResponse;
m_packet_res.m_id = pReceivedPacket->Id;
m_packet_res.m_flags = 0;
m_packet_res.m_data.clear();
pEapOutput->fAllowNotifications = FALSE;
pEapOutput->action = EapPeerMethodResponseActionSend;
return;
} else if (!m_packet_req.m_data.empty()) {
// Last fragment received. Append data.
m_packet_req.m_data.insert(m_packet_req.m_data.end(), packet_data_ptr, packet_data_ptr + packet_data_size);
m_module.log_event(&EAPMETHOD_TLS_PACKET_RECV_FRAG_LAST, event_data((unsigned int)eap_type_tls), event_data((unsigned int)packet_data_size), event_data((unsigned int)m_packet_req.m_data.size()), event_data::blank);
} else {
// This is a complete non-fragmented packet.
m_packet_req.m_data.assign(packet_data_ptr, packet_data_ptr + packet_data_size);
m_module.log_event(&EAPMETHOD_TLS_PACKET_RECV, event_data((unsigned int)eap_type_tls), event_data((unsigned int)packet_data_size), event_data::blank);
}
m_packet_req.m_code = (EapCode)pReceivedPacket->Code;
m_packet_req.m_id = pReceivedPacket->Id;
m_packet_req.m_flags = pReceivedPacket->Data[1];
if (m_packet_res.m_flags & flags_res_more_frag) {
// We are sending a fragmented message.
if ( m_packet_req.m_code == EapCodeRequest &&
m_packet_req.m_id == m_packet_res.m_id &&
m_packet_req.m_data.empty() &&
!(m_packet_req.m_flags & (flags_req_length_incl | flags_req_more_frag | flags_req_start)))
{
// This is the ACK of our fragmented message packet. Send the next fragment.
m_packet_res.m_id++;
pEapOutput->fAllowNotifications = FALSE;
pEapOutput->action = EapPeerMethodResponseActionSend;
return;
} else
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, string_printf(__FUNCTION__ " ACK expected, received %u-%u-%x.", m_packet_req.m_code, m_packet_req.m_id, m_packet_req.m_flags));
}
m_packet_res.m_code = EapCodeResponse;
m_packet_res.m_id = m_packet_req.m_id;
m_packet_res.m_flags = 0;
if (pReceivedPacket->Code == EapCodeRequest && (m_packet_req.m_flags & flags_req_start)) {
// This is the EAP-TLS start message: (re)initialize method.
m_phase = phase_handshake_init;
m_sc_queue.assign(m_packet_req.m_data.begin(), m_packet_req.m_data.end());
} else
m_sc_queue.insert(m_sc_queue.end(), m_packet_req.m_data.begin(), m_packet_req.m_data.end());
switch (m_phase) {
case phase_handshake_init:
case phase_handshake_cont:
process_handshake();
break;
case phase_application_data:
process_application_data();
break;
}
pEapOutput->fAllowNotifications = TRUE;
pEapOutput->action = EapPeerMethodResponseActionSend;
// EAP-Request packet was processed. Clear its data since we use the absence of data to detect first of fragmented message packages.
m_packet_req.m_data.clear();
}
void eap::method_tls::get_response_packet(
_Inout_bytecap_(*dwSendPacketSize) EapPacket *pSendPacket,
_Inout_ DWORD *pdwSendPacketSize)
{
assert(pdwSendPacketSize);
assert(pSendPacket);
unsigned int
size_data = (unsigned int)m_packet_res.m_data.size(),
size_packet = size_data + 6;
unsigned short size_packet_limit = (unsigned short)std::min<unsigned int>(*pdwSendPacketSize, USHRT_MAX);
unsigned char *data_dst;
if (!(m_packet_res.m_flags & flags_res_more_frag)) {
// Not fragmented.
if (size_packet <= size_packet_limit) {
// No need to fragment the packet.
m_packet_res.m_flags &= ~flags_res_length_incl; // No need to explicitly include the Length field either.
data_dst = pSendPacket->Data + 2;
m_module.log_event(&EAPMETHOD_TLS_PACKET_SEND, event_data((unsigned int)eap_type_tls), event_data((unsigned int)size_data), event_data::blank);
} else {
// But it should be fragmented.
m_packet_res.m_flags |= flags_res_length_incl | flags_res_more_frag;
*(unsigned int*)(pSendPacket->Data + 2) = (unsigned int)size_packet;
data_dst = pSendPacket->Data + 6;
size_data = size_packet_limit - 10;
size_packet = size_packet_limit;
m_module.log_event(&EAPMETHOD_TLS_PACKET_SEND_FRAG_FIRST, event_data((unsigned int)eap_type_tls), event_data((unsigned int)size_data), event_data((unsigned int)(m_packet_res.m_data.size() - size_data)), event_data::blank);
}
} else {
// Continuing the fragmented packet...
if (size_packet > size_packet_limit) {
// This is a mid fragment.
m_packet_res.m_flags &= ~flags_res_length_incl;
size_data = size_packet_limit - 6;
size_packet = size_packet_limit;
m_module.log_event(&EAPMETHOD_TLS_PACKET_SEND_FRAG_MID, event_data((unsigned int)eap_type_tls), event_data((unsigned int)size_data), event_data((unsigned int)(m_packet_res.m_data.size() - size_data)), event_data::blank);
} else {
// This is the last fragment.
m_packet_res.m_flags &= ~(flags_res_length_incl | flags_res_more_frag);
m_module.log_event(&EAPMETHOD_TLS_PACKET_SEND_FRAG_LAST, event_data((unsigned int)eap_type_tls), event_data((unsigned int)size_data), event_data((unsigned int)(m_packet_res.m_data.size() - size_data)), event_data::blank);
}
data_dst = pSendPacket->Data + 2;
}
pSendPacket->Code = (BYTE)m_packet_res.m_code;
pSendPacket->Id = m_packet_res.m_id;
*(unsigned short*)pSendPacket->Length = htons((unsigned short)size_packet);
pSendPacket->Data[0] = (BYTE)eap_type_tls;
pSendPacket->Data[1] = m_packet_res.m_flags;
memcpy(data_dst, m_packet_res.m_data.data(), size_data);
m_packet_res.m_data.erase(m_packet_res.m_data.begin(), m_packet_res.m_data.begin() + size_data);
*pdwSendPacketSize = size_packet;
}
void eap::method_tls::get_result(
_In_ EapPeerMethodResultReason reason,
_Inout_ EapPeerMethodResult *ppResult)
{
assert(ppResult);
config_provider &cfg_prov(m_cfg.m_providers.front());
config_method_tls *cfg_method = dynamic_cast<config_method_tls*>(cfg_prov.m_methods.front().get());
assert(cfg_method);
switch (reason) {
case EapPeerMethodResultSuccess: {
m_module.log_event(&EAPMETHOD_TLS_SUCCESS, event_data((unsigned int)eap_type_tls), event_data::blank);
// Derive MSK/EMSK for line encryption.
SecPkgContext_EapKeyBlock key_block;
SECURITY_STATUS status = QueryContextAttributes(m_sc_ctx, SECPKG_ATTR_EAP_KEY_BLOCK, &key_block);
if (FAILED(status))
throw sec_runtime_error(status, __FUNCTION__ "Error generating MSK in Schannel.");
const unsigned char *_key_block = key_block.rgbKeys;
// Fill array with RADIUS attributes.
eap_attr a;
m_eap_attr.clear();
m_eap_attr.reserve(3);
a.create_ms_mppe_key(16, _key_block, sizeof(tls_random));
m_eap_attr.push_back(std::move(a));
_key_block += sizeof(tls_random);
a.create_ms_mppe_key(17, _key_block, sizeof(tls_random));
m_eap_attr.push_back(std::move(a));
_key_block += sizeof(tls_random);
m_eap_attr.push_back(eap_attr::blank);
m_eap_attr_desc.dwNumberOfAttributes = (DWORD)m_eap_attr.size();
m_eap_attr_desc.pAttribs = m_eap_attr.data();
ppResult->pAttribArray = &m_eap_attr_desc;
// Clear credentials as failed.
cfg_method->m_auth_failed = false;
ppResult->fIsSuccess = TRUE;
ppResult->dwFailureReasonCode = ERROR_SUCCESS;
break;
}
case EapPeerMethodResultFailure:
m_module.log_event(&EAPMETHOD_TLS_FAILURE, event_data((unsigned int)eap_type_tls), event_data::blank);
// Mark credentials as failed, so GUI can re-prompt user.
cfg_method->m_auth_failed = true;
// Do not report failure to EAPHost, as it will not save updated configuration then. But we need it to save it, to alert user on next connection attempt.
// EAPHost is well aware of the failed condition.
//ppResult->fIsSuccess = FALSE;
//ppResult->dwFailureReasonCode = EAP_E_AUTHENTICATION_FAILED;
break;
default:
throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported.");
}
// Always ask EAP host to save the connection data.
ppResult->fSaveConnectionData = TRUE;
m_module.pack(m_cfg, &ppResult->pConnectionData, &ppResult->dwSizeofConnectionData);
if (m_blob_cfg)
m_module.free_memory(m_blob_cfg);
m_blob_cfg = ppResult->pConnectionData;
#ifdef EAP_USE_NATIVE_CREDENTIAL_CACHE
ppResult->fSaveUserData = TRUE;
m_module.pack(m_cred, &ppResult->pUserData, &ppResult->dwSizeofUserData);
if (m_blob_cred)
m_module.free_memory(m_blob_cred);
m_blob_cred = ppResult->pUserData;
#endif
}
void eap::method_tls::process_handshake()
{
// Prepare input buffer(s).
SecBuffer buf_in[] = {
{
(unsigned long)m_sc_queue.size(),
SECBUFFER_TOKEN,
m_sc_queue.data()
},
{ 0, SECBUFFER_EMPTY, NULL },
};
SecBufferDesc buf_in_desc = {
SECBUFFER_VERSION,
_countof(buf_in),
buf_in
};
// Prepare output buffer(s).
SecBuffer buf_out[] = {
{ 0, SECBUFFER_TOKEN, NULL },
{ 0, SECBUFFER_ALERT, NULL },
};
sec_buffer_desc buf_out_desc(buf_out, _countof(buf_out));
user_impersonator impersonating(m_user_ctx);
SECURITY_STATUS status;
if (m_phase == phase_handshake_init) {
m_module.log_event(&EAPMETHOD_TLS_HANDSHAKE_START2, event_data((unsigned int)eap_type_tls), event_data::blank);
status = m_sc_ctx.initialize(
m_sc_cred,
!m_sc_target_name.empty() ? m_sc_target_name.c_str() : NULL,
ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY | ISC_REQ_STREAM | /*ISC_REQ_USE_SUPPLIED_CREDS |*/ ISC_REQ_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY,
0,
&buf_in_desc,
&buf_out_desc);
} else {
status = m_sc_ctx.process(
m_sc_cred,
!m_sc_target_name.empty() ? m_sc_target_name.c_str() : NULL,
ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY | ISC_REQ_STREAM | /*ISC_REQ_USE_SUPPLIED_CREDS |*/ ISC_REQ_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY,
0,
&buf_in_desc,
&buf_out_desc);
}
#ifndef SCHANNEL_SRV_CERT_CHECK
if (status == SEC_E_OK)
verify_server_trust();
#endif
if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED) {
// Send Schannel's token via EAP.
assert(buf_out[0].BufferType == SECBUFFER_TOKEN);
assert(m_sc_ctx.m_attrib & ISC_RET_ALLOCATED_MEMORY);
m_packet_res.m_data.assign((const unsigned char*)buf_out[0].pvBuffer, (const unsigned char*)buf_out[0].pvBuffer + buf_out[0].cbBuffer);
if (buf_in[1].BufferType == SECBUFFER_EXTRA) {
// Server appended extra data. Process it.
process_application_data(&*(m_sc_queue.end() - buf_in[1].cbBuffer), buf_in[1].cbBuffer);
}
m_sc_queue.clear();
m_phase = status == SEC_E_OK ? phase_application_data : phase_handshake_cont;
} else if (status == SEC_E_INCOMPLETE_MESSAGE) {
// Schannel neeeds more data. Send ACK packet to server to send more.
} else if (FAILED(status)) {
if (m_sc_ctx.m_attrib & ISC_RET_EXTENDED_ERROR) {
// Send alert via EAP. Not that EAP will transmit it once we throw this is an error...
assert(buf_out[1].BufferType == SECBUFFER_ALERT);
assert(m_sc_ctx.m_attrib & ISC_RET_ALLOCATED_MEMORY);
m_packet_res.m_data.assign((const unsigned char*)buf_out[1].pvBuffer, (const unsigned char*)buf_out[1].pvBuffer + buf_out[1].cbBuffer);
}
throw sec_runtime_error(status, __FUNCTION__ " Schannel error.");
}
}
void eap::method_tls::process_application_data()
{
if (m_sc_queue.empty()) {
// An ACK packet received. Nothing to unencrypt.
process_application_data(NULL, 0);
return;
}
if (!(m_sc_ctx.m_attrib & ISC_RET_CONFIDENTIALITY))
throw runtime_error(__FUNCTION__ " Connection is not encrypted.");
// Prepare input/output buffer(s).
SecBuffer buf[] = {
{ 0, SECBUFFER_TOKEN, NULL },
{ 0, SECBUFFER_ALERT, NULL },
{
(unsigned long)m_sc_queue.size(),
SECBUFFER_DATA,
m_sc_queue.data()
},
};
SecBufferDesc buf_desc = {
SECBUFFER_VERSION,
_countof(buf),
buf
};
// Decrypt the message.
SECURITY_STATUS status = DecryptMessage(m_sc_ctx, &buf_desc, 0, NULL);
if (status == SEC_E_OK) {
assert(buf[2].BufferType == SECBUFFER_DATA);
process_application_data(buf[2].pvBuffer, buf[2].cbBuffer);
} else if (status == SEC_E_INCOMPLETE_MESSAGE) {
// Schannel neeeds more data. Send ACK packet to server to send more.
} else if (status == SEC_I_CONTEXT_EXPIRED) {
// Server initiated connection shutdown.
m_sc_queue.clear();
m_phase = phase_shutdown;
} else if (status == SEC_I_RENEGOTIATE) {
// Re-negotiation required.
m_sc_queue.clear();
m_phase = phase_handshake_init;
process_handshake();
} else if (FAILED(status)) {
if (m_sc_ctx.m_attrib & ISC_RET_EXTENDED_ERROR) {
// Send alert via EAP. Not that EAP will transmit it once we throw this is an error...
assert(buf[1].BufferType == SECBUFFER_ALERT);
assert(m_sc_ctx.m_attrib & ISC_RET_ALLOCATED_MEMORY);
m_packet_res.m_data.assign((const unsigned char*)buf[1].pvBuffer, (const unsigned char*)buf[1].pvBuffer + buf[1].cbBuffer);
}
throw sec_runtime_error(status, __FUNCTION__ " Schannel error.");
}
}
void eap::method_tls::process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg)
{
UNREFERENCED_PARAMETER(msg);
UNREFERENCED_PARAMETER(size_msg);
// TODO: Parse application data (Diameter AVP)
}
#ifndef SCHANNEL_SRV_CERT_CHECK
void eap::method_tls::verify_server_trust() const
{
SECURITY_STATUS status;
cert_context cert;
status = QueryContextAttributes(m_sc_ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&cert);
if (FAILED(status))
throw sec_runtime_error(status, __FUNCTION__ " Error retrieving server certificate from Schannel.");
const config_provider &cfg_prov(m_cfg.m_providers.front());
const config_method_tls *cfg_method = dynamic_cast<const config_method_tls*>(cfg_prov.m_methods.front().get());
assert(cfg_method);
// Check server name.
if (!cfg_method->m_server_names.empty()) {
bool
has_san = false,
found = false;
// Search subjectAltName2 and subjectAltName.
for (DWORD i = 0; !found && i < cert->pCertInfo->cExtension; i++) {
unique_ptr<CERT_ALT_NAME_INFO, LocalFree_delete<CERT_ALT_NAME_INFO> > san_info;
if (strcmp(cert->pCertInfo->rgExtension[i].pszObjId, szOID_SUBJECT_ALT_NAME2) == 0) {
unsigned char *output = NULL;
DWORD size_output;
if (!CryptDecodeObjectEx(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
szOID_SUBJECT_ALT_NAME2,
cert->pCertInfo->rgExtension[i].Value.pbData, cert->pCertInfo->rgExtension[i].Value.cbData,
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_ENABLE_PUNYCODE_FLAG,
NULL,
&output, &size_output))
throw win_runtime_error(__FUNCTION__ " Error decoding certificate extension.");
san_info.reset((CERT_ALT_NAME_INFO*)output);
} else if (strcmp(cert->pCertInfo->rgExtension[i].pszObjId, szOID_SUBJECT_ALT_NAME) == 0) {
unsigned char *output = NULL;
DWORD size_output;
if (!CryptDecodeObjectEx(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
szOID_SUBJECT_ALT_NAME,
cert->pCertInfo->rgExtension[i].Value.pbData, cert->pCertInfo->rgExtension[i].Value.cbData,
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_ENABLE_PUNYCODE_FLAG,
NULL,
&output, &size_output))
throw win_runtime_error(__FUNCTION__ " Error decoding certificate extension.");
san_info.reset((CERT_ALT_NAME_INFO*)output);
} else {
// Skip this extension.
continue;
}
has_san = true;
for (list<wstring>::const_iterator s = cfg_method->m_server_names.cbegin(), s_end = cfg_method->m_server_names.cend(); !found && s != s_end; ++s) {
for (DWORD i = 0; !found && i < san_info->cAltEntry; i++) {
if (san_info->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME &&
_wcsicmp(s->c_str(), san_info->rgAltEntry[i].pwszDNSName) == 0)
{
m_module.log_event(&EAPMETHOD_TLS_SERVER_NAME_TRUSTED1, event_data(san_info->rgAltEntry[i].pwszDNSName), event_data::blank);
found = true;
}
}
}
}
if (!has_san) {
// Certificate has no subjectAltName. Compare against Common Name.
wstring subj;
if (!CertGetNameStringW(cert, CERT_NAME_DNS_TYPE, CERT_NAME_STR_ENABLE_PUNYCODE_FLAG, NULL, subj))
throw win_runtime_error(__FUNCTION__ " Error retrieving server's certificate subject name.");
for (list<wstring>::const_iterator s = cfg_method->m_server_names.cbegin(), s_end = cfg_method->m_server_names.cend(); !found && s != s_end; ++s) {
if (_wcsicmp(s->c_str(), subj.c_str()) == 0) {
m_module.log_event(&EAPMETHOD_TLS_SERVER_NAME_TRUSTED1, event_data(subj), event_data::blank);
found = true;
}
}
}
if (!found)
throw win_runtime_error(ERROR_INVALID_DOMAINNAME, __FUNCTION__ " Server name is not on the list of trusted server names.");
}
if (cert->pCertInfo->Issuer.cbData == cert->pCertInfo->Subject.cbData &&
memcmp(cert->pCertInfo->Issuer.pbData, cert->pCertInfo->Subject.pbData, cert->pCertInfo->Issuer.cbData) == 0)
throw com_runtime_error(CRYPT_E_SELF_SIGNED, __FUNCTION__ " Server is using a self-signed certificate. Cannot trust it.");
// Create temporary certificate store of our trusted root CAs.
cert_store store;
if (!store.create(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, 0, NULL))
throw win_runtime_error(ERROR_INVALID_DOMAINNAME, __FUNCTION__ " Error creating temporary certificate store.");
for (list<cert_context>::const_iterator c = cfg_method->m_trusted_root_ca.cbegin(), c_end = cfg_method->m_trusted_root_ca.cend(); c != c_end; ++c)
CertAddCertificateContextToStore(store, *c, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
// Add all intermediate certificates from the server's certificate chain.
for (cert_context c(cert); c;) {
DWORD flags = 0;
c.attach(CertGetIssuerCertificateFromStore(cert->hCertStore, c, NULL, &flags));
if (!c) break;
if (c->pCertInfo->Issuer.cbData == c->pCertInfo->Subject.cbData &&
memcmp(c->pCertInfo->Issuer.pbData, c->pCertInfo->Subject.pbData, c->pCertInfo->Issuer.cbData) == 0)
{
// Skip the root CA certificates (self-signed). We define in whom we trust!
continue;
}
CertAddCertificateContextToStore(store, c, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
}
// Prepare the certificate chain validation, and check.
CERT_CHAIN_PARA chain_params = {
sizeof(chain_params), // cbSize
{
USAGE_MATCH_TYPE_AND, // RequestedUsage.dwType
{}, // RequestedUsage.Usage
},
#ifdef CERT_CHAIN_PARA_HAS_EXTRA_FIELDS
{}, // RequestedIssuancePolicy
1, // dwUrlRetrievalTimeout (1ms to speed up checking)
#else
#define _S2(x) #x
#define _S(x) _S2(x)
#pragma message(__FILE__ "(" _S(__LINE__) "): warning X0000: Please define CERT_CHAIN_PARA_HAS_EXTRA_FIELDS constant when compiling this project.")
#endif
};
cert_chain_context context;
if (!context.create(NULL, cert, NULL, store, &chain_params, 0))
throw win_runtime_error(__FUNCTION__ " Error creating certificate chain context.");
// Check chain validation error flags. Ignore CERT_TRUST_IS_UNTRUSTED_ROOT flag since we check root CA explicitly.
if (context->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR &&
(cfg_method->m_trusted_root_ca.empty() || (context->TrustStatus.dwErrorStatus & ~CERT_TRUST_IS_UNTRUSTED_ROOT) != CERT_TRUST_NO_ERROR))
throw win_runtime_error(context->TrustStatus.dwErrorStatus, "Error validating certificate chain.");
if (!cfg_method->m_trusted_root_ca.empty()) {
// Verify Root CA against our trusted root CA list
if (context->cChain != 1)
throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Multiple chain verification not supported.");
if (context->rgpChain[0]->cElement == 0)
throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Can not verify empty certificate chain.");
PCCERT_CONTEXT cert_root = context->rgpChain[0]->rgpElement[context->rgpChain[0]->cElement-1]->pCertContext;
for (list<cert_context>::const_iterator c = cfg_method->m_trusted_root_ca.cbegin(), c_end = cfg_method->m_trusted_root_ca.cend();; ++c) {
if (c != c_end) {
if (cert_root->cbCertEncoded == (*c)->cbCertEncoded &&
memcmp(cert_root->pbCertEncoded, (*c)->pbCertEncoded, cert_root->cbCertEncoded) == 0)
{
// Trusted root CA found.
break;
}
} else {
// Not found.
throw win_runtime_error(ERROR_FILE_NOT_FOUND, __FUNCTION__ " Server's certificate not issued by one of configured trusted root CAs.");
}
}
}
m_module.log_event(&EAPMETHOD_TLS_SERVER_CERT_TRUSTED, event_data::blank);
}
#endif

View File

@@ -22,7 +22,16 @@
#include "../include/Config.h"
#include "../include/Credentials.h"
#include "../include/Method.h"
#include "../include/TLS.h"
#include "../../EAPBase/include/EAPXML.h"
#include <WinStd/Cred.h>
#include <WinStd/EAP.h>
#include <EapHostError.h>
#include <schnlsp.h>
#include <time.h>
#include <algorithm>

279
lib/TLS/src/TLS.cpp Normal file
View File

@@ -0,0 +1,279 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 G<>ANT
This file is part of G<>ANTLink.
G<>ANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
G<>ANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with G<>ANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
#include "StdAfx.h"
using namespace std;
using namespace winstd;
//////////////////////////////////////////////////////////////////////
// eap::tls_version
//////////////////////////////////////////////////////////////////////
const eap::tls_version eap::tls_version_1_0 = { 3, 1 };
const eap::tls_version eap::tls_version_1_1 = { 3, 2 };
const eap::tls_version eap::tls_version_1_2 = { 3, 3 };
//////////////////////////////////////////////////////////////////////
// eap::tls_random
//////////////////////////////////////////////////////////////////////
void eap::tls_random::randomize(_In_ HCRYPTPROV cp)
{
_time32((__time32_t*)data);
if (!CryptGenRandom(cp, sizeof(data) - sizeof(__time32_t), data + sizeof(__time32_t)))
throw win_runtime_error(__FUNCTION__ " Error creating randomness.");
}
//////////////////////////////////////////////////////////////////////
// eap::tls_master_secret
//////////////////////////////////////////////////////////////////////
eap::tls_master_secret::tls_master_secret()
{
}
eap::tls_master_secret::tls_master_secret(_In_ HCRYPTPROV cp, _In_ tls_version ver)
{
data[0] = ver.major;
data[1] = ver.minor;
if (!CryptGenRandom(cp, sizeof(data) - 2, data + 2))
throw win_runtime_error(__FUNCTION__ " Error creating PMS randomness.");
}
eap::tls_master_secret::tls_master_secret(_In_ const sanitizing_blob_f<48> &other) :
sanitizing_blob_xf<48>(other)
{
}
#ifdef _DEBUG
eap::tls_master_secret::tls_master_secret(_Inout_ sanitizing_blob_zf<48> &&other) :
sanitizing_blob_xf<48>(std::move(other))
{
}
#endif
//////////////////////////////////////////////////////////////////////
// eap::hmac_padding
//////////////////////////////////////////////////////////////////////
eap::hmac_padding::hmac_padding()
{
}
eap::hmac_padding::hmac_padding(
_In_ HCRYPTPROV cp,
_In_ ALG_ID alg,
_In_bytecount_(size_secret ) const void *secret,
_In_ size_t size_secret,
_In_opt_ unsigned char pad)
{
if (size_secret > sizeof(hmac_padding)) {
// If the secret is longer than padding, use secret's hash instead.
crypt_hash hash;
if (!hash.create(cp, alg))
throw win_runtime_error(__FUNCTION__ " Error creating hash.");
if (!CryptHashData(hash, (const BYTE*)secret, (DWORD)size_secret, 0))
throw win_runtime_error(__FUNCTION__ " Error hashing.");
DWORD size_hash = sizeof(hmac_padding);
if (!CryptGetHashParam(hash, HP_HASHVAL, data, &size_hash, 0))
throw win_runtime_error(__FUNCTION__ " Error finishing hash.");
size_secret = size_hash;
} else
memcpy(data, secret, size_secret);
for (size_t i = 0; i < size_secret; i++)
data[i] ^= pad;
memset(data + size_secret, pad, sizeof(hmac_padding) - size_secret);
}
eap::hmac_padding::hmac_padding(_In_ const sanitizing_blob_f<64> &other) :
sanitizing_blob_xf<64>(other)
{
}
#ifdef _DEBUG
eap::hmac_padding::hmac_padding(_Inout_ sanitizing_blob_zf<64> &&other) :
sanitizing_blob_xf<64>(std::move(other))
{
}
#endif
//////////////////////////////////////////////////////////////////////
// eap::hmac_hash
//////////////////////////////////////////////////////////////////////
eap::hmac_hash::hmac_hash(
_In_ HCRYPTPROV cp,
_In_ ALG_ID alg,
_In_bytecount_(size_secret ) const void *secret,
_In_ size_t size_secret)
{
// Prepare inner padding and forward to the other constructor.
this->hmac_hash::hmac_hash(cp, alg, hmac_padding(cp, alg, secret, size_secret));
}
eap::hmac_hash::hmac_hash(
_In_ HCRYPTPROV cp,
_In_ ALG_ID alg,
_In_ const hmac_padding &padding)
{
// Create inner hash.
if (!m_hash_inner.create(cp, alg))
throw win_runtime_error(__FUNCTION__ " Error creating inner hash.");
// Initialize it with the inner padding.
if (!CryptHashData(m_hash_inner, padding.data, sizeof(hmac_padding), 0))
throw win_runtime_error(__FUNCTION__ " Error hashing secret XOR inner padding.");
// Convert inner padding to outer padding for final calculation.
hmac_padding padding_out;
for (size_t i = 0; i < sizeof(hmac_padding); i++)
padding_out.data[i] = padding.data[i] ^ (0x36 ^ 0x5c);
// Create outer hash.
if (!m_hash_outer.create(cp, alg))
throw win_runtime_error(__FUNCTION__ " Error creating outer hash.");
// Initialize it with the outer padding.
if (!CryptHashData(m_hash_outer, padding_out.data, sizeof(hmac_padding), 0))
throw win_runtime_error(__FUNCTION__ " Error hashing secret XOR inner padding.");
}
//////////////////////////////////////////////////////////////////////
// eap::tls_conn_state
//////////////////////////////////////////////////////////////////////
eap::tls_conn_state::tls_conn_state()
#ifdef _DEBUG
// Initialize state primitive members for diagnostic purposes.
:
m_alg_encrypt (0),
m_size_enc_key (0),
m_size_enc_iv (0),
m_size_enc_block(0),
m_alg_mac (0),
m_size_mac_key (0),
m_size_mac_hash (0)
#endif
{
}
eap::tls_conn_state::tls_conn_state(_In_ const tls_conn_state &other) :
m_alg_encrypt (other.m_alg_encrypt ),
m_size_enc_key (other.m_size_enc_key ),
m_size_enc_iv (other.m_size_enc_iv ),
m_size_enc_block(other.m_size_enc_block),
m_key (other.m_key ),
m_alg_mac (other.m_alg_mac ),
m_size_mac_key (other.m_size_mac_key ),
m_size_mac_hash (other.m_size_mac_hash ),
m_padding_hmac (other.m_padding_hmac )
{
}
eap::tls_conn_state::tls_conn_state(_Inout_ tls_conn_state &&other) :
m_alg_encrypt (std::move(other.m_alg_encrypt )),
m_size_enc_key (std::move(other.m_size_enc_key )),
m_size_enc_iv (std::move(other.m_size_enc_iv )),
m_size_enc_block(std::move(other.m_size_enc_block)),
m_key (std::move(other.m_key )),
m_alg_mac (std::move(other.m_alg_mac )),
m_size_mac_key (std::move(other.m_size_mac_key )),
m_size_mac_hash (std::move(other.m_size_mac_hash )),
m_padding_hmac (std::move(other.m_padding_hmac ))
{
#ifdef _DEBUG
// Reinitialize other state primitive members for diagnostic purposes.
other.m_alg_encrypt = 0;
other.m_size_enc_key = 0;
other.m_size_enc_iv = 0;
other.m_size_enc_block = 0;
other.m_alg_mac = 0;
other.m_size_mac_key = 0;
other.m_size_mac_hash = 0;
#endif
}
eap::tls_conn_state& eap::tls_conn_state::operator=(_In_ const tls_conn_state &other)
{
if (this != std::addressof(other)) {
m_alg_encrypt = other.m_alg_encrypt ;
m_size_enc_key = other.m_size_enc_key ;
m_size_enc_iv = other.m_size_enc_iv ;
m_size_enc_block = other.m_size_enc_block;
m_key = other.m_key ;
m_alg_mac = other.m_alg_mac ;
m_size_mac_key = other.m_size_mac_key ;
m_size_mac_hash = other.m_size_mac_hash ;
m_padding_hmac = other.m_padding_hmac ;
}
return *this;
}
eap::tls_conn_state& eap::tls_conn_state::operator=(_Inout_ tls_conn_state &&other)
{
if (this != std::addressof(other)) {
m_alg_encrypt = std::move(other.m_alg_encrypt );
m_size_enc_key = std::move(other.m_size_enc_key );
m_size_enc_iv = std::move(other.m_size_enc_iv );
m_size_enc_block = std::move(other.m_size_enc_block);
m_key = std::move(other.m_key );
m_alg_mac = std::move(other.m_alg_mac );
m_size_mac_key = std::move(other.m_size_mac_key );
m_size_mac_hash = std::move(other.m_size_mac_hash );
m_padding_hmac = std::move(other.m_padding_hmac );
#ifdef _DEBUG
// Reinitialize other state primitive members for diagnostic purposes.
other.m_alg_encrypt = 0;
other.m_size_enc_key = 0;
other.m_size_enc_iv = 0;
other.m_size_enc_block = 0;
other.m_alg_mac = 0;
other.m_size_mac_key = 0;
other.m_size_mac_hash = 0;
#endif
}
return *this;
}

View File

@@ -24,9 +24,16 @@
#include <WinStd/Common.h>
#include <wx/filedlg.h>
#include <wx/msgdlg.h>
#include <Windows.h>
#include <cryptuiapi.h>
#include <WinCrypt.h> // Must include after <Windows.h>
#include <list>
#include <string>
///
/// Helper class for auto-destroyable certificates used in wxWidget's item containers
@@ -49,32 +56,24 @@ class wxFQDNValidator;
class wxFQDNListValidator;
///
/// EAPTLS credential panel
/// TLS credential panel
///
class wxEAPTLSCredentialsPanel;
class wxTLSCredentialsPanel;
///
/// EAPTLS server trust configuration panel
/// TLS server trust configuration panel
///
class wxEAPTLSServerTrustPanel;
class wxTLSServerTrustPanel;
///
/// TLS credentials configuration panel
///
typedef wxEAPCredentialsConfigPanel<eap::config_tls, eap::credentials_tls, wxEAPTLSCredentialsPanel> wxEAPTLSCredentialsConfigPanel;
typedef wxEAPCredentialsConfigPanel<eap::credentials_tls, wxTLSCredentialsPanel> wxTLSCredentialsConfigPanel;
///
/// EAPTLS configuration panel
/// TLS configuration panel
///
class wxEAPTLSConfigPanel;
namespace eap
{
///
/// Helper function to compile human-readable certificate name for UI display
///
void get_cert_title(PCCERT_CONTEXT cert, winstd::tstring &title);
}
class wxTLSConfigPanel;
#pragma once
@@ -120,7 +119,7 @@ public:
///
/// Construct the validator with a value to store data
///
wxHostNameValidator(std::string *val = NULL);
wxHostNameValidator(std::wstring *val = NULL);
///
/// Copy constructor
@@ -150,10 +149,10 @@ public:
///
/// Parses FQDN value
///
static bool Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::string *val_out = NULL);
static bool Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::wstring *val_out = NULL);
protected:
std::string *m_val; ///< Pointer to variable to receive control's parsed value
std::wstring *m_val; ///< Pointer to variable to receive control's parsed value
};
@@ -166,7 +165,7 @@ public:
///
/// Construct the validator with a value to store data
///
wxFQDNValidator(std::string *val = NULL);
wxFQDNValidator(std::wstring *val = NULL);
///
/// Copy constructor
@@ -196,10 +195,10 @@ public:
///
/// Parses FQDN value
///
static bool Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::string *val_out = NULL);
static bool Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::wstring *val_out = NULL);
protected:
std::string *m_val; ///< Pointer to variable to receive control's parsed value
std::wstring *m_val; ///< Pointer to variable to receive control's parsed value
};
@@ -212,7 +211,7 @@ public:
///
/// Construct the validator with a value to store data
///
wxFQDNListValidator(std::list<std::string> *val = NULL);
wxFQDNListValidator(std::list<std::wstring> *val = NULL);
///
/// Copy constructor
@@ -242,47 +241,54 @@ public:
///
/// Parses FQDN list value
///
static bool Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::list<std::string> *val_out = NULL);
static bool Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::list<std::wstring> *val_out = NULL);
protected:
std::list<std::string> *m_val; ///< Pointer to variable to receive control's parsed value
std::list<std::wstring> *m_val; ///< Pointer to variable to receive control's parsed value
};
class wxEAPTLSCredentialsPanel : public wxCredentialsPanel<wxEAPTLSCredentialsPanelBase, eap::credentials_tls>
class wxTLSCredentialsPanel : public wxEAPCredentialsPanelBase<eap::credentials_tls, wxTLSCredentialsPanelBase>
{
public:
///
/// Constructs a configuration panel
///
wxEAPTLSCredentialsPanel(eap::credentials_tls &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false);
/// \param[in] prov Provider configuration data
/// \param[in] cfg Configuration data
/// \param[inout] cred Credentials data
/// \param[in] pszCredTarget Target name of credentials in Windows Credential Manager. Can be further decorated to create final target name.
/// \param[in] parent Parent window
/// \param[in] is_config Is this panel used to pre-enter credentials? When \c true, the "Remember" checkbox is always selected and disabled.
///
wxTLSCredentialsPanel(const eap::config_provider &prov, const eap::config_method_with_cred &cfg, eap::credentials_tls &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false);
protected:
/// \cond internal
virtual bool TransferDataToWindow();
virtual bool TransferDataFromWindow();
virtual void OnCertSelect(wxCommandEvent& event);
virtual void OnUpdateUI(wxUpdateUIEvent& event);
/// \endcond
protected:
winstd::library m_shell32; ///< shell32.dll resource library reference
wxIcon m_icon; ///< Panel icon
winstd::library m_shell32; ///< shell32.dll resource library reference
wxIcon m_icon; ///< Panel icon
};
class wxEAPTLSServerTrustPanel : public wxEAPTLSServerTrustConfigPanelBase
class wxTLSServerTrustPanel : public wxEAPTLSServerTrustConfigPanelBase
{
public:
///
/// Constructs a configuration panel
///
wxEAPTLSServerTrustPanel(eap::config_tls &cfg, wxWindow* parent);
wxTLSServerTrustPanel(const eap::config_provider &prov, eap::config_method_tls &cfg, wxWindow* parent);
protected:
/// \cond internal
virtual bool TransferDataToWindow();
virtual bool TransferDataFromWindow();
virtual void OnRootCA(wxCommandEvent& event);
virtual void OnUpdateUI(wxUpdateUIEvent& event);
virtual void OnRootCADClick(wxCommandEvent& event);
virtual void OnRootCAAddStore(wxCommandEvent& event);
virtual void OnRootCAAddFile(wxCommandEvent& event);
@@ -301,24 +307,26 @@ protected:
bool AddRootCA(PCCERT_CONTEXT cert);
protected:
eap::config_tls &m_cfg; ///< TLS configuration
winstd::library m_certmgr; ///< certmgr.dll resource library reference
wxIcon m_icon; ///< Panel icon
const eap::config_provider &m_prov; ///< EAP provider
eap::config_method_tls &m_cfg; ///< TLS configuration
winstd::library m_certmgr; ///< certmgr.dll resource library reference
wxIcon m_icon; ///< Panel icon
std::list<std::wstring> m_server_names_val; ///< Acceptable authenticating server names
};
class wxEAPTLSConfigPanel : public wxPanel
class wxTLSConfigPanel : public wxPanel
{
public:
///
/// Constructs a configuration panel
///
wxEAPTLSConfigPanel(eap::config_tls &cfg, LPCTSTR pszCredTarget, wxWindow* parent);
wxTLSConfigPanel(const eap::config_provider &prov, eap::config_method_tls &cfg, LPCTSTR pszCredTarget, wxWindow* parent);
///
/// Destructs the configuration panel
///
virtual ~wxEAPTLSConfigPanel();
virtual ~wxTLSConfigPanel();
protected:
/// \cond internal
@@ -326,6 +334,8 @@ protected:
/// \endcond
protected:
wxEAPTLSServerTrustPanel *m_server_trust; ///< Server trust configuration panel
wxEAPTLSCredentialsConfigPanel *m_credentials; ///< Credentials configuration panel
const eap::config_provider &m_prov; ///< EAP provider
eap::config_method_tls &m_cfg; ///< TLS configuration
wxTLSServerTrustPanel *m_server_trust; ///< Server trust configuration panel
wxTLSCredentialsConfigPanel *m_credentials; ///< Credentials configuration panel
};

View File

@@ -74,11 +74,11 @@ wxEAPTLSServerTrustConfigPanelBase::wxEAPTLSServerTrustConfigPanelBase( wxWindow
sb_server_names->Add( m_server_names_label, 0, wxBOTTOM, 5 );
m_server_names = new wxTextCtrl( sb_server_trust->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_server_names->SetToolTip( _("A semicolon delimited list of acceptable server FQDN names; blank to skip name check; \"*\" wildchar allowed") );
m_server_names->SetToolTip( _("A semicolon delimited list of acceptable server FQDN names; blank to skip name check; Unicode characters allowed") );
sb_server_names->Add( m_server_names, 0, wxEXPAND|wxBOTTOM, 5 );
m_server_names_note = new wxStaticText( sb_server_trust->GetStaticBox(), wxID_ANY, _("(Example: foo.bar.com;*.domain.org)"), wxDefaultPosition, wxDefaultSize, 0 );
m_server_names_note = new wxStaticText( sb_server_trust->GetStaticBox(), wxID_ANY, _("(Example: foo.bar.com;server2.bar.com)"), wxDefaultPosition, wxDefaultSize, 0 );
m_server_names_note->Wrap( -1 );
sb_server_names->Add( m_server_names_note, 0, wxALIGN_RIGHT, 5 );
@@ -96,7 +96,7 @@ wxEAPTLSServerTrustConfigPanelBase::wxEAPTLSServerTrustConfigPanelBase( wxWindow
this->Layout();
// Connect Events
m_root_ca->Connect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( wxEAPTLSServerTrustConfigPanelBase::OnRootCA ), NULL, this );
this->Connect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( wxEAPTLSServerTrustConfigPanelBase::OnUpdateUI ) );
m_root_ca->Connect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler( wxEAPTLSServerTrustConfigPanelBase::OnRootCADClick ), NULL, this );
m_root_ca_add_store->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPTLSServerTrustConfigPanelBase::OnRootCAAddStore ), NULL, this );
m_root_ca_add_file->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPTLSServerTrustConfigPanelBase::OnRootCAAddFile ), NULL, this );
@@ -106,7 +106,7 @@ wxEAPTLSServerTrustConfigPanelBase::wxEAPTLSServerTrustConfigPanelBase( wxWindow
wxEAPTLSServerTrustConfigPanelBase::~wxEAPTLSServerTrustConfigPanelBase()
{
// Disconnect Events
m_root_ca->Disconnect( wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler( wxEAPTLSServerTrustConfigPanelBase::OnRootCA ), NULL, this );
this->Disconnect( wxEVT_UPDATE_UI, wxUpdateUIEventHandler( wxEAPTLSServerTrustConfigPanelBase::OnUpdateUI ) );
m_root_ca->Disconnect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler( wxEAPTLSServerTrustConfigPanelBase::OnRootCADClick ), NULL, this );
m_root_ca_add_store->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPTLSServerTrustConfigPanelBase::OnRootCAAddStore ), NULL, this );
m_root_ca_add_file->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxEAPTLSServerTrustConfigPanelBase::OnRootCAAddFile ), NULL, this );
@@ -114,7 +114,7 @@ wxEAPTLSServerTrustConfigPanelBase::~wxEAPTLSServerTrustConfigPanelBase()
}
wxEAPTLSCredentialsPanelBase::wxEAPTLSCredentialsPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
wxTLSCredentialsPanelBase::wxTLSCredentialsPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
{
wxStaticBoxSizer* sb_credentials;
sb_credentials = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("TLS Client Certificate") ), wxVERTICAL );
@@ -175,14 +175,8 @@ wxEAPTLSCredentialsPanelBase::wxEAPTLSCredentialsPanelBase( wxWindow* parent, wx
this->SetSizer( sb_credentials );
this->Layout();
// Connect Events
m_cert_select->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( wxEAPTLSCredentialsPanelBase::OnCertSelect ), NULL, this );
}
wxEAPTLSCredentialsPanelBase::~wxEAPTLSCredentialsPanelBase()
wxTLSCredentialsPanelBase::~wxTLSCredentialsPanelBase()
{
// Disconnect Events
m_cert_select->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( wxEAPTLSCredentialsPanelBase::OnCertSelect ), NULL, this );
}

View File

@@ -77,7 +77,7 @@
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
<event name="OnUpdateUI">OnUpdateUI</event>
<object class="wxStaticBoxSizer" expanded="1">
<property name="id">wxID_ANY</property>
<property name="label">Server Trust</property>
@@ -431,7 +431,7 @@
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnListBox">OnRootCA</event>
<event name="OnListBox"></event>
<event name="OnListBoxDClick">OnRootCADClick</event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
@@ -870,7 +870,7 @@
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip">A semicolon delimited list of acceptable server FQDN names; blank to skip name check; &quot;*&quot; wildchar allowed</property>
<property name="tooltip">A semicolon delimited list of acceptable server FQDN names; blank to skip name check; Unicode characters allowed</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
@@ -940,7 +940,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">(Example: foo.bar.com;*.domain.org)</property>
<property name="label">(Example: foo.bar.com;server2.bar.com)</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
@@ -1013,7 +1013,7 @@
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">wxEAPTLSCredentialsPanelBase</property>
<property name="name">wxTLSCredentialsPanelBase</property>
<property name="pos"></property>
<property name="size">500,-1</property>
<property name="subclass"></property>
@@ -1426,7 +1426,7 @@
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRadioButton">OnCertSelect</event>
<event name="OnRadioButton"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>

View File

@@ -53,7 +53,7 @@ class wxEAPTLSServerTrustConfigPanelBase : public wxPanel
wxStaticText* m_server_names_note;
// Virtual event handlers, overide them in your derived class
virtual void OnRootCA( wxCommandEvent& event ) { event.Skip(); }
virtual void OnUpdateUI( wxUpdateUIEvent& event ) { event.Skip(); }
virtual void OnRootCADClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRootCAAddStore( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRootCAAddFile( wxCommandEvent& event ) { event.Skip(); }
@@ -68,9 +68,9 @@ class wxEAPTLSServerTrustConfigPanelBase : public wxPanel
};
///////////////////////////////////////////////////////////////////////////////
/// Class wxEAPTLSCredentialsPanelBase
/// Class wxTLSCredentialsPanelBase
///////////////////////////////////////////////////////////////////////////////
class wxEAPTLSCredentialsPanelBase : public wxPanel
class wxTLSCredentialsPanelBase : public wxPanel
{
private:
@@ -81,15 +81,11 @@ class wxEAPTLSCredentialsPanelBase : public wxPanel
wxRadioButton* m_cert_select;
wxChoice* m_cert_select_val;
wxCheckBox* m_remember;
// Virtual event handlers, overide them in your derived class
virtual void OnCertSelect( wxCommandEvent& event ) { event.Skip(); }
public:
wxEAPTLSCredentialsPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,-1 ), long style = wxTAB_TRAVERSAL );
~wxEAPTLSCredentialsPanelBase();
wxTLSCredentialsPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,-1 ), long style = wxTAB_TRAVERSAL );
~wxTLSCredentialsPanelBase();
};

View File

@@ -25,8 +25,3 @@
#include "../../../include/Version.h"
#include "../include/TLS_UI.h"
#include <wx/filedlg.h>
#include <wx/msgdlg.h>
#include <cryptuiapi.h>

View File

@@ -20,46 +20,9 @@
#include "StdAfx.h"
#pragma comment(lib, "Cryptui.lib")
#pragma comment(lib, "Crypt32.lib")
//////////////////////////////////////////////////////////////////////
// eap::get_cert_title
//////////////////////////////////////////////////////////////////////
void eap::get_cert_title(PCCERT_CONTEXT cert, winstd::tstring &title)
{
winstd::tstring name, str, issuer;
FILETIME ft;
SYSTEMTIME st;
title.clear();
// Prepare certificate information
CertGetNameString(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, name);
title += name;
FileTimeToLocalFileTime(&(cert->pCertInfo->NotBefore), &ft);
FileTimeToSystemTime(&ft, &st);
GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, str);
title += _T(", ");
title += str;
FileTimeToLocalFileTime(&(cert->pCertInfo->NotAfter ), &ft);
FileTimeToSystemTime(&ft, &st);
GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, str);
title += _T('-');
title += str;
CertGetNameString(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, issuer);
if (name != issuer) {
title += _T(", ");
title += issuer;
}
}
//////////////////////////////////////////////////////////////////////
// wxCertificateClientData
//////////////////////////////////////////////////////////////////////
@@ -83,7 +46,7 @@ wxCertificateClientData::~wxCertificateClientData()
wxIMPLEMENT_DYNAMIC_CLASS(wxHostNameValidator, wxValidator);
wxHostNameValidator::wxHostNameValidator(std::string *val) :
wxHostNameValidator::wxHostNameValidator(std::wstring *val) :
m_val(val),
wxValidator()
{
@@ -135,7 +98,7 @@ bool wxHostNameValidator::TransferFromWindow()
}
bool wxHostNameValidator::Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::string *val_out)
bool wxHostNameValidator::Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::wstring *val_out)
{
const wxStringCharType *buf = val_in;
@@ -145,7 +108,7 @@ bool wxHostNameValidator::Parse(const wxString &val_in, size_t i_start, size_t i
// End of host name found.
if (val_out) val_out->assign(val_in.c_str() + i_start, i - i_start);
return true;
} else if (_tcschr(wxT("abcdefghijklmnopqrstuvwxyz0123456789-*"), buf[i])) {
} else if (buf[i] == _T('-') || buf[i] == _T('_') || _istalnum(buf[i])) {
// Valid character found.
i++;
} else {
@@ -166,7 +129,7 @@ bool wxHostNameValidator::Parse(const wxString &val_in, size_t i_start, size_t i
wxIMPLEMENT_DYNAMIC_CLASS(wxFQDNValidator, wxValidator);
wxFQDNValidator::wxFQDNValidator(std::string *val) :
wxFQDNValidator::wxFQDNValidator(std::wstring *val) :
m_val(val),
wxValidator()
{
@@ -218,7 +181,7 @@ bool wxFQDNValidator::TransferFromWindow()
}
bool wxFQDNValidator::Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::string *val_out)
bool wxFQDNValidator::Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::wstring *val_out)
{
const wxStringCharType *buf = val_in;
@@ -247,7 +210,7 @@ bool wxFQDNValidator::Parse(const wxString &val_in, size_t i_start, size_t i_end
wxIMPLEMENT_DYNAMIC_CLASS(wxFQDNListValidator, wxValidator);
wxFQDNListValidator::wxFQDNListValidator(std::list<std::string> *val) :
wxFQDNListValidator::wxFQDNListValidator(std::list<std::wstring> *val) :
m_val(val),
wxValidator()
{
@@ -283,7 +246,7 @@ bool wxFQDNListValidator::TransferToWindow()
if (m_val) {
wxString str;
for (std::list<std::string>::const_iterator name = m_val->cbegin(), name_end = m_val->cend(); name != name_end; ++name) {
for (std::list<std::wstring>::const_iterator name = m_val->cbegin(), name_end = m_val->cend(); name != name_end; ++name) {
if (!str.IsEmpty()) str += wxT("; ");
str += *name;
}
@@ -304,11 +267,11 @@ bool wxFQDNListValidator::TransferFromWindow()
}
bool wxFQDNListValidator::Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::list<std::string> *val_out)
bool wxFQDNListValidator::Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::list<std::wstring> *val_out)
{
const wxStringCharType *buf = val_in;
std::string _fqdn, *fqdn = val_out ? &_fqdn : NULL;
std::list<std::string> _val_out;
std::wstring _fqdn, *fqdn = val_out ? &_fqdn : NULL;
std::list<std::wstring> _val_out;
size_t i = i_start;
for (;;) {
@@ -332,7 +295,7 @@ bool wxFQDNListValidator::Parse(const wxString &val_in, size_t i_start, size_t i
// Skip trailing white-space.
for (; i < i_end && _istspace(buf[i_end - 1]); i_end--);
if (wxHostNameValidator::Parse(val_in, i, i_end, ctrl, parent, fqdn)) {
if (wxFQDNValidator::Parse(val_in, i, i_end, ctrl, parent, fqdn)) {
// The rest of the FQDN list parsed succesfully.
if (fqdn && !fqdn->empty()) _val_out.push_back(std::move(*fqdn));
if (val_out) *val_out = std::move(_val_out);
@@ -345,11 +308,11 @@ bool wxFQDNListValidator::Parse(const wxString &val_in, size_t i_start, size_t i
//////////////////////////////////////////////////////////////////////
// wxEAPTLSCredentialsPanel
// wxTLSCredentialsPanel
//////////////////////////////////////////////////////////////////////
wxEAPTLSCredentialsPanel::wxEAPTLSCredentialsPanel(eap::credentials_tls &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config) :
wxCredentialsPanel<wxEAPTLSCredentialsPanelBase, eap::credentials_tls>(cred, pszCredTarget, parent, is_config)
wxTLSCredentialsPanel::wxTLSCredentialsPanel(const eap::config_provider &prov, const eap::config_method_with_cred &cfg, eap::credentials_tls &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config) :
wxEAPCredentialsPanelBase<eap::credentials_tls, wxTLSCredentialsPanelBase>(prov, cfg, cred, pszCredTarget, parent, is_config)
{
// Load and set icon.
if (m_shell32.load(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
@@ -357,10 +320,8 @@ wxEAPTLSCredentialsPanel::wxEAPTLSCredentialsPanel(eap::credentials_tls &cred, L
}
bool wxEAPTLSCredentialsPanel::TransferDataToWindow()
bool wxTLSCredentialsPanel::TransferDataToWindow()
{
wxCHECK(__super::TransferDataToWindow(), false);
// Populate certificate list.
bool is_found = false;
winstd::cert_store store;
@@ -380,8 +341,7 @@ bool wxEAPTLSCredentialsPanel::TransferDataToWindow()
m_cred.m_cert &&
m_cred.m_cert->cbCertEncoded == data->m_cert->cbCertEncoded &&
memcmp(m_cred.m_cert->pbCertEncoded, data->m_cert->pbCertEncoded, m_cred.m_cert->cbCertEncoded) == 0;
winstd::tstring name;
eap::get_cert_title(cert, name);
winstd::tstring name(std::move(eap::get_cert_title(cert)));
int i = m_cert_select_val->Append(name, data.release());
if (is_selected) {
m_cert_select_val->SetSelection(i);
@@ -391,50 +351,63 @@ bool wxEAPTLSCredentialsPanel::TransferDataToWindow()
}
if (is_found) {
m_cert_select ->SetValue(true);
m_cert_select_val->Enable(true);
m_cert_select->SetValue(true);
} else {
m_cert_none ->SetValue(true);
m_cert_select_val->Enable(false);
m_cert_none->SetValue(true);
if (!m_cert_select_val->IsEmpty())
m_cert_select_val->SetSelection(0);
}
return true;
return wxEAPCredentialsPanelBase<eap::credentials_tls, wxTLSCredentialsPanelBase>::TransferDataToWindow();
}
bool wxEAPTLSCredentialsPanel::TransferDataFromWindow()
bool wxTLSCredentialsPanel::TransferDataFromWindow()
{
if (m_cert_none->GetValue())
m_cred.clear();
m_cred.m_cert.free();
else {
const wxCertificateClientData *data = dynamic_cast<const wxCertificateClientData*>(m_cert_select_val->GetClientObject(m_cert_select_val->GetSelection()));
if (data) {
if (data)
m_cred.m_cert.attach_duplicated(data->m_cert);
// Generate identity. TODO: Find which CERT_NAME_... constant returns valid identity (username@domain or DOMAIN\Username).
CertGetNameString(m_cred.m_cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, m_cred.m_identity);
} else
m_cred.clear();
else
m_cred.m_cert.free();
}
return __super::TransferDataFromWindow();
// Inherited TransferDataFromWindow() calls m_cred.store().
// Therefore, call it only now, that m_cred is set.
return wxEAPCredentialsPanelBase<eap::credentials_tls, wxTLSCredentialsPanelBase>::TransferDataFromWindow();
}
void wxEAPTLSCredentialsPanel::OnCertSelect(wxCommandEvent& event)
void wxTLSCredentialsPanel::OnUpdateUI(wxUpdateUIEvent& event)
{
UNREFERENCED_PARAMETER(event);
m_cert_select_val->Enable(m_cert_select->GetValue());
if (!m_is_config && m_cfg.m_use_preshared) {
// Credential prompt mode & Using pre-shared credentials
// To avoid run-away selection of radio buttons, disable the selected one last.
if (m_cert_none->GetValue()) {
m_cert_select->Enable(false);
m_cert_none ->Enable(false);
} else {
m_cert_none ->Enable(false);
m_cert_select->Enable(false);
}
m_cert_select_val->Enable(false);
} else {
// Configuration mode or using own credentials. Selectively enable/disable controls.
m_cert_select_val->Enable(m_cert_select->GetValue());
}
wxEAPCredentialsPanelBase<eap::credentials_tls, wxTLSCredentialsPanelBase>::OnUpdateUI(event);
}
//////////////////////////////////////////////////////////////////////
// wxEAPTLSServerTrustPanel
// wxTLSServerTrustPanel
//////////////////////////////////////////////////////////////////////
wxEAPTLSServerTrustPanel::wxEAPTLSServerTrustPanel(eap::config_tls &cfg, wxWindow* parent) :
wxTLSServerTrustPanel::wxTLSServerTrustPanel(const eap::config_provider &prov, eap::config_method_tls &cfg, wxWindow* parent) :
m_prov(prov),
m_cfg(cfg),
wxEAPTLSServerTrustConfigPanelBase(parent)
{
@@ -442,47 +415,70 @@ wxEAPTLSServerTrustPanel::wxEAPTLSServerTrustPanel(eap::config_tls &cfg, wxWindo
if (m_certmgr.load(_T("certmgr.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
wxSetIconFromResource(m_server_trust_icon, m_icon, m_certmgr, MAKEINTRESOURCE(218));
m_server_names->SetValidator(wxFQDNListValidator(&(m_cfg.m_server_names)));
// Do not use cfg.m_server_names directly, so we can decide not to store the value in case of provider-locked configuration.
// Never rely on control disabled state alone, as they can be enabled using external tool like Spy++.
m_server_names->SetValidator(wxFQDNListValidator(&m_server_names_val));
}
bool wxEAPTLSServerTrustPanel::TransferDataToWindow()
bool wxTLSServerTrustPanel::TransferDataToWindow()
{
wxCHECK(wxEAPTLSServerTrustConfigPanelBase::TransferDataToWindow(), false);
// Populate trusted CA list.
for (std::list<winstd::cert_context>::const_iterator cert = m_cfg.m_trusted_root_ca.cbegin(), cert_end = m_cfg.m_trusted_root_ca.cend(); cert != cert_end; ++cert) {
winstd::tstring name;
if (CertGetNameString(*cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, name) > 0)
m_root_ca->Append(wxString(name), new wxCertificateClientData(cert->duplicate()));
for (std::list<winstd::cert_context>::const_iterator cert = m_cfg.m_trusted_root_ca.cbegin(), cert_end = m_cfg.m_trusted_root_ca.cend(); cert != cert_end; ++cert)
m_root_ca->Append(wxString(eap::get_cert_title(*cert)), new wxCertificateClientData(cert->duplicate()));
// Set server acceptable names. The edit control will get populated by validator.
m_server_names_val = m_cfg.m_server_names;
return wxEAPTLSServerTrustConfigPanelBase::TransferDataToWindow();
}
bool wxTLSServerTrustPanel::TransferDataFromWindow()
{
wxCHECK(wxEAPTLSServerTrustConfigPanelBase::TransferDataFromWindow(), false);
if (!m_prov.m_read_only) {
// This is not a provider-locked configuration. Save the data.
// Parse trusted CA list.
m_cfg.m_trusted_root_ca.clear();
for (unsigned int i = 0, i_end = m_root_ca->GetCount(); i < i_end; i++) {
wxCertificateClientData *cert = dynamic_cast<wxCertificateClientData*>(m_root_ca->GetClientObject(i));
if (cert)
m_cfg.add_trusted_ca(cert->m_cert->dwCertEncodingType, cert->m_cert->pbCertEncoded, cert->m_cert->cbCertEncoded);
}
// Save acceptable server names.
m_cfg.m_server_names = m_server_names_val;
}
return true;
}
bool wxEAPTLSServerTrustPanel::TransferDataFromWindow()
void wxTLSServerTrustPanel::OnUpdateUI(wxUpdateUIEvent& event)
{
// Parse trusted CA list.
m_cfg.m_trusted_root_ca.clear();
for (unsigned int i = 0, i_end = m_root_ca->GetCount(); i < i_end; i++) {
wxCertificateClientData *cert = dynamic_cast<wxCertificateClientData*>(m_root_ca->GetClientObject(i));
if (cert)
m_cfg.add_trusted_ca(cert->m_cert->dwCertEncodingType, cert->m_cert->pbCertEncoded, cert->m_cert->cbCertEncoded);
UNREFERENCED_PARAMETER(event);
if (m_prov.m_read_only) {
// This is provider-locked configuration. Disable controls.
m_root_ca_add_store->Enable(false);
m_root_ca_add_file ->Enable(false);
m_root_ca_remove ->Enable(false);
m_server_names ->Enable(false);
} else {
// This is not a provider-locked configuration. Selectively enable/disable controls.
m_root_ca_add_store->Enable(true);
m_root_ca_add_file ->Enable(true);
wxArrayInt selections;
m_root_ca_remove->Enable(m_root_ca->GetSelections(selections) ? true : false);
m_server_names ->Enable(true);
}
return wxEAPTLSServerTrustConfigPanelBase::TransferDataFromWindow();
}
void wxEAPTLSServerTrustPanel::OnRootCA(wxCommandEvent& event)
{
wxCertificateClientData *cert = dynamic_cast<wxCertificateClientData*>(event.GetClientObject());
m_root_ca_remove->Enable(cert ? true : false);
}
void wxEAPTLSServerTrustPanel::OnRootCADClick(wxCommandEvent& event)
void wxTLSServerTrustPanel::OnRootCADClick(wxCommandEvent& event)
{
wxCertificateClientData *cert = dynamic_cast<wxCertificateClientData*>(event.GetClientObject());
if (cert)
@@ -490,7 +486,7 @@ void wxEAPTLSServerTrustPanel::OnRootCADClick(wxCommandEvent& event)
}
void wxEAPTLSServerTrustPanel::OnRootCAAddStore(wxCommandEvent& event)
void wxTLSServerTrustPanel::OnRootCAAddStore(wxCommandEvent& event)
{
UNREFERENCED_PARAMETER(event);
@@ -504,7 +500,7 @@ void wxEAPTLSServerTrustPanel::OnRootCAAddStore(wxCommandEvent& event)
}
void wxEAPTLSServerTrustPanel::OnRootCAAddFile(wxCommandEvent& event)
void wxTLSServerTrustPanel::OnRootCAAddFile(wxCommandEvent& event)
{
UNREFERENCED_PARAMETER(event);
@@ -534,19 +530,17 @@ void wxEAPTLSServerTrustPanel::OnRootCAAddFile(wxCommandEvent& event)
}
void wxEAPTLSServerTrustPanel::OnRootCARemove(wxCommandEvent& event)
void wxTLSServerTrustPanel::OnRootCARemove(wxCommandEvent& event)
{
UNREFERENCED_PARAMETER(event);
wxArrayInt selections;
for (int i = m_root_ca->GetSelections(selections); i--; )
m_root_ca->Delete(selections[i]);
m_root_ca_remove->Enable(false);
}
bool wxEAPTLSServerTrustPanel::AddRootCA(PCCERT_CONTEXT cert)
bool wxTLSServerTrustPanel::AddRootCA(PCCERT_CONTEXT cert)
{
for (unsigned int i = 0, i_end = m_root_ca->GetCount(); i < i_end; i++) {
wxCertificateClientData *c = dynamic_cast<wxCertificateClientData*>(m_root_ca->GetClientObject(i));
@@ -556,61 +550,53 @@ bool wxEAPTLSServerTrustPanel::AddRootCA(PCCERT_CONTEXT cert)
{
// This certificate is already on the list.
m_root_ca->SetSelection(i);
m_root_ca_remove->Enable();
return false;
}
}
// Add certificate to the list.
winstd::tstring name;
if (CertGetNameString(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, name) > 0) {
int i = m_root_ca->Append(wxString(name), new wxCertificateClientData(CertDuplicateCertificateContext(cert)));
if (0 <= i) {
m_root_ca->SetSelection(i);
m_root_ca_remove->Enable();
}
return true;
}
int i = m_root_ca->Append(wxString(eap::get_cert_title(cert)), new wxCertificateClientData(CertDuplicateCertificateContext(cert)));
if (0 <= i)
m_root_ca->SetSelection(i);
return false;
return true;
}
//////////////////////////////////////////////////////////////////////
// wxEAPTLSConfigPanel
// wxTLSConfigPanel
//////////////////////////////////////////////////////////////////////
wxEAPTLSConfigPanel::wxEAPTLSConfigPanel(eap::config_tls &cfg, LPCTSTR pszCredTarget, wxWindow* parent) : wxPanel(parent)
wxTLSConfigPanel::wxTLSConfigPanel(const eap::config_provider &prov, eap::config_method_tls &cfg, LPCTSTR pszCredTarget, wxWindow* parent) :
m_prov(prov),
m_cfg(cfg),
wxPanel(parent)
{
wxBoxSizer* sb_content;
sb_content = new wxBoxSizer( wxVERTICAL );
m_server_trust = new wxEAPTLSServerTrustPanel(cfg, this);
if (cfg.m_allow_save) {
sb_content->Add(m_server_trust, 0, wxDOWN|wxEXPAND, 5);
m_credentials = new wxEAPTLSCredentialsConfigPanel(cfg, pszCredTarget, this);
sb_content->Add(m_credentials, 0, wxUP|wxEXPAND, 5);
} else {
sb_content->Add(m_server_trust, 0, wxEXPAND, 5);
m_credentials = NULL;
}
m_server_trust = new wxTLSServerTrustPanel(prov, cfg, this);
sb_content->Add(m_server_trust, 0, wxDOWN|wxEXPAND, 5);
m_credentials = new wxTLSCredentialsConfigPanel(prov, cfg, pszCredTarget, this);
sb_content->Add(m_credentials, 0, wxUP|wxEXPAND, 5);
this->SetSizer(sb_content);
this->Layout();
// Connect Events
this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxEAPTLSConfigPanel::OnInitDialog));
this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxTLSConfigPanel::OnInitDialog));
}
wxEAPTLSConfigPanel::~wxEAPTLSConfigPanel()
wxTLSConfigPanel::~wxTLSConfigPanel()
{
// Disconnect Events
this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxEAPTLSConfigPanel::OnInitDialog));
this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxTLSConfigPanel::OnInitDialog));
}
void wxEAPTLSConfigPanel::OnInitDialog(wxInitDialogEvent& event)
void wxTLSConfigPanel::OnInitDialog(wxInitDialogEvent& event)
{
// Forward the event to child panels.
m_server_trust->GetEventHandler()->ProcessEvent(event);

View File

@@ -81,15 +81,15 @@
<ItemGroup>
<ClInclude Include="..\include\Config.h" />
<ClInclude Include="..\include\Credentials.h" />
<ClInclude Include="..\include\Method.h" />
<ClInclude Include="..\include\Module.h" />
<ClInclude Include="..\include\Session.h" />
<ClInclude Include="..\src\StdAfx.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\Config.cpp" />
<ClCompile Include="..\src\Credentials.cpp" />
<ClCompile Include="..\src\Method.cpp" />
<ClCompile Include="..\src\Module.cpp" />
<ClCompile Include="..\src\Session.cpp" />
<ClCompile Include="..\src\StdAfx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>

View File

@@ -20,7 +20,7 @@
<ClInclude Include="..\include\Credentials.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\Session.h">
<ClInclude Include="..\include\Method.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\Module.h">
@@ -37,10 +37,10 @@
<ClCompile Include="..\src\Credentials.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\Module.cpp">
<ClCompile Include="..\src\Method.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\Session.cpp">
<ClCompile Include="..\src\Module.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

View File

@@ -25,75 +25,46 @@ namespace eap
///
/// TTLS configuration
///
class config_ttls;
}
namespace eapserial
{
///
/// Packs a TTLS based method configuration
///
/// \param[inout] cursor Memory cursor
/// \param[in] val Configuration to pack
///
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::config_ttls &val);
///
/// Returns packed size of a TTLS based method configuration
///
/// \param[in] val Configuration to pack
///
/// \returns Size of data when packed (in bytes)
///
inline size_t get_pk_size(const eap::config_ttls &val);
///
/// Unpacks a TTLS based method configuration
///
/// \param[inout] cursor Memory cursor
/// \param[out] val Configuration to unpack to
///
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::config_ttls &val);
class config_method_ttls;
}
#pragma once
#include "Credentials.h"
#include "../../TLS/include/Config.h"
#include "../../PAP/include/Config.h"
#include <Windows.h>
#include <assert.h>
#include <memory>
namespace eap {
class config_ttls : public config_tls
class config_method_ttls : public config_method_tls
{
public:
///
/// Constructs configuration
///
/// \param[in] mod Reference of the EAP module to use for global services
/// \param[in] mod EAP module to use for global services
///
config_ttls(_In_ module &mod);
config_method_ttls(_In_ module &mod);
///
/// Copies configuration
///
/// \param[in] other Configuration to copy from
///
config_ttls(const _In_ config_ttls &other);
config_method_ttls(const _In_ config_method_ttls &other);
///
/// Moves configuration
///
/// \param[in] other Configuration to move from
///
config_ttls(_Inout_ config_ttls &&other);
///
/// Destructs configuration
///
virtual ~config_ttls();
config_method_ttls(_Inout_ config_method_ttls &&other);
///
/// Copies configuration
@@ -102,7 +73,7 @@ namespace eap {
///
/// \returns Reference to this object
///
config_ttls& operator=(const _In_ config_ttls &other);
config_method_ttls& operator=(const _In_ config_method_ttls &other);
///
/// Moves configuration
@@ -111,7 +82,7 @@ namespace eap {
///
/// \returns Reference to this object
///
config_ttls& operator=(_Inout_ config_ttls &&other);
config_method_ttls& operator=(_Inout_ config_method_ttls &&other);
///
/// Clones configuration
@@ -124,101 +95,60 @@ namespace eap {
/// @{
///
/// Save configuration to XML document
/// Save to XML document
///
/// \param[in] pDoc XML document
/// \param[in] pConfigRoot Suggested root element for saving configuration
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
/// \param[in] pConfigRoot Suggested root element for saving
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const;
virtual void save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const;
///
/// Load configuration from XML document
/// Load from XML document
///
/// \param[in] pConfigRoot Root element for loading configuration
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
/// \param[in] pConfigRoot Root element for loading
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError);
virtual void load(_In_ IXMLDOMNode *pConfigRoot);
/// @}
/// \name BLOB management
/// @{
///
/// Packs a configuration
///
/// \param[inout] cursor Memory cursor
///
virtual void operator<<(_Inout_ cursor_out &cursor) const;
///
/// Returns packed size of a configuration
///
/// \returns Size of data when packed (in bytes)
///
virtual size_t get_pk_size() const;
///
/// Unpacks a configuration
///
/// \param[inout] cursor Memory cursor
///
virtual void operator>>(_Inout_ cursor_in &cursor);
///
/// Returns EAP method type of this configuration
///
/// \returns `eap::type_ttls`
///
virtual eap::type_t get_method_id() const;
virtual winstd::eap_type_t get_method_id() const;
///
/// Generates public identity using current configuration and given credentials
///
std::wstring get_public_identity(const credentials_ttls &cred) const;
public:
config *m_inner; ///< Inner authentication configuration
std::unique_ptr<config_method_with_cred> m_inner; ///< Inner authentication configuration
std::wstring m_anonymous_identity; ///< Anonymous identity
};
}
namespace eapserial
{
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::config_ttls &val)
{
pack(cursor, (const eap::config_tls&)val);
if (val.m_inner) {
if (dynamic_cast<eap::config_pap*>(val.m_inner)) {
pack(cursor, eap::type_pap);
pack(cursor, (const eap::config_pap&)*val.m_inner);
} else {
assert(0); // Unsupported inner authentication method type.
pack(cursor, eap::type_undefined);
}
} else
pack(cursor, eap::type_undefined);
}
inline size_t get_pk_size(const eap::config_ttls &val)
{
size_t size_inner;
if (val.m_inner) {
if (dynamic_cast<eap::config_pap*>(val.m_inner)) {
size_inner =
get_pk_size(eap::type_pap) +
get_pk_size((const eap::config_pap&)*val.m_inner);
} else {
size_inner = get_pk_size(eap::type_undefined);
assert(0); // Unsupported inner authentication method type.
}
} else
size_inner = get_pk_size(eap::type_undefined);
return
get_pk_size((const eap::config_tls&)val) +
size_inner;
}
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::config_ttls &val)
{
unpack(cursor, (eap::config_tls&)val);
if (val.m_inner)
delete val.m_inner;
eap::type_t eap_type;
unpack(cursor, eap_type);
switch (eap_type) {
case eap::type_pap:
val.m_inner = new eap::config_pap(val.m_module);
unpack(cursor, (eap::config_pap&)*val.m_inner);
break;
default:
val.m_inner = NULL;
assert(0); // Unsupported inner authentication method type.
}
}
}

View File

@@ -26,39 +26,14 @@ namespace eap
class credentials_ttls;
}
namespace eapserial
{
///
/// Packs a TTLS based method credentials
///
/// \param[inout] cursor Memory cursor
/// \param[in] val Configuration to pack
///
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::credentials_ttls &val);
///
/// Returns packed size of a TTLS based method credentials
///
/// \param[in] val Configuration to pack
///
/// \returns Size of data when packed (in bytes)
///
inline size_t get_pk_size(const eap::credentials_ttls &val);
///
/// Unpacks a TTLS based method credentials
///
/// \param[inout] cursor Memory cursor
/// \param[out] val Configuration to unpack to
///
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::credentials_ttls &val);
}
#pragma once
#include "../../TLS/include/Credentials.h"
#include "../../PAP/include/Credentials.h"
#include <memory>
#include <utility>
namespace eap
{
@@ -68,7 +43,7 @@ namespace eap
///
/// Constructs credentials
///
/// \param[in] mod Reference of the EAP module to use for global services
/// \param[in] mod EAP module to use for global services
///
credentials_ttls(_In_ module &mod);
@@ -119,38 +94,56 @@ namespace eap
///
/// Test credentials if blank
///
/// \returns
/// - \c true if blank
/// - \c false otherwise
///
virtual bool empty() const;
/// \name XML credentials management
/// @{
///
/// Save credentials to XML document
/// Save to XML document
///
/// \param[in] pDoc XML document
/// \param[in] pConfigRoot Suggested root element for saving credentials
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
/// \param[in] pConfigRoot Suggested root element for saving
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const;
virtual void save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const;
///
/// Load credentials from XML document
/// Load from XML document
///
/// \param[in] pConfigRoot Root element for loading credentials
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
/// \param[in] pConfigRoot Root element for loading
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError);
virtual void load(_In_ IXMLDOMNode *pConfigRoot);
/// @}
/// \name BLOB management
/// @{
///
/// Packs a configuration
///
/// \param[inout] cursor Memory cursor
///
virtual void operator<<(_Inout_ cursor_out &cursor) const;
///
/// Returns packed size of a configuration
///
/// \returns Size of data when packed (in bytes)
///
virtual size_t get_pk_size() const;
///
/// Unpacks a configuration
///
/// \param[inout] cursor Memory cursor
///
virtual void operator>>(_Inout_ cursor_in &cursor);
/// \name Storage
/// @{
@@ -158,82 +151,49 @@ namespace eap
/// Save credentials to Windows Credential Manager
///
/// \param[in] pszTargetName The name in Windows Credential Manager to store credentials as
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
///
virtual bool store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError) const;
virtual void store(_In_z_ LPCTSTR pszTargetName) const;
///
/// Retrieve credentials from Windows Credential Manager
///
/// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
///
/// \returns
/// - \c true if succeeded
/// - \c false otherwise. See \p ppEapError for details.
virtual void retrieve(_In_z_ LPCTSTR pszTargetName);
///
virtual bool retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError);
/// Return target suffix for Windows Credential Manager credential name
///
virtual LPCTSTR target_suffix() const;
///
/// Returns credential identity.
///
virtual std::wstring get_identity() const;
/// @}
///
/// Combine credentials in the following order:
///
/// 1. Cached credentials
/// 2. Pre-configured credentials
/// 3. Stored credentials
///
/// \param[in] cred_cached Cached credentials (optional, can be \c NULL)
/// \param[in] cfg Method configuration
/// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from (optional, can be \c NULL)
///
/// \returns
/// - \c true if credentials were set;
/// - \c false otherwise
///
std::pair<source_t, source_t> combine(
_In_ const credentials_ttls *cred_cached,
_In_ const config_method_ttls &cfg,
_In_opt_z_ LPCTSTR pszTargetName);
public:
credentials *m_inner; ///< Inner credentials
std::unique_ptr<credentials> m_inner; ///< Inner credentials
};
}
namespace eapserial
{
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::credentials_ttls &val)
{
pack(cursor, (const eap::credentials_tls&)val);
if (val.m_inner) {
if (dynamic_cast<eap::credentials_pap*>(val.m_inner)) {
pack(cursor, (unsigned char)eap::type_pap);
pack(cursor, (const eap::credentials_pap&)*val.m_inner);
} else {
assert(0); // Unsupported inner authentication method type.
pack(cursor, (unsigned char)0);
}
} else
pack(cursor, (unsigned char)0);
}
inline size_t get_pk_size(const eap::credentials_ttls &val)
{
size_t size_inner = sizeof(unsigned char);
if (val.m_inner) {
if (dynamic_cast<eap::credentials_pap*>(val.m_inner))
size_inner += get_pk_size((const eap::credentials_pap&)*val.m_inner);
else
assert(0); // Unsupported inner authentication method type.
}
return
get_pk_size((const eap::credentials_tls&)val) +
size_inner;
}
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::credentials_ttls &val)
{
unpack(cursor, (eap::credentials_tls&)val);
assert(!val.m_inner);
unsigned char eap_type;
unpack(cursor, eap_type);
switch (eap_type) {
case eap::type_pap:
val.m_inner = new eap::credentials_pap(val.m_module);
unpack(cursor, (eap::credentials_pap&)*val.m_inner);
break;
case 0 : break;
default : assert(0); // Unsupported inner authentication method type.
}
}
}

141
lib/TTLS/include/Method.h Normal file
View File

@@ -0,0 +1,141 @@
/*
Copyright 2015-2016 Amebis
Copyright 2016 GÉANT
This file is part of GÉANTLink.
GÉANTLink is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GÉANTLink is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
*/
namespace eap
{
///
/// EAP-TTLS method
///
class method_ttls;
}
#pragma once
#include "Config.h"
#include "Credentials.h"
#include "../../TLS/include/Method.h"
#include "../../EAPBase/include/Method.h"
namespace eap
{
class method_ttls : public method_tls
{
public:
///
/// EAP-TTLS packet flags
///
/// \sa [Extensible Authentication Protocol Tunneled Transport Layer Security Authenticated Protocol Version 0 (EAP-TTLSv0) (Chapter: 9.1 Packet Format)](https://tools.ietf.org/html/rfc5281#section-9.1)
///
#pragma warning(suppress: 4480)
enum flags_t : unsigned char {
flags_length_incl = method_tls::flags_req_length_incl, ///< Length included
flags_more_frag = method_tls::flags_req_more_frag, ///< More fragments
flags_start = method_tls::flags_req_start, ///< Start
flags_ver_mask = 0x07, ///< Version mask
};
public:
///
/// Constructs an EAP method
///
/// \param[in] mod EAP module to use for global services
/// \param[in] cfg Providers configuration
/// \param[in] cred User credentials
///
method_ttls(_In_ module &module, _In_ config_provider_list &cfg, _In_ credentials_ttls &cred);
///
/// Moves an EAP method
///
/// \param[in] other EAP method to move from
///
method_ttls(_Inout_ method_ttls &&other);
///
/// Moves an EAP method
///
/// \param[in] other EAP method to move from
///
/// \returns Reference to this object
///
method_ttls& operator=(_Inout_ method_ttls &&other);
/// \name Packet processing
/// @{
///
/// Processes a packet received by EAPHost from a supplicant.
///
/// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx)
///
virtual void process_request_packet(
_In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket,
_In_ DWORD dwReceivedPacketSize,
_Inout_ EapPeerMethodOutput *pEapOutput);
///
/// Obtains a response packet from the EAP method.
///
/// \sa [EapPeerGetResponsePacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363610.aspx)
///
virtual void get_response_packet(
_Inout_bytecap_(*dwSendPacketSize) EapPacket *pSendPacket,
_Inout_ DWORD *pdwSendPacketSize);
///
/// Obtains the result of an authentication session from the EAP method.
///
/// \sa [EapPeerGetResult function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363611.aspx)
///
virtual void get_result(
_In_ EapPeerMethodResultReason reason,
_Inout_ EapPeerMethodResult *ppResult);
/// @}
protected:
///
/// Processes an application message
///
/// \param[in] msg Application message data
/// \param[in] size_msg Application message data size
///
virtual void process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg);
///
/// Makes a PAP client message
///
/// \sa [Extensible Authentication Protocol Tunneled Transport Layer Security Authenticated Protocol Version 0 (EAP-TTLSv0) (Chapter 11.2.5. PAP)](https://tools.ietf.org/html/rfc5281#section-11.2.5)
///
/// \returns PAP client message
///
sanitizing_blob make_pap_client() const;
public:
credentials_ttls &m_cred; ///< TTLS credentials
#pragma warning(suppress: 4480)
enum version_t :unsigned char {
version_0 = 0, ///< EAP-TTLS v0
} m_version; ///< EAP-TTLS version
};
}

Some files were not shown because too many files have changed in this diff Show More