Example #1
0
func exit() {
	lg.Infoln("alkasir is shutting down")
	atexitMu.Lock() // this lock should be kept, one shutdown should be enough for everyone.
	lg.Flush()
	if err := clientconfig.Write(); err != nil {
		lg.Errorf("could not save config file: %s", err.Error())
	}
	lg.V(9).Infoln("running atexit funcs")
	for _, f := range atexitFuncs {
		funcName := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
		lg.V(10).Infoln("Running at exit func", funcName)
		f()
		lg.V(10).Infoln("Finished at exit func", funcName)
	}
	atexitFuncs = atexitFuncs[:0]
	lg.V(9).Infoln("atexit funcs done")
	lg.V(9).Infoln("stopping connectionmanager")
	service.StopConnectionManager()
	lg.V(9).Infoln("stopping services")
	service.StopAll()
	lg.V(9).Infoln("services stopped")
	lg.V(9).Infoln("waiting for UI shutdown to finish")
	uiRunning.Wait()
	lg.V(9).Infoln("ui shut down")

	lg.Flush()
	lg.Infoln("alkasir shutdown complete")
	lg.Flush()
	time.Sleep(time.Millisecond * 1)
	os.Exit(0)
}
Example #2
0
func upgradeBinaryCheck(diffsBaseURL string) error {
	artifactNameMu.Lock()
	artifact := artifactName
	artifactNameMu.Unlock()

	cl, err := NewRestClient()
	if err != nil {
		return err
	}

	res, found, err := cl.CheckBinaryUpgrade(shared.BinaryUpgradeRequest{
		Artifact:    artifact,
		FromVersion: VERSION,
	})
	if err != nil {
		return err
	}
	if !found {
		lg.Infoln("no update found")
		return nil
	}
	lg.Warningf("found update %+v", res)

	httpclient, err := service.NewTransportHTTPClient(2 * time.Hour)
	if err != nil {
		return err
	}

	opts, err := upgradebin.NewUpdaterOptions(res, shared.UpgradeVerificationPublicKey)
	if err != nil {
		return err
	}

	u, err := url.Parse(diffsBaseURL)
	if err != nil {
		lg.Errorln(err)
		return err
	}
	u.Path = path.Join(u.Path, artifact, VERSION, res.Version)
	URL := u.String()

	lg.Infoln("downloading", URL)
	resp, err := httpclient.Get(URL)
	if err != nil {
		lg.Errorln(err)
		return err
	}

	defer resp.Body.Close()
	err = upgradebin.Apply(resp.Body, opts)
	if err != nil {
		lg.Errorln(err)
		// will be retried the next time the client starts
		return nil
	}

	return nil

}
Example #3
0
func (w *WMGUI) Language(lang string) error {
	w.langMu.Lock()
	defer w.langMu.Unlock()
	T, err := i18n.Tfunc(lang)
	if err != nil {
		return err
	}
	quitMsg := T("quit_alkasir")
	helpMsg := T("action_help")
	copyMsg := T("copy_browser_code_to_clipboard")
	openMsg := T("open_in_browser")
	if !w.langSet {
		w.open = systray.AddMenuItem(openMsg, openMsg)
		w.help = systray.AddMenuItem(helpMsg, helpMsg)
		w.copy = systray.AddMenuItem(copyMsg, copyMsg)
		w.quit = systray.AddMenuItem(quitMsg, quitMsg)
		w.langSet = true

		go func() {
			for {
				select {
				case <-w.quit.ClickedCh:
					lg.Infoln("quit clicked")
					go func() {
						ui.Actions.Quit <- true
					}()
				case <-w.copy.ClickedCh:
					go func() {
						lg.Infoln("copy to clipboard clicked")
						ui.Actions.CopyBrowserCodeToClipboard <- true
					}()
				case <-w.help.ClickedCh:
					go func() {
						lg.Infoln("help clicked")
						ui.Actions.Help <- true
					}()
				case <-w.open.ClickedCh:
					go func() {
						lg.Infoln("open browser clicked")
						ui.Actions.OpenInBrowser <- true
					}()
				}
			}
		}()
		return nil
	}
	w.quit.SetTitle(quitMsg)
	w.quit.SetTooltip(quitMsg)
	w.help.SetTitle(helpMsg)
	w.help.SetTooltip(helpMsg)
	w.copy.SetTitle(copyMsg)
	w.copy.SetTooltip(copyMsg)
	w.open.SetTitle(openMsg)
	w.open.SetTooltip(openMsg)
	return nil
}
Example #4
0
func upgradeBinaryCheck() error {
	if !upgradeEnabled {
		lg.Infoln("binary upgrades are disabled using the command line flag")
		return nil
	}
	artifactNameMu.Lock()
	artifact := artifactName
	artifactNameMu.Unlock()

	cl, err := NewRestClient()
	if err != nil {
		return err
	}
	// TODO: check for current artifact + version (need to add artifact id to cmd's)
	res, found, err := cl.CheckBinaryUpgrade(shared.BinaryUpgradeRequest{
		Artifact:    artifact,
		FromVersion: VERSION,
	})
	if err != nil {
		return err
	}
	if !found {
		lg.Infoln("no update found")
		return nil
	}
	lg.Warningf("found update %+v", res)

	httpclient, err := service.NewTransportHTTPClient()
	if err != nil {
		return err
	}

	opts, err := upgradebin.NewUpdaterOptions(res, shared.UpgradeVerificationPublicKey)
	if err != nil {
		return err
	}

	URL := fmt.Sprintf("https://central.server.domain/u/%s/%s/%s", artifact, VERSION, res.Version)
	lg.Infoln("downloading %s", URL)
	resp, err := httpclient.Get(URL)
	if err != nil {
		lg.Errorln(err)
		return err
	}

	defer resp.Body.Close()
	err = upgradebin.Apply(resp.Body, opts)
	if err != nil {
		lg.Errorln(err)
		// will be retried the next time the client starts
		return nil
	}

	return nil

}
Example #5
0
// UpgradeConfig updates the config, if needed.
func UpgradeConfig() (bool, error) {
	currentConrfigMu.Lock()
	defer currentConrfigMu.Unlock()
	if !currentConfig.configRead {
		return false, errors.New("config not read")
	}
	prevVer := currentConfig.Settings.Version

	switch currentConfig.Settings.Version {
	case 0: // when config file was created from template
		currentConfig.Settings.Version = 1
		fallthrough
	case 1:
		lg.Infoln("updating configuration to v1")
		m := &modifyConnections{
			Connections: currentConfig.Settings.Connections,
			Add: []string{
				"aieyJ0Ijoib2JmczQiLCJzIjoiXCJjZXJ0PUdzVFAxVmNwcjBJeE9aUkNnUHZ0Z1JsZVJWQzFTRmpYWVhxSDVvSEhYVFJ4M25QVnZXN2xHK2RkREhKWmw4YjBOVFZ1VGc7aWF0LW1vZGU9MFwiIiwiYSI6IjEzOS4xNjIuMjIxLjEyMzo0NDMifQ==",
				"aieyJ0Ijoib2JmczQiLCJzIjoiXCJjZXJ0PTMzdXNkSUVDemFyRUpsWFpQM0w0Y2x0bi9vNXdhVUlOcHRUU0JSYk5BQVpVcVlsajhiZm5MWGYyb3BFNHE2c0NlYzY3Ync7aWF0LW1vZGU9MFwiIiwiYSI6IjQ2LjIxLjEwMi4xMDk6NDQzIn0=",
			},
			Remove: []string{
				// NOTE: old hash function used, not a current format ID
				"xFa9T1i6bJMJIvK6kxFA1xvQGfW58BY3OLkrPXbpvAY=",
			},
		}
		currentConfig.Settings.Connections = m.Update()
		currentConfig.Settings.Version = 2
		fallthrough
	case 2:
		m := &modifyConnections{
			Connections: currentConfig.Settings.Connections,
			Protect: []string{
				"z0VZS-Kx9tMfoBEyX6br19GaJgKDe0IK0i6JKyhKp2s",
				"ipJ2oW8xr9TFDvfU92qGvDaPwZttf_GSjGZ4KW7inBI",
			},
			Remove: []string{
				"Ul3D2G1dI3_Z4sLXQ9IUQdIFH4pSDyNjTwf_auy93Os",
			},
		}
		currentConfig.Settings.Connections = m.Update()
		currentConfig.Settings.Version = 3
		fallthrough
	case 3:
		key := browsercode.NewKey()
		currentConfig.Settings.Local.ClientAuthKey = key
		currentConfig.Settings.Local.ClientBindAddr = "127.0.0.1:8899"
		currentConfig.Settings.Version = 4
		fallthrough
	case 4:
		lg.Infoln("Settings version", currentConfig.Settings.Version)
	default:
		lg.Errorln("Future configuration version!", currentConfig.Settings.Version)
	}
	return currentConfig.Settings.Version != prevVer, nil
}
Example #6
0
func Read(bank int) ([]omron.Entry, error) {
	var entries []omron.Entry

	const (
		config      = 0x1
		iface       = 0x0
		setup       = 0x0
		endpointOut = 2
		endpointIn  = 0x81
	)
	epOut, err := usbdevice.OpenEndpoint(config, iface, setup, endpointOut|uint8(usb.ENDPOINT_DIR_OUT))
	// dev, err := usbdevice.Open()
	if err != nil {
		return entries, err
	}

	epIn, err := usbdevice.OpenEndpoint(config, iface, setup, endpointIn|uint8(usb.ENDPOINT_DIR_IN))
	if err != nil {
		return entries, err
	}

	n, err := epOut.Write(cmdInit)
	if err != nil {
		return entries, err
	}
	lg.Infoln("wrote", n, "bytes")
	// dev.Configs()
	var readBytes []byte
	n, err = epIn.Read(readBytes)
	if err != nil {
		return entries, err
	}
	lg.Infoln("read", n, "bytes")

	os.Exit(1)
	addr := (0x02AC)

	for i := 0; i < 70; i++ {
		// if (abort) {}

		cmdData[4] = byte(addr >> 8)
		cmdData[5] = byte(addr & 0xFF)

	}

	os.Exit(1)
	return entries, nil
}
Example #7
0
func (b *BuildQuery) getVersion() (*Artifact, error) {
	lg.Infof("Getting versions of %s", b.ArtifactDisplayName())
	c, err := getNexusClient()
	if err != nil {
		return nil, err
	}

	artifacts, err := c.Artifacts(
		search.InRepository{
			RepositoryID: repoID,
			Criteria: search.ByCoordinates{
				GroupID:    "com.alkasir",
				Version:    b.Version,
				ArtifactID: b.Cmd,
				Classifier: b.Classifier(),
			},
		},
	)
	if err != nil {
		return nil, err
	}
	if len(artifacts) != 1 {
		lg.Infoln(artifacts)
		return nil, errors.New("one match expected")
	}
	return &Artifact{Artifact: artifacts[0]}, nil
}
Example #8
0
func (b *BuildQuery) getMasterSnapshot(repoID string) (*Artifact, error) {
	c, err := getNexusClient()
	if err != nil {
		return nil, err
	}
	artifacts, err := c.Artifacts(
		search.InRepository{
			RepositoryID: repoID,
			Criteria: search.ByCoordinates{
				GroupID:    "com.alkasir",
				Version:    "SNAPSHOT",
				ArtifactID: b.Cmd,
				Classifier: b.Classifier(),
			},
		},
	)
	if err != nil {
		return nil, err
	}
	if len(artifacts) != 1 {

		lg.Infoln(artifacts)
		return nil, fmt.Errorf("found more than one result: %v", artifacts)
	}
	return &Artifact{Artifact: artifacts[0]}, nil
}
Example #9
0
// GenPAC regenerates the proxy auto configration file file
func GenPAC() []byte {
	buf := new(bytes.Buffer)

	direct := getDirectList()
	blocked := getBlockedList()

	data := struct {
		BlockedMethod  string
		DirectDomains  string
		BlockedDomains string
		TopLevel       string
		DefaultMethod  string
	}{
		pac.blockedMethod,
		direct,
		blocked,
		pac.topLevelDomain,
		pac.defaultMethod,
	}

	if err := pac.template.Execute(buf, data); err != nil {
		lg.Infoln("Error generating pac file:", err)
		panic("Error generating pac file")
	}
	return buf.Bytes()
}
Example #10
0
func TestServiceClientFail(t *testing.T) {
	if os.Getenv("ALKASIR_SERVICE") == "transport" {
		failToStart = false
		server.AddChecker(MockTransportCheck)
		if !server.CheckServiceEnv() {
			lg.Infoln("error no support")
		}
		server.RunService()
		return
	}
	service.UpdateConnections(testConnections)
	service.UpdateTransports(testTransports)
	service.Arg = "-test.run=TestServiceClientFail"

	connection := shared.Connection{
		Transport: "socks5",
	}
	connection1Proxy, err := service.NewTransportService(connection)
	if err != nil {
		t.Fatalf("could not start %v", err)
	}

	err = connection1Proxy.Start()
	if err != nil {
		panic(err)
	}

	if err != nil {
		t.Fatalf("process ran with err %v, want exit status 0", err)
	}
}
Example #11
0
// LinkBinaries links any binaries from an extracted archive path to PWD.
func (a *Artifact) LinkBinaries() error {
	bins := a.Binaries()
	for _, file := range bins {
		basename := filepath.Base(file)
		lg.Infoln(file, basename)
		os.Remove(basename)
		os.Symlink(file, basename)
	}
	return nil
}
Example #12
0
// ReadConfig read all app settings from available config files and/or defalts.
func Read() (*Config, error) {
	err := readSettings(currentConfig)
	if err != nil {
		return nil, err
	}
	err = readHostFiles(currentConfig)
	if err != nil {
		lg.Infoln("could not read host lists..")
	}
	currentConfig.configRead = true
	return currentConfig, nil
}
Example #13
0
func (a *Artifact) Run(cmdglob string) error {
	files, err := a.GlobPath(cmdglob)
	if err != nil {
		return err
	}
	if len(files) != 1 {
		lg.Infoln("wrong number of results for glob", files)
		os.Exit(1)
	}
	cmd := exec.Command(files[0], os.Args[2:]...)
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return cmd.Run()
}
Example #14
0
func (s *Services) Method(id string) *Method {
	if strings.TrimSpace(id) == "" {
		lg.Infoln("trying to fetch method by illegal key")
		return nil
	}
	var method *Method
	allMethods := s.AllMethods()
	for _, m := range allMethods {
		if m.ID == id {
			method = &Method{}
			*method = *m
		}
	}
	return method
}
Example #15
0
// InitDBopens a connection to the database.
func OpenDB() error {
	var err error
	sqlDB, err = db.Open(pgConnFlag)
	if err != nil {
		return err
	}

	if err := sqlDB.Ping(); err != nil {
		sqlDB.Close()
		sqlDB = nil
		return err
	}
	lg.Infoln("Successfully connected to the database")
	return nil
}
Example #16
0
// InitDB opens a connection to the database.
func InitDB() error {
	var err error
	sqlDB, err = Open(*pgConnString)
	if err != nil {
		return err
	}

	if err := sqlDB.Ping(); err != nil {
		sqlDB.Close()
		sqlDB = nil
		return err
	}
	sqlDB.SetMaxIdleConns(100)
	lg.Infoln("Successfully connected to the database")
	return nil
}
Example #17
0
// simple loop for commands / subcommands
func commandHandler(args []string) error {
	if len(args) < 1 {
		printHelp()
		os.Exit(1)
	}
	lg.Infoln(args)
	var trail []string
	node := rootCommand
	var findCmd string
	for {
		if len(args) < 1 {
			fmt.Println("")
			fmt.Printf("command '%s' not found in '%s'\n",
				findCmd, strings.Join(trail, " "))
			return errCommandNotFound
		}
		findCmd = args[0]
		trail = append(trail, findCmd)
		c, ok := node.Get(findCmd)
		if !ok {
			fmt.Println("")
			fmt.Printf("command '%s' not found in '%s'\n",
				findCmd, strings.Join(trail, " "))
			return errCommandNotFound
		}
		newArgs := args[1:]
		if c.Func != nil {
			err := c.Func(newArgs)
			if err != nil {
				switch err {
				case errNoValue:
					fmt.Println("")
					fmt.Printf("command '%s' requires additional arguments\n",
						strings.Join(trail, " "))
					return nil
				}
				fmt.Printf("error running cmd %v %v", trail, newArgs)
				return err
			}
			return nil
		}
		node = c
		args = newArgs
	}
}
Example #18
0
func TestServerFail(t *testing.T) {
	if os.Getenv("__TEST_SUBCMD") == "1" {
		server.AddChecker(MockTransportCheck)
		failToStart = true
		if !server.CheckServiceEnv() {
			lg.Infoln("error no support")
		}
		server.RunService()
		return
	}
	cmd := exec.Command(os.Args[0], "-test.run=TestServerFail")
	env := append(os.Environ(), "__TEST_SUBCMD=1")
	cmd.Env = env
	// cmd.Stdout = os.Stdout
	err := cmd.Run()
	if e, ok := err.(*exec.ExitError); ok && !e.Success() {
		return
	}
	t.Fatalf("process ran with err %v, want exit status 1", err)
}
Example #19
0
func TestServerSuccess(t *testing.T) {
	if os.Getenv("__TEST_SUBCMD") == "1" {
		failToStart = false
		server.AddChecker(MockTransportCheck)
		if !server.CheckServiceEnv() {
			lg.Infoln("error no support")
		}
		server.RunService()
		return
	}
	cmd := exec.Command(os.Args[0], "-test.run=TestServerSuccess")
	env := append(os.Environ(), "__TEST_SUBCMD=1")
	env = append(env, "ALKASIR_SERVICE=transport")
	env = append(env, "ALKASIR_TRANSPORT=socks5")
	cmd.Env = env
	// cmd.Stdout = os.Stdout
	err := cmd.Run()
	if err != nil {
		t.Fatalf("process ran with err %v, want exit status 0", err)
	}
}
Example #20
0
// StartBinaryUpgradeChecker checks for binary upgrades when the connection is
// up and on a schedule.
//
// This function runs in it's own goroutine.
func StartBinaryUpgradeChecker(diffsBaseURL string) {
	if !upgradeEnabled {
		lg.Infoln("binary upgrades are disabled using the command line flag")
		return
	}
	if VERSION == "" {
		lg.Warningln("VERSION not set, binary upgrades are disabled")
		return
	}
	_, err := version.NewVersion(VERSION)
	if err != nil {
		lg.Warningf("VERSION '%s' is not a valid semver version, binary upgrades are disabled: %v", VERSION, err)
		return
	}

	connectionEventListener := make(chan service.ConnectionHistory)
	uChecker, _ := NewUpdateChecker("binary")
	service.AddListener(connectionEventListener)
	for {
		select {
		// Update when the transport connection comes up
		case event := <-connectionEventListener:
			if event.IsUp() {
				uChecker.Activate()
				uChecker.UpdateNow()
			}

		// Update by request of the update checker
		case request := <-uChecker.RequestC:
			err := upgradeBinaryCheck(diffsBaseURL)
			if err != nil {
				lg.Errorln(err)
				request.ResponseC <- UpdateError
			} else {
				request.ResponseC <- UpdateSuccess
			}
		}
	}
}
Example #21
0
// Initialize service
func (s *Service) initService() error {
	cmd := s.cmd
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	s.stdout = stdout
	stderr, err := cmd.StderrPipe()
	if err != nil {
		return err
	}
	s.stderr = stderr

	stdin, err := cmd.StdinPipe()
	if err != nil {
		return err
	}
	s.stdin = stdin

	if lg.V(5) {
		alkasirEnv := ""
		for _, v := range s.cmd.Env {
			if strings.HasPrefix(v, "ALKASIR_") {
				alkasirEnv += v + " "
			}
		}
		lg.Infof("Starting service: %s %s", alkasirEnv, cmd.Path)
	}
	err = cmd.Start()
	if err != nil {
		return err
	}

	scanner := bufio.NewScanner(stdout)
	var transportErrMsg string
	transportErr := false
	var line string
	for scanner.Scan() {
		line = scanner.Text()

		lg.V(5).Infoln("DBG: ", line)

		if errorM.MatchString(line) {
			transportErr = true
			transportErrMsg = line
			return errors.New("error: " + transportErrMsg)
		} else if doneM.MatchString(line) {
			break
		} else if exposeM.MatchString(line) {
			match := exposeM.FindStringSubmatch(line)
			s.Response["bindaddr"] = match[3]
			s.Response["protocol"] = match[2]
			s.registerMethod(match[1], match[2], match[3])
		} else if versionM.MatchString(line) {
		} else if parentM.MatchString(line) {
			match := parentM.FindStringSubmatch(line)
			s.Response["parentaddr"] = match[3]
		} else {
			lg.Infoln("not handled line:", line)
			return errors.New("unhandeled line")
		}
	}
	if transportErr {
		err := cmd.Wait()
		if err != nil {
			lg.Warningln(err)
		}
		lg.Fatal(transportErrMsg)
		return errors.New("transport err")
	}
	return err
}
Example #22
0
func GetPublicIPAddr() net.IP {
	publicIP.init.Do(func() {
		lg.Infoln("starting public ip address updater")

		var gotIP sync.Once
		publicIP.hasIP.Add(1)

		go func() {
			timeout := time.Duration(10 * time.Second)
			client := http.Client{
				Timeout:   timeout,
				Transport: v4Transport,
			}
			var services []string = make([]string, 0)
			services = append(services, wanipservices...)
			shuffleStrings(services)
			serviceIdx := 0
			refreshTicker := time.Tick(time.Minute * 10)
		loop:
			for {
				serviceIdx = (serviceIdx + 1) % (len(services))
				if serviceIdx == 0 {
					gotIP.Do(func() { publicIP.hasIP.Done() })
				}
				URL := services[serviceIdx]
				resp, err := client.Get(URL)

				if err != nil {
					lg.Warningf("Could not read response from %s: %v", URL, err)
					<-time.After(time.Second * 2)
					continue loop

				}
				data, err := ioutil.ReadAll(resp.Body)
				if err != nil {
					lg.Warningf("Could not read response from %s: %v", URL, err)
					resp.Body.Close()
					<-time.After(time.Second * 2)
					continue loop
				}
				resp.Body.Close()
				str := strings.TrimSpace(string(data))
				ip := net.ParseIP(str)
				if ip == nil {
					lg.Warningf("error parsing ip from %s from: %.50s", URL, str)
					<-time.After(time.Second * 2)
					continue loop
				}
				publicIP.Lock()
				if publicIP.ip == nil || !publicIP.ip.Equal(ip) {
					lg.V(5).Infof("Public ip address change: %s -> %s via %s", publicIP.ip, ip, URL)
				}
				publicIP.ip = &ip
				publicIP.Unlock()
				gotIP.Do(func() { publicIP.hasIP.Done() })
				select {
				case <-refreshTicker:
					lg.V(30).Infoln("refreshing IP address")
				}
			}
		}()
	})
	publicIP.hasIP.Wait()
	publicIP.Lock()
	ip := publicIP.ip
	publicIP.Unlock()
	if ip != nil {
		return ip.To4()
	}
	return nil
}
Example #23
0
func StartConnectionManager(authKey string) {
	go updateTransportOkLoop()

	listeners := make([]chan ConnectionHistory, 0)

	// TODO: Test on irregular intervals
	reverifyTicker := time.NewTicker(connectionManagerTimings.TestTransportTicker)

	// the key is Connection.UUID
	histories := make(map[string][]ConnectionEvent)
	currents := make(map[string]*ConnectionEvent)

	currentConnectionID := ""
	currentConnectionsMu.Lock()
	currentConnIdx := 0
	if len(currents) < 1 {
		go connect(currentConnections[currentConnIdx], authKey)
		currentConnectionID = currentConnections[currentConnIdx].ID
	}
	currentConnectionsMu.Unlock()

	firstUpNoProblems := true // no need to spam the user with popups

	var reconnectTimer *time.Timer
	var connectionTestRunning bool
loop:

	for {
	s:
		select {
		case <-stopCh:
			lg.Infoln("connection manager shut down")
			break loop

		case <-reconnectCh:
			currentConnectionsMu.Lock()
			if len(currentConnections) < 1 {
				currentConnectionsMu.Unlock()
				lg.Warningln("No connections enabled")
				reconnectTimer = time.AfterFunc(connectionManagerTimings.ReconnectTransportDelay, func() {
					reconnectCh <- true
				})
				break s
			}
			currentConnIdx = (currentConnIdx + 1) % (len(currentConnections))
			c := currentConnections[currentConnIdx]
			lg.V(10).Infof("reconnecting to transport %v", c)
			go connect(currentConnections[currentConnIdx], authKey)
			currentConnectionID = c.ID
			currentConnectionsMu.Unlock()

		case listener := <-addNetworkStateListener:
			listeners = append(listeners, listener)

		case event := <-connectionEvents:
			if _, v := histories[event.Connection.ID]; !v {
				histories[event.Connection.ID] = make([]ConnectionEvent, 0)
			} else if len(histories[event.Connection.ID]) > 20 {
				lg.V(5).Infoln("trimming connection history")
				histories[event.Connection.ID] = histories[event.Connection.ID][:20]
			}
			histories[event.Connection.ID] = append(histories[event.Connection.ID], event)
			currents[event.Connection.ID] = &event
			emitEvent := ConnectionHistory{
				History: histories[event.Connection.ID],
			}

			if lg.V(3) {
				switch event.State {
				case Failed, TestFailed:
					lg.Warningln("event  ", event.Connection.ID, ": ", event.State)
				default:
					lg.Infoln("event  ", event.Connection.ID, ": ", event.State)
				}
			}
			switch event.State {
			case Up:
				if firstUpNoProblems {
					firstUpNoProblems = false
				} else {
					ui.Notify("transport_connected_message")
				}
			case Failed:
				firstUpNoProblems = false
				ui.Notify("transport_error_message")
			case TestFailed:
				firstUpNoProblems = false
				ui.Notify("transport_retry")
			case Ended:
				delete(currents, event.Connection.ID)
				lg.V(15).Infoln("waiting before sending reconnect")
				if reconnectTimer != nil {
					reconnectTimer.Stop()
				}
				reconnectTimer = time.AfterFunc(connectionManagerTimings.ReconnectTransportDelay, func() {
					reconnectCh <- true
				})
			}
			lg.V(7).Infoln("Forwarding connection event to listeners", emitEvent.Current())
			for _, l := range listeners {
				l <- emitEvent
			}

		case <-reverifyTicker.C:
			if !connectionTestRunning {
				conn, ok := currents[currentConnectionID]
				if ok && conn.State == Up {
					connectionTestRunning = true
					go func() {
						err := testConn(conn)
						if err != nil {
							lg.Warningln(err)
							connectionTestedCh <- false
						}
						connectionTestedCh <- true
					}()
				}
			}

		case <-connectionTestedCh:
			connectionTestRunning = false
		}
	}
}
Example #24
0
func samplesAnalyzer() {
loop:
	for samples := range sampleAnalysisC {
		var (
			newTokenSample db.Sample
			clientSamples  = make(map[string]db.Sample, 0)
			centralSamples = make(map[string]db.Sample, 0)
		)

		// organize input data
		for _, s := range samples {
			switch s.Type {
			case "NewClientToken":
				if newTokenSample.Token != "" {
					lg.Error("got more than one newTokenSample, aborting")
					continue loop
				}
				newTokenSample = s
			case "HTTPHeader", "DNSQuery":
				switch s.Origin {
				case "Central":
					centralSamples[s.Type] = s
				case "Client":
					clientSamples[s.Type] = s
				}
			default:
				lg.Errorf("dont know how to handle %d %s, skipping", s.ID, s.Type)
			}
		}

		// validate that wanted data types are available
		if newTokenSample.Token == "" {
			lg.Errorln("No newTokenSample, aborting")
			continue loop
		}
		if !shared.AcceptedHost(newTokenSample.Host) {
			lg.Warningln("not accepted host id:", newTokenSample.ID, newTokenSample.Host)
			continue loop
		}
		for _, smap := range []map[string]db.Sample{clientSamples, centralSamples} {
			for _, stype := range []string{"HTTPHeader"} {
				if _, ok := smap[stype]; !ok {
					lg.Errorf("missing %s, cannot analyse", stype)
					continue loop
				}
			}
		}

		// parse data
		clientSample := clientSamples["HTTPHeader"]
		var clientHeader measure.HTTPHeaderResult
		centralSample := centralSamples["HTTPHeader"]
		var centralHeader measure.HTTPHeaderResult

		if err := json.Unmarshal(clientSample.Data, &clientHeader); err != nil {
			lg.Errorln(err)
			continue loop
		}
		if err := json.Unmarshal(centralSample.Data, &centralHeader); err != nil {
			lg.Error(err)
			continue loop
		}

		// score data
		score := scoreHTTPHeaders(clientHeader, centralHeader)
		lg.V(10).Infof("session:%s %s", newTokenSample.Token, score)

		if score.Score() >= 0.5 {
			lg.Infoln("publishing session", newTokenSample.Token)
			hostPublishC <- newTokenSample
		} else {
			lg.Infoln("not publishing session", newTokenSample.Token)
		}
	}
}
Example #25
0
func createUpgradeAuto(args []string) error {
	var (
		privPemFlag string
		pubPemFlag  string
	)
	fs := flag.NewFlagSet("upgrade create", flag.ExitOnError)
	fs.StringVar(&privPemFlag, "privpem", "upgrades-private-key.pem", "path to load private key file from")
	fs.StringVar(&pubPemFlag, "pubpem", "upgrades-public-key.pem", "path to load public key file from")
	fs.Parse(args)
	args = fs.Args()

	privPem, err := ioutil.ReadFile(privPemFlag)
	if err != nil {
		if os.IsNotExist(err) {
			lg.Errorf("%s does not exist", privPemFlag)
			return nil
		}
		return err
	}

	pubPem, err := ioutil.ReadFile(pubPemFlag)
	if err != nil {
		if os.IsNotExist(err) {
			lg.Errorf("%s does not exist", pubPemFlag)
			return nil
		}
		return err
	}

	results, err := makepatch.RunPatchesCreate(
		jobQs, string(privPem), string(pubPem), nWorkersFlag)
	if err != nil {
		panic(err)
	}
	if len(results) < 1 {
		lg.Fatalln("no patch results returned")
	}

	var allFiles []*tar.Header
	err = filepath.Walk("diffs", func(path string, f os.FileInfo, err error) error {
		if f.IsDir() {
			return nil
		}

		allFiles = append(allFiles, &tar.Header{
			Name: path,
			Mode: 0600,
			Size: f.Size(),
		})
		return nil
	})
	if err != nil {
		lg.Fatal(err)
	}

	latestVersion := results[0].NewVersion
	filename := fmt.Sprintf("alkasir-binpatches-for-%s.tar", latestVersion)
	tarfile, err := os.Create(filename)
	if err != nil {
		panic(err)
	}

	tw := tar.NewWriter(tarfile)

	for _, hdr := range allFiles {
		if err := tw.WriteHeader(hdr); err != nil {
			log.Fatalln(err)
		}
		s, err := os.Open(hdr.Name)
		if err != nil {
			return err
		}
		_, err = io.Copy(tw, s)
		if err != nil {
			lg.Fatal(err)
		}

		err = s.Close()
		if err != nil {
			lg.Fatal(err)
		}

	}

	if err := tw.Close(); err != nil {
		log.Fatalln(err)
	}

	lg.Infoln("done")
	return nil
}
Example #26
0
func CreatePatch(job CreatePatchJob) (CreatePatchResult, error) {
	var emptyResult = CreatePatchResult{}

	logstr := fmt.Sprintf("%s -> %s (%s)", job.OldVersion, job.NewVersion, job.Artifact)

	outfile := filepath.Join(diffsDir,
		job.Artifact,
		job.OldVersion,
		job.NewVersion)

	lg.V(10).Infoln("load new binary into memory", logstr)
	var newData []byte
	{
		var err error
		newData, err = ioutil.ReadFile(job.NewBinary)
		if err != nil {
			return emptyResult, nil
		}
	}

	lg.V(10).Infoln("shasum new", logstr)
	var latestSumBytes []byte
	{
		h := sha256.New()
		h.Write(newData)
		latestSumBytes = h.Sum(nil)
	}

	latestSum := base64.RawURLEncoding.EncodeToString(
		latestSumBytes)

	lg.V(10).Infoln("sign new", logstr)
	var latestSig string
	{
		privateKey, err := upgradebin.DecodePrivateKey([]byte(job.PrivateKey))
		if err != nil {
			return emptyResult, err
		}
		latestSig = base64.RawURLEncoding.EncodeToString(
			ed25519.Sign(privateKey, latestSumBytes)[:])

	}

	var diff []byte
	{
		lg.V(10).Infoln("generate diff", logstr)
		var patch bytes.Buffer
		newFile := bytes.NewReader(newData)
		oldFile, err := os.Open(job.OldBinary)
		if err != nil {
			return emptyResult, nil
		}
		defer oldFile.Close()
		if err := binarydist.Diff(oldFile, newFile, &patch); err != nil {
			return emptyResult, nil
		}
		diff = patch.Bytes()
	}

	{
		lg.V(10).Infoln("write diff", logstr)
		if err := os.MkdirAll(filepath.Dir(outfile), 0775); err != nil {
			return emptyResult, err
		}
		if err := ioutil.WriteFile(outfile, diff, 0775); err != nil {
			return emptyResult, err
		}
	}

	res := CreatePatchResult{
		job:              job,
		Artifact:         job.Artifact,
		NewVersion:       job.NewVersion,
		OldVersion:       job.OldVersion,
		SHA256Sum:        latestSum,
		ED25519Signature: latestSig,
		DiffFile:         outfile,
	}

	data, err := json.MarshalIndent(res, "", "  ")
	if err != nil {
		return emptyResult, err
	}
	err = ioutil.WriteFile(fmt.Sprintf("%s.json", outfile), data, 0775)
	if err != nil {
		return emptyResult, err
	}

	lg.Infoln("done", logstr)
	return res, nil
}
Example #27
0
// initDone means handing off the service process output to it's own goroutine.
func (s *Service) initDone() error {

	lg.V(5).Infof("s.request: %+v", s.Request)
	lg.V(5).Infof("s.response: %+v", s.Response)
	s.waiter.Add(1)
	s.running = true
	go func() {
		defer func() {
			s.running = false
		}()

		go func() {
			scanner := bufio.NewScanner(s.stdout)
			for scanner.Scan() {
				if scanner.Err() != nil {
					lg.Warningln("service stdout", scanner.Err())
					break
				}
				line := scanner.Text()
				lg.Infoln(s.ID, "stdout:", line)
			}
			lg.V(20).Infof("service outch closed %s", s.ID)
		}()

		go func() {
			scanner := bufio.NewScanner(s.stderr)
			for scanner.Scan() {
				if scanner.Err() != nil {
					lg.Warningln("service stderr", scanner.Err())
					break
				}
				line := scanner.Text()
				lg.Infoln(s.ID, "stderr:", line)
			}
			lg.V(20).Infof("service stderr closed %s", s.ID)
		}()

		s.quit = make(chan bool)
		defer close(s.quit)

		select {
		case <-s.quit:
			lg.V(6).Infof("stopping service %s", s.ID)

			if err := s.stdin.Close(); err != nil {
				lg.Errorf("could not close stdin for %s: %s", s.ID, err.Error())
			}

			if err := s.stdout.Close(); err != nil {
				lg.Errorf("could not close stdout for %s: %s", s.ID, err.Error())
			}

			if err := s.stderr.Close(); err != nil {
				lg.Errorf("could not close stderr for %s: %s", s.ID, err.Error())
			}

			lg.V(10).Infof("Killing process service %s", s.ID)

		}

		lg.V(10).Infof("stopped service %s", s.ID)
		if s.removeOnStop {
			ManagedServices.remove(s)
		}
		s.waiter.Done()
	}()
	return nil
}
Example #28
0
func (m *modifyConnections) Update() []shared.Connection {

	lg.Infoln("updating connections..")

	if lg.V(19) {
		lg.Infof("pre upgrade state:")
		for _, v := range m.Connections {
			lg.Infoln(v)

		}
	}

	// create map for id lookups
	conns := make(map[string]shared.Connection, 0)
	for _, connection := range m.Connections {
		conns[connection.ID] = connection
	}

	// remove old old connections
	for _, ID := range m.Remove {
		if _, ok := conns[ID]; ok {
			lg.V(19).Infof("remove connection: %s", ID)
			delete(conns, ID)
		}
	}

	// add new connections
	for _, v := range m.Add {
		conn, err := shared.DecodeConnection(v)
		if err != nil {
			lg.Fatal(err)
		}
		ID := conn.ID
		if _, ok := conns[ID]; !ok {
			lg.V(19).Infof("add connection: %s", ID)
			conns[ID] = conn
		}
	}

	// protect connections
	for _, ID := range m.Protect {
		if _, ok := conns[ID]; ok {
			c := conns[ID]
			c.Protected = true
			conns[ID] = c
			lg.V(19).Infof("protected connection: %s", ID)
		}
	}

	var result []shared.Connection
	for _, v := range conns {
		result = append(result, v)
	}
	if lg.V(19) {
		lg.Infof("upgraded connections result:")
		for _, v := range result {
			lg.Infoln(v)

		}
	}
	return result
}
Example #29
0
// Init does precondition check if the application can/should be started.
// Init will return an error message with reason for exit printed.
func Run() {
	if debugEnabled {
		log.Println("ALKASIR_DEBUG ENABLED!")
		err := os.Setenv("ALKASIR_DEBUG", "1")
		if err != nil {
			log.Fatal(err)
		}
	}
	if hotEnabled {
		log.Println("ALKASIR_HOT ENABLED!")
		err := os.Setenv("ALKASIR_HOT", "1")
		if err != nil {
			log.Fatal(err)
		}
	}

	// the darwin systray does not exit the main loop
	if runtime.GOOS != "darwin" {
		uiRunning.Add(1)
	}

	err := ui.Run(func() {
		Atexit(ui.Done)

		// start the getpublic ip updater.
		go func() {
			_ = shared.GetPublicIPAddr()
		}()

		if debugEnabled {
			go func() {
				err := http.ListenAndServe(
					fmt.Sprintf("localhost:%d", debugPort), nil)
				if err != nil {
					panic(err)
				}
			}()
		}

		// wipe user data
		if wipeData {
			settingsdir := clientconfig.ConfigPath()
			if settingsdir == "" {
				log.Println("[wipe] Configdir not set")
				os.Exit(1)
			}
			settingsfile := clientconfig.ConfigPath("settings.json")
			if _, err := os.Stat(settingsfile); os.IsNotExist(err) {
				log.Println("[wipe] No settings.json in configdir, will NOT wipe data")
				os.Exit(1)
			}
			log.Println("Wiping all user data")
			if err := os.RemoveAll(settingsdir); err != nil {
				log.Println(err)
			}
		}

		// Prepare logging
		logdir := clientconfig.ConfigPath("log")
		err := os.MkdirAll(logdir, 0775)
		if err != nil {
			log.Println("Could not create logging directory")
			os.Exit(1)
		}
		err = flag.Set("log_dir", logdir)
		if err != nil {
			panic(err)
		}
		lg.SetSrcHighlight("alkasir/cmd", "alkasir/pkg")
		lg.CopyStandardLogTo("INFO")

		// Start init
		if VERSION != "" {
			lg.Infoln("Alkasir v" + VERSION)
		} else {
			lg.Warningln("Alkasir dev version (VERSION not set)")
		}

		lg.V(1).Info("Log v-level:", lg.Verbosity())
		_, err = clientconfig.Read()
		if err != nil {
			lg.Infoln("Could not read config")
			exit()
		}
		lg.V(30).Infoln("settings", clientconfig.Get().Settings)

		if saveChromeExt {
			err := saveChromeExtension()
			if err != nil {
				lg.Fatal(err)
			}
		}

		{
			configChanged, err := clientconfig.UpgradeConfig()
			if err != nil {
				lg.Fatalln("Could not upgrade config", err)

			}
			clientconfig.Update(func(conf *clientconfig.Config) error {

				if clientAuthKeyFlag != "" {
					lg.Warningln("Overriding generated authKey with", clientAuthKeyFlag)
					conf.Settings.Local.ClientAuthKey = clientAuthKeyFlag
					configChanged = true
				}

				if bindAddrFlag != "" {
					lg.Warningln("Overriding configured bindAddr with", bindAddrFlag)
					conf.Settings.Local.ClientBindAddr = bindAddrFlag
					configChanged = true
				}

				if centralAddrFlag != "" {
					lg.Warningln("Overriding central server addr with", centralAddrFlag)
					conf.Settings.Local.CentralAddr = centralAddrFlag
					configChanged = true
				}

				return nil
			})

			if configChanged {
				if err := clientconfig.Write(); err != nil {
					lg.Warning(err)
				}
			}

		}
		conf := clientconfig.Get()
		loadTranslations(LanguageOptions...)
		if err := ui.Language(conf.Settings.Local.Language); err != nil {
			lg.Warningln(err)
		}

		go func() {
			select {
			case <-sigIntC:
				exit()
			case <-ui.Actions.Quit:
				exit()
			}
		}()

		for _, e := range []error{
			mime.AddExtensionType(".json", "application/json"),
			mime.AddExtensionType(".js", "application/javascript"),
			mime.AddExtensionType(".css", "text/css"),
			mime.AddExtensionType(".md", "text/plain"),
		} {
			if e != nil {
				lg.Warning(e)
			}
		}

		err = startInternalHTTPServer(conf.Settings.Local.ClientAuthKey)
		if err != nil {
			lg.Fatal("could not start internal http services")
		}

		// Connect the default transport
		service.UpdateConnections(conf.Settings.Connections)
		service.UpdateTransports(conf.Settings.Transports)
		go service.StartConnectionManager(conf.Settings.Local.ClientAuthKey)

		// TODO: async
		pac.UpdateDirectList(conf.DirectHosts.Hosts)
		pac.UpdateBlockedList(conf.BlockedHostsCentral.Hosts, conf.BlockedHosts.Hosts)
		lastBlocklistChange = time.Now()

		go StartBlocklistUpgrader()
		if upgradeDiffsBaseURL != "" {
			lg.V(19).Infoln("upgradeDiffsBaseURL is ", upgradeDiffsBaseURL)
			go StartBinaryUpgradeChecker(upgradeDiffsBaseURL)
		} else {
			lg.Warningln("empty upgradeDiffsBaseURL, disabling upgrade checks")
		}

		lg.V(5).Info("Alkasir has started")

	})
	// the darwin systray does not exit the main loop
	if runtime.GOOS != "darwin" {
		uiRunning.Done()
	}

	lg.Infoln("ui.Run ended")
	if err != nil {
		log.Println("client.Run error:", err)
	}
}
Example #30
0
// Run runs the initialized server.
func Run() {
	var wg sync.WaitGroup

	// start monitor server
	go startMonitoring(*monitorBindAddr)

	// start the getpublic ip updater.
	go func() {
		_ = shared.GetPublicIPAddr()
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		lg.V(2).Infoln("Loading recent sessions from postgres...")
		recents, err := sqlDB.RecentSuggestionSessions(20000)
		if err != nil {
			lg.Fatal(err)
		}
		db.SessionTokens.Reset(recents)
		lg.V(2).Infof("Loaded %d sessions from postgres...", len(recents))
		lg.Flush()

	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		conn := redisPool.Get()
		defer conn.Close()
		lg.V(2).Infoln("BGPDump refresh started...")
		n, err := internet.RefreshBGPDump(conn)
		lg.V(2).Infof("BGPDump refresh ended, %d items added.", n)
		lg.Flush()
		if err != nil {
			if *offline {
				lg.Infoln("offline", err)
			} else {
				lg.Fatal(err)
			}
		}
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		conn := redisPool.Get()
		defer conn.Close()
		lg.V(2).Infoln("CIDRReport refresh started...")
		n, err := internet.RefreshCIDRReport(conn)
		lg.V(2).Infof("CIDRReport refresh ended, %d items added", n)
		if err != nil {
			if *offline {
				lg.Infoln("offline", err)
			} else {
				lg.Fatal(err)
			}
		}
	}()
	wg.Wait()

	// start signal handling
	wg.Add(1)
	go func() {
		ch := make(chan os.Signal)
		signal.Notify(ch, syscall.SIGINT)
		lg.Infoln(<-ch)
		wg.Done()
	}()

	internetClient := db.NewInternetClient(redisPool)
	maxmindClient := db.NewMaxmindClient(mmCountryDB, mmCityDB)

	clients := db.Clients{
		DB:       sqlDB,
		Internet: internetClient,
		Maxmind:  maxmindClient,
	}

	// start http json api server
	go func(addr string, dba db.Clients) {
		mux, err := apiMux(dba)
		lg.Info("Starting http server", addr)
		err = http.ListenAndServe(addr, mux)
		if err != nil {
			lg.Fatal(err)
		}
	}(*apiBindAddr, clients)

	// start http export api server
	go func(addr string, dba db.Clients) {
		if *exportApiSecretKey == "" {
			lg.Warningln("exportApiSecretKey flag/env not set, will not start export api server")
			b := make([]byte, 32)
			_, err := rand.Read(b)
			if err != nil {
				lg.Fatalf("random generator not functioning...")
				return
			}
			suggestedkey := base64.StdEncoding.EncodeToString(b)
			lg.Infoln("suggested export key:", suggestedkey)
			return
		}
		key, err := base64.StdEncoding.DecodeString(*exportApiSecretKey)
		if err != nil {
			lg.Fatalf("could not decode export api secret key: %s", *exportApiSecretKey)
		}

		mux, err := apiMuxExport(dba, key)
		lg.Info("Starting export api server", addr)
		err = http.ListenAndServe(addr, mux)
		if err != nil {
			lg.Fatal(err)
		}
	}(*exportApiBindAddr, clients)

	go analysis.StartAnalysis(clients)
	startMeasurer(clients)

	wg.Wait()
}