]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/contrib/ipfilter/netinet/ip_pptp_pxy.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / contrib / ipfilter / netinet / ip_pptp_pxy.c
1 /*
2  * Copyright (C) 2012 by Darren Reed.
3  *
4  * Simple PPTP transparent proxy for in-kernel use.  For use with the NAT
5  * code.
6  *
7  * $Id$
8  *
9  */
10 #define IPF_PPTP_PROXY
11
12
13
14 /*
15  * PPTP proxy
16  */
17 typedef struct pptp_side {
18         u_32_t          pptps_nexthdr;
19         u_32_t          pptps_next;
20         int             pptps_state;
21         int             pptps_gothdr;
22         int             pptps_len;
23         int             pptps_bytes;
24         char            *pptps_wptr;
25         char            pptps_buffer[512];
26 } pptp_side_t;
27
28 typedef struct pptp_pxy {
29         nat_t           *pptp_nat;
30         struct ipstate  *pptp_state;
31         u_short         pptp_call[2];
32         pptp_side_t     pptp_side[2];
33         ipnat_t         *pptp_rule;
34 } pptp_pxy_t;
35
36 typedef struct pptp_hdr {
37         u_short         pptph_len;
38         u_short         pptph_type;
39         u_32_t          pptph_cookie;
40 } pptp_hdr_t;
41
42 #define PPTP_MSGTYPE_CTL        1
43 #define PPTP_MTCTL_STARTREQ     1
44 #define PPTP_MTCTL_STARTREP     2
45 #define PPTP_MTCTL_STOPREQ      3
46 #define PPTP_MTCTL_STOPREP      4
47 #define PPTP_MTCTL_ECHOREQ      5
48 #define PPTP_MTCTL_ECHOREP      6
49 #define PPTP_MTCTL_OUTREQ       7
50 #define PPTP_MTCTL_OUTREP       8
51 #define PPTP_MTCTL_INREQ        9
52 #define PPTP_MTCTL_INREP        10
53 #define PPTP_MTCTL_INCONNECT    11
54 #define PPTP_MTCTL_CLEAR        12
55 #define PPTP_MTCTL_DISCONNECT   13
56 #define PPTP_MTCTL_WANERROR     14
57 #define PPTP_MTCTL_LINKINFO     15
58
59
60 void ipf_p_pptp_main_load __P((void));
61 void ipf_p_pptp_main_unload __P((void));
62 int ipf_p_pptp_new __P((void *, fr_info_t *, ap_session_t *, nat_t *));
63 void ipf_p_pptp_del __P((ipf_main_softc_t *, ap_session_t *));
64 int ipf_p_pptp_inout __P((void *, fr_info_t *, ap_session_t *, nat_t *));
65 void ipf_p_pptp_donatstate __P((fr_info_t *, nat_t *, pptp_pxy_t *));
66 int ipf_p_pptp_message __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *));
67 int ipf_p_pptp_nextmessage __P((fr_info_t *, nat_t *, pptp_pxy_t *, int));
68 int ipf_p_pptp_mctl __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *));
69
70 static  frentry_t       pptpfr;
71
72 static  int     pptp_proxy_init = 0;
73 static  int     ipf_p_pptp_debug = 0;
74 static  int     ipf_p_pptp_gretimeout = IPF_TTLVAL(120);        /* 2 minutes */
75
76
77 /*
78  * PPTP application proxy initialization.
79  */
80 void
81 ipf_p_pptp_main_load()
82 {
83         bzero((char *)&pptpfr, sizeof(pptpfr));
84         pptpfr.fr_ref = 1;
85         pptpfr.fr_age[0] = ipf_p_pptp_gretimeout;
86         pptpfr.fr_age[1] = ipf_p_pptp_gretimeout;
87         pptpfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
88         MUTEX_INIT(&pptpfr.fr_lock, "PPTP proxy rule lock");
89         pptp_proxy_init = 1;
90 }
91
92
93 void
94 ipf_p_pptp_main_unload()
95 {
96         if (pptp_proxy_init == 1) {
97                 MUTEX_DESTROY(&pptpfr.fr_lock);
98                 pptp_proxy_init = 0;
99         }
100 }
101
102
103 /*
104  * Setup for a new PPTP proxy.
105  *
106  * NOTE: The printf's are broken up with %s in them to prevent them being
107  * optimised into puts statements on FreeBSD (this doesn't exist in the kernel)
108  */
109 int
110 ipf_p_pptp_new(arg, fin, aps, nat)
111         void *arg;
112         fr_info_t *fin;
113         ap_session_t *aps;
114         nat_t *nat;
115 {
116         pptp_pxy_t *pptp;
117         ipnat_t *ipn;
118         ipnat_t *np;
119         int size;
120         ip_t *ip;
121
122         if (fin->fin_v != 4)
123                 return -1;
124
125         ip = fin->fin_ip;
126         np = nat->nat_ptr;
127         size = np->in_size;
128
129         if (ipf_nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_osrcip,
130                           ip->ip_dst) != NULL) {
131                 if (ipf_p_pptp_debug > 0)
132                         printf("ipf_p_pptp_new: GRE session already exists\n");
133                 return -1;
134         }
135
136         KMALLOC(pptp, pptp_pxy_t *);
137         if (pptp == NULL) {
138                 if (ipf_p_pptp_debug > 0)
139                         printf("ipf_p_pptp_new: malloc for aps_data failed\n");
140                 return -1;
141         }
142         KMALLOCS(ipn, ipnat_t *, size);
143         if (ipn == NULL) {
144                 KFREE(pptp);
145                 return -1;
146         }
147
148         aps->aps_data = pptp;
149         aps->aps_psiz = sizeof(*pptp);
150         bzero((char *)pptp, sizeof(*pptp));
151         bzero((char *)ipn, size);
152         pptp->pptp_rule = ipn;
153
154         /*
155          * Create NAT rule against which the tunnel/transport mapping is
156          * created.  This is required because the current NAT rule does not
157          * describe GRE but TCP instead.
158          */
159         ipn->in_size = size;
160         ipn->in_ifps[0] = fin->fin_ifp;
161         ipn->in_apr = NULL;
162         ipn->in_use = 1;
163         ipn->in_hits = 1;
164         ipn->in_ippip = 1;
165         ipn->in_snip = ntohl(nat->nat_nsrcaddr);
166         ipn->in_nsrcaddr = fin->fin_saddr;
167         ipn->in_dnip = ntohl(nat->nat_ndstaddr);
168         ipn->in_ndstaddr = nat->nat_ndstaddr;
169         ipn->in_redir = np->in_redir;
170         ipn->in_osrcaddr = nat->nat_osrcaddr;
171         ipn->in_odstaddr = nat->nat_odstaddr;
172         ipn->in_osrcmsk = 0xffffffff;
173         ipn->in_nsrcmsk = 0xffffffff;
174         ipn->in_odstmsk = 0xffffffff;
175         ipn->in_ndstmsk = 0xffffffff;
176         ipn->in_flags = (np->in_flags | IPN_PROXYRULE);
177         MUTEX_INIT(&ipn->in_lock, "pptp proxy NAT rule");
178
179         ipn->in_namelen = np->in_namelen;
180         bcopy(np->in_names, ipn->in_ifnames, ipn->in_namelen);
181         ipn->in_ifnames[0] = np->in_ifnames[0];
182         ipn->in_ifnames[1] = np->in_ifnames[1];
183
184         ipn->in_pr[0] = IPPROTO_GRE;
185         ipn->in_pr[1] = IPPROTO_GRE;
186
187         pptp->pptp_side[0].pptps_wptr = pptp->pptp_side[0].pptps_buffer;
188         pptp->pptp_side[1].pptps_wptr = pptp->pptp_side[1].pptps_buffer;
189         return 0;
190 }
191
192
193 void
194 ipf_p_pptp_donatstate(fin, nat, pptp)
195         fr_info_t *fin;
196         nat_t *nat;
197         pptp_pxy_t *pptp;
198 {
199         ipf_main_softc_t *softc = fin->fin_main_soft;
200         fr_info_t fi;
201         grehdr_t gre;
202         nat_t *nat2;
203         u_char p;
204         ip_t *ip;
205
206         ip = fin->fin_ip;
207         p = ip->ip_p;
208
209         nat2 = pptp->pptp_nat;
210         if ((nat2 == NULL) || (pptp->pptp_state == NULL)) {
211                 bcopy((char *)fin, (char *)&fi, sizeof(fi));
212                 bzero((char *)&gre, sizeof(gre));
213                 fi.fin_fi.fi_p = IPPROTO_GRE;
214                 fi.fin_fr = &pptpfr;
215                 if ((nat->nat_dir == NAT_OUTBOUND && fin->fin_out) ||
216                     (nat->nat_dir == NAT_INBOUND && !fin->fin_out)) {
217                         fi.fin_data[0] = pptp->pptp_call[0];
218                         fi.fin_data[1] = pptp->pptp_call[1];
219                 } else {
220                         fi.fin_data[0] = pptp->pptp_call[1];
221                         fi.fin_data[1] = pptp->pptp_call[0];
222                 }
223                 ip = fin->fin_ip;
224                 ip->ip_p = IPPROTO_GRE;
225                 fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
226                 fi.fin_flx |= FI_IGNORE;
227                 fi.fin_dp = &gre;
228                 gre.gr_flags = htons(1 << 13);
229
230                 fi.fin_fi.fi_saddr = nat->nat_osrcaddr;
231                 fi.fin_fi.fi_daddr = nat->nat_odstaddr;
232         }
233
234         /*
235          * Update NAT timeout/create NAT if missing.
236          */
237         if (nat2 != NULL)
238                 ipf_queueback(softc->ipf_ticks, &nat2->nat_tqe);
239         else {
240 #ifdef USE_MUTEXES
241                 ipf_nat_softc_t *softn = softc->ipf_nat_soft;
242 #endif
243
244                 MUTEX_ENTER(&softn->ipf_nat_new);
245                 nat2 = ipf_nat_add(&fi, pptp->pptp_rule, &pptp->pptp_nat,
246                                    NAT_SLAVE, nat->nat_dir);
247                 MUTEX_EXIT(&softn->ipf_nat_new);
248                 if (nat2 != NULL) {
249                         (void) ipf_nat_proto(&fi, nat2, 0);
250                         MUTEX_ENTER(&nat2->nat_lock);
251                         ipf_nat_update(&fi, nat2);
252                         MUTEX_EXIT(&nat2->nat_lock);
253                 }
254         }
255
256         READ_ENTER(&softc->ipf_state);
257         if (pptp->pptp_state != NULL) {
258                 ipf_queueback(softc->ipf_ticks, &pptp->pptp_state->is_sti);
259                 RWLOCK_EXIT(&softc->ipf_state);
260         } else {
261                 RWLOCK_EXIT(&softc->ipf_state);
262                 if (nat2 != NULL) {
263                         if (nat->nat_dir == NAT_INBOUND)
264                                 fi.fin_fi.fi_daddr = nat2->nat_ndstaddr;
265                         else
266                                 fi.fin_fi.fi_saddr = nat2->nat_osrcaddr;
267                 }
268                 fi.fin_ifp = NULL;
269                 (void) ipf_state_add(softc, &fi, &pptp->pptp_state, 0);
270         }
271         ip->ip_p = p;
272         return;
273 }
274
275
276 /*
277  * Try and build up the next PPTP message in the TCP stream and if we can
278  * build it up completely (fits in our buffer) then pass it off to the message
279  * parsing function.
280  */
281 int
282 ipf_p_pptp_nextmessage(fin, nat, pptp, rev)
283         fr_info_t *fin;
284         nat_t *nat;
285         pptp_pxy_t *pptp;
286         int rev;
287 {
288         static const char *funcname = "ipf_p_pptp_nextmessage";
289         pptp_side_t *pptps;
290         u_32_t start, end;
291         pptp_hdr_t *hdr;
292         tcphdr_t *tcp;
293         int dlen, off;
294         u_short len;
295         char *msg;
296
297         tcp = fin->fin_dp;
298         dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
299         start = ntohl(tcp->th_seq);
300         pptps = &pptp->pptp_side[rev];
301         off = (char *)tcp - (char *)fin->fin_ip + (TCP_OFF(tcp) << 2) +
302               fin->fin_ipoff;
303
304         if (dlen <= 0)
305                 return 0;
306         /*
307          * If the complete data packet is before what we expect to see
308          * "next", just ignore it as the chances are we've already seen it.
309          * The next if statement following this one really just causes packets
310          * ahead of what we've seen to be dropped, implying that something in
311          * the middle went missing and we want to see that first.
312          */
313         end = start + dlen;
314         if (pptps->pptps_next > end && pptps->pptps_next > start)
315                 return 0;
316
317         if (pptps->pptps_next != start) {
318                 if (ipf_p_pptp_debug > 5)
319                         printf("%s: next (%x) != start (%x)\n", funcname,
320                                 pptps->pptps_next, start);
321                 return -1;
322         }
323
324         msg = (char *)fin->fin_dp + (TCP_OFF(tcp) << 2);
325
326         while (dlen > 0) {
327                 off += pptps->pptps_bytes;
328                 if (pptps->pptps_gothdr == 0) {
329                         /*
330                          * PPTP has an 8 byte header that inclues the cookie.
331                          * The start of every message should include one and
332                          * it should match 1a2b3c4d.  Byte order is ignored,
333                          * deliberately, when printing out the error.
334                          */
335                         len = MIN(8 - pptps->pptps_bytes, dlen);
336                         COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr);
337                         pptps->pptps_bytes += len;
338                         pptps->pptps_wptr += len;
339                         hdr = (pptp_hdr_t *)pptps->pptps_buffer;
340                         if (pptps->pptps_bytes == 8) {
341                                 pptps->pptps_next += 8;
342                                 if (ntohl(hdr->pptph_cookie) != 0x1a2b3c4d) {
343                                         if (ipf_p_pptp_debug > 1)
344                                                 printf("%s: bad cookie (%x)\n",
345                                                        funcname,
346                                                        hdr->pptph_cookie);
347                                         return -1;
348                                 }
349                         }
350                         dlen -= len;
351                         msg += len;
352                         off += len;
353
354                         pptps->pptps_gothdr = 1;
355                         len = ntohs(hdr->pptph_len);
356                         pptps->pptps_len = len;
357                         pptps->pptps_nexthdr += len;
358
359                         /*
360                          * If a message is too big for the buffer, just set
361                          * the fields for the next message to come along.
362                          * The messages defined in RFC 2637 will not exceed
363                          * 512 bytes (in total length) so this is likely a
364                          * bad data packet, anyway.
365                          */
366                         if (len > sizeof(pptps->pptps_buffer)) {
367                                 if (ipf_p_pptp_debug > 3)
368                                         printf("%s: message too big (%d)\n",
369                                                funcname, len);
370                                 pptps->pptps_next = pptps->pptps_nexthdr;
371                                 pptps->pptps_wptr = pptps->pptps_buffer;
372                                 pptps->pptps_gothdr = 0;
373                                 pptps->pptps_bytes = 0;
374                                 pptps->pptps_len = 0;
375                                 break;
376                         }
377                 }
378
379                 len = MIN(pptps->pptps_len - pptps->pptps_bytes, dlen);
380                 COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr);
381                 pptps->pptps_bytes += len;
382                 pptps->pptps_wptr += len;
383                 pptps->pptps_next += len;
384
385                 if (pptps->pptps_len > pptps->pptps_bytes)
386                         break;
387
388                 ipf_p_pptp_message(fin, nat, pptp, pptps);
389                 pptps->pptps_wptr = pptps->pptps_buffer;
390                 pptps->pptps_gothdr = 0;
391                 pptps->pptps_bytes = 0;
392                 pptps->pptps_len = 0;
393
394                 start += len;
395                 msg += len;
396                 dlen -= len;
397         }
398
399         return 0;
400 }
401
402
403 /*
404  * handle a complete PPTP message
405  */
406 int
407 ipf_p_pptp_message(fin, nat, pptp, pptps)
408         fr_info_t *fin;
409         nat_t *nat;
410         pptp_pxy_t *pptp;
411         pptp_side_t *pptps;
412 {
413         pptp_hdr_t *hdr = (pptp_hdr_t *)pptps->pptps_buffer;
414
415         switch (ntohs(hdr->pptph_type))
416         {
417         case PPTP_MSGTYPE_CTL :
418                 ipf_p_pptp_mctl(fin, nat, pptp, pptps);
419                 break;
420
421         default :
422                 break;
423         }
424         return 0;
425 }
426
427
428 /*
429  * handle a complete PPTP control message
430  */
431 int
432 ipf_p_pptp_mctl(fin, nat, pptp, pptps)
433         fr_info_t *fin;
434         nat_t *nat;
435         pptp_pxy_t *pptp;
436         pptp_side_t *pptps;
437 {
438         u_short *buffer = (u_short *)(pptps->pptps_buffer);
439         pptp_side_t *pptpo;
440
441         if (pptps == &pptp->pptp_side[0])
442                 pptpo = &pptp->pptp_side[1];
443         else
444                 pptpo = &pptp->pptp_side[0];
445
446         /*
447          * Breakout to handle all the various messages.  Most are just state
448          * transition.
449          */
450         switch (ntohs(buffer[4]))
451         {
452         case PPTP_MTCTL_STARTREQ :
453                 pptps->pptps_state = PPTP_MTCTL_STARTREQ;
454                 break;
455         case PPTP_MTCTL_STARTREP :
456                 if (pptpo->pptps_state == PPTP_MTCTL_STARTREQ)
457                         pptps->pptps_state = PPTP_MTCTL_STARTREP;
458                 break;
459         case PPTP_MTCTL_STOPREQ :
460                 pptps->pptps_state = PPTP_MTCTL_STOPREQ;
461                 break;
462         case PPTP_MTCTL_STOPREP :
463                 if (pptpo->pptps_state == PPTP_MTCTL_STOPREQ)
464                         pptps->pptps_state = PPTP_MTCTL_STOPREP;
465                 break;
466         case PPTP_MTCTL_ECHOREQ :
467                 pptps->pptps_state = PPTP_MTCTL_ECHOREQ;
468                 break;
469         case PPTP_MTCTL_ECHOREP :
470                 if (pptpo->pptps_state == PPTP_MTCTL_ECHOREQ)
471                         pptps->pptps_state = PPTP_MTCTL_ECHOREP;
472                 break;
473         case PPTP_MTCTL_OUTREQ :
474                 pptps->pptps_state = PPTP_MTCTL_OUTREQ;
475                 break;
476         case PPTP_MTCTL_OUTREP :
477                 if (pptpo->pptps_state == PPTP_MTCTL_OUTREQ) {
478                         pptps->pptps_state = PPTP_MTCTL_OUTREP;
479                         pptp->pptp_call[0] = buffer[7];
480                         pptp->pptp_call[1] = buffer[6];
481                         ipf_p_pptp_donatstate(fin, nat, pptp);
482                 }
483                 break;
484         case PPTP_MTCTL_INREQ :
485                 pptps->pptps_state = PPTP_MTCTL_INREQ;
486                 break;
487         case PPTP_MTCTL_INREP :
488                 if (pptpo->pptps_state == PPTP_MTCTL_INREQ) {
489                         pptps->pptps_state = PPTP_MTCTL_INREP;
490                         pptp->pptp_call[0] = buffer[7];
491                         pptp->pptp_call[1] = buffer[6];
492                         ipf_p_pptp_donatstate(fin, nat, pptp);
493                 }
494                 break;
495         case PPTP_MTCTL_INCONNECT :
496                 pptps->pptps_state = PPTP_MTCTL_INCONNECT;
497                 break;
498         case PPTP_MTCTL_CLEAR :
499                 pptps->pptps_state = PPTP_MTCTL_CLEAR;
500                 break;
501         case PPTP_MTCTL_DISCONNECT :
502                 pptps->pptps_state = PPTP_MTCTL_DISCONNECT;
503                 break;
504         case PPTP_MTCTL_WANERROR :
505                 pptps->pptps_state = PPTP_MTCTL_WANERROR;
506                 break;
507         case PPTP_MTCTL_LINKINFO :
508                 pptps->pptps_state = PPTP_MTCTL_LINKINFO;
509                 break;
510         }
511
512         return 0;
513 }
514
515
516 /*
517  * For outgoing PPTP packets.  refresh timeouts for NAT & state entries, if
518  * we can.  If they have disappeared, recreate them.
519  */
520 int
521 ipf_p_pptp_inout(arg, fin, aps, nat)
522         void *arg;
523         fr_info_t *fin;
524         ap_session_t *aps;
525         nat_t *nat;
526 {
527         pptp_pxy_t *pptp;
528         tcphdr_t *tcp;
529         int rev;
530
531         if ((fin->fin_out == 1) && (nat->nat_dir == NAT_INBOUND))
532                 rev = 1;
533         else if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND))
534                 rev = 1;
535         else
536                 rev = 0;
537
538         tcp = (tcphdr_t *)fin->fin_dp;
539         if ((tcp->th_flags & TH_OPENING) == TH_OPENING) {
540                 pptp = (pptp_pxy_t *)aps->aps_data;
541                 pptp->pptp_side[1 - rev].pptps_next = ntohl(tcp->th_ack);
542                 pptp->pptp_side[1 - rev].pptps_nexthdr = ntohl(tcp->th_ack);
543                 pptp->pptp_side[rev].pptps_next = ntohl(tcp->th_seq) + 1;
544                 pptp->pptp_side[rev].pptps_nexthdr = ntohl(tcp->th_seq) + 1;
545         }
546         return ipf_p_pptp_nextmessage(fin, nat, (pptp_pxy_t *)aps->aps_data,
547                                      rev);
548 }
549
550
551 /*
552  * clean up after ourselves.
553  */
554 void
555 ipf_p_pptp_del(softc, aps)
556         ipf_main_softc_t *softc;
557         ap_session_t *aps;
558 {
559         pptp_pxy_t *pptp;
560
561         pptp = aps->aps_data;
562
563         if (pptp != NULL) {
564                 /*
565                  * Don't bother changing any of the NAT structure details,
566                  * *_del() is on a callback from aps_free(), from nat_delete()
567                  */
568
569                 READ_ENTER(&softc->ipf_state);
570                 if (pptp->pptp_state != NULL) {
571                         ipf_state_setpending(softc, pptp->pptp_state);
572                 }
573                 RWLOCK_EXIT(&softc->ipf_state);
574
575                 if (pptp->pptp_nat != NULL)
576                         ipf_nat_setpending(softc, pptp->pptp_nat);
577                 pptp->pptp_rule->in_flags |= IPN_DELETE;
578                 ipf_nat_rule_deref(softc, &pptp->pptp_rule);
579         }
580 }