~mvo/snappy/snappy-snapfs-refactor-ftw

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
 * Copyright (C) 2014-2015 Canonical Ltd
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package oauth

import (
	"bytes"
	"fmt"
	"time"

	"launchpad.net/snappy/helpers"
)

// Token contains the sso token
type Token struct {
	TokenKey       string `json:"token_key"`
	TokenSecret    string `json:"token_secret"`
	ConsumerSecret string `json:"consumer_secret"`
	ConsumerKey    string `json:"consumer_key"`
}

// see https://dev.twitter.com/oauth/overview/percent-encoding-parameters
func needsEscape(c byte) bool {
	return !(('A' <= c && c <= 'Z') ||
		('a' <= c && c <= 'z') ||
		('0' <= c && c <= '9') ||
		(c == '-') ||
		(c == '.') ||
		(c == '_') ||
		(c == '~'))
}

// quote will quote all bytes in the input string that oauth requries to
// be quoted
func quote(s string) string {
	buf := bytes.NewBuffer(nil)
	// set to worst case max size, to avoid reallocs
	sin := []byte(s)
	buf.Grow(len(sin) * 3)

	for _, c := range sin {
		if needsEscape(c) {
			fmt.Fprintf(buf, "%%%02X", c)
		} else {
			fmt.Fprintf(buf, "%c", c)
		}
	}

	return buf.String()
}

// FIXME: replace with a real oauth1 library - or wait until oauth2 becomes
// available

// MakePlaintextSignature makes a oauth v1 plaintext signature
func MakePlaintextSignature(token *Token) string {
	// hrm, rfc5849 says that nonce, timestamp are not used for PLAINTEXT
	// but our sso server is unhappy without, so
	nonce := helpers.MakeRandomString(60)
	timestamp := time.Now().Unix()

	s := fmt.Sprintf(`OAuth oauth_nonce="%s", oauth_timestamp="%v", oauth_version="1.0", oauth_signature_method="PLAINTEXT", oauth_consumer_key="%s", oauth_token="%s", oauth_signature="%s&%s"`, nonce, timestamp, quote(token.ConsumerKey), quote(token.TokenKey), quote(token.ConsumerSecret), quote(token.TokenSecret))
	return s
}