gsasl  1.10.0
About: GNU SASL is an implementation of the Simple Authentication and Security Layer (SASL). Development version.
  Fossies Dox: gsasl-1.10.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

imap.c
Go to the documentation of this file.
1 /* imap.c --- Implement IMAP profile of SASL login.
2  * Copyright (C) 2002-2021 Simon Josefsson
3  *
4  * This file is part of GNU SASL.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #include "imap.h"
22 
23 int
25 {
26  char *in;
27 
28  if (!readln (&in))
29  return 0;
30 
31  return 1;
32 }
33 
34 int
36 {
37  char *in;
38  int has_tls = 0;
39 
40  if (!writeln (". CAPABILITY"))
41  return 0;
42 
43  if (!readln (&in))
44  return 0;
45 
46  has_tls = strstr (in, "STARTTLS") != NULL;
47 
48  if (!readln (&in))
49  return 0;
50 
51  return has_tls;
52 }
53 
54 int
56 {
57  char *in;
58 
59  if (!writeln (". STARTTLS"))
60  return 0;
61 
62  if (!readln (&in))
63  return 0;
64 
65  return 1;
66 }
67 
68 int
69 imap_select_mechanism (char **mechlist)
70 {
71  char *in;
72 
74  {
76  fprintf (stderr, _("Input list of SASL mechanisms:\n"));
77  if (!readln (&in))
78  return 0;
79  *mechlist = in;
80  }
81  else
82  {
83  if (!writeln (". CAPABILITY"))
84  return 0;
85 
86  if (!readln (&in))
87  return 0;
88 
89  /* XXX parse IMAP capability line */
90 
91  *mechlist = in;
92 
93  if (!readln (&in))
94  return 0;
95  }
96 
97  return 1;
98 }
99 
100 int
101 imap_authenticate (const char *mech)
102 {
104  {
105  if (!args_info.quiet_given)
106  fprintf (stderr, _("Using mechanism:\n"));
107  puts (mech);
108  }
109  else
110  {
111  char *buf;
112  int rc;
113  int len;
114 
115  len = asprintf (&buf, ". AUTHENTICATE %s", mech);
116  if (len < 0)
117  return 0;
118  rc = writeln (buf);
119  free (buf);
120  if (!rc)
121  return 0;
122  }
123 
124  return 1;
125 }
126 
127 int
128 imap_step_send (const char *data)
129 {
130  char *buf;
131  int rc;
132  int len;
133 
135  len = asprintf (&buf, "+ %s", data);
136  else
137  len = asprintf (&buf, "%s", data);
138  if (len < 0)
139  return 0;
140  rc = writeln (buf);
141  free (buf);
142  if (!rc)
143  return 0;
144 
145  return 1;
146 }
147 
148 /* Return 1 on token, 2 on protocol success, 3 on protocol fail, 0 on
149  errors. */
150 int
151 imap_step_recv (char **data)
152 {
153  char *p;
154 
155  if (!readln (data))
156  return 0;
157 
158  p = *data;
159 
160  if (!args_info.server_flag)
161  {
162  /* skip untagged responses which can be returned by the server after
163  authentication (e.g. dovecot returns new '* CAPABILITY' information
164  before the final '. OK'). */
165  while (*p == '*')
166  {
167  if (!readln (data))
168  return 0;
169  p = *data;
170  }
171 
172  if (strlen (p) >= 4 && strncmp (p, ". OK", 4) == 0)
173  return 2;
174 
175  if (strlen (p) >= 2 && strncmp (p, ". ", 2) == 0)
176  return 3;
177 
178  if (strlen (p) >= 2 && strncmp (p, "+ ", 2) == 0)
179  memmove (&p[0], &p[2], strlen (p) - 1);
180  /* This is a workaround for servers (e.g., Microsoft Exchange)
181  that return '+' instead of the correct '+ '. */
182  else if (strcmp (p, "+\n") == 0)
183  p[0] = '\0';
184  else
185  {
186  fprintf (stderr, _("warning: server did not return a token\n"));
187  return 3;
188  }
189  }
190 
191  if (p[strlen (p) - 1] == '\n')
192  p[strlen (p) - 1] = '\0';
193  if (p[strlen (p) - 1] == '\r')
194  p[strlen (p) - 1] = '\0';
195 
196  return 1;
197 }
198 
199 int
201 {
202  char *in;
203 
204  if (!writeln (". LOGOUT"))
205  return 0;
206 
207  /* read "* BYE ..." */
208  if (!readln (&in))
209  return 0;
210 
211  free (in);
212 
213  /* read ". OK ..." */
214  if (!readln (&in))
215  return 0;
216 
217  free (in);
218 
219  return 1;
220 }
#define _
Definition: arpa_inet.in.h:50
int asprintf(char **resultp, const char *format,...)
Definition: asprintf.c:30
#define NULL
Definition: stddef.in.h:72
int readln(char **out)
Definition: gsasl.c:162
int writeln(const char *str)
Definition: gsasl.c:139
struct gengetopt_args_info args_info
Definition: gsasl.c:37
int imap_step_send(const char *data)
Definition: imap.c:128
int imap_select_mechanism(char **mechlist)
Definition: imap.c:69
int imap_authenticate(const char *mech)
Definition: imap.c:101
int imap_greeting(void)
Definition: imap.c:24
int imap_starttls(void)
Definition: imap.c:55
int imap_step_recv(char **data)
Definition: imap.c:151
int imap_logout(void)
Definition: imap.c:200
int imap_has_starttls(void)
Definition: imap.c:35
int rc
Definition: error.c:42
const char * p
Definition: mbrtowc-impl.h:42
char buf[4]
Definition: mbrtowc-impl.h:39
int server_flag
Act as server. (default=off).
Definition: gsasl_cmd.h:48
unsigned int quiet_given
Whether quiet was given.
Definition: gsasl_cmd.h:168