securid 0.1 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3ba152af81ffc60b57fdebc419824bb5b98cf74e
4
+ data.tar.gz: 6c6527fa4fe5f43bebc9adf130b7394ff8c3c852
5
+ SHA512:
6
+ metadata.gz: 5d8d893afbe8ad4feb725d791d5d5b7ca072d45ab5e42c110908c21f20e1bc26abcae58d3e7afa01659c96ec72a86bc5ac1a1163887eaec287b3e080d7b908b3
7
+ data.tar.gz: 1a56068c8874462c4b78678e45eb2e27afe150b55c5403d14bb395acc12d8c31160ca704fb6046d3b349bb0b406603681f598839e9ffa3bc58b6be716c9f0f38
@@ -5,6 +5,7 @@ require 'mkmf'
5
5
  dir_config('aceclnt')
6
6
 
7
7
  have_header('acexport.h')
8
+ have_header('securid.h')
8
9
  have_library('aceclnt')
9
10
 
10
- create_makefile('securid')
11
+ create_makefile('securid/securid')
@@ -1,5 +1,17 @@
1
1
  #include "ruby.h"
2
2
  #include "acexport.h"
3
+ #include "status_display.h"
4
+ #include "securid.h"
5
+
6
+ #ifdef WIN32
7
+ #include <winsock.h>
8
+ #else
9
+ #include <sys/socket.h>
10
+ #include <netinet/in.h>
11
+ #include <arpa/inet.h>
12
+ #endif
13
+
14
+ #define CTEST(v) ((v) ? Qtrue : Qfalse)
3
15
 
4
16
  // module RSA
5
17
  static VALUE rb_mRSA;
@@ -10,133 +22,833 @@ static VALUE rb_mRSASecurID;
10
22
  // class RSA::SecurID::SecurIDError < StandardError
11
23
  static VALUE rb_eSecurIDError;
12
24
 
13
- // def RSA::SecurID.authenticate(username, passcode)
14
- static VALUE t_authenticate (VALUE self, VALUE username, VALUE passcode)
25
+ // class RSA::SecurID::Session
26
+ static VALUE rb_cRSASecurIDSession;
27
+
28
+ // ID used for session storage on RSA::SecurID::Session
29
+ ID securid_id_session;
30
+
31
+ // ID used for status storage on RSA::SecurID::Session
32
+ ID securid_id_session_status;
33
+
34
+ // ID used for test mode storage on RSA::SecurID::Session
35
+ ID securid_id_session_test_mode;
36
+
37
+ // symbol version of 'test_mode'
38
+ static VALUE rb_symTestMode;
39
+
40
+ // symbol version of 'resynchronize'
41
+ static VALUE rb_symResynchronize;
42
+
43
+ // symbol version of 'change_pin'
44
+ static VALUE rb_symChangePin;
45
+
46
+ // symbol version of 'denied'
47
+ static VALUE rb_symDenied;
48
+
49
+ // IDs used to identify RSA::SecurID::Session constants
50
+ ID securid_id_session_authenticated;
51
+ ID securid_id_session_denied;
52
+ ID securid_id_session_change_pin;
53
+ ID securid_id_session_resynchronize;
54
+
55
+ // symbols used to in the agent status hash
56
+ static VALUE rb_symConfigVersion; // 'config_version'
57
+ static VALUE rb_symMaxServers; // 'max_servers'
58
+ static VALUE rb_symMaxReplicas; // 'max_replicas'
59
+ static VALUE rb_symMaxRetries; // 'max_retries'
60
+ static VALUE rb_symBaseTimeout; // 'base_timeout'
61
+ static VALUE rb_symUseDES; // 'use_des'
62
+ static VALUE rb_symTrusted; // 'trusted'
63
+ static VALUE rb_symPort; // 'port'
64
+ static VALUE rb_symServiceName; // 'service_name'
65
+ static VALUE rb_symServiceProtocol; // 'service_protocol'
66
+ static VALUE rb_symServiceProtocolVersion; // 'service_protocol_version'
67
+ static VALUE rb_symServerReleaseNumber; // 'server_release_number'
68
+ static VALUE rb_symServers; // 'servers'
69
+ static VALUE rb_symMajor; // 'major'
70
+ static VALUE rb_symMinor; // 'minor'
71
+ static VALUE rb_symPatch; // 'patch'
72
+ static VALUE rb_symBuild; // 'build'
73
+ static VALUE rb_symAddress; // 'address'
74
+ static VALUE rb_symActiveAddress; // 'active_address'
75
+ static VALUE rb_symAliases; // 'aliases'
76
+ static VALUE rb_symDisplayStatus; // 'display_status'
77
+ static VALUE rb_symHostname; // 'hostname'
78
+ static VALUE rb_symPrimary; // 'primary'
79
+ static VALUE rb_symMaster; // 'master'
80
+ static VALUE rb_symSlave; // 'slave'
81
+ static VALUE rb_symSelectable; // 'selectable'
82
+ static VALUE rb_symEmergency; // 'emergency'
83
+ static VALUE rb_symSuspended; // 'suspended'
84
+ static VALUE rb_symAddressVerified; // 'address_verified'
85
+
86
+ static void securid_session_free(void *ptr)
15
87
  {
16
- // the authentication handle representing a single authentication
17
- // context, i.e. a multi-step authentication attempt
18
- SDI_HANDLE aceHdl;
19
-
20
- // a string containing the username
21
- SD_CHAR *userID = StringValuePtr(username);
22
-
23
- // a string containing the passcode
24
- SD_CHAR *pass = StringValuePtr(passcode);
25
-
26
- // a hint to the developer about how long to display the next
27
- // prompt string for the user
28
- SD_I32 respTimeout;
29
-
30
- // an indicator of the maximum number of bytes of data expected
31
- // in the next developer-supplied response
32
- SD_I32 nextRespLen;
33
-
34
- // a developer-supplied character array to be filled in by the
35
- // API with the string that the caller uses as the next message
36
- // displayed to the user
37
- SD_CHAR promptStr[512];
38
-
39
- // the size of the developer-supplied storage for the prompt
40
- // string
41
- SD_I32 promptStrLen;
42
-
43
- // a flag that is set by the API to indicate whether more data
44
- // is needed by the authentication context
45
- SD_BOOL moreData;
46
-
47
- // a flag that guides the developer as to whether the next
48
- // expected response is echoed to the screen
49
- SD_BOOL echoFlag;
50
-
51
- // the final authentication status
52
- SD_I32 authStatus;
53
-
54
- // initialize the authentication library. even though it will only do anything
55
- // the first time it is called, subsequent calls should still return true if the
56
- // initialization previously succeeded.
57
- if (!AceInitialize())
58
- {
59
- // the authentication library failed to initialize.
60
- rb_raise(rb_eSecurIDError, "Failed to initialize authentication library");
61
- }
62
-
63
- int retVal;
64
-
65
- // reset size of prompt string
66
- promptStrLen = sizeof(promptStr);
67
-
68
- // start our authentication attempt by first sending the username to
69
- // the authentication manager.
70
- retVal = AceStartAuth(&aceHdl, userID, strlen(userID), &moreData, &echoFlag, &respTimeout, &nextRespLen, promptStr, &promptStrLen);
71
-
72
- if (retVal != ACM_OK)
73
- {
74
- // the authentication attempt could not be started for some reason.
75
- rb_raise(rb_eSecurIDError, "Failed to start authentication attempt - Code %d", retVal);
76
- }
77
-
78
- if (!moreData)
79
- {
80
- // the authentication manager should have asked for a passcode
81
- AceCloseAuth(aceHdl);
82
- rb_raise(rb_eSecurIDError, "Authentication manager did not ask for a passcode");
83
- }
84
-
85
- // reset size of prompt string
86
- promptStrLen = sizeof(promptStr);
87
-
88
- // the authentication manager wants us to prompt the user for more data. because
89
- // this function is non-interactive, we assume the manager wants the passcode. since
90
- // we already have it, we'll pass it along without prompting the user.
91
- retVal = AceContinueAuth(aceHdl, pass, strlen(pass), &moreData, &echoFlag, &respTimeout, &nextRespLen, promptStr, &promptStrLen);
92
-
93
- if (retVal != ACM_OK)
94
- {
95
- // the authentication attempt could not be continued for some reason.
96
- AceCloseAuth(aceHdl);
97
- rb_raise(rb_eSecurIDError, "Failed to continue authentication attempt - Code %d", retVal);
98
- }
99
-
100
- if (moreData)
101
- {
102
- // either our assumption that the authentication manager wanted the passcode was
103
- // incorrect, or something else went wrong.
104
- AceCloseAuth(aceHdl);
105
- rb_raise(rb_eSecurIDError, "Authentication manager asked for more than a passcode");
106
- }
107
-
108
- // ask the authentication manager for the status of this authentication attempt.
109
- retVal = AceGetAuthenticationStatus(aceHdl, &authStatus);
110
-
111
- // finalize this authentication attempt by closing our handle.
112
- AceCloseAuth(aceHdl);
113
-
114
- if (retVal != ACE_SUCCESS)
115
- {
116
- // the authentication status could not be retrieved for some reason.
117
- rb_raise(rb_eSecurIDError, "Failed to retrieve authentication status - Code %d", retVal);
118
- }
119
-
120
- // check the status of the authentication attempt and return true or false.
121
- if (authStatus == ACM_OK)
122
- return Qtrue;
123
- else if (authStatus == ACM_ACCESS_DENIED)
124
- return Qfalse;
125
-
126
- rb_raise(rb_eSecurIDError, "Unexpected authentication status - Code %d", authStatus);
127
- }
128
-
129
- void Init_securid ()
88
+ securid_session_t *session = (securid_session_t *)ptr;
89
+ if (session->handle != SDI_HANDLE_NONE)
90
+ {
91
+ SD_Close(session->handle);
92
+ session->handle = SDI_HANDLE_NONE;
93
+ }
94
+ }
95
+
96
+ static void securid_session_mark(void *ptr)
130
97
  {
131
- // module RSA
132
- rb_mRSA = rb_define_module("RSA");
98
+
99
+ }
133
100
 
