lluserauth.cpp

Go to the documentation of this file.
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 // NOTE: MUST include these after otherincludes since queue gets redefined!?!!
00047 #include <curl/curl.h>
00048 #include <xmlrpc-epi/xmlrpc.h>
00049 
00050 
00051 
00052 // Don't define PLATFORM_STRING for unknown platforms - they need
00053 // to get added to the login cgi script, so we want this to cause an
00054 // error if we get compiled for a different platform.
00055 // *FIX: This is misreporting on linux. Change this so that linux is
00056 // in fact reporting linux.
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                         << /*dpasswd.c_str() <<*/ 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         //mDownloadTimer.reset();
00118         
00119         // create the request
00120         XMLRPC_REQUEST request = XMLRPC_RequestNew();
00121         XMLRPC_RequestSetMethodName(request, method);
00122         XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
00123 
00124         // stuff the parameters
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); // Includes channel name
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         // A bit of security through obscurity: id0 is volume_serial
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         // append optional requests in an array
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         // put the parameters on the request
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 // Legacy version of constructor
00173 
00174 // passwd is already MD5 hashed by the time we get to it.
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                         << /*dpasswd.c_str() <<*/ 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         //mDownloadTimer.reset();
00204         
00205         // create the request
00206         XMLRPC_REQUEST request = XMLRPC_RequestNew();
00207         XMLRPC_RequestSetMethodName(request, method);
00208         XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
00209 
00210         // stuff the parameters
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); // Includes channel name
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         // A bit of security through obscurity: id0 is volume_serial
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         // append optional requests in an array
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         // put the parameters on the request
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         // if curl was ok, parse the download area.
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                         //llinfos "option key: " << key << llendl;
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                         //llinfos "option val: " << val << llendl;
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         // The job of this function is to parse sCurlDownloadArea and
00349         // extract every member into either the mResponses or
00350         // mOptions. For now, we will only be looking at mResponses, which
00351         // will all be string => string pairs.
00352         UserAuthcode rv = E_UNHANDLED_ERROR;
00353         XMLRPC_REQUEST response = mTransaction->response();
00354         if(!response) return rv;
00355 
00356         // clear out any old parsing
00357         mResponses.clear();
00358         mOptions.clear();
00359 
00360         // Now, parse everything
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];           /* Flawfinder: ignore */
00383                         snprintf(buf, MAX_STRING, "%d", XMLRPC_GetValueInt(current));           /* Flawfinder: ignore */
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                         // whoops - bad response
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                 // found the option set, copyt them onto the container.
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 

Generated on Fri May 16 08:34:08 2008 for SecondLife by  doxygen 1.5.5