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