4782: Added 2 functions, at_sign_request() and at_verify_request() to validate tokens...
authorharris wong <hwong@ocad.ca>
Wed, 17 Aug 2011 20:13:42 +0000 (20:13 -0000)
committerharris wong <hwong@ocad.ca>
Wed, 17 Aug 2011 20:13:42 +0000 (20:13 -0000)
docs/mods/_core/users/instructor_requests.php

index 3d9423c..6d5eb64 100644 (file)
@@ -18,6 +18,78 @@ define('AT_INCLUDE_PATH', '../../../include/');
 require(AT_INCLUDE_PATH.'vitals.inc.php');
 admin_authenticate(AT_ADMIN_PRIV_USERS);
 
+/**
+ * A simple method to sign the request with the secret using HMAC.  
+ * @param   String      Use UTC time, gmdate("Y-m-d\TH:i:s\Z");
+ * @param   String      Hashed secret.  Unique per user.   
+ */
+function at_sign_request($timestamp, $publicKey) {
+    global $db;
+    if (!isset($_SESSION['login'])) {
+        return $url;
+    }
+    $sql = 'SELECT last_login FROM ' . TABLE_PREFIX . "admins WHERE login='$_SESSION[login]'";
+    $result = mysql_query($sql, $db);
+    $row = mysql_fetch_assoc($result);
+    //This key should be unique often enough yet binds to the user only.
+    //easier way is to create a key table
+    $privateKey = hash_hmac('sha256', $row['last_login'], $row['password']);
+
+    /* 
+     * Our simple way to sign the key
+     * include GET header, then sort query, add current timestamp, sign it.
+     */
+    $canonicalArray['publicKey'] = $publicKey;
+    $canonicalArray['timestamp'] = $timestamp;
+
+    $str = "GET http/1.0\n";
+    foreach ($canonicalArray as $k => $v) {
+        $str .= "$k=" . rawurlencode($v) . "\n";
+    }
+    $hmacSignature = base64_encode(hash_hmac('sha512', $str, $privateKey, true));
+    return rawurlencode($hmacSignature);
+}
+
+/**
+ * Verify request by the given signedUrl
+ * @param   String      querystring without '?', usually the $_SERVER['QUERY_STRING']
+ *
+ */
+function at_verify_request($signature, $timestamp, $publicKey) {
+    global $db;
+    if ($signature == "" || $timestamp == "" || $publicKey == "") {
+        //if parameters are empty, return false.
+        return false;
+    }
+    $sql = 'SELECT last_login FROM ' . TABLE_PREFIX . "admins WHERE login='$_SESSION[login]'";
+    $result = mysql_query($sql, $db);
+    $row = mysql_fetch_assoc($result);
+    $privateKey = hash_hmac('sha256', $row['last_login'], $row['password']);
+    
+    $canonicalArray = array();
+    $canonicalArray['publicKey'] = $publicKey;
+    $canonicalArray['timestamp'] = $timestamp;
+    //check expirary
+    $timeDiff = time() - strtotime($canonicalArray['timestamp']);
+    if ($timeDiff > 36000) {
+        //more than 10mins, expired.
+        //TODO: use constants.
+        die('time expired');
+        return false;
+    }
+    //check data integrity
+    //generate our own hmac to check
+    $str = "GET http/1.0\n";
+    foreach ($canonicalArray as $k => $v) {
+        $str .= "$k=" . rawurlencode($v) . "\n";
+    }
+    $hmacSignature = base64_encode(hash_hmac('sha512', $str, $privateKey, true));
+    if (rawurldecode($signature) === $hmacSignature) {
+        return true;
+    } 
+    return false;    
+}
+
 if (isset($_GET['deny']) && isset($_GET['id'])) {
        header('Location: admin_deny.php?id='.$_GET['id']);
        exit;
@@ -29,6 +101,13 @@ if (isset($_GET['deny']) && isset($_GET['id'])) {
        */
 
 } else if (isset($_GET['approve']) && isset($_GET['id'])) {
+    //verify token first.
+    if (!at_verify_request($_GET['auth_token'], $_GET['auth_timestamp'], $_GET['auth_publicKey'])) {
+        $msg->addError('INVALID_AUTH_REQUEST');
+        header('Location: instructor_requests.php');
+        exit;
+    }
+    
        $id = intval($_GET['id']);
 
        $sql = 'DELETE FROM '.TABLE_PREFIX.'instructor_approvals WHERE member_id='.$id;
@@ -76,6 +155,10 @@ if (isset($_GET['deny']) && isset($_GET['id'])) {
        $msg->addError('NO_ITEM_SELECTED');
 }
 
+/* Authentication info */
+$timestamp = gmdate("Y-m-d\TH:i:s\Z");
+$publicKey = hash('sha256', mt_rand());
+
 require(AT_INCLUDE_PATH.'header.inc.php'); 
 
 $sql   = "SELECT M.login, M.first_name, M.last_name, M.email, M.member_id, A.* FROM ".TABLE_PREFIX."members M, ".TABLE_PREFIX."instructor_approvals A WHERE A.member_id=M.member_id ORDER BY M.login";
@@ -98,6 +181,9 @@ $num_pending = mysql_num_rows($result);
 <tfoot>
 <tr>
        <td colspan="6">
+       <input type="hidden" name="auth_publicKey" value="<?php echo $publicKey; ?>" />
+       <input type="hidden" name="auth_timestamp" value="<?php echo $timestamp; ?>" />
+       <input type="hidden" name="auth_token" value="<?php echo at_sign_request($timestamp, $publicKey); ?>" />
        <input type="submit" name="deny" value="<?php echo _AT('deny'); ?>" /> 
        <input type="submit" name="approve" value="<?php echo _AT('approve'); ?>" /></td>
 </tr>