Implement SMTP AUTH (via GSASL).
* configure.ac (MU_COND_GSASL): New cond. * include/mailutils/smtp.h (MU_SMTP_PARAM_DOMAIN) (MU_SMTP_PARAM_USERNAME, MU_SMTP_PARAM_PASSWORD) (MU_SMTP_PARAM_SERVICE, MU_SMTP_PARAM_REALM) (MU_SMTP_PARAM_HOST, MU_SMTP_MAX_PARAM): New constants. (mu_smtp_set_domain, mu_smtp_get_param): Remove. (mu_smtp_set_param, mu_smtp_get_param): New prototypes. (mu_smtp_auth, mu_smtp_add_auth_mech) (mu_smtp_add_auth_mech_list, mu_smtp_mech_select): New prototypes. * include/mailutils/sys/smtp.h (_mu_smtp) <domain>: Remove. (_mu_smtp) <authimpl, param, authmech>: New members. (_mu_smtp_gsasl_auth, _mu_smtp_mech_impl): New prototypes. * libproto/mailer/Makefile.am [MU_COND_GSASL]: Define SMTP_GSASL. (libmu_mailer_la_SOURCES): Add new sources. * libproto/mailer/smtp_domain.c: Remove. * libproto/mailer/smtp_param.c: New file. * libproto/mailer/smtp_mech.c: New file. * libproto/mailer/smtp_auth.c: New file. * libproto/mailer/smtp_gsasl.c: New file. * libproto/mailer/smtp_create.c (mu_smtp_destroy): Free new members of struct _mu_smtp. * libproto/mailer/smtp_ehlo.c (mu_smtp_ehlo): Use param[MU_SMTP_PARAM_DOMAIN] instead of domain. * testsuite/smtpsend.c: Handle SMTP AUTH. * libmu_auth/gsasl.c (mu_gsasl_stream_create): Bugfix. * libmailutils/xscript-stream.c (_xscript_ctl) <MU_IOCTL_SWAP_STREAM>: If instream!=outstream, combine them first into an iostream.
Showing
15 changed files
with
681 additions
and
36 deletions
... | @@ -287,6 +287,7 @@ MU_CHECK_GSASL(0.2.3, [ | ... | @@ -287,6 +287,7 @@ MU_CHECK_GSASL(0.2.3, [ |
287 | MU_AUTHLIBS="$MU_AUTHLIBS $GSASL_LIBS" | 287 | MU_AUTHLIBS="$MU_AUTHLIBS $GSASL_LIBS" |
288 | IMAP_AUTHOBJS="$IMAP_AUTHOBJS auth_gsasl.o" | 288 | IMAP_AUTHOBJS="$IMAP_AUTHOBJS auth_gsasl.o" |
289 | status_gsasl=yes]) | 289 | status_gsasl=yes]) |
290 | AM_CONDITIONAL([MU_COND_GSASL],[test "$status_gsasl" = "yes"]) | ||
290 | 291 | ||
291 | AC_SUBST(SITE_CRAM_MD5_PWD,"\$(sysconfdir)/cram-md5.pwd") | 292 | AC_SUBST(SITE_CRAM_MD5_PWD,"\$(sysconfdir)/cram-md5.pwd") |
292 | 293 | ... | ... |
... | @@ -23,6 +23,18 @@ | ... | @@ -23,6 +23,18 @@ |
23 | 23 | ||
24 | typedef struct _mu_smtp *mu_smtp_t; | 24 | typedef struct _mu_smtp *mu_smtp_t; |
25 | 25 | ||
26 | enum | ||
27 | { | ||
28 | MU_SMTP_PARAM_DOMAIN, | ||
29 | MU_SMTP_PARAM_USERNAME, | ||
30 | MU_SMTP_PARAM_PASSWORD, | ||
31 | MU_SMTP_PARAM_SERVICE, | ||
32 | MU_SMTP_PARAM_REALM, | ||
33 | MU_SMTP_PARAM_HOST | ||
34 | }; | ||
35 | |||
36 | #define MU_SMTP_MAX_PARAM (MU_SMTP_PARAM_HOST+1) | ||
37 | |||
26 | int mu_smtp_create (mu_smtp_t *); | 38 | int mu_smtp_create (mu_smtp_t *); |
27 | void mu_smtp_destroy (mu_smtp_t *); | 39 | void mu_smtp_destroy (mu_smtp_t *); |
28 | int mu_smtp_set_carrier (mu_smtp_t smtp, mu_stream_t str); | 40 | int mu_smtp_set_carrier (mu_smtp_t smtp, mu_stream_t str); |
... | @@ -40,8 +52,8 @@ int mu_smtp_trace_mask (mu_smtp_t smtp, int op, int lev); | ... | @@ -40,8 +52,8 @@ int mu_smtp_trace_mask (mu_smtp_t smtp, int op, int lev); |
40 | 52 | ||
41 | int mu_smtp_disconnect (mu_smtp_t smtp); | 53 | int mu_smtp_disconnect (mu_smtp_t smtp); |
42 | int mu_smtp_ehlo (mu_smtp_t smtp); | 54 | int mu_smtp_ehlo (mu_smtp_t smtp); |
43 | int mu_smtp_set_domain (mu_smtp_t smtp, const char *newdom); | 55 | int mu_smtp_set_param (mu_smtp_t smtp, int code, const char *val); |
44 | int mu_smtp_get_domain (mu_smtp_t smtp, const char **pdom); | 56 | int mu_smtp_get_param (mu_smtp_t smtp, int code, const char **param); |
45 | int mu_smtp_capa_test (mu_smtp_t smtp, const char *capa, const char **pret); | 57 | int mu_smtp_capa_test (mu_smtp_t smtp, const char *capa, const char **pret); |
46 | int mu_smtp_starttls (mu_smtp_t smtp); | 58 | int mu_smtp_starttls (mu_smtp_t smtp); |
47 | 59 | ||
... | @@ -51,4 +63,11 @@ int mu_smtp_send_stream (mu_smtp_t smtp, mu_stream_t str); | ... | @@ -51,4 +63,11 @@ int mu_smtp_send_stream (mu_smtp_t smtp, mu_stream_t str); |
51 | int mu_smtp_rset (mu_smtp_t smtp); | 63 | int mu_smtp_rset (mu_smtp_t smtp); |
52 | int mu_smtp_quit (mu_smtp_t smtp); | 64 | int mu_smtp_quit (mu_smtp_t smtp); |
53 | 65 | ||
66 | int mu_smtp_auth (mu_smtp_t smtp); | ||
67 | |||
68 | int mu_smtp_add_auth_mech (mu_smtp_t smtp, const char *mech); | ||
69 | int mu_smtp_clear_auth_mech (mu_smtp_t smtp); | ||
70 | int mu_smtp_add_auth_mech_list (mu_smtp_t smtp, mu_list_t list); | ||
71 | int mu_smtp_mech_select (mu_smtp_t smtp, const char **pmech); | ||
72 | |||
54 | #endif | 73 | #endif | ... | ... |
... | @@ -46,11 +46,17 @@ enum mu_smtp_state | ... | @@ -46,11 +46,17 @@ enum mu_smtp_state |
46 | struct _mu_smtp | 46 | struct _mu_smtp |
47 | { | 47 | { |
48 | int flags; | 48 | int flags; |
49 | char *domain; | 49 | |
50 | mu_stream_t carrier; | 50 | mu_stream_t carrier; |
51 | enum mu_smtp_state state; | 51 | enum mu_smtp_state state; |
52 | mu_list_t capa; | 52 | mu_list_t capa; |
53 | 53 | mu_list_t authimpl; /* List of implemented authentication mechs */ | |
54 | |||
55 | /* User-supplied data */ | ||
56 | char *param[MU_SMTP_MAX_PARAM]; | ||
57 | mu_list_t authmech; /* List of allowed authentication mechs */ | ||
58 | |||
59 | /* I/O buffers */ | ||
54 | char replcode[4]; | 60 | char replcode[4]; |
55 | char *replptr; | 61 | char *replptr; |
56 | 62 | ||
... | @@ -81,5 +87,7 @@ struct _mu_smtp | ... | @@ -81,5 +87,7 @@ struct _mu_smtp |
81 | int _mu_smtp_trace_enable (mu_smtp_t smtp); | 87 | int _mu_smtp_trace_enable (mu_smtp_t smtp); |
82 | int _mu_smtp_trace_disable (mu_smtp_t smtp); | 88 | int _mu_smtp_trace_disable (mu_smtp_t smtp); |
83 | int _mu_smtp_xscript_level (mu_smtp_t smtp, int xlev); | 89 | int _mu_smtp_xscript_level (mu_smtp_t smtp, int xlev); |
90 | int _mu_smtp_gsasl_auth (mu_smtp_t smtp); | ||
91 | int _mu_smtp_mech_impl (mu_smtp_t smtp, mu_list_t list); | ||
84 | 92 | ||
85 | #endif | 93 | #endif | ... | ... |
... | @@ -292,11 +292,17 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg) | ... | @@ -292,11 +292,17 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg) |
292 | mu_stream_t tmp; | 292 | mu_stream_t tmp; |
293 | 293 | ||
294 | if (pstr[0] != pstr[1]) | 294 | if (pstr[0] != pstr[1]) |
295 | return EINVAL; /* FIXME */ | 295 | { |
296 | tmp = pstr[0]; | 296 | status = mu_iostream_create (&tmp, pstr[0], pstr[1]); |
297 | if (status) | ||
298 | return status; | ||
299 | } | ||
300 | else | ||
301 | tmp = pstr[0]; | ||
297 | pstr[0] = sp->transport; | 302 | pstr[0] = sp->transport; |
298 | pstr[1] = sp->transport; | 303 | pstr[1] = sp->transport; |
299 | sp->transport = tmp; | 304 | sp->transport = tmp; |
305 | /* FIXME */ | ||
300 | if (!(str->flags & MU_STREAM_AUTOCLOSE)) | 306 | if (!(str->flags & MU_STREAM_AUTOCLOSE)) |
301 | { | 307 | { |
302 | if (pstr[0]) | 308 | if (pstr[0]) | ... | ... |
... | @@ -206,7 +206,7 @@ mu_gsasl_stream_create (mu_stream_t *stream, mu_stream_t transport, | ... | @@ -206,7 +206,7 @@ mu_gsasl_stream_create (mu_stream_t *stream, mu_stream_t transport, |
206 | rc = gsasl_encoder_stream (&in, transport, ctx, MU_STREAM_READ); | 206 | rc = gsasl_encoder_stream (&in, transport, ctx, MU_STREAM_READ); |
207 | if (rc) | 207 | if (rc) |
208 | return rc; | 208 | return rc; |
209 | rc = gsasl_encoder_stream (&out, transport, ctx, MU_STREAM_WRITE); | 209 | rc = gsasl_decoder_stream (&out, transport, ctx, MU_STREAM_WRITE); |
210 | if (rc) | 210 | if (rc) |
211 | { | 211 | { |
212 | mu_stream_destroy (&in); | 212 | mu_stream_destroy (&in); | ... | ... |
... | @@ -23,22 +23,30 @@ lib_LTLIBRARIES = libmu_mailer.la | ... | @@ -23,22 +23,30 @@ lib_LTLIBRARIES = libmu_mailer.la |
23 | libmu_mailer_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@ | 23 | libmu_mailer_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@ |
24 | libmu_mailer_la_LIBADD = ${MU_LIB_AUTH} ${MU_LIB_MAILUTILS} @INTLLIBS@ | 24 | libmu_mailer_la_LIBADD = ${MU_LIB_AUTH} ${MU_LIB_MAILUTILS} @INTLLIBS@ |
25 | 25 | ||
26 | if MU_COND_GSASL | ||
27 | SMTP_GSASL=smtp_gsasl.c | ||
28 | endif | ||
29 | EXTRA_DIST=smtp_gsasl.c | ||
30 | |||
26 | libmu_mailer_la_SOURCES = \ | 31 | libmu_mailer_la_SOURCES = \ |
27 | mbox.c\ | 32 | mbox.c\ |
28 | prog.c\ | 33 | prog.c\ |
29 | sendmail.c\ | 34 | sendmail.c\ |
30 | smtp.c\ | 35 | smtp.c\ |
36 | smtp_auth.c\ | ||
31 | smtp_capa.c\ | 37 | smtp_capa.c\ |
32 | smtp_carrier.c\ | 38 | smtp_carrier.c\ |
33 | smtp_create.c\ | 39 | smtp_create.c\ |
34 | smtp_data.c\ | 40 | smtp_data.c\ |
35 | smtp_disconnect.c\ | 41 | smtp_disconnect.c\ |
36 | smtp_domain.c\ | ||
37 | smtp_ehlo.c\ | 42 | smtp_ehlo.c\ |
43 | $(SMTP_GSASL)\ | ||
38 | smtp_io.c\ | 44 | smtp_io.c\ |
39 | smtp_mail.c\ | 45 | smtp_mail.c\ |
40 | smtp_rcpt.c\ | 46 | smtp_mech.c\ |
41 | smtp_open.c\ | 47 | smtp_open.c\ |
48 | smtp_param.c\ | ||
49 | smtp_rcpt.c\ | ||
42 | smtp_rset.c\ | 50 | smtp_rset.c\ |
43 | smtp_starttls.c\ | 51 | smtp_starttls.c\ |
44 | smtp_trace.c\ | 52 | smtp_trace.c\ | ... | ... |
libproto/mailer/smtp_auth.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | |||
21 | #include <errno.h> | ||
22 | #include <mailutils/errno.h> | ||
23 | #include <mailutils/smtp.h> | ||
24 | #include <mailutils/sys/smtp.h> | ||
25 | |||
26 | int | ||
27 | mu_smtp_auth (mu_smtp_t smtp) | ||
28 | { | ||
29 | if (!smtp) | ||
30 | return EINVAL; | ||
31 | if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR)) | ||
32 | return MU_ERR_FAILURE; | ||
33 | if (MU_SMTP_FISSET (smtp, _MU_SMTP_AUTH)) | ||
34 | return MU_ERR_SEQ; | ||
35 | if (smtp->state != MU_SMTP_MAIL) | ||
36 | return MU_ERR_SEQ; | ||
37 | |||
38 | #if defined(WITH_GSASL) | ||
39 | return _mu_smtp_gsasl_auth (smtp); | ||
40 | #else | ||
41 | /* FIXME: Provide support for some basic authentication methods */ | ||
42 | return ENOSYS; | ||
43 | #endif | ||
44 | } |
... | @@ -45,6 +45,7 @@ mu_smtp_create (mu_smtp_t *psmtp) | ... | @@ -45,6 +45,7 @@ mu_smtp_create (mu_smtp_t *psmtp) |
45 | void | 45 | void |
46 | mu_smtp_destroy (mu_smtp_t *psmtp) | 46 | mu_smtp_destroy (mu_smtp_t *psmtp) |
47 | { | 47 | { |
48 | int i; | ||
48 | struct _mu_smtp *smtp; | 49 | struct _mu_smtp *smtp; |
49 | 50 | ||
50 | if (!psmtp || !*psmtp) | 51 | if (!psmtp || !*psmtp) |
... | @@ -52,9 +53,15 @@ mu_smtp_destroy (mu_smtp_t *psmtp) | ... | @@ -52,9 +53,15 @@ mu_smtp_destroy (mu_smtp_t *psmtp) |
52 | smtp = *psmtp; | 53 | smtp = *psmtp; |
53 | mu_stream_destroy (&smtp->carrier); | 54 | mu_stream_destroy (&smtp->carrier); |
54 | mu_list_destroy (&smtp->capa); | 55 | mu_list_destroy (&smtp->capa); |
56 | mu_list_destroy (&smtp->authimpl); | ||
55 | free (smtp->rdbuf); | 57 | free (smtp->rdbuf); |
56 | free (smtp->flbuf); | 58 | free (smtp->flbuf); |
57 | mu_list_destroy (&smtp->mlrepl); | 59 | mu_list_destroy (&smtp->mlrepl); |
60 | |||
61 | mu_list_destroy (&smtp->authmech); | ||
62 | for (i = 0; i < MU_SMTP_MAX_PARAM; i++) | ||
63 | free (smtp->param[i]); | ||
64 | |||
58 | free (smtp); | 65 | free (smtp); |
59 | *psmtp = NULL; | 66 | *psmtp = NULL; |
60 | } | 67 | } | ... | ... |
... | @@ -53,7 +53,7 @@ mu_smtp_ehlo (mu_smtp_t smtp) | ... | @@ -53,7 +53,7 @@ mu_smtp_ehlo (mu_smtp_t smtp) |
53 | if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR)) | 53 | if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR)) |
54 | return MU_ERR_FAILURE; | 54 | return MU_ERR_FAILURE; |
55 | 55 | ||
56 | if (!smtp->domain) | 56 | if (!smtp->param[MU_SMTP_PARAM_DOMAIN]) |
57 | { | 57 | { |
58 | char *host; | 58 | char *host; |
59 | char *p; | 59 | char *p; |
... | @@ -65,11 +65,12 @@ mu_smtp_ehlo (mu_smtp_t smtp) | ... | @@ -65,11 +65,12 @@ mu_smtp_ehlo (mu_smtp_t smtp) |
65 | p++; | 65 | p++; |
66 | else | 66 | else |
67 | p = host; | 67 | p = host; |
68 | status = mu_smtp_set_domain (smtp, p); | 68 | status = mu_smtp_set_param (smtp, MU_SMTP_PARAM_DOMAIN, p); |
69 | MU_SMTP_CHECK_ERROR (smtp, status); | 69 | MU_SMTP_CHECK_ERROR (smtp, status); |
70 | } | 70 | } |
71 | 71 | ||
72 | status = mu_smtp_write (smtp, "EHLO %s\r\n", smtp->domain); | 72 | status = mu_smtp_write (smtp, "EHLO %s\r\n", |
73 | smtp->param[MU_SMTP_PARAM_DOMAIN]); | ||
73 | MU_SMTP_CHECK_ERROR (smtp, status); | 74 | MU_SMTP_CHECK_ERROR (smtp, status); |
74 | status = mu_smtp_response (smtp); | 75 | status = mu_smtp_response (smtp); |
75 | MU_SMTP_CHECK_ERROR (smtp, status); | 76 | MU_SMTP_CHECK_ERROR (smtp, status); |
... | @@ -84,7 +85,8 @@ mu_smtp_ehlo (mu_smtp_t smtp) | ... | @@ -84,7 +85,8 @@ mu_smtp_ehlo (mu_smtp_t smtp) |
84 | return MU_ERR_REPLY; | 85 | return MU_ERR_REPLY; |
85 | else | 86 | else |
86 | { | 87 | { |
87 | status = mu_smtp_write (smtp, "HELO %s\r\n", smtp->domain); | 88 | status = mu_smtp_write (smtp, "HELO %s\r\n", |
89 | smtp->param[MU_SMTP_PARAM_DOMAIN]); | ||
88 | MU_SMTP_CHECK_ERROR (smtp, status); | 90 | MU_SMTP_CHECK_ERROR (smtp, status); |
89 | status = mu_smtp_response (smtp); | 91 | status = mu_smtp_response (smtp); |
90 | MU_SMTP_CHECK_ERROR (smtp, status); | 92 | MU_SMTP_CHECK_ERROR (smtp, status); | ... | ... |
libproto/mailer/smtp_gsasl.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | |||
21 | #include <errno.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | #include <mailutils/argcv.h> | ||
25 | #include <mailutils/diag.h> | ||
26 | #include <mailutils/errno.h> | ||
27 | #include <mailutils/cctype.h> | ||
28 | #include <mailutils/list.h> | ||
29 | #include <mailutils/mutil.h> | ||
30 | #include <mailutils/smtp.h> | ||
31 | #include <mailutils/stream.h> | ||
32 | #include <mailutils/sys/smtp.h> | ||
33 | #include <mailutils/gsasl.h> | ||
34 | #include <gsasl.h> | ||
35 | |||
36 | static int | ||
37 | get_implemented_mechs (Gsasl *ctx, mu_list_t *plist) | ||
38 | { | ||
39 | char *listmech; | ||
40 | mu_list_t supp = NULL; | ||
41 | int rc; | ||
42 | int mechc; | ||
43 | char **mechv; | ||
44 | |||
45 | rc = gsasl_server_mechlist (ctx, &listmech); | ||
46 | if (rc != GSASL_OK) | ||
47 | { | ||
48 | mu_diag_output (MU_DIAG_ERROR, | ||
49 | "cannot get list of available SASL mechanisms: %s", | ||
50 | gsasl_strerror (rc)); | ||
51 | return 1; | ||
52 | } | ||
53 | |||
54 | rc = mu_argcv_get (listmech, "", NULL, &mechc, &mechv); | ||
55 | if (rc == 0) | ||
56 | { | ||
57 | int i; | ||
58 | |||
59 | rc = mu_list_create (&supp); | ||
60 | if (rc == 0) | ||
61 | { | ||
62 | mu_list_set_destroy_item (supp, mu_list_free_item); | ||
63 | for (i = 0; i < mechc; i++) | ||
64 | mu_list_append (supp, mechv[i]); | ||
65 | } | ||
66 | free (mechv); | ||
67 | } | ||
68 | free (listmech); | ||
69 | *plist = supp; | ||
70 | return rc; | ||
71 | } | ||
72 | |||
73 | static int | ||
74 | _smtp_callback (Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop) | ||
75 | { | ||
76 | int rc = GSASL_OK; | ||
77 | mu_smtp_t smtp = gsasl_callback_hook_get (ctx); | ||
78 | char *p; | ||
79 | |||
80 | switch (prop) | ||
81 | { | ||
82 | case GSASL_PASSWORD: | ||
83 | gsasl_property_set (sctx, prop, smtp->param[MU_SMTP_PARAM_PASSWORD]); | ||
84 | break; | ||
85 | |||
86 | case GSASL_AUTHID: | ||
87 | case GSASL_ANONYMOUS_TOKEN: | ||
88 | gsasl_property_set (sctx, prop, smtp->param[MU_SMTP_PARAM_USERNAME]); | ||
89 | break; | ||
90 | |||
91 | case GSASL_AUTHZID: | ||
92 | gsasl_property_set (sctx, prop, NULL); | ||
93 | break; | ||
94 | |||
95 | case GSASL_SERVICE: | ||
96 | gsasl_property_set (sctx, prop, | ||
97 | smtp->param[MU_SMTP_PARAM_SERVICE] ? | ||
98 | smtp->param[MU_SMTP_PARAM_SERVICE] : "smtp"); | ||
99 | break; | ||
100 | |||
101 | case GSASL_REALM: | ||
102 | p = smtp->param[MU_SMTP_PARAM_REALM] ? | ||
103 | smtp->param[MU_SMTP_PARAM_REALM] : | ||
104 | smtp->param[MU_SMTP_PARAM_DOMAIN]; | ||
105 | |||
106 | if (!p) | ||
107 | rc = GSASL_NO_HOSTNAME; | ||
108 | else | ||
109 | gsasl_property_set (sctx, prop, p); | ||
110 | break; | ||
111 | |||
112 | case GSASL_HOSTNAME: | ||
113 | if (smtp->param[MU_SMTP_PARAM_HOST]) | ||
114 | p = smtp->param[MU_SMTP_PARAM_HOST]; | ||
115 | else if (mu_get_host_name (&p)) | ||
116 | { | ||
117 | rc = GSASL_NO_HOSTNAME; | ||
118 | break; | ||
119 | } | ||
120 | else | ||
121 | gsasl_property_set (sctx, prop, p); | ||
122 | break; | ||
123 | |||
124 | default: | ||
125 | rc = GSASL_NO_CALLBACK; | ||
126 | mu_diag_output (MU_DIAG_NOTICE, | ||
127 | "unsupported callback property %d", prop); | ||
128 | break; | ||
129 | } | ||
130 | |||
131 | return rc; | ||
132 | } | ||
133 | |||
134 | static int | ||
135 | restore_and_return (mu_smtp_t smtp, mu_stream_t *str, int code) | ||
136 | { | ||
137 | int rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_SWAP_STREAM, str); | ||
138 | if (rc) | ||
139 | { | ||
140 | mu_error ("%s failed when it should not: %s", | ||
141 | "MU_IOCTL_SWAP_STREAM", | ||
142 | mu_stream_strerror (smtp->carrier, rc)); | ||
143 | abort (); | ||
144 | } | ||
145 | return code; | ||
146 | } | ||
147 | |||
148 | int | ||
149 | insert_gsasl_stream (mu_smtp_t smtp, Gsasl_session *sess_ctx) | ||
150 | { | ||
151 | mu_stream_t stream[2], newstream[2]; | ||
152 | int rc; | ||
153 | |||
154 | stream[0] = stream[1] = NULL; | ||
155 | rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_SWAP_STREAM, stream); | ||
156 | if (rc) | ||
157 | { | ||
158 | mu_error ("%s failed: %s", "MU_IOCTL_SWAP_STREAM", | ||
159 | mu_stream_strerror (smtp->carrier, rc)); | ||
160 | return MU_ERR_FAILURE; | ||
161 | } | ||
162 | |||
163 | rc = gsasl_encoder_stream (&newstream[0], stream[0], sess_ctx, | ||
164 | MU_STREAM_READ); | ||
165 | if (rc) | ||
166 | { | ||
167 | mu_error ("%s failed: %s", "gsasl_encoder_stream", | ||
168 | mu_strerror (rc)); | ||
169 | return restore_and_return (smtp, stream, MU_ERR_FAILURE); | ||
170 | } | ||
171 | |||
172 | rc = gsasl_decoder_stream (&newstream[1], stream[1], sess_ctx, | ||
173 | MU_STREAM_WRITE); | ||
174 | if (rc) | ||
175 | { | ||
176 | mu_error ("%s failed: %s", "gsasl_decoder_stream", | ||
177 | mu_strerror (rc)); | ||
178 | mu_stream_destroy (&newstream[0]); | ||
179 | return restore_and_return (smtp, stream, MU_ERR_FAILURE); | ||
180 | } | ||
181 | |||
182 | mu_stream_flush (stream[1]); | ||
183 | |||
184 | rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_SWAP_STREAM, newstream); | ||
185 | if (rc) | ||
186 | { | ||
187 | mu_error ("%s failed when it should not: %s", | ||
188 | "MU_IOCTL_SWAP_STREAM", | ||
189 | mu_stream_strerror (smtp->carrier, rc)); | ||
190 | abort (); | ||
191 | } | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int | ||
197 | do_gsasl_auth (mu_smtp_t smtp, Gsasl *ctx, const char *mech) | ||
198 | { | ||
199 | Gsasl_session *sess; | ||
200 | int rc, status; | ||
201 | char *output = NULL; | ||
202 | |||
203 | rc = gsasl_client_start (ctx, mech, &sess); | ||
204 | if (rc != GSASL_OK) | ||
205 | { | ||
206 | mu_diag_output (MU_DIAG_ERROR, "SASL gsasl_client_start: %s", | ||
207 | gsasl_strerror (rc)); | ||
208 | return MU_ERR_FAILURE; | ||
209 | } | ||
210 | |||
211 | status = mu_smtp_write (smtp, "AUTH %s\r\n", mech); | ||
212 | MU_SMTP_CHECK_ERROR (smtp, rc); | ||
213 | |||
214 | status = mu_smtp_response (smtp); | ||
215 | MU_SMTP_CHECK_ERROR (smtp, status); | ||
216 | if (smtp->replcode[0] != '3') | ||
217 | { | ||
218 | mu_diag_output (MU_DIAG_ERROR, | ||
219 | "GSASL handshake aborted: " | ||
220 | "unexpected reply: %s %s", | ||
221 | smtp->replcode, smtp->replptr); | ||
222 | return MU_ERR_REPLY; | ||
223 | } | ||
224 | |||
225 | do | ||
226 | { | ||
227 | rc = gsasl_step64 (sess, smtp->replptr, &output); | ||
228 | if (rc != GSASL_NEEDS_MORE && rc != GSASL_OK) | ||
229 | break; | ||
230 | |||
231 | status = mu_smtp_write (smtp, "%s\r\n", output); | ||
232 | MU_SMTP_CHECK_ERROR (smtp, status); | ||
233 | |||
234 | free (output); | ||
235 | output = NULL; | ||
236 | |||
237 | status = mu_smtp_response (smtp); | ||
238 | MU_SMTP_CHECK_ERROR (smtp, status); | ||
239 | if (smtp->replcode[0] == '2') | ||
240 | { | ||
241 | rc = GSASL_OK; | ||
242 | break; | ||
243 | } | ||
244 | else if (smtp->replcode[0] != '3') | ||
245 | break; | ||
246 | } while (rc == GSASL_NEEDS_MORE); | ||
247 | |||
248 | if (output) | ||
249 | free (output); | ||
250 | |||
251 | if (rc != GSASL_OK) | ||
252 | { | ||
253 | mu_diag_output (MU_DIAG_ERROR, "GSASL error: %s", gsasl_strerror (rc)); | ||
254 | return 1; | ||
255 | } | ||
256 | |||
257 | if (smtp->replcode[0] != '2') | ||
258 | { | ||
259 | mu_diag_output (MU_DIAG_ERROR, | ||
260 | "GSASL handshake failed: %s %s", | ||
261 | smtp->replcode, smtp->replptr); | ||
262 | return MU_ERR_REPLY; | ||
263 | } | ||
264 | |||
265 | /* Authentication successful */ | ||
266 | MU_SMTP_FSET (smtp, _MU_SMTP_AUTH); | ||
267 | |||
268 | return insert_gsasl_stream (smtp, sess); | ||
269 | } | ||
270 | |||
271 | int | ||
272 | _mu_smtp_gsasl_auth (mu_smtp_t smtp) | ||
273 | { | ||
274 | int rc; | ||
275 | Gsasl *ctx; | ||
276 | mu_list_t mech_list; | ||
277 | const char *mech; | ||
278 | |||
279 | rc = gsasl_init (&ctx); | ||
280 | if (rc != GSASL_OK) | ||
281 | { | ||
282 | mu_diag_output (MU_DIAG_ERROR, | ||
283 | "cannot initialize GSASL: %s", | ||
284 | gsasl_strerror (rc)); | ||
285 | return MU_ERR_FAILURE; | ||
286 | } | ||
287 | rc = get_implemented_mechs (ctx, &mech_list); | ||
288 | if (rc) | ||
289 | return rc; | ||
290 | rc = _mu_smtp_mech_impl (smtp, mech_list); | ||
291 | if (rc) | ||
292 | { | ||
293 | mu_list_destroy (&mech_list); | ||
294 | return rc; | ||
295 | } | ||
296 | |||
297 | rc = mu_smtp_mech_select (smtp, &mech); | ||
298 | if (rc) | ||
299 | { | ||
300 | mu_diag_output (MU_DIAG_DEBUG, | ||
301 | "no suitable authentication mechanism found"); | ||
302 | return rc; | ||
303 | } | ||
304 | |||
305 | mu_diag_output (MU_DIAG_DEBUG, "selected authentication mechanism %s", | ||
306 | mech); | ||
307 | |||
308 | gsasl_callback_hook_set (ctx, smtp); | ||
309 | gsasl_callback_set (ctx, _smtp_callback); | ||
310 | |||
311 | rc = do_gsasl_auth (smtp, ctx, mech); | ||
312 | if (rc == 0) | ||
313 | { | ||
314 | /* Invalidate the capability list */ | ||
315 | mu_list_destroy (&smtp->capa); | ||
316 | } | ||
317 | |||
318 | return rc; | ||
319 | } |
libproto/mailer/smtp_mech.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | |||
21 | #include <errno.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | #include <mailutils/errno.h> | ||
25 | #include <mailutils/cctype.h> | ||
26 | #include <mailutils/cstr.h> | ||
27 | #include <mailutils/list.h> | ||
28 | #include <mailutils/iterator.h> | ||
29 | #include <mailutils/mutil.h> | ||
30 | #include <mailutils/smtp.h> | ||
31 | #include <mailutils/sys/smtp.h> | ||
32 | |||
33 | static int | ||
34 | _mech_comp (const void *item, const void *data) | ||
35 | { | ||
36 | return mu_c_strcasecmp ((const char*)item, (const char*)data); | ||
37 | } | ||
38 | |||
39 | int | ||
40 | mu_smtp_add_auth_mech (mu_smtp_t smtp, const char *mech) | ||
41 | { | ||
42 | char *p; | ||
43 | |||
44 | if (!smtp) | ||
45 | return EINVAL; | ||
46 | if (!smtp->authmech) | ||
47 | { | ||
48 | int rc = mu_list_create (&smtp->authmech); | ||
49 | if (rc) | ||
50 | return rc; | ||
51 | mu_list_set_destroy_item (smtp->authmech, mu_list_free_item); | ||
52 | mu_list_set_comparator (smtp->authmech, _mech_comp); | ||
53 | } | ||
54 | p = strdup (mech); | ||
55 | if (!p) | ||
56 | return ENOMEM; | ||
57 | mu_strupper (p); | ||
58 | return mu_list_append (smtp->authmech, p); | ||
59 | } | ||
60 | |||
61 | int | ||
62 | mu_smtp_clear_auth_mech (mu_smtp_t smtp) | ||
63 | { | ||
64 | if (!smtp) | ||
65 | return EINVAL; | ||
66 | mu_list_clear (smtp->authmech); | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int | ||
71 | _mech_append (void *item, void *data) | ||
72 | { | ||
73 | mu_smtp_t smtp = data; | ||
74 | const char *mech = item; | ||
75 | return mu_smtp_add_auth_mech (smtp, mech); | ||
76 | } | ||
77 | |||
78 | int | ||
79 | mu_smtp_add_auth_mech_list (mu_smtp_t smtp, mu_list_t list) | ||
80 | { | ||
81 | if (!smtp) | ||
82 | return EINVAL; | ||
83 | return mu_list_do (list, _mech_append, smtp); | ||
84 | } | ||
85 | |||
86 | /* Set a list of implemented authentication mechanisms */ | ||
87 | int | ||
88 | _mu_smtp_mech_impl (mu_smtp_t smtp, mu_list_t list) | ||
89 | { | ||
90 | mu_list_destroy (&smtp->authimpl); | ||
91 | smtp->authimpl = list; | ||
92 | mu_list_set_comparator (smtp->authimpl, _mech_comp); | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | |||
97 | static int | ||
98 | _mech_copy (void *item, void *data) | ||
99 | { | ||
100 | const char *mech = item; | ||
101 | mu_list_t list = data; | ||
102 | return mu_list_append (list, (void *)mech); | ||
103 | } | ||
104 | |||
105 | /* Select authentication mechanism to use */ | ||
106 | int | ||
107 | mu_smtp_mech_select (mu_smtp_t smtp, const char **pmech) | ||
108 | { | ||
109 | int rc; | ||
110 | const char *authstr; | ||
111 | mu_list_t alist; | ||
112 | mu_iterator_t itr; | ||
113 | |||
114 | if (!smtp) | ||
115 | return EINVAL; | ||
116 | |||
117 | /* Obtain the list of mechanisms supported by the server */ | ||
118 | rc = mu_smtp_capa_test (smtp, "AUTH", &authstr); | ||
119 | if (rc) | ||
120 | return rc; | ||
121 | |||
122 | /* Create an intersection of implemented and allowed mechanisms */ | ||
123 | if (!smtp->authimpl) | ||
124 | return MU_ERR_NOENT; /* obvious case */ | ||
125 | |||
126 | if (!smtp->authmech) | ||
127 | { | ||
128 | rc = mu_list_create (&alist); | ||
129 | if (rc == 0) | ||
130 | rc = mu_list_do (smtp->authimpl, _mech_copy, alist); | ||
131 | } | ||
132 | else | ||
133 | { | ||
134 | rc = mu_list_intersect_dup (&alist, smtp->authmech, smtp->authimpl, | ||
135 | NULL, NULL); | ||
136 | } | ||
137 | if (rc) | ||
138 | return rc; | ||
139 | |||
140 | /* Select first element from the intersection that occurs also in the | ||
141 | list of methods supported by the server */ | ||
142 | rc = mu_list_get_iterator (alist, &itr); | ||
143 | if (rc == 0) | ||
144 | { | ||
145 | const char *p; | ||
146 | int res = 1; | ||
147 | |||
148 | rc = MU_ERR_NOENT; | ||
149 | authstr += 5; /* "AUTH */ | ||
150 | for (mu_iterator_first (itr); rc && !mu_iterator_is_done (itr); | ||
151 | mu_iterator_next (itr)) | ||
152 | { | ||
153 | const char *mech; | ||
154 | mu_iterator_current (itr, (void**) &mech); | ||
155 | for (p = authstr; *p; ) | ||
156 | { | ||
157 | char *end; | ||
158 | |||
159 | p = mu_str_stripws ((char *)p); | ||
160 | end = mu_str_skip_class_comp (p, MU_CTYPE_SPACE); | ||
161 | |||
162 | res = mu_c_strncasecmp (mech, p, end - p); | ||
163 | if (res == 0) | ||
164 | { | ||
165 | *pmech = mech; | ||
166 | rc = 0; | ||
167 | break; | ||
168 | } | ||
169 | p = end; | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | |||
174 | /* cleanup and return */ | ||
175 | mu_list_destroy (&alist); | ||
176 | return rc; | ||
177 | } |
1 | |||
2 | /* GNU Mailutils -- a suite of utilities for electronic mail | 1 | /* GNU Mailutils -- a suite of utilities for electronic mail |
3 | Copyright (C) 2010 Free Software Foundation, Inc. | 2 | Copyright (C) 2010 Free Software Foundation, Inc. |
4 | 3 | ||
... | @@ -28,28 +27,32 @@ | ... | @@ -28,28 +27,32 @@ |
28 | #include <mailutils/smtp.h> | 27 | #include <mailutils/smtp.h> |
29 | #include <mailutils/sys/smtp.h> | 28 | #include <mailutils/sys/smtp.h> |
30 | 29 | ||
31 | int | 30 | int |
32 | mu_smtp_set_domain (mu_smtp_t smtp, const char *newdom) | 31 | mu_smtp_set_param (mu_smtp_t smtp, int pcode, const char *newparam) |
33 | { | 32 | { |
34 | char *dom; | 33 | char *param; |
35 | 34 | ||
36 | if (!smtp) | 35 | if (!smtp) |
37 | return EINVAL; | 36 | return EINVAL; |
38 | 37 | if (pcode < 0 || pcode >= MU_SMTP_MAX_PARAM) | |
39 | dom = strdup (newdom); | 38 | return EINVAL; |
40 | if (!dom) | 39 | |
40 | param = strdup (newparam); | ||
41 | if (!param) | ||
41 | return ENOMEM; | 42 | return ENOMEM; |
42 | free (smtp->domain); | 43 | free (smtp->param[pcode]); |
43 | smtp->domain = dom; | 44 | smtp->param[pcode] = param; |
44 | return 0; | 45 | return 0; |
45 | } | 46 | } |
46 | 47 | ||
47 | int | 48 | int |
48 | mu_smtp_get_domain (mu_smtp_t smtp, const char **pdom) | 49 | mu_smtp_get_param (mu_smtp_t smtp, int pcode, const char **pparam) |
49 | { | 50 | { |
50 | if (!smtp) | 51 | if (!smtp) |
51 | return EINVAL; | 52 | return EINVAL; |
52 | *pdom = smtp->domain; | 53 | if (pcode < 0 || pcode >= MU_SMTP_MAX_PARAM) |
54 | return EINVAL; | ||
55 | *pparam = smtp->param[pcode]; | ||
53 | return 0; | 56 | return 0; |
54 | } | 57 | } |
55 | 58 | ... | ... |
... | @@ -92,7 +92,7 @@ mu_smtp_starttls (mu_smtp_t smtp) | ... | @@ -92,7 +92,7 @@ mu_smtp_starttls (mu_smtp_t smtp) |
92 | mu_list_destroy (&smtp->capa); | 92 | mu_list_destroy (&smtp->capa); |
93 | return 0; | 93 | return 0; |
94 | #else | 94 | #else |
95 | return ENOTSUP; | 95 | return ENOSYS; |
96 | #endif | 96 | #endif |
97 | } | 97 | } |
98 | 98 | ... | ... |
... | @@ -25,7 +25,9 @@ | ... | @@ -25,7 +25,9 @@ |
25 | 25 | ||
26 | static char usage_text[] = | 26 | static char usage_text[] = |
27 | "usage: %s hostname [port=N] [trace=N] [tls=N] [from=STRING] [rcpt=STRING]\n" | 27 | "usage: %s hostname [port=N] [trace=N] [tls=N] [from=STRING] [rcpt=STRING]\n" |
28 | " [domain=STRING] input=FILE raw=N\n"; | 28 | " [domain=STRING] [user=STRING] [pass=STRING]\n" |
29 | " [service=STRING] [realm=STRING] [host=STRING]\n" | ||
30 | " [auth=method[,...]] [input=FILE] [raw=N]\n"; | ||
29 | 31 | ||
30 | static void | 32 | static void |
31 | usage () | 33 | usage () |
... | @@ -49,10 +51,8 @@ main (int argc, char **argv) | ... | @@ -49,10 +51,8 @@ main (int argc, char **argv) |
49 | { | 51 | { |
50 | int i; | 52 | int i; |
51 | char *host; | 53 | char *host; |
52 | char *domain = NULL; | ||
53 | char *infile = NULL; | 54 | char *infile = NULL; |
54 | int port = 25; | 55 | int port = 25; |
55 | int trace = 0; | ||
56 | int tls = 0; | 56 | int tls = 0; |
57 | int raw = 1; | 57 | int raw = 1; |
58 | int flags = 0; | 58 | int flags = 0; |
... | @@ -61,6 +61,7 @@ main (int argc, char **argv) | ... | @@ -61,6 +61,7 @@ main (int argc, char **argv) |
61 | mu_stream_t instr; | 61 | mu_stream_t instr; |
62 | char *from = NULL; | 62 | char *from = NULL; |
63 | mu_list_t rcpt_list = NULL; | 63 | mu_list_t rcpt_list = NULL; |
64 | mu_list_t meth_list = NULL; | ||
64 | 65 | ||
65 | mu_set_program_name (argv[0]); | 66 | mu_set_program_name (argv[0]); |
66 | #ifdef WITH_TLS | 67 | #ifdef WITH_TLS |
... | @@ -70,6 +71,8 @@ main (int argc, char **argv) | ... | @@ -70,6 +71,8 @@ main (int argc, char **argv) |
70 | if (argc < 2) | 71 | if (argc < 2) |
71 | usage (); | 72 | usage (); |
72 | 73 | ||
74 | MU_ASSERT (mu_smtp_create (&smtp)); | ||
75 | |||
73 | for (i = 1; i < argc; i++) | 76 | for (i = 1; i < argc; i++) |
74 | { | 77 | { |
75 | if (strncmp (argv[i], "port=", 5) == 0) | 78 | if (strncmp (argv[i], "port=", 5) == 0) |
... | @@ -82,11 +85,28 @@ main (int argc, char **argv) | ... | @@ -82,11 +85,28 @@ main (int argc, char **argv) |
82 | } | 85 | } |
83 | } | 86 | } |
84 | else if (strncmp (argv[i], "trace=", 6) == 0) | 87 | else if (strncmp (argv[i], "trace=", 6) == 0) |
85 | trace = atoi (argv[i] + 6); | 88 | mu_smtp_trace (smtp, atoi (argv[i] + 6) ? |
89 | MU_SMTP_TRACE_SET : MU_SMTP_TRACE_CLR); | ||
86 | else if (strncmp (argv[i], "tls=", 4) == 0) | 90 | else if (strncmp (argv[i], "tls=", 4) == 0) |
87 | tls = atoi (argv[i] + 4); | 91 | tls = atoi (argv[i] + 4); |
88 | else if (strncmp (argv[i], "domain=", 7) == 0) | 92 | else if (strncmp (argv[i], "domain=", 7) == 0) |
89 | domain = argv[i] + 7; | 93 | MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_DOMAIN, |
94 | argv[i] + 7)); | ||
95 | else if (strncmp (argv[i], "user=", 5) == 0) | ||
96 | MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_USERNAME, | ||
97 | argv[i] + 5)); | ||
98 | else if (strncmp (argv[i], "pass=", 5) == 0) | ||
99 | MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_PASSWORD, | ||
100 | argv[i] + 5)); | ||
101 | else if (strncmp (argv[i], "service=", 8) == 0) | ||
102 | MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_SERVICE, | ||
103 | argv[i] + 8)); | ||
104 | else if (strncmp (argv[i], "realm=", 6) == 0) | ||
105 | MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_REALM, | ||
106 | argv[i] + 6)); | ||
107 | else if (strncmp (argv[i], "host=", 5) == 0) | ||
108 | MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_HOST, | ||
109 | argv[i] + 5)); | ||
90 | else if (strncmp (argv[i], "infile=", 7) == 0) | 110 | else if (strncmp (argv[i], "infile=", 7) == 0) |
91 | infile = argv[i] + 7; | 111 | infile = argv[i] + 7; |
92 | else if (strncmp (argv[i], "raw=", 4) == 0) | 112 | else if (strncmp (argv[i], "raw=", 4) == 0) |
... | @@ -99,6 +119,22 @@ main (int argc, char **argv) | ... | @@ -99,6 +119,22 @@ main (int argc, char **argv) |
99 | } | 119 | } |
100 | else if (strncmp (argv[i], "from=", 5) == 0) | 120 | else if (strncmp (argv[i], "from=", 5) == 0) |
101 | from = argv[i] + 5; | 121 | from = argv[i] + 5; |
122 | else if (strncmp (argv[i], "auth=", 5) == 0) | ||
123 | { | ||
124 | int mc, j; | ||
125 | char **mv; | ||
126 | |||
127 | if (!meth_list) | ||
128 | MU_ASSERT (mu_list_create (&meth_list)); | ||
129 | |||
130 | MU_ASSERT (mu_argcv_get_np (argv[i] + 5, strlen (argv[i] + 5), | ||
131 | ",", NULL, | ||
132 | 0, | ||
133 | &mc, &mv, NULL)); | ||
134 | for (j = 0; j < mc; j++) | ||
135 | MU_ASSERT (mu_list_append (meth_list, mv[j])); | ||
136 | free (mv); | ||
137 | } | ||
102 | else | 138 | else |
103 | host = argv[i]; | 139 | host = argv[i]; |
104 | } | 140 | } |
... | @@ -116,18 +152,12 @@ main (int argc, char **argv) | ... | @@ -116,18 +152,12 @@ main (int argc, char **argv) |
116 | else | 152 | else |
117 | MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD, flags)); | 153 | MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD, flags)); |
118 | 154 | ||
119 | MU_ASSERT (mu_smtp_create (&smtp)); | ||
120 | |||
121 | host = argv[1]; | 155 | host = argv[1]; |
122 | MU_ASSERT (mu_tcp_stream_create (&stream, host, port, MU_STREAM_RDWR)); | 156 | MU_ASSERT (mu_tcp_stream_create (&stream, host, port, MU_STREAM_RDWR)); |
123 | MU_ASSERT (mu_stream_open (stream)); | 157 | MU_ASSERT (mu_stream_open (stream)); |
124 | mu_smtp_set_carrier (smtp, stream); | 158 | mu_smtp_set_carrier (smtp, stream); |
125 | //mu_stream_unref (stream); | 159 | //mu_stream_unref (stream); |
126 | 160 | ||
127 | if (trace) | ||
128 | mu_smtp_trace (smtp, MU_SMTP_TRACE_SET); | ||
129 | if (domain) | ||
130 | mu_smtp_set_domain (smtp, domain); | ||
131 | if (!from) | 161 | if (!from) |
132 | { | 162 | { |
133 | from = getenv ("USER"); | 163 | from = getenv ("USER"); |
... | @@ -153,6 +183,26 @@ main (int argc, char **argv) | ... | @@ -153,6 +183,26 @@ main (int argc, char **argv) |
153 | MU_ASSERT (mu_smtp_ehlo (smtp)); | 183 | MU_ASSERT (mu_smtp_ehlo (smtp)); |
154 | } | 184 | } |
155 | 185 | ||
186 | if (meth_list) | ||
187 | { | ||
188 | int status; | ||
189 | |||
190 | MU_ASSERT (mu_smtp_add_auth_mech_list (smtp, meth_list)); | ||
191 | status = mu_smtp_auth (smtp); | ||
192 | switch (status) | ||
193 | { | ||
194 | case 0: | ||
195 | case ENOSYS: | ||
196 | case MU_ERR_NOENT: | ||
197 | /* Ok, skip it */ | ||
198 | break; | ||
199 | |||
200 | default: | ||
201 | mu_error ("authentication failed: %s", mu_strerror (status)); | ||
202 | exit (1); | ||
203 | } | ||
204 | } | ||
205 | |||
156 | if (raw) | 206 | if (raw) |
157 | { | 207 | { |
158 | /* Raw sending mode: send from the stream directly */ | 208 | /* Raw sending mode: send from the stream directly */ | ... | ... |
-
Please register or sign in to post a comment