134
- // module RSA::SecurID
135
- rb_mRSASecurID = rb_define_module_under(rb_mRSA, "SecurID");
101
+ static size_t securid_session_size(void const *ptr)
102
+ {
103
+ return sizeof(securid_session_t);
104
+ }
136
105
 
137
- // class RSA::SecurID::SecurIDError < StandardError
138
- rb_eSecurIDError = rb_define_class_under(rb_mRSASecurID, "SecurIDError", rb_eStandardError);
106
+ struct rb_data_type_struct securid_session_data_type = {
107
+ "RSA::SecurID::Session Storage",
108
+ {
109
+ securid_session_mark, /* dmark */
110
+ securid_session_free, /* dfree */
111
+ securid_session_size, /* dsize */
112
+ {NULL, NULL}
113
+ },
114
+ NULL,
115
+ NULL,
116
+ RUBY_TYPED_FREE_IMMEDIATELY
117
+ };
118
+
119
+ /*
120
+ * @overload authenticate(username, password)
121
+ * @deprecated Use {Session#authenticate} instead.
122
+ * @param username [String] The username to authenticate with.
123
+ * @param passcode [String] The passcode to authenticate with. Passcodes are the user's pin
124
+ * concatenated with the current token value.
125
+ *
126
+ * Performs a basic non-interactive authentication attempt.
127
+ *
128
+ * @return [Boolean] +true+ on authentication succes, +false+ on authentication denial.
129
+ * @raise [SecureIDError] if anything beyond a basic rejection of the authentication
130
+ * happened such as a pin must be changed, the token needs resynchronization, the ACE
131
+ * server can't be found, etc.
132
+ */
133
+ static VALUE securid_authenticate(VALUE self, VALUE username, VALUE passcode)
134
+ {
135
+ // the authentication handle representing a single authentication
136
+ // context, i.e. a multi-step authentication attempt
137
+ SDI_HANDLE aceHdl;
138
+
139
+ // a string containing the username
140
+ SD_CHAR *userID = StringValuePtr(username);
141
+
142
+ // a string containing the passcode
143
+ SD_CHAR *pass = StringValuePtr(passcode);
144
+
145
+ // a hint to the developer about how long to display the next
146
+ // prompt string for the user
147
+ SD_I32 respTimeout;
148
+
149
+ // an indicator of the maximum number of bytes of data expected
150
+ // in the next developer-supplied response
151
+ SD_I32 nextRespLen;
152
+
153
+ // a developer-supplied character array to be filled in by the
154
+ // API with the string that the caller uses as the next message
155
+ // displayed to the user
156
+ SD_CHAR promptStr[512];
157
+
158
+ // the size of the developer-supplied storage for the prompt
159
+ // string
160
+ SD_I32 promptStrLen;
161
+
162
+ // a flag that is set by the API to indicate whether more data
163
+ // is needed by the authentication context
164
+ SD_BOOL moreData;
165
+
166
+ // a flag that guides the developer as to whether the next
167
+ // expected response is echoed to the screen
168
+ SD_BOOL echoFlag;
169
+
170
+ // the final authentication status
171
+ SD_I32 authStatus;
172
+
173
+ // initialize the authentication library. even though it will only do anything
174
+ // the first time it is called, subsequent calls should still return true if the
175
+ // initialization previously succeeded.
176
+ if (!AceInitialize())
177
+ {
178
+ // the authentication library failed to initialize.
179
+ rb_raise(rb_eSecurIDError, "Failed to initialize authentication library");
180
+ }
181
+
182
+ int retVal;
183
+
184
+ // reset size of prompt string
185
+ promptStrLen = sizeof(promptStr);
186
+
187
+ // start our authentication attempt by first sending the username to
188
+ // the authentication manager.
189
+ retVal = AceStartAuth(&aceHdl, userID, strlen(userID), &moreData, &echoFlag, &respTimeout, &nextRespLen, promptStr, &promptStrLen);
190
+
191
+ if (retVal != ACM_OK)
192
+ {
193
+ // the authentication attempt could not be started for some reason.
194
+ rb_raise(rb_eSecurIDError, "Failed to start authentication attempt - Code %d", retVal);
195
+ }
196
+
197
+ if (!moreData)
198
+ {
199
+ // the authentication manager should have asked for a passcode
200
+ AceCloseAuth(aceHdl);
201
+ rb_raise(rb_eSecurIDError, "Authentication manager did not ask for a passcode");
202
+ }
203
+
204
+ // reset size of prompt string
205
+ promptStrLen = sizeof(promptStr);
206
+
207
+ // the authentication manager wants us to prompt the user for more data. because
208
+ // this function is non-interactive, we assume the manager wants the passcode. since
209
+ // we already have it, we'll pass it along without prompting the user.
210
+ retVal = AceContinueAuth(aceHdl, pass, strlen(pass), &moreData, &echoFlag, &respTimeout, &nextRespLen, promptStr, &promptStrLen);
211
+
212
+ if (retVal != ACM_OK)
213
+ {
214
+ // the authentication attempt could not be continued for some reason.
215
+ AceCloseAuth(aceHdl);
216
+ rb_raise(rb_eSecurIDError, "Failed to continue authentication attempt - Code %d", retVal);
217
+ }
218
+
219
+ if (moreData)
220
+ {
221
+ // either our assumption that the authentication manager wanted the passcode was
222
+ // incorrect, or something else went wrong.
223
+ AceCloseAuth(aceHdl);
224
+ rb_raise(rb_eSecurIDError, "Authentication manager asked for more than a passcode");
225
+ }
226
+
227
+ // ask the authentication manager for the status of this authentication attempt.
228
+ retVal = AceGetAuthenticationStatus(aceHdl, &authStatus);
229
+
230
+ // finalize this authentication attempt by closing our handle.
231
+ AceCloseAuth(aceHdl);
232
+
233
+ if (retVal != ACE_SUCCESS)
234
+ {
235
+ // the authentication status could not be retrieved for some reason.
236
+ rb_raise(rb_eSecurIDError, "Failed to retrieve authentication status - Code %d", retVal);
237
+ }
238
+
239
+ // check the status of the authentication attempt and return true or false.
240
+ if (authStatus == ACM_OK)
241
+ return Qtrue;
242
+ else if (authStatus == ACM_ACCESS_DENIED)
243
+ return Qfalse;
244
+
245
+ rb_raise(rb_eSecurIDError, "Unexpected authentication status - Code %d", authStatus);
246
+ }
247
+
248
+ // Checks that the status of the session `self` matches the constant identified by `status_id`. Pass
249
+ // 0 for `status_id` to check if the the status of `self` is Qnil.
250
+ void securid_session_check_status(VALUE self, ID status_id)
251
+ {
252
+ VALUE current_status = rb_ivar_get(self, securid_id_session_status);
253
+ VALUE compared_status;
254
+ int invalid_state;
255
+
256
+ if (status_id)
257
+ {
258
+ compared_status = rb_const_get(rb_cRSASecurIDSession, status_id);
259
+ invalid_state = !rb_eql(current_status, compared_status);
260
+ } else
261
+ {
262
+ invalid_state = !NIL_P(current_status);
263
+ }
264
+
265
+ if (invalid_state)
266
+ {
267
+ rb_raise(rb_eSecurIDError, "Session is in an invalid state for the requested operation");
268
+ }
269
+ }
139
270
 
