nokogiri-xmlsec-instructure 0.9.4 → 0.10.1

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
  SHA256:
3
- metadata.gz: ed59b79032290908cffa12a20deb7b0d5c2195e45a817e430d49bfc404243bee
4
- data.tar.gz: b315b63fe30ab7760719bce3e435b36c3565b658eb0ac42d1fb6d6f48c65b974
3
+ metadata.gz: 72eea7707ea8c4d24e0cb82afc804752be0313d810554ca54f4ea9e4a3f857e9
4
+ data.tar.gz: 4641d782e76a25aa3f251ff160f04d66198a1c2c3a4020f625dc29f7bbe5e365
5
5
  SHA512:
6
- metadata.gz: 660d2ff3242177e1e6fd09112afed32ae5507d331c3c2fedd7c920a75cf09b58115ca14d3915fa76297ee7879594b314caacef967b5b90903d3fd1b9b36a4aff
7
- data.tar.gz: d96e85677b8f9c34b3df00ae1d878d1de8c8f69d7ed5d78f76a680a504e8afcee4d55c398ccdc6e766a773a1bb45466bbe507985930839c4591dd2c452d8153d
6
+ metadata.gz: f116055729f4a0bddbee6432c99e9f505aad12a45452121d4fb14414de8eaf613009db60d28d55a7e7c8b7c5678e67e7d3a297741186f4e9eabcf4d08b88385c
7
+ data.tar.gz: d73b7b9d8ff63621b3162b4d83dfcf8ffd52b253d589fc863ef44d47847801e23ad8a386b4459a933431c5eaef0e377051089e8c4af06cde05522e3d390f4ae3
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
1
  *.gem
2
2
  *.rbc
3
3
  .bundle
4
+ .byebug_history
4
5
  .config
5
6
  .yardoc
6
7
  Gemfile.lock
@@ -9,6 +10,7 @@ _yardoc
9
10
  coverage
10
11
  doc/
11
12
  lib/bundler/man
13
+ lib/nokogiri_ext_xmlsec.bundle
12
14
  pkg
13
15
  rdoc
14
16
  spec/reports
data/README.md CHANGED
@@ -10,6 +10,14 @@ to `Nokogiri::XML::Document`.
10
10
 
11
11
  ## Installation
12
12
 
13
+ Install this before attempting to install; or else it may fail (tested on CentOS 7) while trying to find -lltdl from the xmlsec1-openssl lib. I'm guessing it's a dependency. Someone else may know more.
14
+
15
+ # CentOS/RHEL
16
+ yum install libtool-ltdl-devel
17
+
18
+ # Debian/Ubuntu
19
+ apt install -y libxmlsec1-dev
20
+
13
21
  Add this line to your application's Gemfile:
14
22
 
15
23
  gem 'nokogiri-xmlsec'
@@ -20,7 +20,6 @@ void Init_nokogiri_ext_xmlsec() {
20
20
  xmlInitParser();
21
21
  LIBXML_TEST_VERSION
22
22
  xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
23
- xmlSubstituteEntitiesDefault(1);
24
23
  // xslt
25
24
 
26
25
  #ifndef XMLSEC_NO_XSLT
@@ -66,10 +65,6 @@ void Init_nokogiri_ext_xmlsec() {
66
65
  rb_raise(rb_eRuntimeError, "xmlsec-crypto initialization failed");
67
66
  }
68
67
 
69
- // Set Error callback catcher last because various modules also call this.
70
- // This way we always win.
71
- xmlSecErrorsSetCallback(storeErrorCallback);
72
-
73
68
  /* ruby classes & objects */
74
69
  Init_Nokogiri_ext();
75
70
  }
@@ -1,6 +1,11 @@
1
1
  #include "xmlsecrb.h"
2
2
  #include "util.h"
3
3
 
4
+ // technically we should include nokogiri.h, but we don't know
5
+ // how to find it. we _know_ this function will exist at runtime
6
+ // though, so just declare it here
7
+ void noko_xml_document_pin_node(xmlNodePtr);
8
+
4
9
  VALUE decrypt_with_key(VALUE self, VALUE rb_key_name, VALUE rb_key) {
5
10
  VALUE rb_exception_result = Qnil;
6
11
  const char* exception_message = NULL;
@@ -58,7 +63,7 @@ done:
58
63
  // the replaced node is orphaned, but not freed; let Nokogiri
59
64
  // own it now
60
65
  if(encCtx->replacedNodeList != NULL) {
61
- nokogiri_root_node(encCtx->replacedNodeList);
66
+ noko_xml_document_pin_node(encCtx->replacedNodeList);
62
67
  // no really, please don't free it
63
68
  encCtx->replacedNodeList = NULL;
64
69
  }
@@ -69,6 +74,8 @@ done:
69
74
  xmlSecKeysMngrDestroy(keyManager);
70
75
  }
