1/* 2 * ssl_client_cert_providers.c: providers for 3 * SVN_AUTH_CRED_SSL_CLIENT_CERT 4 * 5 * ==================================================================== 6 * Licensed to the Apache Software Foundation (ASF) under one 7 * or more contributor license agreements. See the NOTICE file 8 * distributed with this work for additional information 9 * regarding copyright ownership. The ASF licenses this file 10 * to you under the Apache License, Version 2.0 (the 11 * "License"); you may not use this file except in compliance 12 * with the License. You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, 17 * software distributed under the License is distributed on an 18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19 * KIND, either express or implied. See the License for the 20 * specific language governing permissions and limitations 21 * under the License. 22 * ==================================================================== 23 */ 24 25/* ==================================================================== */ 26 27 28 29/*** Includes. ***/ 30 31#include <apr_pools.h> 32#include "svn_hash.h" 33#include "svn_auth.h" 34#include "svn_error.h" 35#include "svn_config.h" 36 37 38/*-----------------------------------------------------------------------*/ 39/* File provider */ 40/*-----------------------------------------------------------------------*/ 41 42/* retrieve and load the ssl client certificate file from servers 43 config */ 44static svn_error_t * 45ssl_client_cert_file_first_credentials(void **credentials_p, 46 void **iter_baton, 47 void *provider_baton, 48 apr_hash_t *parameters, 49 const char *realmstring, 50 apr_pool_t *pool) 51{ 52 svn_config_t *cfg = svn_hash_gets(parameters, 53 SVN_AUTH_PARAM_CONFIG_CATEGORY_SERVERS); 54 const char *server_group = svn_hash_gets(parameters, 55 SVN_AUTH_PARAM_SERVER_GROUP); 56 const char *cert_file; 57 58 cert_file = 59 svn_config_get_server_setting(cfg, server_group, 60 SVN_CONFIG_OPTION_SSL_CLIENT_CERT_FILE, 61 NULL); 62 63 if (cert_file != NULL) 64 { 65 svn_auth_cred_ssl_client_cert_t *cred = 66 apr_palloc(pool, sizeof(*cred)); 67 68 cred->cert_file = cert_file; 69 cred->may_save = FALSE; 70 *credentials_p = cred; 71 } 72 else 73 { 74 *credentials_p = NULL; 75 } 76 77 *iter_baton = NULL; 78 return SVN_NO_ERROR; 79} 80 81 82static const svn_auth_provider_t ssl_client_cert_file_provider = 83 { 84 SVN_AUTH_CRED_SSL_CLIENT_CERT, 85 ssl_client_cert_file_first_credentials, 86 NULL, 87 NULL 88 }; 89 90 91/*** Public API to SSL file providers. ***/ 92void svn_auth_get_ssl_client_cert_file_provider 93 (svn_auth_provider_object_t **provider, apr_pool_t *pool) 94{ 95 svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po)); 96 po->vtable = &ssl_client_cert_file_provider; 97 *provider = po; 98} 99 100 101/*-----------------------------------------------------------------------*/ 102/* Prompt provider */ 103/*-----------------------------------------------------------------------*/ 104 105/* Baton type for prompting to send client ssl creds. 106 There is no iteration baton type. */ 107typedef struct ssl_client_cert_prompt_provider_baton_t 108{ 109 svn_auth_ssl_client_cert_prompt_func_t prompt_func; 110 void *prompt_baton; 111 112 /* how many times to re-prompt after the first one fails */ 113 int retry_limit; 114} ssl_client_cert_prompt_provider_baton_t; 115 116/* Iteration baton. */ 117typedef struct ssl_client_cert_prompt_iter_baton_t 118{ 119 /* The original provider baton */ 120 ssl_client_cert_prompt_provider_baton_t *pb; 121 122 /* The original realmstring */ 123 const char *realmstring; 124 125 /* how many times we've reprompted */ 126 int retries; 127} ssl_client_cert_prompt_iter_baton_t; 128 129 130static svn_error_t * 131ssl_client_cert_prompt_first_cred(void **credentials_p, 132 void **iter_baton, 133 void *provider_baton, 134 apr_hash_t *parameters, 135 const char *realmstring, 136 apr_pool_t *pool) 137{ 138 ssl_client_cert_prompt_provider_baton_t *pb = provider_baton; 139 ssl_client_cert_prompt_iter_baton_t *ib = 140 apr_pcalloc(pool, sizeof(*ib)); 141 const char *no_auth_cache = svn_hash_gets(parameters, 142 SVN_AUTH_PARAM_NO_AUTH_CACHE); 143 144 SVN_ERR(pb->prompt_func((svn_auth_cred_ssl_client_cert_t **) credentials_p, 145 pb->prompt_baton, realmstring, ! no_auth_cache, 146 pool)); 147 148 ib->pb = pb; 149 ib->realmstring = apr_pstrdup(pool, realmstring); 150 ib->retries = 0; 151 *iter_baton = ib; 152 153 return SVN_NO_ERROR; 154} 155 156 157static svn_error_t * 158ssl_client_cert_prompt_next_cred(void **credentials_p, 159 void *iter_baton, 160 void *provider_baton, 161 apr_hash_t *parameters, 162 const char *realmstring, 163 apr_pool_t *pool) 164{ 165 ssl_client_cert_prompt_iter_baton_t *ib = iter_baton; 166 const char *no_auth_cache = svn_hash_gets(parameters, 167 SVN_AUTH_PARAM_NO_AUTH_CACHE); 168 169 if ((ib->pb->retry_limit >= 0) && (ib->retries >= ib->pb->retry_limit)) 170 { 171 /* give up, go on to next provider. */ 172 *credentials_p = NULL; 173 return SVN_NO_ERROR; 174 } 175 ib->retries++; 176 177 return ib->pb->prompt_func((svn_auth_cred_ssl_client_cert_t **) 178 credentials_p, ib->pb->prompt_baton, 179 ib->realmstring, ! no_auth_cache, pool); 180} 181 182 183static const svn_auth_provider_t ssl_client_cert_prompt_provider = { 184 SVN_AUTH_CRED_SSL_CLIENT_CERT, 185 ssl_client_cert_prompt_first_cred, 186 ssl_client_cert_prompt_next_cred, 187 NULL 188}; 189 190 191/*** Public API to SSL prompting providers. ***/ 192void svn_auth_get_ssl_client_cert_prompt_provider 193 (svn_auth_provider_object_t **provider, 194 svn_auth_ssl_client_cert_prompt_func_t prompt_func, 195 void *prompt_baton, 196 int retry_limit, 197 apr_pool_t *pool) 198{ 199 svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po)); 200 ssl_client_cert_prompt_provider_baton_t *pb = apr_palloc(pool, sizeof(*pb)); 201 202 pb->prompt_func = prompt_func; 203 pb->prompt_baton = prompt_baton; 204 pb->retry_limit = retry_limit; 205 206 po->vtable = &ssl_client_cert_prompt_provider; 207 po->provider_baton = pb; 208 *provider = po; 209} 210