Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / btls / btls-x509-lookup-mono.c
1 //
2 //  btls-x509-lookup-mono.c
3 //  MonoBtls
4 //
5 //  Created by Martin Baulig on 3/6/16.
6 //  Copyright © 2016 Xamarin. All rights reserved.
7 //
8
9 #include <btls-x509-lookup.h>
10 #include <btls-x509-lookup-mono.h>
11 #include <openssl/stack.h>
12
13 // random high number
14 #define MONO_BTLS_X509_L_MONO_ADD       36292
15
16 typedef struct MonoLookupNode MonoLookupNode;
17 struct MonoLookupNode {
18         MonoBtlsX509LookupMono *mono;
19         MonoLookupNode *next;
20 };
21
22 typedef struct {
23         MonoLookupNode *nodes;
24 } MonoLookup;
25
26 struct MonoBtlsX509LookupMono {
27         const void *instance;
28         MonoBtlsX509LookupMono_BySubject by_subject_func;
29         MonoLookup *lookup;
30 };
31
32 MONO_API MonoBtlsX509LookupMono *
33 mono_btls_x509_lookup_mono_new (void)
34 {
35         MonoBtlsX509LookupMono *mono;
36
37         mono = OPENSSL_malloc (sizeof (MonoBtlsX509LookupMono));
38         if (!mono)
39                 return NULL;
40
41         memset (mono, 0, sizeof (MonoBtlsX509LookupMono));
42         return mono;
43 }
44
45 MONO_API void
46 mono_btls_x509_lookup_mono_init (MonoBtlsX509LookupMono *mono, const void *instance,
47                                  MonoBtlsX509LookupMono_BySubject by_subject_func)
48 {
49         mono->instance = instance;
50         mono->by_subject_func = by_subject_func;
51 }
52
53 static int
54 mono_lookup_install (MonoLookup *lookup, MonoBtlsX509LookupMono *mono)
55 {
56         MonoLookupNode *node;
57
58         node = OPENSSL_malloc (sizeof (MonoLookupNode));
59         if (!node)
60                 return 0;
61
62         memset (node, 0, sizeof (MonoLookupNode));
63         mono->lookup = lookup;
64         node->mono = mono;
65         node->next = lookup->nodes;
66         lookup->nodes = node;
67         return 1;
68 }
69
70 static int
71 mono_lookup_uninstall (MonoBtlsX509LookupMono *mono)
72 {
73         MonoLookupNode **ptr;
74
75         if (!mono->lookup)
76                 return 0;
77
78         for (ptr = &mono->lookup->nodes; *ptr; ptr = &(*ptr)->next) {
79                 if ((*ptr)->mono == mono) {
80                         *ptr = (*ptr)->next;
81                         return 1;
82                 }
83         }
84
85         return 0;
86 }
87
88 MONO_API int
89 mono_btls_x509_lookup_mono_free (MonoBtlsX509LookupMono *mono)
90 {
91         mono->instance = NULL;
92         mono->by_subject_func = NULL;
93
94         if (mono->lookup) {
95                 if (!mono_lookup_uninstall (mono))
96                         return 0;
97         }
98
99         mono->lookup = NULL;
100
101         OPENSSL_free (mono);
102         return 1;
103 }
104
105 static int
106 mono_lookup_ctrl (X509_LOOKUP *ctx, int cmd, const char *argp, long argl, char **ret)
107 {
108         MonoLookup *lookup = (MonoLookup*)ctx->method_data;
109         MonoBtlsX509LookupMono *mono = (MonoBtlsX509LookupMono*)argp;
110
111         if (!lookup || cmd != MONO_BTLS_X509_L_MONO_ADD)
112                 return 0;
113         if (!mono || mono->lookup)
114                 return 0;
115
116         return mono_lookup_install (lookup, mono);
117 }
118
119 static int
120 mono_lookup_new (X509_LOOKUP *ctx)
121 {
122         MonoLookup *data;
123
124         data = OPENSSL_malloc (sizeof (MonoLookup));
125         if (!data)
126                 return 0;
127
128         memset (data, 0, sizeof (MonoLookup));
129         ctx->method_data = (void *)data;
130         return 1;
131 }
132
133 static void
134 mono_lookup_free (X509_LOOKUP *ctx)
135 {
136         MonoLookup *lookup;
137         MonoLookupNode *ptr;
138
139         lookup = (MonoLookup *)ctx->method_data;
140         ctx->method_data = NULL;
141         if (!lookup)
142                 return;
143
144         ptr = lookup->nodes;
145         lookup->nodes = NULL;
146
147         while (ptr) {
148                 MonoLookupNode *node = ptr;
149                 ptr = ptr->next;
150
151                 if (node->mono)
152                         node->mono->lookup = NULL;
153                 node->mono = NULL;
154                 node->next = NULL;
155                 OPENSSL_free (node);
156         }
157
158         OPENSSL_free (lookup);
159 }
160
161 static int
162 mono_lookup_get_by_subject (X509_LOOKUP *ctx, int type, X509_NAME *name, X509_OBJECT *obj_ret)
163 {
164         MonoLookup *lookup;
165         MonoBtlsX509Name *name_obj;
166         MonoLookupNode *node;
167         X509 *x509 = NULL;
168         int ret = 0;
169
170         lookup = (MonoLookup *)ctx->method_data;
171
172         if (!lookup || !lookup->nodes)
173                 return 0;
174         if (type != X509_LU_X509)
175                 return 0;
176
177         name_obj = mono_btls_x509_name_from_name (name);
178         x509 = NULL;
179
180         for (node = lookup->nodes; node; node = node->next) {
181                 if (!node->mono || !node->mono->by_subject_func)
182                         continue;
183                 ret = (* node->mono->by_subject_func) (node->mono->instance, name_obj, &x509);
184                 if (ret)
185                         break;
186         }
187
188         mono_btls_x509_name_free (name_obj);
189
190         if (!ret) {
191                 if (x509)
192                         X509_free(x509);
193                 return 0;
194         }
195
196         obj_ret->type = X509_LU_X509;
197         obj_ret->data.x509 = x509;
198         return 1;
199 }
200
201 static X509_LOOKUP_METHOD mono_lookup_method = {
202         "Mono lookup method",
203         mono_lookup_new,                /* new */
204         mono_lookup_free,               /* free */
205         NULL,                           /* init */
206         NULL,                           /* shutdown */
207         mono_lookup_ctrl,               /* ctrl */
208         mono_lookup_get_by_subject,     /* get_by_subject */
209         NULL,                           /* get_by_issuer_serial */
210         NULL,                           /* get_by_fingerprint */
211         NULL,                           /* get_by_alias */
212 };
213
214 MONO_API X509_LOOKUP_METHOD *
215 mono_btls_x509_lookup_mono_method (void)
216 {
217         return &mono_lookup_method;
218 }
219
220 MONO_API int
221 mono_btls_x509_lookup_add_mono (MonoBtlsX509Lookup *lookup, MonoBtlsX509LookupMono *mono)
222 {
223         if (mono_btls_x509_lookup_get_type (lookup) != MONO_BTLS_X509_LOOKUP_TYPE_MONO)
224                 return 0;
225         return X509_LOOKUP_ctrl (mono_btls_x509_lookup_peek_lookup (lookup),
226                                  MONO_BTLS_X509_L_MONO_ADD,
227                                  (void*)mono, 0, NULL);
228 }