func newServerContactReqChan(conn *ricochetConn, msg *packet.OpenChannel) (*contactReqChan, error) { ch := new(contactReqChan) ch.conn = conn ch.chanID = (uint16)(msg.GetChannelIdentifier()) ch.reqData = new(ContactRequest) ext, err := proto.GetExtension(msg, packet.E_ContactRequest) if err != nil { return nil, err } if ext == nil { return nil, fmt.Errorf("server: missing ContactRequest extension") } req := ext.(*packet.ContactRequest) ch.reqData.Hostname = conn.hostname ch.reqData.MyNickname = req.GetNickname() if len(ch.reqData.MyNickname) > ContactReqNicknameMaxCharacters { return nil, fmt.Errorf("server: ContactRequest nickname too long") } ch.reqData.Message = req.GetMessageText() if len(ch.reqData.Message) > ContactReqMessageMaxCharacters { return nil, fmt.Errorf("server: ContactRequest message too long") } return ch, nil }
func newServerChatChan(conn *ricochetConn, msg *packet.OpenChannel) (*chatChan, error) { ch := new(chatChan) ch.conn = conn ch.chanID = (uint16)(msg.GetChannelIdentifier()) ch.isOutgoing = false return ch, nil }
func newServerAuthHSChan(conn *ricochetConn, msg *packet.OpenChannel) (*authHSChan, error) { ch := new(authHSChan) ch.conn = conn ch.chanID = (uint16)(msg.GetChannelIdentifier()) ext, err := proto.GetExtension(msg, packet.E_ClientCookie) if err != nil { return nil, err } ch.clientCookie = ext.([]byte) if len(ch.clientCookie) != authHiddenServiceCookieSize { return nil, fmt.Errorf("invalid AuthHiddenService client_cookie") } return ch, nil }
func (ch *controlChan) onOpenChannelMsg(msg *packet.OpenChannel) error { log := ch.conn.endpoint.log chanType := msg.GetChannelType() rawChanID := msg.GetChannelIdentifier() if rawChanID <= 0 || rawChanID >= math.MaxUint16 { return fmt.Errorf("attempted to open invalid channel ID: %v", rawChanID) } chanID := (uint16)(rawChanID) // So f*****g stupid. if ch.conn.isServer && (chanID&1 == 0) { return fmt.Errorf("client attempted to open even channel ID: %v", chanID) } if !ch.conn.isServer && (chanID&1 == 1) { return fmt.Errorf("server attempted to open odd channel ID: %v", chanID) } if ch.conn.chanMap[chanID] != nil { return fmt.Errorf("attempted to open duplicate channel ID: %v", chanID) } log.Printf("chan open attempt: %v (%d)", chanType, chanID) var newCh ricochetChan var err error switch chanType { case authHiddenServiceChannelType: if !ch.conn.isServer { return fmt.Errorf("attempted to open auth channel to client") } if ch.isAuthenticated { return fmt.Errorf("attempted to open auth channel when authed") } if ch.authChan != invalidChanID { return fmt.Errorf("attempted to open auth channel when one exists") } if newCh, err = newServerAuthHSChan(ch.conn, msg); err != nil { return err } ch.authChan = (int)(chanID) case contactReqChannelType: if !ch.conn.isServer { return fmt.Errorf("attempted to open contact req channel to client") } if !ch.isAuthenticated { return fmt.Errorf("attempted to open contact req channel pre-auth") } if ch.contactReqChan != invalidChanID { return fmt.Errorf("attempted to open contact req channel when one exists") } if newCh, err = newServerContactReqChan(ch.conn, msg); err != nil { return err } ch.contactReqChan = (int)(chanID) case chatChannelType: if !ch.isAuthenticated { return fmt.Errorf("attempted to open chat channel pre-auth") } if ch.incomingChatChan != invalidChanID { return fmt.Errorf("attempted to open chat channel when one exists") } if newCh, err = newServerChatChan(ch.conn, msg); err != nil { return err } ch.incomingChatChan = (int)(chanID) default: return fmt.Errorf("attempted to open unknown channel type") } // Send the response and add the channel to the global channel map. // // Note: The code will opt to tear down the connection instead of sending // any sort of failure response. Rather rude, but that's arguably correct // behavior for most responses anyway. if newCh != nil && err == nil { if err = newCh.onOpenChannel(); err != nil { return err } ch.conn.Lock() defer ch.conn.Unlock() ch.conn.chanMap[chanID] = newCh } return err }