github.com/Psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/accesscontrol/accesscontrol_test.go (about)

     1  /*
     2   * Copyright (c) 2018, Psiphon Inc.
     3   * All rights reserved.
     4   *
     5   * This program is free software: you can redistribute it and/or modify
     6   * it under the terms of the GNU General Public License as published by
     7   * the Free Software Foundation, either version 3 of the License, or
     8   * (at your option) any later version.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package accesscontrol
    21  
    22  import (
    23  	"encoding/base64"
    24  	"encoding/json"
    25  	"fmt"
    26  	"testing"
    27  	"time"
    28  )
    29  
    30  func TestAuthorization(t *testing.T) {
    31  
    32  	correctAccess := "access1"
    33  	otherAccess := "access2"
    34  
    35  	correctSigningKey, correctVerificationKey, err := NewKeyPair(correctAccess)
    36  	if err != nil {
    37  		t.Fatalf("NewKeyPair failed: %s", err)
    38  	}
    39  
    40  	otherSigningKey, otherVerificationKey, err := NewKeyPair(otherAccess)
    41  	if err != nil {
    42  		t.Fatalf("NewKeyPair failed: %s", err)
    43  	}
    44  
    45  	invalidSigningKey, _, err := NewKeyPair(correctAccess)
    46  	if err != nil {
    47  		t.Fatalf("NewKeyPair failed: %s", err)
    48  	}
    49  
    50  	keyRing := &VerificationKeyRing{
    51  		Keys: []*VerificationKey{correctVerificationKey, otherVerificationKey},
    52  	}
    53  
    54  	// Test: valid key
    55  
    56  	err = ValidateSigningKey(correctSigningKey)
    57  	if err != nil {
    58  		t.Fatalf("ValidateSigningKey failed: %s", err)
    59  	}
    60  
    61  	// Test: invalid key
    62  
    63  	err = ValidateSigningKey(&SigningKey{})
    64  	if err == nil {
    65  		t.Fatalf("ValidateSigningKey unexpected success")
    66  	}
    67  
    68  	// Test: valid key ring
    69  
    70  	err = ValidateVerificationKeyRing(keyRing)
    71  	if err != nil {
    72  		t.Fatalf("ValidateVerificationKeyRing failed: %s", err)
    73  	}
    74  
    75  	// Test: invalid key ring
    76  
    77  	invalidKeyRing := &VerificationKeyRing{
    78  		Keys: []*VerificationKey{&VerificationKey{}},
    79  	}
    80  
    81  	err = ValidateVerificationKeyRing(invalidKeyRing)
    82  	if err == nil {
    83  		t.Fatalf("ValidateVerificationKeyRing unexpected success")
    84  	}
    85  
    86  	// Test: valid authorization
    87  
    88  	id := []byte("0000000000000001")
    89  
    90  	expires := time.Now().Add(10 * time.Second)
    91  
    92  	auth, issuedID, err := IssueAuthorization(correctSigningKey, id, expires)
    93  	if err != nil {
    94  		t.Fatalf("IssueAuthorization failed: %s", err)
    95  	}
    96  
    97  	// Test: re-issuing authorization with the same seedAuthorizationID yields
    98  	// the same value
    99  
   100  	reauth, _, err := IssueAuthorization(correctSigningKey, id, expires)
   101  	if err != nil {
   102  		t.Fatalf("IssueAuthorization failed: %s", err)
   103  	}
   104  
   105  	if auth != reauth {
   106  		t.Fatalf("unexpected difference in authorizations")
   107  	}
   108  
   109  	// Decode the signed authorization and check that the auth ID in the JSON
   110  	// matches the one returned by IssueAuthorization.
   111  
   112  	decodedAuthorization, err := base64.StdEncoding.DecodeString(auth)
   113  	if err != nil {
   114  		t.Fatalf("DecodeString failed: %s", err)
   115  	}
   116  
   117  	type partialSignedAuthorization struct {
   118  		Authorization json.RawMessage
   119  	}
   120  	var partialSignedAuth partialSignedAuthorization
   121  	err = json.Unmarshal(decodedAuthorization, &partialSignedAuth)
   122  	if err != nil {
   123  		t.Fatalf("Unmarshal failed: %s", err)
   124  	}
   125  
   126  	var unmarshaledAuth map[string]interface{}
   127  	err = json.Unmarshal(partialSignedAuth.Authorization, &unmarshaledAuth)
   128  	if err != nil {
   129  		t.Fatalf("Unmarshal failed: %s", err)
   130  	}
   131  
   132  	authID, ok := unmarshaledAuth["ID"].(string)
   133  	if !ok {
   134  		t.Fatalf("Failed to find auth ID in unmarshaled auth: %s", unmarshaledAuth)
   135  	}
   136  
   137  	if string(authID) != base64.StdEncoding.EncodeToString(issuedID) {
   138  		t.Fatalf("Expected auth ID in signed auth (%s) to match that returned by IssueAuthorization (%s)", string(authID), base64.StdEncoding.EncodeToString(issuedID))
   139  	}
   140  
   141  	fmt.Printf("encoded authorization length: %d\n", len(auth))
   142  
   143  	verifiedAuth, err := VerifyAuthorization(keyRing, auth)
   144  	if err != nil {
   145  		t.Fatalf("VerifyAuthorization failed: %s", err)
   146  	}
   147  
   148  	if verifiedAuth.AccessType != correctAccess {
   149  		t.Fatalf("unexpected access type: %s", verifiedAuth.AccessType)
   150  	}
   151  
   152  	// Test: expired authorization
   153  
   154  	expires = time.Now().Add(-10 * time.Second)
   155  
   156  	auth, _, err = IssueAuthorization(correctSigningKey, id, expires)
   157  	if err != nil {
   158  		t.Fatalf("IssueAuthorization failed: %s", err)
   159  	}
   160  
   161  	_, err = VerifyAuthorization(keyRing, auth)
   162  	// TODO: check error message?
   163  	if err == nil {
   164  		t.Fatalf("VerifyAuthorization unexpected success")
   165  	}
   166  
   167  	// Test: authorization signed with key not in key ring
   168  
   169  	expires = time.Now().Add(10 * time.Second)
   170  
   171  	auth, _, err = IssueAuthorization(invalidSigningKey, id, expires)
   172  	if err != nil {
   173  		t.Fatalf("IssueAuthorization failed: %s", err)
   174  	}
   175  
   176  	_, err = VerifyAuthorization(keyRing, auth)
   177  	// TODO: check error message?
   178  	if err == nil {
   179  		t.Fatalf("VerifyAuthorization unexpected success")
   180  	}
   181  
   182  	// Test: authorization signed with valid key, but hacked access type
   183  
   184  	expires = time.Now().Add(10 * time.Second)
   185  
   186  	auth, _, err = IssueAuthorization(otherSigningKey, id, expires)
   187  	if err != nil {
   188  		t.Fatalf("IssueAuthorization failed: %s", err)
   189  	}
   190  
   191  	decodedAuth, err := base64.StdEncoding.DecodeString(auth)
   192  	if err != nil {
   193  		t.Fatalf("DecodeString failed: %s", err)
   194  	}
   195  
   196  	var hackSignedAuth signedAuthorization
   197  	err = json.Unmarshal(decodedAuth, &hackSignedAuth)
   198  	if err != nil {
   199  		t.Fatalf("Unmarshal failed: %s", err)
   200  	}
   201  
   202  	var hackAuth Authorization
   203  	err = json.Unmarshal(hackSignedAuth.Authorization, &hackAuth)
   204  	if err != nil {
   205  		t.Fatalf("Unmarshal failed: %s", err)
   206  	}
   207  
   208  	hackAuth.AccessType = correctAccess
   209  
   210  	marshaledAuth, err := json.Marshal(hackAuth)
   211  	if err != nil {
   212  		t.Fatalf("Marshall failed: %s", err)
   213  	}
   214  
   215  	hackSignedAuth.Authorization = marshaledAuth
   216  
   217  	marshaledSignedAuth, err := json.Marshal(hackSignedAuth)
   218  	if err != nil {
   219  		t.Fatalf("Marshall failed: %s", err)
   220  	}
   221  
   222  	encodedSignedAuth := base64.StdEncoding.EncodeToString(marshaledSignedAuth)
   223  
   224  	_, err = VerifyAuthorization(keyRing, encodedSignedAuth)
   225  	// TODO: check error message?
   226  	if err == nil {
   227  		t.Fatalf("VerifyAuthorization unexpected success")
   228  	}
   229  }