<commit_before>/*
   Copyright The containerd Authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package cni

import (
	"context"
	"fmt"
	"strings"
	"sync"

	cnilibrary "github.com/containernetworking/cni/libcni"
	"github.com/containernetworking/cni/pkg/types"
	types100 "github.com/containernetworking/cni/pkg/types/100"
)

type CNI interface {
	// Setup setup the network for the namespace
	Setup(ctx context.Context, id string, path string, opts ...NamespaceOpts) (*Result, error)
	// Remove tears down the network of the namespace.
	Remove(ctx context.Context, id string, path string, opts ...NamespaceOpts) error
	// Check checks if the network is still in desired state
	Check(ctx context.Context, id string, path string, opts ...NamespaceOpts) error
	// Load loads the cni network config
	Load(opts ...Opt) error
	// Status checks the status of the cni initialization
	Status() error
	// GetConfig returns a copy of the CNI plugin configurations as parsed by CNI
	GetConfig() *ConfigResult
}

type ConfigResult struct {
	PluginDirs       []string
	PluginConfDir    string
	PluginMaxConfNum int
	Prefix           string
	Networks         []*ConfNetwork
}

type ConfNetwork struct {
	Config *NetworkConfList
	IFName string
}

// NetworkConfList is a source bytes to string version of cnilibrary.NetworkConfigList
type NetworkConfList struct {
	Name       string
	CNIVersion string
	Plugins    []*NetworkConf
	Source     string
}

// NetworkConf is a source bytes to string conversion of cnilibrary.NetworkConfig
type NetworkConf struct {
	Network *types.NetConf
	Source  string
}

type libcni struct {
	config

	cniConfig    cnilibrary.CNI
	networkCount int // minimum network plugin configurations needed to initialize cni
	networks     []*Network
	sync.RWMutex
}

func defaultCNIConfig() *libcni {
	return &libcni{
		config: config{
			pluginDirs:       []string{DefaultCNIDir},
			pluginConfDir:    DefaultNetDir,
			pluginMaxConfNum: DefaultMaxConfNum,
			prefix:           DefaultPrefix,
		},
		cniConfig: &cnilibrary.CNIConfig{
			Path: []string{DefaultCNIDir},
		},
		networkCount: 1,
	}
}

// New creates a new libcni instance.
func New(config ...Opt) (CNI, error) {
	cni := defaultCNIConfig()
	var err error
	for _, c := range config {
		if err = c(cni); err != nil {
			return nil, err
		}
	}
	return cni, nil
}

// Load loads the latest config from cni config files.
func (c *libcni) Load(opts ...Opt) error {
	var err error
	c.Lock()
	defer c.Unlock()
	// Reset the networks on a load operation to ensure
	// config happens on a clean slate
	c.reset()

	for _, o := range opts {
		if err = o(c); err != nil {
			return fmt.Errorf("cni config load failed: %v: %w", err, ErrLoad)
		}
	}
	return nil
}

// Status returns the status of CNI initialization.
func (c *libcni) Status() error {
	c.RLock()
	defer c.RUnlock()
	if len(c.networks) < c.networkCount {
		return ErrCNINotInitialized
	}
	return nil
}

// Networks returns all the configured networks.
// NOTE: Caller MUST NOT modify anything in the returned array.
func (c *libcni) Networks() []*Network {
	c.RLock()
	defer c.RUnlock()
	return append([]*Network{}, c.networks...)
}

// Setup setups the network in the namespace and returns a Result
func (c *libcni) Setup(ctx context.Context, id string, path string, opts ...NamespaceOpts) (*Result, error) {
	if err := c.Status(); err != nil {
		return nil, err
	}
	ns, err := newNamespace(id, path, opts...)
	if err != nil {
		return nil, err
	}
	result, err := c.attachNetworks(ctx, ns)
	if err != nil {
		return nil, err
	}
	return c.createResult(result)
}

type asynchAttachResult struct {
	index int
	res   *types100.Result
	err   error
}

func asynchAttach(ctx context.Context, index int, n *Network, ns *Namespace, wg *sync.WaitGroup, rc chan asynchAttachResult) {
	defer wg.Done()
	r, err := n.Attach(ctx, ns)
	rc <- asynchAttachResult{index: index, res: r, err: err}
}

func (c *libcni) attachNetworks(ctx context.Context, ns *Namespace) ([]*types100.Result, error) {
	var wg sync.WaitGroup
	var firstError error
	results := make([]*types100.Result, len(c.Networks()))
	rc := make(chan asynchAttachResult)

	for i, network := range c.Networks() {
		wg.Add(1)
		go asynchAttach(ctx, i, network, ns, &wg, rc)
	}

	for range c.Networks() {
		rs := <-rc
		if rs.err != nil && firstError == nil {
			firstError = rs.err
		}
		results[rs.index] = rs.res
	}
	wg.Wait()

	return results, firstError
}

// Remove removes the network config from the namespace
func (c *libcni) Remove(ctx context.Context, id string, path string, opts ...NamespaceOpts) error {
	if err := c.Status(); err != nil {
		return err
	}
	ns, err := newNamespace(id, path, opts...)
	if err != nil {
		return err
	}
	for _, network := range c.Networks() {
		if err := network.Remove(ctx, ns); err != nil {
			// Based on CNI spec v0.7.0, empty network namespace is allowed to
			// do best effort cleanup. However, it is not handled consistently
			// right now:
			// https://github.com/containernetworking/plugins/issues/210
			// TODO(random-liu): Remove the error handling when the issue is
			// fixed and the CNI spec v0.6.0 support is deprecated.
			// NOTE(claudiub): Some CNIs could return a "not found" error, which could mean that
			// it was already deleted.
			if (path == "" && strings.Contains(err.Error(), "no such file or directory")) || strings.Contains(err.Error(), "not found") {
				continue
			}
			return err
		}
	}
	return nil
}

// Check checks if the network is still in desired state
func (c *libcni) Check(ctx context.Context, id string, path string, opts ...NamespaceOpts) error {
	if err := c.Status(); err != nil {
		return err
	}
	ns, err := newNamespace(id, path, opts...)
	if err != nil {
		return err
	}
	for _, network := range c.Networks() {
		err := network.Check(ctx, ns)
		if err != nil {
			return err
		}
	}

	return nil
}

// GetConfig returns a copy of the CNI plugin configurations as parsed by CNI
func (c *libcni) GetConfig() *ConfigResult {
	c.RLock()
	defer c.RUnlock()
	r := &ConfigResult{
		PluginDirs:       c.config.pluginDirs,
		PluginConfDir:    c.config.pluginConfDir,
		PluginMaxConfNum: c.config.pluginMaxConfNum,
		Prefix:           c.config.prefix,
	}
	for _, network := range c.networks {
		conf := &NetworkConfList{
			Name:       network.config.Name,
			CNIVersion: network.config.CNIVersion,
			Source:     string(network.config.Bytes),
		}
		for _, plugin := range network.config.Plugins {
			conf.Plugins = append(conf.Plugins, &NetworkConf{
				Network: plugin.Network,
				Source:  string(plugin.Bytes),
			})
		}
		r.Networks = append(r.Networks, &ConfNetwork{
			Config: conf,
			IFName: network.ifName,
		})
	}
	return r
}

func (c *libcni) reset() {
	c.networks = nil
}
<commit_msg>cni: fix data-race on lazy init by ensureExec().<commit_after>/*
   Copyright The containerd Authors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package cni

import (
	"context"
	"fmt"
	"os"
	"strings"
	"sync"

	cnilibrary "github.com/containernetworking/cni/libcni"
	"github.com/containernetworking/cni/pkg/invoke"
	"github.com/containernetworking/cni/pkg/types"
	types100 "github.com/containernetworking/cni/pkg/types/100"
	"github.com/containernetworking/cni/pkg/version"
)

type CNI interface {
	// Setup setup the network for the namespace
	Setup(ctx context.Context, id string, path string, opts ...NamespaceOpts) (*Result, error)
	// Remove tears down the network of the namespace.
	Remove(ctx context.Context, id string, path string, opts ...NamespaceOpts) error
	// Check checks if the network is still in desired state
	Check(ctx context.Context, id string, path string, opts ...NamespaceOpts) error
	// Load loads the cni network config
	Load(opts ...Opt) error
	// Status checks the status of the cni initialization
	Status() error
	// GetConfig returns a copy of the CNI plugin configurations as parsed by CNI
	GetConfig() *ConfigResult
}

type ConfigResult struct {
	PluginDirs       []string
	PluginConfDir    string
	PluginMaxConfNum int
	Prefix           string
	Networks         []*ConfNetwork
}

type ConfNetwork struct {
	Config *NetworkConfList
	IFName string
}

// NetworkConfList is a source bytes to string version of cnilibrary.NetworkConfigList
type NetworkConfList struct {
	Name       string
	CNIVersion string
	Plugins    []*NetworkConf
	Source     string
}

// NetworkConf is a source bytes to string conversion of cnilibrary.NetworkConfig
type NetworkConf struct {
	Network *types.NetConf
	Source  string
}

type libcni struct {
	config

	cniConfig    cnilibrary.CNI
	networkCount int // minimum network plugin configurations needed to initialize cni
	networks     []*Network
	sync.RWMutex
}

func defaultCNIConfig() *libcni {
	return &libcni{
		config: config{
			pluginDirs:       []string{DefaultCNIDir},
			pluginConfDir:    DefaultNetDir,
			pluginMaxConfNum: DefaultMaxConfNum,
			prefix:           DefaultPrefix,
		},
		cniConfig: cnilibrary.NewCNIConfig(
			[]string{
				DefaultCNIDir,
			},
			&invoke.DefaultExec{
				RawExec:       &invoke.RawExec{Stderr: os.Stderr},
				PluginDecoder: version.PluginDecoder{},
			},
		),
		networkCount: 1,
	}
}

// New creates a new libcni instance.
func New(config ...Opt) (CNI, error) {
	cni := defaultCNIConfig()
	var err error
	for _, c := range config {
		if err = c(cni); err != nil {
			return nil, err
		}
	}
	return cni, nil
}

// Load loads the latest config from cni config files.
func (c *libcni) Load(opts ...Opt) error {
	var err error
	c.Lock()
	defer c.Unlock()
	// Reset the networks on a load operation to ensure
	// config happens on a clean slate
	c.reset()

	for _, o := range opts {
		if err = o(c); err != nil {
			return fmt.Errorf("cni config load failed: %v: %w", err, ErrLoad)
		}
	}
	return nil
}

// Status returns the status of CNI initialization.
func (c *libcni) Status() error {
	c.RLock()
	defer c.RUnlock()
	if len(c.networks) < c.networkCount {
		return ErrCNINotInitialized
	}
	return nil
}

// Networks returns all the configured networks.
// NOTE: Caller MUST NOT modify anything in the returned array.
func (c *libcni) Networks() []*Network {
	c.RLock()
	defer c.RUnlock()
	return append([]*Network{}, c.networks...)
}

// Setup setups the network in the namespace and returns a Result
func (c *libcni) Setup(ctx context.Context, id string, path string, opts ...NamespaceOpts) (*Result, error) {
	if err := c.Status(); err != nil {
		return nil, err
	}
	ns, err := newNamespace(id, path, opts...)
	if err != nil {
		return nil, err
	}
	result, err := c.attachNetworks(ctx, ns)
	if err != nil {
		return nil, err
	}
	return c.createResult(result)
}

type asynchAttachResult struct {
	index int
	res   *types100.Result
	err   error
}

func asynchAttach(ctx context.Context, index int, n *Network, ns *Namespace, wg *sync.WaitGroup, rc chan asynchAttachResult) {
	defer wg.Done()
	r, err := n.Attach(ctx, ns)
	rc <- asynchAttachResult{index: index, res: r, err: err}
}

func (c *libcni) attachNetworks(ctx context.Context, ns *Namespace) ([]*types100.Result, error) {
	var wg sync.WaitGroup
	var firstError error
	results := make([]*types100.Result, len(c.Networks()))
	rc := make(chan asynchAttachResult)

	for i, network := range c.Networks() {
		wg.Add(1)
		go asynchAttach(ctx, i, network, ns, &wg, rc)
	}

	for range c.Networks() {
		rs := <-rc
		if rs.err != nil && firstError == nil {
			firstError = rs.err
		}
		results[rs.index] = rs.res
	}
	wg.Wait()

	return results, firstError
}

// Remove removes the network config from the namespace
func (c *libcni) Remove(ctx context.Context, id string, path string, opts ...NamespaceOpts) error {
	if err := c.Status(); err != nil {
		return err
	}
	ns, err := newNamespace(id, path, opts...)
	if err != nil {
		return err
	}
	for _, network := range c.Networks() {
		if err := network.Remove(ctx, ns); err != nil {
			// Based on CNI spec v0.7.0, empty network namespace is allowed to
			// do best effort cleanup. However, it is not handled consistently
			// right now:
			// https://github.com/containernetworking/plugins/issues/210
			// TODO(random-liu): Remove the error handling when the issue is
			// fixed and the CNI spec v0.6.0 support is deprecated.
			// NOTE(claudiub): Some CNIs could return a "not found" error, which could mean that
			// it was already deleted.
			if (path == "" && strings.Contains(err.Error(), "no such file or directory")) || strings.Contains(err.Error(), "not found") {
				continue
			}
			return err
		}
	}
	return nil
}

// Check checks if the network is still in desired state
func (c *libcni) Check(ctx context.Context, id string, path string, opts ...NamespaceOpts) error {
	if err := c.Status(); err != nil {
		return err
	}
	ns, err := newNamespace(id, path, opts...)
	if err != nil {
		return err
	}
	for _, network := range c.Networks() {
		err := network.Check(ctx, ns)
		if err != nil {
			return err
		}
	}

	return nil
}

// GetConfig returns a copy of the CNI plugin configurations as parsed by CNI
func (c *libcni) GetConfig() *ConfigResult {
	c.RLock()
	defer c.RUnlock()
	r := &ConfigResult{
		PluginDirs:       c.config.pluginDirs,
		PluginConfDir:    c.config.pluginConfDir,
		PluginMaxConfNum: c.config.pluginMaxConfNum,
		Prefix:           c.config.prefix,
	}
	for _, network := range c.networks {
		conf := &NetworkConfList{
			Name:       network.config.Name,
			CNIVersion: network.config.CNIVersion,
			Source:     string(network.config.Bytes),
		}
		for _, plugin := range network.config.Plugins {
			conf.Plugins = append(conf.Plugins, &NetworkConf{
				Network: plugin.Network,
				Source:  string(plugin.Bytes),
			})
		}
		r.Networks = append(r.Networks, &ConfNetwork{
			Config: conf,
			IFName: network.ifName,
		})
	}
	return r
}

func (c *libcni) reset() {
	c.networks = nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"code.google.com/p/go.crypto/scrypt"
	"crypto/aes"
	"crypto/sha256"
	"encoding/hex"
	"flag"
	"github.com/piotrnar/gocoin/btc"
	"log"
	"math"
	"math/big"
)

func sha256Twice(b []byte) []byte {
	h := sha256.New()
	h.Write(b)
	hashedOnce := h.Sum(nil)
	h.Reset()
	h.Write(hashedOnce)
	return h.Sum(nil)
}

func verifyPassphrase(encryptedKey string, passphrase string) bool {
	dec := btc.Decodeb58(encryptedKey)[:39] // trim to length 39 (not sure why needed)
	if dec == nil {
		log.Fatal("Cannot decode base58 string " + encryptedKey)
	}

	// log.Printf("Decoded base58 string to %s (length %d)", hex.EncodeToString(dec), len(dec))

	if dec[0] == 0x01 && dec[1] == 0x42 {
		// log.Print("EC multiply mode not used")

		log.Fatal("TODO: implement decryption when EC multiply mode not used")
	} else if dec[0] == 0x01 && dec[1] == 0x43 {
		// log.Print("EC multiply mode used")

		compress := dec[2]&0x20 == 0x20
		hasLotSequence := dec[2]&0x04 == 0x04

		var ownerSalt, ownerEntropy []byte
		if hasLotSequence {
			ownerSalt = dec[7:11]
			ownerEntropy = dec[7:15]
		} else {
			ownerSalt = dec[7:15]
			ownerEntropy = ownerSalt
		}

		// log.Printf("Owner salt: %s", hex.EncodeToString(ownerSalt))
		// log.Printf("Has lot/sequence: %t", hasLotSequence)
		// log.Printf("Compress: %t", compress)

		prefactorA, err := scrypt.Key([]byte(passphrase), ownerSalt, 16384, 8, 8, 32)
		if prefactorA == nil {
			log.Fatal(err)
		}

		var passFactor []byte

		if hasLotSequence {
			// lotNumber := int(ownerSalt[4])*4096 + int(ownerSalt[5])*16 + int(ownerSalt[6])/16
			// sequenceNumber := int(ownerSalt[6]&0x0f)*256 + int(ownerSalt[7])
			// log.Printf("Lot number: %d", lotNumber)
			// log.Printf("Sequence number: %d", sequenceNumber)

			prefactorB := bytes.Join([][]byte{prefactorA, ownerEntropy}, nil)
			passFactor = sha256Twice(prefactorB)
		} else {
			passFactor = prefactorA
		}

		// log.Printf("passfactor: %s (length %d)", hex.EncodeToString(passFactor), len(passFactor))

		passpoint, err := btc.PublicFromPrivate(passFactor, true)
		if passpoint == nil {
			log.Fatal(err)
		}

		// log.Printf("passpoint: %s", hex.EncodeToString(passpoint))

		encryptedpart1 := dec[15:23]
		encryptedpart2 := dec[23:39]

		derived, err := scrypt.Key(passpoint, bytes.Join([][]byte{dec[3:7], ownerEntropy}, nil), 1024, 1, 1, 64)
		if derived == nil {
			log.Fatal(err)
		}

		h, err := aes.NewCipher(derived[32:])
		if h == nil {
			log.Fatal(err)
		}

		unencryptedpart2 := make([]byte, 16)
		h.Decrypt(unencryptedpart2, encryptedpart2)
		for i := range unencryptedpart2 {
			unencryptedpart2[i] ^= derived[i+16]
		}

		encryptedpart1 = bytes.Join([][]byte{encryptedpart1, unencryptedpart2[:8]}, nil)

		unencryptedpart1 := make([]byte, 16)
		h.Decrypt(unencryptedpart1, encryptedpart1)
		for i := range unencryptedpart1 {
			unencryptedpart1[i] ^= derived[i]
		}

		seeddb := bytes.Join([][]byte{unencryptedpart1[:16], unencryptedpart2[8:]}, nil)

		factorb := sha256Twice(seeddb)

		// log.Printf("passfactor: %s", hex.EncodeToString(passFactor))
		// log.Printf("factorb: %s", hex.EncodeToString(factorb))

		bigN, success := new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
		if !success {
			log.Fatal("Failed to create Int for N")
		}

		passFactorBig := new(big.Int).SetBytes(passFactor)
		factorbBig := new(big.Int).SetBytes(factorb)

		privKey := new(big.Int)
		privKey.Mul(passFactorBig, factorbBig)
		privKey.Mod(privKey, bigN)

		pubKey, err := btc.PublicFromPrivate(privKey.Bytes(), compress)
		if pubKey == nil {
			log.Fatal(err)
		}

		addr := btc.NewAddrFromPubkey(pubKey, 0).String()

		addrHashed := sha256Twice([]byte(addr))

		if addrHashed[0] != dec[3] || addrHashed[1] != dec[4] || addrHashed[2] != dec[5] || addrHashed[3] != dec[6] {
			return false
		}

		log.Printf("Address: %s", addr)
		log.Printf("Private key: %s", hex.EncodeToString(privKey.Bytes()))
		return true
	}

	log.Fatal("Malformed byte slice")
	return false
}

var totalTried = 0

func searchRange(start int, finish int, encryptedKey string, charset string, c chan string) {
	i := 0
	for _, rune1 := range charset {
		for _, rune2 := range charset {
			for _, rune3 := range charset {
				if start <= i {
					guess := string(rune1) + string(rune2) + string(rune3)

					// log.Printf("Trying %s", guess)
					if verifyPassphrase(encryptedKey, guess) {
						c <- "Found!"
					}

					if totalTried%10 == 0 {
						log.Printf("%d passphrases tried", totalTried)
					}

					totalTried++
				} else if i == finish {
					// Not found within this range - bail.
					return
				}

				i++
			}
		}
	}
}

func main() {
	var routines int
	flag.IntVar(&routines, "routines", 1, "number of goroutines to spawn")
	flag.Parse()

	encryptedKey := flag.Arg(0)

	length := 3 // Length of passphrase, hardcoded for now...

	if encryptedKey == "" {
		log.Fatal("encryptedKey required")
	}

	if routines < 1 {
		log.Fatal("routines must be >= 1")
	}

	if length < 1 {
		log.Fatal("length must be >= 1")
	}

	//charset := " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"
	//charset := "0123456789"
	charset := " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"

	spaceSize := int(math.Pow(float64(len(charset)), float64(length)))
	blockSize := spaceSize / routines

	log.Printf("Routines: %d", routines)
	log.Printf("Space size: %d", spaceSize)
	log.Printf("Block size: %d", blockSize)

	c := make(chan string)

	for i := 0; i < routines; i++ {
		var finish int
		if i == routines-1 {
			// Last block needs to go right to the end of the search space
			finish = spaceSize
		} else {
			finish = i*blockSize + blockSize
		}
		go searchRange(i*blockSize, finish, flag.Arg(0), charset, c)
	}

	<-c
}
<commit_msg>Remove lots of debug code. Output the passphrase!<commit_after>package main

import (
	"bytes"
	"code.google.com/p/go.crypto/scrypt"
	"crypto/aes"
	"crypto/sha256"
	"encoding/hex"
	"flag"
	"github.com/piotrnar/gocoin/btc"
	"log"
	"math"
	"math/big"
)

func sha256Twice(b []byte) []byte {
	h := sha256.New()
	h.Write(b)
	hashedOnce := h.Sum(nil)
	h.Reset()
	h.Write(hashedOnce)
	return h.Sum(nil)
}

func verifyPassphrase(encryptedKey string, passphrase string) bool {
	dec := btc.Decodeb58(encryptedKey)[:39] // trim to length 39 (not sure why needed)
	if dec == nil {
		log.Fatal("Cannot decode base58 string " + encryptedKey)
	}

	if dec[0] == 0x01 && dec[1] == 0x42 {
		log.Fatal("TODO: implement decryption when EC multiply mode not used")
	} else if dec[0] == 0x01 && dec[1] == 0x43 {
		compress := dec[2]&0x20 == 0x20
		hasLotSequence := dec[2]&0x04 == 0x04

		var ownerSalt, ownerEntropy []byte
		if hasLotSequence {
			ownerSalt = dec[7:11]
			ownerEntropy = dec[7:15]
		} else {
			ownerSalt = dec[7:15]
			ownerEntropy = ownerSalt
		}

		prefactorA, err := scrypt.Key([]byte(passphrase), ownerSalt, 16384, 8, 8, 32)
		if prefactorA == nil {
			log.Fatal(err)
		}

		var passFactor []byte
		if hasLotSequence {
			prefactorB := bytes.Join([][]byte{prefactorA, ownerEntropy}, nil)
			passFactor = sha256Twice(prefactorB)
		} else {
			passFactor = prefactorA
		}

		passpoint, err := btc.PublicFromPrivate(passFactor, true)
		if passpoint == nil {
			log.Fatal(err)
		}

		encryptedpart1 := dec[15:23]
		encryptedpart2 := dec[23:39]

		derived, err := scrypt.Key(passpoint, bytes.Join([][]byte{dec[3:7], ownerEntropy}, nil), 1024, 1, 1, 64)
		if derived == nil {
			log.Fatal(err)
		}

		h, err := aes.NewCipher(derived[32:])
		if h == nil {
			log.Fatal(err)
		}

		unencryptedpart2 := make([]byte, 16)
		h.Decrypt(unencryptedpart2, encryptedpart2)
		for i := range unencryptedpart2 {
			unencryptedpart2[i] ^= derived[i+16]
		}

		encryptedpart1 = bytes.Join([][]byte{encryptedpart1, unencryptedpart2[:8]}, nil)

		unencryptedpart1 := make([]byte, 16)
		h.Decrypt(unencryptedpart1, encryptedpart1)
		for i := range unencryptedpart1 {
			unencryptedpart1[i] ^= derived[i]
		}

		seeddb := bytes.Join([][]byte{unencryptedpart1[:16], unencryptedpart2[8:]}, nil)
		factorb := sha256Twice(seeddb)

		bigN, success := new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
		if !success {
			log.Fatal("Failed to create Int for N")
		}

		passFactorBig := new(big.Int).SetBytes(passFactor)
		factorbBig := new(big.Int).SetBytes(factorb)

		privKey := new(big.Int)
		privKey.Mul(passFactorBig, factorbBig)
		privKey.Mod(privKey, bigN)

		pubKey, err := btc.PublicFromPrivate(privKey.Bytes(), compress)
		if pubKey == nil {
			log.Fatal(err)
		}

		addr := btc.NewAddrFromPubkey(pubKey, 0).String()

		addrHashed := sha256Twice([]byte(addr))

		if addrHashed[0] != dec[3] || addrHashed[1] != dec[4] || addrHashed[2] != dec[5] || addrHashed[3] != dec[6] {
			return false
		}

		log.Printf("Address: %s", addr)
		log.Printf("Private key: %s", hex.EncodeToString(privKey.Bytes()))
		log.Printf("Passphrase was: %s", passphrase)
		return true
	}

	log.Fatal("Malformed byte slice")
	return false
}

var totalTried = 0

func searchRange(start int, finish int, encryptedKey string, charset string, c chan string) {
	i := 0
	for _, rune1 := range charset {
		for _, rune2 := range charset {
			for _, rune3 := range charset {
				if start <= i {
					guess := string(rune1) + string(rune2) + string(rune3)

					if verifyPassphrase(encryptedKey, guess) {
						c <- "Found!"
					}

					if totalTried%10 == 0 {
						log.Printf("%d passphrases tried", totalTried)
					}

					totalTried++
				} else if i == finish {
					return
				}

				i++
			}
		}
	}
}

func main() {
	var routines int
	flag.IntVar(&routines, "routines", 1, "number of goroutines to spawn")
	flag.Parse()

	encryptedKey := flag.Arg(0)

	length := 3 // Length of passphrase, hardcoded for now...

	if encryptedKey == "" {
		log.Fatal("encryptedKey required")
	}

	if routines < 1 {
		log.Fatal("routines must be >= 1")
	}

	if length < 1 {
		log.Fatal("length must be >= 1")
	}

	//charset := " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"
	//charset := "0123456789"
	charset := " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"

	spaceSize := int(math.Pow(float64(len(charset)), float64(length)))
	blockSize := spaceSize / routines

	c := make(chan string)

	for i := 0; i < routines; i++ {
		var finish int
		if i == routines-1 {
			// Last block needs to go right to the end of the search space
			finish = spaceSize
		} else {
			finish = i*blockSize + blockSize
		}
		go searchRange(i*blockSize, finish, flag.Arg(0), charset, c)
	}

	<-c
}
<|endoftext|>


<commit_before>package bridge

import (
	"errors"
	"log"
	"net"
	"net/url"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
	"sync"

	dockerapi "github.com/fsouza/go-dockerclient"
)

var serviceIDPattern = regexp.MustCompile(`^(.+?):([a-zA-Z0-9][a-zA-Z0-9_.-]+):[0-9]+(?::udp)?$`)

type Bridge struct {
	sync.Mutex
	registry       RegistryAdapter
	docker         *dockerapi.Client
	services       map[string][]*Service
	deadContainers map[string]*DeadContainer
	config         Config
}

func New(docker *dockerapi.Client, adapterUri string, config Config) (*Bridge, error) {
	uri, err := url.Parse(adapterUri)
	if err != nil {
		return nil, errors.New("bad adapter uri: " + adapterUri)
	}
	factory, found := AdapterFactories.Lookup(uri.Scheme)
	if !found {
		return nil, errors.New("unrecognized adapter: " + adapterUri)
	}

	log.Println("Using", uri.Scheme, "adapter:", uri)
	return &Bridge{
		docker:         docker,
		config:         config,
		registry:       factory.New(uri),
		services:       make(map[string][]*Service),
		deadContainers: make(map[string]*DeadContainer),
	}, nil
}

func (b *Bridge) Ping() error {
	return b.registry.Ping()
}

func (b *Bridge) Add(containerId string) {
	b.Lock()
	defer b.Unlock()
	b.add(containerId, false)
}

func (b *Bridge) Remove(containerId string) {
	b.remove(containerId, true)
}

func (b *Bridge) RemoveOnExit(containerId string) {
	b.remove(containerId, b.shouldRemove(containerId))
}

func (b *Bridge) Refresh() {
	b.Lock()
	defer b.Unlock()

	for containerId, deadContainer := range b.deadContainers {
		deadContainer.TTL -= b.config.RefreshInterval
		if deadContainer.TTL <= 0 {
			delete(b.deadContainers, containerId)
		}
	}

	for containerId, services := range b.services {
		for _, service := range services {
			err := b.registry.Refresh(service)
			if err != nil {
				log.Println("refresh failed:", service.ID, err)
				continue
			}
			log.Println("refreshed:", containerId[:12], service.ID)
		}
	}
}

func (b *Bridge) Sync(quiet bool) {
	b.Lock()
	defer b.Unlock()

	containers, err := b.docker.ListContainers(dockerapi.ListContainersOptions{})
	if err != nil && quiet {
		log.Println("error listing containers, skipping sync")
		return
	} else if err != nil && !quiet {
		log.Fatal(err)
	}

	log.Printf("Syncing services on %d containers", len(containers))

	// NOTE: This assumes reregistering will do the right thing, i.e. nothing..
	for _, listing := range containers {
		services := b.services[listing.ID]
		if services == nil {
			b.add(listing.ID, quiet)
		} else {
			for _, service := range services {
				err := b.registry.Register(service)
				if err != nil {
					log.Println("sync register failed:", service, err)
				}
			}
		}
	}

	// Clean up services that were registered previously, but aren't
	// acknowledged within registrator
	if b.config.Cleanup {
		// Remove services if its corresponding container is not running
		log.Println("Listing non-exited containers")
		filters := map[string][]string{"status": {"created", "restarting", "running", "paused"}}
		nonExitedContainers, err := b.docker.ListContainers(dockerapi.ListContainersOptions{Filters: filters})
		if err != nil {
			log.Println("error listing nonExitedContainers, skipping sync", err)
			return
		}
		for listingId, _ := range b.services {
			found := false
			for _, container := range nonExitedContainers {
				if listingId == container.ID {
					found = true
					break
				}
			}
			// This is a container that does not exist
			if !found {
				log.Printf("stale: Removing service %s because it does not exist", listingId)
				go b.RemoveOnExit(listingId)
			}
		}

		log.Println("Cleaning up dangling services")
		extServices, err := b.registry.Services()
		if err != nil {
			log.Println("cleanup failed:", err)
			return
		}

	Outer:
		for _, extService := range extServices {
			matches := serviceIDPattern.FindStringSubmatch(extService.ID)
			if len(matches) != 3 {
				// There's no way this was registered by us, so leave it
				continue
			}
			serviceHostname := matches[1]
			if serviceHostname != Hostname {
				// ignore because registered on a different host
				continue
			}
			serviceContainerName := matches[2]
			for _, listing := range b.services {
				for _, service := range listing {
					if service.Name == extService.Name && serviceContainerName == service.Origin.container.Name[1:] {
						continue Outer
					}
				}
			}
			log.Println("dangling:", extService.ID)
			err := b.registry.Deregister(extService)
			if err != nil {
				log.Println("deregister failed:", extService.ID, err)
				continue
			}
			log.Println(extService.ID, "removed")
		}
	}
}

func (b *Bridge) add(containerId string, quiet bool) {
	if d := b.deadContainers[containerId]; d != nil {
		b.services[containerId] = d.Services
		delete(b.deadContainers, containerId)
	}

	if b.services[containerId] != nil {
		log.Println("container, ", containerId[:12], ", already exists, ignoring")
		// Alternatively, remove and readd or resubmit.
		return
	}

	container, err := b.docker.InspectContainer(containerId)
	if err != nil {
		log.Println("unable to inspect container:", containerId[:12], err)
		return
	}

	ports := make(map[string]ServicePort)

	// Extract configured host port mappings, relevant when using --net=host
	for port, published := range container.HostConfig.PortBindings {
		ports[string(port)] = servicePort(container, port, published)
	}

	// Extract runtime port mappings, relevant when using --net=bridge
	for port, published := range container.NetworkSettings.Ports {
		ports[string(port)] = servicePort(container, port, published)
	}

	if len(ports) == 0 && !quiet {
		log.Println("ignored:", container.ID[:12], "no published ports")
		return
	}

	for _, port := range ports {
		if b.config.Internal != true && port.HostPort == "" {
			if !quiet {
				log.Println("ignored:", container.ID[:12], "port", port.ExposedPort, "not published on host")
			}
			continue
		}
		service := b.newService(port, len(ports) > 1)
		if service == nil {
			if !quiet {
				log.Println("ignored:", container.ID[:12], "service on port", port.ExposedPort)
			}
			continue
		}
		err := b.registry.Register(service)
		if err != nil {
			log.Println("register failed:", service, err)
			continue
		}
		b.services[container.ID] = append(b.services[container.ID], service)
		log.Println("added:", container.ID[:12], service.ID)
	}
}

func (b *Bridge) newService(port ServicePort, isgroup bool) *Service {
	container := port.container
	defaultName := strings.Split(path.Base(container.Config.Image), ":")[0]

	// not sure about this logic. kind of want to remove it.
	hostname := Hostname
	if hostname == "" {
		hostname = port.HostIP
	}
	if port.HostIP == "0.0.0.0" {
		ip, err := net.ResolveIPAddr("ip", hostname)
		if err == nil {
			port.HostIP = ip.String()
		}
	}

	if b.config.HostIp != "" {
		port.HostIP = b.config.HostIp
	}

	metadata, metadataFromPort := serviceMetaData(container.Config, port.ExposedPort)

	ignore := mapDefault(metadata, "ignore", "")
	if ignore != "" {
		return nil
	}

	service := new(Service)
	service.Origin = port
	service.ID = hostname + ":" + container.Name[1:] + ":" + port.ExposedPort
	service.Name = mapDefault(metadata, "name", defaultName)
	if isgroup && !metadataFromPort["name"] {
		service.Name += "-" + port.ExposedPort
	}
	var p int
	if b.config.Internal == true {
		service.IP = port.ExposedIP
		p, _ = strconv.Atoi(port.ExposedPort)
	} else {
		service.IP = port.HostIP
		p, _ = strconv.Atoi(port.HostPort)
	}
	service.Port = p

	if port.PortType == "udp" {
		service.Tags = combineTags(
			mapDefault(metadata, "tags", ""), b.config.ForceTags, "udp")
		service.ID = service.ID + ":udp"
	} else {
		service.Tags = combineTags(
			mapDefault(metadata, "tags", ""), b.config.ForceTags)
	}

	id := mapDefault(metadata, "id", "")
	if id != "" {
		service.ID = id
	}

	delete(metadata, "id")
	delete(metadata, "tags")
	delete(metadata, "name")
	service.Attrs = metadata
	service.TTL = b.config.RefreshTtl

	return service
}

func (b *Bridge) remove(containerId string, deregister bool) {
	b.Lock()
	defer b.Unlock()

	if deregister {
		deregisterAll := func(services []*Service) {
			for _, service := range services {
				err := b.registry.Deregister(service)
				if err != nil {
					log.Println("deregister failed:", service.ID, err)
					continue
				}
				log.Println("removed:", containerId[:12], service.ID)
			}
		}
		deregisterAll(b.services[containerId])
		if d := b.deadContainers[containerId]; d != nil {
			deregisterAll(d.Services)
			delete(b.deadContainers, containerId)
		}
	} else if b.config.RefreshTtl != 0 && b.services[containerId] != nil {
		// need to stop the refreshing, but can't delete it yet
		b.deadContainers[containerId] = &DeadContainer{b.config.RefreshTtl, b.services[containerId]}
	}
	delete(b.services, containerId)
}

// bit set on ExitCode if it represents an exit via a signal
var dockerSignaledBit = 128

func (b *Bridge) shouldRemove(containerId string) bool {
	if b.config.DeregisterCheck == "always" {
		return true
	}
	container, err := b.docker.InspectContainer(containerId)
	if _, ok := err.(*dockerapi.NoSuchContainer); ok {
		// the container has already been removed from Docker
		// e.g. probabably run with "--rm" to remove immediately
		// so its exit code is not accessible
		log.Printf("registrator: container %v was removed, could not fetch exit code", containerId[:12])
		return true
	}

	switch {
	case err != nil:
		log.Printf("registrator: error fetching status for container %v on \"die\" event: %v\n", containerId[:12], err)
		return false
	case container.State.Running:
		log.Printf("registrator: not removing container %v, still running", containerId[:12])
		return false
	case container.State.ExitCode == 0:
		return true
	case container.State.ExitCode&dockerSignaledBit == dockerSignaledBit:
		return true
	}
	return false
}

var Hostname string

func init() {
	// It's ok for Hostname to ultimately be an empty string
	// An empty string will fall back to trying to make a best guess
	Hostname, _ = os.Hostname()
}
<commit_msg>Fixes logic for appending port to SERVICE_NAME<commit_after>package bridge

import (
	"errors"
	"log"
	"net"
	"net/url"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
	"sync"

	dockerapi "github.com/fsouza/go-dockerclient"
)

var serviceIDPattern = regexp.MustCompile(`^(.+?):([a-zA-Z0-9][a-zA-Z0-9_.-]+):[0-9]+(?::udp)?$`)

type Bridge struct {
	sync.Mutex
	registry       RegistryAdapter
	docker         *dockerapi.Client
	services       map[string][]*Service
	deadContainers map[string]*DeadContainer
	config         Config
}

func New(docker *dockerapi.Client, adapterUri string, config Config) (*Bridge, error) {
	uri, err := url.Parse(adapterUri)
	if err != nil {
		return nil, errors.New("bad adapter uri: " + adapterUri)
	}
	factory, found := AdapterFactories.Lookup(uri.Scheme)
	if !found {
		return nil, errors.New("unrecognized adapter: " + adapterUri)
	}

	log.Println("Using", uri.Scheme, "adapter:", uri)
	return &Bridge{
		docker:         docker,
		config:         config,
		registry:       factory.New(uri),
		services:       make(map[string][]*Service),
		deadContainers: make(map[string]*DeadContainer),
	}, nil
}

func (b *Bridge) Ping() error {
	return b.registry.Ping()
}

func (b *Bridge) Add(containerId string) {
	b.Lock()
	defer b.Unlock()
	b.add(containerId, false)
}

func (b *Bridge) Remove(containerId string) {
	b.remove(containerId, true)
}

func (b *Bridge) RemoveOnExit(containerId string) {
	b.remove(containerId, b.shouldRemove(containerId))
}

func (b *Bridge) Refresh() {
	b.Lock()
	defer b.Unlock()

	for containerId, deadContainer := range b.deadContainers {
		deadContainer.TTL -= b.config.RefreshInterval
		if deadContainer.TTL <= 0 {
			delete(b.deadContainers, containerId)
		}
	}

	for containerId, services := range b.services {
		for _, service := range services {
			err := b.registry.Refresh(service)
			if err != nil {
				log.Println("refresh failed:", service.ID, err)
				continue
			}
			log.Println("refreshed:", containerId[:12], service.ID)
		}
	}
}

func (b *Bridge) Sync(quiet bool) {
	b.Lock()
	defer b.Unlock()

	containers, err := b.docker.ListContainers(dockerapi.ListContainersOptions{})
	if err != nil && quiet {
		log.Println("error listing containers, skipping sync")
		return
	} else if err != nil && !quiet {
		log.Fatal(err)
	}

	log.Printf("Syncing services on %d containers", len(containers))

	// NOTE: This assumes reregistering will do the right thing, i.e. nothing..
	for _, listing := range containers {
		services := b.services[listing.ID]
		if services == nil {
			b.add(listing.ID, quiet)
		} else {
			for _, service := range services {
				err := b.registry.Register(service)
				if err != nil {
					log.Println("sync register failed:", service, err)
				}
			}
		}
	}

	// Clean up services that were registered previously, but aren't
	// acknowledged within registrator
	if b.config.Cleanup {
		// Remove services if its corresponding container is not running
		log.Println("Listing non-exited containers")
		filters := map[string][]string{"status": {"created", "restarting", "running", "paused"}}
		nonExitedContainers, err := b.docker.ListContainers(dockerapi.ListContainersOptions{Filters: filters})
		if err != nil {
			log.Println("error listing nonExitedContainers, skipping sync", err)
			return
		}
		for listingId, _ := range b.services {
			found := false
			for _, container := range nonExitedContainers {
				if listingId == container.ID {
					found = true
					break
				}
			}
			// This is a container that does not exist
			if !found {
				log.Printf("stale: Removing service %s because it does not exist", listingId)
				go b.RemoveOnExit(listingId)
			}
		}

		log.Println("Cleaning up dangling services")
		extServices, err := b.registry.Services()
		if err != nil {
			log.Println("cleanup failed:", err)
			return
		}

	Outer:
		for _, extService := range extServices {
			matches := serviceIDPattern.FindStringSubmatch(extService.ID)
			if len(matches) != 3 {
				// There's no way this was registered by us, so leave it
				continue
			}
			serviceHostname := matches[1]
			if serviceHostname != Hostname {
				// ignore because registered on a different host
				continue
			}
			serviceContainerName := matches[2]
			for _, listing := range b.services {
				for _, service := range listing {
					if service.Name == extService.Name && serviceContainerName == service.Origin.container.Name[1:] {
						continue Outer
					}
				}
			}
			log.Println("dangling:", extService.ID)
			err := b.registry.Deregister(extService)
			if err != nil {
				log.Println("deregister failed:", extService.ID, err)
				continue
			}
			log.Println(extService.ID, "removed")
		}
	}
}

func (b *Bridge) add(containerId string, quiet bool) {
	if d := b.deadContainers[containerId]; d != nil {
		b.services[containerId] = d.Services
		delete(b.deadContainers, containerId)
	}

	if b.services[containerId] != nil {
		log.Println("container, ", containerId[:12], ", already exists, ignoring")
		// Alternatively, remove and readd or resubmit.
		return
	}

	container, err := b.docker.InspectContainer(containerId)
	if err != nil {
		log.Println("unable to inspect container:", containerId[:12], err)
		return
	}

	ports := make(map[string]ServicePort)

	// Extract configured host port mappings, relevant when using --net=host
	for port, published := range container.HostConfig.PortBindings {
		ports[string(port)] = servicePort(container, port, published)
	}

	// Extract runtime port mappings, relevant when using --net=bridge
	for port, published := range container.NetworkSettings.Ports {
		ports[string(port)] = servicePort(container, port, published)
	}

	if len(ports) == 0 && !quiet {
		log.Println("ignored:", container.ID[:12], "no published ports")
		return
	}

	servicePorts := make(map[string]ServicePort)
	for key, port := range ports {
		if b.config.Internal != true && port.HostPort == "" {
			if !quiet {
				log.Println("ignored:", container.ID[:12], "port", port.ExposedPort, "not published on host")
			}
			continue
		}
		servicePorts[key] = port
	}

	isGroup := len(servicePorts) > 1
	for _, port := range servicePorts {
		service := b.newService(port, isGroup)
		if service == nil {
			if !quiet {
				log.Println("ignored:", container.ID[:12], "service on port", port.ExposedPort)
			}
			continue
		}
		err := b.registry.Register(service)
		if err != nil {
			log.Println("register failed:", service, err)
			continue
		}
		b.services[container.ID] = append(b.services[container.ID], service)
		log.Println("added:", container.ID[:12], service.ID)
	}
}

func (b *Bridge) newService(port ServicePort, isgroup bool) *Service {
	container := port.container
	defaultName := strings.Split(path.Base(container.Config.Image), ":")[0]

	// not sure about this logic. kind of want to remove it.
	hostname := Hostname
	if hostname == "" {
		hostname = port.HostIP
	}
	if port.HostIP == "0.0.0.0" {
		ip, err := net.ResolveIPAddr("ip", hostname)
		if err == nil {
			port.HostIP = ip.String()
		}
	}

	if b.config.HostIp != "" {
		port.HostIP = b.config.HostIp
	}

	metadata, metadataFromPort := serviceMetaData(container.Config, port.ExposedPort)

	ignore := mapDefault(metadata, "ignore", "")
	if ignore != "" {
		return nil
	}

	service := new(Service)
	service.Origin = port
	service.ID = hostname + ":" + container.Name[1:] + ":" + port.ExposedPort
	service.Name = mapDefault(metadata, "name", defaultName)
	if isgroup && !metadataFromPort["name"] {
		service.Name += "-" + port.ExposedPort
	}
	var p int
	if b.config.Internal == true {
		service.IP = port.ExposedIP
		p, _ = strconv.Atoi(port.ExposedPort)
	} else {
		service.IP = port.HostIP
		p, _ = strconv.Atoi(port.HostPort)
	}
	service.Port = p

	if port.PortType == "udp" {
		service.Tags = combineTags(
			mapDefault(metadata, "tags", ""), b.config.ForceTags, "udp")
		service.ID = service.ID + ":udp"
	} else {
		service.Tags = combineTags(
			mapDefault(metadata, "tags", ""), b.config.ForceTags)
	}

	id := mapDefault(metadata, "id", "")
	if id != "" {
		service.ID = id
	}

	delete(metadata, "id")
	delete(metadata, "tags")
	delete(metadata, "name")
	service.Attrs = metadata
	service.TTL = b.config.RefreshTtl

	return service
}

func (b *Bridge) remove(containerId string, deregister bool) {
	b.Lock()
	defer b.Unlock()

	if deregister {
		deregisterAll := func(services []*Service) {
			for _, service := range services {
				err := b.registry.Deregister(service)
				if err != nil {
					log.Println("deregister failed:", service.ID, err)
					continue
				}
				log.Println("removed:", containerId[:12], service.ID)
			}
		}
		deregisterAll(b.services[containerId])
		if d := b.deadContainers[containerId]; d != nil {
			deregisterAll(d.Services)
			delete(b.deadContainers, containerId)
		}
	} else if b.config.RefreshTtl != 0 && b.services[containerId] != nil {
		// need to stop the refreshing, but can't delete it yet
		b.deadContainers[containerId] = &DeadContainer{b.config.RefreshTtl, b.services[containerId]}
	}
	delete(b.services, containerId)
}

// bit set on ExitCode if it represents an exit via a signal
var dockerSignaledBit = 128

func (b *Bridge) shouldRemove(containerId string) bool {
	if b.config.DeregisterCheck == "always" {
		return true
	}
	container, err := b.docker.InspectContainer(containerId)
	if _, ok := err.(*dockerapi.NoSuchContainer); ok {
		// the container has already been removed from Docker
		// e.g. probabably run with "--rm" to remove immediately
		// so its exit code is not accessible
		log.Printf("registrator: container %v was removed, could not fetch exit code", containerId[:12])
		return true
	}

	switch {
	case err != nil:
		log.Printf("registrator: error fetching status for container %v on \"die\" event: %v\n", containerId[:12], err)
		return false
	case container.State.Running:
		log.Printf("registrator: not removing container %v, still running", containerId[:12])
		return false
	case container.State.ExitCode == 0:
		return true
	case container.State.ExitCode&dockerSignaledBit == dockerSignaledBit:
		return true
	}
	return false
}

var Hostname string

func init() {
	// It's ok for Hostname to ultimately be an empty string
	// An empty string will fall back to trying to make a best guess
	Hostname, _ = os.Hostname()
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"syscall"
	"time"
)

type Service struct {
	Name       string `json:"name"`
	BridgeName string
	BridgeIP   string `json:"bridge-ip"`
	NginxConf  string `json:"nginx-config"`
	Pid        int
	Containers map[string]Container
	NginxUpStream
}

type Container struct {
	Name        string
	ServiceName string `json:"service-name"`
	Command     string `json:"command"`
	Pid         int
	IP          string
	StartTime   time.Time
	VEth        string
}

type NginxUpStream struct {
	LoadBalanceType string
	Servers         []string
	UpStreamConfig  string `json:"nginx-upstream"`
}

var services map[string]Service
var containers map[string]Container

const (
	bridgeNameBase = "brocker"
	vethNameBase   = "veth"
	MOUNT_LOC      = "/app"
	CONTAIN_DIR    = "/container"
)

func (c *Container) setName() {
	value := fmt.Sprintf("%s%s%s", c.Name, c.StartTime, c.Command)
	sha := sha1.New()
	sha.Write([]byte(value))
	c.Name = hex.EncodeToString(sha.Sum(nil))[:8]
}

func (c *Container) Close() {
	if err := execInContainter("/bin/umount /app", c.Pid); err != nil {
		fmt.Println("Cannot unmount /app: ", err)
	}

	p, _ := os.FindProcess(c.Pid)
	p.Kill()
}

func (s *Service) reload() {
	if err := execInContainter(fmt.Sprintf("/usr/sbin/nginx -s reload -c %s", s.NginxConf), s.Pid); err != nil {
		fmt.Println("Cannot reload nginx: ", err)
		return
	}
}

func (s *Service) Stop() {
	if err := execInContainter(fmt.Sprintf("/usr/sbin/nginx -s stop -c %s", s.NginxConf), s.Pid); err != nil {
		fmt.Println(err)
	}

	for _, c := range s.Containers {
		c.Close()
	}

	delete_bridge := strings.Split(fmt.Sprintf("ip link delete %s type bridge", s.BridgeName), " ")
	if err := exec.Command(delete_bridge[0], delete_bridge[1:]...).Run(); err != nil {
		fmt.Printf("Cannot delete bridge %s", s.BridgeName)
	}
}

func (n *NginxUpStream) writeConfig() {
	if _, err := os.Stat(n.UpStreamConfig); os.IsNotExist(err) {
		fmt.Println("Cannot update config", err)
		return
	}

	var buffer bytes.Buffer
	buffer.WriteString("upstream myapp1 {\n")
	buffer.WriteString(n.LoadBalanceType)
	buffer.WriteString(";\n")
	for _, s := range n.Servers {
		buffer.WriteString(fmt.Sprintf("server %s;\n", s))
	}
	buffer.WriteString("\n}")

	if err := ioutil.WriteFile(n.UpStreamConfig, buffer.Bytes(), 0644); err != nil {
		fmt.Println(err)
		return
	}
}

func init() {
	services = make(map[string]Service)
	containers = make(map[string]Container)
}

func main() {
	ctrl_c := make(chan os.Signal, 1)
	signal.Notify(ctrl_c, os.Interrupt)
	go func() {
		for _ = range ctrl_c {
			for _, s := range services {
				s.Stop()
			}
			os.Exit(0)
		}
	}()

	http.HandleFunc("/api/v1/service/add", service_add)
	http.HandleFunc("/api/v1/container/run", container_run)
	http.HandleFunc("/api/v1/container/list", container_list)
	http.HandleFunc("/api/v1/container/exec", container_exec)
	err := http.ListenAndServe(":3000", nil)
	if err != nil {
		fmt.Println(err)
	}
}

func service_add(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Invalid Request!", http.StatusMethodNotAllowed)
		return
	}

	s := Service{
		Containers: make(map[string]Container),
	}

	if err := json.NewDecoder(r.Body).Decode(&s); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if _, ok := services[s.Name]; ok {
		http.Error(w, "Service already exists", http.StatusInternalServerError)
		return
	}

	if _, err := os.Stat(s.NginxConf); os.IsNotExist(err) {
		http.Error(w, fmt.Sprintf("Cannot open %s\n%s", s.NginxConf, err.Error()), http.StatusInternalServerError)
		return
	}

	s.BridgeName = fmt.Sprintf("%s%d", bridgeNameBase, len(services)+1)

	s.LoadBalanceType = "least_conn"
	if err := service_create_network(s); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	path, err := exec.LookPath("nginx")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	c := Container{
		Name:        fmt.Sprintf("%s-nginx", s.Name),
		ServiceName: s.Name,
		Command:     fmt.Sprintf("%s -c %s", path, s.NginxConf),
	}

	go run(c, true)

	w.WriteHeader(http.StatusCreated)
}

func container_run(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Invalid Request!", http.StatusMethodNotAllowed)
		return
	}

	var c Container
	if err := json.NewDecoder(r.Body).Decode(&c); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if _, ok := services[c.ServiceName]; ok == false {
		http.Error(w, "Service does not exists", http.StatusInternalServerError)
		return
	}

	go run(c, false)

	w.WriteHeader(http.StatusCreated)
}

func container_list(w http.ResponseWriter, r *http.Request) {
	if err := json.NewEncoder(w).Encode(containers); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func container_exec(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Invalid Request!", http.StatusMethodNotAllowed)
		return
	}

	data := struct {
		Name string `json:"name"`
	}{}
	if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	for _, c := range containers {
		if c.Name == data.Name {
			w.Write([]byte(fmt.Sprintf("%d", c.Pid)))
			return
		}
	}
}

func service_create_network(s Service) error {
	create_bridge := strings.Split(fmt.Sprintf("/sbin/ip link add name %s type bridge", s.BridgeName), " ")
	set_bridge_up := strings.Split(fmt.Sprintf("/sbin/ip link set %s up", s.BridgeName), " ")
	set_bridge_ip := strings.Split(fmt.Sprintf("/sbin/ifconfig %s %s", s.BridgeName, s.BridgeIP), " ")

	if err := exec.Command(create_bridge[0], create_bridge[1:]...).Run(); err != nil {
		return err
	}

	if err := exec.Command(set_bridge_up[0], set_bridge_up[1:]...).Run(); err != nil {
		return err
	}

	if err := exec.Command(set_bridge_ip[0], set_bridge_ip[1:]...).Run(); err != nil {
		return err
	}

	services[s.Name] = s
	return nil
}

func run(c Container, isNginx bool) {
	fmt.Println("running parent")
	s := services[c.ServiceName]
	runcmd := "/home/yup/p/containers/brocker-run/brocker-run"

	cmd := &exec.Cmd{
		Path: runcmd,
		Args: append([]string{runcmd}, c.Command),
	}
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: syscall.CLONE_NEWPID |
			syscall.CLONE_NEWNS |
			syscall.CLONE_NEWNET,
	}

	if err := cmd.Start(); err != nil {
		fmt.Println(err)
	}

	c.Pid = cmd.Process.Pid
	c.VEth = fmt.Sprintf("%s%d", vethNameBase, len(containers))
	link := strings.Split(fmt.Sprintf("/sbin/ip link add name %s type veth peer name veth1 netns %d", c.VEth, c.Pid), " ")
	if err := exec.Command(link[0], link[1:]...).Run(); err != nil {
		fmt.Println(err)
		return
	}

	uplink := strings.Split(fmt.Sprintf("/sbin/ifconfig %s up", c.VEth), " ")
	if err := exec.Command(uplink[0], uplink[1:]...).Run(); err != nil {
		fmt.Println(err)
		return
	}

	bridge := strings.Split(fmt.Sprintf("/sbin/ip link set %s master %s", c.VEth, s.BridgeName), " ")
	if err := exec.Command(bridge[0], bridge[1:]...).Run(); err != nil {
		fmt.Println(err)
		return
	}

	bridgeip := net.ParseIP(s.BridgeIP)
	lastOctet := bridgeip[15] + byte(len(s.Containers)+1)
	ip := net.IPv4(bridgeip[12], bridgeip[13], bridgeip[14], lastOctet)
	c.IP = ip.String()

	if err := execInContainter(fmt.Sprintf("/sbin/ifconfig veth1 %s", ip.String()), c.Pid); err != nil {
		fmt.Println(err)
		return
	}

	/*
		Allows the use of CLONE_NEWNS on ubuntu boxes. util-linux <= 2.27 have issues
		with systemd making / shared across all namespaces
	*/
	if err := execInContainter("/bin/mount --make-private -o remount /", c.Pid); err != nil {
		fmt.Println(err)
		return
	}

	if err := os.Mkdir(fmt.Sprintf("%s/%s", CONTAIN_DIR, c.Name), 0644); err != nil {
		fmt.Println(err)
		return
	}

	if err := execInContainter(fmt.Sprintf("/bin/mount --bind %s/%s %s", CONTAIN_DIR, c.Name, MOUNT_LOC), c.Pid); err != nil {
		fmt.Println(err)
		return
	}

	c.StartTime = time.Now()
	c.setName()
	containers[c.Name] = c
	s.Containers[c.Name] = c

	if isNginx {
		s.Pid = c.Pid
	} else {
		s.Servers = append(s.Servers, fmt.Sprintf("%s:8080", c.IP))
		s.writeConfig()
		s.reload()
	}
	services[c.ServiceName] = s

	fmt.Println(cmd.Process.Pid)

	cmd.Wait()

	delete(containers, c.Name)
	delete(services[c.ServiceName].Containers, c.Name)
}

