Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * This file is part of Adblock Plus <http://adblockplus.org/>, | |
3 * Copyright (C) 2006-2014 Eyeo GmbH | |
4 * | |
5 * Adblock Plus is free software: you can redistribute it and/or modify | |
6 * it under the terms of the GNU General Public License version 3 as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * Adblock Plus is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 * GNU General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU General Public License | |
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | |
16 */ | |
17 | |
18 package org.adblockplus.android.configurators; | |
19 | |
20 import java.io.File; | |
21 import java.io.FileNotFoundException; | |
22 import java.net.InetAddress; | |
23 import java.util.List; | |
24 | |
25 import org.adblockplus.android.Utils; | |
26 | |
27 import com.stericson.RootTools.RootTools; | |
28 | |
29 import android.content.Context; | |
30 import android.util.Log; | |
31 | |
32 /** | |
33 * Proxy registration using RootTools and iptables. | |
34 * | |
35 * @author rjeschke | |
36 */ | |
37 public class IptablesProxyConfigurator implements ProxyConfigurator | |
38 { | |
39 private static final String TAG = Utils.getTag(IptablesProxyConfigurator.class ); | |
40 private static final int DEFAULT_TIMEOUT = 3000; | |
41 private static final String IPTABLES_RETURN = " -t nat -m owner --uid-owner {{ UID}} -A OUTPUT -p tcp -j RETURN\n"; | |
42 private static final String IPTABLES_ADD_HTTP = " -t nat -A OUTPUT -p tcp --dp ort 80 -j REDIRECT --to {{PORT}}\n"; | |
43 | |
44 private final Context context; | |
45 private String iptables = null; | |
Felix Dahlke
2014/08/19 09:06:00
null is the default, isn't it?
René Jeschke
2014/08/19 10:41:33
Jup, of course :-D
| |
46 | |
47 public IptablesProxyConfigurator(final Context context) | |
48 { | |
49 this.context = context; | |
50 } | |
51 | |
52 @Override | |
53 public boolean initialize() | |
54 { | |
55 try | |
56 { | |
57 if (!RootTools.isAccessGiven()) | |
58 { | |
59 throw new IllegalStateException("No root access"); | |
60 } | |
61 | |
62 final File ipt = this.context.getFileStreamPath("iptables"); | |
63 | |
64 if (!ipt.exists()) | |
65 { | |
66 throw new FileNotFoundException("No iptables executable"); | |
67 } | |
68 | |
69 final String path = ipt.getAbsolutePath(); | |
70 | |
71 RootTools.sendShell("chmod 700 " + path, DEFAULT_TIMEOUT); | |
72 | |
73 boolean compatible = false; | |
74 boolean version = false; | |
75 | |
76 final String command = path + " --version\n" + path + " -L -t nat -n\n"; | |
77 | |
78 final List<String> result = RootTools.sendShell(command, DEFAULT_TIMEOUT); | |
79 | |
80 for (final String line : result) | |
81 { | |
82 if (line.contains("OUTPUT")) | |
83 { | |
84 compatible = true; | |
85 } | |
86 if (line.contains("v1.4.")) | |
87 { | |
88 version = true; | |
89 } | |
90 } | |
91 | |
92 if (!(compatible && version)) | |
93 { | |
94 throw new IllegalStateException("Incompatible iptables excutable"); | |
95 } | |
96 | |
97 this.iptables = path; | |
98 | |
99 return true; | |
100 } | |
101 catch (final Exception e) | |
102 { | |
103 return false; | |
104 } | |
105 } | |
106 | |
107 @Override | |
108 public boolean registerProxy(final InetAddress address, final int port) | |
109 { | |
110 try | |
111 { | |
112 final int uid = this.context.getPackageManager().getPackageInfo(this.conte xt.getPackageName(), 0).applicationInfo.uid; | |
113 | |
114 final StringBuilder cmd = new StringBuilder(); | |
115 cmd.append(this.iptables); | |
116 cmd.append(IPTABLES_RETURN.replace("{{UID}}", String.valueOf(uid))); | |
117 cmd.append('\n'); | |
118 cmd.append(this.iptables); | |
119 cmd.append(IPTABLES_ADD_HTTP.replace("{{PORT}}", String.valueOf(port))); | |
120 | |
121 RootTools.sendShell(cmd.toString(), DEFAULT_TIMEOUT); | |
122 | |
123 return true; | |
124 } | |
125 catch (final Exception e) | |
126 { | |
127 // I leave this logging message for now, passing 'init' and failing 'regis ter' definitely is a failure | |
128 Log.e(TAG, "Couldn't register proxy using iptables.", e); | |
129 return false; | |
130 } | |
131 } | |
132 | |
133 @Override | |
134 public void unregisterProxy() | |
135 { | |
136 try | |
137 { | |
138 // TODO: Maybe we should use a more selective unregister process instead o f | |
Felix Dahlke
2014/08/19 09:06:00
That sounds like something that should be an issue
René Jeschke
2014/08/19 10:41:33
Done.
| |
139 // just dropping every OUTPUT NAT rule? | |
140 RootTools.sendShell(this.iptables + " -t nat -F OUTPUT", DEFAULT_TIMEOUT); | |
141 } | |
142 catch (final Exception e) | |
143 { | |
144 Log.w(TAG, "Failed to unregister proxy using iptables.", e); | |
145 } | |
146 } | |
147 | |
148 @Override | |
149 public void shutdown() | |
150 { | |
151 // Nothing to do here | |
152 } | |
153 | |
154 public static List<String> getIptablesOutput(final Context context) | |
155 { | |
156 try | |
157 { | |
158 if (!RootTools.isAccessGiven()) | |
159 { | |
160 throw new IllegalStateException("No root access"); | |
161 } | |
162 | |
163 final File ipt = context.getFileStreamPath("iptables"); | |
164 | |
165 if (!ipt.exists()) | |
166 { | |
167 throw new FileNotFoundException("No iptables executable"); | |
168 } | |
169 | |
170 final String path = ipt.getAbsolutePath(); | |
171 | |
172 RootTools.sendShell("chmod 700 " + path, DEFAULT_TIMEOUT); | |
173 | |
174 boolean compatible = false; | |
175 boolean version = false; | |
176 | |
177 String command = path + " --version\n" + path + " -L -t nat -n\n"; | |
178 | |
179 final List<String> result = RootTools.sendShell(command, DEFAULT_TIMEOUT); | |
180 | |
181 for (final String line : result) | |
182 { | |
183 if (line.contains("OUTPUT")) | |
184 { | |
185 compatible = true; | |
186 } | |
187 if (line.contains("v1.4.")) | |
188 { | |
189 version = true; | |
190 } | |
191 } | |
192 | |
193 if (!(compatible && version)) | |
194 { | |
195 throw new IllegalStateException("Incompatible iptables excutable"); | |
196 } | |
197 | |
198 command = path + " -L -t nat -n\n"; | |
199 | |
200 return RootTools.sendShell(command, DEFAULT_TIMEOUT); | |
201 } | |
202 catch (final Throwable t) | |
203 { | |
204 return null; | |
205 } | |
206 } | |
207 | |
208 @Override | |
209 public ProxyRegistrationType getType() | |
210 { | |
211 return ProxyRegistrationType.IPTABLES; | |
212 } | |
213 | |
214 @Override | |
215 public boolean isRegistered() | |
216 { | |
217 // TODO Auto-generated method stub | |
Felix Dahlke
2014/08/19 09:06:00
Better remove this auto generated comment, and the
René Jeschke
2014/08/19 10:41:33
Done, there has been something missing here *cough
| |
218 return false; | |
219 } | |
220 | |
221 @Override | |
222 public boolean isSticky() | |
223 { | |
224 // TODO Auto-generated method stub | |
225 return false; | |
226 } | |
227 | |
228 @Override | |
229 public String toString() | |
230 { | |
231 return "[ProxyConfigurator: " + this.getType() + "]"; | |
232 } | |
233 } | |
OLD | NEW |