Completed
Push — master ( 75babc...67a09a )
by Paul
03:02
created

index.php ➔ updateReg()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 1
eloc 4
c 2
b 0
f 1
nc 1
nop 1
dl 0
loc 5
rs 9.4285
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 52 and the first side effect is on line 36.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Copyright (c) 2014 Yubico AB
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are
8
 * met:
9
 *
10
 *   * Redistributions of source code must retain the above copyright
11
 *     notice, this list of conditions and the following disclaimer.
12
 *
13
 *   * Redistributions in binary form must reproduce the above
14
 *     copyright notice, this list of conditions and the following
15
 *     disclaimer in the documentation and/or other materials provided
16
 *     with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 */
30
31
/**
32
 * This is a simple example using PDO and a sqlite database for storing
33
 * registrations. It supports multiple registrations associated with each user.
34
 */
35
36
require_once('../../src/u2flib_server/U2F.php');
37
38
$dbfile = '/var/tmp/u2f-pdo.sqlite';
39
40
$pdo = new PDO("sqlite:$dbfile");
41
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
42
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
43
44
$pdo->exec("create table if not exists users (id integer primary key, name varchar(255))");
45
$pdo->exec("create table if not exists registrations (id integer primary key, user_id integer, keyHandle varchar(255), publicKey varchar(255), certificate text, counter integer)");
46
47
$scheme = isset($_SERVER['HTTPS']) ? "https://" : "http://";
48
$u2f = new u2flib_server\U2F($scheme . $_SERVER['HTTP_HOST']);
49
50
session_start();
51
52
function createAndGetUser($name) {
53
    global $pdo;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
54
    $sel = $pdo->prepare("select * from users where name = ?");
55
    $sel->execute(array($name));
56
    $user = $sel->fetch();
57
    if(!$user) {
58
        $ins = $pdo->prepare("insert into users (name) values(?)");
59
        $ins->execute(array($name));
60
        $sel->execute(array($name));
61
        $user = $sel->fetch();
62
    }
63
    return $user;
64
}
65
66
function getRegs($user_id) {
67
    global $pdo;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
68
    $sel = $pdo->prepare("select * from registrations where user_id = ?");
69
    $sel->execute(array($user_id));
70
    return $sel->fetchAll();
71
}
72
73
function addReg($user_id, $reg) {
74
    global $pdo;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
75
    $ins = $pdo->prepare("insert into registrations (user_id, keyHandle, publicKey, certificate, counter) values (?, ?, ?, ?, ?)");
76
    $ins->execute(array($user_id, $reg->keyHandle, $reg->publicKey, $reg->certificate, $reg->counter));
77
}
78
79
function updateReg($reg) {
80
    global $pdo;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
81
    $upd = $pdo->prepare("update registrations set counter = ? where id = ?");
82
    $upd->execute(array($reg->counter, $reg->id));
83
}
84
85
?>
86
87
<html>
88
<head>
89
    <title>PHP U2F example</title>
90
91
    <script src="../assets/u2f-api.js"></script>
92
93
    <script>
94
        <?php
95
96
        if($_SERVER['REQUEST_METHOD'] === 'POST') {
97
          if(!$_POST['username']) {
98
            echo "alert('no username provided!');";
99
          } else if(!isset($_POST['action']) && !isset($_POST['register2']) && !isset($_POST['authenticate2'])) {
100
            echo "alert('no action provided!');";
101
          } else {
102
            $user = createAndGetUser($_POST['username']);
103
104
            if(isset($_POST['action'])) {
105
              switch($_POST['action']):
106
                case 'register':
107
                  try {
108
                    $data = $u2f->getRegisterData(getRegs($user->id));
109
110
                    list($req,$sigs) = $data;
111
                    $_SESSION['regReq'] = json_encode($req);
112
                    echo "var req = " . json_encode($req) . ";";
113
                    echo "var sigs = " . json_encode($sigs) . ";";
114
                    echo "var username = '" . $user->name . "';";
115
        ?>
116
        setTimeout(function() {
117
            console.log("Register: ", req);
118
            u2f.register([req], sigs, function(data) {
119
                var form = document.getElementById('form');
120
                var reg = document.getElementById('register2');
121
                var user = document.getElementById('username');
122
                console.log("Register callback", data);
123
                if(data.errorCode) {
124
                    alert("registration failed with errror: " + data.errorCode);
125
                    return;
126
                }
127
                reg.value = JSON.stringify(data);
128
                user.value = username;
129
                form.submit();
130
            });
131
        }, 1000);
132
        <?php
133
                  } catch( Exception $e ) {
134
                    echo "alert('error: " . $e->getMessage() . "');";
135
                  }
136
137
                  break;
138
139
                case 'authenticate':
140
                  try {
141
                    $reqs = json_encode($u2f->getAuthenticateData(getRegs($user->id)));
142
143
                    $_SESSION['authReq'] = $reqs;
144
                    echo "var req = $reqs;";
145
                    echo "var username = '" . $user->name . "';";
146
        ?>
147
        setTimeout(function() {
148
            console.log("sign: ", req);
149
            u2f.sign(req, function(data) {
150
                var form = document.getElementById('form');
151
                var auth = document.getElementById('authenticate2');
152
                var user = document.getElementById('username');
153
                console.log("Authenticate callback", data);
154
                auth.value=JSON.stringify(data);
155
                user.value = username;
156
                form.submit();
157
            });
158
        }, 1000);
159
        <?php
160
                  } catch( Exception $e ) {
161
                    echo "alert('error: " . $e->getMessage() . "');";
162
                  }
163
164
                  break;
165
166
              endswitch;
167
            } else if($_POST['register2']) {
168
              try {
169
                $reg = $u2f->doRegister(json_decode($_SESSION['regReq']), json_decode($_POST['register2']));
170
                addReg($user->id, $reg);
171
              } catch( Exception $e ) {
172
                echo "alert('error: " . $e->getMessage() . "');";
173
              } finally {
174
                $_SESSION['regReq'] = null;
175
              }
176
            } else if($_POST['authenticate2']) {
177
              try {
178
                $reg = $u2f->doAuthenticate(json_decode($_SESSION['authReq']), getRegs($user->id), json_decode($_POST['authenticate2']));
179
                updateReg($reg);
180
                echo "alert('success: " . $reg->counter . "');";
181
              } catch( Exception $e ) {
182
                echo "alert('error: " . $e->getMessage() . "');";
183
              } finally {
184
                $_SESSION['authReq'] = null;
185
              }
186
            }
187
          }
188
        }
189
        ?>
190
    </script>
191
</head>
192
<body>
193
194
<form method="POST" id="form">
195
    username: <input name="username" id="username"/><br/>
196
    register: <input value="register" name="action" type="radio"/><br/>
197
    authenticate: <input value="authenticate" name="action" type="radio"/><br/>
198
    <input type="hidden" name="register2" id="register2"/>
199
    <input type="hidden" name="authenticate2" id="authenticate2"/>
200
    <button type="submit">Submit!</button>
201
</form>
202
203
</body>
204
</html>
205