diff --git a/cmd/cookie.go b/cmd/cookie.go new file mode 100644 index 0000000..adedcd7 --- /dev/null +++ b/cmd/cookie.go @@ -0,0 +1,186 @@ +package cmd + +import ( + "bufio" + "fmt" + "net/http" + "net/http/cookiejar" + "net/url" + "os" + "strconv" + "strings" + "time" + + "golang.org/x/net/publicsuffix" +) + +// cookieCMD Pass the data to the HTTP server in the Cookie header. +// -b, --cookie data +func cookiesCmd(cookiesCommandString []string) (map[string]string, error) { + + cookies := make(map[string]string) + for _, cookieSlice := range cookiesCommandString { + cookieSplit := strings.Split(cookieSlice, "=") + cookies[cookieSplit[0]] = cookieSplit[1] + } + + return cookies, nil +} + +// cookieFileCmd Pass the data to the HTTP server in the Cookie header. +// -b, --cookie filename +func cookieFileCmd(cookieFileString string) (*http.Cookie, error) { + + if _, err := os.Stat(cookieFileString); err == nil { + var cookie *http.Cookie + file, err := os.Open(cookieFileString) + if err != nil { + return nil, err + } + defer file.Close() + + lineNum := 1 + scanner := bufio.NewScanner(file) + for scanner.Scan() { + cookieLine := scanner.Text() + cookie, err = parseCookieLine(cookieLine, lineNum) + if cookie == nil { + return nil, err + } + if err != nil { + return nil, err + } + } + + return cookie, nil + + } else { + return nil, err + + } +} + +// cookieJarCMD Specify to which file you want curl to write all cookies after a completed operation. +// -c, --cookie-jar +func cookieJarCmd(r http.Request, cookieJarDirectory string) (string, error) { + cookieJarFile := cookieJarDirectory + "/" + r.URL.Host + ".txt" + + cookieJar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) + + if err != nil { + return "", err + } + + for _, c := range r.Cookies() { + cookieJar.SetCookies(r.URL, []*http.Cookie{c}) + } + + jarFile, err := os.Create(cookieJarFile) + if err != nil { + return "", err + } + + defer jarFile.Close() + + for _, cookies := range cookieJar.Cookies(r.URL) { + cookieLine := cookies.Name + "=" + cookies.Value + "; " + "Path=" + cookies.Path + "; " + "Domain=" + cookies.Domain + "; " + "Expires=" + cookies.Expires.Format("Mon, 02 Jan 2006 15:04:05 MST") + "; " + "Secure=" + strconv.FormatBool(cookies.Secure) + "; " + "HttpOnly=" + strconv.FormatBool(cookies.HttpOnly) + "\n" + jarFile.WriteString(cookieLine) + } + + return "", nil +} + +const httpOnlyPrefix = "#HttpOnly_" + +func parseCookieLine(cookieLine string, lineNum int) (*http.Cookie, error) { + var err error + cookieLineHttpOnly := false + if strings.HasPrefix(cookieLine, httpOnlyPrefix) { + cookieLineHttpOnly = true + cookieLine = strings.TrimPrefix(cookieLine, httpOnlyPrefix) + } + + if strings.HasPrefix(cookieLine, "#") || cookieLine == "" { + return nil, nil + } + + cookieFields := strings.Split(cookieLine, "\t") + + if len(cookieFields) < 6 || len(cookieFields) > 7 { + return nil, fmt.Errorf("incorrect number of fields in line %d. Expected 6 or 7, got %d.", lineNum, len(cookieFields)) + } + + for i, v := range cookieFields { + cookieFields[i] = strings.TrimSpace(v) + } + + cookie := &http.Cookie{ + Domain: cookieFields[0], + Path: cookieFields[2], + Name: cookieFields[5], + HttpOnly: cookieLineHttpOnly, + } + cookie.Secure, err = strconv.ParseBool(cookieFields[3]) + if err != nil { + return nil, err + } + expiresInt, err := strconv.ParseInt(cookieFields[4], 10, 64) + if err != nil { + return nil, err + } + if expiresInt > 0 { + cookie.Expires = time.Unix(expiresInt, 0) + } + + if len(cookieFields) == 7 { + cookie.Value = cookieFields[6] + } + + return cookie, nil +} + +// LoadCookieJarFile takes a path to a curl (netscape) cookie jar file and crates a go http.CookieJar with the contents +func LoadCookieJarFile(path string) (http.CookieJar, error) { + jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) + if err != nil { + return nil, err + } + + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + + lineNum := 1 + scanner := bufio.NewScanner(file) + for scanner.Scan() { + cookieLine := scanner.Text() + cookie, err := parseCookieLine(cookieLine, lineNum) + if cookie == nil { + continue + } + if err != nil { + return nil, err + } + + var cookieScheme string + if cookie.Secure { + cookieScheme = "https" + } else { + cookieScheme = "http" + } + cookieUrl := &url.URL{ + Scheme: cookieScheme, + Host: cookie.Domain, + } + + cookies := jar.Cookies(cookieUrl) + cookies = append(cookies, cookie) + jar.SetCookies(cookieUrl, cookies) + + lineNum++ + } + + return jar, nil +} diff --git a/cmd/root.go b/cmd/root.go index 7942730..603650e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,9 +2,11 @@ package cmd import ( "fmt" + "os" + "strings" + "github.com/academic/gURL/src" "github.com/spf13/cobra" - "os" ) var ( @@ -32,6 +34,11 @@ var ( // proxyNegotiate is the flag variable whether indicates command contains --proxy-negotiate flag. proxyNegotiate = false + // cookie Pass the data to the HTTP server in the Cookie header. + // -b, --cookie + cookieFile = "" + cookies []string + // c is the client. c = src.NewClient() ) @@ -59,6 +66,8 @@ func Execute() { rootCmd.PersistentFlags().BoolVarP(&proxyDigest, "proxy-digest", "", false, "Use Digest authentication on the proxy") rootCmd.PersistentFlags().BoolVarP(&proxyNTLM, "proxy-ntlm", "", false, "Use NTLM authentication on the proxy") rootCmd.PersistentFlags().BoolVarP(&proxyNegotiate, "proxy-negotiate", "", false, "Use HTTP Negotiate (SPNEGO) authentication on the proxy") + rootCmd.Flags().StringSliceVarP(&cookies, "cookie", "b", []string{}, " Pass the data to the HTTP server in the Cookie header.") + if err := rootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) @@ -83,5 +92,17 @@ func checkFlags() error { c.AddHeader("Proxy-Authenticate", fmt.Sprintf("Basic %s", proxyUserCredentials)) } } + if len(cookies) > 0 { + + if strings.Contains(cookies[0], "=") { + cookies, err := cookiesCmd(cookies) + if err != nil { + return err + } + c.AddCookies(cookies) + + } + + } return nil } diff --git a/go.mod b/go.mod index 6b8c028..71e25eb 100644 --- a/go.mod +++ b/go.mod @@ -5,5 +5,6 @@ go 1.15 require ( github.com/json-iterator/go v1.1.11 github.com/spf13/cobra v1.1.3 - github.com/valyala/fasthttp v1.26.0 + github.com/valyala/fasthttp v1.34.0 + golang.org/x/net v0.0.0-20220225172249-27dd8689420f ) diff --git a/go.sum b/go.sum index 866960b..5d5d2e1 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E= -github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -56,7 +56,6 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -104,8 +103,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.12.2 h1:2KCfW3I9M7nSc5wOqXAlW2v2U6v+w6cbjvbfp+OykW8= -github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U= +github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -177,8 +176,8 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.26.0 h1:k5Tooi31zPG/g8yS6o2RffRO2C9B9Kah9SY8j/S7058= -github.com/valyala/fasthttp v1.26.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA= +github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4= +github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -192,7 +191,7 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -225,9 +224,9 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= -golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -251,14 +250,17 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/src/client.go b/src/client.go index ef272cc..9f117a6 100644 --- a/src/client.go +++ b/src/client.go @@ -6,9 +6,6 @@ import ( "errors" "flag" "fmt" - jsoniter "github.com/json-iterator/go" - "github.com/valyala/fasthttp" - "github.com/valyala/fasthttp/fasthttpproxy" "io" "mime/multipart" "net/url" @@ -17,6 +14,10 @@ import ( "strings" "sync" "time" + + jsoniter "github.com/json-iterator/go" + "github.com/valyala/fasthttp" + "github.com/valyala/fasthttp/fasthttpproxy" ) var (