NeoMutt  2024-03-23-23-gec7045
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
gsasl.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <gsasl.h>
31#include <stdbool.h>
32#include "mutt/lib.h"
33#include "connaccount.h"
34#include "connection.h"
35#include "gsasl2.h"
36#include "mutt_account.h"
37
39static Gsasl *MuttGsaslCtx = NULL;
40
48static int mutt_gsasl_callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop)
49{
50 int rc = GSASL_NO_CALLBACK;
51
52 struct Connection *conn = gsasl_session_hook_get(sctx);
53 if (!conn)
54 {
55 mutt_debug(LL_DEBUG1, "missing session hook data!\n");
56 return rc;
57 }
58
59 switch (prop)
60 {
61 case GSASL_PASSWORD:
62 if (mutt_account_getpass(&conn->account))
63 return rc;
64 gsasl_property_set(sctx, GSASL_PASSWORD, conn->account.pass);
65 rc = GSASL_OK;
66 break;
67
68 case GSASL_AUTHID:
69 /* whom the provided password belongs to: login */
71 return rc;
72 gsasl_property_set(sctx, GSASL_AUTHID, conn->account.login);
73 rc = GSASL_OK;
74 break;
75
76 case GSASL_AUTHZID:
77 /* name of the user whose mail/resources you intend to access: user */
78 if (mutt_account_getuser(&conn->account))
79 return rc;
80 gsasl_property_set(sctx, GSASL_AUTHZID, conn->account.user);
81 rc = GSASL_OK;
82 break;
83
84 case GSASL_ANONYMOUS_TOKEN:
85 gsasl_property_set(sctx, GSASL_ANONYMOUS_TOKEN, "dummy");
86 rc = GSASL_OK;
87 break;
88
89 case GSASL_SERVICE:
90 {
91 const char *service = NULL;
92 switch (conn->account.type)
93 {
95 service = "imap";
96 break;
98 service = "pop";
99 break;
101 service = "smtp";
102 break;
103 default:
104 return rc;
105 }
106 gsasl_property_set(sctx, GSASL_SERVICE, service);
107 rc = GSASL_OK;
108 break;
109 }
110
111 case GSASL_HOSTNAME:
112 gsasl_property_set(sctx, GSASL_HOSTNAME, conn->account.host);
113 rc = GSASL_OK;
114 break;
115
116 default:
117 break;
118 }
119
120 return rc;
121}
122
127static bool mutt_gsasl_init(void)
128{
129 if (MuttGsaslCtx)
130 return true;
131
132 int rc = gsasl_init(&MuttGsaslCtx);
133 if (rc != GSASL_OK)
134 {
135 MuttGsaslCtx = NULL;
136 mutt_debug(LL_DEBUG1, "libgsasl initialisation failed (%d): %s.\n", rc,
137 gsasl_strerror(rc));
138 return false;
139 }
140
141 gsasl_callback_set(MuttGsaslCtx, mutt_gsasl_callback);
142 return true;
143}
144
149{
150 if (!MuttGsaslCtx)
151 return;
152
153 gsasl_done(MuttGsaslCtx);
154 MuttGsaslCtx = NULL;
155}
156
163const char *mutt_gsasl_get_mech(const char *requested_mech, const char *server_mechlist)
164{
165 if (!mutt_gsasl_init())
166 return NULL;
167
168 /* libgsasl does not do case-independent string comparisons,
169 * and stores its methods internally in uppercase. */
170 char *uc_server_mechlist = mutt_str_dup(server_mechlist);
171 if (uc_server_mechlist)
172 mutt_str_upper(uc_server_mechlist);
173
174 char *uc_requested_mech = mutt_str_dup(requested_mech);
175 if (uc_requested_mech)
176 mutt_str_upper(uc_requested_mech);
177
178 const char *sel_mech = NULL;
179 if (uc_requested_mech)
180 sel_mech = gsasl_client_suggest_mechanism(MuttGsaslCtx, uc_requested_mech);
181 else
182 sel_mech = gsasl_client_suggest_mechanism(MuttGsaslCtx, uc_server_mechlist);
183
184 FREE(&uc_requested_mech);
185 FREE(&uc_server_mechlist);
186
187 return sel_mech;
188}
189
198int mutt_gsasl_client_new(struct Connection *conn, const char *mech, Gsasl_session **sctx)
199{
200 if (!mutt_gsasl_init())
201 return -1;
202
203 int rc = gsasl_client_start(MuttGsaslCtx, mech, sctx);
204 if (rc != GSASL_OK)
205 {
206 *sctx = NULL;
207 mutt_debug(LL_DEBUG1, "gsasl_client_start failed (%d): %s.\n", rc, gsasl_strerror(rc));
208 return -1;
209 }
210
211 gsasl_session_hook_set(*sctx, conn);
212 return 0;
213}
214
219void mutt_gsasl_client_finish(Gsasl_session **sctx)
220{
221 gsasl_finish(*sctx);
222 *sctx = NULL;
223}
int mutt_account_getpass(struct ConnAccount *cac)
Fetch password into ConnAccount, if necessary.
Definition: connaccount.c:131
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
Definition: connaccount.c:52
int mutt_account_getlogin(struct ConnAccount *cac)
Retrieve login info into ConnAccount, if necessary.
Definition: connaccount.c:101
Connection Credentials.
An open network connection (socket)
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
GNU SASL authentication support.
static int mutt_gsasl_callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop)
Callback to retrieve authname or user from ConnAccount.
Definition: gsasl.c:48
static Gsasl * MuttGsaslCtx
Global GNU SASL handle.
Definition: gsasl.c:39
const char * mutt_gsasl_get_mech(const char *requested_mech, const char *server_mechlist)
Pick a connection mechanism.
Definition: gsasl.c:163
int mutt_gsasl_client_new(struct Connection *conn, const char *mech, Gsasl_session **sctx)
Create a new GNU SASL client.
Definition: gsasl.c:198
void mutt_gsasl_cleanup(void)
Shutdown GNU SASL library.
Definition: gsasl.c:148
void mutt_gsasl_client_finish(Gsasl_session **sctx)
Free a GNU SASL client.
Definition: gsasl.c:219
static bool mutt_gsasl_init(void)
Initialise GNU SASL library.
Definition: gsasl.c:127
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
#define FREE(x)
Definition: memory.h:45
Convenience wrapper for the library headers.
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
char * mutt_str_upper(char *str)
Convert all characters in the string to uppercase.
Definition: string.c:385
ConnAccount object used by POP and IMAP.
@ MUTT_ACCT_TYPE_SMTP
Smtp Account.
Definition: mutt_account.h:40
@ MUTT_ACCT_TYPE_POP
Pop Account.
Definition: mutt_account.h:39
@ MUTT_ACCT_TYPE_IMAP
Imap Account.
Definition: mutt_account.h:38
char login[128]
Login name.
Definition: connaccount.h:55
char user[128]
Username.
Definition: connaccount.h:56
char pass[256]
Password.
Definition: connaccount.h:57
char host[128]
Server to login to.
Definition: connaccount.h:54
unsigned char type
Connection type, e.g. MUTT_ACCT_TYPE_IMAP.
Definition: connaccount.h:59
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:49