From dcdc63fde6148d30f7a6e7de6c6f374b84607bcc Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Tue, 17 May 2016 14:27:43 +0200 Subject: [PATCH] Support for credential management added --- build/WinStd.vcxproj | 1 + build/WinStd.vcxproj.filters | 3 + include/WinStd/Cred.h | 270 +++++++++++++++++++++++++++++++++++ src/StdAfx.h | 1 + 4 files changed, 275 insertions(+) create mode 100644 include/WinStd/Cred.h diff --git a/build/WinStd.vcxproj b/build/WinStd.vcxproj index 1e8085c9..09e03c49 100644 --- a/build/WinStd.vcxproj +++ b/build/WinStd.vcxproj @@ -82,6 +82,7 @@ + diff --git a/build/WinStd.vcxproj.filters b/build/WinStd.vcxproj.filters index 6136d96a..4080982b 100644 --- a/build/WinStd.vcxproj.filters +++ b/build/WinStd.vcxproj.filters @@ -49,5 +49,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/include/WinStd/Cred.h b/include/WinStd/Cred.h new file mode 100644 index 00000000..f968c261 --- /dev/null +++ b/include/WinStd/Cred.h @@ -0,0 +1,270 @@ +/* + Copyright 1991-2016 Amebis + Copyright 2016 GÉANT + + This file is part of WinStd. + + Setup 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. + + Setup 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 Setup. If not, see . +*/ + +#include "Common.h" + +#include + +#include + +namespace winstd +{ + template struct CredFree_delete; + template struct CredFree_delete<_Ty[]>; + class credential; +} + +template inline BOOL CredProtectA(_In_ BOOL fAsSelf, _In_ LPCSTR pszCredentials, _In_ DWORD cchCredentials, _Out_ std::basic_string<_Elem, _Traits, _Ax> &sProtectedCredentials, _Out_ CRED_PROTECTION_TYPE *ProtectionType); +template inline BOOL CredProtectW(_In_ BOOL fAsSelf, _In_ LPCWSTR pszCredentials, _In_ DWORD cchCredentials, _Out_ std::basic_string<_Elem, _Traits, _Ax> &sProtectedCredentials, _Out_ CRED_PROTECTION_TYPE *ProtectionType); +template inline BOOL CredUnprotectA(_In_ BOOL fAsSelf, _In_ LPCSTR pszProtectedCredentials, _In_ DWORD cchCredentials, _Out_ std::basic_string<_Elem, _Traits, _Ax> &sCredentials); +template inline BOOL CredUnprotectW(_In_ BOOL fAsSelf, _In_ LPCWSTR pszProtectedCredentials, _In_ DWORD cchCredentials, _Out_ std::basic_string<_Elem, _Traits, _Ax> &sCredentials); + +#pragma once + + +namespace winstd +{ + /// \addtogroup ATLCryptoAPI + /// @{ + + /// + /// Deleter for unique_ptr using CredFree + /// + template struct CredFree_delete + { + typedef CredFree_delete<_Ty> _Myt; + + /// + /// Default construct + /// + CredFree_delete() {} + + /// + /// Construct from another CredFree_delete + /// + template CredFree_delete(const CredFree_delete<_Ty2>&) {} + + /// + /// Delete a pointer + /// + void operator()(_Ty *_Ptr) const + { + CredFree(_Ptr); + } + }; + + + /// + /// Deleter for unique_ptr to array of unknown size using CredFree + /// + template struct CredFree_delete<_Ty[]> + { + typedef CredFree_delete<_Ty> _Myt; + + /// + /// Default construct + /// + CredFree_delete() {} + + /// + /// Delete a pointer + /// + void operator()(_Ty *_Ptr) const + { + CredFree(_Ptr); + } + + /// + /// Delete a pointer of another type + /// + template + void operator()(_Other *) const + { + CredFree(_Ptr); + } + }; + + + /// + /// PCREDENTIAL wrapper class + /// + class credential : public handle + { + public: + /// + /// Closes the credential. + /// + /// \sa [CredFree function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa374796.aspx) + /// + virtual ~credential() + { + if (m_h) + CredFree(m_h); + } + + protected: + /// + /// Closes the credential. + /// + /// \sa [CredFree function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa374796.aspx) + /// + virtual void free_internal() + { + CredFree(m_h); + } + }; + + /// @} +} + + +/// +/// \defgroup WinStdCryptoAPI Cryptography API +/// Integrates WinStd classes with Microsoft Cryptography API +/// +/// @{ + +inline BOOL CredEnumerate(_In_ LPCTSTR Filter, _In_ DWORD Flags, _Out_ DWORD *Count, _Out_ std::unique_ptr > &cCredentials) +{ + PCREDENTIAL *pCredentials; + if (CredEnumerate(Filter, Flags, Count, &pCredentials)) { + cCredentials.swap(std::unique_ptr >(pCredentials)); + return TRUE; + } else + return FALSE; +} + + +/// +/// Encrypts the specified credentials so that only the current security context can decrypt them. +/// +/// \sa [CredProtect function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa374803.aspx) +/// +template +inline BOOL CredProtectA(_In_ BOOL fAsSelf, _In_ LPCSTR pszCredentials, _In_ DWORD cchCredentials, _Out_ std::basic_string<_Elem, _Traits, _Ax> &sProtectedCredentials, _Out_ CRED_PROTECTION_TYPE *ProtectionType) +{ + _Elem buf[WINSTD_STACK_BUFFER_BYTES/sizeof(_Elem)]; + DWORD dwSize = _countof(buf); + + // Try with the stack buffer first. + if (CredProtectA(fAsSelf, (LPSTR)pszCredentials, cchCredentials, buf, &dwSize, ProtectionType)) { + // Copy from stack. + sProtectedCredentials.assign(buf, dwSize - 1); + return TRUE; + } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + // Allocate on heap and retry. + auto buf = std::unique_ptr<_Elem[]>(new _Elem[dwSize]); + if (CredProtectA(fAsSelf, (LPSTR)pszCredentials, cchCredentials, buf.get(), &dwSize, ProtectionType)) { + sProtectedCredentials.assign(buf.get(), dwSize - 1); + return TRUE; + } + } + + return FALSE; +} + + +/// +/// Encrypts the specified credentials so that only the current security context can decrypt them. +/// +/// \sa [CredProtect function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa374803.aspx) +/// +template +inline BOOL CredProtectW(_In_ BOOL fAsSelf, _In_ LPCWSTR pszCredentials, _In_ DWORD cchCredentials, _Out_ std::basic_string<_Elem, _Traits, _Ax> &sProtectedCredentials, _Out_ CRED_PROTECTION_TYPE *ProtectionType) +{ + _Elem buf[WINSTD_STACK_BUFFER_BYTES/sizeof(_Elem)]; + DWORD dwSize = _countof(buf); + + // Try with the stack buffer first. + if (CredProtectW(fAsSelf, (LPWSTR)pszCredentials, cchCredentials, buf, &dwSize, ProtectionType)) { + // Copy from stack. + sProtectedCredentials.assign(buf, dwSize - 1); + return TRUE; + } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + // Allocate on heap and retry. + auto buf = std::unique_ptr<_Elem[]>(new _Elem[dwSize]); + if (CredProtectW(fAsSelf, (LPWSTR)pszCredentials, cchCredentials, buf.get(), &dwSize, ProtectionType)) { + sProtectedCredentials.assign(buf.get(), dwSize - 1); + return TRUE; + } + } + + return FALSE; +} + + +/// +/// Decrypts credentials that were previously encrypted by using the CredProtect function. +/// +/// \sa [CredUnprotect function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375186.aspx) +/// +template +inline BOOL CredUnprotectA(_In_ BOOL fAsSelf, _In_ LPCSTR pszProtectedCredentials, _In_ DWORD cchCredentials, _Out_ std::basic_string<_Elem, _Traits, _Ax> &sCredentials) +{ + _Elem buf[WINSTD_STACK_BUFFER_BYTES/sizeof(_Elem)]; + DWORD dwSize = _countof(buf); + + // Try with the stack buffer first. + if (CredUnprotectA(fAsSelf, (LPSTR)pszProtectedCredentials, cchCredentials, buf, &dwSize)) { + // Copy from stack. + sCredentials.assign(buf, dwSize); + return TRUE; + } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + // Allocate on heap and retry. + auto buf = std::unique_ptr<_Elem[]>(new _Elem[dwSize]); + if (CredUnprotectA(fAsSelf, (LPSTR)pszProtectedCredentials, cchCredentials, buf.get(), &dwSize)) { + sCredentials.assign(buf.get(), dwSize); + return TRUE; + } + } + + return FALSE; +} + + +/// +/// Decrypts credentials that were previously encrypted by using the CredProtect function. +/// +/// \sa [CredUnprotect function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375186.aspx) +/// +template +inline BOOL CredUnprotectW(_In_ BOOL fAsSelf, _In_ LPCWSTR pszProtectedCredentials, _In_ DWORD cchCredentials, _Out_ std::basic_string<_Elem, _Traits, _Ax> &sCredentials) +{ + _Elem buf[WINSTD_STACK_BUFFER_BYTES/sizeof(_Elem)]; + DWORD dwSize = _countof(buf); + + // Try with the stack buffer first. + if (CredUnprotectW(fAsSelf, (LPWSTR)pszProtectedCredentials, cchCredentials, buf, &dwSize)) { + // Copy from stack. + sCredentials.assign(buf, dwSize); + return TRUE; + } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + // Allocate on heap and retry. + auto buf = std::unique_ptr<_Elem[]>(new _Elem[dwSize]); + if (CredUnprotectW(fAsSelf, (LPWSTR)pszProtectedCredentials, cchCredentials, buf.get(), &dwSize)) { + sCredentials.assign(buf.get(), dwSize); + return TRUE; + } + } + + return FALSE; +} + +/// @} diff --git a/src/StdAfx.h b/src/StdAfx.h index 56836c6b..82383df9 100644 --- a/src/StdAfx.h +++ b/src/StdAfx.h @@ -21,6 +21,7 @@ #pragma once #include "../include/WinStd/Base64.h" +#include "../include/WinStd/Cred.h" #include "../include/WinStd/Crypt.h" #include "../include/WinStd/EAP.h" #include "../include/WinStd/Common.h"