summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/tests/Security/mixed_security_test/server.cpp
blob: c26bbcff3954a9297674f437c117bc5f0f41f268 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
// -*- C++ -*-

#include <ace/SString.h>
#include <ace/ARGV.h>

#include <orbsvcs/SecurityLevel2C.h>
#include <orbsvcs/SecurityLevel3C.h>

#include "Foo_i.h"
#include "constants.h"

ACE_RCSID (Secure_Invocation,
           server,
           "$Id$")

/*
  This tests the ability to use the SecurityManager/AccessDecision tools
  to permit unsecured access to specific object references, while all other
  references must be accessed via secured means.  (Note that, for the purposes
  of this conversation, "secured access" refers to the transport type, and
  an SSLIOP transport satisfies the requirements for "secured access.")

  In order to test this, we present a modified version of the
  Secure_Invocation test which creates two references of the same type
  (using the same type tests that access is granted on a per-object
  rather than per-type basis) and uses the AccessDecision tools to
  permit unsecured access to one of them, while leaving the other
  restricted only to secured access.  The server then publishes each
  of these IORs in different files.

  The other half is the client side.  The client will operate the same
  as it currently does, just performing the invocations on both IORs.
  When invoking on the secured reference, the client's insecure
  invocation should receive a NO_PERMISSION.  However, when invoking
  on the permitted reference, the insecure invocation AND the secure
  invocation should both succeed.

  IMPORTANT: SSLIOP is configured without "-SSLNoProtection" in the
  service configurator service listing.
 */

// Init/setup exception
struct RirFailedException
{
  RirFailedException (const char* token = 0) : token_(token) { }
  const char* token_;
};

template <typename REALTYPE>
typename REALTYPE::_ptr_type
rir(CORBA::ORB_ptr orb, const char* token)
{
  if (CORBA::is_nil (orb) || token == 0)
    return REALTYPE::_nil();

  CORBA::Object_var o = orb->resolve_initial_references (token);
  if (CORBA::is_nil (o.in()))
    throw RirFailedException (token);

  typename REALTYPE::_var_type r = REALTYPE::_narrow (o.in());
  return r._retn();
}

void
init_and_setup (int& argc,
		char* argv[],
		CORBA::ORB_var& orb,
		PortableServer::POA_var& rootpoa,
		PortableServer::POAManager_var& poamgr,
		SecurityLevel3::SecurityCurrent_var& sl3current,
		TAO::SL2::AccessDecision_var& sl2ad)
{
  orb = CORBA::ORB_init (argc, argv);
  rootpoa = rir<PortableServer::POA> (orb, "RootPOA");
  poamgr = rootpoa->the_POAManager();
  
  sl3current =
    rir<SecurityLevel3::SecurityCurrent>(orb, "SecurityLevel3:SecurityCurrent");

  SecurityLevel2::SecurityManager_var sl2sm =
    rir<SecurityLevel2::SecurityManager> (orb,
					  "SecurityLevel2:SecurityManager");
  SecurityLevel2::AccessDecision_var ad = sl2sm->access_decision ();

  sl2ad = TAO::SL2::AccessDecision::_narrow (ad.in ());
  if (CORBA::is_nil (sl2ad.in ()))
    throw "non-tao accessdecision";
}

struct IORPublicationException
{
  static const unsigned int OK = 0;
  static const unsigned int BAD_PARAM = 1;
  static const unsigned int IO_FAILURE = 2;

  IORPublicationException (unsigned why, int errnoval = 0)
    : why_(why), errnoval_(errnoval) { }

  unsigned int why_; // one of the const values above
  int errnoval_; // if set, the relevant value of errno at failure
};

