commit 58858475e5ba737ca0e7e271b7604fe1ac06bf75
Author: Quinn Jarrell <[email protected]>
Date:   Mon Jun 23 16:15:18 2014 -0400

    Added a loading configuration file on the server side. The format is 
identical to the client configuration file except ClientTransportationPlugin is 
ServerTransportationPlugin. Uses go-shellwords to parse the config files.
---
 fog-server/Makefile      |    2 +-
 fog-server/config.go     |  145 ++++++++++++++++++++++++++++++++++++++++++++++
 fog-server/fog-server.go |   80 ++++---------------------
 fog-server/fogrc         |   13 +++++
 fog-server/torrc         |    2 +-
 5 files changed, 171 insertions(+), 71 deletions(-)

diff --git a/fog-server/Makefile b/fog-server/Makefile
index c7d474b..1a153a6 100644
--- a/fog-server/Makefile
+++ b/fog-server/Makefile
@@ -1,6 +1,6 @@
 GOBUILDFLAGS =
 
-./fog-server: ./fog-server.go ./stack.go
+./fog-server: ./fog-server.go ./stack.go ./config.go
        go build $(GOBUILDFLAGS) -o "$@" $^
 
 test:
diff --git a/fog-server/config.go b/fog-server/config.go
new file mode 100644
index 0000000..615ea47
--- /dev/null
+++ b/fog-server/config.go
@@ -0,0 +1,145 @@
+package main
+
+import (
+       "errors"
+       "fmt"
+       "io/ioutil"
+       "strings"
+)
+
+import "git.torproject.org/pluggable-transports/goptlib.git"
+import "github.com/mattn/go-shellwords"
+
+// Represents a server transport plugin configuration like:
+//     ServerTransportPlugin MethodName exec Command
+type ServerTransportPlugin struct {
+       MethodName string
+       Command    []string
+       Options    pt.Args
+}
+
+type Configuration struct {
+       // Map from method names to command strings.
+       Transports map[string][]string
+       // Map from method names to ServerTransportOptions.
+       Options map[string]pt.Args
+       // Map from tor-friendly names like "obfs3_websocket" to systematic
+       // names like "obfs3|websocket".
+       Aliases map[string]string
+}
+
+func (conf *Configuration) MethodNames() []string {
+       result := make([]string, 0)
+       // We understand all the single transports
+       for k, _ := range conf.Transports {
+               result = append(result, k)
+       }
+       // and aliases.
+       for k, _ := range conf.Aliases {
+               result = append(result, k)
+       }
+       return result
+}
+
+// Parse a (possibly composed) method name into a slice of single method names.
+func (conf *Configuration) ParseMethodName(methodName string) []string {
+       if name, ok := conf.Aliases[methodName]; ok {
+               methodName = name
+       }
+       return strings.Split(methodName, "|")
+}
+
+func (conf *Configuration) PluginList(methodName string) 
([]ServerTransportPlugin, error) {
+       names := conf.ParseMethodName(methodName)
+       stp := make([]ServerTransportPlugin, 0)
+       for _, name := range names {
+               command, ok := conf.Transports[name]
+               if !ok {
+                       return nil, errors.New(fmt.Sprintf("no transport named 
%q", name))
+               }
+               options := conf.Options[name]
+               stp = append(stp, ServerTransportPlugin{name, command, options})
+       }
+       return stp, nil
+}
+
+// Initialize a configuration object
+func getConfiguration() (conf *Configuration) {
+       conf = new(Configuration)
+       conf.Transports = make(map[string][]string)
+       conf.Aliases = make(map[string]string)
+       conf.Options = make(map[string]pt.Args)
+       return conf
+}
+
+// Reads a configuration file and returns the contents
+func ReadConfigFile(fileName string) (*Configuration, error) {
+       var contents []byte
+       contents, err := ioutil.ReadFile(fileName)
+       if err != nil {
+               return nil, errors.New(fmt.Sprintf("Error reading configuration 
file %s contents.", fileName))
+       }
+       return ParseConfiguration(string(contents), getConfiguration())
+}
+
+// Parses a configuration string and fills the config object's fields with the 
requested Aliases and ServerTransportPlugins
+func ParseConfiguration(configString string, config *Configuration) 
(*Configuration, error) {
+       lines := strings.Split(configString, "\n")
+       for lineCounter, line := range lines {
+               if len(line) > 0 && line[0] != '#' { // Check for empty lines 
and comment tags on the first
+                       line = strings.TrimSpace(line)
+                       delimitedTokens, err := shellwords.Parse(line)
+                       if err != nil {
+                               return nil, errors.New(fmt.Sprintf("Line %v: 
\"%v\" was split incorrectly by shellwords. Error: %v", lineCounter, line, err))
+                       }
+                       if len(delimitedTokens) > 1 {
+                               configLineType := delimitedTokens[0] // This 
can be either Alias or ServerTransportPlugin
+                               if configLineType == "ServerTransportPlugin" {
+                                       err = parseTransportLine(config, 
delimitedTokens, lineCounter)
+                                       if err != nil {
+                                               return nil, err
+                                       }
+                               } else if configLineType == "Alias" {
+                                       err = parseAliasLine(config, 
delimitedTokens, lineCounter)
+                                       if err != nil {
+                                               return nil, err
+                                       }
+                               } else {
+                                       log("Configuration file has unknown 
line %s: %s", lineCounter, line)
+                               }
+                       }
+               }
+       }
+       return config, nil
+}
+
+// Parses a ServerTransportPlugin line.
+// Ex: ServerTransportPlugin dummy obfsproxy --client T managed
+func parseTransportLine(config *Configuration, tokens []string, lineCounter 
int) error {
+       transportName := tokens[1]
+       transportCmdLine := tokens[2:]
+       if _, ok := config.Transports[transportName]; ok {
+               return errors.New(fmt.Sprintf("Configuration file has duplicate 
ServerTransportPlugin lines. Duplicate line is at line number %s", lineCounter))
+       }
+       config.Transports[transportName] = transportCmdLine
+       return nil
+}
+
+// Parses an alias line
+// Ex: Alias b64_b64 b64|b64
+func parseAliasLine(config *Configuration, tokens []string, lineCounter int) 
error {
+       var aliasName string
+       var aliasPath []string
+       aliasName = tokens[1]
+       aliasPath = strings.Split(tokens[2], "|")
+       if _, hashed := config.Aliases[aliasName]; hashed {
+               return errors.New(fmt.Sprintf("Configuration file has duplicate 
Alias lines. Duplicate line is at line number %s", lineCounter))
+       }
+       for _, ptName := range aliasPath {
+               if _, hashed := config.Transports[ptName]; !hashed {
+                       log("Transport map is missing pluggable transport %s 
needed for chain %s. Check your configuration file for a ServerTransportPlugin 
line can launch %s", ptName, aliasName, ptName)
+               }
+       }
+       config.Aliases[aliasName] = tokens[2]
+       return nil
+}
\ No newline at end of file
diff --git a/fog-server/fog-server.go b/fog-server/fog-server.go
index cf77a6a..9ee2703 100644
--- a/fog-server/fog-server.go
+++ b/fog-server/fog-server.go
@@ -39,6 +39,7 @@ func usage() {
        fmt.Printf("  -h, --help   show this help.\n")
        fmt.Printf("  --log FILE   log messages to FILE (default stderr).\n")
        fmt.Printf("  --port PORT  listen on PORT (overrides Tor's requested 
port).\n")
+       fmt.Printf("  -f, --file FILE   Loads and runs configuration FILE.\n")
 }
 
 var logMutex sync.Mutex
@@ -174,14 +175,6 @@ func encodeServerTransportOptions(methodName string, opts 
pt.Args) string {
        return strings.Join(parts, ";")
 }
 
-// Represents a server transport plugin configuration like:
-//     ServerTransportPlugin MethodName exec Command
-type ServerTransportPlugin struct {
-       MethodName string
-       Command    []string
-       Options    pt.Args
-}
-
 func startProcesses(connectBackAddr net.Addr, plugins []ServerTransportPlugin) 
(bindAddr *net.TCPAddr, procs ProcList, err error) {
        var stdout io.ReadCloser
 
@@ -393,72 +386,17 @@ func startChain(methodName string, bindaddr *net.TCPAddr, 
plugins []ServerTransp
        return chain, nil
 }
 
-type Configuration struct {
-       // Map from method names to command strings.
-       Transports map[string][]string
-       // Map from method names to ServerTransportOptions.
-       Options map[string]pt.Args
-       // Map from tor-friendly names like "obfs3_websocket" to systematic
-       // names like "obfs3|websocket".
-       Aliases map[string]string
-}
-
-func (conf *Configuration) MethodNames() []string {
-       result := make([]string, 0)
-       // We understand all the single transports
-       for k, _ := range conf.Transports {
-               result = append(result, k)
-       }
-       // and aliases.
-       for k, _ := range conf.Aliases {
-               result = append(result, k)
-       }
-       return result
-}
-
-// Parse a (possibly composed) method name into a slice of single method names.
-func (conf *Configuration) ParseMethodName(methodName string) []string {
-       if name, ok := conf.Aliases[methodName]; ok {
-               methodName = name
-       }
-       return strings.Split(methodName, "|")
-}
-
-func (conf *Configuration) PluginList(methodName string) 
([]ServerTransportPlugin, error) {
-       names := conf.ParseMethodName(methodName)
-       stp := make([]ServerTransportPlugin, 0)
-       for _, name := range names {
-               command, ok := conf.Transports[name]
-               if !ok {
-                       return nil, errors.New(fmt.Sprintf("no transport named 
%q", name))
-               }
-               options := conf.Options[name]
-               stp = append(stp, ServerTransportPlugin{name, command, options})
-       }
-       return stp, nil
-}
-
-// Simulate loading a configuration file.
-func getConfiguration() (conf *Configuration) {
-       conf = new(Configuration)
-       conf.Transports = make(map[string][]string)
-       conf.Aliases = make(map[string]string)
-       conf.Options = make(map[string]pt.Args)
-       conf.Transports["obfs3"] = []string{"obfsproxy", "managed"}
-       conf.Transports["websocket"] = []string{"pt-websocket-server"}
-       // conf.Options["obfs3"] = make(pt.Args)
-       // conf.Options["obfs3"]["secret"] = []string{"foo"}
-       conf.Aliases["obfs3_websocket"] = "obfs3|websocket"
-       return conf
-}
-
 func main() {
        var logFilename string
        var port int
+       var configFilename string
+       var conf *Configuration
 
        flag.Usage = usage
        flag.StringVar(&logFilename, "log", "", "log file to write to")
        flag.IntVar(&port, "port", 0, "port to listen on if unspecified by Tor")
+       flag.StringVar(&configFilename, "file", "fogrc", "The fog file to read 
the configuration from.")
+       flag.StringVar(&configFilename, "f", "fogrc", "The fog file to read the 
configuration from.")
        flag.Parse()
 
        if logFilename != "" {
@@ -469,11 +407,15 @@ func main() {
                }
                logFile = f
        }
+       var err error
 
+       conf, err = ReadConfigFile(configFilename)
+       if err != nil {
+               log("Error in reading configuration file: %s", err)
+               os.Exit(1)
+       }
        log("Starting.")
 
-       var err error
-       conf := getConfiguration()
        ptInfo, err = pt.ServerSetup(conf.MethodNames())
        if err != nil {
                log("Error in ServerSetup: %s", err)
diff --git a/fog-server/fogrc b/fog-server/fogrc
new file mode 100644
index 0000000..870d8b6
--- /dev/null
+++ b/fog-server/fogrc
@@ -0,0 +1,13 @@
+#Based off of ticket #9744
+#Server transports are setup like so:
+#ServerTransportPlugin name commandline
+#For instance to launch obfs3, the server transport line should be this
+#ServerTransportPlugin obfs3 obfsproxy managed
+#
+#For chaining transports together, an alias line is used.
+#Alias chainname firsttransportname|secondtransportname
+#tor expects alias to use underscores instead of pipes. So an alias links the 
tor version of a plugin chain to the actual plugins. See ticket #9580
+
+ServerTransportPlugin obfs3 obfsproxy managed
+ServerTransportPlugin websocket pt-websocket-server
+Alias obfs3_websocket obfs3|websocket
\ No newline at end of file
diff --git a/fog-server/torrc b/fog-server/torrc
index f103ddc..88258fa 100644
--- a/fog-server/torrc
+++ b/fog-server/torrc
@@ -2,4 +2,4 @@ ORPort 9999
 ExtORPort 5555
 BridgeRelay 1
 SocksPort 0
-ServerTransportPlugin obfs3_websocket exec ./bin/fog-server
+ServerTransportPlugin obfs3_websocket exec ./fog-server

_______________________________________________
tor-commits mailing list
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to