func loadTunnel(name string, local bool) *conf.Config { var err error var tun string cl := NewClient(serverAddress(), moleIni.Get("server", "fingerprint")) if local { fd, err := os.Open(name) fatalErr(err) bs, err := ioutil.ReadAll(fd) fatalErr(err) tuni, err := authenticated(cl, func() (interface{}, error) { return cl.Deobfuscate(string(bs)) }) fatalErr(err) tun = tuni.(string) } else { tuni, err := authenticated(cl, func() (interface{}, error) { return cl.Get(name) }) fatalErr(err) tun = tuni.(string) tun, err = cl.Deobfuscate(tun) fatalErr(err) } cfg, err := conf.Load(bytes.NewBufferString(tun)) fatalErr(err) return cfg }
func loadFile(f string) (*conf.Config, error) { fd, err := os.Open(f) if err != nil { panic(err) } return conf.Load(fd) }
func showCommand(args []string) { fs := flag.NewFlagSet("show", flag.ExitOnError) raw := fs.Bool("r", false, "Show raw tunnel file") fs.Usage = usageFor(fs, msgShowUsage) fs.Parse(args) args = fs.Args() if len(args) != 1 { fs.Usage() exit(3) } cl := NewClient(serverAddress(), moleIni.Get("server", "fingerprint")) res, err := authenticated(cl, func() (interface{}, error) { return cl.Get(args[0]) }) fatalErr(err) tun := res.(string) if *raw { // No log function, since it must be possible to pipe to a valid file fmt.Printf(tun) } else { cfg, err := conf.Load(bytes.NewBufferString(tun)) fatalErr(err) if remapIntfs { cfg.Remap() } for _, cmt := range cfg.Comments { infoln("; " + cmt) } for _, cmt := range cfg.General.Comments { infoln("; " + cmt) } for _, host := range cfg.Hosts { infof("Host %q", host.Name) infof(" %s@%s:%d", host.User, host.Addr, host.Port) if host.Pass != "" { infoln(" Password authentication") } if host.Key != "" { infoln(" Key authentication") } } for _, fwd := range cfg.Forwards { infof("Forward %q", fwd.Name) for _, cmt := range fwd.Comments { infoln(" ; " + cmt) } for _, line := range fwd.Lines { infoln(" " + line.String()) } } } }
func storeList(rw http.ResponseWriter, req *http.Request) { defer listCacheLock.Unlock() listCacheLock.Lock() if listCache == nil { files, err := filepath.Glob(storeDir + "/data/*.ini") if err != nil { rw.WriteHeader(500) rw.Write([]byte(err.Error())) return } for _, file := range files { item := listItem{ Name: path.Base(file[:len(file)-4]), } f, err := os.Open(file) if err != nil { log.Printf("Warning: %q: %s", file, err) item.Features = conf.FeatureError item.Description = "- unreadable -" listCache = append(listCache, item) continue } cfg, err := conf.Load(f) f.Close() if err != nil { log.Printf("Warning: %q: %s", file, err) item.Features = conf.FeatureError item.Description = "- parse error -" listCache = append(listCache, item) continue } var hosts []string for _, h := range cfg.Hosts { hosts = append(hosts, h.Name) } item.Features = cfg.FeatureFlags() item.Description = cfg.General.Description item.Hosts = hosts item.Version = float64(cfg.General.Version) / 100 listCache = append(listCache, item) } } rw.Header().Set("Content-Type", "application/json") json.NewEncoder(rw).Encode(listCache) }
func pushCommand(args []string) { fs := flag.NewFlagSet("push", flag.ExitOnError) fs.Usage = usageFor(fs, msgPushUsage) fs.Parse(args) args = fs.Args() if len(args) != 1 { fs.Usage() exit(3) } filename := filepath.Base(args[0]) if ext := filepath.Ext(filename); ext != ".ini" { fatalf(msgFileNotInit, filename) } // Read file, err := os.Open(args[0]) fatalErr(err) bs, err := ioutil.ReadAll(file) fatalErr(err) _ = file.Close() // Verify _, err = conf.Load(bytes.NewBuffer(bs)) fatalErr(err) // Push tunnelname := filename[:len(filename)-4] cl := NewClient(serverAddress(), moleIni.Get("server", "fingerprint")) _, err = authenticated(cl, func() (interface{}, error) { return nil, cl.Put(tunnelname, bytes.NewBuffer(bs)) }) fatalErr(err) okf(msgOkPushed, tunnelname) }
func putFile(rw http.ResponseWriter, req *http.Request) { defer func() { defer listCacheLock.Unlock() listCacheLock.Lock() listCache = nil }() tun := req.URL.Path[7:] if !filenamePattern.MatchString(tun) { rw.WriteHeader(403) rw.Write([]byte("filename not conformant to " + filenamePattern.String())) return } iniFile := path.Join(storeDir, "data", tun) // Read pushed data data, err := ioutil.ReadAll(req.Body) req.Body.Close() if err != nil { rw.WriteHeader(500) rw.Write([]byte(err.Error())) return } // Verify the configuration _, err = conf.Load(bytes.NewBuffer(data)) if err != nil { rw.WriteHeader(500) rw.Write([]byte(err.Error())) return } // Get the raw INI inf := ini.Parse(bytes.NewBuffer(data)) // Obfuscate shouldSaveKeys := false for _, section := range inf.Sections() { for _, option := range inf.Options(section) { for i := range obfuscateKeys { if option == obfuscateKeys[i] { val := inf.Get(section, option) if oval := obfuscate(val); oval != val { inf.Set(section, option, oval) shouldSaveKeys = true } break } } } } if shouldSaveKeys { saveKeys() } // Save outf, err := os.Create(iniFile) if err != nil { rw.WriteHeader(500) rw.Write([]byte(err.Error())) return } inf.Write(outf) outf.Close() if !disableGit { // Commit dir := path.Join(storeDir, "data") user := req.Header.Get("X-Mole-Authenticated") gitCommit(dir, "push "+tun, user) } }