void
publish_ior (CORBA::ORB_ptr orb, CORBA::Object_ptr o, const char* filename)
{
  if (filename == 0 || CORBA::is_nil (orb) || CORBA::is_nil (o))
    throw IORPublicationException (IORPublicationException::BAD_PARAM);

  CORBA::String_var ior = orb->object_to_string (o);

  FILE *output_file = ACE_OS::fopen (filename, "w");
  if (output_file == 0)
    {
      ACE_ERROR ((LM_ERROR,
		  "Cannot open output file %s for writing IOR\n",
		  filename));
      throw IORPublicationException (IORPublicationException::IO_FAILURE,
				     errno);
    }

  ACE_OS::fprintf (output_file, "%s", ior.in() );
  ACE_OS::fclose (output_file);
}

int
main (int argc, char *argv[])
{
  // Necessary nonsense to make up for deficencies doing this
  // in run_test.pl on Windows platforms.
  ACE_TString env ("SSL_CERT_FILE=");
  env += TAO_Mixed_Security_Test::cert_file;
  ACE_OS::putenv (env.c_str ());

  CORBA::ORB_var orb;
  Foo_i *server1;
  Foo_i *server2;

  try
    {
      // 1. ORB setup: init,
      //    grab refs for RootPOA, SL3::SecCurrent, poamgr, AccessDecision, etc.
      PortableServer::POA_var rootpoa;
      PortableServer::POAManager_var poamgr;
      SecurityLevel3::SecurityCurrent_var sl3current;
      TAO::SL2::AccessDecision_var sl2ad;

      // throws exception if it can't work
      init_and_setup (argc, argv, orb, rootpoa, poamgr, sl3current, sl2ad);
      ACE_DEBUG ((LM_DEBUG, "mixed_security/server: "
		  "init and setup complete\n"));

      // 2. Create servant #1 of Foo_i, and its associated Object
      ACE_NEW_RETURN (server1, Foo_i (orb.in(), sl3current.in()), 1);
      Foo::Bar_var server1_obj = server1->_this ();
      ACE_DEBUG ((LM_DEBUG, "mixed_security/server: "
		  "created servant/object #1\n"));

      // 3. Create servant #2 of Foo_i, and its associated Object
      ACE_NEW_RETURN (server2, Foo_i (orb.in(), sl3current.in()), 1);
      Foo::Bar_var server2_obj = server2->_this ();
      ACE_DEBUG ((LM_DEBUG, "mixed_security/server: "
		  "created servant/object #2\n"));

      // 4. add servant #2's Object reference to the "permitted" list.
      sl2ad->add_object (server2_obj.in(), true);
      ACE_DEBUG ((LM_DEBUG, "mixed_security/server: "
		  "added object #2 as a permitted reference for "
		  "non-secure invocations\n"));

      // 5. publish references to #1 and #2 to distinct files
      publish_ior (orb, server1_obj,
		   TAO_Mixed_Security_Test::restricted_ior_file);
      publish_ior (orb, server2_obj,
		   TAO_Mixed_Security_Test::permitted_ior_file);
      ACE_DEBUG ((LM_DEBUG, "mixed_security/server: "
		  "published IORs for objects\n"));

      // 6. activate the POA manager
      poamgr->activate ();
 
      // 7. run the orb.
      ACE_DEBUG ((LM_DEBUG, "mixed_security/server: "
		  "running the orb\n"));
      orb->run ();
    }
  catch (const RirFailedException& e)
    {
      ACE_ERROR ((LM_ERROR,
		  "mixed_security/server: resolve_initial_references"
		  " failed for %s\n",
		  e.token_));
      return 1;
    }
  catch (const IORPublicationException& e)
    {
      ACE_ERROR ((LM_ERROR,
		  "mixed_security/server: failed to publish IOR (%s)\n",
		  (e.why_ == IORPublicationException::BAD_PARAM) ? "BAD_PARAM" :
		  (e.why_ == IORPublicationException::IO_FAILURE) ? "IO_FAILURE":
		  "<unknown>"));
    }
  catch (CORBA::Exception& ex)
    {
      ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
                           "Caught exception:");
      return 1;
    }

  // Do I need to delete server1 and server2, or, since they're refcounted,
  // will they get automatically cleaned up on POA destruction?
  orb->destroy ();

  return 0;
}