140
- // def RSA::SecurID.authenticate(username, passcode)
141
- rb_define_module_function(rb_mRSASecurID, "authenticate", t_authenticate, 2);
271
+ int securid_session_is_test_mode(VALUE self)
272
+ {
273
+ VALUE test_mode = rb_ivar_get(self, securid_id_session_test_mode);
274
+ return RTEST(test_mode);
275
+ }
276
+
277
+ int securid_session_is_test_mode_resynchronize(VALUE self)
278
+ {
279
+ VALUE test_mode = rb_ivar_get(self, securid_id_session_test_mode);
280
+ return rb_eql(test_mode, rb_symResynchronize);
281
+ }
282
+
283
+ int securid_session_is_test_mode_change_pin(VALUE self)
284
+ {
285
+ VALUE test_mode = rb_ivar_get(self, securid_id_session_test_mode);
286
+ return rb_eql(test_mode, rb_symChangePin);
287
+ }
288
+
289
+ int securid_session_is_test_mode_denied(VALUE self)
290
+ {
291
+ VALUE test_mode = rb_ivar_get(self, securid_id_session_test_mode);
292
+ return rb_eql(test_mode, rb_symDenied);
293
+ }
294
+
295
+ /*
296
+ * @overload initialize(options={})
297
+ * @param options [Hash{Symbol=>Symbol,Boolean}] A hash of options.
298
+ * @option options [Symbol,Boolean] :test_mode (false) Indicates if the test mode
299
+ * should be enabled, and if so, what mode to enable.
300
+ * Allowed options are: +true+, +false+, +:resynchronize+, +:change_pin+, +:denied+.
301
+ * +true+ means that all authentication steps are returned as successful.
302
+ *
303
+ * Creates a new session. The session will talk to the RSA server configured via the
304
+ * RSA configuration associated with the installed library, or skip talking to the server
305
+ * entirely if in test mode.
306
+ *
307
+ */
308
+ static VALUE securid_session_initialize(int argc, VALUE *argv, VALUE self)
309
+ {
310
+ securid_session_t *session;
311
+ VALUE session_data;
312
+ VALUE options = Qnil;
313
+ VALUE test_mode = Qfalse;
314
+
315
+ rb_scan_args(argc, argv, "0:", &options);
316
+
317
+ // Allocate a new securid_session_t and wrap it as a ruby object
318
+ session_data = TypedData_Make_Struct(rb_cData, securid_session_t, &securid_session_data_type, session);
319
+ session->handle = SDI_HANDLE_NONE;
320
+
321
+ // Stick our new securid_session_t into an instance variable on self
322
+ rb_ivar_set(self, securid_id_session, session_data);
323
+
324
+ // Initalize our status to nil
325
+ rb_ivar_set(self, securid_id_session_status, Qnil);
326
+
327
+ // Initalize our test_mode to the supplied option
328
+ if (!NIL_P(options))
329
+ {
330
+ test_mode = rb_hash_aref(options, rb_symTestMode);
331
+ }
332
+ rb_ivar_set(self, securid_id_session_test_mode, test_mode);
333
+
334
+ return self;
335
+ }
336
+
337
+ /*
338
+ * @overload authenticate(username, passcode)
339
+ * @param username [String] The username to authenticate with.
340
+ * @param passcode [String] The passcode to authenticate with. Passcodes are the user's pin concatenated
341
+ * with the current token value.
342
+ *
343
+ * Attempts to authenticate the user against the RSA ACE server using the username, pin, and token value.
344
+ * It will indicate if authentication fails due to token issue (pin change or resynchronization request),
345
+ * or a normal authentication failure (denied). The session object will have the returned status stored in
346
+ * its {#status status} attribute. A session with a status of {AUTHENTICATED} or
347
+ * {DENIED} can not be reused. A session with a status of {MUST_CHANGE_PIN} or
348
+ * {MUST_RESYNCHRONIZE} can be used to complete the required step, and then be used to reauthenticate
349
+ * with another call to {#authenticate}
350
+ *
351
+ * This method can only be called when the session state is {UNSTARTED}. Calling it in any other state
352
+ * will result in a {SecurIDError} being raised.
353
+ *
354
+ * @raise [SecurIDError] if the session is not in the {UNSTARTED} state or if an internal error occurs.
355
+ * @return [Symbol] The state of the authentication request, which is one of the constants {AUTHENTICATED},
356
+ * {DENIED}, {MUST_CHANGE_PIN}, or {MUST_RESYNCHRONIZE}.
357
+ */
358
+ static VALUE securid_session_authenticate(VALUE self, VALUE username, VALUE passcode)
359
+ {
360
+ int return_value;
361
+ VALUE session_data;
362
+ VALUE status = Qnil;
363
+ securid_session_t *session;
364
+ SD_CHAR *username_str;
365
+ SD_CHAR *passcode_str;
366
+
367
+ // Check that we are in an allowed state
368
+ securid_session_check_status(self, (ID)0);
369
+
370
+ if (!securid_session_is_test_mode(self))
371
+ {
372
+ // Fetch our securid_session_t from self
373
+ session_data = rb_ivar_get(self, securid_id_session);
374
+ TypedData_Get_Struct(session_data, securid_session_t, &securid_session_data_type, session);
375
+
376
+ // Convert our arguments to C Strings
377
+ username_str = StringValueCStr(username);
378
+ passcode_str = StringValueCStr(passcode);
379
+
380
+ // Initalize the session handler
381
+ return_value = SD_Init(&session->handle);
382
+ if (return_value != ACM_OK)
383
+ {
384
+ rb_raise(rb_eSecurIDError, "Failed to initialize session handler - code %d", return_value);
385
+ }
386
+
387
+ // Lock the username, part of the Two Step Authentication flow
388
+ return_value = SD_Lock(session->handle, username_str);
389
+ if (return_value != ACM_OK)
390
+ {
391
+ rb_raise(rb_eSecurIDError, "Failed to lock username - code %d", return_value);
392
+ }
393
+
394
+ return_value = SD_Check(session->handle, passcode_str, username_str);
395
+
396
+ if (return_value == ACM_OK)
397
+ {
398
+ // We are authenticated
399
+ status = rb_const_get(rb_cRSASecurIDSession, securid_id_session_authenticated);
400
+ } else if (return_value == ACM_ACCESS_DENIED)
401
+ {
402
+ // We are denied
403
+ status = rb_const_get(rb_cRSASecurIDSession, securid_id_session_denied);
404
+ } else if (return_value == ACM_NEXT_CODE_REQUIRED)
405
+ {
406
+ // We need the user to resynchronize the token
407
+ status = rb_const_get(rb_cRSASecurIDSession, securid_id_session_resynchronize);
408
+ } else if (return_value == ACM_NEW_PIN_REQUIRED)
409
+ {
410
+ // We need the user to enter a new pin
411
+ status = rb_const_get(rb_cRSASecurIDSession, securid_id_session_change_pin);
412
+ } else
413
+ {
414
+ // Internal error of some sort
415
+ rb_raise(rb_eSecurIDError, "Failed to authenticate the user - code %d", return_value);
416
+ }
417
+ } else
418
+ {
419
+ if (securid_session_is_test_mode_resynchronize(self))
420
+ {
421
+ // Force resynchronize in resynchronization test mode
422
+ status = rb_const_get(rb_cRSASecurIDSession, securid_id_session_resynchronize);
423
+ } else if (securid_session_is_test_mode_change_pin(self))
424
+ {
425
+ // Force pin change in pin change test mode
426
+ status = rb_const_get(rb_cRSASecurIDSession, securid_id_session_change_pin);
427
+ } else if (securid_session_is_test_mode_denied(self))
428
+ {
429
+ // Force denied in denied test mode
430
+ status = rb_const_get(rb_cRSASecurIDSession, securid_id_session_denied);
431
+ } else
432
+ {
433
+ // Force success in test mode
434
+ status = rb_const_get(rb_cRSASecurIDSession, securid_id_session_authenticated);
435
+ }
436
+ }
437
+
438
+ // Update our status
439
+ rb_ivar_set(self, securid_id_session_status, status);
440
+
441
+ return status;
442
+ }
443
+
444
+ /*
445
+ * @overload change_pin(pin)
446
+ * @param pin [String] The new pin for the token.
447
+ *
448
+ * Changes the pin associated with the token. This method can only be called when the
449
+ * session is in the {MUST_CHANGE_PIN} state. Calling it in any other state will result
450
+ * in a {SecurIDError} being raised. After calling {#change_pin}, the session state is
451
+ * reset to {UNSTARTED}. A subsequent call to {#authenticate} is needed to actually
452
+ * authenticate the user.
453
+ *
454
+ * The typical flow for chaning the pin is first call {#authenticate} with the old pin,
455
+ * see that we are in the {MUST_CHANGE_PIN} state, call {#change_pin} to with the new
456
+ * pin, then call {#authenticate} with the new pin to finally authorize the user.
457
+ *
458
+ *
459
+ * @raise [SecurIDError] if the session is not in the {MUST_CHANGE_PIN} state, if an
460
+ * internal error occurs, or the change request fails.
461
+ * @return [true] Always returns +true+ or raises an error.
462
+ */
463
+ static VALUE securid_session_change_pin(VALUE self, VALUE pin)
464
+ {
465
+ VALUE session_data;
466
+ securid_session_t *session;
467
+ SD_CHAR *pin_str;
468
+ int return_value;
469
+
470
+ // Check that we are in an allowed state
471
+ securid_session_check_status(self, securid_id_session_change_pin);
472
+
473
+ if (!securid_session_is_test_mode(self))
474
+ {
475
+ // Fetch our securid_session_t from self
476
+ session_data = rb_ivar_get(self, securid_id_session);
477
+ TypedData_Get_Struct(session_data, securid_session_t, &securid_session_data_type, session);
478
+
479
+ // Convert our arguments to C Strings
480
+ pin_str = StringValueCStr(pin);
481
+
482
+ return_value = SD_Pin(session->handle, pin_str);
483
+ if (return_value != ACM_NEW_PIN_ACCEPTED)
484
+ {
485
+ // Changing pin failed for internal reasons
486
+ rb_raise(rb_eSecurIDError, "Failed to change the pin - code %d", return_value);
487
+ }
488
+ } else
489
+ {
490
+ if (securid_session_is_test_mode_change_pin(self))
491
+ {
492
+ // exit pin change test mode for regular test mode
493
+ rb_ivar_set(self, securid_id_session_test_mode, Qtrue);
494
+ }
495
+ }
496
+
497
+ // Update our status to be unstarted.
498
+ rb_ivar_set(self, securid_id_session_status, Qnil);
499
+
500
+ return Qtrue;
501
+ }
502
+
503
+ /*
504
+ * Cancels a pin change request. On success the session state will be set back to {UNSTARTED}.
505
+ * This method can only be called when the session is in the {MUST_CHANGE_PIN} state. Calling
506
+ * it in any other state will raise a {SecurIDError}.
507
+ *
508
+ *
509
+ * @raise [SecurIDError] if the session is not in the {MUST_CHANGE_PIN} state, if an internal
510
+ * error occurs, or if the the canceling fails.
511
+ * @return [true] Always returns +true+ or raises an error.
512
+ */
513
+ static VALUE securid_session_cancel_pin(VALUE self)
514
+ {
515
+ VALUE session_data;
516
+ securid_session_t *session;
517
+ SD_CHAR *pin_str;
518
+ int return_value;
519
+
520
+ // Check that we are in an allowed state
521
+ securid_session_check_status(self, securid_id_session_change_pin);
522
+
523
+ if (!securid_session_is_test_mode(self))
524
+ {
525
+ // Fetch our securid_session_t from self
526
+ session_data = rb_ivar_get(self, securid_id_session);
527
+ TypedData_Get_Struct(session_data, securid_session_t, &securid_session_data_type, session);
528
+
529
+ return_value = SD_Pin(session->handle, NULL);
530
+ if (return_value != ACM_NEW_PIN_ACCEPTED)
531
+ {
532
+ rb_raise(rb_eSecurIDError, "Failed to cancel changing the pin - code %d", return_value);
533
+ }
534
+ }
535
+
536
+ // Update our status to be unstarted.
537
+ rb_ivar_set(self, securid_id_session_status, Qnil);
538
+
539
+ return Qtrue;
540
+ }
541
+
542
+ /*
543
+ * @overload resynchronize(passcode)
544
+ * @param passcode [String] The user's pin concatenated with the _next_ token value.
545
+ *
546
+ * Completes the token resynchronize flow. This method should be called when the server is requesting the user
547
+ * to resynchronize their token. It is not possible to initiate a resychronization request with this method. The
548
+ * session must be in the {MUST_RESYNCHRONIZE} state. Callig it in any other state will raise a {SecurIDError}.
549
+ *
550
+ *
551
+ * @raise [SecurIDError] if the session is not in the {MUST_RESYNCHRONIZE} state or the resynchronization fails
552
+ * for any reason other than the passcode not matching.
553
+ * @return [Symbol] Either {AUTHENTICATED} or {DENIED} depending on if the resynchronization was successful.
554
+ */
555
+ static VALUE securid_session_resynchronize(VALUE self, VALUE passcode)
556
+ {
557
+ int return_value;
558
+ VALUE session_data;
559
+ VALUE status;
560
+ securid_session_t *session;
561
+ SD_CHAR *passcode_str;
562
+
563
+ // Check that we are in an allowed state
564
+ securid_session_check_status(self, securid_id_session_resynchronize);
565
+
566
+ if (!securid_session_is_test_mode(self))
567
+ {
568
+ // Fetch our securid_session_t from self
569
+ session_data = rb_ivar_get(self, securid_id_session);
570
+ TypedData_Get_Struct(session_data, securid_session_t, &securid_session_data_type, session);
571
+
572
+ // Convert our arguments to C Strings
573
+ passcode_str = StringValueCStr(passcode);
574
+
575
+ // Initalize the session handler
576
+ return_value = SD_Next(session->handle, passcode_str);
577
+ if (return_value == ACM_OK)
578
+ {
579
+ // We are authenticated
580
+ status = rb_const_get(rb_cRSASecurIDSession, securid_id_session_authenticated);
581
+ } else if (return_value == ACM_ACCESS_DENIED)
582
+ {
583
+ // We are denied
584
+ status = rb_const_get(rb_cRSASecurIDSession, securid_id_session_denied);
585
+ } else {
586
+ // Internal error of some sort
587
+ rb_raise(rb_eSecurIDError, "Failed to synchronize the token - code %d", return_value);
588
+ }
589
+ } else {
590
+ if (securid_session_is_test_mode_resynchronize(self))
591
+ {
592
+ // exit resynchronization test mode for regular test mode
593
+ rb_ivar_set(self, securid_id_session_test_mode, Qtrue);
594
+ }
595
+ // Force success in test mode
596
+ status = rb_const_get(rb_cRSASecurIDSession, securid_id_session_authenticated);
597
+ }
598
+
599
+ // Update our status
600
+ rb_ivar_set(self, securid_id_session_status, status);
601
+
602
+ return status;
603
+ }
604
+
605
+
606
+ /*
607
+ * Fetches the status of the RSA agent. This includes details about the RSA ACE server
608
+ * the agent is communicating with. *NOTE:* this method can not be called in test mode
609
+ * unless there is an actual RSA agent present. The returned status hash is a ruby
610
+ * version of the +S_status_display+ struct populated by +AceAgentStatusDisplay+, and
611
+ * any questions about the meaning of its fields should be directed there.
612
+ *
613
+ * @example Returned Status Hash
614
+ * {
615
+ * config_version: 15,
616
+ * max_servers: 1,
617
+ * max_replicas: 4,
618
+ * max_retries: 5,
619
+ * base_timeout: 5,
620
+ * use_des: 1,
621
+ * trusted: 0,
622
+ * port: 5500,
623
+ * service_protocol_version: 0,
624
+ * service_name: "securid",
625
+ * service_protocol: "udp",
626
+ * server_release_number: {
627
+ * major: 0,
628
+ * minor: 0,
629
+ * patch: 0,
630
+ * build: 0
631
+ * },
632
+ * servers: [
633
+ * {
634
+ * hostname: "rsa.example.com",
635
+ * address: "192.168.0.1",
636
+ * active_address: nil,
637
+ * aliases: [],
638
+ * display_status: {
639
+ * primary: true,
640
+ * master: true,
641
+ * slave: false,
642
+ * selectable: false,
643
+ * emergency: false,
644
+ * suspended: true
645
+ * }
646
+ * },
647
+ * {
648
+ * hostname: nil,
649
+ * address: "192.168.0.2",
650
+ * active_address: nil,
651
+ * aliases: [],
652
+ * display_status: {
653
+ * primary: false,
654
+ * master: false,
655
+ * slave: false,
656
+ * selectable: false,
657
+ * emergency: false,
658
+ * suspended: true
659
+ * }
660
+ * }
661
+ * ]
662
+ * }
663
+ *
664
+ * @raise [SecurIDError] if the RSA agent failed to initialize.
665
+ * @return [Hash] The status hash, keyed by symbols.
666
+ */
667
+ static VALUE securid_agent_status(VALUE self) {
668
+ VALUE status = Qfalse;
669
+ VALUE server_release_number;
670
+ VALUE server_details;
671
+ VALUE servers;
672
+ VALUE server_aliases;
673
+ VALUE display_status;
674
+ S_status_display agent_status;
675
+ DISP_SRVR_INFO * server_info;
676
+ int return_value, i, j, str_length;
677
+ struct in_addr addr;
678
+
679
+ // Initialize the library. Safe to call multiple times.
680
+ if (AceInitialize() != SD_TRUE) {
681
+ rb_raise(rb_eSecurIDError, "Failed to initialize authentication agent");
682
+ }
683
+
684
+ // Make sure we are zero'd
685
+ memset(&agent_status, 0, sizeof(agent_status));
686
+ // Set the struct size so the SDK can identify the version used
687
+ agent_status.u32Size = (SD_U32) sizeof(agent_status);
688
+ // Fetch the agent status
689
+ return_value = AceAgentStatusDisplay(&agent_status);
690
+
691
+ if (return_value == ACE_SUCCESS) {
692
+ status = rb_hash_new();
693
+
694
+ // Populate status hash
695
+ rb_hash_aset(status, rb_symConfigVersion, INT2NUM(agent_status.config_version));
696
+ rb_hash_aset(status, rb_symMaxServers, INT2NUM(agent_status.acmmaxservers));
697
+ rb_hash_aset(status, rb_symMaxReplicas, INT2NUM(agent_status.acmmaxreplicas));
698
+ rb_hash_aset(status, rb_symMaxRetries, INT2NUM(agent_status.acmmaxretries));
699
+ rb_hash_aset(status, rb_symBaseTimeout, INT2NUM(agent_status.acmbasetimeout));
700
+ rb_hash_aset(status, rb_symUseDES, INT2NUM(agent_status.use_des));
701
+ rb_hash_aset(status, rb_symTrusted, INT2NUM(agent_status.trusted));
702
+ rb_hash_aset(status, rb_symPort, INT2NUM(agent_status.acmport));
703
+ rb_hash_aset(status, rb_symServiceProtocolVersion, INT2NUM(agent_status.server_hi_protocol));
704
+
705
+ str_length = strnlen(agent_status.acmservice, sizeof(agent_status.acmservice) / sizeof(SD_CHAR));
706
+ rb_hash_aset(status, rb_symServiceName, rb_str_new(agent_status.acmservice, str_length));
707
+
708
+ str_length = strnlen(agent_status.acmprotocol, sizeof(agent_status.acmprotocol) / sizeof(SD_CHAR));
709
+ rb_hash_aset(status, rb_symServiceProtocol, rb_str_new(agent_status.acmprotocol, str_length));
710
+
711
+ // Populate release number hash
712
+ server_release_number = rb_hash_new();
713
+ rb_hash_aset(server_release_number, rb_symMajor, INT2NUM(agent_status.server_release_from_server[0]));
714
+ rb_hash_aset(server_release_number, rb_symMinor, INT2NUM(agent_status.server_release_from_server[1]));
715
+ rb_hash_aset(server_release_number, rb_symPatch, INT2NUM(agent_status.server_release_from_server[2]));
716
+ rb_hash_aset(server_release_number, rb_symBuild, INT2NUM(agent_status.server_release_from_server[3]));
717
+ rb_hash_aset(status, rb_symServerReleaseNumber, server_release_number);
718
+
719
+ servers = rb_ary_new();
720
+
721
+ // Populate server array
722
+ for (i = 0; i < agent_status.acmmaxreplicas; ++i) {
723
+ server_info = &agent_status.acm_servers[i];
724
+
725
+ if (!(server_info->addr && server_info->hostname)) {
726
+ continue;
727
+ }
728
+
729
+ server_details = rb_hash_new();
730
+
731
+ str_length = strnlen(server_info->hostname, DISP_LENHOSTNAME);
732
+ rb_hash_aset(server_details, rb_symHostname, str_length ? rb_str_new(server_info->hostname, str_length) : Qnil);
733
+
734
+ addr.s_addr = server_info->addr;
735
+ rb_hash_aset(server_details, rb_symAddress, server_info->addr ? rb_str_new2(inet_ntoa(addr)) : Qnil);
736
+
737
+ addr.s_addr = server_info->active_addr;
738
+ rb_hash_aset(server_details, rb_symActiveAddress, server_info->active_addr ? rb_str_new2(inet_ntoa(addr)) : Qnil);
739
+
740
+ // build server aliases array
741
+ server_aliases = rb_ary_new();
742
+ for (j = 0; j < DISP_MAXALIASES; ++j) {
743
+ if (!server_info->aliases[j]) {
744
+ continue;
745
+ }
746
+ addr.s_addr = server_info->aliases[j];
747
+ rb_ary_push(server_aliases, rb_str_new2(inet_ntoa(addr)));
748
+ }
749
+ rb_hash_aset(server_details, rb_symAliases, server_aliases);
750
+
751
+ display_status = rb_hash_new();
752
+ rb_hash_aset(display_status, rb_symPrimary, CTEST(server_info->display_status & DISP_STATUS_PRIMARY));
753
+ rb_hash_aset(display_status, rb_symMaster, CTEST(server_info->display_status & DISP_MSTR_SLAVE && i == 0));
754
+ rb_hash_aset(display_status, rb_symSlave, CTEST(server_info->display_status & DISP_MSTR_SLAVE && i > 0));
755
+ rb_hash_aset(display_status, rb_symSelectable, CTEST(server_info->display_status & DISP_STATUS_SELECTABLE));
756
+ rb_hash_aset(display_status, rb_symEmergency, CTEST(server_info->display_status & DISP_STATUS_EMERGENCY));
757
+ rb_hash_aset(display_status, rb_symSuspended, CTEST(server_info->display_status & DISP_STATUS_SUSPENDED));
758
+ rb_hash_aset(server_details, rb_symDisplayStatus, display_status);
759
+
760
+ // Add server details to servers array
761
+ rb_ary_push(servers, server_details);
762
+ }
763
+
764
+ // Add servers array to status hash
765
+ rb_hash_aset(status, rb_symServers, servers);
766
+ }
767
+
768
+ return status;
769
+ }
770
+
771
+ void Init_securid()
772
+ {
773
+ securid_id_session = rb_intern("session_handler"); // hidden from the ruby runtime due to its name
774
+ securid_id_session_status = rb_intern("@status");
775
+ securid_id_session_test_mode = rb_intern("@test_mode");
776
+ securid_id_session_authenticated = rb_intern("AUTHENTICATED");
777
+ securid_id_session_denied = rb_intern("DENIED");
778
+ securid_id_session_change_pin = rb_intern("MUST_CHANGE_PIN");
779
+ securid_id_session_resynchronize = rb_intern("MUST_RESYNCHRONIZE");
780
+ rb_symTestMode = ID2SYM(rb_intern("test_mode"));
781
+ rb_symResynchronize = ID2SYM(rb_intern("resynchronize"));
782
+ rb_symChangePin = ID2SYM(rb_intern("change_pin"));
783
+ rb_symDenied = ID2SYM(rb_intern("denied"));
784
+
785
+ rb_symConfigVersion = ID2SYM(rb_intern("config_version"));
786
+ rb_symMaxServers = ID2SYM(rb_intern("max_servers"));
787
+ rb_symMaxReplicas = ID2SYM(rb_intern("max_replicas"));
788
+ rb_symMaxRetries = ID2SYM(rb_intern("max_retries"));
789
+ rb_symBaseTimeout = ID2SYM(rb_intern("base_timeout"));
790
+ rb_symUseDES = ID2SYM(rb_intern("use_des"));
791
+ rb_symTrusted = ID2SYM(rb_intern("trusted"));
792
+ rb_symPort = ID2SYM(rb_intern("port"));
793
+ rb_symServiceName = ID2SYM(rb_intern("service_name"));
794
+ rb_symServiceProtocol = ID2SYM(rb_intern("service_protocol"));
795
+ rb_symServiceProtocolVersion = ID2SYM(rb_intern("service_protocol_version"));
796
+ rb_symServerReleaseNumber = ID2SYM(rb_intern("server_release_number"));
797
+ rb_symServers = ID2SYM(rb_intern("servers"));
798
+ rb_symMajor = ID2SYM(rb_intern("major"));
799
+ rb_symMinor = ID2SYM(rb_intern("minor"));
800
+ rb_symPatch = ID2SYM(rb_intern("patch"));
801
+ rb_symBuild = ID2SYM(rb_intern("build"));
802
+ rb_symAddress = ID2SYM(rb_intern("address"));
803
+ rb_symActiveAddress = ID2SYM(rb_intern("active_address"));
804
+ rb_symAliases = ID2SYM(rb_intern("aliases"));
805
+ rb_symDisplayStatus = ID2SYM(rb_intern("display_status"));
806
+ rb_symHostname = ID2SYM(rb_intern("hostname"));
807
+ rb_symPrimary = ID2SYM(rb_intern("primary"));
808
+ rb_symMaster = ID2SYM(rb_intern("master"));
809
+ rb_symSlave = ID2SYM(rb_intern("slave"));
810
+ rb_symSelectable = ID2SYM(rb_intern("selectable"));
811
+ rb_symEmergency = ID2SYM(rb_intern("emergency"));
812
+ rb_symSuspended = ID2SYM(rb_intern("suspended"));
813
+ rb_symAddressVerified = ID2SYM(rb_intern("address_verified"));
814
+
815
+ // module RSA
816
+ rb_mRSA = rb_define_module("RSA");
817
+
818
+ // module RSA::SecurID
819
+ rb_mRSASecurID = rb_define_module_under(rb_mRSA, "SecurID");
820
+
821
+ /*
822
+ * Document-class: RSA::SecurID::SecurIDError
823
+ *
824
+ * The error class used by the {Session} class to indicate internal state or communication
825
+ * errors. Error codes found in the messages can be referenced against the RSA SDK
826
+ * documentation.
827
+ *
828
+ */
829
+ rb_eSecurIDError = rb_define_class_under(rb_mRSASecurID, "SecurIDError", rb_eStandardError);
830
+
831
+ // def RSA::SecurID.authenticate(username, passcode)
832
+ rb_define_module_function(rb_mRSASecurID, "authenticate", securid_authenticate, 2);
833
+
834
+ // def RSA::SecurID.agent_status
835
+ rb_define_module_function(rb_mRSASecurID, "agent_status", securid_agent_status, 0);
836
+
837
+ // class RSA::SecurID::Session
838
+ rb_cRSASecurIDSession = rb_define_class_under(rb_mRSASecurID, "Session", rb_cObject);
839
+
840
+ // def RSA::SecurID::Session.new
841
+ rb_define_method(rb_cRSASecurIDSession, "initialize", securid_session_initialize, -1);
842
+
843
+ // def RSA::SecurID::Session#authenticate(username, passcode)
844
+ rb_define_method(rb_cRSASecurIDSession, "authenticate", securid_session_authenticate, 2);
845
+
846
+ // def RSA::SecurID::Session#change_pin(pin)
847
+ rb_define_method(rb_cRSASecurIDSession, "change_pin", securid_session_change_pin, 1);
848
+
849
+ // def RSA::SecurID::Session#cancel_pin
850
+ rb_define_method(rb_cRSASecurIDSession, "cancel_pin", securid_session_cancel_pin, 0);
851
+
852
+ // def RSA::SecurID::Session#resynchronize
853
+ rb_define_method(rb_cRSASecurIDSession, "resynchronize", securid_session_resynchronize, 1);
142
854
  }
