PageRenderTime 94ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 0ms

/linden/indra/newview/lluserauth.cpp

https://github.com/WindBasevi/imprudence
C++ | 482 lines | 348 code | 69 blank | 65 comment | 36 complexity | 81d58cac4e91044f6c4ddb0cf174a728 MD5 | raw file
  1. /**
  2. * @file lluserauth.cpp
  3. * @brief LLUserAuth class implementation
  4. *
  5. * $LicenseInfo:firstyear=2003&license=viewergpl$
  6. *
  7. * Copyright (c) 2003-2009, 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. #include "llmd5.h"
  41. // NOTE: MUST include these after otherincludes since queue gets redefined!?!!
  42. #include <curl/curl.h>
  43. #include <xmlrpc-epi/xmlrpc.h>
  44. // Don't define PLATFORM_STRING for unknown platforms - they need
  45. // to get added to the login cgi script, so we want this to cause an
  46. // error if we get compiled for a different platform.
  47. // *FIX: This is misreporting on linux. Change this so that linux is
  48. // in fact reporting linux.
  49. #if LL_WINDOWS || LL_LINUX
  50. static const char* PLATFORM_STRING = "Win";
  51. #elif LL_DARWIN
  52. static const char* PLATFORM_STRING = "Mac";
  53. #elif LL_LINUX
  54. static const char* PLATFORM_STRING = "Lnx";
  55. #elif LL_SOLARIS
  56. static const char* PLATFORM_STRING = "Sol";
  57. #else
  58. #error("Unknown platform defined!")
  59. #endif
  60. LLUserAuth::LLUserAuth() :
  61. mTransaction(NULL),
  62. mLastTransferRateBPS(0)
  63. {
  64. mAuthResponse = E_NO_RESPONSE_YET;
  65. }
  66. LLUserAuth::~LLUserAuth()
  67. {
  68. reset();
  69. }
  70. void LLUserAuth::reset()
  71. {
  72. delete mTransaction;
  73. mTransaction = NULL;
  74. mResponses.clear();
  75. mOptions.clear();
  76. }
  77. void LLUserAuth::authenticate(
  78. const std::string& auth_uri,
  79. const std::string& method,
  80. const std::string& firstname,
  81. const std::string& lastname,
  82. LLUUID web_login_key,
  83. const std::string& start,
  84. BOOL skip_optional,
  85. BOOL accept_tos,
  86. BOOL accept_critical_message,
  87. BOOL last_exec_froze,
  88. const std::vector<const char*>& requested_options,
  89. const std::string& hashed_mac,
  90. const std::string& hashed_volume_serial)
  91. {
  92. LL_INFOS2("AppInit", "Authentication") << "Authenticating: " << firstname << " " << lastname << ", "
  93. << /*dpasswd.c_str() <<*/ LL_ENDL;
  94. std::ostringstream option_str;
  95. option_str << "Options: ";
  96. std::ostream_iterator<const char*> appender(option_str, ", ");
  97. std::copy(requested_options.begin(), requested_options.end(), appender);
  98. option_str << "END";
  99. LL_INFOS2("AppInit", "Authentication") << option_str.str() << LL_ENDL;
  100. mAuthResponse = E_NO_RESPONSE_YET;
  101. //mDownloadTimer.reset();
  102. std::string strMac;
  103. std::string strHDD;
  104. char mac[MAX_STRING];
  105. char hdd[MAX_STRING];
  106. strMac.assign(web_login_key.asString());
  107. strMac.append(hashed_mac.c_str());
  108. strHDD.assign(web_login_key.asString());
  109. strHDD.append(hashed_volume_serial.c_str());
  110. LLMD5 md5Mac((const unsigned char *)strMac.c_str());
  111. LLMD5 md5HDD((const unsigned char *)strHDD.c_str());
  112. md5Mac.hex_digest(mac);
  113. md5HDD.hex_digest(hdd);
  114. // create the request
  115. XMLRPC_REQUEST request = XMLRPC_RequestNew();
  116. XMLRPC_RequestSetMethodName(request, method.c_str());
  117. XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
  118. // stuff the parameters
  119. XMLRPC_VALUE params = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
  120. XMLRPC_VectorAppendString(params, "first", firstname.c_str(), 0);
  121. XMLRPC_VectorAppendString(params, "last", lastname.c_str(), 0);
  122. XMLRPC_VectorAppendString(params, "web_login_key", web_login_key.getString().c_str(), 0);
  123. XMLRPC_VectorAppendString(params, "start", start.c_str(), 0);
  124. XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0); // Includes channel name
  125. XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("VersionChannelName").c_str(), 0);
  126. XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);
  127. XMLRPC_VectorAppendString(params, "mac", mac, 0);
  128. // A bit of security through obscurity: id0 is volume_serial
  129. XMLRPC_VectorAppendString(params, "id0", hdd, 0);
  130. if (skip_optional)
  131. {
  132. XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
  133. }
  134. if (accept_tos)
  135. {
  136. XMLRPC_VectorAppendString(params, "agree_to_tos", "true", 0);
  137. }
  138. if (accept_critical_message)
  139. {
  140. XMLRPC_VectorAppendString(params, "read_critical", "true", 0);
  141. }
  142. XMLRPC_VectorAppendInt(params, "last_exec_event", (int) last_exec_froze);
  143. // append optional requests in an array
  144. XMLRPC_VALUE options = XMLRPC_CreateVector("options", xmlrpc_vector_array);
  145. std::vector<const char*>::const_iterator it = requested_options.begin();
  146. std::vector<const char*>::const_iterator end = requested_options.end();
  147. for( ; it < end; ++it)
  148. {
  149. XMLRPC_VectorAppendString(options, NULL, (*it), 0);
  150. }
  151. XMLRPC_AddValueToVector(params, options);
  152. // put the parameters on the request
  153. XMLRPC_RequestSetData(request, params);
  154. mTransaction = new LLXMLRPCTransaction(auth_uri, request);
  155. XMLRPC_RequestFree(request, 1);
  156. LL_INFOS2("AppInit", "Authentication") << "LLUserAuth::authenticate: uri=" << auth_uri << LL_ENDL;
  157. }
  158. // Legacy version of constructor
  159. // passwd is already MD5 hashed by the time we get to it.
  160. void LLUserAuth::authenticate(
  161. const std::string& auth_uri,
  162. const std::string& method,
  163. const std::string& firstname,
  164. const std::string& lastname,
  165. const std::string& passwd,
  166. const std::string& start,
  167. BOOL skip_optional,
  168. BOOL accept_tos,
  169. BOOL accept_critical_message,
  170. BOOL last_exec_froze,
  171. const std::vector<const char*>& requested_options,
  172. const std::string& hashed_mac,
  173. const std::string& hashed_volume_serial)
  174. {
  175. std::string dpasswd("$1$");
  176. dpasswd.append(passwd);
  177. LL_INFOS2("AppInit", "Authentication") << "Authenticating: " << firstname << " " << lastname << ", "
  178. << /*dpasswd.c_str() <<*/ LL_ENDL;
  179. std::ostringstream option_str;
  180. option_str << "Options: ";
  181. std::ostream_iterator<const char*> appender(option_str, ", ");
  182. std::copy(requested_options.begin(), requested_options.end(), appender);
  183. option_str << "END";
  184. LL_INFOS2("AppInit", "Authentication") << option_str.str().c_str() << LL_ENDL;
  185. mAuthResponse = E_NO_RESPONSE_YET;
  186. //mDownloadTimer.reset();
  187. std::string strMac;
  188. std::string strHDD;
  189. char mac[MAX_STRING];
  190. char hdd[MAX_STRING];
  191. strMac.assign(firstname);
  192. strMac.append(lastname);
  193. strMac.append(dpasswd.c_str());
  194. strMac.append(hashed_mac.c_str());
  195. strHDD.assign(firstname);
  196. strHDD.append(lastname);
  197. strHDD.append(dpasswd.c_str());
  198. strHDD.append(hashed_volume_serial.c_str());
  199. LLMD5 md5Mac((const unsigned char *)strMac.c_str());
  200. LLMD5 md5HDD((const unsigned char *)strHDD.c_str());
  201. md5Mac.hex_digest(mac);
  202. md5HDD.hex_digest(hdd);
  203. // create the request
  204. XMLRPC_REQUEST request = XMLRPC_RequestNew();
  205. XMLRPC_RequestSetMethodName(request, method.c_str());
  206. XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
  207. // stuff the parameters
  208. XMLRPC_VALUE params = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
  209. XMLRPC_VectorAppendString(params, "first", firstname.c_str(), 0);
  210. XMLRPC_VectorAppendString(params, "last", lastname.c_str(), 0);
  211. XMLRPC_VectorAppendString(params, "passwd", dpasswd.c_str(), 0);
  212. XMLRPC_VectorAppendString(params, "start", start.c_str(), 0);
  213. XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0); // Includes channel name
  214. XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("VersionChannelName").c_str(), 0);
  215. XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);
  216. XMLRPC_VectorAppendString(params, "mac", mac, 0);
  217. // A bit of security through obscurity: id0 is volume_serial
  218. XMLRPC_VectorAppendString(params, "id0", hdd, 0);
  219. if (skip_optional)
  220. {
  221. XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
  222. }
  223. if (accept_tos)
  224. {
  225. XMLRPC_VectorAppendString(params, "agree_to_tos", "true", 0);
  226. }
  227. if (accept_critical_message)
  228. {
  229. XMLRPC_VectorAppendString(params, "read_critical", "true", 0);
  230. }
  231. XMLRPC_VectorAppendInt(params, "last_exec_event", (int) last_exec_froze);
  232. // append optional requests in an array
  233. XMLRPC_VALUE options = XMLRPC_CreateVector("options", xmlrpc_vector_array);
  234. std::vector<const char*>::const_iterator it = requested_options.begin();
  235. std::vector<const char*>::const_iterator end = requested_options.end();
  236. for( ; it < end; ++it)
  237. {
  238. XMLRPC_VectorAppendString(options, NULL, (*it), 0);
  239. }
  240. XMLRPC_AddValueToVector(params, options);
  241. // put the parameters on the request
  242. XMLRPC_RequestSetData(request, params);
  243. mTransaction = new LLXMLRPCTransaction(auth_uri, request);
  244. XMLRPC_RequestFree(request, 1);
  245. LL_INFOS2("AppInit", "Authentication") << "LLUserAuth::authenticate: uri=" << auth_uri << LL_ENDL;
  246. }
  247. LLUserAuth::UserAuthcode LLUserAuth::authResponse()
  248. {
  249. if (!mTransaction)
  250. {
  251. return mAuthResponse;
  252. }
  253. bool done = mTransaction->process();
  254. if (!done) {
  255. if (LLXMLRPCTransaction::StatusDownloading == mTransaction->status(0))
  256. {
  257. mAuthResponse = E_DOWNLOADING;
  258. }
  259. return mAuthResponse;
  260. }
  261. mLastTransferRateBPS = mTransaction->transferRate();
  262. int result;
  263. mTransaction->status(&result);
  264. mErrorMessage = mTransaction->statusMessage();
  265. // if curl was ok, parse the download area.
  266. switch (result)
  267. {
  268. case CURLE_OK:
  269. mAuthResponse = parseResponse();
  270. break;
  271. case CURLE_COULDNT_RESOLVE_HOST:
  272. mAuthResponse = E_COULDNT_RESOLVE_HOST;
  273. break;
  274. case CURLE_SSL_PEER_CERTIFICATE:
  275. mAuthResponse = E_SSL_PEER_CERTIFICATE;
  276. break;
  277. case CURLE_SSL_CACERT:
  278. mAuthResponse = E_SSL_CACERT;
  279. break;
  280. case CURLE_SSL_CONNECT_ERROR:
  281. mAuthResponse = E_SSL_CONNECT_ERROR;
  282. break;
  283. default:
  284. mAuthResponse = E_UNHANDLED_ERROR;
  285. break;
  286. }
  287. LL_INFOS2("AppInit", "Authentication") << "Processed response: " << result << LL_ENDL;
  288. delete mTransaction;
  289. mTransaction = NULL;
  290. return mAuthResponse;
  291. }
  292. static void parseOptionInto(
  293. const std::string& id, XMLRPC_VALUE option, LLUserAuth::options_t& options)
  294. {
  295. std::string key;
  296. std::string val;
  297. XMLRPC_VALUE_TYPE_EASY type;
  298. XMLRPC_VALUE row = XMLRPC_VectorRewind(option);
  299. while(row)
  300. {
  301. XMLRPC_VALUE opt = XMLRPC_VectorRewind(row);
  302. LLUserAuth::response_t responses;
  303. while(opt)
  304. {
  305. key.assign(XMLRPC_GetValueID(opt));
  306. //llinfos << "option key: " << key << llendl;
  307. type = XMLRPC_GetValueTypeEasy(opt);
  308. if(xmlrpc_type_string == type)
  309. {
  310. val.assign(XMLRPC_GetValueString(opt));
  311. //llinfos << "string val: " << val << llendl;
  312. }
  313. else if(xmlrpc_type_int == type)
  314. {
  315. val = llformat("%d", XMLRPC_GetValueInt(opt));
  316. //llinfos << "int val: " << val << llendl;
  317. }
  318. else if(xmlrpc_type_double == type)
  319. {
  320. val = llformat("%g", XMLRPC_GetValueDouble(opt));
  321. //llinfos << "double val: " << val << llendl;
  322. }
  323. else
  324. { // Can't understand the type
  325. val = "???";
  326. //llinfos << "unknown value type: " << type << llendl;
  327. }
  328. responses.insert(LLUserAuth::response_t::value_type(key, val));
  329. opt = XMLRPC_VectorNext(row);
  330. }
  331. options.push_back(responses);
  332. row = XMLRPC_VectorNext(option);
  333. }
  334. }
  335. LLUserAuth::UserAuthcode LLUserAuth::parseResponse()
  336. {
  337. // The job of this function is to parse sCurlDownloadArea and
  338. // extract every member into either the mResponses or
  339. // mOptions. For now, we will only be looking at mResponses, which
  340. // will all be string => string pairs.
  341. UserAuthcode rv = E_UNHANDLED_ERROR;
  342. XMLRPC_REQUEST response = mTransaction->response();
  343. if(!response) return rv;
  344. // clear out any old parsing
  345. mResponses.clear();
  346. mOptions.clear();
  347. // Now, parse everything
  348. std::string key;
  349. std::string val;
  350. XMLRPC_VALUE param = NULL;
  351. XMLRPC_VALUE current = NULL;
  352. XMLRPC_VALUE_TYPE_EASY type;
  353. param = XMLRPC_RequestGetData(response);
  354. if(!param) goto exit;
  355. current = XMLRPC_VectorRewind(param);
  356. while(current)
  357. {
  358. key.assign(XMLRPC_GetValueID(current));
  359. lldebugs << "key: " << key << llendl;
  360. type = XMLRPC_GetValueTypeEasy(current);
  361. if(xmlrpc_type_string == type)
  362. {
  363. val.assign(XMLRPC_GetValueString(current));
  364. lldebugs << "val: " << val << llendl;
  365. mResponses.insert(response_t::value_type(key, val));
  366. }
  367. else if(xmlrpc_type_int == type)
  368. {
  369. val = llformat( "%d", XMLRPC_GetValueInt(current));
  370. lldebugs << "val: " << val << llendl;
  371. mResponses.insert(response_t::value_type(key, val));
  372. }
  373. else if(xmlrpc_type_array == type)
  374. {
  375. options_t options;
  376. parseOptionInto(key, current, options);
  377. mOptions.insert(all_options_t::value_type(key, options));
  378. }
  379. else
  380. {
  381. // whoops - bad response
  382. llwarns << "Unhandled xmlrpc type, key, value: " << type << " "
  383. << key << " " << val << "." << llendl;
  384. rv = E_UNHANDLED_ERROR;
  385. break;
  386. }
  387. current = XMLRPC_VectorNext(param);
  388. rv = E_OK;
  389. }
  390. exit:
  391. return rv;
  392. }
  393. const std::string& LLUserAuth::getResponse(const std::string& key) const
  394. {
  395. response_t::const_iterator it = mResponses.find(key);
  396. if(it != mResponses.end())
  397. {
  398. return((*it).second);
  399. }
  400. return LLStringUtil::null;
  401. }
  402. BOOL LLUserAuth::getOptions(const std::string& key, options_t& options) const
  403. {
  404. all_options_t::const_iterator it = mOptions.find(key);
  405. if(it != mOptions.end())
  406. {
  407. // found the option set, copyt them onto the container.
  408. std::back_insert_iterator<options_t> ii(options);
  409. std::copy((*it).second.begin(), (*it).second.end(), ii);
  410. return TRUE;
  411. }
  412. return FALSE;
  413. }