tanker-core 2.4.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 57f44d6be8d76f8ff69da88a526b3c8c072f4e808e47a285a87ed55f2e875b59
4
+ data.tar.gz: e516030ca9398dc735fd7761a35cad49c48d9b21a9e17e552868d723eb822baf
5
+ SHA512:
6
+ metadata.gz: 1750b63a90e38b18cc85640e04e6eb6393c7cf199b29cb05f6d4d90c7df2d5ac07c0b061be2361079d49f1aab0f9bdf8e450936f1a0c883134d7c8274a2a9e30
7
+ data.tar.gz: a030e6c1572f5c9afa10132e19bbb43f9f80ab7f040a19ab6e10ceaa1256b760ee4fd7c434bfe48b932b0ddda1294979e4725215befe68068bff9eada75a90a0
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2020 Kontrol SAS
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,30 @@
1
+ .. image:: https://img.shields.io/badge/License-Apache%202.0-blue.svg
2
+ :target: https://opensource.org/licenses/Apache-2.0
3
+
4
+ Tanker Ruby SDK
5
+ =================
6
+
7
+ Overview
8
+ --------
9
+
10
+ The `Tanker SDK <https://tanker.io>`_ provides an easy-to-use SDK allowing you to protect your users'
11
+ data.
12
+
13
+ This repository only contains Ruby bindings. The core library can be found in the `TankerHQ/sdk-native GitHub project <https://github.com/TankerHQ/sdk-native>`_.
14
+
15
+ Contributing
16
+ ------------
17
+
18
+ We are actively working to allow external developers to build and test this project
19
+ from source. That being said, we welcome feedback of any kind. Feel free to
20
+ open issues on the GitHub bug tracker.
21
+
22
+ Running the tests: `bundle exec rake spec`
23
+
24
+ Checking vulnerabilities in the dependencies: `bundle exec bundle-audit check --update`
25
+
26
+ Documentation
27
+ -------------
28
+
29
+ See the `API documentation <https://tankerhq.github.io/sdk-ruby>`_.
30
+
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'tanker/core'
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+ require_relative 'admin/c_admin'
5
+ require_relative 'admin/c_admin/c_app_descriptor'
6
+ require_relative 'admin/app'
7
+
8
+ module Tanker
9
+ class Admin
10
+ def initialize(admin_url, id_token, api_url)
11
+ @admin_url = admin_url
12
+ @id_token = id_token
13
+ @api_url = api_url
14
+ end
15
+
16
+ # Authenticate to the Tanker admin server API
17
+ # This must be called before doing any other operation
18
+ def connect
19
+ @cadmin = CAdmin.tanker_admin_connect(@admin_url, @id_token).get
20
+ cadmin_addr = @cadmin.address
21
+ ObjectSpace.define_finalizer(@cadmin) do |_|
22
+ CAdmin.tanker_admin_destroy(FFI::Pointer.new(:void, cadmin_addr)).get
23
+ end
24
+ end
25
+
26
+ def create_app(name)
27
+ assert_connected
28
+ descriptor_ptr = CAdmin.tanker_admin_create_app(@cadmin, name).get
29
+ descriptor = CAdmin::CAppDescriptor.new(descriptor_ptr)
30
+ App.new(@api_url, descriptor[:id], descriptor[:auth_token], descriptor[:private_key])
31
+ end
32
+
33
+ def delete_app(app_id)
34
+ assert_connected
35
+ CAdmin.tanker_admin_delete_app(@cadmin, app_id).get
36
+ end
37
+
38
+ def app_update(app_id, oidc_client_id, oidc_client_provider)
39
+ assert_connected
40
+ CAdmin.tanker_admin_app_update(@cadmin, app_id, oidc_client_id, oidc_client_provider).get
41
+ end
42
+
43
+ private
44
+
45
+ def assert_connected
46
+ raise 'You need to connect() before using the admin API!' if @cadmin.nil?
47
+ end
48
+ end
49
+
50
+ private_constant :Admin
51
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tanker
4
+ class Admin
5
+ # Information from the Admin SDK concerning a Tanker application
6
+ class App
7
+ attr_reader :url, :id, :auth_token, :private_key
8
+
9
+ def initialize(url, id, auth_token, private_key)
10
+ @url = url
11
+ @id = id
12
+ @auth_token = auth_token
13
+ @private_key = private_key
14
+ end
15
+
16
+ def get_verification_code(email)
17
+ CAdmin.tanker_get_verification_code(@url, @id, @auth_token, email).get_string
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+ require 'tanker/c_tanker/c_future'
5
+
6
+ module Tanker
7
+ class Admin
8
+ module CAdmin
9
+ extend FFI::Library
10
+
11
+ ffi_lib "#{__dir__}/../../../vendor/libctanker/linux64/tanker/lib/libtanker_admin-c.so"
12
+
13
+ typedef :pointer, :admin_pointer
14
+
15
+ # Note: We use those CFutures with the tanker_future_* functions exposed by CTanker,
16
+ # this is safe because we only do simple synchronous blocking calls, without using tanker_future_then.
17
+
18
+ attach_function :tanker_admin_connect, [:string, :string], CTanker::CFuture
19
+ attach_function :tanker_admin_create_app, [:admin_pointer, :string], CTanker::CFuture
20
+ attach_function :tanker_admin_delete_app, [:admin_pointer, :string], CTanker::CFuture
21
+ attach_function :tanker_admin_destroy, [:admin_pointer], CTanker::CFuture
22
+ attach_function :tanker_admin_app_descriptor_free, [:pointer], :void
23
+ attach_function :tanker_admin_app_update, [:admin_pointer, :string, :string, :string], CTanker::CFuture
24
+ attach_function :tanker_get_verification_code, [:string, :string, :string, :string], CTanker::CFuture
25
+ end
26
+
27
+ private_constant :CAdmin
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+
5
+ module Tanker
6
+ class Admin
7
+ class CAdmin::CAppDescriptor < FFI::ManagedStruct
8
+ layout :name, :string,
9
+ :id, :string,
10
+ :auth_token, :string,
11
+ :private_key, :string,
12
+ :public_key, :string
13
+
14
+ def get_verification_code(email)
15
+ CTanker.tanker_get_verification_code(email).get
16
+ end
17
+
18
+ def self.release(ptr)
19
+ CAdmin.tanker_admin_app_descriptor_free ptr
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+ require_relative 'core/options'
5
+ require_relative 'sharing_options'
6
+ require_relative 'c_tanker/c_future'
7
+ require_relative 'c_tanker/c_verification'
8
+ require_relative 'c_tanker/c_verification_method'
9
+ require_relative 'c_tanker/c_log_record'
10
+ require_relative 'c_tanker/c_event'
11
+ require_relative 'c_tanker/c_device_info'
12
+
13
+ module FFI::Library
14
+ # Marking a function blocking releases the global Ruby lock.
15
+ # This is required for every function that could invoke a callback (including log handler) in another thread
16
+ def blocking_attach_function(func, args, returns = nil)
17
+ attach_function func, args, returns, blocking: true
18
+ end
19
+ end
20
+
21
+ module Tanker
22
+ module CTanker
23
+ extend FFI::Library
24
+
25
+ ffi_lib "#{__dir__}/../../vendor/libctanker/linux64/tanker/lib/libctanker.so"
26
+
27
+ typedef :pointer, :session_pointer
28
+ typedef :pointer, :enc_sess_pointer
29
+ typedef :pointer, :stream_pointer
30
+ typedef :pointer, :read_operation_pointer
31
+
32
+ callback :log_handler_callback, [CLogRecord.by_ref], :void
33
+ callback :event_callback, [:pointer], :void
34
+ callback :stream_input_source_callback, [:pointer, :int64, :read_operation_pointer, :pointer], :void
35
+
36
+ blocking_attach_function :tanker_init, [], :void
37
+ blocking_attach_function :tanker_version_string, [], :string
38
+ blocking_attach_function :tanker_create, [Tanker::Core::Options], CFuture
39
+ blocking_attach_function :tanker_destroy, [:session_pointer], CFuture
40
+ blocking_attach_function :tanker_start, [:session_pointer, :string], CFuture
41
+ blocking_attach_function :tanker_register_identity, [:session_pointer, CVerification], CFuture
42
+ blocking_attach_function :tanker_verify_identity, [:session_pointer, CVerification], CFuture
43
+ blocking_attach_function :tanker_get_verification_methods, [:session_pointer], CFuture
44
+ blocking_attach_function :tanker_set_verification_method, [:session_pointer, CVerification], CFuture
45
+ blocking_attach_function :tanker_stop, [:session_pointer], CFuture
46
+ blocking_attach_function :tanker_status, [:session_pointer], :uint32
47
+ blocking_attach_function :tanker_generate_verification_key, [:session_pointer], CFuture
48
+ blocking_attach_function :tanker_device_id, [:session_pointer], CFuture
49
+ blocking_attach_function :tanker_revoke_device, [:session_pointer, :string], CFuture
50
+ blocking_attach_function :tanker_get_device_list, [:session_pointer], CFuture
51
+
52
+ blocking_attach_function :tanker_attach_provisional_identity, [:session_pointer, :string], CFuture
53
+ blocking_attach_function :tanker_verify_provisional_identity, [:session_pointer, CVerification], CFuture
54
+
55
+ blocking_attach_function :tanker_encrypted_size, [:uint64], :uint64
56
+ blocking_attach_function :tanker_decrypted_size, [:pointer, :uint64], CFuture
57
+ blocking_attach_function :tanker_get_resource_id, [:pointer, :uint64], CFuture
58
+
59
+ blocking_attach_function :tanker_encrypt, [:session_pointer, :pointer, :pointer, :uint64,
60
+ Tanker::EncryptionOptions], CFuture
61
+ blocking_attach_function :tanker_decrypt, [:session_pointer, :pointer, :pointer, :uint64], CFuture
62
+ blocking_attach_function :tanker_share, [:session_pointer, :pointer, :uint64, :pointer, :uint64,
63
+ :pointer, :uint64], CFuture
64
+
65
+ blocking_attach_function :tanker_future_wait, [CFuture], :void
66
+ blocking_attach_function :tanker_future_has_error, [CFuture], :bool
67
+ blocking_attach_function :tanker_future_get_error, [CFuture], CTankerError.by_ref
68
+ blocking_attach_function :tanker_future_get_voidptr, [CFuture], :pointer
69
+ blocking_attach_function :tanker_future_destroy, [CFuture], :void
70
+
71
+ blocking_attach_function :tanker_create_group, [:session_pointer, :pointer, :uint64], CFuture
72
+ blocking_attach_function :tanker_update_group_members, [:session_pointer, :string,
73
+ :pointer, :uint64], CFuture
74
+
75
+ blocking_attach_function :tanker_encryption_session_open, [:session_pointer, :pointer, :uint64,
76
+ :pointer, :uint64], CFuture
77
+ blocking_attach_function :tanker_encryption_session_close, [:enc_sess_pointer], CFuture
78
+ blocking_attach_function :tanker_encryption_session_encrypted_size, [:uint64], :uint64
79
+ blocking_attach_function :tanker_encryption_session_get_resource_id, [:enc_sess_pointer], CFuture
80
+ blocking_attach_function :tanker_encryption_session_encrypt, [:enc_sess_pointer, :pointer,
81
+ :pointer, :uint64], CFuture
82
+ blocking_attach_function :tanker_encryption_session_stream_encrypt, [:enc_sess_pointer,
83
+ :stream_input_source_callback, :pointer],
84
+ CFuture
85
+
86
+ blocking_attach_function :tanker_stream_encrypt, [:session_pointer, :stream_input_source_callback,
87
+ :pointer, Tanker::EncryptionOptions], CFuture
88
+ blocking_attach_function :tanker_stream_decrypt, [:session_pointer, :stream_input_source_callback,
89
+ :pointer], CFuture
90
+ blocking_attach_function :tanker_stream_read_operation_finish, [:read_operation_pointer, :int64], :void
91
+ blocking_attach_function :tanker_stream_read, [:stream_pointer, :pointer, :int64], CFuture
92
+
93
+ blocking_attach_function :tanker_stream_get_resource_id, [:stream_pointer], CFuture
94
+ blocking_attach_function :tanker_stream_close, [:stream_pointer], CFuture
95
+
96
+ blocking_attach_function :tanker_set_log_handler, [:log_handler_callback], :void
97
+ blocking_attach_function :tanker_event_connect, [:session_pointer, :uint32, :event_callback, :pointer], CFuture
98
+
99
+ blocking_attach_function :tanker_prehash_password, [:string], CFuture
100
+
101
+ blocking_attach_function :tanker_free_buffer, [:pointer], :void
102
+ blocking_attach_function :tanker_free_verification_method_list, [:pointer], :void
103
+ blocking_attach_function :tanker_free_device_list, [:pointer], :void
104
+ end
105
+
106
+ private_constant :CTanker
107
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+
5
+ module Tanker
6
+ module CTanker
7
+ class CDeviceInfo < FFI::Struct
8
+ layout :device_id, :string,
9
+ :is_revoked, :bool
10
+
11
+ attr_reader :device_id
12
+
13
+ def initialize(pointer)
14
+ super pointer
15
+ @device_id = self[:device_id]
16
+ @is_revoked = self[:is_revoked]
17
+ end
18
+
19
+ def revoked?
20
+ @is_revoked
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+
5
+ module Tanker::CTanker
6
+ # Tanker events for which handlers can be attached
7
+ module CTankerEvent
8
+ SESSION_CLOSED = 0
9
+ DEVICE_REVOKED = 1
10
+ end
11
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+ require 'tanker/error'
5
+ require_relative 'c_tanker_error'
6
+
7
+ module Tanker
8
+ module CTanker
9
+ extend FFI::Library
10
+
11
+ ffi_lib "#{__dir__}/../../../vendor/libctanker/linux64/tanker/lib/libctanker.so"
12
+
13
+ class CFuture < FFI::AutoPointer
14
+ def initialize(ptr, proc = nil, &block)
15
+ super
16
+ @cfuture = ptr
17
+ end
18
+
19
+ def self.release(ptr)
20
+ CTanker.tanker_future_destroy ptr
21
+ end
22
+
23
+ def get
24
+ CTanker.tanker_future_wait @cfuture
25
+ if CTanker.tanker_future_has_error @cfuture
26
+ cerr = CTanker.tanker_future_get_error @cfuture
27
+ raise Error, cerr
28
+ else
29
+ CTanker.tanker_future_get_voidptr @cfuture
30
+ end
31
+ end
32
+
33
+ def get_string # rubocop:disable Naming/AccessorMethodName (this is not a getter)
34
+ str_ptr = get
35
+ str = str_ptr.get_string(0).force_encoding(Encoding::UTF_8)
36
+ CTanker.tanker_free_buffer str_ptr
37
+ str
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+
5
+ # Log record of the log handler callback
6
+ class CLogRecord < FFI::Struct
7
+ layout :category, :string,
8
+ :level, :uint32,
9
+ :file, :string,
10
+ :line, :uint32,
11
+ :message, :string
12
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+
5
+ module Tanker::CTanker
6
+ # Fun fact: Strings in structs with the FFI lib are read-only,
7
+ # you can't just assign a string literal to a cstring.
8
+ # They'd rather not handle allocations transparently (lifetimes are tricky),
9
+ # so we have to take care of allocations and lifetimes ourselves.
10
+ def self.new_cstring(str_or_nil, manual = false)
11
+ return nil if str_or_nil.nil?
12
+
13
+ cstr = FFI::MemoryPointer.from_string(str_or_nil)
14
+ cstr.autorelease = !manual
15
+ cstr
16
+ end
17
+
18
+ def self.new_cstring_array(strings)
19
+ cstrings = FFI::MemoryPointer.new(:pointer, strings.length)
20
+ cstrings.write_array_of_pointer(strings.map { |id| new_cstring id })
21
+ cstrings
22
+ end
23
+
24
+ def self.free_manual_cstring(cstr_or_nil)
25
+ cstr_or_nil&.free
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+
5
+ module Tanker::CTanker
6
+ # Errors returned by native tanker futures
7
+ class CTankerError < FFI::Struct
8
+ layout :error_code, :int,
9
+ :error_message, :string
10
+ end
11
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+ require 'tanker/core/verification'
5
+ require 'tanker/c_tanker/c_string'
6
+
7
+ module Tanker
8
+ module CTanker
9
+ class CEmailVerification < FFI::Struct
10
+ layout :version, :uint8,
11
+ :email, :pointer,
12
+ :verification_code, :pointer
13
+
14
+ def initialize(email, verification_code)
15
+ # Note: Instance variables are required to keep the CStrings alive
16
+ @email = CTanker.new_cstring email
17
+ @verification_code = CTanker.new_cstring verification_code
18
+
19
+ self[:version] = 1
20
+ self[:email] = @email
21
+ self[:verification_code] = @verification_code
22
+ end
23
+ end
24
+
25
+ class CVerification < FFI::Struct
26
+ layout :version, :uint8,
27
+ :type, :uint8,
28
+ :verification_key, :pointer,
29
+ :email_verification, CEmailVerification,
30
+ :passphrase, :pointer,
31
+ :oidc_id_token, :pointer
32
+
33
+ TYPE_EMAIL = 1
34
+ TYPE_PASSPHRASE = 2
35
+ TYPE_VERIFICATION_KEY = 3
36
+ TYPE_OIDC_ID_TOKEN = 4
37
+
38
+ def initialize(verification)
39
+ unless verification.is_a? Tanker::Verification
40
+ raise TypeError, 'Verification argument is not a Tanker::Verification'
41
+ end
42
+
43
+ # Note: Instance variables are required to keep the CStrings alive
44
+ case verification
45
+ when Tanker::EmailVerification
46
+ self[:type] = TYPE_EMAIL
47
+ self[:email_verification] = CEmailVerification.new verification.email, verification.verification_code
48
+ when Tanker::PassphraseVerification
49
+ @passphrase = CTanker.new_cstring verification.passphrase
50
+ self[:type] = TYPE_PASSPHRASE
51
+ self[:passphrase] = @passphrase
52
+ when Tanker::VerificationKeyVerification
53
+ @verification_key = CTanker.new_cstring verification.verification_key
54
+ self[:type] = TYPE_VERIFICATION_KEY
55
+ self[:verification_key] = @verification_key
56
+ when Tanker::OIDCIDTokenVerification
57
+ @oidc_id_token = CTanker.new_cstring verification.oidc_id_token
58
+ self[:type] = TYPE_OIDC_ID_TOKEN
59
+ self[:oidc_id_token] = @oidc_id_token
60
+ else
61
+ raise ArgumentError, 'Unknown Tanker::Verification type!'
62
+ end
63
+
64
+ self[:version] = 3
65
+ end
66
+ end
67
+ end
68
+ end