1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <string> 6 7 #include "base/basictypes.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/string_util.h" 10 #include "base/utf_string_conversions.h" 11 #include "net/base/net_errors.h" 12 #include "net/http/http_auth_handler_basic.h" 13 #include "net/http/http_request_info.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace net { 17 18 TEST(HttpAuthHandlerBasicTest, GenerateAuthToken) { 19 static const struct { 20 const char* username; 21 const char* password; 22 const char* expected_credentials; 23 } tests[] = { 24 { "foo", "bar", "Basic Zm9vOmJhcg==" }, 25 // Empty username 26 { "", "foobar", "Basic OmZvb2Jhcg==" }, 27 // Empty password 28 { "anon", "", "Basic YW5vbjo=" }, 29 // Empty username and empty password. 30 { "", "", "Basic Og==" }, 31 }; 32 GURL origin("http://www.example.com"); 33 HttpAuthHandlerBasic::Factory factory; 34 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 35 std::string challenge = "Basic realm=\"Atlantis\""; 36 scoped_ptr<HttpAuthHandler> basic; 37 EXPECT_EQ(OK, factory.CreateAuthHandlerFromString( 38 challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog(), &basic)); 39 string16 username(ASCIIToUTF16(tests[i].username)); 40 string16 password(ASCIIToUTF16(tests[i].password)); 41 HttpRequestInfo request_info; 42 std::string auth_token; 43 int rv = basic->GenerateAuthToken(&username, &password, &request_info, 44 NULL, &auth_token); 45 EXPECT_EQ(OK, rv); 46 EXPECT_STREQ(tests[i].expected_credentials, auth_token.c_str()); 47 } 48 } 49 50 TEST(HttpAuthHandlerBasicTest, HandleAnotherChallenge) { 51 static const struct { 52 const char* challenge; 53 HttpAuth::AuthorizationResult expected_rv; 54 } tests[] = { 55 // The handler is initialized using this challenge. The first 56 // time HandleAnotherChallenge is called with it should cause it 57 // to treat the second challenge as a rejection since it is for 58 // the same realm. 59 { 60 "Basic realm=\"First\"", 61 HttpAuth::AUTHORIZATION_RESULT_REJECT 62 }, 63 64 // A challenge for a different realm. 65 { 66 "Basic realm=\"Second\"", 67 HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM 68 }, 69 70 // Although RFC 2617 isn't explicit about this case, if there is 71 // more than one realm directive, we pick the last one. So this 72 // challenge should be treated as being for "First" realm. 73 { 74 "Basic realm=\"Second\",realm=\"First\"", 75 HttpAuth::AUTHORIZATION_RESULT_REJECT 76 }, 77 78 // And this one should be treated as if it was for "Second." 79 { 80 "basic realm=\"First\",realm=\"Second\"", 81 HttpAuth::AUTHORIZATION_RESULT_DIFFERENT_REALM 82 } 83 }; 84 85 GURL origin("http://www.example.com"); 86 HttpAuthHandlerBasic::Factory factory; 87 scoped_ptr<HttpAuthHandler> basic; 88 EXPECT_EQ(OK, factory.CreateAuthHandlerFromString( 89 tests[0].challenge, HttpAuth::AUTH_SERVER, origin, 90 BoundNetLog(), &basic)); 91 92 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 93 std::string challenge(tests[i].challenge); 94 HttpAuth::ChallengeTokenizer tok(challenge.begin(), 95 challenge.end()); 96 EXPECT_EQ(tests[i].expected_rv, basic->HandleAnotherChallenge(&tok)); 97 } 98 } 99 100 TEST(HttpAuthHandlerBasicTest, InitFromChallenge) { 101 static const struct { 102 const char* challenge; 103 int expected_rv; 104 const char* expected_realm; 105 } tests[] = { 106 // No realm (we allow this even though realm is supposed to be required 107 // according to RFC 2617.) 108 { 109 "Basic", 110 OK, 111 "", 112 }, 113 114 // Realm is empty string. 115 { 116 "Basic realm=\"\"", 117 OK, 118 "", 119 }, 120 121 // Realm is valid. 122 { 123 "Basic realm=\"test_realm\"", 124 OK, 125 "test_realm", 126 }, 127 128 // The parser ignores tokens which aren't known. 129 { 130 "Basic realm=\"test_realm\",unknown_token=foobar", 131 OK, 132 "test_realm", 133 }, 134 135 // The parser skips over tokens which aren't known. 136 { 137 "Basic unknown_token=foobar,realm=\"test_realm\"", 138 OK, 139 "test_realm", 140 }, 141 142 #if 0 143 // TODO(cbentzel): It's unclear what the parser should do in these cases. 144 // It seems like this should either be treated as invalid, 145 // or the spaces should be used as a separator. 146 { 147 "Basic realm=\"test_realm\" unknown_token=foobar", 148 OK, 149 "test_realm", 150 }, 151 152 // The parser skips over tokens which aren't known. 153 { 154 "Basic unknown_token=foobar realm=\"test_realm\"", 155 OK, 156 "test_realm", 157 }, 158 #endif 159 160 // The parser fails when the first token is not "Basic". 161 { 162 "Negotiate", 163 ERR_INVALID_RESPONSE, 164 "" 165 }, 166 167 // Although RFC 2617 isn't explicit about this case, if there is 168 // more than one realm directive, we pick the last one. 169 { 170 "Basic realm=\"foo\",realm=\"bar\"", 171 OK, 172 "bar", 173 }, 174 }; 175 HttpAuthHandlerBasic::Factory factory; 176 GURL origin("http://www.example.com"); 177 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 178 std::string challenge = tests[i].challenge; 179 scoped_ptr<HttpAuthHandler> basic; 180 int rv = factory.CreateAuthHandlerFromString( 181 challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog(), &basic); 182 EXPECT_EQ(tests[i].expected_rv, rv); 183 if (rv == OK) 184 EXPECT_EQ(tests[i].expected_realm, basic->realm()); 185 } 186 } 187 188 } // namespace net 189