vacman_controller 0.2.2 → 0.5.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3d98133ea201d0ae3720517f298c719979a91fee
4
- data.tar.gz: 1c6ae1f43a4cc27ff8285073ea9d789c0b5c6c62
2
+ SHA256:
3
+ metadata.gz: 5ddbe7c0b1cf7bc1f64efa3ffa86ea66925dbdb27afa2f68434f0acfd3493fb8
4
+ data.tar.gz: cf653c109a8ba1bebdae0ecbdef5662978a05e56bfab0ee8a9f223ebc922d6fc
5
5
  SHA512:
6
- metadata.gz: 6c7e8cec7e94fab24bad7188374685263192721cf70ba66e751ef73e25dd24dbe0baaaed9e46b7a8d2e5fcc1e9f5055c4058857f85bf458e28297093312948e1
7
- data.tar.gz: 862c00c0d793e934d9bdb88af6bd7f06ac5cae8264a77a63afd84563f4c642fa9c65a8f5373083fb7e0c4edfa0f126e890f460e2992a147eb7daa4518a09dd88
6
+ metadata.gz: e81eed72afeda1a0d31053e55cc3eeaa7274e6324f02f8eb528361edd285e61a9a5e15b6a0de21abc8a1659c143f8dfcc93a449c6ebfa61f55e1cbf3aee2b13c
7
+ data.tar.gz: 97857b1596694fd6d40ff34aa8aad9b88b273b62fe69e2c5d90320c83fd21772599add8ce3f69a8e6094f5b03eed4d90c568fc78c923f9313951b71c8655f9a0
@@ -17,8 +17,8 @@ append_cflags "-I#{VACMAN_CONTROLLER}/include -Wall -std=c99 -Wno-declaration-af
17
17
  append_ldflags "-L#{VACMAN_CONTROLLER}/lib -laal2sdk -Wl,-rpath #{VACMAN_CONTROLLER}/lib"
18
18
 
19
19
  if find_library('aal2sdk', 'AAL2DPXInit', "#{VACMAN_CONTROLLER}/lib")
20
- create_makefile('vacman_controller/vacman_controller')
21
- else
20
+ create_makefile('vacman_controller/low_level')
21
+ else
22
22
  puts "No libaal2sdk found"
23
23
  exit 1
24
24
  end
@@ -1,60 +1,79 @@
1
+ /*
2
+ * Vacman Controller wrapper
3
+ *
4
+ * This Ruby Extension wraps the VASCO Vacman Controller
5
+ * library and makes its API accessible to Ruby code.
6
+ *
7
+ * (C) 2013 https://github.com/mlankenau
8
+ * (C) 2019 m.barnaba@ifad.org
9
+ */
10
+
1
11
  #include <ruby.h>
2
12
  #include <string.h>
3
13
  #include <aal2sdk.h>
4
14
 
5
- static VALUE e_vacmanerror; // our ruby exception type
6
- TKernelParms KernelParms; // Kernel Params
15
+
16
+ /* The Vacman default kernel parameters, set up upon extension initialisation. */
17
+ TKernelParms g_KernelParms;
18
+
19
+ /* Ruby exception type, defined as VacmanController::Error in Ruby land. */
20
+ static VALUE e_VacmanError;
21
+
7
22
 
8
23
  /*
9
- * raise an error and tell wich method failed with wich error code
24
+ * Raises an Error, decoding the Vacman Controller error code.
10
25
  */
