github.com/ldc1995/fabric-ca@v2.0.0-alpha.0.20200422214819-8d49c278c386+incompatible/lib/serverrequestcontext.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  	"crypto/x509"
    11  	"encoding/hex"
    12  	"encoding/json"
    13  	"fmt"
    14  	"io/ioutil"
    15  	"net/http"
    16  	"strconv"
    17  	"strings"
    18  
    19  	"github.com/cloudflare/cfssl/config"
    20  	"github.com/cloudflare/cfssl/log"
    21  	"github.com/cloudflare/cfssl/revoke"
    22  	"github.com/cloudflare/cfssl/signer"
    23  	gmux "github.com/gorilla/mux"
    24  	"github.com/hyperledger/fabric-ca/api"
    25  	"github.com/hyperledger/fabric-ca/lib/attr"
    26  	"github.com/hyperledger/fabric-ca/lib/attrmgr"
    27  	"github.com/hyperledger/fabric-ca/lib/caerrors"
    28  	cr "github.com/hyperledger/fabric-ca/lib/server/certificaterequest"
    29  	"github.com/hyperledger/fabric-ca/lib/server/idemix"
    30  	"github.com/hyperledger/fabric-ca/lib/server/user"
    31  	"github.com/hyperledger/fabric-ca/util"
    32  	"github.com/jmoiron/sqlx"
    33  	"github.com/pkg/errors"
    34  )
    35  
    36  // ServerRequestContext defines the functionality of a server request context object
    37  type ServerRequestContext interface {
    38  	BasicAuthentication() (string, error)
    39  	TokenAuthentication() (string, error)
    40  	GetCaller() (user.User, error)
    41  	HasRole(role string) error
    42  	ChunksToDeliver(string) (int, error)
    43  	GetReq() *http.Request
    44  	GetQueryParm(name string) string
    45  	GetBoolQueryParm(name string) (bool, error)
    46  	GetResp() http.ResponseWriter
    47  	GetCertificates(cr.CertificateRequest, string) (*sqlx.Rows, error)
    48  	IsLDAPEnabled() bool
    49  	ReadBody(interface{}) error
    50  	ContainsAffiliation(string) error
    51  	CanActOnType(string) error
    52  }
    53  
    54  // serverRequestContextImpl represents an HTTP request/response context in the server
    55  type serverRequestContextImpl struct {
    56  	req            *http.Request
    57  	resp           http.ResponseWriter
    58  	endpoint       *serverEndpoint
    59  	ca             *CA
    60  	enrollmentID   string
    61  	enrollmentCert *x509.Certificate
    62  	ui             user.User
    63  	caller         user.User
    64  	body           struct {
    65  		read bool   // true after body is read
    66  		buf  []byte // the body itself
    67  		err  error  // any error from reading the body
    68  	}
    69  	callerRoles map[string]bool
    70  }
    71  
    72  const (
    73  	registrarRole = "hf.Registrar.Roles"
    74  )
    75  
    76  // newServerRequestContext is the constructor for a serverRequestContextImpl
    77  func newServerRequestContext(r *http.Request, w http.ResponseWriter, se *serverEndpoint) *serverRequestContextImpl {
    78  	return &serverRequestContextImpl{
    79  		req:      r,
    80  		resp:     w,
    81  		endpoint: se,
    82  	}
    83  }
    84  
    85  // BasicAuthentication authenticates the caller's username and password
    86  // found in the authorization header and returns the username
    87  func (ctx *serverRequestContextImpl) BasicAuthentication() (string, error) {
    88  	r := ctx.req
    89  	// Get the authorization header
    90  	authHdr := r.Header.Get("authorization")
    91  	if authHdr == "" {
    92  		return "", caerrors.NewHTTPErr(401, caerrors.ErrNoAuthHdr, "No authorization header")
    93  	}
    94  	// Extract the username and password from the header
    95  	username, password, ok := r.BasicAuth()
    96  	if !ok {
    97  		return "", caerrors.NewAuthenticationErr(caerrors.ErrNoUserPass, "No user/pass in authorization header")
    98  	}
    99  	// Get the CA that is targeted by this request
   100  	ca, err := ctx.GetCA()
   101  	if err != nil {
   102  		return "", err
   103  	}
   104  	// Error if max enrollments is disabled for this CA
   105  	log.Debugf("ca.Config: %+v", ca.Config)
   106  	caMaxEnrollments := ca.Config.Registry.MaxEnrollments
   107  	if caMaxEnrollments == 0 {
   108  		return "", caerrors.NewAuthenticationErr(caerrors.ErrEnrollDisabled, "Enroll is disabled")
   109  	}
   110  	// Get the user info object for this user
   111  	ctx.ui, err = ca.registry.GetUser(username, nil)
   112  	if err != nil {
   113  		return "", caerrors.NewAuthenticationErr(caerrors.ErrInvalidUser, "Failed to get user: %s", err)
   114  	}
   115  
   116  	attempts := ctx.ui.GetFailedLoginAttempts()
   117  	allowedAttempts := ca.Config.Cfg.Identities.PasswordAttempts
   118  	if allowedAttempts > 0 {
   119  		if attempts == ca.Config.Cfg.Identities.PasswordAttempts {
   120  			msg := fmt.Sprintf("Incorrect password entered %d times, max incorrect password limit of %d reached", attempts, ca.Config.Cfg.Identities.PasswordAttempts)
   121  			log.Errorf(msg)
   122  			return "", caerrors.NewHTTPErr(401, caerrors.ErrPasswordAttempts, msg)
   123  		}
   124  	}
   125  
   126  	// Check the user's password and max enrollments if supported by registry
   127  	err = ctx.ui.Login(password, caMaxEnrollments)
   128  	if err != nil {
   129  		return "", caerrors.NewAuthenticationErr(caerrors.ErrInvalidPass, "Login failure: %s", err)
   130  	}
   131  	// Store the enrollment ID associated with this server request context
   132  	ctx.enrollmentID = username
   133  	ctx.caller, err = ctx.GetCaller()
   134  	if err != nil {
   135  		return "", err
   136  	}
   137  	// Return the username
   138  	return username, nil
   139  }
   140  
   141  // TokenAuthentication authenticates the caller by token
   142  // in the authorization header.
   143  // Returns the enrollment ID or error.
   144  func (ctx *serverRequestContextImpl) TokenAuthentication() (string, error) {
   145  	r := ctx.req
   146  	// Get the authorization header
   147  	authHdr := r.Header.Get("authorization")
   148  	if authHdr == "" {
   149  		return "", caerrors.NewHTTPErr(401, caerrors.ErrNoAuthHdr, "No authorization header")
   150  	}
   151  	// Get the CA
   152  	ca, err := ctx.GetCA()
   153  	if err != nil {
   154  		return "", err
   155  	}
   156  	// Get the request body
   157  	body, err := ctx.ReadBodyBytes()
   158  	if err != nil {
   159  		return "", err
   160  	}
   161  	if idemix.IsToken(authHdr) {
   162  		return ctx.verifyIdemixToken(authHdr, r.Method, r.URL.RequestURI(), body)
   163  	}
   164  	return ctx.verifyX509Token(ca, authHdr, r.Method, r.URL.RequestURI(), body)
   165  }
   166  
   167  func (ctx *serverRequestContextImpl) verifyIdemixToken(authHdr, method, uri string, body []byte) (string, error) {
   168  	log.Debug("Caller is using Idemix credential")
   169  	var err error
   170  
   171  	ctx.enrollmentID, err = ctx.ca.issuer.VerifyToken(authHdr, method, uri, body)
   172  	if err != nil {
   173  		return "", err
   174  	}
   175  
   176  	caller, err := ctx.GetCaller()
   177  	if err != nil {
   178  		return "", err
   179  	}
   180  
   181  	if caller.IsRevoked() {
   182  		return "", caerrors.NewAuthorizationErr(caerrors.ErrRevokedID, "Enrollment ID is revoked, unable to process request")
   183  	}
   184  
   185  	return ctx.enrollmentID, nil
   186  }
   187  
   188  func (ctx *serverRequestContextImpl) verifyX509Token(ca *CA, authHdr, method, uri string, body []byte) (string, error) {
   189  	log.Debug("Caller is using a x509 certificate")
   190  	// Verify the token; the signature is over the header and body
   191  	cert, err2 := util.VerifyToken(ca.csp, authHdr, method, uri, body, ca.server.Config.CompMode1_3)
   192  	if err2 != nil {
   193  		return "", caerrors.NewAuthenticationErr(caerrors.ErrInvalidToken, "Invalid token in authorization header: %s", err2)
   194  	}
   195  	// Make sure the caller's cert was issued by this CA
   196  	err2 = ca.VerifyCertificate(cert)
   197  	if err2 != nil {
   198  		return "", caerrors.NewAuthenticationErr(caerrors.ErrUntrustedCertificate, "Untrusted certificate: %s", err2)
   199  	}
   200  	id := util.GetEnrollmentIDFromX509Certificate(cert)
   201  	log.Debugf("Checking for revocation/expiration of certificate owned by '%s'", id)
   202  
   203  	// VerifyCertificate ensures that the certificate passed in hasn't
   204  	// expired and checks the CRL for the server.
   205  	expired, checked := revoke.VerifyCertificate(cert)
   206  	if !checked {
   207  		return "", caerrors.NewHTTPErr(401, caerrors.ErrCertRevokeCheckFailure, "Failed while checking for revocation")
   208  	}
   209  	if expired {
   210  		return "", caerrors.NewAuthenticationErr(caerrors.ErrCertExpired,
   211  			"The certificate in the authorization header is a revoked or expired certificate")
   212  	}
   213  	aki := hex.EncodeToString(cert.AuthorityKeyId)
   214  	serial := util.GetSerialAsHex(cert.SerialNumber)
   215  	aki = strings.ToLower(strings.TrimLeft(aki, "0"))
   216  	serial = strings.ToLower(strings.TrimLeft(serial, "0"))
   217  
   218  	certificate, err := ca.GetCertificate(serial, aki)
   219  	if err != nil {
   220  		return "", err
   221  	}
   222  	if certificate.Status == "revoked" {
   223  		return "", caerrors.NewAuthenticationErr(caerrors.ErrCertRevoked, "The certificate in the authorization header is a revoked certificate")
   224  	}
   225  
   226  	ctx.enrollmentID = id
   227  	ctx.enrollmentCert = cert
   228  	ctx.caller, err = ctx.GetCaller()
   229  	if err != nil {
   230  		return "", err
   231  	}
   232  	log.Debugf("Successful token authentication of '%s'", id)
   233  	return id, nil
   234  }
   235  
   236  // GetECert returns the enrollment certificate of the caller, assuming
   237  // token authentication was successful.
   238  func (ctx *serverRequestContextImpl) GetECert() *x509.Certificate {
   239  	return ctx.enrollmentCert
   240  }
   241  
   242  // GetCA returns the CA to which this request is targeted and checks to make sure the database has been initialized
   243  func (ctx *serverRequestContextImpl) GetCA() (*CA, error) {
   244  	_, err := ctx.getCA()
   245  	if err != nil {
   246  		return nil, errors.WithMessage(err, "Failed to get CA instance")
   247  	}
   248  	if ctx.ca.db == nil || !ctx.ca.db.IsInitialized() {
   249  		err := ctx.ca.initDB(ctx.ca.server.dbMetrics)
   250  		if err != nil {
   251  			return nil, errors.WithMessage(err, fmt.Sprintf("%s handler failed to initialize DB", strings.TrimLeft(ctx.req.URL.String(), "/")))
   252  		}
   253  		err = ctx.ca.issuer.Init(false, ctx.ca.db, ctx.ca.levels)
   254  		if err != nil {
   255  			return nil, nil
   256  		}
   257  	}
   258  	return ctx.ca, nil
   259  }
   260  
   261  // GetCA returns the CA to which this request is targeted
   262  func (ctx *serverRequestContextImpl) getCA() (*CA, error) {
   263  	if ctx.ca == nil {
   264  		// Get the CA name
   265  		name, err := ctx.getCAName()
   266  		if err != nil {
   267  			return nil, err
   268  		}
   269  		// Get the CA by its name
   270  		ctx.ca, err = ctx.endpoint.Server.GetCA(name)
   271  		if err != nil {
   272  			return nil, err
   273  		}
   274  	}
   275  	return ctx.ca, nil
   276  }
   277  
   278  // GetAttrExtension returns an attribute extension to place into a signing request
   279  func (ctx *serverRequestContextImpl) GetAttrExtension(attrReqs []*api.AttributeRequest, profile string) (*signer.Extension, error) {
   280  	ca, err := ctx.GetCA()
   281  	if err != nil {
   282  		return nil, err
   283  	}
   284  	ui, err := ca.registry.GetUser(ctx.enrollmentID, nil)
   285  	if err != nil {
   286  		return nil, err
   287  	}
   288  	allAttrs, err := ui.GetAttributes(nil)
   289  	if err != nil {
   290  		return nil, err
   291  	}
   292  	if attrReqs == nil {
   293  		attrReqs = getDefaultAttrReqs(allAttrs)
   294  		if attrReqs == nil {
   295  			// No attributes are being requested, so we are done
   296  			return nil, nil
   297  		}
   298  	}
   299  	attrs, err := ca.attrMgr.ProcessAttributeRequests(
   300  		convertAttrReqs(attrReqs),
   301  		convertAttrs(allAttrs),
   302  	)
   303  	if err != nil {
   304  		return nil, err
   305  	}
   306  	if attrs != nil {
   307  		buf, err := json.Marshal(attrs)
   308  		if err != nil {
   309  			errors.Wrap(err, "Failed to marshal attributes")
   310  		}
   311  		ext := &signer.Extension{
   312  			ID:       config.OID(attrmgr.AttrOID),
   313  			Critical: false,
   314  			Value:    hex.EncodeToString(buf),
   315  		}
   316  		log.Debugf("Attribute extension being added to certificate is: %+v", ext)
   317  		return ext, nil
   318  	}
   319  	return nil, nil
   320  }
   321  
   322  // caNameReqBody is a sparse request body to unmarshal only the CA name
   323  type caNameReqBody struct {
   324  	CAName string `json:"caname,omitempty"`
   325  }
   326  
   327  // getCAName returns the targeted CA name for this request
   328  func (ctx *serverRequestContextImpl) getCAName() (string, error) {
   329  	// Check the query parameters first
   330  	ca := ctx.req.URL.Query().Get("ca")
   331  	if ca != "" {
   332  		return ca, nil
   333  	}
   334  	// Next, check the request body, if there is one
   335  	var body caNameReqBody
   336  	_, err := ctx.TryReadBody(&body)
   337  	if err != nil {
   338  		return "", err
   339  	}
   340  	if body.CAName != "" {
   341  		return body.CAName, nil
   342  	}
   343  	// No CA name in the request body either, so use the default CA name
   344  	return ctx.endpoint.Server.CA.Config.CA.Name, nil
   345  }
   346  
   347  // ReadBody reads the request body and JSON unmarshals into 'body'
   348  func (ctx *serverRequestContextImpl) ReadBody(body interface{}) error {
   349  	empty, err := ctx.TryReadBody(body)
   350  	if err != nil {
   351  		return err
   352  	}
   353  	if empty {
   354  		return caerrors.NewHTTPErr(400, caerrors.ErrEmptyReqBody, "Empty request body")
   355  	}
   356  	return nil
   357  }
   358  
   359  // TryReadBody reads the request body into 'body' if not empty
   360  func (ctx *serverRequestContextImpl) TryReadBody(body interface{}) (bool, error) {
   361  	buf, err := ctx.ReadBodyBytes()
   362  	if err != nil {
   363  		return false, err
   364  	}
   365  	empty := len(buf) == 0
   366  	if !empty {
   367  		err = json.Unmarshal(buf, body)
   368  		if err != nil {
   369  			return true, caerrors.NewHTTPErr(400, caerrors.ErrBadReqBody, "Invalid request body: %s; body=%s",
   370  				err, string(buf))
   371  		}
   372  	}
   373  	return empty, nil
   374  }
   375  
   376  // ReadBodyBytes reads the request body and returns bytes
   377  func (ctx *serverRequestContextImpl) ReadBodyBytes() ([]byte, error) {
   378  	if !ctx.body.read {
   379  		r := ctx.req
   380  		buf, err := ioutil.ReadAll(r.Body)
   381  		ctx.body.buf = buf
   382  		ctx.body.err = err
   383  		ctx.body.read = true
   384  	}
   385  	err := ctx.body.err
   386  	if err != nil {
   387  		return nil, caerrors.NewHTTPErr(500, caerrors.ErrReadingReqBody, "Failed reading request body: %s", err)
   388  	}
   389  	return ctx.body.buf, nil
   390  }
   391  
   392  func (ctx *serverRequestContextImpl) GetUser(userName string) (user.User, error) {
   393  	ca, err := ctx.getCA()
   394  	if err != nil {
   395  		return nil, err
   396  	}
   397  	registry := ca.registry
   398  
   399  	user, err := registry.GetUser(userName, nil)
   400  	if err != nil {
   401  		return nil, err
   402  	}
   403  
   404  	err = ctx.CanManageUser(user)
   405  	if err != nil {
   406  		return nil, err
   407  	}
   408  
   409  	return user, nil
   410  }
   411  
   412  // CanManageUser determines if the caller has the right type and affiliation to act on on a user
   413  func (ctx *serverRequestContextImpl) CanManageUser(user user.User) error {
   414  	userAff := strings.Join(user.GetAffiliationPath(), ".")
   415  	err := ctx.ContainsAffiliation(userAff)
   416  	if err != nil {
   417  		return err
   418  	}
   419  
   420  	userType := user.GetType()
   421  	err = ctx.CanActOnType(userType)
   422  	if err != nil {
   423  		return err
   424  	}
   425  
   426  	return nil
   427  }
   428  
   429  // CanModifyUser determines if the modifications to the user are allowed
   430  func (ctx *serverRequestContextImpl) CanModifyUser(req *api.ModifyIdentityRequest, checkAff bool, checkType bool, checkAttrs bool, userToModify user.User) error {
   431  	if checkAff {
   432  		reqAff := req.Affiliation
   433  		log.Debugf("Checking if caller is authorized to change affiliation to '%s'", reqAff)
   434  		err := ctx.ContainsAffiliation(reqAff)
   435  		if err != nil {
   436  			return err
   437  		}
   438  	}
   439  
   440  	if checkType {
   441  		reqType := req.Type
   442  		log.Debugf("Checking if caller is authorized to change type to '%s'", reqType)
   443  		err := ctx.CanActOnType(reqType)
   444  		if err != nil {
   445  			return err
   446  		}
   447  	}
   448  
   449  	if checkAttrs {
   450  		reqAttrs := req.Attributes
   451  		log.Debugf("Checking if caller is authorized to change attributes to %+v", reqAttrs)
   452  		err := attr.CanRegisterRequestedAttributes(reqAttrs, userToModify, ctx.caller)
   453  		if err != nil {
   454  			return caerrors.NewAuthorizationErr(caerrors.ErrRegAttrAuth, "Failed to register attributes: %s", err)
   455  		}
   456  	}
   457  
   458  	return nil
   459  }
   460  
   461  // GetCaller gets the user who is making this server request
   462  func (ctx *serverRequestContextImpl) GetCaller() (user.User, error) {
   463  	if ctx.caller != nil {
   464  		return ctx.caller, nil
   465  	}
   466  
   467  	var err error
   468  	id := ctx.enrollmentID
   469  	if id == "" {
   470  		return nil, caerrors.NewAuthenticationErr(caerrors.ErrCallerIsNotAuthenticated, "Caller is not authenticated")
   471  	}
   472  	ca, err := ctx.GetCA()
   473  	if err != nil {
   474  		return nil, err
   475  	}
   476  	// Get the user info object for this user
   477  	ctx.caller, err = ca.registry.GetUser(id, nil)
   478  	if err != nil {
   479  		return nil, caerrors.NewAuthenticationErr(caerrors.ErrGettingUser, "Failed to get user")
   480  	}
   481  	return ctx.caller, nil
   482  }
   483  
   484  // ContainsAffiliation returns an error if the requested affiliation does not contain the caller's affiliation
   485  func (ctx *serverRequestContextImpl) ContainsAffiliation(affiliation string) error {
   486  	validAffiliation, err := ctx.containsAffiliation(affiliation)
   487  	if err != nil {
   488  		return errors.WithMessage(err, "Failed to validate if caller has authority to act on affiliation")
   489  	}
   490  	if !validAffiliation {
   491  		return caerrors.NewAuthorizationErr(caerrors.ErrCallerNotAffiliated, "Caller does not have authority to act on affiliation '%s'", affiliation)
   492  	}
   493  	return nil
   494  }
   495  
   496  // containsAffiliation returns true if the requested affiliation contains the caller's affiliation
   497  func (ctx *serverRequestContextImpl) containsAffiliation(affiliation string) (bool, error) {
   498  	caller, err := ctx.GetCaller()
   499  	if err != nil {
   500  		return false, err
   501  	}
   502  
   503  	callerAffiliationPath := user.GetAffiliation(caller)
   504  	log.Debugf("Checking to see if affiliation '%s' contains caller's affiliation '%s'", affiliation, callerAffiliationPath)
   505  
   506  	// If the caller has root affiliation return "true"
   507  	if callerAffiliationPath == "" {
   508  		log.Debug("Caller has root affiliation")
   509  		return true, nil
   510  	}
   511  
   512  	if affiliation == callerAffiliationPath {
   513  		return true, nil
   514  	}
   515  
   516  	callerAffiliationPath = callerAffiliationPath + "."
   517  	if strings.HasPrefix(affiliation, callerAffiliationPath) {
   518  		return true, nil
   519  	}
   520  
   521  	return false, nil
   522  }
   523  
   524  // IsRegistrar returns an error if the caller is not a registrar
   525  func (ctx *serverRequestContextImpl) IsRegistrar() error {
   526  	_, isRegistrar, err := ctx.isRegistrar()
   527  	if err != nil {
   528  		return err
   529  	}
   530  	if !isRegistrar {
   531  		return caerrors.NewAuthorizationErr(caerrors.ErrMissingRegAttr, "Caller is not a registrar")
   532  	}
   533  
   534  	return nil
   535  }
   536  
   537  // isRegistrar returns back true if the caller is a registrar along with the types the registrar is allowed to register
   538  func (ctx *serverRequestContextImpl) isRegistrar() (string, bool, error) {
   539  	caller, err := ctx.GetCaller()
   540  	if err != nil {
   541  		return "", false, err
   542  	}
   543  
   544  	log.Debugf("Checking to see if caller '%s' is a registrar", caller.GetName())
   545  
   546  	rolesStr, err := caller.GetAttribute("hf.Registrar.Roles")
   547  	if err != nil {
   548  		return "", false, caerrors.NewAuthorizationErr(caerrors.ErrRegAttrAuth, "'%s' is not a registrar", caller.GetName())
   549  	}
   550  
   551  	// Has some value for attribute 'hf.Registrar.Roles' then user is a registrar
   552  	if rolesStr.Value != "" {
   553  		return rolesStr.Value, true, nil
   554  	}
   555  
   556  	return "", false, nil
   557  }
   558  
   559  // CanActOnType returns true if the caller has the proper authority to take action on specific type
   560  func (ctx *serverRequestContextImpl) CanActOnType(userType string) error {
   561  	canAct, err := ctx.canActOnType(userType)
   562  	if err != nil {
   563  		return errors.WithMessage(err, "Failed to verify if user can act on type")
   564  	}
   565  	if !canAct {
   566  		return caerrors.NewAuthorizationErr(caerrors.ErrCallerNotAffiliated, "Registrar does not have authority to act on type '%s'", userType)
   567  	}
   568  	return nil
   569  }
   570  
   571  func (ctx *serverRequestContextImpl) canActOnType(requestedType string) (bool, error) {
   572  	caller, err := ctx.GetCaller()
   573  	if err != nil {
   574  		return false, err
   575  	}
   576  
   577  	log.Debugf("Checking to see if caller '%s' can act on type '%s'", caller.GetName(), requestedType)
   578  
   579  	typesStr, isRegistrar, err := ctx.isRegistrar()
   580  	if err != nil {
   581  		return false, err
   582  	}
   583  	if !isRegistrar {
   584  		return false, caerrors.NewAuthorizationErr(caerrors.ErrRegAttrAuth, "'%s' is not allowed to manage users", caller.GetName())
   585  	}
   586  
   587  	if util.ListContains(typesStr, "*") {
   588  		return true, nil
   589  	}
   590  
   591  	var types []string
   592  	if typesStr != "" {
   593  		types = strings.Split(typesStr, ",")
   594  	} else {
   595  		types = make([]string, 0)
   596  	}
   597  	if requestedType == "" {
   598  		requestedType = "client"
   599  	}
   600  	if !util.StrContained(requestedType, types) {
   601  		log.Debugf("Caller with types '%s' is not authorized to act on '%s'", types, requestedType)
   602  		return false, nil
   603  	}
   604  
   605  	return true, nil
   606  }
   607  
   608  // HasRole returns an error if the caller does not have the attribute or the value is false for a boolean attribute
   609  func (ctx *serverRequestContextImpl) HasRole(role string) error {
   610  	hasRole, err := ctx.hasRole(role)
   611  	if err != nil {
   612  		return err
   613  	}
   614  	if !hasRole {
   615  		return caerrors.NewAuthorizationErr(caerrors.ErrMissingRole, "Caller has a value of 'false' for attribute/role '%s'", role)
   616  	}
   617  	return nil
   618  }
   619  
   620  // HasRole returns true if the caller has the attribute and value of the attribute is true
   621  func (ctx *serverRequestContextImpl) hasRole(role string) (bool, error) {
   622  	if ctx.callerRoles == nil {
   623  		ctx.callerRoles = make(map[string]bool)
   624  	}
   625  
   626  	roleStatus, hasRole := ctx.callerRoles[role]
   627  	if hasRole {
   628  		return roleStatus, nil
   629  	}
   630  
   631  	caller, err := ctx.GetCaller()
   632  	if err != nil {
   633  		return false, err
   634  	}
   635  
   636  	roleAttr, err := caller.GetAttribute(role)
   637  	if err != nil {
   638  		return false, caerrors.NewAuthorizationErr(caerrors.ErrInvokerMissAttr, "Invoker does not have following role'%s': '%s'", role, err)
   639  	}
   640  	roleStatus, err = strconv.ParseBool(roleAttr.Value)
   641  	if err != nil {
   642  		return false, caerrors.NewHTTPErr(400, caerrors.ErrInvalidBool, "Failed to get boolean value of '%s': '%s'", role, err)
   643  	}
   644  	ctx.callerRoles[role] = roleStatus
   645  
   646  	return ctx.callerRoles[role], nil
   647  }
   648  
   649  // GetVar returns the parameter path variable from the URL
   650  func (ctx *serverRequestContextImpl) GetVar(name string) (string, error) {
   651  	vars := gmux.Vars(ctx.req)
   652  	if vars == nil {
   653  		return "", caerrors.NewHTTPErr(500, caerrors.ErrHTTPRequest, "Failed to correctly handle HTTP request")
   654  	}
   655  	value := vars[name]
   656  	return value, nil
   657  }
   658  
   659  // GetBoolQueryParm returns query parameter from the URL
   660  func (ctx *serverRequestContextImpl) GetBoolQueryParm(name string) (bool, error) {
   661  	var err error
   662  
   663  	value := false
   664  	param := ctx.req.URL.Query().Get(name)
   665  	if param != "" {
   666  		value, err = strconv.ParseBool(strings.ToLower(param))
   667  		if err != nil {
   668  			return false, caerrors.NewHTTPErr(400, caerrors.ErrUpdateConfigRemoveAff, "Failed to correctly parse value of '%s' query parameter: %s", name, err)
   669  		}
   670  	}
   671  
   672  	return value, nil
   673  }
   674  
   675  // GetQueryParm returns the value of query param based on name
   676  func (ctx *serverRequestContextImpl) GetQueryParm(name string) string {
   677  	return ctx.req.URL.Query().Get(name)
   678  }
   679  
   680  // GetReq returns the http.Request
   681  func (ctx *serverRequestContextImpl) GetReq() *http.Request {
   682  	return ctx.req
   683  }
   684  
   685  // GetResp returns the http.ResponseWriter
   686  func (ctx *serverRequestContextImpl) GetResp() http.ResponseWriter {
   687  	return ctx.resp
   688  }
   689  
   690  // GetCertificates executes the DB query to get back certificates based on the filters passed in
   691  func (ctx *serverRequestContextImpl) GetCertificates(req cr.CertificateRequest, callerAff string) (*sqlx.Rows, error) {
   692  	return ctx.ca.certDBAccessor.GetCertificates(req, callerAff)
   693  }
   694  
   695  // ChunksToDeliver returns the number of chunks to deliver per flush
   696  func (ctx *serverRequestContextImpl) ChunksToDeliver(envVar string) (int, error) {
   697  	var chunkSize int
   698  	var err error
   699  
   700  	if envVar == "" {
   701  		chunkSize = 100
   702  	} else {
   703  		chunkSize, err = strconv.Atoi(envVar)
   704  		if err != nil {
   705  			return 0, caerrors.NewHTTPErr(500, caerrors.ErrParsingIntEnvVar, "Incorrect format specified for environment variable '%s', an integer value is required: %s", envVar, err)
   706  		}
   707  	}
   708  	return chunkSize, nil
   709  }
   710  
   711  // Registry returns the registry for the ca
   712  func (ctx *serverRequestContextImpl) GetRegistry() user.Registry {
   713  	return ctx.ca.registry
   714  }
   715  
   716  func (ctx *serverRequestContextImpl) GetCAConfig() *CAConfig {
   717  	return ctx.ca.Config
   718  }
   719  
   720  func (ctx *serverRequestContextImpl) IsLDAPEnabled() bool {
   721  	return ctx.ca.Config.LDAP.Enabled
   722  }
   723  
   724  func convertAttrReqs(attrReqs []*api.AttributeRequest) []attrmgr.AttributeRequest {
   725  	rtn := make([]attrmgr.AttributeRequest, len(attrReqs))
   726  	for i := range attrReqs {
   727  		rtn[i] = attrmgr.AttributeRequest(attrReqs[i])
   728  	}
   729  	return rtn
   730  }
   731  
   732  func convertAttrs(attrs []api.Attribute) []attrmgr.Attribute {
   733  	rtn := make([]attrmgr.Attribute, len(attrs))
   734  	for i := range attrs {
   735  		rtn[i] = attrmgr.Attribute(&attrs[i])
   736  	}
   737  	return rtn
   738  }
   739  
   740  // Return attribute requests for attributes which should by default be added to an ECert
   741  func getDefaultAttrReqs(attrs []api.Attribute) []*api.AttributeRequest {
   742  	count := 0
   743  	for _, attr := range attrs {
   744  		if attr.ECert {
   745  			count++
   746  		}
   747  	}
   748  	if count == 0 {
   749  		return nil
   750  	}
   751  	reqs := make([]*api.AttributeRequest, count)
   752  	count = 0
   753  	for _, attr := range attrs {
   754  		if attr.ECert {
   755  			reqs[count] = &api.AttributeRequest{Name: attr.Name}
   756  			count++
   757  		}
   758  	}
   759  	return reqs
   760  }