Exemple #1
0
// Given a set of PEM Block bytes (for example from a file that contains user data in PEM format), get a UserSet of multiple users
func NewUserSet(PEMBlockBytes []byte) (UserSet, error) {
	var userset UserSet
	for {
		var PEMBlock *pem.Block
		PEMBlock, PEMBlockBytes = pem.Decode(PEMBlockBytes)
		if PEMBlock == nil {
			PEMBlockBytes = []byte(strings.TrimSpace(string(PEMBlockBytes))) // Trim remaining whitespace
			if len(PEMBlockBytes) == 0 {
				break // We're done
			} else {
				// There's still data to be processed, but we can't make sense of it
				return nil, ErrUserExtraData
			}
		}
		if PEMBlock.Type != "PUBLIC KEY" {
			return nil, errors.New("Found unexpected " + PEMBlock.Type + " when processing PEM Blocks")
		}
		user, err := NewUserFromBlock(PEMBlock)
		if err != nil {
			return nil, err
		}
		err = userset.Add(user)
		if err != nil {
			return nil, err
		}
	}
	return userset, nil
}
Exemple #2
0
// The default URL Checker constrains the crawler to the domains of the seed URLs
func defaultCheckURL(crawler *Crawler, checkurl string) error {
	parsedURL, err := url.Parse(checkurl)
	if err != nil {
		return err
	}
	for _, seedURL := range crawler.URLs {
		parsedSeed, err := url.Parse(seedURL)
		if err != nil {
			return err
		}
		if parsedSeed.Host == parsedURL.Host {
			return nil
		}
	}
	return errors.New("URL not in approved domain")
}
Exemple #3
0
func GetDBSize(dbname string) (size string, err error) {
	info, err := os.Stat(DataDir + "/" + dbname)
	if err != nil {
		return "", err
	}
	if !info.IsDir() {
		return "", ErrInvalidDir
	}

	cmd := exec.Command("du", DataDir+"/"+dbname, "-s", "-k")
	output, err := cmd.CombinedOutput()
	if err != nil {
		return "", errors.Append(err, errors.New(string(output)))
	}
	size = strings.TrimSpace(strings.Split(string(output), "\t")[0])

	return size, nil
}
Exemple #4
0
package errors_test

import (
	stderrors "errors"
	"github.com/phayes/errors"
	"testing"
)

var (
	Strger  = stringer{}
	ErrFoo  = errors.New("Fooey")
	ErrBar  = errors.New("Barf")
	ErrStd  = stderrors.New("This is a stanard error from the standard library.")
	ErrStd2 = stderrors.New("Another standard error from the standard library.")
	ErrFmt  = errors.Newf("%s", Strger)
)

type stringer struct{}

func (s stringer) String() string {
	return "stringer out"
}

