From: Jason Cooper <cyanogen at lakedaemon.net> Signed-off-by: Jason Cooper <cyanogen at lakedaemon.net> --- Android.mk | 2 +- mtpd.c | 52 ++++++++++++++++++++++++++++++++- mtpd.h | 1 + openconnect.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 openconnect.c diff --git a/Android.mk b/Android.mk index b74e13d..344e438 100644 --- a/Android.mk +++ b/Android.mk @@ -19,7 +19,7 @@ ifneq ($(TARGET_SIMULATOR),true) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES := mtpd.c l2tp.c pptp.c openvpn.c +LOCAL_SRC_FILES := mtpd.c l2tp.c pptp.c openvpn.c openconnect.c LOCAL_SHARED_LIBRARIES := libcutils libcrypto LOCAL_CFLAGS := -DANDROID_CHANGES LOCAL_C_INCLUDES := external/openssl/include frameworks/base/cmds/keystore diff --git a/mtpd.c b/mtpd.c index fdeb887..d886799 100644 --- a/mtpd.c +++ b/mtpd.c @@ -43,7 +43,8 @@ int the_socket = -1; extern struct protocol l2tp; extern struct protocol pptp; extern struct protocol openvpn; -static struct protocol *protocols[] = {&l2tp, &pptp, &openvpn, NULL}; +extern struct protocol openconnect; +static struct protocol *protocols[] = {&l2tp, &pptp, &openvpn, &openconnect, NULL}; static struct protocol *the_protocol; static int pppd_argc; @@ -316,6 +317,53 @@ void create_socket(int family, int type, char *server, char *port) log_print(INFO, "Connection established (socket = %d)", the_socket); } +void start_daemon_pipe(char *name, char *args[], char *data, int datalen) +{ + int fd[2]; + + if (pppd_pid) { + log_print(WARNING, "%s is already started (pid = %d)", name, pppd_pid); + return; + } + + log_print(INFO, "Starting %s", name); + + pipe(fd); + + pppd_pid = fork(); + if (pppd_pid < 0) { + log_print(FATAL, "Fork() %s", strerror(errno)); + exit(SYSTEM_ERROR); + } + + if (pppd_pid == 0) { + /* child, receiver of data on stdin */ + close(fd[1]); + dup2(fd[0], 0); + + int fdc = open("/dev/null",O_RDWR|O_CREAT|O_TRUNC); + dup2(fdc, 1); + dup2(fdc, 2); + + execvp(name, args); + + log_print(FATAL, "Exec() %s", strerror(errno)); + close(fd[0]); + exit(1); /* Pretending a fatal error in pppd. */ + } else { + /* parent, transmitter of data */ + close(fd[0]); + + if(data != NULL && datalen >= 0) { + write(fd[1], data, datalen); + free(data); + } + close(fd[1]); + } + + log_print(INFO, "%s started (pid = %d)", name, pppd_pid); +} + void start_daemon(char *name, char *args[], int pppox) { int i; @@ -338,7 +386,7 @@ void start_daemon(char *name, char *args[], int pppox) dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); - + execvp(name, args); log_print(FATAL, "Exec() %s", strerror(errno)); exit(1); /* Pretending a fatal error in pppd. */ diff --git a/mtpd.h b/mtpd.h index 0cdc509..7cab37c 100644 --- a/mtpd.h +++ b/mtpd.h @@ -49,6 +49,7 @@ void log_print(int level, char *format, ...); void create_socket(int family, int type, char *server, char *port); void start_pppd(int pppox); void start_daemon(char *name, char *args[], int pppox); +void start_daemon_pipe(char *name, char *args[], char *data, int datalen); /* Each protocol must implement everything defined in this structure. Note that * timeout intervals are in milliseconds, where zero means forever. To indicate diff --git a/openconnect.c b/openconnect.c new file mode 100644 index 0000000..c5364b1 --- /dev/null +++ b/openconnect.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2011 Jason Cooper <cyanogen at lakedaemon.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* copied from openvpn.c which was (same license): + * + * Copyright (C) 2010 James Bottomley <James.Bottomley at suse.de> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#include "mtpd.h" + +static int openconnect_connect(int argc, char **argv) +{ + char *args[argc + 10]; + char *data; + int i, j; + + /* blank it out */ + for (i=0; i < (argc + 10); i++) + args[i] = NULL; + + args[0] = "openconnect"; + /* for privilege separation, drop to user vpn */ + args[1] = "-U"; + args[2] = "vpn"; + /* use this script to configure routes/dns */ + args[3] = "-s"; + args[4] = "su -c /system/xbin/openconnect-up.sh"; + + + for (i = 0, j = 5; i < argc; i++, j++) { + args[j] = argv[i]; + + if(strcmp("--passwd-on-stdin", argv[i]) == 0) { + data = strdup(argv[i + 1]); + i++; + } else if(strcmp("--cookie-on-stdin", argv[i]) == 0) { + data = strdup(argv[i + 1]); + i++; + } + } + + start_daemon_pipe("openconnect", args, data, strlen(data)); + + return 0; +} + +static void openconnect_shutdown(void) +{ +} + +struct protocol openconnect = { + .name = "openconnect", + .usage = "[openconnect args]", + .connect = openconnect_connect, + .process = NULL, + .timeout = NULL, + .shutdown = openconnect_shutdown, +}; -- 1.7.0.4