github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/common/cauthdsl/cauthdsl.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8                   http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package cauthdsl
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"github.com/hyperledger/fabric/common/flogging"
    23  	"github.com/hyperledger/fabric/msp"
    24  	cb "github.com/hyperledger/fabric/protos/common"
    25  	mb "github.com/hyperledger/fabric/protos/msp"
    26  )
    27  
    28  var cauthdslLogger = flogging.MustGetLogger("cauthdsl")
    29  
    30  // compile recursively builds a go evaluatable function corresponding to the policy specified
    31  func compile(policy *cb.SignaturePolicy, identities []*mb.MSPPrincipal, deserializer msp.IdentityDeserializer) (func([]*cb.SignedData, []bool) bool, error) {
    32  	switch t := policy.Type.(type) {
    33  	case *cb.SignaturePolicy_NOutOf_:
    34  		policies := make([]func([]*cb.SignedData, []bool) bool, len(t.NOutOf.Policies))
    35  		for i, policy := range t.NOutOf.Policies {
    36  			compiledPolicy, err := compile(policy, identities, deserializer)
    37  			if err != nil {
    38  				return nil, err
    39  			}
    40  			policies[i] = compiledPolicy
    41  
    42  		}
    43  		return func(signedData []*cb.SignedData, used []bool) bool {
    44  			cauthdslLogger.Debugf("Gate evaluation starts: (%v)", t)
    45  			verified := int32(0)
    46  			_used := make([]bool, len(used))
    47  			for _, policy := range policies {
    48  				copy(_used, used)
    49  				if policy(signedData, _used) {
    50  					verified++
    51  					copy(used, _used)
    52  				}
    53  			}
    54  
    55  			if verified >= t.NOutOf.N {
    56  				cauthdslLogger.Debugf("Gate evaluation succeeds: (%v)", t)
    57  			} else {
    58  				cauthdslLogger.Debugf("Gate evaluation fails: (%v)", t)
    59  			}
    60  
    61  			return verified >= t.NOutOf.N
    62  		}, nil
    63  	case *cb.SignaturePolicy_SignedBy:
    64  		if t.SignedBy < 0 || t.SignedBy >= int32(len(identities)) {
    65  			return nil, fmt.Errorf("Identity index out of range, requested %v, but identies length is %d", t.SignedBy, len(identities))
    66  		}
    67  		signedByID := identities[t.SignedBy]
    68  		return func(signedData []*cb.SignedData, used []bool) bool {
    69  			cauthdslLogger.Debugf("Principal evaluation starts: (%v) (used %v)", t, used)
    70  			for i, sd := range signedData {
    71  				if used[i] {
    72  					continue
    73  				}
    74  				identity, err := deserializer.DeserializeIdentity(sd.Identity)
    75  				if err != nil {
    76  					cauthdslLogger.Errorf("Principal deserialization failed: (%s) for identity %v", err, sd.Identity)
    77  					continue
    78  				}
    79  				err = identity.SatisfiesPrincipal(signedByID)
    80  				if err == nil {
    81  					cauthdslLogger.Debugf("Principal matched by identity: (%v) for %v", t, sd.Identity)
    82  					err = identity.Verify(sd.Data, sd.Signature)
    83  					if err == nil {
    84  						cauthdslLogger.Debugf("Principal evaluation succeeds: (%v) (used %v)", t, used)
    85  						used[i] = true
    86  						return true
    87  					}
    88  				} else {
    89  					cauthdslLogger.Debugf("Identity (%v) does not satisfy principal: %s", sd.Identity, err)
    90  				}
    91  			}
    92  			cauthdslLogger.Debugf("Principal evaluation fails: (%v) %v", t, used)
    93  			return false
    94  		}, nil
    95  	default:
    96  		return nil, fmt.Errorf("Unknown type: %T:%v", t, t)
    97  	}
    98  }