func execInContainter(cmd string, pid int) error {
	command := strings.Split(fmt.Sprintf("nsenter --target %d --pid --net --mount %s", pid, cmd), " ")
	if err := exec.Command(command[0], command[1:]...).Run(); err != nil {
		return err
	}

	return nil
}
<commit_msg>Better placement of name and time<commit_after>package main

import (
	"bytes"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"syscall"
	"time"
)

type Service struct {
	Name       string `json:"name"`
	BridgeName string
	BridgeIP   string `json:"bridge-ip"`
	NginxConf  string `json:"nginx-config"`
	Pid        int
	Containers map[string]Container
	NginxUpStream
}

type Container struct {
	Name        string
	ServiceName string `json:"service-name"`
	Command     string `json:"command"`
	Pid         int
	IP          string
	StartTime   time.Time
	VEth        string
}

type NginxUpStream struct {
	LoadBalanceType string
	Servers         []string
	UpStreamConfig  string `json:"nginx-upstream"`
}

var services map[string]Service
var containers map[string]Container

const (
	bridgeNameBase = "brocker"
	vethNameBase   = "veth"
	MOUNT_LOC      = "/app"
	CONTAIN_DIR    = "/container"
)

func (c *Container) setName() {
	value := fmt.Sprintf("%s%s%s", c.Name, c.StartTime, c.Command)
	sha := sha1.New()
	sha.Write([]byte(value))
	c.Name = hex.EncodeToString(sha.Sum(nil))[:8]
}

