lluserauth.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:13k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lluserauth.cpp
  3.  * @brief LLUserAuth class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2003&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2003-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "lluserauth.h"
  34. #include <sstream>
  35. #include <iterator>
  36. #include "lldir.h"
  37. #include "llappviewer.h"
  38. #include "llviewercontrol.h"
  39. #include "llxmlrpctransaction.h"
  40. // NOTE: MUST include these after otherincludes since queue gets redefined!?!!
  41. #include <curl/curl.h>
  42. #include <xmlrpc-epi/xmlrpc.h>
  43. // Don't define PLATFORM_STRING for unknown platforms - they need
  44. // to get added to the login cgi script, so we want this to cause an
  45. // error if we get compiled for a different platform.
  46. // *FIX: This is misreporting on linux. Change this so that linux is
  47. // in fact reporting linux.
  48. #if LL_WINDOWS || LL_LINUX  
  49. static const char* PLATFORM_STRING = "Win";
  50. #elif LL_DARWIN
  51. static const char* PLATFORM_STRING = "Mac";
  52. #elif LL_LINUX
  53. static const char* PLATFORM_STRING = "Lnx";
  54. #elif LL_SOLARIS
  55. static const char* PLATFORM_STRING = "Sol";
  56. #else
  57. #error("Unknown platform defined!")
  58. #endif
  59. LLUserAuth::LLUserAuth() :
  60. mTransaction(NULL),
  61. mLastTransferRateBPS(0)
  62. {
  63. mAuthResponse = E_NO_RESPONSE_YET;
  64. }
  65. LLUserAuth::~LLUserAuth()
  66. {
  67. reset();
  68. }
  69. void LLUserAuth::reset()
  70. {
  71. delete mTransaction;
  72. mTransaction = NULL;
  73. mResponses.clear();
  74. mOptions.clear();
  75. }
  76. void LLUserAuth::authenticate(
  77. const std::string& auth_uri,
  78. const std::string& method,
  79. const std::string& firstname,
  80. const std::string& lastname,
  81. LLUUID web_login_key,
  82. const std::string& start,
  83. BOOL skip_optional,
  84. BOOL accept_tos,
  85. BOOL accept_critical_message,
  86. BOOL last_exec_froze, 
  87. const std::vector<const char*>& requested_options,
  88. const std::string& hashed_mac,
  89. const std::string& hashed_volume_serial)
  90. {
  91. LL_INFOS2("AppInit", "Authentication") << "Authenticating: " << firstname << " " << lastname << ", "
  92. << /*dpasswd.c_str() <<*/ LL_ENDL;
  93. std::ostringstream option_str;
  94. option_str << "Options: ";
  95. std::ostream_iterator<const char*> appender(option_str, ", ");
  96. std::copy(requested_options.begin(), requested_options.end(), appender);
  97. option_str << "END";
  98. LL_INFOS2("AppInit", "Authentication") << option_str.str() << LL_ENDL;
  99. mAuthResponse = E_NO_RESPONSE_YET;
  100. //mDownloadTimer.reset();
  101. // create the request
  102. XMLRPC_REQUEST request = XMLRPC_RequestNew();
  103. XMLRPC_RequestSetMethodName(request, method.c_str());
  104. XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
  105. // stuff the parameters
  106. XMLRPC_VALUE params = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
  107. XMLRPC_VectorAppendString(params, "first", firstname.c_str(), 0);
  108. XMLRPC_VectorAppendString(params, "last", lastname.c_str(), 0);
  109. XMLRPC_VectorAppendString(params, "web_login_key", web_login_key.getString().c_str(), 0);
  110. XMLRPC_VectorAppendString(params, "start", start.c_str(), 0);
  111. XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0); // Includes channel name
  112. XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("VersionChannelName").c_str(), 0);
  113. XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);
  114. XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0);
  115. // A bit of security through obscurity: id0 is volume_serial
  116. XMLRPC_VectorAppendString(params, "id0", hashed_volume_serial.c_str(), 0);
  117. if (skip_optional)
  118. {
  119. XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
  120. }
  121. if (accept_tos)
  122. {
  123. XMLRPC_VectorAppendString(params, "agree_to_tos", "true", 0);
  124. }
  125. if (accept_critical_message)
  126. {
  127. XMLRPC_VectorAppendString(params, "read_critical", "true", 0);
  128. }
  129. XMLRPC_VectorAppendInt(params, "last_exec_event", (int) last_exec_froze);
  130. // append optional requests in an array
  131. XMLRPC_VALUE options = XMLRPC_CreateVector("options", xmlrpc_vector_array);
  132. std::vector<const char*>::const_iterator it = requested_options.begin();
  133. std::vector<const char*>::const_iterator end = requested_options.end();
  134. for( ; it < end; ++it)
  135. {
  136. XMLRPC_VectorAppendString(options, NULL, (*it), 0);
  137. }
  138. XMLRPC_AddValueToVector(params, options);
  139. // put the parameters on the request
  140. XMLRPC_RequestSetData(request, params);
  141. mTransaction = new LLXMLRPCTransaction(auth_uri, request);
  142. XMLRPC_RequestFree(request, 1);
  143. LL_INFOS2("AppInit", "Authentication") << "LLUserAuth::authenticate: uri=" << auth_uri << LL_ENDL;
  144. }
  145. // Legacy version of constructor
  146. // passwd is already MD5 hashed by the time we get to it.
  147. void LLUserAuth::authenticate(
  148. const std::string& auth_uri,
  149. const std::string& method,
  150. const std::string& firstname,
  151. const std::string& lastname,
  152. const std::string& passwd,
  153. const std::string& start,
  154. BOOL skip_optional,
  155. BOOL accept_tos,
  156. BOOL accept_critical_message,
  157. BOOL last_exec_froze, 
  158. const std::vector<const char*>& requested_options,
  159. const std::string& hashed_mac,
  160. const std::string& hashed_volume_serial)
  161. {
  162. std::string dpasswd("$1$");
  163. dpasswd.append(passwd);
  164. LL_INFOS2("AppInit", "Authentication") << "Authenticating: " << firstname << " " << lastname << ", "
  165. << /*dpasswd.c_str() <<*/ LL_ENDL;
  166. std::ostringstream option_str;
  167. option_str << "Options: ";
  168. std::ostream_iterator<const char*> appender(option_str, ", ");
  169. std::copy(requested_options.begin(), requested_options.end(), appender);
  170. option_str << "END";
  171. LL_INFOS2("AppInit", "Authentication") << option_str.str().c_str() << LL_ENDL;
  172. mAuthResponse = E_NO_RESPONSE_YET;
  173. //mDownloadTimer.reset();
  174. // create the request
  175. XMLRPC_REQUEST request = XMLRPC_RequestNew();
  176. XMLRPC_RequestSetMethodName(request, method.c_str());
  177. XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
  178. // stuff the parameters
  179. XMLRPC_VALUE params = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
  180. XMLRPC_VectorAppendString(params, "first", firstname.c_str(), 0);
  181. XMLRPC_VectorAppendString(params, "last", lastname.c_str(), 0);
  182. XMLRPC_VectorAppendString(params, "passwd", dpasswd.c_str(), 0);
  183. XMLRPC_VectorAppendString(params, "start", start.c_str(), 0);
  184. XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0); // Includes channel name
  185. XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("VersionChannelName").c_str(), 0);
  186. XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);
  187. XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0);
  188. // A bit of security through obscurity: id0 is volume_serial
  189. XMLRPC_VectorAppendString(params, "id0", hashed_volume_serial.c_str(), 0);
  190. if (skip_optional)
  191. {
  192. XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
  193. }
  194. if (accept_tos)
  195. {
  196. XMLRPC_VectorAppendString(params, "agree_to_tos", "true", 0);
  197. }
  198. if (accept_critical_message)
  199. {
  200. XMLRPC_VectorAppendString(params, "read_critical", "true", 0);
  201. }
  202. XMLRPC_VectorAppendInt(params, "last_exec_event", (int) last_exec_froze);
  203. // append optional requests in an array
  204. XMLRPC_VALUE options = XMLRPC_CreateVector("options", xmlrpc_vector_array);
  205. std::vector<const char*>::const_iterator it = requested_options.begin();
  206. std::vector<const char*>::const_iterator end = requested_options.end();
  207. for( ; it < end; ++it)
  208. {
  209. XMLRPC_VectorAppendString(options, NULL, (*it), 0);
  210. }
  211. XMLRPC_AddValueToVector(params, options);
  212. // put the parameters on the request
  213. XMLRPC_RequestSetData(request, params);
  214. mTransaction = new LLXMLRPCTransaction(auth_uri, request);
  215. XMLRPC_RequestFree(request, 1);
  216. LL_INFOS2("AppInit", "Authentication") << "LLUserAuth::authenticate: uri=" << auth_uri << LL_ENDL;
  217. }
  218. LLUserAuth::UserAuthcode LLUserAuth::authResponse()
  219. {
  220. if (!mTransaction)
  221. {
  222. return mAuthResponse;
  223. }
  224. bool done = mTransaction->process();
  225. if (!done) {
  226. if (LLXMLRPCTransaction::StatusDownloading == mTransaction->status(0))
  227. {
  228. mAuthResponse = E_DOWNLOADING;
  229. }
  230. return mAuthResponse;
  231. }
  232. mLastTransferRateBPS = mTransaction->transferRate();
  233. int result;
  234. mTransaction->status(&result);
  235. mErrorMessage = mTransaction->statusMessage();
  236. // if curl was ok, parse the download area.
  237. switch (result)
  238. {
  239. case CURLE_OK:
  240. mAuthResponse = parseResponse();
  241. break;
  242. case CURLE_COULDNT_RESOLVE_HOST:
  243. mAuthResponse = E_COULDNT_RESOLVE_HOST;
  244. break;
  245. case CURLE_SSL_PEER_CERTIFICATE:
  246. mAuthResponse = E_SSL_PEER_CERTIFICATE;
  247. break;
  248. case CURLE_SSL_CACERT:
  249. mAuthResponse = E_SSL_CACERT;
  250. break;
  251. case CURLE_SSL_CONNECT_ERROR:
  252. mAuthResponse = E_SSL_CONNECT_ERROR;
  253. break;
  254. default:
  255. mAuthResponse = E_UNHANDLED_ERROR;
  256. break;
  257. }
  258. LL_INFOS2("AppInit", "Authentication") << "Processed response: " << result << LL_ENDL;
  259. delete mTransaction;
  260. mTransaction = NULL;
  261. return mAuthResponse;
  262. }
  263. static void parseOptionInto(
  264. const std::string& id, XMLRPC_VALUE option, LLUserAuth::options_t& options)
  265. {
  266. std::string key;
  267. std::string val;
  268. XMLRPC_VALUE_TYPE_EASY type;
  269. XMLRPC_VALUE row = XMLRPC_VectorRewind(option);
  270. while(row)
  271. {
  272. XMLRPC_VALUE opt  = XMLRPC_VectorRewind(row);
  273. LLUserAuth::response_t responses;
  274. while(opt)
  275. {
  276. key.assign(XMLRPC_GetValueID(opt));
  277. //llinfos << "option key: " << key << llendl;
  278. type = XMLRPC_GetValueTypeEasy(opt);
  279. if(xmlrpc_type_string == type)
  280. {
  281. val.assign(XMLRPC_GetValueString(opt));
  282. //llinfos << "string val: " << val << llendl;
  283. }
  284. else if(xmlrpc_type_int == type)
  285. {
  286. val = llformat("%d", XMLRPC_GetValueInt(opt));
  287. //llinfos << "int val: " << val << llendl;
  288. }
  289. else if(xmlrpc_type_double == type)
  290. {
  291. val = llformat("%g", XMLRPC_GetValueDouble(opt));
  292. //llinfos << "double val: " << val << llendl;
  293. }
  294. else
  295. { // Can't understand the type
  296. val = "???";
  297. //llinfos << "unknown value type: " << type << llendl;
  298. }
  299. responses.insert(LLUserAuth::response_t::value_type(key, val));
  300. opt = XMLRPC_VectorNext(row);
  301. }
  302. options.push_back(responses);
  303. row = XMLRPC_VectorNext(option);
  304. }
  305. }
  306. LLUserAuth::UserAuthcode LLUserAuth::parseResponse()
  307. {
  308. // The job of this function is to parse sCurlDownloadArea and
  309. // extract every member into either the mResponses or
  310. // mOptions. For now, we will only be looking at mResponses, which
  311. // will all be string => string pairs.
  312. UserAuthcode rv = E_UNHANDLED_ERROR;
  313. XMLRPC_REQUEST response = mTransaction->response();
  314. if(!response) return rv;
  315. // clear out any old parsing
  316. mResponses.clear();
  317. mOptions.clear();
  318. // Now, parse everything
  319. std::string key;
  320. std::string val;
  321. XMLRPC_VALUE param = NULL;
  322. XMLRPC_VALUE current = NULL;
  323. XMLRPC_VALUE_TYPE_EASY type;
  324. param = XMLRPC_RequestGetData(response);
  325. if(!param) goto exit;
  326. current = XMLRPC_VectorRewind(param);
  327. while(current)
  328. {
  329. key.assign(XMLRPC_GetValueID(current));
  330. lldebugs << "key: " << key << llendl;
  331. type = XMLRPC_GetValueTypeEasy(current);
  332. if(xmlrpc_type_string == type)
  333. {
  334. val.assign(XMLRPC_GetValueString(current));
  335. lldebugs << "val: " << val << llendl;
  336. mResponses.insert(response_t::value_type(key, val));
  337. }
  338. else if(xmlrpc_type_int == type)
  339. {
  340. val = llformat( "%d", XMLRPC_GetValueInt(current));
  341. lldebugs << "val: " << val << llendl;
  342. mResponses.insert(response_t::value_type(key, val));
  343. }
  344. else if(xmlrpc_type_array == type)
  345. {
  346. options_t options;
  347. parseOptionInto(key, current, options);
  348. mOptions.insert(all_options_t::value_type(key, options));
  349. }
  350. else
  351. {
  352. // whoops - bad response
  353. llwarns << "Unhandled xmlrpc type, key, value: " << type << " "
  354. << key << " " << val << "." << llendl;
  355. rv = E_UNHANDLED_ERROR;
  356. break;
  357. }
  358. current = XMLRPC_VectorNext(param);
  359. rv = E_OK;
  360. }
  361.  exit:
  362. return rv;
  363. }
  364. const std::string& LLUserAuth::getResponse(const std::string& key) const
  365. {
  366. response_t::const_iterator it = mResponses.find(key);
  367. if(it != mResponses.end())
  368. {
  369. return((*it).second);
  370. }
  371. return LLStringUtil::null;
  372. }
  373. BOOL LLUserAuth::getOptions(const std::string& key, options_t& options) const
  374. {
  375. all_options_t::const_iterator it = mOptions.find(key);
  376. if(it != mOptions.end())
  377. {
  378. // found the option set, copyt them onto the container.
  379. std::back_insert_iterator<options_t> ii(options);
  380. std::copy((*it).second.begin(), (*it).second.end(), ii);
  381. return TRUE;
  382. }
  383. return FALSE;
  384. }