Skip to content

Commit c44f9a2

Browse files
author
Austin Ziegler
committed
Moved core extensions to Net::BER. Documented.
1 parent c3f991f commit c44f9a2

File tree

17 files changed

+312
-248
lines changed

17 files changed

+312
-248
lines changed

History.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
=== Net::LDAP NEXT / 2010-__-__
2+
* Moved the core class extensions extensions from being in the Net::LDAP
3+
hierarchy to the Net::BER hierarchy as most of the methods therein are
4+
related to BER-encoding values. This will make extracting Net::BER from
5+
Net::LDAP easier in the future.
6+
* Documented the core class extension methods.
7+
18
=== Net::LDAP 0.1.1 / 2010-03-18
29
* Fixing a critical problem with sockets.
310

lib/net/ber.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ def to_ber
6767

6868
module Net
6969
module BER
70+
# Used for BER-encoding the length and content bytes of a Fixnum integer
71+
# values.
72+
MAX_FIXNUM_SIZE = 0.size
73+
7074
class BerError < StandardError; end
7175

7276
class BerIdentifiedString < String
@@ -92,4 +96,4 @@ def to_ber
9296
end
9397
end
9498

95-
require 'net/ber/ber_parser'
99+
require 'net/ber/core_ext'

lib/net/ber/core_ext.rb

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# NET::BER
2+
# Mixes ASN.1/BER convenience methods into several standard classes. Also
3+
# provides BER parsing functionality.
4+
#
5+
#--
6+
# Copyright (C) 2006 by Francis Cianfrocca and other contributors. All
7+
# Rights Reserved.
8+
#
9+
# Gmail: garbagecat10
10+
#
11+
# This program is free software; you can redistribute it and/or modify
12+
# it under the terms of the GNU General Public License as published by
13+
# the Free Software Foundation; either version 2 of the License, or
14+
# (at your option) any later version.
15+
#
16+
# This program is distributed in the hope that it will be useful,
17+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
# GNU General Public License for more details.
20+
#
21+
# You should have received a copy of the GNU General Public License
22+
# along with this program; if not, write to the Free Software
23+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24+
#++
25+
26+
require 'net/ber/ber_parser'
27+
class IO
28+
include Net::BER::BERParser
29+
end
30+
31+
class StringIO
32+
include Net::BER::BERParser
33+
end
34+
35+
if defined? ::OpenSSL
36+
class OpenSSL::SSL::SSLSocket
37+
include Net::BER::BERParser
38+
end
39+
end
40+
41+
module Net::BER::Extensions; end
42+
43+
require 'net/ber/core_ext/string'
44+
class String
45+
include Net::BER::BERParser
46+
include Net::BER::Extensions::String
47+
end
48+
49+
require 'net/ber/core_ext/array'
50+
class Array
51+
include Net::BER::Extensions::Array
52+
end
53+
54+
require 'net/ber/core_ext/bignum'
55+
class Bignum
56+
include Net::BER::Extensions::Bignum
57+
end
58+
59+
require 'net/ber/core_ext/fixnum'
60+
class Fixnum
61+
include Net::BER::Extensions::Fixnum
62+
end
63+
64+
require 'net/ber/core_ext/true_class'
65+
class TrueClass
66+
include Net::BER::Extensions::TrueClass
67+
end
68+
69+
require 'net/ber/core_ext/false_class'
70+
class FalseClass
71+
include Net::BER::Extensions::FalseClass
72+
end

