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 gsasl".
http://git.savannah.gnu.org/cgit/gsasl.git/commit/?id=01213eae08e5b736781d0e14f6d10a7e35e1e3c8 The branch, master has been updated via 01213eae08e5b736781d0e14f6d10a7e35e1e3c8 (commit) via f4bc359074ca470fcbf43bef2f7994a067941c74 (commit) via 4e3b6f70b4c3f55d6207ea2de72d6526304eb161 (commit) via 5d0ad5517d1b4586c41550ea477de5aa19482d1e (commit) via 0a18684417d625d40898f9bd019894bfdbcc48bb (commit) from 337a07ef42b02ed9235e5e153818e61f2b95ea76 (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 01213eae08e5b736781d0e14f6d10a7e35e1e3c8 Author: Simon Josefsson <[email protected]> Date: Mon Mar 26 20:51:00 2012 +0200 Add example SMTP server. commit f4bc359074ca470fcbf43bef2f7994a067941c74 Author: Simon Josefsson <[email protected]> Date: Mon Mar 26 20:50:24 2012 +0200 Support SAML20 callbacks. commit 4e3b6f70b4c3f55d6207ea2de72d6526304eb161 Author: Simon Josefsson <[email protected]> Date: Fri Mar 23 14:37:33 2012 +0100 Handle when AUTH tokens are on final 250 line. commit 5d0ad5517d1b4586c41550ea477de5aa19482d1e Author: Simon Josefsson <[email protected]> Date: Fri Mar 23 13:15:17 2012 +0100 Prepare for --listen. commit 0a18684417d625d40898f9bd019894bfdbcc48bb Author: Simon Josefsson <[email protected]> Date: Fri Mar 23 13:11:24 2012 +0100 Don't even try to get channel binding when --no-cb was given. ----------------------------------------------------------------------- Summary of changes: .gitignore | 2 + examples/Makefile.am | 2 +- examples/smtp-server.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++++ src/callbacks.c | 21 ++++ src/gsasl.c | 1 + src/gsasl.ggo | 1 + src/smtp.c | 9 +- 7 files changed, 320 insertions(+), 4 deletions(-) create mode 100644 examples/smtp-server.c diff --git a/.gitignore b/.gitignore index 63fd66b..cc8f785 100644 --- a/.gitignore +++ b/.gitignore @@ -102,6 +102,8 @@ examples/client-xmpp-saml20.o examples/client.o examples/server-xmpp-saml20 examples/server-xmpp-saml20.o +examples/smtp-server +examples/smtp-server.o gl/.deps/ gl/.libs/ gl/Makefile diff --git a/examples/Makefile.am b/examples/Makefile.am index d4454ca..8313d63 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -22,5 +22,5 @@ LDADD = ../lib/src/libgsasl.la EXTRA_DIST = README -noinst_PROGRAMS = client client-serverfirst client-mech \ +noinst_PROGRAMS = client client-serverfirst client-mech smtp-server \ client-callback client-xmpp-saml20 server-xmpp-saml20 diff --git a/examples/smtp-server.c b/examples/smtp-server.c new file mode 100644 index 0000000..74b2427 --- /dev/null +++ b/examples/smtp-server.c @@ -0,0 +1,288 @@ +/* smtp-server.c --- Example SMTP server with SASL authentication + * Copyright (C) 2012 Simon Josefsson + * + * This file is part of GNU SASL. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +/* This is a minimal SMTP server with GNU SASL authentication support. + The only valid password is "sesam". This server will complete + authentications using LOGIN, PLAIN, DIGEST-MD5, CRAM-MD5, and + SCRAM-SHA-1. It accepts an optional command line parameter + specifying the service name (i.e., a numerical port number or + /etc/services name). By default it listens on port "2000". */ + +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> +#include <netdb.h> +#include <signal.h> + +#include <gsasl.h> + +static int +callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop) +{ + int rc = GSASL_NO_CALLBACK; + + switch (prop) + { + case GSASL_PASSWORD: + gsasl_property_set (sctx, prop, "sesam"); + rc = GSASL_OK; + break; + + default: + /* You may want to log (at debug verbosity level) that an + unknown property was requested here, possibly after filtering + known rejected property requests. */ + break; + } + + return rc; +} + +static ssize_t +gettrimline (char **line, size_t * n, FILE * fh) +{ + ssize_t s = getline (line, n, fh); + + if (s >= 2) + { + if ((*line)[strlen (*line) - 1] == '\n') + (*line)[strlen (*line) - 1] = '\0'; + if ((*line)[strlen (*line) - 1] == '\r') + (*line)[strlen (*line) - 1] = '\0'; + } + + printf ("C: %s\n", *line); + + return s; +} + +#define print(fh, ...) \ + printf ("S: "), printf (__VA_ARGS__), fprintf (fh, __VA_ARGS__) + +static void +server_auth (FILE * fh, Gsasl_session * session) +{ + char *line = NULL; + size_t n = 0; + char *p; + int rc; + + /* The ordering and the type of checks in the following loop has to + be adapted for each protocol depending on its SASL properties. + SMTP is a "server-first" SASL protocol. This implementation do + not support piggy-backing of the initial client challenge nor + piggy-backing of the terminating server response. See RFC 2554 + and RFC 4422 for terminology. That profile results in the + following loop structure. Ask on the help-gsasl list if you are + uncertain. */ + do + { + rc = gsasl_step64 (session, line, &p); + if (rc == GSASL_NEEDS_MORE || (rc == GSASL_OK && p && *p)) + { + print (fh, "334 %s\n", p); + gsasl_free (p); + + if (gettrimline (&line, &n, fh) < 0) + { + print (fh, "221 localhost getline failure\n"); + goto done; + } + } + } + while (rc == GSASL_NEEDS_MORE); + + if (rc != GSASL_OK) + { + print (fh, "535 gsasl_step64 (%d): %s\n", rc, gsasl_strerror (rc)); + goto done; + } + + print (fh, "235 OK\n"); + +done: + free (line); +} + +static void +smtp (FILE * fh, Gsasl * ctx) +{ + char *line = NULL; + size_t n = 0; + int rc; + + print (fh, "220 localhost ESMTP GNU SASL smtp-server\n"); + + while (gettrimline (&line, &n, fh) >= 0) + { + if (strncmp (line, "EHLO ", 5) == 0 || strncmp (line, "ehlo ", 5) == 0) + { + char *mechlist; + + rc = gsasl_server_mechlist (ctx, &mechlist); + if (rc != GSASL_OK) + { + print (fh, "221 localhost gsasl_server_mechlist (%d): %s\n", + rc, gsasl_strerror (rc)); + goto done; + } + + print (fh, "250-localhost\n"); + print (fh, "250 AUTH %s\n", mechlist); + + gsasl_free (mechlist); + } + else if (strncmp (line, "AUTH ", 5) == 0 + || strncmp (line, "auth ", 5) == 0) + { + Gsasl_session *session = NULL; + + if ((rc = gsasl_server_start (ctx, line + 5, &session)) != GSASL_OK) + { + print (fh, "221 localhost gsasl_server_start (%d): %s\n", + rc, gsasl_strerror (rc)); + goto done; + } + + server_auth (fh, session); + + gsasl_finish (session); + } + else if (strncmp (line, "QUIT", 4) == 0 + || strncmp (line, "quit", 4) == 0) + { + print (fh, "221 localhost QUIT\n"); + goto done; + } + else + print (fh, "500 unrecognized command\n"); + } + + print (fh, "221 localhost getline failure\n"); + +done: + free (line); +} + +int +main (int argc, char *argv[]) +{ + const char *service = argc > 1 ? argv[1] : "2000"; + volatile int run = 1; + struct addrinfo hints, *addrs; + int sockfd; + int rc; + int yes = 1; + Gsasl *ctx; + + rc = gsasl_init (&ctx); + if (rc < 0) + { + printf ("gsasl_init (%d): %s\n", rc, gsasl_strerror (rc)); + exit (EXIT_FAILURE); + } + + printf ("smtp-server [gsasl header %s library %s]\n", + GSASL_VERSION, gsasl_check_version (NULL)); + + gsasl_callback_set (ctx, callback); + + memset (&hints, 0, sizeof (hints)); + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + hints.ai_socktype = SOCK_STREAM; + + rc = getaddrinfo (NULL, service, &hints, &addrs); + if (rc < 0) + { + printf ("getaddrinfo: %s\n", gai_strerror (rc)); + exit (EXIT_FAILURE); + } + + sockfd = socket (addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol); + if (sockfd < 0) + { + perror ("socket"); + exit (EXIT_FAILURE); + } + + if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (yes)) < 0) + { + perror ("setsockopt"); + exit (EXIT_FAILURE); + } + + rc = bind (sockfd, addrs->ai_addr, addrs->ai_addrlen); + if (rc < 0) + { + perror ("bind"); + exit (EXIT_FAILURE); + } + + freeaddrinfo (addrs); + + rc = listen (sockfd, SOMAXCONN); + if (rc < 0) + { + perror ("listen"); + exit (EXIT_FAILURE); + } + + signal (SIGPIPE, SIG_IGN); + + while (run) + { + struct sockaddr from; + socklen_t fromlen; + char host[NI_MAXHOST]; + int fd; + FILE *fh; + + fd = accept (sockfd, &from, &fromlen); + if (fd < 0) + { + perror ("accept"); + continue; + } + + rc = getnameinfo (&from, fromlen, host, sizeof (host), + NULL, 0, NI_NUMERICHOST); + if (rc == 0) + printf ("connection from %s\n", host); + else + printf ("getnameinfo: %s\n", gai_strerror (rc)); + + fh = fdopen (fd, "w+"); + if (!fh) + { + perror ("fdopen"); + close (fd); + continue; + } + + smtp (fh, ctx); + + fclose (fh); + } + + close (sockfd); + gsasl_done (ctx); + + return 0; +} diff --git a/src/callbacks.c b/src/callbacks.c index cfdd942..db7c2e4 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -216,6 +216,27 @@ callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop) } break; + case GSASL_SAML20_IDP_IDENTIFIER: + { + char *str = readutf8line ("Enter SAML authentication identifier " + "(e.g. \"http://example.org/\"): "); + + gsasl_property_set (sctx, GSASL_SAML20_IDP_IDENTIFIER, str); + + rc = GSASL_OK; + } + break; + + case GSASL_SAML20_AUTHENTICATE_IN_BROWSER: + { + const char *url = gsasl_property_get (sctx, GSASL_SAML20_REDIRECT_URL); + + printf ("Please visit this URL to authenticate:\n%s\n", url); + + rc = GSASL_OK; + } + break; + default: fprintf (stderr, "warning: mechanism requested unsupported property `%d'\n", diff --git a/src/gsasl.c b/src/gsasl.c index 1c87a86..e214c27 100644 --- a/src/gsasl.c +++ b/src/gsasl.c @@ -607,6 +607,7 @@ main (int argc, char *argv[]) } #if HAVE_GNUTLS_SESSION_CHANNEL_BINDING + if (!args_info.no_cb_flag) { gnutls_datum cb; diff --git a/src/gsasl.ggo b/src/gsasl.ggo index b5c31ad..5ba2f93 100644 --- a/src/gsasl.ggo +++ b/src/gsasl.ggo @@ -27,6 +27,7 @@ option "server-mechanisms" - "Write name of supported server mechanisms separate section "Network options" option "connect" - "Connect to TCP server and negotiate on stream instead of stdin/stdout. PORT is the protocol service, or an integer denoting the port, and defaults to 143 (imap) if not specified. Also sets the --hostname default." string typestr="HOST[:PORT]" no +#option "listen" - "Listen on network socket and provide authentication services following the supported protocols. This implies --server and defaults to IMAP mode." string typestr="HOST:[PORT]" no argoptional default="localhost:143" section "Generic options" option "application-data" d "After authentication, read data from stdin and run it through the mechanism's security layer and print it base64 encoded to stdout. The default is to terminate after authentication." flag on diff --git a/src/smtp.c b/src/smtp.c index 61391e8..649b2c7 100644 --- a/src/smtp.c +++ b/src/smtp.c @@ -91,9 +91,12 @@ smtp_select_mechanism (char **mechlist) if (!readln (&in)) return 0; -#define GREETING "250-AUTH " - if (strncmp (in, GREETING, strlen (GREETING)) == 0) - *mechlist = in + strlen (GREETING); +#define GREETING1 "250-AUTH " +#define GREETING2 "250 AUTH " + if (strncmp (in, GREETING1, strlen (GREETING1)) == 0) + *mechlist = in + strlen (GREETING1); + else if (strncmp (in, GREETING2, strlen (GREETING2)) == 0) + *mechlist = in + strlen (GREETING2); } while (strncmp (in, "250 ", 4) != 0); } hooks/post-receive -- GNU gsasl _______________________________________________ Gsasl-commit mailing list [email protected] https://lists.gnu.org/mailman/listinfo/gsasl-commit
