Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: src/org/adblockplus/android/configurators/IptablesProxyConfigurator.java

Issue 4705284891082752: Proxy configurators (Closed)
Patch Set: Created Aug. 11, 2014, 12:36 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld