diff --git a/fedictl/fedictl.go b/fedictl/fedictl.go index 3e0465c..31210fb 100644 --- a/fedictl/fedictl.go +++ b/fedictl/fedictl.go @@ -1,13 +1,14 @@ package main import ( - "encoding/binary" + "bytes" "encoding/json" "flag" "fmt" - "io" - "net" + "log" + "net/http" "os" + "time" "gitlab.com/khanzf/fedilogue/shared" ) @@ -25,7 +26,7 @@ func main() { /* Condition verification */ totalflags := 0 var commandMap shared.CommandMap - var responseback shared.ResponseBack + //var responseback shared.ResponseBack if *shutdownPtr { totalflags++ @@ -68,79 +69,96 @@ func main() { fmt.Println(err) return } + payload := bytes.NewReader(commandByte) - c, err := net.Dial("tcp", "127.0.0.1:5555") + req, err := http.NewRequest("POST", "http://127.0.0.1:5555/"+commandMap.Type, payload) if err != nil { - fmt.Println(err) - return - } - sizebytes := make([]byte, 4) - b := len(commandByte) - - // Send the request - binary.LittleEndian.PutUint32(sizebytes, uint32(b)) - _, err = c.Write(sizebytes) - if err != nil { - fmt.Println(err) - return - } - _, err = c.Write(commandByte) - if err != nil { - fmt.Println(err) - return + log.Fatal("Error condition") } - // Read the response - n, err := io.ReadFull(c, sizebytes) - if err != nil || n != 4 { - fmt.Println("err", err, n) - } - jsonsize := int(binary.LittleEndian.Uint32(sizebytes)) - responsebytes := make([]byte, jsonsize) - _, err = io.ReadFull(c, responsebytes) + client := &http.Client{Timeout: 10 * time.Second} + _, err = client.Do(req) + //res, err := client.Do(req) if err != nil { - fmt.Println("Read Error", err) - } - err = json.Unmarshal(responsebytes, &responseback) - if err != nil { - fmt.Println("Unmarshal error", err) + log.Fatal(err) } - switch commandMap.Type { - case "add": - fmt.Println(responseback.Message) - case "status": - fmt.Println("Status\t\tLastRun\t\t\tCaptureType\tEndpoint") - for endpoint, runninginstance := range responseback.RunningInstances { - if runninginstance.Status == 0 { - fmt.Fprintf(os.Stdout, "New\t") - fmt.Fprintf(os.Stdout, "\tNever\t\t\t") - } else if runninginstance.Status == 200 { - fmt.Fprintf(os.Stdout, "Running\t") - fmt.Fprintf(os.Stdout, "\t%s\t", runninginstance.LastRun) - } else if runninginstance.Status == 429 { - fmt.Fprintf(os.Stdout, "TooManyRequests\t") - fmt.Fprintf(os.Stdout, "%s\t", runninginstance.LastRun) - } else if runninginstance.Status == 600 { - fmt.Fprintf(os.Stdout, "ClientIssue") - fmt.Fprintf(os.Stdout, "\t%s\t", runninginstance.LastRun) - } else if runninginstance.Status == 602 { - fmt.Fprintf(os.Stdout, "BadInstance") - fmt.Fprintf(os.Stdout, "\t%s\t", runninginstance.LastRun) - } else if runninginstance.Status == 605 { - fmt.Fprintf(os.Stdout, "UnsupportedNode") - fmt.Fprintf(os.Stdout, "\t%s\t", runninginstance.LastRun) - } else { - fmt.Fprintf(os.Stdout, "%d\t", runninginstance.Status) - fmt.Fprintf(os.Stdout, "\t%s\t", runninginstance.LastRun) - } - if runninginstance.LastRun == "Queued" { - fmt.Fprintf(os.Stdout, "\t\t") - } - fmt.Fprintf(os.Stdout, "\t%s\t", runninginstance.CaptureType) - fmt.Fprintf(os.Stdout, "%s\n", endpoint) + //resp, err := client.Do(req) + + /* + c, err := net.Dial("tcp", "127.0.0.1:5555") + if err != nil { + fmt.Println(err) + return } - case "follow": - fmt.Println("This is a follow test") - } + sizebytes := make([]byte, 4) + b := len(commandByte) + + // Send the request + binary.LittleEndian.PutUint32(sizebytes, uint32(b)) + _, err = c.Write(sizebytes) + if err != nil { + fmt.Println(err) + return + } + _, err = c.Write(commandByte) + if err != nil { + fmt.Println(err) + return + } + + // Read the response + n, err := io.ReadFull(c, sizebytes) + if err != nil || n != 4 { + fmt.Println("err", err, n) + } + jsonsize := int(binary.LittleEndian.Uint32(sizebytes)) + responsebytes := make([]byte, jsonsize) + _, err = io.ReadFull(c, responsebytes) + if err != nil { + fmt.Println("Read Error", err) + } + err = json.Unmarshal(responsebytes, &responseback) + if err != nil { + fmt.Println("Unmarshal error", err) + } + + switch commandMap.Type { + case "add": + fmt.Println(responseback.Message) + case "status": + fmt.Println("Status\t\tLastRun\t\t\tCaptureType\tEndpoint") + for endpoint, runninginstance := range responseback.RunningInstances { + if runninginstance.Status == 0 { + fmt.Fprintf(os.Stdout, "New\t") + fmt.Fprintf(os.Stdout, "\tNever\t\t\t") + } else if runninginstance.Status == 200 { + fmt.Fprintf(os.Stdout, "Running\t") + fmt.Fprintf(os.Stdout, "\t%s\t", runninginstance.LastRun) + } else if runninginstance.Status == 429 { + fmt.Fprintf(os.Stdout, "TooManyRequests\t") + fmt.Fprintf(os.Stdout, "%s\t", runninginstance.LastRun) + } else if runninginstance.Status == 600 { + fmt.Fprintf(os.Stdout, "ClientIssue") + fmt.Fprintf(os.Stdout, "\t%s\t", runninginstance.LastRun) + } else if runninginstance.Status == 602 { + fmt.Fprintf(os.Stdout, "BadInstance") + fmt.Fprintf(os.Stdout, "\t%s\t", runninginstance.LastRun) + } else if runninginstance.Status == 605 { + fmt.Fprintf(os.Stdout, "UnsupportedNode") + fmt.Fprintf(os.Stdout, "\t%s\t", runninginstance.LastRun) + } else { + fmt.Fprintf(os.Stdout, "%d\t", runninginstance.Status) + fmt.Fprintf(os.Stdout, "\t%s\t", runninginstance.LastRun) + } + if runninginstance.LastRun == "Queued" { + fmt.Fprintf(os.Stdout, "\t\t") + } + fmt.Fprintf(os.Stdout, "\t%s\t", runninginstance.CaptureType) + fmt.Fprintf(os.Stdout, "%s\n", endpoint) + } + case "follow": + fmt.Println("This is a follow test") + } + */ } diff --git a/fedilogue/ctl.go b/fedilogue/ctl.go index 09c628c..8590767 100644 --- a/fedilogue/ctl.go +++ b/fedilogue/ctl.go @@ -1,41 +1,42 @@ package main import ( - "encoding/binary" "encoding/json" - "io" - "net" + "fmt" + "io/ioutil" + "log" + "net/http" "gitlab.com/khanzf/fedilogue/shared" ) -func startctl() { - logInfo("Starting ctl listener on 127.0.0.1:5555") - l, err := net.Listen("tcp", "127.0.0.1:5555") +func cmdFollow(w http.ResponseWriter, r *http.Request) { + body, err := ioutil.ReadAll(r.Body) if err != nil { - logFatal.Fatal("Unable to start listener:", err) + fmt.Println(err) + return } - defer l.Close() + defer r.Body.Close() - commandClient := make(chan net.Conn) - - go func(l net.Listener) { - for { - c, err := l.Accept() - if err != nil { - logFatal.Fatal("Error on accept", err) - } - commandClient <- c - } - }(l) - - for { - c := <-commandClient // New client connection - go handleClient(c) + var commandmap shared.CommandMap + err = json.Unmarshal(body, &commandmap) + if err != nil { + logWarn("Unable to unmarshal here, exiting...") + return } + go followInbox(commandmap.Endpoint) + + fmt.Fprintf(w, "{}") +} + +func startctl() { + http.HandleFunc("/follow", cmdFollow) + log.Print("Starting HTTP inbox on port 127.0.0.1:5555") + log.Fatal(http.ListenAndServe("127.0.0.1:5555", nil)) } +/* func handleClient(commandClient net.Conn) { defer commandClient.Close() sizebyte := make([]byte, 4) @@ -124,3 +125,4 @@ func handleClient(commandClient net.Conn) { logFatal.Fatal("Error on write:", err) } } +*/ diff --git a/fedilogue/follow.go b/fedilogue/follow.go new file mode 100644 index 0000000..46bee26 --- /dev/null +++ b/fedilogue/follow.go @@ -0,0 +1,142 @@ +package main + +import ( + "bytes" + "crypto/tls" + "crypto/x509" + + "encoding/pem" + "fmt" + "io/ioutil" + "log" + "net/http" + "strings" + "time" + + "github.com/go-fed/httpsig" +) + +func followInbox(inboxurl string) { + + matchset := re.FindStringSubmatch(inboxurl) + if matchset == nil { + log.Fatal("Unable to regex") + } + inboxhostname := matchset[1] + fmt.Println("The hostname is", inboxhostname) + + keyBytes, err := ioutil.ReadFile("keys/private.pem") + if err != nil { + log.Fatal(err) + } + + pemBlock, _ := pem.Decode(keyBytes) + if pemBlock == nil { + log.Fatal("Invalid PEM format") + } + + privateKey, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes) + if err != nil { + log.Fatal(err) + } + + jsonRequest := fmt.Sprintf(`{"@context":["https://www.w3.org/ns/activitystreams","https://%[2]s/schemas/litepub-0.1.jsonld",{"@language":"und"}],"actor":"https://%[2]s/relay","cc":[],"id":"https://%[2]s/activities/bd0614f5-371d-4bd2-88b3-1ee12f7bf42a","object":"%[1]s","state":"pending","to":["%[1]s"],"type":"Follow"}`, inboxurl, settings.Hostname) + + //var jsonBytes []byte + jsonBytes := []byte(jsonRequest) + payload := bytes.NewReader(jsonBytes) + + prefs := []httpsig.Algorithm{httpsig.RSA_SHA256} + digestAlgorithm := httpsig.DigestSha256 + headers := []string{httpsig.RequestTarget, "date", "host"} + signer, _, err := httpsig.NewSigner(prefs, digestAlgorithm, headers, httpsig.Signature, 0) + if err != nil { + log.Fatal(err.Error()) + } + + req, err := http.NewRequest("POST", inboxurl, payload) + if err != nil { + log.Fatal(err.Error()) + } + if payload != nil { + req.Header.Add("content-type", "application/json") + } + req.Header.Add("date", time.Now().UTC().Format(http.TimeFormat)) + req.Header.Add("host", inboxhostname) + + keyID := "https://" + settings.Hostname + "/relay" + + err = signer.SignRequest(privateKey, keyID, req, jsonBytes) + if err != nil { + log.Fatal(err.Error()) + } + req.Header["Signature"][0] = strings.Replace(req.Header["Signature"][0], "algorithm=\"hs2019\"", "algorithm=\"rsa-sha256\"", 1) + + customTransport := http.DefaultTransport.(*http.Transport).Clone() + customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + client := &http.Client{Timeout: 10 * time.Second, Transport: customTransport} + + // client := &http.Client{Timeout: 10 * time.Second} + res, err := client.Do(req) + if err != nil { + log.Fatal(err) + } + + defer res.Body.Close() + body, err := ioutil.ReadAll(res.Body) + fmt.Printf("Body : %s", body) + + /* + matchset := re.FindStringSubmatch(targetInbox) + if matchset == nil { + return + } + inboxHost := matchset[1] + keyBytes, err := ioutil.ReadFile("keys/private.pem") + if err != nil { + log.Fatal(err) + } + + pemBlock, _ := pem.Decode(keyBytes) + if pemBlock == nil { + log.Fatal("Invalid PEM format") + } + + privateKey, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes) + if err != nil { + log.Fatal(err) + } + + //var jsonBytes []byte + jsonRequest := "{}" + jsonBytes := []byte(jsonRequest) + payload := bytes.NewReader(jsonBytes) + + prefs := []httpsig.Algorithm{httpsig.RSA_SHA256} + digestAlgorithm := httpsig.DigestSha256 + headers := []string{httpsig.RequestTarget, "date", "host"} + signer, _, err := httpsig.NewSigner(prefs, digestAlgorithm, headers, httpsig.Signature, 0) + if err != nil { + log.Fatal(err.Error()) + } + + req, err := http.NewRequest("POST", targetInbox, payload) + if err != nil { + log.Fatal(err.Error()) + } + if payload != nil { + req.Header.Add("content-type", "application/json") + } + req.Header.Add("date", time.Now().UTC().Format(http.TimeFormat)) + req.Header.Add("host", inboxHost) + + keyID := "https://" + settings.Hostname + "/relay#mainkey" + + err = signer.SignRequest(privateKey, keyID, req, jsonBytes) + if err != nil { + log.Fatal(err.Error()) + } + + fmt.Println(req) + */ +} diff --git a/fedilogue/web.go b/fedilogue/web.go index fb65e23..a4bd80b 100644 --- a/fedilogue/web.go +++ b/fedilogue/web.go @@ -192,7 +192,7 @@ func internalFetch(w http.ResponseWriter, r *http.Request) { func relay(w http.ResponseWriter, r *http.Request) { - fmt.Println("Requesting: ", r.Host, " /relay") + fmt.Println("Someone out there requested /relay") publicKeyBytes, err := ioutil.ReadFile("keys/public.pem") publicKeyString := string(publicKeyBytes)