Skip to content

Commit

Permalink
Also check command line option syntax.
Browse files Browse the repository at this point in the history
  • Loading branch information
cyfdecyf committed Mar 6, 2013
1 parent 7d376f9 commit 857443c
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 67 deletions.
7 changes: 2 additions & 5 deletions auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ var auth struct {

allowedClient []netAddr

authed *TimeoutSet // cache authentication based on client i
authed *TimeoutSet // cache authentication based on client ip

template *template.Template
}
Expand Down Expand Up @@ -87,11 +87,8 @@ func parseUserPasswd(val string) {
return
}
auth.required = true
// password format checking is done in checkConfig in config.go
arr := strings.SplitN(val, ":", 2)
if len(arr) != 2 || arr[0] == "" || arr[1] == "" {
fmt.Println("User password syntax wrong, should be in the form of user:passwd")
os.Exit(1)
}
auth.user, auth.passwd = arr[0], arr[1]
}

Expand Down
120 changes: 80 additions & 40 deletions config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"encoding/base64"
"flag"
"fmt"
"github.com/cyfdecyf/bufio"
Expand All @@ -11,7 +12,6 @@ import (
"strconv"
"strings"
"time"
"encoding/base64"
)

const (
Expand All @@ -20,26 +20,27 @@ const (
)

type Config struct {
RcFile string // config file
ListenAddr []string
AddrInPAC []string
SocksParent string
HttpParent string
RcFile string // config file
ListenAddr []string
AddrInPAC []string
SocksParent string
HttpParent string
hasHttpParent bool
HttpUserPasswd string
HttpAuthHeader []byte
Core int
SshServer string
DetectSSLErr bool
LogFile string
AlwaysProxy bool
ShadowSocks string
ShadowPasswd string
ShadowMethod string // shadowsocks encryption method
UserPasswd string
AllowedClient string
AuthTimeout time.Duration
DialTimeout time.Duration
ReadTimeout time.Duration
httpAuthHeader []byte // basic authentication header constructed from HttpUserPasswd
Core int
SshServer string
DetectSSLErr bool
LogFile string
AlwaysProxy bool
ShadowSocks string
ShadowPasswd string
ShadowMethod string // shadowsocks encryption method
UserPasswd string
AllowedClient string
AuthTimeout time.Duration
DialTimeout time.Duration
ReadTimeout time.Duration

// not configurable in config file
PrintVer bool
Expand Down Expand Up @@ -187,8 +188,8 @@ func (p configParser) ParseAddrInPAC(val string) {
}

func isServerAddrValid(val string) bool {
if val == "" {
return false
if val == "" { // default value is empty
return true
}
_, port := splitHostPort(val)
if port == "" {
Expand All @@ -197,43 +198,45 @@ func isServerAddrValid(val string) bool {
return true
}

var hasHttpParentProxy bool
func isUserPasswdValid(val string) bool {
if val == "" {
return true
}
arr := strings.SplitN(val, ":", 2)
if len(arr) != 2 || arr[0] == "" || arr[1] == "" {
return false
}
return true
}

func (p configParser) ParseSocks(val string) {
fmt.Println("socks option is going to be renamed to socksParent in the future, please change it")
p.ParseSocksParent(val)
}

// error checking is done in check config

func (p configParser) ParseSocksParent(val string) {
if !isServerAddrValid(val) {
fmt.Println("parent socks server must have port specified")
os.Exit(1)
if val == "" {
return
}
config.SocksParent = val
parentProxyCreator = append(parentProxyCreator, createctSocksConnection)
}

func (p configParser) ParseHttpParent(val string) {
if !isServerAddrValid(val) {
fmt.Println("parent http server must have port specified")
os.Exit(1)
if val == "" {
return
}
config.HttpParent = val
hasHttpParentProxy = true
parentProxyCreator = append(parentProxyCreator, createHttpProxyConnection)
}

func (p configParser) ParseHttpUserPasswd(val string) {
if val == "" {
return
}
arr := strings.SplitN(val, ":", 2)
if len(arr) != 2 || arr[0] == "" || arr[1] == "" {
fmt.Println("Parent HTTP User password syntax wrong, should be in the form of user:passwd")
os.Exit(1)
}
userPwd64 := base64.StdEncoding.EncodeToString([]byte(val))
config.HttpAuthHeader = []byte(headerProxyAuthorization + ": Basic " + userPwd64 + CRLF)
config.HttpUserPasswd = val
}

func (p configParser) ParseCore(val string) {
Expand Down Expand Up @@ -272,9 +275,8 @@ func (p configParser) ParseAlwaysProxy(val string) {
}

func (p configParser) ParseShadowSocks(val string) {
if !isServerAddrValid(val) {
fmt.Println("shadowsocks server must have port specified")
os.Exit(1)
if val == "" {
return
}
config.ShadowSocks = val
parentProxyCreator = append(parentProxyCreator, createShadowSocksConnection)
Expand Down Expand Up @@ -399,8 +401,46 @@ func updateConfig(nc *Config) {
os.Exit(1)
}
} else {
// empty string in addrInPac means same as listenAddr
config.AddrInPAC = make([]string, len(config.ListenAddr))
}
if config.HttpParent != "" {
config.hasHttpParent = true
}
if config.HttpUserPasswd != "" {
userPwd64 := base64.StdEncoding.EncodeToString([]byte(config.HttpUserPasswd))
config.httpAuthHeader = []byte(headerProxyAuthorization + ": Basic " + userPwd64 + CRLF)
}
}

// Command line options also need to be checked, so put all checking here and
// call it after updateConfig.
func checkConfig() {
if !isServerAddrValid(config.HttpParent) {
fmt.Println("parent http server must have port specified")
os.Exit(1)
}
if !isServerAddrValid(config.SocksParent) {
fmt.Println("parent socks server must have port specified")
os.Exit(1)
}
if !isServerAddrValid(config.ShadowSocks) {
fmt.Println("shadowsocks server must have port specified")
os.Exit(1)
}
if !isUserPasswdValid(config.UserPasswd) {
fmt.Println("user password syntax wrong, should be in the form of user:passwd")
os.Exit(1)
}
if !isUserPasswdValid(config.HttpUserPasswd) {
fmt.Println("http parent user password syntax wrong, should be in the form of user:passwd")
os.Exit(1)
}
if (config.ShadowSocks != "" && config.ShadowPasswd == "") ||
(config.ShadowSocks == "" && config.ShadowPasswd != "") {
fmt.Println("should give both shadowSocks and shadowPasswd options")
os.Exit(1)
}
}

func mkConfigDir() (err error) {
Expand Down
2 changes: 1 addition & 1 deletion doc/sample-config/rc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ logFile =

# 可使用 goagent 等 HTTP 代理作为二级代理翻墙
#httpParent = 127.0.0.1:8087
# 支持二级HTTP代理的Basic认证
# 支持二级 HTTP 代理的 Basic 认证
#httpUserPasswd = username:password

#############################
Expand Down
4 changes: 2 additions & 2 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ func parseRequest(c *clientConn, r *Request) (err error) {

r.reset()
// for http parent proxy, store the original request line
if hasHttpParentProxy {
if config.hasHttpParent {
r.raw.Write(s)
r.reqLnStart = len(s)
}
Expand All @@ -451,7 +451,7 @@ func parseRequest(c *clientConn, r *Request) (err error) {
}
if r.Method == "CONNECT" {
r.isConnect = true
if bool(dbgRq) && verbose && !hasHttpParentProxy {
if bool(dbgRq) && verbose && !config.hasHttpParent {
r.raw.Write(s)
}
} else {
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func main() {

parseConfig(cmdLineConfig.RcFile)
updateConfig(cmdLineConfig)
checkConfig()

initLog()
initAuth()
Expand Down
13 changes: 9 additions & 4 deletions proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -1014,14 +1014,19 @@ func (sv *serverConn) doConnect(r *Request, c *clientConn) (err error) {

func (sv *serverConn) sendHTTPProxyRequest(r *Request, c *clientConn) (err error) {
if _, err = sv.Write(r.proxyRequestLine()); err != nil {
return c.handleServerWriteError(r, sv, err, "sending proxy request line to server")
return c.handleServerWriteError(r, sv, err,
"sending proxy request line to http parent")
}
// Add authorization header for parent http proxy
if config.HttpAuthHeader != nil {
sv.Write(config.HttpAuthHeader)
if config.httpAuthHeader != nil {
if _, err = sv.Write(config.httpAuthHeader); err != nil {
return c.handleServerWriteError(r, sv, err,
"sending proxy authorization header to http parent")
}
}
if _, err = sv.Write(r.rawHeaderBody()); err != nil {
return c.handleServerWriteError(r, sv, err, "sending proxy request header to server")
return c.handleServerWriteError(r, sv, err,
"sending proxy request header to http parent")
}
/*
if bool(dbgRq) && verbose {
Expand Down
24 changes: 10 additions & 14 deletions shadowsocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,20 @@ var noShadowSocksErr = errors.New("No shadowsocks configuration")
var cipher ss.Cipher

func initShadowSocks() {
if config.ShadowSocks != "" && config.ShadowPasswd != "" {
var err error
if err = ss.SetDefaultCipher(config.ShadowMethod); err != nil {
fmt.Println("Initializing shadowsocks:", err)
os.Exit(1)
}
if cipher, err = ss.NewCipher(config.ShadowPasswd); err != nil {
fmt.Println("Creating shadowsocks cipher:", err)
os.Exit(1)
}
debug.Println("shadowsocks server:", config.ShadowSocks)
// error checking is done in checkConfig
if config.ShadowSocks == "" {
return
}
if (config.ShadowSocks != "" && config.ShadowPasswd == "") ||
(config.ShadowSocks == "" && config.ShadowPasswd != "") {
fmt.Println("Missing option: shadowSocks and shadowPasswd should be both given")
var err error
if err = ss.SetDefaultCipher(config.ShadowMethod); err != nil {
fmt.Println("Initializing shadowsocks:", err)
os.Exit(1)
}
if cipher, err = ss.NewCipher(config.ShadowPasswd); err != nil {
fmt.Println("Creating shadowsocks cipher:", err)
os.Exit(1)
}
debug.Println("shadowsocks server:", config.ShadowSocks)
}

func createShadowSocksConnection(url *URL) (cn conn, err error) {
Expand Down
2 changes: 1 addition & 1 deletion socks.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ var socksMsgVerMethodSelection = []byte{
}

func initSocksServer() {
if len(config.SocksParent) != 0 {
if config.SocksParent != "" {
debug.Println("has socks server:", config.SocksParent)
}
}
Expand Down

0 comments on commit 857443c

Please sign in to comment.