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)  

smtp.c
Go to the documentation of this file.
1 /* smtp.c --- Implement SMTP 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 "smtp.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 ("EHLO [127.0.0.1]"))
41  return 0;
42 
43  do
44  {
45  if (!readln (&in))
46  return 0;
47 
48 #define TLSGREETING "250-STARTTLS"
49  if (strncmp (in, TLSGREETING, strlen (TLSGREETING)) == 0)
50  has_tls = 1;
51  }
52  while (strncmp (in, "250 ", 4) != 0);
53 
54  return has_tls;
55 }
56 
57 int
59 {
60  char *in;
61 
62  if (!writeln ("STARTTLS"))
63  return 0;
64 
65  if (!readln (&in))
66  return 0;
67 
68  return 1;
69 }
70 
71 int
72 smtp_select_mechanism (char **mechlist)
73 {
74  char *in;
75 
77  {
79  fprintf (stderr, _("Input list of SASL mechanisms:\n"));
80  if (!readln (&in))
81  return 0;
82  *mechlist = in;
83  }
84  else
85  {
86  if (!writeln ("EHLO [127.0.0.1]"))
87  return 0;
88 
89  do
90  {
91  if (!readln (&in))
92  return 0;
93 
94 #define GREETING1 "250-AUTH "
95 #define GREETING2 "250 AUTH "
96  if (strncmp (in, GREETING1, strlen (GREETING1)) == 0)
97  *mechlist = in + strlen (GREETING1);
98  else if (strncmp (in, GREETING2, strlen (GREETING2)) == 0)
99  *mechlist = in + strlen (GREETING2);
100  }
101  while (strncmp (in, "250 ", 4) != 0);
102  }
103 
104  return 1;
105 }
106 
107 int
108 smtp_authenticate (const char *mech)
109 {
111  {
112  if (!args_info.quiet_given)
113  fprintf (stderr, _("Using mechanism:\n"));
114  puts (mech);
115  }
116  else
117  {
118  char *buf;
119  int rc;
120  int len;
121 
122  len = asprintf (&buf, "AUTH %s", mech);
123  if (len < 0)
124  return 0;
125  rc = writeln (buf);
126  free (buf);
127  if (!rc)
128  return 0;
129  }
130 
131  return 1;
132 }
133 
134 int
135 smtp_step_send (const char *data)
136 {
137  char *buf;
138  int rc;
139  int len;
140 
142  len = asprintf (&buf, "334 %s", data);
143  else
144  len = asprintf (&buf, "%s", data);
145  if (len < 0)
146  return 0;
147  rc = writeln (buf);
148  free (buf);
149  if (!rc)
150  return 0;
151 
152  return 1;
153 }
154 
155 /* Return 1 on token, 2 on protocol success, 3 on protocol fail, 0 on
156  errors. */
157 int
158 smtp_step_recv (char **data)
159 {
160  char *p;
161 
162  if (!readln (data))
163  return 0;
164 
165  p = *data;
166 
167  if (strlen (p) <= 3)
168  return 0;
169 
170  if (strncmp (p, "334 ", 4) == 0)
171  {
172  memmove (&p[0], &p[4], strlen (p) - 3);
173 
174  if (p[strlen (p) - 1] == '\n')
175  p[strlen (p) - 1] = '\0';
176  if (p[strlen (p) - 1] == '\r')
177  p[strlen (p) - 1] = '\0';
178 
179  return 1;
180  }
181 
182  if (strncmp (p, "235 ", 4) == 0)
183  {
184  /* Never a token here, we don't support additional server
185  information on success. */
186  return 2;
187  }
188 
189  if (strncmp (p, "535 ", 4) == 0)
190  return 3;
191 
192  fprintf (stderr, _("error: could not parse server data:\n%s\n"), p);
193 
194  return 0;
195 }
196 
197 int
199 {
200  char *in;
201 
202  if (!writeln ("QUIT"))
203  return 0;
204 
205  /* read "221 2.0.0 foo closing ..." */
206  if (!readln (&in))
207  return 0;
208 
209  free (in);
210 
211  return 1;
212 }
#define _
Definition: arpa_inet.in.h:50
int asprintf(char **resultp, const char *format,...)
Definition: asprintf.c:30
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 rc
Definition: error.c:42
const char * p
Definition: mbrtowc-impl.h:42
char buf[4]
Definition: mbrtowc-impl.h:39
#define TLSGREETING
int smtp_has_starttls(void)
Definition: smtp.c:35
int smtp_step_send(const char *data)
Definition: smtp.c:135
int smtp_step_recv(char **data)
Definition: smtp.c:158
#define GREETING2
#define GREETING1
int smtp_greeting(void)
Definition: smtp.c:24
int smtp_starttls(void)
Definition: smtp.c:58
int smtp_select_mechanism(char **mechlist)
Definition: smtp.c:72
int smtp_authenticate(const char *mech)
Definition: smtp.c:108
int smtp_logout(void)
Definition: smtp.c:198
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