71
76
 
77
+ xmlSecErrorsSetCallback(xmlSecErrorsDefaultCallback);
78
+
72
79
  if(rb_exception_result != Qnil) {
73
80
  if (hasXmlSecLastError()) {
74
81
  rb_raise(rb_exception_result, "%s, XmlSec error: %s", exception_message,
@@ -12,9 +12,11 @@
12
12
  VALUE encrypt_with_key(VALUE self, VALUE rb_rsa_key_name, VALUE rb_rsa_key,
13
13
  VALUE rb_opts) {
14
14
  VALUE rb_exception_result = Qnil;
15
+ VALUE rb_cert = Qnil;
15
16
  const char* exception_message = NULL;
16
17
 
17
18
  xmlDocPtr doc = NULL;
19
+ xmlNodePtr node = NULL;
18
20
  xmlNodePtr encDataNode = NULL;
19
21
  xmlNodePtr encKeyNode = NULL;
20
22
  xmlNodePtr keyInfoNode = NULL;
@@ -22,17 +24,28 @@ VALUE encrypt_with_key(VALUE self, VALUE rb_rsa_key_name, VALUE rb_rsa_key,
22
24
  xmlSecKeysMngrPtr keyManager = NULL;
23
25
  char *keyName = NULL;
24
26
  char *key = NULL;
27
+ char *certificate = NULL;
25
28
  unsigned int keyLength = 0;
29
+ unsigned int certificateLength = 0;
26
30
 
27
31
  resetXmlSecError();
28
32
 
29
33
  Check_Type(rb_rsa_key, T_STRING);
30
- Check_Type(rb_rsa_key_name, T_STRING);
31
34
  Check_Type(rb_opts, T_HASH);
32
35
 
33
36
  key = RSTRING_PTR(rb_rsa_key);
34
37
  keyLength = RSTRING_LEN(rb_rsa_key);
35
- keyName = StringValueCStr(rb_rsa_key_name);
38
+ if (rb_rsa_key_name != Qnil) {
39
+ Check_Type(rb_rsa_key_name, T_STRING);
40
+ keyName = StringValueCStr(rb_rsa_key_name);
41
+ }
42
+
43
+ rb_cert = rb_hash_aref(rb_opts, ID2SYM(rb_intern("cert")));
44
+ if (!NIL_P(rb_cert)) {
45
+ Check_Type(rb_cert, T_STRING);
46
+ certificate = RSTRING_PTR(rb_cert);
47
+ certificateLength = RSTRING_LEN(rb_cert);
48
+ }
36
49
 
37
50
  XmlEncOptions options;
38
51
  if (!GetXmlEncOptions(rb_opts, &options, &rb_exception_result,
@@ -40,7 +53,8 @@ VALUE encrypt_with_key(VALUE self, VALUE rb_rsa_key_name, VALUE rb_rsa_key,
40
53
  goto done;
41
54
  }
42
55
 
43
- Data_Get_Struct(self, xmlDoc, doc);
56
+ Data_Get_Struct(self, xmlNode, node);
57
+ doc = node->doc;
44
58
 
45
59
  // create encryption template to encrypt XML file and replace
46
60
  // its content with encryption result
@@ -68,10 +82,21 @@ VALUE encrypt_with_key(VALUE self, VALUE rb_rsa_key_name, VALUE rb_rsa_key,
68
82
  goto done;
69
83
  }
70
84
 
71
- if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) {
72
- rb_exception_result = rb_eEncryptionError;
73
- exception_message = "failed to add key name";
74
- goto done;
85
+ if(certificate) {
86
+ // add <dsig:X509Data/>
87
+ if(xmlSecTmplKeyInfoAddX509Data(keyInfoNode) == NULL) {
88
+ rb_exception_result = rb_eSigningError;
89
+ exception_message = "failed to add X509Data node";
90
+ goto done;
91
+ }
92
+ }
93
+
94
+ if(keyName != NULL) {
95
+ if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) {
96
+ rb_exception_result = rb_eEncryptionError;
97
+ exception_message = "failed to add key name";
98
+ goto done;
99
+ }
75
100
  }
76
101
 
77
102
  if ((keyManager = createKeyManagerWithSingleKey(
@@ -100,11 +125,25 @@ VALUE encrypt_with_key(VALUE self, VALUE rb_rsa_key_name, VALUE rb_rsa_key,
100
125
  goto done;
101
126
  }
102
127
 
128
+ if(certificate) {
129
+ // load certificate and add to the key
130
+ if(xmlSecCryptoAppKeyCertLoadMemory(encCtx->encKey,
131
+ (xmlSecByte *)certificate,
132
+ certificateLength,
133
+ xmlSecKeyDataFormatPem) < 0) {
134
+ rb_exception_result = rb_eSigningError;
135
+ exception_message = "failed to load certificate";
136
+ goto done;
137
+ }
138
+ }
139
+
103
140
  // Set key name.
104
- if(xmlSecKeySetName(encCtx->encKey, (xmlSecByte *)keyName) < 0) {
105
- rb_exception_result = rb_eEncryptionError;
106
- exception_message = "failed to set key name";
107
- goto done;
141
+ if(keyName) {
142
+ if(xmlSecKeySetName(encCtx->encKey, (xmlSecByte *)keyName) < 0) {
143
+ rb_exception_result = rb_eEncryptionError;
144
+ exception_message = "failed to set key name";
145
+ goto done;
146
+ }
108
147
  }
109
148
 
110
149
  // Add <enc:EncryptedKey/> node to the <dsig:KeyInfo/> tag to include
@@ -127,7 +166,7 @@ VALUE encrypt_with_key(VALUE self, VALUE rb_rsa_key_name, VALUE rb_rsa_key,
127
166
  }
128
167
 
129
168
  // encrypt the data
130
- if(xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, xmlDocGetRootElement(doc)) < 0) {
169
+ if(xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, node) < 0) {
131
170
  rb_exception_result = rb_eEncryptionError;
132
171
  exception_message = "encryption failed";
133
172
  goto done;
@@ -156,6 +195,8 @@ done:
156
195
  xmlSecKeysMngrDestroy(keyManager);
157
196
  }
158
197
 
198
+ xmlSecErrorsSetCallback(xmlSecErrorsDefaultCallback);
199
+
159
200
  if(rb_exception_result != Qnil) {
160
201
  if (hasXmlSecLastError()) {
161
202
  rb_raise(rb_exception_result, "%s, XmlSec error: %s", exception_message,
@@ -2,7 +2,7 @@
2
2
  #include "util.h"
3
3
 
4
4
  // declaration from Nokogiri proper
5
- VALUE Nokogiri_wrap_xml_node(VALUE klass, xmlNodePtr node) ;
5
+ VALUE noko_xml_node_wrap(VALUE klass, xmlNodePtr node) ;
6
6
 
7
7
  VALUE set_id_attribute(VALUE self, VALUE rb_attr_name) {
8
8
  VALUE rb_exception_result = Qnil;
@@ -14,7 +14,7 @@ VALUE set_id_attribute(VALUE self, VALUE rb_attr_name) {
14
14
  xmlChar *name = NULL;
15
15
  char *idName = NULL;
16
16
  char *exception_attribute_arg = NULL;
17
-
17
+
18
18
  resetXmlSecError();
19
19
 
20
20
  Data_Get_Struct(self, xmlNode, node);
@@ -28,7 +28,7 @@ VALUE set_id_attribute(VALUE self, VALUE rb_attr_name) {
28
28
  exception_message = "Can't find attribute to add register as id";
29
29
  goto done;
30
30
  }
31
-
31
+
32
32
  // get the attribute (id) value
33
33
  name = xmlNodeListGetString(node->doc, attr->children, 1);
34
34
  if(name == NULL) {
@@ -37,7 +37,7 @@ VALUE set_id_attribute(VALUE self, VALUE rb_attr_name) {
37
37
  exception_attribute_arg = idName;
38
38
  goto done;
39
39
  }
40
-
40
+
41
41
  // check that we don't have that id already registered
42
42
  tmp = xmlGetID(node->doc, name);
43
43
  if(tmp != NULL) {
@@ -46,7 +46,7 @@ VALUE set_id_attribute(VALUE self, VALUE rb_attr_name) {
46
46
  exception_attribute_arg = idName;
47
47
  goto done;
48
48
  }
49
-
49
+
50
50
  // finally register id
51
51
  xmlAddID(NULL, node->doc, name, attr);
52
52
 
@@ -56,6 +56,8 @@ done:
56
56
  xmlFree(name);
57
57
  }
58
58
 
59
+ xmlSecErrorsSetCallback(xmlSecErrorsDefaultCallback);
60
+
59
61
  if(rb_exception_result != Qnil) {
60
62
  if (exception_attribute_arg) {
61
63
  if (hasXmlSecLastError()) {
@@ -87,7 +89,7 @@ VALUE get_id(VALUE self, VALUE rb_id)
87
89
  Data_Get_Struct(self, xmlDoc, doc);
88
90
  prop = xmlGetID(doc, (const xmlChar *)StringValueCStr(rb_id));
89
91
  if (prop) {
90
- return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
92
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
91
93
  } else {
92
94
  return Qnil;
93
95
  }
@@ -17,7 +17,7 @@ void Init_Nokogiri_ext() {
17
17
 
18
18
  rb_define_method(rb_cNokogiri_XML_Node, "sign!", sign, 1);
19
19
  rb_define_method(rb_cNokogiri_XML_Node, "verify_with", verify_with, 1);
20
- rb_define_method(rb_cNokogiri_XML_Document, "encrypt_with_key", encrypt_with_key, 3);
20
+ rb_define_method(rb_cNokogiri_XML_Node, "encrypt_with_key", encrypt_with_key, 3);
21
21
  rb_define_method(rb_cNokogiri_XML_Node, "decrypt_with_key", decrypt_with_key, 2);
22
22
  rb_define_method(rb_cNokogiri_XML_Document, "get_id", get_id, 1);
23
23
  rb_define_method(rb_cNokogiri_XML_Node, "set_id_attribute", set_id_attribute, 1);
@@ -232,6 +232,8 @@ done:
232
232
  xmlSecDSigCtxDestroy(dsigCtx);
233
233
  }
234
234
 
235
+ xmlSecErrorsSetCallback(xmlSecErrorsDefaultCallback);
236
+
235
237
  if(rb_exception_result != Qnil) {
236
238
  // remove the signature node before raising an exception, so that
237
239
  // the document is untouched
@@ -246,6 +246,8 @@ done:
246
246
  xmlSecKeysMngrDestroy(keyManager);
247
247
  }
248
248
 
249
+ xmlSecErrorsSetCallback(xmlSecErrorsDefaultCallback);
250
+
249
251
  if(!NIL_P(rb_exception_result)) {
250
252
  if (hasXmlSecLastError()) {
251
253
  rb_raise(rb_exception_result, "%s, XmlSec error: %s", exception_message,
@@ -102,6 +102,7 @@ int hasXmlSecLastError() {
102
102
  void resetXmlSecError() {
103
103
  g_errorStack[0] = '\0';
104
104
  g_errorStackPos = 0;
105
+ xmlSecErrorsSetCallback(storeErrorCallback);
105
106
  }
106
107
 
107
108
  void storeErrorCallback(const char *file,
@@ -18,6 +18,7 @@
18
18
  #include <xmlsec/xmlenc.h>
19
19
  #include <xmlsec/templates.h>
20
20
  #include <xmlsec/crypto.h>
21
+ #include <xmlsec/errors.h>
21
22
 
22
23
  // TODO(awong): Support non-gcc and non-clang compilers.
23
24
  #define EXTENSION_EXPORT __attribute__((visibility("default")))
data/lib/xmlsec.rb CHANGED
@@ -61,12 +61,8 @@ class Nokogiri::XML::Document
61
61
  # # encrypt with a public key and optional key name
62
62
  # doc.encrypt! key: 'public-key', name: 'name'
63
63
  #
64
- def encrypt! opts
65
- if opts[:key]
66
- encrypt_with_key opts[:name].to_s, opts[:key], opts.select { |key, _| key != :key && key != :name }
67
- else
68
- raise "public :key is required for encryption"
69
- end
64
+ def encrypt!(key:, name: nil, **opts)
65
+ root.encrypt_with(key: key, name: name, **opts)
70
66
  self
71
67
  end
72
68
 
@@ -89,6 +85,11 @@ class Nokogiri::XML::Document
89
85
  end
90
86
 
91
87
  class Nokogiri::XML::Node
88
+ def encrypt_with(key:, name: nil, **opts)
89
+ raise ArgumentError("public :key is required for encryption") unless key
90
+ encrypt_with_key(name, key, opts)
91
+ end
92
+
92
93
  def decrypt_with(opts)
93
94
  raise 'inadequate options specified for decryption' unless opts[:key]
94
95
 
@@ -1,3 +1,3 @@
1
1
  module Xmlsec
2
- VERSION = '0.9.4'
2
+ VERSION = '0.10.1'
3
3
  end
@@ -28,9 +28,10 @@ Gem::Specification.new do |spec|
28
28
  spec.require_paths = ["lib"]
29
29
  spec.extensions = %w{ext/nokogiri_ext_xmlsec/extconf.rb}
30
30
 
31
- spec.add_dependency 'nokogiri'
32
-
33
- spec.add_development_dependency "bundler", "~> 1.3"
31
+ spec.add_dependency 'nokogiri', '>= 1.11.2'
32
+
33
+ spec.add_development_dependency "bundler", "~> 2.1"
34
+ spec.add_development_dependency "byebug"
34
35
  spec.add_development_dependency "rake"
35
36
  spec.add_development_dependency "rake-compiler"
36
37
  spec.add_development_dependency "rspec"
@@ -31,4 +31,25 @@ describe "encryption and decryption:" do
31
31
  end
32
32
  end
33
33
 
34
+ it "encrypts a single element" do
35
+ doc = subject
36
+ original = doc.to_s
37
+ node = doc.at_xpath('env:Envelope/env:Data', 'env' => 'urn:envelope')
38
+ node.encrypt_with(key: fixture('rsa.pub'), block_encryption: 'aes128-cbc', key_transport: 'rsa-1_5')
39
+ expect(doc.root.name).to eq 'Envelope'
40
+ expect(doc.root.element_children.first.name).to eq 'EncryptedData'
41
+ encrypted_data = doc.root.element_children.first
42
+ encrypted_data.decrypt_with(key: fixture('rsa.pem'))
43
+ expect(doc.to_s).to eq original
44
+ end
45
+
46
+ it "inserts a certificate" do
47
+ doc = subject
48
+ doc.encrypt!(key: fixture('cert/server.key.decrypted'),
49
+ cert: fixture('cert/server.crt'),
50
+ block_encryption: 'aes128-cbc',
51
+ key_transport: 'rsa-1_5')
52
+ expect(doc.to_s).to match(/X509Data/)
53
+ expect(doc.to_s).not_to match(/X509Data></)
54
+ end
34
55
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nokogiri-xmlsec-instructure
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.4
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Albert J. Wong
8
8
  - Cody Cutrer
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-02-27 00:00:00.000000000 Z
12
+ date: 2021-04-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -17,28 +17,42 @@ dependencies:
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: '0'
20
+ version: 1.11.2
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: '0'
27
+ version: 1.11.2
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: bundler
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '1.3'
34
+ version: '2.1'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '1.3'
41
+ version: '2.1'
42
+ - !ruby/object:Gem::Dependency
43
+ name: byebug
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'
42
56
  - !ruby/object:Gem::Dependency
43
57
  name: rake
44
58
  requirement: !ruby/object:Gem::Requirement
@@ -172,7 +186,7 @@ homepage: https://github.com/instructure/nokogiri-xmlsec-instructure
172
186
  licenses:
173
187
  - MIT
174
188
  metadata: {}
175
- post_install_message:
189
+ post_install_message:
176
190
  rdoc_options: []
177
191
  require_paths:
178
192
  - lib
@@ -187,9 +201,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
187
201
  - !ruby/object:Gem::Version
188
202
  version: '0'
189
203
  requirements: []
190
- rubyforge_project:
191
- rubygems_version: 2.7.3
192
- signing_key:
204
+ rubygems_version: 3.2.15
205
+ signing_key:
193
206
  specification_version: 4
194
207
  summary: Wrapper around http://www.aleksey.com/xmlsec to support XML encryption, decryption,
195
208
  signing and signature validation in Ruby