Class: OpenID::Server::Signatory

Inherits:
Object
  • Object
show all
Defined in:
lib/openid/server.rb

Overview

I sign things.

I also check signatures.

All my state is encapsulated in a store, which means I’m not generally pickleable but I am easy to reconstruct.

Constant Summary collapse

@@_normal_key =

keys have a bogus server URL in them because the filestore really does expect that key to be a URL. This seems a little silly for the server store, since I expect there to be only one server URL.

'http://localhost/|normal'
@@_dumb_key =
'http://localhost/|dumb'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(store) ⇒ Signatory

Create a new Signatory. store is The back-end where my associations are stored.



1009
1010
1011
1012
1013
# File 'lib/openid/server.rb', line 1009

def initialize(store)
  Util.assert(store)
  @store = store
  @secret_lifetime = 14 * 24 * 60 * 60
end

Instance Attribute Details

#secret_lifetimeObject

The number of seconds a secret remains valid. Defaults to 14 days.



988
989
990
# File 'lib/openid/server.rb', line 988

def secret_lifetime
  @secret_lifetime
end

#storeObject

Returns the value of attribute store.



1005
1006
1007
# File 'lib/openid/server.rb', line 1005

def store
  @store
end

Class Method Details

._dumb_keyObject



1001
1002
1003
# File 'lib/openid/server.rb', line 1001

def self._dumb_key
  @@_dumb_key
end

._normal_keyObject



997
998
999
# File 'lib/openid/server.rb', line 997

def self._normal_key
  @@_normal_key
end

Instance Method Details

#create_association(dumb = true, assoc_type = 'HMAC-SHA1') ⇒ Object

Make a new association.



1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
# File 'lib/openid/server.rb', line 1076

def create_association(dumb=true, assoc_type='HMAC-SHA1')
  secret = CryptUtil.random_string(OpenID.get_secret_size(assoc_type))
  uniq = Util.to_base64(CryptUtil.random_string(4))
  handle = sprintf('{%s}{%x}{%s}', assoc_type, Time.now.to_i, uniq)

  assoc = Association.from_expires_in(
      secret_lifetime, handle, secret, assoc_type)

  if dumb
    key = @@_dumb_key
  else
    key = @@_normal_key
  end

  @store.store_association(key, assoc)
  return assoc
end

#get_association(assoc_handle, dumb, checkExpiration = true) ⇒ Object

Get the association with the specified handle.



1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
# File 'lib/openid/server.rb', line 1095

def get_association(assoc_handle, dumb, checkExpiration=true)
  # Hmm.  We've created an interface that deals almost entirely
  # with assoc_handles.  The only place outside the Signatory
  # that uses this (and thus the only place that ever sees
  # Association objects) is when creating a response to an
  # association request, as it must have the association's
  # secret.

  if !assoc_handle
    raise ArgumentError.new("assoc_handle must not be None")
  end

  if dumb
    key = @@_dumb_key
  else
    key = @@_normal_key
  end

  assoc = @store.get_association(key, assoc_handle)
  if assoc and assoc.expires_in <= 0
    Util.log(sprintf("requested %sdumb key %s is expired (by %s seconds)",
                     (!dumb) ? 'not-' : '',
                     assoc_handle, assoc.expires_in))
    if checkExpiration
      @store.remove_association(key, assoc_handle)
      assoc = nil
    end
  end

  return assoc
end

#invalidate(assoc_handle, dumb) ⇒ Object

Invalidates the association with the given handle.



1128
1129
1130
1131
1132
1133
1134
1135
1136
# File 'lib/openid/server.rb', line 1128

def invalidate(assoc_handle, dumb)
  if dumb
    key = @@_dumb_key
  else
    key = @@_normal_key
  end

  @store.remove_association(key, assoc_handle)
end

#sign(response) ⇒ Object

Sign a response.

I take an OpenIDResponse, create a signature for everything in its signed list, and return a new copy of the response object with that signature included.



1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
# File 'lib/openid/server.rb', line 1040

def sign(response)
  signed_response = response.copy
  assoc_handle = response.request.assoc_handle
  if assoc_handle
    # normal mode disabling expiration check because even if the
    # association is expired, we still need to know some
    # properties of the association so that we may preserve
    # those properties when creating the fallback association.
    assoc = get_association(assoc_handle, false, false)

    if !assoc or assoc.expires_in <= 0
      # fall back to dumb mode
      signed_response.fields.set_arg(
            OPENID_NS, 'invalidate_handle', assoc_handle)
      assoc_type = assoc ? assoc.assoc_type : 'HMAC-SHA1'
      if assoc and assoc.expires_in <= 0
        # now do the clean-up that the disabled checkExpiration
        # code didn't get to do.
        invalidate(assoc_handle, false)
      end
      assoc = create_association(true, assoc_type)
    end
  else
    # dumb mode.
    assoc = create_association(true)
  end

  begin
    signed_response.fields = assoc.sign_message(signed_response.fields)
  rescue KVFormError => err
    raise EncodingError, err
  end
  return signed_response
end

#verify(assoc_handle, message) ⇒ Object

Verify that the signature for some data is valid.



1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
# File 'lib/openid/server.rb', line 1016

def verify(assoc_handle, message)
  assoc = get_association(assoc_handle, true)
  if !assoc
    Util.log(sprintf("failed to get assoc with handle %s to verify " +
                     "message %s", assoc_handle, message))
    return false
  end

  begin
    valid = assoc.check_message_signature(message)
  rescue StandardError => ex
    Util.log(sprintf("Error in verifying %s with %s: %s",
                     message, assoc, ex))
    return false
  end

  return valid
end