Merge pull request #3676 from chamons/SignalHandlerAPI_XM45
[mono.git] / mono / btls / btls-x509-store-ctx.c
1 //
2 //  btls-x509-store-ctx.c
3 //  MonoBtls
4 //
5 //  Created by Martin Baulig on 3/5/16.
6 //  Copyright © 2016 Xamarin. All rights reserved.
7 //
8
9 #include <btls-x509-store-ctx.h>
10
11 struct MonoBtlsX509StoreCtx {
12         int owns;
13         X509_STORE_CTX *ctx;
14         CRYPTO_refcount_t references;
15         MonoBtlsX509Store *store;
16         MonoBtlsX509Chain *chain;
17 };
18
19 MonoBtlsX509StoreCtx *
20 mono_btls_x509_store_ctx_from_ptr (X509_STORE_CTX *ptr)
21 {
22         MonoBtlsX509StoreCtx *ctx;
23
24         ctx = OPENSSL_malloc (sizeof(MonoBtlsX509StoreCtx));
25         if (!ctx)
26                 return NULL;
27
28         memset (ctx, 0, sizeof (MonoBtlsX509StoreCtx));
29         ctx->ctx = ptr;
30         ctx->references = 1;
31         return ctx;
32 }
33
34 MonoBtlsX509StoreCtx *
35 mono_btls_x509_store_ctx_new (void)
36 {
37         MonoBtlsX509StoreCtx *ctx;
38
39         ctx = OPENSSL_malloc (sizeof(MonoBtlsX509StoreCtx));
40         if (!ctx)
41                 return NULL;
42
43         memset (ctx, 0, sizeof (MonoBtlsX509StoreCtx));
44         ctx->ctx = X509_STORE_CTX_new ();
45         ctx->references = 1;
46         ctx->owns = 1;
47         return ctx;
48 }
49
50 MonoBtlsX509StoreCtx *
51 mono_btls_x509_store_ctx_up_ref (MonoBtlsX509StoreCtx *ctx)
52 {
53         CRYPTO_refcount_inc (&ctx->references);
54         return ctx;
55 }
56
57 int
58 mono_btls_x509_store_ctx_free (MonoBtlsX509StoreCtx *ctx)
59 {
60         if (!CRYPTO_refcount_dec_and_test_zero (&ctx->references))
61                 return 0;
62
63         if (ctx->owns) {
64                 X509_STORE_CTX_cleanup (ctx->ctx);
65                 X509_STORE_CTX_free (ctx->ctx);
66                 ctx->owns = 0;
67         }
68         if (ctx->store) {
69                 mono_btls_x509_store_free (ctx->store);
70                 ctx->store = NULL;
71         }
72         if (ctx->chain) {
73                 mono_btls_x509_chain_free (ctx->chain);
74                 ctx->chain = NULL;
75         }
76         OPENSSL_free (ctx);
77         return 1;
78 }
79
80 int
81 mono_btls_x509_store_ctx_get_error (MonoBtlsX509StoreCtx *ctx, const char **error_string)
82 {
83         int error;
84
85         error = X509_STORE_CTX_get_error (ctx->ctx);
86         if (error_string)
87                 *error_string = X509_verify_cert_error_string (error);
88         return error;
89 }
90
91 int
92 mono_btls_x509_store_ctx_get_error_depth (MonoBtlsX509StoreCtx *ctx)
93 {
94         return X509_STORE_CTX_get_error_depth (ctx->ctx);
95 }
96
97 MonoBtlsX509Chain *
98 mono_btls_x509_store_ctx_get_chain (MonoBtlsX509StoreCtx *ctx)
99 {
100         STACK_OF(X509) *certs;
101
102         certs = X509_STORE_CTX_get_chain (ctx->ctx);
103         if (!certs)
104                 return NULL;
105
106         return mono_btls_x509_chain_from_certs (certs);
107 }
108
109 MonoBtlsX509Chain *
110 mono_btls_x509_store_ctx_get_untrusted (MonoBtlsX509StoreCtx *ctx)
111 {
112         STACK_OF(X509) *untrusted;
113
114         /*
115          * Unfortunately, there is no accessor function for this.
116          *
117          * This is the set of certificate that's passed in by
118          * X509_STORE_CTX_init() and X509_STORE_CTX_set_chain().
119          */
120         untrusted = ctx->ctx->untrusted;
121         if (!untrusted)
122                 return NULL;
123
124         return mono_btls_x509_chain_from_certs (untrusted);
125 }
126
127 void
128 mono_btls_x509_store_ctx_test (MonoBtlsX509StoreCtx *ctx)
129 {
130         X509_VERIFY_PARAM *param;
131         char *peer;
132
133         fprintf (stderr, "TEST: %p!\n", ctx);
134         param = X509_STORE_CTX_get0_param (ctx->ctx);
135         peer = X509_VERIFY_PARAM_get0_peername(param);
136         fprintf (stderr, "TEST #1: %s\n", peer);
137 }
138
139 int
140 mono_btls_x509_store_ctx_init (MonoBtlsX509StoreCtx *ctx,
141                                    MonoBtlsX509Store *store, MonoBtlsX509Chain *chain)
142 {
143         STACK_OF(X509) *certs;
144         X509 *leaf;
145         int ret;
146
147         if (ctx->store)
148                 return 0;
149
150         certs = mono_btls_x509_chain_peek_certs (chain);
151         if (!certs || !sk_X509_num (certs))
152                 return 0;
153
154         ctx->store = mono_btls_x509_store_up_ref(store);
155         ctx->chain = mono_btls_x509_chain_up_ref(chain);
156
157         leaf = sk_X509_value (certs, 0);
158         ret = X509_STORE_CTX_init (ctx->ctx, mono_btls_x509_store_peek_store (store), leaf, certs);
159         if (ret != 1)
160                 return ret;
161
162         X509_STORE_CTX_set_app_data (ctx->ctx, ctx);
163         return 1;
164 }
165
166 int
167 mono_btls_x509_store_ctx_set_param (MonoBtlsX509StoreCtx *ctx, MonoBtlsX509VerifyParam *param)
168 {
169         return X509_VERIFY_PARAM_set1 (X509_STORE_CTX_get0_param (ctx->ctx), mono_btls_x509_verify_param_peek_param (param));
170 }
171
172 int
173 mono_btls_x509_store_ctx_verify_cert (MonoBtlsX509StoreCtx *ctx)
174 {
175         return X509_verify_cert (ctx->ctx);
176 }
177
178 X509 *
179 mono_btls_x509_store_ctx_get_by_subject (MonoBtlsX509StoreCtx *ctx, MonoBtlsX509Name *name)
180 {
181         X509_OBJECT obj;
182         X509 *x509;
183         int ret;
184
185         ret = X509_STORE_get_by_subject (ctx->ctx, X509_LU_X509, mono_btls_x509_name_peek_name (name), &obj);
186         if (ret != X509_LU_X509) {
187                 X509_OBJECT_free_contents (&obj);
188                 return NULL;
189         }
190
191         x509 = X509_up_ref (obj.data.x509);
192         return x509;
193 }
194
195 X509 *
196 mono_btls_x509_store_ctx_get_current_cert (MonoBtlsX509StoreCtx *ctx)
197 {
198         X509 *x509 = X509_STORE_CTX_get_current_cert (ctx->ctx);
199         if (!x509)
200                 return NULL;
201         return X509_up_ref (x509);
202 }
203
204 X509 *
205 mono_btls_x509_store_ctx_get_current_issuer (MonoBtlsX509StoreCtx *ctx)
206 {
207         X509 *x509 = X509_STORE_CTX_get0_current_issuer (ctx->ctx);
208         if (!x509)
209                 return NULL;
210         return X509_up_ref (x509);
211 }
212
213 MonoBtlsX509VerifyParam *
214 mono_btls_x509_store_ctx_get_verify_param (MonoBtlsX509StoreCtx *ctx)
215 {
216         X509_VERIFY_PARAM *param;
217
218         param = X509_STORE_CTX_get0_param (ctx->ctx);
219         if (!param)
220                 return NULL;
221
222         return mono_btls_x509_verify_param_from_store_ctx (ctx, param);
223 }
224
225 int
226 mono_btls_x509_store_ctx_get_foo (MonoBtlsX509StoreCtx *ctx)
227 {
228         return 0;
229 }