@@ -0,0 +1,11 @@
1
+ #ifndef SECURID_H_
2
+ #define SECURID_H_
3
+
4
+ extern ID securid_id_session;
5
+
6
+ // The internal storage used by RSA::SecurID::Session instances
7
+ typedef struct {
8
+ SDI_HANDLE handle;
9
+ } securid_session_t;
10
+
11
+ #endif
@@ -0,0 +1,56 @@
1
+ require 'securid/securid'
2
+
3
+ module RSA
4
+ module SecurID
5
+
6
+ # Manages a single authentication session against the RSA ACE server. Handles the various life cycle
7
+ # events that may occur, such as token resynchronization and pin changes. Includes a test mode that can
8
+ # simulate various responses when an ACE server is not present (for example during local development).
9
+ # Instances of this class should not be reused unless the RSA flow (and this documentation) indicates
10
+ # otherwise (for example, you can issue an {#authenticate} call after a successful {#change_pin} call).
11
+ #
12
+ # This class assumes you have an understanding of the RSA authentication flow. Timeouts on state
13
+ # transitions are enforced by the server, and are not documented here as they may change between ACE
14
+ # releases.
15
+ #
16
+ # In test mode, this class will send no network traffic and not talk to the RSA agent. The RSA SDK
17
+ # libraries do not even need to be present, just the header files. In the normal mode, the server
18
+ # configuration is imported by the agent directly.
19
+ class Session
20
+
21
+ # Returns the current state of the session, which is one of {AUTHENTICATED}, {DENIED},
22
+ # {MUST_CHANGE_PIN}, {MUST_RESYNCHRONIZE}, or {UNSTARTED}.
23
+ attr_reader :status
24
+
25
+ AUTHENTICATED = :authenticated
26
+ DENIED = :denied
27
+ MUST_CHANGE_PIN = :must_change_pin
28
+ MUST_RESYNCHRONIZE = :must_resynchronize
29
+ UNSTARTED = nil
30
+
31
+ # @return [Boolean] +true+ if the session is in the {MUST_RESYNCHRONIZE} state, +false+ otherwise.
32
+ # Checks if the session is in the {MUST_RESYNCHRONIZE} state.
33
+ def resynchronize?
34
+ @status == MUST_RESYNCHRONIZE
35
+ end
36
+
37
+ # Checks if the session is in the {MUST_CHANGE_PIN} state.
38
+ # @return [Boolean] +true+ if the session is in the {MUST_CHANGE_PIN} state, +false+ otherwise.
39
+ def change_pin?
40
+ @status == MUST_CHANGE_PIN
41
+ end
42
+
43
+ # Checks if the session is in the {AUTHENTICATED} state.
44
+ # @return [Boolean] +true+ if the session is in the {AUTHENTICATED} state, +false+ otherwise.
45
+ def authenticated?
46
+ @status == AUTHENTICATED
47
+ end
48
+
49
+ # Checks if the session is in the {DENIED} state.
50
+ # @return [Boolean] +true+ if the session is in the {DENIED} state, +false+ otherwise.
51
+ def denied?
52
+ @status == DENIED
53
+ end
54
+ end
55
+ end
56
+ end
metadata CHANGED
@@ -1,67 +1,52 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: securid
3
- version: !ruby/object:Gem::Version
4
- hash: 9
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 1
9
- version: "0.1"
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.5
10
5
  platform: ruby