func (c *Container) Close() {
	if err := execInContainter("/bin/umount /app", c.Pid); err != nil {
		fmt.Println("Cannot unmount /app: ", err)
	}

	p, _ := os.FindProcess(c.Pid)
	p.Kill()
}

func (s *Service) reload() {
	if err := execInContainter(fmt.Sprintf("/usr/sbin/nginx -s reload -c %s", s.NginxConf), s.Pid); err != nil {
		fmt.Println("Cannot reload nginx: ", err)
		return
	}
}

func (s *Service) Stop() {
	if err := execInContainter(fmt.Sprintf("/usr/sbin/nginx -s stop -c %s", s.NginxConf), s.Pid); err != nil {
		fmt.Println(err)
	}

	for _, c := range s.Containers {
		c.Close()
	}

	delete_bridge := strings.Split(fmt.Sprintf("ip link delete %s type bridge", s.BridgeName), " ")
	if err := exec.Command(delete_bridge[0], delete_bridge[1:]...).Run(); err != nil {
		fmt.Printf("Cannot delete bridge %s", s.BridgeName)
	}
}

func (n *NginxUpStream) writeConfig() {
	if _, err := os.Stat(n.UpStreamConfig); os.IsNotExist(err) {
		fmt.Println("Cannot update config", err)
		return
	}

	var buffer bytes.Buffer
	buffer.WriteString("upstream myapp1 {\n")
	buffer.WriteString(n.LoadBalanceType)
	buffer.WriteString(";\n")
	for _, s := range n.Servers {
		buffer.WriteString(fmt.Sprintf("server %s;\n", s))
	}
	buffer.WriteString("\n}")

	if err := ioutil.WriteFile(n.UpStreamConfig, buffer.Bytes(), 0644); err != nil {
		fmt.Println(err)
		return
	}
}

