1251881Speter/*
2251881Speter * ssl_server_trust_providers.c: providers for
3251881Speter * SVN_AUTH_CRED_SSL_SERVER_TRUST
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#include <apr_pools.h>
26251881Speter
27251881Speter#include "svn_hash.h"
28251881Speter#include "svn_auth.h"
29251881Speter#include "svn_error.h"
30251881Speter#include "svn_config.h"
31251881Speter#include "svn_string.h"
32251881Speter
33251881Speter
34251881Speter/*-----------------------------------------------------------------------*/
35251881Speter/* File provider                                                         */
36251881Speter/*-----------------------------------------------------------------------*/
37251881Speter
38251881Speter/* retrieve ssl server CA failure overrides (if any) from servers
39251881Speter   config */
40251881Speterstatic svn_error_t *
41251881Speterssl_server_trust_file_first_credentials(void **credentials,
42251881Speter                                        void **iter_baton,
43251881Speter                                        void *provider_baton,
44251881Speter                                        apr_hash_t *parameters,
45251881Speter                                        const char *realmstring,
46251881Speter                                        apr_pool_t *pool)
47251881Speter{
48251881Speter  apr_uint32_t *failures = svn_hash_gets(parameters,
49251881Speter                                         SVN_AUTH_PARAM_SSL_SERVER_FAILURES);
50251881Speter  const svn_auth_ssl_server_cert_info_t *cert_info =
51251881Speter    svn_hash_gets(parameters, SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO);
52251881Speter  apr_hash_t *creds_hash = NULL;
53251881Speter  const char *config_dir;
54251881Speter  svn_error_t *error = SVN_NO_ERROR;
55251881Speter
56251881Speter  *credentials = NULL;
57251881Speter  *iter_baton = NULL;
58251881Speter
59251881Speter  /* Check if this is a permanently accepted certificate */
60251881Speter  config_dir = svn_hash_gets(parameters, SVN_AUTH_PARAM_CONFIG_DIR);
61251881Speter  error =
62251881Speter    svn_config_read_auth_data(&creds_hash, SVN_AUTH_CRED_SSL_SERVER_TRUST,
63251881Speter                              realmstring, config_dir, pool);
64251881Speter  svn_error_clear(error);
65251881Speter  if (! error && creds_hash)
66251881Speter    {
67251881Speter      svn_string_t *trusted_cert, *this_cert, *failstr;
68251881Speter      apr_uint32_t last_failures = 0;
69251881Speter
70289180Speter      trusted_cert = svn_hash_gets(creds_hash, SVN_CONFIG_AUTHN_ASCII_CERT_KEY);
71251881Speter      this_cert = svn_string_create(cert_info->ascii_cert, pool);
72289180Speter      failstr = svn_hash_gets(creds_hash, SVN_CONFIG_AUTHN_FAILURES_KEY);
73251881Speter
74251881Speter      if (failstr)
75289180Speter        SVN_ERR(svn_cstring_atoui(&last_failures, failstr->data));
76251881Speter
77251881Speter      /* If the cert is trusted and there are no new failures, we
78251881Speter       * accept it by clearing all failures. */
79251881Speter      if (trusted_cert &&
80251881Speter          svn_string_compare(this_cert, trusted_cert) &&
81251881Speter          (*failures & ~last_failures) == 0)
82251881Speter        {
83251881Speter          *failures = 0;
84251881Speter        }
85251881Speter    }
86251881Speter
87251881Speter  /* If all failures are cleared now, we return the creds */
88251881Speter  if (! *failures)
89251881Speter    {
90251881Speter      svn_auth_cred_ssl_server_trust_t *creds =
91251881Speter        apr_pcalloc(pool, sizeof(*creds));
92251881Speter      creds->may_save = FALSE; /* No need to save it again... */
93251881Speter      *credentials = creds;
94251881Speter    }
95251881Speter
96251881Speter  return SVN_NO_ERROR;
97251881Speter}
98251881Speter
99251881Speter
100251881Speterstatic svn_error_t *
101251881Speterssl_server_trust_file_save_credentials(svn_boolean_t *saved,
102251881Speter                                       void *credentials,
103251881Speter                                       void *provider_baton,
104251881Speter                                       apr_hash_t *parameters,
105251881Speter                                       const char *realmstring,
106251881Speter                                       apr_pool_t *pool)
107251881Speter{
108251881Speter  svn_auth_cred_ssl_server_trust_t *creds = credentials;
109251881Speter  const svn_auth_ssl_server_cert_info_t *cert_info;
110251881Speter  apr_hash_t *creds_hash = NULL;
111251881Speter  const char *config_dir;
112251881Speter
113251881Speter  if (! creds->may_save)
114251881Speter    return SVN_NO_ERROR;
115251881Speter
116251881Speter  config_dir = svn_hash_gets(parameters, SVN_AUTH_PARAM_CONFIG_DIR);
117251881Speter
118251881Speter  cert_info = svn_hash_gets(parameters, SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO);
119251881Speter
120251881Speter  creds_hash = apr_hash_make(pool);
121289180Speter  svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_ASCII_CERT_KEY,
122251881Speter                svn_string_create(cert_info->ascii_cert, pool));
123289180Speter  svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_FAILURES_KEY,
124251881Speter                svn_string_createf(pool, "%lu",
125251881Speter                                   (unsigned long)creds->accepted_failures));
126251881Speter
127251881Speter  SVN_ERR(svn_config_write_auth_data(creds_hash,
128251881Speter                                     SVN_AUTH_CRED_SSL_SERVER_TRUST,
129251881Speter                                     realmstring,
130251881Speter                                     config_dir,
131251881Speter                                     pool));
132251881Speter  *saved = TRUE;
133251881Speter  return SVN_NO_ERROR;
134251881Speter}
135251881Speter
136251881Speter
137251881Speterstatic const svn_auth_provider_t ssl_server_trust_file_provider = {
138251881Speter  SVN_AUTH_CRED_SSL_SERVER_TRUST,
139289180Speter  ssl_server_trust_file_first_credentials,
140251881Speter  NULL,
141289180Speter  ssl_server_trust_file_save_credentials,
142251881Speter};
143251881Speter
144251881Speter
145251881Speter/*** Public API to SSL file providers. ***/
146251881Spetervoid
147251881Spetersvn_auth_get_ssl_server_trust_file_provider
148251881Speter  (svn_auth_provider_object_t **provider, apr_pool_t *pool)
149251881Speter{
150251881Speter  svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
151251881Speter
152251881Speter  po->vtable = &ssl_server_trust_file_provider;
153251881Speter  *provider = po;
154251881Speter}
155251881Speter
156251881Speter
157251881Speter/*-----------------------------------------------------------------------*/
158251881Speter/* Prompt provider                                                       */
159251881Speter/*-----------------------------------------------------------------------*/
160251881Speter
161251881Speter/* Baton type for prompting to verify server ssl creds.
162251881Speter   There is no iteration baton type. */
163251881Spetertypedef struct ssl_server_trust_prompt_provider_baton_t
164251881Speter{
165251881Speter  svn_auth_ssl_server_trust_prompt_func_t prompt_func;
166251881Speter  void *prompt_baton;
167251881Speter} ssl_server_trust_prompt_provider_baton_t;
168251881Speter
169251881Speter
170251881Speterstatic svn_error_t *
171251881Speterssl_server_trust_prompt_first_cred(void **credentials_p,
172251881Speter                                   void **iter_baton,
173251881Speter                                   void *provider_baton,
174251881Speter                                   apr_hash_t *parameters,
175251881Speter                                   const char *realmstring,
176251881Speter                                   apr_pool_t *pool)
177251881Speter{
178251881Speter  ssl_server_trust_prompt_provider_baton_t *pb = provider_baton;
179251881Speter  apr_uint32_t *failures = svn_hash_gets(parameters,
180251881Speter                                         SVN_AUTH_PARAM_SSL_SERVER_FAILURES);
181251881Speter  const char *no_auth_cache = svn_hash_gets(parameters,
182251881Speter                                            SVN_AUTH_PARAM_NO_AUTH_CACHE);
183251881Speter  const svn_auth_ssl_server_cert_info_t *cert_info =
184251881Speter    svn_hash_gets(parameters, SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO);
185251881Speter  svn_boolean_t may_save = (!no_auth_cache
186251881Speter                            && !(*failures & SVN_AUTH_SSL_OTHER));
187251881Speter
188251881Speter  SVN_ERR(pb->prompt_func((svn_auth_cred_ssl_server_trust_t **)credentials_p,
189251881Speter                          pb->prompt_baton, realmstring, *failures, cert_info,
190251881Speter                          may_save, pool));
191251881Speter
192251881Speter  *iter_baton = NULL;
193251881Speter  return SVN_NO_ERROR;
194251881Speter}
195251881Speter
196251881Speter
197251881Speterstatic const svn_auth_provider_t ssl_server_trust_prompt_provider = {
198251881Speter  SVN_AUTH_CRED_SSL_SERVER_TRUST,
199251881Speter  ssl_server_trust_prompt_first_cred,
200251881Speter  NULL,
201251881Speter  NULL
202251881Speter};
203251881Speter
204251881Speter
205251881Speter/*** Public API to SSL prompting providers. ***/
206251881Spetervoid
207251881Spetersvn_auth_get_ssl_server_trust_prompt_provider
208251881Speter  (svn_auth_provider_object_t **provider,
209251881Speter   svn_auth_ssl_server_trust_prompt_func_t prompt_func,
210251881Speter   void *prompt_baton,
211251881Speter   apr_pool_t *pool)
212251881Speter{
213251881Speter  svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
214251881Speter  ssl_server_trust_prompt_provider_baton_t *pb =
215251881Speter    apr_palloc(pool, sizeof(*pb));
216251881Speter  pb->prompt_func = prompt_func;
217251881Speter  pb->prompt_baton = prompt_baton;
218251881Speter  po->vtable = &ssl_server_trust_prompt_provider;
219251881Speter  po->provider_baton = pb;
220251881Speter  *provider = po;
221251881Speter}
222