This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "GNU Mailutils".
http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=76163154c740039046a2e0ae4b4aa423707c5473 The branch, master has been updated via 76163154c740039046a2e0ae4b4aa423707c5473 (commit) via 652197d52141d5e5a4c8c8c39eeb6b72538ed8b2 (commit) from d72be105ae0d6bb538b3236466219a2f71538ecf (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 76163154c740039046a2e0ae4b4aa423707c5473 Author: Sergey Poznyakoff <g...@gnu.org.ua> Date: Sun Sep 19 23:56:35 2010 +0300 Improve authentication interface in SMTP client. * include/mailutils/smtp.h (MU_SMTP_PARAM_URL): New parameter code. * include/mailutils/sys/smtp.h (_MU_SMTP_CLNPASS): New flag. (_mu_smtp) <secret>: New member. * libproto/mailer/smtp_auth.c (get_ticket) (_mu_smtp_fixup_params): New static functions. (mu_smtp_auth): Call _mu_smtp_fixup_params to supply missing pararameters. * libproto/mailer/smtp_create.c (mu_smtp_destroy): Destroy secret. Take care to erase eventual plaintext representation of the password. * libproto/mailer/smtp_gsasl.c (_smtp_callback): Use mu_smtp_get_param to obtain parameters. * libproto/mailer/smtp_param.c (mu_smtp_set_param): Setting MU_SMTP_PARAM_PASSWORD updates secret. param[MU_SMTP_PARAM_PASSWORD] points (temporarly and on request only) to plaintext password. (mu_smtp_get_param): Likewise for retrieving password. * testsuite/smtpsend.c (main): New parameter url=. commit 652197d52141d5e5a4c8c8c39eeb6b72538ed8b2 Author: Sergey Poznyakoff <g...@gnu.org.ua> Date: Sun Sep 19 22:18:59 2010 +0300 Bugfixes. * libmu_auth/gsasl.c (_gsasl_encoder,_gsasl_decoder): Do not free flt. * include/mailutils/stream.h [__cplusplus]: Protect contents by extern "C". ----------------------------------------------------------------------- Summary of changes: include/mailutils/smtp.h | 5 +- include/mailutils/stream.h | 8 +++ include/mailutils/sys/smtp.h | 14 +++-- libmu_auth/gsasl.c | 2 - libproto/mailer/smtp_auth.c | 108 ++++++++++++++++++++++++++++++++++++++++- libproto/mailer/smtp_create.c | 14 +++++- libproto/mailer/smtp_gsasl.c | 34 +++++++------ libproto/mailer/smtp_param.c | 23 ++++++++- testsuite/smtpsend.c | 5 ++- 9 files changed, 184 insertions(+), 29 deletions(-) diff --git a/include/mailutils/smtp.h b/include/mailutils/smtp.h index 48b2f85..5b64c7f 100644 --- a/include/mailutils/smtp.h +++ b/include/mailutils/smtp.h @@ -30,10 +30,11 @@ enum MU_SMTP_PARAM_PASSWORD, MU_SMTP_PARAM_SERVICE, MU_SMTP_PARAM_REALM, - MU_SMTP_PARAM_HOST + MU_SMTP_PARAM_HOST, + MU_SMTP_PARAM_URL }; -#define MU_SMTP_MAX_PARAM (MU_SMTP_PARAM_HOST+1) +#define MU_SMTP_MAX_PARAM (MU_SMTP_PARAM_URL+1) int mu_smtp_create (mu_smtp_t *); void mu_smtp_destroy (mu_smtp_t *); diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h index 95b2790..cfd9bef 100644 --- a/include/mailutils/stream.h +++ b/include/mailutils/stream.h @@ -20,6 +20,10 @@ #include <mailutils/types.h> #include <stdarg.h> +#ifdef __cplusplus +extern "C" { +#endif + enum mu_buffer_type { mu_buffer_none, @@ -192,4 +196,8 @@ int mu_dbgstream_create(mu_stream_t *pref, mu_debug_t debug, int mu_rdcache_stream_create (mu_stream_t *pstream, mu_stream_t transport, int flags); +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/mailutils/sys/smtp.h b/include/mailutils/sys/smtp.h index e04ae4d..884c921 100644 --- a/include/mailutils/sys/smtp.h +++ b/include/mailutils/sys/smtp.h @@ -22,12 +22,13 @@ # include <mailutils/types.h> # include <mailutils/smtp.h> -# define _MU_SMTP_ESMTP 0x01 /* Connection supports ESMTP */ -# define _MU_SMTP_TRACE 0x02 /* Session trace required/enabled */ -# define _MU_SMTP_ERR 0x04 /* Object in error state */ -# define _MU_SMTP_MLREPL 0x08 /* Last reply was multi-line */ -# define _MU_SMTP_TLS 0x10 /* TLS initiated */ -# define _MU_SMTP_AUTH 0x20 /* Authorization passed */ +# define _MU_SMTP_ESMTP 0x01 /* Connection supports ESMTP */ +# define _MU_SMTP_TRACE 0x02 /* Session trace required/enabled */ +# define _MU_SMTP_ERR 0x04 /* Object in error state */ +# define _MU_SMTP_MLREPL 0x08 /* Last reply was multi-line */ +# define _MU_SMTP_TLS 0x10 /* TLS initiated */ +# define _MU_SMTP_AUTH 0x20 /* Authorization passed */ +# define _MU_SMTP_CLNPASS 0x40 /* Password has been de-obfuscated */ #define MU_SMTP_XSCRIPT_MASK(n) (0x100<<(n)) @@ -55,6 +56,7 @@ struct _mu_smtp /* User-supplied data */ char *param[MU_SMTP_MAX_PARAM]; mu_list_t authmech; /* List of allowed authentication mechs */ + mu_secret_t secret; /* I/O buffers */ char replcode[4]; diff --git a/libmu_auth/gsasl.c b/libmu_auth/gsasl.c index 53c6952..ddcc7d0 100644 --- a/libmu_auth/gsasl.c +++ b/libmu_auth/gsasl.c @@ -69,7 +69,6 @@ _gsasl_encoder (void *xdata, case mu_filter_done: if (flt->bufptr) free (flt->bufptr); - free (flt); return mu_filter_ok; default: @@ -122,7 +121,6 @@ _gsasl_decoder (void *xdata, case mu_filter_done: if (flt->bufptr) free (flt->bufptr); - free (flt); return mu_filter_ok; default: diff --git a/libproto/mailer/smtp_auth.c b/libproto/mailer/smtp_auth.c index b0fccec..364f033 100644 --- a/libproto/mailer/smtp_auth.c +++ b/libproto/mailer/smtp_auth.c @@ -19,9 +19,103 @@ #endif #include <errno.h> +#include <stdlib.h> +#include <mailutils/diag.h> #include <mailutils/errno.h> #include <mailutils/smtp.h> #include <mailutils/sys/smtp.h> +#include <mailutils/mailbox.h> /* Strange, mu_ticket_file is declared here */ +#include <mailutils/mutil.h> +#include <mailutils/auth.h> +#include <mailutils/url.h> + +static int +get_ticket (mu_ticket_t *pticket) +{ + char *filename = mu_tilde_expansion (mu_ticket_file, "/", NULL); + mu_wicket_t wicket; + int rc; + + rc = mu_file_wicket_create (&wicket, filename); + + if (rc == 0) + rc = mu_wicket_get_ticket (wicket, NULL, pticket); + mu_wicket_destroy (&wicket); + free (filename); + return rc; +} + +#define _HAS_USERNAME 0x01 +#define _HAS_PASSWORD 0x02 + +static int +_mu_smtp_fixup_params (mu_smtp_t smtp) +{ + const char *str; + mu_url_t url; + mu_ticket_t ticket = NULL; + int flags = 0; + int rc; + + if (smtp->param[MU_SMTP_PARAM_USERNAME]) + flags |= _HAS_USERNAME; + + if (smtp->secret) + flags |= _HAS_PASSWORD; + + if ((flags & (_HAS_USERNAME|_HAS_PASSWORD)) == (_HAS_USERNAME|_HAS_PASSWORD)) + return 0; /* Nothing to do */ + + if (!smtp->param[MU_SMTP_PARAM_URL]) + return 0; + + rc = mu_url_create (&url, smtp->param[MU_SMTP_PARAM_URL]); + if (rc) + { + mu_diag_output (MU_DIAG_ERROR, "cannot create URL: %s", + mu_strerror (rc)); + return rc; + } + + rc = mu_url_parse (url); + if (rc) + { + mu_diag_output (MU_DIAG_ERROR, "cannot parse URL: %s", + mu_strerror (rc)); + mu_url_destroy (&url); + return rc; + } + + if (!(flags & _HAS_USERNAME)) + { + rc = mu_url_sget_user (url, &str); + if (rc == 0 && + mu_smtp_set_param (smtp, MU_SMTP_PARAM_USERNAME, str) == 0) + flags |= _HAS_USERNAME; + } + + if (!(flags & _HAS_PASSWORD) && mu_url_get_secret (url, &smtp->secret) == 0) + flags |= _HAS_PASSWORD; + + if ((!(flags & _HAS_USERNAME) || + !(flags & _HAS_PASSWORD)) && + get_ticket (&ticket) == 0) + { + if (!(flags & _HAS_USERNAME) && + mu_ticket_get_cred (ticket, url, "SMTP User: ", + &smtp->param[MU_SMTP_PARAM_USERNAME], + NULL) == 0) + flags |= _HAS_USERNAME; + + if (!(flags & _HAS_PASSWORD) && !smtp->secret) + mu_ticket_get_cred (ticket, url, "SMTP Passwd: ", + NULL, &smtp->secret); + mu_ticket_destroy (&ticket); + } + + mu_url_destroy (&url); + return 0; +} int mu_smtp_auth (mu_smtp_t smtp) @@ -34,7 +128,19 @@ mu_smtp_auth (mu_smtp_t smtp) return MU_ERR_SEQ; if (smtp->state != MU_SMTP_MAIL) return MU_ERR_SEQ; - + + /* Obtain missing authentication credentials either from the + URL (when supplied) or from the user ticket file, or by + asking the user, if anything else fails. + + FIXME: This needs some more work. First of all, it should + be called only when really needed (e.g. by mu_smtp_get_param). + Secondly, it should ask the user even if no URL was supplied + (presently it does not). Thirdly, there should be an API to + let caller determine the way of inputting missing data (by + default it does that on tty, which obviously will not suite + GUI applications). */ + _mu_smtp_fixup_params (smtp); #if defined(WITH_GSASL) return _mu_smtp_gsasl_auth (smtp); #else diff --git a/libproto/mailer/smtp_create.c b/libproto/mailer/smtp_create.c index 3a6b20a..5da25f9 100644 --- a/libproto/mailer/smtp_create.c +++ b/libproto/mailer/smtp_create.c @@ -20,6 +20,7 @@ #include <errno.h> #include <stdlib.h> #include <mailutils/list.h> +#include <mailutils/secret.h> #include <mailutils/smtp.h> #include <mailutils/stream.h> #include <mailutils/sys/smtp.h> @@ -59,8 +60,19 @@ mu_smtp_destroy (mu_smtp_t *psmtp) mu_list_destroy (&smtp->mlrepl); mu_list_destroy (&smtp->authmech); + if (smtp->secret) + { + if (MU_SMTP_FISSET (smtp, _MU_SMTP_CLNPASS)) + mu_secret_password_unref (smtp->secret); + mu_secret_destroy (&smtp->secret); + } + for (i = 0; i < MU_SMTP_MAX_PARAM; i++) - free (smtp->param[i]); + { + if (i == MU_SMTP_PARAM_PASSWORD) + continue; + free (smtp->param[i]); + } free (smtp); *psmtp = NULL; diff --git a/libproto/mailer/smtp_gsasl.c b/libproto/mailer/smtp_gsasl.c index 4566f91..57d1fa1 100644 --- a/libproto/mailer/smtp_gsasl.c +++ b/libproto/mailer/smtp_gsasl.c @@ -75,44 +75,48 @@ _smtp_callback (Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop) { int rc = GSASL_OK; mu_smtp_t smtp = gsasl_callback_hook_get (ctx); - char *p; + const char *p = NULL; switch (prop) { case GSASL_PASSWORD: - gsasl_property_set (sctx, prop, smtp->param[MU_SMTP_PARAM_PASSWORD]); + if (mu_smtp_get_param (smtp, MU_SMTP_PARAM_PASSWORD, &p) == 0 && p) + gsasl_property_set (sctx, prop, p); + else + rc = GSASL_NO_PASSWORD; break; case GSASL_AUTHID: case GSASL_ANONYMOUS_TOKEN: - gsasl_property_set (sctx, prop, smtp->param[MU_SMTP_PARAM_USERNAME]); + if (mu_smtp_get_param (smtp, MU_SMTP_PARAM_USERNAME, &p) == 0 && p) + gsasl_property_set (sctx, prop, p); + else if (prop == GSASL_AUTHID) + rc = GSASL_NO_AUTHID; + else + rc = GSASL_NO_ANONYMOUS_TOKEN; break; case GSASL_AUTHZID: - gsasl_property_set (sctx, prop, NULL); + rc = GSASL_NO_AUTHZID; break; case GSASL_SERVICE: - gsasl_property_set (sctx, prop, - smtp->param[MU_SMTP_PARAM_SERVICE] ? - smtp->param[MU_SMTP_PARAM_SERVICE] : "smtp"); + if (mu_smtp_get_param (smtp, MU_SMTP_PARAM_SERVICE, &p) || !p) + p = "smtp"; + gsasl_property_set (sctx, prop, p); break; case GSASL_REALM: - p = smtp->param[MU_SMTP_PARAM_REALM] ? - smtp->param[MU_SMTP_PARAM_REALM] : - smtp->param[MU_SMTP_PARAM_DOMAIN]; - - if (!p) + if ((mu_smtp_get_param (smtp, MU_SMTP_PARAM_REALM, &p) || !p) && + (mu_smtp_get_param (smtp, MU_SMTP_PARAM_DOMAIN, &p) || !p)) rc = GSASL_NO_HOSTNAME; else gsasl_property_set (sctx, prop, p); break; case GSASL_HOSTNAME: - if (smtp->param[MU_SMTP_PARAM_HOST]) - p = smtp->param[MU_SMTP_PARAM_HOST]; - else if (mu_get_host_name (&p)) + if ((mu_smtp_get_param (smtp, MU_SMTP_PARAM_HOST, &p) || !p) && + mu_get_host_name ((char**)&p)) { rc = GSASL_NO_HOSTNAME; break; diff --git a/libproto/mailer/smtp_param.c b/libproto/mailer/smtp_param.c index aee2209..5017c1d 100644 --- a/libproto/mailer/smtp_param.c +++ b/libproto/mailer/smtp_param.c @@ -27,7 +27,7 @@ #include <mailutils/smtp.h> #include <mailutils/sys/smtp.h> - int +int mu_smtp_set_param (mu_smtp_t smtp, int pcode, const char *newparam) { char *param; @@ -36,6 +36,20 @@ mu_smtp_set_param (mu_smtp_t smtp, int pcode, const char *newparam) return EINVAL; if (pcode < 0 || pcode >= MU_SMTP_MAX_PARAM) return EINVAL; + + if (pcode == MU_SMTP_PARAM_PASSWORD) + { + /* Special handling for passwords */ + smtp->param[MU_SMTP_PARAM_PASSWORD] = NULL; + if (smtp->secret) + { + if (MU_SMTP_FISSET (smtp, _MU_SMTP_CLNPASS)) + mu_secret_password_unref (smtp->secret); + mu_secret_destroy (&smtp->secret); + } + MU_SMTP_FCLR (smtp, _MU_SMTP_CLNPASS); + return mu_secret_create (&smtp->secret, newparam, strlen (newparam)); + } param = strdup (newparam); if (!param) @@ -52,6 +66,13 @@ mu_smtp_get_param (mu_smtp_t smtp, int pcode, const char **pparam) return EINVAL; if (pcode < 0 || pcode >= MU_SMTP_MAX_PARAM) return EINVAL; + if (pcode == MU_SMTP_PARAM_PASSWORD && smtp->secret && + !MU_SMTP_FISSET (smtp, _MU_SMTP_CLNPASS)) + { + smtp->param[pcode] = mu_secret_password (smtp->secret); + MU_SMTP_FSET (smtp, _MU_SMTP_CLNPASS); + } + *pparam = smtp->param[pcode]; return 0; } diff --git a/testsuite/smtpsend.c b/testsuite/smtpsend.c index 9978b7a..f3e345a 100644 --- a/testsuite/smtpsend.c +++ b/testsuite/smtpsend.c @@ -27,7 +27,7 @@ static char usage_text[] = "usage: %s hostname [port=N] [trace=N] [tls=N] [from=STRING] [rcpt=STRING]\n" " [domain=STRING] [user=STRING] [pass=STRING]\n" " [service=STRING] [realm=STRING] [host=STRING]\n" -" [auth=method[,...]] [input=FILE] [raw=N]\n"; +" [auth=method[,...]] [url=STRING] [input=FILE] [raw=N]\n"; static void usage () @@ -107,6 +107,9 @@ main (int argc, char **argv) else if (strncmp (argv[i], "host=", 5) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_HOST, argv[i] + 5)); + else if (strncmp (argv[i], "url=", 4) == 0) + MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_URL, + argv[i] + 4)); else if (strncmp (argv[i], "infile=", 7) == 0) infile = argv[i] + 7; else if (strncmp (argv[i], "raw=", 4) == 0) hooks/post-receive -- GNU Mailutils _______________________________________________ Commit-mailutils mailing list Commit-mailutils@gnu.org http://lists.gnu.org/mailman/listinfo/commit-mailutils