func init() {
	services = make(map[string]Service)
	containers = make(map[string]Container)
}

func main() {
	ctrl_c := make(chan os.Signal, 1)
	signal.Notify(ctrl_c, os.Interrupt)
	go func() {
		for _ = range ctrl_c {
			for _, s := range services {
				s.Stop()
			}
			os.Exit(0)
		}
	}()

	http.HandleFunc("/api/v1/service/add", service_add)
	http.HandleFunc("/api/v1/container/run", container_run)
	http.HandleFunc("/api/v1/container/list", container_list)
	http.HandleFunc("/api/v1/container/exec", container_exec)
	err := http.ListenAndServe(":3000", nil)
	if err != nil {
		fmt.Println(err)
	}
}

func service_add(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Invalid Request!", http.StatusMethodNotAllowed)
		return
	}

	s := Service{
		Containers: make(map[string]Container),
	}

	if err := json.NewDecoder(r.Body).Decode(&s); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if _, ok := services[s.Name]; ok {
		http.Error(w, "Service already exists", http.StatusInternalServerError)
		return
	}

	if _, err := os.Stat(s.NginxConf); os.IsNotExist(err) {
		http.Error(w, fmt.Sprintf("Cannot open %s\n%s", s.NginxConf, err.Error()), http.StatusInternalServerError)
		return
	}

	s.BridgeName = fmt.Sprintf("%s%d", bridgeNameBase, len(services)+1)

	s.LoadBalanceType = "least_conn"
	if err := service_create_network(s); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	path, err := exec.LookPath("nginx")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	c := Container{
		Name:        fmt.Sprintf("%s-nginx", s.Name),
		ServiceName: s.Name,
		Command:     fmt.Sprintf("%s -c %s", path, s.NginxConf),
	}

	go run(c, true)

	w.WriteHeader(http.StatusCreated)
}

