github.com/status-im/status-go@v1.1.0/protocol/message_validator.go (about) 1 package protocol 2 3 import ( 4 "errors" 5 "fmt" 6 "strconv" 7 "strings" 8 9 utils "github.com/status-im/status-go/common" 10 "github.com/status-im/status-go/protocol/protobuf" 11 "github.com/status-im/status-go/protocol/v1" 12 ) 13 14 const maxChatMessageTextLength = 4096 15 const maxStatusMessageText = 128 16 17 // maxWhisperDrift is how many milliseconds we allow the clock value to differ 18 // from whisperTimestamp 19 const maxWhisperFutureDriftMs uint64 = 120000 20 21 func validateClockValue(clock uint64, whisperTimestamp uint64) error { 22 if clock == 0 { 23 return errors.New("clock can't be 0") 24 } 25 26 if clock > whisperTimestamp && clock-whisperTimestamp > maxWhisperFutureDriftMs { 27 return errors.New("clock value too high") 28 } 29 30 return nil 31 } 32 33 func ValidateMembershipUpdateMessage(message *protocol.MembershipUpdateMessage, timeNowMs uint64) error { 34 35 for _, e := range message.Events { 36 if err := validateClockValue(e.ClockValue, timeNowMs); err != nil { 37 return err 38 } 39 40 } 41 return nil 42 } 43 44 func ValidateStatusUpdate(message *protobuf.StatusUpdate) error { 45 if message == nil { 46 return errors.New("message can't be nil") 47 } 48 if message.Clock == 0 { 49 return errors.New("clock can't be 0") 50 } 51 52 if message.StatusType == protobuf.StatusUpdate_UNKNOWN_STATUS_TYPE { 53 return errors.New("unknown status type") 54 } 55 56 if len([]rune(message.CustomText)) > maxStatusMessageText { 57 return fmt.Errorf("custom text shouldn't be longer than %d", maxStatusMessageText) 58 } 59 60 return nil 61 62 } 63 64 func ValidateEditMessage(message *protobuf.EditMessage) error { 65 if message == nil { 66 return errors.New("message can't be nil") 67 } 68 if message.Clock == 0 { 69 return errors.New("clock can't be 0") 70 } 71 if len(message.ChatId) == 0 { 72 return errors.New("chat-id can't be empty") 73 } 74 if len(message.MessageId) == 0 { 75 return errors.New("message-id can't be empty") 76 } 77 78 if message.MessageType == protobuf.MessageType_UNKNOWN_MESSAGE_TYPE || message.MessageType == protobuf.MessageType_SYSTEM_MESSAGE_PRIVATE_GROUP { 79 return errors.New("unknown message type") 80 } 81 82 return ValidateText(message.Text) 83 } 84 85 func ValidateDeleteMessage(message *protobuf.DeleteMessage) error { 86 if message == nil { 87 return errors.New("message can't be nil") 88 } 89 90 if len(message.ChatId) == 0 { 91 return errors.New("chat-id can't be empty") 92 } 93 if len(message.MessageId) == 0 { 94 return errors.New("message-id can't be empty") 95 } 96 97 if message.MessageType == protobuf.MessageType_UNKNOWN_MESSAGE_TYPE || message.MessageType == protobuf.MessageType_SYSTEM_MESSAGE_PRIVATE_GROUP { 98 return errors.New("unknown message type") 99 } 100 101 return nil 102 } 103 104 func ValidateDeleteForMeMessage(message *protobuf.SyncDeleteForMeMessage) error { 105 if message == nil { 106 return errors.New("message can't be nil") 107 } 108 109 if len(message.MessageId) == 0 { 110 return errors.New("message-id can't be empty") 111 } 112 113 return nil 114 } 115 116 func ValidateReceivedPairInstallation(message *protobuf.SyncPairInstallation, whisperTimestamp uint64) error { 117 if err := validateClockValue(message.Clock, whisperTimestamp); err != nil { 118 return err 119 } 120 121 if len(strings.TrimSpace(message.Name)) == 0 { 122 return errors.New("name can't be empty") 123 } 124 125 if len(strings.TrimSpace(message.DeviceType)) == 0 { 126 return errors.New("device type can't be empty") 127 } 128 129 if len(strings.TrimSpace(message.InstallationId)) == 0 { 130 return errors.New("installationId can't be empty") 131 } 132 133 return nil 134 } 135 136 func ValidateReceivedSendTransaction(message *protobuf.SendTransaction, whisperTimestamp uint64) error { 137 if err := validateClockValue(message.Clock, whisperTimestamp); err != nil { 138 return err 139 } 140 141 if len(strings.TrimSpace(message.TransactionHash)) == 0 { 142 return errors.New("transaction hash can't be empty") 143 } 144 145 if message.Signature == nil { 146 return errors.New("signature can't be nil") 147 } 148 149 return nil 150 } 151 152 func ValidateReceivedRequestAddressForTransaction(message *protobuf.RequestAddressForTransaction, whisperTimestamp uint64) error { 153 if err := validateClockValue(message.Clock, whisperTimestamp); err != nil { 154 return err 155 } 156 157 if len(strings.TrimSpace(message.Value)) == 0 { 158 return errors.New("value can't be empty") 159 } 160 161 _, err := strconv.ParseFloat(message.Value, 64) 162 if err != nil { 163 return err 164 } 165 166 return nil 167 } 168 169 func ValidateReceivedRequestTransaction(message *protobuf.RequestTransaction, whisperTimestamp uint64) error { 170 if err := validateClockValue(message.Clock, whisperTimestamp); err != nil { 171 return err 172 } 173 174 if len(strings.TrimSpace(message.Value)) == 0 { 175 return errors.New("value can't be empty") 176 } 177 178 if len(strings.TrimSpace(message.Address)) == 0 { 179 return errors.New("address can't be empty") 180 } 181 182 _, err := strconv.ParseFloat(message.Value, 64) 183 if err != nil { 184 return err 185 } 186 187 return nil 188 } 189 190 func ValidateReceivedAcceptRequestAddressForTransaction(message *protobuf.AcceptRequestAddressForTransaction, whisperTimestamp uint64) error { 191 if err := validateClockValue(message.Clock, whisperTimestamp); err != nil { 192 return err 193 } 194 195 if len(message.Id) == 0 { 196 return errors.New("messageID can't be empty") 197 } 198 199 if len(strings.TrimSpace(message.Address)) == 0 { 200 return errors.New("address can't be empty") 201 } 202 203 return nil 204 } 205 206 func ValidateReceivedDeclineRequestAddressForTransaction(message *protobuf.DeclineRequestAddressForTransaction, whisperTimestamp uint64) error { 207 if err := validateClockValue(message.Clock, whisperTimestamp); err != nil { 208 return err 209 } 210 211 if len(message.Id) == 0 { 212 return errors.New("messageID can't be empty") 213 } 214 215 return nil 216 } 217 218 func ValidateReceivedDeclineRequestTransaction(message *protobuf.DeclineRequestTransaction, whisperTimestamp uint64) error { 219 if err := validateClockValue(message.Clock, whisperTimestamp); err != nil { 220 return err 221 } 222 223 if len(message.Id) == 0 { 224 return errors.New("messageID can't be empty") 225 } 226 227 return nil 228 } 229 230 func ValidateText(text string) error { 231 if len(strings.TrimSpace(text)) == 0 { 232 return errors.New("text can't be empty") 233 } 234 235 if len([]rune(text)) > maxChatMessageTextLength { 236 return fmt.Errorf("text shouldn't be longer than %d", maxChatMessageTextLength) 237 } 238 239 return nil 240 } 241 242 func ValidateReceivedChatMessage(message *protobuf.ChatMessage, whisperTimestamp uint64) error { 243 if err := validateClockValue(message.Clock, whisperTimestamp); err != nil { 244 return err 245 } 246 247 if message.Timestamp == 0 { 248 return errors.New("timestamp can't be 0") 249 } 250 251 if message.ContentType != protobuf.ChatMessage_DISCORD_MESSAGE && 252 message.ContentType != protobuf.ChatMessage_BRIDGE_MESSAGE && 253 (message.ContentType != protobuf.ChatMessage_IMAGE || message.Text != "") { 254 if err := ValidateText(message.Text); err != nil { 255 return err 256 } 257 } 258 259 if len(message.ChatId) == 0 { 260 return errors.New("chatId can't be empty") 261 } 262 263 if message.MessageType == protobuf.MessageType_UNKNOWN_MESSAGE_TYPE || message.MessageType == protobuf.MessageType_SYSTEM_MESSAGE_PRIVATE_GROUP { 264 return errors.New("unknown message type") 265 } 266 267 switch message.ContentType { 268 case protobuf.ChatMessage_UNKNOWN_CONTENT_TYPE: 269 return errors.New("unknown content type") 270 271 case protobuf.ChatMessage_TRANSACTION_COMMAND: 272 return errors.New("can't receive request address for transaction from others") 273 274 case protobuf.ChatMessage_STICKER: 275 if message.Payload == nil { 276 return errors.New("no sticker content") 277 } 278 sticker := message.GetSticker() 279 if sticker == nil { 280 return errors.New("no sticker content") 281 } 282 if len(sticker.Hash) == 0 { 283 return errors.New("sticker hash not set") 284 } 285 286 case protobuf.ChatMessage_IMAGE: 287 if message.Payload == nil { 288 return errors.New("no image content") 289 } 290 image := message.GetImage() 291 if image == nil { 292 return errors.New("no image content") 293 } 294 if len(image.Payload) == 0 { 295 return errors.New("image payload empty") 296 } 297 if image.Format == protobuf.ImageFormat_UNKNOWN_IMAGE_FORMAT { 298 return errors.New("image type unknown") 299 } 300 301 case protobuf.ChatMessage_BRIDGE_MESSAGE: 302 if message.Payload == nil { 303 return errors.New("no bridge message content") 304 } 305 bridgeMessage := message.GetBridgeMessage() 306 if bridgeMessage == nil { 307 return errors.New("no bridge message content") 308 } 309 if len(bridgeMessage.UserName) == 0 { 310 return errors.New("no username") 311 } 312 if len(bridgeMessage.BridgeName) == 0 { 313 return errors.New("no bridge name") 314 } 315 if len(bridgeMessage.Content) == 0 { 316 return errors.New("no bridge message content text") 317 } 318 } 319 320 if message.ContentType == protobuf.ChatMessage_AUDIO { 321 if message.Payload == nil { 322 return errors.New("no audio content") 323 } 324 audio := message.GetAudio() 325 if audio == nil { 326 return errors.New("no audio content") 327 } 328 if len(audio.Payload) == 0 { 329 return errors.New("audio payload empty") 330 } 331 332 if audio.Type == protobuf.AudioMessage_UNKNOWN_AUDIO_TYPE { 333 return errors.New("audio type unknown") 334 } 335 } 336 337 if message.ContentType == protobuf.ChatMessage_SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP { 338 return errors.New("private group system message content type not allowed") 339 } 340 341 if message.ContentType == protobuf.ChatMessage_SYSTEM_MESSAGE_MUTUAL_EVENT_SENT || 342 message.ContentType == protobuf.ChatMessage_SYSTEM_MESSAGE_MUTUAL_EVENT_ACCEPTED || 343 message.ContentType == protobuf.ChatMessage_SYSTEM_MESSAGE_MUTUAL_EVENT_REMOVED { 344 return errors.New("mutual state event system message content type not allowed") 345 } 346 347 if err := utils.ValidateDisplayName(&message.DisplayName); err != nil { 348 return err 349 } 350 351 return nil 352 } 353 354 func ValidateReceivedEmojiReaction(emoji *protobuf.EmojiReaction, whisperTimestamp uint64) error { 355 if err := validateClockValue(emoji.Clock, whisperTimestamp); err != nil { 356 return err 357 } 358 359 if len(emoji.MessageId) == 0 { 360 return errors.New("message-id can't be empty") 361 } 362 363 if len(emoji.ChatId) == 0 { 364 return errors.New("chat-id can't be empty") 365 } 366 367 if emoji.Type == protobuf.EmojiReaction_UNKNOWN_EMOJI_REACTION_TYPE { 368 return errors.New("unknown emoji reaction type") 369 } 370 371 if emoji.MessageType == protobuf.MessageType_UNKNOWN_MESSAGE_TYPE { 372 return errors.New("unknown message type") 373 } 374 375 return nil 376 } 377 378 func ValidateReceivedGroupChatInvitation(invitation *protobuf.GroupChatInvitation) error { 379 380 if len(invitation.ChatId) == 0 { 381 return errors.New("chat-id can't be empty") 382 } 383 384 return nil 385 }