From 064c3d4d4b9e8f404779222cdc185971ecaf5be9 Mon Sep 17 00:00:00 2001 From: M66B Date: Sun, 10 Jan 2016 08:14:47 +0100 Subject: [PATCH] Native get uid --- app/app.iml | 1 - app/proguard-rules.pro | 4 +- .../eu/faircode/netguard/SinkholeService.java | 64 +------- app/src/main/jni/netguard.c | 138 +++++++++++++----- 4 files changed, 104 insertions(+), 103 deletions(-) diff --git a/app/app.iml b/app/app.iml index de5fe5b4..693137fa 100644 --- a/app/app.iml +++ b/app/app.iml @@ -98,7 +98,6 @@ - diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 5f111908..a30268f4 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -23,9 +23,9 @@ #NetGuard -keepnames class eu.faircode.netguard.** { *; } -# logPacket(int version, String saddr, int sport, String daddr, int dport, int protocol, String flags) +# logPacket(int version, String saddr, int sport, String daddr, int dport, int protocol, String flags, int uid) -keep class eu.faircode.netguard.SinkholeService { - void logPacket(int, java.lang.String, int, java.lang.String, int, int, java.lang.String); + void logPacket(int, java.lang.String, int, java.lang.String, int, int, java.lang.String, int); } #Support library diff --git a/app/src/main/java/eu/faircode/netguard/SinkholeService.java b/app/src/main/java/eu/faircode/netguard/SinkholeService.java index e68a74a5..0a6ad159 100644 --- a/app/src/main/java/eu/faircode/netguard/SinkholeService.java +++ b/app/src/main/java/eu/faircode/netguard/SinkholeService.java @@ -61,19 +61,15 @@ import android.util.Log; import android.util.TypedValue; import android.widget.RemoteViews; -import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.net.InetAddress; import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Scanner; import java.util.Set; import java.util.TreeMap; @@ -724,7 +720,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS receiveThread.start(); } - private void logPacket(int version, String saddr, int sport, String daddr, int dport, int protocol, String flags) { + private void logPacket(int version, String saddr, int sport, String daddr, int dport, int protocol, String flags, int uid) { try { int connection; if (last_connected) @@ -735,19 +731,6 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS else connection = 0; - int tries = 0; - int uid = getUid(version, InetAddress.getByName(saddr), sport, protocol); - while (uid < 0 && tries < 10) { - try { - Thread.sleep(10); - } catch (InterruptedException ignored) { - } - tries++; - uid = getUid(version, InetAddress.getByName(saddr), sport, protocol); - if (uid >= 0) - Log.w(TAG, "Uid found after try=" + tries); - } - new DatabaseHelper(SinkholeService.this).insertLog( version, daddr, @@ -762,51 +745,6 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS } } - public int getUid(int version, InetAddress source, int sport, int protocol) { - StringBuilder addr = new StringBuilder(); - byte[] b = source.getAddress(); - for (int i = b.length - 1; i >= 0; i--) - addr.append(String.format("%02X", b[i])); - - String port = String.format("%04X", sport); - - int uid = -1; - if (version == 4) { - uid = scanUid("0000000000000000FFFF0000" + addr.toString() + ":" + port, protocol == 6 ? "/proc/net/tcp6" : "/proc/net/udp6"); - if (uid < 0) - uid = scanUid(addr.toString() + ":" + port, protocol == 6 ? "/proc/net/tcp" : "/proc/net/udp"); - if (uid < 0 && protocol == 17) - uid = scanUid("00000000:" + port, "/proc/net/udp"); - } else - uid = scanUid(addr.toString() + ":" + port, protocol == 6 ? "/proc/net/tcp6" : "/proc/net/udp6"); - - return uid; - } - - private static int scanUid(String addr, String name) { - File file = new File(name); - Scanner scanner = null; - try { - scanner = new Scanner(file); - while (scanner.hasNextLine()) { - String line = scanner.nextLine().trim(); - if (line.startsWith("sl")) - continue; - - String[] field = line.split("\\s+"); - if (addr.equals(field[1])) - return Integer.parseInt(field[7]); - } - } catch (FileNotFoundException ex) { - Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); - } finally { - if (scanner != null) - scanner.close(); - } - - return -1; - } - private void stopReceiving() { if (receiveThread != null) receiveThread.interrupt(); diff --git a/app/src/main/jni/netguard.c b/app/src/main/jni/netguard.c index 1890613a..c4918cae 100644 --- a/app/src/main/jni/netguard.c +++ b/app/src/main/jni/netguard.c @@ -1,7 +1,6 @@ #include #include -#include -#include +#include #include #include #include @@ -15,7 +14,7 @@ void decode(JNIEnv *env, jobject instance, jbyte *, int); -void scanproc6(const char *); +int getUid(int protocol, int version, const char *psaddr, int psport); JNIEXPORT void JNICALL Java_eu_faircode_netguard_SinkholeService_jni_1init(JNIEnv *env, jobject instance) { @@ -26,21 +25,18 @@ JNIEXPORT void JNICALL Java_eu_faircode_netguard_SinkholeService_jni_1decode(JNIEnv *env, jobject instance, jbyteArray buffer_, jint length) { jbyte *buffer = (*env)->GetByteArrayElements(env, buffer_, NULL); - decode(env, instance, buffer, length); - (*env)->ReleaseByteArrayElements(env, buffer_, buffer, 0); } JNIEXPORT void JNICALL Java_eu_faircode_netguard_SinkholeService_jni_1receive(JNIEnv *env, jobject instance, jint fd) { int len; - jbyte *buffer = malloc(MAXPKT); + jbyte buffer[MAXPKT]; while (1) { - len = read(fd, buffer, MAXPKT); + len = read(fd, buffer, sizeof(buffer)); if (len < 0) { __android_log_print(ANDROID_LOG_WARN, TAG, "Receive error %d", len); - free(buffer); return; } else if (len > 0) @@ -52,16 +48,18 @@ Java_eu_faircode_netguard_SinkholeService_jni_1receive(JNIEnv *env, jobject inst } void decode(JNIEnv *env, jobject instance, jbyte *buffer, int length) { - jbyte protocol = -1; + jbyte protocol; char source[40]; char dest[40]; char flags[10]; int flen = 0; - void *payload = NULL; + jbyte *payload; + // Get protocol, addresses & payload jbyte version = (*buffer) >> 4; if (version == 4) { struct iphdr *ip4hdr = buffer; + protocol = ip4hdr->protocol; inet_ntop(AF_INET, &ip4hdr->saddr, source, sizeof(source)); inet_ntop(AF_INET, &ip4hdr->daddr, dest, sizeof(dest)); @@ -69,10 +67,11 @@ void decode(JNIEnv *env, jobject instance, jbyte *buffer, int length) { jbyte optlen = 0; if (ip4hdr->ihl > 5) optlen = buffer[20]; - payload = buffer + 20 * sizeof(jbyte) + optlen; + payload = buffer + (20 + optlen) * sizeof(jbyte); } else if (version == 6) { struct ip6_hdr *ip6hdr = buffer; + protocol = ip6hdr->ip6_nxt; inet_ntop(AF_INET6, &ip6hdr->ip6_src, source, sizeof(source)); inet_ntop(AF_INET6, &ip6hdr->ip6_dst, dest, sizeof(dest)); @@ -81,16 +80,18 @@ void decode(JNIEnv *env, jobject instance, jbyte *buffer, int length) { } else { __android_log_print(ANDROID_LOG_WARN, TAG, "Unknown version %d", version); - *source = 0; - *dest = 0; + return; } + // Get ports & flags int sport = -1; int dport = -1; if (protocol == IPPROTO_TCP) { struct tcphdr *tcp = payload; + sport = ntohs(tcp->source); dport = ntohs(tcp->dest); + if (tcp->syn) flags[flen++] = 'S'; if (tcp->ack) @@ -103,6 +104,7 @@ void decode(JNIEnv *env, jobject instance, jbyte *buffer, int length) { flags[flen++] = 'R'; } else if (protocol == IPPROTO_UDP) { struct udphdr *udp = payload; + sport = ntohs(udp->source); dport = ntohs(udp->dest); } @@ -111,40 +113,102 @@ void decode(JNIEnv *env, jobject instance, jbyte *buffer, int length) { __android_log_print(ANDROID_LOG_INFO, TAG, "Packet v%d %s/%d -> %s/%d proto %d flags %s", version, source, sport, dest, dport, protocol, flags); - //scanproc6("/proc/net/tcp6"); + // Get uid + int uid = -1; + if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP) { + // Sleep 10 ms + struct timespec tim, tim2; + tim.tv_sec = 0; + tim.tv_nsec = 10000000L; + nanosleep(&tim, &tim2); + + // Lookup uid + uid = getUid(protocol, version, source, sport); + if (uid < 0 && version == 4) { + int8_t addr128[16]; + char source6[40]; + + memset(addr128, 0, 10); + addr128[10] = 0xFF; + addr128[11] = 0xFF; + + inet_pton(AF_INET, source, addr128 + 12); + inet_ntop(AF_INET6, &addr128, source6, sizeof(source6)); + uid = getUid(protocol, 6, source6, sport); + } + } + + // Call back jclass cls = (*env)->GetObjectClass(env, instance); jmethodID mid = (*env)->GetMethodID(env, cls, "logPacket", - "(ILjava/lang/String;ILjava/lang/String;IILjava/lang/String;)V"); + "(ILjava/lang/String;ILjava/lang/String;IILjava/lang/String;I)V"); if (mid != 0) { jstring jsource = (*env)->NewStringUTF(env, source); jstring jdest = (*env)->NewStringUTF(env, dest); jstring jflags = (*env)->NewStringUTF(env, flags); (*env)->CallVoidMethod(env, instance, mid, - version, jsource, sport, jdest, dport, protocol, jflags); + version, jsource, sport, jdest, dport, protocol, jflags, uid); + (*env)->DeleteLocalRef(env, jsource); + (*env)->DeleteLocalRef(env, jdest); + (*env)->DeleteLocalRef(env, jflags); } } -void scanproc6(const char *file) { - char line[500]; - struct in6_addr *saddr = malloc(sizeof(struct in6_addr)); - char source[40]; - int sport; - int uid; - FILE *fd = fopen(file, "r"); - if (fd != NULL) { - int i = 0; - while (fgets(line, 500, fd) != NULL) { - if (i++) { - sscanf(line, - "%*d: %8X%8X%8X%8X:%X %*X:%*X %*X %*lX:%*lX %*X:%*X %*X %d %*d %*ld ", - saddr, ((void *) saddr) + 4, ((void *) saddr) + 8, ((void *) saddr) + 12, - &sport, &uid); - inet_ntop(AF_INET6, saddr, source, sizeof(source)); - __android_log_print(ANDROID_LOG_INFO, TAG, "proc %s/%d %d", source, sport, uid); - } - } - fclose(fd); +int getUid(int protocol, int version, const char *saddr, int sport) { + char line[250]; + int fields; + int32_t addr32; + int8_t addr128[16]; + char addr[40]; + int port; + int uid = -1; + + // Get proc file name + char *fn = NULL; + if (protocol == IPPROTO_TCP) + fn = (version == 4 ? "/proc/net/tcp" : "/proc/net/tcp6"); + else if (protocol == IPPROTO_UDP) + fn = (version == 4 ? "/proc/net/udp" : "/proc/net/udp6"); + else + return -1; + + // Open proc file + FILE *fd = fopen(fn, "r"); + if (fd == NULL) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "Error opening %s", fn); + return -1; } - free(saddr); + + // Scan proc file + int i = 0; + while (fgets(line, sizeof(line), fd) != NULL) { + if (i++) { + if (version == 4) + fields = sscanf(line, + "%*d: %X:%X %*X:%*X %*X %*lX:%*lX %*X:%*X %*X %d %*d %*ld ", + &addr32, &port, &uid); + else + fields = sscanf(line, + "%*d: %8X%8X%8X%8X:%X %*X:%*X %*X %*lX:%*lX %*X:%*X %*X %d %*d %*ld ", + addr128, addr128 + 4, addr128 + 8, addr128 + 12, &port, &uid); + + if (fields < 3) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "Invalid field #%d: %s", fields, line); + break; + } + + if (version == 4) + inet_ntop(AF_INET, &addr32, addr, sizeof(addr)); + else + inet_ntop(AF_INET6, addr128, addr, sizeof(addr)); + + if (port == sport && strcmp(addr, saddr) == 0) + break; + } + } + + fclose(fd); + + return uid; } \ No newline at end of file