xref: /plugin/davcal/vendor/sabre/http/tests/HTTP/Auth/DigestTest.php (revision a1a3b6794e0e143a4a8b51d3185ce2d339be61ab)
1*a1a3b679SAndreas Boehler<?php
2*a1a3b679SAndreas Boehler
3*a1a3b679SAndreas Boehlernamespace Sabre\HTTP\Auth;
4*a1a3b679SAndreas Boehler
5*a1a3b679SAndreas Boehleruse Sabre\HTTP\Request;
6*a1a3b679SAndreas Boehleruse Sabre\HTTP\Response;
7*a1a3b679SAndreas Boehler
8*a1a3b679SAndreas Boehlerclass DigestTest extends \PHPUnit_Framework_TestCase {
9*a1a3b679SAndreas Boehler
10*a1a3b679SAndreas Boehler    /**
11*a1a3b679SAndreas Boehler     * @var Sabre\HTTP\Response
12*a1a3b679SAndreas Boehler     */
13*a1a3b679SAndreas Boehler    private $response;
14*a1a3b679SAndreas Boehler
15*a1a3b679SAndreas Boehler    /**
16*a1a3b679SAndreas Boehler     * request
17*a1a3b679SAndreas Boehler     *
18*a1a3b679SAndreas Boehler     * @var Sabre\HTTP\Request
19*a1a3b679SAndreas Boehler     */
20*a1a3b679SAndreas Boehler    private $request;
21*a1a3b679SAndreas Boehler
22*a1a3b679SAndreas Boehler    /**
23*a1a3b679SAndreas Boehler     * @var Sabre\HTTP\Auth\Digest
24*a1a3b679SAndreas Boehler     */
25*a1a3b679SAndreas Boehler    private $auth;
26*a1a3b679SAndreas Boehler
27*a1a3b679SAndreas Boehler    const REALM = 'SabreDAV unittest';
28*a1a3b679SAndreas Boehler
29*a1a3b679SAndreas Boehler    function setUp() {
30*a1a3b679SAndreas Boehler
31*a1a3b679SAndreas Boehler        $this->response = new Response();
32*a1a3b679SAndreas Boehler        $this->request = new Request();
33*a1a3b679SAndreas Boehler        $this->auth = new Digest(self::REALM, $this->request, $this->response);
34*a1a3b679SAndreas Boehler
35*a1a3b679SAndreas Boehler
36*a1a3b679SAndreas Boehler    }
37*a1a3b679SAndreas Boehler
38*a1a3b679SAndreas Boehler    function testDigest() {
39*a1a3b679SAndreas Boehler
40*a1a3b679SAndreas Boehler        list($nonce, $opaque) = $this->getServerTokens();
41*a1a3b679SAndreas Boehler
42*a1a3b679SAndreas Boehler        $username = 'admin';
43*a1a3b679SAndreas Boehler        $password = 12345;
44*a1a3b679SAndreas Boehler        $nc = '00002';
45*a1a3b679SAndreas Boehler        $cnonce = uniqid();
46*a1a3b679SAndreas Boehler
47*a1a3b679SAndreas Boehler        $digestHash = md5(
48*a1a3b679SAndreas Boehler            md5($username . ':' . self::REALM . ':' . $password) . ':' .
49*a1a3b679SAndreas Boehler            $nonce . ':' .
50*a1a3b679SAndreas Boehler            $nc . ':' .
51*a1a3b679SAndreas Boehler            $cnonce . ':' .
52*a1a3b679SAndreas Boehler            'auth:' .
53*a1a3b679SAndreas Boehler            md5('GET' . ':' . '/')
54*a1a3b679SAndreas Boehler        );
55*a1a3b679SAndreas Boehler
56*a1a3b679SAndreas Boehler        $this->request->setMethod('GET');
57*a1a3b679SAndreas Boehler        $this->request->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . self::REALM . '", nonce="' . $nonce . '", uri="/", response="' . $digestHash . '", opaque="' . $opaque . '", qop=auth,nc=' . $nc . ',cnonce="' . $cnonce . '"');
58*a1a3b679SAndreas Boehler
59*a1a3b679SAndreas Boehler        $this->auth->init();
60*a1a3b679SAndreas Boehler
61*a1a3b679SAndreas Boehler        $this->assertEquals($username, $this->auth->getUserName());
62*a1a3b679SAndreas Boehler        $this->assertEquals(self::REALM, $this->auth->getRealm());
63*a1a3b679SAndreas Boehler        $this->assertTrue($this->auth->validateA1(md5($username . ':' . self::REALM . ':' . $password)), 'Authentication is deemed invalid through validateA1');
64*a1a3b679SAndreas Boehler        $this->assertTrue($this->auth->validatePassword($password), 'Authentication is deemed invalid through validatePassword');
65*a1a3b679SAndreas Boehler
66*a1a3b679SAndreas Boehler    }
67*a1a3b679SAndreas Boehler
68*a1a3b679SAndreas Boehler    function testInvalidDigest() {
69*a1a3b679SAndreas Boehler
70*a1a3b679SAndreas Boehler        list($nonce, $opaque) = $this->getServerTokens();
71*a1a3b679SAndreas Boehler
72*a1a3b679SAndreas Boehler        $username = 'admin';
73*a1a3b679SAndreas Boehler        $password = 12345;
74*a1a3b679SAndreas Boehler        $nc = '00002';
75*a1a3b679SAndreas Boehler        $cnonce = uniqid();
76*a1a3b679SAndreas Boehler
77*a1a3b679SAndreas Boehler        $digestHash = md5(
78*a1a3b679SAndreas Boehler            md5($username . ':' . self::REALM . ':' . $password) . ':' .
79*a1a3b679SAndreas Boehler            $nonce . ':' .
80*a1a3b679SAndreas Boehler            $nc . ':' .
81*a1a3b679SAndreas Boehler            $cnonce . ':' .
82*a1a3b679SAndreas Boehler            'auth:' .
83*a1a3b679SAndreas Boehler            md5('GET' . ':' . '/')
84*a1a3b679SAndreas Boehler        );
85*a1a3b679SAndreas Boehler
86*a1a3b679SAndreas Boehler        $this->request->setMethod('GET');
87*a1a3b679SAndreas Boehler        $this->request->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . self::REALM . '", nonce="' . $nonce . '", uri="/", response="' . $digestHash . '", opaque="' . $opaque . '", qop=auth,nc=' . $nc . ',cnonce="' . $cnonce . '"');
88*a1a3b679SAndreas Boehler
89*a1a3b679SAndreas Boehler        $this->auth->init();
90*a1a3b679SAndreas Boehler
91*a1a3b679SAndreas Boehler        $this->assertFalse($this->auth->validateA1(md5($username . ':' . self::REALM . ':' . ($password . 'randomness'))), 'Authentication is deemed invalid through validateA1');
92*a1a3b679SAndreas Boehler
93*a1a3b679SAndreas Boehler    }
94*a1a3b679SAndreas Boehler
95*a1a3b679SAndreas Boehler    function testInvalidDigest2() {
96*a1a3b679SAndreas Boehler
97*a1a3b679SAndreas Boehler        $this->request->setMethod('GET');
98*a1a3b679SAndreas Boehler        $this->request->setHeader('Authorization', 'basic blablabla');
99*a1a3b679SAndreas Boehler
100*a1a3b679SAndreas Boehler        $this->auth->init();
101*a1a3b679SAndreas Boehler        $this->assertFalse($this->auth->validateA1(md5('user:realm:password')));
102*a1a3b679SAndreas Boehler
103*a1a3b679SAndreas Boehler    }
104*a1a3b679SAndreas Boehler
105*a1a3b679SAndreas Boehler
106*a1a3b679SAndreas Boehler    function testDigestAuthInt() {
107*a1a3b679SAndreas Boehler
108*a1a3b679SAndreas Boehler        $this->auth->setQOP(Digest::QOP_AUTHINT);
109*a1a3b679SAndreas Boehler        list($nonce, $opaque) = $this->getServerTokens(Digest::QOP_AUTHINT);
110*a1a3b679SAndreas Boehler
111*a1a3b679SAndreas Boehler        $username = 'admin';
112*a1a3b679SAndreas Boehler        $password = 12345;
113*a1a3b679SAndreas Boehler        $nc = '00003';
114*a1a3b679SAndreas Boehler        $cnonce = uniqid();
115*a1a3b679SAndreas Boehler
116*a1a3b679SAndreas Boehler        $digestHash = md5(
117*a1a3b679SAndreas Boehler            md5($username . ':' . self::REALM . ':' . $password) . ':' .
118*a1a3b679SAndreas Boehler            $nonce . ':' .
119*a1a3b679SAndreas Boehler            $nc . ':' .
120*a1a3b679SAndreas Boehler            $cnonce . ':' .
121*a1a3b679SAndreas Boehler            'auth-int:' .
122*a1a3b679SAndreas Boehler            md5('POST' . ':' . '/' . ':' . md5('body'))
123*a1a3b679SAndreas Boehler        );
124*a1a3b679SAndreas Boehler
125*a1a3b679SAndreas Boehler        $this->request->setMethod('POST');
126*a1a3b679SAndreas Boehler        $this->request->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . self::REALM . '", nonce="' . $nonce . '", uri="/", response="' . $digestHash . '", opaque="' . $opaque . '", qop=auth-int,nc=' . $nc . ',cnonce="' . $cnonce . '"');
127*a1a3b679SAndreas Boehler        $this->request->setBody('body');
128*a1a3b679SAndreas Boehler
129*a1a3b679SAndreas Boehler        $this->auth->init();
130*a1a3b679SAndreas Boehler
131*a1a3b679SAndreas Boehler        $this->assertTrue($this->auth->validateA1(md5($username . ':' . self::REALM . ':' . $password)), 'Authentication is deemed invalid through validateA1');
132*a1a3b679SAndreas Boehler
133*a1a3b679SAndreas Boehler    }
134*a1a3b679SAndreas Boehler
135*a1a3b679SAndreas Boehler    function testDigestAuthBoth() {
136*a1a3b679SAndreas Boehler
137*a1a3b679SAndreas Boehler        $this->auth->setQOP(Digest::QOP_AUTHINT | Digest::QOP_AUTH);
138*a1a3b679SAndreas Boehler        list($nonce, $opaque) = $this->getServerTokens(Digest::QOP_AUTHINT | Digest::QOP_AUTH);
139*a1a3b679SAndreas Boehler
140*a1a3b679SAndreas Boehler        $username = 'admin';
141*a1a3b679SAndreas Boehler        $password = 12345;
142*a1a3b679SAndreas Boehler        $nc = '00003';
143*a1a3b679SAndreas Boehler        $cnonce = uniqid();
144*a1a3b679SAndreas Boehler
145*a1a3b679SAndreas Boehler        $digestHash = md5(
146*a1a3b679SAndreas Boehler            md5($username . ':' . self::REALM . ':' . $password) . ':' .
147*a1a3b679SAndreas Boehler            $nonce . ':' .
148*a1a3b679SAndreas Boehler            $nc . ':' .
149*a1a3b679SAndreas Boehler            $cnonce . ':' .
150*a1a3b679SAndreas Boehler            'auth-int:' .
151*a1a3b679SAndreas Boehler            md5('POST' . ':' . '/' . ':' . md5('body'))
152*a1a3b679SAndreas Boehler        );
153*a1a3b679SAndreas Boehler
154*a1a3b679SAndreas Boehler        $this->request->setMethod('POST');
155*a1a3b679SAndreas Boehler        $this->request->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . self::REALM . '", nonce="' . $nonce . '", uri="/", response="' . $digestHash . '", opaque="' . $opaque . '", qop=auth-int,nc=' . $nc . ',cnonce="' . $cnonce . '"');
156*a1a3b679SAndreas Boehler        $this->request->setBody('body');
157*a1a3b679SAndreas Boehler
158*a1a3b679SAndreas Boehler        $this->auth->init();
159*a1a3b679SAndreas Boehler
160*a1a3b679SAndreas Boehler        $this->assertTrue($this->auth->validateA1(md5($username . ':' . self::REALM . ':' . $password)), 'Authentication is deemed invalid through validateA1');
161*a1a3b679SAndreas Boehler
162*a1a3b679SAndreas Boehler    }
163*a1a3b679SAndreas Boehler
164*a1a3b679SAndreas Boehler
165*a1a3b679SAndreas Boehler    private function getServerTokens($qop = Digest::QOP_AUTH) {
166*a1a3b679SAndreas Boehler
167*a1a3b679SAndreas Boehler        $this->auth->requireLogin();
168*a1a3b679SAndreas Boehler
169*a1a3b679SAndreas Boehler        switch ($qop) {
170*a1a3b679SAndreas Boehler            case Digest::QOP_AUTH    : $qopstr = 'auth'; break;
171*a1a3b679SAndreas Boehler            case Digest::QOP_AUTHINT : $qopstr = 'auth-int'; break;
172*a1a3b679SAndreas Boehler            default                  : $qopstr = 'auth,auth-int'; break;
173*a1a3b679SAndreas Boehler        }
174*a1a3b679SAndreas Boehler
175*a1a3b679SAndreas Boehler        $test = preg_match('/Digest realm="' . self::REALM . '",qop="' . $qopstr . '",nonce="([0-9a-f]*)",opaque="([0-9a-f]*)"/',
176*a1a3b679SAndreas Boehler            $this->response->getHeader('WWW-Authenticate'), $matches);
177*a1a3b679SAndreas Boehler
178*a1a3b679SAndreas Boehler        $this->assertTrue($test == true, 'The WWW-Authenticate response didn\'t match our pattern. We received: ' . $this->response->getHeader('WWW-Authenticate'));
179*a1a3b679SAndreas Boehler
180*a1a3b679SAndreas Boehler        $nonce = $matches[1];
181*a1a3b679SAndreas Boehler        $opaque = $matches[2];
182*a1a3b679SAndreas Boehler
183*a1a3b679SAndreas Boehler        // Reset our environment
184*a1a3b679SAndreas Boehler        $this->setUp();
185*a1a3b679SAndreas Boehler        $this->auth->setQOP($qop);
186*a1a3b679SAndreas Boehler
187*a1a3b679SAndreas Boehler        return [$nonce,$opaque];
188*a1a3b679SAndreas Boehler
189*a1a3b679SAndreas Boehler    }
190*a1a3b679SAndreas Boehler
191*a1a3b679SAndreas Boehler}
192