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
82289180Speterstatic const svn_auth_provider_t ssl_client_cert_file_provider = {
83289180Speter  SVN_AUTH_CRED_SSL_CLIENT_CERT,
84289180Speter  ssl_client_cert_file_first_credentials,
85289180Speter  NULL,
86289180Speter  NULL
87289180Speter};
88251881Speter
89251881Speter
90251881Speter/*** Public API to SSL file providers. ***/
91251881Spetervoid svn_auth_get_ssl_client_cert_file_provider
92251881Speter  (svn_auth_provider_object_t **provider, apr_pool_t *pool)
93251881Speter{
94251881Speter  svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
95251881Speter  po->vtable = &ssl_client_cert_file_provider;
96251881Speter  *provider = po;
97251881Speter}
98251881Speter
99251881Speter
100251881Speter/*-----------------------------------------------------------------------*/
101251881Speter/* Prompt provider                                                       */
102251881Speter/*-----------------------------------------------------------------------*/
103251881Speter
104251881Speter/* Baton type for prompting to send client ssl creds.
105251881Speter   There is no iteration baton type. */
106251881Spetertypedef struct ssl_client_cert_prompt_provider_baton_t
107251881Speter{
108251881Speter  svn_auth_ssl_client_cert_prompt_func_t prompt_func;
109251881Speter  void *prompt_baton;
110251881Speter
111251881Speter  /* how many times to re-prompt after the first one fails */
112251881Speter  int retry_limit;
113251881Speter} ssl_client_cert_prompt_provider_baton_t;
114251881Speter
115251881Speter/* Iteration baton. */
116251881Spetertypedef struct ssl_client_cert_prompt_iter_baton_t
117251881Speter{
118251881Speter  /* The original provider baton */
119251881Speter  ssl_client_cert_prompt_provider_baton_t *pb;
120251881Speter
121251881Speter  /* The original realmstring */
122251881Speter  const char *realmstring;
123251881Speter
124251881Speter  /* how many times we've reprompted */
125251881Speter  int retries;
126251881Speter} ssl_client_cert_prompt_iter_baton_t;
127251881Speter
128251881Speter
129251881Speterstatic svn_error_t *
130251881Speterssl_client_cert_prompt_first_cred(void **credentials_p,
131251881Speter                                  void **iter_baton,
132251881Speter                                  void *provider_baton,
133251881Speter                                  apr_hash_t *parameters,
134251881Speter                                  const char *realmstring,
135251881Speter                                  apr_pool_t *pool)
136251881Speter{
137251881Speter  ssl_client_cert_prompt_provider_baton_t *pb = provider_baton;
138251881Speter  ssl_client_cert_prompt_iter_baton_t *ib =
139251881Speter    apr_pcalloc(pool, sizeof(*ib));
140251881Speter  const char *no_auth_cache = svn_hash_gets(parameters,
141251881Speter                                            SVN_AUTH_PARAM_NO_AUTH_CACHE);
142251881Speter
143251881Speter  SVN_ERR(pb->prompt_func((svn_auth_cred_ssl_client_cert_t **) credentials_p,
144251881Speter                          pb->prompt_baton, realmstring, ! no_auth_cache,
145251881Speter                          pool));
146251881Speter
147251881Speter  ib->pb = pb;
148251881Speter  ib->realmstring = apr_pstrdup(pool, realmstring);
149251881Speter  ib->retries = 0;
150251881Speter  *iter_baton = ib;
151251881Speter
152251881Speter  return SVN_NO_ERROR;
153251881Speter}
154251881Speter
155251881Speter
156251881Speterstatic svn_error_t *
157251881Speterssl_client_cert_prompt_next_cred(void **credentials_p,
158251881Speter                                 void *iter_baton,
159251881Speter                                 void *provider_baton,
160251881Speter                                 apr_hash_t *parameters,
161251881Speter                                 const char *realmstring,
162251881Speter                                 apr_pool_t *pool)
163251881Speter{
164251881Speter  ssl_client_cert_prompt_iter_baton_t *ib = iter_baton;
165251881Speter  const char *no_auth_cache = svn_hash_gets(parameters,
166251881Speter                                            SVN_AUTH_PARAM_NO_AUTH_CACHE);
167251881Speter
168251881Speter  if ((ib->pb->retry_limit >= 0) && (ib->retries >= ib->pb->retry_limit))
169251881Speter    {
170251881Speter      /* give up, go on to next provider. */
171251881Speter      *credentials_p = NULL;
172251881Speter      return SVN_NO_ERROR;
173251881Speter    }
174251881Speter  ib->retries++;
175251881Speter
176251881Speter  return ib->pb->prompt_func((svn_auth_cred_ssl_client_cert_t **)
177251881Speter                             credentials_p, ib->pb->prompt_baton,
178251881Speter                             ib->realmstring, ! no_auth_cache, pool);
179251881Speter}
180251881Speter
181251881Speter
182251881Speterstatic const svn_auth_provider_t ssl_client_cert_prompt_provider = {
183251881Speter  SVN_AUTH_CRED_SSL_CLIENT_CERT,
184251881Speter  ssl_client_cert_prompt_first_cred,
185251881Speter  ssl_client_cert_prompt_next_cred,
186251881Speter  NULL
187251881Speter};
188251881Speter
189251881Speter
190251881Speter/*** Public API to SSL prompting providers. ***/
191251881Spetervoid svn_auth_get_ssl_client_cert_prompt_provider
192251881Speter  (svn_auth_provider_object_t **provider,
193251881Speter   svn_auth_ssl_client_cert_prompt_func_t prompt_func,
194251881Speter   void *prompt_baton,
195251881Speter   int retry_limit,
196251881Speter   apr_pool_t *pool)
197251881Speter{
198251881Speter  svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
199251881Speter  ssl_client_cert_prompt_provider_baton_t *pb = apr_palloc(pool, sizeof(*pb));
200251881Speter
201251881Speter  pb->prompt_func = prompt_func;
202251881Speter  pb->prompt_baton = prompt_baton;
203251881Speter  pb->retry_limit = retry_limit;
204251881Speter
205251881Speter  po->vtable = &ssl_client_cert_prompt_provider;
206251881Speter  po->provider_baton = pb;
207251881Speter  *provider = po;
208251881Speter}
209