11
- authors:
6
+ authors:
12
7
  - Ian Lesperance
8
+ - Edward Holets
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2010-06-10 00:00:00 -07:00
18
- default_executable:
12
+ date: 2016-03-14 00:00:00.000000000 Z
19
13
  dependencies: []
20
-
21
- description: A library for authenticating with an RSA SecurID ACE Authentication Server
14
+ description: A library for authenticating with an RSA SecurID ACE Authentication Server.
15
+ Supports synchronous authenttication with ACE Server 6.1 and greater. Supports interactive
16
+ and non-interactive flows.
22
17
  email: ilesperance@ezpublishing.com
23
18
  executables: []
24
-
25
- extensions:
19
+ extensions:
26
20
  - ext/securid/extconf.rb
27
21
  extra_rdoc_files: []
28
-
29
- files:
30
- - ext/securid/securid.c
22
+ files:
31
23
  - ext/securid/extconf.rb
32
- has_rdoc: true
33
- homepage: http://github.com/ezpub/securid
34
- licenses: []
35
-
24
+ - ext/securid/securid.c
25
+ - ext/securid/securid.h
26
+ - lib/securid.rb
27
+ homepage: http://github.com/sendstream/securid
28
+ licenses:
29
+ - MIT
30
+ metadata: {}
36
31
  post_install_message:
37
32
  rdoc_options: []
38
-
39
- require_paths:
33
+ require_paths:
40
34
  - lib
41
- required_ruby_version: !ruby/object:Gem::Requirement
42
- none: false
43
- requirements:
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
44
37
  - - ">="
45
- - !ruby/object:Gem::Version
46
- hash: 3
47
- segments:
48
- - 0
49
- version: "0"
50
- required_rubygems_version: !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
53
42
  - - ">="
54
- - !ruby/object:Gem::Version
55
- hash: 3
56
- segments:
57
- - 0
58
- version: "0"
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
59
45
  requirements: []
60
-
61
46
  rubyforge_project:
62
- rubygems_version: 1.3.7
47
+ rubygems_version: 2.2.2
63
48
  signing_key:
64
- specification_version: 3
49
+ specification_version: 4
65
50
  summary: A library for authenticating with an RSA SecurID ACE Authentication Server
66
51
  test_files: []
67
-
52
+ has_rdoc: