00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "httpAuthorization.h"
00016 #include "httpChannel.h"
00017 #include "urlSpec.h"
00018
00019 #ifdef HAVE_OPENSSL
00020
00021 static const char base64_table[64] = {
00022 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
00023 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
00024 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
00025 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
00026 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
00027 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
00028 'w', 'x', 'y', 'z', '0', '1', '2', '3',
00029 '4', '5', '6', '7', '8', '9', '+', '/',
00030 };
00031
00032 static unsigned char base64_invert[128];
00033 static bool got_base64_invert = false;
00034
00035
00036
00037
00038
00039
00040 HTTPAuthorization::
00041 HTTPAuthorization(const HTTPAuthorization::Tokens &tokens,
00042 const URLSpec &url, bool is_proxy) {
00043 Tokens::const_iterator ti;
00044 ti = tokens.find("realm");
00045 if (ti != tokens.end()) {
00046 _realm = (*ti).second;
00047 }
00048
00049 URLSpec canon = get_canonical_url(url);
00050
00051 ti = tokens.find("domain");
00052 if (ti != tokens.end() && !is_proxy) {
00053
00054
00055 const string &domain = (*ti).second;
00056 size_t p = 0;
00057 while (p < domain.length()) {
00058 while (p < domain.length() && isspace(domain[p])) {
00059 ++p;
00060 }
00061 size_t q = p;
00062 while (q < domain.length() && !isspace(domain[q])) {
00063 ++q;
00064 }
00065 if (q > p) {
00066 string domain_str = domain.substr(p, q - p);
00067 URLSpec domain_url(domain_str);
00068 if (domain_url.has_server()) {
00069
00070 _domain.push_back(get_canonical_url(domain_url).get_url());
00071 } else {
00072
00073 domain_url = canon;
00074 domain_url.set_path(domain_str);
00075 _domain.push_back(domain_url.get_url());
00076 }
00077 }
00078 p = q;
00079 }
00080
00081 } else {
00082
00083
00084 string canon_str = canon.get_url();
00085 size_t slash = canon_str.rfind('/');
00086 nassertv(slash != string::npos);
00087 _domain.push_back(canon_str.substr(0, slash + 1));
00088 }
00089 }
00090
00091
00092
00093
00094
00095
00096 HTTPAuthorization::
00097 ~HTTPAuthorization() {
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 bool HTTPAuthorization::
00109 is_valid() {
00110 return true;
00111 }
00112
00113
00114
00115
00116
00117
00118
00119 void HTTPAuthorization::
00120 parse_authentication_schemes(HTTPAuthorization::AuthenticationSchemes &schemes,
00121 const string &field_value) {
00122
00123
00124
00125
00126
00127
00128
00129
00130 size_t p = 0;
00131 while (p < field_value.length() && isspace(field_value[p])) {
00132 ++p;
00133 }
00134
00135 if (p < field_value.length()) {
00136 size_t q = p;
00137 while (q < field_value.length() && !isspace(field_value[q])) {
00138 ++q;
00139 }
00140
00141 string scheme = HTTPChannel::downcase(field_value.substr(p, q - p));
00142 Tokens *tokens = &(schemes[scheme]);
00143
00144
00145 p = q + 1;
00146 while (p < field_value.length()) {
00147 q = p;
00148 while (q < field_value.length() && field_value[q] != '=' &&
00149 field_value[q] != ',' && !isspace(field_value[q])) {
00150 ++q;
00151 }
00152 if (field_value[q] == '=') {
00153
00154 string token = HTTPChannel::downcase(field_value.substr(p, q - p));
00155 string value;
00156 p = scan_quoted_or_unquoted_string(value, field_value, q + 1);
00157 (*tokens)[token] = value;
00158
00159
00160 while (p < field_value.length() &&
00161 (field_value[p] == ',' || isspace(field_value[p]))) {
00162 ++p;
00163 }
00164
00165 } else {
00166
00167 scheme = HTTPChannel::downcase(field_value.substr(p, q - p));
00168 tokens = &(schemes[scheme]);
00169 p = q + 1;
00170 }
00171 }
00172 }
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 URLSpec HTTPAuthorization::
00184 get_canonical_url(const URLSpec &url) {
00185 URLSpec canon = url;
00186 canon.set_scheme(canon.get_scheme());
00187 canon.set_username(string());
00188 canon.set_port(canon.get_port());
00189 canon.set_path(canon.get_path());
00190
00191 return canon;
00192 }
00193
00194
00195
00196
00197
00198
00199
00200 string HTTPAuthorization::
00201 base64_encode(const string &s) {
00202
00203
00204 size_t num_words = (s.size() + 2) / 3;
00205 string result;
00206 result.reserve(num_words * 4);
00207 size_t p;
00208 for (p = 0; p + 2 < s.size(); p += 3) {
00209 unsigned int word =
00210 ((unsigned)s[p] << 16) |
00211 ((unsigned)s[p + 1] << 8) |
00212 ((unsigned)s[p + 2]);
00213 result += base64_table[(word >> 18) & 0x3f];
00214 result += base64_table[(word >> 12) & 0x3f];
00215 result += base64_table[(word >> 6) & 0x3f];
00216 result += base64_table[(word) & 0x3f];
00217 }
00218
00219 if (p < s.size()) {
00220 unsigned int word = ((unsigned)s[p] << 16);
00221 p++;
00222 if (p < s.size()) {
00223 word |= ((unsigned)s[p] << 8);
00224 p++;
00225 nassertr(p == s.size(), result);
00226
00227 result += base64_table[(word >> 18) & 0x3f];
00228 result += base64_table[(word >> 12) & 0x3f];
00229 result += base64_table[(word >> 6) & 0x3f];
00230 result += '=';
00231 } else {
00232 result += base64_table[(word >> 18) & 0x3f];
00233 result += base64_table[(word >> 12) & 0x3f];
00234 result += '=';
00235 result += '=';
00236 }
00237 }
00238
00239 return result;
00240 }
00241
00242
00243
00244
00245
00246
00247 string HTTPAuthorization::
00248 base64_decode(const string &s) {
00249
00250 if (!got_base64_invert) {
00251 int i;
00252 for (i = 0; i < 128; i++) {
00253 base64_invert[i] = 0xff;
00254 }
00255
00256 for (int i = 0; i < 64; i++) {
00257 base64_invert[(int)base64_table[i]] = i;
00258 }
00259
00260 base64_invert[(int)'='] = 0;
00261
00262 got_base64_invert = true;
00263 }
00264
00265
00266
00267 size_t num_words = s.size() / 4;
00268 string result;
00269 result.reserve(num_words * 3);
00270 size_t p;
00271 for (p = 0; p < s.size(); p += 4) {
00272 unsigned int c0 = base64_invert[s[p] & 0x7f];
00273 unsigned int c1 = base64_invert[s[p + 1] & 0x7f];
00274 unsigned int c2 = base64_invert[s[p + 2] & 0x7f];
00275 unsigned int c3 = base64_invert[s[p + 3] & 0x7f];
00276
00277 unsigned int word =
00278 (c0 << 18) | (c1 << 12) | (c2 << 6) | c3;
00279
00280 result += (char)((word >> 16) & 0xff);
00281 if (s[p + 2] != '=') {
00282 result += (char)((word >> 8) & 0xff);
00283 if (s[p + 3] != '=') {
00284 result += (char)(word & 0xff);
00285 }
00286 }
00287 }
00288
00289 return result;
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 size_t HTTPAuthorization::
00304 scan_quoted_or_unquoted_string(string &result, const string &source,
00305 size_t start) {
00306 result = string();
00307
00308 if (start < source.length()) {
00309 if (source[start] == '"') {
00310
00311 size_t p = start + 1;
00312 while (p < source.length() && source[p] != '"') {
00313 if (source[p] == '\\') {
00314
00315 ++p;
00316 if (p < source.length()) {
00317 result += source[p];
00318 ++p;
00319 }
00320 } else {
00321 result += source[p];
00322 ++p;
00323 }
00324 }
00325 if (p < source.length()) {
00326 ++p;
00327 }
00328 return p;
00329 }
00330
00331
00332 size_t p = start;
00333 while (p < source.length() && source[p] != ',' && !isspace(source[p])) {
00334 result += source[p];
00335 ++p;
00336 }
00337
00338 return p;
00339 }
00340
00341
00342 return start;
00343 }
00344
00345 #endif // HAVE_OPENSSL