func container_run(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Invalid Request!", http.StatusMethodNotAllowed)
		return
	}

	var c Container
	if err := json.NewDecoder(r.Body).Decode(&c); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if _, ok := services[c.ServiceName]; ok == false {
		http.Error(w, "Service does not exists", http.StatusInternalServerError)
		return
	}

	go run(c, false)

	w.WriteHeader(http.StatusCreated)
}

func container_list(w http.ResponseWriter, r *http.Request) {
	if err := json.NewEncoder(w).Encode(containers); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func container_exec(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "Invalid Request!", http.StatusMethodNotAllowed)
		return
	}

	data := struct {
		Name string `json:"name"`
	}{}
	if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	for _, c := range containers {
		if c.Name == data.Name {
			w.Write([]byte(fmt.Sprintf("%d", c.Pid)))
			return
		}
	}
}

func service_create_network(s Service) error {
	create_bridge := strings.Split(fmt.Sprintf("/sbin/ip link add name %s type bridge", s.BridgeName), " ")
	set_bridge_up := strings.Split(fmt.Sprintf("/sbin/ip link set %s up", s.BridgeName), " ")
	set_bridge_ip := strings.Split(fmt.Sprintf("/sbin/ifconfig %s %s", s.BridgeName, s.BridgeIP), " ")

	if err := exec.Command(create_bridge[0], create_bridge[1:]...).Run(); err != nil {
		return err
	}

	if err := exec.Command(set_bridge_up[0], set_bridge_up[1:]...).Run(); err != nil {
		return err
	}

	if err := exec.Command(set_bridge_ip[0], set_bridge_ip[1:]...).Run(); err != nil {
		return err
	}

	services[s.Name] = s
	return nil
}

