Home modules.gotpike.org
Username: Password: [Create Account]
[Forgot Password?]

Modules

ADT
Database
GTK2
GUI
IP
PiJAX
Public
Sql
Stdio
Subversion
System
Tools
Xosd
lua
v4l2
wx

Recent Changes

Public.ZeroMQ 1.1
Public.Template.Mustache 1.0
Public.Protocols.XMPP 1.4
Sql.Provider.jdbc 1.0
Public.Storage.Manta 1.0

Popular Downloads

Public.Parser.JSON2 1.0
Public.Parser.JSON 0.2
GTK2 2.23
Public.Web.FCGI 1.8
Public.Parser.XML2 1.48


Module Information
Subversion
Viewing 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 

/*! @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 */



gotpike.org | Copyright © 2004 - 2019 | Pike is a trademark of Department of Computer and Information Science, Linköping University