]> git.saurik.com Git - apple/network_cmds.git/blame_incremental - racoon.tproj/isakmp_natd.c
network_cmds-245.8.tar.gz
[apple/network_cmds.git] / racoon.tproj / isakmp_natd.c
... / ...
CommitLineData
1
2#include <sys/types.h>
3#include <sys/queue.h>
4#include <sys/socket.h>
5#include <netinet/in.h>
6#include <arpa/inet.h>
7
8#include <string.h>
9
10#include "vmbuf.h"
11#include "plog.h"
12#include "misc.h"
13#include "isakmp_var.h"
14#include "oakley.h"
15#include "isakmp.h"
16
17#include "handler.h"
18#include "isakmp_natd.h"
19
20natd_match_t
21natd_matches(
22 struct ph1handle* iph1,
23 struct isakmp_gen *natd_record)
24{
25 natd_match_t matches = 0;
26#ifdef IKE_NAT_T
27 int dataLen = ntohs(natd_record->len) - sizeof(*natd_record);
28 char* dataPtr = ((char*)natd_record) + sizeof(*natd_record);
29
30 /* Always recreate the natd records in case the ports change */
31 natd_create(iph1);
32
33 if (iph1->local_natd != NULL && dataLen == iph1->local_natd->l &&
34 memcmp(dataPtr, iph1->local_natd->v, dataLen) == 0)
35 {
36 plog(LLV_DEBUG, LOCATION, iph1->remote,
37 "natd payload matches local address\n");
38 matches |= natd_match_local;
39 }
40
41 if (iph1->remote_natd != NULL && dataLen == iph1->remote_natd->l &&
42 memcmp(dataPtr, iph1->remote_natd->v, dataLen) == 0)
43 {
44 plog(LLV_DEBUG, LOCATION, iph1->remote,
45 "natd payload matches remote address\n");
46 matches |= natd_match_remote;
47 }
48#else
49 matches = natd_match_local | natd_match_remote;
50#endif
51
52 if (matches == 0)
53 {
54 plog(LLV_DEBUG, LOCATION, iph1->remote,
55 "natd payload matches no address\n");
56 }
57
58 return matches;
59}
60
61/*
62 * NAT detection record contains a hash of the initiator cookie,
63 * responder cookie, address, and port.
64 */
65typedef struct {
66 cookie_t initiator_cookie;
67 cookie_t responder_cookie;
68 struct in_addr address;
69 u_short port;
70} __attribute__((__packed__)) natd_hash_contents;
71
72int
73natd_create(
74 struct ph1handle* iph1)
75{
76#ifdef IKE_NAT_T
77 natd_hash_contents hash_this;
78 vchar_t data_to_hash;
79
80 if (iph1->remote->sa_family != AF_INET ||
81 iph1->local->sa_family != AF_INET)
82 {
83 /*
84 * NAT traversal is intentionally unsupported on IPv6.
85 */
86 return -1;
87 }
88
89 data_to_hash.l = sizeof(hash_this);
90 data_to_hash.v = (char*)&hash_this;
91
92 memcpy(hash_this.initiator_cookie, iph1->index.i_ck,
93 sizeof(hash_this.initiator_cookie));
94 memcpy(hash_this.responder_cookie, iph1->index.r_ck,
95 sizeof(hash_this.responder_cookie));
96
97 /* Local address */
98 if (iph1->local_natd != NULL)
99 vfree(iph1->local_natd);
100 iph1->local_natd = NULL;
101 hash_this.address = ((struct sockaddr_in*)(iph1->local))->sin_addr;
102 hash_this.port = ((struct sockaddr_in*)(iph1->local))->sin_port;
103 plog(LLV_DEBUG, LOCATION, iph1->remote,
104 "creating local %.8X%.8X:%.8X%.8X %s:%d\n",
105 *(u_long*)&hash_this.initiator_cookie[0],
106 *(u_long*)&hash_this.initiator_cookie[4],
107 *(u_long*)&hash_this.responder_cookie[0],
108 *(u_long*)&hash_this.responder_cookie[4],
109 inet_ntoa(hash_this.address), hash_this.port);
110 iph1->local_natd = oakley_hash(&data_to_hash, iph1);
111 plogdump(LLV_DEBUG, iph1->local_natd->v, iph1->local_natd->l);
112
113 /* Remote address */
114 if (iph1->remote_natd != NULL)
115 vfree(iph1->remote_natd);
116 iph1->remote_natd = NULL;
117 hash_this.address = ((struct sockaddr_in*)(iph1->remote))->sin_addr;
118 hash_this.port = ((struct sockaddr_in*)(iph1->remote))->sin_port;
119 plog(LLV_DEBUG, LOCATION, iph1->remote,
120 "creating remote %.8X%.8X:%.8X%.8X %s:%d\n",
121 *(u_long*)&hash_this.initiator_cookie[0],
122 *(u_long*)&hash_this.initiator_cookie[4],
123 *(u_long*)&hash_this.responder_cookie[0],
124 *(u_long*)&hash_this.responder_cookie[4],
125 inet_ntoa(hash_this.address), hash_this.port);
126 iph1->remote_natd = oakley_hash(&data_to_hash, iph1);
127 plogdump(LLV_DEBUG, iph1->remote_natd->v, iph1->remote_natd->l);
128
129 return (iph1->local_natd != NULL) && (iph1->remote_natd != NULL);
130#else
131 return 0;
132#endif
133}
134
135/* returns the natt type - or 0 if no natt */
136int
137natd_hasnat(
138 const struct ph1handle* iph1)
139{
140#if IKE_NAT_T
141 if ((iph1->natt_flags & natt_natd_received) &&
142 ((iph1->natt_flags & (natt_no_remote_nat | natt_no_local_nat)) !=
143 (natt_no_remote_nat | natt_no_local_nat)))
144 return iph1->natt_flags & NATT_TYPE_MASK;
145 else
146#endif
147 return 0;
148
149}
150
151
152void
153natt_select_type(struct ph1handle* iph1)
154{
155#if IKE_NAT_T
156 int flags = iph1->natt_flags;
157
158 if ((flags & NATT_TYPE_MASK) == 0) {
159 iph1->natd_payload_type = 0;
160 return;
161 }
162
163 iph1->natt_flags &= ~NATT_TYPE_MASK; // clear natt type flags
164
165 /* set the type we prefer */
166 if (flags & natt_type_rfc) {
167 iph1->natt_flags |= natt_type_rfc;
168 iph1->natd_payload_type = ISAKMP_NPTYPE_NATD_RFC;
169 plog(LLV_DEBUG, LOCATION, NULL,
170 "choosing natt type RFC\n");
171
172 } else if (flags & natt_type_apple) {
173 iph1->natt_flags |= natt_type_apple;
174 iph1->natd_payload_type = ISAKMP_NPTYPE_NATD_BADDRAFT;
175 plog(LLV_DEBUG, LOCATION, NULL,
176 "choosing natt type APPLE\n");
177 } else {
178 iph1->natd_payload_type = ISAKMP_NPTYPE_NATD_DRAFT;
179 if (flags & natt_type_02) {
180 iph1->natt_flags |= natt_type_02;
181 plog(LLV_DEBUG, LOCATION, NULL,
182 "choosing natt type 02\n");
183 } else {
184 iph1->natt_flags |= natt_type_02N;
185 plog(LLV_DEBUG, LOCATION, NULL,
186 "choosing natt type 02N\n");
187 }
188
189 }
190
191#endif
192}
193
194
195