// IsConnectionOverTor will make a connection to the check.torproject page to see if we're using Tor or not func (*defaultTorManager) IsConnectionOverTor(d proxy.Dialer) bool { if d == nil { d = proxy.Direct } c := &http.Client{Transport: &http.Transport{Dial: func(network, addr string) (net.Conn, error) { return d.Dial(network, addr) }}} resp, err := c.Get("https://check.torproject.org/api/ip") if err != nil { log.Printf("Got error when trying to check tor: %v", err) return false } content, err := ioutil.ReadAll(resp.Body) if err != nil { log.Printf("Got error when trying to check tor: %v", err) return false } v := CheckTorResult{} err = json.Unmarshal(content, &v) if err != nil { log.Printf("Got error when trying to check tor: %v", err) return false } return v.IsTor }
func dialTimeout(network, addr string, dialer proxy.Dialer, t time.Duration) (c net.Conn, err error) { result := make(chan bool, 1) go func() { c, err = dialer.Dial(network, addr) result <- true }() select { case <-time.After(t): log.Println("tcp: dial timed out") return nil, ourNet.ErrTimeout case <-result: return } }
// Dial establishes a connection to a Riemann server at addr, on the network // netwrk, with a timeout of timeout // // Known networks are "tcp", "tcp4", "tcp6", "udp", "udp4", and "udp6". func DialWithTimeout(netwrk, addr string, timeout time.Duration) (c *Client, err error) { c = new(Client) var cnet network switch netwrk { case "tcp", "tcp4", "tcp6": cnet = new(tcp) case "udp", "udp4", "udp6": cnet = new(udp) default: return nil, fmt.Errorf("dial %q: unsupported network %q", netwrk, netwrk) } var proxyUrl = os.Getenv("RIEMANN_PROXY") // Get a proxy Dialer that will create the connection on our // behalf via the SOCKS5 proxy. Specify the authentication // and re-create the dialer/transport/client if tor's // IsolateSOCKSAuth is needed. var dialer proxy.Dialer if dialer == nil { dialer = proxy.Direct } if proxyUrl != "" { u, err := url.Parse(proxyUrl) if err != nil { fmt.Errorf("Failed to obtain proxy dialer: %v\n", err) } if dialer, err = proxy.FromURL(u, dialer); err != nil { fmt.Errorf("Failed to parse " + proxyUrl + " as a proxy: " + err.Error()) return nil, err } } c.net = cnet c.timeout = timeout c.connection, err = dialer.Dial(netwrk, addr) if err != nil { return nil, err } return c, nil }
func (c *client) dialServer(server string, useRandomIdentity bool) (*transport.Conn, error) { identity := &c.identity identityPublic := &c.identityPublic if useRandomIdentity { var randomIdentity [32]byte c.randBytes(randomIdentity[:]) var randomIdentityPublic [32]byte curve25519.ScalarBaseMult(&randomIdentityPublic, &randomIdentity) identity = &randomIdentity identityPublic = &randomIdentityPublic } serverIdentity, host, err := parseServer(server, c.dev) if err != nil { return nil, err } var tor proxy.Dialer if c.dev { tor = proxy.Direct } else { tor = c.torDialer() } rawConn, err := tor.Dial("tcp", host) if err != nil { return nil, err } // Sometimes Tor holds the connection open but we never receive // anything so we add a 60 second deadline. rawConn.SetDeadline(time.Now().Add(60 * time.Second)) conn := transport.NewClient(rawConn, identity, identityPublic, serverIdentity) if err := conn.Handshake(); err != nil { return nil, err } return conn, nil }
func serveSocks5Client(conn net.Conn, forward proxy.Dialer) { defer conn.Close() buff := make([]byte, 262) reply := []byte{0x05, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22} if _, err := io.ReadFull(conn, buff[:2]); err != nil { return } if buff[0] != socks5Version { reply[1] = socks5AuthNoAccept conn.Write(reply[:2]) return } numMethod := buff[1] if _, err := io.ReadFull(conn, buff[:numMethod]); err != nil { return } reply[1] = socks5AuthNone if _, err := conn.Write(reply[:2]); err != nil { return } if _, err := io.ReadFull(conn, buff[:4]); err != nil { return } if buff[1] != socks5Connect { reply[1] = socks5CommandNotSupported conn.Write(reply) return } addressType := buff[3] addressLen := 0 switch addressType { case socks5IP4: addressLen = net.IPv4len case socks5IP6: addressLen = net.IPv6len case socks5Domain: if _, err := io.ReadFull(conn, buff[:1]); err != nil { return } addressLen = int(buff[0]) default: reply[1] = socks5AddressTypeNotSupported conn.Write(reply) return } host := make([]byte, addressLen) if _, err := io.ReadFull(conn, host); err != nil { return } if _, err := io.ReadFull(conn, buff[:2]); err != nil { return } hostStr := "" switch addressType { case socks5IP4, socks5IP6: ip := net.IP(host) hostStr = ip.String() case socks5Domain: hostStr = string(host) } port := uint16(buff[0])<<8 | uint16(buff[1]) if port < 1 || port > 0xffff { reply[1] = socks5HostUnreachable conn.Write(reply) return } portStr := strconv.Itoa(int(port)) hostStr = net.JoinHostPort(hostStr, portStr) dest, err := forward.Dial("tcp", hostStr) if err != nil { reply[1] = socks5ConnectionRefused conn.Write(reply) return } defer dest.Close() reply[1] = socks5Success if _, err := conn.Write(reply); err != nil { return } go func() { defer conn.Close() defer dest.Close() io.Copy(conn, dest) }() io.Copy(dest, conn) }
func handleConnection(conn *ss.Conn) { var host string connCnt++ // this maybe not accurate, but should be enough if connCnt-nextLogConnCnt >= 0 { // XXX There's no xadd in the atomic package, so it's difficult to log // the message only once with low cost. Also note nextLogConnCnt maybe // added twice for current peak connection number level. log.Printf("Number of client connections reaches %d\n", nextLogConnCnt) nextLogConnCnt += logCntDelta } // function arguments are always evaluated, so surround debug statement // with if statement if debug { debug.Printf("new client %s->%s\n", conn.RemoteAddr().String(), conn.LocalAddr()) } closed := false defer func() { if debug { debug.Printf("closed pipe %s<->%s\n", conn.RemoteAddr(), host) } connCnt-- if !closed { conn.Close() } }() host, extra, err := getRequest(conn) if err != nil { log.Println("error getting request", conn.RemoteAddr(), conn.LocalAddr(), err) return } debug.Println("connecting", host) var dialer proxy.Dialer dialer = proxy.FromEnvironment() remote, err := dialer.Dial("tcp", host) if err != nil { if ne, ok := err.(*net.OpError); ok && (ne.Err == syscall.EMFILE || ne.Err == syscall.ENFILE) { // log too many open file error // EMFILE is process reaches open file limits, ENFILE is system limit log.Println("dial error:", err) } else { log.Println("error connecting to:", host, err) } return } defer func() { if !closed { remote.Close() } }() // write extra bytes read from if extra != nil { // debug.Println("getRequest read extra data, writing to remote, len", len(extra)) if _, err = remote.Write(extra); err != nil { debug.Println("write request extra error:", err) return } } if debug { debug.Printf("piping %s<->%s", conn.RemoteAddr(), host) } go ss.PipeThenClose(conn, remote) ss.PipeThenClose(remote, conn) closed = true return }
func (c *ricochetConn) clientHandshake(d proxy.Dialer, dialHostname string) { var err error log := c.endpoint.log defer func() { if c.conn != nil { c.conn.Close() } c.endpoint.onConnectionClosed(c) }() // Open the connection to the remote HS. var conn net.Conn conn, err = d.Dial("tcp", dialHostname) if err != nil { log.Printf("client: Failed to connect to '%v' : %v", dialHostname, err) return } c.Lock() if c.shouldClose { conn.Close() c.Unlock() return } c.conn = conn c.Unlock() // Arm the handshake timeout. if err := c.conn.SetDeadline(time.Now().Add(handshakeTimeout)); err != nil { log.Printf("client: Failed to arm handshake timeout: %v", err) return } // Send prefix | nVersions | version. hsPrefix := append(handshakePrefix, 1) // Sending one version... hsPrefix = append(hsPrefix, protocolVersion) // ... this one. if _, err := c.conn.Write(hsPrefix); err != nil { log.Printf("client: Failed to send prefix | nVersions | version: %v", err) return } // Read the negotiated version. var respVer [1]byte if _, err := io.ReadFull(c.conn, respVer[:]); err != nil { log.Printf("client: Failed to read negotiated version: %v", err) return } if respVer[0] != protocolVersion { log.Printf("client: Server speaks no compatible versions, closing") return } // Disarm the handshake timeout. if err := c.conn.SetDeadline(time.Time{}); err != nil { log.Printf("client: Failed to disarm handshake timeout: %v", err) return } // Allocate the control channel and start the auth timeout. c.chanMap[controlChanID] = newControlChan(c, controlChanID) f**k := func() { _ = c.conn.Close() } c.authTimer = time.AfterFunc(authenticationTimeout, f**k) // Send the OpenChannel(AuthHS) request before doing anything else. The // rest of the process is driven by receiving responses from the server, // or 'f**k()'. if err := newClientAuthHSChan(c); err != nil { log.Printf("client: Failed to start authentication: %v", err) return } c.incomingPacketWorker() }
func main() { flag.Parse() oldState, err := terminal.MakeRaw(0) if err != nil { panic(err.Error()) } defer terminal.Restore(0, oldState) term := terminal.NewTerminal(os.Stdin, "") updateTerminalSize(term) term.SetBracketedPasteMode(true) defer term.SetBracketedPasteMode(false) resizeChan := make(chan os.Signal) go func() { for _ = range resizeChan { updateTerminalSize(term) } }() signal.Notify(resizeChan, syscall.SIGWINCH) if len(*configFile) == 0 { homeDir := os.Getenv("HOME") if len(homeDir) == 0 { alert(term, "$HOME not set. Please either export $HOME or use the -config-file option.\n") return } persistentDir := filepath.Join(homeDir, "Persistent") if stat, err := os.Lstat(persistentDir); err == nil && stat.IsDir() { // Looks like Tails. homeDir = persistentDir } *configFile = filepath.Join(homeDir, ".xmpp-client") } config, err := ParseConfig(*configFile) if err != nil { alert(term, "Failed to parse config file: "+err.Error()) config = new(Config) if !enroll(config, term) { return } config.filename = *configFile config.Save() } password := config.Password if len(password) == 0 { if password, err = term.ReadPassword(fmt.Sprintf("Password for %s (will not be saved to disk): ", config.Account)); err != nil { alert(term, "Failed to read password: "******"> ") parts := strings.SplitN(config.Account, "@", 2) if len(parts) != 2 { alert(term, "invalid username (want user@domain): "+config.Account) return } user := parts[0] domain := parts[1] var addr string addrTrusted := false if len(config.Server) > 0 && config.Port > 0 { addr = fmt.Sprintf("%s:%d", config.Server, config.Port) addrTrusted = true } else { if len(config.Proxies) > 0 { alert(term, "Cannot connect via a proxy without Server and Port being set in the config file as an SRV lookup would leak information.") return } host, port, err := xmpp.Resolve(domain) if err != nil { alert(term, "Failed to resolve XMPP server: "+err.Error()) return } addr = fmt.Sprintf("%s:%d", host, port) } var dialer proxy.Dialer for i := len(config.Proxies) - 1; i >= 0; i-- { u, err := url.Parse(config.Proxies[i]) if err != nil { alert(term, "Failed to parse "+config.Proxies[i]+" as a URL: "+err.Error()) return } if dialer == nil { dialer = proxy.Direct } if dialer, err = proxy.FromURL(u, dialer); err != nil { alert(term, "Failed to parse "+config.Proxies[i]+" as a proxy: "+err.Error()) return } } var certSHA256 []byte if len(config.ServerCertificateSHA256) > 0 { certSHA256, err = hex.DecodeString(config.ServerCertificateSHA256) if err != nil { alert(term, "Failed to parse ServerCertificateSHA256 (should be hex string): "+err.Error()) return } if len(certSHA256) != 32 { alert(term, "ServerCertificateSHA256 is not 32 bytes long") return } } var createCallback xmpp.FormCallback if *createAccount { createCallback = func(title, instructions string, fields []interface{}) error { return promptForForm(term, user, password, title, instructions, fields) } } xmppConfig := &xmpp.Config{ Log: &lineLogger{term, nil}, CreateCallback: createCallback, TrustedAddress: addrTrusted, Archive: false, ServerCertificateSHA256: certSHA256, TLSConfig: &tls.Config{ MinVersion: tls.VersionTLS10, CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, }, } if len(config.RawLogFile) > 0 { rawLog, err := os.OpenFile(config.RawLogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) if err != nil { alert(term, "Failed to open raw log file: "+err.Error()) return } lock := new(sync.Mutex) in := rawLogger{ out: rawLog, prefix: []byte("<- "), lock: lock, } out := rawLogger{ out: rawLog, prefix: []byte("-> "), lock: lock, } in.other, out.other = &out, &in xmppConfig.InLog = &in xmppConfig.OutLog = &out defer in.flush() defer out.flush() } if dialer != nil { info(term, "Making connection to "+addr+" via proxy") if xmppConfig.Conn, err = dialer.Dial("tcp", addr); err != nil { alert(term, "Failed to connect via proxy: "+err.Error()) return } } conn, err := xmpp.Dial(addr, user, domain, password, xmppConfig) if err != nil { alert(term, "Failed to connect to XMPP server: "+err.Error()) return } s := Session{ account: config.Account, conn: conn, term: term, conversations: make(map[string]*otr.Conversation), knownStates: make(map[string]string), privateKey: new(otr.PrivateKey), config: config, pendingRosterChan: make(chan *rosterEdit), pendingSubscribes: make(map[string]string), lastActionTime: time.Now(), } info(term, "Fetching roster") //var rosterReply chan xmpp.Stanza rosterReply, _, err := s.conn.RequestRoster() if err != nil { alert(term, "Failed to request roster: "+err.Error()) return } conn.SignalPresence("") s.input = Input{ term: term, uidComplete: new(priorityList), } commandChan := make(chan interface{}) go s.input.ProcessCommands(commandChan) stanzaChan := make(chan xmpp.Stanza) go s.readMessages(stanzaChan) s.privateKey.Parse(config.PrivateKey) s.timeouts = make(map[xmpp.Cookie]time.Time) info(term, fmt.Sprintf("Your fingerprint is %x", s.privateKey.Fingerprint())) ticker := time.NewTicker(1 * time.Second) MainLoop: for { select { case now := <-ticker.C: haveExpired := false for _, expiry := range s.timeouts { if now.After(expiry) { haveExpired = true break } } if !haveExpired { continue } newTimeouts := make(map[xmpp.Cookie]time.Time) for cookie, expiry := range s.timeouts { if now.After(expiry) { s.conn.Cancel(cookie) } else { newTimeouts[cookie] = expiry } } s.timeouts = newTimeouts case edit := <-s.pendingRosterChan: if !edit.isComplete { info(s.term, "Please edit "+edit.fileName+" and run /rostereditdone when complete") s.pendingRosterEdit = edit continue } if s.processEditedRoster(edit) { s.pendingRosterEdit = nil } else { alert(s.term, "Please reedit file and run /rostereditdone again") } case rosterStanza, ok := <-rosterReply: if !ok { alert(s.term, "Failed to read roster: "+err.Error()) return } if s.roster, err = xmpp.ParseRoster(rosterStanza); err != nil { alert(s.term, "Failed to parse roster: "+err.Error()) return } for _, entry := range s.roster { s.input.AddUser(entry.Jid) } info(s.term, "Roster received") case cmd, ok := <-commandChan: if !ok { warn(term, "Exiting because command channel closed") break MainLoop } s.lastActionTime = time.Now() switch cmd := cmd.(type) { case quitCommand: for to, conversation := range s.conversations { msgs := conversation.End() for _, msg := range msgs { s.conn.Send(to, string(msg)) } } break MainLoop case versionCommand: replyChan, cookie, err := s.conn.SendIQ(cmd.User, "get", xmpp.VersionQuery{}) if err != nil { alert(s.term, "Error sending version request: "+err.Error()) continue } s.timeouts[cookie] = time.Now().Add(5 * time.Second) go s.awaitVersionReply(replyChan, cmd.User) case rosterCommand: info(s.term, "Current roster:") maxLen := 0 for _, item := range s.roster { if maxLen < len(item.Jid) { maxLen = len(item.Jid) } } for _, item := range s.roster { state, ok := s.knownStates[item.Jid] line := "" if ok { line += "[*] " } else if cmd.OnlineOnly { continue } else { line += "[ ] " } line += item.Jid numSpaces := 1 + (maxLen - len(item.Jid)) for i := 0; i < numSpaces; i++ { line += " " } line += item.Subscription + "\t" + item.Name if ok { line += "\t" + state } info(s.term, line) } case rosterEditCommand: if s.pendingRosterEdit != nil { warn(s.term, "Aborting previous roster edit") s.pendingRosterEdit = nil } rosterCopy := make([]xmpp.RosterEntry, len(s.roster)) copy(rosterCopy, s.roster) go s.editRoster(rosterCopy) case rosterEditDoneCommand: if s.pendingRosterEdit == nil { warn(s.term, "No roster edit in progress. Use /rosteredit to start one") continue } go s.loadEditedRoster(*s.pendingRosterEdit) case toggleStatusUpdatesCommand: s.config.HideStatusUpdates = !s.config.HideStatusUpdates s.config.Save() // Tell the user the current state of the statuses if s.config.HideStatusUpdates { info(s.term, "Status updates disabled") } else { info(s.term, "Status updates enabled") } case confirmCommand: s.handleConfirmOrDeny(cmd.User, true /* confirm */) case denyCommand: s.handleConfirmOrDeny(cmd.User, false /* deny */) case addCommand: s.conn.SendPresence(cmd.User, "subscribe", "" /* generate id */) case msgCommand: conversation, ok := s.conversations[cmd.to] isEncrypted := ok && conversation.IsEncrypted() if cmd.setPromptIsEncrypted != nil { cmd.setPromptIsEncrypted <- isEncrypted } if !isEncrypted && config.ShouldEncryptTo(cmd.to) { warn(s.term, fmt.Sprintf("Did not send: no encryption established with %s", cmd.to)) continue } var msgs [][]byte message := []byte(cmd.msg) // Automatically tag all outgoing plaintext // messages with a whitespace tag that // indicates that we support OTR. if config.OTRAutoAppendTag && !bytes.Contains(message, []byte("?OTR")) && (!ok || !conversation.IsEncrypted()) { message = append(message, OTRWhitespaceTag...) } if ok { var err error msgs, err = conversation.Send(message) if err != nil { alert(s.term, err.Error()) break } } else { msgs = [][]byte{[]byte(message)} } for _, message := range msgs { s.conn.Send(cmd.to, string(message)) } case otrCommand: s.conn.Send(string(cmd.User), otr.QueryMessage) case otrInfoCommand: info(term, fmt.Sprintf("Your OTR fingerprint is %x", s.privateKey.Fingerprint())) for to, conversation := range s.conversations { if conversation.IsEncrypted() { info(s.term, fmt.Sprintf("Secure session with %s underway:", to)) printConversationInfo(&s, to, conversation) } } case endOTRCommand: to := string(cmd.User) conversation, ok := s.conversations[to] if !ok { alert(s.term, "No secure session established") break } msgs := conversation.End() for _, msg := range msgs { s.conn.Send(to, string(msg)) } s.input.SetPromptForTarget(cmd.User, false) warn(s.term, "OTR conversation ended with "+cmd.User) case authQACommand: to := string(cmd.User) conversation, ok := s.conversations[to] if !ok { alert(s.term, "Can't authenticate without a secure conversation established") break } msgs, err := conversation.Authenticate(cmd.Question, []byte(cmd.Secret)) if err != nil { alert(s.term, "Error while starting authentication with "+to+": "+err.Error()) } for _, msg := range msgs { s.conn.Send(to, string(msg)) } case authOobCommand: fpr, err := hex.DecodeString(cmd.Fingerprint) if err != nil { alert(s.term, fmt.Sprintf("Invalid fingerprint %s - not authenticated", cmd.Fingerprint)) break } existing := s.config.UserIdForFingerprint(fpr) if len(existing) != 0 { alert(s.term, fmt.Sprintf("Fingerprint %s already belongs to %s", cmd.Fingerprint, existing)) break } s.config.KnownFingerprints = append(s.config.KnownFingerprints, KnownFingerprint{fingerprint: fpr, UserId: cmd.User}) s.config.Save() info(s.term, fmt.Sprintf("Saved manually verified fingerprint %s for %s", cmd.Fingerprint, cmd.User)) case awayCommand: s.conn.SignalPresence("away") case chatCommand: s.conn.SignalPresence("chat") case dndCommand: s.conn.SignalPresence("dnd") case xaCommand: s.conn.SignalPresence("xa") case onlineCommand: s.conn.SignalPresence("") } case rawStanza, ok := <-stanzaChan: if !ok { warn(term, "Exiting because channel to server closed") break MainLoop } switch stanza := rawStanza.Value.(type) { case *xmpp.ClientMessage: s.processClientMessage(stanza) case *xmpp.ClientPresence: s.processPresence(stanza) case *xmpp.ClientIQ: if stanza.Type != "get" && stanza.Type != "set" { continue } reply := s.processIQ(stanza) if reply == nil { reply = xmpp.ErrorReply{ Type: "cancel", Error: xmpp.ErrorBadRequest{}, } } if err := s.conn.SendIQReply(stanza.From, "result", stanza.Id, reply); err != nil { alert(term, "Failed to send IQ message: "+err.Error()) } case *xmpp.StreamError: var text string if len(stanza.Text) > 0 { text = stanza.Text } else { text = fmt.Sprintf("%s", stanza.Any) } alert(term, "Exiting in response to fatal error from server: "+text) break MainLoop default: info(term, fmt.Sprintf("%s %s", rawStanza.Name, rawStanza.Value)) } } } os.Stdout.Write([]byte("\n")) }
func proxyNetDial(dialer proxy.Dialer, network, address string) (net.Conn, error) { if dialer != nil { return dialer.Dial(network, address) } return net.Dial(network, address) }