~ubuntu-branches/ubuntu/maverick/vmware-view-open-client/maverick

« back to all changes in this revision

Viewing changes to broker.cc

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2010-06-04 17:45:04 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20100604174504-zjltuc0hdp4mv7de
Tags: 4.5.0-264434+dfsg-1
* Merging upstream version 4.5.0-264434+dfsg.
* Updating date and version header in manpage.
* Rediffing doc-pdf.patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
 
32
32
#include <boost/bind.hpp>
33
33
#include <glib.h>
 
34
#ifdef __APPLE__
 
35
#include <CoreFoundation/CoreFoundation.h>
 
36
#endif
34
37
 
35
 
#include "app.hh"
 
38
#include "baseApp.hh"
36
39
#include "broker.hh"
 
40
#include "cdkErrors.h"
37
41
#include "desktop.hh"
38
42
#include "tunnel.hh"
39
43
#include "util.hh"
41
45
 
42
46
#define ERR_ALREADY_AUTHENTICATED "ALREADY_AUTHENTICATED"
43
47
#define ERR_AUTHENTICATION_FAILED "AUTHENTICATION_FAILED"
 
48
#define ERR_BASICHTTP_ERROR_SSL_CONNECT_ERROR "BASICHTTP_ERROR_SSL_CONNECT_ERROR"
44
49
#define ERR_DESKTOP_LAUNCH_ERROR "DESKTOP_LAUNCH_ERROR"
 
50
#define ERR_TUNNEL_ERROR "TUNNEL_ERROR"
45
51
#define ERR_NOT_AUTHENTICATED "NOT_AUTHENTICATED"
46
52
#define ERR_NOT_ENTITLED "NOT_ENTITLED"
47
53
#define ERR_UNSUPPORTED_VERSION "UNSUPPORTED_VERSION"
67
73
 */
68
74
 
69
75
Broker::Broker()
70
 
   : mXml(NULL),
 
76
   : mDelegate(NULL),
 
77
     mXml(NULL),
71
78
     mTunnel(NULL),
72
79
     mDesktop(NULL),
73
80
     mCertState(CERT_NOT_REQUESTED),
74
81
     mTunnelState(TUNNEL_DOWN),
75
82
     mGettingDesktops(false),
76
83
     mSmartCardPin(NULL),
77
 
     mAuthRequestId(0)
 
84
     mAuthRequestId(0),
 
85
     mAcceptedDisclaimer(false),
 
86
     mCert(NULL),
 
87
     mKey(NULL)
78
88
{
79
89
}
80
90
 
120
130
void
121
131
Broker::Reset()
122
132
{
123
 
   Poll_CallbackRemove(POLL_CS_MAIN, 0, OnIdleSubmitCertAuth, this,
124
 
                       POLL_REALTIME);
125
133
   Poll_CallbackRemove(POLL_CS_MAIN, 0, RefreshDesktopsTimeout, this,
126
134
                       POLL_REALTIME);
127
135
 
151
159
   ClearSmartCardPinAndReader();
152
160
 
153
161
   mCertState = CERT_NOT_REQUESTED;
 
162
   mAcceptedDisclaimer = false;
 
163
 
 
164
   mTrustedIssuers.clear();
 
165
 
 
166
   X509_free(mCert);
 
167
   mCert = NULL;
 
168
 
 
169
   EVP_PKEY_free(mKey);
 
170
   mKey = NULL;
154
171
}
155
172
 
156
173
 
181
198
   ASSERT(!mXml);
182
199
   ASSERT(!mTunnel);
183
200
 
