1 /*        $NetBSD: isakmp_newg.c,v 1.5 2025/03/07 15:55:29 christos Exp $       */
2 
3 /*        $KAME: isakmp_newg.c,v 1.10 2002/09/27 05:55:52 itojun Exp $          */
4 
5 /*
6  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the project nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "config.h"
35 
36 #include <sys/types.h>
37 #include <sys/param.h>
38 
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <errno.h>
43 
44 #include "var.h"
45 #include "misc.h"
46 #include "vmbuf.h"
47 #include "plog.h"
48 #include "sockmisc.h"
49 #include "debug.h"
50 
51 #include "schedule.h"
52 #include "cfparse_proto.h"
53 #include "isakmp_var.h"
54 #include "isakmp.h"
55 #include "isakmp_newg.h"
56 #include "oakley.h"
57 #include "ipsec_doi.h"
58 #include "crypto_openssl.h"
59 #include "handler.h"
60 #include "pfkey.h"
61 #include "admin.h"
62 #include "str2val.h"
63 #include "vendorid.h"
64 
65 /*
66  * New group mode as responder
67  */
68 /*ARGSUSED*/
69 int
isakmp_newgroup_r(struct ph1handle * iph1 __unused,vchar_t * msg __unused)70 isakmp_newgroup_r(struct ph1handle *iph1 __unused, vchar_t *msg __unused)
71 {
72 #if 0
73           struct isakmp *isakmp = (struct isakmp *)msg->v;
74           struct isakmp_pl_hash *hash = NULL;
75           struct isakmp_pl_sa *sa = NULL;
76           int error = -1;
77           vchar_t *buf;
78           struct oakley_sa *osa;
79           int len;
80 
81           /* validate the type of next payload */
82           /*
83            * ISAKMP_ETYPE_NEWGRP,
84            * ISAKMP_NPTYPE_HASH, (ISAKMP_NPTYPE_VID), ISAKMP_NPTYPE_SA,
85            * ISAKMP_NPTYPE_NONE
86            */
87     {
88           vchar_t *pbuf = NULL;
89           struct isakmp_parse_t *pa;
90 
91           if ((pbuf = isakmp_parse(msg)) == NULL)
92                     goto end;
93 
94           for (pa = (struct isakmp_parse_t *)pbuf->v;
95                pa->type != ISAKMP_NPTYPE_NONE;
96                pa++) {
97 
98                     switch (pa->type) {
99                     case ISAKMP_NPTYPE_HASH:
100                               if (hash) {
101                                         isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
102                                         plog(LLV_ERROR, LOCATION, iph1->remote,
103                                                   "received multiple payload type %d.\n",
104                                                   pa->type);
105                                         vfree(pbuf);
106                                         goto end;
107                               }
108                               hash = (struct isakmp_pl_hash *)pa->ptr;
109                               break;
110                     case ISAKMP_NPTYPE_SA:
111                               if (sa) {
112                                         isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
113                                         plog(LLV_ERROR, LOCATION, iph1->remote,
114                                                   "received multiple payload type %d.\n",
115                                                   pa->type);
116                                         vfree(pbuf);
117                                         goto end;
118                               }
119                               sa = (struct isakmp_pl_sa *)pa->ptr;
120                               break;
121                     case ISAKMP_NPTYPE_VID:
122                               (void)check_vendorid(pa->ptr);
123                               break;
124                     default:
125                               isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
126                               plog(LLV_ERROR, LOCATION, iph1->remote,
127                                         "ignore the packet, "
128                                         "received unexpecting payload type %d.\n",
129                                         pa->type);
130                               vfree(pbuf);
131                               goto end;
132                     }
133           }
134           vfree(pbuf);
135 
136           if (!hash || !sa) {
137                     isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
138                     plog(LLV_ERROR, LOCATION, iph1->remote,
139                               "no HASH, or no SA payload.\n");
140                     goto end;
141           }
142     }
143 
144           /* validate HASH */
145     {
146           char *r_hash;
147           vchar_t *my_hash = NULL;
148           int result;
149 
150           plog(LLV_DEBUG, LOCATION, NULL, "validate HASH\n");
151 
152           len = sizeof(isakmp->msgid) + ntohs(sa->h.len);
153           buf = vmalloc(len);
154           if (buf == NULL) {
155                     plog(LLV_ERROR, LOCATION, NULL,
156                               "failed to get buffer to send.\n");
157                     goto end;
158           }
159           memcpy(buf->v, &isakmp->msgid, sizeof(isakmp->msgid));
160           memcpy(buf->v + sizeof(isakmp->msgid), sa, ntohs(sa->h.len));
161 
162           plog(LLV_DEBUG, LOCATION, NULL, "hash source\n");
163           plogdump(LLV_DEBUG, buf->v, buf->l);
164 
165           my_hash = isakmp_prf(iph1->skeyid_a, buf, iph1);
166           vfree(buf);
167           if (my_hash == NULL)
168                     goto end;
169 
170           plog(LLV_DEBUG, LOCATION, NULL, "hash result\n");
171           plogdump(LLV_DEBUG, my_hash->v, my_hash->l);
172 
173           r_hash = (char *)hash + sizeof(*hash);
174 
175           plog(LLV_DEBUG, LOCATION, NULL, "original hash\n"));
176           plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash)));
177 
178           result = memcmp(my_hash->v, r_hash, my_hash->l);
179           vfree(my_hash);
180 
181           if (result) {
182                     plog(LLV_ERROR, LOCATION, iph1->remote,
183                               "HASH mismatch.\n");
184                     isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_HASH_INFORMATION, NULL);
185                     goto end;
186           }
187     }
188 
189           /* check SA payload and get new one for use */
190           buf = ipsecdoi_get_proposal((struct ipsecdoi_sa *)sa,
191                                                   OAKLEY_NEWGROUP_MODE);
192           if (buf == NULL) {
193                     isakmp_info_send_n1(iph1, ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED, NULL);
194                     goto end;
195           }
196 
197           /* save sa parameters */
198           osa = ipsecdoi_get_oakley(buf);
199           if (osa == NULL) {
200                     isakmp_info_send_n1(iph1, ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED, NULL);
201                     goto end;
202           }
203           vfree(buf);
204 
205           switch (osa->dhgrp) {
206           case OAKLEY_ATTR_GRP_DESC_MODP768:
207           case OAKLEY_ATTR_GRP_DESC_MODP1024:
208           case OAKLEY_ATTR_GRP_DESC_MODP1536:
209                     /*XXX*/
210           default:
211                     isakmp_info_send_n1(iph1, ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED, NULL);
212                     plog(LLV_ERROR, LOCATION, NULL,
213                               "dh group %d isn't supported.\n", osa->dhgrp);
214                     goto end;
215           }
216 
217           plog(LLV_INFO, LOCATION, iph1->remote,
218                     "got new dh group %s.\n", isakmp_pindex(&iph1->index, 0));
219 
220           error = 0;
221 
222 end:
223           if (error) {
224                     if (iph1 != NULL)
225                               (void)isakmp_free_ph1(iph1);
226           }
227           return error;
228 #endif
229           return 0;
230 }
231 
232