lib/net/ber/core_ext/array.rb

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
module Net::BER::Extensions::Array
2+
##
3+
# Converts an Array to a BER sequence. All values in the Array are
4+
# expected to be in BER format prior to calling this method.
5+
def to_ber(id = 0)
6+
# The universal sequence tag 0x30 is composed of the base tag value
7+
# (0x10) and the constructed flag (0x20).
8+
to_ber_seq_internal(0x30 + id)
9+
end
10+
alias_method :to_ber_sequence, :to_ber
11+
12+
##
13+
# Converts an Array to a BER set. All values in the Array are expected to
14+
# be in BER format prior to calling this method.
15+
def to_ber_set(id = 0)
16+
# The universal set tag 0x31 is composed of the base tag value (0x11)
17+
# and the constructed flag (0x20).
18+
to_ber_seq_internal(0x31 + id)
19+
end
20+
21+
##
22+
# Converts an Array to an application-specific sequence, assigned a tag
23+
# value that is meaningful to the particular protocol being used. All
24+
# values in the Array are expected to be in BER format pr prior to calling
25+
# this method.
26+
#--
27+
# Implementor's note 20100320(AZ): RFC 4511 (the LDAPv3 protocol) as well
28+
# as earlier RFCs 1777 and 2559 seem to indicate that LDAP only has
29+
# application constructed sequences (0x60). However, ldapsearch sends some
30+
# context-specific constructed sequences (0xA0); other clients may do the
31+
# same. This behaviour appears to violate the RFCs. In real-world
32+
# practice, we may need to change calls of #to_ber_appsequence to
33+
# #to_ber_contextspecific for full LDAP server compatibility.
34+
#
35+
# This note probably belongs elsewhere.
36+
#++
37+
def to_ber_appsequence(id = 0)
38+
# The application sequence tag always starts from the application flag
39+
# (0x40) and the constructed flag (0x20).
40+
to_ber_seq_internal(0x60 + id)
41+
end
42+
43+
##
44+
# Converts an Array to a context-specific sequence, assigned a tag value
45+
# that is meaningful to the particular context of the particular protocol
46+
# being used. All values in the Array are expected to be in BER format
47+
# prior to calling this method.
48+
def to_ber_contextspecific(id = 0)
49+
# The application sequence tag always starts from the context flag
50+
# (0x80) and the constructed flag (0x20).
51+
to_ber_seq_internal(0xa0 + id)
52+
end
53+
54+
##
55+
# The internal sequence packing routine. All values in the Array are
56+
# expected to be in BER format prior to calling this method.
57+
def to_ber_seq_internal(code)
58+
s = self.join
59+
[code].pack('C') + s.length.to_ber_length_encoding + s
60+
end
61+
private :to_ber_seq_internal
62+
63+
##
64+
# SNMP Object Identifiers (OID) are special arrays
65+
#--
66+
# 20100320 AZ: I do not think that this method should be in BER, since
67+
# this appears to be SNMP-specific. This should probably be subsumed by a
68+
# proper SNMP OID object.
69+
#++
70+
def to_ber_oid
71+
ary = self.dup
72+
first = ary.shift
73+
raise Net::BER::BerError, "Invalid OID" unless [0, 1, 2].include?(first)
74+
first = first * 40 + ary.shift
75+
ary.unshift first
76+
oid = ary.pack("w*")
77+
[6, oid.length].pack("CC") + oid
78+
end
79+
end

lib/net/ber/core_ext/bignum.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module Net::BER::Extensions::Bignum
2+
##
3+
# Converts a Bignum to an uncompressed BER integer.
4+
def to_ber
5+
result = []
6+
7+
# NOTE: Array#pack's 'w' is a BER _compressed_ integer. We need
8+
# uncompressed BER integers, so we're not using that. See also:
9+
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/228864
10+
n = self
11+
while n > 0
12+
b = n & 0xff
13+
result << b
14+
n = n >> 8
15+
end
16+
17+
"\002" + ([result.size] + result.reverse).pack('C*')
18+
end
19+
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Net::BER::Extensions::FalseClass
2+
##
3+
# Converts +false+ to the BER wireline representation of +false+.
4+
def to_ber
5+
"\001\001\000"
6+
end
7+
end

