1251881Speter/*
2251881Speter * ssl_client_cert_providers.c: providers for
3251881Speter * SVN_AUTH_CRED_SSL_CLIENT_CERT
4251881Speter *
5251881Speter * ====================================================================
6251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
7251881Speter *    or more contributor license agreements.  See the NOTICE file
8251881Speter *    distributed with this work for additional information
9251881Speter *    regarding copyright ownership.  The ASF licenses this file
10251881Speter *    to you under the Apache License, Version 2.0 (the
11251881Speter *    "License"); you may not use this file except in compliance
12251881Speter *    with the License.  You may obtain a copy of the License at
13251881Speter *
14251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
15251881Speter *
16251881Speter *    Unless required by applicable law or agreed to in writing,
17251881Speter *    software distributed under the License is distributed on an
18251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19251881Speter *    KIND, either express or implied.  See the License for the
20251881Speter *    specific language governing permissions and limitations
21251881Speter *    under the License.
22251881Speter * ====================================================================
23251881Speter */
24251881Speter
25251881Speter/* ==================================================================== */
26251881Speter
27251881Speter
28251881Speter
29251881Speter/*** Includes. ***/
30251881Speter
31251881Speter#include <apr_pools.h>
32251881Speter#include "svn_hash.h"
33251881Speter#include "svn_auth.h"
34251881Speter#include "svn_error.h"
35251881Speter#include "svn_config.h"
36251881Speter
37251881Speter
38251881Speter/*-----------------------------------------------------------------------*/
39251881Speter/* File provider                                                         */
40251881Speter/*-----------------------------------------------------------------------*/
41251881Speter
42251881Speter/* retrieve and load the ssl client certificate file from servers
43251881Speter   config */
44251881Speterstatic svn_error_t *
45251881Speterssl_client_cert_file_first_credentials(void **credentials_p,
46251881Speter                                       void **iter_baton,
47251881Speter                                       void *provider_baton,
48251881Speter                                       apr_hash_t *parameters,
49251881Speter                                       const char *realmstring,
50251881Speter                                       apr_pool_t *pool)
51251881Speter{
52251881Speter  svn_config_t *cfg = svn_hash_gets(parameters,
53251881Speter                                    SVN_AUTH_PARAM_CONFIG_CATEGORY_SERVERS);
54251881Speter  const char *server_group = svn_hash_gets(parameters,
55251881Speter                                           SVN_AUTH_PARAM_SERVER_GROUP);
56251881Speter  const char *cert_file;
57251881Speter
58251881Speter  cert_file =
59251881Speter    svn_config_get_server_setting(cfg, server_group,
60251881Speter                                  SVN_CONFIG_OPTION_SSL_CLIENT_CERT_FILE,
61251881Speter                                  NULL);
62251881Speter
63251881Speter  if (cert_file != NULL)
64251881Speter    {
65251881Speter      svn_auth_cred_ssl_client_cert_t *cred =
66251881Speter        apr_palloc(pool, sizeof(*cred));
67251881Speter
68251881Speter      cred->cert_file = cert_file;
69251881Speter      cred->may_save = FALSE;
70251881Speter      *credentials_p = cred;
71251881Speter    }
72251881Speter  else
73251881Speter    {
74251881Speter      *credentials_p = NULL;
75251881Speter    }
76251881Speter
77251881Speter  *iter_baton = NULL;
78251881Speter  return SVN_NO_ERROR;
79251881Speter}
80251881Speter
81251881Speter
82251881Speterstatic const svn_auth_provider_t ssl_client_cert_file_provider =
83251881Speter  {
84251881Speter    SVN_AUTH_CRED_SSL_CLIENT_CERT,
85251881Speter    ssl_client_cert_file_first_credentials,
86251881Speter    NULL,
87251881Speter    NULL
88251881Speter  };
89251881Speter
90251881Speter
91251881Speter/*** Public API to SSL file providers. ***/
92251881Spetervoid svn_auth_get_ssl_client_cert_file_provider
93251881Speter  (svn_auth_provider_object_t **provider, apr_pool_t *pool)
94251881Speter{
95251881Speter  svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
96251881Speter  po->vtable = &ssl_client_cert_file_provider;
97251881Speter  *provider = po;
98251881Speter}
99251881Speter
100251881Speter
101251881Speter/*-----------------------------------------------------------------------*/
102251881Speter/* Prompt provider                                                       */
103251881Speter/*-----------------------------------------------------------------------*/
104251881Speter
105251881Speter/* Baton type for prompting to send client ssl creds.
106251881Speter   There is no iteration baton type. */
107251881Spetertypedef struct ssl_client_cert_prompt_provider_baton_t
108251881Speter{
109251881Speter  svn_auth_ssl_client_cert_prompt_func_t prompt_func;
110251881Speter  void *prompt_baton;
111251881Speter
112251881Speter  /* how many times to re-prompt after the first one fails */
113251881Speter  int retry_limit;
114251881Speter} ssl_client_cert_prompt_provider_baton_t;
115251881Speter
116251881Speter/* Iteration baton. */
117251881Spetertypedef struct ssl_client_cert_prompt_iter_baton_t
118251881Speter{
119251881Speter  /* The original provider baton */
120251881Speter  ssl_client_cert_prompt_provider_baton_t *pb;
121251881Speter
122251881Speter  /* The original realmstring */
123251881Speter  const char *realmstring;
124251881Speter
125251881Speter  /* how many times we've reprompted */
126251881Speter  int retries;
127251881Speter} ssl_client_cert_prompt_iter_baton_t;
128251881Speter
129251881Speter
130251881Speterstatic svn_error_t *
131251881Speterssl_client_cert_prompt_first_cred(void **credentials_p,
132251881Speter                                  void **iter_baton,
133251881Speter                                  void *provider_baton,
134251881Speter                                  apr_hash_t *parameters,
135251881Speter                                  const char *realmstring,
136251881Speter                                  apr_pool_t *pool)
137251881Speter{
138251881Speter  ssl_client_cert_prompt_provider_baton_t *pb = provider_baton;
139251881Speter  ssl_client_cert_prompt_iter_baton_t *ib =
140251881Speter    apr_pcalloc(pool, sizeof(*ib));
141251881Speter  const char *no_auth_cache = svn_hash_gets(parameters,
142251881Speter                                            SVN_AUTH_PARAM_NO_AUTH_CACHE);
143251881Speter
144251881Speter  SVN_ERR(pb->prompt_func((svn_auth_cred_ssl_client_cert_t **) credentials_p,
145251881Speter                          pb->prompt_baton, realmstring, ! no_auth_cache,
146251881Speter                          pool));
147251881Speter
148251881Speter  ib->pb = pb;
149251881Speter  ib->realmstring = apr_pstrdup(pool, realmstring);
150251881Speter  ib->retries = 0;
151251881Speter  *iter_baton = ib;
152251881Speter
153251881Speter  return SVN_NO_ERROR;
154251881Speter}
155251881Speter
156251881Speter
157251881Speterstatic svn_error_t *
158251881Speterssl_client_cert_prompt_next_cred(void **credentials_p,
159251881Speter                                 void *iter_baton,
160251881Speter                                 void *provider_baton,
161251881Speter                                 apr_hash_t *parameters,
162251881Speter                                 const char *realmstring,
163251881Speter                                 apr_pool_t *pool)
164251881Speter{
165251881Speter  ssl_client_cert_prompt_iter_baton_t *ib = iter_baton;
166251881Speter  const char *no_auth_cache = svn_hash_gets(parameters,
167251881Speter                                            SVN_AUTH_PARAM_NO_AUTH_CACHE);
168251881Speter
169251881Speter  if ((ib->pb->retry_limit >= 0) && (ib->retries >= ib->pb->retry_limit))
170251881Speter    {
171251881Speter      /* give up, go on to next provider. */
172251881Speter      *credentials_p = NULL;
173251881Speter      return SVN_NO_ERROR;
174251881Speter    }
175251881Speter  ib->retries++;
176251881Speter
177251881Speter  return ib->pb->prompt_func((svn_auth_cred_ssl_client_cert_t **)
178251881Speter                             credentials_p, ib->pb->prompt_baton,
179251881Speter                             ib->realmstring, ! no_auth_cache, pool);
180251881Speter}
181251881Speter
182251881Speter
183251881Speterstatic const svn_auth_provider_t ssl_client_cert_prompt_provider = {
184251881Speter  SVN_AUTH_CRED_SSL_CLIENT_CERT,
185251881Speter  ssl_client_cert_prompt_first_cred,
186251881Speter  ssl_client_cert_prompt_next_cred,
187251881Speter  NULL
188251881Speter};
189251881Speter
190251881Speter
191251881Speter/*** Public API to SSL prompting providers. ***/
192251881Spetervoid svn_auth_get_ssl_client_cert_prompt_provider
193251881Speter  (svn_auth_provider_object_t **provider,
194251881Speter   svn_auth_ssl_client_cert_prompt_func_t prompt_func,
195251881Speter   void *prompt_baton,
196251881Speter   int retry_limit,
197251881Speter   apr_pool_t *pool)
198251881Speter{
199251881Speter  svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
200251881Speter  ssl_client_cert_prompt_provider_baton_t *pb = apr_palloc(pool, sizeof(*pb));
201251881Speter
202251881Speter  pb->prompt_func = prompt_func;
203251881Speter  pb->prompt_baton = prompt_baton;
204251881Speter  pb->retry_limit = retry_limit;
205251881Speter
206251881Speter  po->vtable = &ssl_client_cert_prompt_provider;
207251881Speter  po->provider_baton = pb;
208251881Speter  *provider = po;
209251881Speter}
210