func run(c Container, isNginx bool) {
	fmt.Println("running parent")
	s := services[c.ServiceName]
	runcmd := "/home/yup/p/containers/brocker-run/brocker-run"

	cmd := &exec.Cmd{
		Path: runcmd,
		Args: append([]string{runcmd}, c.Command),
	}
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: syscall.CLONE_NEWPID |
			syscall.CLONE_NEWNS |
			syscall.CLONE_NEWNET,
	}

	if err := cmd.Start(); err != nil {
		fmt.Println(err)
	}

	c.StartTime = time.Now()
	c.setName()

	c.Pid = cmd.Process.Pid
	c.VEth = fmt.Sprintf("%s%d", vethNameBase, len(containers))
	link := strings.Split(fmt.Sprintf("/sbin/ip link add name %s type veth peer name veth1 netns %d", c.VEth, c.Pid), " ")
	if err := exec.Command(link[0], link[1:]...).Run(); err != nil {
		fmt.Println(err)
		return
	}

	uplink := strings.Split(fmt.Sprintf("/sbin/ifconfig %s up", c.VEth), " ")
	if err := exec.Command(uplink[0], uplink[1:]...).Run(); err != nil {
		fmt.Println(err)
		return
	}

	bridge := strings.Split(fmt.Sprintf("/sbin/ip link set %s master %s", c.VEth, s.BridgeName), " ")
	if err := exec.Command(bridge[0], bridge[1:]...).Run(); err != nil {
		fmt.Println(err)
		return
	}

	bridgeip := net.ParseIP(s.BridgeIP)
	lastOctet := bridgeip[15] + byte(len(s.Containers)+1)
	ip := net.IPv4(bridgeip[12], bridgeip[13], bridgeip[14], lastOctet)
	c.IP = ip.String()

	if err := execInContainter(fmt.Sprintf("/sbin/ifconfig veth1 %s", ip.String()), c.Pid); err != nil {
		fmt.Println(err)
		return
	}

	/*
		Allows the use of CLONE_NEWNS on ubuntu boxes. util-linux <= 2.27 have issues
		with systemd making / shared across all namespaces
	*/
	if err := execInContainter("/bin/mount --make-private -o remount /", c.Pid); err != nil {
		fmt.Println(err)
		return
	}

	if err := os.Mkdir(fmt.Sprintf("%s/%s", CONTAIN_DIR, c.Name), 0644); err != nil {
		fmt.Println(err)
		return
	}

	if err := execInContainter(fmt.Sprintf("/bin/mount --bind %s/%s %s", CONTAIN_DIR, c.Name, MOUNT_LOC), c.Pid); err != nil {
		fmt.Println(err)
		return
	}

	containers[c.Name] = c
	s.Containers[c.Name] = c

	if isNginx {
		s.Pid = c.Pid
	} else {
		s.Servers = append(s.Servers, fmt.Sprintf("%s:8080", c.IP))
		s.writeConfig()
		s.reload()
	}
	services[c.ServiceName] = s

	fmt.Println(cmd.Process.Pid)

	cmd.Wait()

	delete(containers, c.Name)
	delete(services[c.ServiceName].Containers, c.Name)
}