lib/net/ber/core_ext/fixnum.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
module Net::BER::Extensions::Fixnum
2+
##
3+
# Converts the fixnum to BER format.
4+
def to_ber
5+
"\002#{to_ber_internal}"
6+
end
7+
8+
##
9+
# Converts the fixnum to BER enumerated format.
10+
def to_ber_enumerated
11+
"\012#{to_ber_internal}"
12+
end
13+
14+
##
15+
# Converts the fixnum to BER length encodining format.
16+
def to_ber_length_encoding
17+
if self <= 127
18+
[self].pack('C')
19+
else
20+
i = [self].pack('N').sub(/^[\0]+/,"")
21+
[0x80 + i.length].pack('C') + i
22+
end
23+
end
24+
25+
##
26+
# Generate a BER-encoding for an application-defined INTEGER. Examples of
27+
# such integers are SNMP's Counter, Gauge, and TimeTick types.
28+
def to_ber_application(tag)
29+
[0x40 + tag].pack("C") + to_ber_internal
30+
end
31+
32+
##
33+
# Used to BER-encode the length and content bytes of a Fixnum. Callers
34+
# must prepend the tag byte for the contained value.
35+
def to_ber_internal
36+
# CAUTION: Bit twiddling ahead. You might want to shield your eyes or
37+
# something.
38+
39+
# Looks for the first byte in the fixnum that is not all zeroes. It does
40+
# this by masking one byte after another, checking the result for bits
41+
# that are left on.
42+
size = Net::BER::MAX_FIXNUM_SIZE
43+
while size > 1
44+
break if (self & (0xff << (size - 1) * 8)) > 0
45+
size -= 1
46+
end
47+
48+
# Store the size of the fixnum in the result
49+
result = [size]
50+
51+
# Appends bytes to result, starting with higher orders first. Extraction
52+
# of bytes is done by right shifting the original fixnum by an amount
53+
# and then masking that with 0xff.
54+
while size > 0
55+
# right shift size - 1 bytes, mask with 0xff
56+
result << ((self >> ((size - 1) * 8)) & 0xff)
57+
size -= 1
58+
end
59+
60+
result.pack('C*')
61+
end
62+
private :to_ber_internal
63+
end

lib/net/ber/core_ext/string.rb

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
require 'stringio'
2+
3+
module Net::BER::Extensions::String
4+
##
5+
# Converts a string to a BER string. Universal octet-strings are tagged
6+
# with 0x04, but other values are possible depending on the context, so we
7+
# let the caller give us one.
8+
#
9+
# User code should call either #to_ber_application_string or
10+
# #to_ber_contextspecific.
11+
def to_ber(code = 0x04)
12+
[code].pack('C') + length.to_ber_length_encoding + self
13+
end
14+
15+
##
16+
# Creates an application-specific BER string encoded value with the
17+
# provided syntax code value.
18+
def to_ber_application_string(code)
19+
to_ber(0x40 + code)
20+
end
21+
22+
##
23+
# Creates a context-specific BER string encoded value with the provided
24+
# syntax code value.
25+
def to_ber_contextspecific(code)
26+
to_ber(0x80 + code)
27+
end
28+
29+
##
30+
# Nondestructively reads a BER object from this string.
31+
def read_ber(syntax = nil)
32+
StringIO.new(self).read_ber(syntax)
33+
end
34+
35+
=begin
36+
# 20100319 AZ I've kept this here because I'm not yet sure if it's
37+
# necessary.
38+
39+
##
40+
# Destructively reads a BER object from this string.
41+
def read_ber!(syntax = nil)
42+
obj, consumed = read_ber_from_string(self, syntax)
43+
if consumed
44+
self.slice!(0...consumed)
45+
obj
46+
else
47+
nil
48+
end
49+
end
50+
=end
51+
end

lib/net/ber/core_ext/true_class.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module Net::BER::Extensions::TrueClass
2+
##
3+
# Converts +true+ to the BER wireline representation of +true+.
4+
def to_ber
5+
# 20100319 AZ: Note that this may not be the completely correct value,
6+
# per some test documentation. We need to determine the truth of this.
7+
"\001\001\001"
8+
end
9+
end

lib/net/ldap.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
require 'net/ldap/dataset'
99
require 'net/ldap/psw'
1010
require 'net/ldap/entry'
11-
require 'net/ldap/core_ext/all'
1211

1312
module Net
1413
# == Net::LDAP

0 commit comments

Comments
 (0)