184
 
   Log("Initialzing connection to broker %s://%s:%d\n",
 
201
   Log("Initializing connection to broker %s://%s:%d\n",
185
202
       secure ? "https" : "http", hostname.c_str(), port);
186
203
 
187
 
   mXml = new BrokerXml(hostname, port, secure);
 
204
   mXml = CreateNewXmlConnection(hostname, port, secure);
188
205
   if (!mCookieFile.empty()) {
189
206
      mXml->SetCookieFile(mCookieFile);
190
207
      mXml->ForgetCookies();
225
242
    * nice not to send it to 1.0 servers.  Sadly, it's the first RPC
226
243
    * we send, so we don't know what version the server is... yet.
227
244
    */
228
 
   char *locale = setlocale(LC_MESSAGES, NULL);
229
 
   if (locale != NULL && locale[0] != '\0' && strcmp(locale, "C") != 0 &&
230
 
       strcmp(locale, "POSIX") != 0) {
231
 
      if (mDelegate) {
232
 
         mDelegate->SetBusy(_("Setting client locale..."));
 
245
#ifndef __APPLE__
 
246
   const char *locale = setlocale(LC_MESSAGES, NULL);
 
247
#else
 
248
   char locale[32] = { '\0' };
 
249
   CFArrayRef langs = CFLocaleCopyPreferredLanguages();
 
250
   CFStringRef localeStr = (CFStringRef)CFArrayGetValueAtIndex(langs, 0);
 
251
   if (CFStringGetCString(localeStr, locale, sizeof(locale),
 
252
                          kCFStringEncodingASCII)) {
 
253
#endif
 
254
      if (locale != NULL && locale[0] != '\0' && strcmp(locale, "C") != 0 &&
 
255
          strcmp(locale, "POSIX") != 0) {
 
256
         mXml->SetLocale(locale,
 
257
                         boost::bind(&Broker::OnInitialRPCAbort, this, _1, _2),
 
258
                         boost::bind(&Broker::OnLocaleSet, this));
233
259
      }
234
 
      mXml->SetLocale(locale,
235
 
                      boost::bind(&Broker::OnInitialRPCAbort, this, _1, _2),
236
 
                      boost::bind(&Broker::OnLocaleSet, this));
 
260
#ifdef __APPLE__
237
261
   }
 
262
   CFRelease(langs);
 
263
#endif
238
264
}
239
265
 
240
266
 
257
283
void
258
284
Broker::AcceptDisclaimer()
259
285
{
260
 
   if (mDelegate) {
261
 
      mDelegate->SetBusy(_("Accepting disclaimer..."));
262
 
   }
 
286
   mAcceptedDisclaimer = true;
263
287
   if (mCertState == CERT_REQUESTED) {
264
288
      /*
265
289
       * Pre-login message is enabled, and the server asked us for a
266
290
       * cert.  We'll reset our connections, and when we do the accept
267
291
       * disclaimer RPC, we'll get asked for a cert again.
268
292
       */
269
 
      Log("Accepting disclaimer and cert was requested; "
270
 
          "enabling cert response and accepting disclaimer.\n");
271
 
      mXml->ResetConnections();
272
 
      mCertState = CERT_SHOULD_RESPOND;
273
 
   }
274
 
   mXml->QueueRequests();
275
 
   mXml->AcceptDisclaimer(
276
 
      boost::bind(&Broker::OnInitialRPCAbort, this, _1, _2),
277
 
      boost::bind(&Broker::OnAuthResult, this, _1, _2));
278
 
   InitTunnel();
279
 
   GetDesktops();
280
 
   mXml->SendQueuedRequests();
 
293
      Log("Accepting disclaimer and cert was requested; prompting user for a "
 
294
          "certificate.\n");
 
295
      if (mDelegate) {
 
296
         mDelegate->RequestCertificate(mTrustedIssuers);
 
297
      }
 
298
   } else {
 
299
      mXml->QueueRequests();
 
300
      mXml->AcceptDisclaimer(
 
301
         boost::bind(&Broker::OnInitialRPCAbort, this, _1, _2),
 
302
         boost::bind(&Broker::OnAuthResult, this, _1, _2));
 
303
      InitTunnel();
 
304
      GetDesktops();
 
305
      mXml->SendQueuedRequests();
 
306
   }
 
307
}
 
308
 
 
309
 
 
310
/*
 
311
 *-----------------------------------------------------------------------------
 
312
 *
 
313
 * cdk::Broker::SubmitCertificate --
 
314
 *
 
315
 *      Set the certificate and private key to use when
 
316
 *      authenticating, and smart card PIN and reader name (if
 
317
 *      available).
 
318
 *
 
319
 *      NULL cert or key signifies not to authenticate using a
 
320
 *      certificate.
 
321
 *
 
322
 * Results:
 
323
 *      None
 
324
 *
 
325
 * Side effects:
 
326
 *      Authentication will continue.
 
327
 *
 
328
 *-----------------------------------------------------------------------------
 
329
 */
 
330
 
 
331
void
 
332
Broker::SubmitCertificate(X509 *cert,                 // IN/OPT
 
333
                          EVP_PKEY *key,              // IN/OPT
 
334
                          const char *pin,            // IN/OPT
 
335
                          const Util::string &reader) // IN/OPT
 
336
{
 
337
   ASSERT(mCertState == CERT_REQUESTED);
 
338
   ASSERT(!mCert);
 
339
   ASSERT(!mKey);
 
340
   ASSERT(!mSmartCardPin);
 
341
   ASSERT(mSmartCardReader.empty());
 
342
 
 
343
   mCert = cert;
 
344
   mKey = key;
 
345
   mSmartCardPin = g_strdup(pin);
 
346
   mSmartCardReader = reader;
 
347
 
 
348
   mCertState = CERT_SHOULD_RESPOND;
 
349
   mXml->ResetConnections();
 
350
 
 
351
   if (mAcceptedDisclaimer) {
 
352
      Log("Accepting disclaimer with cert response enabled.\n");
 
353
      mXml->QueueRequests();
 
354
      mXml->AcceptDisclaimer(
 
355
         boost::bind(&Broker::OnInitialRPCAbort, this, _1, _2),
 
356
         boost::bind(&Broker::OnAuthResult, this, _1, _2));
 
357
      InitTunnel();
 
358
      GetDesktops();
 
359
      mXml->SendQueuedRequests();
 
360
   } else {
 
361
      Log("Getting configuration with cert response enabled.\n");
 
362
      GetConfiguration();
 
363
   }
281
364
}
282
365
 
283
366
 
301
384
Broker::SubmitPasscode(const Util::string &username, // IN
302
385
                       const Util::string &passcode) // IN
303
386
{
304
 
   if (mDelegate) {
305
 
      mDelegate->SetBusy(_("Logging in..."));
306
 
   }
307
387
   mUsername = username;
308
388
   mXml->QueueRequests();
309
389
   mXml->SecurIDUsernamePasscode(
335
415
void
336
416
Broker::SubmitNextTokencode(const Util::string &tokencode) // IN
337
417
{
338
 
   if (mDelegate) {
339
 
      mDelegate->SetBusy(_("Logging in..."));
340
 
   }
341
418
   mXml->QueueRequests();
342
419
   mXml->SecurIDNextTokencode(
343
420
      tokencode,
369
446
Broker::SubmitPins(const Util::string &pin1, // IN
370
447
                   const Util::string &pin2) // IN
371
448
{
372
 
   if (mDelegate) {
373
 
      mDelegate->SetBusy(_("Logging in..."));
374
 
   }
375
449
   mXml->QueueRequests();
376
450
   mXml->SecurIDPins(
377
451
      pin1, pin2,
404
478
                       const Util::string &password, // IN
405
479
                       const Util::string &domain)   // IN
406
480
{
407
 
   if (mDelegate) {
408
 
      mDelegate->SetBusy(_("Logging in..."));
409
 
   }
410
481
   mUsername = username;
411
482
   mDomain = domain;
412
483
   mXml->QueueRequests();
441
512
                       const Util::string &newPassword, // IN
442
513
                       const Util::string &confirm)     // IN
443
514
{
444
 
   if (mDelegate) {
445
 
      mDelegate->SetBusy(_("Changing password..."));
446
 
   }
447
515
   mXml->QueueRequests();
448
516
   mXml->ChangePassword(oldPassword, newPassword, confirm,
449
517
                        boost::bind(&Broker::OnAbort, this, _1,_2),
474
542
Broker::ConnectDesktop(Desktop *desktop) // IN
475
543
{
476
544
   ASSERT(desktop);
477
 
   ASSERT(desktop->GetConnectionState() == Desktop::STATE_DISCONNECTED);
 
545
   // XXX - Log/assert to determine cause of BZ 510532.
 
546
   if (desktop->GetConnectionState() != Desktop::STATE_DISCONNECTED) {
 
547
      Log("Broker::ConnectDesktop: unexpected desktop status "
 
548
          "(see BZ 510532) %d\n", (int)desktop->GetConnectionState());
 
549
      ASSERT_BUG(510532,
 
550
                 desktop->GetConnectionState() == Desktop::STATE_DISCONNECTED);
 
551
   }
478
552
 
479
553
   mDesktop = desktop;
480
554
   if (mDelegate) {
529
603
   if (mDesktop->GetConnectionState() == Desktop::STATE_CONNECTED) {
530
604
      mDesktop->Disconnect();
531
605
   }
 
606
 
 
607
   // XXX - Log/assert to determine cause of BZ 510532.
 
608
   if (mDesktop->GetConnectionState() != Desktop::STATE_DISCONNECTED) {
 
609
      Log("Broker::ReconnectDesktop: unexpected desktop status "
 
610
          "(see BZ 510532) %d\n", (int)mDesktop->GetConnectionState());
 
611
      ASSERT_BUG(510532,
 
612
                 mDesktop->GetConnectionState() == Desktop::STATE_DISCONNECTED);
 
613
   }
532
614
   ConnectDesktop(mDesktop);
533
615
}
534
616
 
687
769
 *      false to remove the handler
688
770
 *
689
771
 * Side effects:
690
 
 *      get-desktops request sent 
 
772
 *      get-desktops request sent
691
773
 *
692
774
 *-----------------------------------------------------------------------------
693
775
 */
721
803
void
722
804
Broker::Logout()
723
805
{
724
 
   if (mDelegate) {
725
 
      mDelegate->SetBusy(_("Logging out..."));
726
 
   }
727
806
   mXml->Logout(boost::bind(&Broker::OnAbort, this, _1, _2),
728
807
                boost::bind(&Broker::OnLogoutResult, this));
729
808
}
748
827
void
749
828
Broker::GetConfiguration()
750
829
{
751
 
   if (mDelegate) {
752
 
      mDelegate->SetBusy(_("Getting server configuration..."));
753
 
   }
754
830
   mXml->GetConfiguration(
755
831
      boost::bind(&Broker::OnInitialRPCAbort, this, _1, _2),
756
832
      boost::bind(&Broker::OnConfigurationDone, this, _1, _2));
842
918
      // get-desktops reply is later in this RPC.
843
919
      return;
844
920
   } else if (result.result != "partial" && result.result != "ok") {
845
 
      App::ShowDialog(GTK_MESSAGE_ERROR, _("Unknown result returned: %s"),
846
 
                      result.result.c_str());
 
921
      BaseApp::ShowError(CDK_ERR_AUTH_UNKNOWN_RESULT, _("Unknown result returned"),
 
922
                         "%s", result.result.c_str());
847
923
      if (mDelegate) {
848
 
         mDelegate->SetReady();
849
924
         mDelegate->RequestBroker();
850
925
      }
851
926
      return;
858
933
   */
859
934
   ResetTunnel();
860
935
 
861
 
   if (mDelegate) {
862
 
      mDelegate->SetReady();
863
 
   }
864
936
   const Util::string error = authInfo.GetError();
865
937
   if (!error.empty()) {
866
 
      App::ShowDialog(GTK_MESSAGE_ERROR, _("Error authenticating: %s"),
867
 
                      error.c_str());
 
938
      BaseApp::ShowError(CDK_ERR_AUTH_ERROR,
 
939
                         _("Error authenticating"), "%s", error.c_str());
868
940
   }
869
941
 
870
942
   if (authInfo.GetAuthType() != BrokerXml::AUTH_DISCLAIMER &&
879
951
       * we gave it.
880
952
       */
881
953
      Log("Got non-disclaimer auth method and cert was previously requested;"
882
 
          " enabling cert response and retrying GetConfiguration()...\n");
 
954
          " promting user for a certificate.\n");
883
955
      mXml->ForgetCookies();
884
 
      mXml->ResetConnections();
885
 
      mCertState = CERT_SHOULD_RESPOND;
886
 
      GetConfiguration();
 
956
      if (mDelegate) {
 
957
         mDelegate->RequestCertificate(mTrustedIssuers);
 
958
      }
887
959
      return;
888
960
   }
889
961
 
913
985
      OnAuthInfoPinChange(authInfo.params);
914
986
      break;
915
987
   case BrokerXml::AUTH_SECURID_WAIT:
916
 
      App::ShowDialog(GTK_MESSAGE_INFO,
917
 
                      _("Your new RSA SecurID PIN has been set.\n\n"
918
 
                        "Please wait for the next tokencode to appear"
919
 
                        " on your RSA SecurID token, then continue."));
 
988
      BaseApp::ShowInfo(_("Your new RSA SecurID PIN has been set"),
 
989
                        _("Please wait for the next tokencode to appear"
 
990
                          " on your RSA SecurID token, then continue."));
920
991
      if (mDelegate) {
921
992
         mDelegate->RequestPasscode(mUsername, false);
922
993
      }
937
1008
      }
938
1009
      break;
939
1010
   case BrokerXml::AUTH_CERT_AUTH:
940
 
      Log("Queueing idle cert auth response\n");
941
 
      Poll_CallbackRemove(POLL_CS_MAIN, 0, OnIdleSubmitCertAuth, this,
942
 
                          POLL_REALTIME);
943
 
      Poll_Callback(POLL_CS_MAIN, 0, OnIdleSubmitCertAuth, this,
944
 
                    POLL_REALTIME, 0, NULL);
 
1011
      mXml->QueueRequests();
 
1012
      mXml->SubmitCertAuth(
 
1013
         true, mSmartCardPin, mSmartCardReader,
 
1014
         boost::bind(&Broker::OnInitialRPCAbort, this, _1, _2),
 
1015
         boost::bind(&Broker::OnAuthResult, this, _1, _2));
 
1016
      InitTunnel();
 
1017
      GetDesktops();
 
1018
      mXml->SendQueuedRequests();
 
1019
      ClearSmartCardPinAndReader();
945
1020
      break;
946
1021
   default:
947
 
      App::ShowDialog(GTK_MESSAGE_ERROR,
948
 
                      _("Unknown authentication method requested: %s"),
949
 
                      authInfo.name.c_str());
 
1022
      BaseApp::ShowError(CDK_ERR_AUTH_UNKNOWN_METHOD_REQUEST,
 
1023
                         _("Unknown authentication method requested"),
 
1024
                         _("Received unknown request \"%s\" from the broker"),
 
1025
                         authInfo.name.c_str());
950
1026
      if (mDelegate) {
951
1027
         mDelegate->RequestBroker();
952
1028
      }
995
1071
      // Ignore other param names, like "error" (which we've already handled).
996
1072
   }
997
1073
   if (!userSelectable && pin.empty()) {
998
 
      App::ShowDialog(GTK_MESSAGE_ERROR,
999
 
                      _("Invalid PIN Change response sent by server."));
 
1074
      BaseApp::ShowError(CDK_ERR_INVALID_SERVER_RESPONSE,
 
1075
                         _("Invalid response from server"),
 
1076
                         _("Invalid PIN Change response sent by server."));
1000
1077
   } else if (mDelegate) {
1001
1078
      mDelegate->RequestPinChange(pin, message, userSelectable);
1002
1079
   }
1223
1300
{
1224
1301
   mGettingDesktops = false;
1225
1302
 
 
1303
   if (desktops.desktops.empty()) {
 
1304
      OnAbort(false,
 
1305
              Util::exception(_("You are not entitled to use the system."),
 
1306
                              ERR_AUTHENTICATION_FAILED));
 
1307
      return;
 
1308
   }
 
1309
 
1226
1310
   std::vector<Desktop *> newDesktops;
1227
1311
   for (BrokerXml::DesktopList::iterator i = desktops.desktops.begin();
1228
1312
        i != desktops.desktops.end(); i++) {
1234
1318
 
1235
1319
   mDesktops = newDesktops;
1236
1320
   if (mDelegate) {
1237
 
      mDelegate->SetReady();
1238
1321
      // This is a superset of UpdateDesktops().
1239
1322
      mDelegate->RequestDesktop();
1240
1323
   }
1262
1345
Broker::OnGetDesktopsRefresh(BrokerXml::EntitledDesktops &desktops) // IN
1263
1346
{
1264
1347
   mGettingDesktops = false;
 
1348
 
 
1349
   if (desktops.desktops.empty()) {
 
1350
      OnAbort(false,
 
1351
              Util::exception(_("You are not entitled to use the system."),
 
1352
                              ERR_AUTHENTICATION_FAILED));
 
1353
      return;
 
1354
   }
 
1355
 
1265
1356
   std::vector<Desktop *> newDesktops;
1266
1357
   for (BrokerXml::DesktopList::iterator i = desktops.desktops.begin();
1267
1358
        i != desktops.desktops.end(); i++) {
1345
1436
Broker::OnLogoutResult()
1346
1437
{
1347
1438
   if (mDelegate) {
1348
 
      mDelegate->SetReady();
1349
1439
      mDelegate->Disconnect();
1350
1440
   }
1351
1441
}
1375
1465
Broker::OnAbort(bool cancelled,      // IN
1376
1466
                Util::exception err) // IN
1377
1467
{
 
1468
   bool showGenericError = false;
 
1469
 
1378
1470
   // Update list to reflect reset Desktop ConnectionState values on failure.
1379
1471
   if (mDelegate) {
1380
1472
      mDelegate->UpdateDesktops();
1381
 
 
1382
 
      mDelegate->SetReady();
1383
1473
   }
1384
1474
   if (cancelled) {
1385
1475
      return;
1386
1476
   }
 
1477
 
1387
1478
   if (err.code() == ERR_AUTHENTICATION_FAILED) {
1388
 
      App::ShowDialog(GTK_MESSAGE_ERROR, _("Error authenticating: %s"),
1389
 
                      err.what());
 
1479
      BaseApp::ShowError(CDK_ERR_AUTH_ERROR, _("Error authenticating"), "%s", err.what());
1390
1480
      if (mDelegate) {
1391
1481
         mDelegate->RequestBroker();
1392
1482
      }
1411
1501
              mTunnel && mTunnel->GetIsBypassed() &&
1412
1502
              !mTunnelMonitor.ShouldThrottle()) {
1413
1503
      /*
 
1504
       * The linux vdm client is hacked to attempt reestablishing a
 
1505
       * tunnel connection if the existing tunnel connection was
 
1506
       * offline-bypassed and the get-destkop-connection fails with
 
1507
       * "DESKTOP_LAUNCH_ERROR".  This covers the case where the
 
1508
       * connection is reestablished and the user attempts to connect
 
1509
       * to a remote desktop.
 
1510
       */
 
1511
      /*
1414
1512
       * XXX: Going this route is very slow, as the broker waits for tunnel
1415
1513
       *      setup before failing the desktop connection.
1416
1514
       */
1417
1515
      ResetTunnel();
1418
1516
      InitTunnel();
 
1517
   } else if (err.code() == ERR_NOT_ENTITLED) {
 
1518
      // This probably means we have out-of-date information; refresh.
 
1519
      GetDesktops(true);
 
1520
      showGenericError = true;
 
1521
   } else if (err.code() == ERR_TUNNEL_ERROR) {
 
1522
      ASSERT(mTunnelState == TUNNEL_GETTING_INFO);
 
1523
      ResetTunnel();
 
1524
      showGenericError = true;
1419
1525
   } else {
1420
 
      if (err.code() == ERR_NOT_ENTITLED) {
1421
 
         // This probably means we have out-of-date information; refresh.
1422
 
         GetDesktops(true);
1423
 
      }
1424
 
      App::ShowDialog(GTK_MESSAGE_ERROR, "%s", _(err.what()));
 
1526
      showGenericError = true;
 
1527
   }
 
1528
 
 
1529
   if (showGenericError) {
 
1530
      Util::string errorDetails = err.details();
 
1531
      if (errorDetails.empty()) {
 
1532
         BaseApp::ShowError(CDK_ERR_AUTH_ERROR, _("An error occurred"),
 
1533
                            "%s", _(err.what()));
 
1534
      } else {
 
1535
         BaseApp::ShowError(CDK_ERR_AUTH_ERROR, _(err.what()), "%s",
 
1536
                            _(errorDetails.c_str()));
 
1537
      }
 
1538
 
 
1539
      if (mDelegate) {
 
1540
         mDelegate->SetReady();
 
1541
      }
1425
1542
   }
1426
1543
}
1427
1544
 
1459
1576
          * doesn't care about our cookie anymore.
1460
1577
          */
1461
1578
         Log("Got auth failure and a cert was requested; "
1462
 
             "enabling cert response and retrying GetConfiguration()...\n");
1463
 
         mXml->ResetConnections();
1464
 
         mCertState = CERT_SHOULD_RESPOND;
1465
 
         GetConfiguration();
 
1579
             "prompting user for a certificate.\n");
 
1580
         if (mDelegate) {
 
1581
            mDelegate->RequestCertificate(mTrustedIssuers);
 
1582
         }
1466
1583
         return;
1467
1584
      }
1468
1585
 
1500
1617
            mXml->SendQueuedRequests();
1501
1618
         }
1502
1619
         return;
 
1620
      } else if (err.code() == ERR_BASICHTTP_ERROR_SSL_CONNECT_ERROR &&
 
1621
                 mCertState == CERT_DID_RESPOND) {
 
1622
         mXml->ResetConnections();
 
1623
         if (mAcceptedDisclaimer) {
 
1624
            Log("Accepting disclaimer and cert response failed; "
 
1625
                "disabling cert response and accepting disclaimer "
 
1626
                "again.\n");
 
1627
            mXml->QueueRequests();
 
1628
            mXml->AcceptDisclaimer(
 
1629
               boost::bind(&Broker::OnInitialRPCAbort, this, _1, _2),
 
1630
               boost::bind(&Broker::OnAuthResult, this, _1, _2));
 
1631
            InitTunnel();
 
1632
            GetDesktops();
 
1633
            mXml->SendQueuedRequests();
 
1634
         } else {
 
1635
            Log("No disclaimer seen, but cert response failed; just trying to "
 
1636
                "GetConfiguration() again.\n");
 
1637
            GetConfiguration();
 
1638
         }
 
1639
         return;
1503
1640
      }
1504
1641
   }
1505
1642
 
1599
1736
       * we should do so.
1600
1737
       */
1601
1738
      mCertState = CERT_REQUESTED;
 
1739
      {
 
1740
         /*
 
1741
          * Cache the issuers since they almost certainly won't change
 
1742
          * between this request and the one we later use to actually
 
1743
          * do certificate authentication.
 
1744
          */
 
1745
         STACK_OF(X509_NAME) *issuers = SSL_get_client_CA_list(ssl);
 
1746
         ASSERT(mTrustedIssuers.empty());
 
1747
         for (int i = 0; i < sk_X509_NAME_num(issuers); i++) {
 
1748
            X509_NAME *issuer = sk_X509_NAME_value(issuers, i);
 
1749
            if (issuer) {
 
1750
               char *dispName = X509_NAME_oneline(issuer, NULL, 0);
 
1751
               if (dispName && strcmp(dispName, "NO X509_NAME")) {
 
1752
                  mTrustedIssuers.push_back(dispName);
 
1753
               }
 
1754
               OPENSSL_free(dispName);
 
1755
            }
 
1756
         }
 
1757
      }
1602
1758
      // fall through...
1603
1759
   case CERT_DID_RESPOND:
1604
1760
   case CERT_REQUESTED:
1605
1761
      break;
1606
1762
   case CERT_SHOULD_RESPOND:
1607
 
      if (mDelegate) {
 
1763
      *x509 = mCert;
 
1764
      mCert = NULL;
 
1765
      *privKey = mKey;
 
1766
      mKey = NULL;
 
1767
      if (!*x509 || !*privKey) {
1608
1768
         ClearSmartCardPinAndReader();
1609
 
         CertAuthInfo info = mDelegate->GetCertAuthInfo(ssl);
1610
 
         *x509 = info.cert;
1611
 
         *privKey = info.key;
1612
 
         mSmartCardPin = info.pin;
1613
 
         mSmartCardReader = info.reader;
1614
 
         if (!*x509 || !*privKey) {
1615
 
            ClearSmartCardPinAndReader();
1616
 
         }
1617
1769
      }
1618
1770
      mCertState = CERT_DID_RESPOND;
1619
1771
      break;
1657
1809
/*
1658
1810
 *-----------------------------------------------------------------------------
1659
1811
 *
1660
 
 * cdk::Broker::OnIdleSubmitCertAuth --
1661
 
 *
1662
 
 *      Submit a cert auth response in an idle handler.  This is
1663
 
 *      needed in the case where we don't have a disclaimer, because
1664
 
 *      the current request is the one which sets our cookie.
1665
 
 *
1666
 
 * Results:
1667
 
 *      FALSE to remove this callback.
1668
 
 *
1669
 
 * Side effects:
1670
 
 *      Accepts the cert-auth response.
1671
 
 *
1672
 
 *-----------------------------------------------------------------------------
1673
 
 */
1674
 
 
1675
 
void
1676
 
Broker::OnIdleSubmitCertAuth(void *data) // IN
1677
 
{
1678
 
   Broker *that = reinterpret_cast<Broker *>(data);
1679
 
   ASSERT(that);
1680
 
 
1681
 
   if (that->mDelegate) {
1682
 
      that->mDelegate->SetBusy(_("Logging in..."));
1683
 
   }
1684
 
 
1685
 
   that->mXml->QueueRequests();
1686
 
   that->mXml->SubmitCertAuth(
1687
 
      true, that->mSmartCardPin, that->mSmartCardReader,
1688
 
      boost::bind(&Broker::OnInitialRPCAbort, that, _1, _2),
1689
 
      boost::bind(&Broker::OnAuthResult, that, _1, _2));
1690
 
   that->InitTunnel();
1691
 
   that->GetDesktops();
1692
 
   that->mXml->SendQueuedRequests();
1693
 
   that->ClearSmartCardPinAndReader();
 
1812
 * cdk::Broker::GetDesktopName --
 
1813
 *
 
1814
 *      Runs through the list of desktops and if the desktop with the given ID
 
1815
 *      is in the list, returns it's name.
 
1816
 *
 
1817
 * Results:
 
1818
 *      Util::string holding the desktop name, or empty.
 
1819
 *
 
1820
 * Side effects:
 
1821
 *      None
 
1822
 *
 
1823
 *-----------------------------------------------------------------------------
 
1824
 */
 
1825
 
 
1826
Util::string
 
1827
Broker::GetDesktopName(Util::string desktopID) // IN
 
1828
{
 
1829
   for (std::vector<Desktop *>::iterator iter = mDesktops.begin();
 
1830
        iter != mDesktops.end(); iter++) {
 
1831
      if ((*iter)->GetID() == desktopID) {
 
1832
         return (*iter)->GetName();
 
1833
      }
 
1834
   }
 
1835
 
 
1836
   return "";
 
1837
}
 
1838
 
 
1839
 
 
1840
/*
 
1841
 *-----------------------------------------------------------------------------
 
1842
 *
 
1843
 *  Broker::CreateNewXmlConnection --
 
1844
 *
 
1845
 *     Creates a new instance of the object used for sending XML requests.
 
1846
 *     This is a virtual method so derived classes can create a specialization
 
1847
 *     of BrokerXML instead.
 
1848
 *
 
1849
 * Results:
 
1850
 *     A new instance of BrokerXml* .
 
1851
 *
 
1852
 * Side effects:
 
1853
 *     The caller is responsible for freeing the returned object.
 
1854
 *
 
1855
 *-----------------------------------------------------------------------------
 
1856
 */
 
1857
 
 
1858
BrokerXml *
 
1859
Broker::CreateNewXmlConnection(const Util::string &hostname,      // IN
 
1860
                               int port,                          // IN
 
1861
                               bool secure)                       // IN
 
1862
{
 
1863
   return new BrokerXml(hostname, port, secure);
 
1864
}
 
1865
 
 
1866
 
 
1867
/*
 
1868
 *-----------------------------------------------------------------------------
 
1869
 *
 
1870
 *  Broker::GetSupportBrokerUrl --
 
1871
 *
 
1872
 *     Returns the URL of the connection server we are connected to.
 
1873
 *
 
1874
 * Results:
 
1875
 *     Util::string with the protocol, hostname, and port of the connection
 
1876
 *     server.
 
1877
 *
 
1878
 * Side effects:
 
1879
 *     None
 
1880
 *
 
1881
 *-----------------------------------------------------------------------------
 
1882
 */
 
1883
 
 
1884
Util::string
 
1885
Broker::GetSupportBrokerUrl()
 
1886
   const
 
1887
{
 
1888
   return Util::Format("%s://%s:%d", GetSecure() ? "https" : "http",
 
1889
                       GetHostname().c_str(), GetPort());
 
1890
}
 
1891
 
 
1892
 
 
1893
/*
 
1894
 *-----------------------------------------------------------------------------
 
1895
 *
 
1896
 *  Broker::CancelRequests --
 
1897
 *
 
1898
 *     Cancels all outstanding requests.
 
1899
 *
 
1900
 * Results:
 
1901
 *     The number of requests that were cancelled.
 
1902
 *
 
1903
 * Side effects:
 
1904
 *     None
 
1905
 *
 
1906
 *-----------------------------------------------------------------------------
 
1907
 */
 
1908
 
 
1909
int
 
1910
Broker::CancelRequests()
 
1911
{
 
1912
   ASSERT(mXml);
 
1913
 
 
1914
   /*
 
1915
    * If the tunnel's state was CONNECTING, but we tried to connect to a
 
1916
    * desktop, when the tunnel finishes connecting, it will try to launch the
 
1917
    * desktop.  In order to avoid this, set mDesktop to NULL so this race
 
1918
    * condition won't happen. See bz 514312.
 
1919
    */
 
1920
   if (mDesktop && mTunnelState == TUNNEL_CONNECTING) {
 
1921
      mDesktop = NULL;
 
1922
   }
 
1923
 
 
1924
   return mXml->CancelRequests();
1694
1925
}
1695
1926
 
1696
1927