// Given an HTTP request, return the string that should be signed for that
// request. The request must include a `Date` header.
//
// See here for more info:
//
//     http://goo.gl/Z8DiC
//
191994
func stringToSign(r *http.Request) (string, error) {
	// Grab the HTTP headers specifically called out by the signing algorithm.
	date, ok := r.Headers["Date"]
	if !ok {
		return "", errors.New("A Date header is required.")
	}

	contentMd5 := r.Headers["Content-MD5"]
	contentType := r.Headers["Content-Type"]

	// We don't yet support CanonicalizedAmzHeaders.
	canonicalizedAmzHeaders := ""

	// Amazon's signing algorithm is weird -- it requires URL encoding for paths,
	// but not query parameters. Luckily we currently only support simple
	// path-style requests.
	canonicalizedResource := (&url.URL{Path: r.Path}).RequestURI()

	// Put everything together.
	return fmt.Sprintf(
		"%s\n%s\n%s\n%s\n%s%s",
		r.Verb,
		contentMd5,
		contentType,
		date,
		canonicalizedAmzHeaders,
		canonicalizedResource), nil
}
537723
func (s3 *S3) authString(req *http.Request) string {
	if req.Header.Get("Date") == "" {
		req.Header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
	}

	// canonicalize amz headers
	a := make([]string, 0, 1)
	for k, _ := range req.Header {
		k = strings.ToLower(k)
		if strings.HasPrefix(k, "x-amz-") {
			a = append(a, k)
		}
	}

	sort.Strings(a)

	for i, v := range a {
		k := http.CanonicalHeaderKey(v)
		vv := req.Header[k]
		a[i] = v + `:` + strings.Join(vv, `,`) + "\n"
	}

	canonicalAmzHeaders := strings.Join(a, "")

	// canonicalize resource
	cres, rawQuery := canonicalResource(req.URL.Path, req.URL.Query())
	req.URL.RawQuery = rawQuery

	return strings.Join([]string{
		strings.TrimSpace(req.Method),
		req.Header.Get("Content-MD5"),
		req.Header.Get("Content-Type"),
		req.Header.Get("Date"),
		canonicalAmzHeaders + cres,
	}, "\n")
}
913164
func (ac AuthConfig) SignRequest(request *http.Request) error {
	// sanitize the path for the chef-server
	// chef-server doesn't support '//' in the Hash Path.
	var endpoint string
	if request.URL.Path != "" {
		endpoint = path.Clean(request.URL.Path)
		request.URL.Path = endpoint
	} else {
		endpoint = request.URL.Path
	}

	vals := map[string]string{
		"Method":             request.Method,
		"Hashed Path":        HashStr(endpoint),
		"Accept":             "application/json",
		"X-Chef-Version":     ChefVersion,
		"X-Ops-Timestamp":    time.Now().UTC().Format(time.RFC3339),
		"X-Ops-UserId":       ac.ClientName,
		"X-Ops-Sign":         "algorithm=sha1;version=1.0",
		"X-Ops-Content-Hash": request.Header.Get("X-Ops-Content-Hash"),
	}

	for _, key := range []string{"Method", "Accept", "X-Chef-Version", "X-Ops-Timestamp", "X-Ops-UserId", "X-Ops-Sign"} {
		request.Header.Set(key, vals[key])
	}

	// To validate the signature it seems to be very particular
	var content string
	for _, key := range []string{"Method", "Hashed Path", "X-Ops-Content-Hash", "X-Ops-Timestamp", "X-Ops-UserId"} {
		content += fmt.Sprintf("%s:%s\n", key, vals[key])
	}
	content = strings.TrimSuffix(content, "\n")
	// generate signed string of headers
	// Since we've gone through additional validation steps above,
	// we shouldn't get an error at this point
	signature, err := GenerateSignature(ac.PrivateKey, content)
	if err != nil {
		return err
	}

	// TODO: THIS IS CHEF PROTOCOL SPECIFIC
	// Signature is made up of n 60 length chunks
	base64sig := Base64BlockEncode(signature, 60)

	// roll over the auth slice and add the apropriate header
	for index, value := range base64sig {
		request.Header.Set(fmt.Sprintf("X-Ops-Authorization-%d", index+1), string(value))
	}

	return nil
}
1079475
func GetBlockDateCtx(r *http.Request) string {
	blockDate, _ := r.Context().Value(CtxBlockDate).(string)
	return blockDate
}
792568
func SignSDKRequestWithCurrentTime(req *request.Request, curTimeFn func() time.Time, opts ...func(*Signer)) {
	// If the request does not need to be signed ignore the signing of the
	// request if the AnonymousCredentials object is used.
	if req.Config.Credentials == credentials.AnonymousCredentials {
		return
	}

	region := req.ClientInfo.SigningRegion
	if region == "" {
		region = aws.StringValue(req.Config.Region)
	}

	name := req.ClientInfo.SigningName
	if name == "" {
		name = req.ClientInfo.ServiceName
	}

	v4 := NewSigner(req.Config.Credentials, func(v4 *Signer) {
		v4.Debug = req.Config.LogLevel.Value()
		v4.Logger = req.Config.Logger
		v4.DisableHeaderHoisting = req.NotHoist
		v4.currentTimeFn = curTimeFn
		if name == "s3" {
			// S3 service should not have any escaping applied
			v4.DisableURIPathEscaping = true
		}
		// Prevents setting the HTTPRequest's Body. Since the Body could be
		// wrapped in a custom io.Closer that we do not want to be stompped
		// on top of by the signer.
		v4.DisableRequestBodyOverwrite = true
	})

	for _, opt := range opts {
		opt(v4)
	}

	curTime := curTimeFn()
	signedHeaders, err := v4.signWithBody(req.HTTPRequest, req.GetBody(),
		name, region, req.ExpireTime, req.ExpireTime > 0, curTime,
	)
	if err != nil {
		req.Error = err
		req.SignedHeaderVals = nil
		return
	}

	req.SignedHeaderVals = signedHeaders
	req.LastSignedAt = curTime
}
709247
func (c *Context) RequestHeader(key string) string {
	return c.Request.Header.Get(key)
}
404024
func (p *Packet) String() string {
	// If there are no headers, print "unsupported protocol".
	if len(p.Headers) == 0 {
		return fmt.Sprintf("%s unsupported protocol %d", p.Time, int(p.Type))
	}
	return fmt.Sprintf("%s %s", p.Time, p.headerString(p.Headers))
}
1117389
func getSignedHeaders(signedHeaders http.Header) string {
	var headers []string
	for k := range signedHeaders {
		headers = append(headers, strings.ToLower(k))
	}
	sort.Strings(headers)
	return strings.Join(headers, ";")
}
1309835
func writeSignV2Headers(buf *bytes.Buffer, req http.Request) {
	buf.WriteString(req.Method + "\n")
	buf.WriteString(req.Header.Get("Content-Md5") + "\n")
	buf.WriteString(req.Header.Get("Content-Type") + "\n")
	buf.WriteString(req.Header.Get("Date") + "\n")
}
1227240
func (t *Token) SignedString(key interface{}) (string, error) {
	var sig, sstr string
	var err error
	if sstr, err = t.SigningString(); err != nil {
		return "", err
	}
	if sig, err = t.Method.Sign(sstr, key); err != nil {
		return "", err
	}
	return strings.Join([]string{sstr, sig}, "."), nil
}
208134
func (app *App) ParseSignedRequest(signedRequest string) (res Result, err error) {
	strs := strings.SplitN(signedRequest, ".", 2)

	if len(strs) != 2 {
		err = fmt.Errorf("invalid signed request format")
		return
	}

	sig, e1 := base64.RawURLEncoding.DecodeString(strs[0])

	if e1 != nil {
		err = fmt.Errorf("fail to decode signed request sig with error %v", e1)
		return
	}

	payload, e2 := base64.RawURLEncoding.DecodeString(strs[1])

	if e2 != nil {
		err = fmt.Errorf("fail to decode signed request payload with error is %v", e2)
		return
	}

	err = json.Unmarshal(payload, &res)

	if err != nil {
		err = fmt.Errorf("signed request payload is not a valid json string with error %v", err)
		return
	}

	var hashMethod string
	err = res.DecodeField("algorithm", &hashMethod)

	if err != nil {
		err = fmt.Errorf("signed request payload doesn't contains a valid 'algorithm' field")
		return
	}

	hashMethod = strings.ToUpper(hashMethod)

	if hashMethod != "HMAC-SHA256" {
		err = fmt.Errorf("signed request payload uses an unknown HMAC method; expect 'HMAC-SHA256' but actual is '%v'", hashMethod)
		return
	}

	hash := hmac.New(sha256.New, []byte(app.AppSecret))
	hash.Write([]byte(strs[1])) // note: here uses the payload base64 string, not decoded bytes
	expectedSig := hash.Sum(nil)

	if !hmac.Equal(sig, expectedSig) {
		err = fmt.Errorf("bad signed request signiture")
		return
	}

	return
}
728218
func (this *Request) Get(f string) string {

	/*
	   Possible future bug.
	   http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
	   Message headers are case-insensitive.
	*/

	return this.Header.Get(f)
}
833751
func (d Date) String() string {
	return fmt.Sprintf(dateFormat, d.Year(), d.Month(), d.Day())
}
698284
func (c *Client) Request(verb, spath string, ro *RequestOptions) (*http.Request, error) {
	log.Printf("[INFO] request: %s %s", verb, spath)

	// Ensure we have a RequestOptions struct (passing nil is an acceptable)
	if ro == nil {
		ro = new(RequestOptions)
	}

	// Create a new URL with the appended path
	u := *c.URL
	u.Path = path.Join(c.URL.Path, spath)

	// Add the token and other params
	if c.Token != "" {
		log.Printf("[DEBUG] request: appending token (%s)", maskString(c.Token))
		if ro.Headers == nil {
			ro.Headers = make(map[string]string)
		}

		ro.Headers[atlasTokenHeader] = c.Token
	}

	return c.rawRequest(verb, &u, ro)
}
811047
func (b *HttpRequest) String() (string, error) {
	data, err := b.Bytes()
	if err != nil {
		return "", err
	}

	return string(data), nil
}
1369613
func (api *API) request(ctx context.Context, method, uri string, reqBody io.Reader, authType int, headers http.Header) (*http.Response, error) {
	req, err := http.NewRequest(method, api.BaseURL+uri, reqBody)
	if err != nil {
		return nil, errors.Wrap(err, "HTTP request creation failed")
	}
	req.WithContext(ctx)

	combinedHeaders := make(http.Header)
	copyHeader(combinedHeaders, api.headers)
	copyHeader(combinedHeaders, headers)
	req.Header = combinedHeaders
	if authType&AuthKeyEmail != 0 {
		req.Header.Set("X-Auth-Key", api.APIKey)
		req.Header.Set("X-Auth-Email", api.APIEmail)
	}
	if authType&AuthUserService != 0 {
		req.Header.Set("X-Auth-User-Service-Key", api.APIUserServiceKey)
	}
	if api.UserAgent != "" {
		req.Header.Set("User-Agent", api.UserAgent)
	}

	if req.Header.Get("Content-Type") == "" {
		req.Header.Set("Content-Type", "application/json")
	}

	resp, err := api.httpClient.Do(req)
	if err != nil {
		return nil, errors.Wrap(err, "HTTP request failed")
	}

	return resp, nil
}
1271743
func (s *Signer) SignRequest(req *http.Request) error {
	type param struct {
		key, val string
	}
	var params []string
	add := func(p param) {
		params = append(params, fmt.Sprintf(`%s="%s"`, p.key, p.val))
	}

	var buf bytes.Buffer
	gz := gzip.NewWriter(&buf)
	if _, err := io.WriteString(gz, s.Token); err != nil {
		return fmt.Errorf("zip token: %s", err)
	}
	if err := gz.Close(); err != nil {
		return fmt.Errorf("zip token: %s", err)
	}
	add(param{
		key: "token",
		val: base64.StdEncoding.EncodeToString(buf.Bytes()),
	})

	if s.Certificate != nil {
		nonce := fmt.Sprintf("%d:%d", time.Now().UnixNano()/1e6, mrand.Int())
		var body []byte
		if req.GetBody != nil {
			r, rerr := req.GetBody()
			if rerr != nil {
				return fmt.Errorf("sts: getting http.Request body: %s", rerr)
			}
			defer r.Close()
			body, rerr = ioutil.ReadAll(r)
			if rerr != nil {
				return fmt.Errorf("sts: reading http.Request body: %s", rerr)
			}
		}
		bhash := sha256.New().Sum(body)

		// Port in the signature must be that of the reverse proxy port, vCenter's default is port 80
		port := "80" // TODO: get from lookup service
		var buf bytes.Buffer
		msg := []string{
			nonce,
			req.Method,
			req.URL.Path,
			strings.ToLower(req.URL.Hostname()),
			port,
		}
		for i := range msg {
			buf.WriteString(msg[i])
			buf.WriteByte('\n')
		}
		buf.Write(bhash)
		buf.WriteByte('\n')

		sum := sha256.Sum256(buf.Bytes())
		key, ok := s.Certificate.PrivateKey.(*rsa.PrivateKey)
		if !ok {
			return errors.New("sts: rsa.PrivateKey is required to sign http.Request")
		}
		sig, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, sum[:])
		if err != nil {
			return err
		}

		add(param{
			key: "signature_alg",
			val: "RSA-SHA256",
		})
		add(param{
			key: "signature",
			val: base64.StdEncoding.EncodeToString(sig),
		})
		add(param{
			key: "nonce",
			val: nonce,
		})
		add(param{
			key: "bodyhash",
			val: base64.StdEncoding.EncodeToString(bhash),
		})
	}

	req.Header.Set("Authorization", fmt.Sprintf("SIGN %s", strings.Join(params, ", ")))

	return nil
}