{"action":"created","comment":{"url":"https://api.github.com/repos/ruby/openssl/pulls/comments/27407234","id":27407234,"diff_hunk":"@@ -168,6 +166,41 @@ def verify_certificate_identity(cert, hostname)\n     end\n     module_function :verify_certificate_identity\n \n+    def verify_hostname(hostname, san) # :nodoc:\n+      san_parts = san.split(\".\")\n+\n+      # TODO: this behavior should probably be more strict\n+      return san == hostname if san_parts.size < 2\n+\n+      host_parts = hostname.split(\".\")\n+      return false unless san_parts.size == host_parts.size\n+\n+      # RFC 6125, section 6.4.3, subitem 1.\n+      # The client SHOULD NOT attempt to match a presented identifier in\n+      # which the wildcard character comprises a label other than the\n+      # left-most label (e.g., do not match bar.*.example.net).\n+      return false unless verify_wildcard(host_parts.shift, san_parts.shift)\n+\n+      san_parts.join(\".\") == host_parts.join(\".\")\n+    end\n+    module_function :verify_hostname\n+\n+    def verify_wildcard(domain_component, san_component) # :nodoc:\n+      parts = san_component.split(\"*\", -1)\n+\n+      return false if parts.size > 2\n+      return san_component == domain_component if parts.size == 1\n+\n+      # RFC 6125, section 6.4.3, subitem 3.\n+      # The client SHOULD NOT attempt to match a presented identifier\n+      # where the wildcard character is embedded within an A-label or\n+      # U-label of an internationalized domain name.\n+      return false if !parts[0].empty? && domain_component.start_with?(\"xn--\")\n+\n+      domain_component.start_with?(parts[0]) && domain_component.end_with?(parts[1])","path":"lib/openssl/ssl.rb","position":55,"original_position":55,"commit_id":"ea9a6f8c074506615e1fe33db7712fde2d0d7284","original_commit_id":"ea9a6f8c074506615e1fe33db7712fde2d0d7284","user":{"login":"stouset","id":4338,"avatar_url":"https://avatars.githubusercontent.com/u/4338?v=3","gravatar_id":"","url":"https://api.github.com/users/stouset","html_url":"https://github.com/stouset","followers_url":"https://api.github.com/users/stouset/followers","following_url":"https://api.github.com/users/stouset/following{/other_user}","gists_url":"https://api.github.com/users/stouset/gists{/gist_id}","starred_url":"https://api.github.com/users/stouset/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stouset/subscriptions","organizations_url":"https://api.github.com/users/stouset/orgs","repos_url":"https://api.github.com/users/stouset/repos","events_url":"https://api.github.com/users/stouset/events{/privacy}","received_events_url":"https://api.github.com/users/stouset/received_events","type":"User","site_admin":false},"body":"This isn't strict enough.\r\n\r\n```ruby\r\n>> san_component = \"abc*bcd\"\r\n>> domain_component = \"abcd\"\r\n>> parts = san_component.split(\"*\", -1)\r\n=> [\"abc\", \"bcd\"]\r\n>> domain_component.start_with?(parts[0]) && domain_component.end_with?(parts[1])\r\n=> true\r\n```","created_at":"2015-03-30T16:41:16Z","updated_at":"2015-03-30T16:41:16Z","html_url":"https://github.com/ruby/openssl/pull/10#discussion_r27407234","pull_request_url":"https://api.github.com/repos/ruby/openssl/pulls/10","_links":{"self":{"href":"https://api.github.com/repos/ruby/openssl/pulls/comments/27407234"},"html":{"href":"https://github.com/ruby/openssl/pull/10#discussion_r27407234"},"pull_request":{"href":"https://api.github.com/repos/ruby/openssl/pulls/10"}}},"pull_request":{"url":"https://api.github.com/repos/ruby/openssl/pulls/10","id":32134490,"html_url":"https://github.com/ruby/openssl/pull/10","diff_url":"https://github.com/ruby/openssl/pull/10.diff","patch_url":"https://github.com/ruby/openssl/pull/10.patch","issue_url":"https://api.github.com/repos/ruby/openssl/issues/10","number":10,"state":"open","locked":false,"title":"Stricter hostname verification","user":{"login":"tarcieri","id":797,"avatar_url":"https://avatars.githubusercontent.com/u/797?v=3","gravatar_id":"","url":"https://api.github.com/users/tarcieri","html_url":"https://github.com/tarcieri","followers_url":"https://api.github.com/users/tarcieri/followers","following_url":"https://api.github.com/users/tarcieri/following{/other_user}","gists_url":"https://api.github.com/users/tarcieri/gists{/gist_id}","starred_url":"https://api.github.com/users/tarcieri/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tarcieri/subscriptions","organizations_url":"https://api.github.com/users/tarcieri/orgs","repos_url":"https://api.github.com/users/tarcieri/repos","events_url":"https://api.github.com/users/tarcieri/events{/privacy}","received_events_url":"https://api.github.com/users/tarcieri/received_events","type":"User","site_admin":false},"body":"This change implements hostname verification more in-line with RFC 6125.\r\n\r\nAdditionally it eliminates the use of regexes when verifying hostnames, opting for simple string comparisons instead.","created_at":"2015-03-27T18:47:50Z","updated_at":"2015-03-30T16:41:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"49d0f639b1b30a947641457596fea0e2649cae5e","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ruby/openssl/pulls/10/commits","review_comments_url":"https://api.github.com/repos/ruby/openssl/pulls/10/comments","review_comment_url":"https://api.github.com/repos/ruby/openssl/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ruby/openssl/issues/10/comments","statuses_url":"https://api.github.com/repos/ruby/openssl/statuses/ea9a6f8c074506615e1fe33db7712fde2d0d7284","head":{"label":"tarcieri:stricter-hostname-verification","ref":"stricter-hostname-verification","sha":"ea9a6f8c074506615e1fe33db7712fde2d0d7284","user":{"login":"tarcieri","id":797,"avatar_url":"https://avatars.githubusercontent.com/u/797?v=3","gravatar_id":"","url":"https://api.github.com/users/tarcieri","html_url":"https://github.com/tarcieri","followers_url":"https://api.github.com/users/tarcieri/followers","following_url":"https://api.github.com/users/tarcieri/following{/other_user}","gists_url":"https://api.github.com/users/tarcieri/gists{/gist_id}","starred_url":"https://api.github.com/users/tarcieri/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tarcieri/subscriptions","organizations_url":"https://api.github.com/users/tarcieri/orgs","repos_url":"https://api.github.com/users/tarcieri/repos","events_url":"https://api.github.com/users/tarcieri/events{/privacy}","received_events_url":"https://api.github.com/users/tarcieri/received_events","type":"User","site_admin":false},"repo":{"id":33002352,"name":"openssl","full_name":"tarcieri/openssl","owner":{"login":"tarcieri","id":797,"avatar_url":"https://avatars.githubusercontent.com/u/797?v=3","gravatar_id":"","url":"https://api.github.com/users/tarcieri","html_url":"https://github.com/tarcieri","followers_url":"https://api.github.com/users/tarcieri/followers","following_url":"https://api.github.com/users/tarcieri/following{/other_user}","gists_url":"https://api.github.com/users/tarcieri/gists{/gist_id}","starred_url":"https://api.github.com/users/tarcieri/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tarcieri/subscriptions","organizations_url":"https://api.github.com/users/tarcieri/orgs","repos_url":"https://api.github.com/users/tarcieri/repos","events_url":"https://api.github.com/users/tarcieri/events{/privacy}","received_events_url":"https://api.github.com/users/tarcieri/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tarcieri/openssl","description":"Provides SSL, TLS and general purpose cryptography.","fork":true,"url":"https://api.github.com/repos/tarcieri/openssl","forks_url":"https://api.github.com/repos/tarcieri/openssl/forks","keys_url":"https://api.github.com/repos/tarcieri/openssl/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tarcieri/openssl/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tarcieri/openssl/teams","hooks_url":"https://api.github.com/repos/tarcieri/openssl/hooks","issue_events_url":"https://api.github.com/repos/tarcieri/openssl/issues/events{/number}","events_url":"https://api.github.com/repos/tarcieri/openssl/events","assignees_url":"https://api.github.com/repos/tarcieri/openssl/assignees{/user}","branches_url":"https://api.github.com/repos/tarcieri/openssl/branches{/branch}","tags_url":"https://api.github.com/repos/tarcieri/openssl/tags","blobs_url":"https://api.github.com/repos/tarcieri/openssl/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tarcieri/openssl/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tarcieri/openssl/git/refs{/sha}","trees_url":"https://api.github.com/repos/tarcieri/openssl/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tarcieri/openssl/statuses/{sha}","languages_url":"https://api.github.com/repos/tarcieri/openssl/languages","stargazers_url":"https://api.github.com/repos/tarcieri/openssl/stargazers","contributors_url":"https://api.github.com/repos/tarcieri/openssl/contributors","subscribers_url":"https://api.github.com/repos/tarcieri/openssl/subscribers","subscription_url":"https://api.github.com/repos/tarcieri/openssl/subscription","commits_url":"https://api.github.com/repos/tarcieri/openssl/commits{/sha}","git_commits_url":"https://api.github.com/repos/tarcieri/openssl/git/commits{/sha}","comments_url":"https://api.github.com/repos/tarcieri/openssl/comments{/number}","issue_comment_url":"https://api.github.com/repos/tarcieri/openssl/issues/comments{/number}","contents_url":"https://api.github.com/repos/tarcieri/openssl/contents/{+path}","compare_url":"https://api.github.com/repos/tarcieri/openssl/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tarcieri/openssl/merges","archive_url":"https://api.github.com/repos/tarcieri/openssl/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tarcieri/openssl/downloads","issues_url":"https://api.github.com/repos/tarcieri/openssl/issues{/number}","pulls_url":"https://api.github.com/repos/tarcieri/openssl/pulls{/number}","milestones_url":"https://api.github.com/repos/tarcieri/openssl/milestones{/number}","notifications_url":"https://api.github.com/repos/tarcieri/openssl/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tarcieri/openssl/labels{/name}","releases_url":"https://api.github.com/repos/tarcieri/openssl/releases{/id}","created_at":"2015-03-27T18:24:58Z","updated_at":"2015-03-27T18:24:59Z","pushed_at":"2015-03-30T00:29:54Z","git_url":"git://github.com/tarcieri/openssl.git","ssh_url":"git@github.com:tarcieri/openssl.git","clone_url":"https://github.com/tarcieri/openssl.git","svn_url":"https://github.com/tarcieri/openssl","homepage":"","size":511,"stargazers_count":0,"watchers_count":0,"language":"C","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"ruby:master","ref":"master","sha":"fe817406894fae2639417711b4d8857c4a0a77b0","user":{"login":"ruby","id":210414,"avatar_url":"https://avatars.githubusercontent.com/u/210414?v=3","gravatar_id":"","url":"https://api.github.com/users/ruby","html_url":"https://github.com/ruby","followers_url":"https://api.github.com/users/ruby/followers","following_url":"https://api.github.com/users/ruby/following{/other_user}","gists_url":"https://api.github.com/users/ruby/gists{/gist_id}","starred_url":"https://api.github.com/users/ruby/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ruby/subscriptions","organizations_url":"https://api.github.com/users/ruby/orgs","repos_url":"https://api.github.com/users/ruby/repos","events_url":"https://api.github.com/users/ruby/events{/privacy}","received_events_url":"https://api.github.com/users/ruby/received_events","type":"Organization","site_admin":false},"repo":{"id":25799462,"name":"openssl","full_name":"ruby/openssl","owner":{"login":"ruby","id":210414,"avatar_url":"https://avatars.githubusercontent.com/u/210414?v=3","gravatar_id":"","url":"https://api.github.com/users/ruby","html_url":"https://github.com/ruby","followers_url":"https://api.github.com/users/ruby/followers","following_url":"https://api.github.com/users/ruby/following{/other_user}","gists_url":"https://api.github.com/users/ruby/gists{/gist_id}","starred_url":"https://api.github.com/users/ruby/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ruby/subscriptions","organizations_url":"https://api.github.com/users/ruby/orgs","repos_url":"https://api.github.com/users/ruby/repos","events_url":"https://api.github.com/users/ruby/events{/privacy}","received_events_url":"https://api.github.com/users/ruby/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ruby/openssl","description":"Provides SSL, TLS and general purpose cryptography.","fork":false,"url":"https://api.github.com/repos/ruby/openssl","forks_url":"https://api.github.com/repos/ruby/openssl/forks","keys_url":"https://api.github.com/repos/ruby/openssl/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ruby/openssl/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ruby/openssl/teams","hooks_url":"https://api.github.com/repos/ruby/openssl/hooks","issue_events_url":"https://api.github.com/repos/ruby/openssl/issues/events{/number}","events_url":"https://api.github.com/repos/ruby/openssl/events","assignees_url":"https://api.github.com/repos/ruby/openssl/assignees{/user}","branches_url":"https://api.github.com/repos/ruby/openssl/branches{/branch}","tags_url":"https://api.github.com/repos/ruby/openssl/tags","blobs_url":"https://api.github.com/repos/ruby/openssl/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ruby/openssl/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ruby/openssl/git/refs{/sha}","trees_url":"https://api.github.com/repos/ruby/openssl/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ruby/openssl/statuses/{sha}","languages_url":"https://api.github.com/repos/ruby/openssl/languages","stargazers_url":"https://api.github.com/repos/ruby/openssl/stargazers","contributors_url":"https://api.github.com/repos/ruby/openssl/contributors","subscribers_url":"https://api.github.com/repos/ruby/openssl/subscribers","subscription_url":"https://api.github.com/repos/ruby/openssl/subscription","commits_url":"https://api.github.com/repos/ruby/openssl/commits{/sha}","git_commits_url":"https://api.github.com/repos/ruby/openssl/git/commits{/sha}","comments_url":"https://api.github.com/repos/ruby/openssl/comments{/number}","issue_comment_url":"https://api.github.com/repos/ruby/openssl/issues/comments{/number}","contents_url":"https://api.github.com/repos/ruby/openssl/contents/{+path}","compare_url":"https://api.github.com/repos/ruby/openssl/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ruby/openssl/merges","archive_url":"https://api.github.com/repos/ruby/openssl/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ruby/openssl/downloads","issues_url":"https://api.github.com/repos/ruby/openssl/issues{/number}","pulls_url":"https://api.github.com/repos/ruby/openssl/pulls{/number}","milestones_url":"https://api.github.com/repos/ruby/openssl/milestones{/number}","notifications_url":"https://api.github.com/repos/ruby/openssl/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ruby/openssl/labels{/name}","releases_url":"https://api.github.com/repos/ruby/openssl/releases{/id}","created_at":"2014-10-27T02:12:48Z","updated_at":"2015-03-26T09:00:47Z","pushed_at":"2015-03-30T00:29:54Z","git_url":"git://github.com/ruby/openssl.git","ssh_url":"git@github.com:ruby/openssl.git","clone_url":"https://github.com/ruby/openssl.git","svn_url":"https://github.com/ruby/openssl","homepage":"","size":511,"stargazers_count":11,"watchers_count":11,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"open_issues_count":5,"forks":6,"open_issues":5,"watchers":11,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ruby/openssl/pulls/10"},"html":{"href":"https://github.com/ruby/openssl/pull/10"},"issue":{"href":"https://api.github.com/repos/ruby/openssl/issues/10"},"comments":{"href":"https://api.github.com/repos/ruby/openssl/issues/10/comments"},"review_comments":{"href":"https://api.github.com/repos/ruby/openssl/pulls/10/comments"},"review_comment":{"href":"https://api.github.com/repos/ruby/openssl/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ruby/openssl/pulls/10/commits"},"statuses":{"href":"https://api.github.com/repos/ruby/openssl/statuses/ea9a6f8c074506615e1fe33db7712fde2d0d7284"}}}}