cztop 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2d264ee06de06bac407c3d7e06c7e70c140ccb22
4
- data.tar.gz: 078a0a7b26a80c8d43e94e5d606acc3772599369
3
+ metadata.gz: d8c82a0f35f091e2d464beabb00adaf5ad0f0b35
4
+ data.tar.gz: aa92e0a78ca5ca7dcc00441d16e004085024a60a
5
5
  SHA512:
6
- metadata.gz: b3baaa8210899a4c87e39731bc9273e77745758057bebc1e01abad0872f3b0c088466a195f8c1ee92401f98571fbb8c1805c9f8e2c017d3abeadc2a88fe54d92
7
- data.tar.gz: 39179480f025cc1d7c36cf5cd394f8dfb4be3a0a3d178463a136fc2e8d287ff696f37ad39a2423cdb35681a7d171a671a9bc9b5b751f3e11667182f892a7cd75
6
+ metadata.gz: 792e7990a6451bd7f02b638e02c782c95c9d54cbc009aa371de33234ed84b06d88737f830406363e96b44425f643c051948a57aa81719e9059627c48252a308b
7
+ data.tar.gz: 1af4724a36e2959e1e94f552c9289e51f98aa5565df5bb6c14cc8a99130401fd4713fa3f75090e2dcdc9cc466521d7e2a51bea756df20d34a10767767d3822d8
data/CHANGES.md CHANGED
@@ -1,3 +1,9 @@
1
+ 0.9.0 (10/20/2016)
2
+ -----
3
+ * add CertStore interface to zcertstore
4
+ * add ability to pass an existing CertStore to Authenticator
5
+ * add ZAP Request/Response classes (useful for testing)
6
+
1
7
  0.8.0 (09/25/2016)
2
8
  -----
3
9
  * update dependency of czmq-ffi-gen to "~> 0.10.0"
