Merge branch 'master' of danga.com:camlistore

This commit is contained in:
Brad Fitzpatrick 2010-12-08 14:29:42 -08:00
commit 66b7eaf912
5 changed files with 83 additions and 45 deletions

View File

@ -3,6 +3,7 @@ include $(GOROOT)/src/Make.inc
TARG=camsigd
GOFILES=\
camsigd.go\
keys.go\
sign.go\
verify.go\

View File

@ -0,0 +1,41 @@
package main
import (
"bytes"
"fmt"
"flag"
"os"
"io/ioutil"
"crypto/openpgp/armor"
"crypto/openpgp/packet"
)
var flagPubKeyDir *string = flag.String("pubkey-dir", "test/pubkey-blobs",
"Temporary development hack; directory to dig-xxxx.camli public keys.")
func openArmoredPublicKeyFile(fileName string) (*packet.PublicKeyPacket, os.Error) {
data, err := ioutil.ReadFile(fileName)
if err != nil {
return nil, os.NewError(fmt.Sprintf("Error reading public key file: %v", err))
}
block, _ := armor.Decode(data)
if block == nil {
return nil, os.NewError("Couldn't find PGP block in public key file")
}
if block.Type != "PGP PUBLIC KEY BLOCK" {
return nil, os.NewError("Invalid public key blob.")
}
buf := bytes.NewBuffer(block.Bytes)
p, err := packet.ReadPacket(buf)
if err != nil {
return nil, os.NewError(fmt.Sprintf("Invalid public key blob: %v", err))
}
pk, ok := p.(packet.PublicKeyPacket)
if !ok {
return nil, os.NewError(fmt.Sprintf("Invalid public key blob; not a public key packet"))
}
return &pk, nil
}

View File

@ -1,17 +1,21 @@
package main
import (
"camli/blobref"
"camli/httputil"
"exec"
"fmt"
"http"
"io/ioutil"
"json"
"log"
"os"
"strings"
"unicode"
)
const kMaxJsonLength = 1024 * 1024
func handleSign(conn http.ResponseWriter, req *http.Request) {
if !(req.Method == "POST" && req.URL.Path == "/camli/sig/sign") {
httputil.BadRequestError(conn, "Inconfigured handler.")
@ -20,20 +24,46 @@ func handleSign(conn http.ResponseWriter, req *http.Request) {
req.ParseForm()
json := req.FormValue("json")
if json == "" {
httputil.BadRequestError(conn, "Missing json parameter.")
jsonStr := req.FormValue("json")
if jsonStr == "" {
httputil.BadRequestError(conn, "Missing json parameter")
return
}
if len(jsonStr) > kMaxJsonLength {
httputil.BadRequestError(conn, "json parameter too large")
return
}
var keyId int
numScanned, err := fmt.Sscanf(req.FormValue("keyid"), "%x", &keyId)
if numScanned != 1 {
httputil.BadRequestError(conn, "Couldn't parse keyid parameter.")
return
trimmedJson := strings.TrimRightFunc(jsonStr, unicode.IsSpace)
jmap := make(map[string]interface{})
if err := json.Unmarshal([]byte(trimmedJson), &jmap); err != nil {
httputil.BadRequestError(conn, "json parameter doesn't parse as JSON.")
return
}
trimmedJson := strings.TrimRightFunc(json, unicode.IsSpace)
camliSigner, hasSigner := jmap["camliSigner"]
if !hasSigner {
httputil.BadRequestError(conn, "json lacks \"camliSigner\" key with public key blobref")
return
}
signerBlob := blobref.Parse(camliSigner.(string))
if signerBlob == nil {
httputil.BadRequestError(conn, "json \"camliSigner\" key is malformed or unsupported")
return
}
publicKeyFile := fmt.Sprintf("%s/%s.camli", *flagPubKeyDir, signerBlob.String())
pk, err := openArmoredPublicKeyFile(publicKeyFile)
if err != nil {
conn.WriteHeader(http.StatusUnauthorized)
fmt.Fprintf(conn, "Failed to find public key for %s", signerBlob)
return
}
// This check should be redundant if the above JSON parse succeeded, but
// for explicitness...
if len(trimmedJson) == 0 || trimmedJson[len(trimmedJson)-1] != '}' {
httputil.BadRequestError(conn, "json parameter lacks trailing '}'.")
return
@ -46,7 +76,7 @@ func handleSign(conn http.ResponseWriter, req *http.Request) {
"--no-default-keyring",
"--keyring", *flagRing,
"--secret-keyring", *flagSecretRing,
"--local-user", fmt.Sprintf("%x", keyId),
"--local-user", pk.KeyIdString(),
"--detach-sign",
"--armor",
"-"},

View File

@ -21,13 +21,10 @@ my $json = $j->objToJson({ "camliVersion" => 1,
"foo" => "bar",
});
print "JSON: [$json]\n";
my $keyid = "26F5ABDA"; # test key
# Sign it.
my $sjson;
{
my $req = req("sign", { "json" => $json, "keyid" => $keyid });
my $req = req("sign", { "json" => $json });
my $res = $ua->request($req);
ok($res, "got an HTTP sig response") or done_testing();
ok($res->is_success, "HTTP sig response is successful") or done_testing();

View File

@ -21,10 +21,8 @@ import (
"crypto/openpgp/packet"
"crypto/rsa"
"crypto/sha1"
"flag"
"fmt"
"http"
"io/ioutil"
"json"
"log"
"os"
@ -35,9 +33,6 @@ var logf = log.Printf
const sigSeparator = `,"camliSig":"`
var flagPubKeyDir *string = flag.String("pubkey-dir", "test/pubkey-blobs",
"Temporary development hack; directory to dig-xxxx.camli public keys.")
// reArmor takes a camliSig (single line armor) and turns it back into an PGP-style
// multi-line armored string
func reArmor(line string) string {
@ -54,32 +49,6 @@ func reArmor(line string) string {
`, line[0:lastEq], line[lastEq:])
}
func openArmoredPublicKeyFile(fileName string) (*packet.PublicKeyPacket, os.Error) {
data, err := ioutil.ReadFile(fileName)
if err != nil {
return nil, os.NewError(fmt.Sprintf("Error reading public key file: %v", err))
}
block, _ := armor.Decode(data)
if block == nil {
return nil, os.NewError("Couldn't find PGP block in public key file")
}
if block.Type != "PGP PUBLIC KEY BLOCK" {
return nil, os.NewError("Invalid public key blob.")
}
buf := bytes.NewBuffer(block.Bytes)
p, err := packet.ReadPacket(buf)
if err != nil {
return nil, os.NewError(fmt.Sprintf("Invalid public key blob: %v", err))
}
pk, ok := p.(packet.PublicKeyPacket)
if !ok {
return nil, os.NewError(fmt.Sprintf("Invalid public key blob; not a public key packet"))
}
return &pk, nil
}
// See doc/json-signing/* for background and details
// on these variable names.
type VerifyRequest struct {