// Generate an outbound TLS connection so we can hand verify the remote side func (this *LinkMgr) safeDial(net string, host string) (net.Conn, error) { var id int _, err := fmt.Sscanf(host, "id_%d:80", &id) if err != nil { return nil, err } this.cmut.RLock() fi, ok := this.friendsId[id] if !ok { this.cmut.RUnlock() this.Log.Printf("No such friend") return nil, fmt.Errorf("Dial of removed friend: %s", host) } this.cmut.RUnlock() this.Log.Printf("Dialing(%s:%d)", fi.host, fi.port) conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", fi.host, fi.port), this.clientTls) if err != nil { this.cmut.Lock() this.UpdateIsGd(fi) this.cmut.Unlock() return nil, err } err = conn.Handshake() if err != nil { return nil, err } state := conn.ConnectionState() if len(state.PeerCertificates) < 1 { err = fmt.Errorf("Missing peer certificate") return nil, err } ident, err := crypto.PublicFromCert(state.PeerCertificates[0]) if err != nil { return nil, err } if ident.Fingerprint().String() != fi.fingerprint.String() { err = fmt.Errorf("Invalid peer certificate") return nil, err } return conn, nil }
// Handle inbound request, implemented on hideServer to make non-public func (hthis *hideServer) ServeHTTP(response http.ResponseWriter, request *http.Request) { this := hthis.impl state := request.TLS if state == nil { this.respondError(response, http.StatusBadRequest, "Must use TLS") return } if len(state.PeerCertificates) < 1 { this.respondError(response, http.StatusForbidden, "Missing peer certificicate") return } id, err := crypto.PublicFromCert(state.PeerCertificates[0]) if err != nil { this.respondError(response, http.StatusForbidden, "Invalid peer certificicate") return } if request.Header.Get("Content-Type") != "application/binary" { this.respondError(response, http.StatusBadRequest, "Invalid content type") return } var service int _, err = fmt.Sscanf(request.URL.Path, "/h0tb0x/%d", &service) if err != nil { this.respondError(response, http.StatusNotFound, fmt.Sprintf("Unknown URL: '%s'", request.URL.Path)) return } if request.Method != "POST" { this.respondError(response, http.StatusMethodNotAllowed, fmt.Sprintf("Invalid method: '%s'", request.Method)) return } this.cmut.RLock() handler, sok := this.handlers[service] if !sok { this.cmut.RUnlock() this.respondError(response, http.StatusForbidden, fmt.Sprintf("Unknown service: %d", service)) return } fi, ok := this.friendsFp[id.Fingerprint().String()] if !ok { this.cmut.RUnlock() this.respondError(response, http.StatusForbidden, fmt.Sprintf("Unknown friend: %s", id.Fingerprint().String())) return } this.wait.Add(1) response.Header().Set("Content-Type", "application/binary") check := &didWrite{inner: response, wrote: false} err = handler(fi.id, id.Fingerprint(), request.Body, check) this.cmut.RUnlock() this.wait.Done() if err != nil && !check.wrote { this.respondError(response, http.StatusInternalServerError, err.Error()) return } }