+autom4te.cache
configure
config.h.in
stamp-h.in
fi
save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $SASL_LIBS"
- AC_CHECK_LIB(sasl, sasl_client_new,
- [SASL_LIBS="$SASL_LIBS -lsasl"],
+ AC_CHECK_LIB(sasl2, sasl_client_new,
+ [SASL_LIBS="$SASL_LIBS -lsasl2"],
[AC_MSG_ERROR(Cyrus SASL library not found)])
LDFLAGS="$save_LDFLAGS"
fi
Richard Coleman (coleman@math.gatech.edu) started the nmh project.
After he grew too busy to continue maintaining it, it was handed off
- to the net at large. Doug Morris (doug@mhost.com) is hosting the
- mailing lists, web pages, and CVS repository for nmh now.
+ to the net at large. Doug Morris (doug@mhost.com) hosted the web
+ site and mailing lists, web pages, and CVS repository for a long
+ time. More recently, the CVS repository has moved to Savannah
+ (http://savannah.gnu.org/projects/nmh) and Ken Hornstein
+ (kenh@pobox.com) is the project maintainer.
4) Why did Richard start the nmh project?
7) Where do I get nmh?
The latest version of nmh is available at
- ftp://ftp.mhost.com/pub/nmh/nmh.tar.gz
+ http://savannah.gnu.org/download/nmh
8) Where is the nmh web page?
The nmh home page is located at
- http://www.mhost.com/nmh/
+ http://savannah.gnu.org/projects/nmh/
9) Where is the nmh mailing list?
--- /dev/null
+#
+# README.SASL - Readme about SASL support in nmh
+#
+# $Id$
+#
+
+SASL is short for the Simple Authentication and Security Layer. Is is
+a framework for adding authentication and encryption to network protocols.
+It is described in IETF RFC 2222.
+
+This release of nmh supports SASL for POP and SMTP. The SASL support
+is implemented using the Cyrus-SASL library. This library can be found
+at ftp://ftp.andrew.cmu.edu/pub/cyrus-mail. Obviously, SASL support only
+works if you use --enable-pop and the SMTP mail transport.
+
+This release of NMH only supports "Version 2" of the Cyrus SASL library.
+It should work with any newer Cyrus SASL release, but it was tested with
+Cyrus SASL 2.1.12. In particular, the CRAM-MD5 and GSSAPI (Kerberos 5)
+mechanisms were tested.
+
+Currently, security layers ("encryption" in SASL-speak) are only supported
+for POP. This means that if your POP server _and_ the selected GSSAPI
+mechanism supports it, POP communications will be encrypted. Currently
+SMTP does NOT support security layers; this may be added in a future
+release.
+
+If you are curious as to whether or not your communications are actually
+encrypted or not, you can use the -snoop flag to the POP utilities.
+Communication that is encrypted is preceeded by an (*).
+
+If you would like to use the GSSAPI SASL mechanism (Kerberos V), you
+should read very carefully the documentation that comes with
+Cyrus-SASL, specifically the GSSAPI documentation. Getting the GSSAPI
+plugin to work correctly with SASL can be "interesting" to say the least.
If you wish to change the `configure' script or its related files, you'll need
to first install GNU m4, available from <ftp://ftp.gnu.org/pub/gnu/m4/> and then
-GNU autoconf (<ftp://ftp.gnu.org/pub/gnu/autoconf/>).
+GNU autoconf (<ftp://ftp.gnu.org/pub/gnu/autoconf/>). Nmh is currently using
+a minimum of autoconf 2.54.
Most of the configure-related files are automatically generated. The only files
you should need to manually edit are acconfig.h and configure.in. Don't, for
of the users (and the configure script) it is an output file from the point of
view of the developers (and the autoconf script).
-If you do change acconfig.h or configure.in and want to `cvs commit' them, be
-sure to regenerate the output files and commit them as well. The easiest way to
-regenerate the files is to simply run `make' -- it'll do the necessary calls of
-autoconf and autoheader and will do a `./config.status --recheck', which will
-exercise your new configure script.
-
-When you commit the configure-related files, it's very important to commit them
-in the right order. The timestamps on the files in the CVS archive are based on
-the current time at the moment they were committed -- the timestamps from the
-local files you commit are not copied over. If you commit the files in the
-wrong order, you'll cause unnecessary calls of `autoconf' to occur when people
-try to `make' their copies of the latest CVS source. These people may be
-end-users who don't have any interest in changing the configure-related files
-and don't have autoconf installed. They'll be unable to make without playing
-around with `touch'.
-
-The correct procedure to commit the configure-related files is:
-
- % cvs commit acconfig.h aclocal.m4 configure.in
- % autoheader; autoconf; \date > stamp-h.in
- % cvs commit config.h.in configure stamp-h.in
-
-The reason for the three-step commit is that configure.in contains the RCS $Id
-keyword, so when you commit it, a new version is written locally. Therefore,
-the autoconf regeneration should be held off until after the commit, or your
-local stamp-h.in will become out-of-sync with the CVS version (granted, not that
-big a deal). For the second step, you're doing the same commands as a
-`make reset' would do, but using that command would require extra configure runs
-to make Makefile be up-to-date. The reason for the backslash on `date' is in
-case you have `date' aliased in your shell to use a nonstandard format.
-
-If you haven't changed all the files noted above, just commit the ones you have
-changed, in the stated order (for instance, configure.in, then configure and
-stamp-h.in).
+Note that the automatically generated autoconf files (such as config.h.in,
+stamp-h.in, and configure), are NOT kept in CVS. Thus, when you check out
+a CVS tree, you need to do the following things before you can build
+anything:
+ % autoheader
+ % autoconf
+ % date > stamp-h.in
-------------------
directory structure
#ifdef CYRUS_SASL
#include <sasl.h>
+#include <saslutil.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
static int
sm_auth_sasl(char *user, char *mechlist, char *host)
{
- int result, status, outlen;
- unsigned int buflen;
+ int result, status;
+ unsigned int buflen, outlen;
char *buf, outbuf[BUFSIZ];
const char *chosen_mech;
sasl_security_properties_t secprops;
- sasl_external_properties_t extprops;
sasl_ssf_t *ssf;
int *outbufmax;
return NOTOK;
}
- result = sasl_client_new("smtp", host, NULL, SASL_SECURITY_LAYER, &conn);
+ result = sasl_client_new("smtp", host, NULL, NULL, NULL, 0, &conn);
if (result != SASL_OK) {
sm_ierror("SASL client initialization failed: %s",
memset(&secprops, 0, sizeof(secprops));
secprops.maxbufsize = BUFSIZ;
secprops.max_ssf = 0; /* XXX change this when we do encryption */
- memset(&extprops, 0, sizeof(extprops));
result = sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
return NOTOK;
}
- result = sasl_setprop(conn, SASL_SSF_EXTERNAL, &extprops);
-
- if (result != SASL_OK) {
- sm_ierror("SASL external property initialization failed: %s",
- sasl_errstring(result, NULL, NULL));
- return NOTOK;
- }
-
/*
* Start the actual protocol. Feed the mech list into the library
* and get out a possible initial challenge
*/
- result = sasl_client_start(conn, mechlist, NULL, NULL, &buf, &buflen,
- &chosen_mech);
+ result = sasl_client_start(conn, mechlist, NULL, (const char **) &buf,
+ &buflen, (const char **) &chosen_mech);
if (result != SASL_OK && result != SASL_CONTINUE) {
sm_ierror("SASL client start failed: %s",
if (buflen) {
status = sasl_encode64(buf, buflen, outbuf, sizeof(outbuf), NULL);
- free(buf);
if (status != SASL_OK) {
sm_ierror("SASL base64 encode failed: %s",
sasl_errstring(status, NULL, NULL));
outlen = 0;
} else {
result = sasl_decode64(sm_reply.text, sm_reply.length,
- outbuf, &outlen);
+ outbuf, sizeof(outbuf), &outlen);
if (result != SASL_OK) {
smtalk(SM_AUTH, "*");
}
}
- result = sasl_client_step(conn, outbuf, outlen, NULL, &buf, &buflen);
+ result = sasl_client_step(conn, outbuf, outlen, NULL,
+ (const char **) &buf, &buflen);
if (result != SASL_OK && result != SASL_CONTINUE) {
smtalk(SM_AUTH, "*");
}
status = sasl_encode64(buf, buflen, outbuf, sizeof(outbuf), NULL);
- free(buf);
if (status != SASL_OK) {
smtalk(SM_AUTH, "*");
return RP_BHST;
/*
- * Depending on the mechanism, we need to do a FINAL call to
- * sasl_client_step(). Do that now.
- */
-
- result = sasl_client_step(conn, NULL, 0, NULL, &buf, &buflen);
-
- if (result != SASL_OK) {
- sm_ierror("SASL final client negotiation failed: %s",
- sasl_errstring(result, NULL, NULL));
- return NOTOK;
- }
-
- /*
* We _should_ have completed the authentication successfully.
* Get a few properties from the authentication exchange.
*/
- result = sasl_getprop(conn, SASL_MAXOUTBUF, (void **) &outbufmax);
+ result = sasl_getprop(conn, SASL_MAXOUTBUF, (const void **) &outbufmax);
if (result != SASL_OK) {
sm_ierror("Cannot retrieve SASL negotiated output buffer size: %s",
maxoutbuf = *outbufmax;
- result = sasl_getprop(conn, SASL_SSF, (void **) &ssf);
+ result = sasl_getprop(conn, SASL_SSF, (const void **) &ssf);
sasl_ssf = *ssf;
}
(*psecret)->len = len;
- strcpy((*psecret)->data, pass);
+ strcpy((char *) (*psecret)->data, pass);
/* free(pass); */
return SASL_OK;
#ifdef CYRUS_SASL
# include <sasl.h>
+# include <saslutil.h>
#endif /* CYRUS_SASL */
#include <h/popsbr.h>
#define POP_SASL_CB_N_USER 0
{ SASL_CB_PASS, sasl_get_pass, NULL },
#define POP_SASL_CB_N_PASS 1
+ { SASL_CB_LOG, NULL, NULL },
{ SASL_CB_LIST_END, NULL, NULL },
};
#else /* CYRUS_SASL */
int
pop_auth_sasl(char *user, char *host, char *mech)
{
- int result, status, sasl_capability = 0, outlen;
- unsigned int buflen;
+ int result, status, sasl_capability = 0;
+ unsigned int buflen, outlen;
char server_mechs[256], *buf, outbuf[BUFSIZ];
const char *chosen_mech;
sasl_security_properties_t secprops;
- sasl_external_properties_t extprops;
struct pass_context p_context;
sasl_ssf_t *ssf;
int *moutbuf;
return NOTOK;
}
- result = sasl_client_new("pop", host, NULL, SASL_SECURITY_LAYER, &conn);
+ result = sasl_client_new("pop", host, NULL, NULL, NULL, 0, &conn);
if (result != SASL_OK) {
snprintf(response, sizeof(response), "SASL client initialization "
memset(&secprops, 0, sizeof(secprops));
secprops.maxbufsize = BUFSIZ;
secprops.max_ssf = UINT_MAX;
- memset(&extprops, 0, sizeof(extprops));
result = sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
if (result != SASL_OK) {
snprintf(response, sizeof(response), "SASL security property "
- "initialization failed: %s",
- sasl_errstring(result, NULL, NULL));
- return NOTOK;
- }
-
- result = sasl_setprop(conn, SASL_SSF_EXTERNAL, &extprops);
-
- if (result != SASL_OK) {
- snprintf(response, sizeof(response), "SASL external property "
- "initialization failed: %s",
- sasl_errstring(result, NULL, NULL));
+ "initialization failed: %s", sasl_errdetail(conn));
return NOTOK;
}
* and get out a possible initial challenge
*/
- result = sasl_client_start(conn, mech ? mech : server_mechs,
- NULL, NULL, &buf, &buflen, &chosen_mech);
+ result = sasl_client_start(conn,
+ (const char *) (mech ? mech : server_mechs),
+ NULL, (const char **) &buf,
+ &buflen, &chosen_mech);
if (result != SASL_OK && result != SASL_CONTINUE) {
snprintf(response, sizeof(response), "SASL client start failed: %s",
- sasl_errstring(result, NULL, NULL));
+ sasl_errdetail(conn));
return NOTOK;
}
if (buflen) {
status = sasl_encode64(buf, buflen, outbuf, sizeof(outbuf), NULL);
- free(buf);
if (status != SASL_OK) {
snprintf(response, sizeof(response), "SASL base64 encode "
"failed: %s", sasl_errstring(status, NULL, NULL));
}
result = sasl_decode64(response + 2, strlen(response + 2),
- outbuf, &outlen);
+ outbuf, sizeof(outbuf), &outlen);
if (result != SASL_OK) {
command("*");
return NOTOK;
}
- result = sasl_client_step(conn, outbuf, outlen, NULL, &buf, &buflen);
+ result = sasl_client_step(conn, outbuf, outlen, NULL,
+ (const char **) &buf, &buflen);
if (result != SASL_OK && result != SASL_CONTINUE) {
command("*");
snprintf(response, sizeof(response), "SASL client negotiaton "
- "failed: %s", sasl_errstring(result, NULL, NULL));
+ "failed: %s", sasl_errdetail(conn));
return NOTOK;
}
status = sasl_encode64(buf, buflen, outbuf, sizeof(outbuf), NULL);
- free(buf);
if (status != SASL_OK) {
command("*");
return NOTOK;
/*
- * Depending on the mechanism, we might need to call sasl_client_step()
- * one more time. Do that now.
- */
-
- result = sasl_client_step(conn, NULL, 0, NULL, &buf, &buflen);
-
- if (result != SASL_OK) {
- snprintf(response, sizeof(response), "SASL final client negotiaton "
- "failed: %s", sasl_errstring(result, NULL, NULL));
- return NOTOK;
- }
-
- /*
* We _should_ be okay now. Get a few properties now that negotiation
* has completed.
*/
- result = sasl_getprop(conn, SASL_MAXOUTBUF, (void **) &moutbuf);
+ result = sasl_getprop(conn, SASL_MAXOUTBUF, (const void **) &moutbuf);
if (result != SASL_OK) {
snprintf(response, sizeof(response), "Cannot retrieve SASL negotiated "
- "output buffer size: %s", sasl_errstring(result, NULL, NULL));
+ "output buffer size: %s", sasl_errdetail(conn));
return NOTOK;
}
maxoutbuf = *moutbuf;
- result = sasl_getprop(conn, SASL_SSF, (void **) &ssf);
+ result = sasl_getprop(conn, SASL_SSF, (const void **) &ssf);
sasl_ssf = *ssf;
if (result != SASL_OK) {
snprintf(response, sizeof(response), "Cannot retrieve SASL negotiated "
- "security strength factor: %s",
- sasl_errstring(result, NULL, NULL));
+ "security strength factor: %s", sasl_errdetail(conn));
return NOTOK;
}
return SASL_NOMEM;
(*psecret)->len = len;
- strcpy((*psecret)->data, pass);
+ strcpy((char *) (*psecret)->data, pass);
return SASL_OK;
}
outbuf[sizeof(outbuf) - 3] = '\0'; /* Just in case */
strcat(outbuf, "\r\n");
- result = sasl_encode(conn, outbuf, strlen(outbuf), &buf, &buflen);
+ result = sasl_encode(conn, outbuf, strlen(outbuf),
+ (const char **) &buf, &buflen);
if (result != SASL_OK) {
snprintf(response, sizeof(response), "SASL encoding error: %s",
- sasl_errstring(result, NULL, NULL));
+ sasl_errdetail(conn));
return NOTOK;
}
fwrite(buf, buflen, 1, iop);
- free(buf);
}
#endif /* CYRUS_SASL */
} else {
- result = sasl_decode(conn, tmpbuf, cc, &retbuf, &retbufsize);
+ result = sasl_decode(conn, tmpbuf, cc,
+ (const char **) &retbuf, &retbufsize);
if (result != SASL_OK) {
snprintf(response, sizeof(response), "Error during SASL "
- "decoding: %s", sasl_errstring(result, NULL, NULL));
+ "decoding: %s", sasl_errdetail(conn));
return -2;
}
}
memcpy(buffer, retbuf, retbufsize);
ptr = buffer + 1;
cnt = retbufsize - 1;
- if (sasl_complete)
- free(retbuf);
return (int) buffer[0];
}