11
- static void vacman_raise_error(const char* method, int error_code) {
12
- aat_ascii error_message[100];
13
- AAL2GetErrorMsg (error_code, error_message);
14
- rb_raise(e_vacmanerror, "%s error %d: %s", method, error_code, error_message);
26
+ static void vacman_library_error(const char* method, int vacman_error_code) {
27
+ aat_ascii vacman_error_message[100]; // Recommended value in documentation.
28
+
29
+ AAL2GetErrorMsg(vacman_error_code, vacman_error_message);
30
+
31
+ char error_message[256];
32
+ snprintf(error_message, 255, "%s error %d: %s", method, vacman_error_code,
33
+ vacman_error_message);
34
+
35
+ VALUE exc = rb_exc_new2(e_VacmanError, error_message);
36
+ rb_iv_set(exc, "@library_method", rb_str_new2(method));
37
+ rb_iv_set(exc, "@error_code", INT2FIX(vacman_error_code));
38
+ rb_iv_set(exc, "@error_message", rb_str_new2(vacman_error_message));
39
+
40
+ rb_exc_raise(exc);
15
41
  }
16
42
 
17
43
 
18
44
  /*
19
- * convert a ruby hash to TDigipassBlob structure
45
+ * Use AAL2GetLibraryVersion to obtain library version and return it as a Ruby Hash
20
46
  */
21
- static VALUE rbhash_get_key(VALUE token, const char *property, int type) {
22
- VALUE ret = rb_hash_aref(token, rb_str_new2(property));
47
+ static VALUE vacman_library_version(VALUE module) {
48
+ aat_ascii version[16];
49
+ aat_int32 version_len = sizeof(version);
23
50
 
24
- if (ret == Qnil) {
25
- rb_raise(e_vacmanerror, "invalid token object given: %s property is nil", property);
26
- return Qnil;
27
- }
51
+ aat_ascii bitness[4];
52
+ aat_int32 bitness_len = sizeof(bitness);
28
53
 
29
- if (!RB_TYPE_P(ret, type)) {
30
- rb_raise(e_vacmanerror, "invalid token object given: %s property is not of the correct type", property);
31
- return Qnil;
32
- }
54
+ aat_ascii type[8];
55
+ aat_int32 type_len = sizeof(type);
33
56
 
34
- return ret;
35
- }
57
+ aat_int32 result = AAL2GetLibraryVersion(version, &version_len, bitness,
58
+ &bitness_len, type, &type_len);
36
59
 
37
- static void rbhash_to_digipass(VALUE token, TDigipassBlob* dpdata) {
38
- if (!RB_TYPE_P(token, T_HASH)) {
39
- rb_raise(e_vacmanerror, "invalid token object given, requires an hash");
40
- return;
60
+ if (result != 0) {
61
+ vacman_library_error("AAL2GetLibraryVersion", result);
62
+ return Qnil;
41
63
  }
42
64
 
43
- VALUE blob = rbhash_get_key(token, "blob", T_STRING);
44
- VALUE serial = rbhash_get_key(token, "serial", T_STRING);
45
- VALUE app_name = rbhash_get_key(token, "app_name", T_STRING);
46
- VALUE flag1 = rbhash_get_key(token, "flags1", T_FIXNUM);
47
- VALUE flag2 = rbhash_get_key(token, "flags2", T_FIXNUM);
48
-
49
- memset(dpdata, 0, sizeof(*dpdata));
65
+ VALUE hash = rb_hash_new();
66
+ rb_hash_aset(hash, rb_str_new2("version"), rb_str_new2(version));
67
+ rb_hash_aset(hash, rb_str_new2("bitness"), rb_str_new2(bitness));
68
+ rb_hash_aset(hash, rb_str_new2("type"), rb_str_new2(type));
50
69
 
51
- strcpy(dpdata->Blob, rb_string_value_cstr(&blob));
52
- strncpy(dpdata->Serial, rb_string_value_cstr(&serial), sizeof(dpdata->Serial));
53
- strncpy(dpdata->AppName, rb_string_value_cstr(&app_name), sizeof(dpdata->AppName));
54
- dpdata->DPFlags[0] = rb_fix2int(flag1);
55
- dpdata->DPFlags[1] = rb_fix2int(flag2);
70
+ return hash;
56
71
  }
57
72
 
73
+
74
+ /*
75
+ * Convert a TDigipassBlob structure into a Ruby Hash
76
+ */
58
77
  static void digipass_to_rbhash(TDigipassBlob* dpdata, VALUE hash) {
59
78
  char buffer[256];
60
79
 
@@ -74,39 +93,62 @@ static void digipass_to_rbhash(TDigipassBlob* dpdata, VALUE hash) {
74
93
  rb_hash_aset(hash, rb_str_new2("flags2"), rb_fix_new(dpdata->DPFlags[1]));
75
94
  }
76
95
 
96
+
77
97
  /*
78
- * Get library version and return it as an hash
98
+ * Gets the given property from the given token hash and raises an Error
99
+ * if the following conditions occur:
100
+ *
101
+ * * The key is not found
102
+ * * The key is not of the given type
103
+ *
104
+ * Otherwise, the value corresponding to the key is returned.
105
+ *
79
106
  */
80
- static VALUE vacman_library_version(VALUE module) {
81
- aat_ascii version[16];
82
- aat_int32 version_len = sizeof(version);
107
+ static VALUE rbhash_get_key(VALUE token, const char *property, int type) {
108
+ VALUE ret = rb_hash_aref(token, rb_str_new2(property));
83
109
 
84
- aat_ascii bitness[4];
85
- aat_int32 bitness_len = sizeof(bitness);
110
+ if (ret == Qnil) {
111
+ rb_raise(e_VacmanError, "invalid token object given: %s property is nil", property);
112
+ return Qnil;
113
+ }
86
114
 
87
- aat_ascii type[8];
88
- aat_int32 type_len = sizeof(type);
115
+ if (!RB_TYPE_P(ret, type)) {
116
+ rb_raise(e_VacmanError, "invalid token object given: %s property is not of the correct type", property);
117
+ return Qnil;
118
+ }
89
119
 
90
- aat_int32 result = AAL2GetLibraryVersion(version, &version_len, bitness,
91
- &bitness_len, type, &type_len);
120
+ return ret;
121
+ }
92
122
 
93
- if (result != 0) {
94
- vacman_raise_error("AAL2GetLibraryVersion", result);
95
- return Qnil;
123
+
124
+ /*
125
+ * Convert a Ruby Hash with the required keys to a TDigipassBlob structure.
126
+ */
127
+ static void rbhash_to_digipass(VALUE token, TDigipassBlob* dpdata) {
128
+ if (!RB_TYPE_P(token, T_HASH)) {
129
+ rb_raise(e_VacmanError, "invalid token object given, requires an hash");
130
+ return;
96
131
  }
97
132
 
98
- VALUE hash = rb_hash_new();
99
- rb_hash_aset(hash, rb_str_new2("version"), rb_str_new2(version));
100
- rb_hash_aset(hash, rb_str_new2("bitness"), rb_str_new2(bitness));
101
- rb_hash_aset(hash, rb_str_new2("type"), rb_str_new2(type));
133
+ VALUE blob = rbhash_get_key(token, "blob", T_STRING);
134
+ VALUE serial = rbhash_get_key(token, "serial", T_STRING);
135
+ VALUE app_name = rbhash_get_key(token, "app_name", T_STRING);
136
+ VALUE flag1 = rbhash_get_key(token, "flags1", T_FIXNUM);
137
+ VALUE flag2 = rbhash_get_key(token, "flags2", T_FIXNUM);
102
138
 
103
- return hash;
139
+ memset(dpdata, 0, sizeof(*dpdata));
140
+
141
+ strcpy(dpdata->Blob, rb_string_value_cstr(&blob));
142
+ strncpy(dpdata->Serial, rb_string_value_cstr(&serial), sizeof(dpdata->Serial));
143
+ strncpy(dpdata->AppName, rb_string_value_cstr(&app_name), sizeof(dpdata->AppName));
144
+ dpdata->DPFlags[0] = rb_fix2int(flag1);
145
+ dpdata->DPFlags[1] = rb_fix2int(flag2);
104
146
  }
105
147
 
106
148
 
149
+
107
150
  /*
108
- * generate a password
109
- * this will not work with all the dpx files available, it must be prepared for it
151
+ * Generate an OTP from the given token, if the token allows it.
110
152
  */
111
153
  static VALUE vacman_generate_password(VALUE module, VALUE token) {
112
154
  TDigipassBlob dpdata;
@@ -116,11 +158,11 @@ static VALUE vacman_generate_password(VALUE module, VALUE token) {
116
158
  aat_ascii password[18];
117
159
  memset(password, 0, sizeof(password));
118
160
 
119
- aat_int32 result = AAL2GenPassword(&dpdata, &KernelParms, password, NULL);
161
+ aat_int32 result = AAL2GenPassword(&dpdata, &g_KernelParms, password, NULL);
120
162
  digipass_to_rbhash(&dpdata, token);
121
163
 
122
164
  if (result != 0) {
123
- vacman_raise_error("AAL2GenPassword", result);
165
+ vacman_library_error("AAL2GenPassword", result);
124
166
  return Qnil;
125
167
  }
126
168
 
@@ -129,7 +171,7 @@ static VALUE vacman_generate_password(VALUE module, VALUE token) {
129
171
 
130
172
 
131
173
  /*
132
- * Properties names and IDs registry
174
+ * Vacman properties names and IDs registry
133
175
  */
134
176
  struct token_property {
135
177
  const char *name;
@@ -192,10 +234,11 @@ static long vacman_get_property_id(char *property_name) {
192
234
  }
193
235
  }
194
236
 
195
- rb_raise(e_vacmanerror, "Invalid property name `%s'", property_name);
237
+ rb_raise(e_VacmanError, "Invalid property name `%s'", property_name);
196
238
  return 0;
197
239
  }
198
240
 
241
+
199
242
  /*
200
243
  * Get token property names
201
244
  */
@@ -212,7 +255,7 @@ static VALUE vacman_get_token_property_names(void) {
212
255
 
213
256
 
214
257
  /*
215
- * Get token properties
258
+ * Get the given property value from the given token.
216
259
  */
217
260
  static VALUE vacman_get_token_property(VALUE module, VALUE token, VALUE property) {
218
261
  TDigipassBlob dpdata;
@@ -220,19 +263,19 @@ static VALUE vacman_get_token_property(VALUE module, VALUE token, VALUE property
220
263
 
221
264
  aat_ascii value[64];
222
265
  aat_int32 property_id = vacman_get_property_id(StringValueCStr(property));
223
- aat_int32 result = AAL2GetTokenProperty(&dpdata, &KernelParms, property_id, value);
266
+ aat_int32 result = AAL2GetTokenProperty(&dpdata, &g_KernelParms, property_id, value);
224
267
 
225
268
  if (result == 0) {
226
269
  return rb_str_new2(value);
227
270
  } else {
228
- vacman_raise_error("AAL2GetTokenProperty", result);
271
+ vacman_library_error("AAL2GetTokenProperty", result);
229
272
  return Qnil;
230
273
  }
231
274
  }
232
275
 
233
276
 
234
277
  /*
235
- * Set token properties
278
+ * Set the given token property to the given value.
236
279
  */
237
280
  static VALUE vacman_set_token_property(VALUE module, VALUE token, VALUE property, VALUE rbval) {
238
281
  TDigipassBlob dpdata;
@@ -242,75 +285,75 @@ static VALUE vacman_set_token_property(VALUE module, VALUE token, VALUE property
242
285
 
243
286
  rbhash_to_digipass(token, &dpdata);
244
287
 
245
- aat_int32 result = AAL2SetTokenProperty(&dpdata, &KernelParms, property_id, value);
288
+ aat_int32 result = AAL2SetTokenProperty(&dpdata, &g_KernelParms, property_id, value);
246
289
 
247
290
  digipass_to_rbhash(&dpdata, token);
248
291
 
249
292
  if (result == 0) {
250
293
  return Qtrue;
251
294
  } else {
252
- vacman_raise_error("AAL2SetTokenProperty", result);
295
+ vacman_library_error("AAL2SetTokenProperty", result);
253
296
  return Qnil;
254
297
  }
255
298
  }
256
299
 
257
300
 
258
301
  /*
259
- * Set token static password
302
+ * Changes the static password on the given token.
260
303
  */
261
304
  static VALUE vacman_set_token_pin(VALUE module, VALUE token, VALUE pin) {
262
305
  TDigipassBlob dpdata;
263
306
 
264
307
  if (!RB_TYPE_P(pin, T_STRING)) {
265
- rb_raise(e_vacmanerror, "invalid pin given, requires a string");
308
+ rb_raise(e_VacmanError, "invalid pin given, requires a string");
266
309
  return Qnil;
267
310
  }
268
311
 
269
312
  rbhash_to_digipass(token, &dpdata);
270
313
 
271
314
  aat_ascii *passwd = StringValueCStr(pin);
272
- aat_int32 result = AAL2ChangeStaticPassword(&dpdata, &KernelParms, passwd, passwd);
315
+ aat_int32 result = AAL2ChangeStaticPassword(&dpdata, &g_KernelParms, passwd, passwd);
273
316
 
274
317
  digipass_to_rbhash(&dpdata, token);
275
318
 
276
319
  if (result == 0) {
277
320
  return Qtrue;
278
321
  } else {
279
- vacman_raise_error("AAL2ChangeStaticPassword", result);
322
+ vacman_library_error("AAL2ChangeStaticPassword", result);
280
323
  return Qnil;
281
324
  }
282
325
  }
283
326
 
284
327
 
285
328
  /*
286
- * verify password
287
- * this is the main usecase, check the use input for authentication
329
+ * Verifies the given OTP against the given token.
288
330
  */
289
- static VALUE vacman_verify_password(VALUE module, VALUE token, VALUE password ) {
331
+ static VALUE vacman_verify_password(VALUE module, VALUE token, VALUE password) {
290
332
  TDigipassBlob dpdata;
291
333
 
292
334
  rbhash_to_digipass(token, &dpdata);
293
335
 
294
- aat_int32 result = AAL2VerifyPassword(&dpdata, &KernelParms, rb_string_value_cstr(&password), 0);
336
+ aat_int32 result = AAL2VerifyPassword(&dpdata, &g_KernelParms, rb_string_value_cstr(&password), 0);
295
337
 
296
338
  digipass_to_rbhash(&dpdata, token);
297
339
 
298
340
  if (result == 0)
299
341
  return Qtrue;
300
342
  else {
301
- vacman_raise_error("AAL2VerifyPassword", result);
343
+ vacman_library_error("AAL2VerifyPassword", result);
302
344
  return Qnil;
303
345
  }
304
346
  }
305
347
 
306
348
 
307
-
308
349
  /*
309
- * Import a .DPX file containing token seeds and initialisation values.
350
+ * Imports a .DPX file containing token seeds and initialisation values.
351
+ *
352
+ * Pass the pre-shared key to validate it as the second argument. The
353
+ * key is not validated by the AAL2 library, if you pass a different
354
+ * key than the one that was used to create the DPX, you will get back
355
+ * tokens that generate different OTPs.
310
356
  *
311
- * Pass the pre-shared key to validate it as the second argument. Or if
312
- * you don't have the key, replace the DC line with one from a file you
313
- * know the key. Yes.
314
357
  */
315
358
  static VALUE vacman_import(VALUE module, VALUE filename, VALUE key) {
316
359
  TDPXHandle dpx_handle;
@@ -318,11 +361,15 @@ static VALUE vacman_import(VALUE module, VALUE filename, VALUE key) {
318
361
  aat_ascii appl_names[13*8];
319
362
  aat_int16 token_count;
320
363
 
321
- aat_int32 result = AAL2DPXInit(&dpx_handle, rb_string_value_cstr(&filename), rb_string_value_cstr(&key),
322
- &appl_count, appl_names, &token_count);
364
+ aat_int32 result = AAL2DPXInit(&dpx_handle,
365
+ rb_string_value_cstr(&filename),
366
+ rb_string_value_cstr(&key),
367
+ &appl_count,
368
+ appl_names,
369
+ &token_count);
323
370
 
324
371
  if (result != 0) {
325
- vacman_raise_error("AAL2DPXInit", result);
372
+ vacman_library_error("AAL2DPXInit", result);
326
373
  return Qnil;
327
374
  }
328
375
 
@@ -335,7 +382,7 @@ static VALUE vacman_import(VALUE module, VALUE filename, VALUE key) {
335
382
 
336
383
  while (1) {
337
384
  result = AAL2DPXGetToken(&dpx_handle,
338
- &KernelParms,
385
+ &g_KernelParms,
339
386
  appl_names,
340
387
  sw_out_serial_No,
341
388
  sw_out_type,
@@ -344,9 +391,10 @@ static VALUE vacman_import(VALUE module, VALUE filename, VALUE key) {
344
391
 
345
392
 
346
393
  if (result < 0) {
347
- vacman_raise_error("AAL2DPXGetToken", result);
394
+ vacman_library_error("AAL2DPXGetToken", result);
348
395
  return Qnil;
349
396
  }
397
+
350
398
  if (result == 107) break;
351
399
 
352
400
  VALUE hash = rb_hash_new();
@@ -361,30 +409,48 @@ static VALUE vacman_import(VALUE module, VALUE filename, VALUE key) {
361
409
  return list;
362
410
  }
363
411
 
412
+
413
+ /*
414
+ * Vacman Controller kernel properties
415
+ */
364
416
  struct kernel_property {
365
417
  const char *name;
366
418
  aat_int32 *value;
367
419
  aat_int32 deflt;
368
420
  };
369
421
  static struct kernel_property kernel_properties[] = {
370
- { "ITimeWindow", &KernelParms.ITimeWindow, 30 }, // Identification Window size in time steps
371
- { "STimeWindow", &KernelParms.STimeWindow, 24 }, // Signature Window size in secs
372
- { "DiagLevel", &KernelParms.DiagLevel, 0 }, // Requested Diagnostic Level
373
- { "GMTAdjust", &KernelParms.GMTAdjust, 0 }, // GMT Time adjustment to perform
374
- { "CheckChallenge", &KernelParms.CheckChallenge, 0 }, // Verify Challenge Corrupted (mandatory for Gordian)
375
- { "IThreshold", &KernelParms.IThreshold, 3 }, // Identification Error Threshold
376
- { "SThreshold", &KernelParms.SThreshold, 1 }, // Signature Error Threshold
377
- { "ChkInactDays", &KernelParms.ChkInactDays, 0 }, // Check Inactive Days
378
- { "DeriveVector", &KernelParms.DeriveVector, 0 }, // Vector used to make Data Encryption unique
379
- { "SyncWindow", &KernelParms.SyncWindow, 2 }, // Synchronisation Time Window (h)
380
- { "OnLineSG", &KernelParms.OnLineSG, 2 }, // On line signature
381
- { "EventWindow", &KernelParms.EventWindow, 100 }, // Event Window size in nbr of iterations
382
- { "HSMSlotId", &KernelParms.HSMSlotId, 0 }, // HSM Slot id uses to store DB and Transport Key
422
+ { "ITimeWindow", &g_KernelParms.ITimeWindow, 30 }, // Identification Window size in time steps
423
+ { "STimeWindow", &g_KernelParms.STimeWindow, 24 }, // Signature Window size in secs
424
+ { "DiagLevel", &g_KernelParms.DiagLevel, 0 }, // Requested Diagnostic Level
425
+ { "GMTAdjust", &g_KernelParms.GMTAdjust, 0 }, // GMT Time adjustment to perform
426
+ { "CheckChallenge", &g_KernelParms.CheckChallenge, 0 }, // Verify Challenge Corrupted (mandatory for Gordian)
427
+ { "IThreshold", &g_KernelParms.IThreshold, 3 }, // Identification Error Threshold
428
+ { "SThreshold", &g_KernelParms.SThreshold, 1 }, // Signature Error Threshold
429
+ { "ChkInactDays", &g_KernelParms.ChkInactDays, 0 }, // Check Inactive Days
430
+ { "DeriveVector", &g_KernelParms.DeriveVector, 0 }, // Vector used to make Data Encryption unique
431
+ { "SyncWindow", &g_KernelParms.SyncWindow, 2 }, // Synchronisation Time Window (h)
432
+ { "OnLineSG", &g_KernelParms.OnLineSG, 2 }, // On line signature
433
+ { "EventWindow", &g_KernelParms.EventWindow, 100 }, // Event Window size in nbr of iterations
434
+ { "HSMSlotId", &g_KernelParms.HSMSlotId, 0 }, // HSM Slot id uses to store DB and Transport Key
383
435
  };
384
436
  static size_t kernel_properties_count = sizeof(kernel_properties)/sizeof(struct kernel_property);
385
437
 
386
438
  /*
387
- * Get kernel property names
439
+ * Initialise the kernel parameters with their defaults
440
+ */
441
+ static void vacman_init_kernel_params() {
442
+ memset(&g_KernelParms, 0, sizeof(g_KernelParms));
443
+
444
+ g_KernelParms.ParmCount = 19; /* Number of valid parameters in this list */
445
+
446
+ for (size_t i = 0; i < kernel_properties_count; i++) {
447
+ *kernel_properties[i].value = kernel_properties[i].deflt;
448
+ }
449
+ }
450
+
451
+
452
+ /*
453
+ * Get kernel parameter names
388
454
  */
389
455
  static VALUE vacman_get_kernel_property_names(void) {
390
456
  VALUE ret = rb_ary_new();
@@ -397,6 +463,7 @@ static VALUE vacman_get_kernel_property_names(void) {
397
463
  return ret;
398
464
  }
399
465
 
466
+
400
467
  /*
401
468
  * Set kernel parameter
402
469
  */
@@ -411,7 +478,7 @@ static VALUE vacman_set_kernel_param(VALUE module, VALUE paramname, VALUE rbval)
411
478
  }
412
479
  }
413
480
 
414
- rb_raise(e_vacmanerror, "Invalid kernel param %s", name);
481
+ rb_raise(e_VacmanError, "Invalid kernel param %s", name);
415
482
  return Qnil;
416
483
  }
417
484
 
@@ -428,48 +495,36 @@ static VALUE vacman_get_kernel_param(VALUE module, VALUE paramname) {
428
495
  }
429
496
  }
430
497
 
431
- rb_raise(e_vacmanerror, "Invalid kernel param %s", name);
498
+ rb_raise(e_VacmanError, "Invalid kernel param %s", name);
432
499
  return Qnil;
433
500
  }
434
501
 
435
- /*
436
- * Init the kernel parameters, with their defaults
437
- */
438
- static void init_kernel_params() {
439
- memset(&KernelParms, 0, sizeof(TKernelParms));
440
-
441
- KernelParms.ParmCount = 19; /* Number of valid parameters in this list */
442
-
443
- for (size_t i = 0; i < kernel_properties_count; i++) {
444
- *kernel_properties[i].value = kernel_properties[i].deflt;
445
- }
446
- }
447
-
448
502
 
449
503
  /*
450
- * rubys entry point to load the extension
504
+ * Extension entry point
451
505
  */
452
- void Init_vacman_controller(void) {
453
- VALUE vacman_module = rb_define_module("VacmanLowLevel");
454
-
455
- e_vacmanerror = rb_define_class("VacmanError", rb_eStandardError);
456
- init_kernel_params();
457
-
458
- rb_define_singleton_method(vacman_module, "version", vacman_library_version, 0);
459
-
460
- rb_define_singleton_method(vacman_module, "import", vacman_import, 2);
461
-
462
- rb_define_singleton_method(vacman_module, "generate_password", vacman_generate_password, 1);
463
- rb_define_singleton_method(vacman_module, "verify_password", vacman_verify_password, 2);
464
-
465
- rb_define_singleton_method(vacman_module, "get_kernel_param", vacman_get_kernel_param, 1);
466
- rb_define_singleton_method(vacman_module, "set_kernel_param", vacman_set_kernel_param, 2);
467
-
468
- rb_define_singleton_method(vacman_module, "get_token_property", vacman_get_token_property, 2);
469
- rb_define_singleton_method(vacman_module, "set_token_property", vacman_set_token_property, 3);
470
-
471
- rb_define_singleton_method(vacman_module, "set_token_pin", vacman_set_token_pin, 2);
472
-
473
- rb_define_singleton_method(vacman_module, "token_property_names", vacman_get_token_property_names, 0);
474
- rb_define_singleton_method(vacman_module, "kernel_property_names", vacman_get_kernel_property_names, 0);
506
+ void Init_low_level(void) {
507
+ VALUE controller = rb_define_module("VacmanController");
508
+ VALUE lowlevel = rb_define_module_under(controller, "LowLevel");
509
+
510
+ e_VacmanError = rb_define_class_under(controller, "Error", rb_eStandardError);
511
+
512
+ vacman_init_kernel_params();
513
+
514
+ /* Global methods */
515
+ rb_define_singleton_method(lowlevel, "library_version", vacman_library_version, 0);
516
+ rb_define_singleton_method(lowlevel, "import", vacman_import, 2);
517
+
518
+ /* Token methods */
519
+ rb_define_singleton_method(lowlevel, "token_property_names", vacman_get_token_property_names, 0);
520
+ rb_define_singleton_method(lowlevel, "get_token_property", vacman_get_token_property, 2);
521
+ rb_define_singleton_method(lowlevel, "set_token_property", vacman_set_token_property, 3);
522
+ rb_define_singleton_method(lowlevel, "generate_password", vacman_generate_password, 1);
523
+ rb_define_singleton_method(lowlevel, "verify_password", vacman_verify_password, 2);
524
+ rb_define_singleton_method(lowlevel, "set_token_pin", vacman_set_token_pin, 2);
525
+
526
+ /* Kernel methods */
527
+ rb_define_singleton_method(lowlevel, "kernel_property_names", vacman_get_kernel_property_names, 0);
528
+ rb_define_singleton_method(lowlevel, "get_kernel_param", vacman_get_kernel_param, 1);
529
+ rb_define_singleton_method(lowlevel, "set_kernel_param", vacman_set_kernel_param, 2);
475
530
  }
@@ -1,176 +1,60 @@
1
- require 'vacman_controller/vacman_controller'
1
+ require 'vacman_controller/low_level'
2
+ require 'vacman_controller/token'
3
+ require 'vacman_controller/kernel'
4
+ require 'vacman_controller/error'
2
5
 
3
- # Provides VACMAN Controller functionality to identify and authorize user via VASCO DIGIPASS tokens.
4
- #
6
+ # Wraps VACMAN Controller functionality for Ruby.
5
7
  #
6
8
  module VacmanController
7
- extend self
8
-
9
- # Import .dpx file containing the secure token-data
10
- #
11
- # == Parameters:
12
- # filename::
13
- # The path of the .dpx file to load
14
- # key::
15
- # The secure key to decrypt the dpx file
16
- #
17
- # == Returns:
18
- # A list of hashes. Each hash contains
19
- # serial: the serial number of the token
20
- # blob: the blob containing some secret magic data
21
- # app_name: the application name (the security method)
22
- # flags1: some flags
23
- # flags2: more flags
24
- #
25
- # this hash must be persisted and regained for each call of verify_password and generate_password
26
- #
27
- def import(filename, key)
28
- VacmanLowLevel.import(filename, key)
29
- end
30
-
31
-
32
-
33
- # Generate a Password for a user. This does the same as hitting the button on your hardware token
34
- #
35
- # == Parameters:
36
- # hash::
37
- # The hash for a specific token (you get these in import)
38
- #
39
- # == Returns:
40
- # The password string. The password is only valid for a period (todo: add method to change the period, currently its 30 seconds)
41
- #
42
- def generate_password(hash)
43
- VacmanLowLevel.generate_password(hash)
44
- end
45
-
46
-
47
-
48
- # Verify a password. This is the usecase a user sends you a password generated by his token and we have to verify it.
49
- #
50
- # == Parameters:
51
- # hash::
52
- # The hash for a specific token (you get these in import)
53
- # pw::
54
- # The password provided by the user
55
- #
56
- # == Returns:
57
- # true if the password is valid, false otherwise
58
- #
59
- # ATTENTION: it is very important to persist the hash afterwards!!!
60
- #
61
- def verify_password(hash, pw)
62
- VacmanLowLevel.verify_password(hash, pw)
63
- end
64
-
65
-
66
-
67
- # Gets the available kernel property names
68
- #
69
- def kernel_property_names
70
- @_kernel_property_names ||= VacmanLowLevel.kernel_property_names
71
- end
72
-
73
-
74
-
75
- # Get a kernel parameter, wich is a basically a setting for vacman controller
76
- #
77
- # == Parameters:
78
- # name::
79
- # the param name. Most TKernelParms struct elements are accessible.
80
- #
81
- def get_kernel_param(name)
82
- VacmanLowLevel.get_kernel_param(name)
83
- end
84
-
85
-
86
-
87
- # Change a kernel parameter, wich is a basically a setting for vacman controller
88
- #
89
- # == Parameters:
90
- # name::
91
- # the param name. Most TKernelParms struct elements are accessible.
92
- # val::
93
- # the fixnum value
94
- #
95
- def set_kernel_param(name, val)
96
- VacmanLowLevel.set_kernel_param(name, val)
97
- end
98
9
 
99
-
100
-
101
- # Returns all configured kernel parameters
102
- #
103
- def get_kernel_all_parameters
104
- kernel_property_names.inject({}) do |h, name|
105
- h.update(name => (get_kernel_param(name) rescue "ERROR: #$!"))
10
+ VERSION = '0.5.0'
11
+
12
+ class << self
13
+ # Imports a .dpx file containing the token key material.
14
+ #
15
+ # == Parameters:
16
+ #
17
+ # filename::
18
+ # The path of the .dpx file to load
19
+ #
20
+ # key::
21
+ # The transport key to decrypt the dpx file
22
+ #
23
+ # == Returns:
24
+ # An Array of Ruby Hashes. Each Hash contains the following keys:
25
+ #
26
+ # serial: the serial number of the token
27
+ # blob: the blob containing some secret magic data
28
+ # app_name: the application name (the security method)
29
+ # flags1: flags
30
+ # flags2: flags
31
+ #
32
+ # This is only for low-level usage. For a Ruby API, look at
33
+ # +VacmanController::Token.import+.
34
+ #
35
+ def import(filename, key)
36
+ VacmanController::LowLevel.import(filename, key)
37
+
38
+ rescue VacmanController::Error => e
39
+ # We handle two undocumented error codes here
40
+ case e.error_code
41
+ when -15
42
+ raise VacmanController::Error, "#{e.library_method} error #{e.error_code}: invalid transport key"
43
+
44
+ when -20
45
+ raise VacmanController::Error, "#{e.library_method} error #{e.error_code}: cannot open DPX file"
46
+
47
+ else
48
+ raise # Sorry, I did my best.
49
+
50
+ end
106
51
  end
107
- end
108
-
109
-
110
-
111
- # Gets the available token property names
112
- #
113
- def token_property_names
114
- @_token_property_names ||= VacmanLowLevel.token_property_names
115
- end
116
-
117
-
118
-
119
- # Get a token single property
120
- #
121
- # == Parameters:
122
- # hash::
123
- # the hash for a specific token (you get these in import)
124
- # property::
125
- # the property name. See +token_property_names+
126
- #
127
- def get_token_property(hash, property)
128
- VacmanLowLevel.get_token_property(hash, property)
129
- end
130
52
 
131
-
132
-
133
- # Set a token single property
134
- #
135
- # == Parameters:
136
- # hash::
137
- # the hash for a specific token (you get these in import)
138
- # property::
139
- # the property name. See +token_property_names+
140
- # value::
141
- # the property value. Only values convertible to integer are supported.
142
- #
143
- # possible names:
144
- #
145
- #
146
- def set_token_property(hash, property, value)
147
- VacmanLowLevel.set_token_property(hash, property, value)
148
- end
149
-
150
-
151
-
152
- # Set a token PIN
153
- #
154
- # == Parameters:
155
- # hash::
156
- # the hash for a specific token (you get these in import)
157
- # pin::
158
- # the new PIN. must be a string.
159
- #
160
- # possible names:
161
- #
162
- #
163
- def set_token_pin(hash, pin)
164
- VacmanLowLevel.set_token_pin(hash, pin)
165
- end
166
-
167
-
168
-
169
- # Returns all properties configured for a token
170
- #
171
- def get_token_all_properties(hash)
172
- token_property_names.inject({}) do |h, name|
173
- h.update(name => (get_token_property(hash, name) rescue "ERROR: #$!"))
53
+ # Returns the +Kernel+ module
54
+ #
55
+ def kernel
56
+ VacmanController::Kernel
174
57
  end
175
58
  end
59
+
176
60
  end
@@ -0,0 +1,16 @@
1
+ module VacmanController
2
+
3
+ # Represents a Vacman Controller Library error.
4
+ #
5
+ class Error < StandardError
6
+ # The AAL2 library method that errored
7
+ attr_reader :library_method
8
+
9
+ # The error code returned by the AAL2 library
10
+ attr_reader :error_code
11
+
12
+ # The error message retrieved by the AAL2 library
13
+ attr_reader :error_message
14
+ end
15
+
16
+ end
@@ -0,0 +1,71 @@
1
+ module VacmanController
2
+
3
+ module Kernel
4
+ class << self
5
+ # Returns the library version as an hash
6
+ #
7
+ def version
8
+ @_version = VacmanController::LowLevel.library_version
9
+ end
10
+
11
+
12
+ # Gets the available kernel property names
13
+ #
14
+ def property_names
15
+ @_property_names ||= VacmanController::LowLevel.kernel_property_names.freeze
16
+ end
17
+
18
+
19
+ # Shows the kernel version, bitness, type and parameters in your
20
+ # development console.
21
+ #
22
+ def inspect
23
+ "#<#{self.name} version=#{version['version'].inspect} bitness=#{version['bitness'].inspect} "\
24
+ "type=#{version['type'].inspect} parameters=#{all.inspect}>>"
25
+ end
26
+
27
+
28
+ # Returns all configured parameters
29
+ #
30
+ def all
31
+ property_names.inject({}) do |h, name|
32
+ h.update(name => (self[name] rescue "ERROR: #$!"))
33
+ end
34
+ end
35
+ alias to_h all
36
+
37
+
38
+ # Get a Kernel property, that is a runtime parameter of Vacman Controller,
39
+ # stored in the TKernelParms structure.
40
+ #
41
+ # == Parameters:
42
+ # name::
43
+ # The param name. See +property_names+ for a list of available property
44
+ # names.
45
+ #
46
+ def [](name)
47
+ VacmanController::LowLevel.get_kernel_param(name)
48
+ end
49
+
50
+
51
+ # Set a Kernel property.
52
+ #
53
+ # == Parameters:
54
+ # name::
55
+ # the param name. See +property_names+ for a list of available property
56
+ # names. The Kernel parameters are all int32 properties.
57
+ #
58
+ # val::
59
+ # the integer value
60
+ #
61
+ def []=(name, val)
62
+ Mutex.synchronize do
63
+ VacmanController::LowLevel.set_kernel_param(name, val)
64
+ end
65
+ end
66
+
67
+ Mutex = Thread::Mutex.new
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,182 @@
1
+ require 'vacman_controller/token/properties'
2
+
3
+ module VacmanController
4
+
5
+ class Token
6
+ # Opens the given dpx_filename with the given transport key and,
7
+ # if successful, returns Token instances for all tokens in the
8
+ # DPX file.
9
+ #
10
+ def self.import(dpx_filename, transport_key)
11
+ VacmanController.import(dpx_filename, transport_key).map do |hash|
12
+ Token.new(hash)
13
+ end
14
+ end
15
+
16
+
17
+ # Initialises a Token instance with the given token hash.
18
+ #
19
+ def initialize(token_hash)
20
+ @token_hash = token_hash
21
+ end
22
+
23
+
24
+ # Return the token serial number
25
+ #
26
+ def serial
27
+ @token_hash.fetch('serial').dup
28
+ end
29
+
30
+
31
+ # Returns the token Application Name
32
+ #
33
+ def app_name
34
+ @token_hash.fetch('app_name').dup
35
+ end
36
+
37
+
38
+ # Renders this token in your development console
39
+ # and in your logs (possibly)
40
+ #
41
+ def inspect
42
+ "#<#{self.class.name} serial=#{serial.inspect} app_name=#{app_name.inspect}>"
43
+ end
44
+
45
+
46
+ # Returns the token as an hash, that is suitable for passing to
47
+ # the low-level functions, or for persistance purposes.
48
+ #
49
+ def to_h
50
+ @token_hash
51
+ end
52
+
53
+
54
+ # Verify a password. This is the usecase a user sends you an OTP
55
+ # generated by their token and we have to verify it.
56
+ #
57
+ # == Parameters:
58
+ # otp::
59
+ # The OTP provided by the user
60
+ #
61
+ # == Returns:
62
+ # true if the password is valid, false otherwise
63
+ #
64
+ # ATTENTION: it is very important to persist the token hash
65
+ # afterwards.
66
+ #
67
+ def verify(otp)
68
+ verify!(otp)
69
+ rescue VacmanController::Error
70
+ false
71
+ end
72
+
73
+
74
+ # Same as verify, but raises a VacmanController::Error if OTP verification
75
+ # fails.
76
+ #
77
+ def verify!(otp)
78
+ VacmanController::LowLevel.verify_password(@token_hash, otp.to_s)
79
+ end
80
+
81
+
82
+ # Generate an OTPfrom this token. This does the same as hitting the button
83
+ # on the hardware token.
84
+ #
85
+ # == Returns:
86
+ # The OTP as a String. The OTP is only valid for a limited time period.
87
+ #
88
+ # Not all tokens support OTP generation.
89
+ #
90
+ def generate
91
+ VacmanController::LowLevel.generate_password(@token_hash)
92
+ end
93
+
94
+
95
+ # Set this token's PIN
96
+ #
97
+ # == Parameters:
98
+ # pin::
99
+ # the new PIN. Must be coercible to String.
100
+ #
101
+ def set_pin(pin)
102
+ VacmanController::LowLevel.set_token_pin(@token_hash, pin.to_s)
103
+ end
104
+
105
+
106
+ ####################################################################
107
+ ##### Properties Management
108
+ ####################################################################
109
+
110
+ # Enables the PIN on this token
111
+ #
112
+ def enable_pin!
113
+ properties[:pin_enabled] = 1
114
+ true
115
+ end
116
+
117
+
118
+ # Disables the PIN on this token
119
+ #
120
+ def disable_pin!
121
+ properties[:pin_enabled] = 2
122
+ true
123
+ end
124
+
125
+
126
+ # Forces PIN change on this token
127
+ #
128
+ def force_pin_change!
129
+ properties[:pin_change_forced] = 1
130
+ true
131
+ end
132
+
133
+
134
+ # Resets the token error count
135
+ #
136
+ def reset_error_count!
137
+ properties[:error_count] = 0
138
+ true
139
+ end
140
+
141
+
142
+ # Sets the "disabled" token status
143
+ #
144
+ def disable!
145
+ properties[:token_status] = 0
146
+ true
147
+ end
148
+
149
+
150
+ # Set the primary application enabled status
151
+ #
152
+ def enable_primary_only!
153
+ properties[:token_status] = 1
154
+ true
155
+ end
156
+
157
+
158
+ # Set the backup application enabled status
159
+ #
160
+ def enable_backup_only!
161
+ properties[:token_status] = 2
162
+ true
163
+ end
164
+
165
+
166
+ # Set both primary and backup application enabled status
167
+ #
168
+ def enable!
169
+ properties[:token_status] = 3
170
+ true
171
+ end
172
+
173
+
174
+ # Returns a +Token::Properties+ object giving low-level access to the
175
+ # token properties.
176
+ #
177
+ def properties
178
+ @_properties = VacmanController::Token::Properties.new(self)
179
+ end
180
+ end
181
+
182
+ end
@@ -0,0 +1,193 @@
1
+ module VacmanController
2
+ class Token
3
+
4
+ class Properties
5
+ class << self
6
+ # Gets the available token property names
7
+ #
8
+ def names
9
+ @_names ||= VacmanController::LowLevel.token_property_names.freeze
10
+ end
11
+ end
12
+
13
+
14
+ def initialize(token)
15
+ @token = token
16
+ end
17
+
18
+
19
+ def inspect
20
+ all.inspect
21
+ end
22
+
23
+
24
+ def all
25
+ self.class.names.inject({}) do |h, name|
26
+ h.update(name => (self[name] rescue "ERROR: #$!"))
27
+ end
28
+ end
29
+ alias to_h all
30
+
31
+
32
+ # Get a Token property
33
+ #
34
+ # == Parameters:
35
+ #
36
+ # property::
37
+ # the property name. See +Token::Properties.names+
38
+ #
39
+ def [](name)
40
+ name = name.to_s
41
+ value = VacmanController::LowLevel.get_token_property(@token.to_h, name)
42
+
43
+ cast(name, value)
44
+ end
45
+
46
+
47
+ # Set a Token property
48
+ #
49
+ # == Parameters:
50
+ #
51
+ # property::
52
+ # the property name. See +Token.property_names+
53
+ #
54
+ # value::
55
+ # the property value. Only values convertible to integer are
56
+ # supported.
57
+ #
58
+ def []=(name, value)
59
+ name = name.to_s
60
+ value = value.to_i
61
+
62
+ check_bounded_property!(name, value)
63
+
64
+ VacmanController::LowLevel.set_token_property(@token.to_h, name, value)
65
+ end
66
+
67
+
68
+ protected
69
+ def bounded_property?(name)
70
+ PROPERTY_BOUNDS.key?(name)
71
+ end
72
+
73
+ # The library also does these checks, but we want to present
74
+ # custom error message to the caller.
75
+ #
76
+ def check_bounded_property!(name, value)
77
+ return unless bounded_property?(name)
78
+
79
+ min, max = PROPERTY_BOUNDS.fetch(name)
80
+
81
+ if value < min || value > max
82
+ raise VacmanController::Error,
83
+ "Invalid #{name} value provided: #{value}. " \
84
+ "Must be between greater than #{min} and less than #{max}."
85
+ end
86
+
87
+ true
88
+ end
89
+
90
+ PROPERTY_BOUNDS = {
91
+ 'last_time_used' => [ 631152000, 2147483647 ],
92
+
93
+ 'last_time_shift' => [ -100_000, 100_000 ],
94
+
95
+ 'pin_min_length' => [ 3, 8 ],
96
+ 'pin_minimum_length' => [ 3, 8 ],
97
+
98
+ 'virtual_token_grace_period' => [ 1, 364 ],
99
+
100
+ 'virtual_token_remain_use' => [ 0, 254 ],
101
+
102
+ 'event_value' => [ 0, 4_294_967_294 ],
103
+ }
104
+
105
+ def cast(property, value)
106
+
107
+ # Short-circuit on 'NA'
108
+ return nil if value == 'NA' or value == 'DISABLE'
109
+
110
+ case property
111
+ when # Integer values
112
+ 'use_count',
113
+ 'pin_len',
114
+ 'pin_length',
115
+ 'pin_min_len',
116
+ 'pin_minimum_length',
117
+ 'last_time_shift',
118
+ 'virtual_token_remain_use',
119
+ 'error_count',
120
+ 'event_value',
121
+ 'last_event_value',
122
+ 'max_dtf_number',
123
+ 'response_len',
124
+ 'response_length',
125
+ 'time_step'
126
+
127
+ value.to_i
128
+
129
+ when # Boolean values
130
+ 'time_based_algo',
131
+ 'event_based_algo',
132
+ 'pin_supported',
133
+ 'unlock_supported',
134
+ 'pin_ch_on',
135
+ 'pin_change_enabled',
136
+ 'pin_enabled',
137
+ 'pin_ch_forced',
138
+ 'pin_change_forced',
139
+ 'sync_windows',
140
+ 'primary_token_enabled',
141
+ 'virtual_token_supported',
142
+ 'virtual_token_enabled',
143
+ 'derivation_supported',
144
+ 'response_chk',
145
+ 'response_checksum',
146
+ 'triple_des_used',
147
+ 'use_3des'
148
+
149
+ case value
150
+ when 'YES' then true
151
+ when 'NO' then false
152
+ end
153
+
154
+ when # Date/time values
155
+ 'last_time_used',
156
+ 'virtual_token_grace_period'
157
+
158
+ # AAL2 returns UTC values, we add the timezone.
159
+ Time.strptime("#{value} UTC", '%a %b %d %H:%M:%S %Y %Z')
160
+
161
+ when
162
+ 'auth_mode'
163
+
164
+ case value
165
+ when 'RO' then :response_only
166
+ when 'SG' then :signature_application
167
+ when 'CR' then :challenge_response
168
+ when 'MM' then :multi_mode
169
+ when 'UL' then :unlock_v2
170
+ else
171
+ value
172
+ end
173
+
174
+ else # String values
175
+
176
+ value
177
+ end
178
+ end
179
+
180
+ private
181
+ def method_missing(name, *args, &block)
182
+ prop, setter = name.to_s.match(/\A(.+?)(=)?\Z/).values_at(1, 2)
183
+
184
+ if setter
185
+ self[prop] = args.first
186
+ else
187
+ self[prop]
188
+ end
189
+ end
190
+ end
191
+
192
+ end
193
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vacman_controller
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcus Lankenau
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-01-07 00:00:00.000000000 Z
12
+ date: 2019-04-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake-compiler
@@ -25,7 +25,36 @@ dependencies:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
- description: Authenticate user via vacman controller
28
+ - !ruby/object:Gem::Dependency
29
+ name: rspec
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: guard-rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ description: Expose the AAL2 SDK API via a set of Ruby classes optimised for developer
57
+ happiness
29
58
  email:
30
59
  - marcus.lankenau@gmail.com
31
60
  - marcello.barnaba@gmail.com
@@ -35,9 +64,13 @@ extensions:
35
64
  extra_rdoc_files: []
36
65
  files:
37
66
  - ext/vacman_controller/extconf.rb
38
- - ext/vacman_controller/vacman_controller.c
67
+ - ext/vacman_controller/low_level.c
39
68
  - lib/vacman_controller.rb
40
- homepage: http://github.com/ifad/vacman_controller
69
+ - lib/vacman_controller/error.rb
70
+ - lib/vacman_controller/kernel.rb
71
+ - lib/vacman_controller/token.rb
72
+ - lib/vacman_controller/token/properties.rb
73
+ homepage: https://github.com/ifad/vacman_controller
41
74
  licenses: []
42
75
  metadata: {}
43
76
  post_install_message:
@@ -56,8 +89,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
56
89
  version: '0'
57
90
  requirements: []
58
91
  rubyforge_project:
59
- rubygems_version: 2.5.2.1
92
+ rubygems_version: 2.7.6
60
93
  signing_key:
61
94
  specification_version: 4
62
- summary: Access to the vacman controller library
95
+ summary: Ruby layer to access VASCO Vacman Controller functions
63
96
  test_files: []