00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "lluserauth.h"
00035
00036 #include <sstream>
00037 #include <iterator>
00038
00039 #include "lldir.h"
00040 #include "llversionviewer.h"
00041 #include "llappviewer.h"
00042 #include "llviewerbuild.h"
00043 #include "llviewercontrol.h"
00044 #include "llxmlrpctransaction.h"
00045
00046
00047 #include <curl/curl.h>
00048 #include <xmlrpc-epi/xmlrpc.h>
00049
00050
00051
00052
00053
00054
00055
00056
00057 #if LL_WINDOWS || LL_LINUX
00058 static const char* PLATFORM_STRING = "Win";
00059 #elif LL_DARWIN
00060 static const char* PLATFORM_STRING = "Mac";
00061 #elif LL_LINUX
00062 static const char* PLATFORM_STRING = "Lnx";
00063 #elif LL_SOLARIS
00064 static const char* PLATFORM_STRING = "Sol";
00065 #else
00066 #error("Unknown platform defined!")
00067 #endif
00068
00069
00070 LLUserAuth::LLUserAuth() :
00071 mTransaction(NULL),
00072 mLastTransferRateBPS(0)
00073 {
00074 mAuthResponse = E_NO_RESPONSE_YET;
00075 }
00076
00077 LLUserAuth::~LLUserAuth()
00078 {
00079 reset();
00080 }
00081
00082 void LLUserAuth::reset()
00083 {
00084 delete mTransaction;
00085 mTransaction = NULL;
00086 mResponses.clear();
00087 mOptions.clear();
00088 }
00089
00090
00091 void LLUserAuth::authenticate(
00092 const char* auth_uri,
00093 const char* method,
00094 const char* firstname,
00095 const char* lastname,
00096 LLUUID web_login_key,
00097 const char* start,
00098 BOOL skip_optional,
00099 BOOL accept_tos,
00100 BOOL accept_critical_message,
00101 BOOL last_exec_froze,
00102 const std::vector<const char*>& requested_options,
00103 const std::string& hashed_mac,
00104 const std::string& hashed_volume_serial)
00105 {
00106 LL_INFOS2("AppInit", "Authentication") << "Authenticating: " << firstname << " " << lastname << ", "
00107 << LL_ENDL;
00108 std::ostringstream option_str;
00109 option_str << "Options: ";
00110 std::ostream_iterator<const char*> appender(option_str, ", ");
00111 std::copy(requested_options.begin(), requested_options.end(), appender);
00112 option_str << "END";
00113
00114 LL_INFOS2("AppInit", "Authentication") << option_str.str().c_str() << LL_ENDL;
00115
00116 mAuthResponse = E_NO_RESPONSE_YET;
00117
00118
00119
00120 XMLRPC_REQUEST request = XMLRPC_RequestNew();
00121 XMLRPC_RequestSetMethodName(request, method);
00122 XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
00123
00124
00125 XMLRPC_VALUE params = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
00126 XMLRPC_VectorAppendString(params, "first", firstname, 0);
00127 XMLRPC_VectorAppendString(params, "last", lastname, 0);
00128 XMLRPC_VectorAppendString(params, "web_login_key", web_login_key.getString().c_str(), 0);
00129 XMLRPC_VectorAppendString(params, "start", start, 0);
00130 XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0);
00131 XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("VersionChannelName").c_str(), 0);
00132 XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);
00133 XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0);
00134
00135 XMLRPC_VectorAppendString(params, "id0", hashed_volume_serial.c_str(), 0);
00136 if (skip_optional)
00137 {
00138 XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
00139 }
00140 if (accept_tos)
00141 {
00142 XMLRPC_VectorAppendString(params, "agree_to_tos", "true", 0);
00143 }
00144 if (accept_critical_message)
00145 {
00146 XMLRPC_VectorAppendString(params, "read_critical", "true", 0);
00147 }
00148 XMLRPC_VectorAppendInt(params, "last_exec_event", (int) last_exec_froze);
00149
00150
00151 XMLRPC_VALUE options = XMLRPC_CreateVector("options", xmlrpc_vector_array);
00152 std::vector<const char*>::const_iterator it = requested_options.begin();
00153 std::vector<const char*>::const_iterator end = requested_options.end();
00154 for( ; it < end; ++it)
00155 {
00156 XMLRPC_VectorAppendString(options, NULL, (*it), 0);
00157 }
00158 XMLRPC_AddValueToVector(params, options);
00159
00160
00161 XMLRPC_RequestSetData(request, params);
00162
00163 mTransaction = new LLXMLRPCTransaction(auth_uri, request);
00164
00165 XMLRPC_RequestFree(request, 1);
00166
00167 LL_INFOS2("AppInit", "Authentication") << "LLUserAuth::authenticate: uri=" << auth_uri << LL_ENDL;
00168 }
00169
00170
00171
00172
00173
00174
00175 void LLUserAuth::authenticate(
00176 const char* auth_uri,
00177 const char* method,
00178 const char* firstname,
00179 const char* lastname,
00180 const char* passwd,
00181 const char* start,
00182 BOOL skip_optional,
00183 BOOL accept_tos,
00184 BOOL accept_critical_message,
00185 BOOL last_exec_froze,
00186 const std::vector<const char*>& requested_options,
00187 const std::string& hashed_mac,
00188 const std::string& hashed_volume_serial)
00189 {
00190 std::string dpasswd("$1$");
00191 dpasswd.append(passwd);
00192 LL_INFOS2("AppInit", "Authentication") << "Authenticating: " << firstname << " " << lastname << ", "
00193 << LL_ENDL;
00194 std::ostringstream option_str;
00195 option_str << "Options: ";
00196 std::ostream_iterator<const char*> appender(option_str, ", ");
00197 std::copy(requested_options.begin(), requested_options.end(), appender);
00198 option_str << "END";
00199
00200 LL_INFOS2("AppInit", "Authentication") << option_str.str().c_str() << LL_ENDL;
00201
00202 mAuthResponse = E_NO_RESPONSE_YET;
00203
00204
00205
00206 XMLRPC_REQUEST request = XMLRPC_RequestNew();
00207 XMLRPC_RequestSetMethodName(request, method);
00208 XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
00209
00210
00211 XMLRPC_VALUE params = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
00212 XMLRPC_VectorAppendString(params, "first", firstname, 0);
00213 XMLRPC_VectorAppendString(params, "last", lastname, 0);
00214 XMLRPC_VectorAppendString(params, "passwd", dpasswd.c_str(), 0);
00215 XMLRPC_VectorAppendString(params, "start", start, 0);
00216 XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0);
00217 XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("VersionChannelName").c_str(), 0);
00218 XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);
00219 XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0);
00220
00221 XMLRPC_VectorAppendString(params, "id0", hashed_volume_serial.c_str(), 0);
00222 if (skip_optional)
00223 {
00224 XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
00225 }
00226 if (accept_tos)
00227 {
00228 XMLRPC_VectorAppendString(params, "agree_to_tos", "true", 0);
00229 }
00230 if (accept_critical_message)
00231 {
00232 XMLRPC_VectorAppendString(params, "read_critical", "true", 0);
00233 }
00234 XMLRPC_VectorAppendInt(params, "last_exec_event", (int) last_exec_froze);
00235
00236
00237 XMLRPC_VALUE options = XMLRPC_CreateVector("options", xmlrpc_vector_array);
00238 std::vector<const char*>::const_iterator it = requested_options.begin();
00239 std::vector<const char*>::const_iterator end = requested_options.end();
00240 for( ; it < end; ++it)
00241 {
00242 XMLRPC_VectorAppendString(options, NULL, (*it), 0);
00243 }
00244 XMLRPC_AddValueToVector(params, options);
00245
00246
00247 XMLRPC_RequestSetData(request, params);
00248
00249 mTransaction = new LLXMLRPCTransaction(auth_uri, request);
00250
00251 XMLRPC_RequestFree(request, 1);
00252
00253 LL_INFOS2("AppInit", "Authentication") << "LLUserAuth::authenticate: uri=" << auth_uri << LL_ENDL;
00254 }
00255
00256
00257 LLUserAuth::UserAuthcode LLUserAuth::authResponse()
00258 {
00259 if (!mTransaction)
00260 {
00261 return mAuthResponse;
00262 }
00263
00264 bool done = mTransaction->process();
00265
00266 if (!done) {
00267 if (LLXMLRPCTransaction::StatusDownloading == mTransaction->status(0))
00268 {
00269 mAuthResponse = E_DOWNLOADING;
00270 }
00271
00272 return mAuthResponse;
00273 }
00274
00275
00276 mLastTransferRateBPS = mTransaction->transferRate();
00277
00278 int result;
00279 mTransaction->status(&result);
00280 mErrorMessage = mTransaction->statusMessage();
00281
00282
00283 switch (result)
00284 {
00285 case CURLE_OK:
00286 mAuthResponse = parseResponse();
00287 break;
00288 case CURLE_COULDNT_RESOLVE_HOST:
00289 mAuthResponse = E_COULDNT_RESOLVE_HOST;
00290 break;
00291 case CURLE_SSL_PEER_CERTIFICATE:
00292 mAuthResponse = E_SSL_PEER_CERTIFICATE;
00293 break;
00294 case CURLE_SSL_CACERT:
00295 mAuthResponse = E_SSL_CACERT;
00296 break;
00297 case CURLE_SSL_CONNECT_ERROR:
00298 mAuthResponse = E_SSL_CONNECT_ERROR;
00299 break;
00300 default:
00301 mAuthResponse = E_UNHANDLED_ERROR;
00302 break;
00303 }
00304
00305 LL_INFOS2("AppInit", "Authentication") << "Processed response: " << result << LL_ENDL;
00306
00307 delete mTransaction;
00308 mTransaction = NULL;
00309
00310 return mAuthResponse;
00311 }
00312
00313 static void parseOptionInto(
00314 const std::string& id, XMLRPC_VALUE option, LLUserAuth::options_t& options)
00315 {
00316 std::string key;
00317 std::string val;
00318 XMLRPC_VALUE_TYPE_EASY type;
00319 XMLRPC_VALUE row = XMLRPC_VectorRewind(option);
00320 while(row)
00321 {
00322 XMLRPC_VALUE opt = XMLRPC_VectorRewind(row);
00323 LLUserAuth::response_t responses;
00324 while(opt)
00325 {
00326 key.assign(XMLRPC_GetValueID(opt));
00327
00328 type = XMLRPC_GetValueTypeEasy(opt);
00329 if(xmlrpc_type_string == type)
00330 {
00331 val.assign(XMLRPC_GetValueString(opt));
00332 }
00333 else if(xmlrpc_type_int == type)
00334 {
00335 val = llformat("%d", XMLRPC_GetValueInt(opt));
00336 }
00337
00338 responses.insert(LLUserAuth::response_t::value_type(key, val));
00339 opt = XMLRPC_VectorNext(row);
00340 }
00341 options.push_back(responses);
00342 row = XMLRPC_VectorNext(option);
00343 }
00344 }
00345
00346 LLUserAuth::UserAuthcode LLUserAuth::parseResponse()
00347 {
00348
00349
00350
00351
00352 UserAuthcode rv = E_UNHANDLED_ERROR;
00353 XMLRPC_REQUEST response = mTransaction->response();
00354 if(!response) return rv;
00355
00356
00357 mResponses.clear();
00358 mOptions.clear();
00359
00360
00361 std::string key;
00362 std::string val;
00363 XMLRPC_VALUE param = NULL;
00364 XMLRPC_VALUE current = NULL;
00365 XMLRPC_VALUE_TYPE_EASY type;
00366 param = XMLRPC_RequestGetData(response);
00367 if(!param) goto exit;
00368 current = XMLRPC_VectorRewind(param);
00369 while(current)
00370 {
00371 key.assign(XMLRPC_GetValueID(current));
00372 lldebugs << "key: " << key << llendl;
00373 type = XMLRPC_GetValueTypeEasy(current);
00374 if(xmlrpc_type_string == type)
00375 {
00376 val.assign(XMLRPC_GetValueString(current));
00377 lldebugs << "val: " << val << llendl;
00378 mResponses.insert(response_t::value_type(key, val));
00379 }
00380 else if(xmlrpc_type_int == type)
00381 {
00382 char buf[MAX_STRING];
00383 snprintf(buf, MAX_STRING, "%d", XMLRPC_GetValueInt(current));
00384 val.assign(buf);
00385 lldebugs << "val: " << val << llendl;
00386 mResponses.insert(response_t::value_type(key, val));
00387 }
00388 else if(xmlrpc_type_array == type)
00389 {
00390 options_t options;
00391 parseOptionInto(key, current, options);
00392 mOptions.insert(all_options_t::value_type(key, options));
00393 }
00394 else
00395 {
00396
00397 llwarns << "Unhandled xmlrpc type, key, value: " << type << " "
00398 << key << " " << val << "." << llendl;
00399 rv = E_UNHANDLED_ERROR;
00400 break;
00401 }
00402 current = XMLRPC_VectorNext(param);
00403 rv = E_OK;
00404 }
00405
00406 exit:
00407 return rv;
00408 }
00409
00410 const char* LLUserAuth::getResponse(const char* name) const
00411 {
00412 if(!name) return NULL;
00413 std::string key(name);
00414 response_t::const_iterator it = mResponses.find(key);
00415 if(it != mResponses.end())
00416 {
00417 return((*it).second.c_str());
00418 }
00419 return NULL;
00420 }
00421
00422 BOOL LLUserAuth::getOptions(const char* name, options_t& options) const
00423 {
00424 if(!name) return FALSE;
00425 std::string key(name);
00426 all_options_t::const_iterator it = mOptions.find(key);
00427 if(it != mOptions.end())
00428 {
00429
00430 std::back_insert_iterator<options_t> ii(options);
00431 std::copy((*it).second.begin(), (*it).second.end(), ii);
00432 return TRUE;
00433 }
00434 return FALSE;
00435 }
00436
00437
00438