Subversion Repositories Applications.annuaire

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
42 aurelien 1
<?php
2
 
3
/**
4
 * This module contains code for dealing with associations between
5
 * consumers and servers.
6
 *
7
 * PHP versions 4 and 5
8
 *
9
 * LICENSE: See the COPYING file included in this distribution.
10
 *
11
 * @package OpenID
12
 * @author JanRain, Inc. <openid@janrain.com>
13
 * @copyright 2005 Janrain, Inc.
14
 * @license http://www.gnu.org/copyleft/lesser.html LGPL
15
 */
16
 
17
/**
18
 * @access private
19
 */
20
require_once 'Auth/OpenID/CryptUtil.php';
21
 
22
/**
23
 * @access private
24
 */
25
require_once 'Auth/OpenID/KVForm.php';
26
 
27
/**
28
 * This class represents an association between a server and a
29
 * consumer.  In general, users of this library will never see
30
 * instances of this object.  The only exception is if you implement a
31
 * custom {@link Auth_OpenID_OpenIDStore}.
32
 *
33
 * If you do implement such a store, it will need to store the values
34
 * of the handle, secret, issued, lifetime, and assoc_type instance
35
 * variables.
36
 *
37
 * @package OpenID
38
 */
39
class Auth_OpenID_Association {
40
 
41
    /**
42
     * This is a HMAC-SHA1 specific value.
43
     *
44
     * @access private
45
     */
46
    var $SIG_LENGTH = 20;
47
 
48
    /**
49
     * The ordering and name of keys as stored by serialize.
50
     *
51
     * @access private
52
     */
53
    var $assoc_keys = array(
54
                            'version',
55
                            'handle',
56
                            'secret',
57
                            'issued',
58
                            'lifetime',
59
                            'assoc_type'
60
                            );
61
 
62
    /**
63
     * This is an alternate constructor (factory method) used by the
64
     * OpenID consumer library to create associations.  OpenID store
65
     * implementations shouldn't use this constructor.
66
     *
67
     * @access private
68
     *
69
     * @param integer $expires_in This is the amount of time this
70
     * association is good for, measured in seconds since the
71
     * association was issued.
72
     *
73
     * @param string $handle This is the handle the server gave this
74
     * association.
75
     *
76
     * @param string secret This is the shared secret the server
77
     * generated for this association.
78
     *
79
     * @param assoc_type This is the type of association this
80
     * instance represents.  The only valid value of this field at
81
     * this time is 'HMAC-SHA1', but new types may be defined in the
82
     * future.
83
     *
84
     * @return association An {@link Auth_OpenID_Association}
85
     * instance.
86
     */
87
    function fromExpiresIn($expires_in, $handle, $secret, $assoc_type)
88
    {
89
        $issued = time();
90
        $lifetime = $expires_in;
91
        return new Auth_OpenID_Association($handle, $secret,
92
                                           $issued, $lifetime, $assoc_type);
93
    }
94
 
95
    /**
96
     * This is the standard constructor for creating an association.
97
     * The library should create all of the necessary associations, so
98
     * this constructor is not part of the external API.
99
     *
100
     * @access private
101
     *
102
     * @param string $handle This is the handle the server gave this
103
     * association.
104
     *
105
     * @param string $secret This is the shared secret the server
106
     * generated for this association.
107
     *
108
     * @param integer $issued This is the time this association was
109
     * issued, in seconds since 00:00 GMT, January 1, 1970.  (ie, a
110
     * unix timestamp)
111
     *
112
     * @param integer $lifetime This is the amount of time this
113
     * association is good for, measured in seconds since the
114
     * association was issued.
115
     *
116
     * @param string $assoc_type This is the type of association this
117
     * instance represents.  The only valid value of this field at
118
     * this time is 'HMAC-SHA1', but new types may be defined in the
119
     * future.
120
     */
121
    function Auth_OpenID_Association(
122
        $handle, $secret, $issued, $lifetime, $assoc_type)
123
    {
124
        if ($assoc_type != 'HMAC-SHA1') {
125
            $fmt = 'HMAC-SHA1 is the only supported association type (got %s)';
126
            trigger_error(sprintf($fmt, $assoc_type), E_USER_ERROR);
127
        }
128
 
129
        $this->handle = $handle;
130
        $this->secret = $secret;
131
        $this->issued = $issued;
132
        $this->lifetime = $lifetime;
133
        $this->assoc_type = $assoc_type;
134
    }
135
 
136
    /**
137
     * This returns the number of seconds this association is still
138
     * valid for, or 0 if the association is no longer valid.
139
     *
140
     * @return integer $seconds The number of seconds this association
141
     * is still valid for, or 0 if the association is no longer valid.
142
     */
143
    function getExpiresIn($now = null)
144
    {
145
        if ($now == null) {
146
            $now = time();
147
        }
148
 
149
        return max(0, $this->issued + $this->lifetime - $now);
150
    }
151
 
152
    /**
153
     * This checks to see if two {@link Auth_OpenID_Association}
154
     * instances represent the same association.
155
     *
156
     * @return bool $result true if the two instances represent the
157
     * same association, false otherwise.
158
     */
159
    function equal($other)
160
    {
161
        return ((gettype($this) == gettype($other))
162
                && ($this->handle == $other->handle)
163
                && ($this->secret == $other->secret)
164
                && ($this->issued == $other->issued)
165
                && ($this->lifetime == $other->lifetime)
166
                && ($this->assoc_type == $other->assoc_type));
167
    }
168
 
169
    /**
170
     * Convert an association to KV form.
171
     *
172
     * @return string $result String in KV form suitable for
173
     * deserialization by deserialize.
174
     */
175
    function serialize()
176
    {
177
        $data = array(
178
                     'version' => '2',
179
                     'handle' => $this->handle,
180
                     'secret' => base64_encode($this->secret),
181
                     'issued' => strval(intval($this->issued)),
182
                     'lifetime' => strval(intval($this->lifetime)),
183
                     'assoc_type' => $this->assoc_type
184
                     );
185
 
186
        assert(array_keys($data) == $this->assoc_keys);
187
 
188
        return Auth_OpenID_KVForm::fromArray($data, $strict = true);
189
    }
190
 
191
    /**
192
     * Parse an association as stored by serialize().  This is the
193
     * inverse of serialize.
194
     *
195
     * @param string $assoc_s Association as serialized by serialize()
196
     * @return Auth_OpenID_Association $result instance of this class
197
     */
198
    function deserialize($class_name, $assoc_s)
199
    {
200
        $pairs = Auth_OpenID_KVForm::toArray($assoc_s, $strict = true);
201
        $keys = array();
202
        $values = array();
203
        foreach ($pairs as $key => $value) {
204
            if (is_array($value)) {
205
                list($key, $value) = $value;
206
            }
207
            $keys[] = $key;
208
            $values[] = $value;
209
        }
210
 
211
        $class_vars = get_class_vars($class_name);
212
        $class_assoc_keys = $class_vars['assoc_keys'];
213
 
214
        sort($keys);
215
        sort($class_assoc_keys);
216
 
217
        if ($keys != $class_assoc_keys) {
218
            trigger_error('Unexpected key values: ' . strval($keys),
219
                          E_USER_WARNING);
220
            return null;
221
        }
222
 
223
        $version = $pairs['version'];
224
        $handle = $pairs['handle'];
225
        $secret = $pairs['secret'];
226
        $issued = $pairs['issued'];
227
        $lifetime = $pairs['lifetime'];
228
        $assoc_type = $pairs['assoc_type'];
229
 
230
        if ($version != '2') {
231
            trigger_error('Unknown version: ' . $version, E_USER_WARNING);
232
            return null;
233
        }
234
 
235
        $issued = intval($issued);
236
        $lifetime = intval($lifetime);
237
        $secret = base64_decode($secret);
238
 
239
        return new $class_name(
240
            $handle, $secret, $issued, $lifetime, $assoc_type);
241
    }
242
 
243
    /**
244
     * Generate a signature for a sequence of (key, value) pairs
245
     *
246
     * @access private
247
     * @param array $pairs The pairs to sign, in order.  This is an
248
     * array of two-tuples.
249
     * @return string $signature The binary signature of this sequence
250
     * of pairs
251
     */
252
    function sign($pairs)
253
    {
254
        $kv = Auth_OpenID_KVForm::fromArray($pairs);
255
        return Auth_OpenID_HMACSHA1($this->secret, $kv);
256
    }
257
 
258
    /**
259
     * Generate a signature for some fields in a dictionary
260
     *
261
     * @access private
262
     * @param array $fields The fields to sign, in order; this is an
263
     * array of strings.
264
     * @param array $data Dictionary of values to sign (an array of
265
     * string => string pairs).
266
     * @return string $signature The signature, base64 encoded
267
     */
268
    function signDict($fields, $data, $prefix = 'openid.')
269
    {
270
        $pairs = array();
271
        foreach ($fields as $field) {
272
            $pairs[] = array($field, $data[$prefix . $field]);
273
        }
274
 
275
        return base64_encode($this->sign($pairs));
276
    }
277
 
278
    /**
279
     * Add a signature to an array of fields
280
     *
281
     * @access private
282
     */
283
    function addSignature($fields, &$data, $prefix = 'openid.')
284
    {
285
        $sig = $this->signDict($fields, $data, $prefix);
286
        $signed = implode(",", $fields);
287
        $data[$prefix . 'sig'] = $sig;
288
        $data[$prefix . 'signed'] = $signed;
289
    }
290
 
291
    /**
292
     * Confirm that the signature of these fields matches the
293
     * signature contained in the data
294
     *
295
     * @access private
296
     */
297
    function checkSignature($data, $prefix = 'openid.')
298
    {
299
        $signed = $data[$prefix . 'signed'];
300
        $fields = explode(",", $signed);
301
        $expected_sig = $this->signDict($fields, $data, $prefix);
302
        $request_sig = $data[$prefix . 'sig'];
303
 
304
        return ($request_sig == $expected_sig);
305
    }
306
}
307
 
308
?>