Coverage Report

Created: 2023-09-25 07:17

/src/neomutt/imap/auth.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file
3
 * IMAP authenticator multiplexor
4
 *
5
 * @authors
6
 * Copyright (C) 1996-1998 Michael R. Elkins <me@mutt.org>
7
 * Copyright (C) 1996-1999 Brandon Long <blong@fiction.net>
8
 * Copyright (C) 1999-2001 Brendan Cully <brendan@kublai.com>
9
 *
10
 * @copyright
11
 * This program is free software: you can redistribute it and/or modify it under
12
 * the terms of the GNU General Public License as published by the Free Software
13
 * Foundation, either version 2 of the License, or (at your option) any later
14
 * version.
15
 *
16
 * This program is distributed in the hope that it will be useful, but WITHOUT
17
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
19
 * details.
20
 *
21
 * You should have received a copy of the GNU General Public License along with
22
 * this program.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
/**
26
 * @page imap_auth Authenticator multiplexor
27
 *
28
 * IMAP authenticator multiplexor
29
 */
30
31
#include "config.h"
32
#include <string.h>
33
#include "private.h"
34
#include "mutt/lib.h"
35
#include "config/lib.h"
36
#include "core/lib.h"
37
#include "auth.h"
38
39
/**
40
 * struct ImapAuth - IMAP authentication multiplexor
41
 */
42
struct ImapAuth
43
{
44
  /**
45
   * authenticate - Authenticate an IMAP connection
46
   * @param adata Imap Account data
47
   * @param method Use this named method, or any available method if NULL
48
   * @retval #ImapAuthRes Result, e.g. #IMAP_AUTH_SUCCESS
49
   */
50
  enum ImapAuthRes (*authenticate)(struct ImapAccountData *adata, const char *method);
51
52
  const char *method; ///< Name of authentication method supported, NULL means variable.
53
      ///< If this is not null, authenticate may ignore the second parameter.
54
};
55
56
/**
57
 * ImapAuthenticators - Accepted authentication methods
58
 */
59
static const struct ImapAuth ImapAuthenticators[] = {
60
  // clang-format off
61
  { imap_auth_oauth, "oauthbearer" },
62
  { imap_auth_xoauth2, "xoauth2" },
63
  { imap_auth_plain, "plain" },
64
#if defined(USE_SASL_CYRUS)
65
  { imap_auth_sasl, NULL },
66
#elif defined(USE_SASL_GNU)
67
  { imap_auth_gsasl, NULL },
68
#else
69
  { imap_auth_anon, "anonymous" },
70
#endif
71
#ifdef USE_GSS
72
  { imap_auth_gss, "gssapi" },
73
#endif
74
/* SASL includes CRAM-MD5 (and GSSAPI, but that's not enabled by default) */
75
#ifndef HAVE_SASL
76
  { imap_auth_cram_md5, "cram-md5" },
77
#endif
78
  { imap_auth_login, "login" },
79
  // clang-format on
80
};
81
82
/**
83
 * imap_auth_is_valid - Check if string is a valid imap authentication method
84
 * @param authenticator Authenticator string to check
85
 * @retval true Argument is a valid auth method
86
 *
87
 * Validate whether an input string is an accepted imap authentication method as
88
 * defined by #ImapAuthenticators.
89
 */
90
bool imap_auth_is_valid(const char *authenticator)
91
0
{
92
0
  for (size_t i = 0; i < mutt_array_size(ImapAuthenticators); i++)
93
0
  {
94
0
    const struct ImapAuth *auth = &ImapAuthenticators[i];
95
0
    if (auth->method && mutt_istr_equal(auth->method, authenticator))
96
0
      return true;
97
0
  }
98
99
0
  return false;
100
0
}
101
102
/**
103
 * imap_authenticate - Authenticate to an IMAP server
104
 * @param adata Imap Account data
105
 * @retval enum ImapAuthRes, e.g. #IMAP_AUTH_SUCCESS
106
 *
107
 * Attempt to authenticate using either user-specified authentication method if
108
 * specified, or any.
109
 */
110
int imap_authenticate(struct ImapAccountData *adata)
111
0
{
112
0
  int rc = IMAP_AUTH_FAILURE;
113
114
0
  const struct Slist *c_imap_authenticators = cs_subset_slist(NeoMutt->sub, "imap_authenticators");
115
0
  if (c_imap_authenticators && (c_imap_authenticators->count > 0))
116
0
  {
117
0
    mutt_debug(LL_DEBUG2, "Trying user-defined imap_authenticators\n");
118
119
    /* Try user-specified list of authentication methods */
120
0
    struct ListNode *np = NULL;
121
0
    STAILQ_FOREACH(np, &c_imap_authenticators->head, entries)
122
0
    {
123
0
      mutt_debug(LL_DEBUG2, "Trying method %s\n", np->data);
124
125
0
      for (size_t i = 0; i < mutt_array_size(ImapAuthenticators); i++)
126
0
      {
127
0
        const struct ImapAuth *auth = &ImapAuthenticators[i];
128
0
        if (!auth->method || mutt_istr_equal(auth->method, np->data))
129
0
        {
130
0
          rc = auth->authenticate(adata, np->data);
131
0
          if (rc == IMAP_AUTH_SUCCESS)
132
0
          {
133
0
            return rc;
134
0
          }
135
0
        }
136
0
      }
137
0
    }
138
0
  }
139
0
  else
140
0
  {
141
    /* Fall back to default: any authenticator */
142
0
    mutt_debug(LL_DEBUG2, "Trying pre-defined imap_authenticators\n");
143
144
0
    for (size_t i = 0; i < mutt_array_size(ImapAuthenticators); i++)
145
0
    {
146
0
      rc = ImapAuthenticators[i].authenticate(adata, NULL);
147
0
      if (rc == IMAP_AUTH_SUCCESS)
148
0
        return rc;
149
0
    }
150
0
  }
151
152
0
  mutt_error(_("No authenticators available or wrong credentials"));
153
0
  return rc;
154
0
}