
Contents of /Subversion-0.112/auth.c:
/* ================================================================
* Copyright (c) 2000-2004 CollabNet. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowledgment: "This product includes
* software developed by CollabNet (http://www.Collab.Net/)."
* Alternately, this acknowledgment may appear in the software itself, if
* and wherever such third-party acknowledgments normally appear.
*
* 4. The hosted project names must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact info@collab.net.
*
* 5. Products derived from this software may not use the "Tigris" name
* nor may "Tigris" appear in their names without prior written
* permission of CollabNet.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL COLLABNET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of CollabNet.
*/
#include "svnmod.h"
#include <svn_auth.h>
/*! @module Subversion */
/*! @module Auth
*!
*! The Auth submodule provides a set of classes for providing
*! authentication information to the various Subversion components.
*/
/*! @class AuthProvider
*!
*! Base class for all authorization provider variants.
*/
/* Function indices for callbacks */
static int first_credentials_function, next_credentials_function, save_credentials_function;
struct program *svn_pike_auth_provider_program = NULL;
/* Internal object structure */
struct auth_provider_obj {
svn_auth_provider_object_t ap;
struct object *obj;
int idlevel;
};
#define THIS ((struct auth_provider_obj *)(Pike_fp->current_storage))
enum auth_parameter_type {
PARAMETER_TYPE_UNKNOWN = 0,
PARAMETER_TYPE_BOOL,
PARAMETER_TYPE_STRING,
PARAMETER_TYPE_UINT32,
PARAMETER_TYPE_CONFIG,
PARAMETER_TYPE_SERVER_CERT,
};
/* Determine type of a parameter */
static enum auth_parameter_type check_auth_parameter_type (const char *name)
{
if (!strcmp (name, SVN_AUTH_PARAM_DEFAULT_USERNAME) ||
!strcmp (name, SVN_AUTH_PARAM_DEFAULT_PASSWORD) ||
!strcmp (name, SVN_AUTH_PARAM_SERVER_GROUP) ||
!strcmp (name, SVN_AUTH_PARAM_CONFIG_DIR))
return PARAMETER_TYPE_STRING;
else if(!strcmp (name, SVN_AUTH_PARAM_NON_INTERACTIVE) ||
#ifdef SVN_AUTH_PARAM_DONT_STORE_PASSWORDS
!strcmp (name, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS) ||
#endif
!strcmp (name, SVN_AUTH_PARAM_NO_AUTH_CACHE))
return PARAMETER_TYPE_BOOL;
else if(!strcmp (name, SVN_AUTH_PARAM_SSL_SERVER_FAILURES))
return PARAMETER_TYPE_UINT32;
else if(!strcmp (name, SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO))
return PARAMETER_TYPE_SERVER_CERT;
#if 0
else if(!strcmp (name, SVN_AUTH_PARAM_CONFIG))
return PARAMETER_TYPE_CONFIG;
#endif
else
return PARAMETER_TYPE_UNKNOWN;
}
/* Convert an apr_hash_t of authentication parameters to a mapping */
static void push_auth_parameters (apr_hash_t *parameters, apr_pool_t *pool)
{
apr_hash_index_t *hi;
INT32 n_items = 0;
for (hi = apr_hash_first (pool, parameters);
hi;
hi = apr_hash_next (hi)) {
const void *name;
void *val;
enum auth_parameter_type pt;
apr_hash_this (hi, &name, NULL, &val);
if ((pt = check_auth_parameter_type ((const char *)name))
!= PARAMETER_TYPE_UNKNOWN) {
svn_pike_push_utf8 ((const char *)name);
switch(pt) {
case PARAMETER_TYPE_BOOL:
push_int (1);
break;
case PARAMETER_TYPE_STRING:
svn_pike_push_utf8 ((char *)val);
break;
case PARAMETER_TYPE_UINT32:
push_int (*(apr_uint32_t *)val);
break;
#if 0
case PARAMETER_TYPE_CONFIG:
push_config ((svn_config_t *)val);
break;
#endif
case PARAMETER_TYPE_SERVER_CERT:
{
svn_auth_ssl_server_cert_info_t *sci =
(svn_auth_ssl_server_cert_info_t *)val;
svn_pike_push_utf8 (sci->hostname);
svn_pike_push_utf8 (sci->fingerprint);
svn_pike_push_utf8 (sci->valid_from);
svn_pike_push_utf8 (sci->valid_until);
svn_pike_push_utf8 (sci->issuer_dname);
svn_pike_push_utf8 (sci->ascii_cert);
f_aggregate (6);
}
break;
}
n_items ++;
}
}
f_aggregate_mapping (2*n_items);
}
/*! @decl mixed first_credentials( mapping(string:mixed) parameters, @
*! string realm )
*!
*! Return a set of valid credentials within @[realm], or 0 if no
*! credentials are avaialble. The type of a credentials value differs
*! with the different subclasses of @[AuthProvider].
*!
*! This function should be overridden by the user class to provide
*! actual credentials. The default implementation always returns 0.
*!
*! @param parameters
*! Any run-time data that the provider may need. Currently supported
*! parameters are:
*! @mapping
*! @member string "svn:auth:username"
*! Default username.
*! @member string "svn:auth:password"
*! Default password.
*! @member int(1..1) "svn:auth:non-interactive"
*! The application doesn't want any providers to prompt users.
*! @member int(1..1) "svn:auth:dont-store-passwords"
*! The application doesn't want any providers to save passwords to disk.
*! @member int(1..1) "svn:auth:no-auth-cache"
*! The application doesn't want any providers to save credentials to disk.
*! @member int "svn:auth:ssl:failures"
*! Bitmask of failures detected by the SSL certificate validator.
*! @member array(string) "svn:auth:ssl:cert-info"
*! Certificate info for the SSL server. The elements in the array are:
*! @array
*! @elem string hostname
*! Primary CN
*! @elem string fingerprint
*! ASCII fingerprint
*! @elem string valid_from
*! ASCII date from which the certificate is valid
*! @elem string valid_until
*! ASCII date until which the certificate is valid
*! @elem string issuer_dname
*! DN of the certificate issuer
*! @elem string ascii_cert
*! Base-64 encoded DER certificate representation
*! @endarray
*! @member string "svn:auth:server-group"
*! The current server group.
*! @member string "svn:auth:config-dir"
*! A configuration directory that overrides the default
*! @tt{~/.subversion@}.
*! @endmapping
*! @param realm
*! The realm to aquire credentials for.
*!
*! @returns
*! A credentials set, or 0 if no credentials are available.
*/
static void f_first_credentials (INT32 args)
{
pop_n_elems (args);
push_int (0);
}
static svn_error_t *first_credentials_null (void **credentials,
void **iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
*credentials = NULL;
*iter_baton = NULL;
return SVN_NO_ERROR;
}
static svn_error_t *first_credentials_x (void **credentials,
void **iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool,
void *(*make_cred)(struct svalue *,
apr_pool_t *))
{
JMP_BUF recovery;
svn_error_t *err = SVN_NO_ERROR;
struct auth_provider_obj *apo = provider_baton;
*credentials = NULL;
*iter_baton = NULL;
do {
struct thread_state *_tmp=thread_state_for_id (th_self ());
HIDE_GLOBAL_VARIABLES ();
THREADS_DISALLOW ();
if (SETJMP (recovery))
err = svn_pike_make_svn_error (&throw_value);
else {
struct svalue f;
low_object_index_no_free(&f, apo->obj, apo->idlevel +
first_credentials_function);
push_auth_parameters (parameters, pool);
svn_pike_push_utf8 (realmstring);
apply_svalue (&f, 2);
*credentials = make_cred(Pike_sp-1, pool);
pop_stack ();
}
UNSETJMP (recovery);
THREADS_ALLOW ();
} while (0);
return err;
}
/*! @decl mixed next_credentials( mapping(string:mixed) parameters, @
*! string realm )
*!
*! If the provider can provide multiple sets of credentials, this
*! function should return the next one available. The iteration is
*! started with the call to @[first_credentials()]. When no more
*! credentials are available, 0 should be returned. The type of a
*! credentials value differs with the different subclasses of
*! @[AuthProvider].
*!
*! This function may be overridden by the user class to provide
*! actual credentials. The default implementation always returns 0.
*!
*! @param parameters
*! Any run-time data that the provider may need. See @[first_credentials()].
*! @param realm
*! The realm to aquire credentials for.
*!
*! @returns
*! A credentials set, or 0 if no more credentials are available.
*/
static void f_next_credentials (INT32 args)
{
pop_n_elems (args);
push_int (0);
}
static svn_error_t *next_credentials_null (void **credentials,
void *iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
*credentials = NULL;
return SVN_NO_ERROR;
}
static svn_error_t *next_credentials_x (void **credentials,
void *iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool,
void *(*make_cred)(struct svalue *,
apr_pool_t *))
{
JMP_BUF recovery;
svn_error_t *err = SVN_NO_ERROR;
struct auth_provider_obj *apo = provider_baton;
*credentials = NULL;
do {
struct thread_state *_tmp=thread_state_for_id (th_self ());
HIDE_GLOBAL_VARIABLES ();
THREADS_DISALLOW ();
if (SETJMP (recovery))
err = svn_pike_make_svn_error (&throw_value);
else {
struct svalue f;
low_object_index_no_free(&f, apo->obj, apo->idlevel +
next_credentials_function);
push_auth_parameters (parameters, pool);
svn_pike_push_utf8 (realmstring);
apply_svalue (&f, 2);
*credentials = make_cred(Pike_sp-1, pool);
pop_stack ();
}
UNSETJMP (recovery);
THREADS_ALLOW ();
} while (0);
return err;
}
/*! @decl int(0..1) save_credentials( mixed credentials, @
*! mapping(string:mixed) parameters, @
*! string realm )
*!
*! Store @[credentials] for future use. The provider is not required
*! to save; if it refuses or is unable to save for non-fatal reasons,
*! it should return 0. The type of a credentials value differs with
*! the different subclasses of @[AuthProvider].
*!
*! This function may be overridden by the user class to actually
*! store credentials. The default implementation always returns 0.
*!
*! @param credentials
*! The credentials to save.
*! @param parameters
*! Any run-time data that the provider may need. See @[first_credentials()].
*! @param realm
*! The realm to save credentials for.
*!
*! @returns
*! 1 if the credentials were saved, 0 if the credentials were not saved.
*/
static void f_save_credentials (INT32 args)
{
pop_n_elems (args);
push_int (0);
}
static svn_error_t *save_credentials_null (svn_boolean_t *saved,
void *credentials,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
*saved = FALSE;
return SVN_NO_ERROR;
}
static svn_error_t *save_credentials_x (svn_boolean_t *saved,
void *credentials,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool,
void (*push_cred)(void *))
{
JMP_BUF recovery;
svn_error_t *err = SVN_NO_ERROR;
struct auth_provider_obj *apo = provider_baton;
*saved = FALSE;
do {
struct thread_state *_tmp=thread_state_for_id (th_self ());
HIDE_GLOBAL_VARIABLES ();
THREADS_DISALLOW ();
if (SETJMP (recovery))
err = svn_pike_make_svn_error (&throw_value);
else {
struct svalue f;
low_object_index_no_free(&f, apo->obj, apo->idlevel +
save_credentials_function);
push_cred (credentials);
push_auth_parameters (parameters, pool);
svn_pike_push_utf8 (realmstring);
apply_svalue (&f, 3);
*saved = !UNSAFE_IS_ZERO (Pike_sp-1);
pop_stack ();
}
UNSETJMP (recovery);
THREADS_ALLOW ();
} while (0);
return err;
}
static const svn_auth_provider_t null_auth_provider_vtable = {
"(null)",
first_credentials_null,
next_credentials_null,
save_credentials_null
};
static void init_auth_provider (struct object *o)
{
struct auth_provider_obj *apo = THIS;
apo->ap.provider_baton = apo;
apo->ap.vtable = &null_auth_provider_vtable;
apo->obj = o;
apo->idlevel = Pike_fp->context.identifier_level;
}
/*! @endclass */
/*! @class SimpleProvider
*!
*! Simple username/password pair authentication provider
*!
*! The credentials value is an array with the following contents:
*! @array
*! @elem string username
*! Username.
*! @elem string password
*! Password.
*! @elem int(0..1) may_save
*! Indicates if the credentials may be saved (to disk).
*! @endarray
*/
/*! @decl inherit AuthProvider */
void *make_simple_cred (struct svalue *credentials, apr_pool_t *pool)
{
svn_auth_cred_simple_t *acs;
struct pike_string *username, *password;
if (credentials->type != PIKE_T_ARRAY ||
credentials->u.array->size != 3 ||
ITEM(credentials->u.array)[0].type != PIKE_T_STRING ||
ITEM(credentials->u.array)[1].type != PIKE_T_STRING ||
ITEM(credentials->u.array)[2].type != PIKE_T_INT)
Pike_error ("Invalid credentials type.\n");
username = svn_pike_to_utf8 (ITEM(credentials->u.array)[0].u.string);
password = svn_pike_to_utf8 (ITEM(credentials->u.array)[1].u.string);
acs = apr_pcalloc (pool, sizeof (*acs));
acs->username = apr_pstrdup (pool, APR_STR0 (username));
acs->password = apr_pstrdup (pool, APR_STR0 (password));
acs->may_save = !!ITEM(credentials->u.array)[2].u.integer;
do_free_string (username);
do_free_string (password);
return acs;
}
static void push_simple_cred (void *credentials)
{
svn_auth_cred_simple_t *acs = credentials;
svn_pike_push_utf8 (acs->username);
svn_pike_push_utf8 (acs->password);
push_int (acs->may_save);
f_aggregate (3);
}
static svn_error_t *first_credentials_simple (void **credentials,
void **iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return first_credentials_x (credentials, iter_baton, provider_baton,
parameters, realmstring, pool,
make_simple_cred);
}
static svn_error_t *next_credentials_simple (void **credentials,
void *iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return next_credentials_x (credentials, iter_baton, provider_baton,
parameters, realmstring, pool,
make_simple_cred);
}
static svn_error_t *save_credentials_simple (svn_boolean_t *saved,
void *credentials,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return save_credentials_x (saved, credentials, provider_baton,
parameters, realmstring, pool,
push_simple_cred);
}
static const svn_auth_provider_t simple_auth_provider_vtable = {
SVN_AUTH_CRED_SIMPLE,
first_credentials_simple,
next_credentials_simple,
save_credentials_simple
};
static void init_simple_provider (struct object *o)
{
struct auth_provider_obj *apo = THIS;
apo->ap.vtable = &simple_auth_provider_vtable;
}
/*! @endclass */
/*! @class UsernameProvider
*!
*! Username provider
*!
*! The credentials value is an array with the following contents:
*! @array
*! @elem string username
*! Username.
*! @elem int(0..1) may_save
*! Indicates if the credentials may be saved (to disk).
*! @endarray
*/
/*! @decl inherit AuthProvider */
void *make_username_cred (struct svalue *credentials, apr_pool_t *pool)
{
svn_auth_cred_username_t *acu;
struct pike_string *username;
if (credentials->type != PIKE_T_ARRAY ||
credentials->u.array->size != 2 ||
ITEM(credentials->u.array)[0].type != PIKE_T_STRING ||
ITEM(credentials->u.array)[1].type != PIKE_T_INT)
Pike_error ("Invalid credentials type.\n");
username = svn_pike_to_utf8 (ITEM(credentials->u.array)[0].u.string);
acu = apr_pcalloc (pool, sizeof (*acu));
acu->username = apr_pstrdup (pool, APR_STR0 (username));
acu->may_save = !!ITEM(credentials->u.array)[1].u.integer;
do_free_string (username);
return acu;
}
static void push_username_cred (void *credentials)
{
svn_auth_cred_username_t *acu = credentials;
svn_pike_push_utf8 (acu->username);
push_int (acu->may_save);
f_aggregate (2);
}
static svn_error_t *first_credentials_username (void **credentials,
void **iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return first_credentials_x (credentials, iter_baton, provider_baton,
parameters, realmstring, pool,
make_username_cred);
}
static svn_error_t *next_credentials_username (void **credentials,
void *iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return next_credentials_x (credentials, iter_baton, provider_baton,
parameters, realmstring, pool,
make_username_cred);
}
static svn_error_t *save_credentials_username (svn_boolean_t *saved,
void *credentials,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return save_credentials_x (saved, credentials, provider_baton,
parameters, realmstring, pool,
push_username_cred);
}
static const svn_auth_provider_t username_auth_provider_vtable = {
SVN_AUTH_CRED_USERNAME,
first_credentials_username,
next_credentials_username,
save_credentials_username
};
static void init_username_provider (struct object *o)
{
struct auth_provider_obj *apo = THIS;
apo->ap.vtable = &username_auth_provider_vtable;
}
/*! @endclass */
/*! @class ClientCertProvider
*!
*! SSL client certificate provider
*!
*! The credentials value is an array with the following contents:
*! @array
*! @elem string cert_file
*! Full path to the certificate file.
*! @elem int(0..1) may_save
*! Indicates if the credentials may be saved (to disk).
*! @endarray
*/
/*! @decl inherit AuthProvider */
void *make_clientcert_cred (struct svalue *credentials, apr_pool_t *pool)
{
svn_auth_cred_ssl_client_cert_t *acscc;
struct pike_string *cert_file;
if (credentials->type != PIKE_T_ARRAY ||
credentials->u.array->size != 2 ||
ITEM(credentials->u.array)[0].type != PIKE_T_STRING ||
ITEM(credentials->u.array)[1].type != PIKE_T_INT)
Pike_error ("Invalid credentials type.\n");
cert_file = svn_pike_to_utf8 (ITEM(credentials->u.array)[0].u.string);
acscc = apr_pcalloc (pool, sizeof (*acscc));
acscc->cert_file = apr_pstrdup (pool, APR_STR0 (cert_file));
acscc->may_save = !!ITEM(credentials->u.array)[1].u.integer;
do_free_string (cert_file);
return acscc;
}
static void push_clientcert_cred (void *credentials)
{
svn_auth_cred_ssl_client_cert_t *acscc = credentials;
svn_pike_push_utf8 (acscc->cert_file);
push_int (acscc->may_save);
f_aggregate (2);
}
static svn_error_t *first_credentials_clientcert (void **credentials,
void **iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return first_credentials_x (credentials, iter_baton, provider_baton,
parameters, realmstring, pool,
make_clientcert_cred);
}
static svn_error_t *next_credentials_clientcert (void **credentials,
void *iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return next_credentials_x (credentials, iter_baton, provider_baton,
parameters, realmstring, pool,
make_clientcert_cred);
}
static svn_error_t *save_credentials_clientcert (svn_boolean_t *saved,
void *credentials,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return save_credentials_x (saved, credentials, provider_baton,
parameters, realmstring, pool,
push_clientcert_cred);
}
static const svn_auth_provider_t clientcert_auth_provider_vtable = {
SVN_AUTH_CRED_SSL_CLIENT_CERT,
first_credentials_clientcert,
next_credentials_clientcert,
save_credentials_clientcert
};
static void init_clientcert_provider (struct object *o)
{
struct auth_provider_obj *apo = THIS;
apo->ap.vtable = &clientcert_auth_provider_vtable;
}
/*! @endclass */
/*! @class ClientCertPWProvider
*!
*! Provides passphrases for SSL client certificates
*!
*! The credentials value is an array with the following contents:
*! @array
*! @elem string password
*! Certificate password.
*! @elem int(0..1) may_save
*! Indicates if the credentials may be saved (to disk).
*! @endarray
*/
/*! @decl inherit AuthProvider */
void *make_clientcertpw_cred (struct svalue *credentials, apr_pool_t *pool)
{
svn_auth_cred_ssl_client_cert_pw_t *acsccp;
struct pike_string *password;
if (credentials->type != PIKE_T_ARRAY ||
credentials->u.array->size != 2 ||
ITEM(credentials->u.array)[0].type != PIKE_T_STRING ||
ITEM(credentials->u.array)[1].type != PIKE_T_INT)
Pike_error ("Invalid credentials type.\n");
password = svn_pike_to_utf8 (ITEM(credentials->u.array)[0].u.string);
acsccp = apr_pcalloc (pool, sizeof (*acsccp));
acsccp->password = apr_pstrdup (pool, APR_STR0 (password));
acsccp->may_save = !!ITEM(credentials->u.array)[1].u.integer;
do_free_string (password);
return acsccp;
}
static void push_clientcertpw_cred (void *credentials)
{
svn_auth_cred_ssl_client_cert_pw_t *acsccp = credentials;
svn_pike_push_utf8 (acsccp->password);
push_int (acsccp->may_save);
f_aggregate (2);
}
static svn_error_t *first_credentials_clientcertpw (void **credentials,
void **iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return first_credentials_x (credentials, iter_baton, provider_baton,
parameters, realmstring, pool,
make_clientcertpw_cred);
}
static svn_error_t *next_credentials_clientcertpw (void **credentials,
void *iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return next_credentials_x (credentials, iter_baton, provider_baton,
parameters, realmstring, pool,
make_clientcertpw_cred);
}
static svn_error_t *save_credentials_clientcertpw (svn_boolean_t *saved,
void *credentials,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return save_credentials_x (saved, credentials, provider_baton,
parameters, realmstring, pool,
push_clientcertpw_cred);
}
static const svn_auth_provider_t clientcertpw_auth_provider_vtable = {
SVN_AUTH_CRED_SSL_CLIENT_CERT_PW,
first_credentials_clientcertpw,
next_credentials_clientcertpw,
save_credentials_clientcertpw
};
static void init_clientcertpw_provider (struct object *o)
{
struct auth_provider_obj *apo = THIS;
apo->ap.vtable = &clientcertpw_auth_provider_vtable;
}
/*! @endclass */
/*! @class ServerTrustProvider
*!
*! Server verification provider
*!
*! The credentials value is an array with the following contents:
*! @array
*! @elem int(0..1) may_save
*! Indicates if the credentials may be saved (to disk).
*! @elem int accepted_failures
*! Bit mask of accepted failures.
*! @endarray
*/
/*! @decl inherit AuthProvider */
void *make_servertrust_cred (struct svalue *credentials, apr_pool_t *pool)
{
svn_auth_cred_ssl_server_trust_t *acsst;
if (credentials->type != PIKE_T_ARRAY ||
credentials->u.array->size != 2 ||
ITEM(credentials->u.array)[0].type != PIKE_T_INT ||
ITEM(credentials->u.array)[1].type != PIKE_T_INT)
Pike_error ("Invalid credentials type.\n");
acsst = apr_pcalloc (pool, sizeof (*acsst));
acsst->may_save = !!ITEM(credentials->u.array)[0].u.integer;
acsst->accepted_failures = ITEM(credentials->u.array)[1].u.integer;
return acsst;
}
static void push_servertrust_cred (void *credentials)
{
svn_auth_cred_ssl_server_trust_t *acsst = credentials;
push_int (acsst->may_save);
push_int (acsst->accepted_failures);
f_aggregate (2);
}
static svn_error_t *first_credentials_servertrust (void **credentials,
void **iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return first_credentials_x (credentials, iter_baton, provider_baton,
parameters, realmstring, pool,
make_servertrust_cred);
}
static svn_error_t *next_credentials_servertrust (void **credentials,
void *iter_baton,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return next_credentials_x (credentials, iter_baton, provider_baton,
parameters, realmstring, pool,
make_servertrust_cred);
}
static svn_error_t *save_credentials_servertrust (svn_boolean_t *saved,
void *credentials,
void *provider_baton,
apr_hash_t *parameters,
const char *realmstring,
apr_pool_t *pool)
{
return save_credentials_x (saved, credentials, provider_baton,
parameters, realmstring, pool,
push_servertrust_cred);
}
static const svn_auth_provider_t servertrust_auth_provider_vtable = {
SVN_AUTH_CRED_SSL_SERVER_TRUST,
first_credentials_servertrust,
next_credentials_servertrust,
save_credentials_servertrust
};
static void init_servertrust_provider (struct object *o)
{
struct auth_provider_obj *apo = THIS;
apo->ap.vtable = &servertrust_auth_provider_vtable;
}
/*! @endclass */
/* Initialize Auth submodule */
void svn_pike_init_auth (void)
{
struct program *auth_program;
struct svalue prog;
prog.type = PIKE_T_PROGRAM;
prog.subtype = 0;
start_new_program ();
/*! @class AuthProvider */
start_new_program ();
ADD_STORAGE (struct auth_provider_obj);
set_init_callback(init_auth_provider);
first_credentials_function = ADD_FUNCTION ("first_credentials",
f_first_credentials,
tFunc (tMap (tStr, tMixed) tStr,
tMixed), 0);
next_credentials_function = ADD_FUNCTION ("next_credentials",
f_next_credentials,
tFunc (tMap (tStr, tMixed) tStr,
tMixed), 0);
save_credentials_function = ADD_FUNCTION ("save_credentials",
f_save_credentials,
tFunc (tMixed tMap (tStr, tMixed)
tStr, tInt01), 0);
/*! @decl constant SSL_NOTYETVALID
*! @decl constant SSL_EXPIRED
*! @decl constant SSL_CNMISMATCH
*! @decl constant SSL_UNKNOWNCA
*! @decl constant SSL_OTHER
*!
*! Bits that can be set in the "svn:auth:ssl:failures" parameter to
*! indicate various certificate validation failures.
*!
*! @seealso
*! @[ServerTrustProvider]
*/
ADD_INT_CONSTANT ("SSL_NOTYETVALID", SVN_AUTH_SSL_NOTYETVALID, 0);
ADD_INT_CONSTANT ("SSL_EXPIRED", SVN_AUTH_SSL_EXPIRED, 0);
ADD_INT_CONSTANT ("SSL_CNMISMATCH", SVN_AUTH_SSL_CNMISMATCH, 0);
ADD_INT_CONSTANT ("SSL_UNKNOWNCA", SVN_AUTH_SSL_UNKNOWNCA, 0);
ADD_INT_CONSTANT ("SSL_OTHER", SVN_AUTH_SSL_OTHER, 0);
svn_pike_auth_provider_program = end_program ();
prog.u.program = svn_pike_auth_provider_program;
add_program_constant ("AuthProvider", svn_pike_auth_provider_program, 0);
/*! @endclass */
start_new_program ();
do_inherit(&prog, 0, NULL);
set_init_callback(init_simple_provider);
end_class ("SimpleProvider", 0);
start_new_program ();
do_inherit(&prog, 0, NULL);
set_init_callback(init_username_provider);
end_class ("UsernameProvider", 0);
start_new_program ();
do_inherit(&prog, 0, NULL);
set_init_callback(init_clientcert_provider);
end_class ("ClientCertProvider", 0);
start_new_program ();
do_inherit(&prog, 0, NULL);
set_init_callback(init_clientcertpw_provider);
end_class ("ClientCertPWProvider", 0);
start_new_program ();
do_inherit(&prog, 0, NULL);
set_init_callback(init_servertrust_provider);
end_class ("ServerTrustProvider", 0);
auth_program = end_program ();
add_object_constant ("Auth", clone_object (auth_program, 0), 0);
free_program (auth_program);
}
/*! @endmodule */
/*! @endmodule */