func execInContainter(cmd string, pid int) error {
	command := strings.Split(fmt.Sprintf("nsenter --target %d --pid --net --mount %s", pid, cmd), " ")
	if err := exec.Command(command[0], command[1:]...).Run(); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The ring package implements operations on circular lists.
package ring

// A Ring is an element of a circular list, or ring.
// Rings do not have a beginning or end; a pointer to any ring element
// serves as reference to the entire ring. Empty rings are represented
// as nil Ring pointers. The zero value for a Ring is a one-element
// ring with a nil Value.
//
type Ring struct {
	next, prev *Ring;
	Value interface{};  // for use by client; untouched by this library
}

func (r *Ring) init() *Ring {
	r.next = r;
	r.prev = r;
	return r;
}

// Next returns the next ring element. r must not be empty.
func (r *Ring) Next() *Ring {
	if r.next == nil {
		return r.init();
	}
	return r.next;
}

// Prev returns the previous ring element. r must not be empty.
func (r *Ring) Prev() *Ring {
	if r.next == nil {
		return r.init();
	}
	return r.prev;
}

// Move moves n % r.Len() elements backward (n < 0) or forward (n > 0)
// in the ring and returns that ring element. r must not be empty.
//
func (r *Ring) Move(n int) *Ring {
	if r.next == nil {
		return r.init();
	}
	switch {
	case n < 0:
		for ; n < 0; n++ {
			r = r.prev;
		}
	case n > 0:
		for ; n > 0; n-- {
			r = r.next;
		}
	}
	return r;
}

// New creates a ring of n elements.
func New(n int) *Ring {
	if n <= 0 {
		return nil;
	}
	r := new(Ring);
	p := r;
	for i := 1; i < n; i++ {
		p.next = &Ring{prev: p};
		p = p.next;
	}
	p.next = r;
	r.prev = p;
	return r;
}

// Link connects ring r with with ring s such that r.Next(1)
// becomes s and returns the original value for r.Next(1).
// r must not be empty.
//
// If r and s point to the same ring, linking
// them removes the elements between r and s from the ring.
// The removed elements form a subring and the result is a
// reference to that subring (if no elements were removed,
// the result is still the original value for r.Next(1),
// and not nil).
//
// If r and s point to different rings, linking
// them creates a single ring with the elements of s inserted
// after r. The result points to the element following the
// last element of s after insertion.
//
func (r *Ring) Link(s *Ring) *Ring {
	n := r.Next();
	if s != nil {
		p := s.Prev();
		// Note: Cannot use multiple assignment because
		// evaluation order of LHS is not specified.
		r.next = s;
		s.prev = r;
		n.prev = p;
		p.next = n;
	}
	return n;
}

// Unlink removes n % r.Len() elements from the ring r, starting
// at r.Next(). If n % r.Len() == 0, r remains unchanged.
// The result is the removed subring. r must not be empty.
//
func (r *Ring) Unlink(n int) *Ring {
	if n <= 0 {
		return nil;
	}
	return r.Link(r.Move(n + 1));
}

// Len computes the number of elements in ring r.
// It executes in time proportional to the number of elements.
//
func (r *Ring) Len() int {
	n := 0;
	if r != nil {
		n = 1;
		for p := r.Next(); p != r; p = p.next {
			n++;
		}
	}
	return n;
}

// Forward returns a channel for forward iteration through a ring.
// Iteration is undefined if the ring is changed during iteration.
//
func (r *Ring) Forward() <-chan *Ring {
	c := make(chan *Ring);
	go func() {
		if r != nil {
			c <- r;
			for p := r.Next(); p != r; p = p.next {
				c <- p;
			}
		}
		close(c);
	}();
	return c;
}

// Backward returns a channel for backward iteration through a ring.
// Iteration is undefined if the ring is changed during iteration.
//
func (r *Ring) Backward() <-chan *Ring {
	c := make(chan *Ring);
	go func() {
		if r != nil {
			c <- r;
			for p := r.Prev(); p != r; p = p.prev {
				c <- p;
			}
		}
		close(c);
	}();
	return c;
}
<commit_msg>Fixed typos in comments.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The ring package implements operations on circular lists.
package ring

// A Ring is an element of a circular list, or ring.
// Rings do not have a beginning or end; a pointer to any ring element
// serves as reference to the entire ring. Empty rings are represented
// as nil Ring pointers. The zero value for a Ring is a one-element
// ring with a nil Value.
//
type Ring struct {
	next, prev *Ring;
	Value interface{};  // for use by client; untouched by this library
}

func (r *Ring) init() *Ring {
	r.next = r;
	r.prev = r;
	return r;
}

// Next returns the next ring element. r must not be empty.
func (r *Ring) Next() *Ring {
	if r.next == nil {
		return r.init();
	}
	return r.next;
}

// Prev returns the previous ring element. r must not be empty.
func (r *Ring) Prev() *Ring {
	if r.next == nil {
		return r.init();
	}
	return r.prev;
}

// Move moves n % r.Len() elements backward (n < 0) or forward (n >= 0)
// in the ring and returns that ring element. r must not be empty.
//
func (r *Ring) Move(n int) *Ring {
	if r.next == nil {
		return r.init();
	}
	switch {
	case n < 0:
		for ; n < 0; n++ {
			r = r.prev;
		}
	case n > 0:
		for ; n > 0; n-- {
			r = r.next;
		}
	}
	return r;
}

// New creates a ring of n elements.
func New(n int) *Ring {
	if n <= 0 {
		return nil;
	}
	r := new(Ring);
	p := r;
	for i := 1; i < n; i++ {
		p.next = &Ring{prev: p};
		p = p.next;
	}
	p.next = r;
	r.prev = p;
	return r;
}

// Link connects ring r with with ring s such that r.Next()
// becomes s and returns the original value for r.Next().
// r must not be empty.
//
// If r and s point to the same ring, linking
// them removes the elements between r and s from the ring.
// The removed elements form a subring and the result is a
// reference to that subring (if no elements were removed,
// the result is still the original value for r.Next(),
// and not nil).
//
// If r and s point to different rings, linking
// them creates a single ring with the elements of s inserted
// after r. The result points to the element following the
// last element of s after insertion.
//
func (r *Ring) Link(s *Ring) *Ring {
	n := r.Next();
	if s != nil {
		p := s.Prev();
		// Note: Cannot use multiple assignment because
		// evaluation order of LHS is not specified.
		r.next = s;
		s.prev = r;
		n.prev = p;
		p.next = n;
	}
	return n;
}

// Unlink removes n % r.Len() elements from the ring r, starting
// at r.Next(). If n % r.Len() == 0, r remains unchanged.
// The result is the removed subring. r must not be empty.
//
func (r *Ring) Unlink(n int) *Ring {
	if n <= 0 {
		return nil;
	}
	return r.Link(r.Move(n + 1));
}

// Len computes the number of elements in ring r.
// It executes in time proportional to the number of elements.
//
func (r *Ring) Len() int {
	n := 0;
	if r != nil {
		n = 1;
		for p := r.Next(); p != r; p = p.next {
			n++;
		}
	}
	return n;
}

// Forward returns a channel for forward iteration through a ring.
// Iteration is undefined if the ring is changed during iteration.
//
func (r *Ring) Forward() <-chan *Ring {
	c := make(chan *Ring);
	go func() {
		if r != nil {
			c <- r;
			for p := r.Next(); p != r; p = p.next {
				c <- p;
			}
		}
		close(c);
	}();
	return c;
}

// Backward returns a channel for backward iteration through a ring.
// Iteration is undefined if the ring is changed during iteration.
//
func (r *Ring) Backward() <-chan *Ring {
	c := make(chan *Ring);
	go func() {
		if r != nil {
			c <- r;
			for p := r.Prev(); p != r; p = p.prev {
				c <- p;
			}
		}
		close(c);
	}();
	return c;
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ssh

import (
	"crypto/rand"
	"errors"
	"io"
)

// authenticate authenticates with the remote server. See RFC 4252.
func (c *ClientConn) authenticate(session []byte) error {
	// initiate user auth session
	if err := c.writePacket(marshal(msgServiceRequest, serviceRequestMsg{serviceUserAuth})); err != nil {
		return err
	}
	packet, err := c.readPacket()
	if err != nil {
		return err
	}
	var serviceAccept serviceAcceptMsg
	if err := unmarshal(&serviceAccept, packet, msgServiceAccept); err != nil {
		return err
	}
	// during the authentication phase the client first attempts the "none" method
	// then any untried methods suggested by the server.
	tried, remain := make(map[string]bool), make(map[string]bool)
	for auth := ClientAuth(new(noneAuth)); auth != nil; {
		ok, methods, err := auth.auth(session, c.config.User, c.transport)
		if err != nil {
			return err
		}
		if ok {
			// success
			return nil
		}
		tried[auth.method()] = true
		delete(remain, auth.method())
		for _, meth := range methods {
			if tried[meth] {
				// if we've tried meth already, skip it.
				continue
			}
			remain[meth] = true
		}
		auth = nil
		for _, a := range c.config.Auth {
			if remain[a.method()] {
				auth = a
				break
			}
		}
	}
	return errors.New("ssh: unable to authenticate, no supported methods remain")
}

// A ClientAuth represents an instance of an RFC 4252 authentication method.
type ClientAuth interface {
	// auth authenticates user over transport t.
	// Returns true if authentication is successful.
	// If authentication is not successful, a []string of alternative
	// method names is returned.
	auth(session []byte, user string, t *transport) (bool, []string, error)

	// method returns the RFC 4252 method name.
	method() string
}

// "none" authentication, RFC 4252 section 5.2.
type noneAuth int

func (n *noneAuth) auth(session []byte, user string, t *transport) (bool, []string, error) {
	if err := t.writePacket(marshal(msgUserAuthRequest, userAuthRequestMsg{
		User:    user,
		Service: serviceSSH,
		Method:  "none",
	})); err != nil {
		return false, nil, err
	}

	packet, err := t.readPacket()
	if err != nil {
		return false, nil, err
	}

	switch packet[0] {
	case msgUserAuthSuccess:
		return true, nil, nil
	case msgUserAuthFailure:
		msg := decode(packet).(*userAuthFailureMsg)
		return false, msg.Methods, nil
	}
	return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
}

func (n *noneAuth) method() string {
	return "none"
}

// "password" authentication, RFC 4252 Section 8.
type passwordAuth struct {
	ClientPassword
}

func (p *passwordAuth) auth(session []byte, user string, t *transport) (bool, []string, error) {
	type passwordAuthMsg struct {
		User     string
		Service  string
		Method   string
		Reply    bool
		Password string
	}

	pw, err := p.Password(user)
	if err != nil {
		return false, nil, err
	}

	if err := t.writePacket(marshal(msgUserAuthRequest, passwordAuthMsg{
		User:     user,
		Service:  serviceSSH,
		Method:   "password",
		Reply:    false,
		Password: pw,
	})); err != nil {
		return false, nil, err
	}

	packet, err := t.readPacket()
	if err != nil {
		return false, nil, err
	}

	switch packet[0] {
	case msgUserAuthSuccess:
		return true, nil, nil
	case msgUserAuthFailure:
		msg := decode(packet).(*userAuthFailureMsg)
		return false, msg.Methods, nil
	}
	return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
}

func (p *passwordAuth) method() string {
	return "password"
}

// A ClientPassword implements access to a client's passwords.
type ClientPassword interface {
	// Password returns the password to use for user.
	Password(user string) (password string, err error)
}

// ClientAuthPassword returns a ClientAuth using password authentication.
func ClientAuthPassword(impl ClientPassword) ClientAuth {
	return &passwordAuth{impl}
}

// ClientKeyring implements access to a client key ring.
type ClientKeyring interface {
	// Key returns the i'th rsa.Publickey or dsa.Publickey, or nil if
	// no key exists at i.
	Key(i int) (key interface{}, err error)

	// Sign returns a signature of the given data using the i'th key
	// and the supplied random source.
	Sign(i int, rand io.Reader, data []byte) (sig []byte, err error)
}

// "publickey" authentication, RFC 4252 Section 7.
type publickeyAuth struct {
	ClientKeyring
}

func (p *publickeyAuth) auth(session []byte, user string, t *transport) (bool, []string, error) {
	type publickeyAuthMsg struct {
		User    string
		Service string
		Method  string
		// HasSig indicates to the reciver packet that the auth request is signed and
		// should be used for authentication of the request.
		HasSig   bool
		Algoname string
		Pubkey   string
		// Sig is defined as []byte so marshal will exclude it during the query phase
		Sig []byte `ssh:"rest"`
	}

	// Authentication is performed in two stages. The first stage sends an
	// enquiry to test if each key is acceptable to the remote. The second
	// stage attempts to authenticate with the valid keys obtained in the
	// first stage.

	var index int
	// a map of public keys to their index in the keyring
	validKeys := make(map[int]interface{})
	for {
		key, err := p.Key(index)
		if err != nil {
			return false, nil, err
		}
		if key == nil {
			// no more keys in the keyring
			break
		}
		pubkey := serializePublickey(key)
		algoname := algoName(key)
		msg := publickeyAuthMsg{
			User:     user,
			Service:  serviceSSH,
			Method:   p.method(),
			HasSig:   false,
			Algoname: algoname,
			Pubkey:   string(pubkey),
		}
		if err := t.writePacket(marshal(msgUserAuthRequest, msg)); err != nil {
			return false, nil, err
		}
		packet, err := t.readPacket()
		if err != nil {
			return false, nil, err
		}
		switch packet[0] {
		case msgUserAuthPubKeyOk:
			msg := decode(packet).(*userAuthPubKeyOkMsg)
			if msg.Algo != algoname || msg.PubKey != string(pubkey) {
				continue
			}
			validKeys[index] = key
		case msgUserAuthFailure:
		default:
			return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
		}
		index++
	}

	// methods that may continue if this auth is not successful.
	var methods []string
	for i, key := range validKeys {
		pubkey := serializePublickey(key)
		algoname := algoName(key)
		// TODO(dfc) use random source from the ClientConfig
		sign, err := p.Sign(i, rand.Reader, buildDataSignedForAuth(session, userAuthRequestMsg{
			User:    user,
			Service: serviceSSH,
			Method:  p.method(),
		}, []byte(algoname), pubkey))
		if err != nil {
			return false, nil, err
		}
		// manually wrap the serialized signature in a string
		s := serializeSignature(algoname, sign)
		sig := make([]byte, stringLength(s))
		marshalString(sig, s)
		msg := publickeyAuthMsg{
			User:     user,
			Service:  serviceSSH,
			Method:   p.method(),
			HasSig:   true,
			Algoname: algoname,
			Pubkey:   string(pubkey),
			Sig:      sig,
		}
		p := marshal(msgUserAuthRequest, msg)
		if err := t.writePacket(p); err != nil {
			return false, nil, err
		}
		packet, err := t.readPacket()
		if err != nil {
			return false, nil, err
		}
		switch packet[0] {
		case msgUserAuthSuccess:
			return true, nil, nil
		case msgUserAuthFailure:
			msg := decode(packet).(*userAuthFailureMsg)
			methods = msg.Methods
			continue
		case msgDisconnect:
			return false, nil, io.EOF
		default:
			return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
		}
	}
	return false, methods, nil
}

func (p *publickeyAuth) method() string {
	return "publickey"
}

// ClientAuthPublickey returns a ClientAuth using public key authentication.
func ClientAuthPublickey(impl ClientKeyring) ClientAuth {
	return &publickeyAuth{impl}
}
<commit_msg>exp/ssh: use ClientConfig.rand() for publickey authentication<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ssh

import (
	"errors"
	"io"
)

// authenticate authenticates with the remote server. See RFC 4252.
func (c *ClientConn) authenticate(session []byte) error {
	// initiate user auth session
	if err := c.writePacket(marshal(msgServiceRequest, serviceRequestMsg{serviceUserAuth})); err != nil {
		return err
	}
	packet, err := c.readPacket()
	if err != nil {
		return err
	}
	var serviceAccept serviceAcceptMsg
	if err := unmarshal(&serviceAccept, packet, msgServiceAccept); err != nil {
		return err
	}
	// during the authentication phase the client first attempts the "none" method
	// then any untried methods suggested by the server.
	tried, remain := make(map[string]bool), make(map[string]bool)
	for auth := ClientAuth(new(noneAuth)); auth != nil; {
		ok, methods, err := auth.auth(session, c.config.User, c.transport, c.config.rand())
		if err != nil {
			return err
		}
		if ok {
			// success
			return nil
		}
		tried[auth.method()] = true
		delete(remain, auth.method())
		for _, meth := range methods {
			if tried[meth] {
				// if we've tried meth already, skip it.
				continue
			}
			remain[meth] = true
		}
		auth = nil
		for _, a := range c.config.Auth {
			if remain[a.method()] {
				auth = a
				break
			}
		}
	}
	return errors.New("ssh: unable to authenticate, no supported methods remain")
}

// A ClientAuth represents an instance of an RFC 4252 authentication method.
type ClientAuth interface {
	// auth authenticates user over transport t.
	// Returns true if authentication is successful.
	// If authentication is not successful, a []string of alternative
	// method names is returned.
	auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error)

	// method returns the RFC 4252 method name.
	method() string
}

// "none" authentication, RFC 4252 section 5.2.
type noneAuth int

func (n *noneAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
	if err := t.writePacket(marshal(msgUserAuthRequest, userAuthRequestMsg{
		User:    user,
		Service: serviceSSH,
		Method:  "none",
	})); err != nil {
		return false, nil, err
	}

	packet, err := t.readPacket()
	if err != nil {
		return false, nil, err
	}

	switch packet[0] {
	case msgUserAuthSuccess:
		return true, nil, nil
	case msgUserAuthFailure:
		msg := decode(packet).(*userAuthFailureMsg)
		return false, msg.Methods, nil
	}
	return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
}

func (n *noneAuth) method() string {
	return "none"
}

// "password" authentication, RFC 4252 Section 8.
type passwordAuth struct {
	ClientPassword
}

func (p *passwordAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
	type passwordAuthMsg struct {
		User     string
		Service  string
		Method   string
		Reply    bool
		Password string
	}

	pw, err := p.Password(user)
	if err != nil {
		return false, nil, err
	}

	if err := t.writePacket(marshal(msgUserAuthRequest, passwordAuthMsg{
		User:     user,
		Service:  serviceSSH,
		Method:   "password",
		Reply:    false,
		Password: pw,
	})); err != nil {
		return false, nil, err
	}

	packet, err := t.readPacket()
	if err != nil {
		return false, nil, err
	}

	switch packet[0] {
	case msgUserAuthSuccess:
		return true, nil, nil
	case msgUserAuthFailure:
		msg := decode(packet).(*userAuthFailureMsg)
		return false, msg.Methods, nil
	}
	return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
}

func (p *passwordAuth) method() string {
	return "password"
}

// A ClientPassword implements access to a client's passwords.
type ClientPassword interface {
	// Password returns the password to use for user.
	Password(user string) (password string, err error)
}

// ClientAuthPassword returns a ClientAuth using password authentication.
func ClientAuthPassword(impl ClientPassword) ClientAuth {
	return &passwordAuth{impl}
}

// ClientKeyring implements access to a client key ring.
type ClientKeyring interface {
	// Key returns the i'th rsa.Publickey or dsa.Publickey, or nil if
	// no key exists at i.
	Key(i int) (key interface{}, err error)

	// Sign returns a signature of the given data using the i'th key
	// and the supplied random source.
	Sign(i int, rand io.Reader, data []byte) (sig []byte, err error)
}

// "publickey" authentication, RFC 4252 Section 7.
type publickeyAuth struct {
	ClientKeyring
}

func (p *publickeyAuth) auth(session []byte, user string, t *transport, rand io.Reader) (bool, []string, error) {
	type publickeyAuthMsg struct {
		User    string
		Service string
		Method  string
		// HasSig indicates to the reciver packet that the auth request is signed and
		// should be used for authentication of the request.
		HasSig   bool
		Algoname string
		Pubkey   string
		// Sig is defined as []byte so marshal will exclude it during the query phase
		Sig []byte `ssh:"rest"`
	}

	// Authentication is performed in two stages. The first stage sends an
	// enquiry to test if each key is acceptable to the remote. The second
	// stage attempts to authenticate with the valid keys obtained in the
	// first stage.

	var index int
	// a map of public keys to their index in the keyring
	validKeys := make(map[int]interface{})
	for {
		key, err := p.Key(index)
		if err != nil {
			return false, nil, err
		}
		if key == nil {
			// no more keys in the keyring
			break
		}
		pubkey := serializePublickey(key)
		algoname := algoName(key)
		msg := publickeyAuthMsg{
			User:     user,
			Service:  serviceSSH,
			Method:   p.method(),
			HasSig:   false,
			Algoname: algoname,
			Pubkey:   string(pubkey),
		}
		if err := t.writePacket(marshal(msgUserAuthRequest, msg)); err != nil {
			return false, nil, err
		}
		packet, err := t.readPacket()
		if err != nil {
			return false, nil, err
		}
		switch packet[0] {
		case msgUserAuthPubKeyOk:
			msg := decode(packet).(*userAuthPubKeyOkMsg)
			if msg.Algo != algoname || msg.PubKey != string(pubkey) {
				continue
			}
			validKeys[index] = key
		case msgUserAuthFailure:
		default:
			return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
		}
		index++
	}

	// methods that may continue if this auth is not successful.
	var methods []string
	for i, key := range validKeys {
		pubkey := serializePublickey(key)
		algoname := algoName(key)
		sign, err := p.Sign(i, rand, buildDataSignedForAuth(session, userAuthRequestMsg{
			User:    user,
			Service: serviceSSH,
			Method:  p.method(),
		}, []byte(algoname), pubkey))
		if err != nil {
			return false, nil, err
		}
		// manually wrap the serialized signature in a string
		s := serializeSignature(algoname, sign)
		sig := make([]byte, stringLength(s))
		marshalString(sig, s)
		msg := publickeyAuthMsg{
			User:     user,
			Service:  serviceSSH,
			Method:   p.method(),
			HasSig:   true,
			Algoname: algoname,
			Pubkey:   string(pubkey),
			Sig:      sig,
		}
		p := marshal(msgUserAuthRequest, msg)
		if err := t.writePacket(p); err != nil {
			return false, nil, err
		}
		packet, err := t.readPacket()
		if err != nil {
			return false, nil, err
		}
		switch packet[0] {
		case msgUserAuthSuccess:
			return true, nil, nil
		case msgUserAuthFailure:
			msg := decode(packet).(*userAuthFailureMsg)
			methods = msg.Methods
			continue
		case msgDisconnect:
			return false, nil, io.EOF
		default:
			return false, nil, UnexpectedMessageError{msgUserAuthSuccess, packet[0]}
		}
	}
	return false, methods, nil
}

func (p *publickeyAuth) method() string {
	return "publickey"
}

// ClientAuthPublickey returns a ClientAuth using public key authentication.
func ClientAuthPublickey(impl ClientKeyring) ClientAuth {
	return &publickeyAuth{impl}
}
<|endoftext|>