gitee.com/zhaochuninhefei/fabric-ca-gm@v0.0.2/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/fabric-ca-gm/internal/pkg/api" 19 "gitee.com/zhaochuninhefei/fabric-ca-gm/lib/caerrors" 20 http "gitee.com/zhaochuninhefei/gmgo/gmhttp" 21 tls "gitee.com/zhaochuninhefei/gmgo/gmtls" 22 "gitee.com/zhaochuninhefei/gmgo/x509" 23 "gitee.com/zhaochuninhefei/zcgolog/zclog" 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 }