Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rgw: swift: The http referer should be parsed to compare in swift API #13005

Merged
merged 1 commit into from Jan 30, 2017

Conversation

Jing-Scott
Copy link
Contributor

The http referer should be parsed to compare with the url set on the container read acl. If we set .r:www.example.com on container read acl, we should parse the hostname 'www.example.com' of the http referer like 'http://www.example.com' from the http request.

Signed-off-by: Jing Wenjun jingwenjun@cmss.chinamobile.com

Copy link
Contributor

@rzarzynski rzarzynski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Jing-Scott: Overall this PR looks good. Some minor changes are needed.

url_spec.length(), url_spec);
}

return false;
}

bool get_http_host(std::string url, std::string& http_host) const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: may we take the url parameter as boost::string_ref and return boost::optional<boost::string_ref>? Then method signature would look like following one:

boost::optional<boost::string_ref> get_http_host(const boost::string_ref url) const

url_spec.length(), url_spec);
}

return false;
}

bool get_http_host(std::string url, std::string& http_host) const {
int pos = url.find("://");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please switch to size_t?

url_spec.length(), url_spec);
}

return false;
}

bool get_http_host(std::string url, std::string& http_host) const {
int pos = url.find("://");
if (pos < 0 || pos == (int)url.size() - 3)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please compare with the npos member of a corresponding string class.

url_spec.length(), url_spec);
}

return false;
}

bool get_http_host(std::string url, std::string& http_host) const {
int pos = url.find("://");
if (pos < 0 || pos == (int)url.size() - 3)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No magics, please. Consider boost::string_ref::ends_with, boost::algorithm::ends_with or even strlen("://").

url_spec.length(), url_spec);
}

return false;
}

bool get_http_host(std::string url, std::string& http_host) const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to make this method public.

return false;

string scheme = url.substr(0, pos);
if (scheme.empty())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe starts_with("://") in the previous if?


string url_sub = url.substr(pos + 3);
pos = url_sub.find('@');
if (pos == (int)url_sub.size())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I would say this condition is always false.

if (pos == (int)url_sub.size())
return false;

url_sub = url_sub.substr(pos + 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If url_sub doesn't contain @ then we're doing std::string::npos + 1 which results to 0 on most implementations. However, this isn't a way to go.

@Jing-Scott
Copy link
Contributor Author

Jing-Scott commented Jan 26, 2017

@rzarzynski
Your comments make sense to me. I've updated the commit according to your suggestion. please check it . Thanks!

The http referer should be parsed to compare with the url set on the container read acl. If we set .r:www.example.com on container read acl, we should parse the hostname 'www.example.com' of the http referer like 'http://www.example.com' from the http request.

Fixes: http://tracker.ceph.com/issues/18685
Signed-off-by: Jing Wenjun <jingwenjun@cmss.chinamobile.com>
Copy link
Contributor

@rzarzynski rzarzynski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only cosmetic changes needed. We're getting close. :-)

if (!get_http_host(http_referer, http_host))
bool is_match(boost::string_ref http_referer) const {
boost::optional<boost::string_ref> http_host = get_http_host(http_referer);
if ((*http_host).empty()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In get_http_host you might want to return boost::none if parsing fails. Then this conditional would look like:

if (! http_host) {
  return false;
}

return true;
}

if (http_host.length() < url_spec.length()) {
if ((*http_host).length() < host_spec.length()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boost::optional has overloads for the -> operator, so you may write here (and in others places) just:

if (http_host->length() < host_spec.length()) {

/* Wildcard support: a referer matches the spec when its last char are
* perfectly equal to spec. */
return !http_host.compare(http_host.length() - url_spec.length(),
url_spec.length(), url_spec);
return (*http_host).ends_with(host_spec);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, now the code is really much easier to understand. I missed the opportunity for ends_with last time. Thanks for applying it here!

std::string http_host;
if (!get_http_host(http_referer, http_host))
bool is_match(boost::string_ref http_referer) const {
boost::optional<boost::string_ref> http_host = get_http_host(http_referer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, maybe const here?
BTW: using auto is also perfectly fine in the project.

size_t pos = url.find("://");
if (pos == boost::string_ref::npos || url.starts_with("://") ||
url.ends_with("://") || url.ends_with('@')) {
return boost::string_ref(nullptr, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would propose returning boost::none (according to one of the comments above).

@Jing-Scott
Copy link
Contributor Author

@rzarzynski
done. thanks for your patience. your comments help me to understand boost::string_ref and boost::optional deeply!

Copy link
Contributor

@rzarzynski rzarzynski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes! Could you please also prepend the link to tracker issue with the Fixes tag? That and squashing commits would help with backporting the fix to Kraken and Jewel.

/* Wildcard support: a referer matches the spec when its last char are
* perfectly equal to spec. */
return !http_referer.compare(http_referer.length() - url_spec.length(),
url_spec.length(), url_spec);
return (*http_host).ends_with(host_spec);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The -> operator can be applied here as well. I've missed that last time, sorry.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, it's my carelessness!

return false;
}

boost::string_ref host_spec(url_spec);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm not sure whether we really need the host_spec temporary. IIUC boost::string_ref has the operator== overload for std::string so we could compare *http_host directly with url_spec.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if using operator== like *http_host == url_spec directly, it will return error. So here I use ->compare to compare http_host with url_spec insteaded.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ouch, my fault. Sorry.

@Jing-Scott
Copy link
Contributor Author

Hi, @rzarzynski
I've squashed them. the bug is created in tracker and it is included in commit message. Pls check it! Thanks a lot!

http://tracker.ceph.com/issues/18685

Copy link
Contributor

@rzarzynski rzarzynski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very good, thanks! I will schedule a Teuthology run soon.

@rzarzynski
Copy link
Contributor

The Teuthology run looks good to me. There is one but unrelated failure. Merging.

@rzarzynski rzarzynski merged commit fca5b3c into ceph:master Jan 30, 2017
@Jing-Scott Jing-Scott deleted the dev/swift-http-url-parse branch February 2, 2017 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants