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) }
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 }
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 }
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 }
// 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 }
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 }
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 }
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 }
// 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() }
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) } }
// 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 }
// 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 }
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() }
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 }
// 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 }
// 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 }
// 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 } }
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) }
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) } }
// 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 } } } }
// 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 }
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 }
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 } } }
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, ¢ralHeader); 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) } } }
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 }
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 }
// 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 }
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 }
// 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) } }
// 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() }