C0 code coverage information

Generated on Fri Jul 11 15:55:32 -0700 2008 with rcov 0.7.0


Code reported as executed by Ruby looks like this...
and this: this line is also marked as covered.
Lines considered as run by rcov, but not reported by Ruby, look like this,
and this: these lines were inferred by rcov (using simple heuristics).
Finally, here's a line marked as not executed.
Name Total lines Lines of code Total coverage Code coverage
lib/openid/association.rb 249 197
98.8% 
98.5% 
  1 require "openid/kvform"
  2 require "openid/util"
  3 require "openid/cryptutil"
  4 require "openid/message"
  5 
  6 module OpenID
  7 
  8   def self.get_secret_size(assoc_type)
  9     if assoc_type == 'HMAC-SHA1'
 10       return 20
 11     elsif assoc_type == 'HMAC-SHA256'
 12       return 32
 13     else
 14       raise ArgumentError("Unsupported association type: #{assoc_type}")
 15     end
 16   end
 17 
 18   # An Association holds the shared secret between a relying party and
 19   # an OpenID provider.
 20   class Association
 21     attr_reader :handle, :secret, :issued, :lifetime, :assoc_type
 22 
 23     FIELD_ORDER =
 24       [:version, :handle, :secret, :issued, :lifetime, :assoc_type,]
 25 
 26     # Load a serialized Association
 27     def self.deserialize(serialized)
 28       parsed = Util.kv_to_seq(serialized)
 29       parsed_fields = parsed.map{|k, v| k.to_sym}
 30       if parsed_fields != FIELD_ORDER
 31           raise ProtocolError, 'Unexpected fields in serialized association'\
 32           " (Expected #{FIELD_ORDER.inspect}, got #{parsed_fields.inspect})"
 33       end
 34       version, handle, secret64, issued_s, lifetime_s, assoc_type =
 35         parsed.map {|field, value| value}
 36       if version != '2'
 37         raise ProtocolError, "Attempted to deserialize unsupported version "\
 38                              "(#{parsed[0][1].inspect})"
 39       end
 40 
 41       self.new(handle,
 42                Util.from_base64(secret64),
 43                Time.at(issued_s.to_i),
 44                lifetime_s.to_i,
 45                assoc_type)
 46     end
 47 
 48     # Create an Association with an issued time of now
 49     def self.from_expires_in(expires_in, handle, secret, assoc_type)
 50       issued = Time.now
 51       self.new(handle, secret, issued, expires_in, assoc_type)
 52     end
 53 
 54     def initialize(handle, secret, issued, lifetime, assoc_type)
 55       @handle = handle
 56       @secret = secret
 57       @issued = issued
 58       @lifetime = lifetime
 59       @assoc_type = assoc_type
 60     end
 61 
 62     # Serialize the association to a form that's consistent across
 63     # JanRain OpenID libraries.
 64     def serialize
 65       data = {
 66         :version => '2',
 67         :handle => handle,
 68         :secret => Util.to_base64(secret),
 69         :issued => issued.to_i.to_s,
 70         :lifetime => lifetime.to_i.to_s,
 71         :assoc_type => assoc_type,
 72       }
 73 
 74       Util.assert(data.length == FIELD_ORDER.length)
 75 
 76       pairs = FIELD_ORDER.map{|field| [field.to_s, data[field]]}
 77       return Util.seq_to_kv(pairs, strict=true)
 78     end
 79 
 80     # The number of seconds until this association expires
 81     def expires_in(now=nil)
 82       if now.nil?
 83         now = Time.now.to_i
 84       else
 85         now = now.to_i
 86       end
 87       time_diff = (issued.to_i + lifetime) - now
 88       if time_diff < 0
 89         return 0
 90       else
 91         return time_diff
 92       end
 93     end
 94 
 95     # Generate a signature for a sequence of [key, value] pairs
 96     def sign(pairs)
 97       kv = Util.seq_to_kv(pairs)
 98       case assoc_type
 99       when 'HMAC-SHA1'
