1 /*        $NetBSD: rsalist.c,v 1.8 2025/03/07 15:55:29 christos Exp $ */
2 
3 /* Id: rsalist.c,v 1.3 2004/11/08 12:04:23 ludvigm Exp */
4 
5 /*
6  * Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
7  * Contributed by: Michal Ludvig <mludvig@suse.cz>, SUSE Labs
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the project nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include "config.h"
36 
37 #include <stdio.h>
38 #include <string.h>
39 
40 #include <sys/types.h>
41 #include <sys/queue.h>
42 #include <sys/socket.h>
43 #include <netdb.h>
44 
45 #include <openssl/bn.h>
46 #include <openssl/rsa.h>
47 
48 #include "misc.h"
49 #include "plog.h"
50 #include "prsa_tok.h"
51 #include "sockmisc.h"
52 #include "rsalist.h"
53 #include "genlist.h"
54 #include "remoteconf.h"
55 #include "crypto_openssl.h"
56 
57 #ifndef LIST_FIRST
58 #define LIST_FIRST(head)        ((head)->lh_first)
59 #endif
60 
61 #ifndef LIST_NEXT
62 #define LIST_NEXT(elm, field)   ((elm)->field.le_next)
63 #endif
64 
65 int
rsa_key_insert(struct genlist * list,struct netaddr * src,struct netaddr * dst,RSA * rsa)66 rsa_key_insert(struct genlist *list, struct netaddr *src,
67                  struct netaddr *dst, RSA *rsa)
68 {
69           struct rsa_key *rsa_key;
70 
71           rsa_key = calloc(sizeof(struct rsa_key), 1);
72           rsa_key->rsa = rsa;
73 
74           if (src)
75                     rsa_key->src = src;
76           else
77                     rsa_key->src = calloc(sizeof(*rsa_key->src), 1);
78 
79           if (dst)
80                     rsa_key->dst = dst;
81           else
82                     rsa_key->dst = calloc(sizeof(*rsa_key->dst), 1);
83 
84           genlist_append(list, rsa_key);
85 
86           return 0;
87 }
88 
89 struct rsa_key *
rsa_key_dup(struct rsa_key * key)90 rsa_key_dup(struct rsa_key *key)
91 {
92           struct rsa_key *new;
93 
94           new = calloc(sizeof(struct rsa_key), 1);
95           if (new == NULL)
96                     return NULL;
97 
98           if (key->rsa) {
99                     const BIGNUM *d;
100                     RSA_get0_key(key->rsa, NULL, NULL, &d);
101                     new->rsa = d != NULL ? RSAPrivateKey_dup(key->rsa) : RSAPublicKey_dup(key->rsa);
102                     if (new->rsa == NULL)
103                               goto dup_error;
104           }
105 
106           if (key->src) {
107                     new->src = malloc(sizeof(*new->src));
108                     if (new->src == NULL)
109                               goto dup_error;
110                     memcpy(new->src, key->src, sizeof(*new->src));
111           }
112           if (key->dst) {
113                     new->dst = malloc(sizeof(*new->dst));
114                     if (new->dst == NULL)
115                               goto dup_error;
116                     memcpy(new->dst, key->dst, sizeof(*new->dst));
117           }
118 
119           return new;
120 
121 dup_error:
122           if (new->rsa != NULL)
123                     RSA_free(new->rsa);
124           if (new->dst != NULL)
125                     free(new->dst);
126           if (new->src != NULL)
127                     free(new->src);
128 
129           free(new);
130           return NULL;
131 }
132 
133 void
rsa_key_free(void * data)134 rsa_key_free(void *data)
135 {
136           struct rsa_key *rsa_key;
137 
138 
139           rsa_key = (struct rsa_key *)data;
140           if (rsa_key->src)
141                     free(rsa_key->src);
142           if (rsa_key->dst)
143                     free(rsa_key->dst);
144           if (rsa_key->rsa)
145                     RSA_free(rsa_key->rsa);
146 
147           free(rsa_key);
148 }
149 
150 /*ARGSUSED*/
151 static void *
rsa_key_dump_one(void * entry,void * arg __unused)152 rsa_key_dump_one(void *entry, void *arg __unused)
153 {
154           struct rsa_key *key = entry;
155 
156           plog(LLV_DEBUG, LOCATION, NULL, "Entry %s\n",
157                naddrwop2str_fromto("%s -> %s", key->src,
158                                          key->dst));
159           if (loglevel > LLV_DEBUG)
160                     RSA_print_fp(stdout, key->rsa, 4);
161 
162           return NULL;
163 }
164 
165 void
rsa_key_dump(struct genlist * list)166 rsa_key_dump(struct genlist *list)
167 {
168           genlist_foreach(list, rsa_key_dump_one, NULL);
169 }
170 
171 /*ARGSUSED*/
172 static void *
rsa_list_count_one(void * entry __unused,void * arg)173 rsa_list_count_one(void *entry __unused, void *arg)
174 {
175           if (arg)
176                     (*(unsigned long *)arg)++;
177           return NULL;
178 }
179 
180 unsigned long
rsa_list_count(struct genlist * list)181 rsa_list_count(struct genlist *list)
182 {
183           unsigned long count = 0;
184           genlist_foreach(list, rsa_list_count_one, &count);
185           return count;
186 }
187 
188 struct lookup_result {
189           struct ph1handle *iph1;
190           int max_score;
191           struct genlist *winners;
192 };
193 
194 static void *
rsa_lookup_key_one(void * entry,void * data)195 rsa_lookup_key_one(void *entry, void *data)
196 {
197           int local_score, remote_score;
198           struct lookup_result *req = data;
199           struct rsa_key *key = entry;
200 
201           local_score = naddr_score(key->src, req->iph1->local);
202           remote_score = naddr_score(key->dst, req->iph1->remote);
203 
204           plog(LLV_DEBUG, LOCATION, NULL, "Entry %s scored %d/%d\n",
205                     naddrwop2str_fromto("%s -> %s", key->src, key->dst),
206                     local_score, remote_score);
207 
208           if (local_score >= 0 && remote_score >= 0) {
209                     if (local_score + remote_score > req->max_score) {
210                               req->max_score = local_score + remote_score;
211 //                            genlist_free(req->winners, NULL);
212                     }
213 
214                     if (local_score + remote_score >= req->max_score) {
215                               genlist_append(req->winners, key);
216                     }
217           }
218 
219           /* Always traverse the whole list */
220           return NULL;
221 }
222 
223 struct genlist *
rsa_lookup_keys(struct ph1handle * iph1,int my)224 rsa_lookup_keys(struct ph1handle *iph1, int my)
225 {
226           struct genlist *list;
227           struct lookup_result r;
228 
229           plog(LLV_DEBUG, LOCATION, NULL, "Looking up RSA key for %s\n",
230                saddr2str_fromto("%s <-> %s", iph1->local, iph1->remote));
231 
232           r.iph1 = iph1;
233           r.max_score = -1;
234           r.winners = genlist_init();
235 
236           if (my)
237                     list = iph1->rmconf->rsa_private;
238           else
239                     list = iph1->rmconf->rsa_public;
240 
241           genlist_foreach(list, rsa_lookup_key_one, &r);
242 
243           if (loglevel >= LLV_DEBUG)
244                     rsa_key_dump(r.winners);
245 
246           return r.winners;
247 }
248 
249 int
rsa_parse_file(struct genlist * list,const char * fname,enum rsa_key_type type)250 rsa_parse_file(struct genlist *list, const char *fname, enum rsa_key_type type)
251 {
252           int ret;
253 
254           plog(LLV_DEBUG, LOCATION, NULL, "Parsing %s\n", fname);
255           ret = prsa_parse_file(list, fname, type);
256           if (loglevel >= LLV_DEBUG)
257                     rsa_key_dump(list);
258           return ret;
259 }
260 
261 RSA *
rsa_try_check_rsasign(vchar_t * source,vchar_t * sig,struct genlist * list)262 rsa_try_check_rsasign(vchar_t *source, vchar_t *sig, struct genlist *list)
263 {
264           struct rsa_key *key;
265           struct genlist_entry *gp;
266 
267           for(key = genlist_next(list, &gp); key; key = genlist_next(NULL, &gp)) {
268                     plog(LLV_DEBUG, LOCATION, NULL, "Checking key %s...\n",
269                               naddrwop2str_fromto("%s -> %s", key->src, key->dst));
270                     if (eay_check_rsasign(source, sig, key->rsa) == 0) {
271                               plog(LLV_DEBUG, LOCATION, NULL, " ... YEAH!\n");
272                               return key->rsa;
273                     }
274                     plog(LLV_DEBUG, LOCATION, NULL, " ... nope.\n");
275           }
276           return NULL;
277 }
278