github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/chat/errors.go (about)

     1  package chat
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"net"
     7  	"time"
     8  
     9  	"github.com/keybase/client/go/chat/types"
    10  	"github.com/keybase/client/go/ephemeral"
    11  	"github.com/keybase/client/go/libkb"
    12  	"github.com/keybase/client/go/protocol/chat1"
    13  	"github.com/keybase/client/go/protocol/gregor1"
    14  	"github.com/keybase/client/go/protocol/keybase1"
    15  	"github.com/keybase/client/go/teams"
    16  	"github.com/keybase/go-framed-msgpack-rpc/rpc"
    17  	"golang.org/x/net/context"
    18  )
    19  
    20  var ErrChatServerTimeout = errors.New("timeout calling chat server")
    21  var ErrDuplicateConnection = errors.New("error calling chat server")
    22  var ErrKeyServerTimeout = errors.New("timeout calling into key server")
    23  
    24  func NewPermanentUnboxingError(inner error) types.UnboxingError {
    25  	return PermanentUnboxingError{inner}
    26  }
    27  
    28  type PermanentUnboxingError struct{ inner error }
    29  
    30  func (e PermanentUnboxingError) Error() string {
    31  	switch err := e.inner.(type) {
    32  	case EphemeralUnboxingError, NotAuthenticatedForThisDeviceError:
    33  		return err.Error()
    34  	default:
    35  		return fmt.Sprintf("Unable to decrypt chat message: %s", err.Error())
    36  	}
    37  }
    38  
    39  func (e PermanentUnboxingError) IsPermanent() bool { return true }
    40  
    41  func (e PermanentUnboxingError) Inner() error { return e.inner }
    42  
    43  func (e PermanentUnboxingError) ExportType() chat1.MessageUnboxedErrorType {
    44  	switch err := e.inner.(type) {
    45  	case VersionError:
    46  		return err.ExportType()
    47  	case EphemeralUnboxingError:
    48  		return chat1.MessageUnboxedErrorType_EPHEMERAL
    49  	case NotAuthenticatedForThisDeviceError, InvalidMACError:
    50  		return chat1.MessageUnboxedErrorType_PAIRWISE_MISSING
    51  	default:
    52  		return chat1.MessageUnboxedErrorType_MISC
    53  	}
    54  }
    55  
    56  func (e PermanentUnboxingError) VersionKind() chat1.VersionKind {
    57  	switch err := e.inner.(type) {
    58  	case VersionError:
    59  		return err.VersionKind()
    60  	default:
    61  		return ""
    62  	}
    63  }
    64  
    65  func (e PermanentUnboxingError) VersionNumber() int {
    66  	switch err := e.inner.(type) {
    67  	case VersionError:
    68  		return err.VersionNumber()
    69  	default:
    70  		return 0
    71  	}
    72  }
    73  
    74  func (e PermanentUnboxingError) IsCritical() bool {
    75  	switch err := e.inner.(type) {
    76  	case VersionError:
    77  		return err.IsCritical()
    78  	default:
    79  		return false
    80  	}
    81  }
    82  
    83  func (e PermanentUnboxingError) InternalError() string {
    84  	switch err := e.Inner().(type) {
    85  	case types.InternalError:
    86  		return err.InternalError()
    87  	default:
    88  		return err.Error()
    89  	}
    90  }
    91  
    92  func (e PermanentUnboxingError) ToStatus() (status keybase1.Status) {
    93  	if ee, ok := e.inner.(libkb.ExportableError); ok {
    94  		status = ee.ToStatus()
    95  		status.Desc = e.Error()
    96  	} else {
    97  		status = keybase1.Status{
    98  			Name: "GENERIC",
    99  			Code: libkb.SCGeneric,
   100  			Desc: e.Error(),
   101  		}
   102  	}
   103  	return status
   104  }
   105  
   106  // =============================================================================
   107  
   108  func NewTransientUnboxingError(inner error) types.UnboxingError {
   109  	return TransientUnboxingError{inner}
   110  }
   111  
   112  type TransientUnboxingError struct{ inner error }
   113  
   114  func (e TransientUnboxingError) Error() string {
   115  	return fmt.Sprintf("Unable to decrypt chat message (transient): %s", e.inner.Error())
   116  }
   117  
   118  func (e TransientUnboxingError) IsPermanent() bool { return false }
   119  
   120  func (e TransientUnboxingError) Inner() error { return e.inner }
   121  
   122  func (e TransientUnboxingError) ExportType() chat1.MessageUnboxedErrorType {
   123  	return chat1.MessageUnboxedErrorType_MISC
   124  }
   125  
   126  func (e TransientUnboxingError) VersionKind() chat1.VersionKind {
   127  	return ""
   128  }
   129  
   130  func (e TransientUnboxingError) VersionNumber() int {
   131  	return 0
   132  }
   133  
   134  func (e TransientUnboxingError) IsCritical() bool {
   135  	return false
   136  }
   137  
   138  func (e TransientUnboxingError) InternalError() string {
   139  	switch err := e.Inner().(type) {
   140  	case types.InternalError:
   141  		return err.InternalError()
   142  	default:
   143  		return err.Error()
   144  	}
   145  }
   146  
   147  func (e TransientUnboxingError) ToStatus() (status keybase1.Status) {
   148  	if ee, ok := e.inner.(libkb.ExportableError); ok {
   149  		status = ee.ToStatus()
   150  		status.Desc = e.Error()
   151  	} else {
   152  		status = keybase1.Status{
   153  			Name: "GENERIC",
   154  			Code: libkb.SCGeneric,
   155  			Desc: e.Error(),
   156  		}
   157  	}
   158  	return status
   159  }
   160  
   161  // =============================================================================
   162  
   163  type EphemeralAlreadyExpiredError struct{}
   164  
   165  func NewEphemeralAlreadyExpiredError() EphemeralAlreadyExpiredError {
   166  	return EphemeralAlreadyExpiredError{}
   167  }
   168  
   169  func (e EphemeralAlreadyExpiredError) Error() string {
   170  	return "Exploding message is expired"
   171  }
   172  
   173  func (e EphemeralAlreadyExpiredError) InternalError() string {
   174  	return e.Error()
   175  }
   176  
   177  // =============================================================================
   178  
   179  type EphemeralUnboxingError struct {
   180  	inner ephemeral.EphemeralKeyError
   181  }
   182  
   183  func NewEphemeralUnboxingError(inner ephemeral.EphemeralKeyError) EphemeralUnboxingError {
   184  	return EphemeralUnboxingError{inner}
   185  }
   186  
   187  func (e EphemeralUnboxingError) Error() string {
   188  	return e.inner.HumanError()
   189  }
   190  
   191  func (e EphemeralUnboxingError) InternalError() string {
   192  	return e.inner.Error()
   193  }
   194  
   195  // =============================================================================
   196  
   197  type PublicTeamEphemeralKeyError struct{}
   198  
   199  func NewPublicTeamEphemeralKeyError() PublicTeamEphemeralKeyError {
   200  	return PublicTeamEphemeralKeyError{}
   201  }
   202  
   203  func (e PublicTeamEphemeralKeyError) Error() string {
   204  	return "Cannot use exploding messages for a public team."
   205  }
   206  
   207  // =============================================================================
   208  
   209  type NotAuthenticatedForThisDeviceError struct{ inner ephemeral.EphemeralKeyError }
   210  
   211  func NewNotAuthenticatedForThisDeviceError(mctx libkb.MetaContext, memberCtime *keybase1.Time,
   212  	contentCtime gregor1.Time) NotAuthenticatedForThisDeviceError {
   213  	inner := ephemeral.NewNotAuthenticatedForThisDeviceError(mctx, memberCtime, contentCtime)
   214  	return NotAuthenticatedForThisDeviceError{inner: inner}
   215  }
   216  
   217  func (e NotAuthenticatedForThisDeviceError) Error() string {
   218  	return e.inner.HumanError()
   219  }
   220  
   221  func (e NotAuthenticatedForThisDeviceError) InternalError() string {
   222  	return e.inner.Error()
   223  }
   224  
   225  // =============================================================================
   226  
   227  type InvalidMACError struct{}
   228  
   229  func NewInvalidMACError() InvalidMACError {
   230  	return InvalidMACError{}
   231  }
   232  
   233  func (e InvalidMACError) Error() string {
   234  	return "invalid MAC"
   235  }
   236  
   237  // =============================================================================
   238  
   239  type ConsistencyErrorCode int
   240  
   241  const (
   242  	DuplicateID ConsistencyErrorCode = iota
   243  	OutOfOrderID
   244  	InconsistentHash
   245  	IncorrectHash
   246  )
   247  
   248  type ChatThreadConsistencyError interface {
   249  	error
   250  	Code() ConsistencyErrorCode
   251  }
   252  
   253  type chatThreadConsistencyErrorImpl struct {
   254  	msg  string
   255  	code ConsistencyErrorCode
   256  }
   257  
   258  func (e chatThreadConsistencyErrorImpl) Error() string {
   259  	return e.msg
   260  }
   261  
   262  func (e chatThreadConsistencyErrorImpl) Code() ConsistencyErrorCode {
   263  	return e.code
   264  }
   265  
   266  func NewChatThreadConsistencyError(code ConsistencyErrorCode, msg string, formatArgs ...interface{}) ChatThreadConsistencyError {
   267  	return &chatThreadConsistencyErrorImpl{
   268  		code: code,
   269  		msg:  fmt.Sprintf(msg, formatArgs...),
   270  	}
   271  }
   272  
   273  // =============================================================================
   274  
   275  type BoxingError struct {
   276  	Msg  string
   277  	Perm bool
   278  }
   279  
   280  func NewBoxingError(msg string, perm bool) BoxingError {
   281  	return BoxingError{
   282  		Msg:  msg,
   283  		Perm: perm,
   284  	}
   285  }
   286  
   287  func (e BoxingError) Error() string {
   288  	return fmt.Sprintf("encryption error: %s perm: %v", e.Msg, e.Perm)
   289  }
   290  
   291  func (e BoxingError) IsImmediateFail() (chat1.OutboxErrorType, bool) {
   292  	if e.Perm {
   293  		return chat1.OutboxErrorType_MISC, true
   294  	}
   295  	return 0, false
   296  }
   297  
   298  // =============================================================================
   299  
   300  type RestrictedBotChannelError struct{}
   301  
   302  func NewRestrictedBotChannelError() RestrictedBotChannelError {
   303  	return RestrictedBotChannelError{}
   304  }
   305  
   306  func (e RestrictedBotChannelError) Error() string {
   307  	return "bot restricted from sending to this channel"
   308  }
   309  
   310  func (e RestrictedBotChannelError) IsImmediateFail() (chat1.OutboxErrorType, bool) {
   311  	return chat1.OutboxErrorType_RESTRICTEDBOT, true
   312  }
   313  
   314  // =============================================================================
   315  
   316  type BoxingCryptKeysError struct {
   317  	Err error
   318  }
   319  
   320  // Cause implements the pkg/errors Cause() method, also cloned in libkb via HumanError,
   321  // so that we know which error to show to the human being using keybase (rather than
   322  // for our own internal uses).
   323  func (e BoxingCryptKeysError) Cause() error {
   324  	return e.Err
   325  }
   326  
   327  func NewBoxingCryptKeysError(err error) BoxingCryptKeysError {
   328  	return BoxingCryptKeysError{
   329  		Err: err,
   330  	}
   331  }
   332  
   333  func (e BoxingCryptKeysError) Error() string {
   334  	return fmt.Sprintf("boxing error: unable to get crypt keys: %s", e.Err.Error())
   335  }
   336  
   337  func (e BoxingCryptKeysError) Inner() error {
   338  	return e.Err
   339  }
   340  
   341  func (e BoxingCryptKeysError) IsImmediateFail() (chat1.OutboxErrorType, bool) {
   342  	if _, ok := e.Err.(libkb.IdentifySummaryError); ok {
   343  		return chat1.OutboxErrorType_IDENTIFY, true
   344  	}
   345  	return 0, false
   346  }
   347  
   348  // =============================================================================
   349  
   350  type BodyHashInvalid struct{}
   351  
   352  func (e BodyHashInvalid) Error() string {
   353  	return "chat body hash invalid"
   354  }
   355  
   356  type VersionError struct {
   357  	Kind     string
   358  	Version  int
   359  	Critical bool
   360  }
   361  
   362  func (e VersionError) Error() string {
   363  	return fmt.Sprintf("Unable to decrypt because current client is out of date. Please update your version of Keybase! Chat version error: [ unhandled: %s version: %d critical: %v ]", e.Kind, e.Version, e.Critical)
   364  }
   365  
   366  func (e VersionError) ExportType() chat1.MessageUnboxedErrorType {
   367  	if e.Critical {
   368  		return chat1.MessageUnboxedErrorType_BADVERSION_CRITICAL
   369  	}
   370  	return chat1.MessageUnboxedErrorType_BADVERSION
   371  }
   372  
   373  func (e VersionError) VersionKind() chat1.VersionKind {
   374  	return chat1.VersionKind(e.Kind)
   375  }
   376  
   377  func (e VersionError) VersionNumber() int {
   378  	return e.Version
   379  }
   380  
   381  func (e VersionError) IsCritical() bool {
   382  	return e.Critical
   383  }
   384  
   385  func NewMessageBoxedVersionError(version chat1.MessageBoxedVersion) VersionError {
   386  	return VersionError{
   387  		Kind:     string(chat1.VersionErrorMessageBoxed),
   388  		Version:  int(version),
   389  		Critical: true,
   390  	}
   391  }
   392  
   393  func NewHeaderVersionError(version chat1.HeaderPlaintextVersion,
   394  	defaultHeader chat1.HeaderPlaintextUnsupported) VersionError {
   395  	return VersionError{
   396  		Kind:     string(chat1.VersionErrorHeader),
   397  		Version:  int(version),
   398  		Critical: defaultHeader.Mi.Crit,
   399  	}
   400  }
   401  
   402  func NewBodyVersionError(version chat1.BodyPlaintextVersion, defaultBody chat1.BodyPlaintextUnsupported) VersionError {
   403  	return VersionError{
   404  		Kind:     string(chat1.VersionErrorBody),
   405  		Version:  int(version),
   406  		Critical: defaultBody.Mi.Crit,
   407  	}
   408  }
   409  
   410  // =============================================================================
   411  
   412  type HeaderMismatchError struct {
   413  	Field string
   414  }
   415  
   416  var _ error = (*HeaderMismatchError)(nil)
   417  
   418  func (e HeaderMismatchError) Error() string {
   419  	return fmt.Sprintf("chat header mismatch on %q", e.Field)
   420  }
   421  
   422  func NewHeaderMismatchError(field string) HeaderMismatchError {
   423  	return HeaderMismatchError{Field: field}
   424  }
   425  
   426  // =============================================================================
   427  
   428  type OfflineError struct {
   429  }
   430  
   431  func (e OfflineError) Error() string {
   432  	return "operation failed: no connection to chat server"
   433  }
   434  
   435  type OfflineClient struct {
   436  }
   437  
   438  func (e OfflineClient) Call(ctx context.Context, method string, arg interface{},
   439  	res interface{}, timeout time.Duration) error {
   440  	return OfflineError{}
   441  }
   442  
   443  func (e OfflineClient) CallCompressed(ctx context.Context, method string, arg interface{},
   444  	res interface{}, ctype rpc.CompressionType, timeout time.Duration) error {
   445  	return OfflineError{}
   446  }
   447  
   448  func (e OfflineClient) Notify(ctx context.Context, method string, arg interface{}, timeout time.Duration) error {
   449  	return OfflineError{}
   450  }
   451  
   452  // =============================================================================
   453  
   454  type DuplicateTopicNameError struct {
   455  	Conv chat1.ConversationLocal
   456  }
   457  
   458  func (e DuplicateTopicNameError) Error() string {
   459  	return fmt.Sprintf("channel name %s is already in use in %v",
   460  		e.Conv.GetTopicName(), e.Conv.Info.TlfName)
   461  }
   462  
   463  // =============================================================================
   464  
   465  type ImpteamBadteamError struct {
   466  	Msg string
   467  }
   468  
   469  func (e ImpteamBadteamError) Error() string {
   470  	return fmt.Sprintf("bad iteam found in conv: %s", e.Msg)
   471  }
   472  
   473  // =============================================================================
   474  
   475  type UnknownTLFNameError struct {
   476  	tlfName string
   477  }
   478  
   479  func NewUnknownTLFNameError(name string) UnknownTLFNameError {
   480  	return UnknownTLFNameError{
   481  		tlfName: name,
   482  	}
   483  }
   484  
   485  func (e UnknownTLFNameError) Error() string {
   486  	return fmt.Sprintf("unknown conversation name: %s", e.tlfName)
   487  }
   488  
   489  // =============================================================================
   490  
   491  type AttachmentUploadError struct {
   492  	Msg  string
   493  	Perm bool
   494  }
   495  
   496  func NewAttachmentUploadError(msg string, perm bool) AttachmentUploadError {
   497  	return AttachmentUploadError{
   498  		Msg:  msg,
   499  		Perm: perm,
   500  	}
   501  }
   502  
   503  func (e AttachmentUploadError) Error() string {
   504  	return fmt.Sprintf("attachment failed to upload; %s", e.Msg)
   505  }
   506  
   507  func (e AttachmentUploadError) IsImmediateFail() (chat1.OutboxErrorType, bool) {
   508  	return chat1.OutboxErrorType_MISC, e.Perm
   509  }
   510  
   511  // =============================================================================
   512  
   513  type SenderTestImmediateFailError struct {
   514  }
   515  
   516  func (e SenderTestImmediateFailError) Error() string {
   517  	return "sender test immediate fail error"
   518  }
   519  
   520  func (e SenderTestImmediateFailError) IsImmediateFail() (chat1.OutboxErrorType, bool) {
   521  	return chat1.OutboxErrorType_MISC, true
   522  }
   523  
   524  // =============================================================================
   525  
   526  type DecryptionKeyNotFoundError struct {
   527  	generation            int
   528  	kbfsEncrypted, public bool
   529  }
   530  
   531  func NewDecryptionKeyNotFoundError(generation int, public, kbfsEncrypted bool) DecryptionKeyNotFoundError {
   532  	return DecryptionKeyNotFoundError{
   533  		generation:    generation,
   534  		kbfsEncrypted: kbfsEncrypted,
   535  		public:        public,
   536  	}
   537  }
   538  
   539  func (e DecryptionKeyNotFoundError) Error() string {
   540  	return fmt.Sprintf("decryption key not found for generation: %v kbfsEncrypted: %v public: %v",
   541  		e.generation, e.kbfsEncrypted, e.public)
   542  }
   543  
   544  // =============================================================================
   545  
   546  type OfflineErrorKind int
   547  
   548  const (
   549  	OfflineErrorKindOnline OfflineErrorKind = iota
   550  	OfflineErrorKindOfflineBasic
   551  	OfflineErrorKindOfflineReconnect
   552  )
   553  
   554  func IsOfflineError(err error) OfflineErrorKind {
   555  	// Check type
   556  	switch terr := err.(type) {
   557  	case net.Error:
   558  		return OfflineErrorKindOfflineReconnect
   559  	case libkb.APINetError:
   560  		return OfflineErrorKindOfflineBasic
   561  	case OfflineError:
   562  		return OfflineErrorKindOfflineBasic
   563  	case TransientUnboxingError:
   564  		return IsOfflineError(terr.Inner())
   565  	}
   566  	// Check error itself
   567  	switch err {
   568  	case context.DeadlineExceeded:
   569  		fallthrough
   570  	case ErrChatServerTimeout:
   571  		return OfflineErrorKindOfflineReconnect
   572  	case ErrDuplicateConnection:
   573  		return OfflineErrorKindOfflineBasic
   574  	}
   575  
   576  	// Unfortunately, Go throws these without a type and they can occasionally
   577  	// propagate up. The strings were copied from
   578  	// https://golang.org/src/crypto/tls/conn.go
   579  	switch err.Error() {
   580  	case "tls: use of closed connection",
   581  		"tls: protocol is shutdown":
   582  		return OfflineErrorKindOfflineReconnect
   583  	}
   584  	return OfflineErrorKindOnline
   585  }
   586  
   587  func IsRekeyError(err error) (typ chat1.ConversationErrorType, ok bool) {
   588  	switch err := err.(type) {
   589  	case types.UnboxingError:
   590  		return IsRekeyError(err.Inner())
   591  	case libkb.NeedSelfRekeyError:
   592  		return chat1.ConversationErrorType_SELFREKEYNEEDED, true
   593  	case libkb.NeedOtherRekeyError:
   594  		return chat1.ConversationErrorType_OTHERREKEYNEEDED, true
   595  	default:
   596  		if teams.IsTeamReadError(err) {
   597  			return chat1.ConversationErrorType_OTHERREKEYNEEDED, true
   598  		}
   599  	}
   600  	return chat1.ConversationErrorType_NONE, false
   601  }
   602  
   603  // =============================================================================
   604  
   605  type FTLError struct {
   606  	msg string
   607  }
   608  
   609  func NewFTLError(s string) error {
   610  	return &FTLError{msg: s}
   611  }
   612  
   613  func (f FTLError) Error() string {
   614  	return fmt.Sprintf("FTL Error: %s", f.msg)
   615  }
   616  
   617  // =============================================================================
   618  
   619  type DevStoragePermissionDeniedError struct {
   620  	role keybase1.TeamRole
   621  }
   622  
   623  func NewDevStoragePermissionDeniedError(role keybase1.TeamRole) error {
   624  	return &DevStoragePermissionDeniedError{role: role}
   625  }
   626  
   627  func (e *DevStoragePermissionDeniedError) Error() string {
   628  	return fmt.Sprintf("role %q is not high enough", e.role)
   629  }
   630  
   631  // =============================================================================
   632  
   633  type DevStorageAdminOnlyError struct {
   634  	msg string
   635  }
   636  
   637  func NewDevStorageAdminOnlyError(msg string) error {
   638  	return &DevStorageAdminOnlyError{msg: msg}
   639  }
   640  
   641  func (e *DevStorageAdminOnlyError) Error() string {
   642  	return fmt.Sprintf("found a conversation and a message, but role checking failed: %s", e.msg)
   643  }