summaryrefslogtreecommitdiff
path: root/subversion/libsvn_subr/win32_crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_subr/win32_crypto.c')
-rw-r--r--subversion/libsvn_subr/win32_crypto.c310
1 files changed, 177 insertions, 133 deletions
diff --git a/subversion/libsvn_subr/win32_crypto.c b/subversion/libsvn_subr/win32_crypto.c
index 016bba9..e16866a 100644
--- a/subversion/libsvn_subr/win32_crypto.c
+++ b/subversion/libsvn_subr/win32_crypto.c
@@ -21,6 +21,9 @@
* ====================================================================
*/
+/* prevent "empty compilation unit" warning on e.g. UNIX */
+typedef int win32_crypto__dummy;
+
/* ==================================================================== */
#if defined(WIN32) && !defined(__MINGW32__)
@@ -28,32 +31,85 @@
/*** Includes. ***/
#include <apr_pools.h>
+#include <apr_base64.h>
#include "svn_auth.h"
#include "svn_error.h"
+#include "svn_hash.h"
#include "svn_utf.h"
#include "svn_config.h"
#include "svn_user.h"
+#include "svn_base64.h"
#include "private/svn_auth_private.h"
#include "svn_private_config.h"
#include <wincrypt.h>
-#include <apr_base64.h>
-
-/*-----------------------------------------------------------------------*/
-/* Windows simple provider, encrypts the password on Win2k and later. */
-/*-----------------------------------------------------------------------*/
+
/* The description string that's combined with unencrypted data by the
Windows CryptoAPI. Used during decryption to verify that the
encrypted data were valid. */
static const WCHAR description[] = L"auth_svn.simple.wincrypt";
+
+/* Return a copy of ORIG, encrypted using the Windows CryptoAPI and
+ allocated from POOL. */
+const svn_string_t *
+encrypt_data(const svn_string_t *orig,
+ apr_pool_t *pool)
+{
+ DATA_BLOB blobin;
+ DATA_BLOB blobout;
+ const svn_string_t *crypted = NULL;
+
+ blobin.cbData = orig->len;
+ blobin.pbData = (BYTE *)orig->data;
+ if (CryptProtectData(&blobin, description, NULL, NULL, NULL,
+ CRYPTPROTECT_UI_FORBIDDEN, &blobout))
+ {
+ crypted = svn_string_ncreate((const char *)blobout.pbData,
+ blobout.cbData, pool);
+ LocalFree(blobout.pbData);
+ }
+ return crypted;
+}
+
+/* Return a copy of CRYPTED, decrypted using the Windows CryptoAPI and
+ allocated from POOL. */
+const svn_string_t *
+decrypt_data(const svn_string_t *crypted,
+ apr_pool_t *pool)
+{
+ DATA_BLOB blobin;
+ DATA_BLOB blobout;
+ LPWSTR descr;
+ const svn_string_t *orig = NULL;
+
+ blobin.cbData = crypted->len;
+ blobin.pbData = (BYTE *)crypted->data;
+ if (CryptUnprotectData(&blobin, &descr, NULL, NULL, NULL,
+ CRYPTPROTECT_UI_FORBIDDEN, &blobout))
+ {
+ if (0 == lstrcmpW(descr, description))
+ orig = svn_string_ncreate((const char *)blobout.pbData,
+ blobout.cbData, pool);
+ LocalFree(blobout.pbData);
+ LocalFree(descr);
+ }
+ return orig;
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* Windows simple provider, encrypts the password on Win2k and later. */
+/*-----------------------------------------------------------------------*/
+
/* Implementation of svn_auth__password_set_t that encrypts
the incoming password using the Windows CryptoAPI. */
-static svn_boolean_t
-windows_password_encrypter(apr_hash_t *creds,
+static svn_error_t *
+windows_password_encrypter(svn_boolean_t *done,
+ apr_hash_t *creds,
const char *realmstring,
const char *username,
const char *in,
@@ -61,32 +117,26 @@ windows_password_encrypter(apr_hash_t *creds,
svn_boolean_t non_interactive,
apr_pool_t *pool)
{
- DATA_BLOB blobin;
- DATA_BLOB blobout;
- svn_boolean_t crypted;
+ const svn_string_t *coded;
- blobin.cbData = strlen(in);
- blobin.pbData = (BYTE*) in;
- crypted = CryptProtectData(&blobin, description, NULL, NULL, NULL,
- CRYPTPROTECT_UI_FORBIDDEN, &blobout);
- if (crypted)
+ coded = encrypt_data(svn_string_create(in, pool), pool);
+ if (coded)
{
- char *coded = apr_palloc(pool, apr_base64_encode_len(blobout.cbData));
- apr_base64_encode(coded, (const char*)blobout.pbData, blobout.cbData);
- crypted = svn_auth__simple_password_set(creds, realmstring, username,
- coded, parameters,
- non_interactive, pool);
- LocalFree(blobout.pbData);
+ coded = svn_base64_encode_string2(coded, FALSE, pool);
+ SVN_ERR(svn_auth__simple_password_set(done, creds, realmstring, username,
+ coded->data, parameters,
+ non_interactive, pool));
}
- return crypted;
+ return SVN_NO_ERROR;
}
/* Implementation of svn_auth__password_get_t that decrypts
the incoming password using the Windows CryptoAPI and verifies its
validity. */
-static svn_boolean_t
-windows_password_decrypter(const char **out,
+static svn_error_t *
+windows_password_decrypter(svn_boolean_t *done,
+ const char **out,
apr_hash_t *creds,
const char *realmstring,
const char *username,
@@ -94,32 +144,26 @@ windows_password_decrypter(const char **out,
svn_boolean_t non_interactive,
apr_pool_t *pool)
{
- DATA_BLOB blobin;
- DATA_BLOB blobout;
- LPWSTR descr;
- svn_boolean_t decrypted;
- char *in;
-
- if (!svn_auth__simple_password_get(&in, creds, realmstring, username,
- parameters, non_interactive, pool))
- return FALSE;
-
- blobin.cbData = strlen(in);
- blobin.pbData = apr_palloc(pool, apr_base64_decode_len(in));
- apr_base64_decode((char*)blobin.pbData, in);
- decrypted = CryptUnprotectData(&blobin, &descr, NULL, NULL, NULL,
- CRYPTPROTECT_UI_FORBIDDEN, &blobout);
- if (decrypted)
+ const svn_string_t *orig;
+ const char *in;
+
+ SVN_ERR(svn_auth__simple_password_get(done, &in, creds, realmstring, username,
+ parameters, non_interactive, pool));
+ if (!*done)
+ return SVN_NO_ERROR;
+
+ orig = svn_base64_decode_string(svn_string_create(in, pool), pool);
+ orig = decrypt_data(orig, pool);
+ if (orig)
{
- if (0 == lstrcmpW(descr, description))
- *out = apr_pstrndup(pool, (const char*)blobout.pbData, blobout.cbData);
- else
- decrypted = FALSE;
- LocalFree(blobout.pbData);
- LocalFree(descr);
+ *out = orig->data;
+ *done = TRUE;
}
-
- return decrypted;
+ else
+ {
+ *done = FALSE;
+ }
+ return SVN_NO_ERROR;
}
/* Get cached encrypted credentials from the simple provider's cache. */
@@ -131,14 +175,14 @@ windows_simple_first_creds(void **credentials,
const char *realmstring,
apr_pool_t *pool)
{
- return svn_auth__simple_first_creds_helper(credentials,
- iter_baton,
- provider_baton,
- parameters,
- realmstring,
- windows_password_decrypter,
- SVN_AUTH__WINCRYPT_PASSWORD_TYPE,
- pool);
+ return svn_auth__simple_creds_cache_get(credentials,
+ iter_baton,
+ provider_baton,
+ parameters,
+ realmstring,
+ windows_password_decrypter,
+ SVN_AUTH__WINCRYPT_PASSWORD_TYPE,
+ pool);
}
/* Save encrypted credentials to the simple provider's cache. */
@@ -150,13 +194,13 @@ windows_simple_save_creds(svn_boolean_t *saved,
const char *realmstring,
apr_pool_t *pool)
{
- return svn_auth__simple_save_creds_helper(saved, credentials,
- provider_baton,
- parameters,
- realmstring,
- windows_password_encrypter,
- SVN_AUTH__WINCRYPT_PASSWORD_TYPE,
- pool);
+ return svn_auth__simple_creds_cache_set(saved, credentials,
+ provider_baton,
+ parameters,
+ realmstring,
+ windows_password_encrypter,
+ SVN_AUTH__WINCRYPT_PASSWORD_TYPE,
+ pool);
}
static const svn_auth_provider_t windows_simple_provider = {
@@ -186,8 +230,9 @@ svn_auth_get_windows_simple_provider(svn_auth_provider_object_t **provider,
/* Implementation of svn_auth__password_set_t that encrypts
the incoming password using the Windows CryptoAPI. */
-static svn_boolean_t
-windows_ssl_client_cert_pw_encrypter(apr_hash_t *creds,
+static svn_error_t *
+windows_ssl_client_cert_pw_encrypter(svn_boolean_t *done,
+ apr_hash_t *creds,
const char *realmstring,
const char *username,
const char *in,
@@ -195,32 +240,27 @@ windows_ssl_client_cert_pw_encrypter(apr_hash_t *creds,
svn_boolean_t non_interactive,
apr_pool_t *pool)
{
- DATA_BLOB blobin;
- DATA_BLOB blobout;
- svn_boolean_t crypted;
+ const svn_string_t *coded;
- blobin.cbData = strlen(in);
- blobin.pbData = (BYTE*) in;
- crypted = CryptProtectData(&blobin, description, NULL, NULL, NULL,
- CRYPTPROTECT_UI_FORBIDDEN, &blobout);
- if (crypted)
+ coded = encrypt_data(svn_string_create(in, pool), pool);
+ if (coded)
{
- char *coded = apr_palloc(pool, apr_base64_encode_len(blobout.cbData));
- apr_base64_encode(coded, (const char*)blobout.pbData, blobout.cbData);
- crypted = svn_auth__ssl_client_cert_pw_set(creds, realmstring, username,
- coded, parameters,
- non_interactive, pool);
- LocalFree(blobout.pbData);
+ coded = svn_base64_encode_string2(coded, FALSE, pool);
+ SVN_ERR(svn_auth__ssl_client_cert_pw_set(done, creds, realmstring,
+ username, coded->data,
+ parameters, non_interactive,
+ pool));
}
- return crypted;
+ return SVN_NO_ERROR;
}
/* Implementation of svn_auth__password_get_t that decrypts
the incoming password using the Windows CryptoAPI and verifies its
validity. */
-static svn_boolean_t
-windows_ssl_client_cert_pw_decrypter(const char **out,
+static svn_error_t *
+windows_ssl_client_cert_pw_decrypter(svn_boolean_t *done,
+ const char **out,
apr_hash_t *creds,
const char *realmstring,
const char *username,
@@ -228,32 +268,27 @@ windows_ssl_client_cert_pw_decrypter(const char **out,
svn_boolean_t non_interactive,
apr_pool_t *pool)
{
- DATA_BLOB blobin;
- DATA_BLOB blobout;
- LPWSTR descr;
- svn_boolean_t decrypted;
- char *in;
-
- if (!svn_auth__ssl_client_cert_pw_get(&in, creds, realmstring, username,
- parameters, non_interactive, pool))
- return FALSE;
-
- blobin.cbData = strlen(in);
- blobin.pbData = apr_palloc(pool, apr_base64_decode_len(in));
- apr_base64_decode((char*)blobin.pbData, in);
- decrypted = CryptUnprotectData(&blobin, &descr, NULL, NULL, NULL,
- CRYPTPROTECT_UI_FORBIDDEN, &blobout);
- if (decrypted)
+ const svn_string_t *orig;
+ const char *in;
+
+ SVN_ERR(svn_auth__ssl_client_cert_pw_get(done, &in, creds, realmstring,
+ username, parameters,
+ non_interactive, pool));
+ if (!*done)
+ return SVN_NO_ERROR;
+
+ orig = svn_base64_decode_string(svn_string_create(in, pool), pool);
+ orig = decrypt_data(orig, pool);
+ if (orig)
{
- if (0 == lstrcmpW(descr, description))
- *out = apr_pstrndup(pool, (const char*)blobout.pbData, blobout.cbData);
- else
- decrypted = FALSE;
- LocalFree(blobout.pbData);
- LocalFree(descr);
+ *out = orig->data;
+ *done = TRUE;
}
-
- return decrypted;
+ else
+ {
+ *done = FALSE;
+ }
+ return SVN_NO_ERROR;
}
/* Get cached encrypted credentials from the simple provider's cache. */
@@ -265,15 +300,10 @@ windows_ssl_client_cert_pw_first_creds(void **credentials,
const char *realmstring,
apr_pool_t *pool)
{
- return svn_auth__ssl_client_cert_pw_file_first_creds_helper
- (credentials,
- iter_baton,
- provider_baton,
- parameters,
- realmstring,
- windows_ssl_client_cert_pw_decrypter,
- SVN_AUTH__WINCRYPT_PASSWORD_TYPE,
- pool);
+ return svn_auth__ssl_client_cert_pw_cache_get(
+ credentials, iter_baton, provider_baton, parameters, realmstring,
+ windows_ssl_client_cert_pw_decrypter,
+ SVN_AUTH__WINCRYPT_PASSWORD_TYPE, pool);
}
/* Save encrypted credentials to the simple provider's cache. */
@@ -285,15 +315,10 @@ windows_ssl_client_cert_pw_save_creds(svn_boolean_t *saved,
const char *realmstring,
apr_pool_t *pool)
{
- return svn_auth__ssl_client_cert_pw_file_save_creds_helper
- (saved,
- credentials,
- provider_baton,
- parameters,
- realmstring,
- windows_ssl_client_cert_pw_encrypter,
- SVN_AUTH__WINCRYPT_PASSWORD_TYPE,
- pool);
+ return svn_auth__ssl_client_cert_pw_cache_set(
+ saved, credentials, provider_baton, parameters, realmstring,
+ windows_ssl_client_cert_pw_encrypter,
+ SVN_AUTH__WINCRYPT_PASSWORD_TYPE, pool);
}
static const svn_auth_provider_t windows_ssl_client_cert_pw_provider = {
@@ -411,19 +436,17 @@ windows_ssl_server_trust_first_credentials(void **credentials,
const char *realmstring,
apr_pool_t *pool)
{
- apr_uint32_t *failures = apr_hash_get(parameters,
- SVN_AUTH_PARAM_SSL_SERVER_FAILURES,
- APR_HASH_KEY_STRING);
+ apr_uint32_t *failure_ptr = svn_hash_gets(parameters,
+ SVN_AUTH_PARAM_SSL_SERVER_FAILURES);
+ apr_uint32_t failures = *failure_ptr;
const svn_auth_ssl_server_cert_info_t *cert_info =
- apr_hash_get(parameters,
- SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO,
- APR_HASH_KEY_STRING);
+ svn_hash_gets(parameters, SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO);
*credentials = NULL;
*iter_baton = NULL;
/* We can accept only unknown certificate authority. */
- if (*failures & SVN_AUTH_SSL_UNKNOWNCA)
+ if (failures & SVN_AUTH_SSL_UNKNOWNCA)
{
svn_boolean_t ok;
@@ -433,15 +456,16 @@ windows_ssl_server_trust_first_credentials(void **credentials,
if (ok)
{
/* Clear failure flag. */
- *failures &= ~SVN_AUTH_SSL_UNKNOWNCA;
+ failures &= ~SVN_AUTH_SSL_UNKNOWNCA;
}
}
/* If all failures are cleared now, we return the creds */
- if (! *failures)
+ if (! failures)
{
svn_auth_cred_ssl_server_trust_t *creds =
apr_pcalloc(pool, sizeof(*creds));
+ creds->accepted_failures = *failure_ptr & ~failures;
creds->may_save = FALSE; /* No need to save it. */
*credentials = creds;
}
@@ -467,4 +491,24 @@ svn_auth_get_windows_ssl_server_trust_provider
*provider = po;
}
+static const svn_auth_provider_t windows_server_authority_provider = {
+ SVN_AUTH_CRED_SSL_SERVER_AUTHORITY,
+ windows_ssl_server_trust_first_credentials,
+ NULL,
+ NULL,
+};
+
+/* Public API */
+void
+svn_auth__get_windows_ssl_server_authority_provider(
+ svn_auth_provider_object_t **provider,
+ apr_pool_t *pool)
+{
+ svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
+
+ po->vtable = &windows_server_authority_provider;
+ *provider = po;
+}
+
+
#endif /* WIN32 */