blob: 7a58a27cf12c5006ac4f656805ad58490e8c7d1c [file] [log] [blame]
Chia-chi Yeh063bb922009-06-15 14:43:38 +08001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* A simple implementation of PPTP Network Server (RFC 2637) which only
18 * creates a single session. The following code only handles control packets.
19 * Data packets are handled by PPPoPNS driver which can be found in Android
20 * kernel tree. */
21
Sam Protsenko0368bbd2018-06-08 01:11:16 +030022#include <stdbool.h>
Chia-chi Yeh063bb922009-06-15 14:43:38 +080023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <errno.h>
27#include <sys/types.h>
28#include <sys/socket.h>
Sam Protsenko0368bbd2018-06-08 01:11:16 +030029#include <netdb.h>
30#include <unistd.h>
Chia-chi Yeh063bb922009-06-15 14:43:38 +080031#include <arpa/inet.h>
Chia-chi Yeh0f725852011-07-18 13:57:17 -070032#include <linux/netdevice.h>
33#include <linux/if_pppox.h>
Sam Protsenko537773c2018-06-25 21:20:39 +030034#include <linux/types.h>
Chia-chi Yeh063bb922009-06-15 14:43:38 +080035
36#include "mtpd.h"
37
38enum pptp_message {
39 SCCRQ = 1,
40 SCCRP = 2,
41 STOPCCRQ = 3,
42 STOPCCRP = 4,
43 ECHORQ = 5,
44 ECHORP = 6,
45 OCRQ = 7,
46 OCRP = 8,
47 ICRQ = 9,
48 ICRP = 10,
49 ICCN = 11,
50 CCRQ = 12,
51 CDN = 13,
52 WEN = 14,
53 SLI = 15,
54 MESSAGE_MAX = 15,
55};
56
57static char *messages[] = {
58 NULL, "SCCRQ", "SCCRP", "STOPCCRQ", "STOPCCRP", "ECHORQ", "ECHORP",
59 "OCRQ", "OCRP", "ICRQ", "ICRP", "ICCN", "CCRQ", "CDN", "WEN", "SLI",
60};
61
62static uint8_t lengths[] = {
63 0, 156, 156, 16, 16, 16, 20, 168, 32, 220, 24, 28, 16, 148, 40, 24,
64};
65
66#define CONTROL_MESSAGE htons(1)
67#define MAGIC_COOKIE htonl(0x1A2B3C4D)
68#define PROTOCOL_VERSION htons(0x0100)
69
70#define RESULT_OK 1
71#define RESULT_ERROR 2
72
73/* Some implementation uses 0 instead of 1, so we allow both of them. */
74#define ESTABLISHED(result) (result <= 1)
75
76#define HEADER_SIZE 8
77#define MIN_MESSAGE_SIZE 10
78
Sam Protsenko537773c2018-06-25 21:20:39 +030079static __be16 local;
80static __be16 remote;
Chia-chi Yeh063bb922009-06-15 14:43:38 +080081static uint16_t state;
Sam Protsenko0368bbd2018-06-08 01:11:16 +030082static const char *remote_name; /* server host name or IP address */
Chia-chi Yeh063bb922009-06-15 14:43:38 +080083
84#define MAX_PACKET_LENGTH 220
85
86/* We define all the fields we used in this structure. Type conversion and byte
87 * alignment are solved in one place. Although it looks a little bit ugly, it
88 * really makes life easier. */
89static struct packet {
90 int length;
91 int expect;
92 union {
93 uint8_t buffer[MAX_PACKET_LENGTH];
94 struct {
95 struct __attribute__((packed)) {
96 uint16_t length;
97 uint16_t type;
98 uint32_t cookie;
99 } header;
100 uint16_t message;
101 uint16_t reserved;
102 union {
103 struct __attribute__((packed)) {
104 uint16_t protocol_version;
105 uint8_t result;
106 uint8_t error;
107 uint32_t framing;
108 uint32_t bearer;
109 uint16_t channels;
110 uint16_t firmware_revision;
111 char host[64];
112 } sccrp, sccrq;
113 struct __attribute__((packed)) {
114 uint16_t call;
115 uint16_t serial;
116 uint32_t minimum_speed;
117 uint32_t maximum_speed;
118 uint32_t bearer;
119 uint32_t framing;
120 uint16_t window_size;
121 } ocrq;
122 struct __attribute__((packed)) {
123 uint16_t call;
124 uint16_t peer;
125 uint8_t result;
126 } ocrp, icrp;
127 struct __attribute__((packed)) {
128 uint32_t identifier;
129 uint8_t result;
130 } echorq, echorp;
131 struct __attribute__((packed)) {
132 uint16_t call;
133 } icrq, ccrq, cdn;
134 };
135 } __attribute__((packed));
136 } __attribute__((aligned(4)));
137} incoming, outgoing;
138
139static void set_message(uint16_t message)
140{
141 uint16_t length = lengths[message];
142 memset(outgoing.buffer, 0, length);
143 outgoing.length = length;
144 outgoing.header.length = htons(length);
145 outgoing.header.type = CONTROL_MESSAGE;
146 outgoing.header.cookie = MAGIC_COOKIE;
147 outgoing.message = htons(message);
148}
149
150static void send_packet()
151{
152 send(the_socket, outgoing.buffer, outgoing.length, 0);
153}
154
155static int recv_packet()
156{
157 int length;
158
159 /* We are going to read a new message if incoming.expect is 0. */
160 if (!incoming.expect) {
161 incoming.length = 0;
162 incoming.expect = HEADER_SIZE;
163 }
164
165 /* The longest message defined in RFC 2637 is 220 bytes, but the protocol
166 * itself allows up to 65536 bytes. Therefore we always read a complete
167 * message but only keep the first 220 bytes before passing up. */
168 length = incoming.expect - incoming.length;
169 if (incoming.length >= MAX_PACKET_LENGTH) {
170 uint8_t buffer[length];
171 length = recv(the_socket, buffer, length, 0);
172 } else {
173 if (incoming.expect > MAX_PACKET_LENGTH) {
174 length = MAX_PACKET_LENGTH - incoming.length;
175 }
176 length = recv(the_socket, &incoming.buffer[incoming.length], length, 0);
177 }
178 if (length == -1) {
179 if (errno == EINTR) {
180 return 0;
181 }
182 log_print(FATAL, "Recv() %s", strerror(errno));
183 exit(NETWORK_ERROR);
184 }
185 if (length == 0) {
186 log_print(DEBUG, "Connection closed");
187 log_print(INFO, "Remote server hung up");
188 return -REMOTE_REQUESTED;
189 }
190 incoming.length += length;
191
192 /* If incoming.header is valid, check cookie and update incoming.expect. */
193 if (incoming.length == HEADER_SIZE && incoming.expect == HEADER_SIZE) {
194 if (incoming.header.cookie != MAGIC_COOKIE) {
195 log_print(DEBUG, "Loss of synchronization");
196 log_print(ERROR, "Protocol error");
197 return -PROTOCOL_ERROR;
198 }
199 incoming.expect = ntohs(incoming.header.length);
200 if (incoming.expect < HEADER_SIZE) {
201 log_print(DEBUG, "Invalid message length");
202 log_print(ERROR, "Protocol error");
203 return -PROTOCOL_ERROR;
204 }
205 }
206
207 /* Now we have a complete message. Reset incoming.expect. */
208 if (incoming.length == incoming.expect) {
209 incoming.expect = 0;
210
211 /* Return 1 if it is a control message. */
212 if (incoming.header.type == CONTROL_MESSAGE) {
213 return 1;
214 }
Sam Protsenko537773c2018-06-25 21:20:39 +0300215 log_print(DEBUG, "Ignored non-control message (type = %u)",
216 (unsigned)ntohs(incoming.header.type));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800217 }
218 return 0;
219}
220
Chia-chi Yeh7b66d202011-06-28 16:39:23 -0700221static int pptp_connect(char **arguments)
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800222{
Sam Protsenko0368bbd2018-06-08 01:11:16 +0300223 remote_name = arguments[0];
224
Chia-chi Yeh7b66d202011-06-28 16:39:23 -0700225 create_socket(AF_UNSPEC, SOCK_STREAM, arguments[0], arguments[1]);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800226
227 log_print(DEBUG, "Sending SCCRQ");
228 state = SCCRQ;
229 set_message(SCCRQ);
230 outgoing.sccrq.protocol_version = PROTOCOL_VERSION;
231 outgoing.sccrq.framing = htonl(3);
232 outgoing.sccrq.bearer = htonl(3);
233 outgoing.sccrq.channels = htons(1);
234 strcpy(outgoing.sccrq.host, "anonymous");
235 send_packet();
236 return 0;
237}
238
Sam Protsenko0368bbd2018-06-08 01:11:16 +0300239/**
Alistair Strachana378c552019-05-28 17:18:36 -0700240 * Check if upstream kernel implementation of PPTP should be used.
Sam Protsenko0368bbd2018-06-08 01:11:16 +0300241 *
Alistair Strachana378c552019-05-28 17:18:36 -0700242 * @return true If upstream PPTP should be used, which is the case if
243 * the obsolete OPNS feature is not available.
Sam Protsenko0368bbd2018-06-08 01:11:16 +0300244 */
245static bool check_pptp(void)
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800246{
Alistair Strachana378c552019-05-28 17:18:36 -0700247 int fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OPNS);
Sam Protsenko0368bbd2018-06-08 01:11:16 +0300248
249 if (fd < 0) {
Alistair Strachana378c552019-05-28 17:18:36 -0700250 return true;
Sam Protsenko0368bbd2018-06-08 01:11:16 +0300251 } else {
252 close(fd);
Alistair Strachana378c552019-05-28 17:18:36 -0700253 return false;
Sam Protsenko0368bbd2018-06-08 01:11:16 +0300254 }
255}
256
257/**
258 * Create OPNS session.
259 *
260 * @deprecated It will be removed soon in favor of upstream PPTP.
261 *
262 * @return PPPoX socket file descriptor
263 */
264static int create_pppox_opns(void)
265{
266 int pppox;
267
268 log_print(WARNING, "Using deprecated OPNS protocol. "
269 "Its support will be removed soon. "
270 "Please enable PPTP support in your kernel");
271
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800272 log_print(INFO, "Creating PPPoX socket");
Sam Protsenko0368bbd2018-06-08 01:11:16 +0300273 pppox = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OPNS);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800274
275 if (pppox == -1) {
276 log_print(FATAL, "Socket() %s", strerror(errno));
Chia-chi Yeh0f725852011-07-18 13:57:17 -0700277 exit(SYSTEM_ERROR);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800278 } else {
279 struct sockaddr_pppopns address = {
280 .sa_family = AF_PPPOX,
Chia-chi Yeh0f725852011-07-18 13:57:17 -0700281 .sa_protocol = PX_PROTO_OPNS,
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800282 .tcp_socket = the_socket,
283 .local = local,
284 .remote = remote,
285 };
Chia-chi Yehea299e62011-07-13 19:36:46 -0700286 if (connect(pppox, (struct sockaddr *)&address, sizeof(address))) {
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800287 log_print(FATAL, "Connect() %s", strerror(errno));
Chia-chi Yeh0f725852011-07-18 13:57:17 -0700288 exit(SYSTEM_ERROR);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800289 }
290 }
291 return pppox;
292}
293
Sam Protsenko0368bbd2018-06-08 01:11:16 +0300294/**
295 * Get IP address by host name.
296 *
297 * @param name Host name to get IP address for
298 *
299 * @return IP address for given host name
300 */
301static struct in_addr get_addr_by_name(const char *name)
302{
303 struct addrinfo hints;
304 struct addrinfo *res, *rp;
305 struct in_addr addr;
306 int err;
307
308 memset(&hints, 0, sizeof(struct addrinfo));
309 hints.ai_family = AF_INET; /* allow only IPv4 */
310 hints.ai_socktype = SOCK_DGRAM; /* UDP */
311 hints.ai_protocol = 0; /* any protocol */
312
313 err = getaddrinfo(name, NULL, &hints, &res);
314 if (err) {
315 log_print(FATAL, "%s: getaddrinfo: %s", __func__, gai_strerror(err));
316 exit(SYSTEM_ERROR);
317 }
318
319 for (rp = res; rp != NULL; rp = rp->ai_next) {
320 /* For now we only support IPv4 */
321 if (rp->ai_family == AF_INET) {
322 addr = ((struct sockaddr_in *)rp->ai_addr)->sin_addr;
323 break;
324 }
325 }
326
327 if (rp == NULL) {
328 log_print(FATAL, "%s: No IPv4 addresses found", __func__);
329 freeaddrinfo(res);
330 exit(SYSTEM_ERROR);
331 }
332
333 freeaddrinfo(res);
334
335 return addr;
336}
337
338/**
339 * Get local IP address.
340 *
341 * Make a socket connection with remote server and then call getsockname() on
342 * the connected socket. This will return the local IP address.
343 *
344 * @param remote_addr Server IP address
345 *
346 * @return Local IP address
347 */
348static struct in_addr get_local_addr(struct in_addr remote_addr)
349{
350 int sock;
351 struct sockaddr_in addr;
352 socklen_t addr_len;
353
354 addr_len = sizeof(struct sockaddr_in);
355 addr.sin_addr = remote_addr;
356 addr.sin_family = AF_INET;
357 addr.sin_port = htons(0);
358
359 sock = socket(AF_INET, SOCK_DGRAM, 0);
360 if (sock < 0) {
361 log_print(FATAL, "%s: Socket() %s", __func__, strerror(errno));
362 exit(SYSTEM_ERROR);
363 }
364
365 if (connect(sock, (struct sockaddr*)&addr, sizeof(addr))) {
366 close(sock);
367 log_print(FATAL, "%s: Connect() %s", __func__, strerror(errno));
368 exit(SYSTEM_ERROR);
369 }
370
371 getsockname(sock, (struct sockaddr*)&addr, &addr_len);
372 close(sock);
373
374 return addr.sin_addr;
375}
376
377/**
378 * Create PPTP session.
379 *
380 * @return PPTP socket file descriptor
381 */
382static int create_pppox_pptp(void)
383{
384 int pptp_fd;
385 struct sockaddr_pppox src, dst;
386 struct in_addr remote_addr; /* server IP address */
387 struct in_addr local_addr; /* client IP address */
388
389 remote_addr = get_addr_by_name(remote_name);
390 local_addr = get_local_addr(remote_addr);
391
392 src.sa_family = AF_PPPOX;
393 src.sa_protocol = PX_PROTO_PPTP;
394 src.sa_addr.pptp.call_id = ntohs(local);
395 src.sa_addr.pptp.sin_addr = local_addr;
396
397 dst.sa_family = AF_PPPOX;
398 dst.sa_protocol = PX_PROTO_PPTP;
399 dst.sa_addr.pptp.call_id = ntohs(remote);
400 dst.sa_addr.pptp.sin_addr = remote_addr;
401
402 pptp_fd = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_PPTP);
403 if (pptp_fd < 0) {
404 log_print(FATAL, "Failed to create PPTP socket (%s)", strerror(errno));
405 exit(SYSTEM_ERROR);
406 }
407
408 if (bind(pptp_fd, (struct sockaddr*)&src, sizeof(src))) {
409 log_print(FATAL, "Failed to bind PPTP socket (%s)", strerror(errno));
410 close(pptp_fd);
411 exit(SYSTEM_ERROR);
412 }
413
414 if (connect(pptp_fd, (struct sockaddr*)&dst, sizeof(dst))) {
415 log_print(FATAL, "Failed to connect PPTP socket (%s)", strerror(errno));
416 close(pptp_fd);
417 exit(SYSTEM_ERROR);
418 }
419
420 return pptp_fd;
421}
422
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800423static int pptp_process()
424{
425 int result = recv_packet();
426 if (result <= 0) {
427 return result;
428 }
429
430 if (incoming.length < MIN_MESSAGE_SIZE) {
431 log_print(DEBUG, "Control message too short");
432 return 0;
433 }
434 incoming.message = ntohs(incoming.message);
435 if (incoming.message > MESSAGE_MAX || !messages[incoming.message]) {
436 log_print(DEBUG, "Received UNKNOWN %d", incoming.message);
437 return 0;
438 }
439 if (incoming.length < lengths[incoming.message]) {
440 log_print(DEBUG, "Received %s with invalid length (length = %d)",
Chia-chi Yehea299e62011-07-13 19:36:46 -0700441 messages[incoming.message], incoming.length);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800442 return 0;
443 }
444
445 switch(incoming.message) {
446 case SCCRP:
447 if (state == SCCRQ) {
Chia-chi Yehea299e62011-07-13 19:36:46 -0700448 if (incoming.sccrp.protocol_version == PROTOCOL_VERSION &&
449 ESTABLISHED(incoming.sccrp.result)) {
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800450 while (!local) {
451 local = random();
452 }
453 log_print(DEBUG, "Received SCCRP -> Sending OCRQ "
Sam Protsenko537773c2018-06-25 21:20:39 +0300454 "(local = %u)", (unsigned)ntohs(local));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800455 log_print(INFO, "Tunnel established");
456 state = OCRQ;
457 set_message(OCRQ);
458 outgoing.ocrq.call = local;
459 outgoing.ocrq.serial = random();
460 outgoing.ocrq.minimum_speed = htonl(1000);
461 outgoing.ocrq.maximum_speed = htonl(100000000);
462 outgoing.ocrq.bearer = htonl(3);
463 outgoing.ocrq.framing = htonl(3);
464 outgoing.ocrq.window_size = htons(8192);
465 send_packet();
466 return 0;
467 }
468 log_print(DEBUG, "Received SCCRP (result = %d)",
Chia-chi Yehea299e62011-07-13 19:36:46 -0700469 incoming.sccrq.result);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800470 log_print(INFO, "Remote server hung up");
471 return -REMOTE_REQUESTED;
472 }
473 break;
474
475 case OCRP:
476 if (state == OCRQ && incoming.ocrp.peer == local) {
477 if (ESTABLISHED(incoming.ocrp.result)) {
478 remote = incoming.ocrp.call;
Sam Protsenko537773c2018-06-25 21:20:39 +0300479 log_print(DEBUG, "Received OCRQ (remote = %u)",
480 (unsigned)ntohs(remote));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800481 log_print(INFO, "Session established");
482 state = OCRP;
Sam Protsenko0368bbd2018-06-08 01:11:16 +0300483
484 if (check_pptp())
485 start_pppd_pptp(create_pppox_pptp());
486 else
487 start_pppd(create_pppox_opns());
488
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800489 return 0;
490 }
491 log_print(DEBUG, "Received OCRP (result = %d)",
Chia-chi Yehea299e62011-07-13 19:36:46 -0700492 incoming.ocrp.result);
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800493 log_print(INFO, "Remote server hung up");
494 return -REMOTE_REQUESTED;
495 }
496 break;
497
498 case STOPCCRQ:
499 log_print(DEBUG, "Received STOPCCRQ");
500 log_print(INFO, "Remote server hung up");
501 state = STOPCCRQ;
502 return -REMOTE_REQUESTED;
503
504 case CCRQ:
505 /* According to RFC 2637 page 45, we should never receive CCRQ for
506 * outgoing calls. However, some implementation only acts as PNS and
507 * always uses CCRQ to clear a call, so here we still handle it. */
508 if (state == OCRP && incoming.ccrq.call == remote) {
Sam Protsenko537773c2018-06-25 21:20:39 +0300509 log_print(DEBUG, "Received CCRQ (remote = %u)",
510 (unsigned)ntohs(remote));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800511 log_print(INFO, "Remote server hung up");
512 return -REMOTE_REQUESTED;
513 }
514 break;
515
516 case CDN:
517 if (state == OCRP && incoming.cdn.call == remote) {
Sam Protsenko537773c2018-06-25 21:20:39 +0300518 log_print(DEBUG, "Received CDN (remote = %u)",
519 (unsigned)ntohs(remote));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800520 log_print(INFO, "Remote server hung up");
521 return -REMOTE_REQUESTED;
522 }
523 break;
524
525 case ECHORQ:
526 log_print(DEBUG, "Received ECHORQ -> Sending ECHORP");
527 set_message(ECHORP);
528 outgoing.echorp.identifier = incoming.echorq.identifier;
529 outgoing.echorp.result = RESULT_OK;
530 send_packet();
531 return 0;
532
533 case WEN:
534 case SLI:
535 log_print(DEBUG, "Recevied %s", messages[incoming.message]);
536 return 0;
537
538 case ICRQ:
Sam Protsenko537773c2018-06-25 21:20:39 +0300539 log_print(DEBUG, "Received ICRQ (remote = %u, call = %u) -> "
540 "Sending ICRP with error", (unsigned)ntohs(remote),
541 (unsigned)ntohs(incoming.icrq.call));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800542 set_message(ICRP);
543 outgoing.icrp.peer = incoming.icrq.call;
544 outgoing.icrp.result = RESULT_ERROR;
545 send_packet();
546 return 0;
547
548 case OCRQ:
Sam Protsenko537773c2018-06-25 21:20:39 +0300549 log_print(DEBUG, "Received OCRQ (remote = %u, call = %u) -> "
550 "Sending OCRP with error", (unsigned)ntohs(remote),
551 (unsigned)ntohs(incoming.ocrq.call));
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800552 set_message(OCRP);
553 outgoing.ocrp.peer = incoming.ocrq.call;
554 outgoing.ocrp.result = RESULT_ERROR;
555 send_packet();
556 return 0;
557 }
558
559 /* We reach here if we got an unexpected message. Just log it. */
560 log_print(DEBUG, "Received UNEXPECTED %s", messages[incoming.message]);
561 return 0;
562}
563
564static int pptp_timeout()
565{
566 return 0;
567}
568
569static void pptp_shutdown()
570{
571 /* Normally we should send STOPCCRQ and wait for STOPCCRP, but this might
572 * block for a long time. Here we simply take the shortcut: do nothing. */
573}
574
575struct protocol pptp = {
576 .name = "pptp",
Chia-chi Yeh7b66d202011-06-28 16:39:23 -0700577 .arguments = 2,
Chia-chi Yeh063bb922009-06-15 14:43:38 +0800578 .usage = "<server> <port>",
579 .connect = pptp_connect,
580 .process = pptp_process,
581 .timeout = pptp_timeout,
582 .shutdown = pptp_shutdown,
583};