github.com/hxx258456/fabric-ca-gm@v0.0.3-0.20221111064038-a268ad7e3a37/lib/util.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package lib
     8  
     9  import (
    10  	"encoding/json"
    11  	"encoding/pem"
    12  	"fmt"
    13  	"io/ioutil"
    14  	"os"
    15  	"path/filepath"
    16  	"strings"
    17  
    18  	"gitee.com/zhaochuninhefei/zcgolog/zclog"
    19  	http "github.com/hxx258456/ccgo/gmhttp"
    20  	tls "github.com/hxx258456/ccgo/gmtls"
    21  	"github.com/hxx258456/ccgo/x509"
    22  	"github.com/hxx258456/fabric-ca-gm/internal/pkg/api"
    23  	"github.com/hxx258456/fabric-ca-gm/lib/caerrors"
    24  	"github.com/pkg/errors"
    25  	"github.com/spf13/viper"
    26  )
    27  
    28  var clientAuthTypes = map[string]tls.ClientAuthType{
    29  	"noclientcert":               tls.NoClientCert,
    30  	"requestclientcert":          tls.RequestClientCert,
    31  	"requireanyclientcert":       tls.RequireAnyClientCert,
    32  	"verifyclientcertifgiven":    tls.VerifyClientCertIfGiven,
    33  	"requireandverifyclientcert": tls.RequireAndVerifyClientCert,
    34  }
    35  
    36  // BytesToX509Cert converts bytes (PEM or DER) to an X509 certificate
    37  func BytesToX509Cert(bytes []byte) (*x509.Certificate, error) {
    38  	dcert, _ := pem.Decode(bytes)
    39  	if dcert != nil {
    40  		bytes = dcert.Bytes
    41  	}
    42  	cert, err := x509.ParseCertificate(bytes)
    43  	if err != nil {
    44  		return nil, errors.Wrap(err, "Buffer was neither PEM nor DER encoding")
    45  	}
    46  	return cert, err
    47  }
    48  
    49  // LoadPEMCertPool loads a pool of PEM certificates from list of files
    50  func LoadPEMCertPool(certFiles []string) (*x509.CertPool, error) {
    51  	certPool := x509.NewCertPool()
    52  
    53  	if len(certFiles) > 0 {
    54  		for _, cert := range certFiles {
    55  			zclog.Debugf("Reading cert file: %s", cert)
    56  			pemCerts, err := ioutil.ReadFile(cert)
    57  			if err != nil {
    58  				return nil, err
    59  			}
    60  
    61  			zclog.Debugf("Appending cert %s to pool", cert)
    62  			if !certPool.AppendCertsFromPEM(pemCerts) {
    63  				return nil, errors.New("Failed to load cert pool")
    64  			}
    65  		}
    66  	}
    67  
    68  	return certPool, nil
    69  }
    70  
    71  // UnmarshalConfig unmarshals a configuration file
    72  func UnmarshalConfig(config interface{}, vp *viper.Viper, configFile string,
    73  	server bool) error {
    74  
    75  	vp.SetConfigFile(configFile)
    76  	err := vp.ReadInConfig()
    77  	if err != nil {
    78  		return errors.Wrapf(err, "Failed to read config file '%s'", configFile)
    79  	}
    80  
    81  	err = vp.Unmarshal(config)
    82  	if err != nil {
    83  		return errors.Wrapf(err, "Incorrect format in file '%s'", configFile)
    84  	}
    85  	if server {
    86  		serverCfg := config.(*ServerConfig)
    87  		err = vp.Unmarshal(&serverCfg.CAcfg)
    88  		if err != nil {
    89  			return errors.Wrapf(err, "Incorrect format in file '%s'", configFile)
    90  		}
    91  	}
    92  	return nil
    93  }
    94  
    95  // 获取该注册用户能拉取证书的最大次数
    96  //  根据请求的MaxEnrollments与ca配置的MaxEnrollments确定实际的MaxEnrollments
    97  //  请求值<-1直接返回0和错误
    98  //  ca配置为-1而请求为0,则返回-1
    99  //  ca配置为-1而请求非0,返回请求值
   100  //  ca配置为0返回0和错误
   101  //  ca配置>0,请求-1,返回0和错误
   102  //  ca配置>0,请求0,返回ca配置
   103  //  ca配置>0,请求>ca配置,返回0和错误
   104  //  ca配置>0,请求>0且<=ca配置,返回请求值
   105  func getMaxEnrollments(userMaxEnrollments int, caMaxEnrollments int) (int, error) {
   106  	zclog.Debugf("Max enrollment value verification - User specified max enrollment: %d, CA max enrollment: %d", userMaxEnrollments, caMaxEnrollments)
   107  	if userMaxEnrollments < -1 {
   108  		return 0, caerrors.NewHTTPErr(400, caerrors.ErrInvalidMaxEnroll, "Max enrollment in registration request may not be less than -1, but was %d", userMaxEnrollments)
   109  	}
   110  	switch caMaxEnrollments {
   111  	case -1:
   112  		if userMaxEnrollments == 0 {
   113  			// The user is requesting the matching limit of the CA, so gets infinite
   114  			return caMaxEnrollments, nil
   115  		}
   116  		// There is no CA max enrollment limit, so simply use the user requested value
   117  		return userMaxEnrollments, nil
   118  	case 0:
   119  		// The CA max enrollment is 0, so registration is disabled.
   120  		return 0, caerrors.NewHTTPErr(400, caerrors.ErrInvalidMaxEnroll, "Registration is disabled")
   121  	default:
   122  		switch userMaxEnrollments {
   123  		case -1:
   124  			// User requested infinite enrollments is not allowed
   125  			return 0, caerrors.NewHTTPErr(400, caerrors.ErrInvalidMaxEnroll, "Registration for infinite enrollments is not allowed")
   126  		case 0:
   127  			// User is requesting the current CA maximum
   128  			return caMaxEnrollments, nil
   129  		default:
   130  			// User is requesting a specific positive value; make sure it doesn't exceed the CA maximum.
   131  			if userMaxEnrollments > caMaxEnrollments {
   132  				return 0, caerrors.NewHTTPErr(400, caerrors.ErrInvalidMaxEnroll, "Requested enrollments (%d) exceeds maximum allowable enrollments (%d)", userMaxEnrollments, caMaxEnrollments)
   133  			}
   134  			// otherwise, use the requested maximum
   135  			return userMaxEnrollments, nil
   136  		}
   137  	}
   138  }
   139  
   140  func addQueryParm(req *http.Request, name, value string) {
   141  	url := req.URL.Query()
   142  	url.Add(name, value)
   143  	req.URL.RawQuery = url.Encode()
   144  }
   145  
   146  // IdentityDecoder decodes streams of data coming from the server into an Identity object
   147  func IdentityDecoder(decoder *json.Decoder) error {
   148  	var id api.IdentityInfo
   149  	err := decoder.Decode(&id)
   150  	if err != nil {
   151  		return err
   152  	}
   153  	fmt.Printf("Name: %s, Type: %s, Affiliation: %s, Max Enrollments: %d, Attributes: %+v\n", id.ID, id.Type, id.Affiliation, id.MaxEnrollments, id.Attributes)
   154  	return nil
   155  }
   156  
   157  // TODO 代码补充
   158  // AffiliationDecoder decodes streams of data coming from the server into an Affiliation object
   159  func AffiliationDecoder(decoder *json.Decoder) error {
   160  	var aff api.AffiliationInfo
   161  	err := decoder.Decode(&aff)
   162  	if err != nil {
   163  		return err
   164  	}
   165  	fmt.Printf("%s\n", aff.Name)
   166  	return nil
   167  }
   168  
   169  // CertificateDecoder is needed to keep track of state, to see how many certificates
   170  // have been returned for each enrollment ID.
   171  type CertificateDecoder struct {
   172  	certIDCount map[string]int
   173  	storePath   string
   174  }
   175  
   176  // NewCertificateDecoder returns decoder for certificates
   177  func NewCertificateDecoder(storePath string) *CertificateDecoder {
   178  	cd := &CertificateDecoder{}
   179  	cd.certIDCount = make(map[string]int)
   180  	cd.storePath = storePath
   181  	return cd
   182  }
   183  
   184  // CertificateDecoder decodes streams of data coming from the server
   185  func (cd *CertificateDecoder) CertificateDecoder(decoder *json.Decoder) error {
   186  	var cert certPEM
   187  	err := decoder.Decode(&cert)
   188  	if err != nil {
   189  		return err
   190  	}
   191  	block, rest := pem.Decode([]byte(cert.PEM))
   192  	if block == nil || len(rest) > 0 {
   193  		return errors.New("Certificate decoding error")
   194  	}
   195  	certificate, err := x509.ParseCertificate(block.Bytes)
   196  	if err != nil {
   197  		return err
   198  	}
   199  	enrollmentID := certificate.Subject.CommonName
   200  	if cd.storePath != "" {
   201  		err = cd.storeCert(enrollmentID, cd.storePath, []byte(cert.PEM))
   202  		if err != nil {
   203  			return err
   204  		}
   205  	}
   206  	result, err := x509.CertificateText(certificate)
   207  	if err != nil {
   208  		return err
   209  	}
   210  	zclog.Infof("===== lib/util.go CertificateDecoder 证书内容: \n%s\n", result)
   211  	return nil
   212  }
   213  
   214  // storeCert stores the certificate on the file system
   215  func (cd *CertificateDecoder) storeCert(enrollmentID, storePath string, cert []byte) error {
   216  	cd.certIDCount[enrollmentID] = cd.certIDCount[enrollmentID] + 1
   217  
   218  	err := os.MkdirAll(storePath, os.ModePerm)
   219  	if err != nil {
   220  		return err
   221  	}
   222  
   223  	var filePath string
   224  	singleCertName := fmt.Sprintf("%s.pem", enrollmentID)
   225  	switch cd.certIDCount[enrollmentID] {
   226  	case 1: // Only one certificate returned, don't need to append number to certificate file name
   227  		filePath = filepath.Join(storePath, singleCertName)
   228  	case 2: // Two certificates returned, rename the old certificate to have number at the end
   229  		err := os.Rename(filepath.Join(storePath, singleCertName), filepath.Join(storePath, fmt.Sprintf("%s-1.pem", enrollmentID)))
   230  		if err != nil {
   231  			return errors.WithMessage(err, fmt.Sprintf("Failed to rename certificate: %s", singleCertName))
   232  		}
   233  		filePath = filepath.Join(storePath, fmt.Sprintf("%s-%d.pem", enrollmentID, cd.certIDCount[enrollmentID]))
   234  	default:
   235  		filePath = filepath.Join(storePath, fmt.Sprintf("%s-%d.pem", enrollmentID, cd.certIDCount[enrollmentID]))
   236  	}
   237  
   238  	err = ioutil.WriteFile(filePath, cert, 0644)
   239  	if err != nil {
   240  		return errors.WithMessage(err, fmt.Sprintf("Failed to store certificate at: %s", storePath))
   241  	}
   242  
   243  	return nil
   244  }
   245  
   246  // // SM2证书请求 转换 X509 证书请求
   247  // func ParseSm2CertificateRequest2X509(sm2req *gx509.CertificateRequest) *x509.CertificateRequest {
   248  // 	x509req := &x509.CertificateRequest{
   249  // 		Raw:                      sm2req.Raw,                      // Complete ASN.1 DER content (CSR, signature algorithm and signature).
   250  // 		RawTBSCertificateRequest: sm2req.RawTBSCertificateRequest, // Certificate request info part of raw ASN.1 DER content.
   251  // 		RawSubjectPublicKeyInfo:  sm2req.RawSubjectPublicKeyInfo,  // DER encoded SubjectPublicKeyInfo.
   252  // 		RawSubject:               sm2req.RawSubject,               // DER encoded Subject.
   253  
   254  // 		Version:            sm2req.Version,
   255  // 		Signature:          sm2req.Signature,
   256  // 		SignatureAlgorithm: x509.SignatureAlgorithm(sm2req.SignatureAlgorithm),
   257  
   258  // 		PublicKeyAlgorithm: x509.PublicKeyAlgorithm(sm2req.PublicKeyAlgorithm),
   259  // 		PublicKey:          sm2req.PublicKey,
   260  
   261  // 		Subject: sm2req.Subject,
   262  
   263  // 		// Attributes is the dried husk of a bug and shouldn't be used.
   264  // 		Attributes: sm2req.Attributes,
   265  
   266  // 		// Extensions contains raw X.509 extensions. When parsing CSRs, this
   267  // 		// can be used to extract extensions that are not parsed by this
   268  // 		// package.
   269  // 		Extensions: sm2req.Extensions,
   270  
   271  // 		// ExtraExtensions contains extensions to be copied, raw, into any
   272  // 		// marshaled CSR. Values override any extensions that would otherwise
   273  // 		// be produced based on the other fields but are overridden by any
   274  // 		// extensions specified in Attributes.
   275  // 		//
   276  // 		// The ExtraExtensions field is not populated when parsing CSRs, see
   277  // 		// Extensions.
   278  // 		ExtraExtensions: sm2req.ExtraExtensions,
   279  
   280  // 		// Subject Alternate Name values.
   281  // 		DNSNames:       sm2req.DNSNames,
   282  // 		EmailAddresses: sm2req.EmailAddresses,
   283  // 		IPAddresses:    sm2req.IPAddresses,
   284  // 	}
   285  // 	return x509req
   286  // }
   287  
   288  var providerName string
   289  
   290  func IsGMConfig() bool {
   291  	// 目前强制使用国密
   292  	if providerName == "" {
   293  		return true
   294  	}
   295  	if strings.ToUpper(providerName) == "SW" {
   296  		return true
   297  	}
   298  	if strings.ToUpper(providerName) == "GM" {
   299  		return true
   300  	}
   301  	return true
   302  }
   303  
   304  func SetProviderName(name string) {
   305  	providerName = name
   306  }