/* 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 . */ #define IDR_EAP_KEY_PUBLIC 1 #define IDR_EAP_KEY_PRIVATE 2 #ifndef EAP_ENCRYPT_BLOBS #define EAP_ENCRYPT_BLOBS 1 #endif #define _HOST_LOW_ENDIAN #if !defined(RC_INVOKED) && !defined(MIDL_PASS) #include #include #include #include #include #include #include #include namespace eap { /// /// Output BLOB cursor /// struct cursor_out; /// /// Input BLOB cursor /// struct cursor_in; /// /// Sanitizing dynamically allocated BLOB /// typedef std::vector > sanitizing_blob; /// /// Diameter AVP flags /// enum diameter_avp_flags_t; /// /// Diameter AVP /// struct diameter_avp; } /// /// Packs a boolean /// /// \param[inout] cursor Memory cursor /// \param[in] val Variable with data to pack /// inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const bool &val); /// /// Returns packed size of a boolean /// /// \param[in] val Data to pack /// /// \returns Size of data when packed (in bytes) /// inline size_t pksizeof(_In_ const bool &val); /// /// Unpacks a boolean /// /// \param[inout] cursor Memory cursor /// \param[out] val Variable to receive unpacked value /// inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ bool &val); /// /// Packs a byte /// /// \param[inout] cursor Memory cursor /// \param[in] val Variable with data to pack /// inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const unsigned char &val); /// /// Returns packed size of a byte /// /// \param[in] val Data to pack /// /// \returns Size of data when packed (in bytes) /// inline size_t pksizeof(_In_ const unsigned char &val); /// /// Unpacks a byte /// /// \param[inout] cursor Memory cursor /// \param[out] val Variable to receive unpacked value /// inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ unsigned char &val); /// /// Packs an unsigned int /// /// \param[inout] cursor Memory cursor /// \param[in] val Variable with data to pack /// inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const unsigned int &val); /// /// Returns packed size of an unsigned int /// /// \param[in] val Data to pack /// /// \returns Size of data when packed (in bytes) /// inline size_t pksizeof(_In_ const unsigned int &val); /// /// Unpacks an unsigned int /// /// \param[inout] cursor Memory cursor /// \param[out] val Variable to receive unpacked value /// inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ unsigned int &val); #ifdef _WIN64 /// /// Packs a size_t /// /// \param[inout] cursor Memory cursor /// \param[in] val Variable with data to pack /// inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const size_t &val); /// /// Returns packed size of a size_t /// /// \param[in] val Data to pack /// /// \returns Size of data when packed (in bytes) /// inline size_t pksizeof(_In_ const size_t &val); /// /// Unpacks a size_t /// /// \param[inout] cursor Memory cursor /// \param[out] val Variable to receive unpacked value /// inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ size_t &val); #endif /// /// Packs a string /// /// \param[inout] cursor Memory cursor /// \param[in] val String to pack /// template inline void operator<<(_Inout_ eap::cursor_out &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 inline size_t pksizeof(const std::basic_string<_Elem, _Traits, _Ax> &val); /// /// Unpacks a string /// /// \param[inout] cursor Memory cursor /// \param[out] val String to unpack to /// template inline void operator>>(_Inout_ eap::cursor_in &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 inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const std::basic_string &val); /// /// Returns packed size of a wide string /// /// \param[in] val String to pack /// /// \returns Size of data when packed (in bytes) /// template inline size_t pksizeof(const std::basic_string &val); /// /// Unpacks a wide string /// /// \param[inout] cursor Memory cursor /// \param[out] val String to unpack to /// template inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ std::basic_string &val); /// /// Packs a vector /// /// \param[inout] cursor Memory cursor /// \param[in] val Vector to pack /// template inline void operator<<(_Inout_ eap::cursor_out &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 inline size_t pksizeof(const std::vector<_Ty, _Ax> &val); /// /// Unpacks a vector /// /// \param[inout] cursor Memory cursor /// \param[out] val Vector to unpack to /// template inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ std::vector<_Ty, _Ax> &val); /// /// Packs a list /// /// \param[inout] cursor Memory cursor /// \param[in] val List to pack /// template inline void operator<<(_Inout_ eap::cursor_out &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 inline size_t pksizeof(const std::list<_Ty, _Ax> &val); /// /// Unpacks a list /// /// \param[inout] cursor Memory cursor /// \param[out] val List to unpack to /// template inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ std::list<_Ty, _Ax> &val); /// /// Packs a std::unique_ptr /// /// \param[inout] cursor Memory cursor /// \param[in] val std::unique_ptr to pack /// template inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const std::unique_ptr<_Ty, _Dx> &val); /// /// Returns packed size of a std::unique_ptr /// /// \param[in] val std::unique_ptr to pack /// /// \returns Size of data when packed (in bytes) /// template inline size_t pksizeof(const std::unique_ptr<_Ty, _Dx> &val); ///// ///// Unpacks a std::unique_ptr ///// ///// \note Not generally unpackable, since we do not know, how to create a new instance of unique_ptr. ///// ///// \param[inout] cursor Memory cursor ///// \param[out] val std::unique_ptr to unpack to ///// //template inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ std::unique_ptr<_Ty, _Dx> &val); /// /// Packs a certificate context /// /// \param[inout] cursor Memory cursor /// \param[in] val Certificate context to pack /// inline void operator<<(_Inout_ eap::cursor_out &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 pksizeof(const winstd::cert_context &val); /// /// Unpacks a certificate context /// /// \param[inout] cursor Memory cursor /// \param[out] val Certificate context to unpack to /// inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ winstd::cert_context &val); /// /// Packs an EAP method type /// /// \param[inout] cursor Memory cursor /// \param[in] val EAP method type to pack /// inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const winstd::eap_type_t &val); /// /// Returns packed size of an EAP method type /// /// \param[in] val EAP method type to pack /// /// \returns Size of data when packed (in bytes) /// inline size_t pksizeof(const winstd::eap_type_t &val); /// /// Unpacks an EAP method type /// /// \param[inout] cursor Memory cursor /// \param[out] val EAP method type to unpack to /// inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ winstd::eap_type_t &val); #ifndef htonll /// /// Convert host converts an unsigned __int64 from host to TCP/IP network byte order. /// /// \param[in] val A 64-bit unsigned number in host byte order. /// /// \returns The value in TCP/IP's network byte order. /// inline unsigned __int64 htonll(unsigned __int64 val); #endif #pragma once namespace eap { struct cursor_out { typedef unsigned char *ptr_type; ptr_type ptr; ///< Pointer to first data unwritten ptr_type ptr_end; ///< Pointer to the end of available memory }; struct cursor_in { typedef const unsigned char *ptr_type; ptr_type ptr; ///< Pointer to first data unread ptr_type ptr_end; ///< Pointer to the end of BLOB }; #pragma warning(suppress: 4480) enum diameter_avp_flags_t : unsigned char { diameter_avp_flag_vendor = 0x80, ///< Vendor-ID present diameter_avp_flag_mandatory = 0x40, ///< Mandatory }; #pragma pack(push) #pragma pack(1) struct diameter_avp { unsigned char code[4]; ///< AVP Code unsigned char flags; ///< AVP Flags unsigned char length[3]; ///< AVP Length #pragma warning(push) #pragma warning(disable: 4201) union { struct { unsigned char vendor[4]; ///< Vendor-ID unsigned char v_data[1]; ///< Data (when Vendor-ID present) }; unsigned char data[1]; ///< Data (when Vendor-ID absent) }; #pragma warning(pop) }; #pragma pack(pop) } inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const bool &val) { eap::cursor_out::ptr_type ptr_end = cursor.ptr + 1; assert(ptr_end <= cursor.ptr_end); *cursor.ptr = val ? 1 : 0; cursor.ptr = ptr_end; } inline size_t pksizeof(_In_ const bool &val) { UNREFERENCED_PARAMETER(val); return sizeof(unsigned char); } inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ bool &val) { eap::cursor_in::ptr_type ptr_end = cursor.ptr + 1; assert(ptr_end <= cursor.ptr_end); val = *cursor.ptr ? true : false; cursor.ptr = ptr_end; } inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const unsigned char &val) { eap::cursor_out::ptr_type ptr_end = cursor.ptr + 1; assert(ptr_end <= cursor.ptr_end); *cursor.ptr = val; cursor.ptr = ptr_end; } inline size_t pksizeof(_In_ const unsigned char &val) { UNREFERENCED_PARAMETER(val); return sizeof(unsigned char); } inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ unsigned char &val) { eap::cursor_in::ptr_type ptr_end = cursor.ptr + 1; assert(ptr_end <= cursor.ptr_end); val = *cursor.ptr; cursor.ptr = ptr_end; } inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const unsigned int &val) { eap::cursor_out::ptr_type ptr_end = cursor.ptr + sizeof(unsigned int); assert(ptr_end <= cursor.ptr_end); *(unsigned int*)cursor.ptr = val; cursor.ptr = ptr_end; } inline size_t pksizeof(_In_ const unsigned int &val) { UNREFERENCED_PARAMETER(val); return sizeof(unsigned int); } inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ unsigned int &val) { eap::cursor_in::ptr_type ptr_end = cursor.ptr + sizeof(unsigned int); assert(ptr_end <= cursor.ptr_end); val = *(unsigned int*)cursor.ptr; cursor.ptr = ptr_end; } #ifdef _WIN64 inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const size_t &val) { eap::cursor_out::ptr_type ptr_end = cursor.ptr + sizeof(size_t); assert(ptr_end <= cursor.ptr_end); *(size_t*)cursor.ptr = val; cursor.ptr = ptr_end; } inline size_t pksizeof(_In_ const size_t &val) { UNREFERENCED_PARAMETER(val); return sizeof(size_t); } inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ size_t &val) { eap::cursor_in::ptr_type ptr_end = cursor.ptr + sizeof(size_t); assert(ptr_end <= cursor.ptr_end); val = *(size_t*)cursor.ptr; cursor.ptr = ptr_end; } #endif template inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const std::basic_string<_Elem, _Traits, _Ax> &val) { std::basic_string<_Elem, _Traits, _Ax>::size_type count = val.length(); assert(strlen(val.c_str()) == count); // String should not contain zero terminators. size_t size = sizeof(_Elem)*(count + 1); eap::cursor_out::ptr_type ptr_end = cursor.ptr + size; assert(ptr_end <= cursor.ptr_end); memcpy(cursor.ptr, (const _Elem*)val.c_str(), size); cursor.ptr = ptr_end; } template inline size_t pksizeof(const std::basic_string<_Elem, _Traits, _Ax> &val) { return sizeof(_Elem)*(val.length() + 1); } template inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ std::basic_string<_Elem, _Traits, _Ax> &val) { size_t count_max = cursor.ptr_end - cursor.ptr; std::basic_string<_Elem, _Traits, _Ax>::size_type count = strnlen((const _Elem*&)cursor.ptr, count_max); assert(count < count_max); // String should be zero terminated. val.assign((const _Elem*&)cursor.ptr, count); cursor.ptr += sizeof(_Elem)*(count + 1); } template inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const std::basic_string &val) { std::string val_utf8; WideCharToMultiByte(CP_UTF8, 0, val.c_str(), (int)val.length(), val_utf8, NULL, NULL); cursor << val_utf8; } template inline size_t pksizeof(const std::basic_string &val) { return sizeof(char)*(WideCharToMultiByte(CP_UTF8, 0, val.c_str(), (int)val.length(), NULL, 0, NULL, NULL) + 1); } template inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ std::basic_string &val) { std::string val_utf8; cursor >> val_utf8; MultiByteToWideChar(CP_UTF8, 0, val_utf8.c_str(), (int)val_utf8.length(), val); } template inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const std::vector<_Ty, _Ax> &val) { std::vector<_Ty, _Ax>::size_type count = val.size(); cursor << count; // 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++) cursor << val[i]; } template inline size_t pksizeof(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. std::vector<_Ty, _Ax>::size_type count = val.size(); size_t size = pksizeof(count); for (std::vector<_Ty, _Ax>::size_type i = 0; i < count; i++) size += pksizeof(val[i]); return size; } template inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ std::vector<_Ty, _Ax> &val) { std::vector<_Ty, _Ax>::size_type count; cursor >> count; // 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; cursor >> el; val.push_back(el); } } template inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const std::list<_Ty, _Ax> &val) { std::list<_Ty, _Ax>::size_type count = val.size(); cursor << count; // 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) cursor << *i; } template inline size_t pksizeof(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. std::list<_Ty, _Ax>::size_type count = val.size(); size_t size = pksizeof(count); for (std::list<_Ty, _Ax>::const_iterator i = val.cbegin(), i_end = val.cend(); i != i_end; ++i) size += pksizeof(*i); return size; } template inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ std::list<_Ty, _Ax> &val) { std::list<_Ty, _Ax>::size_type count; cursor >> count; // 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; cursor >> el; val.push_back(el); } } template inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const std::unique_ptr<_Ty, _Dx> &val) { if (val) { cursor << true; cursor << *val; } else cursor << false; } template inline size_t pksizeof(const std::unique_ptr<_Ty, _Dx> &val) { return val ? pksizeof(true) + pksizeof(*val) : pksizeof(false); } inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const winstd::cert_context &val) { if (val) { cursor << (unsigned int)val->dwCertEncodingType; cursor << (unsigned int)val->cbCertEncoded ; eap::cursor_out::ptr_type ptr_end = cursor.ptr + val->cbCertEncoded; assert(ptr_end <= cursor.ptr_end); memcpy(cursor.ptr, val->pbCertEncoded, val->cbCertEncoded); cursor.ptr = ptr_end; } else { cursor << (unsigned int)0; cursor << (unsigned int)0; } } inline size_t pksizeof(const winstd::cert_context &val) { return val ? pksizeof((unsigned int)val->dwCertEncodingType) + pksizeof((unsigned int)val->cbCertEncoded ) + val->cbCertEncoded : pksizeof((unsigned int)0) + pksizeof((unsigned int)0); } inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ winstd::cert_context &val) { DWORD dwCertEncodingType; cursor >> (unsigned int&)dwCertEncodingType; DWORD dwCertEncodedSize; cursor >> (unsigned int&)dwCertEncodedSize; if (dwCertEncodedSize) { eap::cursor_in::ptr_type ptr_end = cursor.ptr + dwCertEncodedSize; assert(ptr_end <= cursor.ptr_end); val.create(dwCertEncodingType, (BYTE*)cursor.ptr, dwCertEncodedSize); cursor.ptr = ptr_end; } else val.free(); } inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const winstd::eap_type_t &val) { cursor << (unsigned char)val; } inline size_t pksizeof(_In_ const winstd::eap_type_t &val) { return pksizeof((unsigned char)val); } inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ winstd::eap_type_t &val) { cursor >> (unsigned char&)val; } #ifndef htonll inline unsigned __int64 htonll(unsigned __int64 val) { return (unsigned __int64)htonl((u_long)((val >> 32) & 0xffffffff)) | (unsigned __int64)htonl((u_long)((val ) & 0xffffffff)) << 32; } #endif #endif