func TestFooWrappingStdError(t *testing.T) {
	err := FooWrappingStdError()
	if !errors.Equal(err, ErrFoo) || !errors.Equal(ErrFoo, err) {
		t.Error("Foo not determined to be equal to an errors.Error based on itself")
		return
	}
	if !errors.IsA(err, ErrStd) {
		t.Error("Error that wraps standard library not determined to contain the standard")
Exemple #5
0
	"crypto/x509"
	"encoding/pem"
	"github.com/phayes/errors"
	"strings"
)

type User struct {
	PublicKey  PublicKey         // base64 encoded PEM formatted public-key
	Perms      []string          // List of permissions. @@TODO: Maybe this shouldn't be a string but should be an enumeration
	Properties map[string]string // List of all key->value properties
}

type UserSet []User

var (
	ErrUserInvalidPEM      = errors.New("Could not decode PEM Block for user")
	ErrUserBlockNotFound   = errors.New("Could not find PUBLIC KEY block for user")
	ErrUserPermsNotFound   = errors.New("No permissions specified for user")
	ErrUserPermsInvalid    = errors.New("Could not parse user permissions")
	ErrUserExtraData       = errors.New("Could not parse PEM Blocks or extra data found that could not be parsed.")
	ErrUserSetUserExists   = errors.New("Could not add User to UserSet. User already exists with the same public-key")
	ErrUserSetUserNotFound = errors.New("Could not find user")
)

func NewUser(PEMBlockBytes []byte) (*User, error) {
	PEMBlock, _ := pem.Decode(PEMBlockBytes)
	if PEMBlock == nil {
		return nil, ErrUserInvalidPEM
	}
	return NewUserFromBlock(PEMBlock)
}
Exemple #6
0
import (
	"bytes"
	"github.com/phayes/errors"
	"regexp"
	"time"
)

const (
	MaxElectionIDSize = 32 // Votes are stored in a postgres table named votes_<electon-id> so we need to limit the election ID size.
)

var (
	ValidElectionID = regexp.MustCompile(`^[0-9a-z_]+$`) // Regex for valid characters. We use this ID to construct the name of a table, so we need to limit allowed characters.

	ErrElectionIDTooBig      = errors.Newf("Invalid ElectionID. Too many characters. Maximum is %i characters", MaxElectionIDSize)
	ErrEelectionInvalid      = errors.New("Cannot parse election. Invalid format")
	ErrElectionIDInvalid     = errors.New("ElectionID contains illigal characters. Only lowercase alpha-numeric characters allowed")
	ErrElectionStartInvalid  = errors.New("Invalid election start time")
	ErrElectionEndInvalid    = errors.New("Invalid election end time")
	ErrElectionInvalidTagSet = errors.New("Cannot parse TagSet in election")
	ErrElectionInvalidKey    = errors.New("Cannot parse PublicKey in election")
	ErrElectionInvalidSig    = errors.New("Cannot parse Signature in election")
	ErrEletionSigNotFound    = errors.New("Could not verify election signature: Signature does not exist")
)

type Election struct {
	ElectionID string
	Start      time.Time // Start date & time (RFC-1123 format with a numeric timezone)
	End        time.Time // End date & time (RFC-1123 format with a numeric timezone)
	TagSet               // Optional key-value tag-set
	PublicKey            // The public key of the admin that created this election
Exemple #7
0
const (
	MaxTagKeySize   = 64
	MaxTagValueSize = 256
)

type Tag struct {
	Key   []byte
	Value []byte
}

type TagSet []Tag

var (
	ErrTagKeyTooBig    = errors.Newf("Tag key too long. Maximum tag key size is $i characters", MaxTagKeySize)
	ErrTagValTooBig    = errors.Newf("Tag value too long. Maximum tag value size is $i characters", MaxTagValueSize)
	ErrTagMalformed    = errors.New("Malformed tag")
	ErrTagKeyMalformed = errors.New("Malformed tag key") //@@TODO: Actually put some limits around allowed-charcters for keys
	ErrTagKeyNotFound  = errors.New("Missing tag key")
	ErrTagValNotFound  = errors.New("Missing tag value")
)

func NewTag(rawTag []byte) (Tag, error) {
	parts := bytes.SplitN(rawTag, []byte("="), 2)
	if len(parts) != 2 {
		return Tag{}, ErrTagMalformed
	}
	if len(parts[0]) == 0 {
		return Tag{}, ErrTagKeyNotFound
	}
	if len(parts[0]) > MaxTagKeySize {
		return Tag{}, ErrTagKeyTooBig
Exemple #8
0
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/hex"
	"encoding/pem"
	"fmt"
	"github.com/phayes/errors"
)

// A DER encoded private key
type PrivateKey []byte

var (
	ErrPrivatKeyInvalidPEM = errors.New("Could not decode Prviate Key PEM Block")
	ErrPrivatKeyWrongType  = errors.New("Could not find RSA PRIVATE KEY block")
	ErrPrivatKeyGenerate   = errors.New("Could not generate new PrivateKey")
	ErrPrivatKeyCryptoKey  = errors.New("Could not create from rsa.CryptoKey from PrivateKey. Could not parse PrivateKey bytes")
	ErrPrivatKeySign       = errors.New("PrivateKey could not sign bytes")
	ErrPrivateKeySHA256    = errors.New("Invalid SHA256 Hash checksum")
)

// Create a new PrivateKey from a PEM Block bytes
func NewPrivateKey(PEMBlockBytes []byte) (PrivateKey, error) {
	PEMBlock, _ := pem.Decode(PEMBlockBytes)
	if PEMBlock == nil {
		return nil, ErrPrivatKeyInvalidPEM
	}
	return NewPrivateKeyFromBlock(PEMBlock)
}
Exemple #9
0
import (
	"flag"
	"fmt"
	"github.com/phayes/errors"
	"github.com/vaughan0/go-ini"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strings"
)

var (
	ErrDataDir    = errors.New("Could not determine mysql data directory")
	ErrInvalidDB  = errors.New("Invalid database name")
	ErrInvalidDir = errors.New("Invalid database directory")
	ValidDBName   = regexp.MustCompile("[0-9a-zA-Z$_]+")
	DataDir       string
)

func main() {
	flag.Parse()

	c, err := ini.LoadFile("/etc/my.cnf")
	if err != nil {
		// Syntax errors are OK because my.cnf contains weird syntax
		if _, ok := err.(ini.ErrSyntax); !ok {
			log.Fatal(err)
		}
Exemple #10
0
package cryptoballot

import (
	"crypto"
	"crypto/rsa"
	"crypto/sha256"
	"encoding/base64"
	"github.com/phayes/errors"
)

// An RSA signature. Raw bytes.
type Signature []byte

var (
	ErrSignatureBase64   = errors.New("Invalid Signature. Could not read base64 encoded bytes")
	ErrSignatureTooShort = errors.New("Invalid Signature. Signature too short")
	ErrSignatureVerify   = errors.New("Could not cryptographically verify signature")
)

// Create a new signature from a base64 encoded item, as we would get in a PUT or POST request
//@@TODO: Test to make sure "Signature too short" is working as expected
func NewSignature(Base64Signature []byte) (Signature, error) {
	dbuf := make([]byte, base64.StdEncoding.DecodedLen(len(Base64Signature)))
	n, err := base64.StdEncoding.Decode(dbuf, Base64Signature)
	if err != nil {
		return nil, errors.Wrap(err, ErrSignatureBase64)
	}
	if n < 128 {
		return nil, ErrSignatureTooShort
	}
	sig := dbuf[:n]
Exemple #11
0
)

type State int

// URL states.
// You can query the current state of a url by calling Crawler.GetURL(url)
const (
	StateNotFound State = iota
	StatePending  State = iota
	StateRunning  State = iota
	StateRejected State = iota
	StateDone     State = iota
)

var (
	ErrReqFailed      = errors.New("HTTP request failed")
	ErrBodyRead       = errors.New("Error reading HTTP response body")
	ErrAlreadyStarted = errors.New("Cannot start crawler that is already running")
	ErrHeaderRejected = errors.New("CheckHeader rejected URL")
	ErrURLRejected    = errors.New("CheckURL rejected URL")
	ErrBadHttpCode    = errors.New("Bad HTTP reponse code")
	ErrBadContentType = errors.New("Unsupported Content-Type")
)

// When handling a crawled page a Response is passed to the Handler function.
// A crawlbot.Response is an http.Response with a few extra fields.
type Response struct {
	// The http.Reponse object
	*http.Response

	// The for this Response
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"github.com/phayes/errors"
)

type SignatureRequest struct {
	ElectionID string
	RequestID  []byte // SHA256 (hex) of base64 encoded public-key
	PublicKey         // base64 encoded PEM formatted public-key
	BallotHash []byte // SHA256 (hex-encoded) of the ballot. This would generally be blinded.
	Signature         // Voter signature for the ballot request
}

var (
	ErrSignatureRequestInvalid    = errors.New("Cannot read Signature Request. Invalid format")
	ErrSignatureRequestPublicKey  = errors.New("Cannot read Signature Request. Invalid Public Key")
	ErrSignatureRequestID         = errors.New("Invalid SignatureRequest ID. A SignatureRequest ID must be the (hex encoded) SHA256 of the voters public key.")
	ErrSignatureRequestBallotHash = errors.New("Invalid Signature Request. Ballot hash must be hex encoded.")
	ErrSignatureRequestHashBits   = errors.New("Invalid Signature Request. You must provide exactly 256 bits for the blinded SHA256 ballot hash")
	ErrSignatureRequestSigInvalid = errors.New("Invalid Signature Request. Could not parse voter signature")
	ErrSignatureRequestSigNotFoud = errors.New("Could not verify voter signature on Signature Request: voter-signature does not exist")
	ErrSignatureRequestSignBallot = errors.New("Could not sign ballot")
)

// Given a raw Signature Request string (as a []byte -- see documentation for format), return a new SignatureRequest object.
// Generally the Signature Request string is coming from a voter in a POST body.
// This will also verify the signature on the SignatureRequest and return an error if the request does not pass crypto verification
func NewSignatureRequest(rawSignatureRequest []byte) (*SignatureRequest, error) {
	var (
		err        error
Exemple #13
0
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/base64"
	"encoding/hex"
	"github.com/phayes/errors"
)

const (
	absoluteMinPublicKeySize = 2048 // We cannot go lower than this since it would hinder our ability to differentiate between public keys and tagsets on ballots
)

var (
	MinPublicKeySize = 4096 // Recommended minimum public key size -- this can be changed

	ErrPubicMinKeySize    = errors.New("Invalid public key - too short")
	ErrPublicKeyBase64    = errors.New("Invalid Public Key. Could not read base64 encoded bytes")
	ErrPublicKeyLen       = errors.New("Could not determine PublicKey key length")
	ErrPublicKeyCryptoKey = errors.New("Could not create from rsa.PublicKey from PublicKey. Could not parse PublicKey bytes")
)

// A DER encoded public key
type PublicKey []byte

// Create a new PublicKey from a base64 encoded item, as we would get in a PUT or POST request
// This function also performs error checking to make sure the key is valid.
func NewPublicKey(base64PublicKey []byte) (PublicKey, error) {
	decodedLen := base64.StdEncoding.DecodedLen(len(base64PublicKey))
	dbuf := make([]byte, decodedLen)
	n, err := base64.StdEncoding.Decode(dbuf, base64PublicKey)
	if err != nil {
Exemple #14
0
	"github.com/phayes/errors"
	"regexp"
)

const (
	MaxBallotIDSize = 128
)

var (
	// maxBallotSize: election-id (max 128 bytes) + BallotID + Vote + (64 tags) + signature + line-seperators
	MaxBallotSize = MaxElectionIDSize + MaxBallotIDSize + (maxVoteSize) + (64 * (MaxTagKeySize + MaxTagValueSize + 1)) + base64.StdEncoding.EncodedLen(1024) + (4*2 + 64 + 64)
	ValidBallotID = regexp.MustCompile(`^[0-9a-zA-Z\-\.\[\]_~:/?#@!$&'()*+,;=]+$`) // Regex for valid characters. More or less the same as RFC 3986, sec 2.

	ErrBallotTooBig        = errors.Newf("This ballot is too big. Maximum ballot size is %i bytes", MaxBallotSize)
	ErrBallotIDTooBig      = errors.Newf("Ballot ID is too big. Maximum ballot-id size is %i characters", MaxBallotIDSize)
	ErrBallotInvalid       = errors.New("Invalid ballot format")
	ErrBallotIDInvalid     = errors.New("Ballot ID contains illigal characters. Valid characters are as per RFC 3986, sec 2: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=")
	ErrBallotInvalidVote   = errors.New("Cannot parse Cote in ballot")
	ErrBallotInvalidTagSet = errors.New("Cannot parse TagSet in ballot")
	ErrBallotInvalidSig    = errors.New("Cannot parse ballot Signature")
	ErrBallotSigNotFound   = errors.New("Could not verify ballot signature: Signature does not exist")
)

type Ballot struct {
	ElectionID string
	BallotID   string // Random user-selected string. Valid characters are as per RFC 3986, sec 2: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
	Vote              // Ordered list of choice
	TagSet            // Arbitrary key-value store
	Signature         // Crypto signature for the ballot (signed by ballot-clerk server)
}
package cryptoballot

import (
	"bytes"
	"github.com/phayes/errors"
)

type FulfilledSignatureRequest struct {
	SignatureRequest
	BallotSignature Signature // ElectionClerk signature signing off on the validity of the ballot
}

var (
	ErrFulfilledSignatureRequestInvalid = errors.New("Cannot read Fulfilled Signature Request. Invalid format")
)

// Given the raw bytes of a Fulfilled Signature Request, get a FulfilledSignatureRequest object
func NewFulfilledSignatureRequest(rawBytes []byte) (*FulfilledSignatureRequest, error) {
	parts := bytes.Split(rawBytes, []byte("\n\n"))

	if len(parts) != 6 {
		return &FulfilledSignatureRequest{}, ErrFulfilledSignatureRequestInvalid
	}

	signatureRequest, err := NewSignatureRequest(bytes.Join(parts[:5], []byte("\n\n")))
	if err != nil {
		return &FulfilledSignatureRequest{}, err
	}
	ballotSignature, err := NewSignature(parts[5])
	if err != nil {
		return &FulfilledSignatureRequest{}, err