Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Side by Side Diff: net/ftp/ftp_network_transaction.cc

Issue 2539583002: Use overflow-safe string-to-int parsing methods for FTP ports. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | net/ftp/ftp_network_transaction_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/ftp/ftp_network_transaction.h" 5 #include "net/ftp/ftp_network_transaction.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/metrics/histogram_macros.h" 10 #include "base/metrics/histogram_macros.h"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_split.h" 12 #include "base/strings/string_split.h"
13 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h" 15 #include "base/values.h"
16 #include "net/base/address_list.h" 16 #include "net/base/address_list.h"
17 #include "net/base/escape.h" 17 #include "net/base/escape.h"
18 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
19 #include "net/base/parse_number.h"
19 #include "net/base/port_util.h" 20 #include "net/base/port_util.h"
20 #include "net/base/url_util.h" 21 #include "net/base/url_util.h"
21 #include "net/ftp/ftp_request_info.h" 22 #include "net/ftp/ftp_request_info.h"
22 #include "net/ftp/ftp_util.h" 23 #include "net/ftp/ftp_util.h"
23 #include "net/log/net_log.h" 24 #include "net/log/net_log.h"
24 #include "net/log/net_log_event_type.h" 25 #include "net/log/net_log_event_type.h"
25 #include "net/log/net_log_source.h" 26 #include "net/log/net_log_source.h"
26 #include "net/socket/client_socket_factory.h" 27 #include "net/socket/client_socket_factory.h"
27 #include "net/socket/stream_socket.h" 28 #include "net/socket/stream_socket.h"
28 #include "url/url_constants.h" 29 #include "url/url_constants.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 } 117 }
117 } 118 }
118 119
119 // From RFC 2428 Section 3: 120 // From RFC 2428 Section 3:
120 // The text returned in response to the EPSV command MUST be: 121 // The text returned in response to the EPSV command MUST be:
121 // <some text> (<d><d><d><tcp-port><d>) 122 // <some text> (<d><d><d><tcp-port><d>)
122 // <d> is a delimiter character, ideally to be | 123 // <d> is a delimiter character, ideally to be |
123 bool ExtractPortFromEPSVResponse(const FtpCtrlResponse& response, int* port) { 124 bool ExtractPortFromEPSVResponse(const FtpCtrlResponse& response, int* port) {
124 if (response.lines.size() != 1) 125 if (response.lines.size() != 1)
125 return false; 126 return false;
126 const char* ptr = response.lines[0].c_str(); 127
127 while (*ptr && *ptr != '(') 128 base::StringPiece epsv_line(response.lines[0]);
128 ++ptr; 129 size_t start = epsv_line.find('(');
129 if (!*ptr) 130 // If the line doesn't have a '(' or doesn't have enough characters after the
130 return false; 131 // first '(', fail.
131 char sep = *(++ptr); 132 if (start == epsv_line.npos || epsv_line.length() - start < 6)
eroman 2016/11/28 22:51:57 This is more commonly written as |StringPiece::npo
mmenke 2016/11/28 23:15:48 Done.
132 if (!sep || isdigit(sep) || *(++ptr) != sep || *(++ptr) != sep)
133 return false;
134 if (!isdigit(*(++ptr)))
135 return false;
136 *port = *ptr - '0';
137 while (isdigit(*(++ptr))) {
138 *port *= 10;
139 *port += *ptr - '0';
140 }
141 if (*ptr != sep)
142 return false; 133 return false;
143 134
144 return true; 135 // Make sure we have "(<d><d><d>...", where <d> is not a number.
136 if (isdigit(epsv_line[start + 1]) ||
137 epsv_line[start + 1] != epsv_line[start + 2] ||
138 epsv_line[start + 1] != epsv_line[start + 3]) {
mmenke 2016/11/28 22:28:18 This is still ugly, but it seems a bit better to m
eroman 2016/11/28 22:51:57 Can you extract epsv_line[start+1] to a variable?
mmenke 2016/11/28 23:15:48 Done.
139 return false;
140 }
141
142 // Skip over those characters.
143 start += 4;
144
145 // Make sure there's a terminal <d>.
146 size_t end = epsv_line.find(epsv_line[start - 1], start);
eroman 2016/11/28 22:51:57 Same comment. Rather than using epsv_line[start-1]
mmenke 2016/11/28 23:15:48 Done.
147 if (end == epsv_line.npos)
eroman 2016/11/28 22:51:57 StringPiece::npos
mmenke 2016/11/28 23:15:48 Done.
148 return false;
149
150 return ParseInt32(epsv_line.substr(start, end - start),
151 ParseIntFormat::NON_NEGATIVE, port);
145 } 152 }
146 153
147 // There are two way we can receive IP address and port. 154 // There are two way we can receive IP address and port.
148 // (127,0,0,1,23,21) IP address and port encapsulated in (). 155 // (127,0,0,1,23,21) IP address and port encapsulated in ().
149 // 127,0,0,1,23,21 IP address and port without (). 156 // 127,0,0,1,23,21 IP address and port without ().
150 // 157 //
151 // See RFC 959, Section 4.1.2 158 // See RFC 959, Section 4.1.2
152 bool ExtractPortFromPASVResponse(const FtpCtrlResponse& response, int* port) { 159 bool ExtractPortFromPASVResponse(const FtpCtrlResponse& response, int* port) {
153 if (response.lines.size() != 1) 160 if (response.lines.size() != 1)
154 return false; 161 return false;
(...skipping 29 matching lines...) Expand all
184 // Split the line into comma-separated pieces and extract 191 // Split the line into comma-separated pieces and extract
185 // the last two. 192 // the last two.
186 std::vector<base::StringPiece> pieces = base::SplitStringPiece( 193 std::vector<base::StringPiece> pieces = base::SplitStringPiece(
187 line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 194 line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
188 if (pieces.size() != 6) 195 if (pieces.size() != 6)
189 return false; 196 return false;
190 197
191 // Ignore the IP address supplied in the response. We are always going 198 // Ignore the IP address supplied in the response. We are always going
192 // to connect back to the same server to prevent FTP PASV port scanning. 199 // to connect back to the same server to prevent FTP PASV port scanning.
193 int p0, p1; 200 int p0, p1;
194 if (!base::StringToInt(pieces[4], &p0)) 201 if (!ParseInt32(pieces[4], ParseIntFormat::NON_NEGATIVE, &p0))
eroman 2016/11/28 22:51:57 ParseUint32() ? or should we add a ParseUint8() ?
mmenke 2016/11/28 23:15:48 Went with ParseUint32 (Don't think adding a new me
195 return false; 202 return false;
196 if (!base::StringToInt(pieces[5], &p1)) 203 if (!ParseInt32(pieces[5], ParseIntFormat::NON_NEGATIVE, &p1))
197 return false; 204 return false;
205 if (p0 >= 256 || p1 >= 256)
eroman 2016/11/28 22:51:57 optional nit: I think it would be clearer writte a
mmenke 2016/11/28 23:15:48 Done.
206 return false;
207
198 *port = (p0 << 8) + p1; 208 *port = (p0 << 8) + p1;
199
200 return true; 209 return true;
201 } 210 }
202 211
203 } // namespace 212 } // namespace
204 213
205 FtpNetworkTransaction::FtpNetworkTransaction( 214 FtpNetworkTransaction::FtpNetworkTransaction(
206 HostResolver* resolver, 215 HostResolver* resolver,
207 ClientSocketFactory* socket_factory) 216 ClientSocketFactory* socket_factory)
208 : command_sent_(COMMAND_NONE), 217 : command_sent_(COMMAND_NONE),
209 io_callback_(base::Bind(&FtpNetworkTransaction::OnIOComplete, 218 io_callback_(base::Bind(&FtpNetworkTransaction::OnIOComplete,
(...skipping 1133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1343 if (!had_error_type[type]) { 1352 if (!had_error_type[type]) {
1344 had_error_type[type] = true; 1353 had_error_type[type] = true;
1345 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorHappened", 1354 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorHappened",
1346 type, NUM_OF_NET_ERROR_TYPES); 1355 type, NUM_OF_NET_ERROR_TYPES);
1347 } 1356 }
1348 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorCount", 1357 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorCount",
1349 type, NUM_OF_NET_ERROR_TYPES); 1358 type, NUM_OF_NET_ERROR_TYPES);
1350 } 1359 }
1351 1360
1352 } // namespace net 1361 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/ftp/ftp_network_transaction_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698