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 "viewer.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 LLUserAuth *gUserAuthp = NULL;
00070 
00071 
00072 LLUserAuth::LLUserAuth() :
00073         mTransaction(NULL),
00074         mLastTransferRateBPS(0)
00075 {
00076         mAuthResponse = E_NO_RESPONSE_YET;
00077 }
00078 
00079 LLUserAuth::~LLUserAuth()
00080 {
00081         delete mTransaction;
00082         mTransaction = NULL;
00083 }
00084 
00085 // passwd is already MD5 hashed by the time we get to it.
00086 void LLUserAuth::authenticate(
00087         const char* auth_uri,
00088         const char* method,
00089         const char* firstname,
00090         const char* lastname,
00091         const char* passwd,
00092         const char* start,
00093         BOOL skip_optional,
00094         BOOL accept_tos,
00095         BOOL accept_critical_message,
00096         const LLUUID& viewer_digest,
00097         BOOL last_exec_froze, 
00098         const std::vector<const char*>& requested_options,
00099         const std::string& hashed_mac,
00100         const std::string& hashed_volume_serial)
00101 {
00102         std::string dpasswd("$1$");
00103         dpasswd.append(passwd);
00104         llinfos << "Authenticating: " << firstname << " " << lastname << ", "
00105                         << /*dpasswd.c_str() <<*/ llendl;
00106         std::ostringstream option_str;
00107         option_str << "Options: ";
00108         std::ostream_iterator<const char*> appender(option_str, ", ");
00109         std::copy(requested_options.begin(), requested_options.end(), appender);
00110         option_str << "END";
00111         llinfos << option_str.str().c_str() << llendl;
00112 
00113         mAuthResponse = E_NO_RESPONSE_YET;
00114         //mDownloadTimer.reset();
00115         
00116         // create the request
00117         XMLRPC_REQUEST request = XMLRPC_RequestNew();
00118         XMLRPC_RequestSetMethodName(request, method);
00119         XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
00120 
00121         // stuff the parameters
00122         XMLRPC_VALUE params = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
00123         XMLRPC_VectorAppendString(params, "first", firstname, 0);
00124         XMLRPC_VectorAppendString(params, "last", lastname, 0);
00125         XMLRPC_VectorAppendString(params, "passwd", dpasswd.c_str(), 0);
00126         XMLRPC_VectorAppendString(params, "start", start, 0);
00127         XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0); // Includes channel name
00128         XMLRPC_VectorAppendString(params, "channel", gChannelName.c_str(), 0);
00129         XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);
00130         XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0);
00131         // A bit of security through obscurity: id0 is volume_serial
00132         XMLRPC_VectorAppendString(params, "id0", hashed_volume_serial.c_str(), 0);
00133         if (skip_optional)
00134         {
00135                 XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
00136         }
00137         if (accept_tos)
00138         {
00139                 XMLRPC_VectorAppendString(params, "agree_to_tos", "true", 0);
00140         }
00141         if (accept_critical_message)
00142         {
00143                 XMLRPC_VectorAppendString(params, "read_critical", "true", 0);
00144         }
00145         XMLRPC_VectorAppendString(params, "viewer_digest", viewer_digest.asString().c_str(), 0);
00146         XMLRPC_VectorAppendInt(params, "last_exec_event", (int) last_exec_froze);
00147 
00148         // append optional requests in an array
00149         XMLRPC_VALUE options = XMLRPC_CreateVector("options", xmlrpc_vector_array);
00150         std::vector<const char*>::const_iterator it = requested_options.begin();
00151         std::vector<const char*>::const_iterator end = requested_options.end();
00152         for( ; it < end; ++it)
00153         {
00154                 XMLRPC_VectorAppendString(options, NULL, (*it), 0);
00155         }
00156         XMLRPC_AddValueToVector(params, options);
00157 
00158         // put the parameters on the request
00159         XMLRPC_RequestSetData(request, params);
00160 
00161         mTransaction = new LLXMLRPCTransaction(auth_uri, request);
00162         
00163         XMLRPC_RequestFree(request, 1);
00164 
00165         llinfos << "LLUserAuth::authenticate: uri=" << auth_uri << llendl;
00166 }
00167 
00168 LLUserAuth::UserAuthcode LLUserAuth::authResponse()
00169 {
00170         if (!mTransaction)
00171         {
00172                 return mAuthResponse;
00173         }
00174         
00175         bool done = mTransaction->process();
00176 
00177         if (!done) {
00178                 if (LLXMLRPCTransaction::StatusDownloading == mTransaction->status(0))
00179                 {
00180                         mAuthResponse = E_DOWNLOADING;
00181                 }
00182                 
00183                 return mAuthResponse;
00184         }
00185         
00186         
00187         mLastTransferRateBPS = mTransaction->transferRate();
00188 
00189         int result;
00190         mTransaction->status(&result);
00191         mErrorMessage = mTransaction->statusMessage();
00192         
00193         // if curl was ok, parse the download area.
00194         switch (result)
00195         {
00196         case CURLE_OK:
00197                 mAuthResponse = parseResponse();
00198                 break;
00199         case CURLE_COULDNT_RESOLVE_HOST:
00200                 mAuthResponse = E_COULDNT_RESOLVE_HOST;
00201                 break;
00202         case CURLE_SSL_PEER_CERTIFICATE:
00203                 mAuthResponse = E_SSL_PEER_CERTIFICATE;
00204                 break;
00205         case CURLE_SSL_CACERT:
00206                 mAuthResponse = E_SSL_CACERT;
00207                 break;
00208         case CURLE_SSL_CONNECT_ERROR:
00209                 mAuthResponse = E_SSL_CONNECT_ERROR;
00210                 break;
00211         default:
00212                 mAuthResponse = E_UNHANDLED_ERROR;
00213                 break;
00214         }
00215         
00216         llinfos << "Processed response: " << result << llendl;
00217 
00218         delete mTransaction;
00219         mTransaction = NULL;
00220         
00221         return mAuthResponse;
00222 }
00223 
00224 static void parseOptionInto(
00225         const std::string& id, XMLRPC_VALUE option, LLUserAuth::options_t& options)
00226 {
00227         std::string key;
00228         std::string val;
00229         XMLRPC_VALUE_TYPE_EASY type;
00230         XMLRPC_VALUE row = XMLRPC_VectorRewind(option);
00231         while(row)
00232         {
00233                 XMLRPC_VALUE opt  = XMLRPC_VectorRewind(row);
00234                 LLUserAuth::response_t responses;
00235                 while(opt)
00236                 {
00237                         key.assign(XMLRPC_GetValueID(opt));
00238                         //llinfos "option key: " << key << llendl;
00239                         type = XMLRPC_GetValueTypeEasy(opt);
00240                         if(xmlrpc_type_string == type)
00241                         {
00242                                 val.assign(XMLRPC_GetValueString(opt));
00243                         }
00244                         else if(xmlrpc_type_int == type)
00245                         {
00246                                 val = llformat("%d", XMLRPC_GetValueInt(opt));
00247                         }
00248                         //llinfos "option val: " << val << llendl;
00249                         responses.insert(LLUserAuth::response_t::value_type(key, val));
00250                         opt = XMLRPC_VectorNext(row);
00251                 }
00252                 options.push_back(responses);
00253                 row = XMLRPC_VectorNext(option);
00254         }
00255 }
00256 
00257 LLUserAuth::UserAuthcode LLUserAuth::parseResponse()
00258 {
00259         // The job of this function is to parse sCurlDownloadArea and
00260         // extract every member into either the mResponses or
00261         // mOptions. For now, we will only be looking at mResponses, which
00262         // will all be string => string pairs.
00263         UserAuthcode rv = E_UNHANDLED_ERROR;
00264         XMLRPC_REQUEST response = mTransaction->response();
00265         if(!response) return rv;
00266 
00267         // clear out any old parsing
00268         mResponses.clear();
00269         mOptions.clear();
00270 
00271         // Now, parse everything
00272         std::string key;
00273         std::string val;
00274         XMLRPC_VALUE param = NULL;
00275         XMLRPC_VALUE current = NULL;
00276         XMLRPC_VALUE_TYPE_EASY type;
00277         param = XMLRPC_RequestGetData(response);
00278         if(!param) goto exit;
00279         current = XMLRPC_VectorRewind(param);
00280         while(current)
00281         {
00282                 key.assign(XMLRPC_GetValueID(current));
00283                 lldebugs << "key: " << key << llendl;
00284                 type = XMLRPC_GetValueTypeEasy(current);
00285                 if(xmlrpc_type_string == type)
00286                 {
00287                         val.assign(XMLRPC_GetValueString(current));
00288                         lldebugs << "val: " << val << llendl;
00289                         mResponses.insert(response_t::value_type(key, val));
00290                 }
00291                 else if(xmlrpc_type_int == type)
00292                 {
00293                         char buf[MAX_STRING];           /* Flawfinder: ignore */
00294                         snprintf(buf, MAX_STRING, "%d", XMLRPC_GetValueInt(current));           /* Flawfinder: ignore */
00295                         val.assign(buf);
00296                         lldebugs << "val: " << val << llendl;
00297                         mResponses.insert(response_t::value_type(key, val));
00298                 }
00299                 else if(xmlrpc_type_array == type)
00300                 {
00301                         options_t options;
00302                         parseOptionInto(key, current, options);
00303                         mOptions.insert(all_options_t::value_type(key, options));
00304                 }
00305                 else
00306                 {
00307                         // whoops - bad response
00308                         llwarns << "Unhandled xmlrpc type, key, value: " << type << " "
00309                                         << key << " " << val << "." << llendl;
00310                         rv = E_UNHANDLED_ERROR;
00311                         break;
00312                 }
00313                 current = XMLRPC_VectorNext(param);
00314                 rv = E_OK;
00315         }
00316 
00317  exit:
00318         return rv;
00319 }
00320 
00321 const char* LLUserAuth::getResponse(const char* name) const
00322 {
00323         if(!name) return NULL;
00324         std::string key(name);
00325         response_t::const_iterator it = mResponses.find(key);
00326         if(it != mResponses.end())
00327         {
00328                 return((*it).second.c_str());
00329         }
00330         return NULL;
00331 }
00332 
00333 BOOL LLUserAuth::getOptions(const char* name, options_t& options) const
00334 {
00335         if(!name) return FALSE;
00336         std::string key(name);
00337         all_options_t::const_iterator it = mOptions.find(key);
00338         if(it != mOptions.end())
00339         {
00340                 // found the option set, copyt them onto the container.
00341                 std::back_insert_iterator<options_t> ii(options);
00342                 std::copy((*it).second.begin(), (*it).second.end(), ii);
00343                 return TRUE;
00344         }
00345         return FALSE;
00346 }
00347 
00348 

Generated on Thu Jul 1 06:09:24 2010 for Second Life Viewer by  doxygen 1.4.7