data/README.md CHANGED
@@ -97,6 +97,7 @@ Here's an overview of the core classes:
97
97
  * [Z85](http://www.rubydoc.info/gems/cztop/CZTop/Z85)
98
98
  * [Padded](http://www.rubydoc.info/gems/cztop/CZTop/Z85/Padded) < Z85
99
99
  * [Pipe](http://www.rubydoc.info/gems/cztop/CZTop/Z85/Pipe)
100
+ * [ZAP](http://www.rubydoc.info/gems/cztop/CZTop/ZAP)
100
101
 
101
102
  More information in the [API documentation](http://www.rubydoc.info/github/paddor/cztop).
102
103
 
@@ -18,8 +18,18 @@ module CZTop
18
18
  # This installs authentication on all {Socket}s and {Actor}s. Until you
19
19
  # add policies, all incoming _NULL_ connections are allowed,
20
20
  # and all _PLAIN_ and _CURVE_ connections are denied.
21
- def initialize
22
- @actor = Actor.new(ZAUTH_FPTR)
21
+ #
22
+ # @param cert_store [CertStore] a custom certificate store
23
+ # @note If you pass a {CertStore}, its native object will be owned by the
24
+ # actor (and freed by it when the actor terminates). That means you MUST
25
+ # disale auto free in the CertStore object.
26
+ def initialize(cert_store = nil)
27
+ if cert_store
28
+ raise ArgumentError unless cert_store.is_a?(CertStore)
29
+ cert_store = cert_store.ffi_delegate
30
+ cert_store.__undef_finalizer # native object is now owned by zauth() actor
31
+ end
32
+ @actor = Actor.new(ZAUTH_FPTR, cert_store)
23
33
  end
24
34
 
25
35
  # @return [Actor] the actor behind this authenticator
@@ -72,17 +82,17 @@ module CZTop
72
82
  @actor.wait
73
83
  end
74
84
 
75
- ANY_CERTIFICATE = "*"
85
+ # used to allow any CURVE client
86
+ ALLOW_ANY = "*"
76
87
 
77
88
  # Configure CURVE authentication, using a directory that holds all public
78
89
  # client certificates, i.e. their public keys. The certificates must have been
79
90
  # created using {Certificate#save}/{Certificate#save_public}. You can add
80
91
  # and remove certificates in that directory at any time.
81
92
  #
82
- # @param directory [String] the directory to take the keys from (the
83
- # default value will allow any certificate)
93
+ # @param directory [String] the directory to take the keys from
84
94
  # @return [void]
85
- def curve(directory = ANY_CERTIFICATE)
95
+ def curve(directory = ALLOW_ANY)
86
96
  @actor << ["CURVE", directory]
87
97
  @actor.wait
88
98
  end
@@ -0,0 +1,42 @@
1
+ module CZTop
2
+
3
+ # A store for CURVE security certificates, either backed by files on disk or
4
+ # in-memory.
5
+ #
6
+ # @see http://api.zeromq.org/czmq3-0:zcertstore
7
+ class CertStore
8
+ include ::CZMQ::FFI
9
+ include HasFFIDelegate
10
+ extend CZTop::HasFFIDelegate::ClassMethods
11
+
12
+ # Initializes a new certificate store.
13
+ #
14
+ # @param location [String, #to_s, nil] location the path to the
15
+ # directories to load certificates from, or nil if no certificates need
16
+ # to be loaded from the disk
17
+ def initialize(location = nil)
18
+ location = location.to_s if location
19
+ attach_ffi_delegate(Zcertstore.new(location))
20
+ end
21
+
22
+ # Looks up a certificate in the store by its public key.
23
+ #
24
+ # @param pubkey [String] the public key in question, in Z85 format
25
+ # @return [Certificate] the matching certificate, if found
26
+ # @return [nil] if no matching certificate was found
27
+ def lookup(pubkey)
28
+ ptr = ffi_delegate.lookup(pubkey)
29
+ return nil if ptr.null?
30
+ Certificate.from_ffi_delegate(ptr)
31
+ end
32
+
33
+ # Inserts a new certificate into the store.
34
+ #
35
+ # @param cert [Certificate] the certificate to insert
36
+ # @return [void]
37
+ def insert(cert)
38
+ raise ArgumentError unless cert.is_a?(Certificate)
39
+ ffi_delegate.insert(cert.ffi_delegate)
40
+ end
41
+ end
42
+ end
data/lib/cztop/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module CZTop
2
- VERSION = "0.8.0"
2
+ VERSION = "0.9.0"
3
3
  end
data/lib/cztop/zap.rb ADDED
@@ -0,0 +1,234 @@
1
+ module CZTop
2
+ # This module provides two classes useful when implementing your own ZAP
3
+ # authentication handler or when directly communicating with one. Within
4
+ # CZTop, it's merely used for testing.
5
+ #
6
+ # Some of the features:
7
+ # * useful for both sides of the ZAP communication, i.e. useful for testing
8
+ # * security mechanism agnostic
9
+ # * protocol errors, version mismatches, and internal errors as exceptions
10
+ # * useful to implement your own ZAP handler
11
+ #
12
+ # @note This is not needed to be able to use {CZTop::Authenticator}!
13
+ # @see https://rfc.zeromq.org/spec:27/ZAP
14
+ module ZAP
15
+ # the endpoint a ZAP authenticator has bound to
16
+ ENDPOINT = "inproc://zeromq.zap.01"
17
+
18
+ # the ZAP version supported by this code
19
+ VERSION = "1.0"
20
+
21
+ # superclass for ZAP errors
22
+ class Error < StandardError
23
+ end
24
+
25
+ # used when the response contains an unsupported version
26
+ class VersionMismatch < Error
27
+ end
28
+
29
+ # security mechanisms mentioned in ZeroMQ RFC 27.
30
+ module Mechanisms
31
+ NULL = "NULL"
32
+ PLAIN = "PLAIN"
33
+ CURVE = "CURVE"
34
+ end
35
+
36
+ # Represents a ZAP request.
37
+ class Request
38
+ # Crafts a new {Request} from a message.
39
+ #
40
+ # @param msg [CZTop::message] the message
41
+ # @return [Request] the request
42
+ # @raise [VersionMismatch] if the message contains an unsupported version
43
+ def self.from_message(msg)
44
+ version, # The version frame, which SHALL contain the three octets "1.0".
45
+ request_id, # The request id, which MAY contain an opaque binary blob.
46
+ domain, # The domain, which SHALL contain a string.
47
+ address, # The address, the origin network IP address.
48
+ identity, # The identity, the connection Identity, if any.
49
+ mechanism, # The mechanism, which SHALL contain a string.
50
+ *credentials = # The credentials, which SHALL be zero or more opaque frames.
51
+ msg.to_a
52
+
53
+ raise VersionMismatch if version != VERSION
54
+
55
+ new(domain, credentials, mechanism: mechanism).tap do |r|
56
+ r.version = version
57
+ r.request_id = request_id
58
+ r.address = address
59
+ r.identity = identity
60
+ end
61
+ end
62
+
63
+ # @return [String] ZAP version
64
+ attr_accessor :version
65
+
66
+ # @return [String, #to_s] the authentication domain
67
+ attr_accessor :domain
68
+
69
+ # @return [Array<String, #to_s>] the credentials, 0 or more
70
+ attr_accessor :credentials
71
+
72
+ # @return [String, #to_s]
73
+ attr_accessor :request_id
74
+
75
+ # @return [String, #to_s]
76
+ attr_accessor :address
77
+
78
+ # @return [String, #to_s] the connection identity
79
+ attr_accessor :identity
80
+
81
+ # @see Mechanisms
82
+ # @return [String, #to_s] the security mechanism to be used
83
+ attr_accessor :mechanism
84
+
85
+ # Initializes a new ZAP request. The security mechanism is set to
86
+ # CURVE (can be changed later).
87
+ #
88
+ # @param domain [String] the domain within to authenticate
89
+ # @param credentials [Array<String>] the credentials of the user,
90
+ # depending on the security mechanism used
91
+ def initialize(domain, credentials = [], mechanism: Mechanisms::CURVE)
92
+ @domain = domain
93
+ @credentials = credentials
94
+ @mechanism = mechanism
95
+ @version = VERSION
96
+ end
97
+
98
+ # Creates a sendable message from this {Request}.
99
+ # @return [CZTop::Message} this request packed into a message
100
+ def to_msg
101
+ fields = [ @version, @request_id, @domain, @address,
102
+ @identity, @mechanism, @credentials].flatten.map(&:to_s)
103
+
104
+ CZTop::Message.new(fields)
105
+ end
106
+ end
107
+
108
+ # Represents a ZAP response.
109
+ class Response
110
+
111
+ # used to indicate a temporary error
112
+ class TemporaryError < Error
113
+ end
114
+
115
+ # used to indicate an internal error of the authenticator
116
+ class InternalError < Error
117
+ end
118
+
119
+ # Status codes of ZAP responses.
120
+ module StatusCodes
121
+ SUCCESS = "200"
122
+ TEMPORARY_ERROR = "300"
123
+ AUTHENTICATION_FAILURE = "400"
124
+ INTERNAL_ERROR = "500"
125
+
126
+ ALL = [
127
+ SUCCESS,
128
+ TEMPORARY_ERROR,
129
+ AUTHENTICATION_FAILURE,
130
+ INTERNAL_ERROR
131
+ ]
132
+ end
133
+
134
+ include StatusCodes
135
+
136
+ # Crafts a new {Response} from a message.
137
+ #
138
+ # @param msg [CZTop::message] the message
139
+ # @return [Response] the response
140
+ # @raise [VersionMismatch] if the message contains an unsupported version
141
+ # @raise [TemporaryError] if the status code indicates a temporary error
142
+ # @raise [InternalError] if the status code indicates an internal error,
143
+ # or the status code is invalid
144
+ def self.from_message(msg)
145
+ version, # The version frame, which SHALL contain the three octets "1.0".
146
+ request_id, # The request id, which MAY contain an opaque binary blob.
147
+ status_code, # The status code, which SHALL contain a string.
148
+ status_text, # The status text, which MAY contain a string.
149
+ user_id, # The user id, which SHALL contain a string.
150
+ meta_data = # The meta data, which MAY contain a blob.
151
+ msg.to_a
152
+
153
+ raise VersionMismatch if version != VERSION
154
+
155
+ case status_code
156
+ when SUCCESS, AUTHENTICATION_FAILURE
157
+ # valid codes, nothing to do
158
+ when TEMPORARY_ERROR
159
+ raise TemporaryError, status_text
160
+ when INTERNAL_ERROR
161
+ raise InternalError, status_text
162
+ else
163
+ raise InternalError, "invalid status code"
164
+ end
165
+
166
+ new(status_code).tap do |r|
167
+ r.version = version
168
+ r.request_id = request_id
169
+ r.status_code = status_code
170
+ r.status_text = status_text
171
+ r.user_id = user_id
172
+ r.meta_data = meta_data
173
+ end
174
+ end
175
+
176
+ # @return [String] ZAP version
177
+ attr_accessor :version
178
+
179
+ # @return [String] the original request ID
180
+ attr_accessor :request_id
181
+
182
+ # @return [String] status code
183
+ # @see StatusCodes
184
+ attr_accessor :status_code
185
+
186
+ # @return [String] status explanation
187
+ attr_accessor :status_text
188
+
189
+ # @return [String] meta data in ZMTP 3.0 format
190
+ attr_writer :meta_data
191
+
192
+ # @return [String] the user ID
193
+ attr_writer :user_id
194
+
195
+ # Initializes a new response.
196
+ #
197
+ # @param status_code [String, #to_s] ZAP status code
198
+ def initialize(status_code)
199
+ @status_code = status_code.to_s
200
+ raise ArgumentError unless ALL.include?(@status_code)
201
+ @version = VERSION
202
+ end
203
+
204
+ # @return [Boolean] whether the authentication was successful
205
+ def success?
206
+ @status_code == SUCCESS
207
+ end
208
+
209
+ # Returns the user ID, if authentication was successful.
210
+ # @return [String] the user ID of the authenticated user
211
+ # @return [nil] if authentication was unsuccessful
212
+ def user_id
213
+ return nil unless success?
214
+ @user_id
215
+ end
216
+
217
+ # Returns the meta data, if authentication was successful.
218
+ # @return [String] the meta data for the authenticated user
219
+ # @return [nil] if authentication was unsuccessful
220
+ def meta_data
221
+ return nil unless success?
222
+ @meta_data
223
+ end
224
+
225
+ # Creates a sendable message from this {Response}.
226
+ # @return [CZTop::Message} this request packed into a message
227
+ def to_msg
228
+ fields = [@version, @request_id, @status_code,
229
+ @status_text, @user_id, @meta_data].map(&:to_s)
230
+ CZTop::Message.new(fields)
231
+ end
232
+ end
233
+ end
234
+ end
@@ -64,7 +64,7 @@ module CZTop
64
64
 
65
65
  # @!endgroup
66
66
 
67
- # @!group (CURVE) Security
67
+ # @!group Security Mechanisms
68
68
 
69
69
  # @return [Boolean] whether this zocket is a CURVE server
70
70
  def CURVE_server?() Zsock.curve_server(@zocket) > 0 end
data/lib/cztop.rb CHANGED
@@ -16,6 +16,7 @@ require_relative 'cztop/actor'
16
16
  require_relative 'cztop/authenticator'
17
17
  require_relative 'cztop/beacon'
18
18
  require_relative 'cztop/certificate'
19
+ require_relative 'cztop/cert_store'
19
20
  require_relative 'cztop/config'
20
21
  require_relative 'cztop/frame'
21
22
  require_relative 'cztop/message'
@@ -33,6 +34,7 @@ require_relative 'cztop/message/frames'
33
34
  require_relative 'cztop/socket/types'
34
35
  require_relative 'cztop/z85/padded'
35
36
  require_relative 'cztop/z85/pipe'
37
+ require_relative 'cztop/zap'
36
38
 
37
39
 
38
40
  # make Ctrl-C work in case a low-level call hangs
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cztop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrik Wenger
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-09-25 00:00:00.000000000 Z
11
+ date: 2016-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: czmq-ffi-gen
@@ -251,6 +251,7 @@ files:
251
251
  - lib/cztop/actor.rb
252
252
  - lib/cztop/authenticator.rb
253
253
  - lib/cztop/beacon.rb
254
+ - lib/cztop/cert_store.rb
254
255
  - lib/cztop/certificate.rb
255
256
  - lib/cztop/config.rb
256
257
  - lib/cztop/config/comments.rb
@@ -271,6 +272,7 @@ files:
271
272
  - lib/cztop/z85.rb
272
273
  - lib/cztop/z85/padded.rb
273
274
  - lib/cztop/z85/pipe.rb
275
+ - lib/cztop/zap.rb
274
276
  - lib/cztop/zsock_options.rb
275
277
  - perf/README.md
276
278
  - perf/inproc_lat.rb