100         CryptUtil.hmac_sha1(@secret, kv)
101       when 'HMAC-SHA256'
102         CryptUtil.hmac_sha256(@secret, kv)
103       else
104         raise ProtocolError, "Association has unknown type: "\
105           "#{assoc_type.inspect}"
106       end
107     end
108 
109     # Generate the list of pairs that form the signed elements of the
110     # given message
111     def make_pairs(message)
112       signed = message.get_arg(OPENID_NS, 'signed')
113       if signed.nil?
114         raise ProtocolError, 'Missing signed list'
115       end
116       signed_fields = signed.split(',', -1)
117       data = message.to_post_args
118       signed_fields.map {|field| [field, data.fetch('openid.'+field,'')] }
119     end
120 
121     # Return whether the message's signature passes
122     def check_message_signature(message)
123       message_sig = message.get_arg(OPENID_NS, 'sig')
124       if message_sig.nil?
125         raise ProtocolError, "#{message} has no sig."
126       end
127       calculated_sig = get_message_signature(message)
128       return calculated_sig == message_sig
129     end
130 
131     # Get the signature for this message
132     def get_message_signature(message)
133       Util.to_base64(sign(make_pairs(message)))
134     end
135 
136     def ==(other)
137       (other.class == self.class and 
138        other.handle == self.handle and
139        other.secret == self.secret and
140 
141        # The internals of the time objects seemed to differ
142        # in an opaque way when serializing/unserializing.
143        # I don't think this will be a problem.
144        other.issued.to_i == self.issued.to_i and
145 
146        other.lifetime == self.lifetime and
147        other.assoc_type == self.assoc_type)
148     end
149 
150     # Add a signature (and a signed list) to a message.
151     def sign_message(message)
152       if (message.has_key?(OPENID_NS, 'sig') or
153           message.has_key?(OPENID_NS, 'signed'))
154         raise ArgumentError, 'Message already has signed list or signature'
155       end
156 
157       extant_handle = message.get_arg(OPENID_NS, 'assoc_handle')
158       if extant_handle and extant_handle != self.handle
159         raise ArgumentError, "Message has a different association handle"
160       end
161 
162       signed_message = message.copy()
163       signed_message.set_arg(OPENID_NS, 'assoc_handle', self.handle)
164       message_keys = signed_message.to_post_args.keys()
165 
166       signed_list = []
167       message_keys.each { |k|
168         if k.starts_with?('openid.')
169           signed_list << k[7..-1]
170         end
171       }
172 
173       signed_list << 'signed'
174       signed_list.sort!
175 
176       signed_message.set_arg(OPENID_NS, 'signed', signed_list.join(','))
177       sig = get_message_signature(signed_message)
178       signed_message.set_arg(OPENID_NS, 'sig', sig)
179       return signed_message
180     end
181   end
182 
183   class AssociationNegotiator
184     attr_reader :allowed_types
185 
186     def self.get_session_types(assoc_type)
187       case assoc_type
188       when 'HMAC-SHA1'
189         ['DH-SHA1', 'no-encryption']
190       when 'HMAC-SHA256'
191         ['DH-SHA256', 'no-encryption']
192       else
193         raise ProtocolError, "Unknown association type #{assoc_type.inspect}"
194       end
195     end
196 
197     def self.check_session_type(assoc_type, session_type)
198       if !get_session_types(assoc_type).include?(session_type)
199         raise ProtocolError, "Session type #{session_type.inspect} not "\
200                              "valid for association type #{assoc_type.inspect}"
201       end
202     end
203 
204     def initialize(allowed_types)
205       self.allowed_types=(allowed_types)
206     end
207 
208     def copy
209       Marshal.load(Marshal.dump(self))
210     end
211 
212     def allowed_types=(allowed_types)
213       allowed_types.each do |assoc_type, session_type|
214         self.class.check_session_type(assoc_type, session_type)
215       end
216       @allowed_types = allowed_types
217     end
218 
219     def add_allowed_type(assoc_type, session_type=nil)
220       if session_type.nil?
221         session_types = self.class.get_session_types(assoc_type)
222       else
223         self.class.check_session_type(assoc_type, session_type)
224         session_types = [session_type]
225       end
226       for session_type in session_types do
227         @allowed_types << [assoc_type, session_type]
228       end
229     end
230 
231     def allowed?(assoc_type, session_type)
232       @allowed_types.include?([assoc_type, session_type])
233     end
234 
235     def get_allowed_type
236       @allowed_types.empty? ? nil : @allowed_types[0]
237     end
238   end
239 
240   DefaultNegotiator =
241     AssociationNegotiator.new([['HMAC-SHA1', 'DH-SHA1'],
242                                ['HMAC-SHA1', 'no-encryption'],
243                                ['HMAC-SHA256', 'DH-SHA256'],
244                                ['HMAC-SHA256', 'no-encryption']])
245 
246   EncryptedNegotiator =
247     AssociationNegotiator.new([['HMAC-SHA1', 'DH-SHA1'],
248                                ['HMAC-SHA256', 'DH-SHA256']])
249 end

Generated using the rcov code coverage analysis tool for Ruby version 0.7.0.

Valid XHTML 1.0! Valid CSS!